Explorar o código

Merge remote-tracking branch 'origin/master' into master

肖路 hai 11 horas
pai
achega
afd3e617d5
Modificáronse 60 ficheiros con 1524 adicións e 57 borrados
  1. 8 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerContactService.java
  2. 6 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java
  3. 15 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/dto/CustomerInfoDTO.java
  4. 31 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/BusConn.java
  5. 128 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/CustInfo.java
  6. 43 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/DlvAddr.java
  7. 40 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/GathBn.java
  8. 6 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteCustInfoService.java
  9. 6 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteExternalItemService.java
  10. 36 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyLogisticsCompanyDto.java
  11. 70 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/push/SalBkApl.java
  12. 65 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/push/SalBkDet.java
  13. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCompanyService.java
  14. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCurrencyService.java
  15. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCustomerLevelService.java
  16. 2 1
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCustomerTypeService.java
  17. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComDeptService.java
  18. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComLogisticsCompanyService.java
  19. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComStaffService.java
  20. 5 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComWarehouseService.java
  21. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteCreditLevelService.java
  22. 1 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/controller/pc/PcStatementProductController.java
  23. 5 0
      ruoyi-modules/ruoyi-customer/pom.xml
  24. 19 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java
  25. 18 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerContactServiceImpl.java
  26. 33 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java
  27. 14 4
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteSupplierInfoServiceImpl.java
  28. 10 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java
  29. 2 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java
  30. 12 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContactServiceImpl.java
  31. 266 26
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  32. 12 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/FollowUpLogServiceImpl.java
  33. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoServiceImpl.java
  34. 18 4
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyCommonController.java
  35. 15 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteCustInfoServiceImpl.java
  36. 8 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalItemServiceImpl.java
  37. 5 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalItemService.java
  38. 16 3
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalItemServiceImpl.java
  39. 1 1
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/EpAdModuleItem.java
  40. 1 1
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/EpAdModuleItemBo.java
  41. 1 1
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/EpAdModuleItemVo.java
  42. 5 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderReturnController.java
  43. 32 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/pc/PcOrderController.java
  44. 45 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/DeptPurchaseVo.java
  45. 5 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderMainVo.java
  46. 52 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/PurchaseDetailVo.java
  47. 18 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java
  48. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderReturnService.java
  49. 228 8
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java
  50. 96 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderReturnServiceImpl.java
  51. 1 2
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java
  52. 10 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCompanyServiceImpl.java
  53. 10 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCurrencyServiceImpl.java
  54. 10 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCustomerLevelServiceImpl.java
  55. 10 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCustomerTypeServiceImpl.java
  56. 11 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComDeptServiceImpl.java
  57. 8 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComLogisticsCompanyServiceImpl.java
  58. 11 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComStaffServiceImpl.java
  59. 26 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComWarehouseServiceImpl.java
  60. 11 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCreditLevelServiceImpl.java

+ 8 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerContactService.java

@@ -2,7 +2,15 @@ package org.dromara.customer.api;
 
 import org.dromara.customer.api.domain.vo.RemoteCustomerContactVo;
 
+import java.util.Map;
+import java.util.Set;
+
 public interface RemoteCustomerContactService {
 
     RemoteCustomerContactVo selectCustomerContactByCustomerIdAndUserId(Long customerId, Long userId);
+
+    /**
+     * 根据联系人ID批量查询联系人信息(含部门名称、联系人姓名)
+     */
+    Map<Long, RemoteCustomerContactVo> selectCustomerContactByIds(Set<Long> contactIds);
 }

+ 6 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java

@@ -48,4 +48,10 @@ public interface RemoteCustomerService {
      */
     Boolean isNeedAffirmOrder(Long customerId);
 
+    String selectCustomerShippingAddressNoById(Long addressId);
+
+    /**
+     * 客户详细信息 拼接json格式
+     */
+    String customerInfoJson(Long customerId);
 }

+ 15 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/dto/CustomerInfoDTO.java

@@ -51,5 +51,20 @@ public class CustomerInfoDTO implements Serializable {
      */
     private String regCountyNo;
 
+    /**
+     * 传真
+     */
+    private String fax;
+
+    /**
+     * 所属公司
+     */
+    private Long belongCompanyId;
+
+    /**
+     * 交易币别编码
+     */
+    private String currencyCode;
+
 
 }

+ 31 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/BusConn.java

@@ -0,0 +1,31 @@
+package org.dromara.customer.api.erp.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 业务联系人 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-09
+ */
+@Data
+public class BusConn implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 客户 */
+    private String CustId;
+
+    /** 来源客户联系人 */
+    private String FrLkmId;
+
+    /** 主要联系人 */
+    private Boolean IsMainPer;
+
+    /** 标识号 */
+    private Integer RowCd;
+}

+ 128 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/CustInfo.java

@@ -0,0 +1,128 @@
+package org.dromara.customer.api.erp.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 客户信息 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-09
+ */
+@Data
+public class CustInfo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 编号 */
+    private String CustId;
+
+    /** 名称 */
+    private String CustNm;
+
+    /** 业务人员 */
+    private String PerId;
+
+    /** 联系地址 */
+    private String Addr;
+
+    /** 资本额 */
+    private BigDecimal CapAmt;
+
+    /** 结账日(半月结) */
+    private Integer ChkHalfDa;
+
+    /** 结账日 */
+    private Integer ChkoutDa;
+
+    /** 结账日(周结) */
+    private Integer ChkWeekDa;
+
+    /** 城市 */
+    private String CityId;
+
+    /** 国家/地区 */
+    private String CountryId;
+
+    /** 信用等级 */
+    private String CreCls;
+
+    /** 企业规模 */
+    private String CropSclId;
+
+    /** 公司 */
+    private String CU_comCo;
+
+    /** 销售开票类型 */
+    private String CU_SalesInvoice;
+
+    /** 交易币别 */
+    private String CurId;
+
+    /** 客户来源 */
+    private String CustSrcId;
+
+    /** 类别 */
+    private String CustTyId;
+
+    /** 电子邮件 */
+    private String Email;
+
+    /** 传真号码 */
+    private String FaxNo;
+
+    /** 客户等级 */
+    private String GadId;
+
+    /** 收款条件 */
+    private Integer GathCnd;
+
+    /** 收款天数 */
+    private Integer GathDays;
+
+    /** 发票地址 */
+    private String InvoAddr;
+
+    /** 发票抬头 */
+    private String InvoTt;
+
+    /** 网址 */
+    private String LkUrl;
+
+    /** 办公电话 */
+    private String OfiTel;
+
+    /** 负责人 */
+    private String Principal;
+
+    /** 省份 */
+    private String PrvnId;
+
+    /** QQ/MSN */
+    private String QQMSN;
+
+    /** 备注 */
+    private String Remark;
+
+    /** 业务助理 */
+    private String SalAsstId;
+
+    /** 简称 */
+    private String SrtNm;
+
+    /** 统一社会信用代码 */
+    private String TaxChkNo;
+
+    /** 行业别 */
+    private String TradTy;
+
+    /** 有效期从 */
+    private Integer ValidityFromDate;
+
+    /** 有效期至 */
+    private Integer ValidityToDate;
+}

+ 43 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/DlvAddr.java

@@ -0,0 +1,43 @@
+package org.dromara.customer.api.erp.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 送货地址 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-09
+ */
+@Data
+public class DlvAddr implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 地址 */
+    private String Addr;
+
+    /** 地址编号 */
+    private String AddrNo;
+
+    /** 客户 */
+    private String CustId;
+
+    /** 联系人 */
+    private String ConnPer;
+
+    /** 联系人职称 */
+    private String ConnPos;
+
+    /** 联系电话 */
+    private String ConnTel;
+
+    /** 主要送货地址 */
+    private Boolean IsMainAddr;
+
+    /** 邮政编码 */
+    private String PtC;
+}

+ 40 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/erp/domain/push/GathBn.java

@@ -0,0 +1,40 @@
+package org.dromara.customer.api.erp.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 银行账户 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-09
+ */
+@Data
+public class GathBn implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 银行账号 */
+    private String BnAccNo;
+
+    /** 客户 */
+    private String CustId;
+
+    /** 开户银行 */
+    private String AccBn;
+
+    /** 账户名称 */
+    private String AccNm;
+
+    /** 主账户 */
+    private Boolean MainAcc;
+
+    /** 序号 */
+    private Integer RowNo;
+
+    /** 联系电话 */
+    private String TelNo;
+}

+ 6 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteCustInfoService.java

@@ -0,0 +1,6 @@
+package org.dromara.external.api.service;
+
+public interface RemoteCustInfoService {
+
+    String customerInfoJson();
+}

+ 6 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteExternalItemService.java

@@ -2,6 +2,9 @@ package org.dromara.external.api.service;
 
 import org.dromara.external.api.domain.ExternalItemDto;
 
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author
  * @date 2026/3/27 上午12:30
@@ -11,4 +14,7 @@ public interface RemoteExternalItemService {
     * 获取项目信息
     * */
     ExternalItemDto getItemInfo(Long itemId);
+
+    /*批量根据项目key查询项目名称*/
+    Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys);
 }

+ 36 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyLogisticsCompanyDto.java

@@ -0,0 +1,36 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 物流公司响应数据
+ *
+ * @author
+ * @date 2026/6/9
+ */
+@Data
+public class ThirdpartyLogisticsCompanyDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /**
+     * 物流公司编号
+     */
+    private String logisticsNo;
+
+    /**
+     * 物流公司编码
+     */
+    private String logisticsCode;
+
+    /**
+     * 物流公司名称
+     */
+    private String logisticsName;
+}

+ 70 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/push/SalBkApl.java

@@ -0,0 +1,70 @@
+package org.dromara.product.api.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 退货申请主表 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-10
+ */
+@Data
+public class SalBkApl implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 单据日期 */
+    private Integer BlDa;
+
+    /** 单据编号 */
+    private String BlNo;
+
+    /** 公司 */
+    private String CoId;
+
+    /** 交易币别 */
+    private String CurId;
+
+    /** 客户 */
+    private String CustId;
+
+    /** 业务人员 */
+    private String PerId;
+
+    /** 发货日期 */
+    private Integer SalDa;
+
+    /** 地址 */
+    private String Addr;
+
+    /** 送货地址编号 */
+    private String AddrNo;
+
+    /** 联系人 */
+    private String ConnPer;
+
+    /** 联系电话 */
+    private String ConnTel;
+
+    /** 所属部门 */
+    private String DeptId;
+
+    /** 传真号码 */
+    private String Fax;
+
+    /** 单价含税 */
+    private Boolean IsPrWTax;
+
+    /** 单据类型 */
+    private String TypeId;
+
+    /** 商城订单退货号 */
+    private String X_WebOrdBackNo;
+
+    /** 商城订单号 */
+    private String X_WebOrdNo;
+}

