Parcourir la source

feat(qw): 添加企业微信客户转接功能

- 新增 is_transfer 字段用于标识客户是否已转接
- 添加 QwExternalContactTransferLog 相关字段和方法
- 实现客户转接完成后的信息继承逻辑
- 重构客户转接数据同步逻辑,支持在职和离职两种场景
- 添加转接日志记录和状态管理功能
- 完善客户转接过程中的 fs_user_id 继承机制
xw il y a 1 semaine
Parent
commit
b676b047a9

+ 3 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java

@@ -518,7 +518,9 @@ public class QwExternalContactController extends BaseController
 
 
 
-
+    /**
+     * 离职继承 分配客户
+     */
     @PreAuthorize("@ss.hasPermi('qw:externalContact:transfer')")
     @Log(title = "企业微信客户", businessType = BusinessType.UPDATE)
     @PutMapping("/resignedTransfer")

+ 2 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContact.java

@@ -149,6 +149,8 @@ public class QwExternalContact extends BaseEntity
     private Integer isReply;
     // 是否被邀请进群0否1是
     private Integer joinGroup;
+    // 是否转接客户 0否 1是
+    private Integer isTransfer;
     // 广告链路唯一id
     private String traceId;
 

+ 6 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
 import com.fs.course.param.FsCourseListBySidebarParam;
 import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.domain.QwExternalContactTransferLog;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.param.*;
 import com.fs.qw.param.newparam.ExternalContactPageListParam;
