Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

lfx 1 miesiąc temu
rodzic
commit
ea16e1ef4a
32 zmienionych plików z 2089 dodań i 266 usunięć
  1. 12 1
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/controller/HeiHuOrderController.java
  2. 7 1
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/HeiHuOrderService.java
  3. 578 13
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java
  4. 6 7
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/EqbServiceImpl.java
  5. 74 2
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdCustomerServiceImpl.java
  6. 89 6
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdDeliveryServiceImpl.java
  7. 77 4
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdMaterialServiceImpl.java
  8. 259 55
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdOrderServiceImpl.java
  9. 2 1
      mjava-huagao/src/main/resources/application-dev.yml
  10. 2 1
      mjava-huagao/src/main/resources/application-prod.yml
  11. 2 1
      mjava-huagao/src/main/resources/application-prod2.yml
  12. 11 9
      mjava-huagao/src/test/java/com/malk/huagao/EqbTest.java
  13. 1 1
      mjava-junengtai/src/main/java/com/malk/junengtai/service/Impl/PurchaseServiceImpl.java
  14. 1 1
      mjava-junengtai/src/main/resources/application.yml
  15. 32 8
      mjava-lianan/src/main/java/com/malk/lianan/service/impl/LianAnGyServiceImpl.java
  16. 5 1
      mjava-mc/src/main/java/com/malk/mc/service/impl/McYdServiceImpl.java
  17. 27 0
      mjava-ounuo/src/main/java/com/malk/tuosi/entity/PersonalMonthlySuccessrate.java
  18. 9 0
      mjava-ounuo/src/main/java/com/malk/tuosi/mapper/PersonalMonthlySuccessrateMapper.java
  19. 19 6
      mjava-ounuo/src/main/java/com/malk/tuosi/schedule/ScheduleTask.java
  20. 7 0
      mjava-ounuo/src/main/java/com/malk/tuosi/service/PersonalMonthlySuccessrateService.java
  21. 14 0
      mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/PersonalMonthlySuccessrateServiceImpl.java
  22. 2 0
      mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/TbServiceImpl.java
  23. 614 138
      mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java
  24. 36 5
      mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java
  25. 1 1
      mjava-siku/src/main/resources/application.yml
  26. 4 4
      mjava-siku/src/test/java/com.malk.siku/SkTest.java
  27. 49 0
      mjava-zhongche/pom.xml
  28. 17 0
      mjava-zhongche/src/main/java/com/malk/zhongche/ZhongcheApplication.java
  29. 28 0
      mjava-zhongche/src/main/resources/application-dev.yml
  30. 28 0
      mjava-zhongche/src/main/resources/application-prod.yml
  31. 15 0
      mjava-zhongche/src/main/resources/application.yml
  32. 61 0
      mjava-zhongche/src/main/resources/logback-spring.xml

+ 12 - 1
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/controller/HeiHuOrderController.java

@@ -98,8 +98,19 @@ public class HeiHuOrderController {
     @PostMapping("/test12")
     @Scheduled(cron = "0 */5 * * * ?")
     McR purchaseSchedule(){
-        return McR.success(huOrderService.purchaseSchedule());
+        List<Map<String, Object>> dataList = huOrderService.queryAllPurchase();
+
+        return McR.success(huOrderService.purchaseSchedule(dataList));
     }
 
+//    /*todo:定时抓取修改采购订单*/
+//    @SneakyThrows
+//    @PostMapping("/testUpdate")
+//    @Scheduled(cron = "0 3,8 * * * ?")
+//    McR purchaseUpdateSchedule(){
+//        log.info("开始执行定时抓取修改后的采购订单数据");
+//        System.out.println("开始执行定时抓取修改后的采购订单数据");
+//        return McR.success(huOrderService.purchaseUpdateSchedule());
+//    }
 
 }

+ 7 - 1
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/HeiHuOrderService.java

@@ -7,6 +7,7 @@ import com.malk.server.common.McR;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -42,6 +43,11 @@ public interface HeiHuOrderService {
     String getProductColor(@RequestParam List list) throws JacksonException;
 
     /*采购订单定时同步*/
-    McR purchaseSchedule() throws JacksonException;
+    McR purchaseSchedule(List<Map<String, Object>> dataList) throws JacksonException;
+
+    List<Map<String, Object>> queryAllPurchase();
+
+    McR purchaseUpdateSchedule() throws JacksonException;
+
 
 }

+ 578 - 13
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java

@@ -1,16 +1,14 @@
 package com.malk.fenggefushi.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.fasterxml.jackson.core.JacksonException;
-import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.malk.fenggefushi.entity.Order;
 import com.malk.fenggefushi.service.HeiHuOrderService;
-import com.malk.fenggefushi.test.test;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDSearch;
@@ -22,7 +20,6 @@ import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
-import org.checkerframework.checker.fenum.qual.SwingBoxOrientation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -31,7 +28,6 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -431,8 +427,8 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                 row.put("textField_mhsj6gtq",productDescription);//todo:产品描述
                 JSONArray array1 = detail.getJSONArray("customFieldValues");
                 color = array1.stream()
-                                .map(obj -> (JSONObject) obj)
-                                        .filter(item -> item.getIntValue("fieldId") == 82259)
+                        .map(obj -> (JSONObject) obj)
+                        .filter(item -> item.getIntValue("fieldId") == 82259)
                         .map(item -> item.getString("value"))
                         .findFirst()
                         .orElse(null);
@@ -1001,13 +997,507 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
         return colorValue;
     }
 
+    @SneakyThrows
     @Override