+ 65 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/push/SalBkDet.java

@@ -0,0 +1,65 @@
+package org.dromara.product.api.domain.push;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 退货申请明细 - ERP推送
+ *
+ * @author LionLi
+ * @date 2026-06-10
+ */
+@Data
+public class SalBkDet implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /** 单据编号 */
+    private String BlNo;
+
+    /** 税码编号 */
+    private String TaxId;
+
+    /** 来源单号 */
+    private String FrBlNo;
+
+    /** 来源标识号 */
+    private Integer FrRowCd;
+
+    /** 来源单种类 */
+    private Integer FrSrcTag;
+
+    /** 类型 */
+    private Integer IxTy;
+
+    /** 金额 */
+    private BigDecimal OAmt;
+
+    /** 含税金额 */
+    private BigDecimal OAmtWTax;
+
+    /** 产品编号 */
+    private String ProdId;
+
+    /** 标识号 */
+    private Integer RowCd;
+
+    /** 序号 */
+    private Integer RowNo;
+
+    /** 退货数量 */
+    private BigDecimal ShpmSQty;
+
+    /** 交易价 */
+    private BigDecimal SPr;
+
+    /** 交易数量 */
+    private BigDecimal SQty;
+
+    /** 仓库编号 */
+    private String WhsId;
+}

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

@@ -13,4 +13,6 @@ public interface RemoteComCompanyService {
     RemoteComCompanyVo selectByCompanyName(String companyName);
 
     List<RemoteComCompanyVo> selectCompanyList();
+
+    String selectCompanyCodeById(Long companyId);
 }

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

@@ -17,4 +17,6 @@ public interface RemoteComCurrencyService {
      * @return 交易币别VO列表
      */
     List<RemoteComCurrencyVo> selectCurrencyByIds(Set<Long> ids);
+
+    String selectCurrencyCodeById(Long id);
 }

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

@@ -22,4 +22,6 @@ public interface RemoteComCustomerLevelService {
     Map<Long, String> selectCustomerLevelNameByIds(Set<Long> ids);
 
     List<RemoteComCustomerLevelVo> selectCustomerLevelList();
+
+    String selectCustomerLevelNoById(Long id);
 }

+ 2 - 1
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCustomerTypeService.java

@@ -1,6 +1,5 @@
 package org.dromara.system.api;
 
-import org.dromara.system.api.domain.vo.RemoteComCustomerLevelVo;
 import org.dromara.system.api.domain.vo.RemoteComCustomerTypeVo;
 
 import java.util.List;
@@ -16,4 +15,6 @@ public interface RemoteComCustomerTypeService {
      * @return 客户类型VO列表
      */
     List<RemoteComCustomerTypeVo> selectCustomerTypeByIds(Set<Long> ids);
+
+    String selectCustomerTypeNoNameById(Long id);
 }

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

@@ -6,4 +6,6 @@ import java.util.Set;
 public interface RemoteComDeptService {
 
     Map<Long, String> selectDeptNameByIds(Set<Long> ids);
+
+    String selectDeptNOById(Long id);
 }

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

@@ -21,4 +21,6 @@ public interface RemoteComLogisticsCompanyService {
     * 通过名称获取id
     * */
     RemoteLogisticsCompanyVo selectLogisticsCompanyByName(String name);
+
+    List<RemoteLogisticsCompanyVo> selectLogisticsCompanyList();
 }

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

@@ -26,4 +26,6 @@ public interface RemoteComStaffService {
 
     RemoteComStaffVo selectStaffByUserId(Long userId);
 
+    String selectStaffCodeById(Long staffId);
+
 }

+ 5 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComWarehouseService.java

@@ -0,0 +1,5 @@
+package org.dromara.system.api;
+
+public interface RemoteComWarehouseService {
+    String getWarehouseNoById(Long warehouseId);
+}

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

@@ -19,4 +19,6 @@ public interface RemoteCreditLevelService {
     Map<Long, String> selectCreditLevelNameByIds(Set<Long> ids);
 
     RemoteCreditLevelVo selectByCreditLevelName(String creditLevelName);
+
+    String selectCreditLevelCodeById(Long id);
 }

+ 1 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/controller/pc/PcStatementProductController.java

@@ -1,5 +1,6 @@
 package org.dromara.bill.controller.pc;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;

+ 5 - 0
ruoyi-modules/ruoyi-customer/pom.xml

@@ -128,6 +128,11 @@
             <artifactId>ruoyi-api-order</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-api-external</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 19 - 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.*;
 import org.dromara.customer.domain.dto.ReleaseToPoolDto;
@@ -25,6 +26,7 @@ import org.dromara.customer.service.ICustomerInfoService;
 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.*;
@@ -80,8 +82,25 @@ public class CustomerInfoController extends BaseController {
      * <p>数据权限通过框架 @DataPermission 注解自动处理,
      * 根据角色数据范围(全部/本部门/本部门及以下/仅本人)自动过滤</p>
      */
+//    @DataPermission({
+//        @DataColumn(key = "deptName", value = "create_dept"),
+//        @DataColumn(key = "userName", value = "create_by"),
+//        @DataColumn(key = "salesPersonName", value = "sales_person_id"),
+//        @DataColumn(key = "serviceStaffName", value = "service_staff_id")
+//    })
     @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);
     }
 

+ 18 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerContactServiceImpl.java

@@ -10,6 +10,11 @@ import org.dromara.customer.domain.vo.CustomerContactVo;
 import org.dromara.customer.service.ICustomerContactService;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 @Slf4j
 @Service
 @RequiredArgsConstructor
@@ -23,4 +28,17 @@ public class RemoteCustomerContactServiceImpl implements RemoteCustomerContactSe
         CustomerContactVo customerContactVo = customerContactService.selectCustomerContactByCustomerIdAndUserId(customerId, userId);
         return BeanUtil.toBean(customerContactVo, RemoteCustomerContactVo.class);
     }
+
+    @Override
+    public Map<Long, RemoteCustomerContactVo> selectCustomerContactByIds(Set<Long> contactIds) {
+        if (contactIds == null || contactIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        return customerContactService.selectContactByIds(contactIds)
+            .entrySet().stream()
+            .collect(Collectors.toMap(
+                Map.Entry::getKey,
+                e -> BeanUtil.toBean(e.getValue(), RemoteCustomerContactVo.class)
+            ));
+    }
 }

+ 33 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java

@@ -12,11 +12,14 @@ import org.dromara.customer.api.domain.dto.CustomerAddressDTO;
 import org.dromara.customer.api.domain.dto.CustomerInfoDTO;
 import org.dromara.customer.domain.CustomerContact;
 import org.dromara.customer.domain.CustomerInfo;
+import org.dromara.customer.domain.CustomerSalesInfo;
 import org.dromara.customer.domain.CustomerShippingAddress;
 import org.dromara.customer.mapper.CustomerInfoMapper;
+import org.dromara.customer.mapper.CustomerSalesInfoMapper;
 import org.dromara.customer.service.ICustomerContactService;
 import org.dromara.customer.service.ICustomerInfoService;
 import org.dromara.customer.service.ICustomerShippingAddressService;
+import org.dromara.system.api.RemoteComCurrencyService;
 import org.springframework.stereotype.Service;
 
 import java.util.Collections;
