瀏覽代碼

Merge remote-tracking branch 'origin/master'

“lqy 1 月之前
父節點
當前提交
1d739ef7cf
共有 74 個文件被更改,包括 6337 次插入1227 次删除
  1. 3 2
      mjava-boyang/src/main/java/com/malk/boyang/service/impl/BoyangServiceImpl.java
  2. 4 0
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/HeiHuOrderService.java
  3. 867 301
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java
  4. 84 0
      mjava-heshu/pom.xml
  5. 17 0
      mjava-heshu/src/main/java/com/malk/heshu/HeShuApplication.java
  6. 24 0
      mjava-heshu/src/main/java/com/malk/heshu/config/KDWebApiConf.java
  7. 34 0
      mjava-heshu/src/main/java/com/malk/heshu/config/KDWebApiConfig.java
  8. 254 0
      mjava-heshu/src/main/java/com/malk/heshu/controller/HeShuController.java
  9. 18 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/BillQuery.java
  10. 26 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/ContactInfo.java
  11. 189 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/CustomerInfo.java
  12. 40 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/FBillHead.java
  13. 15 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/FNumber.java
  14. 18 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/IdObject.java
  15. 7 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/Model.java
  16. 215 0
      mjava-heshu/src/main/java/com/malk/heshu/entity/SupplierEntity.java
  17. 54 0
      mjava-heshu/src/main/java/com/malk/heshu/schedule/XiDingTask.java
  18. 45 0
      mjava-heshu/src/main/resources/application-dev.yml
  19. 45 0
      mjava-heshu/src/main/resources/application-prod.yml
  20. 15 0
      mjava-heshu/src/main/resources/application.yml
  21. 61 0
      mjava-heshu/src/main/resources/logback-spring.xml
  22. 320 0
      mjava-heshu/src/test/java/com/malk/heshu/JdTest.java
  23. 7 6
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/EqbServiceImpl.java
  24. 1 1
      mjava-huagao/src/test/java/com/malk/huagao/EqbTest.java
  25. 14 0
      mjava-jinlun/src/main/java/com/malk/jinlun/schedule/JinlunTask.java
  26. 4 1
      mjava-jinlun/src/main/java/com/malk/jinlun/service/CpClient.java
  27. 6 0
      mjava-jinlun/src/main/java/com/malk/jinlun/service/JinlunTaskService.java
  28. 41 1
      mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/CpClientImpl.java
  29. 393 12
      mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunTaskServiceImpl.java
  30. 2 2
      mjava-jinlun/src/main/resources/application-dev.yml
  31. 2 2
      mjava-jinlun/src/main/resources/application-prod.yml
  32. 9 0
      mjava-jinlun/src/test/java/com/malk/jinlun/DdTest.java
  33. 26 0
      mjava-kabeiyi/pom.xml
  34. 35 0
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/controller/KabeiyiController.java
  35. 5 0
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/KabeiyiService.java
  36. 612 393
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/impl/KabeiyiServiceImpl.java
  37. 37 0
      mjava-kabeiyi/src/main/resources/application-dev.yml
  38. 14 0
      mjava-kabeiyi/src/main/resources/application-prod.yml
  39. 1 1
      mjava-kabeiyi/src/main/resources/application.yml
  40. 5 5
      mjava-lingmingguangzi/src/main/java/com/malk/lingmingguangzi/service/LingmingguangziServiceImpl.java
  41. 1 1
      mjava-lingmingguangzi/src/main/resources/application.yml
  42. 5 1
      mjava-ounuo/src/main/java/com/malk/tuosi/entity/PersonalMonthlySuccessrate.java
  43. 504 183
      mjava-ounuo/src/main/java/com/malk/tuosi/schedule/ScheduleTask.java
  44. 6 3
      mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/TbServiceImpl.java
  45. 1 1
      mjava-ounuo/src/main/resources/application.yml
  46. 65 9
      mjava-siku/src/main/java/com/malk/siku/controller/SikuController.java
  47. 30 0
      mjava-siku/src/main/java/com/malk/siku/schedule/SikuTask.java
  48. 12 0
      mjava-siku/src/main/java/com/malk/siku/service/SikuService.java
  49. 6 0
      mjava-siku/src/main/java/com/malk/siku/service/SikuTaskService.java
  50. 930 137
      mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java
  51. 215 0
      mjava-siku/src/main/java/com/malk/siku/service/impl/SikuTaskServiceImpl.java
  52. 95 7
      mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java
  53. 48 7
      mjava-siku/src/main/java/com/malk/siku/utils/MkYpUtil.java
  54. 178 0
      mjava-siku/src/main/java/com/malk/siku/utils/QyddUtil.java
  55. 0 8
      mjava-siku/src/main/resources/application-dev.yml
  56. 1 9
      mjava-siku/src/main/resources/application-prod.yml
  57. 129 1
      mjava-siku/src/test/java/com.malk.siku/SkTest.java
  58. 0 1
      mjava-tonglibo/pom.xml
  59. 37 22
      mjava-tonglibo/src/main/java/com/malk/tonglibo/controller/machineController.java
  60. 7 0
      mjava-tonglibo/src/main/java/com/malk/tonglibo/entity/MachineData.java
  61. 5 4
      mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/ChangeDetector.java
  62. 81 31
      mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/DeviceDataPersistTask.java
  63. 5 4
      mjava-tonglibo/src/main/resources/application-dev.yml
  64. 4 4
      mjava-tonglibo/src/main/resources/application-prod.yml
  65. 27 23
      mjava-tonglibo/src/main/resources/mapper/MachineDataMapper.xml
  66. 14 5
      mjava-zhiwei/src/main/java/com/malk/zhiwei/schedule/ScheduleTask.java
  67. 3 0
      mjava-zhiwei/src/main/java/com/malk/zhiwei/service/ZwService.java
  68. 99 3
      mjava-zhiwei/src/main/java/com/malk/zhiwei/service/impl/ZwServiceImpl.java
  69. 3 3
      mjava-zhiwei/src/main/resources/application-prod.yml
  70. 13 1
      mjava-zhiwei/src/test/java/com/malk/zhiwei/JdTest.java
  71. 6 0
      mjava-zhongche/src/main/java/com/malk/zhongche/controller/ZhongcheController.java
  72. 4 0
      mjava-zhongche/src/main/java/com/malk/zhongche/service/ZhongcheService.java
  73. 215 32
      mjava-zhongche/src/main/java/com/malk/zhongche/service/impl/ZhongcheServiceImpl.java
  74. 19 0
      mjava-zhongche/src/test/java/com/malk/zhongche/ZcTest.java

+ 3 - 2
mjava-boyang/src/main/java/com/malk/boyang/service/impl/BoyangServiceImpl.java

