|
@@ -5,21 +5,38 @@ import com.alibaba.fastjson.JSONArray;
|
|
import com.fs.common.utils.DateUtils;
|
|
import com.fs.common.utils.DateUtils;
|
|
import com.fs.company.mapper.CompanyUserMapper;
|
|
import com.fs.company.mapper.CompanyUserMapper;
|
|
import com.fs.course.domain.FsCourseFinishTemp;
|
|
import com.fs.course.domain.FsCourseFinishTemp;
|
|
|
|
+import com.fs.course.domain.FsCourseWatchLog;
|
|
import com.fs.course.mapper.FsCourseFinishTempMapper;
|
|
import com.fs.course.mapper.FsCourseFinishTempMapper;
|
|
import com.fs.course.service.IFsCourseFinishTempService;
|
|
import com.fs.course.service.IFsCourseFinishTempService;
|
|
import com.fs.course.vo.FsCourseFinishTempListVO;
|
|
import com.fs.course.vo.FsCourseFinishTempListVO;
|
|
import com.fs.course.vo.FsCourseFinishTempVO;
|
|
import com.fs.course.vo.FsCourseFinishTempVO;
|
|
import com.fs.fastGpt.domain.FastGptChatReplaceWords;
|
|
import com.fs.fastGpt.domain.FastGptChatReplaceWords;
|
|
import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
|
|
import com.fs.fastGpt.mapper.FastGptChatReplaceWordsMapper;
|
|
|
|
+import com.fs.qw.domain.QwCourseFinishRemarkRty;
|
|
|
|
+import com.fs.qw.domain.QwExternalContact;
|
|
|
|
+import com.fs.qw.domain.QwUser;
|
|
|
|
+import com.fs.qw.mapper.QwExternalContactMapper;
|
|
import com.fs.qw.mapper.QwUserMapper;
|
|
import com.fs.qw.mapper.QwUserMapper;
|
|
|
|
+import com.fs.qw.service.IQwCourseFinishRemarkRtyService;
|
|
|
|
+import com.fs.qw.service.IQwExternalContactService;
|
|
|
|
+import com.fs.qw.service.impl.QwExternalContactServiceImpl;
|
|
import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
import com.fs.qw.vo.QwUserVO;
|
|
import com.fs.qw.vo.QwUserVO;
|
|
|
|
+import com.fs.qwApi.domain.QwExternalContactRemarkResult;
|
|
|
|
+import com.fs.qwApi.param.QwExternalContactRemarkParam;
|
|
|
|
+import com.fs.qwApi.service.QwApiService;
|
|
|
|
+import com.fs.voice.utils.StringUtil;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
-import java.util.Arrays;
|
|
|
|
-import java.util.List;
|
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
+import java.util.*;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Consumer;
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
|
|
/**
|
|
/**
|
|
* 完课模板Service业务层处理
|
|
* 完课模板Service业务层处理
|
|
@@ -27,6 +44,7 @@ import java.util.function.Consumer;
|
|
* @author fs
|
|
* @author fs
|
|
* @date 2024-12-19
|
|
* @date 2024-12-19
|
|
*/
|
|
*/
|
|
|
|
+@Slf4j
|
|
@Service
|
|
@Service
|
|
public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
|
|
public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
|
|
{
|
|
{
|
|
@@ -42,6 +60,19 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
|
|
@Autowired
|
|
@Autowired
|
|
private CompanyUserMapper companyUserMapper;
|
|
private CompanyUserMapper companyUserMapper;
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ private IQwExternalContactService iQwExternalContactService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private QwApiService qwApiService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private QwExternalContactMapper qwExternalContactMapper;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private IQwCourseFinishRemarkRtyService finishRemarkRtyService;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* 查询完课模板
|
|
* 查询完课模板
|
|
*
|
|
*
|
|
@@ -175,6 +206,185 @@ public class FsCourseFinishTempServiceImpl implements IFsCourseFinishTempService
|
|
fsCourseFinishTempMapper.deleteByParentIds(ids);
|
|
fsCourseFinishTempMapper.deleteByParentIds(ids);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 完课用户 打备注
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void finishCourseExtContactIdByRemark(FsCourseWatchLog watchLog) {
|
|
|
|
+
|
|
|
|
+ Long qwExternalContactId = watchLog.getQwExternalContactId();
|
|
|
|
+
|
|
|
|
+ Date finishTime = watchLog.getFinishTime();
|
|
|
|
+ LocalDate localDate = finishTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
|
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMdd");
|
|
|
|
+ String monthDay = localDate.format(formatter);
|
|
|
|
+
|
|
|
|
+ DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("dd");
|
|
|
|
+ String dayOfMonth = localDate.format(dayFormatter);
|
|
|
|
+
|
|
|
|
+ QwUser qwUserByRedisForId = iQwExternalContactService.getQwUserByRedisForId(String.valueOf(watchLog.getQwUserId()));
|
|
|
|
+ if (qwUserByRedisForId == null || qwUserByRedisForId.getIsSendMsg() == null) {
|
|
|
|
+ log.error("无企微员工信息 {} 跳过处理。", watchLog.getQwUserId());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //不用完课备注
|
|
|
|
+ if (qwUserByRedisForId.getIsSendMsg() == 5) {
|
|
|
|
+ log.error("员工不用完课备注 {} 跳过处理。", watchLog.getQwUserId());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int isSendMsg = qwUserByRedisForId.getIsSendMsg();
|
|
|
|
+
|
|
|
|
+ QwExternalContact externalContact = iQwExternalContactService.selectQwExternalContactByRemark(qwExternalContactId);
|
|
|
|
+
|
|
|
|
+ if (externalContact != null) {
|
|
|
|
+
|
|
|
|
+ String oldRemark = externalContact.getRemark();
|
|
|
|
+ String newRemark = "";
|
|
|
|
+ String newNotes = "*" + monthDay + "完";
|
|
|
|
+ String newNotesDay = "*" + dayOfMonth + "完";
|
|
|
|
+
|
|
|
|
+ if (StringUtil.strIsNullOrEmpty(oldRemark)) {
|
|
|
|
+ oldRemark = externalContact.getName();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 2. 提取所有旧标记(无论类型)
|
|
|
|
+ List<String> allOldMarks = new ArrayList<>();
|
|
|
|
+ Pattern markPattern = Pattern.compile("\\*(\\d{1,4})完");
|
|
|
|
+ Matcher markMatcher = markPattern.matcher(oldRemark);
|
|
|
|
+ while (markMatcher.find()) {
|
|
|
|
+ allOldMarks.add(markMatcher.group());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 3. 检查是否需要更新
|
|
|
|
+ boolean shouldUpdate = true;
|
|
|
|
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
|
|
|
|
+
|
|
|
|
+ // Convert input dates to full YYYYMMDD format
|
|
|
|
+ String fullMonthDay = String.valueOf(currentYear) + monthDay; // becomes YYYYMMDD
|
|
|
|
+ String fullDayOfMonth = String.valueOf(currentYear) +
|
|
|
|
+ String.format("%02d", Calendar.getInstance().get(Calendar.MONTH) + 1) +
|
|
|
|
+ String.format("%02d", Integer.parseInt(dayOfMonth));
|
|
|
|
+
|
|
|
|
+ for (String mark : allOldMarks) {
|
|
|
|
+ Matcher numMatcher = Pattern.compile("\\*(\\d{1,4})完").matcher(mark);
|
|
|
|
+ if (numMatcher.find()) {
|
|
|
|
+ String numStr = numMatcher.group(1);
|
|
|
|
+ String fullOldDate;
|
|
|
|
+
|
|
|
|
+ if (numStr.length() <= 2) { // 处理 "*D完" 格式
|
|
|
|
+
|
|
|
|
+ int day = Integer.parseInt(numStr);
|
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
|
+ int currentMonth = cal.get(Calendar.MONTH) + 1;
|
|
|
|
+ int currentDay = cal.get(Calendar.DAY_OF_MONTH);
|
|
|
|
+ int year = cal.get(Calendar.YEAR);
|
|
|
|
+
|
|
|
|
+ // 获取上个月的最大天数
|
|
|
|
+ int prevMonth = (currentMonth == 1) ? 12 : currentMonth - 1;
|
|
|
|
+ int prevYear = (currentMonth == 1) ? year - 1 : year;
|
|
|
|
+ cal.set(prevYear, prevMonth - 1, 1); // Calendar 月份是 0-based
|
|
|
|
+ int maxDaysInPrevMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
|
|
|
+
|
|
|
|
+ // 如果 day > 上个月的天数,说明是上个月的日期
|
|
|
|
+ if (day > maxDaysInPrevMonth || day > currentDay + 7) {
|
|
|
|
+ currentMonth = prevMonth;
|
|
|
|
+ year = prevYear;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fullOldDate = String.format("%04d%02d%02d", year, currentMonth, day);
|
|
|
|
+
|
|
|
|
+ // 比较日期
|
|
|
|
+ if (Integer.parseInt(fullOldDate) >= Integer.parseInt(fullMonthDay) ||
|
|
|
|
+ Integer.parseInt(fullOldDate) >= Integer.parseInt(fullDayOfMonth)) {
|
|
|
|
+ shouldUpdate = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!shouldUpdate) {
|
|
|
|
+ return; // 不更新
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 根据 isSendMsg 决定标记格式
|
|
|
|
+ String markToAdd = (isSendMsg == 3 || isSendMsg == 4) ? newNotesDay : newNotes;
|
|
|
|
+
|
|
|
|
+ // 先移除现有标记
|
|
|
|
+ String remarkWithoutMark = oldRemark.replaceAll("\\*\\d{2,4}完", "").trim();
|
|
|
|
+
|
|
|
|
+ // 添加新标记(考虑长度限制)
|
|
|
|
+ int keepLength = 20 - markToAdd.length();
|
|
|
|
+ if (keepLength < 0) keepLength = 0;
|
|
|
|
+
|
|
|
|
+ if (isSendMsg == 1 || isSendMsg == 3) {
|
|
|
|
+ // 添加到前面
|
|
|
|
+ newRemark = markToAdd + (remarkWithoutMark.length() > keepLength ?
|
|
|
|
+ remarkWithoutMark.substring(0, keepLength) : remarkWithoutMark);
|
|
|
|
+ } else { // isSendMsg == 2 或 4
|
|
|
|
+ // 添加到后面
|
|
|
|
+ newRemark = (remarkWithoutMark.length() > keepLength ?
|
|
|
|
+ remarkWithoutMark.substring(0, keepLength) : remarkWithoutMark) + markToAdd;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QwExternalContactRemarkParam remarkParam = new QwExternalContactRemarkParam();
|
|
|
|
+ remarkParam.setRemark(newRemark);
|
|
|
|
+ remarkParam.setUserid(externalContact.getUserId());
|
|
|
|
+ remarkParam.setExternal_userid(externalContact.getExternalUserId());
|
|
|
|
+
|
|
|
|
+ for (int attempt = 1; attempt <= 2; attempt++) {
|
|
|
|
+ try {
|
|
|
|
+ QwExternalContactRemarkResult qwResult = qwApiService.externalcontactRemark(remarkParam, externalContact.getCorpId());
|
|
|
|
+ if (qwResult.getErrcode() == 0) {
|
|
|
|
+
|
|
|
|
+ QwExternalContact contactNew = new QwExternalContact();
|
|
|
|
+ contactNew.setId(externalContact.getId());
|
|
|
|
+ contactNew.setRemark(newRemark);
|
|
|
|
+ qwExternalContactMapper.updateQwExternalContact(contactNew);
|
|
|
|
+
|
|
|
|
+ log.info("完课成功添加备注:" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ if (attempt==2 && (qwResult.getErrcode() == 45033 || qwResult.getErrcode()== -1 || qwResult.getErrcode()== 60020)) {
|
|
|
|
+ QwCourseFinishRemarkRty remarkRty=new QwCourseFinishRemarkRty();
|
|
|
|
+ remarkRty.setQwUserId(externalContact.getUserId());
|
|
|
|
+ remarkRty.setCorpId(externalContact.getCorpId());
|
|
|
|
+ remarkRty.setExternalUserId(externalContact.getExternalUserId());
|
|
|
|
+ remarkRty.setExternalId(externalContact.getId());
|
|
|
|
+ remarkRty.setRemark(newRemark);
|
|
|
|
+ remarkRty.setCreateTime(new Date());
|
|
|
|
+ finishRemarkRtyService.insertOrUpdateQwCourseFinishRemarkRty(remarkRty);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ log.error("完课加备注失败:" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark + "|原因" + qwResult.getErrmsg());
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("添加备注异常 [尝试第 " + attempt + " 次]:" + externalContact.getName() + "|" + externalContact.getExternalUserId() + "|" + externalContact.getCorpId() + "|" + externalContact.getUserId() + "|" + newRemark + "|" + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 若不是最后一次尝试,则等待3秒再试
|
|
|
|
+ if (attempt < 2) {
|
|
|
|
+ try {
|
|
|
|
+ Thread.sleep(3000);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ log.warn("线程等待被中断", e);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ log.error("完课加备注失败无客户信息:" + watchLog);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
// @Override
|
|
// @Override
|
|
// public void updateFsCourseFinishTempByCompanyUserId() {
|
|
// public void updateFsCourseFinishTempByCompanyUserId() {
|
|
// List<FsCourseFinishTemp> fsCourseFinishTemps = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyList();
|
|
// List<FsCourseFinishTemp> fsCourseFinishTemps = fsCourseFinishTempMapper.selectFsCourseFinishTempByCompanyList();
|