@@ -39,6 +42,10 @@ public class RemoteCustomerServiceImpl implements RemoteCustomerService {
 
     private final ICustomerShippingAddressService customerShippingAddressService;
 
+    private final CustomerSalesInfoMapper customerSalesInfoMapper;
+
+    private final RemoteComCurrencyService remoteComCurrencyService;
+
 
     @Override
     public Map<Long, String> selectCustomerNameByIds(Set<Long> ids) {
@@ -116,7 +123,14 @@ public class RemoteCustomerServiceImpl implements RemoteCustomerService {
     @Override
     public CustomerInfoDTO selectCustomerInfoById(Long customerId) {
         CustomerInfo customerInfo = customerInfoService.getById(customerId);
-        return BeanUtil.toBean(customerInfo, CustomerInfoDTO.class);
+        CustomerInfoDTO dto = BeanUtil.toBean(customerInfo, CustomerInfoDTO.class);
+        if (dto != null) {
+            CustomerSalesInfo salesInfo = customerSalesInfoMapper.selectByCustomerId(customerId);
+            if (salesInfo != null && salesInfo.getDealCurrencyId() != null) {
+                dto.setCurrencyCode(remoteComCurrencyService.selectCurrencyCodeById(salesInfo.getDealCurrencyId()));
+            }
+        }
+        return dto;
     }
 
     @Override
@@ -149,4 +163,22 @@ public class RemoteCustomerServiceImpl implements RemoteCustomerService {
     public Boolean isNeedAffirmOrder(Long customerId) {
         return customerInfoService.isNeedAffirmOrder(customerId);
     }
+
+    @Override
+    public String selectCustomerShippingAddressNoById(Long addressId) {
+        String addressNo = "";
+        CustomerShippingAddress one = customerShippingAddressService.getOne(Wrappers.lambdaQuery(CustomerShippingAddress.class)
+            .eq(CustomerShippingAddress::getId, addressId)
+            .last("limit 1")
+        );
+        if (one != null) {
+            addressNo = one.getShippingAddressNo();
+        }
+        return addressNo;
+    }
+
+    @Override
+    public String customerInfoJson(Long customerId) {
+        return customerInfoService.customerInfoJson(customerId);
+    }
 }

+ 14 - 4
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteSupplierInfoServiceImpl.java

@@ -11,9 +11,7 @@ import org.dromara.customer.api.domain.dto.SupplierAreaDTO;
 import org.dromara.customer.api.domain.dto.SupplierAuthorizeDTO;
 import org.dromara.customer.domain.ContractSupply;
 import org.dromara.customer.domain.SupplierContact;
-import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.SupplyArea;
-import org.dromara.customer.domain.vo.SupplyAreaVo;
 import org.dromara.customer.service.*;
 import org.springframework.stereotype.Service;
 
@@ -61,12 +59,15 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
     }
 
     @Override
-    public List<Long> getSupplierIdsBySupplyArea(String areaname,String level) {
-        return supplyAreaService.getSupplierIdsBySupplyArea(areaname,level);
+    public List<Long> getSupplierIdsBySupplyArea(String areaname, String level) {
+        return supplyAreaService.getSupplierIdsBySupplyArea(areaname, level);
     }
 
     @Override
     public List<Long> getContractIdBySupplySupplierID(Set<Long> SupplierID) {
+        if (CollUtil.isEmpty(SupplierID)) {
+            return Collections.emptyList();
+        }
         return contractSupplyService.list(
             Wrappers.lambdaQuery(ContractSupply.class)
                 .in(ContractSupply::getSupplierId, SupplierID)
@@ -76,6 +77,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, Long> contractToSupplierMap(List<Long> contractSupplyIds) {
+        if (CollUtil.isEmpty(contractSupplyIds)) {
+            return Collections.emptyMap();
+        }
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>().in(ContractSupply::getId, contractSupplyIds)
         );
@@ -86,6 +90,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, String> selectEnterpriseNameByIds(List<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyMap();
+        }
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>().in(ContractSupply::getId, ids)
         );
@@ -115,6 +122,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, SupplierAreaDTO> selectSupplierInfoByContractIds(List<Long> contractSupplyIds) {
+        if (CollUtil.isEmpty(contractSupplyIds)) {
+            return Collections.emptyMap();
+        }
         // 1 查询合同供货
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>()

+ 10 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java

@@ -10,6 +10,8 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 客户联系人信息Service接口
@@ -35,6 +37,14 @@ public interface ICustomerContactService extends IService<CustomerContact> {
      */
     CustomerContactVo selectCustomerContactByCustomerIdAndUserId(Long customerId, Long userId);
 
+    /**
+     * 根据联系人ID批量查询联系人信息
+     *
+     * @param contactIds 联系人ID集合
+     * @return key=contactId, value=CustomerContactVo
+     */
+    Map<Long, CustomerContactVo> selectContactByIds(Set<Long> contactIds);
+
     /**
      * 分页查询客户联系人信息列表
      *

+ 2 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java

@@ -204,4 +204,6 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
      * @return 导入模板VO列表
      */
     List<CustomerInfoImportVo> queryImportTemplateList(int limit);
+
+   String customerInfoJson(Long customerId);
 }

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

@@ -89,6 +89,17 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
         return baseMapper.selectVoOne(new LambdaQueryWrapper<CustomerContact>().eq(CustomerContact::getCustomerId, customerId).eq(CustomerContact::getUserId, userId).eq(CustomerContact::getDelFlag, '0').last("limit 1"));
     }
 
+    @Override
+    public Map<Long, CustomerContactVo> selectContactByIds(Set<Long> contactIds) {
+        if (contactIds == null || contactIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<CustomerContactVo> list = baseMapper.selectVoByIds(contactIds);
+        return list.stream()
+            .filter(vo -> vo != null && vo.getId() != null)
+            .collect(Collectors.toMap(CustomerContactVo::getId, vo -> vo, (k1, k2) -> k1));
+    }
+
     /**
      * 分页查询客户联系人信息列表
      *
@@ -152,7 +163,7 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
         lqw.eq(bo.getCustomerId() != null, CustomerContact::getCustomerId, bo.getCustomerId());
         lqw.like(StringUtils.isNotBlank(bo.getContactNo()), CustomerContact::getContactNo, bo.getContactNo());
         lqw.like(StringUtils.isNotBlank(bo.getContactName()), CustomerContact::getContactName, bo.getContactName());
-        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), CustomerContact::getPhone, bo.getPhone());
+        lqw.like(StringUtils.isNotBlank(bo.getPhone()), CustomerContact::getPhone, bo.getPhone());
         lqw.eq(StringUtils.isNotBlank(bo.getOfficePhone()), CustomerContact::getOfficePhone, bo.getOfficePhone());
         lqw.eq(StringUtils.isNotBlank(bo.getOfficePhoneTwo()), CustomerContact::getOfficePhoneTwo, bo.getOfficePhoneTwo());
         lqw.eq(StringUtils.isNotBlank(bo.getGender()), CustomerContact::getGender, bo.getGender());

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

@@ -3,6 +3,7 @@ package org.dromara.customer.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.crypto.digest.BCrypt;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -14,6 +15,7 @@ import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.constant.GlobalConstants;
 import org.dromara.common.core.context.PlatformContext;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.core.enums.FormatsType;
 import org.dromara.common.core.enums.IsDefault;
 import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.DateUtils;
@@ -25,6 +27,10 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.RedisUtils;
 import org.dromara.common.redis.utils.SequenceUtils;
 import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.customer.api.erp.domain.push.BusConn;
+import org.dromara.customer.api.erp.domain.push.CustInfo;
+import org.dromara.customer.api.erp.domain.push.DlvAddr;
+import org.dromara.customer.api.erp.domain.push.GathBn;
 import org.dromara.customer.domain.*;
 import org.dromara.customer.domain.bo.*;
 import org.dromara.customer.domain.vo.*;
@@ -746,7 +752,37 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<CustomerInfo> lqw = Wrappers.lambdaQuery();
         lqw.orderByDesc(CustomerInfo::getId);
-
+        // 数据权限过滤:只能查看自己创建的、或者是业务负责人、或者是客服支持的客户
+        // 超级管理员或租户管理员可查看全部数据
+        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()
+            && (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());
@@ -1023,18 +1059,35 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         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()
-            );
+            // 如果角色相同,恢复并更新
+            if (Objects.equals(existingUser.getRoleCode(), roleCode)) {
+                teamMemberMapper.restoreMemberById(
+                    existingUser.getId(),
+                    userNo,
+                    realName,
+                    roleCode,
+                    updateAccredit,
+                    izManager,
+                    LoginHelper.getUserId(),
+                    LoginHelper.getDeptId(),
+                    PlatformContext.getPlatform()
+                );
+            } else {
+                // 角色不同(如同一个人既是负责人又是客服),新增一条记录
+                TeamMember member = new TeamMember();
+                member.setDataType(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);
+            }
         } else {
             // 5. 如果人员不存在,执行新增
             TeamMember member = new TeamMember();
@@ -1083,7 +1136,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
         // 3. 插入新的关联数据
         saveAssociatedData(customerId, bo);
-
+        customerInfoJson(customerId);
         return true;
     }
 
@@ -1185,10 +1238,15 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                 }
             }
         }
-        return baseMapper.update(null,
+
+        Integer num = baseMapper.update(null,
             new LambdaUpdateWrapper<CustomerInfo>()
                 .set(CustomerInfo::getStatus, status)
                 .eq(CustomerInfo::getId, customerId));
+        if (num > 0) {
+            customerInfoJson(customerId);
+        }
+        return num;
     }
 
     @Override
@@ -1743,6 +1801,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             customerBusinessInfo.setBusinessCustomerName(bo.getBusinessCustomerName());
             customerBusinessInfo.setSocialCreditCode(bo.getSocialCreditCode());
             customerBusinessInfoMapper.insert(customerBusinessInfo);
+            // 将业务员和客服加入团队成员
+            Set<Long> staffIds = new HashSet<>();
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                staffIds.add(bo.getSalesPersonId());
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                staffIds.add(bo.getServiceStaffId());
+            }
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                saveOrUpdateTeamMember(add.getCustomerNo(), bo.getSalesPersonId(),
+                    staffNameMap.get(bo.getSalesPersonId()), "1", 1, 1);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                saveOrUpdateTeamMember(add.getCustomerNo(), bo.getServiceStaffId(),
+                    staffNameMap.get(bo.getServiceStaffId()), "3", 0, 1);
+            }
         }
         return flag;
     }
@@ -1775,6 +1853,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                 customerBusinessInfo.setSocialCreditCode(bo.getSocialCreditCode());
                 customerBusinessInfoMapper.updateById(customerBusinessInfo);
             }
+            // 将业务员和客服加入团队成员
+            Set<Long> staffIds = new HashSet<>();
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                staffIds.add(bo.getSalesPersonId());
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                staffIds.add(bo.getServiceStaffId());
+            }
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                saveOrUpdateTeamMember(update.getCustomerNo(), bo.getSalesPersonId(),
+                    staffNameMap.get(bo.getSalesPersonId()), "1", 1, 1);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                saveOrUpdateTeamMember(update.getCustomerNo(), bo.getServiceStaffId(),
+                    staffNameMap.get(bo.getServiceStaffId()), "3", 0, 1);
+            }
         }
 
         return flag;
@@ -1819,17 +1917,35 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
 
         if (existing != null) {
-            teamMemberMapper.restoreMemberById(
-                existing.getId(),
-                userNo,
-                realName,
-                roleCode,
-                updateAccredit,
-                izManager,
-                LoginHelper.getUserId(),
-                LoginHelper.getDeptId(),
-                PlatformContext.getPlatform()
-            );
+            // 如果角色相同,恢复并更新
+            if (Objects.equals(existing.getRoleCode(), roleCode)) {
+                teamMemberMapper.restoreMemberById(
+                    existing.getId(),
+                    userNo,
+                    realName,
+                    roleCode,
+                    updateAccredit,
+                    izManager,
+                    LoginHelper.getUserId(),
+                    LoginHelper.getDeptId(),
+                    PlatformContext.getPlatform()
+                );
+            } else {
+                // 角色不同(如同一个人既是负责人又是客服),新增一条记录
+                TeamMember member = new TeamMember();
+                member.setDataType(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);
+            }
         } else {
             TeamMember member = new TeamMember();
             member.setDataType(12);
@@ -2281,4 +2397,128 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
         return exportList;
     }
+
+    @Override
+    public String customerInfoJson(Long customerId) {
+        // 1. 查询客户主信息
+        CustomerInfoVo customerInfoVo = baseMapper.selectVoById(customerId);
+        if (customerInfoVo == null) {
+            return "{}";
+        }
+
+        // 2. 查询关联数据
+        CustomerSalesInfo salesInfo = customerSalesInfoMapper.selectByCustomerId(customerInfoVo.getId());
+        CustomerBusinessInfo businessInfo = customerBusinessInfoMapper.selectByCustomerId(customerInfoVo.getId());
+        List<CustomerContact> customerContacts = customerContactMapper.selectListByCustomerId(customerInfoVo.getId());
+        List<CustomerShippingAddressVo> shippingAddressVos = shippingAddressMapper.selectVoList(
+            new LambdaQueryWrapper<CustomerShippingAddress>()
+                .eq(CustomerShippingAddress::getCustomerId, customerInfoVo.getId()));
+        List<CustomerInvoiceInfo> invoiceInfos = customerInvoiceInfoMapper.selectListByCustomerId(customerInfoVo.getId());
+
+        // 3. 映射 CustInfo
+        CustInfo custInfo = new CustInfo();
+        custInfo.setCustId(customerInfoVo.getCustomerNo());
+        custInfo.setCustNm(customerInfoVo.getCustomerName());
+        custInfo.setPerId(remoteComStaffService.selectStaffCodeById((customerInfoVo.getSalesPersonId())));
+        custInfo.setSalAsstId(remoteComStaffService.selectStaffCodeById((customerInfoVo.getServiceStaffId())));
+        custInfo.setAddr(customerInfoVo.getAddress());
+        if (businessInfo != null) {
+            try {
+                custInfo.setCapAmt(new BigDecimal(businessInfo.getRegisteredCapital()));
+            } catch (Exception e) {
+                log.warn("解析注册资本失败: {}", businessInfo.getRegisteredCapital());
+            }
+            custInfo.setPrincipal(businessInfo.getLegalPersonName());
+        }
+        if (salesInfo != null) {
+            custInfo.setChkHalfDa(salesInfo.getBillingDay());
+            custInfo.setChkoutDa(salesInfo.getBillDate());
+            custInfo.setChkWeekDa(salesInfo.getAccountPeriod());
+            custInfo.setCreCls(remoteCreditLevelService.selectCreditLevelCodeById(salesInfo.getCreditLevelId()));
+            custInfo.setCurId(remoteComCurrencyService.selectCurrencyCodeById(salesInfo.getDealCurrencyId()));
+            custInfo.setCustSrcId(salesInfo.getCustomerSource());
+            custInfo.setGathCnd(salesInfo.getSettlementMethod() != null ? salesInfo.getSettlementMethod().intValue() : null);
+            custInfo.setGathDays(salesInfo.getPayDays());
+        }
+        custInfo.setCityId(customerInfoVo.getRegCityNo());
+        custInfo.setCropSclId(customerInfoVo.getEnterpriseScaleId() != null ? enterpriseScaleMapper.selectVoById(customerInfoVo.getEnterpriseScaleId()).getEnterpriseScaleCode() : null);
+        custInfo.setCU_comCo(customerInfoVo.getCompanyName());
+        custInfo.setCU_SalesInvoice(customerInfoVo.getSellInvoiceTypeNo());
+        custInfo.setCustTyId(remoteComCustomerTypeService.selectCustomerTypeNoNameById(customerInfoVo.getCustomerTypeId()));
+        custInfo.setEmail(customerInfoVo.getEmail());
+        custInfo.setFaxNo(customerInfoVo.getFax());
+        custInfo.setInvoAddr(customerInfoVo.getAddress());
+        custInfo.setInvoTt(customerInfoVo.getCustomerName());
+        custInfo.setLkUrl(customerInfoVo.getUrl());
+        custInfo.setOfiTel(customerInfoVo.getLandline());
+        custInfo.setPrvnId(customerInfoVo.getRegProvincialNo());
+        custInfo.setRemark(customerInfoVo.getRemark());
+        custInfo.setSrtNm(customerInfoVo.getShortName());
+        custInfo.setTaxChkNo(customerInfoVo.getSocialCreditCode());
+        custInfo.setGadId(remoteComCustomerLevelService.selectCustomerLevelNoById(customerInfoVo.getCustomerLevelId()));
+        custInfo.setTradTy(customerInfoVo.getIndustryCategoryId() != null ? industryCategoryMapper.selectVoById(customerInfoVo.getIndustryCategoryId()).getIndustryCode() : null);
+        if (customerInfoVo.getValidityFromDate() != null) {
+            custInfo.setValidityFromDate(Integer.parseInt(DateUtils.parseDateToStr(FormatsType.YYYYMMDD, customerInfoVo.getValidityFromDate())));
+        }
+        if (customerInfoVo.getValidityToDate() != null) {
+            custInfo.setValidityToDate(Integer.parseInt(DateUtils.parseDateToStr(FormatsType.YYYYMMDD, customerInfoVo.getValidityToDate())));
+        }
+        custInfo.setCountryId(customerInfoVo.getRegCountyNo());
+        custInfo.setQQMSN(customerInfoVo.getEmail());
+
+        // 4. 映射 DlvAddr 列表
+        List<DlvAddr> dlvAddrList = new ArrayList<>();
+        if (CollUtil.isNotEmpty(shippingAddressVos)) {
+            for (CustomerShippingAddressVo vo : shippingAddressVos) {
+                DlvAddr dlvAddr = new DlvAddr();
+                dlvAddr.setAddr(vo.getAddress());
+                dlvAddr.setAddrNo(vo.getShippingAddressNo());
+                dlvAddr.setCustId(customerInfoVo.getCustomerNo());
+                dlvAddr.setConnPer(vo.getConsignee());
+                dlvAddr.setConnPos(vo.getDeptName());
+                dlvAddr.setConnTel(vo.getPhone());
+                dlvAddr.setIsMainAddr("0".equals(vo.getDefaultAddress()));
+                dlvAddr.setPtC(vo.getPostal());
+                dlvAddrList.add(dlvAddr);
+            }
+        }
+
+        // 5. 映射 GathBn 列表
+        List<GathBn> gathBnList = new ArrayList<>();
+        if (CollUtil.isNotEmpty(invoiceInfos)) {
+            int rowNo = 1;
+            for (CustomerInvoiceInfo info : invoiceInfos) {
+                GathBn gathBn = new GathBn();
+                gathBn.setBnAccNo(info.getBankAccount());
+                gathBn.setCustId(customerInfoVo.getCustomerNo());
+                gathBn.setAccBn(info.getBankName());
+                gathBn.setAccNm(customerInfoVo.getCustomerName());
+                gathBn.setMainAcc("0".equals(info.getIsPrimaryAccount()));
+                gathBn.setRowNo(rowNo++);
+                gathBn.setTelNo(info.getPhone());
+                gathBnList.add(gathBn);
+            }
+        }
+
+        // 6. 映射 BusConn 列表
+        List<BusConn> busConnList = new ArrayList<>();
+        if (CollUtil.isNotEmpty(customerContacts)) {
+            for (CustomerContact contact : customerContacts) {
+                BusConn busConn = new BusConn();
+                busConn.setCustId(customerInfoVo.getCustomerNo());
+                busConn.setFrLkmId(contact.getId() != null ? String.valueOf(contact.getId()) : null);
+                busConn.setIsMainPer("0".equals(contact.getIsPrimary()));
+                busConn.setRowCd(contact.getId() != null ? contact.getId().intValue() : null);
+                busConnList.add(busConn);
+            }
+        }
+
+        // 7. 组装返回JSON
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("CustInfo", custInfo);
+        result.put("DlvAddr", dlvAddrList);
+        result.put("GathBn", gathBnList);
+        result.put("BusConn", busConnList);
+        return JSONUtil.toJsonStr(result);
+    }
 }

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

@@ -96,10 +96,21 @@ public class FollowUpLogServiceImpl implements IFollowUpLogService {
         lqw.eq(StringUtils.isNotBlank(bo.getObjectNo()), FollowUpLog::getObjectNo, bo.getObjectNo());
         lqw.eq(StringUtils.isNotBlank(bo.getCustomerNo()), FollowUpLog::getCustomerNo, bo.getCustomerNo());
         lqw.like(StringUtils.isNotBlank(bo.getCustomerName()), FollowUpLog::getCustomerName, bo.getCustomerName());
-        lqw.like(StringUtils.isNotBlank(bo.getVisitor()), FollowUpLog::getVisitor, bo.getVisitor());
+        lqw.and(StringUtils.isNotBlank(bo.getVisitor()) || bo.getVisitorNo() != null,
+            wrapper -> wrapper
+                .like(StringUtils.isNotBlank(bo.getVisitor()), FollowUpLog::getVisitor, bo.getVisitor())
+                .or()
+                .eq(bo.getVisitorNo() != null, FollowUpLog::getVisitorNo, bo.getVisitorNo())
+        );
         lqw.like(StringUtils.isNotBlank(bo.getFollowPeopleName()), FollowUpLog::getFollowPeopleName, bo.getFollowPeopleName());
         lqw.eq(StringUtils.isNotBlank(bo.getCallTypeCode()), FollowUpLog::getCallTypeCode, bo.getCallTypeCode());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), FollowUpLog::getPlatformCode, bo.getPlatformCode());
+        
+        java.util.Map<String, Object> params = bo.getParams();
+        if (params != null && params.get("beginTime") != null && params.get("endTime") != null) {
+            lqw.between(FollowUpLog::getCallDate, params.get("beginTime"), params.get("endTime"));
+        }
+
         // 增加排重和基础过滤
         lqw.eq(FollowUpLog::getIsDelete, 0);
         lqw.orderByDesc(FollowUpLog::getId);

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

@@ -824,7 +824,7 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
                 vo.setSupplierNo(supplierInfo.getSupplierNo());
 //                vo.setSupplyStatus(supplierInfo.getSupplyStatus());
                 return vo;
-            }).collect(Collectors.toList());
+            }).filter(Objects::nonNull).collect(Collectors.toList());
 
             // 批量处理扩展信息
             supplierVos = batchHandleBaseExtInfo(supplierVos);

+ 18 - 4
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyCommonController.java

@@ -1,16 +1,17 @@
 package org.dromara.external.controller.thirdparty;
 
+import cn.hutool.core.bean.BeanUtil;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.domain.R;
 import org.dromara.external.api.thirdparty.domain.bo.ThirdpartyProductBrandBo;
 import org.dromara.external.api.thirdparty.domain.bo.ThirdpartyProductUnitBo;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyAreaDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductBrandDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductCateDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductUnitDto;
+import org.dromara.external.api.thirdparty.domain.dto.*;
+import org.dromara.system.api.RemoteComLogisticsCompanyService;
+import org.dromara.system.api.domain.vo.RemoteLogisticsCompanyVo;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -30,6 +31,9 @@ import java.util.List;
 @RequestMapping("/api/thirdparty")
 public class ThirdpartyCommonController {
 
+    @DubboReference
+    private RemoteComLogisticsCompanyService remoteComLogisticsCompanyService;
+
     /**
      * 获取区域地址
      */
@@ -69,4 +73,14 @@ public class ThirdpartyCommonController {
         // TODO: 实现产品单位查询逻辑
         return R.ok();
     }
+
+    /**
+     * 物流公司查询
+     */
+    @Operation(summary = "物流公司查询")
+    @PostMapping("/system/getLogisticsCompany")
+    public R<List<ThirdpartyLogisticsCompanyDto>> getLogisticsCompany() {
+        List<RemoteLogisticsCompanyVo> remoteLogisticsCompanyVos = remoteComLogisticsCompanyService.selectLogisticsCompanyList();
+        return R.ok(BeanUtil.copyToList(remoteLogisticsCompanyVos, ThirdpartyLogisticsCompanyDto.class));
+    }
 }

+ 15 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteCustInfoServiceImpl.java

@@ -0,0 +1,15 @@
+package org.dromara.external.dubbo;
+
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.customer.api.RemoteCustomerService;
+import org.dromara.external.api.service.RemoteCustInfoService;
+
+public class RemoteCustInfoServiceImpl implements RemoteCustInfoService {
+
+    @DubboReference
+    private RemoteCustomerService remoteCustomerService;
+    @Override
+    public String customerInfoJson() {
+        return remoteCustomerService.customerInfoJson(null);
+    }
+}

+ 8 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalItemServiceImpl.java

@@ -11,6 +11,9 @@ import org.dromara.external.domain.vo.ExternalItemVo;
 import org.dromara.external.service.IExternalItemService;
 import org.springframework.stereotype.Service;
 
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author
  * @date 2026/1/14 下午5:02
@@ -36,4 +39,9 @@ public class RemoteExternalItemServiceImpl implements RemoteExternalItemService
         }
         return BeanUtil.toBean(externalItemVo, ExternalItemDto.class);
     }
+
+    @Override
+    public Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys) {
+        return externalItemService.selectItemNameByItemKeys(itemKeys);
+    }
 }