@@ -139,6 +140,11 @@ public interface IQwExternalContactService extends IService<QwExternalContact> {
 
     void transferFailByExternalUserId(String externalUserID, String userID, String corpId,String failReason);
 
+    /**
+     * 转接完成:设置 is_transfer=1 并继承 fs_user_id
+     */
+    void applyTransferContactInfo(Long newContactId, QwExternalContactTransferLog transferLog, Long oldContactId);
+
     int updateQwExternalContactStatus(QwExternalContact qwExternalContact);
     /**
      *  企业微信客户与企业客户绑定

+ 49 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -1190,7 +1190,9 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                                     qwExternalContactTransferLog.setTakeoverUserId(qwUser.getQwUserId());
                                     qwExternalContactTransferLog.setCorpId(param.getCorpId());
                                     qwExternalContactTransferLog.setExternalUserId(qwCustomer.getExternal_userid());
+                                    qwExternalContactTransferLog.setHandoverQwUserId(qwExternalContact.getQwUserId());
                                     qwExternalContactTransferLog.setNeedClearTag(param.getNeedClearTag());
+                                    qwExternalContactTransferLog.setFsUserId(qwExternalContact.getFsUserId());
                                     qwExternalContactTransferLogMapper.insertQwExternalContactTransferLog(qwExternalContactTransferLog);
                                     QwExternalContact qwExternal = new QwExternalContact();
                                     qwExternal.setStatus(2);
@@ -2002,6 +2004,7 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             contact1.setTransferStatus(1);
             contact1.setExternalUserId(transferLogListByCheck.getExternalUserId());
             qwExternalContactMapper.updateQwExternalContactByUseridTransfer(contact1);
+            applyTransferContactInfo(qwExternalContact.getId(), transferLogListByCheck, null);
         }
 
 
@@ -2795,8 +2798,17 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             qwExternalContactMapper.updateQwExternalContactByUseridTransfer(contact1);
         }
 
+        Long transferOldContactId = null;
+        if (transferLogListByCheck != null) {
+            transferOldContactId = transferLogListByCheck.getExternalContactId();
+        } else if (!auditUserList.isEmpty()) {
+            transferOldContactId = auditUserList.get(0).getExternalId();
+        }
         //上面存过了,这里就更新
         qwExternalContact.setId(contact.getId());
+        if (transferLogListByCheck != null || !auditUserList.isEmpty()) {
+            fillTransferContactInfo(qwExternalContact, transferLogListByCheck, transferOldContactId);
+        }
         qwExternalContactMapper.updateQwExternalContact(qwExternalContact);
         QwOpenidByExternalcontactParams externalcontactParams = new QwOpenidByExternalcontactParams();
         externalcontactParams.setExternal_userid(externalUserID);
@@ -3365,6 +3377,9 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
         //上面存过了,这里就更新
         qwExternalContact.setId(contact.getId());
+        if (transferLogListByCheck != null) {
+            fillTransferContactInfo(qwExternalContact, transferLogListByCheck, transferLogListByCheck.getExternalContactId());
+        }
         qwExternalContactMapper.updateQwExternalContact(qwExternalContact);
         QwOpenidByExternalcontactParams externalcontactParams = new QwOpenidByExternalcontactParams();
         externalcontactParams.setExternal_userid(externalUserID);
@@ -4446,6 +4461,40 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
     }
 
+    @Override
+    public void applyTransferContactInfo(Long newContactId, QwExternalContactTransferLog transferLog, Long oldContactId) {
+        if (newContactId == null) {
+            return;
+        }
+        QwExternalContact update = new QwExternalContact();
+        update.setId(newContactId);
+        fillTransferContactInfo(update, transferLog, oldContactId);
+        qwExternalContactMapper.updateQwExternalContact(update);
+    }
+
+    private void fillTransferContactInfo(QwExternalContact target, QwExternalContactTransferLog transferLog, Long oldContactId) {
+        target.setIsTransfer(1);
+        Long fsUserId = resolveTransferFsUserId(transferLog, oldContactId);
+        if (fsUserId != null) {
+            target.setFsUserId(fsUserId);
+        }
+    }
+
+    private Long resolveTransferFsUserId(QwExternalContactTransferLog transferLog, Long oldContactId) {
+        if (transferLog != null && transferLog.getFsUserId() != null) {
+            return transferLog.getFsUserId();
+        }
+        Long sourceContactId = oldContactId;
+        if (sourceContactId == null && transferLog != null) {
+            sourceContactId = transferLog.getExternalContactId();
+        }
+        if (sourceContactId == null) {
+            return null;
+        }
+        QwExternalContact oldContact = qwExternalContactMapper.selectQwExternalContactById(sourceContactId);
+        return oldContact == null ? null : oldContact.getFsUserId();
+    }
+
     @Override
     public void transferFailByExternalUserId(String externalUserID, String userID, String corpId, String failReason) {
 

+ 64 - 54
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferLogServiceImpl.java

@@ -143,60 +143,8 @@ public class QwExternalContactTransferLogServiceImpl extends ServiceImpl<QwExter
 
                 List<QwExternalContactTransferLog> transferLogListEntry = entry.getValue();
 
-
-                QwGetTransferParam getTransferParam = new QwGetTransferParam();
-                getTransferParam.setTakeover_userid(keyPartsTakeoverUserId);
-                getTransferParam.setHandover_userid(keyPartsHandoverUserId);
-
-
-                // 第一次请求游标为空
-                String cursor = null;
-                List<QwGetTransferResult.Customer> allCustomers = new ArrayList<>();
-
-                int page = 0;
-                do {
-                    page++;
-
-                    // 设置游标(第一次请求可能不需要设置或设为空)
-                    if (cursor != null) {
-                        getTransferParam.setCursor(cursor);
-                    }
-
-                    // 调用接口
-                    QwGetTransferResult transfer = qwApiService.getTransfer(getTransferParam, keyPartsCorpId);
-
-                    // 检查接口返回是否成功
-                    if (transfer.getErrcode() != 0) {
-                        log.error("获取转移记录失败: errcode={}, errmsg={}, takeover_userid={}, handover_userid={}",
-                                transfer.getErrcode(), transfer.getErrmsg(),
-                                keyPartsTakeoverUserId, keyPartsHandoverUserId);
-                        break;
-                    }
-
-                    // 获取当前页数据
-                    List<QwGetTransferResult.Customer> customers = transfer.getCustomer();
-                    if (customers != null && !customers.isEmpty()) {
-                        allCustomers.addAll(customers);
-                        log.info("第 {} 页获取到 {} 条转移记录", page, customers.size());
-                    } else {
-                        log.info("第 {} 页没有数据", page);
-                        // 如果没有数据,也退出循环
-                        break;
-                    }
-
-                    // 更新游标,准备下一次请求
-                    cursor = transfer.getNext_cursor();
-
-                    // 添加短暂延时,避免请求过快
-                    try {
-                        Thread.sleep(200);
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                        break;
-                    }
-
-                    // 如果next_cursor为空或没有更多数据,则退出循环
-                } while (cursor != null && !cursor.isEmpty() && !"0".equals(cursor));
+                List<QwGetTransferResult.Customer> allCustomers = fetchAllTransferCustomers(
+                        keyPartsCorpId, keyPartsTakeoverUserId, keyPartsHandoverUserId);
 
                 List<QwExternalContactTransferLog> transferLogList=new ArrayList<>();
 
@@ -225,6 +173,13 @@ public class QwExternalContactTransferLogServiceImpl extends ServiceImpl<QwExter
                             qwExternalContact.setUserId(transferLog.getTakeoverUserId());
                             qwExternalContact.setQwUserId(transferLog.getQwUserId());
                             qwExternalContact.setCompanyUserId(transferLog.getCompanyUserId());
+
+                            QwExternalContact takeoverContact = qwExternalContactMapper.selectQwExternalContactUserIdAndExternalIdAndCompanyId(
+                                    transferLog.getExternalUserId(), transferLog.getTakeoverUserId(), transferLog.getCorpId());
+                            if (takeoverContact != null) {
+                                iQwExternalContactService.applyTransferContactInfo(
+                                        takeoverContact.getId(), transferLog, transferLog.getExternalContactId());
+                            }
                         }
                         contactList.add(qwExternalContact);
                     }
@@ -264,4 +219,59 @@ public class QwExternalContactTransferLogServiceImpl extends ServiceImpl<QwExter
         qwExternalContactTransferLogMapper.updateQwExternalContactByStatus();
         qwExternalContactTransferLogMapper.updateQwExternalContactTransferLogByStatus();
     }
+
+    private List<QwGetTransferResult.Customer> fetchAllTransferCustomers(String corpId, String takeoverUserId, String handoverUserId) {
+        List<QwGetTransferResult.Customer> onJobCustomers = fetchTransferCustomers(corpId, takeoverUserId, handoverUserId, true);
+        if (!onJobCustomers.isEmpty()) {
+            return onJobCustomers;
+        }
+        return fetchTransferCustomers(corpId, takeoverUserId, handoverUserId, false);
+    }
+
+    private List<QwGetTransferResult.Customer> fetchTransferCustomers(String corpId, String takeoverUserId, String handoverUserId, boolean onJobTransfer) {
+        QwGetTransferParam getTransferParam = new QwGetTransferParam();
+        getTransferParam.setTakeover_userid(takeoverUserId);
+        getTransferParam.setHandover_userid(handoverUserId);
+
+        String cursor = null;
+        List<QwGetTransferResult.Customer> allCustomers = new ArrayList<>();
+        int page = 0;
+
+        do {
+            page++;
+            if (cursor != null) {
+                getTransferParam.setCursor(cursor);
+            }
+
+            QwGetTransferResult transfer = onJobTransfer
+                    ? qwApiService.getTransfer(getTransferParam, corpId)
+                    : qwApiService.getResignedTransfer(getTransferParam, corpId);
+
+            if (transfer.getErrcode() != 0) {
+                log.warn("获取{}转移记录失败: errcode={}, errmsg={}, takeover_userid={}, handover_userid={}",
+                        onJobTransfer ? "在职" : "离职",
+                        transfer.getErrcode(), transfer.getErrmsg(),
+                        takeoverUserId, handoverUserId);
+                break;
+            }
+
+            List<QwGetTransferResult.Customer> customers = transfer.getCustomer();
+            if (customers == null || customers.isEmpty()) {
+                break;
+            }
+
+            allCustomers.addAll(customers);
+            log.info("获取{}转移记录第 {} 页: {} 条", onJobTransfer ? "在职" : "离职", page, customers.size());
+
+            cursor = transfer.getNext_cursor();
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                break;
+            }
+        } while (cursor != null && !cursor.isEmpty() && !"0".equals(cursor));
+
+        return allCustomers;
+    }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceAsyncHelperImpl.java

@@ -1122,6 +1122,8 @@ public class QwUserServiceAsyncHelperImpl implements IQwUserServiceAsyncHelper {
                                         qwExternalContactTransferLog.setCorpId(param.getCorpId());
                                         qwExternalContactTransferLog.setExternalUserId(qwCustomer.getExternal_userid());
                                         qwExternalContactTransferLog.setHandoverQwUserId(qwExternalContact.getQwUserId());
+                                        qwExternalContactTransferLog.setNeedClearTag(param.getNeedClearTag());
+                                        qwExternalContactTransferLog.setFsUserId(qwExternalContact.getFsUserId());
                                         qwExternalContactTransferLogMapper.insertQwExternalContactTransferLog(qwExternalContactTransferLog);
                                         QwExternalContact qwExternal = new QwExternalContact();
                                         qwExternal.setStatus(2);
@@ -1229,6 +1231,9 @@ public class QwUserServiceAsyncHelperImpl implements IQwUserServiceAsyncHelper {
                                         qwExternalContactTransferLog.setTakeoverUserId(qwUser.getQwUserId());
                                         qwExternalContactTransferLog.setCorpId(param.getCorpId());
                                         qwExternalContactTransferLog.setExternalUserId(qwCustomer.getExternal_userid());
+                                        qwExternalContactTransferLog.setHandoverQwUserId(qwExternalContact.getQwUserId());
+                                        qwExternalContactTransferLog.setNeedClearTag(param.getNeedClearTag());
+                                        qwExternalContactTransferLog.setFsUserId(qwExternalContact.getFsUserId());
                                         qwExternalContactTransferLogMapper.insertQwExternalContactTransferLog(qwExternalContactTransferLog);
                                         QwExternalContact qwExternal = new QwExternalContact();
                                         qwExternal.setStatus(2);

+ 5 - 1
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -44,10 +44,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="lastWatchTime"    column="last_watch_time"    />
         <result property="registerTime"    column="register_time"    />
         <result property="isReply"    column="is_reply"    />
+        <result property="isTransfer"    column="is_transfer"    />
     </resultMap>
 
     <sql id="selectQwExternalContactVo">
-        select id,qw_user_id,register_time,state,way_id,stage_status,first_time,open_id,is_interact,level, unionid, user_id,transfer_time,loss_time,del_time,transfer_num, external_user_id,transfer_status,status,create_time, name, avatar, type, gender, remark, description, tag_ids, remark_mobiles, remark_corp_name, add_way, oper_userid, corp_id, company_id, company_user_id, customer_id, fs_user_id,is_reply from qw_external_contact
+        select id,qw_user_id,register_time,state,way_id,stage_status,first_time,open_id,is_interact,level, unionid, user_id,transfer_time,loss_time,del_time,transfer_num, external_user_id,transfer_status,status,create_time, name, avatar, type, gender, remark, description, tag_ids, remark_mobiles, remark_corp_name, add_way, oper_userid, corp_id, company_id, company_user_id, customer_id, fs_user_id,is_reply,is_transfer from qw_external_contact
     </sql>
 
     <select id="selectQwExternalContactList" parameterType="QwExternalContact" resultMap="QwExternalContactResult">
@@ -282,6 +283,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="levelType != null">level_type,</if>
             <if test="firstTime != null">first_time,</if>
             <if test="registerTime != null">register_time,</if>
+            <if test="isTransfer != null">is_transfer,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
@@ -321,6 +323,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="levelType != null">#{levelType},</if>
             <if test="firstTime != null">#{firstTime},</if>
             <if test="registerTime != null">#{registerTime},</if>
+            <if test="isTransfer != null">#{isTransfer},</if>
          </trim>
     </insert>
 
@@ -363,6 +366,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="levelType != null">level_type = #{levelType},</if>
             <if test="firstTime != null">first_time = #{firstTime},</if>
             <if test="registerTime != null">register_time = #{registerTime},</if>
+            <if test="isTransfer != null">is_transfer = #{isTransfer},</if>
         </trim>
         where id = #{id}
     </update>