-    public McR purchaseSchedule() throws JacksonException {
+    public McR purchaseSchedule(List<Map<String, Object>> dataList) {
         HashMap header = new HashMap();
         header.put("X-AUTH", HeiHuAccessToken().getData().toString());
         header.put("Content-Type", "application/json");
         String targetValue = "合同确认,提交审批";
-        String targetValue1 = "合同修改,修改审批";
+        String targetValueUpdate = "合同修改,修改审批";
+
+        // 定义一个字符串集合,默认包含两个值:"默认值1"、"默认值2"
+        List<String> targetValues = new ArrayList() {{
+            add("合同确认,提交审批");
+            add("合同修改,修改审批");
+        }};
+        Map<String, List<String>> purchaserOrderCodes = new HashMap<>();
+
+
+        if (ObjectUtil.isNotNull(dataList) && dataList.size() > 0) {
+            for (Map<String, Object> item : dataList) {
+                String purchaserName = (String) item.get("purchaserName");
+                if (purchaserName == null) purchaserName = "未知";
+
+//                boolean hasTargetStatus = false;
+                List<Map<String, Object>> customFieldValues = (List<Map<String, Object>>) item.get("customFieldValues");
+                if (customFieldValues != null) {
+                    for (Map<String, Object> field : customFieldValues) {
+                        if (targetValue.equals(field.get("value") ) || targetValueUpdate.equals(field.get("value"))) {
+                            System.out.println("合同状态类型:"+field.get("value"));
+//                        if (targetValue.equals(field.get("value"))) {
+//                            hasTargetStatus = true;
+                            String orderCode = (String) item.get("orderCode");
+                            if (orderCode != null) {
+                                purchaserOrderCodes.computeIfAbsent(purchaserName + "-" + field.get("value"), k -> new ArrayList<>()).add(orderCode);
+                            }
+                            break;
+                        }
+                    }
+                }
+
+            }
+
+        }
+
+        // 输出所有采购员的待审批订单
+        System.out.println("========== 所有采购员的待审批订单统计 ==========");
+
+        if (purchaserOrderCodes.isEmpty()) {
+            System.out.println("没有找到钉钉审批状态为'" + targetValue + "'的订单");
+        } else {
+            int totalPurchasers = purchaserOrderCodes.size();
+            int totalOrders = purchaserOrderCodes.values().stream().mapToInt(List::size).sum();
+
+            System.out.println("共找到 " + totalOrders + " 个待审批订单");
+            System.out.println("涉及 " + totalPurchasers + " 位采购员");
+            System.out.println();
+
+            // 输出每个采购员的情况
+            for (Map.Entry<String, List<String>> entry : purchaserOrderCodes.entrySet()) {
+                String[] split = entry.getKey().split("-");
+                String purchaserName = split[0];
+                String type = split[1];
+                List<String> orderCodes = entry.getValue();
+                int orderCount = orderCodes.size();
+
+                System.out.println("采购员: " + purchaserName);
+                System.out.println("待审批订单数量: " + orderCount);
+                System.out.println("审批类型: " + type);
+
+                if (orderCount > 1) {
+                    System.out.println("⚠️  注意:该采购员有 " + orderCount + " 个待审批订单");
+                }
+                System.out.println("订单编号: " + String.join(", ", orderCodes));
+            }
+
+            // 按订单数量排序输出
+            System.out.println("========== 按待审批订单数量排序 ==========");
+            purchaserOrderCodes.entrySet().stream()
+                    .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()))
+                    .forEach(entry -> {
+                        String[] split = entry.getKey().split("-");
+                        String purchaserName = split[0];
+                        String type = split[1];
+                        List<String> orderCodes = entry.getValue();
+
+                        System.out.println(purchaserName + " (" + orderCodes.size() + "个): " +
+                                String.join(", ", orderCodes));
+
+                        // ========== 修改点1:声明两个列表分别存储不同毛利率的订单数据 ==========
+                        // 针对同一个采购员,遍历下面的订单编号
+                        System.out.println("开始处理采购员 " + purchaserName + " 的 " + orderCodes.size() + " 个待审批订单");
+
+                        // 高毛利率表单数据 (mlv >= 0.15)
+                        HashMap formdataHigh = new HashMap();
+                        List<Map<String,String>> tabledataHigh = new ArrayList();
+
+                        // 低毛利率表单数据 (mlv < 0.15)
+                        HashMap formdataLow = new HashMap();
+                        List<Map<String,String>> tabledataLow = new ArrayList();
+
+                        // ========== 修改点2:为每个订单创建临时存储列表 ==========
+                        // 用于暂存每个订单的明细数据,等计算出毛利率后再决定添加到哪个列表
+//                        Map<String, List<Map<String, String>>> tempOrderDataMap = new HashMap<>();
+                        // 用于存储每个订单的汇总数据,用于计算毛利率
+//                        Map<String, Map<String, Double>> orderSummaryForMlv = new HashMap<>();
+                        List<String> oldIds = new ArrayList<>();
+
+                        for (String orderCode : orderCodes) {
+                            System.out.println("正在处理订单: " + orderCode);
+                            if (type.equals(targetValueUpdate)){
+                                oldIds.add(orderCode);
+                            }
+                            // ========== 修改点3:为当前订单创建临时数据存储 ==========
+                            List<Map<String, String>> currentOrderRows = new ArrayList<>();
+                            double orderTotalSalesAmount = 0.0;
+                            double orderTotalPurchaseAmount = 0.0;
+                            double orderTotalFlygcb = 0.0;
+
+                            //todo:查询订单的销售订单 | 客户  销售订单号  款式  产品描述  颜色 | 数量  销售单价  销售金额 | 币别 美金汇率 辅料预估成本 销售总金额
+                            String customerName = "",orderNumber ="",styleNumber ="",productDescription = "",color = "";
+                            Double number,unitPrice,salesAmount;
+                            String currency = ""; Double USDrate = 0.00; Double flygcb = 0.00; Double saletotalAmount = 0.00;
+                            Double estimatedPrice = 0.00;//辅料预估单价
+
+                            HashMap body = new HashMap();
+                            body.put("orderCode",orderCode);//订单编号
+                            String jsonString = UtilHttp.doPost("https://liteweb.blacklake.cn/api/dytin/external/purchaseOrder/queryList2", header, null, body);
+                            //todo:查询采购订单 生产工厂(供应商)
+                            String shortName = "";
+                            JSONArray dataArray = JSONObject.parseObject(jsonString).getJSONArray("data");
+                            for (int i=0;i<dataArray.size();i++) {
+                                JSONObject data = dataArray.getJSONObject(i);
+                                shortName = data.getString("shortName");//供应商:shortName
+                            }
+                            JSONArray products = JSONObject.parseObject(jsonString).getJSONArray("data").getJSONObject(0).getJSONArray("purchaseSubOrderVOS");
+                            ObjectMapper objectMapper = new ObjectMapper();
+                            JsonNode rootNode = null;
+                            try {
+                                rootNode = objectMapper.readTree(jsonString);
+                            } catch (JsonProcessingException e) {
+                                throw new RuntimeException(e);
+                            }
+                            JsonNode dataNode = rootNode.get("data");
+                            if(dataNode != null && dataNode.isArray()){
+                                for(JsonNode item : dataNode){
+                                    JsonNode orderNoNode = item.get("orderCode");
+                                    JsonNode saleOrders = item.get("relationSaleOrders");
+                                    if(saleOrders != null && saleOrders.isArray() && saleOrders.size() > 0){
+                                        orderNumber = saleOrders.get(0).asText();//销售订单号
+                                    }
+                                }
+                            }
+
+                            HashMap body_A = new HashMap();
+                            body_A.put("orderNo",orderNumber);
+                            String jsonString2 = UtilHttp.doPost("https://liteweb.blacklake.cn/api/dytin/external/saleOrder/queryList2", header, null, body_A);//todo:查询销售订单,获取客户、订单号、款号、产品描述、颜色、数量、销售单价、销售金额、币别
+                            JSONArray array = JSONObject.parseObject(jsonString2).getJSONArray("data");//主表数据
+
+                            boolean isSample = false;//销售订单若为样品订单则不发起钉钉流程
+                            for(int i=0;i<array.size();i++){
+                                JSONObject data = array.getJSONObject(i);
+                                customerName = data.getString("customerCode");//客户
+                            }
+                            ObjectMapper objectMapper2 = new ObjectMapper();
+                            JsonNode dataNode2 = null;//主表数据
+                            try {
+                                dataNode2 = objectMapper2.readTree(jsonString2).get("data");
+                            } catch (JsonProcessingException e) {
+                                throw new RuntimeException(e);
+                            }
+                            for (JsonNode item : dataNode2){
+                                JsonNode customFieldValues = item.get("customFieldValues");
+                                for (JsonNode field : customFieldValues){
+                                    JsonNode fieldIdNode = field.get("fieldId");
+                                    if(fieldIdNode != null && fieldIdNode.asInt() == 161769){
+                                        JsonNode valueNode = field.get("value");
+                                        if(valueNode != null){
+                                            estimatedPrice = valueNode.asDouble();//辅料预估单价
+                                        }
+                                    }
+                                    else if(fieldIdNode != null && fieldIdNode.asInt() == 47771){
+                                        JsonNode valueNode = field.get("value");
+                                        if("样品订单".equals(valueNode.asText())){
+                                            isSample = true;
+                                        }
+                                    }
+                                }
+                            }
+
+                            if (!isSample){
+                                JSONArray products_A = JSONObject.parseObject(jsonString2).getJSONArray("data").getJSONObject(0).getJSONArray("saleManageOrderDetailRowApiVOList");//销售订单明细数据
+
+                                if(products_A != null) {
+                                    for (int i = 0; i < products_A.size(); i++) {
+                                        JSONObject detail = products_A.getJSONObject(i);
+                                        HashMap row = new HashMap();
+                                        row.put("textField_mm2t71jm",orderCode);//todo:采购订单单号
+                                        row.put("textField_ml6g7k5e", customerName);//todo:客户
+                                        row.put("textField_ml6g7k5f", orderNumber);//todo:订单号
+
+                                        styleNumber = detail.getString("productCode");//款号
+                                        row.put("textField_ml7c3yhq", styleNumber);//todo:款号
+
+                                        productDescription = detail.getString("productName");//产品描述
+                                        row.put("textField_ml7c3yhr", productDescription);//todo:产品描述
+
+                                        JSONArray array1 = detail.getJSONArray("customFieldValues");
+                                        color = array1.stream()
+                                                .map(obj -> (JSONObject) obj)
+                                                .filter(item -> item.getIntValue("fieldId") == 82259)
+                                                .map(item -> item.getString("value"))
+                                                .findFirst()
+                                                .orElse(null);
+                                        ArrayList colorList = new ArrayList();
+                                        colorList.add(color);
+                                        String color_AAA = null;
+                                        try {
+                                            color_AAA = getProductColor(colorList);
+                                        } catch (JacksonException e) {
+                                            throw new RuntimeException(e);
+                                        }
+                                        row.put("textField_ml7c3yhs", color_AAA);//todo:颜色
+
+                                        number = detail.getDoubleValue("qty");//数量
+                                        row.put("numberField_ml7c3yht", number);//todo:数量
+
+                                        unitPrice = detail.getDoubleValue("unitPrice");//销售单价
+                                        row.put("numberField_ml7c3yhu", unitPrice);//todo:销售单价
+
+                                        salesAmount = number * unitPrice;//销售金额
+                                        row.put("numberField_ml7c3yhv", salesAmount);//todo:销售金额
+                                        String customFieldValues = detail.getString("customFieldValues");
+                                        ObjectMapper mapper = new ObjectMapper();
+                                        JsonNode jsonarray = null;
+                                        try {
+                                            jsonarray = mapper.readTree(customFieldValues);
+                                        } catch (JsonProcessingException e) {
+                                            throw new RuntimeException(e);
+                                        }
+                                        for (JsonNode node : jsonarray) {
+                                            if (node.get("fieldId").asInt() == 47919) {
+                                                currency = node.get("value").asText();
+                                            } else if (node.get("fieldId").asInt() == 165251) {
+                                                USDrate = node.get("value").asDouble();
+
+                                            } else if (node.get("fieldId").asInt() == 161783) {
+                                                flygcb = node.get("value").asDouble();
+                                            }
+                                        }
+                                        row.put("textField_ml7c3yhw", currency);//todo:币别
+                                        row.put("numberField_ml86221y", USDrate);//todo:美金汇率
+                                        row.put("numberField_ml86221z", flygcb);//todo:辅料预估成本
+                                        if(currency.equals("USD")){
+                                            saletotalAmount = salesAmount * USDrate;
+                                        }else {
+                                            saletotalAmount = salesAmount;
+                                        }
+                                        row.put("numberField_ml862220",saletotalAmount);
+                                        //下面是采购订单的明细数据
+                                        row.put("textField_ml7c3yhx",shortName);//todo:生产工厂
+                                        for(int j=0;j<products.size();j++){
+                                            if(styleNumber.equals(products.getJSONObject(j).getString("productCode"))){
+                                                //找到对应的采购一行数据
+                                                row.put("numberField_ml7c3yhy",products.getJSONObject(j).getDouble("purchasePrice"));//todo:采购单价
+                                                row.put("numberField_ml7c3yhz",products.getJSONObject(j).getDouble("purchaseNum"));//todo:采购数量
+                                                row.put("numberField_ml7c3yi0",products.getJSONObject(j).getDouble("purchasePrice") * products.getJSONObject(j).getDouble("purchaseNum"));//todo:采购金额
+                                            }
+                                        }
+
+                                        // ========== 修改点4:将当前行转换为Map<String,String>并暂存 ==========
+                                        Map<String, String> rowMap = new HashMap<>();
+                                        for (Object key : row.keySet()) {
+                                            Object value = row.get(key);
+                                            rowMap.put(key.toString(), value != null ? value.toString() : "");
+                                        }
+                                        currentOrderRows.add(rowMap);
+
+                                        // ========== 修改点5:累加当前订单的汇总数据用于计算毛利率 ==========
+                                        orderTotalSalesAmount += saletotalAmount;
+                                        orderTotalPurchaseAmount += (Double)row.get("numberField_ml7c3yi0");
+                                        orderTotalFlygcb += flygcb;
+                                    }
+                                }
+
+                                // ========== 修改点6:计算当前订单的毛利率 ==========
+                                double mlv = 0.0;
+                                if (orderTotalSalesAmount > 0) {
+                                    mlv = (orderTotalSalesAmount - orderTotalPurchaseAmount - orderTotalFlygcb) / orderTotalSalesAmount;
+                                }
+
+                                System.out.println("订单 " + orderCode + " 毛利率: " + String.format("%.2f%%", mlv * 100));
+
+                                // ========== 修改点7:根据毛利率决定添加到哪个列表 ==========
+                                if (mlv >= 0.15) {
+                                    // 高毛利率订单
+                                    tabledataHigh.addAll(currentOrderRows);
+                                    System.out.println("订单 " + orderCode + " 归类到高毛利率审批(>=15%)");
+                                } else {
+                                    // 低毛利率订单
+                                    tabledataLow.addAll(currentOrderRows);
+                                    System.out.println("订单 " + orderCode + " 归类到低毛利率审批(<15%)");
+                                }
+                            } else {
+                                try {
+                                    HashMap body1 = new HashMap();
+                                    body1.put("orderCode",orderCode);//订单编号:orderCode
+                                    body1.put("vendorCode",dataArray.getJSONObject(0).getString("vendorCode"));//供应商编码:gysnumber
+                                    String aa = dataArray.getJSONObject(0).getLong("purchaseTime").toString();
+                                    String purchaseTime = Instant.ofEpochMilli(Long.parseLong(aa))
+                                            .atZone(ZoneId.of("Asia/Shanghai"))
+                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+                                    body1.put("purchaseTime",purchaseTime);//采购日期:purchaseTime
+                                    String bb = dataArray.getJSONObject(0).getLong("planArrivalTime").toString();
+                                    String planArrivalTime = Instant.ofEpochMilli(Long.parseLong(bb))
+                                            .atZone(ZoneId.of("Asia/Shanghai"))
+                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+                                    body1.put("planArrivalTime",planArrivalTime);//计划到货日期:planArrivalTime
+                                    ArrayList<Map<String,String>> customFiled = new ArrayList();
+                                    HashMap field = new HashMap();
+                                    field.put("name","采购订单钉钉审批状态");
+                                    field.put("value","审批完成");//审批状态
+                                    customFiled.add(field);
+                                    body1.put("purchaseOrderCustomFieldsValue",customFiled);
+                                    UtilHttp.doPost("https://liteweb.blacklake.cn/api/dytin/external/purchaseOrder/update", header, null, body1);
+                                    log.info("---------【回传,{},采购订单状态完成】-----------",dataArray.getJSONObject(0).getString("orderCode"));
+                                } catch (Exception e) {
+                                    log.info("样品订单的采购订单自动通过审批失败,采购订单编号为:{}",orderCode);
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+
+                        List<Map<String, Object>> oldList = new ArrayList<>();
+                        if (type.equals(targetValueUpdate)){
+                            oldIds.forEach(h->{
+                                List<Map> oldDataList = ydService.queryFormData_all(YDParam.builder()
+                                        .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                        .formUuid("FORM-278D56A5065641F8AC95BCA0A8CE8447D8QY")
+                                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_mmx9gyct", h)))
+                                        .build());
+                                if (ObjectUtil.isNotNull(oldDataList) && oldDataList.size()>0){
+                                    List<Map> sonList = ydService.queryDetails(YDParam.builder()
+                                            .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                            .formInstanceId(UtilMap.getString(oldDataList.get(0),"textField_mmx9gycu"))
+                                            .formUuid("FORM-3A54B12BE3D241218A75242B935F2987YWV2")
+                                            .tableFieldId("tableField_ml6g7k5d")
+                                            .build());
+                                    if (ObjectUtil.isNotNull(sonList) && sonList.size() > 0){
+                                        sonList.forEach(s->{
+                                            Map<String, Object> map = new HashMap<>();
+                                            TABLEFIELD_ENUM.forEach((k,v)->{
+                                                map.put(v,UtilMap.getString(s,k));
+                                            });
+                                            oldList.add(map);
+                                        });
+                                    }
+                                }
+                            });
+                        }
+
+                        // ========== 修改点8:分别处理高低毛利率的审批 ==========
+
+                        // 处理高毛利率的审批 (mlv >= 0.15)
+                        if (!tabledataHigh.isEmpty()) {
+                            System.out.println("\n========== 开始处理高毛利率审批(>=15%),共 " + tabledataHigh.size() + " 条明细 ==========");
+
+                            //组装数据塞到采购明细表
+                            formdataHigh.put("tableField_ml6g7k5d", tabledataHigh);
+
+                            //组装数据塞到采购审批单号明细
+                            List<Map<String, String>> orderSummaryListHigh = calculateOrderSummary(tabledataHigh);
+                            formdataHigh.put("tableField_ml7ch2pj", orderSummaryListHigh);
+                            formdataHigh.put("tableField_mmx6gata", oldList);
+
+                            //数值统计毛利率
+                            int szHigh = 0;
+                            for (Map map : orderSummaryListHigh) {
+                                Object numberFieldMm2t71jo = map.get("numberField_mm2t71jo");
+                                log.info((String) numberFieldMm2t71jo);
+                                szHigh += Integer.parseInt((String) numberFieldMm2t71jo);
+                            }
+                            formdataHigh.put("numberField_mm2t71jp", szHigh);
+
+                            /*发起流程 - 高毛利率审批*/
+                            String userId = getDDToken(purchaserName);
+                            ydClient.operateData(YDParam.builder()
+                                    .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                    .formUuid("FORM-3A54B12BE3D241218A75242B935F2987YWV2")  // 高毛利率使用原表单
+                                    .userId(userId)
+                                    .formDataJson(JSON.toJSONString(formdataHigh))
+                                    .build(), YDConf.FORM_OPERATION.start).toString();
+
+                            /*修改采购订单为审批中*/
+                            for (Map map : orderSummaryListHigh) {
+                                String textFieldMl7ch2pk = (String) map.get("textField_ml7ch2pk");
+                                callback(textFieldMl7ch2pk);
+                            }
+
+                            System.out.println("高毛利率审批流程发起完成");
+                        }
+
+                        // 处理低毛利率的审批 (mlv < 0.15)
+                        if (!tabledataLow.isEmpty()) {
+                            System.out.println("\n========== 开始处理低毛利率审批(<15%),共 " + tabledataLow.size() + " 条明细 ==========");
+
+                            //组装数据塞到采购明细表
+                            formdataLow.put("tableField_ml6g7k5d", tabledataLow);
+                            formdataLow.put("tableField_mmx6gata", oldList);
+
+                            //组装数据塞到采购审批单号明细
+                            List<Map<String, String>> orderSummaryListLow = calculateOrderSummary(tabledataLow);
+                            formdataLow.put("tableField_ml7ch2pj", orderSummaryListLow);
+
+                            //数值统计毛利率
+                            int szLow = 0;
+                            for (Map map : orderSummaryListLow) {
+                                Object numberFieldMm2t71jo = map.get("numberField_mm2t71jo");
+                                log.info((String) numberFieldMm2t71jo);
+                                szLow += Integer.parseInt((String) numberFieldMm2t71jo);
+                            }
+                            formdataLow.put("numberField_mm2t71jp", szLow);
+
+                            /*发起流程 - 低毛利率审批*/
+                            String userId = getDDToken(purchaserName);
+                            // ========== 修改点9:如果低毛利率需要不同表单,可以在这里修改formUuid ==========
+                            ydClient.operateData(YDParam.builder()
+                                    .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                    .formUuid("FORM-3A54B12BE3D241218A75242B935F2987YWV2")  // 如果需要不同流程,替换这里的UUID
+                                    .userId(userId)
+                                    .formDataJson(JSON.toJSONString(formdataLow))
+                                    .build(), YDConf.FORM_OPERATION.start).toString();
+
+                            /*修改采购订单为审批中*/
+                            for (Map map : orderSummaryListLow) {
+                                String textFieldMl7ch2pk = (String) map.get("textField_ml7ch2pk");
+                                callback(textFieldMl7ch2pk);
+                            }
+
+                            System.out.println("低毛利率审批流程发起完成");
+                        }
+
+                    });
+        }
+
+        return null;
+    }
+
+    @SneakyThrows
+    @Override
+    public List<Map<String, Object>> queryAllPurchase() {
+        HashMap header = new HashMap();
+        header.put("X-AUTH", HeiHuAccessToken().getData().toString());
+        header.put("Content-Type", "application/json");
+        boolean hasMoreData = true;
+        int pageNum = 1;
+        int pageSize = 100;
+        List<Map<String, Object>> dataList = new ArrayList<>();
+        while (hasMoreData) {
+            HashMap body = new HashMap();
+            Map<String, Integer> page = new HashMap<>();
+            page.put("pageNum", pageNum);
+            page.put("pageSize", pageSize);
+            List<Integer> status = Arrays.asList(1);
+            body.put("page", page);
+            body.put("status", status);
+
+            String doPost = UtilHttp.doPost("https://liteweb.blacklake.cn/api/dytin/external/purchaseOrder/queryList2", header, null, body);//查询采购订单
+            log.info("header:{}",header.toString());
+            System.out.println("header:" + header.toString());
+            ObjectMapper mapper = new ObjectMapper();
+            Map<String, Object> response = mapper.readValue(doPost, Map.class);
+
+            if (!"01000000".equals(response.get("code"))) {
+                System.out.println("请求失败: " + response.get("msg"));
+                break;
+            }
+
+//            dataList.addAll(UtilMap.getList(response,"data"));
+            List<Map<String, Object>> mapList = (List<Map<String, Object>>) response.get("data");
+            if (ObjectUtil.isNotNull(mapList) && mapList.size() > 0){
+                dataList.addAll(mapList);
+                hasMoreData = mapList.size() >= pageSize;
+            } else {
+                hasMoreData = false;
+            }
+            pageNum++;
+        }
+
+        try {
+            Thread.sleep(200);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return dataList;
+    }
+
+    @Override
+    public McR purchaseUpdateSchedule() throws JacksonException {
+        HashMap header = new HashMap();
+        header.put("X-AUTH", HeiHuAccessToken().getData().toString());
+        header.put("Content-Type", "application/json");
+        String targetValue = "合同修改,修改审批";
         Map<String, List<String>> purchaserOrderCodes = new HashMap<>();
 
         int pageNum = 1;
@@ -1029,7 +1519,7 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
             Map<String, Object> response = mapper.readValue(doPost, Map.class);
 
             if (!"01000000".equals(response.get("code"))) {
-                System.out.println("请求失败: " + response.get("msg"));
+                log.info("请求失败: {}" , response.get("msg"));
                 break;
             }
 
@@ -1043,7 +1533,7 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                     List<Map<String, Object>> customFieldValues = (List<Map<String, Object>>) item.get("customFieldValues");
                     if (customFieldValues != null) {
                         for (Map<String, Object> field : customFieldValues) {
-                            if (targetValue.equals(field.get("value") ) || targetValue1.equals(field.get("value"))) {
+                            if (targetValue.equals(field.get("value"))) {
                                 hasTargetStatus = true;
                                 break;
                             }
@@ -1129,6 +1619,8 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                         Map<String, List<Map<String, String>>> tempOrderDataMap = new HashMap<>();
                         // 用于存储每个订单的汇总数据,用于计算毛利率
                         Map<String, Map<String, Double>> orderSummaryForMlv = new HashMap<>();
+                        List<String> oldHighIds = new ArrayList<>();
+                        List<String> oldLowIds = new ArrayList<>();
 
                         for (String orderCode : orderCodes) {
                             System.out.println("正在处理订单: " + orderCode);
@@ -1309,10 +1801,12 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                             if (mlv >= 0.15) {
                                 // 高毛利率订单
                                 tabledataHigh.addAll(currentOrderRows);
+                                oldHighIds.add(orderCode);
                                 System.out.println("订单 " + orderCode + " 归类到高毛利率审批(>=15%)");
                             } else {
                                 // 低毛利率订单
                                 tabledataLow.addAll(currentOrderRows);
+                                oldLowIds.add(orderCode);
                                 System.out.println("订单 " + orderCode + " 归类到低毛利率审批(<15%)");
                             }
                         }
@@ -1322,9 +1816,34 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                         // 处理高毛利率的审批 (mlv >= 0.15)
                         if (!tabledataHigh.isEmpty()) {
                             System.out.println("\n========== 开始处理高毛利率审批(>=15%),共 " + tabledataHigh.size() + " 条明细 ==========");
-
+                            List<Map<String, Object>> oldList = new ArrayList<>();
+                            oldHighIds.forEach(h->{
+                                List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                                        .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                        .formUuid("FORM-278D56A5065641F8AC95BCA0A8CE8447D8QY")
+                                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_mmx9gyct", h)))
+                                        .build());
+                                if (ObjectUtil.isNotNull(dataList) && dataList.size()>0){
+                                    List<Map> sonList = ydService.queryDetails(YDParam.builder()
+                                            .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                            .formInstanceId(UtilMap.getString(dataList.get(0),"textField_mmx9gycu"))
+                                            .formUuid("FORM-3A54B12BE3D241218A75242B935F2987YWV2")
+                                            .tableFieldId("tableField_ml6g7k5d")
+                                            .build());
+                                    if (ObjectUtil.isNotNull(sonList) && sonList.size() > 0){
+                                        sonList.forEach(s->{
+                                            Map<String, Object> map = new HashMap<>();
+                                            TABLEFIELD_ENUM.forEach((k,v)->{
+                                                map.put(v,UtilMap.getString(s,k));
+                                            });
+                                            oldList.add(map);
+                                        });
+                                    }
+                                }
+                            });
                             //组装数据塞到采购明细表
                             formdataHigh.put("tableField_ml6g7k5d", tabledataHigh);
+                            formdataHigh.put("tableField_mmx6gata", oldList);
 
                             //组装数据塞到采购审批单号明细
                             List<Map<String, String>> orderSummaryListHigh = calculateOrderSummary(tabledataHigh);
@@ -1360,7 +1879,33 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                         // 处理低毛利率的审批 (mlv < 0.15)
                         if (!tabledataLow.isEmpty()) {
                             System.out.println("\n========== 开始处理低毛利率审批(<15%),共 " + tabledataLow.size() + " 条明细 ==========");
-
+                            List<Map<String, Object>> oldList = new ArrayList<>();
+                            oldLowIds.forEach(h->{
+                                List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
+                                        .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                        .formUuid("FORM-278D56A5065641F8AC95BCA0A8CE8447D8QY")
+                                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_mmx9gyct", h)))
+                                        .build());
+                                if (ObjectUtil.isNotNull(dataList) && dataList.size()>0){
+                                    List<Map> sonList = ydService.queryDetails(YDParam.builder()
+                                            .appType(ydConf.getAppType()).systemToken(ydConf.getSystemToken())
+                                            .formInstanceId(UtilMap.getString(dataList.get(0),"textField_mmx9gycu"))
+                                            .formUuid("FORM-3A54B12BE3D241218A75242B935F2987YWV2")
+                                            .tableFieldId("tableField_ml6g7k5d")
+                                            .build());
+                                    if (ObjectUtil.isNotNull(sonList) && sonList.size() > 0){
+                                        sonList.forEach(s->{
+                                            Map<String, Object> map = new HashMap<>();
+                                            TABLEFIELD_ENUM.forEach((k,v)->{
+                                                map.put(v,UtilMap.getString(s,k));
+                                            });
+                                            oldList.add(map);
+                                        });
+                                    }
+                                }
+                            });
+                            //组装数据塞到采购明细表
+                            formdataLow.put("tableField_mmx6gata", oldList);
                             //组装数据塞到采购明细表
                             formdataLow.put("tableField_ml6g7k5d", tabledataLow);
 
@@ -1402,6 +1947,26 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
         return null;
     }
 
+    private static final Map<String,String> TABLEFIELD_ENUM =new HashMap<>();
+    static {
+        TABLEFIELD_ENUM.put("textField_mm2t71jm","textField_mmx6gast");
+        TABLEFIELD_ENUM.put("textField_ml6g7k5e","textField_mmx6gasu");
+        TABLEFIELD_ENUM.put("textField_ml6g7k5f","textField_mmx6gasv");
+        TABLEFIELD_ENUM.put("textField_ml7c3yhq","textField_mmx6gasw");
+        TABLEFIELD_ENUM.put("textField_ml7c3yhr","textField_mmx6gasx");
+        TABLEFIELD_ENUM.put("textField_ml7c3yhs","textField_mmx6gasy");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yht","numberField_mmx6gasz");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yhu","numberField_mmx6gat0");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yhv","numberField_mmx6gat1");
+        TABLEFIELD_ENUM.put("textField_ml7c3yhw","textField_mmx6gat2");
+        TABLEFIELD_ENUM.put("numberField_ml86221y","numberField_mmx6gat3");
+        TABLEFIELD_ENUM.put("numberField_ml86221z","numberField_mmx6gat4");
+        TABLEFIELD_ENUM.put("numberField_ml862220","numberField_mmx6gat5");
+        TABLEFIELD_ENUM.put("textField_ml7c3yhx","textField_mmx6gat6");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yhy","numberField_mmx6gat7");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yhz","numberField_mmx6gat8");
+        TABLEFIELD_ENUM.put("numberField_ml7c3yi0","numberField_mmx6gat9");
+    }
     /**
      * 根据orderCode对tabledata进行分类求和
      * @param tableData 原始明细数据

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

@@ -503,7 +503,6 @@ public class EqbServiceImpl implements EqbService {
         double xsze = UtilMap.getDouble(formData, "numberField_mjb71qac");//销售总额
         String fkfs = UtilMap.getString(formData, "textField_mjb886fw");//付款方式
         String jfnsrsbh = UtilMap.getString(formData, "textField_mjb71q9w");//甲方纳税人识别号
-        String spyx = UtilMap.getString(formData, "textField_mjb71q9y");//收票邮箱
         String jfdb = UtilMap.getString(formData, "textField_mjb886fx");//甲方代表
         String yfdb = UtilMap.getString(formData, "textField_mj8dt3fj");//乙方代表
 
@@ -534,11 +533,6 @@ public class EqbServiceImpl implements EqbService {
         jxsComponent5.put("componentKey", "jfnsrsbh");
         jxsComponent5.put("componentValue", jfnsrsbh);
 
-        //收票邮箱
-        Map jxsComponent6 = new HashMap();
-        jxsComponent6.put("componentKey", "spyx");
-        jxsComponent6.put("componentValue", spyx);
-
         //甲方代表
         Map jxsComponent7 = new HashMap();
         jxsComponent7.put("componentKey", "jfdb");
@@ -584,18 +578,23 @@ public class EqbServiceImpl implements EqbService {
         jxsComponent11.put("componentKey", "jf3");
         jxsComponent11.put("componentValue", jf);
 
+        //日期
+        Map jxsComponent12 = new HashMap();
+        jxsComponent12.put("componentKey", "rq");
+        jxsComponent12.put("componentValue", System.currentTimeMillis());
+
 
         components.add(jxsComponent);
         components.add(jxsComponent2);
         components.add(jxsComponent3);
         components.add(jxsComponent4);
         components.add(jxsComponent5);
-        components.add(jxsComponent6);
         components.add(jxsComponent7);
         components.add(jxsComponent8);
         components.add(jxsComponent9);
         components.add(jxsComponent10);
         components.add(jxsComponent11);
+        components.add(jxsComponent12);
 
         // 构建请求Body体
         reqBodyObj.put("docTemplateId", qtkh_templateId);

+ 74 - 2
mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdCustomerServiceImpl.java

@@ -15,6 +15,7 @@ import com.malk.huagao.service.IKdYdCustomerService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
 import com.malk.utils.UtilMap;
@@ -91,7 +92,7 @@ public class KdYdCustomerServiceImpl extends ServiceImpl<KdYdCustomerMapper, KdY
             }
 
             // === 获取表单数据 ===
-            DDR_New ddrNew = ydClient.queryData(
+            DDR_New ddrNew = retryQueryData(
                     YDParam.builder().formInstId(formInstId).build(),
                     YDConf.FORM_QUERY.retrieve_id
             );
@@ -234,7 +235,7 @@ public class KdYdCustomerServiceImpl extends ServiceImpl<KdYdCustomerMapper, KdY
                     String code = JSON.parseArray(responseBody)
                             .getJSONObject(0)
                             .getString("code");
-                    ydClient.operateData(
+                    retryOperateData(
                             YDParam.builder()
                                     .formInstanceId(formInstId)
                                     .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_ml08nk3y, textareaField_mkxqgrvq, textField_meqhqqvg", code, msg, khbh)))
@@ -296,6 +297,77 @@ public class KdYdCustomerServiceImpl extends ServiceImpl<KdYdCustomerMapper, KdY
         }
     }
 
+    //自带重试的operateData方法
+    private Object retryOperateData(YDParam param, YDConf.FORM_OPERATION formOperation) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
 
+        Object result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.operateData(param, formOperation);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_OPERATION:{},异常信息:{}", JSONObject.toJSONString(param), formOperation,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
+    }
+
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
 
 }

+ 89 - 6
mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdDeliveryServiceImpl.java

@@ -15,6 +15,7 @@ import com.malk.huagao.service.IKdYdDeliveryService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
 import com.malk.utils.UtilMap;
@@ -81,7 +82,8 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
                         .execute();
 
                 String responseBody = response.body();
-                System.out.println("responseBody===="+responseBody);
+//                System.out.println("responseBody===="+responseBody);
+                log.info("删除返回值responseBody===="+responseBody);
                 // 返回删除操作的格式
                 result.put("table", "KD_YD_DELIVERY");
                 result.put("action", "del");
@@ -132,10 +134,10 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
             List<Map> tableField = (List<Map>) formData.get("tableField_mejnamfd");
 
             if (tableField != null && !tableField.isEmpty()) {
-                int detailId = 1;
+//                int detailId = 1;
                 for (Map item : tableField) {
                     Map<String, Object> table1Map = new HashMap<>();
-//                    int detailId = parseInt(safeGetString(item, "numberField_mjzg06br"), 0);
+                    int detailId = parseInt(safeGetString(item, "numberField_mjzg06br"), 1);
                     String wlbm = safeGetString(item, "textField_mejnamff");
                     String wlmc = safeGetString(item, "textField_mejnamfg");
                     String ggxh = safeGetString(item, "textField_mejnamfh");
@@ -149,6 +151,7 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
                     String sjr = safeGetString(item, "textField_mejnamf6");
                     String sjdh = safeGetString(item, "textField_mejnamf7");
                     String sjdz = safeGetString(item, "textareaField_mf6a0h5e");
+                    String bz1 = safeGetString(item, "textareaField_mf6a0h6q");
                     String zbq = safeGetString(item, "numberField_mf6a0h6v");
                     String kddh = safeGetString(item, "textField_mf6a0h6w");
                     String mdh = safeGetString(item, "textField_mf6a0h6y");
@@ -161,6 +164,7 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
                     table1Map.put("xsdw", xsdw);
                     table1Map.put("jjsl", jjsl);
 //                    table1Map.put("count", count);
+                    table1Map.put("bz1", bz1);
                     table1Map.put("ssxl", ssxl);
                     table1Map.put("yhrq", yhrq);
                     table1Map.put("sfzp", sfzp);
@@ -174,7 +178,7 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
                     table1Map.put("mdh", mdh);
 
                     deliveryList.add(table1Map);
-                    detailId++;
+//                    detailId++;
                 }
             }
 
@@ -265,7 +269,7 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
         String formInstId = UtilMap.getString(map, "formInstId");
 
         // 查询原表单数据
-        DDR_New ddrNew = ydClient.queryData(
+        DDR_New ddrNew = retryQueryData(
                 YDParam.builder().formInstId(formInstId).build(),
                 YDConf.FORM_QUERY.retrieve_id
         );
@@ -275,6 +279,8 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
         String glbdjson = String.valueOf(formData1.get("associationFormField_mejmml36_id"));
         String sqr = String.valueOf(formData1.get("employeeField_krbgloal_id"));
         String xsy = String.valueOf(formData1.get("employeeField_mejnamf3_id"));
+        String xszg = String.valueOf(formData1.get("employeeField_mmsna3tn_id"));
+        String zssj = String.valueOf(formData1.get("employeeField_mmsna3tm_id"));
         String fhtzd = String.valueOf(formData1.get("serialNumberField_mheazm7w"));
 
         // 解析关联字段 JSON
@@ -326,6 +332,8 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
                         key.equals("associationFormField_mk0gzflu_id") ||
                         key.equals("employeeField_krbgloal_id") ||
                         key.equals("employeeField_mejnamf3_id") ||
+                        key.equals("employeeField_mmsna3tn_id") ||
+                        key.equals("employeeField_mmsna3tm_id") ||
                         key.equals("serialNumberField_mheazm7w")) {
                     continue;
                 }
@@ -340,6 +348,8 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
             updateMap.put("associationFormField_mk0gzflu", Arrays.asList(getfhdAss(fhtzd, formInstId)));
             updateMap.put("employeeField_krbgloal", sqr);
             updateMap.put("employeeField_mejnamf3", xsy);
+            updateMap.put("employeeField_mmsna3tn", xszg);
+            updateMap.put("employeeField_mmsna3tm", zssj);
             updateMap.put("textField_mjzk47so", fhtzd);
             // 3. 添加处理后的子表数据
             updateMap.put("tableField_mejnamfd", newSubTable);
@@ -347,7 +357,7 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
             System.out.println("sqrid==" + sqrid);
             // 创建新表单实例
             try {
-                ydClient.operateData(
+                retryOperateData(
                         YDParam.builder()
                                 .formUuid("FORM-FAE2575E112644ED914CAB4FEC9309F32AVR")
                                 .formDataJson(JSON.toJSONString(updateMap))
@@ -437,4 +447,77 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
         return new BigDecimal(number.toString())
                 .setScale(2, RoundingMode.HALF_UP);
     }
+
+    //自带重试的operateData方法
+    private Object retryOperateData(YDParam param, YDConf.FORM_OPERATION formOperation) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        Object result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.operateData(param, formOperation);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_OPERATION:{},异常信息:{}", JSONObject.toJSONString(param), formOperation,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
+    }
+
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
 }

+ 77 - 4
mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdMaterialServiceImpl.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDSearch;
+import com.malk.server.common.McException;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
 import com.malk.utils.UtilMap;
@@ -41,7 +42,7 @@ public class KdYdMaterialServiceImpl extends ServiceImpl<KdYdMaterialMapper, KdY
     public void insertkdYdMaterial(Map map) {
         MDC.put("MDC_KEY_PID", "1003");
         String formInstId = UtilMap.getString(map, "formInstId");
-        DDR_New ddrNew = ydClient.queryData(YDParam.builder()
+        DDR_New ddrNew = retryQueryData(YDParam.builder()
                 .formInstId(formInstId)
                 .build(), YDConf.FORM_QUERY.retrieve_id);
         Map formData = ddrNew.getFormData();
@@ -117,7 +118,7 @@ public class KdYdMaterialServiceImpl extends ServiceImpl<KdYdMaterialMapper, KdY
                         Object fmaterialidObj = item.get("FMATERIALID");
                         String fmaterialidStr = String.valueOf(fmaterialidObj);
 
-                        List<Map> list1 = (List<Map>) ydClient.queryData(YDParam.builder()
+                        List<Map> list1 = (List<Map>) retryQueryData(YDParam.builder()
                                 .formUuid("FORM-E64114E9F2C9426E91F92886EDFFA2C08Q90")
                                 .appType("APP_VQDMMWS6OR1VHL8VMFD3")
                                 .systemToken("XE766X81JHKXK4Z27SYOI86CPCLQ3J1LV7ODMH2")
@@ -144,7 +145,7 @@ public class KdYdMaterialServiceImpl extends ServiceImpl<KdYdMaterialMapper, KdY
                 // 执行批量删除
                 if (!list.isEmpty()) {
                     try {
-                        Object deleteResult = ydClient.operateData(YDParam.builder()
+                        Object deleteResult = retryOperateData(YDParam.builder()
                                 .formUuid("FORM-E64114E9F2C9426E91F92886EDFFA2C08Q90")
                                 .formInstanceIdList(list)
                                 .build(), YDConf.FORM_OPERATION.delete_batch);
@@ -297,7 +298,7 @@ public class KdYdMaterialServiceImpl extends ServiceImpl<KdYdMaterialMapper, KdY
                     updateFormData.put("textField_mg4h6mz5", wlbt);
 
                     // 执行操作并获取结果
-                    Object operationResult = ydClient.operateData(YDParam.builder()
+                    Object operationResult = retryOperateData(YDParam.builder()
                             .formUuid("FORM-E64114E9F2C9426E91F92886EDFFA2C08Q90")
                             .appType("APP_VQDMMWS6OR1VHL8VMFD3")
                             .systemToken("XE766X81JHKXK4Z27SYOI86CPCLQ3J1LV7ODMH2")
@@ -397,4 +398,76 @@ public class KdYdMaterialServiceImpl extends ServiceImpl<KdYdMaterialMapper, KdY
         return new BigDecimal(number.toString())
                 .setScale(2, RoundingMode.HALF_UP);
     }
+    //自带重试的operateData方法
+    private Object retryOperateData(YDParam param, YDConf.FORM_OPERATION formOperation) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        Object result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.operateData(param, formOperation);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_OPERATION:{},异常信息:{}", JSONObject.toJSONString(param), formOperation,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
+    }
+
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
 }

+ 259 - 55
mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdOrderServiceImpl.java

@@ -17,6 +17,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDSearch;
+import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
@@ -124,7 +125,7 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
                 String code = JSON.parseArray(responseBody)
                         .getJSONObject(0)
                         .getString("code");
-                ydClient.operateData(
+                retryOperateData(
                         YDParam.builder()
                                 .formInstanceId(formInstId)
                                 .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_ml08nk3y, textareaField_mkxqgrvq", code, msg)))
@@ -142,7 +143,7 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
             }
 
             // 查询表单数据
-            DDR_New ddrNew = ydClient.queryData(YDParam.builder()
+            DDR_New ddrNew = retryQueryData(YDParam.builder()
                     .formInstId(formInstId)
                     .build(), YDConf.FORM_QUERY.retrieve_id);
             Map formData = ddrNew.getFormData();
@@ -347,7 +348,7 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
                 String code = JSON.parseArray(responseBody)
                         .getJSONObject(0)
                         .getString("code");
-                ydClient.operateData(
+                retryOperateData(
                         YDParam.builder()
                                 .formInstanceId(formInstId)
                                 .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_ml08nk3y, textareaField_mkxqgrvq, textField_mjs6fuwo", code, msg, jdbh)))
@@ -379,34 +380,51 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
             String formInstId = UtilMap.getString(map, "formInstId");
             String khbm = UtilMap.getString(map, "khbm");
 
+            // 参数校验
+            if (StringUtils.isBlank(formInstId)) {
+                throw new RuntimeException("订单ID不能为空");
+            }
+            if (StringUtils.isBlank(khbm)) {
+                throw new RuntimeException("客户编号不能为空");
+            }
+
             // 1. 查询订单详情
-            DDR_New ddrNew = ydClient.queryData(YDParam.builder()
+            DDR_New ddrNew = retryQueryData(YDParam.builder()
                     .formInstId(formInstId)
                     .build(), YDConf.FORM_QUERY.retrieve_id);
 
             if (ddrNew == null || ddrNew.getFormData() == null) {
-                throw new RuntimeException("未找到订单信息");
+                throw new RuntimeException("未找到订单信息,订单ID:" + formInstId);
             }
 
             Map formData1 = ddrNew.getFormData();
             String ddje = UtilMap.getString(formData1, "numberField_mfxv2vgj");
 
-            // 参数校验
+            // 订单金额校验
             if (ddje == null || ddje.trim().isEmpty()) {
-                throw new RuntimeException("订单金额不能为空");
+                throw new RuntimeException("订单金额不能为空,订单ID:" + formInstId);
             }
 
-            // 2. 计算订单金额(保留两位小数)
+            // 2. 计算订单金额
             Double orderAmount = null;
             try {
                 orderAmount = Double.parseDouble(ddje);
                 orderAmount = Math.round(orderAmount * 100.0) / 100.0;
+
+                // 订单金额合理性校验
+                if (orderAmount < 0) {
+                    throw new RuntimeException("订单金额不能为负数: " + orderAmount);
+                }
             } catch (NumberFormatException e) {
-                throw new RuntimeException("订单金额格式错误: " + ddje);
+                throw new RuntimeException("订单金额格式错误: " + ddje, e);
             }
 
+            System.out.println("订单信息:订单ID=" + formInstId +
+                    ", 订单金额=" + orderAmount +
+                    ", 客户编号=" + khbm);
+
             // 3. 查询客户历史信息
-            List<Map> list = (List<Map>) ydClient.queryData(YDParam.builder()
+            Object result = retryQueryData(YDParam.builder()
                     .formUuid("FORM-F79B680547674A6BBD11C0D511E3C14B28FY")
                     .searchFieldJson(JSONObject.toJSONString(Arrays.asList(
                             new YDSearch("textField_mjm9k35n",
@@ -417,120 +435,171 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
                     )))
                     .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();
 
+            List<Map> list = (List<Map>) result;
+
             if (list == null || list.isEmpty()) {
                 throw new RuntimeException("未找到客户信息,客户编号:" + khbm);
             }
 
-            // 4. 获取客户现有信息
+            // 4. 获取客户现有信息并进行数据完整性校验
             Map customerData = (Map) list.get(0).get("formData");
             Double historicalAmount = UtilMap.getDouble(customerData, "numberField_mjm9k35k");
             Long dddateTimestampStr = UtilMap.getLong(customerData, "dateField_mjqkkcsg");
             Long sfdateTimestampStr = UtilMap.getLong(customerData, "dateField_mjm9k35l");
+            String originalSelectFieldValue = UtilMap.getString(customerData, "selectField_l3nrjuq0");
+            String originalKhsx = UtilMap.getString(customerData, "selectField_mjsco9d4");
 
-            // 参数校验
+            // 关键字段完整性校验
             if (dddateTimestampStr == null) {
-                throw new RuntimeException("最后成交日期不能为空");
+                throw new RuntimeException("最后成交日期不能为空,客户编号:" + khbm);
             }
 
-            // 处理历史金额
             if (historicalAmount == null) {
-                historicalAmount = 0.0;
-            } else {
-                historicalAmount = Math.round(historicalAmount * 100.0) / 100.0;
+                // 历史金额为null时,记录错误日志并抛出异常,避免错误清零
+                System.err.println("严重错误:未能获取到客户历史金额,客户编号:" + khbm +
+                        ",返回数据:" + JSONObject.toJSONString(customerData));
+                throw new RuntimeException("无法获取客户历史金额,客户编号:" + khbm + ",请检查数据完整性");
             }
 
-            // 5. 计算总金额
+            // 记录更新前的数据快照,便于问题追踪
+            System.out.println("更新前数据快照:客户编号=" + khbm +
+                    ", 历史金额=" + historicalAmount +
+                    ", 最后成交日期=" + timestampToDateString(dddateTimestampStr) +
+                    ", 公海池日期=" + (sfdateTimestampStr != null ? timestampToDateString(sfdateTimestampStr) : "空") +
+                    ", 销售属性=" + originalKhsx +
+                    ", 选择字段=" + originalSelectFieldValue);
+
+            // 5. 金额计算和校验
+            historicalAmount = Math.round(historicalAmount * 100.0) / 100.0;
             Double totalAmount = orderAmount + historicalAmount;
             totalAmount = Math.round(totalAmount * 100.0) / 100.0;
 
+            // 金额变化监控:检测异常的大幅减少
+            if (totalAmount < historicalAmount && totalAmount < historicalAmount * 0.5) {
+                String errorMsg = String.format(
+                        "警告:金额异常减少!客户编号=%s, 订单金额=%.2f, 原历史金额=%.2f, 新总金额=%.2f, 减少比例=%.2f%%",
+                        khbm, orderAmount, historicalAmount, totalAmount,
+                        (historicalAmount - totalAmount) / historicalAmount * 100
+                );
+                System.err.println(errorMsg);
+                // 根据业务需求决定是否抛出异常
+                // throw new RuntimeException(errorMsg);
+            }
+
+            // 订单金额为0时的特殊处理:保持原金额不变
+            if (orderAmount == 0 && historicalAmount > 0) {
+                System.out.println("订单金额为0,保持原累计金额不变:" + historicalAmount);
+                totalAmount = historicalAmount;
+            }
+
             System.out.println("金额计算:订单金额=" + orderAmount +
                     ", 历史金额=" + historicalAmount +
                     ", 总金额=" + totalAmount);
 
-            // 6. 时间戳转换
+            // 6. 时间计算
             long currentTimestamp = System.currentTimeMillis();
-            // 计算时间差(天数)
             long currentToDdDays = (currentTimestamp - dddateTimestampStr) / (1000 * 60 * 60 * 24);
-            long sfToDdDays = (sfdateTimestampStr > 0) ? (sfdateTimestampStr - dddateTimestampStr) / (1000 * 60 * 60 * 24) : 0;
+            long sfToDdDays = (sfdateTimestampStr != null && sfdateTimestampStr > 0) ?
+                    (sfdateTimestampStr - dddateTimestampStr) / (1000 * 60 * 60 * 24) : 0;
 
-            System.out.println("时间计算:当前时间-" + timestampToDateString(String.valueOf(currentTimestamp)) +
-                    ", 成交日期-" + timestampToDateString(dddateTimestampStr) +
+            System.out.println("时间计算:当前时间=" + timestampToDateString(String.valueOf(currentTimestamp)) +
+                    ", 成交日期=" + timestampToDateString(String.valueOf(dddateTimestampStr)) +
                     ", 当前-成交相差=" + currentToDdDays + "天" +
                     ", 公海-成交相差=" + sfToDdDays + "天");
 
+            // 7. 业务规则计算
             String ghcDateTimestamp = null;
-            String selectFieldValue = UtilMap.getString(customerData, "selectField_l3nrjuq0");
-            String khsx = UtilMap.getString(customerData, "selectField_mjsco9d4");
+            String selectFieldValue = originalSelectFieldValue;
+            String khsx = originalKhsx;
 
-// 1. 设置客户属性(单独判断)
+            // 设置客户属性
             if (totalAmount >= 75000 && sfToDdDays <= 180) {
                 khsx = "自行开发";
             }
 
-// 2. 第一个条件:当前时间-成交日期<90天 且 总金额>0 且 公海日期-成交日期≈180天
+            // 业务规则判断
             if (currentToDdDays < 90 && totalAmount > 0 && Math.abs(sfToDdDays - 180) <= 1) {
-                // 在成交日期上加90天
+                // 条件1:在成交日期上加90天
                 ghcDateTimestamp = String.valueOf(calculateTimestamp(sfdateTimestampStr, 90));
                 selectFieldValue = "半年金额不足";
                 System.out.println("条件1触发:公海池时间设为成交日期+90天=" +
                         timestampToDateString(ghcDateTimestamp));
-            }
-// 3. 第二个条件:总金额≥7.5万 且 公海日期-成交日期≤180天
-            else if (totalAmount >= 75000 && sfToDdDays <= 180) {
-                // 在成交日期上加180天
+            } else if (totalAmount >= 75000 && sfToDdDays <= 180) {
+                // 条件2:在成交日期上加180天
                 ghcDateTimestamp = String.valueOf(calculateTimestamp(sfdateTimestampStr, 180));
                 selectFieldValue = "半年金额不足";
                 System.out.println("条件2触发:公海池时间设为成交日期+180天=" +
                         timestampToDateString(ghcDateTimestamp));
-            }
-// 4. 第三个条件:金额<15万 且 公海日期-成交日期>180天
-            else if (totalAmount < 150000 && sfToDdDays > 180) {
+            } else if (totalAmount < 150000 && sfToDdDays > 180) {
+                // 条件3:设置一年金额不足,但不设置公海池日期
                 selectFieldValue = "一年金额不足";
                 System.out.println("条件3触发:金额<15万且公海日期>180天,设置一年金额不足");
-            }
-// 5. 其他情况
-            else {
+            } else if (totalAmount > 150000) {
+                // 【新增】总金额大于15万:释放公海池日期设为成交日期的下一年第一天
+                ghcDateTimestamp = getNextYearFirstDay(dddateTimestampStr);
+                selectFieldValue = "金额充足";
+                System.out.println("条件4触发:总金额>15万,公海池时间设为成交日期下一年第一天=" +
+                        timestampToDateString(ghcDateTimestamp));
+            } else {
+                // 其他情况
                 if (totalAmount > 0) {
-                    // 基础情况:金额大于0
                     ghcDateTimestamp = String.valueOf(calculateTimestamp(sfdateTimestampStr, 90));
                     selectFieldValue = "半年金额不足";
                     System.out.println("基础情况:金额大于0,公海池时间+90天=" +
                             timestampToDateString(ghcDateTimestamp));
                 } else if (totalAmount < 75000) {
-                    // 金额 < 7.5万
                     selectFieldValue = "半年金额不足";
                     System.out.println("金额<7.5万,但未设置公海池时间");
                 } else if (totalAmount < 150000) {
-                    // 7.5万 ≤ 金额 < 15万
                     selectFieldValue = "一年金额不足";
                     System.out.println("金额7.5-15万,但未设置公海池时间");
                 }
             }
 
-
-            // 8. 构建更新数据
+            // 8. 构建更新数据(只更新需要变更的字段)
             Map<String, Object> formData = new HashMap<>();
-            formData.put("dateField_mjm9k35j", dddateTimestampStr); // 最后成交日期(保持原时间戳)
 
-            // 只有selectField有值时才设置
-            if (!selectFieldValue.isEmpty()) {
-                formData.put("selectField_l3nrjuq0", selectFieldValue);
+            // 必须更新的字段
+            formData.put("dateField_mjm9k35j", dddateTimestampStr);  // 最后成交日期
+            formData.put("numberField_mjm9k35k", totalAmount);       // 累计金额
+            formData.put("selectField_mjsco9d4", khsx);              // 销售属性
+
+            // 条件更新:只在有值时才更新 selectField
+            if (selectFieldValue != null && !selectFieldValue.isEmpty()) {
+                if (!selectFieldValue.equals(originalSelectFieldValue)) {
+                    formData.put("selectField_l3nrjuq0", selectFieldValue);
+                    System.out.println("更新选择字段:" + originalSelectFieldValue + " -> " + selectFieldValue);
+                }
             }
 
+            // 条件更新:只在明确需要变更公海池日期时才更新
             if (ghcDateTimestamp != null) {
-                formData.put("dateField_mjm9k35l", ghcDateTimestamp); // 释放公海日期
+                // 只有当新值与旧值不同时才更新
+                String newDateStr = timestampToDateString(ghcDateTimestamp);
+                String oldDateStr = sfdateTimestampStr != null ? timestampToDateString(String.valueOf(sfdateTimestampStr)) : "空";
+                if (!newDateStr.equals(oldDateStr)) {
+                    formData.put("dateField_mjm9k35l", ghcDateTimestamp);
+                    System.out.println("更新公海池日期:" + oldDateStr + " -> " + newDateStr);
+                } else {
+                    System.out.println("公海池日期未变化,跳过更新:" + newDateStr);
+                }
             } else {
-                formData.put("dateField_mjm9k35l", ""); // 明确设置为空
+                // 不设置该字段,upsert操作会保持原值不变
+                System.out.println("公海池日期无需变更,保持原值:" +
+                        (sfdateTimestampStr != null ? timestampToDateString(String.valueOf(sfdateTimestampStr)) : "空"));
             }
 
-            // 更新累计金额(保留两位小数)
-            formData.put("numberField_mjm9k35k", totalAmount);
-            formData.put("selectField_mjsco9d4", khsx);
+            // 9. 数据变更前最终校验
+            if (totalAmount == 0 && historicalAmount > 0) {
+                System.err.println("警告:即将把客户金额从 " + historicalAmount + " 更新为 0,请确认业务逻辑!");
+                // 可选:根据业务需求决定是否继续执行
+                // throw new RuntimeException("金额异常清零,操作已阻止");
+            }
 
-            System.out.println("更新客户数据:" + formData);
+            System.out.println("最终更新数据:" + JSONObject.toJSONString(formData));
 
-            // 9. 执行更新操作
-            ydClient.operateData(YDParam.builder()
+            // 10. 执行更新操作(retryOperateData已内置重试功能)
+            retryOperateData(YDParam.builder()
                     .formUuid("FORM-F79B680547674A6BBD11C0D511E3C14B28FY")
                     .appType("APP_VQDMMWS6OR1VHL8VMFD3")
                     .systemToken("XE766X81JHKXK4Z27SYOI86CPCLQ3J1LV7ODMH2")
@@ -556,6 +625,68 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
         }
     }
 
+    /**
+     * 获取指定时间戳的下一年第一天零点的时间戳
+     * @param timestamp 时间戳(毫秒)
+     * @return 下一年第一天零点的时间戳
+     */
+    private String getNextYearFirstDay(Long timestamp) {
+        if (timestamp == null || timestamp <= 0) {
+            // 如果时间戳无效,返回当前时间下一年第一天
+            timestamp = System.currentTimeMillis();
+        }
+
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTimeInMillis(timestamp);
+
+        // 设置为下一年第一天
+        calendar.add(Calendar.YEAR, 1);
+        calendar.set(Calendar.MONTH, Calendar.JANUARY);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        return String.valueOf(calendar.getTimeInMillis());
+    }
+
+    /**
+     * 计算指定日期加上天数后的时间戳
+     */
+    private long calculateTimestamp(Long baseTimestamp, int daysToAdd) {
+        if (baseTimestamp == null || baseTimestamp <= 0) {
+            baseTimestamp = System.currentTimeMillis();
+        }
+        return baseTimestamp + (daysToAdd * 24L * 60 * 60 * 1000);
+    }
+
+    /**
+     * 时间戳转日期字符串(用于日志)
+     */
+    private String timestampToDateString(Object timestamp) {
+        if (timestamp == null) {
+            return "空";
+        }
+        try {
+            long ts;
+            if (timestamp instanceof String) {
+                ts = Long.parseLong((String) timestamp);
+            } else if (timestamp instanceof Long) {
+                ts = (Long) timestamp;
+            } else {
+                return timestamp.toString();
+            }
+            if (ts <= 0) {
+                return "无效时间戳";
+            }
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            return sdf.format(new Date(ts));
+        } catch (Exception e) {
+            return timestamp.toString();
+        }
+    }
+
     /**
      * 计算时间戳:在基础时间戳上添加天数
      *
@@ -651,4 +782,77 @@ public class KdYdOrderServiceImpl extends ServiceImpl<KdYdOrderMapper, KdYdOrder
         return new BigDecimal(number.toString())
                 .setScale(2, RoundingMode.HALF_UP);
     }
+
+    //自带重试的operateData方法
+    private Object retryOperateData(YDParam param, YDConf.FORM_OPERATION formOperation) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        Object result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.operateData(param, formOperation);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_OPERATION:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formOperation,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_OPERATION:{},异常信息:{}", JSONObject.toJSONString(param), formOperation,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_OPERATION:{}"+formOperation);
+    }
+
+
+    //自带重试的queryData方法
+    private DDR_New retryQueryData(YDParam param, YDConf.FORM_QUERY formQuery) {
+        int maxAttempts = 3; // 尝试的最大次数
+        int attempt = 0;
+
+        DDR_New result = null;
+
+        while (attempt < maxAttempts) {
+            try {
+                result = ydClient.queryData(param, formQuery);
+
+                return result;
+            } catch (McException e) {
+                log.info("错误信息:{}",e.getMessage());
+                if (e.getMessage().equals("The request has failed due to a temporary failure of the server.")) {
+                    attempt++;
+                    // 线程睡眠3秒
+                    try {
+                        Thread.sleep(5000);
+                        log.info("尝试第{}次,param:{},FORM_QUERY:{},异常信息:{}", attempt, JSONObject.toJSONString(param), formQuery,e.getMessage());
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt(); // 重新设置中断状态
+                        System.err.println("Sleep interrupted: " + ie.getMessage());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("操作失败,param:{},FORM_QUERY:{},异常信息:{}", JSONObject.toJSONString(param), formQuery,e.getMessage());
+
+                throw new RuntimeException(e);
+            }
+
+        }
+
+        throw new RuntimeException("超出最大重试次数,param:"+JSONObject.toJSONString(param)+",FORM_QUERY:{}"+formQuery);
+    }
 }

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

@@ -68,7 +68,8 @@ kingdee:
 
 eqb:
   downloadFilePath: C:\\Users\\EDY\\Desktop\\项目\\华高\\电子签\\files\\
-  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+#  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+  signatoryPsnId: 95945af8f0864d15bf186e7808693176 #签署人 俞静妙
 
 #金蝶方开发服务
 kd:

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

@@ -68,7 +68,8 @@ kingdee:
 
 eqb:
   downloadFilePath: /home/server/huagao/files/
-  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+#  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+  signatoryPsnId: 95945af8f0864d15bf186e7808693176 #签署人 俞静妙
 
 #金蝶方开发服务
 kd:

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

@@ -69,7 +69,8 @@ kingdee:
 
 eqb:
   downloadFilePath: /home/server/huagao/files/
-  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+#  signatoryPsnId: c3fb35cb7e574baf97ed9f8917c6327b #签署人 陈伟东
+  signatoryPsnId: 95945af8f0864d15bf186e7808693176 #签署人 俞静妙
 
 #金蝶方开发服务
 kd:

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

@@ -20,7 +20,7 @@ public class EqbTest {
     public static void main(String[] args) {
 
 
-        String responseBody = "[{\"code\":200,\"msg\":\"销售订单编码:DD202601280002单据同步成功\",\"data\":{\"djbh\":\"DD202601280002\"}}]";
+        /*String responseBody = "[{\"code\":200,\"msg\":\"销售订单编码:DD202601280002单据同步成功\",\"data\":{\"djbh\":\"DD202601280002\"}}]";
         System.out.println("响应内容: " + responseBody);
 
         try {
@@ -34,7 +34,9 @@ public class EqbTest {
 
         } catch (Exception e) {
             System.out.println("解析JSON失败: " + e.getMessage());
-        }
+        }*/
+
+
         // 应用ID
         /*String appId = "7439093376";
         // 应用密钥(AppSecret)
@@ -43,12 +45,12 @@ public class EqbTest {
         String host = "https://smlopenapi.esign.cn";*/
 
 
-//        // 应用ID
-//        String appId = "5112033166";
-//        // 应用密钥(AppSecret)
-//        String appKey = "c0641a1f648a68a7014be5a490f0159a";
-//        // e签宝接口调用域名(正式环境)
-//        String host = "https://openapi.esign.cn";
+        // 应用ID
+        String appId = "5112033166";
+        // 应用密钥(AppSecret)
+        String appKey = "c0641a1f648a68a7014be5a490f0159a";
+        // e签宝接口调用域名(正式环境)
+        String host = "https://openapi.esign.cn";
 
 
         //步骤1:上传本地文件并转成HTML格式
@@ -69,7 +71,7 @@ public class EqbTest {
         //正式环境模板id 采购订单模板:a0827f8946994ebfbed7f44e6b8a6ed8
 
         //步骤4:制作含动态表格控件的HTML模板 访问【获取制作合同模板页面】接口返回的创建文件模板页面链接(docTemplateCreateUrl参数值),并在页面中拖动【动态表格】控件来制作模板,若链接失效,调用【获取编辑合同模板页面】接口
-//        getDocTemplateEditUrl(appId,appKey,host,"8b7fef2257bc4093ada330dbf7c874c5");
+        getDocTemplateEditUrl(appId,appKey,host,"8b7fef2257bc4093ada330dbf7c874c5");
 
 
         //步骤5:获取 HTML 模板中控件ID和控件Key

+ 1 - 1
mjava-junengtai/src/main/java/com/malk/junengtai/service/Impl/PurchaseServiceImpl.java

@@ -151,7 +151,7 @@ public class PurchaseServiceImpl implements PurchaseService {
                 Map<String, String> partData = new HashMap<>();
                 partData.put("supplierCode", partNode.get("supplierCode").asText());
                 partData.put("name", partNode.get("name").asText());
-
+                partData.put("createDate",partNode.get("createDate").isNull() ? "" : partNode.get("createDate").asText());
                 List.add(partData);
                 partsMap.put(partNode.get("supplierCode").asText(), partData);
             }

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

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

+ 32 - 8
mjava-lianan/src/main/java/com/malk/lianan/service/impl/LianAnGyServiceImpl.java

@@ -126,8 +126,12 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
 
         Map<String,Object> data = UtilMap.map("ParamSet", Arrays.asList(item));
 
-        Map result = gyPost("T0022", data);
+        String requestNo = gyPost("T0022", data);
 
+        ydClient.operateData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_mmolqml1",requestNo)))
+                .build(), YDConf.FORM_OPERATION.update);
 
         return McR.success();
     }
@@ -202,7 +206,14 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
         Map<String,Object> data = UtilMap.map("ParamSet", Arrays.asList(item));
 
         //工银-单笔付款
-        Map result = gyPost("T0002", data);
+        String requestNo = gyPost("T0002", data);
+
+        //回写请求号
+        ydClient.operateData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_mmolqml1",requestNo)))
+                .build(), YDConf.FORM_OPERATION.update);
+
 
         return McR.success();
     }
@@ -379,7 +390,13 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
 
         Map<String,Object> data = UtilMap.map("ParamSet", Arrays.asList(item));
 
-        Map result = gyPost("T0003", data);
+        String requestNo = gyPost("T0003", data);
+
+        //回写请求号
+        ydClient.operateData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_mmolqml1",requestNo)))
+                .build(), YDConf.FORM_OPERATION.update);
 
 
         return McR.success();
