瀏覽代碼

Merge branch 'master' of https://mc.cloudpure.cn/mjava/cont

# Conflicts:
#	mjava-mc/src/main/java/com/malk/mc/service/McYdService.java
#	mjava-mc/src/main/java/com/malk/mc/service/impl/McYdServiceImpl.java
wzy 5 月之前
父節點
當前提交
3253aba24d
共有 45 個文件被更改,包括 2558 次插入43 次删除
  1. 87 0
      mjava-chuizi/pom.xml
  2. 17 0
      mjava-chuizi/src/main/java/com/malk/chuizi/ChuiZiApplication.java
  3. 22 0
      mjava-chuizi/src/main/java/com/malk/chuizi/common/SeqHelper.java
  4. 24 0
      mjava-chuizi/src/main/java/com/malk/chuizi/config/KDWebApiConf.java
  5. 29 0
      mjava-chuizi/src/main/java/com/malk/chuizi/config/KDWebApiConfig.java
  6. 29 0
      mjava-chuizi/src/main/java/com/malk/chuizi/controller/ChuiziController.java
  7. 22 0
      mjava-chuizi/src/main/java/com/malk/chuizi/controller/DDController.java
  8. 83 0
      mjava-chuizi/src/main/java/com/malk/chuizi/delegate/DDDelegate.java
  9. 22 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/AccountsPayableEntity.java
  10. 26 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/Audit.java
  11. 18 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/BillQuery.java
  12. 15 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/BillTypeID.java
  13. 33 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/Customer.java
  14. 25 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/DefectEntity.java
  15. 15 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/FNumber.java
  16. 63 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/ForecastEntity.java
  17. 16 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/LinkEntry.java
  18. 33 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/Model.java
  19. 28 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/OtherMeet.java
  20. 29 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/OtherMeetEntity.java
  21. 29 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/SaleOrderEntry.java
  22. 16 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/SaleOrderFinance.java
  23. 24 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/Save.java
  24. 22 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/Submit.java
  25. 14 0
      mjava-chuizi/src/main/java/com/malk/chuizi/entity/View.java
  26. 17 0
      mjava-chuizi/src/main/java/com/malk/chuizi/service/ChuiZiService.java
  27. 470 0
      mjava-chuizi/src/main/java/com/malk/chuizi/service/impl/ChuiZiServiceImpl.java
  28. 49 0
      mjava-chuizi/src/main/resources/application-dev.yml
  29. 49 0
      mjava-chuizi/src/main/resources/application-dev2.yml
  30. 49 0
      mjava-chuizi/src/main/resources/application-prod.yml
  31. 15 0
      mjava-chuizi/src/main/resources/application.yml
  32. 61 0
      mjava-chuizi/src/main/resources/logback-spring.xml
  33. 44 22
      mjava-mc/src/main/java/com/malk/mc/controller/McYdController.java
  34. 3 0
      mjava-mc/src/main/java/com/malk/mc/service/McYdService.java
  35. 1 4
      mjava-mc/src/main/java/com/malk/mc/service/impl/McProjectServiceImpl.java
  36. 133 10
      mjava-mc/src/main/java/com/malk/mc/service/impl/McYdServiceImpl.java
  37. 16 0
      mjava-pake/pom.xml
  38. 51 0
      mjava-pake/src/main/java/com/malk/pake/controller/PkProjectController.java
  39. 39 0
      mjava-pake/src/main/java/com/malk/pake/schedule/ScheduleTask.java
  40. 15 0
      mjava-pake/src/main/java/com/malk/pake/service/PkProjectService.java
  41. 507 0
      mjava-pake/src/main/java/com/malk/pake/service/impl/PkProjectServiceImpl.java
  42. 285 0
      mjava-pake/src/main/java/com/malk/pake/utils/HttpUtils.java
  43. 4 1
      mjava-pake/src/main/resources/application-dev.yml
  44. 8 5
      mjava-pake/src/main/resources/application-prod.yml
  45. 1 1
      mjava-pake/src/main/resources/application.yml

+ 87 - 0
mjava-chuizi/pom.xml

@@ -0,0 +1,87 @@
+<?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.2.0.RELEASE</version> <!-- 使用最新的稳定版或其他适用版本 -->
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.malk.chuizi</groupId>
+    <artifactId>mjava-chuizi</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.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.example</groupId>
+            <artifactId>k3cloud</artifactId>
+            <version>8.0.6</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>
+            <version>RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
+
+
+    </dependencies>
+
+    <build>
+        <finalName>chuzii</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-chuizi/src/main/java/com/malk/chuizi/ChuiZiApplication.java

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

+ 22 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/common/SeqHelper.java

@@ -0,0 +1,22 @@
+package com.malk.chuizi.common;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class SeqHelper {
+    static long seq = 0L;
+    static int mod = 10000;
+
+    public SeqHelper() {
+    }
+
+    public static long genSeq() {
+        return ++seq;
+    }
+
+    public static String genNumber(String pre) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMHHmmss");
+        String id = sdf.format(new Date());
+        return pre == null ? id + (genSeq() + (long)mod) : pre + id + (genSeq() + (long)mod);
+    }
+}

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

@@ -0,0 +1,24 @@
+package com.malk.chuizi.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;
+
+}

+ 29 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/config/KDWebApiConfig.java

@@ -0,0 +1,29 @@
+package com.malk.chuizi.config;
+
+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-jianhui/src/main/resources/application-dev.yml");
+            System.out.println("AcctID: " + config.getProperty("X-KDApi-AcctID"));
+            // 打印其他属性...
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 29 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/controller/ChuiziController.java

@@ -0,0 +1,29 @@
+package com.malk.chuizi.controller;
+
+import com.malk.chuizi.service.ChuiZiService;
+import com.malk.server.common.McR;
+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.RestController;
+
+import java.util.Map;
+
+@RestController
+public class ChuiziController {
+
+    @Autowired
+    ChuiZiService chuiZiService;
+    @GetMapping("/test")
+    public McR test(){
+        return McR.success();
+    }
+
+    //新增其他应付单
+    @PostMapping("/saveAccountsPayable")
+    public McR saveOtherMeet(Map processData) {
+        return chuiZiService.saveAccountsPayable(processData);
+    }
+
+
+}

+ 22 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/controller/DDController.java

@@ -0,0 +1,22 @@
+package com.malk.chuizi.controller;
+
+import com.malk.controller.DDCallbackController;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 钉钉事件回调 3_1
+ * -
+ * [子项目直接继承即可有调用, 无需实现]
+ * -
+ * 注解 @RequestMapping 路径不能重复 [主子项目属同一个项目];
+ * 获取项目回调请求地址, https://mc.cloudpure.cn/frp/xxx/dd/callback [调试代理: frp + nginx]
+ */
+@Slf4j
+@RestController
+@RequestMapping("/dd")
+public class DDController extends DDCallbackController {
+
+
+}

+ 83 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/delegate/DDDelegate.java

@@ -0,0 +1,83 @@
+package com.malk.chuizi.delegate;
+
+import com.malk.chuizi.service.ChuiZiService;
+import com.malk.delegate.DDEvent;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Personnel;
+import com.malk.service.dingtalk.DDClient_Workflow;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * OA审批事件 [主项目也有实现, 添加 @Primary 优先注入主项目实现]
+ * -
+ * 取消方案: 撤销和拒绝流程不继续执行连接器, 因此不使用连接器与轮询审批记录方案 [低效而且占用较高钉钉api调次数];
+ * 优化方案: 通过事件订阅实现实时同步所有审批状态, 定时查询钉钉回调失败记录 [配置钉钉事件Delegate, 添加定时任务]
+ */
+@Slf4j
+@Service
+@Primary
+public class DDDelegate implements DDEvent {
+
+    @Autowired
+    ChuiZiService chuiZiService;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Workflow ddClient_workflow;
+    // 审批任务回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Task_Finish(String processInstanceId, String processCode, boolean isAgree, String remark) {
+        log.info("executeEvent_Task_Finish");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Start");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Redirect(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Redirect");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Instance_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Instance_Start");
+    }
+
+
+    /// dingtalk
+    final String APP_EKY = "ding9seotugcsfjlgy8h";
+    final String APP_SECRET = "4k6hoCDUwwpUG5WXijfWcnzIm97j_zGquJqXJgrkBcyp2vo7ceV6dO-nSDUUDMhE";
+    // 审批实例回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Instance_Finish(String processInstanceId, String processCode, boolean isAgree, boolean isTerminate, String staffId) {
+        log.info("executeEvent_Instance_Finish:{}",processCode);
+        String approveResult = isAgree ? "agree" : "refuse";
+//        if (isTerminate) approveResult = "terminated";
+        if  (isAgree){
+            String token = ddClient.getAccessToken(APP_EKY, APP_SECRET);
+            Map processData = ddClient_workflow.getProcessInstanceId(token, processInstanceId);
+            log.info("开始执行回调:{}",processInstanceId);
+            if ("PROC-82233BD3-A274-4B90-8710-97D9F9663634".equals(processCode)){
+                chuiZiService.saveAccountsPayable(processData);
+            }else if ("PROC-D362D97E-916B-4865-B932-13D4A3B4DF1C".equals(processCode)){
+                chuiZiService.saveOtherMeet(processData);
+            }
+        }
+        log.info("审批实例回调执行业务逻辑, {}", approveResult);
+    }
+}

+ 22 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/AccountsPayableEntity.java

@@ -0,0 +1,22 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class AccountsPayableEntity {
+    //实体主键
+    private FNumber FEntryID;
+    //结算方式
+    private FNumber FSETTLETYPEID;
+    //付款用途
+    private FNumber FPURPOSEID;
+    //应付金额
+    private Double FPAYTOTALAMOUNTFOR;
+    //付款金额
+    private Double FPAYAMOUNTFOR_E;
+
+    //关联明细
+    private List<Object> FPaySubEntity;
+}

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

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

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

@@ -0,0 +1,18 @@
+package com.malk.chuizi.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;
+}

+ 15 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/BillTypeID.java

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

+ 33 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/Customer.java

@@ -0,0 +1,33 @@
+package com.malk.chuizi.entity;
+
+public class Customer {
+    long CustID;
+    String FNumber;
+    public long getCustID() {
+        return CustID;
+    }
+    public void setCustID(long custID) {
+        CustID = custID;
+    }
+    public String getFNumber() {
+        return FNumber;
+    }
+    public void setFNumber(String fNumber) {
+        FNumber = fNumber;
+    }
+    public String getFName() {
+        return FName;
+    }
+    public void setFName(String fName) {
+        FName = fName;
+    }
+    String FName;
+
+    String FShortName;
+    public String getFShortName() {
+        return FShortName;
+    }
+    public void setFShortName(String fShortName) {
+        FShortName = fShortName;
+    }
+}

+ 25 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/DefectEntity.java

@@ -0,0 +1,25 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class DefectEntity {
+    //物料id
+    private FNumber FMateridlId;
+    //供应商
+    private FNumber FSupplierId;
+    //单位
+    private FNumber FUnitID;
+    //检验不良数量
+    private double FInspectDefectQty;
+    //不良处理
+    private String FDefProcess;
+    //不良数量
+    private double FDefectiveQty;
+    //使用决策备注
+    private String FMemo;
+    //关联明细
+    private List<Object> FEntity_Link;
+}

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

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

+ 63 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/ForecastEntity.java

@@ -0,0 +1,63 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+@Data
+public class ForecastEntity {
+    //供应组织
+    private FNumber FSupplyOrgId;
+    //客户id
+    private FNumber FCustID;
+    //产品类型
+    private String FProductType;
+    //物料id
+    private FNumber FMaterialID;
+    //单位id
+    private FNumber FUnitID;
+    //数量
+    private double FQty;
+    //预测开始日期
+    private String FStartDate;
+    //预测结束日期
+    private String FEndDate;
+    //基础单位id
+    private FNumber FBaseUnitID;
+    //基础数量
+    private double FBaseQty;
+    //基础订单数量
+    private double FBaseOrderQty;
+    //基础核销数量
+    private double FBaseWriteOffQty;
+    //基础选配数量
+    private double FBaseSelPrdQty;
+    //均化类型
+    private String FAVERATYPE;
+    //均化周期
+    private int FAveraCycle;
+    //库存组织id
+    private FNumber FStockOrgId;
+    //货主类型
+    private String FOwnerTypeId;
+    //货主id
+    private FNumber FOwnerId;
+    //预留类型
+    private String FReserveType;
+    //需求优先级
+    private int FPriority;
+    //核销数量
+    private double FWriteOffQty;
+    //订单数量
+    private double FOrderQty;
+    //选配数量
+    private double FSelPrdQty;
+    //备注
+    private String FRemark;
+    //是否MRP
+    private boolean FIsMRP;
+    //BOM条目id
+    private int FBomEntryId;
+    //是否MRP计算
+    private boolean FISMRPCAL;
+    //变更标识
+    private String FChangeFlag;
+}

+ 16 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/LinkEntry.java

@@ -0,0 +1,16 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+@Data
+public class LinkEntry {
+    private FNumber FMaterialId;
+    private FNumber FUnitID;
+    private double FQty;
+    private FNumber FPriceUnitId;
+    private double FTaxPrice;
+    private boolean FIsFree;
+    private double FEntryTaxRate;
+    private String FDeliveryDate;
+    private String FEntryNote;
+}

+ 33 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/Model.java

