Explorar el Código

Merge remote-tracking branch 'origin/master'

“lqy hace 4 semanas
padre
commit
1b7583c150

+ 34 - 18
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java

@@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.JacksonException;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.malk.fenggefushi.service.HeiHuOrderService;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
@@ -18,6 +19,7 @@ import com.malk.service.aliwork.YDClient;
 import com.malk.service.aliwork.YDService;
 import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
+import jdk.nashorn.internal.ir.ObjectNode;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +34,7 @@ import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
 
 @Slf4j
 @Service
@@ -1191,38 +1194,51 @@ public class HeiHuOrderServiceImpl implements HeiHuOrderService {
                             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:查询销售订单,获取客户、订单号、款号、产品描述、颜色、数量、销售单价、销售金额、币别
+                            log.info("saleOrder/queryList2:{}",jsonString2);
                             JSONArray array = JSONObject.parseObject(jsonString2).getJSONArray("data");//主表数据
-
+                            String finalOrderNumber = orderNumber;
+//                            array = array.stream()
+//                                    .filter(item -> item instanceof JSONObject)          // 确保是 JSONObject
+//                                    .map(item -> (JSONObject) item)
+//                                    .filter(obj -> obj.getString("contractNo").equals(finalOrderNumber))
+//                                    .collect(Collectors.toCollection(JSONArray::new));
                             boolean isSample = false;//销售订单若为样品订单则不发起钉钉流程
                             for(int i=0;i<array.size();i++){
                                 JSONObject data = array.getJSONObject(i);
                                 customerName = data.getString("customerCode");//客户
+                                if (finalOrderNumber.equals(data.getString("contractNo"))){
+                                    log.info("customer123:{}",customerName);
+                                }
                             }
                             ObjectMapper objectMapper2 = new ObjectMapper();
                             JsonNode dataNode2 = null;//主表数据
+                            List<JsonNode> list = new ArrayList<>();
                             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();//辅料预估单价
+                                list = StreamSupport.stream(dataNode2.spliterator(), false)
+                                        .filter(node -> finalOrderNumber.equals(node.get("orderNo").asText()))
+                                        .collect(Collectors.toList());
+                                for (JsonNode item : list){
+                                    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");
-                                        log.info("销售订单类型:{}",valueNode.asText());
-                                        if("样品订单".equals(valueNode.asText())){
-                                            isSample = true;
+                                        else if(fieldIdNode != null && fieldIdNode.asInt() == 47771){
+                                            JsonNode valueNode = field.get("value");
+                                            log.info("销售订单类型:{}",valueNode.asText());
+                                            if("样品订单".equals(valueNode.asText())){
+                                                isSample = true;
+                                            }
                                         }
                                     }
                                 }
+                            } catch (JsonProcessingException e) {
+                                e.printStackTrace();
                             }
 
                             if (!isSample){

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

@@ -447,6 +447,7 @@ public class PkProjectServiceImpl implements PkProjectService {
     public static String getBusinessTravelToken(){
         String result = HttpUtils.httpGet("https://btripopen.alibtrip.com/api/btrip-open-auth/v1/corp-token/action/take?app_key=pqm6bkfs0800&type=0&corp_id=open12pqm6bkfju87v16348dd896bc361558&app_secret=cHFtNmJrZnMwODAwXS1ceXpINzUsazUkVT1tejohZ1o");
         JSONObject jsonObject = JSONObject.parseObject(result);
+        log.info("获取token:{}",jsonObject);
         if (ObjectUtil.isNotNull(jsonObject) && Boolean.parseBoolean(jsonObject.get("success").toString())){
             Object module = jsonObject.get("module");
             jsonObject = JSONObject.parseObject(module.toString());
@@ -456,6 +457,7 @@ public class PkProjectServiceImpl implements PkProjectService {
     }
     //根据token和分页获取所有数据
     public static List<Object> getResult(String url,Map<String,Object> param){
+        log.info("开始第一次获取总数据量:{}",param);
         int pageSize = 100;
         if (param.containsKey("page_size")){
             pageSize = Integer.parseInt(param.get("page_size").toString());

+ 20 - 0
mjava-siku/src/main/java/com/malk/siku/controller/SikuController.java

@@ -115,6 +115,26 @@ public class SikuController {
         return McR.success();
     }
 
+    //每刻报销付款单完成回调
+    @PostMapping("/pay/callback")
+    public McR callback4(@RequestBody Map map){
+        log.info("每刻报销付款单完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack4(map);
+
+        return McR.success();
+    }
+
+    //每刻报销预付退回完成回调
+    @PostMapping("/repay/callback")
+    public McR callback5(@RequestBody Map map){
+        log.info("每刻报销预付退回完成回调:{}", JSONObject.toJSONString(map));
+
+        sikuService.invoiceWriteBack5(map);
+
+        return McR.success();
+    }
+
     //每刻预算冻结/释放
     @PostMapping("/updateBudget")
     public McR updateBudget(@RequestBody Map map){

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

@@ -24,4 +24,8 @@ public interface SikuService {
     McR checkBudgetAmt(Map map);
 
     void updateBudget(Map map);
+
+    void invoiceWriteBack4(Map map);
+
+    void invoiceWriteBack5(Map map);
 }

+ 509 - 44
mjava-siku/src/main/java/com/malk/siku/service/impl/SikuServiceImpl.java

@@ -262,6 +262,7 @@ public class SikuServiceImpl implements SikuService {
             //发票开具成功后回调
             String bizCode = UtilMap.getString(bizData, "bizCode");//发票号码
             String invoiceNumber = UtilMap.getString(bizData, "invoiceNumber");//发票号码
+            long issueDate = UtilMap.getLong(bizData, "issueDate");//开票日期
             String pdfUrl = UtilMap.getString(bizData, "pdfUrl");//pdf文件下载地址
             String downloadPageUrl = UtilMap.getString(bizData, "downloadPageUrl");//发票下载页面链接
             List<Map> detailItems = (List<Map>) UtilMap.getList(bizData, "detailItems");
@@ -272,6 +273,7 @@ public class SikuServiceImpl implements SikuService {
             Map updateFormData = new HashMap();
             updateFormData.put("radioField_mkxripcc","开票成功");
             updateFormData.put("textField_mkxripc6",invoiceNumber);
+            updateFormData.put("dateField_mnfpbwpd",issueDate);
             updateFormData.put("textField_mm3aixk0",downloadPageUrl);
             updateFormData.put("textareaField_mmlzqvn0","");
 
@@ -700,6 +702,8 @@ public class SikuServiceImpl implements SikuService {
 
         List<Map> invoiceTitles = new ArrayList<>();
 
+        List<Map> accounts = new ArrayList<>();
+
         List<Map> invoiceList = UtilMap.getList(formData, "tableField_mn496ozf");
         for (Map invoice : invoiceList) {
             Map invoiceTitle = new HashMap();
@@ -709,9 +713,17 @@ public class SikuServiceImpl implements SikuService {
             invoiceTitle.put("bankBranchName",UtilMap.getString(invoice,"textField_mkddjwyt"));//开户行
             invoiceTitle.put("account",UtilMap.getString(invoice,"textField_mkddjwyu"));//银行账户
             invoiceTitles.add(invoiceTitle);
+
+            Map account = new HashMap();
+            account.put("paymentType","BANK");//账户类型,
+            account.put("bankAcctName",UtilMap.getString(invoice,"textField_mkddjwyr"));//账户名
+            account.put("bankAcctNumber",UtilMap.getString(invoice,"textField_mkddjwyu"));//银行对应银行卡号
+            account.put("bankName",UtilMap.getString(invoice,"textField_mkddjwyt"));//银行名称
+            accounts.add(account);
         }
 
-        customerObj.put("invoiceTitles",invoiceTitles);//发票抬头列表
+        customerObj.put("invoiceTitles",invoiceTitles);//账户信息
+        customerObj.put("accounts",accounts);//账户信息
 
         MkYpUtil.saveClient(Arrays.asList(customerObj));
 
@@ -725,6 +737,12 @@ public class SikuServiceImpl implements SikuService {
 
         Map bizData = UtilMap.getMap(calloutParams, "bizData");
 
+        long verifyDate = UtilMap.getLong(bizData, "verifyDate");//核销日期
+
+        List<Map> upStreamItemList = UtilMap.getList(bizData, "upStreamItemList");//主核销方核销明细
+
+        Double totalVerifyAmount = UtilMap.getDouble(upStreamItemList.get(0), "totalVerifyAmount");//本次核销金额
+
         List<Map> relatedDocuments = UtilMap.getList(bizData, "relatedDocuments");
 
         for (Map relatedDocument : relatedDocuments) {
@@ -733,6 +751,7 @@ public class SikuServiceImpl implements SikuService {
             if ("RECEIVABLE_AR".equals(formType)){
                 String bizCode = UtilMap.getString(relatedDocument, "bizCode");
 
+
                 //应收单查询
                 Map body = new HashMap();
                 body.put("bizCodes",Arrays.asList(bizCode));
@@ -754,9 +773,14 @@ public class SikuServiceImpl implements SikuService {
 
                 String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");
 
+                Map updateFormData = new HashMap();
+                updateFormData.put("numberField_ml8t9c4u",receivedAmount);//已收金额
+                updateFormData.put("dateField_mnfpbwpe",verifyDate);//核销日期
+                updateFormData.put("numberField_mngxcnih",totalVerifyAmount);//本次核销金额
+
                 ydClient.operateData(YDParam.builder()
                         .formInstanceId(formInstanceId)
-                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("numberField_ml8t9c4u",receivedAmount)))
+                        .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                         .build(), YDConf.FORM_OPERATION.update);
 
                 return;
@@ -771,35 +795,69 @@ public class SikuServiceImpl implements SikuService {
     public void invoiceWriteBack3(Map map) {
         String formCode = UtilMap.getString(map, "formCode");
 
-        String operation = UtilMap.getString(map, "operation");
+        if (!formCode.contains("需求") && !formCode.contains("采购")){
+            //判断是否为核销报销单
+            Map formData = UtilMap.getMap(map, "formData");
 
-        if ("FORM_COMPLETE".equals(operation)){
-            //完成
-        }else if ("FORM_REJECT".equals(operation)){
-            //驳回
+            Map expenseList = UtilMap.getMap(formData, "expenseList");
+
+            List<Map> expenseValueList = UtilMap.getList(expenseList, "value");
+
+            for (Map expenseValue : expenseValueList) {
+                Map deductionList = UtilMap.getMap(expenseValue, "deductionList");//当前对公费用核销的数据(当前到票核销场景核销了哪些“预付未到票”记录)
+
+                List<Map> deductionValueList = UtilMap.getList(deductionList, "value");
+
+                Map deductionValue = deductionValueList.get(0);
+
+                Double deductionAmount = UtilMap.getDouble(deductionValue, "deductionAmount");//核销金额
+                String targetFormCode = UtilMap.getString(deductionValue, "targetFormCode");//核销报销单编号
+
+                if (targetFormCode.contains("需求") || targetFormCode.contains("采购")){
+                    //更新宜搭核销金额
+                    updateYdDeduction(targetFormCode,deductionAmount);
+                }
+            }
+
+            return;
         }
 
-        String[] split = formCode.split("-");
+        Map reimburseDetailInfo = MkBxUtil.reimburseDetailInfo(formCode);
 
-        String bh = split[0];//采购需求编号/直接采购单编号
-        int index = Integer.parseInt(split[1]);//子表索引
+        Boolean installment = UtilMap.getBoolean(reimburseDetailInfo, "installment");//是否使用分期付款
 
-        Map formData = UtilMap.getMap(map, "formData");
+        Boolean firstPeriodPayment = UtilMap.getBoolean(reimburseDetailInfo, "firstPeriodPayment");//分期情况下首期是否随本单支付
 
-        Map baseAmount = UtilMap.getMap(formData, "baseAmount");
+        double amt = 0;
 
-        Map value = UtilMap.getMap(baseAmount, "value");
+        if (installment){
+            if (firstPeriodPayment){
+                List<Map> collectionSchedule = UtilMap.getList(reimburseDetailInfo, "collectionSchedule");
 
-        String text = UtilMap.getString(value, "text");
+                Map collectionAmount = UtilMap.getMap(collectionSchedule.get(0), "collectionAmount");
+
+                amt = UtilMap.getDouble(collectionAmount,"amount");
+            }else {
+                return;
+            }
+        }else {
+            amt = UtilMap.getDouble(reimburseDetailInfo, "paymentAmount");//应付金额
+        }
+
+        String[] split = formCode.split("-");
+
+        String bh = split[0];//采购需求编号/直接采购单编号
+        int index = Integer.parseInt(split[1]);//子表索引
 
-        double amt = Double.parseDouble(text);
+        Map updateFormData = new HashMap();
+        List<Map> updateDetailList = new ArrayList<>();
 
         if (formCode.contains("需求")){
             //采购需求&结算
             List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                     .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
                     .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
-                    .build(), YDConf.FORM_QUERY.retrieve_list).getData();
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();
 
             String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");
 
@@ -811,58 +869,61 @@ public class SikuServiceImpl implements SikuService {
                 List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");
 
                 for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
                     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","全部付款");
+                            detailMap.put("selectField_mmvhqm0p","全部付款");
                         }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
-                            detail.put("selectField_mmvhqm0p","部分付款");
+                            detailMap.put("selectField_mmvhqm0p","部分付款");
                         }
 
-                        detail.put("numberField_mmvqom6l",yfkje + amt);
-
-                        break;
+                        detailMap.put("numberField_mmvqom6l",yfkje + amt);
                     }
+                    updateDetailList.add(detailMap);
                 }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
             }else {
                 List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
 
                 for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
                     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","全部付款");
+                            detailMap.put("selectField_mkkmij6a","全部付款");
                         }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
-                            detail.put("selectField_mkkmij6a","部分付款");
+                            detailMap.put("selectField_mkkmij6a","部分付款");
                         }
 
-                        detail.put("numberField_mmvqom6l",yfkje + amt);
-
-                        break;
+                        detailMap.put("numberField_mmvqs9h6",yfkje + amt);
                     }
+                    updateDetailList.add(detailMap);
                 }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
             }
 
             Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
 
-            ydFormData.put("numberField_mkf2qumf",yzf + amt);
+            updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
+            updateFormData.put("numberField_mnibjld0",amt);//最新支付金额
 
             ydClient.operateData(YDParam.builder()
                     .formInstanceId(formInstanceId)
-                    .updateFormDataJson(JSONObject.toJSONString(ydFormData))
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
                     .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", bh)))
-                    .build(), YDConf.FORM_QUERY.retrieve_list).getData();
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();
 
             String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");
 
@@ -874,56 +935,164 @@ public class SikuServiceImpl implements SikuService {
                 List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");
 
                 for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
                     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","全部付款");
+                            detailMap.put("selectField_mmvhtdy0","全部付款");
                         }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
-                            detail.put("selectField_mmvhtdy0","部分付款");
+                            detailMap.put("selectField_mmvhtdy0","部分付款");
                         }
 
-                        detail.put("numberField_mmvqom6k",yfkje + amt);
-
-                        break;
+                        detailMap.put("numberField_mmvqom6k",yfkje + amt);
                     }
+                    updateDetailList.add(detailMap);
                 }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
             }else {
                 List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
 
                 for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
                     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","全部付款");
+                            detailMap.put("selectField_mkkmij6a","全部付款");
                         }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
-                            detail.put("selectField_mkkmij6a","部分付款");
+                            detailMap.put("selectField_mkkmij6a","部分付款");
                         }
 
-                        detail.put("numberField_mmvqom6l",yfkje + amt);
-
-                        break;
+                        detailMap.put("numberField_mmvqom6l",yfkje + amt);
                     }
+                    updateDetailList.add(detailMap);
                 }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
             }
-
             Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
 
-            ydFormData.put("numberField_mkf2qumf",yzf + amt);
+            updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
+            updateFormData.put("numberField_mnibjld0",amt);//最新支付金额
+
 
             ydClient.operateData(YDParam.builder()
                     .formInstanceId(formInstanceId)
-                    .updateFormDataJson(JSONObject.toJSONString(ydFormData))
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
                     .build(), YDConf.FORM_OPERATION.update);
         }
 
     }
 
