Forráskód Böngészése

feat(customer): 实现客户数据权限过滤和员工查询功能

- 修改员工服务默认类型从"3"改为"0"
- 添加通过用户ID查询员工信息的方法
- 集成登录助手实现数据权限控制
- 添加客户列表数据权限过滤逻辑
- 在客户审核流程中增加收货地址验证
- 完善客户销售信息必填字段校验
- 改进订单数据源查询条件处理
- 修正联系人创建时的角色分配
- 优化序列号生成规则实现客户独立计数
hurx 4 napja
szülő
commit
f9ea936c85

+ 2 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComStaffService.java

@@ -22,4 +22,6 @@ public interface RemoteComStaffService {
 
     RemoteComStaffVo selectStaffByStaffName(String staffName);
 
+    RemoteComStaffVo selectStaffByUserId(Long userId);
+
 }

+ 2 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteComStaffVo.java

@@ -27,6 +27,8 @@ public class RemoteComStaffVo implements Serializable {
      */
     private String staffCode;
 
+    private Long userId;
+
     /**
      * 姓名
      */

+ 14 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java

@@ -15,6 +15,7 @@ import org.dromara.common.log.annotation.Log;
 import org.dromara.common.log.enums.BusinessType;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.web.core.BaseController;
 import org.dromara.customer.domain.bo.CustomerClaimBo;
 import org.dromara.customer.domain.bo.CustomerInfoBo;
@@ -30,6 +31,7 @@ import org.dromara.system.api.RemoteProductTaxrateService;
 import org.dromara.system.api.*;
 import org.dromara.system.api.domain.vo.RemoteComCompanyVo;
 import org.dromara.system.api.domain.vo.RemoteComCustomerLevelVo;
+import org.dromara.system.api.domain.vo.RemoteComStaffVo;
 import org.springframework.http.MediaType;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -77,6 +79,18 @@ public class CustomerInfoController extends BaseController {
      */
     @GetMapping("/list")
     public TableDataInfo<CustomerInfoVo> list(CustomerInfoBo bo, PageQuery pageQuery) {
+        Long userId = LoginHelper.getLoginUser().getUserId();
+        RemoteComStaffVo remoteComStaffVo = remoteComStaffService.selectStaffByUserId(userId);
+
+        // 设置数据权限过滤:只能查看自己创建的、或者是业务负责人、或者是客服支持的客户
+        if (remoteComStaffVo != null && remoteComStaffVo.getStaffId() != null) {
+            Long staffId = remoteComStaffVo.getStaffId();
+            // 将权限条件传递到查询条件中
+            bo.setCreateBy(userId);
+            bo.setSalesPersonId(staffId);
+            bo.setServiceStaffId(staffId);
+        }
+
         return customerInfoService.queryPageList(bo, pageQuery);
     }
 

+ 67 - 20
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -107,6 +107,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     private final SupplierBusinessInfoMapper supplierBusinessInfoMapper;
     private final TeamMemberMapper teamMemberMapper;
     private final CrmStaffMapper crmStaffMapper;
+    private final CustomerShippingAddressMapper shippingAddressMapper;
 
 
     /**
@@ -733,19 +734,37 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<CustomerInfo> lqw = Wrappers.lambdaQuery();
         lqw.orderByDesc(CustomerInfo::getId);
-        String platformCode = PlatformContext.getPlatform();
-        if (ObjectUtils.isNotEmpty(platformCode) && "market".equals(platformCode)) {
-            Long userId = LoginHelper.getLoginUser().getUserId();
-            if (null != userId) {
-                lqw.and(wrapper -> wrapper
-                    .eq(CustomerInfo::getCreateBy, userId)
-                    .or()
-                    .eq(CustomerInfo::getCreateBy, 1L)
-                    .or()
-                    .eq(CustomerInfo::getCreateBy, -1L)
-                );
-            }
+
+        // 数据权限过滤:只能查看自己创建的、或者是业务负责人、或者是客服支持的客户
+        if (bo.getCreateBy() != null || bo.getSalesPersonId() != null || bo.getServiceStaffId() != null) {
+            lqw.and(wrapper -> {
+                boolean first = true;
+                if (bo.getCreateBy() != null) {
+                    if (first) {
+                        wrapper.eq(CustomerInfo::getCreateBy, bo.getCreateBy());
+                        first = false;
+                    } else {
+                        wrapper.or().eq(CustomerInfo::getCreateBy, bo.getCreateBy());
+                    }
+                }
+                if (bo.getSalesPersonId() != null) {
+                    if (first) {
+                        wrapper.eq(CustomerInfo::getSalesPersonId, bo.getSalesPersonId());
+                        first = false;
+                    } else {
+                        wrapper.or().eq(CustomerInfo::getSalesPersonId, bo.getSalesPersonId());
+                    }
+                }
+                if (bo.getServiceStaffId() != null) {
+                    if (first) {
+                        wrapper.eq(CustomerInfo::getServiceStaffId, bo.getServiceStaffId());
+                    } else {
+                        wrapper.or().eq(CustomerInfo::getServiceStaffId, bo.getServiceStaffId());
+                    }
+                }
+            });
         }
+
         lqw.eq(StringUtils.isNotBlank(bo.getCustomerNo()), CustomerInfo::getCustomerNo, bo.getCustomerNo());
         lqw.eq(bo.getBelongCompanyId() != null, CustomerInfo::getBelongCompanyId, bo.getBelongCompanyId());
         lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CustomerInfo::getCompanyName, bo.getCompanyName());
@@ -771,8 +790,6 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         lqw.eq(StringUtils.isNotBlank(bo.getProvincialCityCounty()), CustomerInfo::getProvincialCityCounty, bo.getProvincialCityCounty());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CustomerInfo::getStatus, bo.getStatus());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), CustomerInfo::getPlatformCode, bo.getPlatformCode());
-        lqw.eq(bo.getSalesPersonId() != null, CustomerInfo::getSalesPersonId, bo.getSalesPersonId());
-        lqw.eq(bo.getServiceStaffId() != null, CustomerInfo::getServiceStaffId, bo.getServiceStaffId());
         lqw.eq(bo.getBelongingDepartmentId() != null, CustomerInfo::getBelongingDepartmentId, bo.getBelongingDepartmentId());
         Object isHighSeasObj = StringUtils.isNotBlank(bo.getIsHighSeas()) ? bo.getIsHighSeas() : bo.getParams().get("isHighSeas");
         String isHighSeasStr = (isHighSeasObj != null) ? StringUtils.lowerCase(String.valueOf(isHighSeasObj)) : "false";
@@ -907,6 +924,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                     String defaultPassword = "123456";
                     remoteUserBo.setPassword(BCrypt.hashpw(defaultPassword));
                     remoteUserBo.setUserSonType("3");
+                    remoteUserBo.setRoleIds(new Long[]{contactBo.getRoleId()});
                     remoteUserBo.setTenantId(LoginHelper.getTenantId());
 
                     // 2. 调用远程服务创建用户
@@ -919,8 +937,15 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                     // 3. 转换并填充业务联系人数据
                     CustomerContact contact = MapstructUtils.convert(contactBo, CustomerContact.class);
                     contact.setCustomerId(customerId);
-                    String seqId = SequenceUtils.nextPaddedIdStr(CONTACT_NO_KEY, Duration.ofDays(3650), 3);
-                    String contactNo = customerNo + seqId;
+                    // 1. 构造带客户编号的 Key,实现“每个客户独立计数”
+                    String seqKey = "customer_contact:contact_no:" + customerNo;
+
+                    // 2. 调用工具类
+                    String seqId = SequenceUtils.nextPaddedIdStr(seqKey, Duration.ofDays(3650), 4);
+
+                    // 3. 拼接最终结果
+                    String contactNo = "1" + customerNo + seqId;
+
                     // 建立关联
                     contact.setUserId(userId);
                     contact.setContactNo(contactNo);
@@ -1054,6 +1079,28 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
     @Override
     public int updateCustomerCheckStatus(Long customerId, String status) {
+        CustomerInfoVo customerInfo = baseMapper.selectVoById(customerId);
+        if (ObjectUtils.isNotEmpty(customerInfo)) {
+            List<CustomerShippingAddressVo> shippingAddressVos = shippingAddressMapper.selectVoList(new LambdaQueryWrapper<CustomerShippingAddress>().eq(CustomerShippingAddress::getCustomerId, customerInfo.getId()));
+            if (null == shippingAddressVos || shippingAddressVos.size() == 0) {
+                throw new ServiceException("客户收货地址不能为空");
+            }
+            CustomerSalesInfoVo salesInfoVo = customerSalesInfoMapper.selectVoOne(new LambdaQueryWrapper<CustomerSalesInfo>().eq(CustomerSalesInfo::getCustomerId, customerInfo.getId()).last("LIMIT 1"));
+            if (ObjectUtils.isNotEmpty(salesInfoVo)) {
+                if (null == salesInfoVo.getSalesPersonId()) {
+                    throw new ServiceException("ERP销售人员业务人员不能为空");
+                }
+                if (null == salesInfoVo.getServiceStaffId()) {
+                    throw new ServiceException("ERP销售人员客服人员不能为空");
+                }
+                if (null == salesInfoVo.getSettlementMethod()) {
+                    throw new ServiceException("ERP销售人员结算方式不能为空");
+                }
+                if (null == salesInfoVo.getCreditLevel()) {
+                    throw new ServiceException("ERP销售人员信用等级不能为空");
+                }
+            }
+        }
         return baseMapper.update(null,
             new LambdaUpdateWrapper<CustomerInfo>()
                 .set(CustomerInfo::getStatus, status)
@@ -1391,7 +1438,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             remoteUserWechatVo.setPhoneNumber(bo.getPurchasePhone());
             remoteUserWechatVo.setNickname(bo.getPurchaseName());
             remoteUserWechatService.insertUserWechat(remoteUserWechatVo);
-        }else if ("3".equals(bo.getRegisterSource())){
+        } else if ("3".equals(bo.getRegisterSource())) {
             RemoteUserWechatVo remoteUserWechatVo = new RemoteUserWechatVo();
             remoteUserWechatVo.setGzhOpenId(bo.getOpenId());
             remoteUserWechatVo.setUserId(userId);
@@ -1504,9 +1551,9 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             return 0;
         }
 
-        if (salesPersonId == null || deptId == null) {
-            log.warn("转移业务人员失败,业务人员 ID 或部门 ID 为空");
-            throw new ServiceException("业务人员和所属部门不能为空");
+        if (salesPersonId == null ) {
+            log.warn("转移业务人员失败,业务人员 ID 为空");
+            throw new ServiceException("业务人员不能为空");
         }
 
         try {

+ 15 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderMainBo.java

@@ -346,6 +346,21 @@ public class OrderMainBo extends BaseEntity {
      */
     private Long contactId;
 
+    /**
+     * 客户创建者ID(用于数据权限过滤)
+     */
+    private Long customerCreateBy;
+
+    /**
+     * 客户业务负责人ID(用于数据权限过滤)
+     */
+    private Long customerSalesPersonId;
+
+    /**
+     * 客户客服支持ID(用于数据权限过滤)
+     */
+    private Long customerServiceStaffId;
+
     List<OrderProductBo> orderProductBos;
 
     /*订单编号前缀*/

+ 10 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderMainVo.java

@@ -472,4 +472,14 @@ public class OrderMainVo implements Serializable {
      */
     private Long contactId;
 
+    /**
+     * 分配备注
+     */
+    private String assigneeRemark;
+
+    /**
+     * 分配对象名称
+     */
+    private String assigneeName;
+
 }

+ 58 - 2
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -31,7 +31,10 @@ import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
 import org.dromara.external.api.zhongche.domain.bo.OrderRejectBo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
 import org.dromara.order.domain.*;
-import org.dromara.order.domain.bo.*;
+import org.dromara.order.domain.bo.ApiSubmitOrderBo;
+import org.dromara.order.domain.bo.OrderMainBo;
+import org.dromara.order.domain.bo.OrderProductBo;
+import org.dromara.order.domain.bo.PcSubmitOrderBo;
 import org.dromara.order.domain.dto.AssignmentStatsDto;
 import org.dromara.order.domain.vo.*;
 import org.dromara.order.mapper.*;
@@ -224,6 +227,44 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
                 }
             }
         }
