소스 검색

feat(customer): 完善客户团队成员管理功能

- 新增客户时自动初始化销售负责人和服务客服团队成员
- 添加saveOrUpdateTeamMember方法统一处理团队成员的增改操作
- 实现团队成员的软删除和恢复机制,确保唯一性约束
- 在转移业务人员和客服人员时同步更新团队成员信息
- 优化团队成员查询和更新的事务处理逻辑
- 添加平台数据范围过滤器对team_member表的支持
hurx 3 일 전
부모
커밋
73cd23d363

+ 2 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java

@@ -126,7 +126,8 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "mini_page_set",
         "maintain_info",
         "maintenance_server_item",
-        "ep_"
+        "ep_",
+        "team_member"
         // 注意:前缀匹配需特殊处理(如 qrtz_),见 isIgnoreTable 方法
     ));
 

+ 9 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/TeamMemberMapper.java

@@ -37,6 +37,15 @@ public interface TeamMemberMapper extends BaseMapperPlus<TeamMember, TeamMemberV
      */
     TeamMemberVo selectByObjectNoAndUserNoWithDeleted(@Param("objectNo") String objectNo, @Param("userNo") Long userNo);
 
+    /**
+     * 根据对象编号和角色编码查询团队成员(包括已删除的)
+     *
+     * @param objectNo 对象编号(如客户编号)
+     * @param roleCode 角色编码
+     * @return 团队成员信息
+     */
+    TeamMemberVo selectByObjectNoAndRoleCodeWithDeleted(@Param("objectNo") String objectNo, @Param("roleCode") String roleCode);
+
     /**
      * 恢复已删除的团队成员记录
      */

+ 120 - 42
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -35,9 +35,7 @@ import org.dromara.system.api.*;
 import org.dromara.system.api.domain.bo.RemoteUserBo;
 import org.dromara.system.api.domain.dto.AddressAreaDTO;
 import org.dromara.system.api.domain.vo.RemoteDeptVo;
-import org.dromara.system.api.domain.vo.RemoteComStaffVo;
 import org.dromara.system.api.domain.vo.RemoteDictDataVo;
-import org.dromara.system.api.domain.dto.AddressAreaDTO;
 import org.dromara.system.api.domain.vo.RemoteUserWechatVo;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -857,6 +855,33 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
             String customerNo = entity.getCustomerNo();
 
+            // 团队成员初始化逻辑
+            Set<Long> staffIds = new HashSet<>();
+            if (entity.getSalesPersonId() != null) {
+                staffIds.add(entity.getSalesPersonId());
+            }
+            if (entity.getServiceStaffId() != null) {
+                staffIds.add(entity.getServiceStaffId());
+            }
+
+            // 只有当有相关人员时才进行远程查询和入库
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+
+            // 使用提取的方法处理负责人
+            if (entity.getSalesPersonId() != null) {
+                saveOrUpdateTeamMember(customerNo, entity.getSalesPersonId(),
+                    staffNameMap.get(entity.getSalesPersonId()), "1", 1, 1);
+            }
+
+            // 使用提取的方法处理客服
+            if (entity.getServiceStaffId() != null) {
+                saveOrUpdateTeamMember(customerNo, entity.getServiceStaffId(),
+                    staffNameMap.get(entity.getServiceStaffId()), "3", 0, 1);
+            }
+
             /*新增客户时给每个客户创建自己的组织架构*/
             RemoteDeptVo remoteDeptVo = new RemoteDeptVo();
             remoteDeptVo.setParentId(0L);
@@ -964,6 +989,78 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
     }
 
