4 Commits cecef51c3f ... 0bccad9de8

Auteur SHA1 Message Date
  wzy 0bccad9de8 Merge branch 'master' of https://mc.cloudpure.cn/mjava/cont il y a 2 mois
  wzy 520b3896fc 金轮 il y a 2 mois
  wzy 03ef2933d1 华高 il y a 2 mois
  wzy e526ac36d1 博洋家纺 il y a 2 mois
30 fichiers modifiés avec 1770 ajouts et 183 suppressions
  1. 11 2
      mjava-boyang/src/test/java/com/malk/boyang/Test.java
  2. 1 1
      mjava-huagao/src/main/java/com/malk/huagao/utils/MPGenerator.java
  3. 1 1
      mjava-huagao/src/main/resources/application.yml
  4. 2 2
      mjava-huagao/src/test/java/com/malk/huagao/YyYdTest.java
  5. 6 0
      mjava-jinlun/src/main/java/com/malk/jinlun/config/KDWebApiConfig.java
  6. 47 1
      mjava-jinlun/src/main/java/com/malk/jinlun/controller/JinlunController.java
  7. 26 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/Audit.java
  8. 27 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/ContactModel.java
  9. 10 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/CustomerContactEntry.java
  10. 61 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/CustomerModel.java
  11. 15 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/FNumber.java
  12. 15 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/FSTAFFNUMBER.java
  13. 7 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/Model.java
  14. 39 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderEntry.java
  15. 17 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderFinance.java
  16. 24 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderModel.java
  17. 26 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/Save.java
  18. 22 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/Submit.java
  19. 24 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/UnAudit.java
  20. 14 0
      mjava-jinlun/src/main/java/com/malk/jinlun/entity/View.java
  21. 23 3
      mjava-jinlun/src/main/java/com/malk/jinlun/schedule/JinlunTask.java
  22. 19 0
      mjava-jinlun/src/main/java/com/malk/jinlun/service/CpClient.java
  23. 8 2
      mjava-jinlun/src/main/java/com/malk/jinlun/service/JinlunService.java
  24. 12 0
      mjava-jinlun/src/main/java/com/malk/jinlun/service/JinlunTaskService.java
  25. 187 0
      mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/CpClientImpl.java
  26. 503 162
      mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunServiceImpl.java
  27. 576 0
      mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunTaskServiceImpl.java
  28. 8 1
      mjava-jinlun/src/main/resources/application-dev.yml
  29. 18 7
      mjava-jinlun/src/main/resources/application-prod.yml
  30. 21 1
      mjava-jinlun/src/test/java/com/malk/jinlun/DdTest.java

+ 11 - 2
mjava-boyang/src/test/java/com/malk/boyang/Test.java