+        OrderAssignment orderAssignment = orderAssignmentService.getOne(new LambdaQueryWrapper<OrderAssignment>().eq(OrderAssignment::getChildOrderId, id).last("Limit 1"));
+        if (ObjectUtils.isNotEmpty(orderAssignment)) {
+            List<Long> customerIds = new ArrayList<>();
+            List<Long> supplierIds = new ArrayList<>();
+            List<Long> partnerIds = new ArrayList<>();
+            String type = orderAssignment.getAssigneeType();
+            if (AssigneeTypeConstants.CUSTOMER.getCode().equals(type)) {
+                customerIds.add(orderAssignment.getAssigneeId());
+            } else if (AssigneeTypeConstants.SUPPLIER.getCode().equals(type)) {
+                supplierIds.add(orderAssignment.getAssigneeId());
+            } else if (AssigneeTypeConstants.PARTNER.getCode().equals(type)) {
+                partnerIds.add(orderAssignment.getAssigneeId());
+            }
+            Map<Long, String> customerNameMap = Collections.emptyMap();
+            Map<Long, String> supplierNameMap = Collections.emptyMap();
+            Map<Long, String> partnerNameMap = Collections.emptyMap();
+
+            if (!customerIds.isEmpty()) {
+                customerNameMap = remoteCustomerService.selectCustomerNameByIds(new HashSet<>(customerIds));
+            }
+            if (!supplierIds.isEmpty()) {
+                supplierNameMap = remoteSupplierInfoService.selectSupplierNameByIds(new HashSet<>(supplierIds));
+            }
+            if (!partnerIds.isEmpty()) {
+                partnerNameMap = remotePartnerInfoService.selectPartnerNameByIds(new HashSet<>(partnerIds));
+            }
+            orderMainVo.setAssigneeRemark(orderAssignment.getRemark());
+            String assigneeName = null;
+            if (AssigneeTypeConstants.CUSTOMER.getCode().equals(type)) {
+                assigneeName = customerNameMap.get(orderAssignment.getAssigneeId());
+            } else if (AssigneeTypeConstants.SUPPLIER.getCode().equals(type)) {
+                assigneeName = supplierNameMap.get(orderAssignment.getAssigneeId());
+            } else if (AssigneeTypeConstants.PARTNER.getCode().equals(type)) {
+                assigneeName = partnerNameMap.get(orderAssignment.getAssigneeId());
+            }
+            orderMainVo.setAssigneeName(assigneeName);
+        }
+
         // 3. 组装数据
         orderMainVo.setOrderProductList(orderProductVoList);
 
