统计数据
This commit is contained in:
parent
d14002251f
commit
c5eaaf4bb1
@ -41,9 +41,10 @@ public class CustomerDashboardDailyCapabilityHandler implements AgentCapabilityH
|
||||
学员总数:暂未获取
|
||||
今日新增:暂未获取
|
||||
跟进成员数:暂未获取
|
||||
统计管理:暂未获取
|
||||
今日收款:暂未接入
|
||||
""".trim(),
|
||||
List.of("企业微信学员联系 API"),
|
||||
List.of("企业微信学员联系 API", "企业微信统计管理 API"),
|
||||
Map.of("error", e.getMessage() == null ? "api forbidden" : e.getMessage()),
|
||||
Instant.now()
|
||||
);
|
||||
@ -60,15 +61,43 @@ public class CustomerDashboardDailyCapabilityHandler implements AgentCapabilityH
|
||||
学员总数:%d
|
||||
今日新增:%d
|
||||
跟进成员数:%d
|
||||
今日咨询数:%d
|
||||
今日聊天数:%d
|
||||
今日发送消息数:%d
|
||||
今日回复率:%s
|
||||
平均首次回复时长:%s
|
||||
今日负反馈数:%d
|
||||
今日收款:暂未接入
|
||||
""".formatted(stats.totalStudents(), stats.todayNewStudents(), stats.followUserCount()).trim(),
|
||||
List.of("企业微信学员联系 API"),
|
||||
""".formatted(
|
||||
stats.totalStudents(),
|
||||
stats.todayNewStudents(),
|
||||
stats.followUserCount(),
|
||||
stats.todayNewApplyCount(),
|
||||
stats.todayChatCount(),
|
||||
stats.todayMessageCount(),
|
||||
percent(stats.todayReplyPercentage()),
|
||||
seconds(stats.todayAvgReplySeconds()),
|
||||
stats.todayNegativeFeedbackCount()
|
||||
).trim(),
|
||||
List.of("企业微信学员联系 API", "企业微信统计管理 API"),
|
||||
Map.of(
|
||||
"totalStudents", stats.totalStudents(),
|
||||
"todayNewStudents", stats.todayNewStudents(),
|
||||
"followUserCount", stats.followUserCount()
|
||||
"followUserCount", stats.followUserCount(),
|
||||
"todayNewApplyCount", stats.todayNewApplyCount(),
|
||||
"todayChatCount", stats.todayChatCount(),
|
||||
"todayMessageCount", stats.todayMessageCount(),
|
||||
"todayNegativeFeedbackCount", stats.todayNegativeFeedbackCount()
|
||||
),
|
||||
Instant.now()
|
||||
);
|
||||
}
|
||||
|
||||
private String percent(Integer value) {
|
||||
return value == null ? "暂无数据" : value + "%";
|
||||
}
|
||||
|
||||
private String seconds(Integer value) {
|
||||
return value == null ? "暂无数据" : value + "秒";
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +89,26 @@ public class WecomClient {
|
||||
return response;
|
||||
}
|
||||
|
||||
public WecomUserBehaviorDataResponse getStudentContactBehaviorData(List<String> userIds, long startTime, long endTime) {
|
||||
String token = getAccessToken(studentContactSecret());
|
||||
WecomUserBehaviorDataRequest request = new WecomUserBehaviorDataRequest(userIds, startTime, endTime);
|
||||
WecomUserBehaviorDataResponse response = webClient.post()
|
||||
.uri(uriBuilder -> uriBuilder.path("/cgi-bin/externalcontact/get_user_behavior_data")
|
||||
.queryParam("access_token", token)
|
||||
.build())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.bodyValue(request)
|
||||
.retrieve()
|
||||
.bodyToMono(WecomUserBehaviorDataResponse.class)
|
||||
.block();
|
||||
|
||||
if (response == null || !response.success()) {
|
||||
log.error("wecom student contact behavior data failed err={}", response == null ? "null" : response.errmsg());
|
||||
throw new IllegalStateException("WeCom student contact behavior data failed: " + (response == null ? "null" : response.errmsg()));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private String getAccessToken() {
|
||||
if (cachedToken != null && Instant.now().isBefore(tokenExpireAt)) {
|
||||
log.info("wecom gettoken use cached token expireAt={}", tokenExpireAt);
|
||||
|
||||
@ -3,5 +3,11 @@ package com.company.agentfoundation.integration.wecom;
|
||||
public record WecomStudentContactStats(
|
||||
int totalStudents,
|
||||
int todayNewStudents,
|
||||
int followUserCount
|
||||
int followUserCount,
|
||||
int todayNewApplyCount,
|
||||
int todayChatCount,
|
||||
int todayMessageCount,
|
||||
int todayNegativeFeedbackCount,
|
||||
Integer todayReplyPercentage,
|
||||
Integer todayAvgReplySeconds
|
||||
) {}
|
||||
|
||||
@ -24,9 +24,11 @@ public class WecomStudentContactStatsService {
|
||||
public WecomStudentContactStats fetchTodayStats() {
|
||||
List<String> followUsers = wecomClient.getStudentContactFollowUsers().followUser();
|
||||
if (followUsers == null || followUsers.isEmpty()) {
|
||||
return new WecomStudentContactStats(0, 0, 0);
|
||||
return new WecomStudentContactStats(0, 0, 0, 0, 0, 0, 0, null, null);
|
||||
}
|
||||
|
||||
long todayStart = LocalDate.now(CHINA_ZONE).atStartOfDay(CHINA_ZONE).toEpochSecond();
|
||||
long tomorrowStart = LocalDate.now(CHINA_ZONE).plusDays(1).atStartOfDay(CHINA_ZONE).toEpochSecond();
|
||||
Set<String> allStudents = new HashSet<>();
|
||||
Map<String, Long> earliestCreateTimeByStudent = new HashMap<>();
|
||||
for (int start = 0; start < followUsers.size(); start += BATCH_SIZE) {
|
||||
@ -34,13 +36,22 @@ public class WecomStudentContactStatsService {
|
||||
fetchBatch(batchUsers, allStudents, earliestCreateTimeByStudent);
|
||||
}
|
||||
|
||||
long todayStart = LocalDate.now(CHINA_ZONE).atStartOfDay(CHINA_ZONE).toEpochSecond();
|
||||
long tomorrowStart = LocalDate.now(CHINA_ZONE).plusDays(1).atStartOfDay(CHINA_ZONE).toEpochSecond();
|
||||
int todayNew = (int) earliestCreateTimeByStudent.values().stream()
|
||||
.filter(createTime -> createTime != null && createTime >= todayStart && createTime < tomorrowStart)
|
||||
.count();
|
||||
BehaviorSummary behaviorSummary = fetchBehaviorSummary(followUsers, todayStart, tomorrowStart - 1);
|
||||
|
||||
return new WecomStudentContactStats(allStudents.size(), todayNew, followUsers.size());
|
||||
return new WecomStudentContactStats(
|
||||
allStudents.size(),
|
||||
todayNew,
|
||||
followUsers.size(),
|
||||
behaviorSummary.newApplyCount(),
|
||||
behaviorSummary.chatCount(),
|
||||
behaviorSummary.messageCount(),
|
||||
behaviorSummary.negativeFeedbackCount(),
|
||||
behaviorSummary.replyPercentage(),
|
||||
behaviorSummary.avgReplySeconds()
|
||||
);
|
||||
}
|
||||
|
||||
private void fetchBatch(List<String> userIds, Set<String> allStudents, Map<String, Long> earliestCreateTimeByStudent) {
|
||||
@ -68,4 +79,60 @@ public class WecomStudentContactStatsService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BehaviorSummary fetchBehaviorSummary(List<String> followUsers, long startTime, long endTime) {
|
||||
int newApplyCount = 0;
|
||||
int chatCount = 0;
|
||||
int messageCount = 0;
|
||||
int negativeFeedbackCount = 0;
|
||||
int replyPercentageWeightedSum = 0;
|
||||
int replyPercentageWeight = 0;
|
||||
int avgReplyTimeWeightedSum = 0;
|
||||
int avgReplyTimeWeight = 0;
|
||||
|
||||
for (int start = 0; start < followUsers.size(); start += BATCH_SIZE) {
|
||||
List<String> batchUsers = followUsers.subList(start, Math.min(start + BATCH_SIZE, followUsers.size()));
|
||||
WecomUserBehaviorDataResponse response = wecomClient.getStudentContactBehaviorData(batchUsers, startTime, endTime);
|
||||
List<WecomUserBehaviorDataResponse.BehaviorData> behaviorData = response.behaviorData();
|
||||
if (behaviorData == null) {
|
||||
continue;
|
||||
}
|
||||
for (WecomUserBehaviorDataResponse.BehaviorData item : behaviorData) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
int itemChatCount = value(item.chatCnt());
|
||||
int itemMessageCount = value(item.messageCnt());
|
||||
newApplyCount += value(item.newApplyCnt());
|
||||
chatCount += itemChatCount;
|
||||
messageCount += itemMessageCount;
|
||||
negativeFeedbackCount += value(item.negativeFeedbackCnt());
|
||||
if (item.replyPercentage() != null && itemChatCount > 0) {
|
||||
replyPercentageWeightedSum += item.replyPercentage() * itemChatCount;
|
||||
replyPercentageWeight += itemChatCount;
|
||||
}
|
||||
if (item.avgReplyTime() != null && itemMessageCount > 0) {
|
||||
avgReplyTimeWeightedSum += item.avgReplyTime() * itemMessageCount;
|
||||
avgReplyTimeWeight += itemMessageCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Integer replyPercentage = replyPercentageWeight == 0 ? null : replyPercentageWeightedSum / replyPercentageWeight;
|
||||
Integer avgReplySeconds = avgReplyTimeWeight == 0 ? null : avgReplyTimeWeightedSum / avgReplyTimeWeight;
|
||||
return new BehaviorSummary(newApplyCount, chatCount, messageCount, negativeFeedbackCount, replyPercentage, avgReplySeconds);
|
||||
}
|
||||
|
||||
private int value(Integer value) {
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
|
||||
private record BehaviorSummary(
|
||||
int newApplyCount,
|
||||
int chatCount,
|
||||
int messageCount,
|
||||
int negativeFeedbackCount,
|
||||
Integer replyPercentage,
|
||||
Integer avgReplySeconds
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.company.agentfoundation.integration.wecom;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record WecomUserBehaviorDataRequest(
|
||||
@JsonProperty("userid") List<String> userIds,
|
||||
@JsonProperty("start_time") Long startTime,
|
||||
@JsonProperty("end_time") Long endTime
|
||||
) {}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.company.agentfoundation.integration.wecom;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record WecomUserBehaviorDataResponse(
|
||||
Integer errcode,
|
||||
String errmsg,
|
||||
@JsonProperty("behavior_data") List<BehaviorData> behaviorData
|
||||
) {
|
||||
public boolean success() {
|
||||
return errcode == null || errcode == 0;
|
||||
}
|
||||
|
||||
public record BehaviorData(
|
||||
String statTime,
|
||||
@JsonProperty("chat_cnt") Integer chatCnt,
|
||||
@JsonProperty("message_cnt") Integer messageCnt,
|
||||
@JsonProperty("reply_percentage") Integer replyPercentage,
|
||||
@JsonProperty("avg_reply_time") Integer avgReplyTime,
|
||||
@JsonProperty("negative_feedback_cnt") Integer negativeFeedbackCnt,
|
||||
@JsonProperty("new_apply_cnt") Integer newApplyCnt,
|
||||
@JsonProperty("new_contact_cnt") Integer newContactCnt
|
||||
) {}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user