+ 5 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalItemService.java

@@ -9,6 +9,8 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 第三方对接项目管理Service接口
@@ -67,4 +69,7 @@ public interface IExternalItemService extends IService<ExternalItem>{
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /*批量根据项目key查询项目名称*/
+    Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys);
 }

+ 16 - 3
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalItemServiceImpl.java

@@ -23,9 +23,10 @@ import org.dromara.external.domain.ExternalItem;
 import org.dromara.external.mapper.ExternalItemMapper;
 import org.dromara.external.service.IExternalItemService;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
+import cn.hutool.core.collection.CollUtil;
+
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 第三方对接项目管理Service业务层处理
@@ -159,4 +160,16 @@ public class ExternalItemServiceImpl  extends ServiceImpl<ExternalItemMapper, Ex
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    public Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys) {
+        if (CollUtil.isEmpty(itemKeys)) {
+            return Collections.emptyMap();
+        }
+        return baseMapper.selectList(Wrappers.lambdaQuery(ExternalItem.class)
+                .in(ExternalItem::getItemKey, itemKeys)
+                .select(ExternalItem::getItemKey, ExternalItem::getItemName))
+            .stream()
+            .collect(Collectors.toMap(ExternalItem::getItemKey, ExternalItem::getItemName, (k1, k2) -> k1));
+    }
 }

