瀏覽代碼

feat(customer): 添加联系人编号和合同金额精度支持

- 在CustomerContact实体类中新增contactNo字段用于联系人编号
- 在CustomerContract实体类中将contractAmount从String改为BigDecimal类型
- 实现联系人编号的自动生成逻辑,基于客户编号和序列号
- 添加设置主联系人的功能接口和实现
- 优化CustomerContactServiceImpl中的数据校验和异常处理
- 更新CustomerInvoiceInfoService中的主账户设置事务逻辑
- 为EnterpriseScale和IndustryCategory实体添加dataSource字段
- 修复CustomerContractServiceImpl中的查询条件问题
- 优化CustomerShippingAddressServiceImpl中的地址编号生成逻辑
- 在SysCompany相关实体中添加dataSource字段支持
- 移除SysDeptServiceImpl中的状态过滤条件以显示所有部门
hurx 1 月之前
父節點
當前提交
4bd54d1b62
共有 27 個文件被更改,包括 305 次插入73 次删除
  1. 8 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerContactController.java
  2. 4 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerContact.java
  3. 2 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerContract.java
  4. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/EnterpriseScale.java
  5. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/IndustryCategory.java
  6. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContactBo.java
  7. 6 5
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContractBo.java
  8. 10 5
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/EnterpriseScaleBo.java
  9. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/IndustryCategoryBo.java
  10. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContactVo.java
  11. 2 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContractVo.java
  12. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/EnterpriseScaleVo.java
  13. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/IndustryCategoryVo.java
  14. 8 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java
  15. 85 10
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContactServiceImpl.java
  16. 0 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContractServiceImpl.java
  17. 4 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerDeptServiceImpl.java
  18. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  19. 39 4
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInvoiceInfoServiceImpl.java
  20. 77 31
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerShippingAddressServiceImpl.java
  21. 1 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/EnterpriseScaleServiceImpl.java
  22. 10 9
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/IndustryCategoryServiceImpl.java
  23. 5 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysCompany.java
  24. 5 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysCompanyBo.java
  25. 5 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysCompanyVo.java
  26. 1 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysCompanyServiceImpl.java
  27. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java

