Explorar el Código

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

wzy hace 3 semanas
padre
commit
43af805fb4
Se han modificado 25 ficheros con 2297 adiciones y 1027 borrados
  1. 575 480
      mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java
  2. 6 0
      mjava-huagao/src/main/java/com/malk/huagao/service/impl/KdYdDeliveryServiceImpl.java
  3. 26 0
      mjava-kabeiyi/pom.xml
  4. 35 0
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/controller/KabeiyiController.java
  5. 5 0
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/KabeiyiService.java
  6. 612 393
      mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/impl/KabeiyiServiceImpl.java
  7. 37 0
      mjava-kabeiyi/src/main/resources/application-dev.yml
  8. 14 0
      mjava-kabeiyi/src/main/resources/application-prod.yml
  9. 1 1
      mjava-kabeiyi/src/main/resources/application.yml
  10. 3 5
      mjava-lilin/src/main/java/com/malk/lilin/Controller/LiLinController.java
  11. 93 56
      mjava-lilin/src/main/java/com/malk/lilin/Service/impl/LiLinServiceImpl.java
  12. 2 0
      mjava-pake/src/main/java/com/malk/pake/service/impl/PkProjectServiceImpl.java
  13. 0 1
      mjava-tonglibo/pom.xml
  14. 37 22
      mjava-tonglibo/src/main/java/com/malk/tonglibo/controller/machineController.java
  15. 7 0
      mjava-tonglibo/src/main/java/com/malk/tonglibo/entity/MachineData.java
  16. 5 4
      mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/ChangeDetector.java
  17. 81 31
      mjava-tonglibo/src/main/java/com/malk/tonglibo/utils/DeviceDataPersistTask.java
  18. 5 4
      mjava-tonglibo/src/main/resources/application-dev.yml
  19. 4 4
      mjava-tonglibo/src/main/resources/application-prod.yml
  20. 27 23
      mjava-tonglibo/src/main/resources/mapper/MachineDataMapper.xml
  21. 59 0
      mjava-zhiwei/src/main/java/com/malk/zhiwei/schedule/ScheduleTask.java
  22. 22 0
      mjava-zhiwei/src/main/java/com/malk/zhiwei/service/ZwService.java
  23. 639 1
      mjava-zhiwei/src/main/java/com/malk/zhiwei/service/impl/ZwServiceImpl.java
  24. 1 1
      mjava-zhiwei/src/main/resources/application-dev.yml
  25. 1 1
      mjava-zhiwei/src/main/resources/application-prod.yml

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 575 - 480
mjava-fenggefushi/src/main/java/com/malk/fenggefushi/service/Impl/HeiHuOrderServiceImpl.java


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

@@ -369,6 +369,12 @@ public class KdYdDeliveryServiceImpl extends ServiceImpl<KdYdDeliveryMapper, KdY
             } catch (Exception e) {
                 log.error("创建新单据失败,dz=" + dz, e);
             }
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                log.error("线程被中断", e);
+            }
         }
     }
 

+ 26 - 0
mjava-kabeiyi/pom.xml

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 612 - 393
mjava-kabeiyi/src/main/java/com/malk/kabeiyi/service/impl/KabeiyiServiceImpl.java


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

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

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

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

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

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

+ 3 - 5
mjava-lilin/src/main/java/com/malk/lilin/Controller/LiLinController.java

@@ -17,10 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 
 @RestController
 @Slf4j