+ 1 - 1
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/EpAdModuleItem.java

@@ -68,7 +68,7 @@ public class EpAdModuleItem extends TenantEntity {
     /**
      * 销量
      */
-    private Long salesCount;
+    private String salesCount;
 
     /**
      * 排序

+ 1 - 1
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/EpAdModuleItemBo.java

@@ -67,7 +67,7 @@ public class EpAdModuleItemBo extends BaseEntity {
     /**
      * 销量
      */
-    private Long salesCount;
+    private String salesCount;
 
     /**
      * 排序

+ 1 - 1
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/EpAdModuleItemVo.java

@@ -83,7 +83,7 @@ public class EpAdModuleItemVo implements Serializable {
      * 销量
      */
     @ExcelProperty(value = "销量")
-    private Long salesCount;
+    private String salesCount;
 
     /**
      * 排序

+ 5 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderReturnController.java

@@ -104,6 +104,11 @@ public class OrderReturnController extends BaseController {
         return toAjax(orderReturnService.deleteWithValidByIds(List.of(ids), true));
     }
 
+    @GetMapping("/orderReturnToJson")
+    public String orderReturnToJson() {
+        return orderReturnService.orderReturnToJson(2059218403827687426L);
+    }
+
     /**
      * 状态修改
      */

+ 32 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/pc/PcOrderController.java

@@ -25,11 +25,13 @@ import org.dromara.order.domain.OrderCustomerFlowLink;
 import org.dromara.order.domain.OrderCustomerFlowNodeLink;
 import org.dromara.order.domain.bo.*;
 import org.dromara.order.domain.dto.OrderPayDto;
-import org.dromara.order.domain.vo.OrderCountVo;
 import org.dromara.order.domain.vo.CustomerOrderTradeDataVo;
+import org.dromara.order.domain.vo.DeptPurchaseVo;
+import org.dromara.order.domain.vo.OrderCountVo;
 import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.domain.vo.OrderStatusStats;
+import org.dromara.order.domain.vo.PurchaseDetailVo;
 import org.dromara.order.service.IOrderCustomerFlowLinkService;
 import org.dromara.order.service.IOrderCustomerFlowNodeLinkService;
 import org.dromara.order.service.IOrderCustomerFlowService;
@@ -526,4 +528,33 @@ public class PcOrderController extends BaseController {
 
         return R.ok();
     }
+
+    /**
+     * 部门采购金额统计
+     * 查询当前客户所有订单,按联系人/部门分组统计下单金额、已完成金额、待完成金额
+     *
+     * @param contactId 下单人ID(可选,筛选指定联系人)
+     */
+    @GetMapping("/deptPurchase")
+    public TableDataInfo<DeptPurchaseVo> deptPurchase(@RequestParam(required = false) Long contactId, PageQuery pageQuery) {
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
+        if (ObjectUtil.isEmpty(customerId)) {
+            return  TableDataInfo.build();
+        }
+        return orderMainService.deptPurchase(customerId, contactId, pageQuery);
+    }
+
+    /**
+     * 采购明细统计
+     * 统计当前客户订单的购买数量、商品数量、品牌数量、品类数量、售后商品数量、平均完成时效、售后商品占比
+     */
+    @GetMapping("/purchaseDetail")
+    public R<PurchaseDetailVo> purchaseDetail() {
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
+        if (ObjectUtil.isEmpty(customerId)) {
+            return R.fail("未获取到当前客户信息");
+        }
+        return orderMainService.purchaseDetail(customerId);
+    }
+
 }

+ 45 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/DeptPurchaseVo.java

@@ -0,0 +1,45 @@
+package org.dromara.order.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 部门采购金额 VO
+ *
+ * @author Claude
+ * @date 2026-06-08
+ */
+@Data
+public class DeptPurchaseVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 部门名称
+     */
+    private String deptName;
+
+    /**
+     * 下单人(联系人姓名)
+     */
+    private String orderPerson;
+
+    /**
+     * 下单金额(所有订单总金额)
+     */
+    private BigDecimal orderAmount;
+
+    /**
+     * 已完成订单金额(orderStatus >= 5)
+     */
+    private BigDecimal completedAmount;
+
+    /**
+     * 待完成订单金额(orderStatus < 5)
+     */
+    private BigDecimal pendingAmount;
+}

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

@@ -482,4 +482,9 @@ public class OrderMainVo implements Serializable {
      */
     private String assigneeName;
 
+    /**
+     * 所属项目名称
+     */
+    private String dataSourceStr;
+
 }

+ 52 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/PurchaseDetailVo.java

@@ -0,0 +1,52 @@
+package org.dromara.order.domain.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 采购明细统计VO
+ *
+ * @author LionLi
+ * @date 2026-06-08
+ */
+@Data
+public class PurchaseDetailVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 统计数据:购买数量、商品数量、品牌数量、品类数量
+     */
+    private List<StatItem> statData;
+
+    /**
+     * 售后数据:售后商品数量、平均完成时效、售后商品占比
+     */
+    private List<AfterSaleItem> afterSaleData;
+
+    @Data
+    @Accessors(chain = true)
+    public static class StatItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+        private String value;
+        private String label;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class AfterSaleItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+        private String label;
+        private String value;
+        private List<Integer> data;
+        private String color;
+        private String type;
+    }
+}

+ 18 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java

@@ -179,4 +179,22 @@ public interface IOrderMainService extends IService<OrderMain> {
 
     R<CustomerOrderTradeDataVo> customerOrderTradeData(Long customerId);
 
+    /**
+     * 部门采购金额统计(按联系人/部门分组,支持分页)
+     *
+     * @param customerId 客户ID
+     * @param contactId  联系人ID(可选,筛选指定下单人)
+     * @param pageQuery  分页参数
+     * @return 部门采购统计分页列表
+     */
+    TableDataInfo<DeptPurchaseVo> deptPurchase(Long customerId, Long contactId, PageQuery pageQuery);
+
+    /**
+     * 采购明细统计(购买数量、商品数量、品牌数量、品类数量、售后统计)
+     *
+     * @param customerId 客户ID
+     * @return 采购明细统计VO
+     */
+    R<PurchaseDetailVo> purchaseDetail(Long customerId);
+
 }

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderReturnService.java

@@ -113,4 +113,6 @@ public interface IOrderReturnService extends IService<OrderReturn> {
      * @return 影响行数
      */
     int apiWithdrawReturn(Long returnId, String returnNo, String withdrawReason);
+
+    String orderReturnToJson(Long returnId);
 }

+ 228 - 8
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -27,6 +27,7 @@ import org.dromara.customer.api.*;
 import org.dromara.customer.api.domain.dto.CustomerInfoDTO;
 import org.dromara.customer.api.domain.vo.RemoteCustomerContactVo;
 import org.dromara.customer.api.domain.vo.RemoteCustomerSalesVo;