@@ -457,13 +474,19 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
 
         Map<String,Object> data = UtilMap.map("ParamSet", Arrays.asList(item));
 
-        Map result = gyPost("T0022", data);
+        String requestNo = gyPost("T0022", data);
+
+        //回写请求号
+        ydClient.operateData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_mmolqml1",requestNo)))
+                .build(), YDConf.FORM_OPERATION.update);
 
 
         return McR.success();
     }
 
-    private Map gyPost(String MesgNo,Map<String,Object> data){
+    private String gyPost(String MesgNo,Map<String,Object> data){
         log.info("data:{}",data);
 
         Map<String,Object> head = new HashMap<>();
@@ -472,7 +495,8 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
         head.put("Timestamp", UtilDateTime.getLocalDateTimeTimeStamp());
         head.put("SystemNo",GYPAY_API_SYS_ID);
         head.put("SystemName",GYPAY_API_SYS_NAME);
-        head.put("RequestNo", IdUtil.nanoId(6));
+        String requestNo = IdUtil.nanoId(6);
+        head.put("RequestNo", requestNo);
 
         Map<String,Object> body = new HashMap<>();
         String encrypt = AesUtil.encrypt(JSON.toJSONString(data),GYPAY_API_AES_KEY);
@@ -497,9 +521,9 @@ public class LianAnGyServiceImpl implements LianAnGyPayService {
         String resultData=AesUtil.decrypt(resultBody.getString("Data"),GYPAY_API_AES_KEY);
         System.out.println(resultData);
 
-        Map resultMap = (Map) JSONObject.parse(resultData);
+//        Map resultMap = (Map) JSONObject.parse(resultData);
 
-        return resultMap;
+        return requestNo;
     }
 
     private String getPayStatusName(String payStatus){

+ 5 - 1
mjava-mc/src/main/java/com/malk/mc/service/impl/McYdServiceImpl.java

@@ -272,8 +272,8 @@ public class McYdServiceImpl implements McYdService {
 
     @Override
     public McR multiLocationOutbound(Map map) {
-
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(出库单)
+        log.info("出库单实例id:" + formInstId);
         Map d = ydClient.queryData(YDParam.builder().formInstId(formInstId)
                 .formUuid("FORM-3208DFE5463549A9A57FB94358A75E80PV5F")
                 .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
@@ -347,6 +347,7 @@ public class McYdServiceImpl implements McYdService {
     @Override
     public McR WarehouseStorage(Map map) {
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(入库单)
+        log.info("入库单实例id:"+formInstId);
         Map d = ydClient.queryData(YDParam.builder().formInstId(formInstId)
                 .formUuid("FORM-6DED8EB4CF0446DB8841C7798E106F2886OH")
                 .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
@@ -422,6 +423,7 @@ public class McYdServiceImpl implements McYdService {
     @Override
     public McR ProductReturn(Map map) {
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(退货单)
+        log.info("退货单实例id:"+formInstId);
         Map data = ydClient.queryData(YDParam.builder().formInstId(formInstId)
                 .formUuid("FORM-E40A23253F2F43FEAF0E40F274A67B34OQC9")
                 .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
@@ -500,6 +502,7 @@ public class McYdServiceImpl implements McYdService {
     @Override
     public McR allocateTransfer(Map map) {
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(调拨流程)
+        log.info("调拨流程实例id:"+formInstId);
         Map data = ydClient.queryData(YDParam.builder().formInstId(formInstId)
                 .formUuid("FORM-C6360F0CA28543E8BA99A1DDCF90964FSJEM")
                 .appType("APP_GNQ1RGK68X4JNZUEU8RQ")
@@ -642,6 +645,7 @@ public class McYdServiceImpl implements McYdService {
     @Override
     public McR goodsInandOut(Map map) {
         String formInstId = UtilMap.getString(map,"formInstId");//实例id(进货退货流程)
+        log.info("进货退货流程实例id:"+formInstId);
         Map data = ydClient.queryData(YDParam.builder().formInstId(formInstId)
                 .formUuid("FORM-0D92610ED4AA4B81988CA190EE9A119EX37F")
                 .appType("APP_GNQ1RGK68X4JNZUEU8RQ")

+ 27 - 0
mjava-ounuo/src/main/java/com/malk/tuosi/entity/PersonalMonthlySuccessrate.java

@@ -0,0 +1,27 @@
+package com.malk.tuosi.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 用户实体类
+ * 注意:实体类使用驼峰命名,对应数据库的下划线命名
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PersonalMonthlySuccessrate {
+    /*任务id*/
+    private String taskId;
+    /*任务名称*/
+    private String taskName;
+    /*任务类型*/
+    private String taskType;
+    /*设计人员*/
+    private String designPerson;
+    /*客户*/
+    private String customer;
+    /*时间*/
+    private String time;
+}

+ 9 - 0
mjava-ounuo/src/main/java/com/malk/tuosi/mapper/PersonalMonthlySuccessrateMapper.java

@@ -0,0 +1,9 @@
+package com.malk.tuosi.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.malk.tuosi.entity.PersonalMonthlySuccessrate;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface PersonalMonthlySuccessrateMapper extends BaseMapper<PersonalMonthlySuccessrate> {
+}

+ 19 - 6
mjava-ounuo/src/main/java/com/malk/tuosi/schedule/ScheduleTask.java

@@ -54,7 +54,7 @@ public class ScheduleTask {
     @Autowired
     private ChangeDocumentSourceMapper changeDocumentSourceMapper;
 
-    /*每15分钟定时同步任务状态*/
+    /*每天凌晨定时同步任务状态*/
     @SneakyThrows
     @GetMapping("/renwulist")
     @Scheduled(cron = "0 0 0 * * ?")
@@ -474,12 +474,20 @@ public class ScheduleTask {
             for (int j = 0; j < allIds.size(); j++) {
                 String taskId1 = allIds.get(j);
                 HashMap params3 = new HashMap();
-
+                String status = "";//状态
                 String doneGet = UtilHttp.doGet("https://open.teambition.com/api/v3/task/" + taskId1 + "/node/list", header, new HashMap());
                 JSONObject response = JSON.parseObject(doneGet);
                 JSONArray resultArray = response.getJSONArray("result");
-//                String targetId = "6875f58cf512415e5944c652,6879e63c9cf1bbad8460b777";//【设计单的工作流节点:设计接单(1) 设计接单(2)】
                 String targetName = "设计接";
+                //这里只是遍历每一条任务是否完成status状态
+                for(int n = 0;n < resultArray.size();n++){
+                    JSONObject node = resultArray.getJSONObject(n);
+                    String nodeName = node.getString("name");
+                    if("已完成".equals(nodeName)){
+                       status = node.getString("status");
+                       break;
+                    }
+                }
                 for (int k = 0; k < resultArray.size(); k++) {
                     JSONObject node = resultArray.getJSONObject(k);
                     String currentNodeId = node.getString("name");
@@ -494,9 +502,7 @@ public class ScheduleTask {
                             String time_start = "";//开始时间
                             String time_end = "";//结束时间
                             String task_type = "";//任务类型
-                            String status = "";//状态
                             String department = "";//所属部门
-                            status = node.getString("status");
                             time_start = node.getString("startDate");
                             time_end = node.getString("dueDate");
                             SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
@@ -585,7 +591,7 @@ public class ScheduleTask {
                                                     e.printStackTrace();
                                                 }
                                                 UpdateWrapper<EmployeeWeeklyTasks> updateWrapper = new UpdateWrapper<>();
-                                                updateWrapper.eq("task_id", taskId);
+                                                updateWrapper.eq("task_id", taskId).eq("manager",manager);
                                                 if (EmployeeWeeklyTasksList != null && EmployeeWeeklyTasksList.size() > 0) {
                                                     updateWrapper.set("task_name", taskName);
                                                     updateWrapper.set("manager", manager);
@@ -1336,6 +1342,13 @@ public class ScheduleTask {
         return McR.success();
     }
 
+    /*todo:个人月度成功率*/
+    @SneakyThrows
+    @PostMapping("/personalmonthlySuccessrate")
+    McR personalmonthlySuccessrate(){
+        return McR.success();
+    }
+
     /*todo:人员获取部门*/
     @SneakyThrows
     @PostMapping("/UserGetDeprt")

+ 7 - 0
mjava-ounuo/src/main/java/com/malk/tuosi/service/PersonalMonthlySuccessrateService.java

@@ -0,0 +1,7 @@
+package com.malk.tuosi.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.malk.tuosi.entity.PersonalMonthlySuccessrate;
+
+public interface PersonalMonthlySuccessrateService extends IService<PersonalMonthlySuccessrate> {
+}

+ 14 - 0
mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/PersonalMonthlySuccessrateServiceImpl.java

@@ -0,0 +1,14 @@
+package com.malk.tuosi.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.malk.tuosi.entity.PersonalMonthlySuccessrate;
+import com.malk.tuosi.mapper.PersonalMonthlySuccessrateMapper;
+import com.malk.tuosi.service.PersonalMonthlySuccessrateService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class PersonalMonthlySuccessrateServiceImpl extends ServiceImpl<PersonalMonthlySuccessrateMapper, PersonalMonthlySuccessrate> implements PersonalMonthlySuccessrateService {
+
+}

+ 2 - 0
mjava-ounuo/src/main/java/com/malk/tuosi/service/impl/TbServiceImpl.java

@@ -467,6 +467,8 @@ public class TbServiceImpl implements TBService {
                     message.put("openSpaceId","dtv1.card//IM_GROUP.cidXES2AIusSs+mb9gD8i4w1w==");
                 }else if("张昆".equals(businessManager)){
                     message.put("openSpaceId","dtv1.card//IM_GROUP.cidI3G/EnCvlem5w3+qKfTMDA==");
+                }else if("谷晨单".equals(businessManager)){
+                    message.put("openSpaceId","dtv1.card//IM_GROUP.cidqXtqGAN+Es7L/5m3uaZzSg==");
                 }
 //                message.put("openSpaceId", "dtv1.card//IM_GROUP.cidTppONwRCrkshRlCt28O+NA==");//正式群id:cidTppONwRCrkshRlCt28O+NA==   测试群id:cidKoVDKhvynnj+73h0uxSJBA==
                 message.put("cardTemplateId", "160b26bf-d699-49fc-a6dc-9cd20eed7750.schema");

+ 614 - 138
mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java

@@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.io.FileOutputStream;
@@ -59,13 +60,14 @@ public class SikuServiceImpl implements SikuService {
         }else {
             //供应商
             String hzlx = UtilMap.getString(formData, "radioField_mketkvw7");
+            String freeType = UtilMap.getString(formData, "radioField_mmyoc59n");//free类别
 
             partner.put("parentBizCode", "GYS");//所属分类业务编码
-            partner.put("name", "Free".equals(hzlx) ? UtilMap.getString(formData,"textField_mkkixdd6") : UtilMap.getString(formData,"textField_mketkvv0"));//往来单位中文名
+            partner.put("name", "个人".equals(freeType) ? UtilMap.getString(formData,"textField_mkkixdd6") : UtilMap.getString(formData,"textField_mketkvv0"));//往来单位中文名
             partner.put("partnerType", "供应商");//往来关系,可选值为:"供应商"、"客户"、"供应商,客户"(既是供应商又是客户的情况下以中文逗号分隔(供应商在前))
-            partner.put("partnerProperty", "Free".equals(hzlx) ? "个体工商户" : "公司");//往来性质,可选值为:"公司"、"个体工商户"
+            partner.put("partnerProperty", "个人".equals(freeType) ? "个体工商户" : "公司");//往来性质,可选值为:"公司"、"个体工商户"
             partner.put("businessCode", UtilMap.getString(formData,"serialNumberField_mketkvw4"));//往来单位编码,不超过50个字符
-            partner.put("taxNumber", "Free".equals(hzlx) ? "" : UtilMap.getString(formData,"textField_mketkvxo"));//税务登记号,不超过200个字符
+            partner.put("taxNumber", "个人".equals(freeType) ? "" : UtilMap.getString(formData,"textField_mketkvxo"));//税务登记号,不超过200个字符
             partner.put("readOnly", false);//是否只读,默认false。如果为true,那么在每刻系统中往来单位的所有信息(如权限范围、收款账户等)均无法修改。(接口更新操作不受限制)
             partner.put("reMark", "");//往来单位备注
             partner.put("enabled", "启用".equals(UtilMap.getString(formData,"radioField_mketkvw8")));//是否启用(true:启用;false:禁用)。若该参数为空,新增则默认为true,更新则保持系统内状态。
@@ -76,8 +78,22 @@ public class SikuServiceImpl implements SikuService {
 
         Map result = MkBxUtil.saveTradingPartner(body);
 
-        //保存供应商账户
-        if ("供应商".equals(type)){
+        List<Map> data = UtilMap.getList(result, "data");
+
+        String status = UtilMap.getString(data.get(0), "status");
+
+        if ("ALL_FAIL".equals(status)){
+            //保存往来单位失败回写错误信息
+            String message = UtilMap.getString(data.get(0), "message");
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstId)
+                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库失败",message)))
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+
+        //保存往来单位账户
+        if ("SUCCESS".equals(status)){
             Map account = new HashMap();
             account.put("businessCode",UtilMap.getString(formData,"serialNumberField_mketkvw4"));
 
@@ -89,7 +105,23 @@ public class SikuServiceImpl implements SikuService {
 
             account.put("accounts",Arrays.asList(accountItem));
 
-            MkBxUtil.saveAccount(Arrays.asList(account));
+            Map result2 = MkBxUtil.saveAccount(Arrays.asList(account));
+
+            List<Map> data2 = UtilMap.getList(result2, "data");
+            String status2 = UtilMap.getString(data2.get(0), "status");
+            if ("ALL_FAIL".equals(status2)){
+                String message = UtilMap.getString(data2.get(0), "message");
+
+                ydClient.operateData(YDParam.builder()
+                        .formInstanceId(formInstId)
+                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库成功,账号保存失败",message)))
+                        .build(), YDConf.FORM_OPERATION.update);
+            }else {
+                ydClient.operateData(YDParam.builder()
+                        .formInstanceId(formInstId)
+                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库成功","")))
+                        .build(), YDConf.FORM_OPERATION.update);
+            }
         }
 
         return McR.success();
@@ -108,6 +140,10 @@ public class SikuServiceImpl implements SikuService {
         application.put("bizCode", UtilMap.getString(formData,"serialNumberField_mknspz75"));//外部系统中的开票申请单业务编码。必须系统内唯一,用于判断开票申请单是否已导入。
 
         application.put("clientBizCode",UtilMap.getString(formData,"textField_mkxpe3fj"));//收票方bizCode(客户的业务编码(云票系统内维护的))与收票方开票信息字段二选一必填
+        application.put("clientLegalEntityBizCode",UtilMap.getString(formData,"textField_mkddjwys"));//收票方抬头code,如果不传默认第一个(云票系统内维护的)
+
+        application.put("submitterBizCode","18857526310");//提交人工号,单据状态为审批中时必填  todo 暂时固定 周漂
+        application.put("applicantBizCode","18857526310");//开票申请人工号 todo 暂时固定 周漂
 
         /*Map clientLegalEntityOaDto = new HashMap();//收票方开票信息(不在云票系统内维护的)与收票方bizCode(客户的业务编码)二选一必填且优先级高于收票方bizCode(客户的业务编码)(也就是当两字段都有值时,忽略客户的业务编码)
         clientLegalEntityOaDto.put("invoiceTitle",UtilMap.getString(formData,"selectField_mkxmix7e"));//名称
@@ -117,7 +153,7 @@ public class SikuServiceImpl implements SikuService {
 
         application.put("clientLegalEntityOaDto",clientLegalEntityOaDto);*/
 
-        application.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mm2wj87x"));//公司主体code(后续传税号)
+        application.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mn4dhy5g"));//公司主体code(后续传税号)
         application.put("estimatedDate",System.currentTimeMillis());//预计开票时间
         String fplx = UtilMap.getString(formData, "selectField_mkdnuvem");//发票类型
         String estimatedInvoiceType = "";
@@ -135,11 +171,12 @@ public class SikuServiceImpl implements SikuService {
 
         application.put("phoneNumber",UtilMap.getString(formData,"textField_mkdo0azf"));//收票人电话
         application.put("email",UtilMap.getString(formData,"textField_mkdo0azn"));//收票邮箱
+        application.put("autoSendMail",true);//是否自动发送邮件/短信,若传true且填写正确的收票邮箱/手机号,则在开票申请单完全开票后自动发邮件/短信。不填写收票邮箱/短信或传false时,将不会自动交付电子发票。
         application.put("applicationComment",UtilMap.getString(formData,"textareaField_mkdo0aze"));//开票备注
 
         Map item = new HashMap();
         item.put("productBizCode","1001");//产品bizcode
-        item.put("invoiceName",UtilMap.getString(formData,"textField_mkgarw4d"));//开票名称
+        item.put("invoiceName",UtilMap.getString(formData,"textField_mn4ajusx"));//开票名称
         item.put("taxPercent",UtilMap.getDouble(formData,"numberField_mkgkboht")/100);//税率
         item.put("forexName","CNY");//币种
         item.put("exchangeRate",1);//外汇汇率
@@ -213,50 +250,82 @@ public class SikuServiceImpl implements SikuService {
         } return estimatedInvoiceType;
     }
 
+    @Async
     @Override
     public void invoiceWriteBack2(Map map) {
         //获取发票信息
         Map calloutParams = UtilMap.getMap(map, "calloutParams");
+        String serviceType = UtilMap.getString(calloutParams, "serviceType");
         Map bizData = UtilMap.getMap(calloutParams, "bizData");
 
-        String bizCode = UtilMap.getString(bizData, "bizCode");//发票号码
-        String invoiceNumber = UtilMap.getString(bizData, "invoiceNumber");//发票号码
-        String pdfUrl = UtilMap.getString(bizData, "pdfUrl");//pdf文件下载地址
-        String downloadPageUrl = UtilMap.getString(bizData, "downloadPageUrl");//发票下载页面链接
-        List<Map> detailItems = (List<Map>) UtilMap.getList(bizData, "detailItems");
-        List<Map> documentCorrelates = UtilMap.getList(detailItems.get(0), "documentCorrelates");
-        String lsh = UtilMap.getString(documentCorrelates.get(0), "bizCode");//开票申请单编号
-
-        //回写宜搭
-        Map formData = new HashMap();
-        formData.put("radioField_mkxripcc","开票成功");
-        formData.put("textField_mkxripc6",invoiceNumber);
-        formData.put("textField_mm3aixk0",downloadPageUrl);
-        formData.put("textareaField_mmlzqvn0","");
-
-        if (Strings.isNotBlank(pdfUrl)){
-            String fileName = invoiceNumber + ".pdf";
-            String downloadPath = downloadFilePath + fileName;
-            downloadFile(pdfUrl,downloadPath);//下载pdf发票
-
-            String downloadUri = downloadUrl + "/files/" + fileName + "?option=download" + fileName;
-            String previewUri = downloadUrl + "/files/"+fileName+"?option=preview" + fileName;
-
-            Map attachmentField = new HashMap();
-            attachmentField.put("downloadUrl",downloadUri);
-            attachmentField.put("name",fileName);
-            attachmentField.put("previewUrl",previewUri);
-            attachmentField.put("url",downloadUri);
-            attachmentField.put("ext","pdf");
-            formData.put("attachmentField_mkxripc5",Arrays.asList(attachmentField));
+        if ("INVOICE_VAT_INVOICED_NOTIFY_AR".equals(serviceType)){
+            //发票开具成功后回调
+            String bizCode = UtilMap.getString(bizData, "bizCode");//发票号码
+            String invoiceNumber = UtilMap.getString(bizData, "invoiceNumber");//发票号码
+            String pdfUrl = UtilMap.getString(bizData, "pdfUrl");//pdf文件下载地址
+            String downloadPageUrl = UtilMap.getString(bizData, "downloadPageUrl");//发票下载页面链接
+            List<Map> detailItems = (List<Map>) UtilMap.getList(bizData, "detailItems");
+            List<Map> documentCorrelates = UtilMap.getList(detailItems.get(0), "documentCorrelates");
+            String lsh = UtilMap.getString(documentCorrelates.get(0), "bizCode");//开票申请单编号
+
+            //回写宜搭
+            Map updateFormData = new HashMap();
+            updateFormData.put("radioField_mkxripcc","开票成功");
+            updateFormData.put("textField_mkxripc6",invoiceNumber);
+            updateFormData.put("textField_mm3aixk0",downloadPageUrl);
+            updateFormData.put("textareaField_mmlzqvn0","");
+
+            if (Strings.isNotBlank(pdfUrl)){
+                String fileName = invoiceNumber + ".pdf";
+                String downloadPath = downloadFilePath + fileName;
+                downloadFile(pdfUrl,downloadPath);//下载pdf发票
+
+                String downloadUri = downloadUrl + "/files/" + fileName + "?option=download" + fileName;
+                String previewUri = downloadUrl + "/files/"+fileName+"?option=preview" + fileName;
+
+                Map attachmentField = new HashMap();
+                attachmentField.put("downloadUrl",downloadUri);
+                attachmentField.put("name",fileName);
+                attachmentField.put("previewUrl",previewUri);
+                attachmentField.put("url",downloadUri);
+                attachmentField.put("ext","pdf");
+                updateFormData.put("attachmentField_mkxripc5",Arrays.asList(attachmentField));
+            }
+
+            Map data = ((List<Map>)ydClient.queryData(YDParam.builder()
+                    .formInstanceId(bizCode)
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",lsh)))
+                    .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
+                    .build(), YDConf.FORM_QUERY.retrieve_list).getData()).get(0);
+
+            String formInstanceId = UtilMap.getString(data, "formInstanceId");
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .build(), YDConf.FORM_OPERATION.update);
+
+        }else if ("INVOICE_APPLICATION_VAT_FAIL_NOTIFY_AR".equals(serviceType)){
+            //开票失败后回调
+            String invoiceErrorMsg = UtilMap.getString(bizData, "invoiceErrorMsg");
+
+            String bizCode = UtilMap.getString(bizData, "bizCode");
+
+
+            Map data = ((List<Map>)ydClient.queryData(YDParam.builder()
+                    .formInstanceId(bizCode)
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",bizCode)))
+                    .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
+                    .build(), YDConf.FORM_QUERY.retrieve_list).getData()).get(0);
+
+            String formInstanceId = UtilMap.getString(data, "formInstanceId");
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("radioField_mkxripcc, textareaField_mmlzqvn0","开票失败",invoiceErrorMsg)))
+                    .build(), YDConf.FORM_OPERATION.update);
         }
 
-        ydClient.operateData(YDParam.builder()
-                .formInstanceId(bizCode)
-                .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",lsh)))
-                .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
-                .formDataJson(JSONObject.toJSONString(formData))
-                .build(), YDConf.FORM_OPERATION.upsert);
     }
 
     @Override
@@ -267,7 +336,214 @@ public class SikuServiceImpl implements SikuService {
                 .formInstanceId(formInstId)
                 .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
 
-        Map body = new HashMap();
+        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
+        String formSubTypeBizCode = "FT208629766551519240";//项目支付单
+
+        Double amt = UtilMap.getDouble(formData, "numberField_mkkmij6i");
+
+        String empId = "";
+        String deptBusinessCode = "";
+
+        String ydfqr = UtilMap.getString(formData, "textField_mmwvodde");//宜搭发起人工号
+
+        if (amt >= 5000){
+            //支付金额>=5000元,每刻发起人为宜搭采购单据发起人;每刻中的【费用承担部门】实际为采购单发起人所在部门,非每刻单据发起人部门
+            Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
+            if (Objects.nonNull(employeeDetails)){
+                List<Map> departments = UtilMap.getList(employeeDetails, "departments");
+                deptBusinessCode = UtilMap.getString(departments.get(0), "businessCode");
+
+                empId = ydfqr;
+            }else {
+                empId = "002";//默认沃洲洋
+                deptBusinessCode = "DI203800035494740082";//默认DI203800035494740082
+            }
+        }else {
+            //支付金额<5000元,每刻发起人为宜搭采购单据中的中台采购;每刻中的【费用承担部门】实际为采购单发起人所在部门,非每刻单据发起人部门
+            Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
+            if (Objects.nonNull(employeeDetails)){
+                List<Map> departments = UtilMap.getList(employeeDetails, "departments");
+                deptBusinessCode = UtilMap.getString(departments.get(0), "businessCode");
+            }else {
+                deptBusinessCode = "DI203800035494740082";//默认DI203800035494740082
+            }
+
+            String ztcggh = UtilMap.getString(formData, "textField_mmwvfb97");//中台采购工号
+            Map employeeDetails2 = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ztcggh)));
+
+            if (Objects.nonNull(employeeDetails2)){
+                empId = ztcggh;
+            }else {
+                empId = "002";//默认沃洲洋
+            }
+        }
+
+        String submittedUserEmployeeId = empId;//提单人工号
+        String legalEntityBizCode = UtilMap.getString(formData, "textField_mmd6hio7");//公司抬头编码
+        String coverUserEmployeeId = empId;//承担人工号
+        String coverDepartmentBizCode = deptBusinessCode;//承担部门编码
+
+        String xqbh = UtilMap.getString(formData, "serialNumberField_mkkmij3o");//需求编号
+        long ldjssj = UtilMap.getLong(formData, "dateField_mkdf8q8q");//落地结束时间
+        String isFree = "FREE需求".equals(type) ? "是" : "否";//是否free
+        String isDdf = "是".equals(UtilMap.getString(formData, "radioField_mkf2quln")) ? "1" : "2";//是否代垫付
+        String xmsssyb = UtilMap.getString(formData, "selectField_mkdedkv7");//项目所属事业部
+        String projectCode = UtilMap.getString(formData, "textField_mmoh6nvx");//项目编码
+
+        //针对多供应商分期付款拆分多条每刻项目支付单
+        if ("常规需求".equals(type)){
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细
+
+            int index = 0;
+            for (Map detail : detailList) {
+                index++;
+                String uuid = UtilMap.getString(detail, "textField_mmvhqm0q");//子表uuid
+                Map body = new HashMap();
+                body.put("formCode",xqbh + "-" + index);//有值时会使用该值作为单据号
+                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号
+                body.put("submittedUserEmployeeId",submittedUserEmployeeId);//提单人工号
+                body.put("reimburseName",UtilMap.getString(detail,"textareaField_mkkmij5i"));//报销事由
+                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
+                body.put("coverUserEmployeeId",coverUserEmployeeId);//承担人工号
+                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码
+                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位编码
+
+
+                Map customObject = new HashMap();
+                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
+                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mmvhqm0u"));}});//期望支付日期
+                customObject.put("CF6",isFree);////free  是;否
+                customObject.put("CF5",isDdf);//代垫付  是:1  ;  否:2
+                customObject.put("CF2",xmsssyb);//项目所属事业部
+                customObject.put("CF1",projectCode);//项目
+                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwt2wcn"));//逾期天数
+
+
+                body.put("customObject",customObject);
+
+                //报销单费用导入
+                Map expenseListItem = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij5e")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                expenseListItem.put("consumeAmount",consumeAmount);
+                expenseListItem.put("corpExpense",true);//是否对公费用,需要填写true
+                String gysej = UtilMap.getString(detail, "selectField_mkkkw28y");//供应商二级
+                expenseListItem.put("expenseTypeBizCode",MkBxUtil.expenseTypeSearch(UtilMap.map("keyword",gysej)));//费用类型业务编码
+                expenseListItem.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
+                expenseListItem.put("consumeLocation",consumeLocation);
+
+                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                Map body2 = new HashMap();
+                body2.put("employeeId","002");//需要导入的对应员工的工号
+                body2.put("expenseList",Arrays.asList(expenseListItem));
+
+                List<String> expenseCodes = MkBxUtil.receiveExpense(body2);
+
+                body.put("expenseCodes",expenseCodes);//费用类型业务编码
+
+                //收款账户
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mkkmij6z"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mkkmij6y"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                body.put("payeeAccount",payeeAccount);
+
+                body.put("stagingFlag",true);//暂存标识,默认为false表示不暂存
+
+
+                Map result = MkBxUtil.receiveReimburse(body);
+
+            }
+        }else {
+            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细
+
+            int index = 0;
+            for (Map detail : detailList) {
+                index ++;
+                String uuid = UtilMap.getString(detail, "textField_mmvhqm0s");//子表uuid
+                Map body = new HashMap();
+//                body.put("formCode",xqbh + "-" + uuid);//有值时会使用该值作为单据号
+                body.put("formCode",xqbh + "-" +index);//有值时会使用该值作为单据号
+                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号
+                body.put("submittedUserEmployeeId",submittedUserEmployeeId);//提单人工号
+                body.put("reimburseName","FREE-" + UtilMap.getString(detail,"selectField_mkkixdd7"));//报销事由
+                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
+                body.put("coverUserEmployeeId",coverUserEmployeeId);//承担人工号
+                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码
+                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位编码
+
+                Map customObject = new HashMap();
+                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
+                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mkkkw298"));}});//期望支付日期
+                customObject.put("CF6",isFree);//free  是;否
+                customObject.put("CF5",isDdf);//代垫付  是:1  ;  否:2
+                customObject.put("CF2",xmsssyb);//项目所属事业部
+                customObject.put("CF1",projectCode);//项目
+                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkx"));//逾期天数
+
+                body.put("customObject",customObject);
+
+                //报销单费用导入
+                Map expenseListItem = new HashMap();
+
+                Map consumeAmount = new HashMap();
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij6p")));//结算金额
+                consumeAmount.put("currency","CNY");
+
+                expenseListItem.put("consumeAmount",consumeAmount);
+                expenseListItem.put("corpExpense",true);//是否对公费用,需要填写true
+                String gysej = UtilMap.getString(detail, "selectField_mmwuzaql");//供应商二级
+                expenseListItem.put("expenseTypeBizCode",MkBxUtil.expenseTypeSearch(UtilMap.map("keyword",gysej)));//费用类型业务编码
+                expenseListItem.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位业务编码
+
+                Map consumeLocation = new HashMap();
+                consumeLocation.put("cityPair",null);
+                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
+                expenseListItem.put("consumeLocation",consumeLocation);
+
+                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+
+                Map body2 = new HashMap();
+                body2.put("employeeId","002");//需要导入的对应员工的工号
+                body2.put("expenseList",Arrays.asList(expenseListItem));
+
+                List<String> expenseCodes = MkBxUtil.receiveExpense(body2);
+
+                body.put("expenseCodes",expenseCodes);//费用类型业务编码
+
+                //收款账户
+                Map payeeAccount = new HashMap();
+                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mketkvxa"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mketkvxc"));//银行账户
+                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
+                payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
+                body.put("payeeAccount",payeeAccount);
+
+                body.put("stagingFlag",true);//暂存标识,默认为false表示不暂存
+
+
+                Map result = MkBxUtil.receiveReimburse(body);
+
+            }
+
+        }
+
+        /*Map body = new HashMap();
         body.put("formCode",UtilMap.getString(formData,"serialNumberField_mkkmij3o"));//有值时会使用该值作为单据号
         body.put("formSubTypeBizCode","FT208629766551519240");//表单类型的业务编号  todo 暂时写死 FT208629766551519240 宜搭支付单
         body.put("submittedUserEmployeeId","002");//提单人工号 todo 暂时写死 002 wzy
@@ -282,12 +558,10 @@ public class SikuServiceImpl implements SikuService {
         customObject.put("CF6",UtilMap.getString(formData,"radioField_mkf2quln"));////free  是;否
         customObject.put("CF5","是".equals(UtilMap.getString(formData,"radioField_mkf2quln")) ? "1" : "2");//代垫付  是:1  ;  否:2
         customObject.put("CF2",UtilMap.getString(formData,"selectField_mkdedkv7"));//项目所属事业部
-        customObject.put("CF1",UtilMap.getString(formData,"textField_mkkmij50"));//项目
+        customObject.put("CF1",UtilMap.getString(formData,"textField_mmoh6nvx"));//项目
 
         body.put("customObject",customObject);
 
-        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
-
         List<String> expenseCodes = new ArrayList<>();
         List<Map> collectionSchedule = new ArrayList<>();
 
@@ -392,7 +666,7 @@ public class SikuServiceImpl implements SikuService {
 
         body.put("stagingFlag",false);////暂存标识,默认为false表示不暂存
 
-        Map result = MkBxUtil.receiveReimburse(body);
+        Map result = MkBxUtil.receiveReimburse(body);*/
 
         return McR.success();
     }
@@ -425,13 +699,18 @@ public class SikuServiceImpl implements SikuService {
         customerObj.put("contacts",contacts);//联系人列表
 
         List<Map> invoiceTitles = new ArrayList<>();
-        Map invoiceTitle = new HashMap();
-        invoiceTitle.put("invoiceTitle",UtilMap.getString(formData,"textField_mkddjwyr"));//发票抬头
-        invoiceTitle.put("dutyParagraph",UtilMap.getString(formData,"textField_mkddjwys"));//税号
-        invoiceTitle.put("bizCode",UtilMap.getString(formData,"textField_mkddjwys"));//业务编码
-        invoiceTitle.put("bankBranchName",UtilMap.getString(formData,"textField_mkddjwyt"));//开户行
-        invoiceTitle.put("account",UtilMap.getString(formData,"textField_mkddjwyu"));//银行账户
-        invoiceTitles.add(invoiceTitle);
+
+        List<Map> invoiceList = UtilMap.getList(formData, "tableField_mn496ozf");
+        for (Map invoice : invoiceList) {
+            Map invoiceTitle = new HashMap();
+            invoiceTitle.put("invoiceTitle",UtilMap.getString(invoice,"textField_mkddjwyr"));//发票抬头
+            invoiceTitle.put("dutyParagraph",UtilMap.getString(invoice,"textField_mkddjwys"));//税号
+            invoiceTitle.put("bizCode",UtilMap.getString(invoice,"textField_mkddjwys"));//业务编码
+            invoiceTitle.put("bankBranchName",UtilMap.getString(invoice,"textField_mkddjwyt"));//开户行
+            invoiceTitle.put("account",UtilMap.getString(invoice,"textField_mkddjwyu"));//银行账户
+            invoiceTitles.add(invoiceTitle);
+        }
+
         customerObj.put("invoiceTitles",invoiceTitles);//发票抬头列表
 
         MkYpUtil.saveClient(Arrays.asList(customerObj));
@@ -439,6 +718,7 @@ public class SikuServiceImpl implements SikuService {
         return McR.success();
     }
 
+    @Async
     @Override
     public void invoiceWriteBack(Map map) {
         Map calloutParams = UtilMap.getMap(map, "calloutParams");
@@ -486,10 +766,24 @@ public class SikuServiceImpl implements SikuService {
 
     }
 
+    @Async
     @Override
     public void invoiceWriteBack3(Map map) {
         String formCode = UtilMap.getString(map, "formCode");
 
+        String operation = UtilMap.getString(map, "operation");
+
+        if ("FORM_COMPLETE".equals(operation)){
+            //完成
+        }else if ("FORM_REJECT".equals(operation)){
+            //驳回
+        }
+
+        String[] split = formCode.split("-");
+
+        String bh = split[0];//采购需求编号/直接采购单编号
+        int index = Integer.parseInt(split[1]);//子表索引
+
         Map formData = UtilMap.getMap(map, "formData");
 
         Map baseAmount = UtilMap.getMap(formData, "baseAmount");
@@ -504,27 +798,127 @@ public class SikuServiceImpl implements SikuService {
             //采购需求&结算
             List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                     .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
-                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", formCode)))
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                     .build(), YDConf.FORM_QUERY.retrieve_list).getData();
 
             String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");
 
+            Map ydFormData = UtilMap.getMap(data.get(0), "formData");
+
+            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");
+
+            if ("常规需求".equals(type)){
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");
+
+                for (Map detail : detailList) {
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
+                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
+                        String fkzt = UtilMap.getString(detail, "selectField_mmvhqm0p");//付款状态
+                        if (yfkje + amt == jscb){
+                            detail.put("selectField_mmvhqm0p","全部付款");
+                        }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
+                            detail.put("selectField_mmvhqm0p","部分付款");
+                        }
+
+                        detail.put("numberField_mmvqom6l",yfkje + amt);
+
+                        break;
+                    }
+                }
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+
+                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
+                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqs9h6");//已付款金额
+                        String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态
+
+                        if (yfkje + amt == jscb){
+                            detail.put("selectField_mkkmij6a","全部付款");
+                        }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
+                            detail.put("selectField_mkkmij6a","部分付款");
+                        }
+
+                        detail.put("numberField_mmvqom6l",yfkje + amt);
+
+                        break;
+                    }
+                }
+            }
+
+            Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
+
+            ydFormData.put("numberField_mkf2qumf",yzf + amt);
+
             ydClient.operateData(YDParam.builder()
                     .formInstanceId(formInstanceId)
-                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("numberField_mkf2qumf",amt)))
+                    .updateFormDataJson(JSONObject.toJSONString(ydFormData))
                     .build(), YDConf.FORM_OPERATION.update);
         }else {
             //直接采购结算单
             List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                     .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
-                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", formCode)))
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                     .build(), YDConf.FORM_QUERY.retrieve_list).getData();
 
             String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");
 
+            Map ydFormData = UtilMap.getMap(data.get(0), "formData");
+
+            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");
+
+            if ("常规采购".equals(type)){
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");
+
+                for (Map detail : detailList) {
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
+                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6k");//已付款金额
+                        String fkzt = UtilMap.getString(detail, "selectField_mmvhtdy0");//付款状态
+                        if (yfkje + amt == jscb){
+                            detail.put("selectField_mmvhtdy0","全部付款");
+                        }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
+                            detail.put("selectField_mmvhtdy0","部分付款");
+                        }
+
+                        detail.put("numberField_mmvqom6k",yfkje + amt);
+
+                        break;
+                    }
+                }
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+
+                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
+                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
+                        String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态
+
+                        if (yfkje + amt == jscb){
+                            detail.put("selectField_mkkmij6a","全部付款");
+                        }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
+                            detail.put("selectField_mkkmij6a","部分付款");
+                        }
+
+                        detail.put("numberField_mmvqom6l",yfkje + amt);
+
+                        break;
+                    }
+                }
+            }
+
+            Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
+
+            ydFormData.put("numberField_mkf2qumf",yzf + amt);
+
             ydClient.operateData(YDParam.builder()
                     .formInstanceId(formInstanceId)
-                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("numberField_mkf2qumf",amt)))
+                    .updateFormDataJson(JSONObject.toJSONString(ydFormData))
                     .build(), YDConf.FORM_OPERATION.update);
         }
 
@@ -538,132 +932,214 @@ public class SikuServiceImpl implements SikuService {
                 .formInstanceId(formInstId)
                 .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
 
-        Map body = new HashMap();
-        body.put("formCode",UtilMap.getString(formData,"serialNumberField_mkkmij3o"));//有值时会使用该值作为单据号
-        body.put("formSubTypeBizCode","FT208629766551519240");//表单类型的业务编号  todo 暂时写死 FT208629766551519240 宜搭支付单
-        body.put("submittedUserEmployeeId","002");//提单人工号 todo 暂时写死 002 wzy
-        body.put("reimburseName",UtilMap.getString(formData,"textareaField_mmbmohr9"));//报销事由
-        body.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mmd6hio7"));//公司抬头编码
-        body.put("coverUserEmployeeId","002");//承担人工号 todo 暂时写死 002 wzy
-        body.put("coverDepartmentBizCode","DI203800035494740082");//承担部门编码 todo 暂时写死 DI203800035494740082
+        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
+        String formSubTypeBizCode = "FT208629766551519240";//项目支付单
 
-        Map customObject = new HashMap();
-        customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkdf8q8q"));}});//落地结束时间
-        customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkkkw298"));}});//预计支付日期
-        customObject.put("CF6",UtilMap.getString(formData,"radioField_mkf2quln"));////free  是;否
-        customObject.put("CF5","是".equals(UtilMap.getString(formData,"radioField_mkf2quln")) ? "1" : "2");//代垫付  是:1  ;  否:2
-        customObject.put("CF2",UtilMap.getString(formData,"selectField_mkdedkv7"));//项目所属事业部
-        customObject.put("CF1",UtilMap.getString(formData,"textField_mkkmij50"));//项目
+        Double amt = UtilMap.getDouble(formData, "numberField_mkkmij6i");
 
-        body.put("customObject",customObject);
+        String empId = "";
+        String deptBusinessCode = "";
 
-        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
+        String ydfqr = UtilMap.getString(formData, "textField_mmwvodde");//宜搭发起人工号
 
-        List<String> expenseCodes = new ArrayList<>();
-        List<Map> collectionSchedule = new ArrayList<>();
+        if (amt >= 5000){
+            //支付金额>=5000元,每刻发起人为宜搭采购单据发起人;每刻中的【费用承担部门】实际为采购单发起人所在部门,非每刻单据发起人部门
+            Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
+            if (Objects.nonNull(employeeDetails)){
+                List<Map> departments = UtilMap.getList(employeeDetails, "departments");
+                deptBusinessCode = UtilMap.getString(departments.get(0), "businessCode");
 
-        List<Map> expenseList = new ArrayList<>();
+                empId = ydfqr;
+            }else {
+                empId = "002";//默认沃洲洋
+                deptBusinessCode = "DI203800035494740082";//默认DI203800035494740082
+            }
+        }else {
+            //支付金额<5000元,每刻发起人为宜搭采购单据中的中台采购;每刻中的【费用承担部门】实际为采购单发起人所在部门,非每刻单据发起人部门
+            Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
+            if (Objects.nonNull(employeeDetails)){
+                List<Map> departments = UtilMap.getList(employeeDetails, "departments");
+                deptBusinessCode = UtilMap.getString(departments.get(0), "businessCode");
+            }else {
+                deptBusinessCode = "DI203800035494740082";//默认DI203800035494740082
+            }
+
+            String ztcggh = UtilMap.getString(formData, "textField_mmwvfb97");//中台采购工号
+            Map employeeDetails2 = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ztcggh)));
+
+            if (Objects.nonNull(employeeDetails2)){
+                empId = ztcggh;
+            }else {
+                empId = "002";//默认沃洲洋
+            }
+        }
+
+        String submittedUserEmployeeId = empId;//提单人工号
+        String legalEntityBizCode = UtilMap.getString(formData, "textField_mmd6hio7");//公司抬头编码
+        String coverUserEmployeeId = empId;//承担人工号
+        String coverDepartmentBizCode = deptBusinessCode;//承担部门编码
+
+        String xqbh = UtilMap.getString(formData, "serialNumberField_mkkmij3o");//需求编号
+        long ldjssj = UtilMap.getLong(formData, "dateField_mkdf8q8q");//落地结束时间
+        String isFree = "FREE采购".equals(UtilMap.getString(formData, "radioField_mkf2quln")) ? "是" : "否";//是否free
+        String isDdf = "是".equals(UtilMap.getString(formData, "radioField_mkf2qulo")) ? "1" : "2";//是否代垫付
+        String xmsssyb = UtilMap.getString(formData, "selectField_mkdedkv7");//项目所属事业部
+        String projectCode = UtilMap.getString(formData, "textField_mmoh6nvx");//项目编码
 
+        //针对多供应商分期付款拆分多条每刻项目支付单
         if ("常规采购".equals(type)){
             List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细
-
-            for (Map result : detailList) {
-                Map item = new HashMap();
+            int index = 0;
+            for (Map detail : detailList) {
+                index++;
+                String uuid = UtilMap.getString(detail, "textField_mmvhqm0q");//子表uuid
+                Map body = new HashMap();
+                body.put("formCode",xqbh + "-" + index);//有值时会使用该值作为单据号
+                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号
+                body.put("submittedUserEmployeeId",submittedUserEmployeeId);//提单人工号
+                body.put("reimburseName",UtilMap.getString(detail,"textareaField_mkkmij5i"));//报销事由
+                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
+                body.put("coverUserEmployeeId",coverUserEmployeeId);//承担人工号
+                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码
+                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位编码
+
+
+                Map customObject = new HashMap();
+                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
+                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mkkkw298"));}});//期望支付日期
+                customObject.put("CF6",isFree);//free  是;否
+                customObject.put("CF5",isDdf);//代垫付  是:1  ;  否:2
+                customObject.put("CF2",xmsssyb);//项目所属事业部
+                customObject.put("CF1",projectCode);//项目
+                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkv"));//逾期天数
+
+                body.put("customObject",customObject);
+
+                //报销单费用导入
+                Map expenseListItem = new HashMap();
 
                 Map consumeAmount = new HashMap();
-                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij5e")));//结算金额
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij5e")));//结算金额
                 consumeAmount.put("currency","CNY");
 
-                item.put("consumeAmount",consumeAmount);
-                item.put("corpExpense",true);//是否对公费用,需要填写true
-                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
-                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
-                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
-                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
-                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//往来单位业务编码
+                expenseListItem.put("consumeAmount",consumeAmount);
+                expenseListItem.put("corpExpense",true);//是否对公费用,需要填写true
+                String gysej = UtilMap.getString(detail, "selectField_mkkkw28y");//供应商二级
+                expenseListItem.put("expenseTypeBizCode",MkBxUtil.expenseTypeSearch(UtilMap.map("keyword",gysej)));//费用类型业务编码
+                expenseListItem.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位业务编码
 
                 Map consumeLocation = new HashMap();
                 consumeLocation.put("cityPair",null);
-                consumeLocation.put("location","110001");
-                item.put("consumeLocation",consumeLocation);
+                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
+                expenseListItem.put("consumeLocation",consumeLocation);
 
-                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
 
-                expenseList.add(item);
+                Map body2 = new HashMap();
+                body2.put("employeeId","002");//需要导入的对应员工的工号
+                body2.put("expenseList",Arrays.asList(expenseListItem));
 
+                List<String> expenseCodes = MkBxUtil.receiveExpense(body2);
 
-                Map collectionScheduleItem = new HashMap();
+                body.put("expenseCodes",expenseCodes);//费用类型业务编码
+
+                //收款账户
                 Map payeeAccount = new HashMap();
-                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mkkmij6z"));//账户名
-                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mkkmij6y"));//银行账户
+                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mkkmij6z"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mkkmij6y"));//银行账户
                 payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                 payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
-                collectionScheduleItem.put("payeeAccount",payeeAccount);
-                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//收款往来单位编码
-                collectionScheduleItem.put("amountRatio",0);//收款比例
-                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
-                collectionScheduleItem.put("collectionType","BANK");//支付类型
+                body.put("payeeAccount",payeeAccount);
+
+                body.put("stagingFlag",true);//暂存标识,默认为false表示不暂存
+
+
+                Map result = MkBxUtil.receiveReimburse(body);
 
-                collectionSchedule.add(collectionScheduleItem);
             }
         }else {
             List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细
 
-            for (Map result : detailList) {
-                Map item = new HashMap();
+            int index = 0;
+            for (Map detail : detailList) {
+                index ++;
+                String uuid = UtilMap.getString(detail, "textField_mmvhqm0s");//子表uuid
+                Map body = new HashMap();
+//                body.put("formCode",xqbh + "-" + uuid);//有值时会使用该值作为单据号
+                body.put("formCode",xqbh + "-" +index);//有值时会使用该值作为单据号
+                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号
+                body.put("submittedUserEmployeeId",submittedUserEmployeeId);//提单人工号
+                body.put("reimburseName","FREE-" + UtilMap.getString(detail,"selectField_mkkixdd7"));//报销事由
+                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
+                body.put("coverUserEmployeeId",coverUserEmployeeId);//承担人工号
+                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码
+                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位编码
+
+                Map customObject = new HashMap();
+                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
+                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mmvhtdy4"));}});//期望支付日期
+                customObject.put("CF6",isFree);//free  是;否
+                customObject.put("CF5",isDdf);//代垫付  是:1  ;  否:2
+                customObject.put("CF2",xmsssyb);//项目所属事业部
+                customObject.put("CF1",projectCode);//项目
+                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkx"));//逾期天数
+
+                body.put("customObject",customObject);
+
+                //报销单费用导入
+                Map expenseListItem = new HashMap();
 
                 Map consumeAmount = new HashMap();
-                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij6p")));//结算金额
+                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij6p")));//结算金额
                 consumeAmount.put("currency","CNY");
 
-                item.put("consumeAmount",consumeAmount);
-                item.put("corpExpense",true);//是否对公费用,需要填写true
-                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
-                item.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
-                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
-                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
-                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//往来单位业务编码
+                expenseListItem.put("consumeAmount",consumeAmount);
+                expenseListItem.put("corpExpense",true);//是否对公费用,需要填写true
+                String gysej = UtilMap.getString(detail, "selectField_mmwuzaql");//供应商二级
+                expenseListItem.put("expenseTypeBizCode",MkBxUtil.expenseTypeSearch(UtilMap.map("keyword",gysej)));//费用类型业务编码
+                expenseListItem.put("corpType","NO_RECEIPT");//业务场景:ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
+                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额(预付未到票场景必填)
+                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间(预付未到票场景必填)
+                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位业务编码
 
                 Map consumeLocation = new HashMap();
                 consumeLocation.put("cityPair",null);
-                consumeLocation.put("location","110001");
-                item.put("consumeLocation",consumeLocation);
+                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
+                expenseListItem.put("consumeLocation",consumeLocation);
 
-                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
+                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人(预付未到票/到票部分支付或不支付 两种场景必填) todo 暂时写死 002 wzy
 
-                expenseList.add(item);
+                Map body2 = new HashMap();
+                body2.put("employeeId","002");//需要导入的对应员工的工号
+                body2.put("expenseList",Arrays.asList(expenseListItem));
 
+                List<String> expenseCodes = MkBxUtil.receiveExpense(body2);
 
-                Map collectionScheduleItem = new HashMap();
+                body.put("expenseCodes",expenseCodes);//费用类型业务编码
+
+                //收款账户
                 Map payeeAccount = new HashMap();
-                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mketkvxa"));//账户名
-                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mketkvxc"));//银行账户
+                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mketkvxa"));//账户名
+                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mketkvxc"));//银行账户
                 payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                 payeeAccount.put("accountType","CORP");//收款账户类型:个人(员工)-PERSONAL,公司(往来单位)-CORP
-                collectionScheduleItem.put("payeeAccount",payeeAccount);
-                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//收款往来单位编码
-                collectionScheduleItem.put("amountRatio",0);//收款比例
-                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
-                collectionScheduleItem.put("collectionType","BANK");//支付类型
+                body.put("payeeAccount",payeeAccount);
+
+                body.put("stagingFlag",true);//暂存标识,默认为false表示不暂存
+
+
+                Map result = MkBxUtil.receiveReimburse(body);
 
-                collectionSchedule.add(collectionScheduleItem);
             }
-        }
 
-        //报销单费用导入
-        Map body2 = new HashMap();
-        body2.put("employeeId","002");//需要导入的对应员工的工号
-        body2.put("expenseList",expenseList);
+        }
 
-        expenseCodes = MkBxUtil.receiveExpense(body2);
 
-        body.put("expenseCodes",expenseCodes);//费用类型业务编码
-        body.put("collectionSchedule",collectionSchedule);//多人收款,如果已填充该字段,则无需填充上方的收款账户字段,若传多人收款,则paymentSceneBizCode参数必填
-        body.put("paymentSceneBizCode","DGYSSK");//多人收款场景(支付场景)表单业务编码,需要填写多人收款时必填
 
-        body.put("stagingFlag",false);////暂存标识,默认为false表示不暂存
 
-        Map result = MkBxUtil.receiveReimburse(body);
 
         return McR.success();
     }

+ 36 - 5
mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java

@@ -9,10 +9,7 @@ import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 每刻报销
@@ -84,7 +81,7 @@ public class MkBxUtil {
         return result;
     }
 
-    //保存往来单位
+    //保存往来单位账号
     public static Map saveAccount(Object body){
         Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/tradingPartner/batch/account/save", MkBxUtil.initTokenHeader(), null, body,(Map) null));
 
@@ -122,6 +119,40 @@ public class MkBxUtil {
         return expenseCodes;
     }
 
+    //费用类型查询
+    public static String expenseTypeSearch(Object body){
+        log.info("body:{}",JSONObject.toJSONString(body));
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/expense/type/search", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        List<Map> data = UtilMap.getList(result, "data");
+
+        if (!data.isEmpty()){
+            String bizCode = UtilMap.getString(data.get(0), "bizCode");
+
+            return bizCode;
+        }else {
+            return null;
+        }
+    }
+
+    //根据工号查询员工详情
+    public static Map employeeDetails(Object body){
+        log.info("body:{}",JSONObject.toJSONString(body));
+        Map result = (Map) JSONObject.parse(UtilHttp.doPost("https://" + host + "/api/openapi/employee/details", MkBxUtil.initTokenHeader(), null, body,(Map) null));
+
+        log.info("Result:{}",result);
+
+        List<Map> data = UtilMap.getList(result, "data");
+
+        if (Objects.nonNull(data)){
+            return data.get(0);
+        }else {
+            return null;
+        }
+    }
+
 
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);

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

@@ -12,4 +12,4 @@ spring:
 #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
   global-config:
     db-config:
-      id-type: auto
+      id-type: autos

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

@@ -14,14 +14,14 @@ public class SkTest {
     @Test
     public void getSecret(){
         //每刻报销-测试环境
-        /*String appCode="AP52Y01LHHTAP9";
-        String appSecret="N4WuERLteAUPaWebnsHy";*/
+        String appCode="AP52Y01LHHTAP9";
+        String appSecret="N4WuERLteAUPaWebnsHy";
 
 
 
         //每刻云票-测试环境
-        String appCode="AP53EP1SVDS1N9";
-        String appSecret="qF4nm3nPnyXYcrWcr5jl";
+        /*String appCode="AP53EP1SVDS1N9";
+        String appSecret="qF4nm3nPnyXYcrWcr5jl";*/
 
         long timeMillis = System.currentTimeMillis();
         log.info("time:{}",timeMillis);

+ 49 - 0
mjava-zhongche/pom.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.7.18</version> <!-- 使用最新的稳定版或其他适用版本 -->
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.malk.zhongche</groupId>
+    <artifactId>mjava-zhongche</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>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.malk</groupId>
+            <artifactId>base</artifactId>
+            <version>1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 17 - 0
mjava-zhongche/src/main/java/com/malk/zhongche/ZhongcheApplication.java

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

+ 28 - 0
mjava-zhongche/src/main/resources/application-dev.yml

@@ -0,0 +1,28 @@
+server:
+  port: 9038
+  servlet:
+    context-path: /api/zhongche
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/zhongche/log/
+  level:
+    com.malk.*: debug
+
+# dingtalk
+dingtalk:
+  agentId:
+  appKey:
+  appSecret:
+  corpId:
+  aesKey:
+  token:
+  operator:
+
+aliwork:
+  appType: APP_SL9V2KUH6GBEISLNXXTJ
+  systemToken: HOE66T71Z9H2PLVHM6EU85Q7H2AJ2YV2GRKKMWL1
+
+

+ 28 - 0
mjava-zhongche/src/main/resources/application-prod.yml

@@ -0,0 +1,28 @@
+server:
+  port: 9038
+  servlet:
+    context-path: /api/zhongche
+
+enable:
+  scheduling: false
+logging:
+  config: classpath:logback-spring.xml
+  path: /home/server/zhongche/log/
+  level:
+    com.malk.*: info
+
+# dingtalk
+dingtalk:
+  agentId:
+  appKey:
+  appSecret:
+  corpId:
+  aesKey:
+  token:
+  operator:
+
+aliwork:
+  appType:
+  systemToken:
+
+

+ 15 - 0
mjava-zhongche/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: autos

+ 61 - 0
mjava-zhongche/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>