@@ -120,8 +120,9 @@ public class BoyangServiceImpl implements BoyangService {
                 case "TextField-K2AD4O5B"://文件名称
                     subject = UtilMap.getString(formComponentValue, "value");
 
-                    //将subject里的"/"替换为","
-                    subject = subject.replaceAll("/",",");
+                    //不支持: $\/:*?"<>|
+                    subject = subject.replaceAll("[$/:*?\"<>]"," ");
+
                     break;
                 case "DDSelectField_RIHDKAA2UK00"://文件类型
                     String fileType = UtilMap.getString(formComponentValue, "value");

+ 4 - 0
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/HeiHuOrderService.java

@@ -4,6 +4,7 @@ package com.malk.fenggefushi.service;
 import com.fasterxml.jackson.core.JacksonException;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.malk.server.common.McR;
+import lombok.SneakyThrows;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
@@ -45,6 +46,9 @@ public interface HeiHuOrderService {
     /*采购订单定时同步*/
     McR purchaseSchedule(List<Map<String, Object>> dataList) throws JacksonException;
 
+    @SneakyThrows
+    McR purchaseScheduleTest(List<Map<String, Object>> dataList);
+
     List<Map<String, Object>> queryAllPurchase();
 
     McR purchaseUpdateSchedule() throws JacksonException;

文件差異過大導致無法顯示
+ 867 - 301
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java


+ 84 - 0
mjava-heshu/pom.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.7.18</version> <!-- 使用最新的稳定版或其他适用版本 -->
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.malk.heshu</groupId>
+    <artifactId>mjava-heshu</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.malk</groupId>
+            <artifactId>base</artifactId>
+            <version>1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.example</groupId>
+            <artifactId>k3cloud</artifactId>
+            <version>8.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.example</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>heshu</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <executable>true</executable>
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 17 - 0
mjava-heshu/src/main/java/com/malk/heshu/HeShuApplication.java

@@ -0,0 +1,17 @@
+package com.malk.heshu;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication(scanBasePackages = {"com.malk"})
+@EnableScheduling
+public class HeShuApplication {
+    public static void main(String[] args) {
+        try {
+            SpringApplication.run(HeShuApplication.class,args);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+}

+ 24 - 0
mjava-heshu/src/main/java/com/malk/heshu/config/KDWebApiConf.java

@@ -0,0 +1,24 @@
+package com.malk.heshu.config;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "kingdee")
+@Slf4j
+public class KDWebApiConf {
+
+    private String XKDApiAcctID;
+
+    private String XKDApiUserName;
+
+    private String XKDApiAppID;
+
+    private String XKDApiAppSec;
+
+    private String XKDApiServerUrl;
+
+}

+ 34 - 0
mjava-heshu/src/main/java/com/malk/heshu/config/KDWebApiConfig.java

@@ -0,0 +1,34 @@
+package com.malk.heshu.config;
+
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class KDWebApiConfig {
+    private Properties properties = new Properties();
+
+    public KDWebApiConfig(String filePath) throws IOException {
+        try (FileInputStream input = new FileInputStream(filePath)) {
+            properties.load(input);
+        }
+    }
+
+    public String getProperty(String key) {
+        return properties.getProperty(key);
+    }
+
+//    public static void main(String[] args) {
+//        try {
+//            KDWebApiConfig config = new KDWebApiConfig("mjava-jinlun/src/main/resources/application-dev.yml");
+//            System.out.println("AcctID: " + config.getProperty("X-KDApi-AcctID"));
+//            // 打印其他属性...
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+
+
+}

+ 254 - 0
mjava-heshu/src/main/java/com/malk/heshu/controller/HeShuController.java

@@ -0,0 +1,254 @@
+package com.malk.heshu.controller;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.entity.RepoRet;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
+import com.malk.heshu.entity.*;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.utils.PublicUtil;
+import com.malk.utils.UtilMap;
+import com.malk.heshu.config.KDWebApiConf;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.fail;
+
+@RestController
+@Slf4j
+public class HeShuController {
+
+    @Autowired
+    private KDWebApiConf kdWebApiConf;
+    @Autowired
+    private YDClient ydClient;
+
+    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;
+    }
+    @GetMapping("/test")
+    public McR test(){
+        return McR.success("111");
+    }
+
+    @PostMapping("/saveSupplier")
+    public McR saveSupplier(@RequestBody JSONObject params){
+        log.info("saveSupplier:{}",params);
+        if(PublicUtil.isNull(params,"fid")){
+            return McR.error("201","缺少参数!");
+        }
+        try {
+            Thread.sleep(500);// 休眠5s避免同时更新一条数据
+            Map formData= (Map) ydClient.queryData(YDParam.builder().formInstId(params.getString("fid")).build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+            if(formData==null){
+                return McR.error("201","未查询到数据!");
+            }
+            List<String> types=UtilMap.getList(formData,"checkboxField_mma72l0x");
+            String gysType;
+            if(types.contains("供应商")){
+                gysType="01";
+            }else {
+                gysType="03";
+            }
+            SupplierEntity supplierEntity = BeanUtil.toBean(formData, SupplierEntity.class);
+            SupplierEntity.FBaseInfo fBaseInfo = BeanUtil.toBean(formData, SupplierEntity.FBaseInfo.class);
+            SupplierEntity.FFinanceInfo fFinanceInfo = BeanUtil.toBean(formData, SupplierEntity.FFinanceInfo.class);
+            List<Map> list=UtilMap.getList(formData,"tableField_mma72l0q");
+            List<SupplierEntity.FBankInfo> bkList=new ArrayList<>();
+            for(Map map:list){
+                SupplierEntity.FBankInfo  fBankInfo = BeanUtil.toBean(map, SupplierEntity.FBankInfo.class);
+                bkList.add(fBankInfo);
+            }
+            fBaseInfo.setFDeptId(new IdObject(UtilMap.getString(formData,"textField_mogukmdd")));// 业务部门
+            supplierEntity.setFBaseInfo(fBaseInfo);
+            supplierEntity.setFFinanceInfo(fFinanceInfo);
+            supplierEntity.setFBankInfo(bkList);
+            List<Map> list2=UtilMap.getList(formData,"tableField_mma72kx1");
+            List<SupplierEntity.FSupplierContact> lxrList=new ArrayList<>();
+            for(Map map:list2){
+                SupplierEntity.FSupplierContact  lxrInfo = BeanUtil.toBean(map, SupplierEntity.FSupplierContact.class);
+                lxrList.add(lxrInfo);
+            }
+            supplierEntity.setFSupplierContact(lxrList);
+            supplierEntity.setFGroup(new IdObject(gysType));
+            supplierEntity.setF_UNW_yida("https://garktl.aliwork.com/APP_QM42OEGLMNNGBLIJELJI/processDetail?formUuid=FORM-9C0EC03227CC49738447A27B4563779F0WLW&procInsId="+params.getString("fid"));
+            String operator=UtilMap.getString(formData,"radioField_mma72l0t");// 操作类型 客商准入  客商更新
+            if(operator.equals("客商更新")){
+                String fId=UtilMap.getString(formData,"textField_moi1ejl2");
+                if(!PublicUtil.isNull(fId)){
+                    // 反审核
+                    unAudit("BD_Supplier",fId);
+                    supplierEntity.setFSupplierId(Integer.parseInt(fId));
+                }
+            }
+            return  saveToAudit("BD_Supplier",supplierEntity,params.getString("fid"),params.getString("key"),"selectField_mogukmd9","textareaField_mogukmdb","textField_moi1ejl2",null);
+        }catch (Exception e){
+            return McR.error("201",e.getMessage());
+        }
+    }
+
+    @PostMapping("/saveCust")
+    public McR saveCust(@RequestBody JSONObject params){
+        log.info("saveCust:{}",params);
+        if(PublicUtil.isNull(params,"fid")){
+            return McR.error("201","缺少参数!");
+        }
+        try {
+            Map formData= (Map) ydClient.queryData(YDParam.builder().formInstId(params.getString("fid")).build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+            if(formData==null){
+                return McR.error("201","未查询到数据!");
+            }
+            CustomerInfo customerInfo = BeanUtil.toBean(formData, CustomerInfo.class);
+            List<Map> list=UtilMap.getList(formData,"tableField_mma72l0q");
+            List<CustomerInfo.CustBank> bkList=new ArrayList<>();
+            for(Map map:list){
+                CustomerInfo.CustBank  fBankInfo = BeanUtil.toBean(map, CustomerInfo.CustBank.class);
+                bkList.add(fBankInfo);
+            }
+            customerInfo.setFT_BD_CUSTBANK(bkList);
+            List<Map> list2=UtilMap.getList(formData,"tableField_mma72kx1");
+            List<ContactInfo> lxrList=new ArrayList<>();
+            for(Map map:list2){
+                ContactInfo contactInfo=new ContactInfo();
+                contactInfo.setFName(UtilMap.getString(map,"textField_mma72kx2"));
+                contactInfo.setFMobile(UtilMap.getString(map,"textField_mma72kx3"));
+                contactInfo.setFCompanyType("BD_Customer");
+                contactInfo.setFBizLocation(UtilMap.getString(map,"textField_mogukmdi"));
+                contactInfo.setFBizAddress(UtilMap.getString(map,"textField_mogukmdi"));
+                lxrList.add(contactInfo);
+            }
+            customerInfo.setFSALDEPTID(new FNumber(UtilMap.getString(formData,"textField_mogukmdd")));// 业务部门
+            String custTypeValue=UtilMap.getString(formData,"radioField_mma72kxi");
+            String custType;
+            if(custTypeValue.equals("贸易商")){
+                custType="02";
+            }else if(custTypeValue.equals("工厂")){
+                custType="01";
+            }else {
+                custType="05";
+            }
+            customerInfo.setFGroup(new FNumber(custType));
+            String operator=UtilMap.getString(formData,"radioField_mma72l0t");// 操作类型 客商准入  客商更新
+            if(operator.equals("客商更新")){
+                String fId=UtilMap.getString(formData,"textField_moi1ejl1");
+                if(!PublicUtil.isNull(fId)){
+                    // 反审核
+                    unAudit("BD_Customer",fId);
+                    customerInfo.setFCUSTID(Integer.parseInt(fId));
+                }
+            }
+            return  saveToAudit("BD_Customer",customerInfo,params.getString("fid"),params.getString("key"),"selectField_mogukmd8","textareaField_mogukmda","textField_moi1ejl1",lxrList);
+        }catch (Exception e){
+            return McR.error("201",e.getMessage());
+        }
+    }
+
+
+    private McR saveToAudit(String formid, Object object,String fid,String codeKey,String statusKey,String msgKey,String idKey,List<ContactInfo> lxrList) throws Exception {
+        JSONObject resultObj = new JSONObject();
+        K3CloudApi client = new K3CloudApi(initIden());
+        String result=client.save(formid,JSONObject.toJSONString(UtilMap.map("Model",object)));
+        resultObj.put("save",result);
+        Gson gson = new Gson();
+        RepoRet sRet = gson.fromJson(result, RepoRet.class);
+        JSONObject reObj = JSONObject.parseObject(result,JSONObject.class);
+        if (sRet.isSuccessfully()) {
+            if(!PublicUtil.isNull(codeKey)){
+                // 回写信息
+                Map updateMap=UtilMap.map(codeKey,reObj.getJSONObject("Result").getString("Number"));
+                updateMap.put(statusKey,"成功");
+                updateMap.put(idKey,reObj.getJSONObject("Result").getString("Id"));// ID 内码
+                ydClient.operateData(YDParam.builder().formInstId(fid).updateFormDataJson(
+                        JSONObject.toJSONString(updateMap)
+                ).build(), YDConf.FORM_OPERATION.update);
+            }
+            if(lxrList!=null){
+                for (ContactInfo contactInfo : lxrList) {
+                    contactInfo.setFCompany(new FNumber(reObj.getJSONObject("Result").getString("Number")));
+                    String data=new Gson().toJson(contactInfo);
+                    String id=saveToAudit("BD_CommonContact",new Gson().fromJson(data,Object.class));
+                }
+            }
+            JsonObject jsonData = new JsonObject();
+            jsonData.addProperty("Ids", sRet.getResult().getId());
+            String result2=client.submit(formid, jsonData.toString());
+            resultObj.put("submit",result2);
+            RepoRet sRet2 = gson.fromJson(result, RepoRet.class);
+            if (sRet2.isSuccessfully()) {
+                JsonObject jsonData3 = new JsonObject();
+                jsonData3.addProperty("Ids", sRet2.getResult().getId());
+                String result3 = client.audit(formid, jsonData3.toString());
+                resultObj.put("audit",result3);
+                RepoRet repoRet3 = gson.fromJson(result3, RepoRet.class);
+                if (repoRet3.getResult().getResponseStatus().isIsSuccess()) {
+                    log.info("审批通过,新增完成");
+                    return McR.success(resultObj);
+//                    Map map=UtilMap.map("PkIds, TOrgIds",sRet.getResult().getId(),"1,105818,105822,127834,127835,127838,127843,127846,127847,127848,127850,127862,1370321,1325841,1327202,1646858");
+//                    String result4=client.allocate("formid",JSONObject.toJSONString(map));
+//                    resultObj.put("allocate",result4);
+//                    RepoRet repoRet4 = gson.fromJson(result4, RepoRet.class);
+//                    if (repoRet4.getResult().getResponseStatus().isIsSuccess()) {
+//                        log.info("分配完成");
+//                        return McR.success(resultObj);
+//                    }
+                }
+            }
+        }else {
+            log.info("保存失败:{}",result);
+            Map updateMap=UtilMap.map(statusKey,"失败");
+            updateMap.put(msgKey,result);
+            ydClient.operateData(YDParam.builder().formInstId(fid).updateFormDataJson(
+                    JSONObject.toJSONString(updateMap)
+            ).build(), YDConf.FORM_OPERATION.update);
+        }
+        return McR.error("203",JSONObject.toJSONString(resultObj));
+    }
+    private String saveToAudit(String formid, Object object) throws Exception {
+        K3CloudApi client = new K3CloudApi(initIden());
+        String result=client.save(formid,JSONObject.toJSONString(UtilMap.map("Model",object)));
+        System.out.println(result);
+        Gson gson = new Gson();
+        RepoRet sRet = gson.fromJson(result, RepoRet.class);
+        JSONObject reObj = JSONObject.parseObject(result,JSONObject.class);
+        if (sRet.isSuccessfully()) {
+            return reObj.getJSONObject("Result").getString("Id");
+        }else {
+            return "";
+        }
+    }
+    private void unAudit(String formid,String fNumber) throws Exception {
+        K3CloudApi client = new K3CloudApi(initIden());
+        Gson gson = new Gson();
+        JsonObject jsonData = new JsonObject();
+        jsonData.addProperty("Ids", fNumber);
+        String result=client.unAudit(formid, jsonData.toString());
+        RepoRet sRet2 = gson.fromJson(result, RepoRet.class);
+        if (!sRet2.isSuccessfully()) {
+            log.info("反审核失败:{}",result);
+        }
+    }
+}

+ 18 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/BillQuery.java

@@ -0,0 +1,18 @@
+package com.malk.heshu.entity;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class BillQuery {
+    private String FormId;
+    private String FieldKeys;
+    private List<Map> FilterString;
+    private String OrderString;
+    private int TopRowCount;
+    private int StartRow;
+    private int Limit;
+    private String SubSystemId;
+}

+ 26 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/ContactInfo.java

@@ -0,0 +1,26 @@
+package com.malk.heshu.entity;
+
+import lombok.Data;
+
+@Data
+public class ContactInfo {
+
+    private Integer FCONTACTID; //实体主键
+    private String FNumber; //编码
+    private String FName; //姓名 (必填项)
+    private FNumber Fex; //性别
+    private String FPost; //职务
+    private String FCompanyType; //类型 (必填项)
+    private FNumber FCompany; //所属公司
+    private String FTel; //固定电话
+    private String FMobile; //移动电话
+    private String FFax; //传真
+    private String FEmail; //邮箱
+    private String FBizAddress; //详细地址
+    private String FBizLocation; //地点名称
+    private String FBizLocNumber; //地点编码
+    private String FIsDefaultContact; //默认联系人
+    private String FIsDefaultConsignee; //默认收货地址
+    private String FForbidDate; //禁用日期
+    private FNumber FCustId; //客户编码
+}

+ 189 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/CustomerInfo.java

@@ -0,0 +1,189 @@
+package com.malk.heshu.entity;
+
+import cn.hutool.core.annotation.Alias;
+import lombok.Data;
+import java.util.List;
+
+/**
+ * 客户信息实体类
+ */
+@Data
+public class CustomerInfo {
+    
+    private Integer FCUSTID;                // 主键-客户ID
+    private FNumber FCreateOrgId = new FNumber("000");      // 创建组织(必填)
+    private String FNumber;                 // 客户编码
+    private FNumber FUseOrgId = new FNumber("000");;         // 使用组织
+    @Alias("textField_mma6vp7o")
+    private String FName;                   // 客户名称(必填)
+    private String FShortName;              // 简称
+    private FNumber FCOUNTRY;          // 国家
+    private FNumber FPROVINCIAL;       // 地区
+    private String FADDRESS;                // 通讯地址
+    private String FZIP;                    // 邮政编码
+    private String FWEBSITE;                // 公司网址
+    private String FTEL;                    // 联系电话
+    private String FFAX;                    // 传真
+    private FNumber FCompanyClassify;  // 公司类别
+    private FNumber FCompanyNature;    // 公司性质
+    private FNumber FCompanyScale;     // 公司规模
+    private String FINVOICETITLE;           // 发票抬头
+    @Alias("textField_mma6vp85")
+    private String FTAXREGISTERCODE;        // 纳税登记号
+    @Alias("textField_mma72kwv")
+    private String FINVOICEBANKNAME;        // 开户银行
+    private String FINVOICETEL;             // 开票联系电话
+    @Alias("textField_mma72kww")
+    private String FINVOICEBANKACCOUNT;     // 银行账号
+    private String FINVOICEADDRESS;         // 开票通讯地址
+    private FNumber FSUPPLIERID;       // 对应供应商
+    private String FIsGroup;                // 集团客户
+    private String FIsDefPayer;             // 默认付款方
+    private FNumber FCustTypeId;       // 客户类别
+    private FNumber FGROUPCUSTID;      // 对应集团客户
+
+    @Alias("textField_mma72kww")
+    private FNumber FGroup;            // 客户分组
+    private FNumber FTRADINGCURRID;    // 结算币别(必填)
+    private FNumber FCorrespondOrgId;  // 对应组织
+    private String FDescription;            // 备注
+    private FNumber FSALDEPTID;        // 销售部门
+    private FNumber FSELLER;           // 销售员
+    private FNumber FSETTLETYPEID;     // 结算方式
+    private FNumber FRECCONDITIONID;   // 收款条件
+    private FNumber FDISCOUNTLISTID;   // 折扣表
+    private FNumber FPRICELISTID;      // 价目表
+    private Integer FTRANSLEADTIME;         // 运输提前期
+    private String FInvoiceType;            // 发票类型
+    private FNumber FTaxType;          // 税分类
+    private FNumber FRECEIVECURRID;    // 收款币别
+    private Integer FPriority;               // 客户优先级
+    private FNumber FTaxRate;          // 默认税率
+    private String FISCREDITCHECK;          // 启用信用管理
+    private String FIsTrade;                // 是否交易客户
+    private String F_JX_Combo;              // 是否信用客户(必填)
+    private String FUncheckExpectQty;       // 不校验可发量
+    @Alias("textField_mma6vp7v")
+    private String FLegalPerson;             // 法人代表
+    @Alias("numberField_mma6vp83")
+    private String FRegisterFund;           // 注册资本
+    @Alias("dateField_mma6vp7w")
+    private String FFoundDate;               // 创立日期
+    private String FDomains;                 // 行业
+    @Alias("textField_mma6vp85")
+    private String FSOCIALCRECODE;           // 统一社会信用代码
+    @Alias("textField_mma6vp7p")
+    private String FRegisterAddress;         // 注册地址
+    @Alias("textField_mogukmd2")
+    private String F_UNW_Remark_apv;           // 开票要求
+    private String F_UNW_Text_kpyx;          // 开票电子邮箱
+
+    private CustomerExt FT_BD_CUSTOMEREXT;   // 商务信息
+    private List<CustLocation> FT_BD_CUSTLOCATION;   // 联系人
+    private List<CustBank> FT_BD_CUSTBANK;           // 银行信息
+    private List<CustContact> FT_BD_CUSTCONTACT;     // 地址信息
+    private List<CustOrderOrg> FT_BD_CUSTORDERORG;   // 订货组织
+    private List<CustSubAccount> FT_BD_CUSTSUBACCOUNT; // 子账户信息
+
+
+    // 用户ID字段结构
+    @Data
+    public static class FUserIdField {
+        private String FUserID;
+    }
+    
+    // 商务信息扩展
+    @Data
+    public static class CustomerExt {
+        private Integer FEntryId;                // 主键
+        private String FEnableSL;                // 启用商联在线
+        private String FFreezeLimit;             // 冻结范围
+        private FUserIdField FFreezeOperator;    // 冻结人
+        private String FFreezeDate;              // 冻结日期
+        private FNumber FPROVINCE;          // 省份
+        private FNumber FCITY;              // 城市
+        private FNumber FDefaultConsiLoc;   // 默认收货地点
+        private FNumber FDefaultSettleLoc;  // 默认开票地点
+        private FNumber FDefaultPayerLoc;   // 默认付款地点
+        private FNumber FDefaultContact;    // 默认联系人
+        private Integer FMarginLevel;             // 保证金比例
+        private String FDebitCard;               // 结算卡
+        private FNumber FSettleId;          // 结算方
+        private FNumber FChargeId;          // 付款方
+        private String FALLOWJOINZHJ;             // 允许对接智慧订货
+        private FNumber FStarOrgId;         // 星辰组织
+    }
+    
+    // 联系人信息
+    @Data
+    public static class CustLocation {
+        private FNumber FContactId;         // 联系人编码
+        private String FIsDefaultConsigneeCT;    // 默认收货地址
+        private String FIsCopy;                  // 是否复制
+    }
+    
+    // 银行信息
+    @Data
+    public static class CustBank {
+        private Integer FENTRYID;                // 主键
+        private FNumber FCOUNTRY1;          // 开户国家
+        @Alias("textField_mma72kwy")
+        private String FBANKCODE;                // 银行账号
+        @Alias("textField_mogukmd1")
+        private String FACCOUNTNAME;             // 账户名称
+        private FNumber FBankTypeRec;       // 收款银行
+        private String FTextBankDetail;          // 网点名称
+        private FNumber FBankDetail;        // 银行网点
+        private String FOpenAddressRec;          // 开户行地址
+        @Alias("textField_mma72kwx")
+        private String FOPENBANKNAME;            // 开户银行
+        private String FCNAPS;                   // 联行号
+        private FNumber FCURRENCYID;        // 币别
+        private String FISDEFAULT1;              // 默认
+    }
+    
+    // 地址信息
+    @Data
+    public static class CustContact {
+        private Integer FENTRYID;                // 主键
+        private String FNUMBER1;                 // 交货地点编码
+        @Alias("textField_mogukmdi")
+        private String FNAME1;                   // 交货地点
+        @Alias("textField_mogukmdi")
+        private String FADDRESS1;                // 详细地址
+//        @Alias("textField_mogukmdf")
+        private FNAME FTContact;               // 联系人
+        @Alias("textField_mogukmdg")
+        private String FMOBILE;                  // 移动电话
+        private Integer FTRANSLEADTIME1;         // 运输提前期
+        private String FIsDefaultConsignee;      // 默认收货地址
+        private String FIsDefaultSettle;         // 默认开票地址
+        private String FIsDefaultPayer;          // 默认付款地址
+        private String FIsUsed;                  // 启用
+    }
+
+    @Data
+    public static class FNAME {
+        private String FNAME;
+        public FNAME(String FNAME) {
+            this.FNAME = FNAME;
+        }
+        public FNAME() {}
+    }
+    
+    // 订货组织
+    @Data
+    public static class CustOrderOrg {
+        private Integer FEntryID;                // 主键
+        private FNumber FOrderOrgId;        // 订货组织
+        private String FIsDefaultOrderOrg;       // 默认
+    }
+    
+    // 子账户信息
+    @Data
+    public static class CustSubAccount {
+        private Integer FEntryID;                // 主键
+        private String FSUBACCOUNTTYPE;          // 子账户类型
+        private String FSUBACCOUNT;              // 子账户号
+    }
+}

+ 40 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/FBillHead.java

@@ -0,0 +1,40 @@
+package com.malk.heshu.entity;
+
+import com.malk.utils.UtilMap;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class FBillHead extends Model{
+    private String FID;//实体主键
+    private String FDocumentStatus;//数据状态
+    private String FForbidStatus;//禁用状态
+    private String FName;//名称 (必填项)
+    private String FNumber;//编码
+    private String FDescription;//描述
+    private Map<String,String> FCreateOrgId;//创建组织 (必填项)
+    private Map<String,String> FUseOrgId;//使用组织 (必填项)
+    private String FCreatorId;//创建人
+    private String FModifierId;//修改人
+    private String FCreateDate;//创建日期
+    private String FModifyDate;//修改日期
+    private Map<String,String> F_ABC_Assistant;//项目类型 (必填项)
+    private String F_VPOX_Text;//CRM编号
+
+    public void setFCreateOrgId(String fCreateOrgId){
+        this.FCreateOrgId = UtilMap.map("FNumber",fCreateOrgId);
+    }
+    public void setFUseOrgId(String fUseOrgId){
+        this.FUseOrgId = UtilMap.map("FNumber",fUseOrgId);
+    }
+    public FBillHead(String FName,String FNumber,String type){
+        this.FUseOrgId = UtilMap.map("FNumber","100");
+        this.FCreateOrgId = UtilMap.map("FNumber","100");
+        this.FName=FName;
+        this.FNumber=FNumber;
+        this.F_ABC_Assistant = UtilMap.map("FNumber",type);
+    }
+    public FBillHead(){}
+}

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

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

+ 18 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/IdObject.java

@@ -0,0 +1,18 @@
+package com.malk.heshu.entity;
+
+import lombok.Data;
+
+/**
+ * ID对象,用于存储带有编码或用户ID的对象
+ */
+@Data
+public class IdObject {
+    private String FNumber;      // 编码
+    private String FUserID;      // 用户ID
+    private String FNUMBER;      // 编码(大写形式)
+
+    public IdObject(String FNumber) {
+        this.FNumber = FNumber;
+    }
+    public IdObject(){};
+}

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

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

+ 215 - 0
mjava-heshu/src/main/java/com/malk/heshu/entity/SupplierEntity.java

@@ -0,0 +1,215 @@
+package com.malk.heshu.entity;
+
+import cn.hutool.core.annotation.Alias;
+import lombok.Data;
+import java.util.List;
+
+/**
+ * 供应商实体类
+ */
+@Data
+public class SupplierEntity {
+
+    // 单据头字段
+    private Integer FSupplierId;           // 实体主键
+    private String FDocumentStatus;        // 数据状态
+    private String FForbidStatus;          // 禁用状态
+    @Alias("textField_mma6vp7o")
+    private String FName;                  // 名称(必填项)
+    private String FNumber;                // 编码
+    private String FDescription;           // 描述
+    private IdObject FCreateOrgId = new IdObject("000");         // 创建组织(必填项)
+    private IdObject FUseOrgId = new IdObject("000");            // 使用组织(必填项)
+    private IdObject FCreatorId;           // 创建人
+    private IdObject FModifierId;          // 修改人
+    private String FCreateDate;            // 创建日期
+    private String FModifyDate;            // 修改日期
+    private String FShortName;             // 简称
+    private IdObject FForbiderId;          // 禁用人
+    private String FForbidDate;            // 禁用日期
+    private String FAuditDate;             // 审核日期
+    private IdObject FAuditorId;            // 审核人
+    private IdObject FGroup;               // 供应商分组
+    private IdObject FCorrespondOrgId;      // 对应组织
+    private String FSYNCGYOWNERSTATUS;      // 同步货主状态(GY)
+    private String FRegNumber;              // 注册编码
+    private IdObject FGROUPSUPPLYID;        // 对应集团供应商
+    private String FISGROUP;                // 集团供应商
+    private String F_UNW_yida;              // 宜搭审批连接
+
+    public SupplierEntity() {}
+
+    // 基本信息
+    private FBaseInfo FBaseInfo;
+
+    // 商务信息
+    private FBusinessInfo FBusinessInfo;
+
+    // 财务信息
+    private FFinanceInfo FFinanceInfo;
+
+    // 银行信息
+    private List<FBankInfo> FBankInfo;
+
+    // 组织信息
+    private List<FLocationInfo> FLocationInfo;
+
+    // 联系人
+    private List<FSupplierContact> FSupplierContact;
+
+    /**
+     * 基本信息
+     */
+    @Data
+    public static class FBaseInfo {
+        private Integer FEntryId;                 // 实体主键
+        private IdObject FCountry;                // 国家
+        private IdObject FProvincial;             // 地区
+        private String FAddress;                  // 通讯地址
+        private String FZip;                      // 邮政编码
+        private IdObject FLanguage;               // 语言
+        private String FWebSite;                  // 公司网址
+        private IdObject FTrade;                  // 行业
+        @Alias("dateField_mma6vp7w")
+        private String FFoundDate;                // 创立日期
+        @Alias("textField_mma6vp7v")
+        private String FLegalPerson;              // 法人代表
+        @Alias("numberField_mma6vp83")
+        private Integer FRegisterFund;            // 注册资金(万元)
+        private String FRegisterCode;             // 工商登记号
+        @Alias("textField_mma6vp85")
+        private String FSOCIALCRECODE;            // 统一社会信用代码
+        private String FTendPermit;               // 生产经营许可证
+        @Alias("textField_mma6vp7p")
+        private String FRegisterAddress;          // 注册地址
+        private IdObject FDeptId;                 // 负责部门
+        private IdObject FStaffId;                // 负责人
+        private IdObject FSupplierClassify;       // 供应商分类
+        private String FSupplyClassify;           // 供应类别
+        private IdObject FSupplierGrade;          // 供应商等级
+        private IdObject FCompanyClassify;        // 公司类别
+        private IdObject FCompanyNature;          // 公司性质
+        private IdObject FCompanyScale;           // 公司规模
+        private String FStartDate;                // 生效日期
+        private String FEndDate;                  // 失效日期
+    }
+    
+    /**
+     * 商务信息
+     */
+    @Data
+    public static class FBusinessInfo {
+        private Integer FEntryId;                 // 实体主键
+        private IdObject FPurchaserGroupId;       // 采购组
+        private Integer FMinPOValue;              // 最小订单量
+        private String FNeedConfirm;              // 需要确认
+        private IdObject FParentSupplierId;       // 汇总公司
+        private String FBusinessStatus;           // 业务状态
+        private String FFreezeLimit;              // 冻结范围
+        private IdObject FSettleTypeId;           // 结算方式
+        private IdObject FPRICELISTID;            // 默认价目表
+        private Object FWipStockPlaceId;          // 默认WIP仓位
+        private IdObject FWipStockId;             // 默认WIP仓库
+        private IdObject FDiscountListId;         // 默认折扣表
+        private IdObject FProviderId;             // 供货方
+        private IdObject FFreezeOperator;         // 冻结人
+        private String FFreezeDate;               // 冻结日期
+        private IdObject FVmiStockId;             // VMI仓库
+        private String FVmiBusiness;              // VMI业务
+        private String FEnableSL;                 // 启用供应商协同
+        private Integer FDepositRatio;            // 保证金比例%
+        private String FDefaultContactId;         // 默认联系人
+    }
+    
+    /**
+     * 财务信息
+     */
+    @Data
+    public static class FFinanceInfo {
+        private Integer FEntryId;                 // 实体主键
+        private IdObject FPayCurrencyId;          // 结算币别(必填项)
+        private IdObject FCustomerId;             // 对应客户
+        private Integer FPayAdvanceAmount;        // 单次预付额度
+        @Alias("textField_mma6vp85")
+        private String FTaxRegisterCode;          // 税务登记号
+        private String FTendType;                 // 经营类型
+        private IdObject FTaxType;                // 税分类
+        private String FFinanceDesc;              // 描述
+        private IdObject FPayCondition;           // 付款条件
+        private String FInvoiceType;              // 发票类型
+        private IdObject FSettleId;               // 结算方
+        private IdObject FChargeId;               // 收款方
+        private IdObject FTaxRateId;              // 默认税率
+    }
+    
+    /**
+     * 银行信息
+     */
+    @Data
+    public static class FBankInfo {
+        private Integer FBankId;                  // 实体主键
+        private IdObject FBankCountry;            // 国家
+        @Alias("textField_mma72kwy")
+        private String FBankCode;                 // 银行账号
+        @Alias("textField_mogukmd1")
+        private String FBankHolder;               // 账户名称
+        private String FBankIsDefault;            // 默认
+        private String FBankDesc;                 // 描述
+        private IdObject FBankCurrencyId;         // 币别
+        @Alias("textField_mma72kwx")
+        private String FOpenBankName;             // 开户银行
+        private IdObject FBankTypeRec;            // 收款银行
+        private String FOpenAddressRec;           // 开户行地址
+        private String FCNAPS;                    // 联行号
+        private String FSwiftCode;                // SwiftCode
+        private String FTextBankDetail;           // 网点名称
+        private IdObject FBankDetail;             // 银行网点
+    }
+    
+    /**
+     * 组织信息(地点信息)
+     */
+    @Data
+    public static class FLocationInfo {
+        private Integer FLocationId;              // 实体主键
+        private Integer FTransportDays;           // 运输时间
+        private Integer FPlanDeliveryPeriod;      // 计划交货周期
+        private String FLocDesc;                  // 备注
+        private String FLocNumber;                // 地点编码
+        private String FLocName;                  // 地点名称(必填项)
+        private String FLocAddress;               // 通讯地址(必填项)
+        private String FLocIsUsed;                // 启用
+        private String FLocTel;                   // 电话
+        private String FLocMobile;                // 手机(必填项)
+        private String FLocFax;                   // 传真
+        private String FLocEMail;                 // 电子邮箱
+        private String FIsDefaultSupply;          // 默认供货地址
+        private String FIsDefaultSettle;          // 默认开票地址
+        private String FIsDefaultPayee;           // 默认收款地址
+        private String FLocContact;               // 联系人(旧)
+        private IdObject FLocNewContact;          // 联系人(必填项)
+    }
+    
+    /**
+     * 联系人信息
+     */
+    @Data
+    public static class FSupplierContact {
+        private Integer FContactId;               // 实体主键
+        @Alias("textField_mma72kx2")
+        private String FContact;                  // 联系人
+        private String FPost;                     // 职务
+        @Alias("textField_mma72kx3")
+        private String FTel;                      // 电话
+        private String FMobile;                   // 手机
+        private String FFax;                      // 传真
+        private String FEMail;                    // 电子邮箱
+        private String FIMCode;                   // 即时通讯
+        private String FContactIsDefault;         // 默认联系人
+        private String FContactDescription;       // 备注
+        private String FCommonContactId;          // 供应商联系人
+        private String FContactNumber;            // 编码
+        private String FConForbidStatus;          // 禁用状态
+        private String FGender;                   // 性别
+    }
+}

+ 54 - 0
mjava-heshu/src/main/java/com/malk/heshu/schedule/XiDingTask.java

@@ -0,0 +1,54 @@
+package com.malk.heshu.schedule;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.service.aliwork.YDClient;
+import com.malk.utils.PublicUtil;
+import com.malk.utils.UtilMap;
+import com.malk.heshu.config.KDWebApiConf;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.*;
+
+/**
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"enable.scheduling"})
+public class XiDingTask {
+
+    @Autowired
+    private KDWebApiConf kdWebApiConf;
+
+    @Autowired
+    private YDClient ydClient;
+    @Autowired
+    private YDConf ydConf;
+
+    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;
+    }
+
+}

+ 45 - 0
mjava-heshu/src/main/resources/application-dev.yml

@@ -0,0 +1,45 @@
+server:
+  port: 9000
+  servlet:
+    context-path: /api/heshu
+
+enable:
+  scheduling: true
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/heshu/logs/
+  level:
+    com.malk.*: info
+
+# dingtalk
+dingtalk:
+  agentId: 4424860263
+  appKey: dingwrnq1nh8hoqvtqsr
+  appSecret: EUN7g-sskl5HmUPUhzWxoauTnjGJIHeLs-5W6SkcsH2W_fqGX2O0Hv94mNnVirgf
+  corpId: dingfafe4e9b1128aad035c2f4657eb6378f
+
+# aliwork
+aliwork:
+  appType: APP_QM42OEGLMNNGBLIJELJI
+  systemToken: ZDD66AA1PPG4HEBKPH0TSCZX72QX3O4ZGWFNMZKO
+
+kingdee:
+  # 第三方系统登录授权的账套ID
+  X-KDApi-AcctID: 69b7650beaa43d
+  # 第三方系统登录授权的用户
+  X-KDApi-UserName: Administrator
+  # 第三方系统登录授权的应用ID
+  X-KDApi-AppID: 339218_S41q6zHu4mrb7YWI53TB0a9I1r4Y1rKL
+  # 第三方系统登录授权的应用密钥
+  X-KDApi-AppSec: fae9e4a1820f4e7c839eafebdfa0e4e5
+  # 服务Url地址(公有云统一走网关sdk底层已处理,无需传X-KDApi-ServerUrl,下面这行需要注释)
+  X-KDApi-ServerUrl: http://124.70.8.12/k3cloud/
+  # 账套语系,默认2052
+  # X-KDApi-LCID: 2052
+  # 组织编码,启用多组织时配置对应的组织编码才有效
+  # X-KDApi-OrgNum: 100
+  # 允许的最大连接延时,单位为秒
+  # X-KDApi-ConnectTimeout: 120
+  # 允许的最大读取延时,单位为秒
+  # X-KDApi-RequestTimeout: 120
+

+ 45 - 0
mjava-heshu/src/main/resources/application-prod.yml

@@ -0,0 +1,45 @@
+server:
+  port: 9000
+  servlet:
+    context-path: /api/heshu
+
+enable:
+  scheduling: true
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/heshu/logs/
+  level:
+    com.malk.*: info
+
+# dingtalk
+dingtalk:
+  agentId: 4424860263
+  appKey: dingwrnq1nh8hoqvtqsr
+  appSecret: EUN7g-sskl5HmUPUhzWxoauTnjGJIHeLs-5W6SkcsH2W_fqGX2O0Hv94mNnVirgf
+  corpId: dingfafe4e9b1128aad035c2f4657eb6378f
+
+# aliwork
+aliwork:
+  appType: APP_QM42OEGLMNNGBLIJELJI
+  systemToken: ZDD66AA1PPG4HEBKPH0TSCZX72QX3O4ZGWFNMZKO
+
+kingdee:
+  # 第三方系统登录授权的账套ID
+  X-KDApi-AcctID: 6675a1bf6428ea
+  # 第三方系统登录授权的用户
+  X-KDApi-UserName: Administrator
+  # 第三方系统登录授权的应用ID
+  X-KDApi-AppID: 341950_01aJ5cupVqgaS+Ss6eWoT9WJ5L1W2plp
+  # 第三方系统登录授权的应用密钥
+  X-KDApi-AppSec: 98d2869acbe8499c9c57d20a9ca6807a
+  # 服务Url地址(公有云统一走网关sdk底层已处理,无需传X-KDApi-ServerUrl,下面这行需要注释)
+  X-KDApi-ServerUrl: http://124.70.8.12/k3cloud/
+  # 账套语系,默认2052
+  # X-KDApi-LCID: 2052
+  # 组织编码,启用多组织时配置对应的组织编码才有效
+  # X-KDApi-OrgNum: 100
+  # 允许的最大连接延时,单位为秒
+  # X-KDApi-ConnectTimeout: 120
+  # 允许的最大读取延时,单位为秒
+  # X-KDApi-RequestTimeout: 120
+

+ 15 - 0
mjava-heshu/src/main/resources/application.yml

@@ -0,0 +1,15 @@
+spring:
+  profiles:
+    active: prod
+  servlet:
+    multipart:
+      max-file-size: 100MB
+      max-request-size: 100MB
+  http:
+    enabled: false
+
+#  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  global-config:
+    db-config:
+      id-type: auto

+ 61 - 0
mjava-heshu/src/main/resources/logback-spring.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false" scan="false" scanPeriod="60 seconds">
+    <springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="d:\\jianhui_cloudpure\logs\"/>
+    <property name="FileNamePattern" value="${LOG_HOME}%d{yyyyMM}/%d{dd}"/>
+
+    <!-- 定义控制台输出 -->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %-5level - %logger{50} - %msg%n</pattern>
+        </layout>
+    </appender>
+
+    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 指定日志文件的名称 -->
+        <!--<file>${FileNamePattern}/info.log</file>-->
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${FileNamePattern}/info-%i.log</fileNamePattern>
+            <MaxHistory>30</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>30MB</MaxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
+        </layout>
+    </appender>
+
+    <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
+        <discriminator>
+            <Key>processid</Key>
+            <DefaultValue>sys</DefaultValue>
+        </discriminator>
+        <sift>
+            <appender name="FILE-${processid}"
+                      class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+                    <FileNamePattern>
+                        ${FileNamePattern}/${processid}.log
+                    </FileNamePattern>
+                </rollingPolicy>
+                <layout class="ch.qos.logback.classic.PatternLayout">
+                    <Pattern>
+                        %d{yyyyMMdd:HH:mm:ss.SSS} [%thread] %-5level %msg%n
+                    </Pattern>
+                </layout>
+            </appender>
+        </sift>
+    </appender>
+
+
+    <!-- 日志输出级别 -->
+    <logger name="org.springframework" level="debug"  additivity="false"/>
+    <logger name="com.malk.connecter" level="debug"/>
+    <root level="INFO">
+        <appender-ref ref="stdout"/>
+        <appender-ref ref="appLogAppender"/>
+        <appender-ref ref="SIFT"/>
+    </root>
+</configuration>

+ 320 - 0
mjava-heshu/src/test/java/com/malk/heshu/JdTest.java

@@ -0,0 +1,320 @@
+package com.malk.heshu;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.entity.RepoRet;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.aliwork.YDSearch;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.utils.PublicUtil;
+import com.malk.utils.UtilMap;
+import com.malk.heshu.config.KDWebApiConf;
+import com.malk.heshu.entity.*;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.*;
+
+@Slf4j
+@SpringBootTest
+@RunWith(SpringRunner.class)
+public class JdTest {
+
+    @Autowired
+    private KDWebApiConf kdWebApiConf;
+
+    @Autowired
+    private YDClient ydClient;
+    @Autowired
+    private YDConf ydConf;
+
+    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;
+    }
+
+    @Test
+    public void saveCust() throws Exception {
+        JSONObject params=new JSONObject();
+        params.put("fid","7eeb3600-3450-46e9-b4e7-47ab4e0ad18e");
+        params.put("key","textField_mnhav84y");
+        try {
+            Map formData= (Map) ydClient.queryData(YDParam.builder().formInstId(params.getString("fid")).build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+            if(formData==null){
+                return ;
+            }
+            CustomerInfo customerInfo = BeanUtil.toBean(formData, CustomerInfo.class);
+            List<Map> list=UtilMap.getList(formData,"tableField_mma72l0q");
+            List<CustomerInfo.CustBank> bkList=new ArrayList<>();
+            for(Map map:list){
+                CustomerInfo.CustBank  fBankInfo = BeanUtil.toBean(map, CustomerInfo.CustBank.class);
+                bkList.add(fBankInfo);
+            }
+            customerInfo.setFT_BD_CUSTBANK(bkList);
+            List<Map> list2=UtilMap.getList(formData,"tableField_mma72kx1");
+            List<ContactInfo> lxrList=new ArrayList<>();
+            for(Map map:list2){
+                ContactInfo contactInfo=new ContactInfo();
+                contactInfo.setFName(UtilMap.getString(map,"textField_mma72kx2"));
+                contactInfo.setFMobile(UtilMap.getString(map,"textField_mma72kx3"));
+                contactInfo.setFCompanyType("BD_Customer");
+                contactInfo.setFBizLocation(UtilMap.getString(map,"textField_mogukmdi"));
+                contactInfo.setFBizAddress(UtilMap.getString(map,"textField_mogukmdi"));
+                lxrList.add(contactInfo);
+            }
+            customerInfo.setFSALDEPTID(new FNumber(UtilMap.getString(formData,"textField_mogukmdd")));// 业务部门
+            String custTypeValue=UtilMap.getString(formData,"radioField_mma72kxi");
+            String custType;
+            if(custTypeValue.equals("贸易商")){
+                custType="02";
+            }else if(custTypeValue.equals("工厂")){
+                custType="01";
+            }else {
+                custType="05";
+            }
+            customerInfo.setFGroup(new FNumber(custType));
+            String operator=UtilMap.getString(formData,"radioField_mma72l0t");// 操作类型 客商准入  客商更新
+            if(operator.equals("客商更新")){
+                String fId=UtilMap.getString(formData,"textField_moi1ejl1");
+                if(!PublicUtil.isNull(fId)){
+                    // 反审核
+                    unAudit("BD_Customer",fId);
+                    customerInfo.setFCUSTID(Integer.parseInt(fId));
+                }
+            }
+            McR mcr=saveToAudit("BD_Customer",customerInfo,params.getString("fid"),params.getString("key"),"selectField_mogukmd8","textareaField_mogukmda","textField_moi1ejl1",lxrList);
+            System.out.println(JSONObject.toJSONString(mcr));
+        }catch (Exception e){
+        }
+    }
+
+    @Test
+    public void saveSupplier() throws Exception {
+        Map formData= (Map) ydClient.queryData(YDParam.builder().formInstId("a4fba63b-586c-43ee-9d34-daaeee2b19f1").build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+        System.out.println(formData);
+        SupplierEntity supplierEntity = BeanUtil.toBean(formData, SupplierEntity.class);
+        SupplierEntity.FBaseInfo fBaseInfo = BeanUtil.toBean(formData, SupplierEntity.FBaseInfo.class);
+        List<Map> list=UtilMap.getList(formData,"tableField_mma72l0q");
+        List<SupplierEntity.FBankInfo> bkList=new ArrayList<>();
+        for(Map map:list){
+            SupplierEntity.FBankInfo  fBankInfo = BeanUtil.toBean(map, SupplierEntity.FBankInfo.class);
+            bkList.add(fBankInfo);
+        }
+        supplierEntity.setFBaseInfo(fBaseInfo);
+        supplierEntity.setFBankInfo(bkList);
+        List<Map> list2=UtilMap.getList(formData,"tableField_mma72kx1");
+        List<SupplierEntity.FSupplierContact> lxrList=new ArrayList<>();
+        for(Map map:list2){
+            SupplierEntity.FSupplierContact  lxrInfo = BeanUtil.toBean(map, SupplierEntity.FSupplierContact.class);
+            lxrList.add(lxrInfo);
+        }
+        supplierEntity.setFSupplierContact(lxrList);
+        System.out.println(supplierEntity);
+//        System.out.println(saveToAudit("BD_Supplier",supplierEntity));
+    }
+
+    private McR saveToAudit(String formid, Object object,String fid,String codeKey,String statusKey,String msgKey,String idKey,List<ContactInfo> lxrList) throws Exception {
+        JSONObject resultObj = new JSONObject();
+        K3CloudApi client = new K3CloudApi(initIden());
+        String result=client.save(formid,JSONObject.toJSONString(UtilMap.map("Model",object)));
+        resultObj.put("save",result);
+        Gson gson = new Gson();
+        RepoRet sRet = gson.fromJson(result, RepoRet.class);
+        JSONObject reObj = JSONObject.parseObject(result,JSONObject.class);
+        if (sRet.isSuccessfully()) {
+            if(!PublicUtil.isNull(codeKey)){
+                // 回写信息
+                Map updateMap=UtilMap.map(codeKey,reObj.getJSONObject("Result").getString("Number"));
+                updateMap.put(statusKey,"成功");
+                updateMap.put(idKey,reObj.getJSONObject("Result").getString("Id"));// ID 内码
+                ydClient.operateData(YDParam.builder().formInstId(fid).updateFormDataJson(
+                        JSONObject.toJSONString(updateMap)
+                ).build(), YDConf.FORM_OPERATION.update);
+            }
+            if(lxrList!=null){
+                for (ContactInfo contactInfo : lxrList) {
+                    contactInfo.setFCompany(new FNumber(reObj.getJSONObject("Result").getString("Number")));
+                    String data=new Gson().toJson(contactInfo);
+                    String id=saveToAudit("BD_CommonContact",new Gson().fromJson(data,Object.class));
+                }
+            }
+            JsonObject jsonData = new JsonObject();
+            jsonData.addProperty("Ids", sRet.getResult().getId());
+            String result2=client.submit(formid, jsonData.toString());
+            resultObj.put("submit",result2);
+            RepoRet sRet2 = gson.fromJson(result, RepoRet.class);
+            if (sRet2.isSuccessfully()) {
+                JsonObject jsonData3 = new JsonObject();
+                jsonData3.addProperty("Ids", sRet2.getResult().getId());
+                String result3 = client.audit(formid, jsonData3.toString());
+                resultObj.put("audit",result3);
+                RepoRet repoRet3 = gson.fromJson(result3, RepoRet.class);
+                if (repoRet3.getResult().getResponseStatus().isIsSuccess()) {
+                    log.info("审批通过,新增完成");
+                    return McR.success(resultObj);
+//                    Map map=UtilMap.map("PkIds, TOrgIds",sRet.getResult().getId(),"1,105818,105822,127834,127835,127838,127843,127846,127847,127848,127850,127862,1370321,1325841,1327202,1646858");
+//                    String result4=client.allocate("formid",JSONObject.toJSONString(map));
+//                    resultObj.put("allocate",result4);
+//                    RepoRet repoRet4 = gson.fromJson(result4, RepoRet.class);
+//                    if (repoRet4.getResult().getResponseStatus().isIsSuccess()) {
+//                        log.info("分配完成");
+//                        return McR.success(resultObj);
+//                    }
+                }
+            }
+        }else {
+            log.info("保存失败:{}",result);
+            Map updateMap=UtilMap.map(statusKey,"失败");
+            updateMap.put(msgKey,result);
+            ydClient.operateData(YDParam.builder().formInstId(fid).updateFormDataJson(
+                    JSONObject.toJSONString(updateMap)
+            ).build(), YDConf.FORM_OPERATION.update);
+        }
+        return McR.error("203",JSONObject.toJSONString(resultObj));
+    }
+
+    private void unAudit(String formid,String fNumber) throws Exception {
+        K3CloudApi client = new K3CloudApi(initIden());
+        Gson gson = new Gson();
+        JsonObject jsonData = new JsonObject();
+        jsonData.addProperty("Ids", fNumber);
+        String result=client.unAudit(formid, jsonData.toString());
+        RepoRet sRet2 = gson.fromJson(result, RepoRet.class);
+        if (!sRet2.isSuccessfully()) {
+            log.info("反审核失败:{}",result);
+        }
+    }
+
+    @Test
+    public void queryOrder(){
+        K3CloudApi client = new K3CloudApi(initIden());
+        try {
+            int startRow = 0;
+            int limit = 2000;
+            BillQuery billQuery = new BillQuery();
+            billQuery.setFormId("AR_RECEIVEBILL");
+            billQuery.setFieldKeys("FPAYUNIT.FName,FREALRECAMOUNTFOR,FDATE,FSETTLETYPEID,FSETTLETYPEID.FName,F_ABC_Base1,FRECACCOUNTNAME,FACCOUNTID.FNumber,FACCOUNTID.FName,FSALEERID.FName,F_ABC_Base,F_ABC_BaseProperty,FBPBILLNUMBER,FBPBILLPARAMOUNT,FBPBILLTYPE,FEXPIRY");
+//            billQuery.setFieldKeys("FBillNo,FBillTypeID.FName,FPAYUNITTYPE,FDate,FPAYUNIT.FName,FCURRENCYID.FName,FRECEIVEAMOUNTFOR_H,FREALRECAMOUNTFOR,FSALEERID.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",4,"","","0"));//审核日期在今天之前N天以后
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","420","2025-10-20 00:00:00","","","0"));//审核日期年=XX
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FNumber","67","35","","","0"));//物料编码等于XX
+            billQuery.setFilterString(filterString);
+            billQuery.setLimit(limit);
+            billQuery.setStartRow(startRow);
+            String result=client.billQuery(JSONObject.toJSONString(billQuery));
+            System.out.println(result);
+//            JSONArray jsonArray = JSONArray.parseArray(result);
+//            for(int i=0;i<jsonArray.size();i++){
+//                JSONObject jsonObject = jsonArray.getJSONObject(i);
+//                System.out.println(jsonObject);
+//                Receivebill rb= BeanUtil.toBean(jsonObject, Receivebill.class);
+//                if(!PublicUtil.isNull(rb.getAssociationFormField_lypey1wr())){
+//                    List<Map> data=(List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-8E4AA59DFB354F2D922826F47F70B31AZ8ES")
+//                            .searchCondition(JSONObject.toJSONString(Arrays.asList(YDConf.searchCondition_TextFiled("textField_lx05suvl",rb.getAssociationFormField_lypey1wr(),"eq"))))
+//                            .build(), YDConf.FORM_QUERY.retrieve_list).getData();
+//                    if(data.size()>0){
+//                        System.out.println(data.get(0).get("formInstanceId"));
+//                        List<Map> kh=ydConf.associationForm("FORM-8E4AA59DFB354F2D922826F47F70B31AZ8ES", String.valueOf(data.get(0).get("formInstanceId")),rb.getAssociationFormField_lypey1wr(),"",false);
+//                        rb.setAssociationFormField_lypey1wr(JSONObject.toJSONString(kh));
+//                    }else{
+//                        rb.setAssociationFormField_lypey1wr("[]");
+//                    }
+//                }
+//                Map prodata=new HashMap();
+//                if(!PublicUtil.isNull(rb.getAssociationFormField_lsvmld22())){
+//                    List<Map> data=(List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-2E06211370FA43D3AEAAC0CF7636365491YX")
+//                            .searchCondition(JSONObject.toJSONString(Arrays.asList(YDConf.searchCondition_TextFiled("textField_m0c4utr2",rb.getAssociationFormField_lsvmld22(),"eq"))))
+//                            .build(), YDConf.FORM_QUERY.retrieve_list).getData();
+//                    if(data.size()>0){
+//                        System.out.println(data.get(0).get("formInstanceId"));
+//                        Map formData= UtilMap.getMap(data.get(0),"formData");
+//                        List<Map> kh=ydConf.associationForm("FORM-2E06211370FA43D3AEAAC0CF7636365491YX", String.valueOf(data.get(0).get("formInstanceId")),UtilMap.getString(formData,"textField_m50ci9rk"),"",false);
+//                        rb.setAssociationFormField_lsvmld22(JSONObject.toJSONString(kh));
+//                        prodata.put("textField_lwgba84b",formData.get("textField_m0namazl"));
+//                        prodata.put("textField_lxvrmu61",formData.get("textField_m0namazj"));
+//                        prodata.put("textField_lypey1wx",formData.get("textField_m0c4utr2"));
+//                        prodata.put("textField_m1aft8ye",formData.get("textField_m6yurmat"));
+//                        prodata.put("numberField_lxu21h6c",formData.get("numberField_mdcwz9mr"));
+//                        prodata.put("numberField_lxu29mvg",formData.get("numberField_mdcwz9mv"));
+//                        prodata.put("numberField_lxu336sn",formData.get("numberField_m0gb97py"));
+//                    }else{
+//                        rb.setAssociationFormField_lsvmld22("[]");
+//                    }
+//                }
+//                prodata.putAll(JSONObject.parseObject(JSONObject.toJSONString(rb.toYiDa())));
+//                ydClient.operateData(YDParam.builder().formUuid("FORM-9BDAFB39320246EFACC176C9E33E51DC4N40")
+//                        .formDataJson(JSONObject.toJSONString(prodata)).build(), YDConf.FORM_OPERATION.start);
+//            }
+
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void update(){
+//        unAudit("BD_Customer","");
+    }
+
+    @Test
+    public void queryOrder2(){
+        ContactInfo contactInfo=new ContactInfo();
+        contactInfo.setFName("张三");
+        contactInfo.setFMobile("17700001111");
+        contactInfo.setFCompanyType("BD_Customer");
+        contactInfo.setFCompany(new FNumber("CUST5127"));
+        contactInfo.setFBizLocation("测试地址");
+        contactInfo.setFBizAddress("测试地址");
+        try {
+            String data=new Gson().toJson(contactInfo);
+            System.out.println(data);
+            JSONObject jsonObject=JSONObject.parseObject(data);
+            System.out.println(jsonObject);
+            String id=saveToAudit("BD_CommonContact",new Gson().fromJson(data,Object.class));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    private String saveToAudit(String formid, Object object) throws Exception {
+        K3CloudApi client = new K3CloudApi(initIden());
+        String result=client.save(formid,JSONObject.toJSONString(UtilMap.map("Model",object)));
+        System.out.println(result);
+        Gson gson = new Gson();
+        RepoRet sRet = gson.fromJson(result, RepoRet.class);
+        JSONObject reObj = JSONObject.parseObject(result,JSONObject.class);
+        if (sRet.isSuccessfully()) {
+            return reObj.getJSONObject("Result").getString("Id");
+        }else {
+            return "";
+        }
+    }
+
+
+
+
+
+}

+ 7 - 6
mjava-huagao/src/main/java/com/malk/huagao/service/impl/EqbServiceImpl.java

@@ -426,12 +426,12 @@ public class EqbServiceImpl implements EqbService {
             String xssl = UtilMap.getString(xshtmxList.get(i), "numberField_mfbx1pr4");//销售数量
             double lsdj = UtilMap.getDouble(xshtmxList.get(i), "numberField_mf50cbri");//零售单价
             double pfyhdj = UtilMap.getDouble(xshtmxList.get(i), "numberField_mf50cbrj");//批发优惠单价
-            String zbq = UtilMap.getString(xshtmxList.get(i), "textField_mjas1rkx");//质保期
-
+            int zbq = UtilMap.getInt(xshtmxList.get(i), "numberField_mjb71qay");//质保期
+            String zbqValue = zbq > 0 ? zbq + "年" : "";
             if (i == 0){
-                xshtmx.add(getRowMap(false,i+1,cpmc,cpxh,dw,lsdj,pfyhdj,zbq));
+                xshtmx.add(getRowMap(false,i+1,cpmc,cpxh,dw,lsdj,pfyhdj,zbqValue));
             }else {
-                xshtmx.add(getRowMap(true,i+1,cpmc,cpxh,dw,lsdj,pfyhdj,zbq));
+                xshtmx.add(getRowMap(true,i+1,cpmc,cpxh,dw,lsdj,pfyhdj,zbqValue));
             }
         }
         Map jxsComponent16 = new HashMap();
@@ -558,10 +558,11 @@ public class EqbServiceImpl implements EqbService {
             double zke = UtilMap.getDouble(xshtmxList.get(i), "numberField_mjb71qao");//折扣额
             String bz = UtilMap.getString(xshtmxList.get(i), "textField_mjb71qaq");//备注
 
+            String zbqValue = zbq > 0 ? zbq + "年" : "";
             if (i == 0){
-                xshtmx.add(getRowMap(false,cpmc,cpxh,dw,xssl,hsdj,zbq+"年",smzs,jshj,zke,bz));
+                xshtmx.add(getRowMap(false,cpmc,cpxh,dw,xssl,hsdj,zbqValue,smzs,jshj,zke,bz));
             }else {
-                xshtmx.add(getRowMap(true,cpmc,cpxh,dw,xssl,hsdj,zbq+"年",smzs,jshj,zke,bz));
+                xshtmx.add(getRowMap(true,cpmc,cpxh,dw,xssl,hsdj,zbqValue,smzs,jshj,zke,bz));
             }
         }
         Map jxsComponent9 = new HashMap();

+ 1 - 1
mjava-huagao/src/test/java/com/malk/huagao/EqbTest.java

@@ -132,7 +132,7 @@ public class EqbTest {
 //            reqBodyObj.put("convertToPDF", "true");
             reqBodyObj.put("convertToHTML", true);
             reqBodyObj.put("fileName", "其他客户销售合同.docx");
-            reqBodyObj.put("fileSize", "28246 ");
+            reqBodyObj.put("fileSize", "28246");
             //reqBodyObj.put("convertToHTML", "false");
 
             // 请求Body体数据

+ 14 - 0
mjava-jinlun/src/main/java/com/malk/jinlun/schedule/JinlunTask.java

@@ -56,4 +56,18 @@ public class JinlunTask {
         jinlunTaskService.syncXingneng();
     }
 
+    //定时同步销售订单
+    @Scheduled(cron = "0 6 0 * * ?")
+    public void syncSaleOrder(){
+        jinlunTaskService.syncSaleOrder();
+    }
+
+    //定时同步应收收款核销记录
+    @Scheduled(cron = "0 7 0 * * ?")
+    public void syncReceiptVerification(){
+        jinlunTaskService.syncReceiptVerification();
+    }
+
+
+
 }

+ 4 - 1
mjava-jinlun/src/main/java/com/malk/jinlun/service/CpClient.java

@@ -1,5 +1,6 @@
 package com.malk.jinlun.service;
 
+import java.util.List;
 import java.util.Map;
 
 public interface CpClient {
@@ -11,7 +12,9 @@ public interface CpClient {
 
     Map getCpBo(String schemaCode, String objectId, String userId);
 
-    Map getCpBoList(String schemaCode, Map queryCondition,int page, int size, String userId);
+    Map getCpBoList(String schemaCode, Map queryCondition, Map options,int page, int size, String userId);
+
+    List<Map> getCpUserInfo(String corpId, List<String> departmentIds, List<String> ids, String mobile, String name, int page, int size);
 
     Map getCpBoResultData(Map result);
 

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

@@ -12,4 +12,10 @@ public interface JinlunTaskService {
     void syncSaleReturn();
 
     void syncXingneng();
+
+    void syncSaleOrder();
+
+    //应收收款核销记录
+    void syncReceiptVerification();
+
 }

+ 41 - 1
mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/CpClientImpl.java

@@ -12,7 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 @Service
 public class CpClientImpl implements CpClient {
@@ -139,11 +141,12 @@ public class CpClientImpl implements CpClient {
      * @return
      */
     @Override
-    public Map getCpBoList(String schemaCode, Map queryCondition,int page, int size, String userId){
+    public Map getCpBoList(String schemaCode, Map queryCondition, Map options,int page, int size, String userId){
         Map body = new HashMap();
 
         body.put("queryCondition",queryCondition);
         body.put("schemaCode",schemaCode);
+        body.put("options",options);
         body.put("page",page);
         body.put("size",size);
         body.put("showTotal",true);
@@ -163,6 +166,43 @@ public class CpClientImpl implements CpClient {
         return result;
     }
 
+    /**
+     * 云枢分页查询用户详情
+     * @param corpId
+     * @param departmentIds
+     * @param ids
+     * @param mobile
+     * @param name
+     * @param page
+     * @param size
+     * @return
+     */
+    @Override
+    public List<Map> getCpUserInfo(String corpId, List<String> departmentIds, List<String> ids, String mobile, String name, int page, int size) {
+        Map body = new HashMap();
+        if (Objects.nonNull(corpId)) body.put("corpId",corpId);
+        if (Objects.nonNull(departmentIds)) body.put("departmentIds",departmentIds);
+        if (Objects.nonNull(ids)) body.put("ids",ids);
+        if (Objects.nonNull(mobile)) body.put("mobile",mobile);
+        if (Objects.nonNull(name)) body.put("name",name);
+
+        body.put("page",page);
+        body.put("size",size);
+
+        String s = UtilHttp.doPost(cloudpivotConfig.getRedirectUri() + "openapi/v3/organization/user/detail/query", CloudpivotConfig.initTokenHeader(getCpAccessToken()), null, body);
+
+        Map result = (Map) JSONObject.parse(s);
+
+        isSuccess(result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        List<Map> content = UtilMap.getList(data, "content");
+
+        return content;
+    }
+
+
     //获取云枢表单详情返回结果中单据字段值
     @Override
     public Map getCpBoResultData(Map result){

文件差異過大導致無法顯示
+ 393 - 12
mjava-jinlun/src/main/java/com/malk/jinlun/service/impl/JinlunTaskServiceImpl.java


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

@@ -5,7 +5,7 @@ server:
 
 spring:
   datasource:
-    url: jdbc:mysql://192.168.0.12:3306/cloudpivot?serverTimezone=GMT%2B8
+    url: jdbc:mysql://172.16.10.1:3306/cloudpivot?serverTimezone=GMT%2B8
     username: root
     password: test123456!@#$%
     driver-class-name: com.mysql.cj.jdbc.Driver
@@ -40,7 +40,7 @@ cloudpivot:
   grant_type: client_credentials
   client_id: xclient
   client_secret: 0a417ecce58c31b32364ce19ca8fcd15
-  redirect_uri: http://192.168.0.12/api/
+  redirect_uri: http://172.16.10.1/api/
   operator_user_id: 8ac194c0811240a6b483ebc86aeb9147
 
 kingdee:

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

@@ -5,7 +5,7 @@ server:
 
 spring:
   datasource:
-    url: jdbc:mysql://192.168.0.12:3306/cloudpivot?serverTimezone=GMT%2B8
+    url: jdbc:mysql://172.16.10.1:3306/cloudpivot?serverTimezone=GMT%2B8
     username: root
     password: test123456!@#$%
     driver-class-name: com.mysql.cj.jdbc.Driver
@@ -40,7 +40,7 @@ cloudpivot:
   grant_type: client_credentials
   client_id: xclient
   client_secret: 0a417ecce58c31b32364ce19ca8fcd15
-  redirect_uri: http://192.168.0.12/api/
+  redirect_uri: http://172.16.10.1/api/
   operator_user_id: 8ac194c0811240a6b483ebc86aeb9147
 
 kingdee:

+ 9 - 0
mjava-jinlun/src/test/java/com/malk/jinlun/DdTest.java

@@ -71,6 +71,15 @@ public class DdTest {
     public void test7() {
         jinlunTaskService.syncSaleReturn();
     }
+    @Test
+    public void test16() {
+        jinlunTaskService.syncSaleOrder();
+    }
+
+    @Test
+    public void test17() {
+        jinlunTaskService.syncReceiptVerification();
+    }
 
     @Test
     public void test8() {

+ 26 - 0
mjava-kabeiyi/pom.xml

@@ -45,6 +45,32 @@
             <artifactId>alibabacloud-ocr_api20210707</artifactId>
             <version>3.0.2</version>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.34</version> <!-- 推荐使用最新稳定版 -->
+            <scope>provided</scope> <!-- 必须是 provided -->
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.33</version>  <!-- 必须 >= 8.0 -->
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.3.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.14</version> <!-- 4.x 版本 -->
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20231013</version> <!-- 或最新版本 -->
+        </dependency>
 
     </dependencies>
 

+ 35 - 0
mjava-kabeiyi/src/main/java/com/malk/kabeiyi/controller/KabeiyiController.java

@@ -1,6 +1,8 @@
 package com.malk.kabeiyi.controller;
 
+import com.malk.kabeiyi.entity.OperatingRecordEntity;
 import com.malk.kabeiyi.service.KabeiyiService;
+import com.malk.kabeiyi.service.OperatingRecordService;
 import com.malk.server.common.McR;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.service.dingtalk.DDClient_Workflow;
@@ -27,6 +29,9 @@ public class KabeiyiController {
     @Autowired
     private KabeiyiService kabeiyiService;
 
+    @Autowired
+    private OperatingRecordService  operatingRecordServiceImpl;
+
     //审批实例url前缀
     private static final String PROC_INST_PREFIX_URL = "https://aflow.dingtalk.com/dingtalk/web/query/pchomepage.htm?from=oflow&op=true&corpid=dingc3a744cb591a7346f2c783f7214b6d69#/plainapproval?procInstId=";
     @GetMapping("test")
@@ -108,4 +113,34 @@ public class KabeiyiController {
         kabeiyiService.addVoucher(map);
         return McR.success();
     }
+
+//    付款推送cbs
+    @PostMapping("pushCbs")
+    public McR puchCBS(@RequestBody Map map){
+        kabeiyiService.puchCBS(map);
+        return McR.success();
+    }
+
+//    定时查询cbs付款情况并推送u8凭证
+    @Scheduled(cron = "0 0/40 8-19 * * ?")
+    public McR schedulePaymentCBSToU8() {
+        try {
+            String[] statusList = {"1"};
+            List<OperatingRecordEntity> rescords = operatingRecordServiceImpl.findByStatusAndResCode(statusList);
+            log.info("开始获取排程单,并推送用友,推送数量为:{}",rescords.size());
+            if(rescords.isEmpty() || rescords.size()==0){
+                log.info("没有需要推送的订单。");
+                return McR.success();
+            }
+            for(OperatingRecordEntity entity:rescords){
+                log.info("开始推送订单:{}",entity.toString());
+                kabeiyiService.schedulePaymentCBSToU8(entity);
+            }
+
+            return McR.success();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
 }

+ 5 - 0
mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/KabeiyiService.java

@@ -1,5 +1,6 @@
 package com.malk.kabeiyi.service;
 
+import com.malk.kabeiyi.entity.OperatingRecordEntity;
 import com.malk.server.common.McR;
 import org.springframework.scheduling.annotation.Async;
 
@@ -39,4 +40,8 @@ public interface KabeiyiService {
     void addVoucher(Map map);
 
     String getWeekRange(String dateStr);
+
+    void puchCBS(Map map);
+
+    void schedulePaymentCBSToU8(OperatingRecordEntity entity);
 }

文件差異過大導致無法顯示
+ 612 - 393
mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/impl/KabeiyiServiceImpl.java


+ 37 - 0
mjava-kabeiyi/src/main/resources/application-dev.yml

@@ -17,6 +17,13 @@ logging:
   level:
     com.malk.*: debug
 
+spring:
+  datasource:
+    url: jdbc:mysql://114.55.244.55:3306/kby?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
+    username: root
+    password: Kabeiyi@2025++
+    driver-class-name: com.mysql.cj.jdbc.Driver
+
 mybatis-plus:
   configuration:
     #开启驼峰命名自动映射
@@ -70,3 +77,33 @@ u8:
   appKey : opa52c74dd3e0563458
   appSecret : 5b96fad7470a489bbae369ec79406fb1
 
+#cbs:
+#  ADDRESS: https://cbs8-openapi-reprd.csuat.cmburl.cn/
+#  APP_ID: WmBnthl
+#  APP_SECRET: e8f2a01b20ad4a31ed2f1783578db4cfde1badb5
+#  GRANT_TYPE: client_credentials
+#  PLATFORM_PUBLIC_KEY: 04D56804DC5CB1BC710E6DA73FD9FEDECD82110B0D1B629688C6849AE349BE5B3CB1A5C11528B7ECDCDC2CC20464B232F54C01F2C3B049EEBB4A8158B8C006987A
+#  ENTERPRISE_PRIVATE_KEY: bbb04781d69d4d74a707ee3b22dd28e73190d5919c5279c5de0d4562509182f7
+
+yida:
+  company: selectField_lxwwvggb # 公司抬头
+  schPayAccount : selectField_lxydz0ub  # 付款账号
+  revName: textField_lxwwvggc # 收款人名称
+  revAccount: textField_lxwwvgge # 收款账号
+  revBankName: textField_lxwwvggd # 收款银行
+  revCnapsCode: numberField_lycr2xlb # 收款银行联行号
+  deptName: textField_m2sekyf7 # 部门名称
+  orderCode: textField_lxwwvggg # 合同(订单)名称编号
+  dsSequence: numberField_m2o5b8sh # 数据源序号
+  type: selectField_m2sdpe2p # 类型 固定:采购部专用资金审批
+  purpose: textField_lxwwvggy # 付款用途
+  currency: textField_mhivb4yf # 币种
+  expectTime: dateField_lxwwvggf # 预计付款时间
+  displayUnitCode: textField_mhiyxcb3 # 显示单位编码
+  applyAmount: numberField_lxwwvggi # 申请金额
+  details: tableField_lxwwvggl # 付款明细
+  producter: textField_mhiyxcb4 # 制单人
+  detailMapping:
+    productName: textField_lxwwvggm  #货物或劳务名称
+
+

+ 14 - 0
mjava-kabeiyi/src/main/resources/application-prod.yml

@@ -16,6 +16,12 @@ logging:
   path: /home/server/kabeiyi/log/
   level:
     com.malk.*: info
+spring:
+  datasource:
+    url: jdbc:mysql://114.55.244.55:3306/kby?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
+    username: root
+    password: Kabeiyi@2025++
+    driver-class-name: com.mysql.cj.jdbc.Driver
 
 mybatis-plus:
   configuration:
@@ -69,3 +75,11 @@ u8:
   toAccount: kbeapi
   appKey : opa52c74dd3e0563458
   appSecret : 5b96fad7470a489bbae369ec79406fb1
+
+cbs:
+  ADDRESS: https://cbs8-openapi-reprd.csuat.cmburl.cn/
+  APP_ID: WmBnthl
+  APP_SECRET: e8f2a01b20ad4a31ed2f1783578db4cfde1badb5
+  GRANT_TYPE: client_credentials
+  PLATFORM_PUBLIC_KEY: 04CF771DF8D041481D91F274DADDD404EB271ABB2EF1AF287FF48753477C30B60F0262D21430B6D26AF20A62C5E6D83735EAF2F011C71901661E4F0AF4B9DFA6F6
+  ENTERPRISE_PRIVATE_KEY: 24c0ebb4b3c074ce38318c1a83449200c472bb6ef7bbfe8a7146128e70f96571

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

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

+ 5 - 5
mjava-lingmingguangzi/src/main/java/com/malk/lingmingguangzi/service/LingmingguangziServiceImpl.java

@@ -544,8 +544,8 @@ public class LingmingguangziServiceImpl implements LingmingguangziService {
             detail.put("die_model","");//
             return detail;
         }).collect(Collectors.toList());
-        //附件
-        List<Map> list2 = (List<Map>) formData.get("tableField_ly8fxusx");
+        //附件  20250413 附件过大可能上传超时 暂时不推送erp
+        /*List<Map> list2 = (List<Map>) formData.get("tableField_ly8fxusx");
 
         String[] ERP_FILEPATHS = new String[]{filePathSz,filePathXg,filePathZj,filePathHz};
         String[] ERP_ENVS = new String[]{"深圳","香港","浙江","杭州"};
@@ -585,7 +585,7 @@ public class LingmingguangziServiceImpl implements LingmingguangziService {
                         break;
                     }
                 }
-                /*if ("深圳".equals(type)){
+                if ("深圳".equals(type)){
                     //将downloadurl下载到本地
                     try {
                         downloadFile(ydDownloadUrl, filePathSz,fileName);
@@ -627,12 +627,12 @@ public class LingmingguangziServiceImpl implements LingmingguangziService {
                     } catch (UnsupportedEncodingException e) {
                         throw new RuntimeException(e);
                     }
-                }*/
+                }
 
                 return detail;
             }).collect(Collectors.toList());
             body.put("makSoFilesList",makSoFilesList);
-        }
+        }*/
         body.put("makSoDetailList",makSoDetailList);
 
 

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

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

+ 5 - 1
mjava-ounuo/src/main/java/com/malk/tuosi/entity/PersonalMonthlySuccessrate.java

@@ -24,6 +24,10 @@ public class PersonalMonthlySuccessrate {
     private String department;
     /*客户*/
     private String customer;
-    /*时间*/
+    /*设计等级*/
+    private String designlevel;
+    /*完成时间*/
     private String time;
+    /*节点完成时间*/
+    private String deadlineTime;
 }

文件差異過大導致無法顯示
+ 504 - 183
mjava-ounuo/src/main/java/com/malk/tuosi/schedule/ScheduleTask.java


+ 6 - 3
mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/TbServiceImpl.java

@@ -302,7 +302,8 @@ public class TbServiceImpl implements TBService {
                         header,
                         null,
                         body_AAA);
-                log.info("[创建任务自动更新确认流程]");
+                log.info("自动流程确认,任务id: {}",taskId );
+                log.info("[创建任务自动更新确认流程],{}",doPut);
             }
         }else if (event.equals("v3.task.node.status.update")) {
             /*群卡片推送*/
@@ -459,9 +460,9 @@ public class TbServiceImpl implements TBService {
                     message.put("openSpaceId", "dtv1.card//IM_GROUP.cid2niI2sTPksK5PHpfrLgCPQ==");
                 } else if ("姜华".equals(businessManager)) {
                     message.put("openSpaceId", "dtv1.card//IM_GROUP.cid+J9H07847VNwIYiLpNay0Q==");
-                }else if ("赵宇娟".equals(businessManager)) {
+                }else if ("赵宇娟".equals(businessManager) || "孟露".equals(businessManager)) {
                     message.put("openSpaceId", "dtv1.card//IM_GROUP.cidaUtMTIjDHM60UXFfHegKtg==");
-                } else if ("陈晶".equals(businessManager) || "郝俊秀".equals(businessManager) || "鲁萍".equals(businessManager)) {
+                } else if ("陈晶".equals(businessManager) || "郝俊秀".equals(businessManager)) {
                     message.put("openSpaceId", "dtv1.card//IM_GROUP.cidTppONwRCrkshRlCt28O+NA==");
                 }else if ("张曼".equals(businessManager)){
                     message.put("openSpaceId","dtv1.card//IM_GROUP.cidXES2AIusSs+mb9gD8i4w1w==");
@@ -469,6 +470,8 @@ public class TbServiceImpl implements TBService {
                     message.put("openSpaceId","dtv1.card//IM_GROUP.cidI3G/EnCvlem5w3+qKfTMDA==");
                 }else if("谷晨丹".equals(businessManager)){
                     message.put("openSpaceId","dtv1.card//IM_GROUP.cidqXtqGAN+Es7L/5m3uaZzSg==");
+                }else if("鲁萍".equals(businessManager)){
+                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidibXgbOJLBc5L8xHNRzo5Jg==");
                 }
 //                message.put("openSpaceId", "dtv1.card//IM_GROUP.cidTppONwRCrkshRlCt28O+NA==");//正式群id:cidTppONwRCrkshRlCt28O+NA==   测试群id:cidKoVDKhvynnj+73h0uxSJBA==
                 message.put("cardTemplateId", "160b26bf-d699-49fc-a6dc-9cd20eed7750.schema");

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

@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: prod
+    active: dev

+ 65 - 9
mjava-siku/src/main/java/com/malk/siku/controller/SikuController.java

@@ -76,29 +76,49 @@ public class SikuController {
     }
 
     /**
-     * 采购单可用预算校验
+     * 预付退回导入
      * @param map
      * @return
      */
-    @PostMapping("/checkBudgetAmt")
+    @PostMapping("/saveRepayment")
+    public McR saveRepayment(@RequestBody Map map){
+        return sikuService.saveRepayment(map);
+    }
+
+    /**
+     * 采购单可用预算校验-停用
+     * @param map
+     * @return
+     */
+    /*@PostMapping("/checkBudgetAmt")
     public McR checkBudgetAmt(@RequestBody Map map){
         return sikuService.checkBudgetAmt(map);
-    }
+    }*/
 
-    //每刻云票收款单核销回调
-    @PostMapping("/receive/callback")
+    //每刻云票收款核销回调
+    @PostMapping("/VERIFICATION_AR/callback")
     public McR callback(@RequestBody Map map){
-        log.info("每刻云票收款单核销回调:{}", JSONObject.toJSONString(map));
+        log.info("每刻云票收款核销回调:{}", JSONObject.toJSONString(map));
 
         sikuService.invoiceWriteBack(map);
 
         return McR.success();
     }
 
-    //每刻云票开票回调
-    @PostMapping("/application/callback")
+    //每刻云票应收单回调(开票成功)
+    @PostMapping("/RECEIVABLE_AR/callback")
+    public McR callback9(@RequestBody Map map){
+        log.info("每刻云票应收单完成回调:{}",JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack9(map);
+
+        return McR.success();
+    }
+
+    //每刻云票开票申请单回调(开票失败)
+    @PostMapping("/INVOICE_APPLICATION_AR/callback")
     public McR callback2(@RequestBody Map map){
-        log.info("每刻云票开票回调:{}",JSONObject.toJSONString(map));
+        log.info("每刻云票开票申请单回调:{}",JSONObject.toJSONString(map));
 
         sikuService.invoiceWriteBack2(map);
 
@@ -135,6 +155,36 @@ public class SikuController {
         return McR.success();
     }
 
+    //每刻报销借款单完成回调(押金("是否项目相关"为【是】) 、借款单(项目))
+    @PostMapping("/loan/callback")
+    public McR callback6(@RequestBody Map map){
+        log.info("每刻报销借款单完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack6(map);
+
+        return McR.success();
+    }
+
+    //每刻报销还款单完成回调
+    @PostMapping("/repayment/callback")
+    public McR callback7(@RequestBody Map map){
+        log.info("每刻报销还款单完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack7(map);
+
+        return McR.success();
+    }
+
+    //每刻报销费用报销单完成回调(项目报销单(个人)、项目差旅报销单、打车(企业支付)("是否有项目"为【是】))
+    @PostMapping("/reimbursement2/callback")
+        public McR callback8(@RequestBody Map map){
+        log.info("每刻报销费用报销单完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack8(map);
+
+        return McR.success();
+    }
+
     //每刻预算冻结/释放
     @PostMapping("/updateBudget")
     public McR updateBudget(@RequestBody Map map){
@@ -143,6 +193,12 @@ public class SikuController {
         return McR.success();
     }
 
+    //创建/更新企业滴滴项目
+    @PostMapping("/ddProject")
+    public McR ddProject(@RequestBody Map map){
+        return sikuService.ddProject(map);
+    }
+
     @GetMapping("/files/{fileId}")
     public ResponseEntity<Resource> getFileResource(
             @PathVariable String fileId,

+ 30 - 0
mjava-siku/src/main/java/com/malk/siku/schedule/SikuTask.java

@@ -0,0 +1,30 @@
+package com.malk.siku.schedule;
+
+import com.malk.siku.service.SikuTaskService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"enable.scheduling"})
+public class SikuTask {
+
+    @Autowired
+    private SikuTaskService sikuTaskService;
+
+    //定时同步借款台账
+    //早上9点至晚上6点 每小时同步一次
+    @Scheduled(cron = "0 0 9-18 * * ?")
+    public void syncMaterial(){
+        sikuTaskService.syncLoanManage();
+    }
+
+}

+ 12 - 0
mjava-siku/src/main/java/com/malk/siku/service/SikuService.java

@@ -28,4 +28,16 @@ public interface SikuService {
     void invoiceWriteBack4(Map map);
 
     void invoiceWriteBack5(Map map);
+
+    void invoiceWriteBack6(Map map);
+
+    void invoiceWriteBack7(Map map);
+
+    void invoiceWriteBack8(Map map);
+
+    McR saveRepayment(Map map);
+
+    void invoiceWriteBack9(Map map);
+
+    McR ddProject(Map map);
 }

+ 6 - 0
mjava-siku/src/main/java/com/malk/siku/service/SikuTaskService.java

@@ -0,0 +1,6 @@
+package com.malk.siku.service;
+
+public interface SikuTaskService {
+    void syncLoanManage();
+
+}

文件差異過大導致無法顯示
+ 930 - 137
mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java


+ 215 - 0
mjava-siku/src/main/java/com/malk/siku/service/impl/SikuTaskServiceImpl.java

@@ -0,0 +1,215 @@
+package com.malk.siku.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.siku.service.SikuTaskService;
+import com.malk.siku.utils.MkBxUtil;
+import com.malk.utils.UtilHttp;
+import com.malk.utils.UtilMap;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+@Slf4j
+@Service
+public class SikuTaskServiceImpl implements SikuTaskService {
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Override
+    public void syncLoanManage() {
+        try {
+            log.info("开始同步借还款台账");
+            //删除宜搭借款台账
+            List<List<String>> formInstanceIdListList = new ArrayList<>();//实例id集合,每100条
+
+            DDR_New ddrNew = new DDR_New();
+            int pageSize = 50;
+            int pageNumber = 0;
+            do {
+                pageNumber++;
+
+                ddrNew = retryQueryData(YDParam.builder()
+                        .formUuid("FORM-14F79868B683481295062CD1D643E06EVB7B")
+                        .searchFieldJson("")
+                        .pageNumber(pageNumber)
+                        .pageSize(pageSize)
+                        .build(), YDConf.FORM_QUERY.retrieve_search_form_id);
+
+                formInstanceIdListList.addAll(Collections.singleton((List<String>) ddrNew.getData()));
+
+//                Thread.sleep(1000);
+            }while (ddrNew.getPageNumber() * pageSize < ddrNew.getTotalCount());
+
+            for (List<String> formInstanceIdList : formInstanceIdListList) {
+                if (!formInstanceIdList.isEmpty()){
+                    retryOperateData(YDParam.builder()
+                            .formUuid("FORM-14F79868B683481295062CD1D643E06EVB7B")
+                            .formInstanceIdList(formInstanceIdList)
+                            .build(), YDConf.FORM_OPERATION.delete_batch);
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+
+        //查询每刻最新借款台账
+        List<Map> loanManageList = MkBxUtil.loanManageList();
+
+        for (Map loanManage : loanManageList) {
+            String code = UtilMap.getString(loanManage, "code");//台账编号\
+            String formCode = UtilMap.getString(loanManage, "formCode");//借款单单据号
+
+            String legalEntityName = UtilMap.getString(loanManage, "legalEntityName");//所属公司
+            String departmentName = UtilMap.getString(loanManage, "departmentName");//借款部门
+            String employeeName = UtilMap.getString(loanManage, "employeeName");//借款人
+            List<String> employeeDdUser = getDdUserId(employeeName);
+            String responseUserName = UtilMap.getString(loanManage, "responseUserName");//负责人
+            List<String> responseDdUser = getDdUserId(responseUserName);
+
+            String formName = UtilMap.getString(loanManage, "formName");//事由
+            String formSubTypeName = UtilMap.getString(loanManage, "formSubTypeName");//单据类型
+            long submittedAt = UtilMap.getLong(loanManage, "submittedAt");//提单时间
+            long expectRepaymentTime = UtilMap.getLong(loanManage, "expectRepaymentTime");//预计归还时间
+            int loanAge = UtilMap.getInt(loanManage, "loanAge");//账龄
+            Double amount = UtilMap.getDouble(UtilMap.getMap(loanManage, "approvedAmount"), "amount");//借款金额
+            Double owedAmount = UtilMap.getDouble(UtilMap.getMap(loanManage, "owedAmount"), "amount");//未归还(未核销)
+            Double pendingAmount = UtilMap.getDouble(UtilMap.getMap(loanManage, "pendingAmount"), "amount");//核销中金额
+
+            //借款单详情
+            Map loanDetailInfo = MkBxUtil.loanDetailInfo(formCode);
+            Map customObject = UtilMap.getMap(loanDetailInfo, "customObject");
+
+            Map cf0 = UtilMap.getMap(customObject, "CF0");
+            String projectCode = UtilMap.getString(cf0, "detailBusinessCode");//项目流水号
+            String projectName = UtilMap.getString(cf0, "text");//项目名称
+
+            long settledAt = UtilMap.getLong(loanDetailInfo, "settledAt");//支付时间
+
+            Map formData = new HashMap();
+            formData.put("textField_mnsly3li",code);
+            formData.put("textField_mnsly3lb",legalEntityName);
+            formData.put("textField_mnsly3lc",departmentName);
+            formData.put("employeeField_mnsly3mc",employeeDdUser);
+            formData.put("employeeField_mnsly3md",responseDdUser);
+            formData.put("textField_mnsm8q6f",projectName);
+            formData.put("textField_mnwtwu9z",projectCode);
+            formData.put("textareaField_mnsly3ll",formName);
+            formData.put("textField_mnsly3lg",formSubTypeName);
+            formData.put("dateField_mnsly3lx",submittedAt);
+            formData.put("dateField_mnsly3ly",expectRepaymentTime);
+            formData.put("dateField_mnsly3m3",settledAt);
+            formData.put("numberField_mnsly3m4",loanAge);
+            formData.put("numberField_mnsly3m5",amount);
+            formData.put("numberField_mnsly3ma",owedAmount);
+            formData.put("numberField_mnsly3mb",pendingAmount);
+
+            //同步宜搭借款台账
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-14F79868B683481295062CD1D643E06EVB7B")
+                    .formDataJson(JSONObject.toJSONString(formData))
+                    .build(), YDConf.FORM_OPERATION.create);
+        }
+        System.out.println("111");
+
+    }
+
+
+    //自带重试的operateData方法
+    private Object retryOperateData(YDParam param, YDConf.FORM_OPERATION formOperation) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        Object result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.operateData(param, formOperation);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_OPERATION:{},异常信息:{}", JSONObject.toJSONString(param), formOperation,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
+    }
+
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
+
+    //根据员工名字匹配员工id
+    private List<String> getDdUserId(String Name){
+        HashMap body = new HashMap();
+
+        body.put("queryWord", Name);
+        body.put("offset",0);
+        body.put("size",1);
+
+        String s1 = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/users/search", ddClient.initTokenHeader(), null, body);
+
+        List<String> list = JSONObject.parseObject(s1).getJSONArray("list").toJavaList(String.class);
+
+        return list;
+    }
+}

+ 95 - 7
mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java

@@ -16,15 +16,15 @@ import java.util.*;
  */
 @Slf4j
 public class MkBxUtil {
-
-    @Value("${mk.bx.appCode}")
-    private final static String appCode = "AP52Y01LHHTAP9";
-
-    @Value("${mk.bx.appSecret}")
+    //测试环境
+    /*private final static String appCode = "AP52Y01LHHTAP9";
     private final static String appSecret = "N4WuERLteAUPaWebnsHy";
+    private final static String host = "ng.maycur.com";*/
 
-//    private final static String host = "ng-uat.maycur.com";//测试环境
-    private final static String host = "ng.maycur.com";//生产环境
+    //生产环境
+    private final static String appCode = "AP52RG1SCG8S6L";
+    private final static String appSecret = "YFTbD2MviqUwztBTbMWd";
+    private final static String host = "ng.maycur.com";
 
     private final Object $lock = new Object[0];
 
@@ -72,6 +72,48 @@ public class MkBxUtil {
 
     }
 
+    public static Map initTokenHeader(String thisAppCode,String thisAppSecret){
+
+        Map header = new HashMap();
+
+        String tokenId = UtilToken.get("invalid-tokenId-mkbx");
+        String entCode = UtilToken.get("invalid-entCode-mkbx");
+
+        if (StringUtils.isNotBlank(tokenId) && StringUtils.isNotBlank(entCode)) {
+            header.put("tokenId",tokenId);
+            header.put("entCode",entCode);
+
+            return header;
+        } else {
+            //每刻登录认证
+            Map body = new HashMap();
+
+            long timeMillis = System.currentTimeMillis();
+            body.put("appCode",thisAppCode);
+            body.put("secret",getSecret(thisAppCode,thisAppSecret,timeMillis));
+            body.put("timestamp",timeMillis);
+
+            Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/auth/login", null, null, body));
+
+            Map data = UtilMap.getMap(result, "data");
+
+            tokenId = UtilMap.getString(data, "tokenId");
+            entCode = UtilMap.getString(data, "entCode");
+
+            log.info("每刻报销tokenId, {}", tokenId);
+            log.info("每刻报销entCode, {}", entCode);
+
+            UtilToken.put("invalid-tokenId-mkbx", tokenId, EXPIRES_IN);
+            UtilToken.put("invalid-entCode-mkbx", entCode, EXPIRES_IN);
+
+            header.put("tokenId",tokenId);
+            header.put("entCode",entCode);
+
+            return header;
+        }
+
+    }
+
     //保存往来单位
     public static Map saveTradingPartner(Object body){
         Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/tradingPartner/batch/save", MkBxUtil.initTokenHeader(), null, body,(Map) null));
@@ -119,6 +161,16 @@ public class MkBxUtil {
         return expenseCodes;
     }
 
+    //还款单写入接口
+    public static Map receiveRepayment(Object body){
+        log.info("body:{}",JSONObject.toJSONString(body));
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/receive/repayment", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        return result;
+    }
+
     //费用类型查询
     public static String expenseTypeSearch(Object body){
         log.info("body:{}",JSONObject.toJSONString(body));
@@ -214,6 +266,42 @@ public class MkBxUtil {
         return data;
     }
 
+    //借款单详情
+    public static Map loanDetailInfo(String formCode){
+        Map result = (Map) JSONObject.parse(UtilHttp.doGet("https://" + host + "/api/openapi/form/loan/" + formCode, MkBxUtil.initTokenHeader("AP52RG1SCG8S6L","YFTbD2MviqUwztBTbMWd"), (Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        return data;
+    }
+
+    //借款单台账列表
+    public static List<Map> loanManageList(){
+        Boolean hasNextPage = false;
+
+        List<Map> totalList = new ArrayList<>();
+        int i = 1;
+        do {
+            Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/form/loan/manage", MkBxUtil.initTokenHeader("AP52RG1SCG8S6L","YFTbD2MviqUwztBTbMWd"),null, UtilMap.map("pageNo, pageSize",i,100)));
+
+            log.info("Result:{}",result);
+
+            Map data = UtilMap.getMap(result, "data");
+
+            List<Map> list = UtilMap.getList(data, "list");
+
+            totalList.addAll(list);
+
+            hasNextPage = UtilMap.getBoolean(data, "hasNextPage");
+
+            i++;
+        }while (hasNextPage);
+
+        return totalList;
+    }
+
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);
 

+ 48 - 7
mjava-siku/src/main/java/com/malk/siku/utils/MkYpUtil.java

@@ -18,15 +18,15 @@ import java.util.Map;
  */
 @Slf4j
 public class MkYpUtil {
-
-    @Value("${mk.yp.appCode}")
-    private final static String appCode = "AP53EP1SVDS1N9";
-
-    @Value("${mk.yp.appSecret}")
+    //测试环境
+    /*private final static String appCode = "AP53EP1SVDS1N9";
     private final static String appSecret = "qF4nm3nPnyXYcrWcr5jl";
+    private final static String host = "pms-uat.maycur.com";*/
 
-    private final static String host = "pms-uat.maycur.com";//测试环境
-//    private final static String host = "pms.maycur.com";//生产环境
+    //生产环境
+    private final static String appCode = "AP565SLVOI76UA";
+    private final static String appSecret = "sGoMNMSbaw4MWLLbUTtPye2k6trtfIs1";
+    private final static String host = "pms.maycur.com";
 
     private final Object $lock = new Object[0];
 
@@ -106,6 +106,47 @@ public class MkYpUtil {
         return data2;
     }
 
+    //员工批量查询接口
+    public static List<Map> getAllEmployee(){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/employee/getAllEmployee", MkYpUtil.initTokenHeader(), null, null,(Map) null));
+
+        log.info("Result:{}",result);
+
+        List<Map> data = UtilMap.getList(result, "data");
+
+        return data;
+    }
+
+    //已完成发票数据查询接口V2
+    public static Map getInvoiceInfo(String invoiceNumber){
+        Map body = new HashMap();
+        body.put("searchType","INVOICE_VAT");
+        body.put("invoiceNumber",invoiceNumber);
+        body.put("pageSize",1);
+        body.put("pageNum",1);
+
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/ar/openapi/invoice/v2/search", MkYpUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        List<Map> list = UtilMap.getList(data, "list");
+
+        if (!list.isEmpty()){
+            return list.get(0);
+        }else {
+            return null;
+        }
+    }
+
+    //应收单作废接口
+    public static void receivableObsolete(Map body){
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/ar/openapi/receivable_oa/obsolete", MkYpUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+    }
+
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);
 

+ 178 - 0
mjava-siku/src/main/java/com/malk/siku/utils/QyddUtil.java

@@ -0,0 +1,178 @@
+package com.malk.siku.utils;
+
+import com.alibaba.fastjson.JSONObject;
+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 java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ * 企业滴滴
+ */
+@Slf4j
+public class QyddUtil {
+    private static String client_id = "3295ee5021a0dd6436d18f56e7c761c6";
+    private static String client_secret = "fe5539d17722035cba70a2e6220c43a4";
+    private static String phone = "18857526310";
+    private static String signKey = "038bD3BAb4a25D84dc96";
+    private static String grant_type = "client_credentials";
+    private static String company_id = "1125994055637379";
+    private static String host = "api.es.xiaojukeji.com";
+
+    private static final Long EXPIRES_IN = 1800000L;
+
+    public static String getToken(){
+        String accessToken = "";
+
+        String token = UtilToken.get("invalid-token-qydd");
+
+        if (StringUtils.isNotBlank(token)) {
+            accessToken = token;
+        } else {
+            //企业滴授权认证
+            long timeMillis = System.currentTimeMillis();
+
+            Map<String, Object> body = new HashMap<>();
+            body.put("client_id", client_id);
+            body.put("client_secret", client_secret);
+            body.put("grant_type", grant_type);
+            body.put("phone", phone);
+            body.put("timestamp", timeMillis);
+
+            String sign = genSign(body, signKey, 0);
+
+            System.out.println("sign:"+sign);
+            System.out.println("timestamp:" + timeMillis);
+
+            body.put("sign", sign);
+            Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/river/Auth/authorize", null, null, body));
+
+            log.info("result:{}",result);
+
+            accessToken = UtilMap.getString(result, "access_token");
+
+            UtilToken.put("invalid-token-qydd", accessToken, EXPIRES_IN);
+        }
+
+        return accessToken;
+    }
+
+    public static Map BudgetCenterAdd(Map body){
+        body.put("client_id",client_id);
+        body.put("company_id",company_id);
+        body.put("access_token",getToken());
+        body.put("timestamp",System.currentTimeMillis()/1000);
+        String sign = genSign(body, signKey, 0);
+        body.put("sign",sign);
+        String s = UtilHttp.doPost("https://" + host + "/river/BudgetCenter/add", null, null, body);
+
+        log.info("result:{}",s);
+
+        Map result = (Map)JSONObject.parse(s);
+
+        return result;
+    }
+
+    public static Map BudgetCenterEdit(Map body){
+        body.put("client_id",client_id);
+        body.put("company_id",company_id);
+        body.put("access_token",getToken());
+        body.put("timestamp",System.currentTimeMillis()/1000);
+        String sign = genSign(body, signKey, 0);
+        body.put("sign",sign);
+        String s = UtilHttp.doPost("https://" + host + "/river/BudgetCenter/edit", null, null, body);
+
+        log.info("result:{}",s);
+
+        Map result = (Map)JSONObject.parse(s);
+
+        return result;
+    }
+
+    //java md5算法
+    public static String md5(String plainText) {
+        byte[] secretBytes = null;
+        try {
+            MessageDigest md  = MessageDigest.getInstance("MD5");
+            md.update(plainText.getBytes("utf-8"));
+            secretBytes = md.digest();
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("no such algorithm!");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+
+        String md5code = new BigInteger(1, secretBytes).toString(16);
+        int length = md5code.length();
+        for (int i = 0; i < 32 - length; i++) {
+            md5code = "0" + md5code;
+        }
+        return md5code;
+    }
+    //java sha256算法
+    public static String sha256Hex(String input) {
+        try {
+            // 创建一个MessageDigest实例,并指定使用SHA-256算法
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+
+            // 将输入字符串转换为字节数组,并更新摘要
+            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+
+            // 将字节数组转换为十六进制字符串
+            StringBuilder hexString = new StringBuilder();
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) hexString.append('0');
+                hexString.append(hex);
+            }
+
+            return hexString.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String genSign(Map<String, Object> params, String signKey, Integer signMethod) {
+        params.put("sign_key", signKey);
+        String result = "";
+        try {
+            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(params.entrySet());
+            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
+                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
+                    return (o1.getKey()).compareTo(o2.getKey());
+                }
+            });
+            // 构造签名键值对的格式
+            for (Map.Entry<String, Object> item : infoIds) {
+                if (item.getKey() != null || item.getKey() != "") {
+                    String key = item.getKey();
+                    String val = (item.getValue()+"").trim();
+                    if (result == "") {
+                        result += key + "=" + val;
+                    } else {
+                        result += "&" + key + "=" + val;
+                    }
+                }
+            }
+            //System.out.println(result);
+        } catch(Exception e) {
+            throw new RuntimeException("error");
+        }
+        if(signMethod == 1) {
+            return sha256Hex(result);
+        }
+        return md5(result);
+    }
+
+
+}

+ 0 - 8
mjava-siku/src/main/resources/application-dev.yml

@@ -26,14 +26,6 @@ aliwork:
   systemToken: Y2D66JB1A0B2OMK6OMB29AB8VMP43KJ7UCDKMG46
 
 mk:
-  #每刻报销-测试环境
-  bx:
-    appCode: AP52Y01LHHTAP9
-    appSecret: N4WuERLteAUPaWebnsHy
-  #每刻云票-测试环境
-  yp:
-    appCode: AP53EP1SVDS1N9
-    appSecret: qF4nm3nPnyXYcrWcr5jl
   downloadFilePath: d:\\
   downloadUrl: http://localhost:9037/api/siku/
 

+ 1 - 9
mjava-siku/src/main/resources/application-prod.yml

@@ -4,7 +4,7 @@ server:
     context-path: /api/siku
 
 enable:
-  scheduling: false
+  scheduling: true
 logging:
   config: classpath:logback-spring.xml
   path: /home/server/siku/log/
@@ -26,13 +26,5 @@ aliwork:
   systemToken: Y2D66JB1A0B2OMK6OMB29AB8VMP43KJ7UCDKMG46
 
 mk:
-  #每刻报销-测试环境
-  bx:
-    appCode: AP52Y01LHHTAP9
-    appSecret: N4WuERLteAUPaWebnsHy
-  #每刻云票-测试环境
-  yp:
-    appCode: AP53EP1SVDS1N9
-    appSecret: qF4nm3nPnyXYcrWcr5jl
   downloadFilePath: /home/server/siku/file/
   downloadUrl: https://poc.cloudpure.cn/api/siku/

+ 129 - 1
mjava-siku/src/test/java/com.malk.siku/SkTest.java

@@ -1,23 +1,37 @@
 package com.malk.siku;
 
+import com.malk.siku.service.SikuTaskService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
 @Slf4j
 @SpringBootTest
 @RunWith(SpringRunner.class)
 public class SkTest {
+    @Autowired
+    private SikuTaskService sikuTaskService;
+
     @Test
     public void getSecret(){
         //每刻报销-测试环境
         String appCode="AP52Y01LHHTAP9";
         String appSecret="N4WuERLteAUPaWebnsHy";
 
-
+        //每刻报销-生产环境
+        /*String appCode="AP52RG1SCG8S6L";
+        String appSecret="YFTbD2MviqUwztBTbMWd";*/
 
         //每刻云票-测试环境
         /*String appCode="AP53EP1SVDS1N9";
@@ -30,6 +44,120 @@ public class SkTest {
         log.info("s:{}",s);
     }
 
+    @Test
+    public void ssoGetToken(){
+        //生成token所使用的java代码
+        String ssoSecret = "EC52NRFQYEFIB5:h34BITN5HAtVMt82P9VvTRhFYpCXLgfo";//该秘钥获取路径“设置-安全设置-系统安全策略-SSO”(若无此入口,需项目经理在boss系统开通相关许可)
+        long timestamp = System.currentTimeMillis();
+        String userId = "HZ769";
+        String token = DigestUtils.sha256Hex((ssoSecret + ":" + userId + ":" + timestamp).getBytes());
+
+        System.out.println("timestamp:"+timestamp);
+        System.out.println("token:"+token);
+    }
+
+    @Test
+    public void test(){
+        sikuTaskService.syncLoanManage();
+    }
+
+    //java md5算法
+    public static String md5(String plainText)
+    {
+        byte[] secretBytes = null;
+        try {
+            MessageDigest md  = MessageDigest.getInstance("MD5");
+            md.update(plainText.getBytes("utf-8"));
+            secretBytes = md.digest();
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("no such algorithm!");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+
+        String md5code = new BigInteger(1, secretBytes).toString(16);
+        int length = md5code.length();
+        for (int i = 0; i < 32 - length; i++) {
+            md5code = "0" + md5code;
+        }
+        return md5code;
+    }
+    //java sha256算法
+    public static String sha256Hex(String input) {
+        try {
+            // 创建一个MessageDigest实例,并指定使用SHA-256算法
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+
+            // 将输入字符串转换为字节数组,并更新摘要
+            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+
+            // 将字节数组转换为十六进制字符串
+            StringBuilder hexString = new StringBuilder();
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) hexString.append('0');
+                hexString.append(hex);
+            }
+
+            return hexString.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String genSign(HashMap<String, String> params, String signKey, Integer signMethod)
+    {
+        params.put("sign_key", signKey);
+        String result = "";
+        try {
+            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(params.entrySet());
+            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
+                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
+                    return (o1.getKey()).toString().compareTo(o2.getKey());
+                }
+            });
+            // 构造签名键值对的格式
+            for (Map.Entry<String, String> item : infoIds) {
+                if (item.getKey() != null || item.getKey() != "") {
+                    String key = item.getKey();
+                    String val = item.getValue().trim();
+                    if (result == "") {
+                        result += key + "=" + val;
+                    } else {
+                        result += "&" + key + "=" + val;
+                    }
+                }
+            }
+            //System.out.println(result);
+        } catch(Exception e) {
+            throw new RuntimeException("error");
+        }
+        if(signMethod == 1) {
+            return sha256Hex(result);
+        }
+        return md5(result);
+    }
+
+    public static void main (String[] args) throws java.lang.Exception {
+        long l = System.currentTimeMillis() / 1000;
+
+        HashMap<String, String> map = new HashMap<String, String>();
+        map.put("client_id", "3295ee5021a0dd6436d18f56e7c761c6");
+        map.put("client_secret", "fe5539d17722035cba70a2e6220c43a4");
+        map.put("grant_type", "client_credentials");
+        map.put("phone", "18857526310");
+        long currentTimeMillis = System.currentTimeMillis();
+        map.put("timestamp", currentTimeMillis+"");
+
+        String signKey = "038bD3BAb4a25D84dc96";
+        Integer signMethod = 0;
+        String sign = genSign(map, signKey, signMethod);
+        System.out.println("sign:"+sign);
+        System.out.println("timestamp:"+currentTimeMillis);
+    }
+
 
 
 

+ 0 - 1
mjava-tonglibo/pom.xml

@@ -22,7 +22,6 @@
             <groupId>commons-codec</groupId>
             <artifactId>commons-codec</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>

+ 37 - 22
mjava-tonglibo/src/main/java/com/malk/tonglibo/controller/machineController.java

@@ -47,44 +47,51 @@ public class machineController {
             log.info("设备数据paramsStr:{}", paramsStr);
             String fixedStr = repairMalformedKFields(paramsStr);
             JSONObject params = JSONObject.parseObject(fixedStr);
-
             log.info("修复后设备数据JSON:{}", params);
-
-            // 解析时间
             LocalDateTime time;
             try {
                 time = LocalDateTime.parse((String) params.get("time"), FORMATTER);
             } catch (Exception e) {
-                log.warn("时间解析失败,使用当前时间。原值:{}", params.get("time"));
+                log.warn("时间解析失败:{}", params.get("time"));
                 time = LocalDateTime.now();
             }
             String timeStr = time.format(OUTPUT_FORMATTER);
-            String deviceId = params.getString("id");
+            String paramId = params.getString("id");
             Pattern kPattern = Pattern.compile("^k\\d+$");
             boolean hasValidData = false;
-            // 遍历所有 k* 字段,放入缓冲队列
             for (Map.Entry<String, Object> entry : params.entrySet()) {
                 String key = entry.getKey();
                 if (kPattern.matcher(key).matches()) {
                     try {
                         Object dataObj = entry.getValue();
                         if (dataObj instanceof List) {
+                            List<?> rawDataList = (List<?>) dataObj;
                             List<String> data = new ArrayList<>();
-                            for (Object item : (List<?>) dataObj) {
-                                if (item instanceof Number) {
-                                    data.add(item.toString());
-                                } else if (item == null) {
-                                    data.add("null");
+                            // 转换为字符串,并判断是否有有效值
+                            boolean fieldHasValidValue = false;
+                            for (Object item : rawDataList) {
+                                String strVal;
+                                if (item == null) {
+                                    strVal = "null";
                                 } else {
-                                    data.add(item.toString());
+                                    strVal = item.toString().trim();
+                                }
+                                data.add(strVal);
+                                // 判断这个值是否是“有效值”
+                                if (isValidDataValue(strVal)) {
+                                    fieldHasValidValue = true;
                                 }
                             }
-                            // 创建原始数据对象,放入缓冲队列
-                            RawDeviceData raw = new RawDeviceData(deviceId, time, timeStr, key, data);
-                            if (dataBuffer.offer(raw)) {
-                                hasValidData = true;
+                            // 只有当前字段至少有一个有效值,才放入缓冲队列
+                            if (fieldHasValidValue) {
+                                RawDeviceData raw = new RawDeviceData(paramId, time, timeStr, key, data);
+                                if (dataBuffer.offer(raw)) {
+                                    hasValidData = true;
+                                } else {
+                                    log.warn("缓冲队列已满,丢弃数据 设备编号={}, paramId={}", key, paramId);
+                                }
                             } else {
-                                log.warn("缓冲队列已满,丢弃数据 key={}, deviceId={}", key, deviceId);
+                                log.debug("字段 {} 的所有值均为无效(全0或空),跳过:{}", key, data);
                             }
                         }
                     } catch (Exception fieldEx) {
@@ -92,12 +99,15 @@ public class machineController {
                     }
                 }
             }
-            // 立即返回成功,不等待数据库写入
+
+            // ===== 最终判断:是否真的有有效数据 =====
             if (hasValidData) {
                 return McR.success("设备数据接收成功");
             } else {
+                log.warn("设备数据无效:所有 k* 字段均为 0 或空,paramId={}, time={}", paramId, timeStr);
                 return McR.errorParam("未解析到有效数据");
             }
+
         } catch (Exception e) {
             log.error("设备数据同步异常:", e);
             return McR.errorParam("设备数据同步异常");
@@ -113,7 +123,7 @@ public class machineController {
         for(int i = 0; i < machineData.size(); i++){
             MachineData machinedata = (MachineData) machineData.get(i);
             Map map =new HashMap();
-            map.put("content", machinedata.getMachineNo());
+            map.put("content", machinedata.getMachineFlag());
             map.put("value", machinedata.getJqyxsh());
             result.add(map);
         }
@@ -127,7 +137,7 @@ public class machineController {
         for(int i = 0; i < data.size(); i++){
             MachineData machinedata = (MachineData) data.get(i);
             Map map =new HashMap();
-            map.put("s", machinedata.getMachineNo());
+            map.put("s", machinedata.getMachineFlag());
             map.put("y", machinedata.getZcn());
             map.put("x", machinedata.getTimestr());
             result.add(map);
@@ -159,10 +169,15 @@ public class machineController {
         // 1. 修复 "k1":] → "k1":[]
         result = result.replaceAll("(\"k\\d+\"\\s*:\\s*)\\]", "$1[]");
         // 2. 修复 "k1":  → "k1":[]
-        //    (即冒号后直接跟逗号或其他字符,中间无内容)
-        //    先找这种结构:"k1": ,  或 "k1": }
         result = result.replaceAll("(\"k\\d+\"\\s*:\\s*)([\\,\\}])", "$1[]$2");
         return result;
     }
 
+    private boolean isValidDataValue(String value) {
+        if (value == null || value.isEmpty() || "null".equalsIgnoreCase(value)) {
+            return false;
+        }
+        return !value.matches("^0+(\\.0+)?$");
+    }
+
 }

+ 7 - 0
mjava-tonglibo/src/main/java/com/malk/tonglibo/entity/MachineData.java

@@ -39,8 +39,15 @@ public class MachineData {
     private String xjsj;
     private String tssj;
     private String zysj;
+    private String dn;
     @TableField("machineNo")
     private String machineNo;
+    @TableField("machineName")
+    private String machineName;
+    @TableField("machineCode")
+    private String machineCode;
+    @TableField("machineFlag")
+    private String machineFlag;
 
     private String timestr;
 

+ 5 - 4
mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/ChangeDetector.java

@@ -20,10 +20,10 @@ public class ChangeDetector {
      * 判断当前数据是否为新状态(MD5 指纹不同)
      */
     public boolean isChanged(MachineData data) {
-        String paramId = data.getParamId();
+        String machineNo = data.getMachineNo();
         String fingerprint = generateFingerprint(data);
 
-        String lastFingerprint = lastFingerprintMap.get(paramId);
+        String lastFingerprint = lastFingerprintMap.get(machineNo);
         if (lastFingerprint == null) {
             return true; // 第一次上报,算变化
         }
@@ -34,8 +34,8 @@ public class ChangeDetector {
     /**
      * 记录当前指纹为最新状态
      */
-    public void recordAsCurrent(String paramId, String fingerprint) {
-        lastFingerprintMap.put(paramId, fingerprint);
+    public void recordAsCurrent(String machineNo, String fingerprint) {
+        lastFingerprintMap.put(machineNo, fingerprint);
     }
 
     String concatFields(MachineData data) {
@@ -62,6 +62,7 @@ public class ChangeDetector {
                 .append(defaultString(data.getXjsj()))
                 .append(defaultString(data.getTssj()))
                 .append(defaultString(data.getZysj()))
+                .append(defaultString(data.getDn()))
                 .toString();
     }
 

+ 81 - 31
mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/DeviceDataPersistTask.java

@@ -1,7 +1,15 @@
 package com.malk.tonglibo.utils;
 
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.aliwork.YDSearch;
+import com.malk.service.aliwork.YDClient;
 import com.malk.tonglibo.Mapper.MachineDataMapper;
+import com.malk.tonglibo.Mapper.MachineDetailMapper;
 import com.malk.tonglibo.Service.IMachineDataService;
+import com.malk.tonglibo.entity.MachineDetail;
 import com.malk.tonglibo.entity.RawDeviceData;
 import com.malk.tonglibo.entity.MachineData;
 import lombok.extern.slf4j.Slf4j;
@@ -26,12 +34,16 @@ public class DeviceDataPersistTask {
     private MachineDataMapper machineDataMapper;
     @Autowired
     private IMachineDataService machineDataService;
+    @Autowired
+    private MachineDetailMapper machineDetailMapper;
 
     @Autowired
     private DataBuffer dataBuffer;
 
     @Autowired
     private ChangeDetector changeDetector;
+    @Autowired
+    private YDClient ydClient;
 
 
     @Scheduled(fixedDelay = 1000) // 每秒执行一次
@@ -39,29 +51,48 @@ public class DeviceDataPersistTask {
         List<RawDeviceData> dataList = dataBuffer.drain(500);
         if (dataList.isEmpty()) return;
 
-        List<MachineData> toInsert = new ArrayList<>();
-        int unchangedCount = 0;
+        // "machineNo + 分钟"
+        Map<String, MachineData> latestPerMinute = new HashMap<>();
 
         for (RawDeviceData item : dataList) {
             MachineData data = convertToMachineData(item);
-            if (data == null) continue;
+            if (data == null) {
+                log.warn("设备数据转换失败,跳过: {}", item);
+                continue;
+            }
+
+            //生成 key:machineNo + 时间分钟
+            String minuteKey = data.getMachineNo() + "_" +
+                    data.getTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+            // 保留最新的数据
+            MachineData existing = latestPerMinute.get(minuteKey);
+            if (existing == null || data.getTime().isAfter(existing.getTime())) {
+                latestPerMinute.put(minuteKey, data);
+            }
+        }
+
+        //对每分钟最新数据进行 MD5 变化检测
+        List<MachineData> toInsert = new ArrayList<>();
+        int unchangedCount = 0;
 
-            //使用 MD5 判断是否变化
+        for (MachineData data : latestPerMinute.values()) {
             if (changeDetector.isChanged(data)) {
-                String fingerprint = MD5Util.md5(changeDetector.concatFields(data)); // 或在 convert 时生成
+                String fingerprint = MD5Util.md5(changeDetector.concatFields(data));
                 data.setDataFingerprint(fingerprint);
                 toInsert.add(data);
-                changeDetector.recordAsCurrent(data.getParamId(), fingerprint);
+                changeDetector.recordAsCurrent(data.getMachineNo(), fingerprint); // 更新为当前指纹
             } else {
                 unchangedCount++;
             }
         }
 
+        // 批量入库
         if (!toInsert.isEmpty()) {
             machineDataService.saveBatch(toInsert, 100);
-            log.info("入库 {} 条(变化数据),跳过 {} 条未变数据", toInsert.size(), unchangedCount);
+            log.info("入库 {} 条(每设备每分钟最新且变化数据),跳过 {} 条未变数据,原始上报 {} 条",
+                    toInsert.size(), unchangedCount, dataList.size());
         } else if (unchangedCount > 0) {
-            log.debug("跳过 {} 条未变化数据", unchangedCount);
+            log.debug("跳过 {} 条未变化数据(已按分钟合并)", unchangedCount);
         }
     }
 
@@ -81,30 +112,44 @@ public class DeviceDataPersistTask {
 
             // 填充字段(根据索引取值)
             machineData.setJqyxsh(safeGet(data, 0));
-            machineData.setZcn(safeGet(data, 2));
-            machineData.setZqsj(safeGet(data, 4));
-            machineData.setSgdyl(safeGet(data, 6));
-            machineData.setXgdyl(safeGet(data, 8));
-            machineData.setYskqyl1(safeGet(data, 10));
-            machineData.setYskqyl2(safeGet(data, 12));
-            machineData.setZymwd1(safeGet(data, 14));
-            machineData.setZymwd2(safeGet(data, 16));
-            machineData.setZymwd3(safeGet(data, 18));
-            machineData.setZymwd4(safeGet(data, 20));
-            machineData.setSmwd1(safeGet(data, 22));
-            machineData.setSmwd2(safeGet(data, 24));
-            machineData.setSmwd3(safeGet(data, 26));
-            machineData.setSmwd4(safeGet(data, 28));
-            machineData.setXmwd1(safeGet(data, 30));
-            machineData.setXmwd2(safeGet(data, 32));
-            machineData.setXmwd3(safeGet(data, 34));
-            machineData.setXmwd4(safeGet(data, 36));
-            machineData.setXjsj(safeGet(data, 38));
-            machineData.setTssj(safeGet(data, 40));
-            machineData.setZysj(safeGet(data, 42));
+            machineData.setZcn(safeGet(data, 1));
+            machineData.setDn(safeGet(data, 2));
+            machineData.setZqsj(safeGet(data, 3));
+            machineData.setSgdyl(safeGet(data, 4));
+            machineData.setXgdyl(safeGet(data, 5));
+            machineData.setYskqyl1(safeGet(data, 6));
+            machineData.setYskqyl2(safeGet(data, 7));
+            machineData.setZymwd1(safeGet(data, 8));
+            machineData.setZymwd2(safeGet(data, 9));
+            machineData.setZymwd3(safeGet(data, 10));
+            machineData.setZymwd4(safeGet(data, 11));
+            machineData.setSmwd1(safeGet(data, 12));
+            machineData.setSmwd2(safeGet(data, 13));
+            machineData.setSmwd3(safeGet(data, 14));
+            machineData.setSmwd4(safeGet(data, 15));
+            machineData.setXmwd1(safeGet(data, 16));
+            machineData.setXmwd2(safeGet(data, 17));
+            machineData.setXmwd3(safeGet(data, 18));
+            machineData.setXmwd4(safeGet(data, 19));
+            machineData.setXjsj(safeGet(data, 20));
+            machineData.setTssj(safeGet(data, 21));
+            machineData.setZysj(safeGet(data, 22));
+            List<MachineDetail> machineList = machineDetailMapper.selectList(new QueryWrapper<MachineDetail>().eq("machine_no", key));
+            if (machineList != null && !machineList.isEmpty()){
+                MachineDetail yidaParam = machineList.get(0);
+                String machineName = yidaParam.getMachineName();
+                String machineCode = yidaParam.getMachineCode();
+                String machineFlag = yidaParam.getMachineFlag();
+                if (machineName != null) {
+                    machineData.setMachineName(machineName);
+                    machineData.setMachineCode(machineCode);
+                    machineData.setMachineFlag(machineFlag);
+                } else {
+                    log.warn("未在宜搭中找到设备编号 {} 对应的名称,使用默认值", key);
+                }
+            }
 
             return machineData;
-
         } catch (Exception e) {
             log.error("转换数据失败: {}", item, e);
             return null;
@@ -114,7 +159,12 @@ public class DeviceDataPersistTask {
     // 安全获取索引值
     private String safeGet(List<String> list, int index) {
         if (index >= 0 && index < list.size()) {
-            return list.get(index);
+            String value = list.get(index);
+            // 切割掉 . 后面的数据
+            if (value != null) {
+                String[] parts = value.split("\\.");
+                return parts[0]; // 返回点号前面的部分
+            }
         }
         return "";
     }

+ 5 - 4
mjava-tonglibo/src/main/resources/application-dev.yml

@@ -32,13 +32,14 @@ logging:
 # dingtalk
 dingtalk:
   agentId: 3914874648
-  appKey: dingyedbqoqricilvyog
-  appSecret: CAPT0hNRO5y-rHp81fmzMHz4LXYJhzkHqG1kh1L6OdM_LQPANR9IOoLtJrNLPVCc
+  appKey: dinggps3rba7eb9cexqe
+  appSecret: pjiEz7AR8Meov0tui7-lJ00oQRxGDWAnIKxS_uH7HDe9rop7H2ZdmW1tDuqaEH_F
   corpId: dingf11f7d6ff834577b
   aesKey: UqJRA1RTxarywiIWOK76BN8BSLfAN4gTDo6nEco4sqG
   token: CpR7AsWa026FQV5VBNU5YrO5
 
 aliwork:
-  appType: APP_HJJ3X3QN4WEWDHU2BJR2
-  systemToken: 7X866C81QPIHJKBFFM1QW4S8BV1U3U4MFO5RLY1
+  appType: APP_C83FAK1HS55UIQLP1MBX
+  systemToken: K4666XA1ZQ5O2PYSAKA7M4ZQAFPX3KYNUEK0MZT9
+
 

+ 4 - 4
mjava-tonglibo/src/main/resources/application-prod.yml

@@ -28,13 +28,13 @@ mybatis-plus:
 # dingtalk
 dingtalk:
   agentId: 3914874648
-  appKey: dingyedbqoqricilvyog
-  appSecret: CAPT0hNRO5y-rHp81fmzMHz4LXYJhzkHqG1kh1L6OdM_LQPANR9IOoLtJrNLPVCc
+  appKey: dinggps3rba7eb9cexqe
+  appSecret: pjiEz7AR8Meov0tui7-lJ00oQRxGDWAnIKxS_uH7HDe9rop7H2ZdmW1tDuqaEH_F
   corpId: dingf11f7d6ff834577b
   aesKey: UqJRA1RTxarywiIWOK76BN8BSLfAN4gTDo6nEco4sqG
   token: CpR7AsWa026FQV5VBNU5YrO5
 
 aliwork:
-  appType: APP_HJJ3X3QN4WEWDHU2BJR2
-  systemToken: 7X866C81QPIHJKBFFM1QW4S8BV1U3U4MFO5RLY1
+  appType: APP_C83FAK1HS55UIQLP1MBX
+  systemToken: K4666XA1ZQ5O2PYSAKA7M4ZQAFPX3KYNUEK0MZT9
 

+ 27 - 23
mjava-tonglibo/src/main/resources/mapper/MachineDataMapper.xml

@@ -9,6 +9,7 @@
         SELECT
             paramId,
             machineNo,
+            machineFlag,
             jqyxsh,
             zcn,
             timeStr,
@@ -17,6 +18,7 @@
                  SELECT
                      paramId,
                      machineNo,
+                     machineFlag,
                      zcn,
                      timeStr,
                      jqyxsh,
@@ -57,12 +59,14 @@
         SELECT
             date,
             machineNo,
+            machineFlag,
             zcn,
             timeStr
         FROM (
             SELECT
             DATE(time) AS date,
             machineNo AS machineNo,
+            machineFlag,
             zcn,
             timeStr,
             ROW_NUMBER() OVER (PARTITION BY DATE(time), machineNo ORDER BY time ASC) AS rn
@@ -76,34 +80,34 @@
     </select>
 
     <select id="selectDailyShiftOutput" resultType="map">
-        SELECT
-        CASE
-        WHEN HOUR(time) < 8 THEN DATE_SUB(DATE(time), INTERVAL 1 DAY)
-        ELSE DATE(time)
-        END AS date,
+<!--        SELECT-->
+<!--        CASE-->
+<!--        WHEN HOUR(time) < 8 THEN DATE_SUB(DATE(time), INTERVAL 1 DAY)-->
+<!--        ELSE DATE(time)-->
+<!--        END AS date,-->
 
-        CASE
-        WHEN HOUR(time) >= 8 AND HOUR(time) < 16 THEN '早班'
-        WHEN HOUR(time) >= 16 THEN '中班'
-        ELSE '晚班'
-        END AS shift,
+<!--        CASE-->
+<!--        WHEN HOUR(time) >= 8 AND HOUR(time) < 16 THEN '早班'-->
+<!--        WHEN HOUR(time) >= 16 THEN '中班'-->
+<!--        ELSE '晚班'-->
+<!--        END AS shift,-->
 
-        SUM(CAST(zcn AS DECIMAL(10,2))) AS output
+<!--        SUM(CAST(zcn AS DECIMAL(10,2))) AS output-->
 
-        FROM T_TLB_MACHINEDATA
-        WHERE zcn REGEXP '^[0-9]+(\\.[0-9]+)?$'
-        AND time >= #{startDate}
-        AND time &lt; #{endDate}
+<!--        FROM T_TLB_MACHINEDATA-->
+<!--        WHERE zcn REGEXP '^[0-9]+(\\.[0-9]+)?$'-->
+<!--        AND time >= #{startDate}-->
+<!--        AND time &lt; #{endDate}-->
 
-        GROUP BY
-        CASE WHEN HOUR(time) < 8 THEN DATE_SUB(DATE(time), INTERVAL 1 DAY) ELSE DATE(time) END,
-        CASE
-        WHEN HOUR(time) >= 8 AND HOUR(time) < 16 THEN '早班'
-        WHEN HOUR(time) >= 16 THEN '中班'
-        ELSE '晚班'
-        END
+<!--        GROUP BY-->
+<!--        CASE WHEN HOUR(time) < 8 THEN DATE_SUB(DATE(time), INTERVAL 1 DAY) ELSE DATE(time) END,-->
+<!--        CASE-->
+<!--        WHEN HOUR(time) >= 8 AND HOUR(time) < 16 THEN '早班'-->
+<!--        WHEN HOUR(time) >= 16 THEN '中班'-->
+<!--        ELSE '晚班'-->
+<!--        END-->
 
-        ORDER BY date, FIELD(shift, '早班', '中班', '晚班')
+<!--        ORDER BY date, FIELD(shift, '早班', '中班', '晚班')-->
     </select>
 
 </mapper>

+ 14 - 5
mjava-zhiwei/src/main/java/com/malk/zhiwei/schedule/ScheduleTask.java

@@ -108,13 +108,14 @@ public class ScheduleTask {
     }
 
     //销售订单同步
+    @SneakyThrows
     @Scheduled(cron = "0 15 1 * * ?")
     @PostMapping("/purchaseOrder")
     public void purchaseOrder() throws JsonProcessingException {
         zwService.purchaseOrder();
     }
 
-    //出库单(发货通知单)
+    //出库单(发货通知单)同步
     @SneakyThrows
     @Scheduled(cron = "0 30 1 * * ?")
     @PostMapping("/deliveryOrder")
@@ -122,7 +123,7 @@ public class ScheduleTask {
         zwService.deliveryOrder();
     }
 
-    //退货单
+    //退货单同步
     @SneakyThrows
     @Scheduled(cron = "0 45 1 * * ?")
     @PostMapping("/returnForm")
@@ -130,7 +131,7 @@ public class ScheduleTask {
         zwService.returnForm();
     }
 
-    //补货单
+    //补货单同步
     @SneakyThrows
     @Scheduled(cron = "0 0 2 * * ?")
     @PostMapping("/replenishmentOrder")
@@ -138,7 +139,7 @@ public class ScheduleTask {
         zwService.replenishmentOrder();
     }
 
-    //开票单
+    //开票单同步
     @SneakyThrows
     @Scheduled(cron = "0 15 2 * * ?")
     @PostMapping("/invoice")
@@ -146,7 +147,7 @@ public class ScheduleTask {
         zwService.invoice();
     }
 
-    //应收单
+    //应收单同步
     @SneakyThrows
     @Scheduled(cron = "0 30 2 * * ?")
     @PostMapping("/receivableNote")
@@ -154,4 +155,12 @@ public class ScheduleTask {
         zwService.receivableNote();
     }
 
+    //客户同步
+    @SneakyThrows
+//    @Scheduled(cron ="0 0 3 * * ?")
+    @PostMapping("/customer")
+    public void customer(){
+        zwService.customer();
+    }
+
 }

+ 3 - 0
mjava-zhiwei/src/main/java/com/malk/zhiwei/service/ZwService.java

@@ -41,4 +41,7 @@ public interface ZwService {
     //应收单
     void receivableNote() throws JsonProcessingException;
 
+    //同步客户
+    void customer() throws JsonProcessingException;
+
 }

+ 99 - 3
mjava-zhiwei/src/main/java/com/malk/zhiwei/service/impl/ZwServiceImpl.java

@@ -1,6 +1,7 @@
 package com.malk.zhiwei.service.impl;
 
 import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -12,9 +13,13 @@ import com.kingdee.bos.webapi.sdk.K3CloudApi;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.common.McR;
+import com.malk.server.common.VenR;
 import com.malk.server.dingtalk.DDConf;
+import com.malk.server.dingtalk.DDR;
 import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
 import com.malk.utils.PublicUtil;
+import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import com.malk.zhiwei.config.KDWebApiConf;
 import com.malk.zhiwei.entity.BillQuery;
@@ -27,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
@@ -38,6 +44,8 @@ public class ZwServiceImpl implements ZwService {
     private YDConf ydConf;
     @Autowired
     private DDConf ddConf;
+    @Autowired
+    private DDClient ddClient;
 
     private static String ERP_URL="http://10.0.0.208:80";
     private static String ERP_NAME="064";
@@ -248,9 +256,10 @@ public class ZwServiceImpl implements ZwService {
         BillQuery billQuery = new BillQuery();
         billQuery.setFormId("BD_MATERIAL");//产品信息
         //编码 名称 规格型号 旧物料编码 物料分组 物料属性 基本单位 长 宽 高 体积 面积 密度 标准工时
-        billQuery.setFieldKeys("FNumber,FName,FSpecification,FOldNumber,FMaterialGroup,FErpClsID,FBaseUnitId,FLENGTH,FWIDTH,FHEIGHT,FVOLUME,F_UNW_Qty_r03,F_UNW_Qty_6yt,FPerUnitStandHour");
+        billQuery.setFieldKeys("FCreateOrgId.FNumber,FApproveDate,FNumber,FName,FSpecification,FOldNumber,FMaterialGroup,FErpClsID,FBaseUnitId,FLENGTH,FWIDTH,FHEIGHT,FVOLUME,F_UNW_Qty_r03,F_UNW_Qty_6yt,FPerUnitStandHour");
         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","FApproveDate","265",3,"","","0"));//审核日期在今天之前N天以后
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FCreateOrgId.FNumber","67","101","","","0"));//创建组织为101 研发中心
         billQuery.setFilterString(filterString);
         billQuery.setLimit(limit);
         billQuery.setStartRow(startRow);
@@ -472,7 +481,7 @@ public class ZwServiceImpl implements ZwService {
         //[明细表] FMapId客户物料编码  FMapName客户物料名称  FMaterialId物料编码  FMaterialName物料名称  FMaterialModel型号规格  FF100001厚度  FSalUnitID销售单位  FSalUnitQty销售数量  FIsFree是否赠品  FDeliveryDate退货日期  FReturnType退货类型  FPrice单价 FTaxPrice含税单价  FNote备注
         billQuery.setFieldKeys("FBillNo,FDate,FRetcustId.FName,FSettleCurrId.FName,FSaleOrgId.FName,FSaledeptid.FName,FSalesManId.FName,FMapId.FNumber,FMapName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FAuxpropId.FF100001,FSalUnitID.FName,FSalUnitQty,FIsFree,FDeliveryDate,FReturnType.FDataValue,FPrice,FTaxPrice,FNote");
         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","FApproveDate","265",30,"","","0"));//审核日期在今天之前N天以后
         billQuery.setFilterString(filterString);
         billQuery.setLimit(limit);
         billQuery.setStartRow(startRow);
@@ -876,6 +885,79 @@ public class ZwServiceImpl implements ZwService {
         log.info("应收单(无发票号)已同步,共处理 {} 张单据", orderList.size());
     }
 
+    @SneakyThrows
+    @Override
+    public void customer() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("BD_Customer");//客户
+        //客户编码 客户名称 业务员 销售员 销售部门 收款条件 行业 事业部 终端 纳税人登记号
+        billQuery.setFieldKeys("FNumber,FName,F_UNW_Text_6mb,FSELLER.FName,FSALDEPTID.FName,FRECCONDITIONID.FName,F_UNW_Assistant_mo2.FDataValue,F_UNW_Assistant_9zp.FNumber,F_UNW_Assistant_qov.FNumber,FTAXREGISTERCODE");
+        List<Map> filterString = new ArrayList<>();
+//        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",3,"","","0"));//审核日期在今天之前N天以后
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FCreateOrgId.FNumber","67","100","","","0"));//创建组织为100 宁波致微新材料科技有限公司
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+        // 遍历每条物料记录
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+
+            // 取出各个字段(注意类型转换)
+            String bm = item.getString("FNumber");//客户编码
+            String khmc = item.getString("FName");//客户名称
+
+            String ywy = item.getString("F_UNW_Text_6mb");//业务员
+            Map body = new HashMap();
+            body.put("queryWord",ywy);
+            body.put("offset",0);
+            body.put("size",10);
+            body.put("fullMatchField",1);
+            String doPost = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/users/search", ddClient.initTokenHeader(), null, body);
+            JSONObject resp = JSON.parseObject(doPost);
+            JSONArray ywy_array = resp != null ? resp.getJSONArray("list") : null;
+
+            String xsbm = item.getString("FSALDEPTID.FName");//销售部门
+            Map body_A = new HashMap();
+            body_A.put("queryWord",xsbm);
+            body_A.put("offset",0);
+            body_A.put("size",10);
+            // 获取部门搜索结果
+            String doPost_A = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/departments/search", ddClient.initTokenHeader(), null, body_A);
+            JSONObject respA = JSON.parseObject(doPost_A);
+            JSONArray aaary = respA != null ? respA.getJSONArray("list") : null;
+            List<String> xsbm_array = new ArrayList<>();
+            if (aaary != null && !aaary.isEmpty()) {
+                xsbm_array = aaary.stream()
+                        .map(Object::toString)
+                        .collect(Collectors.toList());
+            }
+// 如果未查到部门,xsbm_array 保持为空列表
+
+            String sktj = item.getString("FRECCONDITIONID.FName");//收款条件
+            String hy = item.getString("F_UNW_Assistant_mo2.FDataValue");//行业
+            String syb = item.getString("F_UNW_Assistant_9zp.FNumber");//事业部
+            String zd = item.getString("F_UNW_Assistant_qov.FNumber");//终端
+            String sh = item.getString("FTAXREGISTERCODE");//纳税登记号
+            //TODO:向宜搭插入数据
+//            String sc = "textField_mnr290ot, employeeField_lqanqe6n_id, employeeField_lqanqe6n_id, departmentSelectField_lympbaya, selectField_mnft99uc, selectField_lqanqe6t, selectField_mnft99ud, selectField_mnft99ue,textField_mn2k7pjl,textField_llujklkq";
+            String sc = "textField_mnr290ot, textField_lqanqe6j, employeeField_lqanqe6n, departmentSelectField_lympbaya, selectField_lqanqe6t, selectField_mnft99uc, selectField_mnft99ud, selectField_mnft99ue, textField_mn2k7pjl, textField_llujklkq";
+            List<Map> conditions = Arrays.asList( YDConf.searchCondition_TextFiled("textField_lqanqe6j", khmc, "eq"));//根据客户名称
+            Map formData = UtilMap.map(sc,bm,khmc,ywy_array,xsbm_array,hy,sktj,syb,zd,sh,sh);
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-A4C9F5F35B48419A9C607D3408ECAB02A7FL")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(formData))
+                    .build(),YDConf.FORM_OPERATION.upsert);
+
+        }
+        log.info("客户已同步");
+    }
+
 
     private McR saveToAudit(String formid, Object object) throws Exception {
         JSONObject resultObj = new JSONObject();
@@ -918,4 +1000,18 @@ public class ZwServiceImpl implements ZwService {
 
         return iden;
     }
+
+
+    /*TODO:钉钉获取应用token*/
+    public McR Accesstoken() throws JsonProcessingException{
+        HashMap body = new HashMap();
+        body.put("appKey","dinga81qkwb0sqxqnviw");
+        body.put("appSecret","IvePeLbMMxAzIr228RaGcOxgSSOuJ0trbenX3BbahjeLFA2YeaFv0W9F_6Ar5G0P");
+        String doGet = UtilHttp.doPost("https://oapi.dingtalk.com/v1.0/oauth2/accessToken", null, null,body);
+        JSONObject jsonObject = JSONObject.parseObject(doGet);
+        String accessToken = jsonObject.getString("access_token");
+        log.info("accessToken:{}",accessToken);
+        return McR.success(accessToken);
+    }
+
 }

+ 3 - 3
mjava-zhiwei/src/main/resources/application-prod.yml

@@ -13,9 +13,9 @@ logging:
 
 # dingtalk
 dingtalk:
-  agentId: 2691784047
-  appKey: dinghbynhnd2dbgypmsa
-  appSecret: Kl5Xw8x0TlEIlvcJuUkYZD18UTTShJmfdKrAIpY8oX-Q_tazyUKA28nQh7dG5-mq
+  agentId: 4457395865
+  appKey: ding2ru5r5d2vtaqf67m
+  appSecret: nuxuhb23-XX26_P5fP8Kbv43R3SzCiEhxkt4hQ_p44XA8r6hR3UkgLrTeXxRH_RA
   corpId:
   aesKey:
   token:

+ 13 - 1
mjava-zhiwei/src/test/java/com/malk/zhiwei/JdTest.java

@@ -12,8 +12,11 @@ import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDSearch;
 import com.malk.server.common.McR;
+import com.malk.server.dingtalk.DDR;
 import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
 import com.malk.utils.PublicUtil;
+import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import com.malk.zhiwei.config.KDWebApiConf;
 import com.malk.zhiwei.entity.*;
@@ -33,6 +36,8 @@ public class JdTest {
 
     @Autowired
     private KDWebApiConf kdWebApiConf;
+    @Autowired
+    private DDClient ddClient;
 
     @Autowired
     private YDClient ydClient;
@@ -192,9 +197,16 @@ public class JdTest {
 
     @Test
     public void queryOrder2(){
-
+        Map body = new HashMap();
+        body.put("queryWord","李英");
+        body.put("offset",0);
+        body.put("size",10);
+        body.put("fullMatchField",1);
+        DDR ddr  = (DDR) UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/users/search", ddClient.initTokenHeader(), new HashMap<>(), body, DDR.class);
+        System.out.println(ddr);
     }
 
 
 
+
 }

+ 6 - 0
mjava-zhongche/src/main/java/com/malk/zhongche/controller/ZhongcheController.java

@@ -26,4 +26,10 @@ public class ZhongcheController {
     public McR updateTaskDelayInfo(@RequestBody Map map){
         return zhongcheService.updateTaskDelayInfo(map);
     }
+
+    //更新父任务任务类型
+    @PostMapping("/updateParentTaskType")
+    public McR updateParentTaskType(@RequestBody Map map){
+        return zhongcheService.updateParentTaskType(map);
+    }
 }

+ 4 - 0
mjava-zhongche/src/main/java/com/malk/zhongche/service/ZhongcheService.java

@@ -9,4 +9,8 @@ public interface ZhongcheService {
 
     McR updateTaskDelayInfo(Map map);
 
+    McR updateParentTaskType(Map map);
+
+    void updateLastTaskSfc();
+
 }

+ 215 - 32
mjava-zhongche/src/main/java/com/malk/zhongche/service/impl/ZhongcheServiceImpl.java

@@ -1,6 +1,8 @@
 package com.malk.zhongche.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.common.McR;
@@ -9,9 +11,12 @@ import com.malk.service.aliwork.YDClient;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.service.dingtalk.DDClient_Contacts;
 import com.malk.service.teambition.TBClient;
+import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
+import com.malk.utils.UtilToken;
 import com.malk.zhongche.service.ZhongcheService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -71,20 +76,20 @@ public class ZhongcheServiceImpl implements ZhongcheService {
 
         String executorId = UtilMap.getString(taskInfo, "executorId");//执行者id
 
-        Map ddUserInfo = tbClient.idMapQuery(executorId, true).get(0);
-
-        Map extra = UtilMap.getMap(ddUserInfo, "extra");
-
-        String ddUserId = UtilMap.getString(extra, "userId");//执行人钉钉userid
-        Map userInfoById = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(),ddUserId);
-        String ddUserName = UtilMap.getString(userInfoById, "name");//执行人钉钉姓名
         Map ddUser = new HashMap();
-        ddUser.put("label",ddUserName);
-        ddUser.put("value",ddUserId);
-        ddUser.put("emplId",ddUserId);
+        if (Strings.isNotBlank(executorId)){
+            Map ddUserInfo = tbClient.idMapQuery(executorId, true).get(0);
+            Map extra = UtilMap.getMap(ddUserInfo, "extra");
+            String ddUserId = UtilMap.getString(extra, "userId");//执行人钉钉userid
+            Map userInfoById = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(),ddUserId);
+            String ddUserName = UtilMap.getString(userInfoById, "name");//执行人钉钉姓名
+            ddUser.put("label",ddUserName);
+            ddUser.put("value",ddUserId);
+            ddUser.put("emplId",ddUserId);
+        }
 
-        long startDate = extracted(UtilMap.getString(taskInfo, "startDate"));//任务开始时间
-        long dueDate = extracted(UtilMap.getString(taskInfo, "dueDate"));//任务截止时间
+        Long startDate = extracted(UtilMap.getString(taskInfo, "startDate"));//任务开始时间
+        Long dueDate = extracted(UtilMap.getString(taskInfo, "dueDate"));//任务截止时间
 
         String tfsId = UtilMap.getString(taskInfo, "tfsId");//任务状态id
 
@@ -93,15 +98,18 @@ public class ZhongcheServiceImpl implements ZhongcheService {
         Map tfsInfo = tbClient.queryProjectCustomFlowStatus(projectId, body).get(0);
         String tfsName = UtilMap.getString(tfsInfo, "name");//任务状态
 
-
-        //获取tb任务上级任务
         String parentTaskId = UtilMap.getString(taskInfo, "parentTaskId");
-        Map parentTaskInfo = tbClient.queryTaskDetail(parentTaskId, null, null).get(0);
-        String parentTaskName = UtilMap.getString(parentTaskInfo, "content");
+        String parentTaskName = "";
+        String rootTaskName = "";
+        if (Strings.isNotBlank(parentTaskId)){
+            //获取tb任务上级任务
+            Map parentTaskInfo = tbClient.queryTaskDetail(parentTaskId, null, null).get(0);
+            parentTaskName = UtilMap.getString(parentTaskInfo, "content");
 
-        //获取tb顶级任务
-        Map rootTaskInfo = getRootTask(parentTaskId);
-        String rootTaskName = UtilMap.getString(rootTaskInfo, "content");
+            //获取tb顶级任务
+            Map rootTaskInfo = getRootTask(parentTaskId);
+            rootTaskName = UtilMap.getString(rootTaskInfo, "content");
+        }
 
         Map result = new HashMap();
         result.put("wtls", wtls);
@@ -127,6 +135,7 @@ public class ZhongcheServiceImpl implements ZhongcheService {
         String projectId = UtilMap.getString(formData, "textField_mkkrgg8u");//项目id
         String taskId = UtilMap.getString(formData, "textField_mkkrgg8y");//任务id
         long dueDate = UtilMap.getLong(formData, "dateField_mn757w7y");//预计完成时间
+        List<String> questionTypes = UtilMap.getList(formData, "multiSelectField_mn757w7v");//任务类型
 
         Map taskInfo = tbClient.queryTaskDetail(taskId, null, null).get(0);
 
@@ -177,9 +186,108 @@ public class ZhongcheServiceImpl implements ZhongcheService {
 
         log.info("map1:{}",JSONObject.toJSONString(map1));
 
+        //更新任务问题类型
+        Map body2 = new HashMap();
+        body2.put("customfieldId", "6941202e92136abe2d9de68f");
+        List<Map> value2 = new ArrayList<>();
+        for (String questionType : questionTypes) {
+            Map map3 = new HashMap();
+            map3.put("title", questionType);
+            value2.add(map3);
+        }
+        body2.put("value",value2);
+
+        Map map2 = tbClient.updateTaskCustomField(taskId, tbConf.getOperatorId(), body2);
+
+        log.info("map1:{}",JSONObject.toJSONString(map1));
+
         return McR.success();
     }
 
+    @Override
+    public McR updateParentTaskType(Map map) {
+        log.info("更新父任务任务类型:{}",JSONObject.toJSONString(map));
+        String taskId = UtilMap.getString(map, "taskId");
+
+        Map taskInfo = tbClient.queryTaskDetail(taskId, null, null).get(0);
+
+        String parentTaskId = UtilMap.getString(taskInfo, "parentTaskId");
+
+        Map parentTaskInfo = tbClient.queryTaskDetail(parentTaskId, null, null).get(0);
+
+        String projectId = UtilMap.getString(parentTaskInfo, "projectId");
+        String sfcId = UtilMap.getString(parentTaskInfo, "sfcId");
+
+        //获取项目任务类型
+        List<Map> result = searchProjectSfc(projectId);
+
+        String sfcId2 = "";//任务(企业)
+        String sfcId3 = "";//末级任务(企业)
+
+        for (Map resultMap : result) {
+            String name = UtilMap.getString(resultMap, "name");
+            String id = UtilMap.getString(resultMap, "id");
+
+            switch (name){
+                case "任务(企业)":sfcId2 = id;break;
+                case "末级任务(企业)":sfcId3 = id;break;
+                default:break;
+            }
+        }
+
+        //若父任务任务类型为末级任务(企业),更新为任务(企业)
+        if (sfcId.equals(sfcId3)){
+            updateTaskSfc(parentTaskId, sfcId2);
+        }
+
+        return McR.success();
+    }
+
+    @Override
+    public void updateLastTaskSfc() {
+        List<String> projectIds = searchProject();
+
+        for (String projectId : projectIds) {
+            if (!"69e1fcd4c41c37563c72888e".equals(projectId)) continue;
+
+            String sfcId = "";//末级任务(企业)
+            String sfcId2 = "";//任务(企业)
+
+            //获取项目任务类型
+            List<Map> result = searchProjectSfc(projectId);
+            for (Map resultMap : result) {
+                String name = UtilMap.getString(resultMap, "name");
+                String id = UtilMap.getString(resultMap, "id");
+
+                switch (name){
+                    case "任务(企业)":sfcId2 = id;break;
+                    case "末级任务(企业)":sfcId = id;break;
+                    default:break;
+                }
+            }
+
+            //查询项目下所有非顶级任务且任务类型为任务(企业)
+            List<Map> taskList = tbClient.queryProjectTaskList(projectId, UtilMap.map("q, pageSize", "taskLayer = exceptTopLevel AND scenarioId = " + sfcId2, 1000), null);
+
+            //遍历所有任务,查询末级任务
+            for (Map task : taskList) {
+                String taskId = UtilMap.getString(task, "id");
+
+                //查询该任务是否有子任务
+                List<Map> sonTaskList = tbClient.queryTaskDetail(null, null, taskId);
+
+                if (sonTaskList.isEmpty()){
+                    //更新任务类型为末级任务(企业)
+                    updateTaskSfc(taskId, sfcId);
+                }
+            }
+
+
+
+
+        }
+    }
+
     private Map getRootTask(String taskId) {
         Map taskInfo = tbClient.queryTaskDetail(taskId, null, null).get(0);
 
@@ -193,22 +301,97 @@ public class ZhongcheServiceImpl implements ZhongcheService {
     }
 
     //转换时区并返回时间戳
-    private static long extracted(String dueDate) {
-        // 1. 解析为 Instant(UTC 时间)
-        Instant instant = Instant.parse(dueDate);
+    private static Long extracted(String dateStr) {
+        if (Strings.isNotBlank(dateStr)){
+            // 1. 解析为 Instant(UTC 时间)
+            Instant instant = Instant.parse(dateStr);
+
+            // 2. 转换为目标时区(Asia/Shanghai, UTC+8)
+            ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
+            ZonedDateTime shanghaiTime = instant.atZone(shanghaiZone);
+
+            // 3. 转换为时间戳(毫秒)
+            long timestamp = shanghaiTime.toInstant().toEpochMilli();
+
+            // 输出结果
+            System.out.println("UTC 时间: " + instant);
+            System.out.println("上海时间: " + shanghaiTime);
+            System.out.println("时间戳(毫秒): " + timestamp);
+
+            return timestamp;
+        }else {
+            return null;
+        }
+
+    }
+
+    private static final Long EXPIRES_IN = 7200000L;
+
+    private String getAccessToken() {
+            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;
+            }
+
+    }
+
+    private Map<String, String> initHeaderToken() {
+        Map header = new HashMap();
+        header.put("Authorization", getAccessToken());
+        header.put("X-Tenant-Id", tbConf.getTenantId());
+        header.put("X-Tenant-Type", "organization");
+        return header;
+    }
+
+    // 操作者ID: 若是查询, 以操作人视角作为权限
+    private Map<String, String> initHeaderToken(String operatorId) {
+        Map header = initHeaderToken();
+        header.put("x-operator-id", operatorId);
+        return header;
+    }
+
+    //搜索项目任务类型
+    private List<Map> searchProjectSfc(String projectId) {
+        String s = UtilHttp.doGet("https://open.teambition.com/api/v3/project/" + projectId + "/scenariofieldconfig/search", initHeaderToken(), UtilMap.map("objectTypes", "task"));
+        Map result = (Map) JSONObject.parse(s);
+
+        log.info("result:{}",result);
+
+        List<Map> list = UtilMap.getList(result, "result");
+
+        return list;
+    }
+
+    //更新任务的任务类型
+    private Map updateTaskSfc(String taskId, String sfcId) {
+        String s = UtilHttp.doPut("https://open.teambition.com/api/v3/task/" + taskId + "/sfc/update", initHeaderToken(tbConf.getOperatorId()), null, UtilMap.map("sfcId", sfcId));
+
+        Map result = (Map) JSONObject.parse(s);
+
+        log.info("result:{}",result);
+
+        return result;
+    }
+
+    //通过TQL搜索项目
+    private List<String> searchProject() {
+        String s = UtilHttp.doGet("https://open.teambition.com/api/project/search", initHeaderToken(tbConf.getOperatorId()), UtilMap.map("pageSize", 100));
 
-        // 2. 转换为目标时区(Asia/Shanghai, UTC+8)
-        ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
-        ZonedDateTime shanghaiTime = instant.atZone(shanghaiZone);
+        Map result = (Map) JSONObject.parse(s);
 
-        // 3. 转换为时间戳(毫秒)
-        long timestamp = shanghaiTime.toInstant().toEpochMilli();
+        log.info("result:{}",result);
 
-        // 输出结果
-        System.out.println("UTC 时间: " + instant);
-        System.out.println("上海时间: " + shanghaiTime);
-        System.out.println("时间戳(毫秒): " + timestamp);
+        List<String> list = UtilMap.getList(result, "result");
 
-        return timestamp;
+        return list;
     }
 }

+ 19 - 0
mjava-zhongche/src/test/java/com/malk/zhongche/ZcTest.java

@@ -1,4 +1,23 @@
 package com.malk.zhongche;
 
+import com.malk.zhongche.service.ZhongcheService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@Slf4j
+@SpringBootTest
+@RunWith(SpringRunner.class)
 public class ZcTest {
+    @Autowired
+    private ZhongcheService zhongcheService;
+
+    @Test
+    //刷新所有项目末级任务的任务类型
+    public void test(){
+        zhongcheService.updateLastTaskSfc();
+    }
 }