+import org.dromara.external.api.service.RemoteExternalItemService;
 import org.dromara.external.api.tongji.RemoteTongJiPullService;
 import org.dromara.external.api.zhongche.RemoteZhongChePullService;
 import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
@@ -115,6 +116,9 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
     @DubboReference
     private RemoteProductService remoteProductService;
 
+    @DubboReference
+    private RemoteExternalItemService remoteExternalItemService;
+
     private final IOrderCustomerFlowLinkService orderCustomerFlowLinkService;
 
     private final IOrderCustomerFlowNodeLinkService orderCustomerFlowNodeLinkService;
@@ -161,7 +165,10 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         if (orderMainVo == null) {
             return null;
         }
-
+        if (StringUtils.isNotBlank(orderMainVo.getDataSource())) {
+            Map<String, String> dataSourceMap = remoteExternalItemService.selectItemNameByItemKeys(Set.of(orderMainVo.getDataSource()));
+            orderMainVo.setDataSourceStr(dataSourceMap.get(orderMainVo.getDataSource()));
+        }
         // 2. 查询关联的商品列表--并且查询商品已发货数量与未发货数量
         List<OrderProductVo> orderProductVoList = orderProductMapper.selectProductsWithDelivered(orderMainVo.getId());
         if (orderProductVoList != null && !orderProductVoList.isEmpty()) {
@@ -321,16 +328,18 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             Set<Long> createUserIds = records.stream().map(OrderMainVo::getCreateBy).collect(Collectors.toSet());
             Set<Long> createDeptIds = records.stream().map(OrderMainVo::getCreateDept).collect(Collectors.toSet());
             Set<Long> orderIds = records.stream().map(OrderMainVo::getParentOrderId).filter(Objects::nonNull).collect(Collectors.toSet());
-
+            Set<String> dataSources = records.stream().map(OrderMainVo::getDataSource).filter(Objects::nonNull).collect(Collectors.toSet());
             Map<Long, String> UserMap = remoteUserService.selectUserNamesByIds(createUserIds.stream().toList());
             Map<Long, String> deptMap = remoteDeptService.selectDeptNameByIds(createDeptIds);
             Map<Long, String> customerMap = remoteCustomerService.selectCustomerNameByIds(customerIds);
+            Map<String, String> dataSourceMap = remoteExternalItemService.selectItemNameByItemKeys(dataSources);
             Map<Long, String> orderNoMap = selectOrderNoByIds(orderIds);
             records.forEach(orderMainVo -> {
                 orderMainVo.setProjectOrderNo(orderNoMap.get(orderMainVo.getParentOrderId()));
                 orderMainVo.setCreateName(UserMap.get(orderMainVo.getCreateBy()));
                 orderMainVo.setCreateDeptName(deptMap.get(orderMainVo.getCreateDept()));
                 orderMainVo.setCustomerName(customerMap.get(orderMainVo.getCustomerId()));
+                orderMainVo.setDataSourceStr(dataSourceMap.get(orderMainVo.getDataSource()));
             });
         }
         return TableDataInfo.build(result);