@@ -0,0 +1,33 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Model {
+    private int FID;
+    private BillTypeID FBillTypeID;//单据类型
+    private String FDATE;//业务日期
+    private String FENDDATE_H;//到期日
+    private String FCONTACTUNITTYPE;//往来单位类型
+    private FNumber FCONTACTUNIT;//往来单位
+    private FNumber FCURRENCYID ;//币别
+    private Double FTOTALAMOUNTFOR_H;//总金额
+    private Double FNOTSETTLEAMOUNTFOR;//未借款金额
+    private FNumber FDEPARTMENTID;//申请部门
+    private FNumber SettlementOrgan;//结算组织(暂无字段)
+    private FNumber PaymentOrgan;//付款组织(暂无字段)
+    private FNumber PurchasingOrgan;//采购组织(暂无字段)
+    private FNumber FPURCHASEDEPTID;//采购部门
+    private FNumber FPURCHASERGROUPID;//采购组
+    private FNumber FPURCHASERID;//采购员
+    private String FRemarks ;//备注
+    private String FREMARK ;//备注
+    private String FBUSINESSTYPE;//业务类型
+    private String FRECTUNITTYPE;//收款单位类型
+    private FNumber FRECTUNIT;//收款单位
+    private List<Object> FEntity;//明细
+    private List<OtherMeetEntity> otherMeetEntityList;//明细
+    private List<AccountsPayableEntity> FPAYBILLENTRY;//明细
+}

+ 28 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/OtherMeet.java

@@ -0,0 +1,28 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OtherMeet {
+    private int FID;
+    private FNumber FBillTypeID;//单据类型
+    private String FDATE;//业务日期
+    private String FENDDATE_H;//到期日
+    private String FCONTACTUNITTYPE;//往来单位类型
+    private FNumber FCONTACTUNIT;//往来单位
+    private FNumber FCURRENCYID ;//币别
+    private Double FTOTALAMOUNTFOR_H;//总金额
+    private Double FNOTSETTLEAMOUNTFOR;//未借款金额
+    private FNumber FDEPARTMENTID;//申请部门
+    private FNumber SettlementOrgan;//结算组织(暂无字段)
+    private FNumber PaymentOrgan;//付款组织(暂无字段)
+    private FNumber PurchasingOrgan;//采购组织(暂无字段)
+    private FNumber FPURCHASEDEPTID;//采购部门
+    private FNumber FPURCHASERGROUPID;//采购组
+    private FNumber FPURCHASERID;//采购员
+    private String FRemarks ;//备注
+    private List<Object> FEntity;//明细
+
+}

+ 29 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/OtherMeetEntity.java

@@ -0,0 +1,29 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OtherMeetEntity {
+    //实体主键
+    private FNumber FEntryID;
+    //费用项目编码
+    private FNumber FCOSTID;
+    //费用项目名称
+    private FNumber FCOSTNAME;
+    //费用承担部门
+    private FNumber FCOSTDEPARTMENTID;
+    //发票类型
+    private String FINVOICETYPE;
+    //税率
+    private Double FEntryTaxRate;
+    //不含税金额
+    private Double FNOTAXAMOUNTFOR;
+    //税额
+    private Double FTAXAMOUNTFOR;
+    //总金额
+    private Double FTOTALAMOUNTFOR;
+    //关联明细
+    private List<Object> FPaySubEntity;
+}

+ 29 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/SaleOrderEntry.java

@@ -0,0 +1,29 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+@Data
+public class SaleOrderEntry {
+    private FNumber FMaterialId;
+    private FNumber FUnitID;
+    private double FQty;
+    private FNumber FPriceUnitId;
+//    private double FPriceUnitQty;
+//    private double FPrice;
+    private double FTaxPrice;
+    private boolean FIsFree;
+    private double FEntryTaxRate;
+    /*private double FTaxAmount_LC;
+    private double FAmount_LC;
+    private double FAllAmount_LC;*/
+    private String FDeliveryDate;
+    /*private FNumber FStockFNumber;
+    private FNumber FSettleOrgIds;
+    private String FOwnerTypeId;
+    private FNumber FOwnerId;*/
+    private String FEntryNote;
+/*    private double F_WMVJ_Decimal;
+    private double F_WMVJ_Amount;
+    private double F_WMVJ_Qty;
+    private boolean F_WMVJ_CheckBox;*/
+}

+ 16 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/SaleOrderFinance.java

@@ -0,0 +1,16 @@
+package com.malk.chuizi.entity;
+
+import lombok.Data;
+
+@Data
+public class SaleOrderFinance {
+    private FNumber FSettleCurrId;
+    private boolean FIsIncludedTax;
+    private boolean FIsPriceExcludeTax;
+    /*private FNumber FExchangeTypeId;
+    private double FMarginLevel;
+    private double FMargin;
+    private boolean FOverOrgTransDirect;
+    private double FAllDisCount;
+    private int FXPKID_F;*/
+}

+ 24 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/entity/Save.java

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

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

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

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

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

+ 17 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/service/ChuiZiService.java

@@ -0,0 +1,17 @@
+package com.malk.chuizi.service;
+
+import com.malk.server.common.McR;
+
+import java.util.Map;
+
+public interface ChuiZiService {
+
+    /**
+     * 费用报销应付单
+     * @param
+     * @return
+     */
+    McR saveOtherMeet(Map processData);
+
+    McR saveAccountsPayable(Map processData);
+}

+ 470 - 0
mjava-chuizi/src/main/java/com/malk/chuizi/service/impl/ChuiZiServiceImpl.java