+    /**
+     * 保存或更新团队成员信息
+     * 如果成员已存在但被删除,则恢复;否则新增
+     *
+     * @param objectNo      客户编号
+     * @param userNo        人员ID
+     * @param realName      人员姓名
+     * @param roleCode      角色编码 (1:负责人, 2:客服)
+     * @param izManager     是否主管
+     * @param updateAccredit 授权更新标识
+     */
+    /**
+     * 保存或更新团队成员信息(公用方法)
+     * 确保一个客户的团队中只能有一个 roleCode=1 的负责人和一个 roleCode=2 的客服支持
+     *
+     * @param objectNo       客户编号
+     * @param userNo         人员ID
+     * @param realName       人员姓名
+     * @param roleCode       角色编码 (1:负责人, 2:客服)
+     * @param izManager      是否主管
+     * @param updateAccredit 授权更新标识
+     */
+    public void saveOrUpdateTeamMember(String objectNo, Long userNo, String realName,
+                                       String roleCode, Integer izManager, Integer updateAccredit) {
+        if (userNo == null || StringUtils.isBlank(objectNo)) {
+            return;
+        }
+
+        // 1. 查找该客户下指定角色的现有成员(包括已删除的)
+        TeamMemberVo existing = teamMemberMapper.selectByObjectNoAndRoleCodeWithDeleted(objectNo, roleCode);
+
+        if (existing != null && !existing.getUserNo().equals(userNo)) {
+            // 2. 如果存在不同的人员占据该角色,先将其软删除或更新状态
+            teamMemberMapper.update(null, new LambdaUpdateWrapper<TeamMember>()
+                .set(TeamMember::getIsDelete, 1)
+                .eq(TeamMember::getId, existing.getId()));
+        }
+
+        // 3. 查找新人员是否已在该客户团队中(任意角色)
+        TeamMemberVo existingUser = teamMemberMapper.selectByObjectNoAndUserNoWithDeleted(objectNo, userNo);
+
+        if (existingUser != null) {
+            // 4. 如果人员已存在,恢复并更新其角色信息
+            teamMemberMapper.restoreMemberById(
+                existingUser.getId(),
+                userNo,
+                realName,
+                roleCode,
+                updateAccredit,
+                izManager,
+                LoginHelper.getUserId(),
+                LoginHelper.getDeptId(),
+                PlatformContext.getPlatform()
+            );
+        } else {
+            // 5. 如果人员不存在,执行新增
+            TeamMember member = new TeamMember();
+            member.setDataType(12); // 12 代表客户类型
+            member.setObjectNo(objectNo);
+            member.setUserNo(userNo);
+            member.setRealName(realName);
+            member.setRoleCode(roleCode);
+            member.setIzManager(izManager);
+            member.setUpdateAccredit(updateAccredit);
+            member.setPlatformCode(PlatformContext.getPlatform());
+            member.setCreateUserId(LoginHelper.getUserId());
+            member.setCreateOrgId(LoginHelper.getDeptId());
+            member.setIsDelete(0);
+            teamMemberMapper.insert(member);
+        }
+    }
+
     /**
      * 修改客户信息
      *
@@ -1543,24 +1640,23 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             return 0;
         }
 
-        if (salesPersonId == null ) {
-            log.warn("转移业务人员失败,业务人员 ID 为空");
-            throw new ServiceException("业务人员不能为空");
-        }
-
         try {
+            // 获取新业务员的姓名
+            Map<Long, String> staffMap = remoteComStaffService.selectStaffNameByIds(Collections.singleton(salesPersonId));
+            String realName = staffMap.get(salesPersonId);
+
             List<CustomerInfo> updateList = new ArrayList<>();
-            CustomerInfo customerInfo = null;
             for (Long customerId : customerIds) {
-                if (customerId == null) {
-                    continue;
-                }
+                if (customerId == null) continue;
 
-                customerInfo = baseMapper.selectById(customerId);
+                CustomerInfo customerInfo = baseMapper.selectById(customerId);
                 if (customerInfo != null) {
                     customerInfo.setSalesPersonId(salesPersonId);
                     customerInfo.setBelongingDepartmentId(deptId);
                     updateList.add(customerInfo);
+
+                    // 同步更新团队成员:角色 1 为负责人
+                    saveOrUpdateTeamMember(customerInfo.getCustomerNo(), salesPersonId, realName, "1", 1, 1);
                 } else {
                     log.warn("客户 ID: {} 不存在,跳过更新", customerId);
                 }
@@ -1573,17 +1669,12 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                         updateList.size(), salesPersonId, deptId);
                     return updateList.size();
                 } else {
-                    log.error("批量更新客户信息失败");
                     throw new ServiceException("批量更新客户信息失败");
                 }
             }
-
-            log.info("没有需要更新的客户销售信息");
             return 0;
-
         } catch (Exception e) {
-            log.error("转移业务人员失败,客户 IDs: {}, 业务员 ID: {}, 部门 ID: {}, 错误:{}",
-                customerIds, salesPersonId, deptId, e.getMessage(), e);
+            log.error("转移业务人员失败,错误:{}", e.getMessage(), e);
             throw new ServiceException("转移业务人员失败:" + e.getMessage());
         }
     }
@@ -1591,28 +1682,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int transferServiceStaff(List<Long> customerIds, Long serviceStaffId) {
-        if (CollUtil.isEmpty(customerIds)) {
-            log.warn("转移客服人员失败,客户 ID 列表为空");
+        if (CollUtil.isEmpty(customerIds) || serviceStaffId == null) {
             return 0;
         }
 
-        if (serviceStaffId == null) {
-            log.warn("转移客服人员失败,客服人员 ID 为空");
-            throw new ServiceException("客服人员和不能为空");
-        }
-
         try {
+            // 获取新客服的姓名
+            Map<Long, String> staffMap = remoteComStaffService.selectStaffNameByIds(Collections.singleton(serviceStaffId));
+            String realName = staffMap.get(serviceStaffId);
+
             List<CustomerInfo> updateList = new ArrayList<>();
-            CustomerInfo customerInfo = null;
             for (Long customerId : customerIds) {
-                if (customerId == null) {
-                    continue;
-                }
+                if (customerId == null) continue;
 
-                customerInfo = baseMapper.selectById(customerId);
+                CustomerInfo customerInfo = baseMapper.selectById(customerId);
                 if (customerInfo != null) {
                     customerInfo.setServiceStaffId(serviceStaffId);
                     updateList.add(customerInfo);
+
+                    // 同步更新团队成员:角色 3 为客服支持
+                    saveOrUpdateTeamMember(customerInfo.getCustomerNo(), serviceStaffId, realName, "3", 0, 1);
                 } else {
                     log.warn("客户 ID: {} 不存在,跳过更新", customerId);
                 }
@@ -1625,25 +1714,14 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                         updateList.size(), serviceStaffId);
                     return updateList.size();
                 } else {
-                    log.error("批量更新客户信息失败");
                     throw new ServiceException("批量更新客户信息失败");
                 }
             }
-
-            log.info("没有需要更新的客户销售信息");
             return 0;
-
         } catch (Exception e) {
-            log.error("转移客服人员失败,客户 IDs: {}, 客服人员 ID: {},  错误:{}",
-                customerIds, serviceStaffId, e.getMessage(), e);
+            log.error("转移客服人员失败,错误:{}", e.getMessage(), e);
             throw new ServiceException("转移客服人员失败:" + e.getMessage());
         }
-
-        // 直接进行批量更新
-//        return baseMapper.update(null, new LambdaUpdateWrapper<CustomerInfo>()
-//            .set(CustomerInfo::getServiceStaffId, serviceStaffId)
-//            .in(CustomerInfo::getId, customerIds)
-//        );
     }
 
     /**

+ 7 - 0
ruoyi-modules/ruoyi-customer/src/main/resources/mapper/customer/TeamMemberMapper.xml

@@ -29,6 +29,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LIMIT 1
     </select>
 
+    <select id="selectByObjectNoAndRoleCodeWithDeleted" resultType="org.dromara.customer.domain.vo.TeamMemberVo">
+        SELECT * FROM team_member
+        WHERE object_no = #{objectNo} AND role_code = #{roleCode}
+        ORDER BY is_delete ASC, update_time DESC
+        LIMIT 1
+    </select>
+
     <update id="restoreMemberById">
         UPDATE team_member SET 
             is_delete = 0,