Explorar el Código

Merge branch 'dev' into ecp

liyuan hace 3 semanas
padre
commit
40ac7f99af
Se han modificado 31 ficheros con 1929 adiciones y 212 borrados
  1. 2 2
      blade-common/src/main/java/org/springblade/common/constant/LauncherConstant.java
  2. 0 44
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZCRMViewARBillHeadSel.java
  3. 158 0
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewARBillHeadSel.java
  4. 8 6
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewCustomerSel.java
  5. 1 1
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewDepartmentSel.java
  6. 8 0
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewItemSel.java
  7. 172 0
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewRecBillHeadSel.java
  8. 102 0
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewSalePriceSel.java
  9. 15 0
      blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewShipSel.java
  10. 34 2
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/common/U9cloudGetTokenUtil.java
  11. 24 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/CommonController.java
  12. 42 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewARBillHeadSelController.java
  13. 0 1
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewCustomerSelController.java
  14. 44 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewRecBillHeadSelController.java
  15. 48 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewSalePriceSelController.java
  16. 7 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewARBillHeadSelMapper.java
  17. 8 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewRecBillHeadSelMapper.java
  18. 8 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewSalePriceSelMapper.java
  19. 13 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewARBillHeadSelService.java
  20. 13 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewRecBillHeadSelService.java
  21. 11 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewSalePriceSelService.java
  22. 179 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewARBillHeadSelServiceImpl.java
  23. 99 39
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewCustomerSelServiceImpl.java
  24. 101 20
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewDepartmentSelServiceImpl.java
  25. 97 19
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewItemSelServiceImpl.java
  26. 119 23
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewOperatorsSelServiceImpl.java
  27. 161 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewRecBillHeadSelServiceImpl.java
  28. 165 0
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewSalePriceSelServiceImpl.java
  29. 97 18
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewShipSelServiceImpl.java
  30. 97 19
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewSupplierSelServiceImpl.java
  31. 96 18
      blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewWhqohSelServiceImpl.java

+ 2 - 2
blade-common/src/main/java/org/springblade/common/constant/LauncherConstant.java

@@ -50,7 +50,7 @@ public interface LauncherConstant {
 	/**
 	 * nacos dev 用戶名
 	 */
-	String NACOS_DEV_USERNAME = "nacos";
+	String NACOS_DEV_USERNAME = "";
 
 	/**
 	 * nacos test 用戶名
@@ -66,7 +66,7 @@ public interface LauncherConstant {
 	/**
 	 * nacos dev 密码
 	 */
-	String NACOS_DEV_PASSWORD = "tbnacos123";
+	String NACOS_DEV_PASSWORD = "";
 
 	/**
 	 * nacos test 密码

+ 0 - 44
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZCRMViewARBillHeadSel.java

@@ -1,44 +0,0 @@
-package org.springblade.u9cloud.entity;
-
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-import org.springblade.core.mp.base.BaseEntity;
-
-/**
- * <p>
- * 应收单表
- * </p>
- *
- * @author your-name
- * @since 2025-07-30
- */
-@Data
-@TableName("zcrm_view_zrbillhead_sel")
-public class ZCRMViewARBillHeadSel extends BaseEntity {
-
-	private static final long serialVersionUID = 1L;
-
-
-	/* ========== 通用字段 ========== */
-
-	@JsonProperty("ORG_ID")
-	@TableField("ORG_ID")
-	private Long orgId;
-
-	@JsonProperty("ORG_CODE")
-	@TableField("ORG_CODE")
-	private String orgCode;
-
-	@JsonProperty("ORG_NAME")
-	@TableField("ORG_NAME")
-	private String orgName;
-
-
-
-
-
-
-}

+ 158 - 0
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewARBillHeadSel.java

@@ -0,0 +1,158 @@
+package org.springblade.u9cloud.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import org.springblade.core.mp.base.BaseEntity;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 应收单表
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@Data
+@TableName("zcrm_view_arbillhead_sel")
+public class ZcrmViewARBillHeadSel extends BaseEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/* ========== 组织相关字段 ========== */
+	@JsonProperty("Org_ID")
+	@TableField("Org_ID")
+	private Long orgId;  // 组织ID
+
+	@JsonProperty("Org_Code")
+	@TableField("Org_Code")
+	private String orgCode;  // 组织编码
+
+	@JsonProperty("Org_Name")
+	@TableField("Org_Name")
+	private String orgName;  // 组织名称
+
+
+	/* ========== 单据类型相关字段 ========== */
+	@JsonProperty("DocType_ID")
+	@TableField("DocType_ID")
+	private Long docTypeId;  // 单据类型ID
+
+	@JsonProperty("DocType_Code")
+	@TableField("DocType_Code")
+	private String docTypeCode;  // 单据类型编码
+
+	@JsonProperty("DocType_Name")
+	@TableField("DocType_Name")
+	private String docTypeName;  // 单据类型名称
+
+
+	/* ========== 单据基本信息 ========== */
+	@JsonProperty("DocNo")
+	@TableField("DocNo")
+	private String docNo;  // 单号
+
+	@JsonProperty("BusinessDate")
+	@TableField("BusinessDate")
+	private LocalDateTime businessDate;  // 日期
+
+	@JsonProperty("DocStatus")
+	@TableField("DocStatus")
+	private Integer docStatus;  // 状态(0开立,1核准中,2已核准,3执行中,4业务关闭)
+
+
+	/* ========== 客户相关字段 ========== */
+	@JsonProperty("Customer_ID")
+	@TableField("Customer_ID")
+	private Long customerId;  // 客户ID
+
+	@JsonProperty("Customer_Code")
+	@TableField("Customer_Code")
+	private String customerCode;  // 客户编码
+
+	@JsonProperty("Customer_Name")
+	@TableField("Customer_Name")
+	private String customerName;  // 客户名称
+
+	@JsonProperty("CustSite_ID")
+	@TableField("CustSite_ID")
+	private Long custSiteId;  // 客户位置ID
+
+	@JsonProperty("CustSite_Code")
+	@TableField("CustSite_Code")
+	private String custSiteCode;  // 客户位置编码
+
+	@JsonProperty("CustSite_Name")
+	@TableField("CustSite_Name")
+	private String custSiteName;  // 客户位置名称
+
+
+	/* ========== 物料相关字段 ========== */
+	@JsonProperty("Item_ID")
+	@TableField("Item_ID")
+	private Long itemId;  // 物料ID
+
+	@JsonProperty("Item_Code")
+	@TableField("Item_Code")
+	private String itemCode;  // 料号
+
+	@JsonProperty("Item_Name")
+	@TableField("Item_Name")
+	private String itemName;  // 品名
+
+	@JsonProperty("SPECS")
+	@TableField("SPECS")
+	private String specs;  // 规格
+
+
+	/* ========== 数量与金额相关字段 ========== */
+	@JsonProperty("Qty")
+	@TableField("Qty")
+	private BigDecimal qty;  // 数量
+
+	@JsonProperty("TaxPrice")
+	@TableField("TaxPrice")
+	private BigDecimal taxPrice;  // 含税单价
+
+	@JsonProperty("PUAmount")
+	@TableField("PUAmount")
+	private BigDecimal puAmount;  // 数量
+
+	@JsonProperty("AROCMoney_NonTax")
+	@TableField("AROCMoney_NonTax")
+	private BigDecimal arocMoneyNonTax;  // 核币未税金额
+
+	@JsonProperty("AROCMoney_GoodsTax")
+	@TableField("AROCMoney_GoodsTax")
+	private BigDecimal arocMoneyGoodsTax;  // 核币税额
+
+	@JsonProperty("AROCMoney_TotalMoney")
+	@TableField("AROCMoney_TotalMoney")
+	private BigDecimal arocMoneyTotalMoney;  // 核币总金额
+
+	@JsonProperty("ARFCMoney_NonTax")
+	@TableField("ARFCMoney_NonTax")
+	private BigDecimal arfcMoneyNonTax;  // 本币未税金额
+
+	@JsonProperty("ARFCMoney_GoodsTax")
+	@TableField("ARFCMoney_GoodsTax")
+	private BigDecimal arfcMoneyGoodsTax;  // 本币税额
+
+	@JsonProperty("ARFCMoney_TotalMoney")
+	@TableField("ARFCMoney_TotalMoney")
+	private BigDecimal arfcMoneyTotalMoney;  // 本币总金额
+
+
+	/* ========== 销售单相关字段 ========== */
+	@JsonProperty("SoDocNo")
+	@TableField("SoDocNo")
+	private String soDocNo;  // 销售单号
+
+	@JsonProperty("SoDocLineNo")
+	@TableField("SoDocLineNo")
+	private Integer soDocLineNo;  // 行号
+
+}

+ 8 - 6
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewCustomerSel.java

@@ -223,11 +223,13 @@ public class ZcrmViewCustomerSel extends BaseEntity {
 	@TableField("ARConfirmTerm_ID")
 	private Long arConfirmTermId;
 
-	@JsonProperty("ARConfirmTerm_CODE")
-	@TableField("ARConfirmTerm_CODE")
-	private String arConfirmTermCode;
+	@JsonProperty("PubDescSeg4_Code")
+	@TableField("PubDescSeg4_Code")
+	private String pubDescSeg4Code;
+
+	@JsonProperty("PubDescSeg4_Name")
+	@TableField("PubDescSeg4_Name")
+	private String pubDescSeg4Name;
+
 
-	@JsonProperty("ARConfirmTerm_NAME")
-	@TableField("ARConfirmTerm_NAME")
-	private String arConfirmTermName;
 }