@@ -417,6 +458,16 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         lqw.eq(StringUtils.isNotBlank(bo.getIsNeedCheck()), OrderMain::getIsNeedCheck, bo.getIsNeedCheck());
         lqw.eq(StringUtils.isNotBlank(bo.getReturnedStatus()), OrderMain::getReturnedStatus, bo.getReturnedStatus());
         lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), OrderMain::getOrderType, bo.getOrderType());
+        if (ObjectUtils.isNotEmpty(bo.getDataSource())){
+            if ("1".equals(bo.getDataSource())){
+                // dataSource="1" 时,查询 dataSource 为空或 null 的数据
+                lqw.and(wrapper -> wrapper.isNull(OrderMain::getDataSource).or().eq(OrderMain::getDataSource, ""));
+            } else {
+                // 其他值时,查询 dataSource 不为空的数据
+                lqw.isNotNull(OrderMain::getDataSource);
+                lqw.ne(OrderMain::getDataSource, "");
+            }
+        }
 
         // 处理 currentLevelStr:支持单个值"1"或多个值"1,2"
         if (StringUtils.isNotBlank(bo.getCurrentLevelStr())) {
@@ -1212,7 +1263,12 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         }
         String orderNo = orderMain.getOrderNo();
         // 查扩展表拿中车订单号(ID一致!)
