|
|
@@ -28,9 +28,11 @@ import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
|
import com.fs.qw.vo.QwSopTempSetting;
|
|
|
import com.fs.sop.domain.QwSopLogs;
|
|
|
import com.fs.sop.mapper.QwSopLogsMapper;
|
|
|
+import com.fs.sop.params.QwRatingConfig;
|
|
|
import com.fs.sop.service.IQwSopLogsService;
|
|
|
import com.fs.system.domain.SysConfig;
|
|
|
import com.fs.system.mapper.SysConfigMapper;
|
|
|
+import com.fs.system.service.ISysConfigService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
@@ -68,6 +70,7 @@ public class SendMsg {
|
|
|
private final AiAddwxSopUserWorkflowMapper aiAddwxSopUserWorkflowMapper;
|
|
|
private final AiAddwxSopUserNodeRuleMapper aiAddwxSopUserNodeRuleMapper;
|
|
|
private final QwExternalContactMapper qwExternalContactMapper;
|
|
|
+ private final ISysConfigService sysConfigService;
|
|
|
|
|
|
@Value("${group-no}")
|
|
|
private String groupNo;
|
|
|
@@ -101,7 +104,7 @@ public class SendMsg {
|
|
|
@Qualifier("customThreadPool")
|
|
|
private ThreadPoolTaskExecutor customThreadPool;
|
|
|
|
|
|
- public SendMsg(QwUserMapper qwUserMapper, QwSopLogsMapper qwSopLogsMapper, IpadSendServer sendServer, SysConfigMapper sysConfigMapper, IQwSopLogsService qwSopLogsService, QwIpadServerMapper qwIpadServerMapper, RedisCacheT<Long> redisCache, AsyncSopTestService asyncSopTestService, ICompanyMiniappService companyMiniappService, IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService, QwPushCountMapper qwPushCountMapper, QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper, IAiAddwxSopUserNodeService aiAddwxSopUserNodeService, AiAddwxSopUserWorkflowMapper aiAddwxSopUserWorkflowMapper, AiAddwxSopUserNodeRuleMapper aiAddwxSopUserNodeRuleMapper, QwExternalContactMapper qwExternalContactMapper) {
|
|
|
+ public SendMsg(QwUserMapper qwUserMapper, QwSopLogsMapper qwSopLogsMapper, IpadSendServer sendServer, SysConfigMapper sysConfigMapper, IQwSopLogsService qwSopLogsService, QwIpadServerMapper qwIpadServerMapper, RedisCacheT<Long> redisCache, AsyncSopTestService asyncSopTestService, ICompanyMiniappService companyMiniappService, IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService, QwPushCountMapper qwPushCountMapper, QwRestrictionPushRecordMapper qwRestrictionPushRecordMapper, IAiAddwxSopUserNodeService aiAddwxSopUserNodeService, AiAddwxSopUserWorkflowMapper aiAddwxSopUserWorkflowMapper, AiAddwxSopUserNodeRuleMapper aiAddwxSopUserNodeRuleMapper, QwExternalContactMapper qwExternalContactMapper, ISysConfigService sysConfigService) {
|
|
|
this.qwUserMapper = qwUserMapper;
|
|
|
this.qwSopLogsMapper = qwSopLogsMapper;
|
|
|
this.sendServer = sendServer;
|
|
|
@@ -118,6 +121,7 @@ public class SendMsg {
|
|
|
this.aiAddwxSopUserWorkflowMapper = aiAddwxSopUserWorkflowMapper;
|
|
|
this.aiAddwxSopUserNodeRuleMapper = aiAddwxSopUserNodeRuleMapper;
|
|
|
this.qwExternalContactMapper = qwExternalContactMapper;
|
|
|
+ this.sysConfigService = sysConfigService;
|
|
|
}
|
|
|
private List<QwUser> getQwUserList() {
|
|
|
if (qwUserList.isEmpty()) {
|
|
|
@@ -156,6 +160,10 @@ public class SendMsg {
|
|
|
// 看课配置文件获取
|
|
|
SysConfig courseConfig = sysConfigMapper.selectConfigByConfigKey("course.config");
|
|
|
CourseConfig config = JSON.parseObject(courseConfig.getConfigValue(), CourseConfig.class);
|
|
|
+
|
|
|
+ String ratingJson = sysConfigService.selectConfigByKey("qwRating:config");
|
|
|
+ QwRatingConfig ratingConfig = JSON.parseObject(ratingJson, QwRatingConfig.class);
|
|
|
+
|
|
|
// 消息发送延迟
|
|
|
int delayStart;
|
|
|
int delayEnd;
|
|
|
@@ -190,7 +198,7 @@ public class SendMsg {
|
|
|
CompletableFuture.runAsync(() -> {
|
|
|
try {
|
|
|
log.info("开始任务:{}", e.getQwUserName());
|
|
|
- processUser(e, delayStart, delayEnd, miniMap, newCtx);
|
|
|
+ processUser(e, delayStart, delayEnd, miniMap, newCtx,ratingConfig);
|
|
|
} catch (Exception exception) {
|
|
|
log.error("发送错误:", exception);
|
|
|
} finally {
|
|
|
@@ -213,7 +221,7 @@ public class SendMsg {
|
|
|
* @param miniMap 小程序配置
|
|
|
* @param ctx 任务上下文(用于取消检查)
|
|
|
*/
|
|
|
- private void processUser(QwUser qwUser, int delayStart, int delayEnd, Map<String, FsCoursePlaySourceConfig> miniMap, TaskContext ctx) {
|
|
|
+ private void processUser(QwUser qwUser, int delayStart, int delayEnd, Map<String, FsCoursePlaySourceConfig> miniMap, TaskContext ctx,QwRatingConfig ratingConfig) {
|
|
|
long start1 = System.currentTimeMillis();
|
|
|
// 获取当前企微待发送记录
|
|
|
List<QwSopLogs> qwSopLogList = qwSopLogsMapper.selectByQwUserId(qwUser.getId());
|
|
|
@@ -306,51 +314,51 @@ public class SendMsg {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
//查询是否有设置限制客服推送消息次数
|
|
|
// Integer pushCount=pushCountMap.containsKey(String.valueOf(companyId)) ? pushCountMap.get(String.valueOf(companyId)): pushCountMap.getOrDefault(String.valueOf(type), -99);
|
|
|
int salesPushCustomerMessageCount = qwRestrictionPushRecordMapper.selectQwRestrictionPushRecord(qwUserId, customerId, type, DateUtils.toStartTime(), DateUtils.toEndTime());
|
|
|
- if (pushCount != -99 && salesPushCustomerMessageCount >= pushCount) {
|
|
|
- content.setSendStatus(2);//设置发送失败状态
|
|
|
- content.setSendRemarks("发送次数达到上限");
|
|
|
- } else {
|
|
|
- // 发送
|
|
|
- sendServer.send(content, user, qwSopLogs, miniMap, parentVo);
|
|
|
- //判断销售推送成功:保存记录
|
|
|
- if (content.getSendStatus() != 2) {
|
|
|
- QwRestrictionPushRecord qrpr = new QwRestrictionPushRecord();
|
|
|
- qrpr.setType(type);
|
|
|
- qrpr.setQwUserId(qwUserId);
|
|
|
- qrpr.setQwExternalId(customerId);
|
|
|
- qrpr.setCompanyId(companyId);
|
|
|
- qrpr.setStatus(1);
|
|
|
- qrpr.setCreateTime(DateUtils.getTime());
|
|
|
- qrpr.setTime(System.currentTimeMillis());
|
|
|
- qwRestrictionPushRecordMapper.insert(qrpr);
|
|
|
+
|
|
|
+ if (CloudHostUtils.hasCloudHostName("今正科技")){
|
|
|
+ //今正要 通过客户等级 限制发送次数 只管 3个类型的
|
|
|
+ Integer sendType = qwSopLogs.getSendType();
|
|
|
+ Integer grade = qwSopLogs.getGrade();
|
|
|
+ boolean shouldSend = true;
|
|
|
+
|
|
|
+ if (sendType == 2 || sendType == 5 || sendType == 11) {
|
|
|
+ if (grade != null) {
|
|
|
+ Integer gradeLimit = getGradeLimit(grade, ratingConfig);
|
|
|
+ if (gradeLimit != null) {
|
|
|
+ if (salesPushCustomerMessageCount >= gradeLimit) {
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks(getGradeLabel(grade) + "级客户发送次数达到上限");
|
|
|
+ shouldSend = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- long end4 = System.currentTimeMillis();
|
|
|
- log.info("请求pad发送完成:{}, {}, 时长4:{}", user.getQwUserName(), qwSopLogs.getId(), end4 - start4);
|
|
|
- if(content.getSendStatus() == 2 && ("请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks()) || "请求失败:请求频率异常".equals(content.getSendRemarks()))){
|
|
|
- QwUser update = new QwUser();
|
|
|
- update.setRemark("请求频率异常,暂停发送,三小时后恢复继续发送");
|
|
|
- update.setUpdateTime(new Date());
|
|
|
- qwUserMapper.update(update, new QueryWrapper<QwUser>().eq("id", user.getId()));
|
|
|
- redisCache.setCacheObject("qw:user:id:" + user.getId(), user.getId(), 3, TimeUnit.HOURS);
|
|
|
- return;
|
|
|
+
|
|
|
+ if (shouldSend) {
|
|
|
+ if (!doSendAndPostProcess(content, user, qwSopLogs, miniMap, parentVo,
|
|
|
+ type, qwUserId, customerId, companyId, start4, ctx)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (pushCount != -99 && salesPushCustomerMessageCount >= pushCount) {
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送次数达到上限");
|
|
|
}
|
|
|
- try {
|
|
|
- if (ctx.isCancelled()) {
|
|
|
+ else {
|
|
|
+ if (!doSendAndPostProcess(content, user, qwSopLogs, miniMap, parentVo,
|
|
|
+ type, qwUserId, customerId, companyId, start4, ctx)) {
|
|
|
return;
|
|
|
}
|
|
|
- int delay = ThreadLocalRandom.current().nextInt(300, 1000);
|
|
|
- log.debug("pad发送消息等待:{}ms", delay);
|
|
|
- Thread.sleep(delay);
|
|
|
- } catch (InterruptedException e) {
|
|
|
- log.error("线程等待错误!");
|
|
|
- Thread.currentThread().interrupt();
|
|
|
- return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
// 推送 APP
|
|
|
boolean hasAppSend = false;
|
|
|
int successCount = 0;
|
|
|
@@ -487,6 +495,84 @@ public class SendMsg {
|
|
|
long end3 = System.currentTimeMillis();
|
|
|
log.info("销售执行完成:{}, 耗时:{}", user.getQwUserName(), end3 - start3);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送消息并处理后续逻辑(保存发送记录、频率异常检测、随机等待)
|
|
|
+ * @return true 继续执行,false 需要中断(频率异常或被取消)
|
|
|
+ */
|
|
|
+ private boolean doSendAndPostProcess(QwSopCourseFinishTempSetting.Setting content, QwUser user,
|
|
|
+ QwSopLogs qwSopLogs, Map<String, FsCoursePlaySourceConfig> miniMap,
|
|
|
+ BaseVo parentVo, Integer type, Long qwUserId, Long customerId,
|
|
|
+ Long companyId, long startTime, TaskContext ctx) {
|
|
|
+ sendServer.send(content, user, qwSopLogs, miniMap, parentVo);
|
|
|
+
|
|
|
+ if (content.getSendStatus() != 2) {
|
|
|
+ QwRestrictionPushRecord qrpr = new QwRestrictionPushRecord();
|
|
|
+ qrpr.setType(type);
|
|
|
+ qrpr.setQwUserId(qwUserId);
|
|
|
+ qrpr.setQwExternalId(customerId);
|
|
|
+ qrpr.setCompanyId(companyId);
|
|
|
+ qrpr.setStatus(1);
|
|
|
+ qrpr.setCreateTime(DateUtils.getTime());
|
|
|
+ qrpr.setTime(System.currentTimeMillis());
|
|
|
+ qwRestrictionPushRecordMapper.insert(qrpr);
|
|
|
+ }
|
|
|
+
|
|
|
+ long end4 = System.currentTimeMillis();
|
|
|
+ log.info("请求pad发送完成:{}, {}, 时长4:{}", user.getQwUserName(), qwSopLogs.getId(), end4 - startTime);
|
|
|
+
|
|
|
+ if (content.getSendStatus() == 2 && ("请求失败:消息发送过于频繁,请稍后再试".equals(content.getSendRemarks())
|
|
|
+ || "请求失败:请求频率异常".equals(content.getSendRemarks()))) {
|
|
|
+ QwUser update = new QwUser();
|
|
|
+ update.setRemark("请求频率异常,暂停发送,三小时后恢复继续发送");
|
|
|
+ update.setUpdateTime(new Date());
|
|
|
+ qwUserMapper.update(update, new QueryWrapper<QwUser>().eq("id", user.getId()));
|
|
|
+ redisCache.setCacheObject("qw:user:id:" + user.getId(), user.getId(), 3, TimeUnit.HOURS);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (ctx.isCancelled()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ int delay = ThreadLocalRandom.current().nextInt(300, 1000);
|
|
|
+ log.debug("pad发送消息等待:{}ms", delay);
|
|
|
+ Thread.sleep(delay);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ log.error("线程等待错误!");
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据客户等级获取发送次数上限
|
|
|
+ * @return 上限值,null 表示不限制(非A/B/C/D级客户)
|
|
|
+ */
|
|
|
+ private Integer getGradeLimit(Integer grade, QwRatingConfig ratingConfig) {
|
|
|
+ switch (grade) {
|
|
|
+ case 1: return ratingConfig.getALevelSend();
|
|
|
+ case 2: return ratingConfig.getBLevelSend();
|
|
|
+ case 3: return ratingConfig.getCLevelSend();
|
|
|
+ case 4: return ratingConfig.getDLevelSend();
|
|
|
+ default: return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取客户等级名称
|
|
|
+ */
|
|
|
+ private String getGradeLabel(Integer grade) {
|
|
|
+ switch (grade) {
|
|
|
+ case 1: return "A";
|
|
|
+ case 2: return "B";
|
|
|
+ case 3: return "C";
|
|
|
+ case 4: return "D";
|
|
|
+ default: return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 今正cid加微后定时发消息
|
|
|
*/
|