@@ -1111,11 +1120,12 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
      */
     @Override
     public int updateStatus(OrderMainBo bo) {
+        OrderMainVo orderMainVo = baseMapper.selectVoById(bo.getId());
         OrderMain order = new OrderMain();
         order.setId(bo.getId());
         order.setOrderStatus(bo.getOrderStatus());
         //如果是项目订单取消则要调用拒单
-        if (Objects.equals("7", bo.getOrderStatus())) {
+        if (ObjectUtils.isNotEmpty(orderMainVo.getDataSource()) && Objects.equals("7", bo.getOrderStatus())) {
             this.reject(bo.getId(), "取消订单");
         }
         return baseMapper.updateById(order);
@@ -1204,7 +1214,7 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         LambdaUpdateWrapper<OrderMain> updateWrapper = new LambdaUpdateWrapper<>();
 
         // 设置更新后的值
-        updateWrapper.set(OrderMain::getOrderStatus, OrderStatus.COMPLETED.getCode());
+        updateWrapper.set(OrderMain::getOrderStatus, OrderStatus.COMPLETED.getCode()).set(OrderMain::getReceivingTime, new Date());
 
         // 构建 WHERE 条件逻辑:
         // (id IN (...) OR parentOrderId IN (...)) AND orderStatus = SHIPPED
@@ -1300,12 +1310,12 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         }
         String crrcOrderNo = ext.getCrrcOrderNo();
         OrderConfirmBo bo = new OrderConfirmBo(crrcOrderNo, orderNo);
-        if ("zhongche".equals(orderMain.getDataSource())  ) {
+        if ("zhongche".equals(orderMain.getDataSource())) {
             GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallOrderConfirm(bo);
             if (goodsUpdateVo.getResult() != 1) {
                 throw new ZhongcheException("中车订单扩展信息不存在");
             }
-        }else if ("tongji".equals(orderMain.getDataSource())  ) {
+        } else if ("tongji".equals(orderMain.getDataSource())) {
             GoodsUpdateVo goodsUpdateVo = tongJiPullService.mallOrderConfirm(bo);
             if (goodsUpdateVo.getResult() != 1) {
                 throw new ZhongcheException("同济订单扩展信息不存在");
@@ -1343,13 +1353,13 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             throw new ZhongcheException("订单扩展信息不存在");
         }
         String crrcOrderNo = ext.getCrrcOrderNo();
-        if ("zhongche".equals(orderMain.getDataSource())  ) {
+        if ("zhongche".equals(orderMain.getDataSource())) {
             OrderRejectBo bo = new OrderRejectBo(crrcOrderNo, orderNo, reason);
             GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallOrderReject(bo);
             if (goodsUpdateVo.getResult() != 1) {
                 throw new ZhongcheException("拒绝失败");
             }
-        }else if ("tongji".equals(orderMain.getDataSource())  ) {
+        } else if ("tongji".equals(orderMain.getDataSource())) {
             OrderRejectBo bo = new OrderRejectBo(crrcOrderNo, orderNo, reason);
             GoodsUpdateVo goodsUpdateVo = tongJiPullService.mallOrderReject(bo);
             if (goodsUpdateVo.getResult() != 1) {
@@ -2288,4 +2298,214 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
 
         return R.ok(vo);
     }
+
+    @Override
+    public TableDataInfo<DeptPurchaseVo> deptPurchase(Long customerId, Long contactId, PageQuery pageQuery) {
+        // 1. 查询当前客户的所有非子单订单
+        LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<OrderMain>()
+            .eq(OrderMain::getCustomerId, customerId)
+            .eq(OrderMain::getCurrentLevel, 1)
+            .eq(OrderMain::getDelFlag, "0");
+        // 可选:按下单人筛选
+        if (contactId != null) {
+            wrapper.eq(OrderMain::getContactId, contactId);
+        }
+        List<OrderMain> orders = baseMapper.selectList(wrapper
+            .select(OrderMain::getTotalAmount, OrderMain::getOrderStatus, OrderMain::getContactId));
+
+        if (CollUtil.isEmpty(orders)) {
+            return new TableDataInfo<>(Collections.emptyList(), 0);
+        }
+
+        // 2. 按 contactId 分组,计算金额
+        Map<Long, BigDecimal[]> amountMap = new LinkedHashMap<>(); // [totalAmount, completedAmount, pendingAmount]
+        for (OrderMain order : orders) {
+            Long orderContactId = order.getContactId();
+            if (orderContactId == null) {
+                continue;
+            }
+            BigDecimal orderAmount = order.getTotalAmount() != null ? order.getTotalAmount() : BigDecimal.ZERO;
+            BigDecimal[] amounts = amountMap.computeIfAbsent(orderContactId, k -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO});
+            amounts[0] = amounts[0].add(orderAmount); // 总金额
+            // orderStatus >= 5 为已完成
+            if (Integer.parseInt(order.getOrderStatus()) >= 5) {
+                amounts[1] = amounts[1].add(orderAmount); // 已完成
+            } else {
+                amounts[2] = amounts[2].add(orderAmount); // 待完成
+            }
+        }
+
+        if (amountMap.isEmpty()) {
+            return new TableDataInfo<>(Collections.emptyList(), 0);
+        }
+
+        // 3. 远程批量查询联系人信息(含部门名称、联系人姓名)
+        Map<Long, RemoteCustomerContactVo> contactMap = remoteCustomerContactService.selectCustomerContactByIds(amountMap.keySet());
+
+        // 4. 组装结果列表
+        List<DeptPurchaseVo> allList = new ArrayList<>();
+        for (Map.Entry<Long, BigDecimal[]> entry : amountMap.entrySet()) {
+            Long ctId = entry.getKey();
+            BigDecimal[] amounts = entry.getValue();
+
+            DeptPurchaseVo vo = new DeptPurchaseVo();
+            RemoteCustomerContactVo contact = contactMap.get(ctId);
+            if (contact != null) {
+                vo.setDeptName(contact.getDeptName());
+                vo.setOrderPerson(contact.getContactName());
+            }
+            vo.setOrderAmount(amounts[0]);
+            vo.setCompletedAmount(amounts[1]);
+            vo.setPendingAmount(amounts[2]);
+            allList.add(vo);
+        }
+
+        // 5. 内存分页
+        int total = allList.size();
+        int pageNum = pageQuery != null ? pageQuery.getPageNum() : 1;
+        int pageSize = pageQuery != null ? pageQuery.getPageSize() : 10;
+        int fromIndex = (pageNum - 1) * pageSize;
+        if (fromIndex >= total) {
+            return new TableDataInfo<>(Collections.emptyList(), total);
+        }
+        int toIndex = Math.min(fromIndex + pageSize, total);
+        List<DeptPurchaseVo> pageList = allList.subList(fromIndex, toIndex);
+
+        return new TableDataInfo<>(pageList, total);
+    }
+
+    @Override
+    public R<PurchaseDetailVo> purchaseDetail(Long customerId) {
+        PurchaseDetailVo vo = new PurchaseDetailVo();
+
+        // ========== 1. 查询当前客户的非子单订单 ==========
+        List<OrderMain> orders = baseMapper.selectList(new LambdaQueryWrapper<OrderMain>()
+            .eq(OrderMain::getCustomerId, customerId)
+            .eq(OrderMain::getCurrentLevel, 1)
+            .eq(OrderMain::getDelFlag, "0"));
+
+        long orderCount = orders.size(); // 购买数量(件)
+
+        if (CollUtil.isEmpty(orders)) {
+            vo.setStatData(buildStatData("0", "0", "0", "0"));
+            vo.setAfterSaleData(buildAfterSaleData("0", "0", "0%",
+                Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
+            return R.ok(vo);
+        }
+
+        List<Long> orderIds = orders.stream().map(OrderMain::getId).collect(Collectors.toList());
+
+        // ========== 2. 查询订单商品(去重产品数、品牌数、品类数) ==========
+        List<OrderProduct> orderProducts = orderProductMapper.selectList(new LambdaQueryWrapper<OrderProduct>()
+            .in(OrderProduct::getOrderId, orderIds)
+            .eq(OrderProduct::getDelFlag, "0"));
+
+        Set<Long> productIds = orderProducts.stream()
+            .map(OrderProduct::getProductId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+        long productCount = productIds.size(); // 商品数量(件)
+
+        // 远程查询商品品牌和品类
+        long brandCount = 0;
+        long categoryCount = 0;
+        if (CollUtil.isNotEmpty(productIds)) {
+            List<ProductVo> productVos = remoteProductService.getProductDetails(new ArrayList<>(productIds));
+            if (CollUtil.isNotEmpty(productVos)) {
+                brandCount = productVos.stream()
+                    .map(ProductVo::getBrandId)
+                    .filter(Objects::nonNull)
+                    .distinct()
+                    .count();
+                // 三类品类 = 去重的底级分类
+                categoryCount = productVos.stream()
+                    .map(ProductVo::getBottomCategoryId)
+                    .filter(Objects::nonNull)
+                    .distinct()
+                    .count();
+            }
+        }
+
+        // ========== 3. 售后统计 ==========
+        // 售后商品数量 = sum(returnProductNum)
+        List<OrderReturn> orderReturns = orderReturnMapper.selectList(new LambdaQueryWrapper<OrderReturn>()
+            .eq(OrderReturn::getCustomerId, customerId)
+            .eq(OrderReturn::getDelFlag, "0"));
+        long afterSaleProductCount = orderReturns.stream()
+            .map(OrderReturn::getReturnProductNum)
+            .filter(Objects::nonNull)
+            .mapToLong(Long::longValue)
+            .sum();
+
+        // 售后商品占比 = 售后商品数 / 商品总数 * 100%
+        String afterSaleRatio;
+        if (productCount > 0) {
+            BigDecimal ratio = BigDecimal.valueOf(afterSaleProductCount)
+                .multiply(BigDecimal.valueOf(100))
+                .divide(BigDecimal.valueOf(productCount), 1, java.math.RoundingMode.HALF_UP);
+            afterSaleRatio = ratio.stripTrailingZeros().toPlainString() + "%";
+        } else {
+            afterSaleRatio = "0%";
+        }
+
+        // 平均完成时效 = average(receivingTime - createTime)  for 已完成订单(orderStatus >= 5)
+        long avgDays = 0;
+        List<OrderMain> completedOrders = orders.stream()
+            .filter(o -> o.getReceivingTime() != null && o.getCreateTime() != null
+                && Integer.parseInt(o.getOrderStatus()) >= 5)
+            .collect(Collectors.toList());
+        if (!completedOrders.isEmpty()) {
+            long totalDays = completedOrders.stream()
+                .mapToLong(o -> {
+                    long diffMillis = o.getReceivingTime().getTime() - o.getCreateTime().getTime();
+                    return Math.max(0, diffMillis / (1000 * 60 * 60 * 24));
+                })
+                .sum();
+            avgDays = totalDays / completedOrders.size();
+        }
+
+        // ========== 4. 组装返回数据 ==========
+        vo.setStatData(buildStatData(
+            String.valueOf(orderCount),
+            String.valueOf(productCount),
+            String.valueOf(brandCount),
+            String.valueOf(categoryCount)
+        ));
+        vo.setAfterSaleData(buildAfterSaleData(
+            String.valueOf(afterSaleProductCount),
+            String.valueOf(avgDays),
+            afterSaleRatio,
+            Collections.emptyList(),
+            Collections.emptyList(),
+            Collections.emptyList()
+        ));
+
+        return R.ok(vo);
+    }
+
+    private List<PurchaseDetailVo.StatItem> buildStatData(String orderCount, String productCount,
+                                                          String brandCount, String categoryCount) {
+        List<PurchaseDetailVo.StatItem> list = new ArrayList<>();
+        list.add(new PurchaseDetailVo.StatItem().setValue(orderCount).setLabel("购买数量(件)"));
+        list.add(new PurchaseDetailVo.StatItem().setValue(productCount).setLabel("商品数量(件)"));
+        list.add(new PurchaseDetailVo.StatItem().setValue(brandCount).setLabel("品牌数量(件)"));
+        list.add(new PurchaseDetailVo.StatItem().setValue(categoryCount).setLabel("三类品类数量(件)"));
+        return list;
+    }
+
+    private List<PurchaseDetailVo.AfterSaleItem> buildAfterSaleData(String afterSaleCount, String avgDays,
+                                                                    String ratio, List<Integer> data1,
+                                                                    List<Integer> data2, List<Integer> data3) {
+        List<PurchaseDetailVo.AfterSaleItem> list = new ArrayList<>();
+        list.add(new PurchaseDetailVo.AfterSaleItem()
+            .setLabel("售后商品数量(件)").setValue(afterSaleCount)
+            .setData(data1).setColor("#e60012").setType("line"));
+        list.add(new PurchaseDetailVo.AfterSaleItem()
+            .setLabel("平均完成时效(天)").setValue(avgDays)
+            .setData(data2).setColor("#3498db").setType("bar"));
+        list.add(new PurchaseDetailVo.AfterSaleItem()
+            .setLabel("售后商品占比").setValue(ratio)
+            .setData(data3).setColor("#f4c542").setType("line"));
+        return list;
+    }
 }

+ 96 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderReturnServiceImpl.java

@@ -1,6 +1,7 @@
 package org.dromara.order.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -8,16 +9,21 @@ 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.FormatsType;
+import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.ObjectUtils;
 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.dromara.customer.api.RemoteCustomerService;
+import org.dromara.customer.api.domain.dto.CustomerInfoDTO;
 import org.dromara.order.domain.*;
 import org.dromara.order.domain.bo.ApiOrderReturnBo;
 import org.dromara.order.domain.bo.OrderReturnBo;
 import org.dromara.order.domain.bo.OrderReturnItemBo;
+import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.domain.vo.OrderReturnItemVo;
 import org.dromara.order.domain.vo.OrderReturnVo;
 import org.dromara.order.mapper.OrderMainMapper;
@@ -26,6 +32,12 @@ import org.dromara.order.mapper.OrderReturnMapper;
 import org.dromara.order.service.IOrderMainCrrcExtService;
 import org.dromara.order.service.IOrderReturnPickCrrcService;
 import org.dromara.order.service.IOrderReturnService;
+import org.dromara.product.api.domain.push.SalBkApl;
+import org.dromara.product.api.domain.push.SalBkDet;
+import org.dromara.system.api.RemoteComCompanyService;
+import org.dromara.system.api.RemoteComDeptService;
+import org.dromara.system.api.RemoteComStaffService;
+import org.dromara.system.api.RemoteComWarehouseService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -47,6 +59,18 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
     @DubboReference
     private RemoteCustomerService remoteCustomerService;
 
+    @DubboReference
+    private RemoteComStaffService remoteComStaffService;
+
+    @DubboReference
+    private RemoteComWarehouseService remoteComWarehouseService;
+
+    @DubboReference
+    private RemoteComCompanyService remoteComCompanyService;
+
+    @DubboReference
+    private RemoteComDeptService remoteComDeptService;
+
     private final OrderReturnMapper baseMapper;
 
     private final OrderMainMapper orderMainMapper;
@@ -241,7 +265,7 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
 
         // 保存明细
         saveOrderReturnItems(entity.getId(), bo.getOrderReturnItemList(), false);
-
+        orderReturnToJson(entity.getId());
         log.info("新增退货单成功,单号: {}", entity.getReturnNo());
         return true;
     }
@@ -602,4 +626,75 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
         return result;
     }
 
+    @Override
+    public String orderReturnToJson(Long returnId) {
+        OrderReturnVo orderReturn = queryById(returnId);
+
+        OrderMainVo orderMainVo = orderMainMapper.selectVoById(orderReturn.getOrderId());
+
+        // 查询客户信息,获取业务人员等
+        CustomerInfoDTO customerInfo = null;
+        if (orderReturn.getCustomerId() != null) {
+            customerInfo = remoteCustomerService.selectCustomerInfoById(orderReturn.getCustomerId());
+        }
+
+        // 1. 映射 SalBkApl
+        SalBkApl salBkApl = new SalBkApl();
+        if (orderReturn.getReturnTime() != null) {
+            salBkApl.setBlDa(Integer.parseInt(DateUtils.parseDateToStr(FormatsType.YYYYMMDD, orderReturn.getReturnTime())));
+        }
+        salBkApl.setBlNo(orderReturn.getReturnNo());
+        salBkApl.setCoId(remoteComCompanyService.selectCompanyCodeById(customerInfo.getBelongCompanyId()));
+        salBkApl.setCurId(customerInfo != null && StringUtils.isNotBlank(customerInfo.getCurrencyCode()) ? customerInfo.getCurrencyCode() : "");
+        salBkApl.setCustId(orderReturn.getCustomerNo());
+        if (customerInfo != null && customerInfo.getSalesPersonId() != null) {
+            salBkApl.setPerId(remoteComStaffService.selectStaffCodeById(customerInfo.getSalesPersonId()));
+        }
+        salBkApl.setAddr(orderReturn.getChargebackAddress());
+        salBkApl.setAddrNo(remoteCustomerService.selectCustomerShippingAddressNoById(orderMainVo.getShippingAddressId()));
+        salBkApl.setConnPer(orderReturn.getChargebackName());
+        salBkApl.setConnTel(orderReturn.getChargebackPhone());
+        if (customerInfo != null && customerInfo.getBelongingDepartmentId() != null) {
+            salBkApl.setDeptId(remoteComDeptService.selectDeptNOById(customerInfo.getBelongingDepartmentId()));
+        }
+        salBkApl.setFax(customerInfo != null && StringUtils.isNotBlank(customerInfo.getFax()) ? customerInfo.getFax() : "");
+        salBkApl.setIsPrWTax(true);
+        salBkApl.setTypeId(orderReturn.getServiceType());
+        salBkApl.setX_WebOrdBackNo(orderReturn.getReturnNo());
+        salBkApl.setX_WebOrdNo(orderReturn.getOrderNo());
+
+        // 2. 映射 SalBkDet 列表
+        List<SalBkDet> salBkDetList = new ArrayList<>();
+        List<OrderReturnItemVo> items = orderReturn.getOrderReturnItemList();
+        if (CollUtil.isNotEmpty(items)) {
+            int rowNo = 1;
+            for (OrderReturnItemVo item : items) {
+                SalBkDet det = new SalBkDet();
+                det.setBlNo(orderReturn.getReturnNo());
+                det.setTaxId("");
+                det.setFrBlNo(orderReturn.getOrderNo());
+                det.setFrRowCd(item.getOrderProductId() != null ? item.getOrderProductId().intValue() : null);
+                det.setFrSrcTag(1);
+                det.setIxTy(1);
+                det.setOAmt(item.getTotalAmount());
+                det.setOAmtWTax(item.getTotalAmount());
+                det.setProdId(item.getProductNo());
+                det.setRowCd(item.getId() != null ? item.getId().intValue() : null);
+                det.setRowNo(rowNo++);
+                det.setShpmSQty(item.getReturnQuantity() != null ? BigDecimal.valueOf(item.getReturnQuantity()) : BigDecimal.ZERO);
+                det.setSPr(item.getUnitPrice());
+                det.setSQty(item.getReturnQuantity() != null ? BigDecimal.valueOf(item.getReturnQuantity()) : BigDecimal.ZERO);
+                if (ObjectUtils.isNotEmpty(orderMainVo) && null != orderMainVo.getWarehouseId()) {
+                    det.setWhsId(remoteComWarehouseService.getWarehouseNoById(orderMainVo.getWarehouseId()));
+                }
+                salBkDetList.add(det);
+            }
+        }
+
+        // 3. 组装返回JSON
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("salBkApl", salBkApl);
+        result.put("salBkDet", salBkDetList);
+        return JSONUtil.toJsonStr(result);
+    }
 }

+ 1 - 2
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java

@@ -1,6 +1,5 @@
 package org.dromara.system.controller.system;
 
-import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.convert.Convert;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.constant.SystemConstants;
@@ -35,7 +34,7 @@ public class SysDeptController extends BaseController {
     /**
      * 获取部门列表
      */
-    @SaCheckPermission("system:dept:list")
+//    @SaCheckPermission("system:dept:list")
     @GetMapping("/list")
     public R<List<SysDeptVo>> list(SysDeptBo dept) {
         List<SysDeptVo> depts = deptService.selectDeptList(dept);

+ 10 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCompanyServiceImpl.java

@@ -39,4 +39,14 @@ public class RemoteComCompanyServiceImpl implements RemoteComCompanyService {
     public List<RemoteComCompanyVo> selectCompanyList() {
         return MapstructUtils.convert(comCompanyService.queryList(new ComCompanyBo()), RemoteComCompanyVo.class);
     }
+
+    @Override
+    public String selectCompanyCodeById(Long companyId) {
+        String companyCode = "";
+        ComCompanyVo comCompanyVo = comCompanyService.queryById(companyId);
+        if (comCompanyVo != null) {
+            companyCode = comCompanyVo.getCompanyCode();
+        }
+        return companyCode;
+    }
 }

+ 10 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCurrencyServiceImpl.java

@@ -40,4 +40,14 @@ public class RemoteComCurrencyServiceImpl implements RemoteComCurrencyService {
             .map(e -> BeanUtil.toBean(e, RemoteComCurrencyVo.class))
             .collect(Collectors.toList());
     }
+
+    @Override
+    public String selectCurrencyCodeById(Long id) {
+        String currencyCode = "";
+        ComCurrencyVo comCurrencyVo = comCurrencyService.queryById( id);
+        if (comCurrencyVo != null) {
+            currencyCode = comCurrencyVo.getCurrencyCode();
+        }
+        return currencyCode;
+    }
 }

+ 10 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCustomerLevelServiceImpl.java

@@ -46,4 +46,14 @@ public class RemoteComCustomerLevelServiceImpl implements RemoteComCustomerLevel
         List<ComCustomerLevelVo> list = comCustomerLevelService.queryList(new ComCustomerLevelBo());
         return BeanUtil.copyToList(list, RemoteComCustomerLevelVo.class);
     }
+
+    @Override
+    public String selectCustomerLevelNoById(Long id) {
+        String levelNo = "";
+        ComCustomerLevelVo comCustomerLevelVo = comCustomerLevelService.queryById(id);
+        if (comCustomerLevelVo != null) {
+            levelNo = comCustomerLevelVo.getLevelCode();
+        }
+        return levelNo;
+    }
 }

+ 10 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComCustomerTypeServiceImpl.java

@@ -40,4 +40,14 @@ public class RemoteComCustomerTypeServiceImpl implements RemoteComCustomerTypeSe
             .map(e -> BeanUtil.toBean(e, RemoteComCustomerTypeVo.class))
             .collect(Collectors.toList());
     }
+
+    @Override
+    public String selectCustomerTypeNoNameById(Long id) {
+        String customerTypeNo="";
+        ComCustomerTypeVo comCustomerTypeVo = comCustomerTypeService.queryById( id);
+        if (comCustomerTypeVo != null) {
+            customerTypeNo = comCustomerTypeVo.getTypeName();
+        }
+        return customerTypeNo;
+    }
 }