-        OrderMainCrrcExt ext = orderMainCrrcExtService.getById(id);
+        OrderMainCrrcExt ext = null;
+        if (null != orderMain.getParentOrderId()) {
+            ext = orderMainCrrcExtService.getById(orderMain.getParentOrderId());
+        } else {
+            ext = orderMainCrrcExtService.getById(id);
+        }
         if (ext == null) {
             throw new ZhongcheException("中车订单扩展信息不存在");
         }

+ 5 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComStaffServiceImpl.java

@@ -41,4 +41,9 @@ public class RemoteComStaffServiceImpl implements RemoteComStaffService {
     public RemoteComStaffVo selectStaffByStaffName(String staffName) {
         return BeanUtil.toBean(comStaffService.selectStaffByStaffName(staffName), RemoteComStaffVo.class);
     }
+
+    @Override
+    public RemoteComStaffVo selectStaffByUserId(Long userId) {
+        return BeanUtil.toBean(comStaffService.selectStaffByUserId(userId), RemoteComStaffVo.class);
+    }
 }

+ 2 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IComStaffService.java

@@ -90,4 +90,6 @@ public interface IComStaffService extends IService<ComStaff> {
 
     ComStaffVo selectStaffByStaffName(String staffName);
 
+    ComStaffVo selectStaffByUserId(Long userId);
+
 }

+ 6 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/ComStaffServiceImpl.java

@@ -227,7 +227,7 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
             user.setPhonenumber(bo.getPhone());
             String defaultPassword = "123456";
             user.setPassword(BCrypt.hashpw(defaultPassword));
-            user.setUserSonType("3");
+            user.setUserSonType("0");
             user.setRoleIds(new Long[]{bo.getRoleId()});
             SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
             int insert = sysUserMapper.insert(sysUser);
@@ -336,4 +336,9 @@ public class ComStaffServiceImpl extends ServiceImpl<ComStaffMapper, ComStaff> i
     public ComStaffVo selectStaffByStaffName(String staffName) {
         return baseMapper.selectVoOne(new LambdaQueryWrapper<ComStaff>().eq(ComStaff::getStaffName, staffName));
     }
+
+    @Override
+    public ComStaffVo selectStaffByUserId(Long userId) {
+        return baseMapper.selectVoOne(new LambdaQueryWrapper<ComStaff>().eq(ComStaff::getUserId, userId).eq(ComStaff::getDelFlag, "0").last("LIMIT 1"));
+    }
 }