+ 8 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerContactController.java

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.customer.domain.bo.CustomerShippingAddressBo;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -62,7 +63,7 @@ public class CustomerContactController extends BaseController {
      */
     @GetMapping("/{id}")
     public R<CustomerContactVo> getInfo(@NotNull(message = "主键不能为空")
-                                     @PathVariable("id") Long id) {
+                                        @PathVariable("id") Long id) {
         return R.ok(customerContactService.queryById(id));
     }
 
@@ -97,4 +98,10 @@ public class CustomerContactController extends BaseController {
                           @PathVariable("ids") Long[] ids) {
         return toAjax(customerContactService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /*设置主联系人*/
+    @PutMapping("/changeIsPrimary")
+    public R<Void> changeIsPrimary(@RequestBody CustomerContactBo bo) {
+        return toAjax(customerContactService.changeIsPrimary(bo));
+    }
 }

+ 4 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerContact.java

@@ -33,6 +33,10 @@ public class CustomerContact extends TenantEntity {
      */
     private Long customerId;
 
+
+    /*联系人编号*/
+    private String contactNo;
+
     /**
      * 联系人姓名
      */

+ 2 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerContract.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.*;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -56,7 +57,7 @@ public class CustomerContract extends TenantEntity {
     /**
      * 合同金额
      */
-    private String contractAmount;
+    private BigDecimal contractAmount;
 
     /**
      * 客服负责人

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/EnterpriseScale.java

@@ -50,4 +50,9 @@ public class EnterpriseScale extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
 }

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/IndustryCategory.java

@@ -50,4 +50,9 @@ public class IndustryCategory extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
 }

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContactBo.java

@@ -32,6 +32,9 @@ public class CustomerContactBo extends BaseEntity {
      */
     private Long customerId;
 
+    /*联系人编号*/
+    private String contactNo;
+
     /**
      * 联系人姓名
      */

+ 6 - 5
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContractBo.java

@@ -9,6 +9,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -56,8 +57,8 @@ public class CustomerContractBo extends BaseEntity {
     /**
      * 合同金额
      */
-    @NotBlank(message = "合同金额不能为空", groups = {AddGroup.class, EditGroup.class})
-    private String contractAmount;
+//    @NotBlank(message = "合同金额不能为空", groups = {AddGroup.class, EditGroup.class})
+    private BigDecimal contractAmount;
 
     /**
      * 客服负责人
@@ -72,19 +73,19 @@ public class CustomerContractBo extends BaseEntity {
     /**
      * 合同类型
      */
-    @NotBlank(message = "合同类型不能为空", groups = {AddGroup.class, EditGroup.class})
+//    @NotBlank(message = "合同类型不能为空", groups = {AddGroup.class, EditGroup.class})
     private String contractType;
 
     /**
      * 合同开始时间
      */
-    @NotNull(message = "合同开始时间不能为空", groups = {AddGroup.class, EditGroup.class})
+//    @NotNull(message = "合同开始时间不能为空", groups = {AddGroup.class, EditGroup.class})
     private Date startTime;
 
     /**
      * 合同结束时间
      */
-    @NotNull(message = "合同结束时间不能为空", groups = {AddGroup.class, EditGroup.class})
+//    @NotNull(message = "合同结束时间不能为空", groups = {AddGroup.class, EditGroup.class})
     private Date endTime;
 
     /**

+ 10 - 5
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/EnterpriseScaleBo.java

@@ -1,13 +1,13 @@
 package org.dromara.customer.domain.bo;
 
-import org.dromara.customer.domain.EnterpriseScale;
-import org.dromara.common.mybatis.core.domain.BaseEntity;
-import org.dromara.common.core.validate.AddGroup;
-import org.dromara.common.core.validate.EditGroup;
 import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import jakarta.validation.constraints.*;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.customer.domain.EnterpriseScale;
 
 /**
  * 企业规模业务对象 enterprise_scale
@@ -38,6 +38,11 @@ public class EnterpriseScaleBo extends BaseEntity {
      */
     private String status;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
     /**
      * 备注
      */

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/IndustryCategoryBo.java

@@ -43,4 +43,9 @@ public class IndustryCategoryBo extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
 }

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContactVo.java

@@ -33,6 +33,9 @@ public class CustomerContactVo implements Serializable {
     @ExcelProperty(value = "联系人ID")
     private Long id;
 
+    /*联系人编号*/
+    private String contactNo;
+
     /**
      * 所属客户ID
      */

+ 2 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContractVo.java

@@ -1,5 +1,6 @@
 package org.dromara.customer.domain.vo;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -66,7 +67,7 @@ public class CustomerContractVo implements Serializable {
      * 合同金额
      */
     @ExcelProperty(value = "合同金额")
-    private String contractAmount;
+    private BigDecimal contractAmount;
 
     /**
      * 客服负责人

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/EnterpriseScaleVo.java

@@ -54,4 +54,9 @@ public class EnterpriseScaleVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
 }

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/IndustryCategoryVo.java

@@ -54,4 +54,9 @@ public class IndustryCategoryVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
 }

+ 8 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java

@@ -2,6 +2,7 @@ package org.dromara.customer.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.customer.domain.CustomerContact;
+import org.dromara.customer.domain.bo.CustomerShippingAddressBo;
 import org.dromara.customer.domain.vo.CustomerContactVo;
 import org.dromara.customer.domain.bo.CustomerContactBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -16,7 +17,7 @@ import java.util.List;
  * @author LionLi
  * @date 2025-12-11
  */
-public interface ICustomerContactService extends IService<CustomerContact>{
+public interface ICustomerContactService extends IService<CustomerContact> {
 
     /**
      * 查询客户联系人信息
@@ -59,6 +60,12 @@ public interface ICustomerContactService extends IService<CustomerContact>{
      */
     Boolean updateByBo(CustomerContactBo bo);
 
+    /**
+     * 设置主联系人
+     */
+    int changeIsPrimary(CustomerContactBo bo);
+
+
     /**
      * 校验并批量删除客户联系人信息信息
      *

+ 85 - 10
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContactServiceImpl.java

@@ -1,27 +1,38 @@
 package org.dromara.customer.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.enums.IsDefault;
+import org.dromara.common.core.enums.SysPlatformYesNo;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.system.api.RemoteDeptService;
-import org.springframework.stereotype.Service;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.redis.utils.SequenceUtils;
+import org.dromara.customer.domain.CustomerContact;
+import org.dromara.customer.domain.CustomerShippingAddress;
 import org.dromara.customer.domain.bo.CustomerContactBo;
+import org.dromara.customer.domain.bo.CustomerShippingAddressBo;
 import org.dromara.customer.domain.vo.CustomerContactVo;
-import org.dromara.customer.domain.CustomerContact;
+import org.dromara.customer.domain.vo.CustomerInfoVo;
+import org.dromara.customer.domain.vo.CustomerShippingAddressVo;
 import org.dromara.customer.mapper.CustomerContactMapper;
+import org.dromara.customer.mapper.CustomerInfoMapper;
 import org.dromara.customer.service.ICustomerContactService;
+import org.dromara.system.api.RemoteDeptService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.time.Duration;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Collection;
 
 /**
  * 客户联系人信息Service业务层处理
@@ -34,11 +45,14 @@ import java.util.Collection;
 @Service
 public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMapper, CustomerContact> implements ICustomerContactService {
 
+    private static final String CONTACT_NO_KEY = "customer_contact:contact_no";
     @DubboReference
     private RemoteDeptService remoteDeptService;
 
     private final CustomerContactMapper baseMapper;
 
+    private final CustomerInfoMapper customerInfoMapper;
+
     /**
      * 查询客户联系人信息
      *
@@ -116,7 +130,32 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
      */
     @Override
     public Boolean insertByBo(CustomerContactBo bo) {
+        // 1. 获取并校验客户编号
+        String customerNo = null;
+        if (bo.getCustomerId() != null) {
+            CustomerInfoVo customerInfoVo = customerInfoMapper.selectVoById(bo.getCustomerId());
+
+            // 【关键修复】防御性编程:如果查不到客户信息,应直接抛错或返回失败,避免生成 "nullxxx" 数据
+            if (customerInfoVo == null) {
+                log.error("客户不存在,无法创建联系人 (ID: " + bo.getCustomerId() + ")");
+                throw new RuntimeException("客户不存在,无法创建联系人 (ID: " + bo.getCustomerId() + ")");
+            }
+
+            customerNo = customerInfoVo.getCustomerNo();
+
+            // 二次校验:防止 customerNo 本身为空
+            if (StringUtils.isBlank(customerNo)) {
+                log.error("客户编号为空,数据异常 (ID: " + bo.getCustomerId() + ")");
+                throw new RuntimeException("客户编号为空,数据异常 (ID: " + bo.getCustomerId() + ")");
+            }
+        }
+
+        // 2. 生成联系人编号
+        String seqId = SequenceUtils.nextPaddedIdStr(CONTACT_NO_KEY, Duration.ofDays(3650), 3);
+        String contactNo = customerNo + seqId;
+
         CustomerContact add = MapstructUtils.convert(bo, CustomerContact.class);
+        add.setContactNo(contactNo);
         validEntityBeforeSave(add);
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
@@ -138,6 +177,42 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
         return baseMapper.updateById(update) > 0;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int changeIsPrimary(CustomerContactBo bo) {
+        if (bo == null || bo.getId() == null) {
+            return 0;
+        }
+        CustomerContactVo contactVo = baseMapper.selectVoById(bo.getId());
+        if (SysPlatformYesNo.YES.getCode().equals(bo.getIsPrimary())) {
+            // 1. 清除该客户下所有主联系人
+            CustomerContact updateObj = new CustomerContact();
+            updateObj.setIsPrimary(SysPlatformYesNo.NO.getCode()); //
+
+            baseMapper.update(
+                updateObj,
+                new LambdaUpdateWrapper<CustomerContact>()
+                    .eq(CustomerContact::getCustomerId, contactVo.getCustomerId()) //
+                    .eq(CustomerContact::getIsPrimary, SysPlatformYesNo.YES.getCode())
+            );
+
+            // 2. 设置当前地址为默认
+            CustomerContact current = new CustomerContact();
+            current.setId(bo.getId());
+            current.setIsPrimary(SysPlatformYesNo.YES.getCode());
+            baseMapper.updateById(current);
+
+            return 1;
+        } else {
+            // 取消默认
+            CustomerContact current = new CustomerContact();
+            current.setId(bo.getId());
+            current.setIsPrimary(SysPlatformYesNo.NO.getCode());
+            baseMapper.updateById(current);
+            return 1;
+        }
+    }
+
     /**
      * 保存前的数据校验
      */

+ 0 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContractServiceImpl.java

@@ -82,7 +82,6 @@ public class CustomerContractServiceImpl extends ServiceImpl<CustomerContractMap
         lqw.eq(bo.getCustomerId() != null, CustomerContract::getCustomerId, bo.getCustomerId());
         lqw.eq(StringUtils.isNotBlank(bo.getContractNo()), CustomerContract::getContractNo, bo.getContractNo());
         lqw.like(StringUtils.isNotBlank(bo.getContractName()), CustomerContract::getContractName, bo.getContractName());
-        lqw.eq(StringUtils.isNotBlank(bo.getContractAmount()), CustomerContract::getContractAmount, bo.getContractAmount());
         lqw.eq(StringUtils.isNotBlank(bo.getCustomerLeader()), CustomerContract::getCustomerLeader, bo.getCustomerLeader());
         lqw.eq(StringUtils.isNotBlank(bo.getProjectLeader()), CustomerContract::getProjectLeader, bo.getProjectLeader());
         lqw.eq(StringUtils.isNotBlank(bo.getContractType()), CustomerContract::getContractType, bo.getContractType());

+ 4 - 2
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerDeptServiceImpl.java

@@ -60,6 +60,7 @@ public class CustomerDeptServiceImpl extends ServiceImpl<CustomerDeptMapper, Cus
         if (null != remoteDeptVo) {
             customerDeptVo.setDeptName(remoteDeptVo.getDeptName());
             customerDeptVo.setParentId(remoteDeptVo.getParentId());
+            customerDeptVo.setStatus(remoteDeptVo.getStatus());
         }
         return customerDeptVo;
     }
@@ -152,7 +153,7 @@ public class CustomerDeptServiceImpl extends ServiceImpl<CustomerDeptMapper, Cus
         return customerDepts.stream()
             .map(cd -> deptMap.get(cd.getDeptId())) // 直接 get,null 表示不匹配
             .filter(Objects::nonNull) // 过滤掉 deptMap 中不存在的
-            .map(sys -> buildCustomerDeptTreeVo(sys, customerDeptsMap.get(sys.getDeptId()), addressVoMap)) // 假设你有 customerDepts 按 deptId 的 map
+            .map(sys -> buildCustomerDeptTreeVo(sys, customerDeptsMap.get(sys.getDeptId()), addressVoMap))
             .sorted(Comparator.comparing(
                 CustomerDeptTreeVo::getOrderNum,
                 Comparator.nullsLast(Comparator.naturalOrder())
@@ -219,6 +220,7 @@ public class CustomerDeptServiceImpl extends ServiceImpl<CustomerDeptMapper, Cus
             RemoteDeptVo remoteDeptVo = new RemoteDeptVo();
             remoteDeptVo.setParentId(bo.getParentId());
             remoteDeptVo.setDeptName(bo.getDeptName());
+            remoteDeptVo.setStatus(bo.getStatus());
             remoteDeptVo.setPlatformCode(PlatformContext.getPlatform());
 
 
@@ -271,7 +273,7 @@ public class CustomerDeptServiceImpl extends ServiceImpl<CustomerDeptMapper, Cus
         // 更新远程部门字段
         remoteDeptVo.setDeptName(bo.getDeptName());
         remoteDeptVo.setParentId(bo.getParentId());
-
+        remoteDeptVo.setStatus(bo.getStatus());
         RemoteDeptVo updatedRemoteDept = remoteDeptService.updateDept(remoteDeptVo);
         if (updatedRemoteDept == null) {
             log.error("远程部门更新失败,deptId={}", deptId);

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

@@ -488,7 +488,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     private LambdaQueryWrapper<CustomerInfo> buildQueryWrapper(CustomerInfoBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<CustomerInfo> lqw = Wrappers.lambdaQuery();
-        lqw.orderByAsc(CustomerInfo::getId);
+        lqw.orderByDesc(CustomerInfo::getId);
         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());

+ 39 - 4
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInvoiceInfoServiceImpl.java

@@ -1,6 +1,8 @@
 package org.dromara.customer.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.enums.SysPlatformYesNo;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -16,6 +18,7 @@ import org.dromara.customer.domain.vo.CustomerInvoiceInfoVo;
 import org.dromara.customer.domain.CustomerInvoiceInfo;
 import org.dromara.customer.mapper.CustomerInvoiceInfoMapper;
 import org.dromara.customer.service.ICustomerInvoiceInfoService;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
@@ -30,7 +33,7 @@ import java.util.Collection;
 @Slf4j
 @RequiredArgsConstructor
 @Service
-public class CustomerInvoiceInfoServiceImpl  extends ServiceImpl<CustomerInvoiceInfoMapper, CustomerInvoiceInfo> implements ICustomerInvoiceInfoService {
+public class CustomerInvoiceInfoServiceImpl extends ServiceImpl<CustomerInvoiceInfoMapper, CustomerInvoiceInfo> implements ICustomerInvoiceInfoService {
 
     private final CustomerInvoiceInfoMapper baseMapper;
 
@@ -41,7 +44,7 @@ public class CustomerInvoiceInfoServiceImpl  extends ServiceImpl<CustomerInvoice
      * @return 客户开票信息
      */
     @Override
-    public CustomerInvoiceInfoVo queryById(Long id){
+    public CustomerInvoiceInfoVo queryById(Long id) {
         return baseMapper.selectVoById(id);
     }
 
@@ -96,9 +99,22 @@ public class CustomerInvoiceInfoServiceImpl  extends ServiceImpl<CustomerInvoice
      * @return 是否新增成功
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean insertByBo(CustomerInvoiceInfoBo bo) {
         CustomerInvoiceInfo add = MapstructUtils.convert(bo, CustomerInvoiceInfo.class);
+
+        // 1. 如果设为“主账户”,先将该客户下其他所有“主账户”降级为“非主账户”
+        if (SysPlatformYesNo.YES.getCode().equals(bo.getIsPrimaryAccount())) {
+            baseMapper.update(null, new LambdaUpdateWrapper<CustomerInvoiceInfo>()
+                .eq(CustomerInvoiceInfo::getCustomerId, add.getCustomerId())
+                .eq(CustomerInvoiceInfo::getIsPrimaryAccount, SysPlatformYesNo.YES.getCode())
+                .set(CustomerInvoiceInfo::getIsPrimaryAccount, SysPlatformYesNo.NO.getCode()));
+        }
+
+        // 2. 业务校验
         validEntityBeforeSave(add);
+
+        // 3. 执行插入
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
             bo.setId(add.getId());
@@ -113,16 +129,35 @@ public class CustomerInvoiceInfoServiceImpl  extends ServiceImpl<CustomerInvoice
      * @return 是否修改成功
      */
     @Override
+    @Transactional(rollbackFor = Exception.class) // 确保事务控制
     public Boolean updateByBo(CustomerInvoiceInfoBo bo) {
         CustomerInvoiceInfo update = MapstructUtils.convert(bo, CustomerInvoiceInfo.class);
+
+        // 防御性检查:确保 ID 存在
+        if (update.getId() == null) {
+            return false;
+        }
+
+        // 1. 如果设为“主账户”,先将该客户下其他所有“主账户”降级
+        if (SysPlatformYesNo.YES.getCode().equals(bo.getIsPrimaryAccount())) {
+            baseMapper.update(null, new LambdaUpdateWrapper<CustomerInvoiceInfo>()
+                .eq(CustomerInvoiceInfo::getCustomerId, update.getCustomerId())
+                .eq(CustomerInvoiceInfo::getIsPrimaryAccount, SysPlatformYesNo.YES.getCode())
+                .ne(CustomerInvoiceInfo::getId, update.getId()) // 排除自己
+                .set(CustomerInvoiceInfo::getIsPrimaryAccount, SysPlatformYesNo.NO.getCode()));
+        }
+
+        // 2. 业务校验
         validEntityBeforeSave(update);
+
+        // 3. 执行更新
         return baseMapper.updateById(update) > 0;
     }
 
     /**
      * 保存前的数据校验
      */
-    private void validEntityBeforeSave(CustomerInvoiceInfo entity){
+    private void validEntityBeforeSave(CustomerInvoiceInfo entity) {
         //TODO 做一些数据校验,如唯一约束
     }
 
@@ -135,7 +170,7 @@ public class CustomerInvoiceInfoServiceImpl  extends ServiceImpl<CustomerInvoice
      */
     @Override
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if(isValid){
+        if (isValid) {
             //TODO 做一些业务上的校验,判断是否需要校验
         }
         return baseMapper.deleteByIds(ids) > 0;

+ 77 - 31
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerShippingAddressServiceImpl.java

@@ -15,12 +15,15 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
 import org.dromara.customer.domain.CustomerShippingAddress;
 import org.dromara.customer.domain.bo.CustomerShippingAddressBo;
+import org.dromara.customer.domain.vo.CustomerInfoVo;
 import org.dromara.customer.domain.vo.CustomerShippingAddressVo;
+import org.dromara.customer.mapper.CustomerInfoMapper;
 import org.dromara.customer.mapper.CustomerShippingAddressMapper;
 import org.dromara.customer.service.ICustomerShippingAddressService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.rmi.ServerException;
 import java.time.Duration;
 import java.util.Collection;
 import java.util.List;
@@ -41,6 +44,8 @@ public class CustomerShippingAddressServiceImpl extends ServiceImpl<CustomerShip
 
     private final CustomerShippingAddressMapper baseMapper;
 
+    private final CustomerInfoMapper customerInfoMapper;
+
     /**
      * 查询客户收货地址
      *
@@ -110,14 +115,49 @@ public class CustomerShippingAddressServiceImpl extends ServiceImpl<CustomerShip
      * @return 是否新增成功
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean insertByBo(CustomerShippingAddressBo bo) {
-        bo.setShippingAddressNo(SequenceUtils.nextPaddedIdStr(SHOPPING_ADDRESS_NO_KEY, Duration.ofDays(3650), 4));
+        // 1. 获取并校验客户编号
+        String customerNo = null;
+        if (bo.getCustomerId() != null) {
+            CustomerInfoVo customerInfoVo = customerInfoMapper.selectVoById(bo.getCustomerId());
+
+            // 【关键修复】防御性编程:如果查不到客户信息,应直接抛错或返回失败,避免生成 "nullxxx" 数据
+            if (customerInfoVo == null) {
+                log.error("客户不存在,无法创建收货地址 (ID: " + bo.getCustomerId() + ")");
+                throw new RuntimeException("客户不存在,无法创建收货地址 (ID: " + bo.getCustomerId() + ")");
+            }
+
+            customerNo = customerInfoVo.getCustomerNo();
+
+            // 二次校验:防止 customerNo 本身为空
+            if (StringUtils.isBlank(customerNo)) {
+                log.error("客户编号为空,数据异常 (ID: " + bo.getCustomerId() + ")");
+                throw new RuntimeException("客户编号为空,数据异常 (ID: " + bo.getCustomerId() + ")");
+            }
+        }
+
+        // 2. 生成收货地址编号
+        String seqId = SequenceUtils.nextPaddedIdStr(SHOPPING_ADDRESS_NO_KEY, Duration.ofDays(3650), 3);
+        String shippingAddressNo = customerNo + seqId;
+
+        // 3. 对象转换
         CustomerShippingAddress add = MapstructUtils.convert(bo, CustomerShippingAddress.class);
+
+        // 4. 设置生成的业务字段
+        add.setShippingAddressNo(shippingAddressNo);
+
+        // 5. 业务校验
         validEntityBeforeSave(add);
+
+        // 6. 执行插入
         boolean flag = baseMapper.insert(add) > 0;
+
+        // 7. 回填 ID
         if (flag) {
             bo.setId(add.getId());
         }
+
         return flag;
     }
 
@@ -137,36 +177,42 @@ public class CustomerShippingAddressServiceImpl extends ServiceImpl<CustomerShip
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int changeDefaultAddress(CustomerShippingAddressBo bo) {
-        if (bo == null || bo.getId() == null) {
-            return 0;
-        }
-        CustomerShippingAddressVo addressVo = baseMapper.selectVoById(bo.getId());
-        if (IsDefault.Yes.getCode().equals(bo.getDefaultAddress())) {
-            // 1. 清除该客户下所有默认地址
-            CustomerShippingAddress updateObj = new CustomerShippingAddress();
-            updateObj.setDefaultAddress(IsDefault.No.getCode()); //
-
-            baseMapper.update(
-                updateObj,
-                new LambdaUpdateWrapper<CustomerShippingAddress>()
-                    .eq(CustomerShippingAddress::getCustomerId, addressVo.getCustomerId()) //
-                    .eq(CustomerShippingAddress::getDefaultAddress, IsDefault.Yes.getCode())
-            );
-
-            // 2. 设置当前地址为默认
-            CustomerShippingAddress current = new CustomerShippingAddress();
-            current.setId(bo.getId());
-            current.setDefaultAddress(IsDefault.Yes.getCode());
-            baseMapper.updateById(current);
-
-            return 1;
-        } else {
-            // 取消默认
-            CustomerShippingAddress current = new CustomerShippingAddress();
-            current.setId(bo.getId());
-            current.setDefaultAddress(IsDefault.No.getCode());
-            baseMapper.updateById(current);
-            return 1;
+        try {
+            if (bo == null || bo.getId() == null) {
+                return 0;
+            }
+            CustomerShippingAddressVo addressVo = baseMapper.selectVoById(bo.getId());
+            log.info("修改默认地址:" + addressVo);
+            if (IsDefault.Yes.getCode().equals(bo.getDefaultAddress())) {
+                // 1. 清除该客户下所有默认地址
+                CustomerShippingAddress updateObj = new CustomerShippingAddress();
+                updateObj.setDefaultAddress(IsDefault.No.getCode()); //
+
+                baseMapper.update(
+                    updateObj,
+                    new LambdaUpdateWrapper<CustomerShippingAddress>()
+                        .eq(CustomerShippingAddress::getCustomerId, addressVo.getCustomerId()) //
+                        .eq(CustomerShippingAddress::getDefaultAddress, IsDefault.Yes.getCode())
+                );
+
+                // 2. 设置当前地址为默认
+                CustomerShippingAddress current = new CustomerShippingAddress();
+                current.setId(bo.getId());
+                current.setDefaultAddress(IsDefault.Yes.getCode());
+                baseMapper.updateById(current);
+
+                return 1;
+            } else {
+                // 取消默认
+                CustomerShippingAddress current = new CustomerShippingAddress();
+                current.setId(bo.getId());
+                current.setDefaultAddress(IsDefault.No.getCode());
+                baseMapper.updateById(current);
+                return 1;
+            }
+        } catch (Exception e) {
+            log.error("修改默认地址失败:" + e.getMessage(), e);
+            throw new RuntimeException(e);
         }
     }
 

+ 1 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/EnterpriseScaleServiceImpl.java

@@ -83,6 +83,7 @@ public class EnterpriseScaleServiceImpl extends ServiceImpl<EnterpriseScaleMappe
         lqw.orderByAsc(EnterpriseScale::getId);
         lqw.like(StringUtils.isNotBlank(bo.getEnterpriseScaleName()), EnterpriseScale::getEnterpriseScaleName, bo.getEnterpriseScaleName());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EnterpriseScale::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), EnterpriseScale::getDataSource, bo.getDataSource());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), EnterpriseScale::getPlatformCode, bo.getPlatformCode());
         return lqw;
     }

+ 10 - 9
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/IndustryCategoryServiceImpl.java

@@ -1,27 +1,27 @@
 package org.dromara.customer.service.impl;
 
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.dromara.common.core.utils.MapstructUtils;
-import org.dromara.common.core.utils.StringUtils;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.mybatis.core.page.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
-import org.springframework.stereotype.Service;
+import org.dromara.customer.domain.IndustryCategory;
 import org.dromara.customer.domain.bo.IndustryCategoryBo;
 import org.dromara.customer.domain.vo.IndustryCategoryVo;
-import org.dromara.customer.domain.IndustryCategory;
 import org.dromara.customer.mapper.IndustryCategoryMapper;
 import org.dromara.customer.service.IIndustryCategoryService;
+import org.springframework.stereotype.Service;
 
 import java.time.Duration;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Collection;
 
 /**
  * 所属行业Service业务层处理
@@ -81,6 +81,7 @@ public class IndustryCategoryServiceImpl extends ServiceImpl<IndustryCategoryMap
         lqw.orderByAsc(IndustryCategory::getId);
         lqw.like(StringUtils.isNotBlank(bo.getIndustryCategoryName()), IndustryCategory::getIndustryCategoryName, bo.getIndustryCategoryName());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IndustryCategory::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), IndustryCategory::getDataSource, bo.getDataSource());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), IndustryCategory::getPlatformCode, bo.getPlatformCode());
         return lqw;
     }

+ 5 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysCompany.java

@@ -92,6 +92,11 @@ public class SysCompany extends TenantEntity {
      */
     private String status;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
     /**
      * 删除标志(0代表存在 2代表删除)
      */

+ 5 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysCompanyBo.java

@@ -89,6 +89,11 @@ public class SysCompanyBo extends BaseEntity {
      */
     private String isShow;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
     /**
      * 状态(0正常 1停用)
      */

+ 5 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysCompanyVo.java

@@ -112,6 +112,11 @@ public class SysCompanyVo implements Serializable {
     @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
     private String status;
 
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
     /**
      * 备注
      */

+ 1 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysCompanyServiceImpl.java

@@ -89,6 +89,7 @@ public class SysCompanyServiceImpl extends ServiceImpl<SysCompanyMapper, SysComp
         lqw.eq(bo.getRegistrationDate() != null, SysCompany::getRegistrationDate, bo.getRegistrationDate());
         lqw.eq(StringUtils.isNotBlank(bo.getIsShow()), SysCompany::getIsShow, bo.getIsShow());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysCompany::getStatus, bo.getStatus());
+        lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), SysCompany::getDataSource, bo.getDataSource());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), SysCompany::getPlatformCode, bo.getPlatformCode());
         return lqw;
     }

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

@@ -229,7 +229,7 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
                 SysDept::getParentId,
                 SysDept::getOrderNum,
                 SysDept::getStatus)
-            .eq(SysDept::getStatus, SystemConstants.NORMAL)
+//            .eq(SysDept::getStatus, SystemConstants.NORMAL)
             .in(CollUtil.isNotEmpty(deptIds), SysDept::getDeptId, deptIds));
     }