+ 1 - 1
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewDepartmentSel.java

@@ -48,5 +48,5 @@ public class ZcrmViewDepartmentSel extends BaseEntity {
 
 	@JsonProperty("Department_IsLeaf")
 	@TableField("Department_IsLeaf")
-	private Boolean departmentIsLeaf;
+	private Integer departmentIsLeaf;
 }

+ 8 - 0
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewItemSel.java

@@ -137,4 +137,12 @@ public class ZcrmViewItemSel extends BaseEntity {
 	@JsonProperty("Item_Price")
 	@TableField("Item_Price")
 	private BigDecimal itemPrice;
+
+	@JsonProperty("PubDescSeg4_Code")
+	@TableField("PubDescSeg4_Code")
+	private String pubDescSeg4Code;
+
+	@JsonProperty("PubDescSeg4_Name")
+	@TableField("PubDescSeg4_Name")
+	private String pubDescSeg4Name;
 }

+ 172 - 0
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewRecBillHeadSel.java

@@ -0,0 +1,172 @@
+package org.springblade.u9cloud.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import org.springblade.core.mp.base.BaseEntity;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 应收单表
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@Data
+@TableName("zcrm_view_recbillhead_sel")
+public class ZcrmViewRecBillHeadSel extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /* ========== 组织相关字段 ========== */
+    @JsonProperty("Org_ID")
+    @TableField("Org_ID")
+    private Long orgId;  // 组织ID
+
+    @JsonProperty("Org_Code")
+    @TableField("Org_Code")
+    private String orgCode;  // 组织编码
+
+    @JsonProperty("Org_Name")
+    @TableField("Org_Name")
+    private String orgName;  // 组织名称
+
+
+    /* ========== 单据类型相关字段 ========== */
+    @JsonProperty("DocType_ID")
+    @TableField("DocType_ID")
+    private Long docTypeId;  // 单据类型ID
+
+    @JsonProperty("DocType_Code")
+    @TableField("DocType_Code")
+    private String docTypeCode;  // 单据类型编码
+
+    @JsonProperty("DocType_Name")
+    @TableField("DocType_Name")
+    private String docTypeName;  // 单据类型名称
+
+
+    /* ========== 单据基本信息 ========== */
+    @JsonProperty("DocNo")
+    @TableField("DocNo")
+    private String docNo;  // 单号
+
+    @JsonProperty("BusinessDate")
+    @TableField("BusinessDate")
+    private LocalDateTime businessDate;  // 日期
+
+    @JsonProperty("DocStatus")
+    @TableField("DocStatus")
+    private Integer docStatus;  // 状态(0开立,1核准中,2已核准,3执行中,4业务关闭)
+
+
+    /* ========== 客户相关字段 ========== */
+    @JsonProperty("Customer_ID")
+    @TableField("Customer_ID")
+    private Long customerId;  // 客户ID
+
+    @JsonProperty("Customer_Code")
+    @TableField("Customer_Code")
+    private String customerCode;  // 客户编码
+
+    @JsonProperty("Customer_Name")
+    @TableField("Customer_Name")
+    private String customerName;  // 客户名称
+
+    @JsonProperty("CustSite_ID")
+    @TableField("CustSite_ID")
+    private Long custSiteId;  // 客户位置ID
+
+    @JsonProperty("CustSite_Code")
+    @TableField("CustSite_Code")
+    private String custSiteCode;  // 客户位置编码
+
+    @JsonProperty("CustSite_Name")
+    @TableField("CustSite_Name")
+    private String custSiteName;  // 客户位置名称
+
+
+    /* ========== 币种相关字段 ========== */
+    @JsonProperty("Currency_ID")
+    @TableField("Currency_ID")
+    private Long currencyId;  // 币种ID
+
+    @JsonProperty("Currency_Code")
+    @TableField("Currency_Code")
+    private String currencyCode;  // 币种编码
+
+    @JsonProperty("Currency_Name")
+    @TableField("Currency_Name")
+    private String currencyName;  // 币种名称
+
+
+    /* ========== 行号与结算方式 ========== */
+    @JsonProperty("LineNum")
+    @TableField("LineNum")
+    private Integer lineNum;  // 行号
+
+    @JsonProperty("SettlementMethod_ID")
+    @TableField("SettlementMethod_ID")
+    private Long settlementMethodId;  // 结算方式ID
+
+    @JsonProperty("SettlementMethod_Code")
+    @TableField("SettlementMethod_Code")
+    private String settlementMethodCode;  // 结算方式编码
+
+    @JsonProperty("SettlementMethod_Name")
+    @TableField("SettlementMethod_Name")
+    private String settlementMethodName;  // 结算方式名称
+
+
+    /* ========== 金额相关字段 ========== */
+    @JsonProperty("Money_FCMoney")
+    @TableField("Money_FCMoney")
+    private BigDecimal moneyFcMoney;  // 本币金额
+
+    @JsonProperty("Money_QCMoney")
+    @TableField("Money_QCMoney")
+    private BigDecimal moneyQcMoney;  // 核币金额
+
+    @JsonProperty("SettlementFee_FCMoney")
+    @TableField("SettlementFee_FCMoney")
+    private BigDecimal settlementFeeFcMoney;  // 手续费本币
+
+    @JsonProperty("SettlementFee_QCMoney")
+    @TableField("SettlementFee_QCMoney")
+    private BigDecimal settlementFeeQcMoney;  // 手续费核币
+
+    @JsonProperty("TaxRate")
+    @TableField("TaxRate")
+    private BigDecimal taxRate;  // 税率
+
+    @JsonProperty("NonTaxMoney_FCMoney")
+    @TableField("NonTaxMoney_FCMoney")
+    private BigDecimal nonTaxMoneyFcMoney;  // 未税金额本币
+
+    @JsonProperty("NonTaxMoney_QCMoney")
+    @TableField("NonTaxMoney_QCMoney")
+    private BigDecimal nonTaxMoneyQcMoney;  // 未税金额核币
+
+    @JsonProperty("TaxMoney_FCMoney")
+    @TableField("TaxMoney_FCMoney")
+    private BigDecimal taxMoneyFcMoney;  // 总金额本币
+
+    @JsonProperty("TaxMoney_QCMoney")
+    @TableField("TaxMoney_QCMoney")
+    private BigDecimal taxMoneyQcMoney;  // 总金额核币
+
+
+    /* ========== 银行相关字段 ========== */
+    @JsonProperty("BankCode")
+    @TableField("BankCode")
+    private String bankCode;  // 银行账号
+
+    @JsonProperty("BankName")
+    @TableField("BankName")
+    private String bankName;  // 收款银行
+
+}

+ 102 - 0
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewSalePriceSel.java

@@ -0,0 +1,102 @@
+package org.springblade.u9cloud.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import org.springblade.core.mp.base.BaseEntity;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 业务员档案视图
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-11-07
+ */
+@Data
+@TableName("zcrm_view_saleprice_sel")
+public class ZcrmViewSalePriceSel extends BaseEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/* ========== 组织相关字段 ========== */
+	@JsonProperty("Org_ID")
+	@TableField("Org_ID")
+	private Long orgId;  // 组织ID
+
+	@JsonProperty("Org_Code")
+	@TableField("Org_Code")
+	private String orgCode;  // 组织编码
+
+	@JsonProperty("Org_Name")
+	@TableField("Org_Name")
+	private String orgName;  // 组织名称
+
+
+	/* ========== 基础信息字段 ========== */
+	@JsonProperty("Code")
+	@TableField("Code")
+	private String code;  // 编码
+
+	@JsonProperty("Name")
+	@TableField("Name")
+	private String name;  // 名称
+
+	@JsonProperty("Status")
+	@TableField("Status")
+	private Integer status;  // 状态(0=开立,1=核准中,2=已核准)
+
+	@JsonProperty("IsIncludeTax")
+	@TableField("IsIncludeTax")
+	private Integer isIncludeTax;  // 价格含税(1=是,0=否)
+
+	@JsonProperty("DocLineNo")
+	@TableField("DocLineNo")
+	private Integer docLineNo;  // 行号
+
+
+	/* ========== 客户相关字段 ========== */
+	@JsonProperty("Customer_ID")
+	@TableField("Customer_ID")
+	private Long customerId;  // 客户ID
+
+	@JsonProperty("Customer_Code")
+	@TableField("Customer_Code")
+	private String customerCode;  // 客户编码
+
+	@JsonProperty("Customer_Name")
+	@TableField("Customer_Name")
+	private String customerName;  // 客户名称
+
+
+	/* ========== 料品相关字段 ========== */
+	@JsonProperty("Item_ID")
+	@TableField("Item_ID")
+	private Long itemId;  // 料品ID
+
+	@JsonProperty("Item_Code")
+	@TableField("Item_Code")
+	private String itemCode;  // 料号
+
+	@JsonProperty("Item_Name")
+	@TableField("Item_Name")
+	private String itemName;  // 品名
+
+
+	/* ========== 价格与日期字段 ========== */
+	@JsonProperty("Price")
+	@TableField("Price")
+	private BigDecimal price;  // 单价
+
+	@JsonProperty("FromDate")
+	@TableField("FromDate")
+	private LocalDateTime fromDate;  // 生效日期
+
+	@JsonProperty("ToDate")
+	@TableField("ToDate")
+	private LocalDateTime toDate;  // 失效日期
+
+}