@@ -37,7 +34,7 @@ public class LiLinController {
     @Autowired
     private DDConf ddConf;
     @GetMapping("/test")
-    public McR test() {
+    public McR test() throws IOException {
 //        List<Map> list = (List<Map>) ydClient.queryData(YDParam.builder()
 //                .formUuid("FORM-754586D31BF6414586E5C20DB3774A7320CV")
 //                .searchFieldJson(JSONObject.toJSONString(Arrays.asList(
@@ -60,6 +57,7 @@ public class LiLinController {
 //                        .build(), YDConf.FORM_OPERATION.multi_update);
 //            }
 //        }
+         liLinService.lilinLS(new HashMap<>());
         return McR.success();
     }
 

+ 93 - 56
mjava-lilin/src/main/java/com/malk/lilin/Service/impl/LiLinServiceImpl.java

@@ -921,58 +921,98 @@ public class LiLinServiceImpl implements LiLinService {
                 accountNo = accountNo.trim();
 
                 log.info("开始对账单同步,accountNo: {}", accountNo);
-
-                // 准备时间范围
+// 准备时间范围
                 String dayFromId = LocalDate.now().minusDays(8).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                 String dayToId = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+                // 准备时间范围
+//                String dayFromId = LocalDate.of(2026, 2, 26).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+//                String dayToId = LocalDate.of(2026, 2, 26).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+
+                // ========== 分页查询 ==========
+                int pageSize = 20;
+                int pageNow = 1;
+                boolean hasMore = true;
+                List<JSONObject> allStatementList = new ArrayList<>();
+
+                while (hasMore) {
+                    // 构建 POST 请求体
+                    MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+                    String requestBodyStr = "securityCode=" + securityCode +
+                            "&accountNo=" + accountNo +
+                            "&dayFromId=" + dayFromId +
+                            "&dayToId=" + dayToId +
+                            "&instructionIdFlag=1" +
+                            "&pageNow=" + pageNow +
+                            "&trxFlag=R" +
+                            "&pageSize=" + pageSize;
+
+                    RequestBody body = RequestBody.create(mediaType, requestBodyStr);
+                    log.info("请求体: {},当前页: {}", requestBodyStr, pageNow);
+
+                    Request request = new Request.Builder()
+                            .url("https://x.xencio.com/c4c3/api/bs/list")
+                            .post(body)
+                            .addHeader("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb")
+                            .addHeader("content-type", "application/x-www-form-urlencoded")
+                            .build();
+
+                    response = client.newCall(request).execute();
+
+                    if (!response.isSuccessful()) {
+                        log.error("银行接口调用失败,HTTP状态码: {}", response.code());
+                        break; // 当前账号查询失败,跳出分页循环
+                    }
 
-                // 构建 POST 请求体
-                MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
-                String requestBodyStr = "securityCode=" + securityCode +
-                        "&accountNo=" + accountNo +
-                        "&dayFromId=" + dayFromId +
-                        "&dayToId=" + dayToId +
-                        "&instructionIdFlag=1" +
-                        "&pageNow=1" +
-                        "&trxFlag=R" +
-                        "&pageSize=20";
-
-                RequestBody body = RequestBody.create(mediaType, requestBodyStr);
-
-                Request request = new Request.Builder()
-                        .url("https://x.xencio.com/c4c3/api/bs/list")
-                        .post(body)
-                        .addHeader("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb")
-                        .addHeader("content-type", "application/x-www-form-urlencoded")
-                        .build();
-
-                response = client.newCall(request).execute();
-
-                if (!response.isSuccessful()) {
-                    log.error("银行接口调用失败,HTTP状态码: {}", response.code());
-                    continue; // 跳过当前账号
-                }
+                    String jsonStr = response.body().string();
+                    log.info("银行接口响应原始数据: {}", jsonStr);
 
-                String jsonStr = response.body().string();
-                log.debug("银行接口响应原始数据: {}", jsonStr);
+                    JSONObject jsonObject = JSON.parseObject(jsonStr);
+                    JSONObject data = jsonObject.getJSONObject("data");
+                    if (data == null) {
+                        log.info("响应中缺少 'data' 字段, accountNo: {}", accountNo);
+                        break;
+                    }
 
-                JSONObject jsonObject = JSON.parseObject(jsonStr);
-                JSONObject data = jsonObject.getJSONObject("data");
-                if (data == null) {
-                    log.error("响应中缺少 'data' 字段, accountNo: {}", accountNo);
-                    continue;
+                    JSONArray statementList = data.getJSONArray("searchBankStatementList");
+                    if (statementList == null || statementList.isEmpty()) {
+                        log.info("银行接口返回空列表,accountNo: {},pageNow: {}", accountNo, pageNow);
+                        break;
+                    }
+
+                    // 将当前页数据添加到总列表中
+                    for (int i = 0; i < statementList.size(); i++) {
+                        allStatementList.add(statementList.getJSONObject(i));
+                    }
+
+                    // 判断是否还有下一页
+                    // 方式1:如果返回的数据量小于 pageSize,说明是最后一页
+                    if (statementList.size() < pageSize) {
+                        hasMore = false;
+                        log.info("已查询完所有数据,总页数: {}", pageNow);
+                    } else {
+                        pageNow++;
+                        // 添加适当延迟,避免请求过快
+                        Thread.sleep(100);
+                    }
+
+                    // 关闭旧的response,准备下一次请求
+                    if (response != null) {
+                        response.close();
+                        response = null;
+                    }
                 }
 
-                JSONArray statementList = data.getJSONArray("searchBankStatementList");
-                if (statementList == null || statementList.isEmpty()) {
-                    log.info("银行接口返回空列表,accountNo: {}", accountNo);
+                log.info("账号 {} 共查询到 {} 条对账单记录", accountNo, allStatementList.size());
+
+                // ========== 处理所有分页数据 ==========
+                if (allStatementList.isEmpty()) {
+                    log.info("账号 {} 无数据需要处理", accountNo);
                     continue;
                 }
 
                 List<Map<String, String>> extractedList = new ArrayList<>();
 
-                for (int i = 0; i < statementList.size(); i++) {
-                    JSONObject item = statementList.getJSONObject(i);
+                for (JSONObject item : allStatementList) {
                     if (item == null) continue;
 
                     Map<String, String> extractedItem = new HashMap<>();
@@ -981,12 +1021,12 @@ public class LiLinServiceImpl implements LiLinService {
                     String crAmount = getStringValue(item, "crAmount");
                     String trxDate = getStringValue(item, "trxDate");
                     String createDate = getStringValue(item, "createDate");
-                    String accountName = getStringValue(item, "accountName"); // 本方账号名称
+                    String accountName = getStringValue(item, "accountName");
                     String userRemarks = getStringValue(item, "userRemarks");
                     String userMemo = getStringValue(item, "userMemo");
                     String transFlag = getStringValue(item, "transFlag");
                     String catalogName = getStringValue(item, "catalogName");
-                    String customerName = getStringValue(item, "customerName"); // 对手方账户名称
+                    String customerName = getStringValue(item, "customerName");
 
                     Long timestamp = null;
                     if (trxDate != null && !trxDate.isEmpty()) {
@@ -994,7 +1034,7 @@ public class LiLinServiceImpl implements LiLinService {
                             timestamp = LocalDateTime.parse(trxDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                                     .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                         } catch (Exception e) {
-                            log.warn("日期解析失败: {}", trxDate);
+                            log.info("日期解析失败: {}", trxDate);
                         }
                     }
                     Long timestamp1 = null;
@@ -1003,7 +1043,7 @@ public class LiLinServiceImpl implements LiLinService {
                             timestamp1 = LocalDateTime.parse(createDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                                     .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                         } catch (Exception e) {
-                            log.warn("日期解析失败: {}", createDate);
+                            log.info("日期解析失败: {}", createDate);
                         }
                     }
 
@@ -1019,7 +1059,7 @@ public class LiLinServiceImpl implements LiLinService {
                     // 检查是否已存在该对账单记录
                     boolean exists = false;
                     int maxRetries = 3;
-                    long retryDelayMs = 1000; // 1秒后重试
+                    long retryDelayMs = 1000;
 
                     for (int attempt = 1; attempt <= maxRetries; attempt++) {
                         try {
@@ -1034,11 +1074,10 @@ public class LiLinServiceImpl implements LiLinService {
                             ).getData();
 
                             exists = list != null && !list.isEmpty();
-                            break; // ✅ 查询成功,跳出重试循环
+                            break;
 
                         } catch (Exception e) {
                             String errorMsg = e.getMessage();
-                            // 🔁 判断是否是“可重试”的临时错误
                             boolean isTransientError = errorMsg != null &&
                                     (errorMsg.contains("temporary failure") ||
                                             errorMsg.contains("500") ||
@@ -1051,30 +1090,27 @@ public class LiLinServiceImpl implements LiLinService {
                                     attempt, bankStatementId, e.getMessage());
 
                             if (attempt == maxRetries) {
-                                // ❌ 最后一次重试仍失败,才抛出异常
-                                log.error("查询宜搭系统最终失败,已重试 {} 次,bankStatementId: {}",
+                                log.info("查询宜搭系统最终失败,已重试 {} 次,bankStatementId: {}",
                                         maxRetries, bankStatementId, e);
                                 throw new RuntimeException("查询宜搭失败,bankStatementId=" + bankStatementId, e);
                             }
 
                             if (isTransientError) {
-                                // ✅ 是临时错误,等待后重试
                                 try {
-                                    Thread.sleep(retryDelayMs * attempt); // 指数退避:1s, 2s, 3s...
+                                    Thread.sleep(retryDelayMs * attempt);
                                 } catch (InterruptedException ie) {
                                     Thread.currentThread().interrupt();
                                     throw new RuntimeException("重试等待被中断", ie);
                                 }
                             } else {
-                                // ❌ 非临时错误(如参数错误、表单不存在),直接放弃重试
-                                log.error("查询失败:非临时性错误,不再重试,bankStatementId: {}", bankStatementId, e);
+                                log.info("查询失败:非临时性错误,不再重试,bankStatementId: {}", bankStatementId, e);
                                 throw new RuntimeException("查询宜搭失败(非临时错误):" + errorMsg, e);
                             }
                         }
                     }
 
                     if (exists) {
-                        log.debug("记录已存在,跳过: bankStatementId={}", bankStatementId);
+                        log.info("记录已存在,跳过: bankStatementId={}", bankStatementId);
                         continue;
                     }
 
@@ -1108,7 +1144,6 @@ public class LiLinServiceImpl implements LiLinService {
                             khaccountName = customerName;
                         }
 
-
                         if (khformInstanceId == null || khaccountName == null) {
                             log.warn("未找到匹配的客户信息: customerName={}", customerName);
                         }
@@ -1158,10 +1193,12 @@ public class LiLinServiceImpl implements LiLinService {
 
             } catch (IOException e) {
                 log.error("网络IO异常: accountNo={}", accountNo, e);
+            } catch (InterruptedException e) {
+                log.error("线程中断异常: accountNo={}", accountNo, e);
+                Thread.currentThread().interrupt();
             } catch (Exception e) {
                 log.error("处理账号异常: accountNo={}", accountNo, e);
             } finally {
-                // 确保 response 被安全关闭
                 if (response != null) {
                     try {
                         response.close();

+ 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());

+ 0 - 1
mjava-tonglibo/pom.xml

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 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