+ 11 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComDeptServiceImpl.java

@@ -3,6 +3,7 @@ package org.dromara.system.dubbo;
 import lombok.RequiredArgsConstructor;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.dromara.system.api.RemoteComDeptService;
+import org.dromara.system.domain.vo.ComDeptVo;
 import org.dromara.system.service.IComDeptService;
 import org.springframework.stereotype.Service;
 
@@ -20,4 +21,14 @@ public class RemoteComDeptServiceImpl implements RemoteComDeptService {
     public Map<Long, String> selectDeptNameByIds(Set<Long> ids) {
         return comDeptService.selectDeptNameByIds(ids);
     }
+
+    @Override
+    public String selectDeptNOById(Long id) {
+        String deptNO = "";
+        ComDeptVo comDeptVo = comDeptService.queryById(id);
+        if (comDeptVo != null) {
+            deptNO = comDeptVo.getDeptCode();
+        }
+        return deptNO;
+    }
 }

+ 8 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComLogisticsCompanyServiceImpl.java

@@ -68,4 +68,12 @@ public class RemoteComLogisticsCompanyServiceImpl implements RemoteComLogisticsC
         );
         return ObjectUtil.isEmpty(one) ? null : BeanUtil.toBean(one, RemoteLogisticsCompanyVo.class);
     }
+
+    /*
+    * 查询物流公司列表*/
+    @Override
+    public List<RemoteLogisticsCompanyVo> selectLogisticsCompanyList() {
+        List<ComLogisticsCompany> list = comLogisticsCompanyService.list();
+        return BeanUtil.copyToList(list, RemoteLogisticsCompanyVo.class);
+    }
 }

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

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import lombok.RequiredArgsConstructor;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.ObjectUtils;
 import org.dromara.system.api.RemoteComStaffService;
 import org.dromara.system.api.domain.vo.RemoteComStaffVo;
 import org.dromara.system.domain.vo.ComStaffVo;
@@ -51,4 +52,14 @@ public class RemoteComStaffServiceImpl implements RemoteComStaffService {
     public RemoteComStaffVo selectStaffByUserId(Long userId) {
         return BeanUtil.toBean(comStaffService.selectStaffByUserId(userId), RemoteComStaffVo.class);
     }
+
+    @Override
+    public String selectStaffCodeById(Long staffId) {
+        String staffCode = "";
+        ComStaffVo comStaffVo = comStaffService.queryById(staffId);
+        if (ObjectUtils.isNotNull(comStaffVo)){
+            staffCode = comStaffVo.getStaffCode();
+        }
+        return staffCode;
+    }
 }

+ 26 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteComWarehouseServiceImpl.java

@@ -0,0 +1,26 @@
+package org.dromara.system.dubbo;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.common.core.utils.ObjectUtils;
+import org.dromara.system.api.RemoteComWarehouseService;
+import org.dromara.system.domain.vo.ComWarehouseVo;
+import org.dromara.system.service.IComWarehouseService;
+import org.springframework.stereotype.Service;
+
+@RequiredArgsConstructor
+@Service
+@DubboService
+public class RemoteComWarehouseServiceImpl implements RemoteComWarehouseService {
+    private final IComWarehouseService warehouseService;
+
+    @Override
+    public String getWarehouseNoById(Long warehouseId) {
+        String warehouseNo = "";
+        ComWarehouseVo warehouse = warehouseService.queryById(warehouseId);
+        if (ObjectUtils.isNotNull(warehouse)){
+            warehouseNo = warehouse.getWarehouseCode();
+        }
+        return warehouseNo;
+    }
+}

+ 11 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCreditLevelServiceImpl.java

@@ -6,6 +6,7 @@ import org.apache.dubbo.config.annotation.DubboService;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.system.api.RemoteCreditLevelService;
 import org.dromara.system.api.domain.vo.RemoteCreditLevelVo;
+import org.dromara.system.domain.vo.CreditLevelVo;
 import org.dromara.system.service.ICreditLevelService;
 import org.springframework.stereotype.Service;
 
@@ -31,4 +32,14 @@ public class RemoteCreditLevelServiceImpl implements RemoteCreditLevelService {
     public RemoteCreditLevelVo selectByCreditLevelName(String creditLevelName) {
         return BeanUtil.toBean(creditLevelService.selectByCreditLevelName(creditLevelName), RemoteCreditLevelVo.class);
     }
+
+    @Override
+    public String selectCreditLevelCodeById(Long id) {
+        String creditLevelCode = "";
+      CreditLevelVo creditLevel = creditLevelService.queryById( id);
+        if (creditLevel != null) {
+            creditLevelCode = creditLevel.getCreditLevelNo();
+        }
+        return creditLevelCode;
+    }
 }