+ 15 - 0
blade-service-api/blade-u9cloud-api/src/main/java/org/springblade/u9cloud/entity/ZcrmViewShipSel.java

@@ -118,4 +118,19 @@ public class ZcrmViewShipSel extends BaseEntity {
 	@JsonProperty("LineStatus")
 	@TableField("LineStatus")
 	private Integer lineStatus;
+
+	@JsonProperty("SoDocNo")
+	@TableField("SoDocNo")
+	private String soDocNo;
+
+	@JsonProperty("SoDocLineNo")
+	@TableField("SoDocLineNo")
+	private Integer soDocLineNo;
+
+	@JsonProperty("ShipAddress")
+	@TableField("ShipAddress")
+	private String shipAddress;
+
+
+
 }

+ 34 - 2
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/common/U9cloudGetTokenUtil.java

@@ -30,13 +30,14 @@ public class U9cloudGetTokenUtil {
 	 */
 	private BladeRedis bladeRedis;
 
+
 	/**
 	 * u9获取token
 	 * @return
 	 */
-	public String getToken() {
+	public String getToken2() {
 		try{
-			if (bladeRedis.exists("token")) return bladeRedis.get("token");
+			if (bladeRedis.exists("token2")) return bladeRedis.get("token2");
 			String url = UriComponentsBuilder.fromHttpUrl(BASE_URL + PATH_LOGIN)
 				.queryParam("clientid", "B2B")
 				.queryParam("clientsecret", "4bd49cc5440c4f158a9f3d6ebfc006e7")
@@ -52,6 +53,37 @@ public class U9cloudGetTokenUtil {
 			System.out.println(response.getBody());
 			JSONObject jsonObject = response.getBody();
 			System.out.println(jsonObject.get("Data").toString());
+			bladeRedis.setEx("token2", jsonObject.get("Data").toString(),60L * 30);
+			return jsonObject.get("Data").toString();
+		} catch (Exception e) {
+			return "";
+		}
+	}
+
+
+
+	/**
+	 * u9获取token
+	 * @return
+	 */
+	public String getToken() {
+		try{
+//			if (bladeRedis.exists("token")) return bladeRedis.get("token");
+			String url = UriComponentsBuilder.fromHttpUrl(BASE_URL + PATH_LOGIN)
+				.queryParam("clientid", "B2B")
+				.queryParam("clientsecret", "4bd49cc5440c4f158a9f3d6ebfc006e7")
+				.queryParam("entcode", "003")
+				.queryParam("usercode", "B2B")
+				.queryParam("orgcode", "002")
+				.encode(StandardCharsets.UTF_8)
+				.toUriString();
+
+			// 2. 发送请求
+			RestTemplate restTemplate = new RestTemplate();
+			ResponseEntity<JSONObject> response = restTemplate.getForEntity(url, JSONObject.class);
+			System.out.println(response.getBody());
+			JSONObject jsonObject = response.getBody();
+			System.out.println(jsonObject.get("Data").toString());
 			bladeRedis.setEx("token", jsonObject.get("Data").toString(),60L * 30);
 			return jsonObject.get("Data").toString();
 		} catch (Exception e) {

+ 24 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/CommonController.java

@@ -33,6 +33,30 @@ public class CommonController { // 类名规范:首字母大写,改为Common
 	private final ZcrmViewSupplierSelService zcrmViewSupplierSelService;
 	private final ZcrmViewWhqohSelService zcrmViewWhqohSelService;
 
+	private final ZcrmViewSalePriceSelService zcrmViewSalePriceSelService;
+	private final ZcrmViewRecBillHeadSelService zcrmViewRecBillHeadSelService;
+	private final ZcrmViewARBillHeadSelService zcrmViewARBillHeadSelService;
+
+
+	/**
+	 * 统一执行U9数据同步,事务保证:任一方法失败则全部回滚
+	 */
+	@GetMapping("/unificationPro")
+	@ApiOperation("U9数据统一同步") // 补充Swagger接口描述(可选)
+	@Transactional(rollbackFor = Exception.class) // 明确对所有Exception回滚
+	public void unificationPro() {
+		boolean res1 = zcrmViewCustomerSelService.insertBatchCustomers();
+//		boolean res2 = zcrmViewDepartmentSelService.insertBatchDepartments();
+		boolean res3 = zcrmViewItemSelService.insertBatchItems();
+//		boolean res4 = zcrmViewOperatorsSelService.insertBatchOperators();
+		boolean res5 = zcrmViewShipSelService.insertBatchShips();
+//		boolean res6 = zcrmViewSupplierSelService.insertBatchSuppliers();
+		boolean res7 = zcrmViewWhqohSelService.insertBatchWhqohs();
+		boolean res8 = zcrmViewSalePriceSelService.insertBatchOperators();
+		boolean res9 = zcrmViewRecBillHeadSelService.insertBatchOperators();
+		boolean res10 = zcrmViewARBillHeadSelService.insertBatchCustomers();
+	}
+
 
 	/**
 	 * 统一执行U9数据同步,事务保证:任一方法失败则全部回滚

+ 42 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewARBillHeadSelController.java

@@ -0,0 +1,42 @@
+package org.springblade.u9cloud.controller;
+
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.service.ZcrmViewARBillHeadSelService;
+import org.springblade.u9cloud.service.ZcrmViewOperatorsSelService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 应收单 前端控制器
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@RestController
+@RequestMapping("/api/viewARBillHeadSel")
+@AllArgsConstructor
+public class ZcrmViewARBillHeadSelController {
+
+
+    private final ZcrmViewARBillHeadSelService zcrmViewARBillHeadSelService;
+
+    /**
+     * 执行同步
+     * @return
+     */
+    @GetMapping("/executionSynchronization")
+    public R<String> executionSynchronization()
+    {
+        boolean res = zcrmViewARBillHeadSelService.insertBatchCustomers();
+        if (res) {
+            return R.data("执行成功");
+        } else {
+            return R.data("执行失败");
+        }
+    }
+}

+ 0 - 1
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewCustomerSelController.java

@@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
 @RestController
 @RequestMapping("/api/viewCustomerSel")
 @AllArgsConstructor
-
 public class ZcrmViewCustomerSelController {
 
 	private final ZcrmViewCustomerSelService zcrmViewCustomerSelService;

+ 44 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewRecBillHeadSelController.java

@@ -0,0 +1,44 @@
+package org.springblade.u9cloud.controller;
+
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.service.ZcrmViewRecBillHeadSelService;
+import org.springblade.u9cloud.service.ZcrmViewShipSelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 收款单 前端控制器
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@RestController
+@RequestMapping("/api/viewRecBillHeadSel")
+@AllArgsConstructor
+public class ZcrmViewRecBillHeadSelController {
+
+    @Autowired
+    private final ZcrmViewRecBillHeadSelService zcrmViewRecBillHeadSelService;
+
+    /**
+     * 执行同步
+     * @return
+     */
+    @GetMapping("/executionSynchronization")
+    public R<String> executionSynchronization()
+    {
+        boolean res = zcrmViewRecBillHeadSelService.insertBatchOperators();
+        if (res) {
+            return R.data("执行成功");
+        } else {
+            return R.data("执行失败");
+        }
+    }
+
+}

+ 48 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ZcrmViewSalePriceSelController.java

@@ -0,0 +1,48 @@
+package org.springblade.u9cloud.controller;
+
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.service.ZcrmViewRecBillHeadSelService;
+import org.springblade.u9cloud.service.ZcrmViewSalePriceSelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 销售价目表 前端控制器
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@RestController
+@RequestMapping("/api/viewSalepriceSel")
+@AllArgsConstructor
+public class ZcrmViewSalePriceSelController {
+
+	@Autowired
+	private final ZcrmViewSalePriceSelService zcrmViewSalePriceSelService;
+
+	/**
+	 * 执行同步
+	 * @return
+	 */
+	@GetMapping("/executionSynchronization")
+	public R<String> executionSynchronization()
+	{
+		boolean res = zcrmViewSalePriceSelService.insertBatchOperators();
+		if (res) {
+			return R.data("执行成功");
+		} else {
+			return R.data("执行失败");
+		}
+	}
+
+
+
+
+
+}

+ 7 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewARBillHeadSelMapper.java

@@ -0,0 +1,7 @@
+package org.springblade.u9cloud.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.u9cloud.entity.ZcrmViewARBillHeadSel;
+
+public interface ZcrmViewARBillHeadSelMapper extends BaseMapper<ZcrmViewARBillHeadSel> {
+}

+ 8 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewRecBillHeadSelMapper.java

@@ -0,0 +1,8 @@
+package org.springblade.u9cloud.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+import org.springblade.u9cloud.entity.ZcrmViewShipSel;
+
+public interface ZcrmViewRecBillHeadSelMapper  extends BaseMapper<ZcrmViewRecBillHeadSel> {
+}

+ 8 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/mapper/ZcrmViewSalePriceSelMapper.java

@@ -0,0 +1,8 @@
+package org.springblade.u9cloud.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+import org.springblade.u9cloud.entity.ZcrmViewSalePriceSel;
+
+public interface ZcrmViewSalePriceSelMapper extends BaseMapper<ZcrmViewSalePriceSel> {
+}

+ 13 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewARBillHeadSelService.java

@@ -0,0 +1,13 @@
+package org.springblade.u9cloud.service;
+
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.u9cloud.entity.ZcrmViewARBillHeadSel;
+
+public interface ZcrmViewARBillHeadSelService extends BaseService<ZcrmViewARBillHeadSel> {
+
+
+    boolean insertBatchCustomers();
+
+
+}

+ 13 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewRecBillHeadSelService.java

@@ -0,0 +1,13 @@
+package org.springblade.u9cloud.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.u9cloud.entity.ZcrmViewOperatorsSel;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+
+public interface ZcrmViewRecBillHeadSelService extends BaseService<ZcrmViewRecBillHeadSel> {
+
+
+    boolean insertBatchOperators();
+
+
+}

+ 11 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/ZcrmViewSalePriceSelService.java

@@ -0,0 +1,11 @@
+package org.springblade.u9cloud.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+import org.springblade.u9cloud.entity.ZcrmViewSalePriceSel;
+
+public interface ZcrmViewSalePriceSelService extends BaseService<ZcrmViewSalePriceSel> {
+
+	boolean insertBatchOperators();
+
+}

+ 179 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewARBillHeadSelServiceImpl.java

@@ -0,0 +1,179 @@
+package org.springblade.u9cloud.service.impl;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.u9cloud.common.U9cloudGetTokenUtil;
+import org.springblade.u9cloud.config.U9cloudConfig;
+import org.springblade.u9cloud.entity.ViewApiResponse;
+import org.springblade.u9cloud.entity.ZcrmViewARBillHeadSel;
+import org.springblade.u9cloud.mapper.ZcrmViewARBillHeadSelMapper;
+import org.springblade.u9cloud.service.ZcrmViewARBillHeadSelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * <p>
+ * 客户档案 服务实现类
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@Service
+@AllArgsConstructor
+public class ZcrmViewARBillHeadSelServiceImpl  extends BaseServiceImpl<ZcrmViewARBillHeadSelMapper, ZcrmViewARBillHeadSel>
+        implements ZcrmViewARBillHeadSelService {
+
+
+    private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean insertBatchCustomers() {
+        try {
+            // 1. 构建请求URL和参数
+            String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
+                    .encode(StandardCharsets.UTF_8)
+                    .toUriString();
+
+            Map<String, String> requestBody = new HashMap<>();
+            requestBody.put("SqlString", "select * from ZCRM_View_ARBillHead_Sel");
+
+            // 2. 设置请求头并构建请求实体
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_JSON);
+            String token = u9cloudGetTokenUtil.getToken();
+            headers.set("token", token);
+            HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
+            // 3. 发送请求并先获取原始JSON字符串(关键:打印原始数据)
+            RestTemplate restTemplate = new RestTemplate();
+            // 先以String类型接收原始响应,避免反序列化失败
+            String rawResponse = restTemplate.postForObject(url, requestEntity, String.class);
+            // 打印原始JSON到控制台,用于对比实体类
+            System.out.println("===== 接口返回原始JSON数据 =====");
+            System.out.println(rawResponse);
+            System.out.println("===============================");
+
+            // 4. 手动解析原始JSON为ViewApiResponse(解决反序列化类型问题)
+            ObjectMapper objectMapper = new ObjectMapper();
+            // 配置支持LocalDateTime等时间类型解析
+            objectMapper.registerModule(new JavaTimeModule());
+            objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+
+            // 解析响应(根据实际data类型调整:若为数组用List,若为对象用单个实体)
+            ViewApiResponse<ZcrmViewARBillHeadSel> apiResponse = objectMapper.readValue(
+                    rawResponse,
+                    new TypeReference<ViewApiResponse<ZcrmViewARBillHeadSel>>() {}
+            );
+
+            // 5. 校验响应合法性
+            if (apiResponse == null || !apiResponse.isSuccess()) {
+                System.err.println("接口返回失败:" + apiResponse.getResMsg());
+                return false;
+            }
+            List<ZcrmViewARBillHeadSel> newARBillHeads = apiResponse.getData();
+            if (newARBillHeads == null || newARBillHeads.isEmpty()) {
+                System.out.println("没有获取到应收单数据");
+                return false;
+            }
+
+            // 6. 提取唯一标识字段(过滤空值)
+            List<String> docNos = newARBillHeads.stream()
+                    .map(ZcrmViewARBillHeadSel::getDocNo)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            List<Long> customerIds = newARBillHeads.stream()
+                    .map(ZcrmViewARBillHeadSel::getCustomerId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            if (docNos.isEmpty() || customerIds.isEmpty()) {
+                System.err.println("存在 DocNo 或 Customer_ID 为空的记录,跳过处理");
+                return false;
+            }
+
+            // 7. 用JdbcTemplate查询已存在记录(联合唯一键查询)
+            List<ZcrmViewARBillHeadSel> existingARBillHeads = new ArrayList<>();
+            try {
+                String sql = "SELECT * FROM zcrm_view_arbillhead_sel " +
+                        "WHERE DocNo IN ('" + String.join("','", docNos) + "') " +  // 字符串类型用单引号包裹
+                        "AND Customer_ID IN (" + String.join(",", customerIds.stream().map(String::valueOf).collect(Collectors.toList())) + ")";
+
+                existingARBillHeads = jdbcTemplate.query(
+                        sql,
+                        new BeanPropertyRowMapper<>(ZcrmViewARBillHeadSel.class)
+                );
+            } catch (Exception e) {
+                throw new RuntimeException("查询已存在应收单记录失败", e);
+            }
+
+            // 8. 构建已存在记录的映射表(以“DocNo-Customer_ID”为唯一键)
+            Map<String, ZcrmViewARBillHeadSel> existingMap = new HashMap<>();
+            for (ZcrmViewARBillHeadSel existing : existingARBillHeads) {
+                String key = existing.getDocNo() + "-" + existing.getCustomerId();
+                existingMap.put(key, existing);
+            }
+
+            // 9. 分离新增和更新列表
+            List<ZcrmViewARBillHeadSel> insertList = new ArrayList<>();
+            List<ZcrmViewARBillHeadSel> updateList = new ArrayList<>();
+
+            for (ZcrmViewARBillHeadSel newARBill : newARBillHeads) {
+                String docNo = newARBill.getDocNo();
+                Long customerId = newARBill.getCustomerId();
+
+                // 跳过关键字段为空的记录
+                if (docNo == null || customerId == null) {
+                    System.err.println("跳过 DocNo 或 Customer_ID 为空的记录");
+                    continue;
+                }
+
+                String key = docNo + "-" + customerId;
+                if (existingMap.containsKey(key)) {
+                    // 已存在:更新(拷贝主键ID)
+                    ZcrmViewARBillHeadSel existing = existingMap.get(key);
+                    newARBill.setId(existing.getId());  // 继承自BaseEntity的id字段
+                    updateList.add(newARBill);
+                } else {
+                    // 不存在:新增
+                    insertList.add(newARBill);
+                }
+            }
+
+            // 10. 执行批量操作
+            boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+            boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+            return insertSuccess && updateSuccess;
+
+        } catch (Exception e) {
+            // 打印异常信息,方便定位问题
+            System.err.println("处理应收单数据时发生异常:");
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+}

+ 99 - 39
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewCustomerSelServiceImpl.java

@@ -1,5 +1,6 @@
 package org.springblade.u9cloud.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.AllArgsConstructor;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.tool.api.R;
@@ -9,8 +10,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewCustomerSel;
 import org.springblade.u9cloud.mapper.ZcrmViewCustomerSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewCustomerSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -18,9 +22,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import org.springblade.u9cloud.config.U9cloudConfig;
 
@@ -41,6 +44,9 @@ public class ZcrmViewCustomerSelServiceImpl extends BaseServiceImpl<ZcrmViewCust
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
 
 	@Override
 	@Transactional(rollbackFor = Exception.class)
@@ -54,85 +60,139 @@ public class ZcrmViewCustomerSelServiceImpl extends BaseServiceImpl<ZcrmViewCust
 		return this.saveBatch(customers);
 	}
 
-
-
 	private final IUserClient userClient;
 
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchCustomers() {
-		// 1. 构建 URL
+		// 1. 构建URL和请求参数(保持不变)
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 请求体
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Customer_Sel");
 
-		// 3. 请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		headers.set("token", u9cloudGetTokenUtil.getToken());
-
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
 
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应(保持不变)
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewCustomerSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewCustomerSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewCustomerSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewCustomerSel> apiResponse = response.getBody();
 
-		// 将 ViewApiResponse<ZcrmViewCustomerSel> 转成 List<ZcrmViewCustomerSel>
+
+		// 3. 处理用户同步(保持不变)
 		try {
 			if (apiResponse != null && apiResponse.isSuccess()) {
 				List<ZcrmViewCustomerSel> customerList = apiResponse.getData();
-				// 检查数据列表不为空再调用接口
 				if (customerList != null && !customerList.isEmpty()) {
 					R<String> result = userClient.insertOrUpdateDealerUser(customerList);
-					System.out.println(result); // R(code=400, success=false, data=null, msg=缺少经销商角色,请先维护角色)
-					// 将R对象转换为Map
 					Map<String, Object> resultMap = new HashMap<>();
-					// 通过反射获取R对象的属性值
 					Class<?> rClass = result.getClass();
 					resultMap.put("code", rClass.getMethod("getCode").invoke(result));
 					resultMap.put("success", rClass.getMethod("isSuccess").invoke(result));
 					resultMap.put("data", rClass.getMethod("getData").invoke(result));
 					resultMap.put("msg", rClass.getMethod("getMsg").invoke(result));
-					// 根据Map中的值进行判断
-					if (!(boolean) resultMap.get("success")) {
-						String errorMsg = (String) resultMap.get("msg");
-						int code = (int) resultMap.get("code");
-
-						// 处理缺少经销商角色的错误
-						if (code == 400) {
-							System.err.println("返回数据:" + resultMap.get("msg"));
-							return false;
-						}
-					} else {
-						System.err.println("同步用户数据成功,返回数据:" + resultMap.get("data"));
+
+					if (!(boolean) resultMap.get("success") && (int) resultMap.get("code") == 400) {
+						System.err.println("用户同步失败:" + resultMap.get("msg"));
+						return false;
 					}
 				}
 			}
 		} catch (Exception e) {
-			// 可以考虑在这里抛出异常让事务回滚,根据业务需求决定
-			 throw new RuntimeException("同步用户数据失败", e);
+			throw new RuntimeException("用户同步异常", e);
+		}
+
+
+		// 4. 核心逻辑:按 customerId + customerCode 去重(改用JdbcTemplate查询)
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewCustomerSel> newCustomers = apiResponse.getData();
+		if (newCustomers == null || newCustomers.isEmpty()) {
+			return false;
+		}
+
+
+		// 4.1 提取新数据中的 customerId 和 customerCode(过滤空值)
+		List<Long> customerIds = newCustomers.stream()
+			.map(ZcrmViewCustomerSel::getCustomerId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> customerCodes = newCustomers.stream()
+			.map(ZcrmViewCustomerSel::getCustomerCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (customerIds.isEmpty() || customerCodes.isEmpty()) {
+			System.err.println("存在 customerId 或 customerCode 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 4.2 关键修改:用JdbcTemplate查询已存在记录(绕开MyBatis拦截器)
+		List<ZcrmViewCustomerSel> existingCustomers = new ArrayList<>();
+		try {
+			// 构建SQL(注意表名和字段名与数据库一致)
+			String sql = "SELECT * FROM zcrm_view_customer_sel " +
+				"WHERE Customer_ID IN (" + String.join(",", customerIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Customer_CODE IN ('" + String.join("','", customerCodes) + "')";
+
+			// 执行查询(用BeanPropertyRowMapper映射实体)
+			existingCustomers = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewCustomerSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在客户记录失败", e);
+		}
+
+
+		// 4.3 用 "customerId-customerCode" 作为唯一键,构建已存在记录的映射表(保持不变)
+		Map<String, ZcrmViewCustomerSel> existingMap = new HashMap<>();
+		for (ZcrmViewCustomerSel existing : existingCustomers) {
+			String key = existing.getCustomerId() + "-" + existing.getCustomerCode();
+			existingMap.put(key, existing);
 		}
 
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewCustomerSel> customers1 = apiResponse.getData();
-			if (customers1 != null && !customers1.isEmpty()) {
-				res = this.saveBatch(customers1);
+
+		// 4.4 分离新增和更新列表(保持不变)
+		List<ZcrmViewCustomerSel> insertList = new ArrayList<>();
+		List<ZcrmViewCustomerSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewCustomerSel newCust : newCustomers) {
+			Long id = newCust.getCustomerId();
+			String code = newCust.getCustomerCode();
+
+			if (id == null || code == null) {
+				System.err.println("跳过 customerId 或 customerCode 为空的记录");
+				continue;
+			}
+
+			String key = id + "-" + code;
+			if (existingMap.containsKey(key)) {
+				ZcrmViewCustomerSel existing = existingMap.get(key);
+				newCust.setId(existing.getId()); // 拷贝主键
+				updateList.add(newCust);
+			} else {
+				insertList.add(newCust);
 			}
 		}
-		return res;
+
+
+		// 5. 执行批量操作(保持不变)
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 	/**

+ 101 - 20
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewDepartmentSelServiceImpl.java

@@ -7,8 +7,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewDepartmentSel;
 import org.springblade.u9cloud.mapper.ZcrmViewDepartmentSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewDepartmentSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -17,9 +20,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 import org.springblade.u9cloud.config.U9cloudConfig;
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -36,6 +38,9 @@ public class ZcrmViewDepartmentSelServiceImpl extends BaseServiceImpl<ZcrmViewDe
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertDepartment(ZcrmViewDepartmentSel zcrmViewDepartmentSel) {
@@ -51,43 +56,119 @@ public class ZcrmViewDepartmentSelServiceImpl extends BaseServiceImpl<ZcrmViewDe
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchDepartments() {
-		// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Department_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		String token = u9cloudGetTokenUtil.getToken();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewDepartmentSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewDepartmentSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewDepartmentSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewDepartmentSel> apiResponse = response.getBody();
-		System.out.println(apiResponse);
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewDepartmentSel> customers1 = apiResponse.getData();
-			System.out.println(customers1);
-			if (!customers1.isEmpty()) {
-				res = this.saveBatch(customers1);
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			System.out.println("响应为空或请求失败");
+			return false;
+		}
+		List<ZcrmViewDepartmentSel> newDepartments = apiResponse.getData();
+		if (newDepartments == null || newDepartments.isEmpty()) {
+			System.out.println("部门数据为空");
+			return false;
+		}
+
+
+		// 4. 提取新数据中的唯一标识(过滤空值)
+		List<Long> departmentIds = newDepartments.stream()
+			.map(ZcrmViewDepartmentSel::getDepartmentId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> departmentCodes = newDepartments.stream()
+			.map(ZcrmViewDepartmentSel::getDepartmentCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (departmentIds.isEmpty() || departmentCodes.isEmpty()) {
+			System.err.println("存在 Department_ID 或 Department_CODE 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewDepartmentSel> existingDepartments = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_department_sel " +
+				"WHERE Department_ID IN (" + String.join(",", departmentIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Department_CODE IN ('" + String.join("','", departmentCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingDepartments = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewDepartmentSel.class)
+			);
+			System.out.println("查询到已存在的部门记录数:" + existingDepartments.size());
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在部门记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"Department_ID-Department_CODE"作为唯一键)
+		Map<String, ZcrmViewDepartmentSel> existingMap = new HashMap<>();
+		for (ZcrmViewDepartmentSel existing : existingDepartments) {
+			String key = existing.getDepartmentId() + "-" + existing.getDepartmentCode();
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewDepartmentSel> insertList = new ArrayList<>();
+		List<ZcrmViewDepartmentSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewDepartmentSel newDept : newDepartments) {
+			Long deptId = newDept.getDepartmentId();
+			String deptCode = newDept.getDepartmentCode();
+
+			// 跳过关键字段为空的记录
+			if (deptId == null || deptCode == null) {
+				System.err.println("跳过 Department_ID 或 Department_CODE 为空的记录");
+				continue;
+			}
+
+			String key = deptId + "-" + deptCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewDepartmentSel existing = existingMap.get(key);
+				newDept.setId(existing.getId()); // 假设主键字段为id
+				updateList.add(newDept);
+			} else {
+				// 不存在:新增
+				insertList.add(newDept);
 			}
 		}
-		return res;
+
+		System.out.println("待新增部门数:" + insertList.size() + ",待更新部门数:" + updateList.size());
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 

+ 97 - 19
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewItemSelServiceImpl.java

@@ -7,8 +7,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewItemSel;
 import org.springblade.u9cloud.mapper.ZcrmViewItemSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewItemSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -18,9 +21,8 @@ import org.springblade.u9cloud.config.U9cloudConfig;
 
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -37,6 +39,9 @@ public class ZcrmViewItemSelServiceImpl extends BaseServiceImpl<ZcrmViewItemSelM
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
 
 	@Override
 	@Transactional(rollbackFor = Exception.class)
@@ -54,41 +59,114 @@ public class ZcrmViewItemSelServiceImpl extends BaseServiceImpl<ZcrmViewItemSelM
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchItems() {
-		// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Item_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
-		String token = u9cloudGetTokenUtil.getToken();
+		String token = u9cloudGetTokenUtil.getToken2();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewItemSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewItemSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewItemSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewItemSel> apiResponse = response.getBody();
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewItemSel> items = apiResponse.getData();
-			if (!items.isEmpty()) {
-				res = this.saveBatch(items);
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewItemSel> newItems = apiResponse.getData();
+		if (newItems == null || newItems.isEmpty()) {
+			return false;
+		}
+
+
+		// 4. 提取新数据中的唯一标识(过滤空值)
+		List<Long> itemIds = newItems.stream()
+			.map(ZcrmViewItemSel::getItemId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> itemCodes = newItems.stream()
+			.map(ZcrmViewItemSel::getItemCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (itemIds.isEmpty() || itemCodes.isEmpty()) {
+			System.err.println("存在 Item_ID 或 Item_Code 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewItemSel> existingItems = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_item_sel " +
+				"WHERE Item_ID IN (" + String.join(",", itemIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Item_Code IN ('" + String.join("','", itemCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingItems = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewItemSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在物料记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"Item_ID-Item_Code"作为唯一键)
+		Map<String, ZcrmViewItemSel> existingMap = new HashMap<>();
+		for (ZcrmViewItemSel existing : existingItems) {
+			String key = existing.getItemId() + "-" + existing.getItemCode();
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewItemSel> insertList = new ArrayList<>();
+		List<ZcrmViewItemSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewItemSel newItem : newItems) {
+			Long itemId = newItem.getItemId();
+			String itemCode = newItem.getItemCode();
+
+			// 跳过关键字段为空的记录
+			if (itemId == null || itemCode == null) {
+				System.err.println("跳过 Item_ID 或 Item_Code 为空的记录");
+				continue;
+			}
+
+			String key = itemId + "-" + itemCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewItemSel existing = existingMap.get(key);
+				newItem.setId(existing.getId()); // 假设主键字段为id
+				updateList.add(newItem);
+			} else {
+				// 不存在:新增
+				insertList.add(newItem);
 			}
 		}
-		return res;
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 

+ 119 - 23
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewOperatorsSelServiceImpl.java

@@ -1,14 +1,19 @@
 package org.springblade.u9cloud.service.impl;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.AllArgsConstructor;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.u9cloud.common.U9cloudGetTokenUtil;
 import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewOperatorsSel;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
 import org.springblade.u9cloud.mapper.ZcrmViewOperatorsSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewOperatorsSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -17,9 +22,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 import org.springblade.u9cloud.config.U9cloudConfig;
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -36,6 +40,9 @@ public class ZcrmViewOperatorsSelServiceImpl extends BaseServiceImpl<ZcrmViewOpe
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertOperators(ZcrmViewOperatorsSel zcrmViewOperatorsSel) {
@@ -52,41 +59,130 @@ public class ZcrmViewOperatorsSelServiceImpl extends BaseServiceImpl<ZcrmViewOpe
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchOperators() {
-		// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Operators_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		String token = u9cloudGetTokenUtil.getToken();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应 - 使用Map接收
 		RestTemplate restTemplate = new RestTemplate();
-		ParameterizedTypeReference<ViewApiResponse<ZcrmViewOperatorsSel>> typeRef =
-			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewOperatorsSel>>() {};
-
-		ResponseEntity<ViewApiResponse<ZcrmViewOperatorsSel>> response =
-			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
-		ViewApiResponse<ZcrmViewOperatorsSel> apiResponse = response.getBody();
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewOperatorsSel> items = apiResponse.getData();
-			if (!items.isEmpty()) {
-				res = this.saveBatch(items);
+		ResponseEntity<Map> response =
+			restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
+
+		System.out.println("原始响应: " + response);
+		Map<String, Object> apiResponse = response.getBody();
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !Boolean.TRUE.equals(apiResponse.get("Success"))) {
+			return false;
+		}
+
+		// 4. 处理数据 - 支持对象和数组两种情况
+		List<ZcrmViewOperatorsSel> newBillList = new ArrayList<>();
+		Object data = apiResponse.get("Data");
+
+		if (data != null) {
+			ObjectMapper mapper = new ObjectMapper();
+			try {
+				if (data instanceof List) {
+					// 如果是数组
+					newBillList = mapper.convertValue(data,
+						mapper.getTypeFactory().constructCollectionType(List.class, ZcrmViewOperatorsSel.class));
+				} else {
+					// 如果是单个对象
+					ZcrmViewOperatorsSel singleItem = mapper.convertValue(data, ZcrmViewOperatorsSel.class);
+					newBillList.add(singleItem);
+				}
+			} catch (Exception e) {
+				throw new RuntimeException("数据转换失败: " + e.getMessage(), e);
+			}
+		}
+
+		// 后面的代码保持不变...
+		if (newBillList.isEmpty()) {
+			System.err.println("获取到的数据为空");
+			return false;
+		}
+
+		// 5. 提取新数据中的唯一标识(过滤空值)
+		List<Long> saleserIds = newBillList.stream()
+			.map(ZcrmViewOperatorsSel::getSaleserId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> saleserCodes = newBillList.stream()
+			.map(ZcrmViewOperatorsSel::getSaleserCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (saleserIds.isEmpty() || saleserCodes.isEmpty()) {
+			System.err.println("存在 Saleser_ID 或 Saleser_CODE 为空的记录,跳过处理");
+			return false;
+		}
+
+		// 6. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewOperatorsSel> existingOperators = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_operators_sel " +
+				"WHERE Saleser_ID IN (" + String.join(",", saleserIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Saleser_CODE IN ('" + String.join("','", saleserCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingOperators = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewOperatorsSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在操作员记录失败", e);
+		}
+
+		// 7. 构建已存在记录的映射表(用"Saleser_ID-Saleser_CODE"作为唯一键)
+		Map<String, ZcrmViewOperatorsSel> existingMap = new HashMap<>();
+		for (ZcrmViewOperatorsSel existing : existingOperators) {
+			String key = existing.getSaleserId() + "-" + existing.getSaleserCode();
+			existingMap.put(key, existing);
+		}
+
+		// 8. 分离新增和更新列表
+		List<ZcrmViewOperatorsSel> insertList = new ArrayList<>();
+		List<ZcrmViewOperatorsSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewOperatorsSel newOperator : newBillList) {
+			Long saleserId = newOperator.getSaleserId();
+			String saleserCode = newOperator.getSaleserCode();
+
+			// 跳过关键字段为空的记录
+			if (saleserId == null || saleserCode == null) {
+				System.err.println("跳过 Saleser_ID 或 Saleser_CODE 为空的记录");
+				continue;
+			}
+
+			String key = saleserId + "-" + saleserCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewOperatorsSel existing = existingMap.get(key);
+				newOperator.setId(existing.getId()); // 假设主键字段为id
+				updateList.add(newOperator);
+			} else {
+				// 不存在:新增
+				insertList.add(newOperator);
 			}
 		}
-		return res;
+
+		// 9. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 

+ 161 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewRecBillHeadSelServiceImpl.java

@@ -0,0 +1,161 @@
+package org.springblade.u9cloud.service.impl;
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.u9cloud.common.U9cloudGetTokenUtil;
+import org.springblade.u9cloud.entity.ViewApiResponse;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+import org.springblade.u9cloud.mapper.ZcrmViewRecBillHeadSelMapper;
+import org.springblade.u9cloud.service.ZcrmViewRecBillHeadSelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import org.springblade.u9cloud.config.U9cloudConfig;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * <p>
+ * 收款单 服务实现类
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@Service
+@AllArgsConstructor
+@Slf4j
+public class ZcrmViewRecBillHeadSelServiceImpl extends BaseServiceImpl<ZcrmViewRecBillHeadSelMapper, ZcrmViewRecBillHeadSel>
+        implements ZcrmViewRecBillHeadSelService {
+
+    private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
+
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean insertBatchOperators() {
+        // 1. 构建URL和请求参数
+        String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
+                .encode(StandardCharsets.UTF_8)
+                .toUriString();
+
+        Map<String, String> requestBody = new HashMap<>();
+        requestBody.put("SqlString", "select * from ZCRM_View_RecBillHead_Sel");
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        String token = u9cloudGetTokenUtil.getToken();
+        headers.set("token", token);
+        HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
+
+        // 2. 发送请求并获取响应
+        RestTemplate restTemplate = new RestTemplate();
+        ParameterizedTypeReference<ViewApiResponse<ZcrmViewRecBillHeadSel>> typeRef =
+                new ParameterizedTypeReference<ViewApiResponse<ZcrmViewRecBillHeadSel>>() {};
+        ResponseEntity<ViewApiResponse<ZcrmViewRecBillHeadSel>> response =
+                restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
+        ViewApiResponse<ZcrmViewRecBillHeadSel> apiResponse = response.getBody();
+
+
+        // 3. 校验响应合法性
+        if (apiResponse == null || !apiResponse.isSuccess()) {
+            return false;
+        }
+        List<ZcrmViewRecBillHeadSel> newBillList = apiResponse.getData();
+        if (newBillList == null || newBillList.isEmpty()) {
+            return false;
+        }
+
+
+        // 4. 提取新数据中的唯一标识(过滤空值)
+        List<String> docNos = newBillList.stream()
+                .map(ZcrmViewRecBillHeadSel::getDocNo)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        List<Long> customerIds = newBillList.stream()
+                .map(ZcrmViewRecBillHeadSel::getCustomerId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        if (docNos.isEmpty() || customerIds.isEmpty()) {
+            System.err.println("存在 DocNo 或 Customer_ID 为空的记录,跳过处理");
+            return false;
+        }
+
+
+        // 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+        List<ZcrmViewRecBillHeadSel> existingBillList = new ArrayList<>();
+        try {
+            // 构建查询SQL(联合查询唯一标识)
+            String sql = "SELECT * FROM zcrm_view_recbillhead_sel " +
+                    "WHERE DocNo IN ('" + String.join("','", docNos) + "') " +
+                    "AND Customer_ID IN (" + customerIds.stream().map(String::valueOf).collect(Collectors.toList()) + ")";
+
+            // 执行查询并映射为实体
+            existingBillList = jdbcTemplate.query(
+                    sql,
+                    new BeanPropertyRowMapper<>(ZcrmViewRecBillHeadSel.class)
+        );
+        } catch (Exception e) {
+            throw new RuntimeException("查询已存在收款单记录失败", e);
+        }
+
+
+        // 6. 构建已存在记录的映射表(用"DocNo-Customer_ID"作为唯一键)
+        Map<String, ZcrmViewRecBillHeadSel> existingMap = new HashMap<>();
+        for (ZcrmViewRecBillHeadSel existing : existingBillList) {
+            String key = existing.getDocNo() + "-" + existing.getCustomerId();
+            existingMap.put(key, existing);
+        }
+
+
+        // 7. 分离新增和更新列表
+        List<ZcrmViewRecBillHeadSel> insertList = new ArrayList<>();
+        List<ZcrmViewRecBillHeadSel> updateList = new ArrayList<>();
+
+        for (ZcrmViewRecBillHeadSel newBill : newBillList) {
+            String docNo = newBill.getDocNo();
+            Long customerId = newBill.getCustomerId();
+
+            // 跳过关键字段为空的记录
+            if (docNo == null || customerId == null) {
+                System.err.println("跳过 DocNo 或 Customer_ID 为空的记录");
+                continue;
+            }
+
+            String key = docNo + "-" + customerId;
+            if (existingMap.containsKey(key)) {
+                // 已存在:更新(拷贝主键ID)
+                ZcrmViewRecBillHeadSel existing = existingMap.get(key);
+                newBill.setId(existing.getId()); // 假设主键字段为id
+                updateList.add(newBill);
+            } else {
+                // 不存在:新增
+                insertList.add(newBill);
+            }
+        }
+
+
+        // 8. 执行批量操作
+        boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+        boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+        return insertSuccess && updateSuccess;
+    }
+}

+ 165 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewSalePriceSelServiceImpl.java

@@ -0,0 +1,165 @@
+package org.springblade.u9cloud.service.impl;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.u9cloud.common.U9cloudGetTokenUtil;
+import org.springblade.u9cloud.config.U9cloudConfig;
+import org.springblade.u9cloud.entity.ViewApiResponse;
+import org.springblade.u9cloud.entity.ZcrmViewRecBillHeadSel;
+import org.springblade.u9cloud.entity.ZcrmViewSalePriceSel;
+import org.springblade.u9cloud.mapper.ZcrmViewRecBillHeadSelMapper;
+import org.springblade.u9cloud.mapper.ZcrmViewSalePriceSelMapper;
+import org.springblade.u9cloud.service.ZcrmViewRecBillHeadSelService;
+import org.springblade.u9cloud.service.ZcrmViewSalePriceSelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * <p>
+ * 销售价目表 服务实现类
+ * </p>
+ *
+ * @author your-name
+ * @since 2025-07-30
+ */
+@Service
+@AllArgsConstructor
+@Slf4j
+public class ZcrmViewSalePriceSelServiceImpl extends BaseServiceImpl<ZcrmViewSalePriceSelMapper, ZcrmViewSalePriceSel>
+	implements ZcrmViewSalePriceSelService {
+
+	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
+
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public boolean insertBatchOperators() {
+		// 1. 构建URL和请求参数
+		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
+			.encode(StandardCharsets.UTF_8)
+			.toUriString();
+
+		Map<String, String> requestBody = new HashMap<>();
+		requestBody.put("SqlString", "select * from ZCRM_View_SalePrice_Sel");
+
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_JSON);
+		String token = u9cloudGetTokenUtil.getToken();
+		headers.set("token", token);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
+
+		// 2. 发送请求并获取响应
+		RestTemplate restTemplate = new RestTemplate();
+		ParameterizedTypeReference<ViewApiResponse<ZcrmViewSalePriceSel>> typeRef =
+			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewSalePriceSel>>() {};
+		ResponseEntity<ViewApiResponse<ZcrmViewSalePriceSel>> response =
+			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
+		ViewApiResponse<ZcrmViewSalePriceSel> apiResponse = response.getBody();
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewSalePriceSel> newPriceList = apiResponse.getData();
+		if (newPriceList == null || newPriceList.isEmpty()) {
+			return false;
+		}
+
+
+		// 4. 提取唯一标识字段(Item_ID和Item_Code,过滤空值)
+		List<Long> itemIds = newPriceList.stream()
+			.map(ZcrmViewSalePriceSel::getItemId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> itemCodes = newPriceList.stream()
+			.map(ZcrmViewSalePriceSel::getItemCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (itemIds.isEmpty() || itemCodes.isEmpty()) {
+			System.err.println("存在 Item_ID 或 Item_Code 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录
+		List<ZcrmViewSalePriceSel> existingPriceList = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合唯一标识:Item_ID和Item_Code)
+			String sql = "SELECT * FROM zcrm_view_saleprice_sel " +
+				"WHERE Item_ID IN (" + itemIds.stream().map(String::valueOf).collect(Collectors.joining(",")) + ") " +
+				"AND Item_Code IN ('" + String.join("','", itemCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingPriceList = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewSalePriceSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在销售价目表记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"Item_ID-Item_Code"作为唯一键)
+		Map<String, ZcrmViewSalePriceSel> existingMap = new HashMap<>();
+		for (ZcrmViewSalePriceSel existing : existingPriceList) {
+			String key = existing.getItemId() + "-" + existing.getItemCode();
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewSalePriceSel> insertList = new ArrayList<>();
+		List<ZcrmViewSalePriceSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewSalePriceSel newPrice : newPriceList) {
+			Long itemId = newPrice.getItemId();
+			String itemCode = newPrice.getItemCode();
+
+			// 跳过关键字段为空的记录
+			if (itemId == null || itemCode == null) {
+				System.err.println("跳过 Item_ID 或 Item_Code 为空的记录");
+				continue;
+			}
+
+			String key = itemId + "-" + itemCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewSalePriceSel existing = existingMap.get(key);
+				newPrice.setId(existing.getId()); // 继承主键ID
+				updateList.add(newPrice);
+			} else {
+				// 不存在:新增
+				insertList.add(newPrice);
+			}
+		}
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
+	}
+
+
+
+
+}

+ 97 - 18
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewShipSelServiceImpl.java

@@ -7,8 +7,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewShipSel;
 import org.springblade.u9cloud.mapper.ZcrmViewShipSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewShipSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -17,9 +20,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 import org.springblade.u9cloud.config.U9cloudConfig;
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -36,6 +38,10 @@ public class ZcrmViewShipSelServiceImpl extends BaseServiceImpl<ZcrmViewShipSelM
 
 	private U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
+
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertShip(ZcrmViewShipSel zcrmViewShipSel) {
@@ -51,40 +57,113 @@ public class ZcrmViewShipSelServiceImpl extends BaseServiceImpl<ZcrmViewShipSelM
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchShips() {
-		// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Ship_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		String token = u9cloudGetTokenUtil.getToken();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
 
-		// 4. 发送 POST
+
+		// 2. 发送请求并获取响应
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewShipSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewShipSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewShipSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewShipSel> apiResponse = response.getBody();
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewShipSel> items = apiResponse.getData();
-			if (!items.isEmpty()) {
-				res = this.saveBatch(items);
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewShipSel> newShips = apiResponse.getData();
+		if (newShips == null || newShips.isEmpty()) {
+			return false;
+		}
+
+
+		// 4. 提取新数据中的唯一标识(过滤空值)
+		List<String> docNos = newShips.stream()
+			.map(ZcrmViewShipSel::getDocNo)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<Long> itemIds = newShips.stream()
+			.map(ZcrmViewShipSel::getItemId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (docNos.isEmpty() || itemIds.isEmpty()) {
+			System.err.println("存在 DocNo 或 Item_ID 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewShipSel> existingShips = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_ship_sel " +
+				"WHERE DocNo IN ('" + String.join("','", docNos) + "') " +  // 字符串类型用单引号
+				"AND Item_ID IN (" + String.join(",", itemIds.stream().map(String::valueOf).collect(Collectors.toList())) + ")";  // 数字类型直接拼接
+
+			// 执行查询并映射为实体
+			existingShips = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewShipSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在发货单记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"DocNo-Item_ID"作为唯一键)
+		Map<String, ZcrmViewShipSel> existingMap = new HashMap<>();
+		for (ZcrmViewShipSel existing : existingShips) {
+			String key = existing.getDocNo() + "-" + existing.getItemId();  // 联合唯一键
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewShipSel> insertList = new ArrayList<>();
+		List<ZcrmViewShipSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewShipSel newShip : newShips) {
+			String docNo = newShip.getDocNo();
+			Long itemId = newShip.getItemId();
+
+			// 跳过关键字段为空的记录
+			if (docNo == null || itemId == null) {
+				System.err.println("跳过 DocNo 或 Item_ID 为空的记录");
+				continue;
+			}
+
+			String key = docNo + "-" + itemId;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewShipSel existing = existingMap.get(key);
+				newShip.setId(existing.getId());  // 假设主键字段为id
+				updateList.add(newShip);
+			} else {
+				// 不存在:新增
+				insertList.add(newShip);
 			}
 		}
-		return res;
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 }

+ 97 - 19
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewSupplierSelServiceImpl.java

@@ -7,8 +7,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewSupplierSel;
 import org.springblade.u9cloud.mapper.ZcrmViewSupplierSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewSupplierSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -18,9 +21,8 @@ import org.springblade.u9cloud.config.U9cloudConfig;
 
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -37,6 +39,10 @@ public class ZcrmViewSupplierSelServiceImpl extends BaseServiceImpl<ZcrmViewSupp
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
+
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertSupplier(ZcrmViewSupplierSel zcrmViewSupplierSel) {
@@ -52,42 +58,114 @@ public class ZcrmViewSupplierSelServiceImpl extends BaseServiceImpl<ZcrmViewSupp
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchSuppliers() {
-
-		// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_Supplier_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		String token = u9cloudGetTokenUtil.getToken();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewSupplierSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewSupplierSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewSupplierSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewSupplierSel> apiResponse = response.getBody();
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewSupplierSel> items = apiResponse.getData();
-			if (!items.isEmpty()) {
-				res = this.saveBatch(items);
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewSupplierSel> newSuppliers = apiResponse.getData();
+		if (newSuppliers == null || newSuppliers.isEmpty()) {
+			return false;
+		}
+
+
+		// 4. 提取新数据中的唯一标识(过滤空值)
+		List<Long> supplierIds = newSuppliers.stream()
+			.map(ZcrmViewSupplierSel::getSupplierId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> supplierCodes = newSuppliers.stream()
+			.map(ZcrmViewSupplierSel::getSupplierCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (supplierIds.isEmpty() || supplierCodes.isEmpty()) {
+			System.err.println("存在 Supplier_ID 或 Supplier_CODE 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewSupplierSel> existingSuppliers = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_supplier_sel " +
+				"WHERE Supplier_ID IN (" + String.join(",", supplierIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Supplier_CODE IN ('" + String.join("','", supplierCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingSuppliers = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewSupplierSel.class)
+			);
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在供应商记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"Supplier_ID-Supplier_CODE"作为唯一键)
+		Map<String, ZcrmViewSupplierSel> existingMap = new HashMap<>();
+		for (ZcrmViewSupplierSel existing : existingSuppliers) {
+			String key = existing.getSupplierId() + "-" + existing.getSupplierCode();
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewSupplierSel> insertList = new ArrayList<>();
+		List<ZcrmViewSupplierSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewSupplierSel newSupplier : newSuppliers) {
+			Long supplierId = newSupplier.getSupplierId();
+			String supplierCode = newSupplier.getSupplierCode();
+
+			// 跳过关键字段为空的记录
+			if (supplierId == null || supplierCode == null) {
+				System.err.println("跳过 Supplier_ID 或 Supplier_CODE 为空的记录");
+				continue;
+			}
+
+			String key = supplierId + "-" + supplierCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewSupplierSel existing = existingMap.get(key);
+				newSupplier.setId(existing.getId()); // 假设主键字段为id
+				updateList.add(newSupplier);
+			} else {
+				// 不存在:新增
+				insertList.add(newSupplier);
 			}
 		}
-		return res;
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 

+ 96 - 18
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/service/impl/ZcrmViewWhqohSelServiceImpl.java

@@ -7,8 +7,11 @@ import org.springblade.u9cloud.entity.ViewApiResponse;
 import org.springblade.u9cloud.entity.ZcrmViewWhqohSel;
 import org.springblade.u9cloud.mapper.ZcrmViewWhqohSelMapper;
 import org.springblade.u9cloud.service.ZcrmViewWhqohSelService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
@@ -17,9 +20,8 @@ import org.springframework.web.util.UriComponentsBuilder;
 import org.springblade.u9cloud.config.U9cloudConfig;
 
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -36,6 +38,9 @@ public class ZcrmViewWhqohSelServiceImpl extends BaseServiceImpl<ZcrmViewWhqohSe
 
 	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
 
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertWhqoh(ZcrmViewWhqohSel zcrmViewWhqohSel) {
@@ -51,41 +56,114 @@ public class ZcrmViewWhqohSelServiceImpl extends BaseServiceImpl<ZcrmViewWhqohSe
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public boolean insertBatchWhqohs() {
-// 1. 构建标准化URL(不带查询参数)
+		// 1. 构建URL和请求参数
 		String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
 			.encode(StandardCharsets.UTF_8)
 			.toUriString();
 
-		// 2. 构建POST请求参数(放在请求体中)
 		Map<String, String> requestBody = new HashMap<>();
 		requestBody.put("SqlString", "select * from ZCRM_View_WhQoh_Sel");
 
-		// 3. 设置请求头
 		HttpHeaders headers = new HttpHeaders();
 		headers.setContentType(MediaType.APPLICATION_JSON);
 		String token = u9cloudGetTokenUtil.getToken();
 		headers.set("token", token);
-		// 4. 构建请求实体
-		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity(requestBody, headers);
+		HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
 
-		// 4. 发送 POST
+		// 2. 发送请求并获取响应
 		RestTemplate restTemplate = new RestTemplate();
 		ParameterizedTypeReference<ViewApiResponse<ZcrmViewWhqohSel>> typeRef =
 			new ParameterizedTypeReference<ViewApiResponse<ZcrmViewWhqohSel>>() {};
-
 		ResponseEntity<ViewApiResponse<ZcrmViewWhqohSel>> response =
 			restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
-
-		// 5. 处理结果
 		ViewApiResponse<ZcrmViewWhqohSel> apiResponse = response.getBody();
-		boolean res = false;
-		if (apiResponse != null && apiResponse.isSuccess()) {
-			List<ZcrmViewWhqohSel> items = apiResponse.getData();
-			if (!items.isEmpty()) {
-				res = this.saveBatch(items);
+
+
+		// 3. 校验响应合法性
+		if (apiResponse == null || !apiResponse.isSuccess()) {
+			return false;
+		}
+		List<ZcrmViewWhqohSel> newWhqohs = apiResponse.getData();
+		if (newWhqohs == null || newWhqohs.isEmpty()) {
+			return false;
+		}
+
+
+		// 4. 提取新数据中的唯一标识(过滤空值)
+		List<Long> itemIds = newWhqohs.stream()
+			.map(ZcrmViewWhqohSel::getItemId)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+		List<String> itemCodes = newWhqohs.stream()
+			.map(ZcrmViewWhqohSel::getItemCode)
+			.filter(Objects::nonNull)
+			.collect(Collectors.toList());
+
+		if (itemIds.isEmpty() || itemCodes.isEmpty()) {
+			System.err.println("存在 Item_ID 或 Item_Code 为空的记录,跳过处理");
+			return false;
+		}
+
+
+		// 5. 用JdbcTemplate查询已存在记录(绕开数据权限拦截器)
+		List<ZcrmViewWhqohSel> existingWhqohs = new ArrayList<>();
+		try {
+			// 构建查询SQL(联合查询唯一标识)
+			String sql = "SELECT * FROM zcrm_view_whqoh_sel " +
+				"WHERE Item_ID IN (" + String.join(",", itemIds.stream().map(String::valueOf).collect(Collectors.toList())) + ") " +
+				"AND Item_Code IN ('" + String.join("','", itemCodes) + "')";
+
+			// 执行查询并映射为实体
+			existingWhqohs = jdbcTemplate.query(
+				sql,
+				new BeanPropertyRowMapper<>(ZcrmViewWhqohSel.class)
+        );
+		} catch (Exception e) {
+			throw new RuntimeException("查询已存在库存记录失败", e);
+		}
+
+
+		// 6. 构建已存在记录的映射表(用"Item_ID-Item_Code"作为唯一键)
+		Map<String, ZcrmViewWhqohSel> existingMap = new HashMap<>();
+		for (ZcrmViewWhqohSel existing : existingWhqohs) {
+			String key = existing.getItemId() + "-" + existing.getItemCode();
+			existingMap.put(key, existing);
+		}
+
+
+		// 7. 分离新增和更新列表
+		List<ZcrmViewWhqohSel> insertList = new ArrayList<>();
+		List<ZcrmViewWhqohSel> updateList = new ArrayList<>();
+
+		for (ZcrmViewWhqohSel newWhqoh : newWhqohs) {
+			Long itemId = newWhqoh.getItemId();
+			String itemCode = newWhqoh.getItemCode();
+
+			// 跳过关键字段为空的记录
+			if (itemId == null || itemCode == null) {
+				System.err.println("跳过 Item_ID 或 Item_Code 为空的记录");
+				continue;
+			}
+
+			String key = itemId + "-" + itemCode;
+			if (existingMap.containsKey(key)) {
+				// 已存在:更新(拷贝主键ID)
+				ZcrmViewWhqohSel existing = existingMap.get(key);
+				newWhqoh.setId(existing.getId()); // 假设主键字段为id
+				updateList.add(newWhqoh);
+			} else {
+				// 不存在:新增
+				insertList.add(newWhqoh);
 			}
 		}
-		return res;
+
+
+		// 8. 执行批量操作
+		boolean insertSuccess = insertList.isEmpty() || this.saveBatch(insertList);
+		boolean updateSuccess = updateList.isEmpty() || this.updateBatchById(updateList);
+
+		return insertSuccess && updateSuccess;
 	}
 
 }