@@ -0,0 +1,470 @@
+package com.malk.chuizi.service.impl;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.Gson;
+import com.kingdee.bos.webapi.entity.IdentifyInfo;
+import com.kingdee.bos.webapi.entity.RepoRet;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
+import com.malk.chuizi.config.KDWebApiConf;
+import com.malk.chuizi.entity.*;
+import com.malk.chuizi.service.ChuiZiService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McR;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Personnel;
+import com.malk.service.dingtalk.DDClient_Workflow;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.util.*;
+
+import static org.junit.Assert.fail;
+
+@Slf4j
+@Service
+public class ChuiZiServiceImpl implements ChuiZiService {
+    @Autowired
+    private KDWebApiConf kdWebApiConf;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Personnel ddClientPersonnel;
+
+    @Value("${dingtalk.agentId}")
+    private Long agentId;
+
+    @Autowired
+    private YDClient ydClient;
+
+    //单据状态
+    private static final Map<String,String> FDOCUMENTSTATUS = new HashMap<>();
+    static{
+        FDOCUMENTSTATUS.put("Z","暂存");
+        FDOCUMENTSTATUS.put("A","创建");
+        FDOCUMENTSTATUS.put("B","审核中");
+        FDOCUMENTSTATUS.put("C","已审核");
+        FDOCUMENTSTATUS.put("D","重新审核");
+    }
+
+    //整单状态
+    private static final Map<String,String> AUDITSTATUS = new HashMap<>();
+    static{
+        AUDITSTATUS.put("U","未审核");
+        AUDITSTATUS.put("A","已审核");
+        AUDITSTATUS.put("I","审核中");
+        AUDITSTATUS.put("P","部分审核");
+        AUDITSTATUS.put("R","重新审核");
+    }
+
+    //禁用状态
+    private static final Map<String,String> FFORBIDSTATUS = new HashMap<>();
+    static{
+        FFORBIDSTATUS.put("A","否");
+        FFORBIDSTATUS.put("B","是");
+    }
+
+    private static final Map<String,String> FFORBIDDENSTATUS = new HashMap<>();
+    static{
+        FFORBIDDENSTATUS.put("0","否");
+        FFORBIDDENSTATUS.put("1","是");
+    }
+
+    private static final Map<String,String> FERPCLSID = new HashMap<>();
+    static {
+        FERPCLSID.put("10","资产");
+        FERPCLSID.put("9","配置");
+        FERPCLSID.put("2","自制");
+        FERPCLSID.put("11","费用");
+        FERPCLSID.put("12","模型");
+        FERPCLSID.put("5","虚拟");
+        FERPCLSID.put("7","一次性");
+        FERPCLSID.put("13","产品系列");
+        FERPCLSID.put("3","委外");
+        FERPCLSID.put("4","特征");
+        FERPCLSID.put("6","服务");
+        FERPCLSID.put("1","外购");
+    }
+
+    private static final Map<String,String> BUSINESS_TYPE = new HashMap<>();
+    static {
+        BUSINESS_TYPE.put("8","发货检验");
+        BUSINESS_TYPE.put("25","生产退料检验");
+        BUSINESS_TYPE.put("26","委外退料检验");
+        BUSINESS_TYPE.put("3","产品检验");
+        BUSINESS_TYPE.put("20","其他检验");
+        BUSINESS_TYPE.put("6","委外工序");
+        BUSINESS_TYPE.put("10","受托材料检验");
+        BUSINESS_TYPE.put("2","委外检验");
+        BUSINESS_TYPE.put("21","工序巡检");
+        BUSINESS_TYPE.put("7","退货检验");
+        BUSINESS_TYPE.put("9","生产线检验");
+        BUSINESS_TYPE.put("1","采购检验");
+        BUSINESS_TYPE.put("4","库存检验");
+        BUSINESS_TYPE.put("5","工序自制");
+    }
+
+    private static final Map<String,String> INSPECT_RESULT = new HashMap<>();
+    static {
+        INSPECT_RESULT.put("1","合格");
+        INSPECT_RESULT.put("2","不合格");
+        INSPECT_RESULT.put("3","保留");
+    }
+    private static final Map<String,String> DEPARTMENT = new HashMap<>();
+    static {
+        DEPARTMENT.put("经营管理部","CZ00104");
+        DEPARTMENT.put("人事行政部","CZ00105");
+        DEPARTMENT.put("销售部","CZ00106");
+        DEPARTMENT.put("技术部","CZ00107");
+        DEPARTMENT.put("IT部门","CZ00107");
+        DEPARTMENT.put("后勤部","CZ00108");
+        DEPARTMENT.put("资材部","CZ00109");
+        DEPARTMENT.put("原料仓库组","CZ0010902");
+        DEPARTMENT.put("成品仓库组","CZ0010903");
+        DEPARTMENT.put("生产计划组","CZ0010904");
+        DEPARTMENT.put("客户服务组","CZ0010905");
+        DEPARTMENT.put("品质部","CZ00110");
+        DEPARTMENT.put("一车间检验组","CZ0011001");
+        DEPARTMENT.put("二车间检验组","CZ0011002");
+        DEPARTMENT.put("三车间检验组","CZ0011003");
+        DEPARTMENT.put("生产部","CZ00111");
+        DEPARTMENT.put("一车间生产组","CZ0011101");
+        DEPARTMENT.put("二车间生产组","CZ0011103");
+        DEPARTMENT.put("三车间生产组","CZ0011105");
+        DEPARTMENT.put("总经办","CZ00101");
+        DEPARTMENT.put("审计部","CZ00102");
+        DEPARTMENT.put("财务部","CZ00103");
+    }
+    private static final Map<String,String> PAYMENT_METHOD = new HashMap<>();
+    static {
+        PAYMENT_METHOD.put("现金","JSFS01_SYS");
+        PAYMENT_METHOD.put("现金支票","JSFS02_SYS");
+        PAYMENT_METHOD.put("转账支票","JSFS03_SYS");
+        PAYMENT_METHOD.put("电汇","JSFS04_SYS");
+        PAYMENT_METHOD.put("信汇","JSFS05_SYS");
+        PAYMENT_METHOD.put("商业承兑汇票","JSFS06_SYS");
+        PAYMENT_METHOD.put("银行承兑汇票","JSFS07_SYS");
+        PAYMENT_METHOD.put("信用证","JSFS08_SYS");
+        PAYMENT_METHOD.put("应收票据背书","JSFS09_SYS");
+        PAYMENT_METHOD.put("票据退票","JSFS12_SYS");
+        PAYMENT_METHOD.put("保证金转货款","JSFS22_SYS");
+        PAYMENT_METHOD.put("微信","JSFS31_SYS");
+        PAYMENT_METHOD.put("支付宝","JSFS32_SYS");
+        PAYMENT_METHOD.put("供应链票据","JSFS36_SYS");
+        PAYMENT_METHOD.put("内部转销","JSFS41_SYS");
+        PAYMENT_METHOD.put("认领结算","JSFS81_SYS");
+
+    }
+    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;
+    }
+
+    private String getString(Object object){
+        return object == null ? "" : object.toString();
+    }
+
+
+    /// dingtalk
+    final String APP_EKY = "ding9seotugcsfjlgy8h";
+    final String APP_SECRET = "4k6hoCDUwwpUG5WXijfWcnzIm97j_zGquJqXJgrkBcyp2vo7ceV6dO-nSDUUDMhE";
+    @Override
+    public McR saveOtherMeet(Map processData) {
+        String userId = String.valueOf(processData.get("originatorUserId"));
+        String workId = getNumberByUserId(userId);
+        Save save = new Save();
+
+        Model otherMeet = new Model();
+        otherMeet.setFCONTACTUNITTYPE("BD_Empinfo");
+        otherMeet.setFBillTypeID(new BillTypeID("QTYFD02_SYS"));
+        otherMeet.setFCONTACTUNIT(new FNumber(workId));//员工号
+        otherMeet.setFDATE(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
+        otherMeet.setFENDDATE_H(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
+        otherMeet.setFCURRENCYID(new FNumber("PRE001"));//币别
+        final double[] sum = {0.0,0.0};
+        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");
+        Map<String, Object> mainData = new HashMap<>();
+        List<Map<String,Object>> sonData = new ArrayList<>();
+        formComponentValues.forEach(e->{
+            String name = e.get("name").toString();
+            if ("金蝶科目".equals(name) || "报销科目".equals(name) || "归属部门".equals(name) || "发票类型".equals(name) || "申请人".equals(name) ) {
+                mainData.put(name, e.get("value"));
+            } else if ("TableField".equals(e.get("componentType"))) {
+                Object parse = JSON.parse(e.get("value").toString());
+                JSONArray jsonArray = JSON.parseArray(parse.toString());
+                for (int i = 0; i < jsonArray.size(); i++) {
+                    JSONObject jsonObject = (JSONObject) jsonArray.get(i);
+                    Object rowValue = jsonObject.get("rowValue");
+                    JSONArray array = JSON.parseArray(rowValue.toString());
+                    for (int i1 = 0; i1 < array.size(); i1++) {
+                        jsonObject = (JSONObject) array.get(i1);
+                        if (jsonObject.containsKey("extendValue")){
+                            rowValue = jsonObject.get("extendValue");
+                            jsonObject = JSONObject.parseObject(rowValue.toString());
+                            rowValue = jsonObject.get("list");
+                            JSONArray array1 =  JSON.parseArray(rowValue.toString());
+                            for (int i2 = 0; i2 < array1.size(); i2++) {
+                                jsonObject = (JSONObject) array1.get(i2);
+                                if (jsonObject.containsKey("rowValue")){
+                                    rowValue = jsonObject.get("rowValue");
+                                    JSONArray array2 = JSON.parseArray(rowValue.toString());
+                                    for (int l = 0; l < array2.size(); l++) {
+                                        Map<String, Object> map = new HashMap<>();
+                                        jsonObject = (JSONObject) array2.get(l);
+                                        //需要改成金额
+                                        if ("金额".equals(jsonObject.get("label"))){
+                                            double amount = Double.parseDouble(jsonObject.get("value") == null ? "0.0" : jsonObject.get("value").toString());
+                                            sum[0] = sum[0] + amount;
+                                            sum[1] = sum[1] + amount;
+                                            map.put("amount",amount);
+
+                                            sonData.add(map);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        });
+        List<Object> objects  = new ArrayList<>();
+        if (ObjectUtil.isNotNull(sonData) && sonData.size()>0){
+            sonData.forEach(e->{
+                OtherMeetEntity otherMeetEntity = new OtherMeetEntity();
+                otherMeetEntity.setFCOSTID(new FNumber(mainData.get("金蝶科目").toString()));
+                otherMeetEntity.setFINVOICETYPE(mainData.get("发票类型").toString());
+                otherMeetEntity.setFCOSTDEPARTMENTID(new FNumber(DEPARTMENT.get(mainData.get("归属部门").toString())));
+                otherMeetEntity.setFEntryTaxRate(0.0);
+                otherMeetEntity.setFNOTAXAMOUNTFOR(Double.parseDouble(e.get("amount").toString()));
+                otherMeetEntity.setFTAXAMOUNTFOR(0.0);
+                otherMeetEntity.setFTOTALAMOUNTFOR(Double.parseDouble(e.get("amount").toString()));
+                otherMeetEntity.setFPaySubEntity(null);
+
+                objects.add(otherMeetEntity);
+            });
+        }
+        otherMeet.setFEntity(objects);
+
+        save.setModel(otherMeet);
+        System.out.println(save);
+
+        try{
+            K3CloudApi client = new K3CloudApi(initIden());
+            //业务对象标识
+            String formId = "AP_OtherPayable";
+            //调用接口
+            String resultJson = client.save(formId,JSONObject.toJSONString(save));
+            //用于记录结果
+            Gson gson = new Gson();
+            //对返回结果进行解析和校验
+            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
+
+            if (isTrue(repoRet)){
+                String id = repoRet.getResult().getId();
+
+                Submit submit = new Submit();
+                submit.setIds(id);
+                //提交
+                String resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
+                RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
+                isTrue(repoRet2);
+
+//                String orderCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
+
+//                ydClient.operateData(YDParam.builder()
+////                        .formInstId(formInstId)
+//                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_m6yntxmz",orderCode)))
+//                        .build(), YDConf.FORM_OPERATION.update);
+
+                if (isTrue(repoRet2)){
+                    Audit audit = new Audit();
+                    audit.setIds(id);
+                    //审核
+                    String resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
+                    RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
+                    isTrue(repoRet3);
+                }
+            }
+        } catch (Exception e) {
+            McR.errorUnknown(e.getMessage());
+        }
+
+        return McR.success();
+    }
+
+    @Override
+    public McR saveAccountsPayable(Map processData) {
+//        String userId = String.valueOf(processData.get("originatorUserId"));
+        Save save = new Save();
+
+        Model model = new Model();
+        model.setFCONTACTUNITTYPE("BD_Supplier");
+        model.setFBillTypeID(new BillTypeID("FKDLX01_SYS"));
+        model.setFDATE(LocalDateTimeUtil.format(LocalDate.now(),"yyyy-MM-dd"));
+        model.setFCURRENCYID(new FNumber("PRE001"));//币别
+        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");
+
+        Map<String, Object> mainData = new HashMap<>();
+
+        formComponentValues.forEach(e->{
+            String name = e.get("name").toString();
+            mainData.put(name, e.get("value"));
+        });
+        List<AccountsPayableEntity> objects  = new ArrayList<>();
+        if (ObjectUtil.isNotNull(mainData)){
+            //主表
+            model.setFREMARK(mainData.get("付款事由").toString());
+            model.setFRECTUNIT(new FNumber(mainData.get("供应商编码").toString()));
+            model.setFCONTACTUNIT(new FNumber(mainData.get("供应商编码").toString()));
+            //明细
+            AccountsPayableEntity accountsPayableEntity = new AccountsPayableEntity();
+            accountsPayableEntity.setFSETTLETYPEID(new FNumber(PAYMENT_METHOD.get(mainData.get("付款方式"))));//结算方式
+            accountsPayableEntity.setFPURPOSEID(new FNumber(mainData.get("付款用途编码").toString()));//付款用途
+            accountsPayableEntity.setFPAYTOTALAMOUNTFOR(Double.parseDouble(mainData.get("付款总额").toString()));
+            accountsPayableEntity.setFPAYAMOUNTFOR_E(Double.parseDouble(mainData.get("付款总额").toString()));
+
+            objects.add(accountsPayableEntity);
+        }
+        model.setFPAYBILLENTRY(objects);
+
+        save.setModel(model);
+        System.out.println(save);
+
+        try{
+            K3CloudApi client = new K3CloudApi(initIden());
+            //业务对象标识
+            String formId = "AP_PAYBILL";
+            //调用接口
+            String resultJson = client.save(formId,JSONObject.toJSONString(save));
+            //用于记录结果
+            Gson gson = new Gson();
+            //对返回结果进行解析和校验
+            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
+
+            if (isTrue(repoRet)){
+                String id = repoRet.getResult().getId();
+
+                Submit submit = new Submit();
+                submit.setIds(id);
+                //提交
+                String resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
+                RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
+                isTrue(repoRet2);
+
+                if (isTrue(repoRet2)){
+                    Audit audit = new Audit();
+                    audit.setIds(id);
+                    //审核
+                    String resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
+                    RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
+                    isTrue(repoRet3);
+                }
+            }
+        } catch (Exception e) {
+            McR.errorUnknown(e.getMessage());
+        }
+
+        return McR.success();
+    }
+
+    public String getNumberByUserId(String workingEmployeeIds) {
+//        log.info("根据钉钉人员id获取员工工号:{}",workingEmployeeIds);
+        List<String> filterList = new ArrayList<>();
+        filterList.add("sys00-jobNumber");
+        List<Map> employeeInfos = ddClientPersonnel.getEmployeeInfos(ddClient.getAccessToken(), Arrays.asList(workingEmployeeIds), agentId, filterList);
+        final String[] value = {""};
+        employeeInfos.forEach(e -> {
+            List<Map> mapList = (List<Map>) e.get("field_data_list");
+            mapList.forEach(m -> {
+                List<Map> valueList = (List<Map>) m.get("field_value_list");
+                value[0] = ObjectUtil.isNotNull(valueList.get(0).get("value")) ? valueList.get(0).get("value").toString() : null;
+            });
+        });
+        return value[0];
+    }
+
+    private String getMultiLanguageTextName(Object object){
+        if (Objects.nonNull(object)){
+            Map map = (Map) object;
+            List<Map> multiLanguageText = (List<Map>) map.get("MultiLanguageText");
+            String value = getString(multiLanguageText.get(0).get("Name"));
+
+            return value;
+        }
+        return null;
+    }
+
+    private String getMultiLanguageTextSpecification(Object object){
+        if (Objects.nonNull(object)){
+            Map map = (Map) object;
+            List<Map> multiLanguageText = (List<Map>) map.get("MultiLanguageText");
+            String value = getString(multiLanguageText.get(0).get("Specification"));
+
+            return value;
+        }
+        return null;
+    }
+
+    private String getEntryNumber(Object object){
+        if (Objects.nonNull(object)){
+            Map map = (Map) object;
+            String value =  getString(map.get("Number"));
+
+            return value;
+        }
+        return null;
+    }
+
+
+    private boolean isTrue(RepoRet repoRet){
+        Gson gson = new Gson();
+
+        if (repoRet.getResult().getResponseStatus().isIsSuccess()) {
+            System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult()));
+            return true;
+        } else {
+            fail("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus()));
+            return false;
+        }
+    }
+
+    private List<Map> getYdFormDataList(String formUuid, String searchCondition, YDConf.FORM_QUERY formQuery) {
+        List<Map> list = new ArrayList<>();
+        DDR_New ddrNew = new DDR_New();
+        int pageNumber = 1;
+        int pageSize = 100;
+        do {
+            ddrNew = ydClient.queryData(YDParam.builder().formUuid(formUuid)
+                    .searchCondition(searchCondition)
+                    .pageNumber(pageNumber)
+                    .pageSize(pageSize).build(), formQuery);
+
+            list.addAll((List<Map>) ddrNew.getData());
+            pageNumber++;
+        }while (ddrNew.getTotalCount() > ddrNew.getPageNumber() * pageSize);
+        return list;
+    }
+
+
+}

+ 49 - 0
mjava-chuizi/src/main/resources/application-dev.yml

@@ -0,0 +1,49 @@
+#测试学习
+server:
+  port: 8109
+  servlet:
+    context-path: /chuizi
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/chuzi/log/
+  level:
+    com.malk.*: debug
+
+# dingtalk
+dingtalk:
+  agentId: 3746535996
+  appKey: ding9seotugcsfjlgy8h
+  appSecret: 4k6hoCDUwwpUG5WXijfWcnzIm97j_zGquJqXJgrkBcyp2vo7ceV6dO-nSDUUDMhE
+  corpId:
+  aesKey: 2qpILM4GJXsv9A24pcLMhzsjsVLhjAarqZzHVl4DgKa
+  token: 93TmIb21XoFozsu5o5unY6p
+#  operator:
+
+#aliwork:
+#  appType: APP_XPPVVMG6HA0GNDPJV4C1
+#  systemToken: 8R7668D1P92RSNTS7OKZG5UR9P333QA7GAJ4MTG
+
+#测试环境
+kingdee:
+# 第三方系统登录授权的账套ID
+  X-KDApi-AcctID: 67d92ff7f69ac8
+  # 第三方系统登录授权的用户
+  X-KDApi-UserName: Administrator
+  # 第三方系统登录授权的应用ID
+  X-KDApi-AppID: 312000_T+5I1yGE2urX5XTuxeSL6z1HSuS8SBrE
+  # 第三方系统登录授权的应用密钥
+  X-KDApi-AppSec: a8cfbf47aa504a528bc5c75d4de2f71d
+  # 服务Url地址(公有云统一走网关sdk底层已处理,无需传X-KDApi-ServerUrl,下面这行需要注释)
+  X-KDApi-ServerUrl: http://124.71.139.0:8283/K3cloud
+  # 账套语系,默认2052
+  # X-KDApi-LCID: 2052
+  # 组织编码,启用多组织时配置对应的组织编码才有效
+  # X-KDApi-OrgNum: 100
+  # 允许的最大连接延时,单位为秒
+  # X-KDApi-ConnectTimeout: 120
+  # 允许的最大读取延时,单位为秒
+  # X-KDApi-RequestTimeout: 120
+

+ 49 - 0
mjava-chuizi/src/main/resources/application-dev2.yml

@@ -0,0 +1,49 @@
+#钉钉测试
+server:
+  port: 9030
+  servlet:
+    context-path: /chuizi
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/jianhui/log/
+  level:
+    com.malk.*: debug
+
+# dingtalk
+dingtalk:
+  agentId: 3366214854
+  appKey: dingntvkzjzxdx8h2m1s
+  appSecret: YfaV5mYOL4F--P8P_G9aD8DP_a8_IgM6dBILsSaTb4LeUZYSntacol55O1tJuqcU
+  corpId: ding923faa53d9d45937acaaa37764f94726
+  aesKey:
+  token:
+  operator: 344749020127590108
+
+aliwork:
+  appType: APP_XPPVVMG6HA0GNDPJV4C1
+  systemToken: 8R7668D1P92RSNTS7OKZG5UR9P333QA7GAJ4MTG
+
+#测试环境
+kingdee:
+# 第三方系统登录授权的账套ID
+  X-KDApi-AcctID: 67adb125bcb53e
+  # 第三方系统登录授权的用户
+  X-KDApi-UserName: Administrator
+  # 第三方系统登录授权的应用ID
+  X-KDApi-AppID: 303494_XZ8JQZuu3mnb49Xu3+XDzd+NzNx7wANv
+  # 第三方系统登录授权的应用密钥
+  X-KDApi-AppSec: 9ba984bc11a14bf1883e23ac223cc733
+  # 服务Url地址(公有云统一走网关sdk底层已处理,无需传X-KDApi-ServerUrl,下面这行需要注释)
+  X-KDApi-ServerUrl: http://124.71.139.0:8283/k3cloud/
+  # 账套语系,默认2052
+  # X-KDApi-LCID: 2052
+  # 组织编码,启用多组织时配置对应的组织编码才有效
+  # X-KDApi-OrgNum: 100
+  # 允许的最大连接延时,单位为秒
+  # X-KDApi-ConnectTimeout: 120
+  # 允许的最大读取延时,单位为秒
+  # X-KDApi-RequestTimeout: 120
+

+ 49 - 0
mjava-chuizi/src/main/resources/application-prod.yml

@@ -0,0 +1,49 @@
+#钉钉测试
+server:
+  port: 8109
+  servlet:
+    context-path: /chuizi
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/jianhui/log/
+  level:
+    com.malk.*: INFO
+
+# dingtalk
+dingtalk:
+  agentId: 3746535996
+  appKey: ding9seotugcsfjlgy8h
+  appSecret: 4k6hoCDUwwpUG5WXijfWcnzIm97j_zGquJqXJgrkBcyp2vo7ceV6dO-nSDUUDMhE
+  corpId:
+  aesKey: 2qpILM4GJXsv9A24pcLMhzsjsVLhjAarqZzHVl4DgKa
+  token: 93TmIb21XoFozsu5o5unY6p
+#  operator:
+
+#aliwork:
+#  appType: APP_XPPVVMG6HA0GNDPJV4C1
+#  systemToken: 8R7668D1P92RSNTS7OKZG5UR9P333QA7GAJ4MTG
+
+#正式环境 锤子塑业2025数据中心
+kingdee:
+  # 第三方系统登录授权的账套ID
+  X-KDApi-AcctID: 670624589dd479
+  # 第三方系统登录授权的用户
+  X-KDApi-UserName: administrator
+  # 第三方系统登录授权的应用ID
+  X-KDApi-AppID: 309474_23ev0dtszrH/7/xH0c5OQY9MTJ0aWOmu
+  # 第三方系统登录授权的应用密钥
+  X-KDApi-AppSec: c9545d83ed7b44728dc0288ca3b3c07d
+  # 服务Url地址(公有云统一走网关sdk底层已处理,无需传X-KDApi-ServerUrl,下面这行需要注释)
+  X-KDApi-ServerUrl: http://124.71.139.0:8283/K3cloud
+  # 账套语系,默认2052
+  # X-KDApi-LCID: 2052
+  # 组织编码,启用多组织时配置对应的组织编码才有效
+  # X-KDApi-OrgNum: 100
+  # 允许的最大连接延时,单位为秒
+  # X-KDApi-ConnectTimeout: 120
+  # 允许的最大读取延时,单位为秒
+  # X-KDApi-RequestTimeout: 120
+

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

@@ -0,0 +1,15 @@
+spring:
+  profiles:
+    active: dev
+  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-chuizi/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="/home/server/log/"/>
+    <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>

+ 44 - 22
mjava-mc/src/main/java/com/malk/mc/controller/McYdController.java

@@ -44,12 +44,12 @@ public class McYdController {
      * @return
      */
     @PostMapping("copy")
-    public McR copy(@RequestBody JSONObject param){
-        if(PublicUtil.isNull(param,"instanceId","formUuid")){
+    public McR copy(@RequestBody JSONObject param) {
+        if (PublicUtil.isNull(param, "instanceId", "formUuid")) {
             return McR.errorNullPointer();
         }
-        ydService.mirrorFormData(param.getString("instanceId"),param.getString("formUuid"),param.getString("processCode"),param.getString("processUserId"),
-                param.getJSONObject("updateData"),param.getString("updateInstanceId"));
+        ydService.mirrorFormData(param.getString("instanceId"), param.getString("formUuid"), param.getString("processCode"), param.getString("processUserId"),
+                param.getJSONObject("updateData"), param.getString("updateInstanceId"));
         return McR.success();
     }
 
@@ -59,26 +59,27 @@ public class McYdController {
      * @return
      */
     @PostMapping("saveGl")
-    public McR saveGl(@RequestBody JSONObject param){
-        if(PublicUtil.isNull(param,"formInstId","formUuid","title","saveFormInstId","compId","appType")){
+    public McR saveGl(@RequestBody JSONObject param) {
+        if (PublicUtil.isNull(param, "formInstId", "formUuid", "title", "saveFormInstId", "compId", "appType")) {
             return McR.errorNullPointer();
         }
-        ydClient.operateData(YDParam.builder().updateFormDataJson(JSONObject.toJSONString(UtilMap.map(param.getString("compId"),Arrays.asList(
-                UtilMap.map("appType, formType, instanceId, title, subTitle, formUuid",param.getString("appType"),"receipt",param.getString("formInstId")
-                        ,param.getString("title"),param.getString("subTitle"),param.getString("formUuid")))
+        ydClient.operateData(YDParam.builder().updateFormDataJson(JSONObject.toJSONString(UtilMap.map(param.getString("compId"), Arrays.asList(
+                UtilMap.map("appType, formType, instanceId, title, subTitle, formUuid", param.getString("appType"), "receipt", param.getString("formInstId")
+                        , param.getString("title"), param.getString("subTitle"), param.getString("formUuid")))
         ))).formInstId(param.getString("saveFormInstId")).build(), YDConf.FORM_OPERATION.update);
         return McR.success();
     }
 
     /**
      * 根据筛选条件获取表单数据
+     *
      * @param
      * @return
      */
     @GetMapping("getFromData")
-    public Map getFromData(String formUuid,String fieldCode,String fileValue){
-        log.info("formUuid:{},fieldCode:{},fileValue:{}",formUuid,fieldCode,fileValue);
-        MDC.put("MDC_KEY_PID","1004");
+    public Map getFromData(String formUuid, String fieldCode, String fileValue) {
+        log.info("formUuid:{},fieldCode:{},fileValue:{}", formUuid, fieldCode, fileValue);
+        MDC.put("MDC_KEY_PID", "1004");
 //        McProject.addYida("1004",new String[] {"APP_YMOUJB8W36ZVCJ9BUE77","YE966DA1CKMCAWSRAM78Y5K6NESA27LKXC9KL6C2"});
 
         fileValue = Objects.nonNull(fileValue) ? fileValue : "";
@@ -106,17 +107,18 @@ public class McYdController {
 
             list.addAll((List<Map>) ddrNew.getData());
             pageNumber++;
-        }while (ddrNew.getTotalCount() > ddrNew.getPageNumber() * pageSize);
+        } while (ddrNew.getTotalCount() > ddrNew.getPageNumber() * pageSize);
         return list;
     }
 
     /**
      * 更新表单数据版本
+     *
      * @param map
      * @return
      */
     @PostMapping("/updateFormDataVersion")
-    public McR updateFormDataVersion(@RequestBody Map map){
+    public McR updateFormDataVersion(@RequestBody Map map) {
         mcYdService.updateFormDataVersion(map);
 
         return McR.success();
@@ -135,40 +137,60 @@ public class McYdController {
 
     /**
      * 发起审批
+     *
      * @param map
      * @return
      */
     @PostMapping("initiateApproval")
-    public McR initiateApproval(@RequestBody Map map){
+    public McR initiateApproval(@RequestBody Map map) {
         return mcYdService.initiateApproval(map);
     }
 
     //子表数值转化为文本,添加千位分隔符
     @PostMapping("/convertSubTableNumber")
-    public McR convertSubTableNumber(@RequestBody Map map){
+    public McR convertSubTableNumber(@RequestBody Map map) {
         return mcYdService.convertSubTableNumber(map);
     }
 
     @PostMapping("/saveApproverToForm")
-    public McR saveApproverToForm(@RequestBody Map map){
-        McException.assertParamException_Null(map,"formInstId","key");
+    public McR saveApproverToForm(@RequestBody Map map) {
+        McException.assertParamException_Null(map, "formInstId", "key");
         return mcYdService.saveApproverToForm(map);
     }
 
     //海天二期开发部分(出库)
     @PostMapping("/multiLocationOutbound")
-    public McR multiLocationOutbound(@RequestBody Map map){
+    public McR multiLocationOutbound(@RequestBody Map map) {
         return mcYdService.multiLocationOutbound(map);
     }
+
     //海天二期开发部分(入库)
     @PostMapping("/WarehouseStorage")
-    public McR WarehouseStorage(@RequestBody Map map){
+    public McR WarehouseStorage(@RequestBody Map map) {
         return mcYdService.WarehouseStorage(map);
     }
+
     //海天二期开发(退货)
     @PostMapping("/ProductReturn")
-    public McR ProductReturn(@RequestBody Map map){return mcYdService.ProductReturn(map);}
+    public McR ProductReturn(@RequestBody Map map) {
+        return mcYdService.ProductReturn(map);
+    }
+
     //海天二期开发(调拨)
     @PostMapping("/allocateTransfer")
-    public McR allocateTransfer(@RequestBody Map map){return mcYdService.allocateTransfer(map);}
+    public McR allocateTransfer(@RequestBody Map map) {
+        return mcYdService.allocateTransfer(map);
+    }
+
+    /**
+     * 分享数据权限
+     * @param map compId 表单分享权限所属, userIds 分享人及被分享人, userId 分享人, content 代办标题, atUserId 被分享人, appUrl 移动端地址, pcUrl PC端地址
+     * @param header POC下MC服务项目pid
+     * @return
+     */
+    @PostMapping("/shareRecord")
+    public McR shareRecord(@RequestBody Map map, @RequestHeader Map header) {
+        map.put("pid",header.get("pid").toString());
+        return mcYdService.shareRecord(map);
+    }
 }

+ 3 - 0
mjava-mc/src/main/java/com/malk/mc/service/McYdService.java

@@ -25,4 +25,7 @@ public interface McYdService {
     McR allocateTransfer(Map map);
 
     void batchUpdateSpecifiedQuantityData(Map map);
+
+    McR shareRecord(Map map);
+
 }

+ 1 - 4
mjava-mc/src/main/java/com/malk/mc/service/impl/McProjectServiceImpl.java

@@ -1,6 +1,5 @@
 package com.malk.mc.service.impl;
 
-import com.alibaba.fastjson.JSONObject;
 import com.malk.core.McProject;
 import com.malk.mc.service.McProjectService;
 import com.malk.server.aliwork.YDConf;
@@ -13,8 +12,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -46,7 +43,7 @@ public class McProjectServiceImpl implements McProjectService {
                 Map formData=UtilMap.getMap(map,"formData");
                 ydData.put(UtilMap.getString(formData,"serialNumberField_lxlfw7nn"),new String[]{UtilMap.getString(formData,"textField_lxlfw7no"),UtilMap.getString(formData,"textField_lxlfw7np")});
                 if(!PublicUtil.isNull(formData,"textField_m7abagvx","textField_m7abagvy")){
-                    ddData.put(UtilMap.getString(formData,"serialNumberField_lxlfw7nn"),new String[]{UtilMap.getString(formData,"textField_m7abagvx"),UtilMap.getString(formData,"textField_m7abagvy")});
+                    ddData.put(UtilMap.getString(formData,"serialNumberField_lxlfw7nn"),new String[]{UtilMap.getString(formData,"textField_m7abagvx"),UtilMap.getString(formData,"textField_m7abagvy"),UtilMap.getString(formData,"textField_mbyfztyy")});
                 }
             }
         }while (i<t);

+ 133 - 10
mjava-mc/src/main/java/com/malk/mc/service/impl/McYdServiceImpl.java

@@ -2,6 +2,7 @@ package com.malk.mc.service.impl;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -9,14 +10,18 @@ import com.malk.core.McProject;
 import com.malk.mc.service.McYdService;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.server.dingtalk.DDConf;
+import com.malk.server.dingtalk.DDR;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
 import com.malk.service.dingtalk.DDClient;
-import com.malk.utils.PublicUtil;
-import com.malk.utils.UtilHttp;
-import com.malk.utils.UtilMap;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import com.malk.service.dingtalk.DDClient_Notice;
+import com.malk.service.dingtalk.DDClient_Workflow;
+import com.malk.utils.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.slf4j.MDC;
@@ -24,10 +29,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
-import javax.rmi.CORBA.Util;
 import java.math.BigDecimal;
 import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Service
@@ -40,7 +47,14 @@ public class McYdServiceImpl implements McYdService {
     private DDConf ddConf;
     @Autowired
     private YDConf ydConf;
+    @Autowired
+    private DDClient_Workflow ddClientWorkflow;
+
+    @Autowired
+    private DDClient_Notice ddClientNotice;
 
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
     @Override
     @Async
     public void updateFormDataVersion(Map map) {
@@ -219,12 +233,17 @@ public class McYdServiceImpl implements McYdService {
 
     @Override
     public McR saveApproverToForm(Map map) {
+        try {
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
         String key = UtilMap.getString(map,"key");
         String formInstId = UtilMap.getString(map,"formInstId");
         JSONArray jsonArray=(JSONArray) ydClient.queryData(YDParam.builder().processInstanceId(formInstId).build(),YDConf.FORM_QUERY.retrieve_approval_record).getResult();
         List<String> userIds = new ArrayList<>();
         extractOperatorIds(jsonArray,userIds);
-        ydClient.operateData(YDParam.builder().updateFormDataJson(JSONObject.toJSONString(UtilMap.map(key,userIds))).formInstId(formInstId).build(), YDConf.FORM_OPERATION.update);
+        ydClient.operateData(YDParam.builder().updateFormDataJson(JSONObject.toJSONString(UtilMap.map(key, userIds))).formInstId(formInstId).build(), YDConf.FORM_OPERATION.update);
         return McR.success();
     }
 
@@ -233,10 +252,10 @@ public class McYdServiceImpl implements McYdService {
 
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(出库单)
         Map d = ydClient.queryData(YDParam.builder().formInstId(formInstId)
-                        .formUuid("FORM-3208DFE5463549A9A57FB94358A75E80PV5F")
-                        .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
-                        .systemToken("XH866P81QDOTQ0218TGZM9WCNXOF24WIP488M7A5")
-                        .userId("332051151139376769").build(),YDConf.FORM_QUERY.retrieve_id).getFormData();
+                .formUuid("FORM-3208DFE5463549A9A57FB94358A75E80PV5F")
+                .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
+                .systemToken("XH866P81QDOTQ0218TGZM9WCNXOF24WIP488M7A5")
+                .userId("332051151139376769").build(),YDConf.FORM_QUERY.retrieve_id).getFormData();
         System.out.println("出库单数据:"+d);
         List<Map> mapList = (List<Map>)d.get("tableField_m8mo8506");
         System.out.println("出库单明细数据:"+mapList);
@@ -248,7 +267,7 @@ public class McYdServiceImpl implements McYdService {
             BigDecimal InventoryCount = BigDecimal.valueOf(0);//库存数量
             BigDecimal OutboundQuantity = BigDecimal.valueOf(0);//
             if(!map1.get("numberField_m9qdwvu1_value").toString().isEmpty()){
-                 InventoryCount = new BigDecimal( map1.get("numberField_m9qdwvu1").toString());
+                InventoryCount = new BigDecimal( map1.get("numberField_m9qdwvu1").toString());
             }
             BigDecimal numberFieldM9qdwvu1 = InventoryCount.subtract( new BigDecimal( map1.get("numberField_m8mo8508").toString()));//存库数量 - 出库数量
             System.out.println("出库后数量:"+numberFieldM9qdwvu1);
@@ -597,6 +616,110 @@ public class McYdServiceImpl implements McYdService {
         return McR.success();
     }
 
+    @Override
+    public McR shareRecord(Map data) {
+        String pid = getString(data.get("pid"));
+        if (Strings.isNotBlank(pid)){
+            //发起审批
+            String[] dd = McProject.getDd(pid);
+            String appKey = "";
+            String appSecret = "";
+            String agentId = "";
+            if (!PublicUtil.isNull(pid) && dd != null && dd.length >= 3) {
+                appKey = dd[0];
+                appSecret = dd[1];
+                agentId = dd[2];
+            }
+            String[] yida = McProject.getYida(pid);
+            String appType = "";
+            String systemToken = "";
+            if (!PublicUtil.isNull(pid) && dd != null && dd.length >= 2) {
+                appType = yida[0];
+                systemToken = yida[1];
+            }
+
+            // 执行分享逻辑 [ 拼接后的权限组 ]
+            McException.assertParamException_Null(data, "compId, userIds, userId, atUserId, isNotice");
+            //开始抓取宜搭对应的子表数据
+            String processInstanceId = data.get("processInstanceId").toString();
+            List<String> atUserId = (List<String>) data.get("atUserId");
+
+            Map map = new HashMap();
+            map.put(UtilMap.getString(data, "compId"),UtilMap.getList(data, "userIds"));
+
+            ydClient.operateData(YDParam.builder()
+                    .appType(appType)
+                    .systemToken(systemToken)
+                    .formInstId(processInstanceId)
+                    .updateFormDataJson(JSON.toJSONString(map))
+                    .build(), YDConf.FORM_OPERATION.update);
+
+            String userIds = String.valueOf(data.get("atUserId"));
+            String[] split = userIds.split(",");
+            ArrayList<String> names = new ArrayList<>();
+            for(Object auserId : split){
+                DDR_New ddrNew = (DDR_New) UtilHttp.doPost("https://oapi.dingtalk.com/topapi/v2/user/get", null, ddClient.initTokenParams(), UtilMap.map("userid", auserId), DDR_New.class);
+                Object result = ddrNew.getResult();
+                if (result != null) {
+                    JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(result));
+                    String name = jsonObject.getString("name");
+                    names.add(name);
+                }
+            }
+            List<Map> searchCondition = new ArrayList<>();
+            searchCondition.addAll(Arrays.asList(
+                    YDConf.searchCondition_TextFiled(data.get("processKey").toString(), data.get("processInstanceId").toString(),"eq")
+            ));
+            String title = UtilMap.getString(data, "content").isEmpty() || !ObjectUtil.isNotNull(UtilMap.getString(data, "content")) ? "单据分享" : UtilMap.getString(data, "content");
+            ydClient.operateData(YDParam.builder()
+                    .appType(appType)
+                    .systemToken(systemToken)
+                    .searchCondition(JSON.toJSONString(searchCondition))
+                    .formUuid(data.get("formId").toString())
+                    .formDataJson(JSON.toJSONString(UtilMap.map(data.get("processKey").toString()+", "+data.get("empKey").toString()+", "+data.get("titleKey").toString(),
+                            data.get("processInstanceId").toString(),UtilMap.getList(data, "userIds"),title)))
+                    .useLatestVersion(true)
+                    .build(), YDConf.FORM_OPERATION.upsert_v2);
+            if (UtilMap.getBoolean(data, "isNotice")) {
+//                data.put("content", names.stream().collect(Collectors.joining(",")) + UtilMap.getString(data, "content"));
+                String appUrl = data.get("appUrl").toString();
+                String pcUrl = data.get("pcUrl").toString();
+                if ( !ObjectUtil.isNotNull(UtilMap.getString(data,"sendType")) || UtilMap.getString(data,"sendType").isEmpty() || "工作通知".equals(UtilMap.getString(data,"sendType"))){
+                    Map<String, String> contentMap = new HashMap<>();
+                    contentMap.put("title",title);
+                    contentMap.put("text",title);
+                    contentMap.put("picUrl",pcUrl+"/processDetail"+"?procInsId="+processInstanceId);
+                    contentMap.put("messageUrl",pcUrl+"/processDetail"+"?procInsId="+processInstanceId);
+
+                    Map<String, Object> msg = new HashMap<>();
+                    msg.put("msgtype","link");
+                    msg.put("link",contentMap);
+                    sendNotification(ddClient.getAccessToken(appKey,appSecret),atUserId,null,false,msg,agentId);
+
+                } else if ("钉钉代办".equals(UtilMap.getString(data, "sendType"))) {
+                    /*查询钉钉人员*/
+                    ddClientWorkflow.createTBTask(ddClient.getAccessToken(appKey,appSecret),UtilMap.getString(data, "userId"),"流程分享:"+UtilMap.getString(data, "content"),UtilMap.getString(data, "content"),
+                            UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().plusDays(7).atTime(LocalTime.MAX)), atUserId,null
+                            ,UtilMap.map("appUrl, pcUrl",appUrl+"/processDetail"+"?procInsId="+processInstanceId,pcUrl+"/processDetail"+"?procInsId="+processInstanceId),false,30,UtilMap.map("dingNotify","1"));
+                }
+            }
+            return McR.success();
+        }
+        return McR.errorParam("参数缺失!");
+    }
+    public String sendNotification(String access_token, List<String> userid_list, List<String> dept_id_list, boolean to_all_user, Map msg, String agent_id) {
+        Map body = UtilMap.map("agent_id, to_all_user, msg", new Object[]{agent_id, to_all_user, msg});
+        if (UtilList.isNotEmpty(userid_list)) {
+            body.put("userid_list", String.join(",", userid_list));
+        }
+        if (UtilList.isNotEmpty(dept_id_list)) {
+            body.put("dept_id_list", String.join(",", dept_id_list));
+        }
+
+        DDR ddr = DDR.doPost("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2", (Map)null, DDConf.initTokenParams(access_token), body);
+        return ddr.getTask_id();
+    }
+
     @Async
     @Override
     public void batchUpdateSpecifiedQuantityData(Map map) {

+ 16 - 0
mjava-pake/pom.xml

@@ -20,6 +20,16 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.13</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.5.13</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -61,6 +71,12 @@
             <artifactId>dingtalk</artifactId>
             <version>1.4.35</version>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 51 - 0
mjava-pake/src/main/java/com/malk/pake/controller/PkProjectController.java

@@ -0,0 +1,51 @@
+package com.malk.pake.controller;
+
+import com.malk.pake.service.PkProjectService;
+import com.malk.server.common.McR;
+import com.malk.utils.UtilMap;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+@RequestMapping("/project")
+@Slf4j
+public class PkProjectController {
+
+    @Autowired
+    private PkProjectService pkProjectService;
+
+
+    @PostMapping("/saleUpdateProject")
+    public void saleUpdateProject(String formInstId){
+        pkProjectService.saleUpdateProject(formInstId);
+    }
+    /**
+     * 推送审批
+     */
+    @PostMapping("/oaUpdateProject")
+    public McR doApprove(String processInstanceId, String type) {
+
+        log.info("推送审批, {} {}", type, processInstanceId);
+        // OA组件name, 匹配宜搭组件ID
+        if ("差旅费报销".equals(type)){
+            Map<String, String> compsId_main = UtilMap.map("费用报销类型, 付款公司, 费用出处, 项目编号, 项目名称, 商机编号, 商机名称", "selectField_m7wq5adn, selectField_m7wq5ado, selectField_m7wq5adp, textField_m7wq5adu, textField_m7wq5adx, textField_m7wq5ae0, textField_m7wq5ae2");
+            Map<String, String> compsId_itinerary = UtilMap.map("出发时间, 返回时间, 原驻地, 出差目的地, 交通工具, 车船费, 途中补贴, 住勤费, 合计金额(元)",
+                    "dateField_m9994caw, dateField_m9994cay, textField_m9994cb2, textField_m9994cb4, textField_m9994cb6, numberField_m9994cba, numberField_m9994cbc, numberField_m9994cbe, numberField_m9994cbg");
+            compsId_main.put("行程明细", "tableField_m9994cau"); // 子表组件
+            pkProjectService.oaUpdateProject(processInstanceId, "FORM-E7D787CEA025411B9ED6CF46E0AB0C3DNXU3", compsId_main, compsId_itinerary, "行程明细");
+        }else {
+            Map<String, String> compsId_main = UtilMap.map("费用报销类型, 付款公司, 费用出处, 项目编号, 项目名称, 商机编号, 商机名称", "selectField_m7wq5adn, selectField_m7wq5ado, selectField_m7wq5adp, textField_m7wq5adu, textField_m7wq5adx, textField_m7wq5ae0, textField_m7wq5ae2");
+            Map<String, String> compsId_itinerary = UtilMap.map("报销类目, 报销内容, 报销金额(元)", "selectField_m7wq5ae7, textareaField_m7wq5ae9, numberField_m7wq5aeb");
+            compsId_main.put("报销明细", "tableField_m7wq5ae5"); // 子表组件
+            pkProjectService.oaUpdateProject(processInstanceId, "FORM-E7D787CEA025411B9ED6CF46E0AB0C3DNXU3", compsId_main, compsId_itinerary, "报销明细");
+        }
+        return McR.success();
+    }
+
+
+}

+ 39 - 0
mjava-pake/src/main/java/com/malk/pake/schedule/ScheduleTask.java

@@ -1,7 +1,9 @@
 package com.malk.pake.schedule;
 
+import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.http.HttpUtil;
 import com.malk.pake.service.PkMaintenanceWarningService;
+import com.malk.pake.service.PkProjectService;
 import com.malk.pake.service.PkWorkingHoursService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +28,8 @@ public class ScheduleTask {
     private PkWorkingHoursService pkWorkingHoursService;
     @Autowired
     private PkMaintenanceWarningService pkMaintenanceWarningService;
+    @Autowired
+    private PkProjectService pkProjectService;
 
     /**
      * 工时填写提醒-按月
@@ -88,4 +92,39 @@ public class ScheduleTask {
             e.printStackTrace();
         }
     }
+    /**
+     * 阿里商旅火车票
+     * 每天00:00获取阿里商旅昨日火车票数据
+     */
+    @Scheduled(cron = "0 10 0 * * ?")
+    public void getTrainInternal() {
+        log.info("阿里商旅火车票");
+        LocalDate now = LocalDate.now();
+        String formatToday = LocalDateTimeUtil.format(now, "yyyy-MM-dd");
+        LocalDate yesterday = now.plusDays(-1);
+        String formatYesterday = LocalDateTimeUtil.format(yesterday, "yyyy-MM-dd");
+        try {
+            pkProjectService.getTrainInternal(formatYesterday,formatToday);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 阿里商旅机票
+     * 每天00:30获取阿里商旅机票昨日数据
+     */
+    @Scheduled(cron = "0 30 1 * * ?")
+    public void getAirInternal() {
+        log.info("阿里商旅机票");
+        LocalDate now = LocalDate.now();
+        String formatToday = LocalDateTimeUtil.format(now, "yyyy-MM-dd");
+        LocalDate yesterday = now.plusDays(-1);
+        String formatYesterday = LocalDateTimeUtil.format(yesterday, "yyyy-MM-dd");
+        try {
+            pkProjectService.getAirInternal(formatYesterday,formatToday);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 15 - 0
mjava-pake/src/main/java/com/malk/pake/service/PkProjectService.java

@@ -0,0 +1,15 @@
+package com.malk.pake.service;
+
+import java.util.Map;
+
+public interface PkProjectService {
+
+    void saleUpdateProject(String formInstId);
+
+    //OA通用报销审批通过后更新写入宜搭
+    void oaUpdateProject(String processInstanceId, String formUuid, Map<String, String> compsId_main, Map<String, String> compsId_itinerary, String compId_sub_oa);
+    //获取日期范围内阿里商旅火车票数据
+    void getTrainInternal(String startDate, String endDate);
+    //获取日期范围内阿里商旅机票数据
+    void getAirInternal(String startDate, String endDate);
+}

+ 507 - 0
mjava-pake/src/main/java/com/malk/pake/service/impl/PkProjectServiceImpl.java

@@ -0,0 +1,507 @@
+package com.malk.pake.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.pake.service.PkProjectService;
+import com.malk.pake.utils.HttpUtils;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Notice;
+import com.malk.service.dingtalk.DDClient_Workflow;
+import com.malk.utils.UtilDateTime;
+import com.malk.utils.UtilMap;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.map.HashedMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Service
+@Slf4j
+public class PkProjectServiceImpl implements PkProjectService {
+
+    @Autowired
+    private DDClient ddClient;
+    @Autowired
+    private DDClient_Notice ddClient_notice;
+    @Autowired
+    private YDClient ydClient;
+    @Autowired
+    private DDClient_Workflow ddClient_workflow;
+
+    private String projectFormUUID = "FORM-7F8921D7324F43B3B1147C1D99A3F758NFIL";
+    private String saleFormUUID = "FORM-4V966N81BW8D84BFBI41WACUKFRZ1XBFPVELLJ";
+    private String trainUUID = "FORM-78E05305A9BB4BBBABF5E34F781530D1RP78";
+    private String airUUID = "FORM-53E3974D2A074B00AA6C66DE278F7938ZNNT";
+
+    /// dingtalk
+    @Value("${dingtalk.appKey}")
+    private String APP_EKY;
+    @Value("${dingtalk.appSecret}")
+    private String APP_SECRET;
+    /// aliwork
+    @Value("${aliwork.appType}")
+    private String APP_TYPE;
+    @Value("${aliwork.systemToken}")
+    private String SYSTRM_TOKEN;
+    /// 阿里商旅
+    @Value("${alibusinesstravel.appKey}")
+    private String BUS_kEY;
+    @Value("${alibusinesstravel.appSecret}")
+    private String BUS_SECRET;
+    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    private static final Map<String,String> AIR_FEE_TYPE  = new HashMap<>();
+    static {
+        AIR_FEE_TYPE.put("10101","机票预订");
+        AIR_FEE_TYPE.put("10202","机票改签手续费");
+        AIR_FEE_TYPE.put("10203","机票改签差价");
+        AIR_FEE_TYPE.put("10301","机票退款");
+        AIR_FEE_TYPE.put("10302","机票改签退款");
+        AIR_FEE_TYPE.put("10303","机票补退");
+        AIR_FEE_TYPE.put("10401","机票保险-航意险购买");
+        AIR_FEE_TYPE.put("10501","机票保险-航意险退保");
+        AIR_FEE_TYPE.put("11001","机票预订服务费");
+        AIR_FEE_TYPE.put("11002","机票改签服务费");
+        AIR_FEE_TYPE.put("10304","机票票据服务费退款");
+        AIR_FEE_TYPE.put("11003","机票票据服务费");
+        AIR_FEE_TYPE.put("11004","机票托管协议服务费");
+        AIR_FEE_TYPE.put("11005","机票改签托管协议服务费");
+    }
+    private static final Map<String,String> TRAIN_FEE_TYPE = new HashMap<>();
+    static {
+       TRAIN_FEE_TYPE.put("6001","火车票预订");
+       TRAIN_FEE_TYPE.put("6003","火车票改签差价");
+       TRAIN_FEE_TYPE.put("6004","火车票改签手续费");
+       TRAIN_FEE_TYPE.put("6005","火车票退票");
+       TRAIN_FEE_TYPE.put("6007","火车票预订服务费");
+       TRAIN_FEE_TYPE.put("6008","火车票改签服务费");
+       TRAIN_FEE_TYPE.put("6009","火车票预订退款");
+       TRAIN_FEE_TYPE.put("6010","火车票改签退款");
+       TRAIN_FEE_TYPE.put("6101","火车票抢票加速包");
+       TRAIN_FEE_TYPE.put("6011","火车票票据服务费");
+       TRAIN_FEE_TYPE.put("6012","火车票技术服务费");
+       TRAIN_FEE_TYPE.put("6013","火车票票据服务费退款");
+       TRAIN_FEE_TYPE.put("6014","火车票线下退改退款");
+    }
+    @Override
+    public void saleUpdateProject(String formInstId) {
+//        log.info("流程id:{}",formInstId);
+        Map formData = ydClient.queryData(YDParam.builder().formInstanceId(formInstId).build(),
+                YDConf.FORM_QUERY.retrieve_id).getFormData();
+        String contractCode = formData.get("textField_llew0vlc").toString();
+        String contractName = formData.get("textareaField_lq0s1gcw").toString();
+        String contractAmount = formData.get("numberField_llew0vlx_value").toString();
+        String projectCode = formData.get("textField_ltpbh04c").toString();
+        if (!projectCode.isEmpty() && ObjectUtil.isNotNull(projectCode)){
+            List<Map<String, Object>> dataList = (List<Map<String, Object>>)ydClient.queryData(YDParam.builder().formUuid(projectFormUUID)
+                            .searchFieldJson(JSONObject.toJSONString(UtilMap.map("textField_llemcq7d", projectCode))).build(),
+                    YDConf.FORM_QUERY.retrieve_search_form).getData();
+
+            List<Map<String,Object>> association = new ArrayList<>();
+            Map<String, Object> map = UtilMap.map("appType, formType, formUuid, instanceId, subTitle, title", "APP_UNSAR4O4Y7NBDUYXLIP4", "process", saleFormUUID, formInstId, contractCode, contractName);
+            association.add(map);
+            dataList.forEach(e->{
+                ydClient.operateData(YDParam.builder()
+                        .formInstanceId(e.get("formInstanceId").toString())
+                        .updateFormDataJson(JSON.toJSONString(UtilMap.map("associationFormField_lmlq4t3o, textField_lmlq4t3p, textField_lmlq4t3q, numberField_m731di5q",association,contractName,contractCode,contractAmount)))
+                        .useLatestVersion(true)
+                        .build(), YDConf.FORM_OPERATION.update);
+            });
+        }
+    }
+
+    @Override
+    public void oaUpdateProject(String processInstanceId, String formUuid, Map<String, String> compsId_main, Map<String, String> compsId_itinerary, String compId_sub_oa) {
+
+        String token = ddClient.getAccessToken(APP_EKY, APP_SECRET);
+//        log.info("processInstanceId:{}",processInstanceId);
+        Map processData = ddClient_workflow.getProcessInstanceId(token, processInstanceId);
+        List<Map> formComponentValues = (List<Map>) processData.get("formComponentValues");
+        String userId = String.valueOf(processData.get("originatorUserId"));
+        long cDate = UtilDateTime.parse(UtilMap.getString(processData, "createTime"), "yyyy-MM-dd'T'HH:mm").getTime();
+        Map formData = UtilMap.map("employeeField_ltxqs53k, departmentSelectField_lu20ayky, dateField_ltxqs53j, textField_lygnetw9", Arrays.asList(userId), Arrays.asList(processData.get("originatorDeptId")), cDate, UtilMap.getString(processData, "businessId"));
+        Optional optional = formComponentValues.stream().filter(item -> "费用出处".equals(item.get("name"))).findAny();
+        if (optional.isPresent() && (UtilMap.getString((Map) optional.get(), "value").equals("项目费用") || UtilMap.getString((Map) optional.get(), "value").equals("研发费用"))){
+            Double OATravelSum = 0.0;//OA差旅费用
+            Double OATrafficSum = 0.0;//OA交通费用
+            Double OAEntertainSum = 0.0;//OA招待费用
+            Double OAOtherSum = 0.0;//OA其他费用
+            optional = formComponentValues.stream().filter(item -> "项目编号".equals(item.get("name"))).findAny();
+            if (!optional.isPresent()){
+                return;
+            }
+            String projectCode = UtilMap.getString((Map) optional.get(), "value");
+            optional = formComponentValues.stream().filter(item -> "费用报销类型".equals(item.get("name"))).findAny();
+            String type = UtilMap.getString((Map) optional.get(), "value");
+            for (String name : compsId_main.keySet()) {
+                String compId = compsId_main.get(name);
+                // 判定是否子表 [宜搭]
+                if (compId.startsWith("tableField_")) {
+                    List<Map> details = new ArrayList<>();
+                    // 兼容明细组件, 存在多条情况 [加班跨天才有有明细]
+                    optional = formComponentValues.stream().filter(item -> compId_sub_oa.equals(item.get("name"))).findAny();
+                    if (!optional.isPresent()) {
+                        continue;
+                    }
+                    String schedule = UtilMap.getString((Map) optional.get(), "value");
+                    List<Map> itineraryList = ((List<Map>) JSON.parse(schedule));
+                    // 循环明细数据
+                    for (Map itinerary : itineraryList) {
+                        List<Map> rowValue = (List<Map>) itinerary.get("rowValue");
+                        Map rowData = new HashedMap();
+                        // 循环子表组件插入宜搭表单
+                        for (String subName : compsId_itinerary.keySet()) {
+                            if ("出发时间".equals(subName) || "返回时间".equals(subName)) {
+                                rowValue.forEach(r->{
+                                    Object label = r.get("label");
+                                    if (label instanceof  JSONArray){
+                                        Object value = r.get("value");
+                                        JSONArray jsonArray = JSONArray.parseArray(value.toString());
+                                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                                        try {
+                                            rowData.put(compsId_itinerary.get("出发时间"), sdf.parse(jsonArray.get(0).toString()).getTime());
+                                            rowData.put(compsId_itinerary.get("返回时间"), sdf.parse(jsonArray.get(1).toString()).getTime());
+                                        } catch (ParseException e) {
+//                                            log.info("字符串时间转字符串出错");
+                                        }
+                                    }
+                                });
+                            }else {
+                                //  加班单跨天 [子表label为空]
+                                try {
+                                    Object value = rowValue.stream().filter(item -> subName.equals(item.get("bizAlias")) || subName.equals(item.get("label"))).findAny().get().get("value");
+                                    rowData.put(compsId_itinerary.get(subName), value);
+                                } catch (Exception e) {
+//                                    log.info("流程版本字段差异");
+                                }
+                            }
+                        }
+                        details.add(rowData);
+                        String category = "";
+                        double amount = 0.0;
+                        if ("行程明细".equals(compId_sub_oa)){
+                            amount = Double.parseDouble(rowValue.stream().filter(item -> "合计金额(元)".equals(item.get("bizAlias")) || "合计金额(元)".equals(item.get("label"))).findAny().get().get("value").toString());
+                        }else {
+                            category = rowValue.stream().filter(item -> "报销类目".equals(item.get("bizAlias")) || "报销类目".equals(item.get("label"))).findAny().get().get("value").toString();
+                            amount =  Double.parseDouble(rowValue.stream().filter(item -> "报销金额(元)".equals(item.get("bizAlias")) || "报销金额(元)".equals(item.get("label"))).findAny().get().get("value").toString());
+                        }
+                        if ("日常费用报销".equals(type)){
+                            if ("团建费".equals(category)){
+                                OAEntertainSum = OAEntertainSum + amount;
+                            } else if ("交通费".equals(category)) {
+                                OATrafficSum = OATrafficSum + amount;
+                            }else {
+                                OAOtherSum = OAOtherSum + amount;
+                            }
+                        }else if ("差旅费报销".equals(type)){
+                            OATravelSum = OATravelSum + amount;
+                        }else if ("业务招待费报销".equals(type)){
+                            OAEntertainSum = OAEntertainSum + amount;
+                        }else if ("交通费".equals(type)){
+                            OATrafficSum = OATrafficSum + amount;
+                        }
+                    }
+                    formData.put(compId, details);
+                }
+                else {
+                    optional = formComponentValues.stream().filter(item -> name.equals(item.get("name"))).findAny();
+                    if (!optional.isPresent()){
+                        continue;
+                    }
+                    formData.put(compId,UtilMap.getString((Map) optional.get(), "value"));
+                }
+            }
+
+            List<Map> dataList = (List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-25910D3D9DA6455C9234BEC1C08687FD0OZK")
+                    .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llemcq7d",projectCode))).build(), YDConf.FORM_QUERY.retrieve_list).getData();
+            Double finalOATravelSum = OATravelSum;
+            Double finalOATrafficSum = OATrafficSum;
+            Double finalOAEntertainSum = OAEntertainSum;
+            Double finalOAOtherSum = OAOtherSum;
+            dataList.forEach(e->{
+                Map data = (Map) e.get("formData");
+                //差旅费用
+                double travelAmount = Double.parseDouble(data.get("numberField_m7473oph_value")==null||data.get("numberField_m7473oph_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473oph_value").toString());
+                //交通费用
+                double trafficAmount = Double.parseDouble(data.get("numberField_m7473opi_value")==null||data.get("numberField_m7473opi_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opi_value").toString());
+                //招待费用
+                double entertainAmount = Double.parseDouble(data.get("numberField_m7473opn_value")==null||data.get("numberField_m7473opn_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opn_value").toString());
+                //其他费用
+                double otherAmount = Double.parseDouble(data.get("numberField_m7473opo_value")==null||data.get("numberField_m7473opo_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opo_value").toString());
+                //累计总成本
+                double totalSumAmount = Double.parseDouble(data.get("numberField_m7473opq_value")==null||data.get("numberField_m7473opq_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opq_value").toString());
+                //预算总成本
+                double totalBudgetedCost = Double.parseDouble(data.get("numberField_m732y3r0_value")==null||data.get("numberField_m732y3r0_value").toString().isEmpty() ? "0.0" : data.get("numberField_m732y3r0_value").toString());
+                //累计报销费
+                double totalApplyCost = Double.parseDouble(data.get("numberField_m7wyydmc_value")==null||data.get("numberField_m7wyydmc_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmc_value").toString());
+                //累计预算报销费用
+                double totalBudgetedApply = Double.parseDouble(data.get("numberField_m7wyydmd_value")==null||data.get("numberField_m7wyydmd_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmd_value").toString());
+                travelAmount = travelAmount + finalOATravelSum;
+                trafficAmount = trafficAmount + finalOATrafficSum;
+                entertainAmount = entertainAmount + finalOAEntertainSum;
+                otherAmount = otherAmount + finalOAOtherSum;
+                totalSumAmount = totalSumAmount + finalOATravelSum + finalOATrafficSum + finalOAEntertainSum + finalOAOtherSum;
+                totalApplyCost = totalApplyCost + finalOATravelSum + finalOATrafficSum + finalOAEntertainSum + finalOAOtherSum;
+                ydClient.operateData(YDParam.builder()
+                        .appType(APP_TYPE)
+                        .systemToken(SYSTRM_TOKEN)
+                        .formInstanceId(e.get("formInstanceId").toString())
+                        .updateFormDataJson(JSON.toJSONString(UtilMap.map("numberField_m7473oph, numberField_m7473opi, numberField_m7473opn, numberField_m7473opo, numberField_m7473opq, numberField_m7473oqm, numberField_m7wyydmc, numberField_m7473oqi",travelAmount,trafficAmount,entertainAmount,otherAmount,totalSumAmount,totalSumAmount/totalBudgetedCost*100,totalApplyCost,totalApplyCost/totalBudgetedApply*100)))
+                        .build(),YDConf.FORM_OPERATION.update);
+            });
+            // 用于审批回传
+//        List<Map> tasks = UtilMap.getList(processData, "tasks");
+//        formData.put("textField_lygvvyd9", tasks.get(0).get("taskId"));
+//        formData.put("textField_lygvvyda", tasks.get(0).get("userId"));
+            formData.put("textField_lyh4y3th", processInstanceId);
+            ydClient.operateData(YDParam.builder()
+                    .appType(APP_TYPE)
+                    .systemToken(SYSTRM_TOKEN)
+                    .formUuid(formUuid)
+                    .formDataJson(JSON.toJSONString(formData))
+                    .userId(userId)
+                    .build(), YDConf.FORM_OPERATION.create);
+        }
+    }
+
+
+    @Override
+    public void getTrainInternal(String startDate, String endDate) {
+        String token = getBusinessTravelToken();
+        if (ObjectUtil.isNotNull(token)){
+            Map<String, Object> param = UtilMap.map("app_key, so_corp_token, page_no, page_size, period_start, period_end", BUS_kEY, token, 1, 100, startDate, endDate);
+            String url = "https://btripopen.alibtrip.com/api/train/v1/bill-settlement?";
+            List<Object> results = getResult(url, param);
+            if (ObjectUtil.isNotNull(results) && results.size()>0){
+                results.forEach(r->{
+                    JSONObject result = JSONObject.parseObject(r.toString());
+                    if (ObjectUtil.isNotNull(result)){
+                        if (ObjectUtil.isNotNull(result.get("project_code")) && !result.get("project_code").toString().isEmpty()){
+                            String projectCode = result.get("project_code").toString();
+
+                            List<Map> dataList = (List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-25910D3D9DA6455C9234BEC1C08687FD0OZK")
+                                    .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llemcq7d",projectCode))).build(), YDConf.FORM_QUERY.retrieve_list).getData();
+                            Double amount = result.get("ticket_corp_pay_price") == null || result.get("ticket_corp_pay_price").toString().isEmpty()?0.0:Double.parseDouble(result.get("ticket_corp_pay_price").toString());
+                            dataList.forEach(e->{
+                                Map data = (Map) e.get("formData");
+                                //差旅费用
+                                double travelAmount = Double.parseDouble(data.get("numberField_m7473oph_value")==null||data.get("numberField_m7473oph_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473oph_value").toString());
+                                //交通费用
+//                            double trafficAmount = Double.parseDouble(data.get("numberField_m7473opi_value")==null||data.get("numberField_m7473opi_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opi_value").toString());
+                                //累计总成本
+                                double totalSumAmount = Double.parseDouble(data.get("numberField_m7473opq_value")==null||data.get("numberField_m7473opq_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opq_value").toString());
+                                //预算总成本
+                                double totalBudgetedCost = Double.parseDouble(data.get("numberField_m732y3r0_value")==null||data.get("numberField_m732y3r0_value").toString().isEmpty() ? "0.0" : data.get("numberField_m732y3r0_value").toString());
+                                //累计报销费
+                                double totalApplyCost = Double.parseDouble(data.get("numberField_m7wyydmc_value")==null||data.get("numberField_m7wyydmc_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmc_value").toString());
+                                //累计预算报销费用
+                                double totalBudgetedApply = Double.parseDouble(data.get("numberField_m7wyydmd_value")==null||data.get("numberField_m7wyydmd_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmd_value").toString());
+                                travelAmount = travelAmount + amount;
+                                totalSumAmount = totalSumAmount + amount;
+                                totalApplyCost = totalApplyCost + amount;
+                                ydClient.operateData(YDParam.builder()
+                                        .appType(APP_TYPE)
+                                        .systemToken(SYSTRM_TOKEN)
+                                        .formInstanceId(e.get("formInstanceId").toString())
+                                        .updateFormDataJson(JSON.toJSONString(UtilMap.map("numberField_m7473oph, numberField_m7473opq, numberField_m7473oqm, numberField_m7wyydmc, numberField_m7473oqi",travelAmount,totalSumAmount,totalSumAmount/totalBudgetedCost*100,totalApplyCost,totalApplyCost/totalBudgetedApply*100)))
+                                        .build(),YDConf.FORM_OPERATION.update);
+                            });
+                        }
+                        HashMap<String, Object> formData = new HashMap<>();
+                        try {
+                            formData.put("dateField_m9jm4pia",simpleDateFormat.parse(result.get("book_time").toString()).getTime());//预定时间
+                            formData.put("textField_m9jm4pib",result.get("booker_name"));//预定人
+                            formData.put("textField_m9jm4pic",result.get("traveler_name"));//出行人
+                            formData.put("textField_m9jm4pid",result.get("cascade_department"));//联级部门
+                            formData.put("textField_m9jm4pik",result.get("cost_center"));//成本中心名称
+                            formData.put("textField_m9jm4pil",result.get("project_name"));//项目名称
+                            formData.put("textField_m9jm4pim",result.get("project_code"));//项目编码
+                            formData.put("textField_m9jm4pj5",TRAIN_FEE_TYPE.get(result.get("fee_type").toString()));//费用类型
+                            formData.put("dateField_m9jm4pit",simpleDateFormat.parse(result.get("dept_date") + " 00:00:00").getTime());//发车日期
+                            formData.put("textField_m9jm4piu",result.get("dept_time"));//发车时间
+                            formData.put("dateField_m9jm4piv",simpleDateFormat.parse(result.get("arr_date") + " 00:00:00").getTime());//到达日期
+                            formData.put("textField_m9jm4piw",result.get("arr_time"));//到达时间
+                            formData.put("textField_m9jm4pj2",result.get("dep_city_name"));//出发城市
+                            formData.put("textField_m9jm4pj3",result.get("arr_city_name"));//到达城市
+                            formData.put("textField_m9jm4pj4",result.get("seat_type"));//坐席
+                            formData.put("numberField_m9jm4pjb",result.get("ticket_corp_pay_price"));//企业支付金额
+                            formData.put("textareaField_m9jm4pjf",result.get("business_trip_result"));//出差事由
+                            formData.put("textareaField_m9jm4pjg",result.get("change_result"));//改签原因
+                            formData.put("textareaField_m9jm4pjh",result.get("refund_reason"));//退订原因
+                            formData.put("textareaField_m9jm4pjn",result.get("exceed_reason"));//超标原因
+                            formData.put("textareaField_m9jm4pjo",result.get("remark"));//备注
+                        } catch (ParseException e) {
+                            throw new RuntimeException(e);
+                        }
+                        ydClient.operateData(YDParam.builder()
+                                .appType(APP_TYPE)
+                                .systemToken(SYSTRM_TOKEN)
+                                .formUuid(trainUUID)
+                                .formDataJson(JSON.toJSONString(formData))
+                                .build(), YDConf.FORM_OPERATION.create);
+                    }
+                });
+            }
+        }
+    }
+
+    @Override
+    public void getAirInternal(String startDate, String endDate) {
+        String token = getBusinessTravelToken();
+        if (ObjectUtil.isNotNull(token)){
+            Map<String, Object> param = UtilMap.map("app_key, so_corp_token, page_no, page_size, period_start, period_end", BUS_kEY, token, 1, 100, startDate, endDate);
+            String url = "https://btripopen.alibtrip.com/api/flight/v1/bill-settlement?";
+            List<Object> results = getResult(url, param);
+            if (ObjectUtil.isNotNull(results) && results.size()>0){
+                results.forEach(r->{
+                    JSONObject result = JSONObject.parseObject(r.toString());
+                    if (ObjectUtil.isNotNull(result)){
+                        if (ObjectUtil.isNotNull(result.get("project_code")) && !result.get("project_code").toString().isEmpty()){
+                            String projectCode = result.get("project_code").toString();
+
+                            List<Map> dataList = (List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-25910D3D9DA6455C9234BEC1C08687FD0OZK")
+                                    .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llemcq7d",projectCode))).build(), YDConf.FORM_QUERY.retrieve_list).getData();
+                            Double amount = result.get("corp_settle_price") == null || result.get("corp_settle_price").toString().isEmpty()?0.0:Double.parseDouble(result.get("corp_settle_price").toString());
+                            dataList.forEach(e->{
+                                Map data = (Map) e.get("formData");
+                                //差旅费用
+                                double travelAmount = Double.parseDouble(data.get("numberField_m7473oph_value")==null||data.get("numberField_m7473oph_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473oph_value").toString());
+                                //交通费用
+//                            double trafficAmount = Double.parseDouble(data.get("numberField_m7473opi_value")==null||data.get("numberField_m7473opi_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opi_value").toString());
+                                //累计总成本
+                                double totalSumAmount = Double.parseDouble(data.get("numberField_m7473opq_value")==null||data.get("numberField_m7473opq_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7473opq_value").toString());
+                                //预算总成本
+                                double totalBudgetedCost = Double.parseDouble(data.get("numberField_m732y3r0_value")==null||data.get("numberField_m732y3r0_value").toString().isEmpty() ? "0.0" : data.get("numberField_m732y3r0_value").toString());
+                                //累计报销费
+                                double totalApplyCost = Double.parseDouble(data.get("numberField_m7wyydmc_value")==null||data.get("numberField_m7wyydmc_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmc_value").toString());
+                                //累计预算报销费用
+                                double totalBudgetedApply = Double.parseDouble(data.get("numberField_m7wyydmd_value")==null||data.get("numberField_m7wyydmd_value").toString().isEmpty() ? "0.0" : data.get("numberField_m7wyydmd_value").toString());
+                                travelAmount = travelAmount + amount;
+                                totalSumAmount = totalSumAmount + amount;
+                                totalApplyCost = totalApplyCost + amount;
+                            ydClient.operateData(YDParam.builder()
+                                    .appType(APP_TYPE)
+                                    .systemToken(SYSTRM_TOKEN)
+                                    .formInstanceId(e.get("formInstanceId").toString())
+                                    .updateFormDataJson(JSON.toJSONString(UtilMap.map("numberField_m7473oph, numberField_m7473opq, numberField_m7473oqm, numberField_m7wyydmc, numberField_m7473oqi",travelAmount,totalSumAmount,totalSumAmount/totalBudgetedCost*100,totalApplyCost,totalApplyCost/totalBudgetedApply*100)))
+                                    .build(),YDConf.FORM_OPERATION.update);
+
+                            });
+                        }
+                        HashMap<String, Object> formData = new HashMap<>();
+                        try {
+                            formData.put("dateField_m9jm4pia",simpleDateFormat.parse(result.get("book_time").toString()).getTime());//预定时间
+                            formData.put("textField_m9jm4pib",result.get("booker_name"));//预定人
+                            formData.put("textField_m9jm4pic",result.get("traveler_name"));//出行人
+                            formData.put("textField_m9jm4pid",result.get("cascade_department"));//联级部门
+                            formData.put("textField_m9jm4pik",result.get("cost_center"));//成本中心名称
+                            formData.put("textField_m9jm4pil",result.get("project_name"));//项目名称
+                            formData.put("textField_m9jm4pim",result.get("project_code"));//项目编码
+                            formData.put("textField_m9jrbcig",result.get("capital_direction"));//资金方向
+                            formData.put("dateField_m9jm4pit",simpleDateFormat.parse(result.get("dept_date") + " 00:00:00").getTime());//起飞日期
+                            formData.put("textField_m9jm4piu",result.get("dept_time"));//起飞时间
+                            formData.put("dateField_m9jm4piv",simpleDateFormat.parse(result.get("arr_date") + " 00:00:00").getTime());//到达日期
+                            formData.put("textField_m9jm4piw",result.get("arr_time"));//到达时间
+                            formData.put("textField_m9jm4pj2",result.get("dept_city"));//起飞城市
+                            formData.put("textField_m9jm4pj3",result.get("arr_city"));//到达城市
+                            formData.put("textField_m9jm4pj4",result.get("cabin_class"));//舱等
+                            formData.put("textField_m9jm4pj5",AIR_FEE_TYPE.get(result.get("fee_type").toString()));//费用类型
+                            formData.put("numberField_m9jm4pjb",result.get("corp_pay_order_fee"));//订单金额
+                            formData.put("numberField_m9jrbcih",result.get("settlement_fee"));//结算金额
+                            formData.put("numberField_m9jrbcii",result.get("corp_settle_price"));//企业支付金额
+                            formData.put("numberField_m9jrbcio",result.get("person_settle_price"));//个人支付金额
+                            formData.put("numberField_m9jrbciq",result.get("refund_fee"));//退票手续费
+                            formData.put("numberField_m9jrbcir",result.get("refund_upgrade_cost"));//改签退票手续费
+                            formData.put("textField_m9jrbcit",result.get("discount"));//折扣率
+                            formData.put("numberField_m9jrbciz",result.get("advance_day"));//提前预定天数
+                            formData.put("textareaField_m9jm4pjf",result.get("business_trip_result"));//出差事由
+                            formData.put("textareaField_m9jm4pjh",result.get("refund_reason"));//退订原因
+                            formData.put("textareaField_m9jm4pjg",result.get("change_result"));//改签原因
+                            formData.put("textareaField_m9jm4pjn",result.get("exceed_reason"));//超标原因
+                            formData.put("textareaField_m9jm4pjo",result.get("remark"));//备注
+                        } catch (ParseException e) {
+                            throw new RuntimeException(e);
+                        }
+                        ydClient.operateData(YDParam.builder()
+                                .appType(APP_TYPE)
+                                .systemToken(SYSTRM_TOKEN)
+                                .formUuid(airUUID)
+                                .formDataJson(JSON.toJSONString(formData))
+                                .build(), YDConf.FORM_OPERATION.create);
+                    }
+                });
+            }
+        }
+    }
+
+    //获取阿里商旅访问token
+    public static String getBusinessTravelToken(){
+        String result = HttpUtils.httpGet("https://btripopen.alibtrip.com/api/btrip-open-auth/v1/corp-token/action/take?app_key=pqm6bkfs0800&type=0&corp_id=open12pqm6bkfju87v16348dd896bc361558&app_secret=cHFtNmJrZnMwODAwXS1ceXpINzUsazUkVT1tejohZ1o");
+        JSONObject jsonObject = JSONObject.parseObject(result);
+        if (ObjectUtil.isNotNull(jsonObject) && Boolean.parseBoolean(jsonObject.get("success").toString())){
+            Object module = jsonObject.get("module");
+            jsonObject = JSONObject.parseObject(module.toString());
+            return jsonObject.get("token").toString();
+        }
+        return null;
+    }
+    //根据token和分页获取所有数据
+    public static List<Object> getResult(String url,Map<String,Object> param){
+        int pageSize = 100;
+        if (param.containsKey("page_size")){
+            pageSize = Integer.parseInt(param.get("page_size").toString());
+        }
+        Map<String, Object> getTotalMap = new HashMap<>(param);
+        getTotalMap.put("page_no",1);
+        getTotalMap.put("page_size",1);
+        JSONObject jsonObject = toRequest(url, getTotalMap);
+        if (ObjectUtil.isNotNull(jsonObject)){
+            List<Object> objects = new ArrayList<>();
+            int totalNum = Integer.parseInt(jsonObject.get("total_num").toString());
+            int totalPages = (int) Math.ceil(totalNum / pageSize) + 1;
+            for (int i = 1; i <= totalPages; i++) {
+                param.put("page_no",i);
+                JSONObject result = toRequest(url, param);
+                List<Object> dataList = (List<Object>) result.get("data_list");
+                objects.addAll(dataList);
+            }
+            return objects;
+        }
+        return null;
+    }
+    //获取module里的数据
+    @SneakyThrows
+    public static JSONObject toRequest(String url, Map<String,Object> param){
+        final String[] redirectUrl = {url};
+        param.forEach((k,v)->{
+            redirectUrl[0] = redirectUrl[0] + k + "=" + v + "&";
+        });
+        if (redirectUrl[0].endsWith("&")){
+            redirectUrl[0] = redirectUrl[0].substring(0,redirectUrl[0].length()-1);
+        }
+        String result = HttpUtils.httpGet(redirectUrl[0]);
+        JSONObject jsonObject = JSONObject.parseObject(result);
+        boolean success = Boolean.parseBoolean(jsonObject.get("success").toString());
+        while (!success){
+            result = HttpUtils.httpGet(redirectUrl[0]);
+            jsonObject = JSONObject.parseObject(result);
+            success = Boolean.parseBoolean(jsonObject.get("success").toString());
+            Thread.sleep(1000);
+        }
+        if (ObjectUtil.isNotNull(jsonObject) && success){
+            Object module = jsonObject.get("module");
+            jsonObject = JSONObject.parseObject(module.toString());
+            return jsonObject;
+        }
+        return null;
+    }
+}

+ 285 - 0
mjava-pake/src/main/java/com/malk/pake/utils/HttpUtils.java

@@ -0,0 +1,285 @@
+package com.malk.pake.utils;
+
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.conn.DnsResolver;
+import org.apache.http.conn.HttpConnectionFactory;
+import org.apache.http.conn.ManagedHttpClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.impl.conn.SystemDefaultDnsResolver;
+import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
+import org.apache.http.impl.io.DefaultHttpResponseParserFactory;
+import org.apache.http.util.EntityUtils;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * http请求封装
+ *
+ * @author lh
+ * @date 2022-09-23
+ */
+@Slf4j
+public class HttpUtils {
+
+    /**
+     * 默认请求类型
+     */
+    private static final String DEFAULT_CONTENT_TYPE = "application/json";
+
+    /**
+     * 默认编码
+     */
+    private static final String DEFAULT_ENCODING = "utf-8";
+
+    /**
+     * GBK编码
+     */
+    private static final String GBK_ENCODING = "GBK";
+
+    /**
+     * 默认超时时间
+     */
+    private static final int DEFAULT_TIME_OUT = 60;
+
+    private static PoolingHttpClientConnectionManager manager = null;
+
+    private static CloseableHttpClient httpClient = null;
+
+    /**
+     * 获取httpclient对象
+     *
+     * @return
+     */
+    public static synchronized CloseableHttpClient getHttpClient(int timeOut) {
+        if (null == httpClient) {
+            log.info("============================================创建");
+            // 注册访问协议相关的socket工厂
+            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
+                    .register("http", PlainConnectionSocketFactory.INSTANCE)
+                    .register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
+                    .build();
+
+            // httpConnection工厂
+            HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connectionFactory =
+                    new ManagedHttpClientConnectionFactory(DefaultHttpRequestWriterFactory.INSTANCE
+                            , DefaultHttpResponseParserFactory.INSTANCE);
+
+            // DNS解析器
+            DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
+            // 创建池化连接管理器
+            manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connectionFactory, dnsResolver);
+            // socket配置
+            SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
+            manager.setDefaultSocketConfig(socketConfig);
+            // 连接池最大连接数
+            manager.setMaxTotal(300);
+            manager.setDefaultMaxPerRoute(200);
+            // 5s检测一次连接池连接
+            manager.setValidateAfterInactivity(5 * 1000);
+            // 默认请求配置
+            RequestConfig requestConfig = RequestConfig.custom()
+                    // 连接超时时间
+                    .setConnectTimeout(timeOut * 1000)
+                    // 等待数据超时时间
+                    .setSocketTimeout(timeOut * 1000)
+                    // 从连接池获取连接超时时间
+                    .setConnectionRequestTimeout(timeOut * 1000)
+                    .build();
+            // 创建httpclient
+            httpClient = HttpClients.custom()
+                    .setConnectionManager(manager)
+                    // 连接池不共享
+                    .setConnectionManagerShared(false)
+                    // 定期回收空闲连接
+                    .evictIdleConnections(timeOut, TimeUnit.SECONDS)
+                    // 定期回收过期连接
+                    .evictExpiredConnections()
+                    .setConnectionTimeToLive(timeOut, TimeUnit.SECONDS)
+                    // 设置默认请求
+                    .setDefaultRequestConfig(requestConfig)
+                    // 连接重用策略
+                    .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
+                    // 长连接配置
+                    .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
+                    // 设置重试次数
+                    .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
+                    .build();
+
+            // jvm停止或重启时,关闭连接池释放连接
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+
+                @Override
+                public void run() {
+                    try {
+                        if (null != httpClient) {
+                            httpClient.close();
+                        }
+                    } catch (Exception e) {
+                        log.error("httpclient关闭异常:{}", e);
+                    }
+                }
+            });
+        }
+        return httpClient;
+    }
+
+    /**
+     * http请求
+     *
+     * @param url
+     * @param params
+     * @return
+     */
+    public static String httpPost(String url, Map params,Map<String,String> headers) {
+        log.info("POST请求url:{}", url);
+        log.info("POST请求参数:{}",JSON.toJSONString(params));
+        CloseableHttpClient httpClient = getHttpClient(DEFAULT_TIME_OUT);
+        HttpPost httpPost = new HttpPost(url);
+
+        if (null != headers){
+            for (String key:headers.keySet()){
+                httpPost.setHeader(key,headers.get(key).toString());
+            }
+        }
+
+        String json = JSON.toJSONString(params);
+        StringEntity stringEntity = new StringEntity(json, DEFAULT_ENCODING);
+        stringEntity.setContentEncoding(DEFAULT_ENCODING);
+        httpPost.setEntity(stringEntity);
+        String result = null;
+        try (CloseableHttpResponse response = httpClient.execute(httpPost);) {
+            HttpEntity entity = response.getEntity();
+            if (null != entity) {
+                result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            log.error("接口请求异常:{}", e);
+        }
+        return result;
+    }
+
+    /**
+     * http请求(POST请求,GBK编码)
+     *
+     * @param url
+     * @param params
+     * @return
+     */
+    public static String httpPostGBK(String url, Map params,Map<String,String> headers) {
+        log.info("POST请求url:{}", url);
+        log.info("POST请求参数:{}",JSON.toJSONString(params));
+        CloseableHttpClient httpClient = getHttpClient(DEFAULT_TIME_OUT);
+        HttpPost httpPost = new HttpPost(url);
+
+        if (null != headers){
+            for (String key:headers.keySet()){
+                httpPost.setHeader(key,headers.get(key).toString());
+            }
+        }
+
+        String json = JSON.toJSONString(params);
+        StringEntity stringEntity = new StringEntity(json, DEFAULT_ENCODING);
+        stringEntity.setContentEncoding(DEFAULT_ENCODING);
+        httpPost.setEntity(stringEntity);
+        String result = null;
+        try (CloseableHttpResponse response = httpClient.execute(httpPost);) {
+            HttpEntity entity = response.getEntity();
+            if (null != entity) {
+//                result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
+                result = EntityUtils.toString(entity, Charset.defaultCharset());
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            log.error("接口请求异常:{}", e);
+        }
+        return result;
+    }
+
+    /**
+     * http请求(POST请求,GBK编码)
+     *
+     * @param url
+     * @param params
+     * @param headers
+     * @param timeOut 超时时间
+     * @return
+     */
+    public static String httpPostGBK(String url, Map params, Map<String, String> headers, int timeOut) {
+        log.info("POST请求url:{}", url);
+        log.info("POST请求参数:{}", JSON.toJSONString(params));
+        CloseableHttpClient httpClient = getHttpClient(timeOut);
+        HttpPost httpPost = new HttpPost(url);
+
+        if (null != headers) {
+            for (String key : headers.keySet()) {
+                httpPost.setHeader(key, headers.get(key).toString());
+            }
+        }
+
+        String json = JSON.toJSONString(params);
+        StringEntity stringEntity = new StringEntity(json, DEFAULT_ENCODING);
+        stringEntity.setContentEncoding(DEFAULT_ENCODING);
+        httpPost.setEntity(stringEntity);
+        String result = null;
+        try (CloseableHttpResponse response = httpClient.execute(httpPost);) {
+            HttpEntity entity = response.getEntity();
+            if (null != entity) {
+//                result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
+                result = EntityUtils.toString(entity, Charset.defaultCharset());
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            log.error("接口请求异常:{}", e);
+        }
+        return result;
+    }
+
+    /**
+     * http请求
+     *
+     * @param url
+     * @return
+     */
+    public static String httpGet(String url) {
+        log.info("请求url:{}", url);
+        CloseableHttpClient httpClient = getHttpClient(DEFAULT_TIME_OUT);
+        HttpGet httpGet = new HttpGet(url);
+        String result = null;
+        try (CloseableHttpResponse response = httpClient.execute(httpGet);) {
+            HttpEntity entity = response.getEntity();
+            if (null != entity) {
+                result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset());
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            log.error("接口请求异常:{}", e);
+        }
+        return result;
+    }
+}
+

+ 4 - 1
mjava-pake/src/main/resources/application-dev.yml

@@ -27,4 +27,7 @@ dingtalk:
 # aliwork
 aliwork:
   appType: APP_UNSAR4O4Y7NBDUYXLIP4
-  systemToken: HP666C71JQMCDBUHBETIS992J3SW3XKUKBCKL53
+  systemToken: HP666C71JQMCDBUHBETIS992J3SW3XKUKBCKL53
+alibusinesstravel:
+  appKey: pqm6bkfs0800
+  appSecret: cHFtNmJrZnMwODAwXS1ceXpINzUsazUkVT1tejohZ1o

+ 8 - 5
mjava-pake/src/main/resources/application-prod.yml

@@ -4,10 +4,10 @@ server:
     context-path: /pake
 spring:
   datasource:
-      url: jdbc:mysql://47.97.181.40:3306/dingtalk?serverTimezone=GMT%2B8
-      username: root
-      password: cp-root@2022++
-      driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.97.181.40:3306/dingtalk?serverTimezone=GMT%2B8
+    username: root
+    password: cp-root@2022++
+    driver-class-name: com.mysql.cj.jdbc.Driver
 enable:
   scheduling: true
 logging:
@@ -27,4 +27,7 @@ dingtalk:
 # aliwork
 aliwork:
   appType: APP_UNSAR4O4Y7NBDUYXLIP4
-  systemToken: HP666C71JQMCDBUHBETIS992J3SW3XKUKBCKL53
+  systemToken: HP666C71JQMCDBUHBETIS992J3SW3XKUKBCKL53
+alibusinesstravel:
+  appKey: pqm6bkfs0800
+  appSecret: cHFtNmJrZnMwODAwXS1ceXpINzUsazUkVT1tejohZ1o

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

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