+    //更新宜搭采购已核销金额
+    private void updateYdDeduction(String formCode, Double deductionAmount) {
+        String[] split = formCode.split("-");
+        String bh = split[0];
+        int index = Integer.parseInt(split[1]);
+
+        Map updateFormData = new HashMap();
+        List<Map> updateDetailList = new ArrayList<>();
+
+        if (formCode.contains("需求")){
+            //采购需求&结算
+            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
+                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatky8");//已核销金额
+
+                        detailMap.put("numberField_mniatky8",yhxje + deductionAmount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatkya");//已核销金额
+
+                        detailMap.put("numberField_mniatkya",yhxje + deductionAmount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
+            }
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
+                    .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", bh)))
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatky8");//已核销金额
+
+                        detailMap.put("numberField_mniatky8",yhxje + deductionAmount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatkya");//已核销金额
+
+                        detailMap.put("numberField_mniatkya",yhxje + deductionAmount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
+            }
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+    }
+
     @Override
     public McR saveBxReimbursement2(Map map) {
         String formInstId = UtilMap.getString(map, "formInstId");
@@ -1270,6 +1439,302 @@ public class SikuServiceImpl implements SikuService {
 
     }
 
+    @Async
+    @Override
+    public void invoiceWriteBack4(Map map) {
+        String formCode = UtilMap.getString(map, "formCode");//付款单编号
+
+        //查询付款单详情
+        Map paymentDetailInfo = MkBxUtil.paymentDetailInfo(formCode);
+
+        String reimburseFormSubTypeBizCode = UtilMap.getString(paymentDetailInfo, "reimburseFormSubTypeBizCode");//关联的报销单的单据小类编码
+
+        //项目支付单(对公)
+        if ("FT208629766551519240".equals(reimburseFormSubTypeBizCode)){
+            String reimburseCode = UtilMap.getString(paymentDetailInfo, "reimburseCode");
+
+            //宜搭推送的项目支付单编号  格式:流水号-index
+            if (reimburseCode.contains("采购") || reimburseCode.contains("需求")){
+                String[] split = reimburseCode.split("-");
+
+                String ydFormCode = split[0];
+                int index = Integer.parseInt(split[1]);
+
+                Map approvedAmount = UtilMap.getMap(paymentDetailInfo, "approvedAmount");
+                Double amt = UtilMap.getDouble(approvedAmount, "amount");//审批通过金额
+
+                long settledAt = UtilMap.getLong(paymentDetailInfo, "settledAt");//支付时间
+
+                Map updateFormData = new HashMap();
+                List<Map> updateDetailList = new ArrayList<>();
+
+                if (reimburseCode.contains("需求")){
+                    //采购需求&结算
+                    List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
+                            .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
+                            .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", ydFormCode)))
+                            .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                            Map detailMap = new HashMap();
+                            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){
+                                    detailMap.put("selectField_mmvhqm0p","全部付款");
+                                }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
+                                    detailMap.put("selectField_mmvhqm0p","部分付款");
+                                }
+
+                                detailMap.put("numberField_mmvqom6l",yfkje + amt);
+                                detailMap.put("dateField_mnh6e4zy",settledAt);
+                            }
+                            updateDetailList.add(detailMap);
+                        }
+                        updateFormData.put("tableField_mkkmij56",updateDetailList);
+                    }else {
+                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                        for (Map detail : detailList) {
+                            Map detailMap = new HashMap();
+                            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)){
+                                    detailMap.put("selectField_mkkmij6a","部分付款");
+                                }
+
+                                detailMap.put("numberField_mmvqs9h6",yfkje + amt);
+                                detailMap.put("dateField_mnh6e4zy",settledAt);
+                            }
+                            updateDetailList.add(detailMap);
+                        }
+                        updateFormData.put("tableField_mkkmij61",updateDetailList);
+                    }
+
+                    Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
+
+                    ydFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
+                    ydFormData.put("numberField_mnibjld0",amt);//最新支付金额
+
+                    ydClient.operateData(YDParam.builder()
+                            .formInstanceId(formInstanceId)
+                            .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", ydFormCode)))
+                            .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                            Map detailMap = new HashMap();
+                            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){
+                                    detailMap.put("selectField_mmvhtdy0","全部付款");
+                                }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
+                                    detailMap.put("selectField_mmvhtdy0","部分付款");
+                                }
+
+                                detailMap.put("numberField_mmvqom6k",yfkje + amt);
+                                detailMap.put("dateField_mnh6e4zy",settledAt);
+                            }
+                            updateDetailList.add(detailMap);
+                        }
+                        updateFormData.put("tableField_mkkmij56",updateDetailList);
+                    }else {
+                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                        for (Map detail : detailList) {
+                            Map detailMap = new HashMap();
+                            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){
+                                    detailMap.put("selectField_mkkmij6a","全部付款");
+                                }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
+                                    detailMap.put("selectField_mkkmij6a","部分付款");
+                                }
+
+                                detailMap.put("numberField_mmvqom6l",yfkje + amt);
+                                detailMap.put("dateField_mnh6e4zy",settledAt);
+                            }
+                            updateDetailList.add(detailMap);
+                        }
+                        updateFormData.put("tableField_mkkmij61",updateDetailList);
+                    }
+
+                    Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付
+
+                    updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
+                    updateFormData.put("numberField_mnibjld0",amt);//最新支付金额
+
+                    ydClient.operateData(YDParam.builder()
+                            .formInstanceId(formInstanceId)
+                            .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                            .build(), YDConf.FORM_OPERATION.update);
+                }
+            }
+        }
+    }
+
+    @Async
+    @Override
+    public void invoiceWriteBack5(Map map) {
+        String formCode = UtilMap.getString(map, "formCode");
+
+        Map repayDetailInfo = MkBxUtil.repayDetailInfo(formCode);
+
+        Map repayAmount = UtilMap.getMap(repayDetailInfo, "repayAmount");
+
+        Double amount = UtilMap.getDouble(repayAmount, "amount");//还款金额
+
+        List<Map> returnDeductions = UtilMap.getList(repayDetailInfo, "returnDeductions");
+
+        for (Map returnDeduction : returnDeductions) {
+            String recordFormCode = UtilMap.getString(returnDeduction, "recordFormCode");
+
+            if (recordFormCode.contains("采购") || recordFormCode.contains("需求")){
+                updateYdRepay(recordFormCode,amount);
+            }
+
+        }
+    }
+
+    //更新宜搭采购已退回金额
+    private void updateYdRepay(String formCode, Double amount) {
+        String[] split = formCode.split("-");
+        String bh = split[0];
+        int index = Integer.parseInt(split[1]);
+
+        Map updateFormData = new HashMap();
+        List<Map> updateDetailList = new ArrayList<>();
+
+        if (formCode.contains("需求")){
+            //采购需求&结算
+            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
+                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
+                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额
+
+                        detailMap.put("numberField_mn4g182f",ythje + amount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额
+
+                        detailMap.put("numberField_mn4g182g",ythje + amount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
+            }
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
+                    .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", bh)))
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).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) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
+                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额
+
+                        detailMap.put("numberField_mn4g182f",ythje + amount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij56",updateDetailList);
+            }else {
+                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");
+
+                for (Map detail : detailList) {
+                    Map detailMap = new HashMap();
+                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
+                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额
+
+                        detailMap.put("numberField_mn4g182g",ythje + amount);
+                    }
+                    updateDetailList.add(detailMap);
+                }
+                updateFormData.put("tableField_mkkmij61",updateDetailList);
+            }
+
+            ydClient.operateData(YDParam.builder()
+                    .formInstanceId(formInstanceId)
+                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
+                    .useLatestVersion(true)
+                    .build(), YDConf.FORM_OPERATION.update);
+        }
+
+    }
+
     //文件下载到本地
     private void downloadFile(String downloadUri,String downloadPath){
         try {

+ 32 - 0
mjava-siku/src/main/java/com/malk/siku/utils/MkBxUtil.java

@@ -181,6 +181,38 @@ public class MkBxUtil {
         return result;
     }
 
+    //付款单详情
+    public static Map paymentDetailInfo(String formCode){
+        Map result = (Map) JSONObject.parse(UtilHttp.doGet("https://" + host + "/api/openapi/payment/detailInfo/" + formCode, MkBxUtil.initTokenHeader(), (Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        return data;
+    }
+
+    //报销单详情
+    public static Map reimburseDetailInfo(String formCode){
+        Map result = (Map) JSONObject.parse(UtilHttp.doGet("https://" + host + "/api/openapi/form/reimburse/" + formCode, MkBxUtil.initTokenHeader(), (Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        return data;
+    }
+
+    //还款单详情
+    public static Map repayDetailInfo(String formCode){
+        Map result = (Map) JSONObject.parse(UtilHttp.doGet("https://" + host + "/api/openapi/form/repayment/" + formCode, MkBxUtil.initTokenHeader(), (Map) null));
+
+        log.info("Result:{}",result);
+
+        Map data = UtilMap.getMap(result, "data");
+
+        return data;
+    }
 
     private static String getSecret(String appCode, String appSecret, long timeMillis){
         log.info("time:{}",timeMillis);

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

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

+ 59 - 0
mjava-zhiwei/src/main/java/com/malk/zhiwei/schedule/ScheduleTask.java

@@ -2,12 +2,15 @@ package com.malk.zhiwei.schedule;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.kingdee.bos.webapi.sdk.K3CloudApi;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.service.aliwork.YDClient;
 import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilMap;
 import com.malk.zhiwei.service.ZwService;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -15,6 +18,8 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.util.HashMap;
 import java.util.List;
@@ -27,6 +32,7 @@ import java.util.Map;
 @Configuration
 @EnableScheduling
 @ConditionalOnProperty(name = {"enable.scheduling"})
+@RestController
 
 public class ScheduleTask {
 
@@ -94,5 +100,58 @@ public class ScheduleTask {
                 .build(), YDConf.FORM_OPERATION.update);
     }
 
+    //产品信息同步
+    @Scheduled(cron = "0 0 1 * * ?")
+    @PostMapping("/product")
+    public void product() throws JsonProcessingException {
+        zwService.product();
+    }
+
+    //销售订单同步
+    @Scheduled(cron = "0 15 1 * * ?")
+    @PostMapping("/purchaseOrder")
+    public void purchaseOrder() throws JsonProcessingException {
+        zwService.purchaseOrder();
+    }
+
+    //出库单(发货通知单)
+    @SneakyThrows
+    @Scheduled(cron = "0 30 1 * * ?")
+    @PostMapping("/deliveryOrder")
+    public void deliveryOrder(){
+        zwService.deliveryOrder();
+    }
+
+    //退货单
+    @SneakyThrows
+    @Scheduled(cron = "0 45 1 * * ?")
+    @PostMapping("/returnForm")
+    public void returnForm(){
+        zwService.returnForm();
+    }
+
+    //补货单
+    @SneakyThrows
+    @Scheduled(cron = "0 0 2 * * ?")
+    @PostMapping("/replenishmentOrder")
+    public void replenishmentOrder(){
+        zwService.replenishmentOrder();
+    }
+
+    //开票单
+    @SneakyThrows
+    @Scheduled(cron = "0 15 2 * * ?")
+    @PostMapping("/invoice")
+    public void invoice(){
+        zwService.invoice();
+    }
+
+    //应收单
+    @SneakyThrows
+    @Scheduled(cron = "0 30 2 * * ?")
+    @PostMapping("/receivableNote")
+    public void receivableNote(){
+        zwService.receivableNote();
+    }
 
 }

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

@@ -1,6 +1,7 @@
 package com.malk.zhiwei.service;
 
 import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JacksonException;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.malk.server.common.McR;
 
@@ -19,4 +20,25 @@ public interface ZwService {
     //客户保存接口
     McR savecustomer(String instanceId) throws JsonProcessingException;
 
+    //同步产品信息
+    void product() throws JsonProcessingException;
+
+    //同步销售订单
+    void purchaseOrder() throws JsonProcessingException;
+
+    //出库单(发货通知单)
+    void deliveryOrder() throws JsonProcessingException;
+
+    //退货单
+    void returnForm() throws JsonProcessingException;
+
+    //补货单
+    void replenishmentOrder() throws JsonProcessingException;
+
+    //开票单
+    void invoice() throws JsonProcessingException;
+
+    //应收单
+    void receivableNote() throws JsonProcessingException;
+
 }

+ 639 - 1
mjava-zhiwei/src/main/java/com/malk/zhiwei/service/impl/ZwServiceImpl.java

@@ -17,6 +17,7 @@ import com.malk.service.aliwork.YDClient;
 import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilMap;
 import com.malk.zhiwei.config.KDWebApiConf;
+import com.malk.zhiwei.entity.BillQuery;
 import com.malk.zhiwei.entity.CustomerModel;
 import com.malk.zhiwei.entity.FNumber;
 import com.malk.zhiwei.service.ZwService;
@@ -223,7 +224,7 @@ public class ZwServiceImpl implements ZwService {
         FNumber xsbm = new FNumber(data.get("textField_mnfujcac").toString());//销售部门
         FNumber xsy = new FNumber(data.get("textField_mnfujcad").toString());//销售员
         String kh = data.get("textField_lqanqe6j").toString();// 客户
-        Object empObj = data.get("employeeField_mnft99uj");
+        Object empObj = data.get("employeeField_lqanqe6n");
         String ywy = "";//业务员
         if (empObj instanceof JSONArray) {
             JSONArray empArray = (JSONArray) empObj;
@@ -238,6 +239,643 @@ public class ZwServiceImpl implements ZwService {
         return saveToAudit("BD_Customer", customerModel);
     }
 
+    @SneakyThrows
+    @Override
+    public void product() {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("BD_MATERIAL");//产品信息
+        //编码 名称 规格型号 旧物料编码 物料分组 物料属性 基本单位 长 宽 高 体积 面积 密度 标准工时
+        billQuery.setFieldKeys("FNumber,FName,FSpecification,FOldNumber,FMaterialGroup,FErpClsID,FBaseUnitId,FLENGTH,FWIDTH,FHEIGHT,FVOLUME,F_UNW_Qty_r03,F_UNW_Qty_6yt,FPerUnitStandHour");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+        // 遍历每条物料记录
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+
+            // 取出各个字段(注意类型转换)
+            String number = item.getString("FNumber");
+            String name = item.getString("FName");
+            String spec = item.getString("FSpecification");
+            String oldNumber = item.getString("FOldNumber");
+            Integer materialGroup = item.getInteger("FMaterialGroup");
+            String erpClsId = item.getString("FErpClsID");
+            Integer baseUnitId = item.getInteger("FBaseUnitId");
+            Double length = item.getDouble("FLENGTH");
+            Double width = item.getDouble("FWIDTH");
+            Double height = item.getDouble("FHEIGHT");
+            Double volume = item.getDouble("FVOLUME");
+            Double area = item.getDouble("F_UNW_Qty_r03");
+            Double density = item.getDouble("F_UNW_Qty_6yt");
+            Double standHour = item.getDouble("FPerUnitStandHour");
+            //TODO:向宜搭插入数据
+            String sc = "textField_l43jpnsf, textField_mcijetil, textField_l43jpnsh, textField_mnhe1ryw, textField_mnhe1rz1, textField_mnhe1rz2, textField_mnhe1rz7, textField_mnhe1rzm," +
+                    " textField_mnhe1rzg, textField_mnhe1rzh, textField_mnhe1rzi, textField_mnhe1rzj, textField_mnhe1rzk, textField_mnhe1rzl";//名称 编码 规格 旧编码 物料分组 物料属性 基本单位 标准工时 长 宽 高 体积 面积 密度
+            List<Map> conditions = Arrays.asList(  YDConf.searchCondition_TextFiled("textField_mcijetil", number, "eq"));
+            Map formData = UtilMap.map(sc,name,number,spec,oldNumber,materialGroup,erpClsId,baseUnitId,length,width,height,volume,area,density,standHour);
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-4A7B1A62CCFC4D758AB98ADE3F97D40COYO2")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(formData))
+                    .build(),YDConf.FORM_OPERATION.upsert);
+
+        }
+        log.info("产品信息已同步");
+    }
+
+    @SneakyThrows
+    @Override
+    public void purchaseOrder(){
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("SAL_SaleOrder");//销售订单
+        //[主表] FSaleOrgId销售组织 FSaleDeptId销售部门 FBillNo单据编号  FCustId客户 F_UNW_Text_ct1客户订单号 FSettleCurrId结算币别 FSalerId销售员 FDate日期 FRecConditionId收款条件
+        //[明细表] FMaterialId物料编码 FMaterialName物料名称 FMaterialModel规格型号 FMapId客户物料编码 F_UNW_BaseProperty_uow客户物料规格 FUnitID销售单位 FQty销售数量 FPriceUnitQty计价数量 FPrice单价 FTaxPrice含税单价 FEntryTaxRate税率 FEntryTaxAmount税额 FAmount金额 FAllAmount价税合计 FDeliveryDate要货日期 FSettleOrgIds结算组织 FIsFree是否赠品
+        billQuery.setFieldKeys("FSaleOrgId.FName,FSaleDeptId.FName,FBillNo,FCustId.FName,F_UNW_Text_ct1,FSettleCurrId.FName,FSalerId.FName,FDate,FRecConditionId.FName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FMapId.FNumber,F_UNW_BaseProperty_uow,FUnitID.FName,FQty,FPriceUnitQty,FPrice,FTaxPrice,FEntryTaxRate,FEntryTaxAmount,FAmount,FAllAmount,FDeliveryDate,FSettleOrgIds.FName,FIsFree");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            String billNo = item.getString("FBillNo");
+            groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+        }
+
+        // 组装最终结果
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0);
+
+            // 主表 Map
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mniksrqa", firstRow.getString("FBillNo"));//单据编号
+            orderMap.put("textField_mniksrq4", firstRow.getString("FSaleOrgId.FName")); // 销售组织
+            orderMap.put("textField_mniksrq5", firstRow.getString("FSaleDeptId.FName")); // 销售组织
+            orderMap.put("textField_mniksrqb", firstRow.getString("FCustId.FName")); // 客户
+            orderMap.put("textField_mniksrqe", firstRow.getString("F_UNW_Text_ct1")); // 客户订单号
+            orderMap.put("textField_mniksrqf", firstRow.getString("FSettleCurrId.FName")); // 结算币别
+            orderMap.put("textField_mniksrqk", firstRow.getString("FSalerId.FName")); // 销售员
+            String fDateRaw = firstRow.getString("FDate");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mniksrql", formattedDate); // 日期
+            orderMap.put("textField_mniksrqm", firstRow.getString("FRecConditionId.FName")); // 收款条件
+
+
+            // 明细数组
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mniksrqo", row.getString("FMaterialId.FNumber"));//物料编码
+                detailMap.put("textField_mniksrqp", row.getString("FMaterialName"));//物料名称
+                detailMap.put("textField_mniksrqq", row.getString("FMaterialModel"));//规格型号
+                detailMap.put("textField_mniksrqr", row.getString("FMapId.FNumber"));//客户物料编码
+                detailMap.put("textField_mniksrqs", row.getString("F_UNW_BaseProperty_uow"));//客户物料规格
+                detailMap.put("textField_mniksrqt", row.getString("FUnitID.FName"));//销售单位
+                detailMap.put("numberField_mniksrqv", row.getString("FQty"));//销售数量
+                detailMap.put("numberField_mniksrqw", row.getString("FPriceUnitQty"));//计价数量
+                detailMap.put("numberField_mniksrqx", row.getString("FPrice"));//单价
+                detailMap.put("numberField_mniksrqy", row.getString("FTaxPrice"));//含税单价
+                detailMap.put("numberField_mniksrqz", row.getString("FEntryTaxRate"));//税率
+                detailMap.put("numberField_mniksrr0", row.getString("FEntryTaxAmount"));//税额
+                detailMap.put("numberField_mniksrr1", row.getString("FAmount"));//金额
+                detailMap.put("numberField_mniksrr2", row.getString("FAllAmount"));//价税合计
+                String deliveryRaw = row.getString("FDeliveryDate");
+                String formattedDelivery = (deliveryRaw != null && deliveryRaw.contains("T")) ? deliveryRaw.split("T")[0] : deliveryRaw;
+                detailMap.put("textField_mniksrr3", formattedDelivery);//要货日期
+                detailMap.put("textField_mniksrr4", row.getString("FSettleOrgIds.FName"));//结算组织
+                detailMap.put("radioField_mniksrr6", row.getString("FAmount").equals("true") ? "是" : "否");//是否赠品
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mniksrqn", details);
+
+            /*写入宜搭*/
+            List<Map> conditions = Arrays.asList(  YDConf.searchCondition_TextFiled("textField_mniksrqa", firstRow.getString("FBillNo"), "eq"));
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-7B112A3733EC412FB27D56D8AC242E5BHIL4")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("销售订单已同步");
+    }
+
+    @SneakyThrows
+    @Override
+    public void deliveryOrder() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("SAL_DELIVERYNOTICE");//发货通知单
+        //[主表]  FBillNo单据编号 FDate日期 FSettleCurrId结算币别  FSaleOrgId销售组织 FSaleDeptId销售部门   FSalesManID销售员   F_UNW_Base_tr7发货客户  F_UNW_CheckBox_xjs是否委外
+        //[明细表] FCustMatName客户物料名称  FCustMatID客户物料编码  FMaterialID物料编码  F_UNW_BaseProperty_3tm客户物料规格型号  FMaterialName物料名称  FMateriaModel型号规格  FUnitID销售单位  FQty销售数量  FIsFree是否赠品  FDeliveryDate要货日期  FDeliveryLoc交货地点 F_UNW_Text_8dq客户订单号
+        billQuery.setFieldKeys("FBillNo,FDate,FSettleCurrId.FName,FSaleOrgId.FName,FSaleDeptId.FName,FSalesManID.FName,F_UNW_Base_tr7.FName,F_UNW_CheckBox_xjs,FCustMatName,FCustMatID.FNumber,FMaterialID.FNumber,F_UNW_BaseProperty_3tm,FMaterialName,FMateriaModel,FUnitID.FName,FQty,FIsFree,FDeliveryDate,FDeliveryLoc.FName,F_UNW_Text_8dq");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            String billNo = item.getString("FBillNo");
+            groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+        }
+
+        // 组装最终结果
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0);
+
+            // 主表 Map
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mnj0cqqp", firstRow.getString("FBillNo"));//单据编号
+            String fDateRaw = firstRow.getString("FDate");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mnj0cqqq", formattedDate); // 日期
+            orderMap.put("textField_mnj0cqqr", firstRow.getString("FSettleCurrId.FName")); // 结算币别
+            orderMap.put("textField_mnj0cqqw", firstRow.getString("FSaleOrgId.FName")); // 销售组织
+            orderMap.put("textField_mnj0cqqx", firstRow.getString("FSaleDeptId.FName")); // 销售部门
+            orderMap.put("textField_mnj0cqqy", firstRow.getString("FSalesManID.FName")); // 销售员
+            orderMap.put("textField_mnj0cqr3", firstRow.getString("F_UNW_Base_tr7.FName")); // 发货客户
+            orderMap.put("radioField_mnj0cqr4", firstRow.getString("F_UNW_CheckBox_xjs").equals("true") ? "是" : "否" ); // 是否委外
+
+
+            // 明细数组
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mnj0cqr6", row.getString("FCustMatName"));//客户物料名称
+                detailMap.put("textField_mnj0cqr7", row.getString("FCustMatID.FNumber"));//客户物料编码
+                detailMap.put("textField_mnj0cqr8", row.getString("FMaterialID.FNumber"));//物料编码
+                detailMap.put("textField_mnj0cqr9", row.getString("F_UNW_BaseProperty_3tm"));//客户物料规格型号
+                detailMap.put("textField_mnj0cqra", row.getString("FMaterialName"));//物料名称
+                detailMap.put("textField_mnj0cqrb", row.getString("FMateriaModel"));//规格型号
+                detailMap.put("textField_mnj0cqrc", row.getString("FUnitID.FName"));//销售单位
+                detailMap.put("numberField_mnj0cqrd", row.getString("FQty"));//销售数量
+                detailMap.put("radioField_mnj0cqre", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
+                String rawDeliveryDate = row.getString("FDeliveryDate");
+                String formattedDeliveryDate = rawDeliveryDate != null ? rawDeliveryDate.replace("T", " ") : null;
+                detailMap.put("textField_mnj0cqrf", formattedDeliveryDate);//要货日期
+                detailMap.put("textField_mnj0cqrg", row.getString("FDeliveryLoc.FName"));//交货地点
+                detailMap.put("textField_mnj0cqrh", row.getString("F_UNW_Text_8dq"));//客户订单号
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mnj0cqr5", details);
+
+            /*写入宜搭*/
+            List<Map> conditions = Arrays.asList(  YDConf.searchCondition_TextFiled("textField_mnj0cqqp", firstRow.getString("FBillNo"), "eq"));
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-50CEB72455534364BF9A97C8A49A3A46TBLI")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("发货通知单已同步");
+    }
+
+    @SneakyThrows
+    @Override
+    public void returnForm() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("SAL_RETURNSTOCK");//退货单
+        //[主表]  FBillNo单据编号 FDate日期 FRetcustId退货客户  FSettleCurrId结算币别  FSaleOrgId销售组织 FSaledeptid销售部门   FSalesManId销售员
+        //[明细表] FMapId客户物料编码  FMapName客户物料名称  FMaterialId物料编码  FMaterialName物料名称  FMaterialModel型号规格  FF100001厚度  FSalUnitID销售单位  FSalUnitQty销售数量  FIsFree是否赠品  FDeliveryDate退货日期  FReturnType退货类型  FPrice单价 FTaxPrice含税单价  FNote备注
+        billQuery.setFieldKeys("FBillNo,FDate,FRetcustId.FName,FSettleCurrId.FName,FSaleOrgId.FName,FSaledeptid.FName,FSalesManId.FName,FMapId.FNumber,FMapName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FAuxpropId.FF100001,FSalUnitID.FName,FSalUnitQty,FIsFree,FDeliveryDate,FReturnType.FDataValue,FPrice,FTaxPrice,FNote");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            String billNo = item.getString("FBillNo");
+            groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+        }
+
+        // 组装最终结果
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0);
+
+            // 主表 Map
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mnmru1xp", firstRow.getString("FBillNo"));//单据编号
+            String fDateRaw = firstRow.getString("FDate");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mnmru1xq", formattedDate); // 日期
+            orderMap.put("textField_mnmru1xr", firstRow.getString("FRetcustId.FName")); // 退货客户
+            orderMap.put("textField_mnmru1y0", firstRow.getString("FSettleCurrId.FName")); // 结算币别
+            orderMap.put("textField_mnmru1y1", firstRow.getString("FSaleOrgId.FName")); // 销售组织
+            orderMap.put("textField_mnmru1y2", firstRow.getString("FSaledeptid.FName")); // 销售部门
+            orderMap.put("textField_mnmru1y3", firstRow.getString("FSalesManId.FName")); // 销售员
+
+
+            // 明细数组
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mnmru1y9", row.getString("FMapId.FNumber"));//客户物料编码
+                detailMap.put("textField_mnmru1ya", row.getString("FMapName"));//客户物料名称
+                detailMap.put("textField_mnmru1yb", row.getString("FMaterialId.FNumber"));//物料编码
+                detailMap.put("textField_mnmru1yc", row.getString("FMaterialName"));//物料名称
+                detailMap.put("textField_mnmru1yd", row.getString("FMaterialModel"));//规格型号
+                detailMap.put("textField_mnmru1ye", row.getString("FAuxpropId.FF100001"));//厚度
+                detailMap.put("textField_mnmru1yf", row.getString("FSalUnitID.FName"));//销售单位
+                detailMap.put("numberField_mnmru1yg", row.getString("FSalUnitQty"));//销售数量
+                detailMap.put("radioField_mnmru1yh", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
+                String rawDeliveryDate = row.getString("FDeliveryDate");
+                String formattedDeliveryDate = rawDeliveryDate != null ? rawDeliveryDate.replace("T", " ") : null;
+                detailMap.put("textField_mnmru1yi", formattedDeliveryDate);//退货日期
+                detailMap.put("textField_mnmru1yj", row.getString("FReturnType.FDataValue"));//退货类型
+                detailMap.put("numberField_mnmru1yk", row.getString("FPrice"));//单价
+                detailMap.put("numberField_mnmru1yl", row.getString("FTaxPrice"));//含税单价
+                detailMap.put("textField_mnmru1ym", row.getString("FNote"));//备注
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mnmru1y8", details);
+
+            /*写入宜搭*/
+            List<Map> conditions = Arrays.asList(  YDConf.searchCondition_TextFiled("textField_mnmru1xp", firstRow.getString("FBillNo"), "eq"));
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-48ADB8AA7FEF4821929BFE8FE5B623E42OKY")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("退货单已同步");
+    }
+
+    @SneakyThrows
+    @Override
+    public void replenishmentOrder() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("SAL_SaleOrder"); // 销售订单
+        // 字段查询与销售订单一致,包含 FIsFree
+        billQuery.setFieldKeys("FSaleOrgId.FName,FSaleDeptId.FName,FBillNo,FCustId.FName,F_UNW_Text_ct1,FSettleCurrId.FName,FSalerId.FName,FDate,FRecConditionId.FName,FMaterialId.FNumber,FMaterialName,FMaterialModel,FMapId.FNumber,F_UNW_BaseProperty_uow,FUnitID.FName,FQty,FPriceUnitQty,FPrice,FTaxPrice,FEntryTaxRate,FEntryTaxAmount,FAmount,FAllAmount,FDeliveryDate,FSettleOrgIds.FName,FIsFree");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic", "FApproveDate", "265", 1, "", "", "0"));
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result = client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组,并过滤出赠品明细
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            // 判断是否赠品:注意金蝶返回的 FIsFree 可能是布尔值或字符串 "true"/"false"
+            boolean isFree = false;
+            Object freeObj = item.get("FIsFree");
+            if (freeObj instanceof Boolean) {
+                isFree = (Boolean) freeObj;
+            } else if (freeObj instanceof String) {
+                isFree = "true".equalsIgnoreCase((String) freeObj);
+            }
+            // 只处理赠品行
+            if (isFree) {
+                String billNo = item.getString("FBillNo");
+                groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+            }
+        }
+
+        // 组装最终结果(仅包含有赠品行明细的订单)
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0); // 取该订单的第一条赠品行(主表字段相同)
+
+            // 主表 Map
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mniksrqa", firstRow.getString("FBillNo")); // 单据编号
+            orderMap.put("textField_mniksrq4", firstRow.getString("FSaleOrgId.FName")); // 销售组织
+            orderMap.put("textField_mniksrq5", firstRow.getString("FSaleDeptId.FName")); // 销售部门
+            orderMap.put("textField_mniksrqb", firstRow.getString("FCustId.FName")); // 客户
+            orderMap.put("textField_mniksrqe", firstRow.getString("F_UNW_Text_ct1")); // 客户订单号
+            orderMap.put("textField_mniksrqf", firstRow.getString("FSettleCurrId.FName")); // 结算币别
+            orderMap.put("textField_mniksrqk", firstRow.getString("FSalerId.FName")); // 销售员
+            String fDateRaw = firstRow.getString("FDate");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mniksrql", formattedDate); // 日期
+            orderMap.put("textField_mniksrqm", firstRow.getString("FRecConditionId.FName")); // 收款条件
+
+            // 明细数组(仅包含赠品行)
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mniksrqo", row.getString("FMaterialId.FNumber")); // 物料编码
+                detailMap.put("textField_mniksrqp", row.getString("FMaterialName")); // 物料名称
+                detailMap.put("textField_mniksrqq", row.getString("FMaterialModel")); // 规格型号
+                detailMap.put("textField_mniksrqr", row.getString("FMapId.FNumber")); // 客户物料编码
+                detailMap.put("textField_mniksrqs", row.getString("F_UNW_BaseProperty_uow")); // 客户物料规格
+                detailMap.put("textField_mniksrqt", row.getString("FUnitID.FName")); // 销售单位
+                detailMap.put("numberField_mniksrqv", row.getString("FQty")); // 销售数量
+                detailMap.put("numberField_mniksrqw", row.getString("FPriceUnitQty")); // 计价数量
+                detailMap.put("numberField_mniksrqx", row.getString("FPrice")); // 单价
+                detailMap.put("numberField_mniksrqy", row.getString("FTaxPrice")); // 含税单价
+                detailMap.put("numberField_mniksrqz", row.getString("FEntryTaxRate")); // 税率
+                detailMap.put("numberField_mniksrr0", row.getString("FEntryTaxAmount")); // 税额
+                detailMap.put("numberField_mniksrr1", row.getString("FAmount")); // 金额
+                detailMap.put("numberField_mniksrr2", row.getString("FAllAmount")); // 价税合计
+                String deliveryRaw = row.getString("FDeliveryDate");
+                String formattedDelivery = (deliveryRaw != null && deliveryRaw.contains("T")) ? deliveryRaw.split("T")[0] : deliveryRaw;
+                detailMap.put("textField_mniksrr3", formattedDelivery); // 要货日期
+                detailMap.put("textField_mniksrr4", row.getString("FSettleOrgIds.FName")); // 结算组织
+                // 赠品标记:这里明细一定是赠品,直接设为"是"
+                detailMap.put("radioField_mniksrr6", "是");
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mniksrqn", details);
+
+            // 写入宜搭补货单表单
+            List<Map> conditions = Arrays.asList(
+                    YDConf.searchCondition_TextFiled("textField_mniksrqa", firstRow.getString("FBillNo"), "eq")
+            );
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-837E203B7DCA4B09A9618AA8F584CC45UDFX")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("补货单已同步,共 {} 个订单包含赠品明细", orderList.size());
+    }
+
+    @SneakyThrows
+    @Override
+    public void invoice() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("AR_receivable");//开票单
+        //[主表]  FBillTypeID单据类型  FCUSTOMERID客户  FSALEERID销售员  FSetAccountType立账类型  FBillNo单据编号  FCURRENCYID币别  FSETTLEORGID结算组织  FDATE业务日期  FENDDATE_H到期日  FDocumentStatus单据状态  FPayConditon收款条件  FSALEDEPTID销售部门  F_UNW_Text_u4s发票号
+        //[明细表] FMATERIALID 物料编码  FCustMatID客户物料编码  FCustMatName客户物料名称  F_UNW_BaseProperty_lad规格型号 FMaterialName物料名称  FPRICEUNITID计价单位  FPriceQty计价数量  FEntryTaxRate税率  FF100001厚度  FBASICUNITQTY计价基本数量  FLot批号  FORDERNUMBER销售订单号  FORDERENTRYSEQ销售订单行号  FSalQty销售数量  FSalUnitId销售单位  FIsFree是否赠品
+        billQuery.setFieldKeys("FBillTypeID.FName,FCUSTOMERID.FName,FSALEERID.FName,FSetAccountType,FBillNo,FCURRENCYID.FName,FSETTLEORGID.FName,FDATE,FENDDATE_H,FDocumentStatus,FPayConditon.FName,FSALEDEPTID.FName,F_UNW_Text_u4s,FMATERIALID.FNumber,FCustMatID.FNumber,FCustMatName,F_UNW_BaseProperty_lad,FMaterialName,FPRICEUNITID.FName,FPriceQty,FEntryTaxRate,FAuxpropId.FF100001,FBASICUNITQTY,FLot.FNumber,FORDERNUMBER,FORDERENTRYSEQ,FSalQty,FSalUnitId.FName,FIsFree");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0"));//审核日期在今天之前N天以后
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result=client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            String billNo = item.getString("FBillNo");
+            groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+        }
+
+        // 组装最终结果
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0);
+
+            // ========== 新增:检查发票号,无发票号则跳过 ==========
+            String invoiceNo = firstRow.getString("F_UNW_Text_u4s");
+            if (invoiceNo == null || invoiceNo.trim().isEmpty()) {
+                log.info("单据编号 {} 无发票号,跳过同步", firstRow.getString("FBillNo"));
+                continue;
+            }
+            // =================================================
+
+            // 主表 Map
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mno1zcb2", firstRow.getString("FBillTypeID.FName"));//单据类型
+            orderMap.put("textField_mno1zcb3", firstRow.getString("FCUSTOMERID.FName")); // 客户
+            orderMap.put("textField_mno1zcb4", firstRow.getString("FSALEERID.FName")); // 销售员
+            String FSetAccountType = "";
+            switch (firstRow.getString("FSetAccountType")){
+                case "1":
+                    FSetAccountType = "业务应收";break;
+                case "2":
+                    FSetAccountType = "暂估应收";break;
+                case "3":
+                    FSetAccountType = "财务应收";break;
+            }
+            orderMap.put("textField_mno1zcb5", FSetAccountType); // 立账类型
+            orderMap.put("textField_mno1zcbb", firstRow.getString("FBillNo")); // 单据编号
+            orderMap.put("textField_mno1zcbc", firstRow.getString("FCURRENCYID.FName")); // 币别
+            orderMap.put("textField_mno1zcbd", firstRow.getString("FSETTLEORGID.FName")); // 结算组织
+            String fDateRaw = firstRow.getString("FDATE");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mno1zcbe", formattedDate); // 业务日期
+            String fDateRaw_A = firstRow.getString("FENDDATE_H");
+            String formattedDate_A = (fDateRaw_A != null && fDateRaw_A.contains("T")) ? fDateRaw_A.split("T")[0] : fDateRaw_A;
+            orderMap.put("textField_mno1zcbk", formattedDate_A); // 到期日
+            orderMap.put("textField_mno1zcbl", firstRow.getString("FPayConditon.FName")); // 收款条件
+            String FDocumentStatus = "";
+            switch (firstRow.getString("FDocumentStatus")){
+                case "A":
+                    FDocumentStatus = "创建";break;
+                case "B":
+                    FDocumentStatus = "审核中";break;
+                case "C":
+                    FDocumentStatus = "已审核";break;
+                case "D":
+                    FDocumentStatus = "重新审核";break;
+                case "Z":
+                    FDocumentStatus = "暂存";break;
+            }
+            orderMap.put("textField_mno1zcbm", FDocumentStatus); // 单据状态
+            orderMap.put("textField_mno1zcbn", firstRow.getString("FSALEDEPTID.FName")); // 销售部门
+            orderMap.put("textField_mno1zcbt", invoiceNo); // 发票号(已确保非空)
+
+            // 明细数组
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mno1zcbv", row.getString("FMATERIALID.FNumber"));//物料编码
+                detailMap.put("textField_mno1zcbw", row.getString("FCustMatID.FNumber"));//客户物料编码
+                detailMap.put("textField_mno1zcbx", row.getString("FCustMatName"));//客户物料名称
+                detailMap.put("textField_mno1zcby", row.getString("F_UNW_BaseProperty_lad"));//规格型号
+                detailMap.put("textField_mno1zcbz", row.getString("FMaterialName"));//物料名称
+                detailMap.put("textField_mno1zcc0", row.getString("FPRICEUNITID.FName"));//计价单位
+                detailMap.put("numberField_mno1zcc2", row.getString("FPriceQty"));//计价数量
+                detailMap.put("numberField_mno1zcc3", row.getString("FEntryTaxRate"));//税率(%)
+                detailMap.put("textField_mno1zcc5", row.getString("FAuxpropId.FF100001"));//厚度
+                detailMap.put("numberField_mno1zcc6", row.getString("FBASICUNITQTY"));//计价基本数量
+                detailMap.put("textField_mno1zcc7", row.getString("FLot.FNumber"));//批号
+                detailMap.put("textField_mno1zcc8", row.getString("FORDERNUMBER"));//销售订单号
+                detailMap.put("textField_mno1zcc9", row.getString("FORDERENTRYSEQ"));//销售订单行号
+                detailMap.put("numberField_mno1zcca", row.getString("FSalQty"));//销售数量
+                detailMap.put("textField_mno1zccb", row.getString("FSalUnitId.FName"));//销售单位
+                detailMap.put("radioField_mno1zccc", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mno1zcbu", details);
+
+            /*写入宜搭*/
+            List<Map> conditions = Arrays.asList(YDConf.searchCondition_TextFiled("textField_mno1zcbb", firstRow.getString("FBillNo"), "eq"));
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-CEF87B7F64004AE1A1D9A2A3A8EC4986O1VK")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("开票单已同步");
+    }
+
+    @SneakyThrows
+    @Override
+    public void receivableNote() throws JsonProcessingException {
+        K3CloudApi client = new K3CloudApi(initIden());
+        int startRow = 0;
+        int limit = 2000;
+        BillQuery billQuery = new BillQuery();
+        billQuery.setFormId("AR_receivable"); // 应收单
+        billQuery.setFieldKeys("FBillTypeID.FName,FCUSTOMERID.FName,FSALEERID.FName,FSetAccountType,FBillNo,FCURRENCYID.FName,FSETTLEORGID.FName,FDATE,FENDDATE_H,FDocumentStatus,FPayConditon.FName,FSALEDEPTID.FName,F_UNW_Text_u4s,FMATERIALID.FNumber,FCustMatID.FNumber,FCustMatName,F_UNW_BaseProperty_lad,FMaterialName,FPRICEUNITID.FName,FPriceQty,FEntryTaxRate,FAuxpropId.FF100001,FBASICUNITQTY,FLot.FNumber,FORDERNUMBER,FORDERENTRYSEQ,FSalQty,FSalUnitId.FName,FIsFree");
+        List<Map> filterString = new ArrayList<>();
+        filterString.add(UtilMap.map("FieldName, Compare, Value, Left, Right, Logic","FApproveDate","265",1,"","","0")); // 审核日期条件
+        billQuery.setFilterString(filterString);
+        billQuery.setLimit(limit);
+        billQuery.setStartRow(startRow);
+        String result = client.billQuery(JSONObject.toJSONString(billQuery));
+        JSONArray jsonArray = JSONArray.parseArray(result);
+
+        // 按 FBillNo 分组
+        Map<String, List<JSONObject>> groupMap = new LinkedHashMap<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject item = jsonArray.getJSONObject(i);
+            String billNo = item.getString("FBillNo");
+            groupMap.computeIfAbsent(billNo, k -> new ArrayList<>()).add(item);
+        }
+
+        // 组装并同步到宜搭(应收单表单)
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Map.Entry<String, List<JSONObject>> entry : groupMap.entrySet()) {
+            List<JSONObject> rows = entry.getValue();
+            JSONObject firstRow = rows.get(0);
+
+            // 二次确认:发票号必须为空(有发票号的跳过)
+            String invoiceNo = firstRow.getString("F_UNW_Text_u4s");
+            if (invoiceNo != null && !invoiceNo.trim().isEmpty()) {
+                log.info("单据编号 {} 含有发票号,不符合应收单同步条件(需要无发票号),跳过", firstRow.getString("FBillNo"));
+                continue;
+            }
+
+            // 组装主表数据
+            Map<String, Object> orderMap = new LinkedHashMap<>();
+            orderMap.put("textField_mno1zcb2", firstRow.getString("FBillTypeID.FName"));      // 单据类型
+            orderMap.put("textField_mno1zcb3", firstRow.getString("FCUSTOMERID.FName"));     // 客户
+            orderMap.put("textField_mno1zcb4", firstRow.getString("FSALEERID.FName"));          // 销售员
+            // 立账类型转换
+            String FSetAccountType = "";
+            switch (firstRow.getString("FSetAccountType")){
+                case "1": FSetAccountType = "业务应收"; break;
+                case "2": FSetAccountType = "暂估应收"; break;
+                case "3": FSetAccountType = "财务应收"; break;
+            }
+            orderMap.put("textField_mno1zcb5", FSetAccountType);//立账类型
+            orderMap.put("textField_mno1zcbb", firstRow.getString("FBillNo"));                 // 单据编号
+            orderMap.put("textField_mno1zcbc", firstRow.getString("FCURRENCYID.FName"));     // 币别
+            orderMap.put("textField_mno1zcbd", firstRow.getString("FSETTLEORGID.FName"));   // 结算组织
+            String fDateRaw = firstRow.getString("FDATE");
+            String formattedDate = (fDateRaw != null && fDateRaw.contains("T")) ? fDateRaw.split("T")[0] : fDateRaw;
+            orderMap.put("textField_mno1zcbe", formattedDate);                                   // 业务日期
+            String fDateRaw_A = firstRow.getString("FENDDATE_H");
+            String formattedDate_A = (fDateRaw_A != null && fDateRaw_A.contains("T")) ? fDateRaw_A.split("T")[0] : fDateRaw_A;
+            orderMap.put("textField_mno1zcbk", formattedDate_A);                             // 到期日
+            orderMap.put("textField_mno1zcbl", firstRow.getString("FPayConditon.FName"));// 收款条件
+            // 单据状态转换
+            String FDocumentStatus = "";
+            switch (firstRow.getString("FDocumentStatus")){
+                case "A": FDocumentStatus = "创建"; break;
+                case "B": FDocumentStatus = "审核中"; break;
+                case "C": FDocumentStatus = "已审核"; break;
+                case "D": FDocumentStatus = "重新审核"; break;
+                case "Z": FDocumentStatus = "暂存"; break;
+            }
+            orderMap.put("textField_mno1zcbm", FDocumentStatus);//单据状态
+            orderMap.put("textField_mno1zcbn", firstRow.getString("FSALEDEPTID.FName"));     // 销售部门
+            orderMap.put("textField_mno1zcbt", "");                                 // 留空
+
+            // 明细数组(字段映射请对应应收单明细表)
+            List<Map<String, Object>> details = new ArrayList<>();
+            for (JSONObject row : rows) {
+                Map<String, Object> detailMap = new LinkedHashMap<>();
+                detailMap.put("textField_mno1zcbv", row.getString("FMATERIALID.FNumber"));//物料编码
+                detailMap.put("textField_mno1zcbw", row.getString("FCustMatID.FNumber"));//客户物料编码
+                detailMap.put("textField_mno1zcbx", row.getString("FCustMatName"));//客户物料名称
+                detailMap.put("textField_mno1zcby", row.getString("F_UNW_BaseProperty_lad"));//规格型号
+                detailMap.put("textField_mno1zcbz", row.getString("FMaterialName"));//物料名称
+                detailMap.put("textField_mno1zcc0", row.getString("FPRICEUNITID.FName"));//计价单位
+                detailMap.put("numberField_mno1zcc2", row.getString("FPriceQty"));//计价数量
+                detailMap.put("numberField_mno1zcc3", row.getString("FEntryTaxRate"));//税率(%)
+                detailMap.put("textField_mno1zcc5", row.getString("FAuxpropId.FF100001"));//厚度
+                detailMap.put("numberField_mno1zcc6", row.getString("FBASICUNITQTY"));//计价基本数量
+                detailMap.put("textField_mno1zcc7", row.getString("FLot.FNumber"));//批号
+                detailMap.put("textField_mno1zcc8", row.getString("FORDERNUMBER"));//销售订单号
+                detailMap.put("textField_mno1zcc9", row.getString("FORDERENTRYSEQ"));//销售订单行号
+                detailMap.put("numberField_mno1zcca", row.getString("FSalQty"));//销售数量
+                detailMap.put("textField_mno1zccb", row.getString("FSalUnitId.FName"));//销售单位
+                detailMap.put("radioField_mno1zccc", row.getString("FIsFree").equals("true") ? "是" : "否");//是否赠品
+                details.add(detailMap);
+            }
+            orderMap.put("tableField_mno1zcbu", details);
+
+            // 写入宜搭
+            List<Map> conditions = Arrays.asList(
+                    YDConf.searchCondition_TextFiled("textField_mno1zcbb", firstRow.getString("FBillNo"), "eq")
+            );
+            ydClient.operateData(YDParam.builder()
+                    .formUuid("FORM-5A0062877EC246959CE85BC7418D1204229L")
+                    .searchCondition(JSONObject.toJSONString(conditions))
+                    .formDataJson(JSONObject.toJSONString(orderMap))
+                    .build(), YDConf.FORM_OPERATION.upsert).toString();
+            orderList.add(orderMap);
+        }
+
+        log.info("应收单(无发票号)已同步,共处理 {} 张单据", orderList.size());
+    }
+
 
     private McR saveToAudit(String formid, Object object) throws Exception {
         JSONObject resultObj = new JSONObject();

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

@@ -7,7 +7,7 @@ enable:
   scheduling: true
 logging:
   config: classpath:logback-spring.xml
-  path: /home/server/zhiwei/log/
+  path: ./log/
   level:
     com.malk.*: debug
 

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

@@ -7,7 +7,7 @@ enable:
   scheduling: true
 logging:
   config: classpath:logback-spring.xml
-  path: /home/server/zhiwei/log/
+  path: ./log/
   level:
     com.malk.*: debug
 

+ 24 - 0
mjava-zhongche/pom.xml

@@ -46,4 +46,28 @@
             <scope>provided</scope>
         </dependency>
     </dependencies>
+
+    <build>
+        <finalName>zhongche</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <executable>true</executable>
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>

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

@@ -0,0 +1,29 @@
+package com.malk.zhongche.controller;
+
+import com.malk.server.common.McR;
+import com.malk.zhongche.service.ZhongcheService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+public class ZhongcheController {
+    @Autowired
+    private ZhongcheService zhongcheService;
+
+    //获取任务信息
+    @GetMapping("/getTaskInfo")
+    public McR getTaskInfo(String taskId,String projectId){
+        return zhongcheService.getTaskInfo(taskId,projectId);
+    }
+
+    //更新任务延期信息
+    @PostMapping("/updateTaskDelayInfo")
+    public McR updateTaskDelayInfo(@RequestBody Map map){
+        return zhongcheService.updateTaskDelayInfo(map);
+    }
+}

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

@@ -0,0 +1,12 @@
+package com.malk.zhongche.service;
+
+import com.malk.server.common.McR;
+
+import java.util.Map;
+
+public interface ZhongcheService {
+    McR getTaskInfo(String taskId,String projectId);
+
+    McR updateTaskDelayInfo(Map map);
+
+}

+ 214 - 0
mjava-zhongche/src/main/java/com/malk/zhongche/service/impl/ZhongcheServiceImpl.java

@@ -0,0 +1,214 @@
+package com.malk.zhongche.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McR;
+import com.malk.server.teambition.TBConf;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import com.malk.service.teambition.TBClient;
+import com.malk.utils.UtilMap;
+import com.malk.zhongche.service.ZhongcheService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+@Slf4j
+@Service
+public class ZhongcheServiceImpl implements ZhongcheService {
+    @Autowired
+    private TBClient tbClient;
+
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private TBConf tbConf;
+
+    @Override
+    public McR getTaskInfo(String taskId,String projectId) {
+        Map taskInfo = tbClient.queryTaskDetail(taskId,null,null).get(0);
+
+        log.info("taskInfo:{}", JSONObject.toJSONString(taskInfo));
+
+        List<Map> customfields = UtilMap.getList(taskInfo, "customfields");
+
+        List<String> wtls = new ArrayList<>();//问题类型
+
+        for (Map customfield : customfields) {
+            String cfId = UtilMap.getString(customfield, "cfId");
+
+            switch (cfId){
+                case "6941202e92136abe2d9de68f"://问题类型
+                    List<Map> value = UtilMap.getList(customfield, "value");
+
+                    for (Map map : value) {
+                        wtls.add(UtilMap.getString(map, "title"));
+                    }
+                    break;
+                case "6969da08b9d8a458d706212d"://完成状态
+                    break;
+                case "6969dc054cd1174e86aa213a"://延期次数
+                    break;
+            }
+        }
+
+        String executorId = UtilMap.getString(taskInfo, "executorId");//执行者id
+
+        Map ddUserInfo = tbClient.idMapQuery(executorId, true).get(0);
+
+        Map extra = UtilMap.getMap(ddUserInfo, "extra");
+
+        String ddUserId = UtilMap.getString(extra, "userId");//执行人钉钉userid
+        Map userInfoById = ddClient_contacts.getUserInfoById(ddClient.getAccessToken(),ddUserId);
+        String ddUserName = UtilMap.getString(userInfoById, "name");//执行人钉钉姓名
+        Map ddUser = new HashMap();
+        ddUser.put("label",ddUserName);
+        ddUser.put("value",ddUserId);
+        ddUser.put("emplId",ddUserId);
+
+        long startDate = extracted(UtilMap.getString(taskInfo, "startDate"));//任务开始时间
+        long dueDate = extracted(UtilMap.getString(taskInfo, "dueDate"));//任务截止时间
+
+        String tfsId = UtilMap.getString(taskInfo, "tfsId");//任务状态id
+
+        Map body = new HashMap();
+        body.put("tfsIds", tfsId);
+        Map tfsInfo = tbClient.queryProjectCustomFlowStatus(projectId, body).get(0);
+        String tfsName = UtilMap.getString(tfsInfo, "name");//任务状态
+
+
+        //获取tb任务上级任务
+        String parentTaskId = UtilMap.getString(taskInfo, "parentTaskId");
+        Map parentTaskInfo = tbClient.queryTaskDetail(parentTaskId, null, null).get(0);
+        String parentTaskName = UtilMap.getString(parentTaskInfo, "content");
+
+        //获取tb顶级任务
+        Map rootTaskInfo = getRootTask(parentTaskId);
+        String rootTaskName = UtilMap.getString(rootTaskInfo, "content");
+
+        Map result = new HashMap();
+        result.put("wtls", wtls);
+        result.put("ddUser", ddUser);
+        result.put("startDate", startDate);
+        result.put("dueDate", dueDate);
+        result.put("tfsName", tfsName);
+        result.put("parentTaskName", parentTaskName);
+        result.put("rootTaskName", rootTaskName);
+
+
+        return McR.success(result);
+    }
+
+    @Override
+    public McR updateTaskDelayInfo(Map map) {
+        String formInstId = UtilMap.getString(map, "formInstId");
+
+        Map formData = ydClient.queryData(YDParam.builder()
+                .formInstanceId(formInstId)
+                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        String projectId = UtilMap.getString(formData, "textField_mkkrgg8u");//项目id
+        String taskId = UtilMap.getString(formData, "textField_mkkrgg8y");//任务id
+        long dueDate = UtilMap.getLong(formData, "dateField_mn757w7y");//预计完成时间
+
+        Map taskInfo = tbClient.queryTaskDetail(taskId, null, null).get(0);
+
+        List<Map> customfields = UtilMap.getList(taskInfo, "customfields");
+
+        int delayNum = 0;//延期次数
+
+        for (Map customfield : customfields) {
+            String cfId = UtilMap.getString(customfield, "cfId");
+
+            switch (cfId){
+                case "6941202e92136abe2d9de68f"://问题类型
+                    break;
+                case "6969da08b9d8a458d706212d"://完成状态
+                    break;
+                case "6969dc054cd1174e86aa213a"://延期次数
+                    List<Map> values = UtilMap.getList(customfield, "value");
+                    if (Objects.nonNull(values) && !values.isEmpty()){
+                        Map value = values.get(0);
+                        delayNum = Integer.parseInt(UtilMap.getString(value, "title"));
+                        break;
+                    }
+            }
+        }
+
+        //更新任务截止时间
+
+        // 1. 转换为 Instant(UTC 时间点)
+        Instant instant = Instant.ofEpochMilli(dueDate);
+
+        // 2.1 转换为 UTC 时间(比上海时间早 8 小时)
+        ZonedDateTime utcTime = instant.atZone(ZoneId.of("UTC"));
+        DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
+        String utcDateTime = utcTime.format(utcFormatter);
+        System.out.println("UTC date-time (比上海早8小时): " + utcDateTime); // 输出: 2026-03-20T01:30:00Z
+
+        tbClient.updateTaskDueDate(taskId, utcDateTime, tbConf.getOperatorId());
+
+        //更新任务延期次数
+        Map body = new HashMap();
+        body.put("customfieldId", "6969dc054cd1174e86aa213a");
+
+        Map value = new HashMap();
+        value.put("title",delayNum + 1 + "");
+        body.put("value",Arrays.asList(value));
+
+        Map map1 = tbClient.updateTaskCustomField(taskId, tbConf.getOperatorId(), body);
+
+        log.info("map1:{}",JSONObject.toJSONString(map1));
+
+        return McR.success();
+    }
+
+    private Map getRootTask(String taskId) {
+        Map taskInfo = tbClient.queryTaskDetail(taskId, null, null).get(0);
+
+        String parentTaskId = UtilMap.getString(taskInfo, "parentTaskId");
+
+        if (Strings.isNotBlank(parentTaskId)){
+            return getRootTask(parentTaskId);
+        }else {
+            return taskInfo;
+        }
+    }
+
+    //转换时区并返回时间戳
+    private static long extracted(String dueDate) {
+        // 1. 解析为 Instant(UTC 时间)
+        Instant instant = Instant.parse(dueDate);
+
+        // 2. 转换为目标时区(Asia/Shanghai, UTC+8)
+        ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
+        ZonedDateTime shanghaiTime = instant.atZone(shanghaiZone);
+
+        // 3. 转换为时间戳(毫秒)
+        long timestamp = shanghaiTime.toInstant().toEpochMilli();
+
+        // 输出结果
+        System.out.println("UTC 时间: " + instant);
+        System.out.println("上海时间: " + shanghaiTime);
+        System.out.println("时间戳(毫秒): " + timestamp);
+
+        return timestamp;
+    }
+}

+ 9 - 5
mjava-zhongche/src/main/resources/application-dev.yml

@@ -13,10 +13,10 @@ logging:
 
 # dingtalk
 dingtalk:
-  agentId:
-  appKey:
-  appSecret:
-  corpId:
+  agentId: 4396020096
+  appKey: ding26hdqsk96t6t6np0
+  appSecret: pBjGhyUDyinn192nDK7DQcaEsaGDDwfTLOsER-X3ZoWhGU9DURZGykRkw3aLgAtE
+  corpId: ding187f52da89b1e5c8a1320dcb25e91351
   aesKey:
   token:
   operator:
@@ -25,4 +25,8 @@ aliwork:
   appType: APP_SL9V2KUH6GBEISLNXXTJ
   systemToken: HOE66T71Z9H2PLVHM6EU85Q7H2AJ2YV2GRKKMWL1
 
-
+teambition:
+  AppID: 69c4f0f024a34a74e1c06d61
+  AppSecret: X77qcnv2AICiv70R41YZxGVFXRrFGCta
+  OperatorId: 67ce737aaec2f7379c7bbf6f
+  TenantId: 658a6467d87ead477d2d3f9d

+ 12 - 8
mjava-zhongche/src/main/resources/application-prod.yml

@@ -9,20 +9,24 @@ logging:
   config: classpath:logback-spring.xml
   path: /home/server/zhongche/log/
   level:
-    com.malk.*: info
+    com.malk.*: debug
 
 # dingtalk
 dingtalk:
-  agentId:
-  appKey:
-  appSecret:
-  corpId:
+  agentId: 4396020096
+  appKey: ding26hdqsk96t6t6np0
+  appSecret: pBjGhyUDyinn192nDK7DQcaEsaGDDwfTLOsER-X3ZoWhGU9DURZGykRkw3aLgAtE
+  corpId: ding187f52da89b1e5c8a1320dcb25e91351
   aesKey:
   token:
   operator:
 
 aliwork:
-  appType:
-  systemToken:
-
+  appType: APP_SL9V2KUH6GBEISLNXXTJ
+  systemToken: HOE66T71Z9H2PLVHM6EU85Q7H2AJ2YV2GRKKMWL1
 
+teambition:
+  AppID: 69c4f0f024a34a74e1c06d61
+  AppSecret: X77qcnv2AICiv70R41YZxGVFXRrFGCta
+  OperatorId: 67ce737aaec2f7379c7bbf6f
+  TenantId: 658a6467d87ead477d2d3f9d

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

@@ -0,0 +1,4 @@
+package com.malk.zhongche;
+
+public class ZcTest {
+}