@@ -11,12 +11,21 @@ import org.apache.commons.codec.digest.HmacUtils;
 
 public class Test {
     public static void main(String[] args) {
+        //测试环境
         // 应用ID
-        String projectId = "1000004";
+        /*String projectId = "1000004";
         // 应用密钥
         String secret = "96Uh7CR83NkN3TA6";
         // 接口调用域名
-        String host = "http://122.227.225.202:9011/";
+        String host = "http://122.227.225.202:9011/";*/
+
+        //正式环境
+        // 应用ID
+        String projectId = "1000003";
+        // 应用密钥
+        String secret = "5V6xsY3q8JWZ9Qik";
+        // 接口调用域名
+        String host = "https://dzqz.beyond-it-service.com/";
 
         // 请求签名鉴权-POST请求
         testPost(projectId, secret, host);

+ 1 - 1
mjava-huagao/src/main/java/com/malk/huagao/utils/MPGenerator.java

@@ -35,7 +35,7 @@ public class MPGenerator {
                             .entity("entity");
                 })
                 .strategyConfig(builder -> {
-                    builder.addInclude("YD_PROD_WORK_HOURS_PRICE")
+                    builder.addInclude("KD_YD_CUSTOMER")
                             .entityBuilder().enableLombok();
                 })
                 .templateEngine(new VelocityTemplateEngine())

+ 1 - 1
mjava-huagao/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: prod
+    active: dev
   servlet:
     multipart:
       max-file-size: 100MB

+ 2 - 2
mjava-huagao/src/test/java/com/malk/huagao/YyYdTest.java

@@ -129,8 +129,8 @@ public class YyYdTest {
 
     @Test
     public void test5(){
-        String stTime="2025-09-25 00:00:00";
-        String edTime="2025-09-26 00:00:00";
+        String stTime="2025-10-11 00:00:00";
+        String edTime="2025-10-16 00:00:00";
         List<Map> list=ydService.queryAllFormData(YDParam.builder().formUuid("FORM-5061F7AE543B429C8241EC730A6F31653NNK").build());
         for(Map map:list){
             Map formData= UtilMap.getMap(map,"formData");

+ 6 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/config/KDWebApiConfig.java

@@ -1,5 +1,8 @@
 package com.malk.jinlun.config;
 
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.Properties;
@@ -26,4 +29,7 @@ public class KDWebApiConfig {
             e.printStackTrace();
         }
     }
+
+
+
 }

+ 47 - 1
mjava-jinlun/src/main/java/com/malk/jinlun/controller/JinlunController.java

@@ -14,7 +14,7 @@ public class JinlunController {
 
     @GetMapping("/test")
     public McR test(){
-        return McR.success();
+        return McR.success("111");
     }
 
     /**
@@ -26,4 +26,50 @@ public class JinlunController {
     public McR addCustomer(@RequestBody Map map){
         return jinlunService.addCustomer(map);
     }
+
+    /**
+     * 金蝶更新客户销售员
+     * @param map
+     * @return
+     */
+    @PostMapping("/updateCustomer")
+    public McR updateCustomer(@RequestBody Map map){
+        jinlunService.updateCustomer(map);
+
+        return McR.success();
+    }
+
+    /**
+     * 金蝶新增客户联系人
+     * @param map
+     * @return
+     */
+    @PostMapping("/addCustomerContact")
+    public McR addCustomerContact(@RequestBody Map map){
+        jinlunService.addCustomerContact(map);
+
+        return McR.success();
+    }
+
+    /**
+     * 金蝶新增销售订单
+     * @param map
+     * @return
+     */
+    @PostMapping("/addSaleOrder")
+    public McR addSaleOrder(@RequestBody Map map){
+        return jinlunService.addSaleOrder(map);
+    }
+
+    /**
+     * 创建tb项目
+     * @param map
+     * @return
+     */
+    @PostMapping("/createTbProject")
+    public McR createTbProject(@RequestBody Map map) {
+        jinlunService.createTbProject(map);
+
+        return McR.success();
+    }
 }

+ 26 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/Audit.java

@@ -0,0 +1,26 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Audit {
+    private int CreateOrgId;
+
+    private List<String> Numbers;
+
+    private String Ids;
+
+    private String InterationFlags;
+
+    private int UseOrgId;
+
+    private String NetworkCtrl;
+
+    private Boolean IsVerifyProcInst;
+
+    private String IgnoreInterationFlag;
+
+    private Boolean UseBatControlTimes;
+}

+ 27 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/ContactModel.java

@@ -0,0 +1,27 @@
+package com.malk.jinlun.entity;
+
+import com.malk.utils.UtilMap;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ContactModel extends Model{
+    private String FName;//联系人名称
+
+    private FNumber FCustId;//客户编号
+
+    private String FMobile;//移动电话
+
+    private FNumber Fex;//性别
+
+    private String FPost;//职务
+
+    private String FTel;//固定电话
+
+    private String FFax;//传真
+
+    private String FEmail;//邮箱
+
+    private String FCompanyType;//类型:BD_Customer:客户,BD_Supplier:供应商
+}

+ 10 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/CustomerContactEntry.java

@@ -0,0 +1,10 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class CustomerContactEntry {
+    private String FNUMBER1;//地点编码
+
+    private String FNAME1;//地点名称
+}

+ 61 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/CustomerModel.java

@@ -0,0 +1,61 @@
+package com.malk.jinlun.entity;
+
+import com.malk.utils.UtilMap;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class CustomerModel extends Model{
+    private int FCUSTID;
+
+    private String FName;//客户名称
+
+    private String FShortName;//简称
+
+    private FNumber FCOUNTRY;//国家
+
+    private FNumber FGroup;//客户分组
+
+    private String F_VMKV_Combo;//客户等级
+
+    private FNumber FCustTypeId;//客类别
+
+    private String FDescription;//备注
+
+    private FNumber FSALDEPTID;//销售部门
+
+    private FNumber FSELLER;//销售员
+
+    private FNumber FRECCONDITIONID;//收款条件
+
+    private FNumber FTRADINGCURRID;//结算币别
+
+    private FNumber FSETTLETYPEID;//结算方式
+
+    private FNumber FTaxRate;//税率
+
+    private FNumber FTaxType;//税分类
+
+    private String FInvoiceType;//发票类型
+
+    private Boolean FISCREDITCHECK;//启用信用管理
+
+    private String FINVOICEBANKACCOUNT;//银行账号
+
+    private String FINVOICETITLE;//发票抬头
+
+    private String FTAXREGISTERCODE;//纳税登记号
+
+    private String FINVOICEBANKNAME;//开户银行
+
+    private String FSOCIALCRECODE;//统一社会信用代码
+
+    private String FINVOICETEL;//开票联系电话
+
+    private String FINVOICEADDRESS;//开票通讯地址
+
+    private List<CustomerContactEntry> FT_BD_CUSTCONTACT;//地址信息
+}

+ 15 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/FNumber.java

@@ -0,0 +1,15 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class FNumber {
+    public FNumber() {
+    }
+
+    public FNumber(String FNumber) {
+        this.FNumber = FNumber;
+    }
+
+    private String FNumber;
+}

+ 15 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/FSTAFFNUMBER.java

@@ -0,0 +1,15 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class FSTAFFNUMBER {
+    public FSTAFFNUMBER() {
+    }
+
+    public FSTAFFNUMBER(String FSTAFFNUMBER) {
+        this.FSTAFFNUMBER = FSTAFFNUMBER;
+    }
+
+    private String FSTAFFNUMBER;
+}

+ 7 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/Model.java

@@ -0,0 +1,7 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class Model {
+}

+ 39 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderEntry.java

@@ -0,0 +1,39 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class SaleOrderEntry {
+    private FNumber FMaterialId;//物料编码
+    private String F_Sl_XSTYPE;//产品类别
+
+//    private FNumber FUnitID;
+    private double FQty;//销售数量
+    private FNumber FPriceUnitId;
+//    private double FPriceUnitQty;
+//    private double FPrice;
+    private double FTaxPrice;//含税单价
+
+    private boolean FIsFree;//是否赠品
+
+    private double FEntryTaxRate;//税率
+
+    /*private double FTaxAmount_LC;
+    private double FAmount_LC;
+    private double FAllAmount_LC;*/
+
+    private String FDeliveryDate;
+
+    /*private FNumber FStockFNumber;
+    private FNumber FSettleOrgIds;
+    private String FOwnerTypeId;
+    private FNumber FOwnerId;*/
+    private String FEntryNote;
+
+    private double F_VMKV_MPPRICE;//报价价格
+    private String F_VMKV_SCCQ1;//生产厂区
+/*    private double F_WMVJ_Decimal;
+    private double F_WMVJ_Amount;
+    private double F_WMVJ_Qty;
+    private boolean F_WMVJ_CheckBox;*/
+}

+ 17 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderFinance.java

@@ -0,0 +1,17 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class SaleOrderFinance {
+    private FNumber FSettleCurrId;//结算币别
+
+    private FNumber FRecConditionId ;//收款条件
+
+    private FNumber FSettleModeId;//结算方式
+
+    private boolean FIsIncludedTax;//是否含税
+
+    private boolean FIsPriceExcludeTax;//价外税
+
+}

+ 24 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/SaleOrderModel.java

@@ -0,0 +1,24 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SaleOrderModel extends Model{
+    private int FID;
+    private FNumber FBillTypeID;//单据类型
+    private String FDate;//日期
+    private String F_NLD_DDTYPE ;//订单类型
+    private String F_WGR_Combo_re5 ;//订单要求
+    private FNumber FCustId;//客户
+    private FNumber FSalerId;//销售员
+    private FSTAFFNUMBER F_Sl_gendanyuan;//跟单员
+    private FNumber FHeadDeliveryWay;//交货方式
+    private String FBusinessType;//业务类型
+    private FNumber FHEADLOCID;//交货地点
+    private String FNote;//备注
+    private String F_Sl_customerbillno;//客户订单号
+    private SaleOrderFinance FSaleOrderFinance;//财务信息
+    private List<SaleOrderEntry> FSaleOrderEntry;//订单明细
+}

+ 26 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/Save.java

@@ -0,0 +1,26 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Save {
+        //默认为空 需要时选择性赋值
+        private List<String> NeedUpDateFields;
+        /*private List<String> NeedReturnFields;
+        private boolean IsDeleteEntry;
+        private String SubSystemId;
+        private boolean IsVerifyBaseDataField;
+        private boolean IsEntryBatchFill;
+        private boolean ValidateFlag;
+        private boolean NumberSearch;
+        private boolean IsAutoAdjustField;
+        private String InterationFlags;
+        private boolean IgnoreInterationFlag;
+        private boolean IsControlPrecision;
+        private boolean ValidateRepeatJson;*/
+
+        //保存实体
+        private Model Model;
+}

+ 22 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/Submit.java

@@ -0,0 +1,22 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Submit {
+    private int CreateOrgId;
+
+    private List<String> Numbers;
+
+    private String Ids;
+
+    private int SelectedPostId;
+
+    private int UseOrgId;
+
+    private Boolean NetworkCtrl;
+
+    private Boolean IgnoreInterationFlag;
+}

+ 24 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/UnAudit.java

@@ -0,0 +1,24 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class UnAudit {
+    private int CreateOrgId;
+
+    private List<String> Numbers;
+
+    private String Ids;
+
+    private String InterationFlags;
+
+    private int UseOrgId;
+
+    private String NetworkCtrl;
+
+    private Boolean IsVerifyProcInst;
+
+    private String IgnoreInterationFlag;
+}

+ 14 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/entity/View.java

@@ -0,0 +1,14 @@
+package com.malk.jinlun.entity;
+
+import lombok.Data;
+
+@Data
+public class View {
+    private int CreateOrgId;
+
+    private String Number;
+
+    private String Id;
+
+    private Boolean IsSortBySeq;
+}

+ 23 - 3
mjava-jinlun/src/main/java/com/malk/jinlun/schedule/JinlunTask.java

@@ -1,6 +1,6 @@
 package com.malk.jinlun.schedule;
 
-import com.malk.jinlun.service.JinlunService;
+import com.malk.jinlun.service.JinlunTaskService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -16,12 +16,32 @@ import org.springframework.scheduling.annotation.Scheduled;
 @EnableScheduling
 @ConditionalOnProperty(name = {"enable.scheduling"})
 public class JinlunTask {
+
     @Autowired
-    private JinlunService jinlunService;
+    private JinlunTaskService jinlunTaskService;
 
     //定时同步物料
     @Scheduled(cron = "0 0 0 * * ?")
     public void syncMaterial(){
-        jinlunService.syncMaterial();
+        jinlunTaskService.syncMaterial();
+    }
+
+    //定时同步销售出库单
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void syncSaleOut(){
+        jinlunTaskService.syncSaleOut();
+    }
+
+    //定时同步收款单
+    @Scheduled(cron = "0 0 2 * * ?")
+    public void syncReceipt(){
+        jinlunTaskService.syncReceipt();
+    }
+
+    //定时同步应收单
+    @Scheduled(cron = "0 0 3 * * ?")
+    public void syncReceivable(){
+        jinlunTaskService.syncReceivable();
     }
+
 }

+ 19 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/service/CpClient.java

@@ -0,0 +1,19 @@
+package com.malk.jinlun.service;
+
+import java.util.Map;
+
+public interface CpClient {
+    String getCpAccessToken();
+
+    Map createCpBo(String schemaCode, Map data, String userId);
+
+    Map updateCpBo(String schemaCode, Map data, String userId);
+
+    Map getCpBo(String schemaCode, String objectId, String userId);
+
+    Map getCpBoList(String schemaCode, Map queryCondition,int page, int size, String userId);
+
+    Map getCpBoResultData(Map result);
+
+    void isSuccess(Map result);
+}

+ 8 - 2
mjava-jinlun/src/main/java/com/malk/jinlun/service/JinlunService.java

@@ -5,7 +5,13 @@ import com.malk.server.common.McR;
 import java.util.Map;
 
 public interface JinlunService {
-    void syncMaterial();
-
     McR addCustomer(Map map);
+
+    void addCustomerContact(Map map);
+
+    void updateCustomer(Map map);
+
+    McR addSaleOrder(Map map);
+
+    McR createTbProject(Map map);
 }

+ 12 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/service/JinlunTaskService.java

@@ -0,0 +1,12 @@
+package com.malk.jinlun.service;
+
+public interface JinlunTaskService {
+    void syncMaterial();
+
+    void syncSaleOut();
+
+    void syncReceipt();
+
+    void syncReceivable();
+
+}

+ 187 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/CpClientImpl.java

@@ -0,0 +1,187 @@
+package com.malk.jinlun.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.base.Strings;
+import com.malk.jinlun.config.CloudpivotConfig;
+import com.malk.jinlun.service.CpClient;
+import com.malk.utils.UtilHttp;
+import com.malk.utils.UtilMap;
+import com.malk.utils.UtilToken;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class CpClientImpl implements CpClient {
+    @Autowired
+    private CloudpivotConfig cloudpivotConfig;
+
+    /**
+     * 云枢获取token
+     * @return
+     */
+    @Override
+    public String getCpAccessToken(){
+        String accessToken = UtilToken.get("invalid-token-cloudpivot");
+
+        if (StringUtils.isNotBlank(accessToken)) {
+            return accessToken;
+        } else {
+            Map<String,Object> params = new HashMap();
+            params.put("grant_type",cloudpivotConfig.getGrantType());
+            params.put("client_id",cloudpivotConfig.getClientId());
+            params.put("client_secret",cloudpivotConfig.getClientSecret());
+
+            String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri()+"oauth/token", null, params, new HashMap());
+
+            Map result = (Map) JSONObject.parse(s);
+
+            accessToken = "bearer" + UtilMap.getString(result, "access_token");
+
+            long expiresIn = UtilMap.getLong(result, "expires_in") * 1000;
+
+            UtilToken.put("invalid-token-cloudpivot", accessToken, expiresIn);
+
+            return accessToken;
+        }
+    }
+
+    /**
+     * 云枢新增表单
+     * @param schemaCode
+     * @param data
+     * @param userId
+     * @return
+     */
+    @Override
+    public Map createCpBo(String schemaCode, Map data, String userId){
+        Map body = new HashMap();
+
+        body.put("data",data);
+        body.put("schemaCode",schemaCode);
+        if (Strings.isNullOrEmpty(userId)){
+            body.put("userId",cloudpivotConfig.getOperatorUserId());
+        }else {
+            body.put("userId",userId);
+        }
+
+        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/create", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+
+        Map result = (Map) JSONObject.parse(s);
+
+        return result;
+    }
+
+    /**
+     * 云枢更新表单
+     * @param schemaCode
+     * @param data
+     * @param userId
+     * @return
+     */
+    @Override
+    public Map updateCpBo(String schemaCode, Map data, String userId){
+        Map body = new HashMap();
+
+        body.put("data",data);
+        body.put("schemaCode",schemaCode);
+        if (Strings.isNullOrEmpty(userId)){
+            body.put("userId",cloudpivotConfig.getOperatorUserId());
+        }else {
+            body.put("userId",userId);
+        }
+
+        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/update", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+
+        Map result = (Map) JSONObject.parse(s);
+
+        return result;
+    }
+
+    /**
+     * 云枢获取表单详情
+     * @param schemaCode
+     * @param objectId
+     * @param userId
+     * @return
+     */
+    @Override
+    public Map getCpBo(String schemaCode, String objectId, String userId){
+        Map body = new HashMap();
+
+        body.put("objectId",objectId);
+        body.put("schemaCode",schemaCode);
+        if (Strings.isNullOrEmpty(userId)){
+            body.put("userId",cloudpivotConfig.getOperatorUserId());
+        }else {
+            body.put("userId",userId);
+        }
+
+        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/get", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+
+        Map result = (Map) JSONObject.parse(s);
+
+        isSuccess(result);
+
+        return result;
+    }
+
+    /**
+     * 云枢获取表单列表
+     * @param schemaCode
+     * @param queryCondition
+     * @param page
+     * @param size
+     * @param userId
+     * @return
+     */
+    @Override
+    public Map getCpBoList(String schemaCode, Map queryCondition,int page, int size, String userId){
+        Map body = new HashMap();
+
+        body.put("queryCondition",queryCondition);
+        body.put("schemaCode",schemaCode);
+        body.put("page",page);
+        body.put("size",size);
+        body.put("showTotal",true);
+
+        if (Strings.isNullOrEmpty(userId)){
+            body.put("userId",cloudpivotConfig.getOperatorUserId());
+        }else {
+            body.put("userId",userId);
+        }
+
+        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/list", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+
+        Map result = (Map) JSONObject.parse(s);
+
+        isSuccess(result);
+
+        return result;
+    }
+
+    //获取云枢表单详情返回结果中单据字段值
+    @Override
+    public Map getCpBoResultData(Map result){
+        Map data = UtilMap.getMap(result, "data");
+
+        Map bizObject = UtilMap.getMap(data, "bizObject");
+
+        Map resultData = UtilMap.getMap(bizObject, "data");
+
+        return resultData;
+    }
+
+    @Override
+    public void isSuccess(Map result){
+        int errcode = UtilMap.getInt(result, "errcode");
+        String errmsg = UtilMap.getString(result, "errmsg");
+
+        if (errcode != 0){
+            throw new RuntimeException("云枢接口调用失败:" + errmsg);
+        }
+    }
+}

+ 503 - 162
mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunServiceImpl.java

@@ -1,240 +1,581 @@
 package com.malk.jinlun.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.google.common.base.Strings;
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.google.gson.Gson;
 import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.entity.RepoRet;
 import com.kingdee.bos.webapi.sdk.K3CloudApi;
-import com.malk.jinlun.config.CloudpivotConfig;
 import com.malk.jinlun.config.KDWebApiConf;
-import com.malk.jinlun.entity.BillQuery;
+import com.malk.jinlun.entity.*;
+import com.malk.jinlun.service.CpClient;
 import com.malk.jinlun.service.JinlunService;
 import com.malk.server.common.McR;
+import com.malk.server.teambition.TBConf;
+import com.malk.server.teambition.TBR;
 import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import com.malk.utils.UtilToken;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.web.bind.annotation.RequestBody;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
+import static org.junit.Assert.fail;
+
+@Slf4j
 @Service
 public class JinlunServiceImpl implements JinlunService {
     @Autowired
     private KDWebApiConf kdWebApiConf;
 
     @Autowired
-    private CloudpivotConfig cloudpivotConfig;
-
-    @Override
-    public void syncMaterial() {
-        K3CloudApi client = new K3CloudApi(initIden());
+    private CpClient cpClient;
 
-        List<Map> result = new ArrayList<>();
-        List<Map> materialList = new ArrayList<>();
-
-        int startRow = 0;
-        int limit = 2000;
+    @Autowired
+    private TBConf tbConf;
 
-        BillQuery billQuery = new BillQuery();
-        billQuery.setFormId("BD_MATERIAL");
-        billQuery.setFieldKeys("FNumber,FName,F_Sl_xingnengid.FName,F_Sl_cihuaid.FName,FErpClsID,F_Sl_xingzhuangid.FName,F_Sl_ducengid.FName,F_Sl_ischongciid.FName,F_Sl_chihuaguige,F_Sl_midu,F_Sl_guige,F_Sl_weight,F_Sl_ischeck,F_Sl_qianguige,F_Sl_cixiangchang,F_NLD_gongyi.FName,F_Sl_biaomianji,FMaterialGroup.FName,FCategoryID.FName,FVOLUME,FBaseUnitId.FName");
-        List<Map> filterString = new ArrayList<>();
+    private final Object $lock = new Object[0];
 
-        //审核日期为昨天至今天
-        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
-//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+    private static final Long EXPIRES_IN = 7200000L;
 
+    @Override
+    public McR addCustomer(@RequestBody Map map) {
+        //查询云枢客户单据详情
+        String objectId = UtilMap.getString(map, "objectId");
 
-        billQuery.setFilterString(filterString);
-        billQuery.setLimit(limit);
+        Map customer = cpClient.getCpBo("ZLKHLC", objectId, null);
+
+        Map data = UtilMap.getMap(customer, "data");
+
+        Map bizObject = UtilMap.getMap(data, "bizObject");
+
+        Map customerData = UtilMap.getMap(bizObject, "data");
+
+        //请求参数,要求为json字符串
+        Save save = new Save();
+        CustomerModel customerModel = new CustomerModel();
+
+        //基本信息
+        String FName = UtilMap.getString(customerData,"ShortText1758195928433");//客户名称
+        String FShortName = UtilMap.getString(customerData,"ShortText1758195937324");//客户简称
+        FNumber FCOUNTRY = new FNumber(UtilMap.getString(customerData,"ShortText1760000048047"));//国家
+        FNumber FGroup = new FNumber(UtilMap.getString(customerData,"Dropdown1758198564777_key"));//客户分组
+        String F_VMKV_Combo = UtilMap.getString(customerData,"Dropdown1758198576644_key");//客户等级
+        FNumber FCustTypeId = new FNumber(UtilMap.getString(customerData,"Dropdown1758196678786_key"));//客户类别
+        String FDescription = UtilMap.getString(customerData,"LongText1758198621716");//备注
+
+        //商务信息
+        FNumber FSELLER = new FNumber(UtilMap.getString(customerData,"ShortText1759997501370"));//销售员
+        FNumber FRECCONDITIONID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199217950_key"));//收款条件
+        FNumber FTRADINGCURRID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199184443_key"));//结算币别
+        FNumber FSETTLETYPEID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199160962_key"));//结算方式
+        FNumber FTaxRate = new FNumber(UtilMap.getString(customerData,"Dropdown1758199231927_key"));//税率
+        FNumber FTaxType = new FNumber(UtilMap.getString(customerData,"Dropdown1758199263660_key"));//税分类
+        String FInvoiceType = UtilMap.getString(customerData,"Dropdown1758199247249_key");//发票类型
+        Boolean FISCREDITCHECK = UtilMap.getBoolean(customerData,"Logic1758199516570");//启用信用管理
+
+        //开票信息
+        String FINVOICEBANKACCOUNT = UtilMap.getString(customerData,"ShortText1758199605057");//银行账号
+        String FINVOICETITLE = UtilMap.getString(customerData,"ShortText1758199610851");//发票抬头
+        String FTAXREGISTERCODE = UtilMap.getString(customerData,"ShortText1758199617057");//纳税登记号
+        String FINVOICEBANKNAME = UtilMap.getString(customerData,"Text1758199624533");//开户银行
+        String FSOCIALCRECODE  = UtilMap.getString(customerData,"Text1758199630373");//统一社会信用代码
+        String FINVOICETEL = UtilMap.getString(customerData,"Text1758199637444");//开票联系电话
+        String FINVOICEADDRESS = UtilMap.getString(customerData,"LongText1758199679685");//开票通讯地址
+
+        //地址信息
+        List<Map> addressList = UtilMap.getList(customerData, "Sheet1758199794948");
+        List<CustomerContactEntry> FT_BD_CUSTCONTACT = new ArrayList<>();
+
+        for (Map address : addressList) {
+            CustomerContactEntry customerContactEntry = new CustomerContactEntry();
+            customerContactEntry.setFNUMBER1(UtilMap.getString(address,"ShortText1758199808715"));//地点编码
+            customerContactEntry.setFNAME1(UtilMap.getString(address,"ShortText1758199824395"));//地点名称
+
+            FT_BD_CUSTCONTACT.add(customerContactEntry);
+        }
 
-        do {
-            billQuery.setStartRow(startRow);
-            String s = null;
+        customerModel.setFName(FName);
+        customerModel.setFShortName(FShortName);
+        customerModel.setFCOUNTRY(FCOUNTRY);
+        customerModel.setFGroup(FGroup);
+        customerModel.setF_VMKV_Combo(F_VMKV_Combo);
+        customerModel.setFCustTypeId(FCustTypeId);
+        customerModel.setFDescription(FDescription);
+        customerModel.setFSELLER(FSELLER);
+        customerModel.setFRECCONDITIONID(FRECCONDITIONID);
+        customerModel.setFTRADINGCURRID(FTRADINGCURRID);
+        customerModel.setFSETTLETYPEID(FSETTLETYPEID);
+        customerModel.setFTaxRate(FTaxRate);
+        customerModel.setFTaxType(FTaxType);
+        customerModel.setFInvoiceType(FInvoiceType);
+        customerModel.setFISCREDITCHECK(FISCREDITCHECK);
+        customerModel.setFINVOICEBANKACCOUNT(FINVOICEBANKACCOUNT);
+        customerModel.setFINVOICETITLE(FINVOICETITLE);
+        customerModel.setFTAXREGISTERCODE(FTAXREGISTERCODE);
+        customerModel.setFINVOICEBANKNAME(FINVOICEBANKNAME);
+        customerModel.setFSOCIALCRECODE(FSOCIALCRECODE);
+        customerModel.setFINVOICETEL(FINVOICETEL);
+        customerModel.setFINVOICEADDRESS(FINVOICEADDRESS);
+        customerModel.setFT_BD_CUSTCONTACT(FT_BD_CUSTCONTACT);
+
+        save.setModel(customerModel);
+        Gson gson2 = new Gson();
+        String jsonData = gson2.toJson(save);
+
+        log.info(jsonData);
 
+        K3CloudApi client = new K3CloudApi(initIden());
+        //业务对象标识
+        String formId = "BD_Customer";
+        //调用接口
+        String resultJson = "";
+        try {
+            resultJson = client.save(formId,jsonData);
+        }catch (Exception e){
+            throw new RuntimeException(e);
+        }
+        //用于记录结果
+        Gson gson = new Gson();
+        //对返回结果进行解析和校验
+        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
+
+        String customerCode = "";
+
+        if (isTrue(repoRet)){
+            String id = repoRet.getResult().getId();
+            Submit submit = new Submit();
+            submit.setIds(id);
+            //提交客户
+            String resultJson2 = "";
             try {
-                s = client.billQuery(JSONObject.toJSONString(billQuery));
-            } catch (Exception e) {
+                resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
+            }catch (Exception e){
                 throw new RuntimeException(e);
             }
-            result = (List<Map>)JSONObject.parse(s);
-            materialList.addAll(result);
-
-            startRow += limit;
-        }while (result.size() == limit);
-
-        for (Map map : result) {
-            Map data = new HashMap();
-            data.put("ShortText1757932581400",UtilMap.getString(map,"FName"));//物料名称
-            data.put("ShortText1757932557449",UtilMap.getString(map,"FNumber"));//物料编码
-            data.put("ShortText1757932601205",UtilMap.getString(map,"F_Sl_xingnengid.FName"));//性能
-            data.put("ShortText1757932616477",UtilMap.getString(map,"F_Sl_cihuaid.FName"));//磁化方向
-            data.put("ShortText1757932652570",UtilMap.getString(map,"F_Sl_xingzhuangid.FName"));//形状
-            data.put("ShortText1757932660567",UtilMap.getString(map,"F_Sl_ducengid.FName"));//镀层
-            data.put("Dropdown1757932715739",UtilMap.getString(map,"F_Sl_ischongciid.FName"));//是否充磁
-            data.put("ShortText1757932699628",UtilMap.getString(map,"F_Sl_chihuaguige"));//磁化规格
-            data.put("Number1757932755471",UtilMap.getDouble(map,"F_Sl_midu"));//密度(g/mm³)
-            data.put("ShortText1757932739089",UtilMap.getString(map,"F_Sl_guige"));//尺寸规格
-            data.put("Number1757932746124",UtilMap.getDouble(map,"F_Sl_weight"));//单重(kg)
-            data.put("Logic1757932804393",UtilMap.getBoolean(map,"F_Sl_ischeck"));//是否需要检验
-            data.put("ShortText1757932821074",UtilMap.getString(map,"F_Sl_qianguige"));//带前后缀规格
-            data.put("Number1757932837126",UtilMap.getDouble(map,"F_Sl_cixiangchang"));//磁向长
-            data.put("ShortText1757932874077",UtilMap.getString(map,"F_NLD_gongyi.FName"));//工序
-            data.put("Number1757932881710",UtilMap.getDouble(map,"F_Sl_biaomianji"));//表面积
-            data.put("ShortText1757933029016",UtilMap.getString(map,"FMaterialGroup.FName"));//物料分组
-            data.put("ShortText1757933017962",UtilMap.getString(map,"FCategoryID.FName"));//存货类别
-
-            String fErpClsID = UtilMap.getString(map, "FErpClsID");
-            String wlsx = "";
-            switch (fErpClsID){
-                case "10":wlsx = "资产";break;
-                case "9":wlsx = "配置";break;
-                case "2":wlsx = "自制";break;
-                case "11":wlsx = "费用";break;
-                case "12":wlsx = "模型";break;
-                case "5":wlsx = "虚拟";break;
-                case "7":wlsx = "一次性";break;
-                case "13":wlsx = "产品系列";break;
-                case "3":wlsx = "委外";break;
-                case "4":wlsx = "特征";break;
-                case "6":wlsx = "服务";break;
-                case "1":wlsx = "原材料";break;
-
+            RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
+            isTrue(repoRet2);
+            customerCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
+            //回写云枢客户编号
+            cpClient.updateCpBo("ZLKHLC",UtilMap.map("id, ShortText1758195840127",objectId,customerCode),null);
+
+            if (isTrue(repoRet2)){
+                Audit audit = new Audit();
+                audit.setNumbers(Arrays.asList(customerCode));
+                //审核客户
+                String resultJson3 = "";
+                try {
+                    resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
+                }catch (Exception e){
+                    throw new RuntimeException(e);
+                }
+
+                RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
+                isTrue(repoRet3);
             }
-            data.put("ShortText1757933048314",wlsx);//物料属性
+        }
+
+
+        return McR.success(customerCode);
+    }
+
+    @Async
+    @Override
+    public void addCustomerContact(Map map) {
+        try {
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+
+        //请求参数,要求为json字符串
+        Save save = new Save();
+        ContactModel contactModel = new ContactModel();
+
+        String objectId = UtilMap.getString(map, "objectId");
+
+        Map contact = cpClient.getCpBo("JL002", objectId, null);
+
+        Map cpBoResultData = cpClient.getCpBoResultData(contact);
 
-            data.put("Number1757933060744",UtilMap.getDouble(map,"FVOLUME"));//体积
-            data.put("ShortText1757933079170",UtilMap.getString(map,"FBaseUnitId.FName"));//基本单位
+        String FName = UtilMap.getString(cpBoResultData, "ShortText1757918028530");//联系人姓名
+        String FMobile = UtilMap.getString(cpBoResultData, "ShortText1760076219303");//移动电话
+        FNumber Fex = new FNumber(UtilMap.getString(cpBoResultData, "Radio1757922932185_key"));//性别
+        String FPost = UtilMap.getString(cpBoResultData, "ShortText1757918203180");//职务
+        String FCompanyType = "BD_Customer";//类型:客户
+        String FTel = UtilMap.getString(cpBoResultData, "ShortText1757922962403");//固定电话
+        String FFax = UtilMap.getString(cpBoResultData, "ShortText1757918148867");//传真
+        String FEmail = UtilMap.getString(cpBoResultData, "ShortText1757918154124");//邮箱
+        FNumber FCustId = new FNumber(UtilMap.getString(cpBoResultData, "ShortText1758159321906"));//客户编码
 
-            String schemaCode = "WL";
+        contactModel.setFName(FName);
+        contactModel.setFMobile(FMobile);
+        contactModel.setFex(Fex);
+        contactModel.setFPost(FPost);
+        contactModel.setFCompanyType(FCompanyType);
+        contactModel.setFTel(FTel);
+        contactModel.setFFax(FFax);
+        contactModel.setFEmail(FEmail);
+        contactModel.setFCustId(FCustId);
 
-            Map body = new HashMap();
+        save.setModel(contactModel);
 
-            body.put("data",data);
-            body.put("schemaCode",schemaCode);
-            body.put("userId",cloudpivotConfig.getOperatorUserId());
+        Gson gson2 = new Gson();
+        String jsonData = gson2.toJson(save);
 
-            //云枢新增物料
-            Map result2 = createCpBo(schemaCode, body,null);
+        log.info(jsonData);
+
+        K3CloudApi client = new K3CloudApi(initIden());
+        //业务对象标识
+        String formId = "BD_CommonContact";
+        //调用接口
+        String resultJson = "";
+        try {
+            resultJson = client.save(formId,jsonData);
+        }catch (Exception e){
+            throw new RuntimeException(e);
         }
+        //用于记录结果
+        Gson gson = new Gson();
+        //对返回结果进行解析和校验
+        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
+
+        isTrue(repoRet);
+
+        String contactCode = repoRet.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
+
+        cpClient.updateCpBo("JL002",UtilMap.map("id, ShortText1760075793733",objectId,contactCode),null);
     }
 
+    @Async
     @Override
-    public McR addCustomer(@RequestBody Map map) {
-        //查询云枢客户单据详情
+    public void updateCustomer(Map map) {
+        K3CloudApi client = new K3CloudApi(initIden());
+        //业务对象标识
+        String formId = "BD_Customer";
+
+        //查询云枢客户详情
         String objectId = UtilMap.getString(map, "objectId");
+        Map customer = cpClient.getCpBo("KHDA", objectId, null);
+        Map customerData = cpClient.getCpBoResultData(customer);
 
-        Map customer = getCpBo("ZLKHLC", objectId, null);
+        String custFNumber = UtilMap.getString(customerData, "ShortText1758195840127");//客户编码
+        FNumber FSELLER = new FNumber(UtilMap.getString(customerData, "ShortText1759998244839"));//销售负责人
 
-        return McR.success();
-    }
+        //反审核
+        UnAudit unAudit = new UnAudit();
+        unAudit.setNumbers(Arrays.asList(custFNumber));//客户编码
 
-    private IdentifyInfo initIden(){
-        //注意 1:此处不再使用参数形式传入用户名及密码等敏感信息,改为在登录配置文件中设置。
-        //注意 2:必须先配置第三方系统登录授权信息后,再进行业务操作,详情参考各语言版本SDK介绍中的登录配置文件说明。
-        //读取配置,初始化SDK
-        IdentifyInfo iden = new IdentifyInfo();
-        iden.setUserName(kdWebApiConf.getXKDApiUserName());
-        iden.setAppId(kdWebApiConf.getXKDApiAppID());
-        iden.setdCID(kdWebApiConf.getXKDApiAcctID());
-        iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
-        iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());
+        RepoRet repoRet = new RepoRet();
 
-        return iden;
-    }
+        try {
+            String resultJson = client.unAudit(formId,new Gson().toJson(unAudit));
+            repoRet = new Gson().fromJson(resultJson, RepoRet.class);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
 
-    /**
-     * 云枢获取token
-     * @return
-     */
-    private String getCpAccessToken(){
-        String accessToken = UtilToken.get("invalid-token-cloudpivot");
+        isTrue(repoRet);
 
-        if (StringUtils.isNotBlank(accessToken)) {
-            return accessToken;
-        } else {
-            Map<String,Object> params = new HashMap();
-            params.put("grant_type",cloudpivotConfig.getGrantType());
-            params.put("client_id",cloudpivotConfig.getClientId());
-            params.put("client_secret",cloudpivotConfig.getClientSecret());
+        //查询客户内码
+        View view = new View();
+        view.setNumber(custFNumber);//客户编码
+
+        RepoRet repoRet2 = new RepoRet();
+
+        try {
+            String resultJson = client.view(formId,new Gson().toJson(view));
+            repoRet2 = new Gson().fromJson(resultJson, RepoRet.class);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        isTrue(repoRet2);
 
-            String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri()+"oauth/token", null, params, new HashMap());
+        int FCUSTID = UtilMap.getDouble((Map) repoRet2.getResult().getResult(), "Id").intValue();
 
-            Map result = (Map) JSONObject.parse(s);
+        //保存
+        Save save = new Save();
+        CustomerModel customerModel = new CustomerModel();
+        customerModel.setFCUSTID(FCUSTID);//客户内码
+        customerModel.setFSELLER(FSELLER);//销售员
+        save.setModel(customerModel);
+        save.setNeedUpDateFields(Arrays.asList("FSELLER"));
 
-            accessToken = "bearer" + UtilMap.getString(result, "access_token");
+        RepoRet repoRet3 = new RepoRet();
+
+        try {
+            String resultJson = client.save(formId,new Gson().toJson(save));
+            repoRet3 = new Gson().fromJson(resultJson, RepoRet.class);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
 
-            long expiresIn = UtilMap.getLong(result, "expires_in") * 1000;
+        isTrue(repoRet3);
 
-            UtilToken.put("invalid-token-cloudpivot", accessToken, expiresIn);
+        //提交
+        Submit submit = new Submit();
+        submit.setNumbers(Arrays.asList(custFNumber));//客户编码
 
-            return accessToken;
+        RepoRet repoRet4 = new RepoRet();
+
+        try {
+            String resultJson = client.submit(formId, JSONObject.toJSONString(submit));
+            repoRet4 = new Gson().fromJson(resultJson, RepoRet.class);
+        }catch (Exception e){
+            throw new RuntimeException(e);
         }
+
+        isTrue(repoRet4);
+
+        //审核
+        Audit audit = new Audit();
+        audit.setNumbers(Arrays.asList(custFNumber));
+
+        RepoRet repoRet5 = new RepoRet();
+
+        try {
+            String resultJson = client.audit(formId,JSONObject.toJSONString(audit));
+            repoRet5 = new Gson().fromJson(resultJson, RepoRet.class);
+        }catch (Exception e){
+            throw new RuntimeException(e);
+        }
+
+        isTrue(repoRet5);
     }
 
-    /**
-     * 云枢新增表单
-     * @param schemaCode
-     * @param data
-     * @param userId
-     * @return
-     */
-    private Map createCpBo(String schemaCode, Map data, String userId){
-        Map body = new HashMap();
+    @Override
+    public McR addSaleOrder(Map map) {
+        //查询云枢客户单据详情
+        String objectId = UtilMap.getString(map, "objectId");
 
-        body.put("data",data);
-        body.put("schemaCode",schemaCode);
-        if (Strings.isNullOrEmpty(userId)){
-            body.put("userId",cloudpivotConfig.getOperatorUserId());
-        }else {
-            body.put("userId",userId);
+        Map saleOrder = cpClient.getCpBo("XSDD", objectId, null);
+
+        Map saleOrderData = cpClient.getCpBoResultData(saleOrder);
+
+        //请求参数,要求为json字符串
+        Save save = new Save();
+        SaleOrderModel saleOrderModel = new SaleOrderModel();
+
+        //基本信息
+        FNumber FBillTypeID = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339062589_key"));//单据类型
+        String FDate = UtilMap.getString(saleOrderData, "Date1758339215935");//日期
+        FNumber FCustId = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760426148831"));//客户
+        String F_NLD_DDTYPE = UtilMap.getString(saleOrderData, "Dropdown1758340059699_key");//订单类型
+        FNumber FSalerId = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760421121913"));//销售员
+        FSTAFFNUMBER F_Sl_gendanyuan = new FSTAFFNUMBER(UtilMap.getString(saleOrderData, "Text1760421147555"));//跟单员
+        String FBusinessType = UtilMap.getString(saleOrderData,"Dropdown1758339265813_key");//业务类型
+        String F_WGR_Combo_re5 = UtilMap.getString(saleOrderData,"Dropdown1758340112723_key");//订单要求
+        FNumber FHEADLOCID = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760507577966"));//交货地点
+        String FNote = UtilMap.getString(saleOrderData,"LongText1758339516625");//备注
+        String F_Sl_customerbillno = UtilMap.getString(saleOrderData,"ShortText1758340044946");//客户订单号
+
+        saleOrderModel.setFBillTypeID(FBillTypeID);
+        saleOrderModel.setFDate(FDate);
+        saleOrderModel.setFCustId(FCustId);
+        saleOrderModel.setF_NLD_DDTYPE(F_NLD_DDTYPE);
+        saleOrderModel.setFSalerId(FSalerId);
+        saleOrderModel.setF_Sl_gendanyuan(F_Sl_gendanyuan);
+        saleOrderModel.setFBusinessType(FBusinessType);
+        saleOrderModel.setF_WGR_Combo_re5(F_WGR_Combo_re5);
+        saleOrderModel.setFHEADLOCID(FHEADLOCID);
+        saleOrderModel.setFNote(FNote);
+        saleOrderModel.setF_Sl_customerbillno(F_Sl_customerbillno);
+
+        //财务信息
+        SaleOrderFinance saleOrderFinance = new SaleOrderFinance();
+        FNumber FSettleCurrId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339227503_key"));//结算币别
+        FNumber FRecConditionId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339314401_key"));//收款条件
+        FNumber FSettleModeId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758340854092_key"));//结算方式
+        boolean FIsIncludedTax = UtilMap.getBoolean(saleOrderData,"Logic1758340099868");//是否含税
+        boolean FIsPriceExcludeTax = UtilMap.getBoolean(saleOrderData,"Logic1758340955492");//价外税
+
+        saleOrderFinance.setFSettleCurrId(FSettleCurrId);
+        saleOrderFinance.setFRecConditionId(FRecConditionId);
+        saleOrderFinance.setFSettleModeId(FSettleModeId);
+        saleOrderFinance.setFIsIncludedTax(FIsIncludedTax);
+        saleOrderFinance.setFIsPriceExcludeTax(FIsPriceExcludeTax);
+
+        saleOrderModel.setFSaleOrderFinance(saleOrderFinance);
+
+        //明细信息
+        List<Map> saleDetailList = UtilMap.getList(saleOrderData, "Sheet1758341252878");
+        List<SaleOrderEntry> saleOrderEntryList = new ArrayList<>();
+
+        for (Map saleDetail : saleDetailList) {
+            FNumber FMaterialId = new FNumber(UtilMap.getString(saleDetail, "ShortText1758341332222"));//物料编码
+            String F_Sl_XSTYPE = UtilMap.getString(saleDetail, "Dropdown1758341293022_key");//产品类别
+            Double FQty = UtilMap.getDouble(saleDetail, "Number1758341381523");//销售数量
+            Double FTaxPrice = UtilMap.getDouble(saleDetail, "Number1758341424993");//含税单价
+            boolean FIsFree = UtilMap.getBoolean(saleDetail,"Logic1758341430353");//是否赠品
+            Double FEntryTaxRate = UtilMap.getDouble(saleDetail, "Number1758349078527");//税率
+            String FDeliveryDate = UtilMap.getString(saleDetail,"Date1758341499356");//客户交期
+            String FEntryNote = UtilMap.getString(saleDetail,"Date1758341499356");//备注
+            Double F_VMKV_MPPRICE = UtilMap.getDouble(saleDetail, "Number1758341576099");//报价价格
+            String F_VMKV_SCCQ1 = UtilMap.getString(saleDetail,"Dropdown1760425152219_key");//生产厂区
+
+            SaleOrderEntry saleOrderEntry = new SaleOrderEntry();
+            saleOrderEntry.setFMaterialId(FMaterialId);
+            saleOrderEntry.setF_Sl_XSTYPE(F_Sl_XSTYPE);
+            saleOrderEntry.setFQty(FQty);
+            saleOrderEntry.setFTaxPrice(FTaxPrice);
+            saleOrderEntry.setFIsFree(FIsFree);
+            saleOrderEntry.setFEntryTaxRate(FEntryTaxRate);
+            saleOrderEntry.setFDeliveryDate(FDeliveryDate);
+            saleOrderEntry.setFEntryNote(FEntryNote);
+            saleOrderEntry.setF_VMKV_MPPRICE(F_VMKV_MPPRICE);
+            saleOrderEntry.setF_VMKV_SCCQ1(F_VMKV_SCCQ1);
+
+            saleOrderEntryList.add(saleOrderEntry);
         }
 
-        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/create", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+        saleOrderModel.setFSaleOrderEntry(saleOrderEntryList);
 
-        Map result = (Map) JSONObject.parse(s);
+        save.setModel(saleOrderModel);
+        Gson gson2 = new Gson();
+        String jsonData = gson2.toJson(save);
 
-        return result;
+        log.info(jsonData);
+
+        K3CloudApi client = new K3CloudApi(initIden());
+        //业务对象标识
+        String formId = "SAL_SaleOrder";
+        //调用接口
+        String resultJson = "";
+        try {
+            resultJson = client.save(formId,jsonData);
+        }catch (Exception e){
+            throw new RuntimeException(e);
+        }
+        //用于记录结果
+        Gson gson = new Gson();
+        //对返回结果进行解析和校验
+        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
+
+        String saleOrderCode = "";
+
+        if (isTrue(repoRet)){
+            String id = repoRet.getResult().getId();
+            Submit submit = new Submit();
+            submit.setIds(id);
+            //提交客户
+            String resultJson2 = "";
+            try {
+                resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
+            }catch (Exception e){
+                throw new RuntimeException(e);
+            }
+            RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
+            isTrue(repoRet2);
+            saleOrderCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
+            //回写云枢销售订单编号
+            cpClient.updateCpBo("XSDD",UtilMap.map("id, ShortText1758339123133",objectId,saleOrderCode),null);
+
+            if (isTrue(repoRet2)){
+                Audit audit = new Audit();
+                audit.setNumbers(Arrays.asList(saleOrderCode));
+                //审核销售订单
+                String resultJson3 = "";
+                try {
+                    resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
+                }catch (Exception e){
+                    throw new RuntimeException(e);
+                }
+
+                RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
+                isTrue(repoRet3);
+            }
+        }
+
+
+        return McR.success(saleOrderCode);
     }
 
-    /**
-     * 云枢获取表单详情
-     * @param schemaCode
-     * @param objectId
-     * @param userId
-     * @return
-     */
-    private Map getCpBo(String schemaCode, String objectId, String userId){
+    @Async
+    @Override
+    public McR createTbProject(Map map) {
+        //查询云枢重要样品打样申请详情
+        String objectId = UtilMap.getString(map, "objectId");
+
+        Map proofing = cpClient.getCpBo("ZYYPDYSQ", objectId, null);
+
+        Map proofingData = cpClient.getCpBoResultData(proofing);
+
+        String projectName = UtilMap.getString(proofingData, "ShortText1758525084919");
+        String templateId = UtilMap.getString(proofingData, "Dropdown1760517115491_key");
+
         Map body = new HashMap();
+        body.put("name",projectName);
+        body.put("templateId",templateId);
 
-        body.put("objectId",objectId);
-        body.put("schemaCode",schemaCode);
-        if (Strings.isNullOrEmpty(userId)){
-            body.put("userId",cloudpivotConfig.getOperatorUserId());
-        }else {
-            body.put("userId",userId);
-        }
+        TBR tbr = (TBR) UtilHttp.doPost("https://open.teambition.com/api/v3/project/create-from-template", initTbHeaderToken(), null,body, TBR.class);
+        Map result = (Map) tbr.getResult();
+        String id = result.get("id").toString();
+
+        //更新云枢打样申请项目id
+        cpClient.updateCpBo("ZYYPDYSQ",UtilMap.map("id, ShortText1760517617788",objectId,id),null);
+
+        return McR.success(id);
+    }
+
+    private IdentifyInfo initIden(){
+        //注意 1:此处不再使用参数形式传入用户名及密码等敏感信息,改为在登录配置文件中设置。
+        //注意 2:必须先配置第三方系统登录授权信息后,再进行业务操作,详情参考各语言版本SDK介绍中的登录配置文件说明。
+        //读取配置,初始化SDK
+        IdentifyInfo iden = new IdentifyInfo();
+        iden.setUserName(kdWebApiConf.getXKDApiUserName());
+        iden.setAppId(kdWebApiConf.getXKDApiAppID());
+        iden.setdCID(kdWebApiConf.getXKDApiAcctID());
+        iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
+        iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());
 
-        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/bo/get", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+        return iden;
+    }
 
-        Map result = (Map) JSONObject.parse(s);
 
-        isSuccess(result);
+    private boolean isTrue(RepoRet repoRet){
+        Gson gson = new Gson();
 
-        return result;
+        if (repoRet.getResult().getResponseStatus().isIsSuccess()) {
+            System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult()));
+            return true;
+        } else {
+            fail("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus()));
+            return false;
+        }
     }
 
-    private void isSuccess(Map result){
-        int errcode = UtilMap.getInt(result, "errcode");
-        String errmsg = UtilMap.getString(result, "errmsg");
+    private Map<String, String> initTbHeaderToken() {
+        Map header = new HashMap();
+        header.put("Authorization", getTbAccessToken());
+        header.put("X-Tenant-Id", tbConf.getTenantId());
+        header.put("X-Tenant-Type", "organization");
+        header.put("x-operator-id", tbConf.getOperatorId());
+        return header;
+    }
 
-        if (errcode != 0){
-            throw new RuntimeException("云枢接口调用失败:" + errmsg);
+    private String getTbAccessToken() {
+        synchronized(this.$lock) {
+            String accessToken = UtilToken.get("invalid-token-teambition");
+            if (StringUtils.isNotBlank(accessToken)) {
+                return accessToken;
+            } else {
+                Algorithm algorithm = Algorithm.HMAC256(tbConf.getAppSecret());
+                long timestamp = System.currentTimeMillis();
+                Date issuedAt = new Date(timestamp);
+                Date expiresAt = new Date(timestamp + EXPIRES_IN);
+                accessToken = JWT.create().withClaim("_appId", tbConf.getAppID()).withIssuedAt(issuedAt).withExpiresAt(expiresAt).sign(algorithm);
+                log.info("响应token, {}", accessToken);
+                UtilToken.put("invalid-token-teambition", accessToken, EXPIRES_IN);
+                return accessToken;
+            }
         }
     }
 

+ 576 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunTaskServiceImpl.java

@@ -0,0 +1,576 @@
+package com.malk.jinlun.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
+import com.malk.jinlun.config.KDWebApiConf;
+import com.malk.jinlun.entity.BillQuery;
+import com.malk.jinlun.service.CpClient;
+import com.malk.jinlun.service.JinlunTaskService;
+import com.malk.utils.UtilMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class JinlunTaskServiceImpl implements JinlunTaskService {
+    @Autowired
+    private KDWebApiConf kdWebApiConf;
+
+    @Autowired
+    private CpClient cpClient;
+
+    @Override
+    public void syncMaterial() {
+        K3CloudApi client = new K3CloudApi(initIden());
+
+        List<Map> result = new ArrayList<>();
+        List<Map> materialList = new ArrayList<>();
+
+        int startRow = 0;
+        int limit = 2000;
+
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("BD_MATERIAL");
+        billQuery.setFieldKeys("FNumber,FName,F_Sl_xingnengid.FName,F_Sl_cihuaid.FName,FSpecification,FErpClsID,F_Sl_xingzhuangid.FName,F_Sl_ducengid.FName,F_Sl_ischongciid.FName,F_Sl_chihuaguige,F_Sl_midu,F_Sl_guige,F_Sl_weight,F_Sl_ischeck,F_Sl_qianguige,F_Sl_cixiangchang,F_NLD_gongyi.FName,F_Sl_biaomianji,FMaterialGroup.FName,FCategoryID.FName,FVOLUME,FBaseUnitId.FName,FSaleUnitId.FName,FSalePriceUnitId.FName");
+        List<Map> filterString = new ArrayList<>();
+
+        //审核日期为昨天至今天
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+
+
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+
+        do {
+            billQuery.setStartRow(startRow);
+            String s = null;
+
+            try {
+                s = client.billQuery(JSONObject.toJSONString(billQuery));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            result = (List<Map>)JSONObject.parse(s);
+            materialList.addAll(result);
+
+            startRow += limit;
+        }while (result.size() == limit);
+
+        for (Map map : result) {
+            Map data = new HashMap();
+            data.put("ShortText1757932581400",UtilMap.getString(map,"FName"));//物料名称
+            data.put("ShortText1757932557449",UtilMap.getString(map,"FNumber"));//物料编码
+            data.put("ShortText1757932601205",UtilMap.getString(map,"F_Sl_xingnengid.FName"));//性能
+            data.put("ShortText1757932616477",UtilMap.getString(map,"F_Sl_cihuaid.FName"));//磁化方向
+            data.put("ShortText1757932652570",UtilMap.getString(map,"F_Sl_xingzhuangid.FName"));//形状
+            data.put("ShortText1757932660567",UtilMap.getString(map,"F_Sl_ducengid.FName"));//镀层
+            data.put("Dropdown1757932715739",UtilMap.getString(map,"F_Sl_ischongciid.FName"));//是否充磁
+            data.put("ShortText1757932699628",UtilMap.getString(map,"F_Sl_chihuaguige"));//磁化规格
+            data.put("Number1757932755471",UtilMap.getDouble(map,"F_Sl_midu"));//密度(g/mm³)
+            data.put("ShortText1757932739089",UtilMap.getString(map,"F_Sl_guige"));//尺寸规格
+            data.put("Number1757932746124",UtilMap.getDouble(map,"F_Sl_weight"));//单重(kg)
+            data.put("Logic1757932804393",UtilMap.getBoolean(map,"F_Sl_ischeck"));//是否需要检验
+            data.put("ShortText1757932821074",UtilMap.getString(map,"F_Sl_qianguige"));//带前后缀规格
+            data.put("Number1757932837126",UtilMap.getDouble(map,"F_Sl_cixiangchang"));//磁向长
+            data.put("ShortText1757932874077",UtilMap.getString(map,"F_NLD_gongyi.FName"));//工序
+            data.put("Number1757932881710",UtilMap.getDouble(map,"F_Sl_biaomianji"));//表面积
+            data.put("ShortText1760342223781",UtilMap.getString(map,"FSpecification"));//规格型号
+            data.put("ShortText1757933029016",UtilMap.getString(map,"FMaterialGroup.FName"));//物料分组
+            data.put("ShortText1757933017962",UtilMap.getString(map,"FCategoryID.FName"));//存货类别
+
+            String fErpClsID = UtilMap.getString(map, "FErpClsID");
+            String wlsx = "";
+            switch (fErpClsID){
+                case "10":wlsx = "资产";break;
+                case "9":wlsx = "配置";break;
+                case "2":wlsx = "自制";break;
+                case "11":wlsx = "费用";break;
+                case "12":wlsx = "模型";break;
+                case "5":wlsx = "虚拟";break;
+                case "7":wlsx = "一次性";break;
+                case "13":wlsx = "产品系列";break;
+                case "3":wlsx = "委外";break;
+                case "4":wlsx = "特征";break;
+                case "6":wlsx = "服务";break;
+                case "1":wlsx = "原材料";break;
+
+            }
+            data.put("ShortText1757933048314",wlsx);//物料属性
+
+            data.put("Number1757933060744",UtilMap.getDouble(map,"FVOLUME"));//体积
+            data.put("ShortText1757933079170",UtilMap.getString(map,"FBaseUnitId.FName"));//基本单位
+            data.put("Text1760411136055",UtilMap.getString(map,"FSaleUnitId.FName"));//销售单位
+            data.put("Text1760411137275",UtilMap.getString(map,"FSalePriceUnitId.FName"));//销售计价单位
+
+            String schemaCode = "WL";
+
+            //查询是否存在
+            Map result2 = cpClient.getCpBoList(schemaCode, UtilMap.map("queryFilterType, propertyCode, propertyValue", "Eq", "ShortText1757932557449", UtilMap.getString(map,"FNumber")), 0, 1, null);
+
+            Map bizObjectPage = UtilMap.getMap(UtilMap.getMap(result2, "data"),"bizObjectPage");
+
+            int totalElements = UtilMap.getInt(bizObjectPage, "totalElements");
+
+            if (totalElements > 0) {
+                //云枢更新销售出库单
+                Map content = ((List<Map>) UtilMap.getList(bizObjectPage, "content")).get(0);
+
+                String bizObjectId = UtilMap.getString(content,"bizObjectId");//主表实例id
+
+                data.put("id",bizObjectId);
+
+                Map result3 = cpClient.updateCpBo(schemaCode, data,null);
+            }else {
+                //云枢新增销售出库单
+                Map result3 = cpClient.createCpBo(schemaCode, data,null);
+            }
+        }
+    }
+
+    @Override
+    public void syncSaleOut() {
+        K3CloudApi client = new K3CloudApi(initIden());
+
+        List<Map> result = new ArrayList<>();
+        List<Map> materialList = new ArrayList<>();
+
+        int startRow = 0;
+        int limit = 2000;
+
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("SAL_OUTSTOCK");
+        billQuery.setFieldKeys("FBillNo,FBillTypeID.FName,FDate,FSettleCurrID.FName,FCustomerID.FName,FCustomerID.FShortName,FHeadLocationID.FName,FMaterialID.FNumber,FMaterialID.FName,FMaterialID.FSpecification,FPriceUnitQty,FRealQty,FPriceUnitId.FName,FBaseUnitID.FName,FIsFree,FPrice,FTaxPrice,FAmount,FAllAmount,FDiscount,FEntrynote");
+        List<Map> filterString = new ArrayList<>();
+
+        //审核日期为昨天至今天
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+
+
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+
+        do {
+            billQuery.setStartRow(startRow);
+            String s = null;
+
+            try {
+                s = client.billQuery(JSONObject.toJSONString(billQuery));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            result = (List<Map>)JSONObject.parse(s);
+            materialList.addAll(result);
+
+            startRow += limit;
+        }while (result.size() == limit);
+
+
+        List<Map<String,Object>> dataList = new ArrayList<>();
+
+        for (Map material : materialList) {
+            Map data = new HashMap();
+
+            data.put("ShortText1760153678207",UtilMap.getString(material,"FBillNo"));//单据编号
+            data.put("ShortText1760153685839",UtilMap.getString(material,"FBillTypeID.FName"));//单据类型
+            data.put("Date1760153694040",UtilMap.getString(material, "FDate").replace("T"," "));//日期
+            data.put("ShortText1760153691233",UtilMap.getString(material,"FSettleCurrID.FName"));//结算币别
+            data.put("ShortText1760153707273",UtilMap.getString(material,"FCustomerID.FName"));//客户名称
+            data.put("ShortText1760153714871",UtilMap.getString(material,"FCustomerID.FShortName"));//客户简称
+            data.put("ShortText1760153722192",UtilMap.getString(material,"FHeadLocationID.FName"));//交货地点
+
+            List<Map> entry = new ArrayList<>();
+            Map entryMap = new HashMap();
+            entryMap.put("Number1760153738400",UtilMap.getString(material,"FMaterialID.FNumber"));//物料编码
+            entryMap.put("ShortText1760153773163",UtilMap.getString(material,"FMaterialID.FNumber"));//物料编码
+            entryMap.put("Text1760153778635",UtilMap.getString(material,"FMaterialID.FName"));//物料名称
+            entryMap.put("Text1760153786986",UtilMap.getString(material,"FMaterialID.FSpecification"));//规格型号
+            entryMap.put("Number1760153811668",UtilMap.getDouble(material,"FPriceUnitQty"));//计价数量
+            entryMap.put("Number1760153958907",UtilMap.getDouble(material,"FRealQty"));//实发数量
+            entryMap.put("Text1760153793403",UtilMap.getString(material,"FPriceUnitId.FName"));//计价单位
+            entryMap.put("Text1760153804514",UtilMap.getString(material,"FBaseUnitID.FName"));//基本单位
+            entryMap.put("Logic1760171983887",UtilMap.getBoolean(material,"FIsFree"));//是否赠品
+            entryMap.put("Number1760153991898",UtilMap.getDouble(material,"FPrice"));//单价
+            entryMap.put("Number1760154006703",UtilMap.getDouble(material,"FTaxPrice"));//计价单价
+            entryMap.put("Number1760154034052",UtilMap.getDouble(material,"FAmount"));//金额
+            entryMap.put("Number1760154039959",UtilMap.getDouble(material,"FAllAmount"));//价税合计
+            entryMap.put("Number1760154058940",UtilMap.getDouble(material,"FDiscount"));//折扣额
+            entryMap.put("ShortText1760154066042",UtilMap.getString(material,"FEntrynote"));//备注
+
+            entry.add(entryMap);
+
+            data.put("Sheet1760153734916",entry);
+
+            dataList.add(data);
+        }
+
+        //处理同一出库单多个明细
+        List<Map<String, Object>> list = mergeListMap(dataList, "ShortText1760153678207", "Sheet1760153734916");
+
+        for (Map<String, Object> map : list) {
+            String schemaCode = "XSCKD";
+            //查询是否存在
+            Map result2 = cpClient.getCpBoList(schemaCode, UtilMap.map("queryFilterType, propertyCode, propertyValue", "Eq", "ShortText1760153678207", UtilMap.getString(map, "ShortText1760153678207")), 0, 1, null);
+
+            Map bizObjectPage = UtilMap.getMap(UtilMap.getMap(result2, "data"),"bizObjectPage");
+
+            int totalElements = UtilMap.getInt(bizObjectPage, "totalElements");
+
+            List<Map> items = (List<Map>) map.get("Sheet1760153734916");
+            if (totalElements > 0) {
+                //云枢更新销售出库单
+                Map content = ((List<Map>) UtilMap.getList(bizObjectPage, "content")).get(0);
+
+                Map map1 = UtilMap.getMap(content, "data");
+                List<Map> list1 = UtilMap.getList(map1, "Sheet1760153734916");
+
+                for (int i = 0; i < items.size(); i++) {
+                    items.get(i).put("rowStatus", "Modified");
+                    items.get(i).put("id", (UtilMap.getString(list1.get(i),"id")));//子表实例id
+                }
+
+                items.forEach(item -> item.put("rowStatus", "Modified"));
+
+                String bizObjectId = UtilMap.getString(content,"bizObjectId");//主表实例id
+
+                map.put("id",bizObjectId);
+
+                Map result3 = cpClient.updateCpBo(schemaCode, map,null);
+            }else {
+                //云枢新增销售出库单
+                items.forEach(item -> item.put("rowStatus", "added"));
+                Map result3 = cpClient.createCpBo(schemaCode, map,null);
+            }
+        }
+    }
+
+    @Override
+    public void syncReceipt() {
+        K3CloudApi client = new K3CloudApi(initIden());
+
+        List<Map> result = new ArrayList<>();
+        List<Map> receiptList = new ArrayList<>();
+
+        int startRow = 0;
+        int limit = 2000;
+
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("AR_RECEIVEBILL");
+        billQuery.setFieldKeys("FBillNo,FBillTypeID.FName,FPAYUNITTYPE,FDate,FPAYUNIT.FName,FCURRENCYID.FName,FRECEIVEAMOUNTFOR_H,FREALRECAMOUNTFOR,F_VMKV_Combo,FSALEERID.FName,F_VMKV_Base_83g.FName,FSETTLETYPEID,FSETTLETYPEID.FName,FPURPOSEID.FName,FACCOUNTID.FNumber,FACCOUNTID.FName,FRECTOTALAMOUNTFOR,FREALRECAMOUNTFOR_D,FCOMMENT");
+        List<Map> filterString = new ArrayList<>();
+
+        //审核日期为昨天至今天
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+
+
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+
+        do {
+            billQuery.setStartRow(startRow);
+            String s = null;
+
+            try {
+                s = client.billQuery(JSONObject.toJSONString(billQuery));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            result = (List<Map>)JSONObject.parse(s);
+            receiptList.addAll(result);
+
+            startRow += limit;
+        }while (result.size() == limit);
+
+
+        List<Map<String,Object>> dataList = new ArrayList<>();
+
+        for (Map receipt : receiptList) {
+            Map data = new HashMap();
+
+            data.put("ShortText1760585125989",UtilMap.getString(receipt,"FBillNo"));//单据编号
+            data.put("ShortText1760585107833",UtilMap.getString(receipt,"FBillTypeID.FName"));//单据类型
+            data.put("Date1760585187315",UtilMap.getString(receipt, "FDate").replace("T"," "));//业务日期
+            data.put("Text1760585197637",UtilMap.getString(receipt,"FSALEERID.FName"));//销售员
+            data.put("ShortText1760585145727",UtilMap.getString(receipt,"F_VMKV_Base_83g.FName"));//跟单员
+            data.put("ShortText1760585132200",UtilMap.getString(receipt,"FPAYUNIT.FName"));//付款单位
+
+            String FPAYUNITTYPE = UtilMap.getString(receipt, "FPAYUNITTYPE");
+            String FPAYUNITTYPE_VALUE = "";
+            switch (FPAYUNITTYPE){
+                case "BD_Supplier" : FPAYUNITTYPE_VALUE = "供应商";break;
+                case "BD_Customer" : FPAYUNITTYPE_VALUE = "客户";break;
+                case "BD_Department" : FPAYUNITTYPE_VALUE = "部门";break;
+                case "BD_Empinfo" : FPAYUNITTYPE_VALUE = "员工";break;
+                case "FIN_OTHERS" : FPAYUNITTYPE_VALUE = "其他往来单位";break;
+                case "ORG_Organizations" : FPAYUNITTYPE_VALUE = "组织机构";break;
+                case "BD_BANK" : FPAYUNITTYPE_VALUE = "银行";break;
+                default:break;
+            }
+            data.put("ShortText1760585114989", FPAYUNITTYPE_VALUE);//付款单位类型
+
+            data.put("ShortText1760585150625",UtilMap.getString(receipt,"FCURRENCYID.FName"));//币别
+
+            String F_VMKV_Combo = UtilMap.getString(receipt, "F_VMKV_Combo");
+            String F_VMKV_Combo_VALUE = "";
+            switch (F_VMKV_Combo){
+                case "ART" : F_VMKV_Combo_VALUE = "佳丰";break;
+                case "JLCC" : F_VMKV_Combo_VALUE = "金轮";break;
+                case "NOT" : F_VMKV_Combo_VALUE = "暂不确定";break;
+                default:break;
+            }
+            data.put("ShortText1760585157387", F_VMKV_Combo_VALUE);//佳丰/金轮
+
+            data.put("Number1760585167781",UtilMap.getDouble(receipt,"FRECEIVEAMOUNTFOR_H"));//应收金额
+            data.put("Number1760585178357",UtilMap.getDouble(receipt,"FREALRECAMOUNTFOR"));//实收金额
+
+            List<Map> entry = new ArrayList<>();
+            Map entryMap = new HashMap();
+            entryMap.put("ShortText1760585209233",UtilMap.getString(receipt,"FSETTLETYPEID.FName"));//结算方式
+            entryMap.put("ShortText1760585224298",UtilMap.getString(receipt,"FPURPOSEID.FName"));//收款用途
+            entryMap.put("ShortText1760585384491",UtilMap.getString(receipt,"FACCOUNTID.FNumber"));//我方银行账户
+            entryMap.put("Text1760585393271",UtilMap.getString(receipt,"FACCOUNTID.FName"));//我方账户名称
+            entryMap.put("Number1760585235219",UtilMap.getDouble(receipt,"FRECTOTALAMOUNTFOR"));//应收金额
+            entryMap.put("Number1760585242849",UtilMap.getDouble(receipt,"FREALRECAMOUNTFOR_D"));//实收金额
+            entryMap.put("ShortText1760585258640",UtilMap.getString(receipt,"FCOMMENT"));//备注
+
+            entry.add(entryMap);
+
+            data.put("Sheet1760585205663",entry);
+
+            dataList.add(data);
+        }
+
+        //处理同一收款单多个明细
+        List<Map<String, Object>> list = mergeListMap(dataList, "ShortText1760585125989", "Sheet1760585205663");
+
+        for (Map<String, Object> map : list) {
+            String schemaCode = "SKD";
+            //查询是否存在
+            Map result2 = cpClient.getCpBoList(schemaCode, UtilMap.map("queryFilterType, propertyCode, propertyValue", "Eq", "ShortText1760585125989", UtilMap.getString(map, "ShortText1760585125989")), 0, 1, null);
+
+            Map bizObjectPage = UtilMap.getMap(UtilMap.getMap(result2, "data"),"bizObjectPage");
+
+            int totalElements = UtilMap.getInt(bizObjectPage, "totalElements");
+
+            List<Map> items = (List<Map>) map.get("Sheet1760585205663");
+            if (totalElements > 0) {
+                //云枢更新收款单
+                Map content = ((List<Map>) UtilMap.getList(bizObjectPage, "content")).get(0);
+
+                Map map1 = UtilMap.getMap(content, "data");
+                List<Map> list1 = UtilMap.getList(map1, "Sheet1760585205663");
+
+                for (int i = 0; i < items.size(); i++) {
+                    items.get(i).put("rowStatus", "Modified");
+                    items.get(i).put("id", (UtilMap.getString(list1.get(i),"id")));//子表实例id
+                }
+
+                items.forEach(item -> item.put("rowStatus", "Modified"));
+
+                String bizObjectId = UtilMap.getString(content,"bizObjectId");//主表实例id
+
+                map.put("id",bizObjectId);
+
+                Map result3 = cpClient.updateCpBo(schemaCode, map,null);
+            }else {
+                //云枢新增收款单
+                items.forEach(item -> item.put("rowStatus", "added"));
+                Map result3 = cpClient.createCpBo(schemaCode, map,null);
+            }
+        }
+    }
+
+    @Override
+    public void syncReceivable() {
+        K3CloudApi client = new K3CloudApi(initIden());
+
+        List<Map> result = new ArrayList<>();
+        List<Map> receiptList = new ArrayList<>();
+
+        int startRow = 0;
+        int limit = 2000;
+
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("AR_receivable");
+        billQuery.setFieldKeys("FBillTypeID.FName,FBillNo,FCUSTOMERID.FName,FSALEERID.FName,F_VMKV_Base_qtr.FName,FSetAccountType,FCURRENCYID.FName,FDate,FENDDATE_H,FPayConditon.FName,FALLAMOUNTFOR,FEntityDetail_FEntryID,FMATERIALID.FNumber,FMATERIALID.FName,FMATERIALID.F_Sl_xingnengid,FPRICEUNITID.FName,FPriceQty,FTaxPrice,FPrice,FEntryTaxRate,FNoTaxAmountFor_D,FTAXAMOUNTFOR_D,FALLAMOUNTFOR_D,FIsFree,FBASICUNITQTY,FLot.FName,FRECEIVEAMOUNT,FComment");
+        List<Map> filterString = new ArrayList<>();
+
+        //审核日期为昨天至今天
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+
+
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+
+        do {
+            billQuery.setStartRow(startRow);
+            String s = null;
+
+            try {
+                s = client.billQuery(JSONObject.toJSONString(billQuery));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            result = (List<Map>)JSONObject.parse(s);
+            receiptList.addAll(result);
+
+            startRow += limit;
+        }while (result.size() == limit);
+
+
+        List<Map<String,Object>> dataList = new ArrayList<>();
+
+        for (Map receipt : receiptList) {
+            Map data = new HashMap();
+
+            data.put("ShortText1760602123650",UtilMap.getString(receipt,"FBillNo"));//发票号码
+            data.put("ShortText1760602106521",UtilMap.getString(receipt,"FBillTypeID.FName"));//单据类型
+            data.put("Date1760602205733",UtilMap.getString(receipt, "FDate").replace("T"," "));//业务日期
+            data.put("ShortText1760602136864",UtilMap.getString(receipt,"FSALEERID.FName"));//销售员
+            data.put("Text1760602141164",UtilMap.getString(receipt,"F_VMKV_Base_qtr.FName"));//跟单员
+            data.put("ShortText1760602119316",UtilMap.getString(receipt,"FCUSTOMERID.FName"));//客户
+
+            String FSetAccountType = UtilMap.getString(receipt, "FSetAccountType");
+            String FSetAccountType_VALUE = "";
+            switch (FSetAccountType){
+                case "1" : FSetAccountType_VALUE = "业务应收";break;
+                case "3" : FSetAccountType_VALUE = "财务应收";break;
+                case "2" : FSetAccountType_VALUE = "暂估应收";break;
+                default:break;
+            }
+
+            data.put("ShortText1760602147441", FSetAccountType_VALUE);//立账类型
+
+            data.put("ShortText1760602218380",UtilMap.getString(receipt,"FPayConditon.FName"));//收款条件
+            data.put("ShortText1760602197718",UtilMap.getString(receipt,"FCURRENCYID.FName"));//币别
+            data.put("Number1760602528131",UtilMap.getString(receipt,"FALLAMOUNTFOR"));//价税合计
+            data.put("Date1760602209998",UtilMap.getString(receipt,"FENDDATE_H").replace("T"," "));//到期日
+
+            List<Map> entry = new ArrayList<>();
+            Map entryMap = new HashMap();
+            entryMap.put("ShortText1760605881791",UtilMap.getString(receipt,"FEntityDetail_FEntryID"));//分录ID
+            entryMap.put("ShortText1760602287318",UtilMap.getString(receipt,"FMATERIALID.FNumber"));//物料编码
+            entryMap.put("Text1760602292846",UtilMap.getString(receipt,"FMATERIALID.FName"));//物料名称
+            entryMap.put("Text1760602314150",UtilMap.getString(receipt,"FMATERIALID.F_Sl_xingnengid"));//性能
+            entryMap.put("Text1760602299878",UtilMap.getString(receipt,"FPRICEUNITID.FName"));//计价单位
+            entryMap.put("Number1760602320518",UtilMap.getString(receipt,"FPriceQty"));//计价数量
+            entryMap.put("Number1760602330651",UtilMap.getString(receipt,"FTaxPrice"));//含税单价
+            entryMap.put("Number1760602338551",UtilMap.getString(receipt,"FPrice"));//单价
+            entryMap.put("Number1760602343876",UtilMap.getString(receipt,"FEntryTaxRate"));//税率
+            entryMap.put("Number1760602347414",UtilMap.getString(receipt,"FNoTaxAmountFor_D"));//不含税金额
+            entryMap.put("Number1760602354115",UtilMap.getString(receipt,"FTAXAMOUNTFOR_D"));//税额
+            entryMap.put("Number1760602359012",UtilMap.getString(receipt,"FALLAMOUNTFOR_D"));//价税合计
+            entryMap.put("Logic1760602369561",UtilMap.getString(receipt,"FIsFree"));//是否赠品
+            entryMap.put("Number1760602378666",UtilMap.getString(receipt,"FBASICUNITQTY"));//销售基本数量
+            entryMap.put("ShortText1760602387059",UtilMap.getString(receipt,"FLot.FName"));//批号
+            entryMap.put("Number1760602396337",UtilMap.getString(receipt,"FRECEIVEAMOUNT"));//已结算金额
+            entryMap.put("Text1760602391849",UtilMap.getString(receipt,"FComment"));//备注
+
+            entry.add(entryMap);
+
+            data.put("Sheet1760602277185",entry);
+
+            dataList.add(data);
+        }
+
+        //处理同一收款单多个明细
+        List<Map<String, Object>> list = mergeListMap(dataList, "ShortText1760602123650", "Sheet1760602277185");
+
+        for (Map<String, Object> map : list) {
+            String schemaCode = "YSD";
+            //查询是否存在
+            Map result2 = cpClient.getCpBoList(schemaCode, UtilMap.map("queryFilterType, propertyCode, propertyValue", "Eq", "ShortText1760602123650", UtilMap.getString(map, "Sheet1760602277185")), 0, 1, null);
+
+            Map bizObjectPage = UtilMap.getMap(UtilMap.getMap(result2, "data"),"bizObjectPage");
+
+            int totalElements = UtilMap.getInt(bizObjectPage, "totalElements");
+
+            List<Map> items = (List<Map>) map.get("Sheet1760602277185");
+            if (totalElements > 0) {
+                //云枢更新应收单
+                Map content = ((List<Map>) UtilMap.getList(bizObjectPage, "content")).get(0);
+
+                Map map1 = UtilMap.getMap(content, "data");
+                List<Map> list1 = UtilMap.getList(map1, "Sheet1760602277185");
+
+                for (int i = 0; i < items.size(); i++) {
+                    items.get(i).put("rowStatus", "Modified");
+                    items.get(i).put("id", (UtilMap.getString(list1.get(i),"id")));//子表实例id
+                }
+
+                items.forEach(item -> item.put("rowStatus", "Modified"));
+
+                String bizObjectId = UtilMap.getString(content,"bizObjectId");//主表实例id
+
+                map.put("id",bizObjectId);
+
+                Map result3 = cpClient.updateCpBo(schemaCode, map,null);
+            }else {
+                //云枢新增应收单
+                items.forEach(item -> item.put("rowStatus", "added"));
+                Map result3 = cpClient.createCpBo(schemaCode, map,null);
+            }
+        }
+    }
+
+    private IdentifyInfo initIden(){
+        //注意 1:此处不再使用参数形式传入用户名及密码等敏感信息,改为在登录配置文件中设置。
+        //注意 2:必须先配置第三方系统登录授权信息后,再进行业务操作,详情参考各语言版本SDK介绍中的登录配置文件说明。
+        //读取配置,初始化SDK
+        IdentifyInfo iden = new IdentifyInfo();
+        iden.setUserName(kdWebApiConf.getXKDApiUserName());
+        iden.setAppId(kdWebApiConf.getXKDApiAppID());
+        iden.setdCID(kdWebApiConf.getXKDApiAcctID());
+        iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
+        iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());
+
+        return iden;
+    }
+
+    public static List<Map<String, Object>> mergeListMap(List<Map<String, Object>> originalList,String key,String list) {
+        // 使用 Map 来临时存储合并后的结果,key 为 code,value 为合并后的 Map
+        Map<String, Map<String, Object>> mergedMap = new HashMap<>();
+
+        for (Map<String, Object> item : originalList) {
+            String code = (String) item.get(key);
+            @SuppressWarnings("unchecked")
+            List<Map<String, Object>> details = (List<Map<String, Object>>) item.get(list);
+
+            if (mergedMap.containsKey(code)) {
+                // 如果已存在该 code,只合并 details
+                Map<String, Object> existingItem = mergedMap.get(code);
+                @SuppressWarnings("unchecked")
+                List<Map<String, Object>> existingDetails = (List<Map<String, Object>>) existingItem.get(list);
+                existingDetails.addAll(details);
+            } else {
+                // 如果不存在该 key,保存整个 Map(包括其他 key)
+                // 但需要深拷贝 list,避免后续修改影响原始数据
+                Map<String, Object> newItem = new HashMap<>();
+                for (Map.Entry<String, Object> entry : item.entrySet()) {
+                    if ("details".equals(entry.getKey())) {
+                        // 深拷贝 details 列表
+                        @SuppressWarnings("unchecked")
+                        List<Map<String, Object>> originalDetails = (List<Map<String, Object>>) entry.getValue();
+                        newItem.put(entry.getKey(), new ArrayList<>(originalDetails));
+                    } else {
+                        newItem.put(entry.getKey(), entry.getValue());
+                    }
+                }
+                mergedMap.put(code, newItem);
+            }
+        }
+
+        // 转换回 List
+        return new ArrayList<>(mergedMap.values());
+    }
+
+
+}

+ 8 - 1
mjava-jinlun/src/main/resources/application-dev.yml

@@ -1,5 +1,5 @@
 server:
-  port: 9035
+  port: 9036
   servlet:
     context-path: /jinlun
 
@@ -21,6 +21,13 @@ dingtalk:
   token:
   operator: 344749020127590108
 
+# teambition
+teambition:
+  AppID: 68ef594a7e7b5487e864f1ca
+  AppSecret: cOHex1jvPDLucx1KHDzAcG34rUdpInSg
+  TenantId: 61e7fd84ba45dcd4761d31f5
+  OperatorId: 68b7ec4b03fae569a6cfdbfd   # TBManager
+
 #云枢
 cloudpivot:
   grant_type: client_credentials

+ 18 - 7
mjava-jinlun/src/main/resources/application-prod.yml

@@ -1,15 +1,15 @@
 server:
-  port: 9035
+  port: 9036
   servlet:
     context-path: /jinlun
 
 enable:
-  scheduling: false
+  scheduling: true
 logging:
   config: classpath:logback-spring.xml
-  path: d:\\jinlun_cloudpure\logs\
+  path: /home/server/jinlun/logs/
   level:
-    com.malk.*: INFO
+    com.malk.*: info
 
 # dingtalk
 dingtalk:
@@ -21,9 +21,20 @@ dingtalk:
   token:
   operator: 344749020127590108
 
-aliwork:
-  appType: APP_XPPVVMG6HA0GNDPJV4C1
-  systemToken: 8R7668D1P92RSNTS7OKZG5UR9P333QA7GAJ4MTG
+# teambition
+teambition:
+  AppID: 68ef594a7e7b5487e864f1ca
+  AppSecret: cOHex1jvPDLucx1KHDzAcG34rUdpInSg
+  TenantId: 61e7fd84ba45dcd4761d31f5
+  OperatorId: 68b7ec4b03fae569a6cfdbfd   # TBManager
+
+#云枢
+cloudpivot:
+  grant_type: client_credentials
+  client_id: xclient
+  client_secret: 0a417ecce58c31b32364ce19ca8fcd15
+  redirect_uri: http://192.168.0.12/api/
+  operator_user_id: 8ac194c0811240a6b483ebc86aeb9147
 
 kingdee:
   # 第三方系统登录授权的账套ID

+ 21 - 1
mjava-jinlun/src/test/java/com/malk/jinlun/DdTest.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.malk.jinlun.service.JinlunService;
+import com.malk.jinlun.service.JinlunTaskService;
 import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import com.malk.utils.UtilToken;
@@ -26,11 +27,30 @@ public class DdTest {
     @Autowired
     private JinlunService jinlunService;
 
+    @Autowired
+    private JinlunTaskService jinlunTaskService;
+
     @Test
     public void test2() {
-        jinlunService.syncMaterial();
+        jinlunTaskService.syncMaterial();
+    }
+
+    @Test
+    public void test4() {
+        jinlunTaskService.syncSaleOut();
+    }
+
+    @Test
+    public void test5() {
+        jinlunTaskService.syncReceipt();
+    }
+
+    @Test
+    public void test6() {
+        jinlunTaskService.syncReceivable();
     }
 
+
     @Test
     public void test3() {
         testGetAccessToken();