package com.malk.lilin.Service.impl; import cn.hutool.crypto.SecureUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.malk.lilin.Service.LiLinService; import com.malk.server.aliwork.YDConf; import com.malk.server.aliwork.YDParam; import com.malk.server.aliwork.YDSearch; import com.malk.server.common.McR; import com.malk.server.dingtalk.DDConf; import com.malk.service.aliwork.YDClient; import com.malk.service.aliwork.YDService; import com.malk.utils.UtilHttp; import com.malk.utils.UtilMap; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.apache.commons.lang3.StringEscapeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.io.IOException; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.atomic.DoubleAdder; import java.util.stream.Collectors; @Slf4j @Service public class LiLinServiceImpl implements LiLinService { @Autowired private YDClient ydClient; @Autowired private YDService ydService; @Autowired private YDConf ydConf; @Autowired private DDConf ddConf; private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#0.00"); @Override public McR lilinUpsert(List rqqj, String bdbh) { List list = (List) ydClient.queryData(YDParam.builder() .formUuid("FORM-5F8B2B6418E14EF0967CC60DA25A7558K5L7") .searchFieldJson(JSONObject.toJSONString(Arrays.asList( new YDSearch("createTime", rqqj, "DateField", YDSearch.Type.DATE_FIELD, YDSearch.Operator.BETWEEN), new YDSearch("textField_m9cdsn32", bdbh, "TextField", YDSearch.Type.TEXT_FIELD, YDSearch.Operator.EQ)))) .build(), YDConf.FORM_QUERY.retrieve_list_all).getData(); List details = new ArrayList<>(); List details2 = new ArrayList<>(); // 存储每个【订单编号】对应的是哪个项目(便于后续处理) Map orderToProjectMap = new HashMap<>(); Map> projectAmountMap = new HashMap<>(); if (list != null && !list.isEmpty()) { for (Map map : list) { try { Map detail = new HashMap<>(); Map formData = (Map) map.get("formData"); String zt = UtilMap.getString(formData, "textField_md6z2k32"); // 如果状态是“已同步”,跳过 if ("已同步".equals(zt)) { continue; } String formInstanceId = UtilMap.getString(map, "formInstanceId"); details2.add(formInstanceId); String ddbh = UtilMap.getString(formData, "textField_m9cdsn32"); // 订单编号 String xmbh = UtilMap.getString(formData, "textField_m9chwmaj"); // 项目编号 if (xmbh == null || xmbh.trim().isEmpty()) { log.warn("明细数据缺少项目编号,跳过: formInstanceId={}", formInstanceId); continue; } // 记录 订单 -> 项目 映射关系 if (ddbh != null && !ddbh.isEmpty()) { orderToProjectMap.put(ddbh, xmbh); } // 获取金额字段(安全获取) BigDecimal je = safeGetBigDecimal(formData, "numberField_m9b2rwwo"); // 含税小计 BigDecimal jews = safeGetBigDecimal(formData, "numberField_m9b2rwwp"); // 无税小计 BigDecimal yf = safeGetBigDecimal(formData, "numberField_majn78hg"); // 运费补贴 // 累加到项目金额 map projectAmountMap.putIfAbsent(xmbh, new HashMap<>()); Map amounts = projectAmountMap.get(xmbh); amounts.merge("numberField_m9b2rwwo", je, BigDecimal::add); amounts.merge("numberField_m9b2rwwp", jews, BigDecimal::add); amounts.merge("numberField_majn78hg", yf, BigDecimal::add); // 处理关联产品字段 String dgcpRaw = String.valueOf(formData.get("associationFormField_m984zbpq_id")); String dgcpString = StringEscapeUtils.unescapeJava(dgcpRaw.substring(1, dgcpRaw.length() - 1)); List dgcps = (List) JSONArray.parse(dgcpString); detail.put("associationFormField_m9cdctdo", dgcps); // 其他字段提取 detail.put("textField_m9cdctdq", safeGetString(formData, "textField_m8yanvkl")); // 型号 detail.put("numberField_m9cdctdx", safeGetString(formData, "numberField_m8yanvkx")); // 数量 detail.put("numberField_m9cdctdw", safeGetString(formData, "numberField_m8yanvkw")); // 销售单价含税 detail.put("selectField_manmqrif", safeGetString(formData, "selectField_m9me4py8")); // 销售税率 detail.put("numberField_m9cdctdy", safeGetString(formData, "numberField_m9b2rwwo")); // 金额小计 detail.put("numberField_majmvrdr", safeGetString(formData, "numberField_majn78hg")); // 运费补贴 detail.put("numberField_m9cdctdv", safeGetString(formData, "numberField_m8yanvkv")); // 销售单价未税 detail.put("numberField_m9cdctdz", safeGetString(formData, "numberField_m9b2rwwp")); // 金额未税小计 detail.put("textField_m96r764p", safeGetString(formData, "selectField_m8xtlcwg")); // 产品小类 detail.put("textField_m96r764o", safeGetString(formData, "selectField_m8xtlcwf")); // 产品大类 detail.put("textField_m9cdctdp", safeGetString(formData, "textField_m8yanvkk")); // 品牌 detail.put("textField_m9cdctdr", safeGetString(formData, "textField_m8yanvks")); // 产品单位 detail.put("textField_m9cdctds", safeGetString(formData, "textField_m8yanvkt")); // 颜色 detail.put("selectField_m9cdcte0", safeGetString(formData, "selectField_m8yanvkn")); // 是否带采 detail.put("selectField_m9cdcte1", safeGetString(formData, "selectField_m8yanvko")); // 是否定制 detail.put("selectField_m9cdcte2", safeGetString(formData, "selectField_m8yanvkp")); // 是否明细 detail.put("textField_m9gewnyi", safeGetString(formData, "textField_m9gfqsow")); // 产品名称 detail.put("textField_m9gewnyj", safeGetString(formData, "textField_m9gfqsox")); // SKU码 detail.put("selectField_m9qrzktd", "未生产"); // 订单状态 detail.put("textField_m9qnz34u", safeGetString(formData, "textField_m9gfqsox")); // 订单明细编号 detail.put("numberField_m9gfg5mi", safeGetString(formData, "numberField_m9gfg5mi")); // 成本单价含税 detail.put("selectField_m9me4py8", safeGetString(formData, "selectField_m9me4py8")); // 成本税率 detail.put("numberField_m9gfg5mj", safeGetString(formData, "numberField_m9gfg5mj")); // 成本单价无税 detail.put("textField_maoynrp4", safeGetString(formData, "textField_maqkme86")); // 供应商名称 detail.put("textField_maoynrp5", safeGetString(formData, "textField_maqkme87")); // 供应商编号 details.add(detail); } catch (Exception e) { log.error("处理子表单数据时发生异常", e); } } try { if (!projectAmountMap.isEmpty()) { for (Map.Entry> entry : projectAmountMap.entrySet()) { String xmbh = entry.getKey(); // 项目编号 Map amounts = entry.getValue(); try { // 查询项目主表单 List xmdata = (List) ydClient.queryData( YDParam.builder() .formUuid("FORM-FFA52F0206684931A0F18C00C2C937EAAVI5") .searchFieldJson(JSONObject.toJSONString(UtilMap.map("textField_m9awsc29, aa", xmbh, ""))) .build(), YDConf.FORM_QUERY.retrieve_list_all ).getData(); if (xmdata != null && !xmdata.isEmpty()) { Map xmmap = xmdata.get(0); String xmformInstanceId = UtilMap.getString(xmmap, "formInstanceId"); Map xmFormData = (Map) xmmap.get("formData"); // 获取当前项目表单中的金额 BigDecimal existingXsddje = safeGetBigDecimal(xmFormData, "numberField_m982msp5"); // 订单金额含税 BigDecimal existingXsddwthj = safeGetBigDecimal(xmFormData, "numberField_m982msp7"); // 订单金额无税 BigDecimal existingXsddwsk = safeGetBigDecimal(xmFormData, "numberField_m9iarxwb"); // 未收款金额 BigDecimal existingXsddwkp = safeGetBigDecimal(xmFormData, "numberField_m9iarxwc"); // 未开票金额 // 获取本次要累加的金额 BigDecimal je = amounts.getOrDefault("numberField_m9b2rwwo", BigDecimal.ZERO); BigDecimal jews = amounts.getOrDefault("numberField_m9b2rwwp", BigDecimal.ZERO); BigDecimal yf = amounts.getOrDefault("numberField_majn78hg", BigDecimal.ZERO); // 累加 existingXsddje = existingXsddje.add(je).add(yf); existingXsddwthj = existingXsddwthj.add(jews); existingXsddwsk = existingXsddwsk.add(je).add(yf); // 含税 + 运费 existingXsddwkp = existingXsddwkp.add(je).add(yf); // 无税金额 // 构建更新数据 Map xmupdateMap = new HashMap<>(); xmupdateMap.put("numberField_m982msp5", existingXsddje.stripTrailingZeros().toPlainString()); xmupdateMap.put("numberField_m982msp7", existingXsddwthj.stripTrailingZeros().toPlainString()); xmupdateMap.put("numberField_m9iarxwb", existingXsddwsk.stripTrailingZeros().toPlainString()); xmupdateMap.put("numberField_m9iarxwc", existingXsddwkp.stripTrailingZeros().toPlainString()); // 执行更新 // ydClient.operateData( // YDParam.builder() // .formInstanceId(xmformInstanceId) // .updateFormDataJson(JSONObject.toJSONString(xmupdateMap)) // .useLatestVersion(true) // .build(), // YDConf.FORM_OPERATION.update // ); ydClient.operateData(YDParam.builder() .formUuid("FORM-FFA52F0206684931A0F18C00C2C937EAAVI5") .appType("APP_RPH7R3LF3SMXLRDY1ZJW") .systemToken("7M866K91D4LVACB4EADAZ5UJG7IN3OGA33WAMNT") .noExecuteExpression(true) .searchCondition(JSONObject.toJSONString(UtilMap.map("textField_marp9xdr", xmformInstanceId))) .formDataJson(JSONObject.toJSONString(xmupdateMap)) .build(), YDConf.FORM_OPERATION.upsert); log.info("已更新项目表单,项目编号:{},累加含税金额:{}", xmbh, je); } else { log.warn("未找到项目表单,项目编号:{}", xmbh); } } catch (Exception e) { log.error("更新项目表单失败,项目编号:{}", xmbh, e); } } } for (String ddbh : orderToProjectMap.keySet()) { List data = (List) ydClient.queryData(YDParam.builder() .formUuid("FORM-C9BC8F7A159E4281B707ADBE1628EB7FDACQ") .searchFieldJson(JSONObject.toJSONString(UtilMap.map("textField_m9cdcten", ddbh))) .build(), YDConf.FORM_QUERY.retrieve_list_all).getData(); if (data == null || data.isEmpty()) { return McR.errorParam("主表单不存在"); } Map mainMap = data.get(0); log.info("主表单数据: {}", mainMap); String formInstanceId1 = UtilMap.getString(mainMap, "formInstanceId"); Map mainFormData = (Map) mainMap.get("formData"); List tableField = (List) mainFormData.get("tableField_m9cdcte4"); System.out.println("主表单数据:" + tableField); if (tableField == null) { tableField = new ArrayList<>(); } tableField.addAll(details); // 修改后的处理逻辑,合并相同SKU的数据 List distinctList = new ArrayList<>(); Map skuMap = new HashMap<>(); for (Map item : tableField) { String sku = safeGetString(item, "textField_m9gewnyj"); Set fillableFields = new HashSet<>(item.keySet()); fillableFields.removeAll(Arrays.asList( "numberField_m9cdctdx", // 数量 "numberField_m9cdctdy", // 销售含税金额小计 "numberField_majmvrdr", // 运费补贴 "numberField_m9cdctdz", // 销售未税金额小计 "numberField_m9gfg5mi", // 成本单价含税 "numberField_m9gfg5mj" // 成本单价无税 // 可继续添加其他数值字段 )); if (skuMap.containsKey(sku)) { // 如果SKU已存在,则累加数值字段 Map existingItem = skuMap.get(sku); // 累加数量 double currentQty = getDoubleSafe(existingItem, "numberField_m9cdctdx"); double newQty = getDoubleSafe(item, "numberField_m9cdctdx"); existingItem.put("numberField_m9cdctdx", currentQty + newQty); // 累加销售含税金额 double currentHsAmount = getDoubleSafe(existingItem, "numberField_m9cdctdy"); double newHsAmount = getDoubleSafe(item, "numberField_m9cdctdy"); existingItem.put("numberField_m9cdctdy", currentHsAmount + newHsAmount); // 累加运费补贴 double currentYfbt = getDoubleSafe(existingItem, "numberField_majmvrdr"); double newYfbt = getDoubleSafe(item, "numberField_majmvrdr"); existingItem.put("numberField_majmvrdr", currentYfbt + newYfbt); // 累加销售未税金额 double currentWsAmount = getDoubleSafe(existingItem, "numberField_m9cdctdz"); double newWsAmount = getDoubleSafe(item, "numberField_m9cdctdz"); existingItem.put("numberField_m9cdctdz", currentWsAmount + newWsAmount); // 累加成本含税 double currentHsCost = getDoubleSafe(existingItem, "numberField_m9gfg5mi"); double newHsCost = getDoubleSafe(item, "numberField_m9gfg5mi"); existingItem.put("numberField_m9gfg5mi", currentHsCost + newHsCost); // 累加成本无税 double currentWsCost = getDoubleSafe(existingItem, "numberField_m9gfg5mj"); double newWsCost = getDoubleSafe(item, "numberField_m9gfg5mj"); existingItem.put("numberField_m9gfg5mj", currentWsCost + newWsCost); for (String field : fillableFields) { Object existingValue = existingItem.get(field); Object newValue = item.get(field); boolean isEmptyExisting = existingValue == null || (existingValue instanceof String && ((String) existingValue).trim().isEmpty()); boolean hasValidNewValue = newValue != null && (!(newValue instanceof String) || !((String) newValue).trim().isEmpty()); if (isEmptyExisting && hasValidNewValue) { existingItem.put(field, newValue); } } } else { // 如果SKU不存在,则添加到map中 skuMap.put(sku, item); } } // 将合并后的数据放入distinctList distinctList.addAll(skuMap.values()); DoubleAdder totalZsl = new DoubleAdder(); DoubleAdder totalXsDj = new DoubleAdder(); DoubleAdder totalJexj = new DoubleAdder(); DoubleAdder totalYfzj = new DoubleAdder(); distinctList.forEach(item -> { totalZsl.add(getDoubleSafe(item, "numberField_m9cdctdx")); totalXsDj.add(getDoubleSafe(item, "numberField_m9cdctdy")); totalJexj.add(getDoubleSafe(item, "numberField_m9cdctdz")); totalYfzj.add(getDoubleSafe(item, "numberField_majmvrdr")); }); Map updateMap = new HashMap<>(); updateMap.put("tableField_m9cdcte4", distinctList); updateMap.put("numberField_m9cdcte5", totalZsl.doubleValue()); updateMap.put("numberField_ma14qlv3", totalZsl.doubleValue()); updateMap.put("numberField_ma14qlv7", totalZsl.doubleValue()); updateMap.put("numberField_maowfpzl", totalZsl.doubleValue()); updateMap.put("numberField_m9cdcte7", totalXsDj.doubleValue() + totalYfzj.doubleValue()); updateMap.put("numberField_m9cdcte9", totalJexj.doubleValue()); updateMap.put("numberField_majmvrdq", totalYfzj.doubleValue()); updateMap.put("numberField_m9iap5e5", totalXsDj.doubleValue() + totalYfzj.doubleValue()); updateMap.put("numberField_m9iap5e6", totalXsDj.doubleValue() + totalYfzj.doubleValue()); System.out.println("updateMap=======" + updateMap); // 更新主表单 // ydClient.operateData(YDParam.builder() // .formInstanceId(formInstanceId1) // .updateFormDataJson(JSONObject.toJSONString(updateMap)) // .useLatestVersion(true) // .build(), YDConf.FORM_OPERATION.update); ydClient.operateData(YDParam.builder() .formUuid("FORM-C9BC8F7A159E4281B707ADBE1628EB7FDACQ") .appType("APP_RPH7R3LF3SMXLRDY1ZJW") .systemToken("7M866K91D4LVACB4EADAZ5UJG7IN3OGA33WAMNT") .noExecuteExpression(true) .searchCondition(JSONObject.toJSONString(UtilMap.map("textField_m9cdcten", ddbh))) .formDataJson(JSONObject.toJSONString(updateMap)) .build(), YDConf.FORM_OPERATION.upsert); // 批量更新子表单状态为“已同步” if (!details2.isEmpty()) { ydClient.operateData(YDParam.builder() .formInstanceIdList(details2) .formUuid("FORM-5F8B2B6418E14EF0967CC60DA25A7558K5L7") .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("textField_md6z2k32", "已同步"))) .useLatestVersion(true) .build(), YDConf.FORM_OPERATION.multi_update); } } } catch (Exception e) { log.error("更新主表单或子表单状态时出错", e); return McR.errorParam("更新失败"); } return McR.success(); } else { return McR.success(); } } @Override public McR hqbank(Map map) { Map jzHeader = new HashMap(); jzHeader.put("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb"); jzHeader.put("content-type", "application/x-www-form-urlencoded"); Map bankMap = new HashMap(); bankMap.put("securityCode", token().getData()); bankMap.put("queryType", "full"); bankMap.put("name", map.get("name")); // bankMap.put("headName", param.get("headBank")); int pageNow = 1; bankMap.put("pageSize", 10); bankMap.put("pageNow", pageNow); String bankResult = UtilHttp.doGet("https://x.xencio.com/c4c3/api/bank/searchBranch", jzHeader, bankMap); JSONObject jsonResponse = JSONObject.parseObject(bankResult); // 获取 data 对象(外层的 data) JSONObject dataObj = jsonResponse.getJSONObject("data"); // 获取 data 数组(真正的数据列表) JSONArray dataList = dataObj.getJSONArray("data"); // 创建用于存储结果的 List List> bankList = new ArrayList<>(); if (dataList != null && !dataList.isEmpty()) { for (int i = 0; i < dataList.size(); i++) { JSONObject item = dataList.getJSONObject(i); // 提取 code 和 name String code = item.getString("code"); String name = item.getString("name"); // 封装到 map Map bankMap1 = new HashMap<>(); bankMap1.put("code", code); bankMap1.put("name", name); // 添加到列表 bankList.add(bankMap1); } } else { System.out.println("data 数组为空或不存在"); } return McR.success(bankList); } public static void main(String[] args) { HashMap mapAll = new HashMap<>(); List> tableField = new ArrayList<>(); Map data1 = new HashMap<>(); data1.put("trxNumber", "FK20250723621"); data1.put("fromAccountCode", "755915704010801"); data1.put("fromAccountName", "企业网银新20161341"); data1.put("toAccountCode", "6214831150131511"); data1.put("toAccountType", "0"); data1.put("toAccountName", "吴极客"); data1.put("payAmount", "1.00"); data1.put("uses", "这是一个测试用途"); // data1.put("instructionId", "F00000123"); Map data2 = new HashMap<>(); data2.put("trxNumber", "FK20250723631"); data2.put("fromAccountCode", "755915704010801"); data2.put("fromAccountName", "企业网银新20161341"); data2.put("toAccountCode", "6214831150131511"); data2.put("toAccountType", "0"); data2.put("toAccountName", "吴极客"); data2.put("payAmount", "1.00"); data2.put("uses", "这是一个测试用途"); // data2.put("instructionId", "F00000123"); // 添加到集合 tableField.add(data1); tableField.add(data2); System.out.println(JSONObject.toJSONString(tableField)); mapAll.put("totalRecord", "2"); mapAll.put("list", JSONObject.toJSONString(tableField)); mapAll.put("totalTrxNumber", "FK20250725713"); mapAll.put("source", "OA"); // mapAll.put("securityCode", securityCode); String url = "https://openapi.xencio.com/sandbox/cfa/api/payment/batchTransfer"; String securityCode = String.valueOf(token().getData()); Map headers = new HashMap<>(); headers.put("x-xencio-client-id", "4d9414e89bc24b0d89b678d9f20bc56a"); headers.put("content-Type", "application/x-www-form-urlencoded"); Map params = new HashMap<>(); // mapAll.put("securityCode", securityCode); mapAll.put("securityCode", securityCode); String response = UtilHttp.doPost(url, headers, null, null, mapAll);//批量制单 log.info("response:{}", response); } @Async @Override public McR lilinZD(Map map) throws IOException { String formInstanceId = String.valueOf(map.get("formInstanceId")); log.info("formInstanceId:{}", formInstanceId); // 获取表单数据 Map data = (Map) ydClient.queryData(YDParam.builder() .formInstId(formInstanceId) .appType(ydConf.getAppType()) .systemToken(ydConf.getSystemToken()) .userId(ddConf.getOperator()) .build(), YDConf.FORM_QUERY.retrieve_id).getFormData(); log.info("form data: {}", data); // 主表字段(复用) String fklx = String.valueOf(data.get("selectField_m9ze3rjf")); // 付款类型 String note = String.valueOf(data.get("textField_m9ze3rk3")); // 付款用途 String toAccountCode = String.valueOf(data.get("textField_m9ze3rjs")); // 收款账号 String toAccountName = String.valueOf(data.get("textField_m9ze3rjl")); // 收款户名 String toBank = String.valueOf(data.get("textField_m9ze3rjr")); // 收款银行支行 String fromAccountCode = String.valueOf(data.get("textField_mdfnuyl9")); // 付款账号 String fromAccountName = String.valueOf(data.get("textField_m9ze3rj8")); // 付款户名 String toAccountTypeStr = String.valueOf(data.get("textField_m9ze3rjm")); // 收款类型 String djlx = String.valueOf(data.get("textField_m9ze3rjr")); // 单据类型 String applyDepartment = String.valueOf(data.get("textField_m9ze3rjy")); // 回单邮箱 String paymentOrderType = djlx.contains("支付宝") ? "alipay" : "common"; // Map accountMap = new HashMap<>(); // accountMap.put("上海韵林礼品有限公司", "1001260509024819590"); // accountMap.put("上海礼林文化科技有限公司", "1001260509424880696"); // accountMap.put("上海泰辰印务科技有限公司", "1001260509324868573"); // accountMap.put("允临实业(上海)有限公司", "1001260509324808614"); // // // 3. 查找对应的账户编码 // String fromAccountCode = null; // 付款账号 // // if (fromAccountName != null && !fromAccountName.trim().isEmpty()) { // fromAccountCode = accountMap.get(fromAccountName.trim()); // } // 判断 toAccountTypeStr 是否等于“对公收款人” String toAccountType = "对公收款人".equals(toAccountTypeStr) ? "0" : "1"; // 公共参数 String securityCode = String.valueOf(token().getData()); Map headers = new HashMap<>(); headers.put("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb"); headers.put("content-type", "application/x-www-form-urlencoded"); String url = "https://x.xencio.com/c4c3/api/payment/transfer"; // 判断是否为物流付款单 if ("物流付款单".equals(fklx)) { // 是物流付款单:遍历子表,每行发起一次支付 List> tableField = (List>) data.get("tableField_m986c5os"); if (tableField == null || tableField.isEmpty()) { log.warn("物流付款单但子表为空,formInstanceId: {}", formInstanceId); return McR.errorParam("子表数据为空"); } for (Map row : tableField) { String instructionId = String.valueOf(row.get("textField_mdnuob9a")); // 子表电子凭证号 String payAmount = String.valueOf(row.get("numberField_m8yf6gn1")); // 子表金额 String projectInfo = getStringValue(row, "textField_m9lfmh1o"); // 项目名称 String projectCode = getStringValue(row, "textField_m9lfmh1p"); // 项目编号 String businessSegment = getStringValue(row, "selectField_mkash8u9"); // 板块名称 String businessProjectStatus = getStringValue(row, "selectField_mkash8ua"); // 项目状态 // 对于employeeField_m9lfmh1r字段的特殊处理 String projectManagerRaw = getStringValue(row, "employeeField_m9lfmh1r"); String projectManager = projectManagerRaw.replace("[\"", "").replace("\"]", "").trim(); // 项目负责人 // 构建 projectInfo Map metaJson1 = new HashMap<>(); metaJson1.put("projectInfo", projectInfo); metaJson1.put("businessSegment", businessSegment); metaJson1.put("businessProjectStatus", businessProjectStatus); metaJson1.put("projectManager", projectManager); metaJson1.put("projectCode", projectCode); String metaJson = JSON.toJSONString(metaJson1); // 组装请求参数 Map mapAll = new HashMap<>(); mapAll.put("instructionId", instructionId); mapAll.put("fromAccountCode", fromAccountCode); mapAll.put("fromAccountName", fromAccountName); mapAll.put("toAccountCode", toAccountCode); mapAll.put("toAccountType", toAccountType); mapAll.put("toAccountName", toAccountName); mapAll.put("payAmount", payAmount); mapAll.put("paymentOrderType", paymentOrderType); mapAll.put("source", "OA"); mapAll.put("note", note); mapAll.put("toBank", toBank); mapAll.put("securityCode", securityCode); mapAll.put("metaJson", metaJson); mapAll.put("applyDepartment", applyDepartment); // 发起支付 String response = UtilHttp.doPost(url, headers, null, null, mapAll); log.info("物流付款单 - 支付成功 [凭证号: {}, 金额: {}], 响应: {}", instructionId, payAmount, response); JSONObject jsonObject = JSON.parseObject(response); // 获取 data 对象 JSONObject redata = jsonObject.getJSONObject("data"); // 从 data 中获取 message String message = redata.getString("message"); String code = redata.getString("code"); String zdqk = "C0000".equals(code) ? "制单成功" : "制单异常"; Map objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("radioField_mel5n51w", zdqk); objectObjectHashMap.put("textareaField_mel5n51x", message); ydClient.operateData(YDParam.builder() .formInstanceId(formInstanceId) .updateFormDataJson(JSON.toJSONString(objectObjectHashMap)) .build(), YDConf.FORM_OPERATION.update); } } else { // 不是物流付款单:使用主表字段,发起一次支付 String instructionId = String.valueOf(data.get("serialNumberField_m9ze3rjd")); // 主表电子凭证号 String payAmount = String.valueOf(data.get("numberField_m9ze3rk4")); // 主表金额 String projectManager = getStringValue(data, "employeeField_mi647wos") .replace("[\"", "").replace("\"]", "").trim(); // 项目负责人 String projectCode = getStringValue(data, "textField_madmzxce"); String businessSegment = getStringValue(data, "selectField_mjqhty52"); // 业务板块 String businessProjectStatus = getStringValue(data, "selectField_m9ks0c66"); // 项目状态 String projectInfo = getStringValue(data, "textField_mayubz25"); // String projectInfo = xmbh + "-" + xmmc; Map metaJson1 = new HashMap<>(); metaJson1.put("projectInfo", projectInfo); metaJson1.put("businessSegment", businessSegment); metaJson1.put("businessProjectStatus", businessProjectStatus); metaJson1.put("projectManager", projectManager); metaJson1.put("projectCode", projectCode); String metaJson = JSON.toJSONString(metaJson1); Map mapAll = new HashMap<>(); mapAll.put("instructionId", instructionId); mapAll.put("fromAccountCode", fromAccountCode); mapAll.put("fromAccountName", fromAccountName); mapAll.put("toAccountCode", toAccountCode); mapAll.put("toAccountName", toAccountName); mapAll.put("toAccountType", toAccountType); mapAll.put("payAmount", payAmount); mapAll.put("paymentOrderType", paymentOrderType); mapAll.put("source", "OA"); mapAll.put("note", note); mapAll.put("toBank", toBank); mapAll.put("securityCode", securityCode); mapAll.put("metaJson", metaJson); mapAll.put("applyDepartment", applyDepartment); String response = UtilHttp.doPost(url, headers, null, null, mapAll); log.info("非物流付款单 - 支付成功 [凭证号: {}, 金额: {}], 响应: {}", instructionId, payAmount, response); JSONObject jsonObject = JSON.parseObject(response); // 获取 data 对象 JSONObject redata = jsonObject.getJSONObject("data"); // 从 data 中获取 message String message = redata.getString("message"); String code = redata.getString("code"); String zdqk = "C0000".equals(code) ? "制单成功" : "制单异常"; Map objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("radioField_mel5n51w", zdqk); objectObjectHashMap.put("textareaField_mel5n51x", message); ydClient.operateData(YDParam.builder() .formInstanceId(formInstanceId) .updateFormDataJson(JSON.toJSONString(objectObjectHashMap)) .build(), YDConf.FORM_OPERATION.update); } return McR.success("处理完成"); } @Override public McR lilinJG(Map map) throws IOException { // 1. 查询所有需要处理的单据(状态为“已审批待付款”或“已审批部分付款”) List list = (List) ydClient.queryData(YDParam.builder() .formUuid("FORM-754586D31BF6414586E5C20DB3774A7320CV") .searchFieldJson(JSONObject.toJSONString(Arrays.asList( new YDSearch("selectField_ma0w9yrb", Arrays.asList("已审批待付款", "已审批部分付款"), "SelectField", YDSearch.Type.RADIO_FIELD, YDSearch.Operator.CONTAINS) ))) .build(), YDConf.FORM_QUERY.retrieve_list_all).getData(); if (list == null || list.isEmpty()) { log.info("没有找到需要处理的单据"); return McR.success("无待处理数据"); } log.info("共查询到 {} 条待处理单据", list.size()); // 公共参数提前准备(安全码、URL、请求头等) String url = "https://x.xencio.com/c4c3/api/payment/transferStatus"; String securityCode = String.valueOf(token().getData()); Map headers = new HashMap<>(); headers.put("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb"); headers.put("content-type", "application/x-www-form-urlencoded"); Map params = new HashMap<>(); params.put("securityCode", securityCode); int successCount = 0; int failCount = 0; List failedIds = new ArrayList<>(); // 2. 遍历 list,逐个执行原 lilinJG 中的处理逻辑 for (Map item : list) { String formInstanceId = String.valueOf(item.get("formInstanceId")); if (formInstanceId == null || "null".equals(formInstanceId.trim()) || formInstanceId.trim().isEmpty()) { log.warn("跳过无效的 formInstanceId: {}", item.get("formInstanceId")); continue; } try { log.info("开始处理单据: formInstanceId={}", formInstanceId); // ===== 开始执行原 lilinJG 方法中的核心逻辑 ===== Map data = (Map) item.get("formData"); if (data == null) { log.warn("获取表单数据为空,formInstanceId: {}", formInstanceId); failCount++; failedIds.add(formInstanceId); continue; } log.info("form data: {}", data); String fklx = String.valueOf(data.get("selectField_m9ze3rjf")); // 付款类型 String mainInstructionId = String.valueOf(data.get("serialNumberField_m9ze3rjd")); // 主表流水号 // ===== 区分处理:是否为物流付款单 ===== if ("物流付款单".equals(fklx)) { // 物流付款单:处理子表 List> tableField = (List>) data.get("tableField_m986c5os"); if (tableField == null || tableField.isEmpty()) { log.warn("物流付款单但子表为空,formInstanceId: {}", formInstanceId); failCount++; failedIds.add(formInstanceId); continue; } List> updatedRows = new ArrayList<>(); int completedCount = 0; String zfqk = ""; String message = ""; long bankTrxTime = 0L; for (int i = 0; i < tableField.size(); i++) { Map row = new HashMap<>(tableField.get(i)); // 复制原数据用于更新 String subInstructionId = String.valueOf(row.get("textField_mdnuob9a")); // 子表流水号 // String xmfzr = String.valueOf(row.get("employeeField_m9lfmh1r_id")); // 项目负责人 // 查询子表支付状态 params.put("instructionId", subInstructionId); String response = UtilHttp.doGet(url, headers, params); log.info("查询子表支付状态 [instructionId: {}], 响应: {}", subInstructionId, response); JSONObject jsonResponse = JSON.parseObject(response); JSONObject dataObj = jsonResponse.getJSONObject("data"); String code = dataObj.getString("code"); String bankTrxTimeStr = dataObj.getString("bankTrxTime"); // 修复:添加空值检查 if (bankTrxTimeStr != null && !bankTrxTimeStr.trim().isEmpty()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date date = sdf.parse(bankTrxTimeStr); bankTrxTime = date.getTime(); // 获取时间戳(毫秒) } catch (ParseException e) { log.warn("时间格式解析失败: {}", bankTrxTimeStr, e); bankTrxTime = 0L; // 解析失败时设为0 } } else { bankTrxTime = 0L; // 空字符串时设为0 } zfqk = "P0000".equals(code) ? "支付成功" : "支付异常"; message = dataObj != null ? dataObj.getString("message") : ""; // long bankTrxTime = dataObj != null ? LocalDateTime.parse(dataObj.getString("bankTrxTime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) // .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : 0L; String status = "未完成"; if (message != null && message.contains("成功")) { status = "已完成"; completedCount++; } // 更新子表字段:selectField_mdmwfibp row.put("selectField_mdmwfibp", status); // row.put("employeeField_m9lfmh1r", xmfzr); row.remove("employeeField_m9lfmh1r"); updatedRows.add(row); } // 构建要更新的子表数据 Map updateData = new HashMap<>(); updateData.put("tableField_m986c5os", updatedRows); updateData.put("radioField_mel5n51w", zfqk); updateData.put("textareaField_mel5n51x", message); // 更新主表状态 String mainStatus; if (completedCount == 0) { mainStatus = "已审批待付款"; } else if (completedCount == updatedRows.size()) { mainStatus = "已审批已付款"; if (bankTrxTime > 0) { updateData.put("dateField_maw6ci7a", bankTrxTime); updateData.put("dateField_me2m3mmd", bankTrxTime); } } else { mainStatus = "已审批部分付款"; } updateData.put("selectField_ma0w9yrb", mainStatus); // 提交更新 ydClient.operateData(YDParam.builder() .formInstanceId(formInstanceId) .updateFormDataJson(JSON.toJSONString(updateData)) .build(), YDConf.FORM_OPERATION.update); log.info("【物流】状态更新完成,主表状态: {}", mainStatus); successCount++; } else { // 非物流付款单:主表单处理 if (mainInstructionId == null || mainInstructionId.isEmpty()) { log.warn("主表流水号为空,formInstanceId: {}", formInstanceId); failCount++; failedIds.add(formInstanceId); continue; } params.put("instructionId", mainInstructionId); String response = UtilHttp.doGet(url, headers, params); log.info("查询主表支付状态 [instructionId: {}], 响应: {}", mainInstructionId, response); JSONObject jsonResponse = JSON.parseObject(response); JSONObject dataObj = jsonResponse.getJSONObject("data"); String message = dataObj != null ? dataObj.getString("message") : ""; String code = dataObj.getString("code"); String bankTrxTimeStr = dataObj.getString("bankTrxTime"); long bankTrxTime = 0L; // 初始化为0 // 修复:添加空值检查 if (bankTrxTimeStr != null && !bankTrxTimeStr.trim().isEmpty()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date date = sdf.parse(bankTrxTimeStr); bankTrxTime = date.getTime(); // 获取时间戳(毫秒) } catch (ParseException e) { log.warn("时间格式解析失败: {}", bankTrxTimeStr, e); bankTrxTime = 0L; // 解析失败时设为0 } } String zfqk = "P0000".equals(code) ? "支付成功" : "支付异常"; Map updateData = new HashMap<>(); updateData.put("selectField_ma0w9yrb", "已审批已付款"); updateData.put("radioField_mel5n51w", zfqk); updateData.put("textareaField_mel5n51x", message); if (message != null && message.contains("成功")) { if (bankTrxTime > 0) { updateData.put("dateField_maw6ci7a", bankTrxTime); updateData.put("dateField_me2m3mmd", bankTrxTime); } ydClient.operateData(YDParam.builder() .formInstanceId(formInstanceId) .updateFormDataJson(JSON.toJSONString( updateData)) .build(), YDConf.FORM_OPERATION.update); log.info("【非物流】支付成功,已更新状态"); successCount++; } else { updateData.remove("selectField_ma0w9yrb"); ydClient.operateData(YDParam.builder() .formInstanceId(formInstanceId) .updateFormDataJson(JSON.toJSONString( updateData)) .build(), YDConf.FORM_OPERATION.update); log.info("【非物流】支付未成功,状态未更新"); failCount++; failedIds.add(formInstanceId); } } // ===== 单条处理结束 ===== } catch (Exception e) { log.error("处理单据失败: formInstanceId={}", formInstanceId, e); failCount++; failedIds.add(formInstanceId); } } // 3. 返回批量处理结果 return McR.success("批量状态同步完成"); } @Override public McR lilinLS(Map map) { List khdaList = Arrays.asList( "1001260509024819590", "121911279910703", "1001260509424880696", "931004010000963305", "1001260509324868573", "440382314019", "1001260509324808614", "31050161373600008173", "1001260509424865022", "1001260509300324484", "1001260509300325413" ); // 获取 token 一次 String securityCode; try { securityCode = String.valueOf(token().getData()); if (securityCode == null || securityCode.isEmpty()) { log.error("获取 securityCode 失败"); return McR.errorParam("安全码获取失败"); } } catch (Exception e) { log.error("调用 token() 异常", e); return McR.errorParam("认证信息获取失败"); } OkHttpClient client = new OkHttpClient(); for (String accountNo : khdaList) { Response response = null; try { if (accountNo == null || accountNo.trim().isEmpty()) { log.warn("跳过空 accountNo"); continue; } 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")); // 构建 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.debug("银行接口响应原始数据: {}", jsonStr); 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: {}", accountNo); continue; } List> extractedList = new ArrayList<>(); for (int i = 0; i < statementList.size(); i++) { JSONObject item = statementList.getJSONObject(i); if (item == null) continue; Map extractedItem = new HashMap<>(); String bankStatementId = getStringValue(item, "bankStatementId"); String bankComments = getStringValue(item, "bankComments"); String crAmount = getStringValue(item, "crAmount"); String trxDate = getStringValue(item, "trxDate"); String createDate = getStringValue(item, "createDate"); 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"); // 对手方账户名称 Long timestamp = null; if (trxDate != null && !trxDate.isEmpty()) { try { timestamp = LocalDateTime.parse(trxDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } catch (Exception e) { log.warn("日期解析失败: {}", trxDate); } } Long timestamp1 = null; if (createDate != null && !createDate.isEmpty()) { try { timestamp1 = LocalDateTime.parse(createDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } catch (Exception e) { log.warn("日期解析失败: {}", createDate); } } extractedItem.put("bankStatementId", bankStatementId); extractedItem.put("bankComments", bankComments); extractedItem.put("crAmount", crAmount); extractedItem.put("accountName", accountName); extractedItem.put("trxDate", trxDate); extractedItem.put("userRemarks", userRemarks); extractedItem.put("customerName", customerName); extractedList.add(extractedItem); // 检查是否已存在该对账单记录 boolean exists = false; int maxRetries = 3; long retryDelayMs = 1000; // 1秒后重试 for (int attempt = 1; attempt <= maxRetries; attempt++) { try { List list = (List) ydClient.queryData( YDParam.builder() .formUuid("FORM-AF6E9FBF8F7642D59A333BC9EF3DF3FB836A") .appType("APP_RPH7R3LF3SMXLRDY1ZJW") .systemToken("7M866K91D4LVACB4EADAZ5UJG7IN3OGA33WAMNT") .searchCondition(JSON.toJSONString(UtilMap.map("textField_mdh05xw6", bankStatementId))) .build(), YDConf.FORM_QUERY.retrieve_list_all ).getData(); exists = list != null && !list.isEmpty(); break; // ✅ 查询成功,跳出重试循环 } catch (Exception e) { String errorMsg = e.getMessage(); // 🔁 判断是否是“可重试”的临时错误 boolean isTransientError = errorMsg != null && (errorMsg.contains("temporary failure") || errorMsg.contains("500") || errorMsg.contains("timeout") || errorMsg.contains("The request has failed due to a temporary failure of the server") || errorMsg.contains("connection") || errorMsg.contains("access_token")); log.warn("查询宜搭系统失败,第 {} 次尝试,bankStatementId: {},错误: {}", attempt, bankStatementId, e.getMessage()); if (attempt == maxRetries) { // ❌ 最后一次重试仍失败,才抛出异常 log.error("查询宜搭系统最终失败,已重试 {} 次,bankStatementId: {}", maxRetries, bankStatementId, e); throw new RuntimeException("查询宜搭失败,bankStatementId=" + bankStatementId, e); } if (isTransientError) { // ✅ 是临时错误,等待后重试 try { Thread.sleep(retryDelayMs * attempt); // 指数退避:1s, 2s, 3s... } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new RuntimeException("重试等待被中断", ie); } } else { // ❌ 非临时错误(如参数错误、表单不存在),直接放弃重试 log.error("查询失败:非临时性错误,不再重试,bankStatementId: {}", bankStatementId, e); throw new RuntimeException("查询宜搭失败(非临时错误):" + errorMsg, e); } } } if (exists) { log.debug("记录已存在,跳过: bankStatementId={}", bankStatementId); continue; } // 查询客户主数据 String khformInstanceId = null; String khaccountName = null; String khaccountbh = null; try { List khlist = (List) ydClient.queryData( YDParam.builder() .formUuid("FORM-E18CC7F3495B45BB852CB386F325BF03IAS3") .appType("APP_RPH7R3LF3SMXLRDY1ZJW") .systemToken("7M866K91D4LVACB4EADAZ5UJG7IN3OGA33WAMNT") .searchCondition(JSON.toJSONString(UtilMap.map("textField_m8sjaafp, aa", customerName, ""))) .build(), YDConf.FORM_QUERY.retrieve_list_all ).getData(); if (khlist != null && !khlist.isEmpty()) { for (Map khitem : khlist) { Map khformData = (Map) khitem.get("formData"); if (khformData != null && customerName.equals(khformData.get("textField_m8sjaafp"))) { khformInstanceId = (String) khitem.get("formInstanceId"); khaccountName = (String) khformData.get("textField_m8sjaafp"); khaccountbh = (String) khformData.get("serialNumberField_m8sjaafi"); break; } } } else { khaccountName = customerName; } if (khformInstanceId == null || khaccountName == null) { log.warn("未找到匹配的客户信息: customerName={}", customerName); } // 构造 formData Map formData = new HashMap<>(); formData.put("dateField_m8yeduje", timestamp1 != null ? timestamp1 : System.currentTimeMillis()); formData.put("dateField_mbg6gyre", timestamp != null ? timestamp : System.currentTimeMillis()); formData.put("numberField_m9ibr418", crAmount); formData.put("employeeField_m8yeduj3", Arrays.asList("275412081437800471")); formData.put("textField_mdh05xw6", bankStatementId); formData.put("textField_m9ibr419", userRemarks); formData.put("textField_mdh51nxq", userMemo); formData.put("textField_mdh51nxr", transFlag); formData.put("textField_mdh51nxs", catalogName); formData.put("selectField_m982msou", accountName); formData.put("textField_megl2h3a", khaccountName); formData.put("numberField_megl2h3k", crAmount); formData.put("radioField_me267g3r", "接口创建"); if (khaccountName != null && khformInstanceId != null) { formData.put("associationFormField_m8yeduj1", Arrays.asList(getkhAss(khaccountName, khformInstanceId))); formData.put("textField_m9i9k5cj", khaccountbh); } formData.put("textField_mbh8usao", khaccountName); // 提交创建流程 ydClient.operateData( YDParam.builder() .formUuid("FORM-AF6E9FBF8F7642D59A333BC9EF3DF3FB836A") .processCode("TPROC--FPB66VB19FKVVL56E43NW6XQCP7T3URA33WAML3") .formDataJson(JSON.toJSONString(formData)) .userId("275412081437800471") .build(), YDConf.FORM_OPERATION.start ); log.info("成功创建对账记录: bankStatementId={}", bankStatementId); } catch (Exception e) { log.error("创建对账记录失败: bankStatementId={}", bankStatementId, e); } } log.info("对账单同步完成,accountNo={},共处理 {} 条", accountNo, extractedList.size()); } catch (IOException e) { log.error("网络IO异常: accountNo={}", accountNo, e); } catch (Exception e) { log.error("处理账号异常: accountNo={}", accountNo, e); } finally { // 确保 response 被安全关闭 if (response != null) { try { response.close(); } catch (Exception e) { log.warn("关闭 HTTP 响应失败", e); } } } } return McR.success("所有账号同步完成"); } // 工具方法:安全获取字符串值 private String getStringValue(JSONObject json, String key) { Object value = json.get(key); return value == null ? "" : value.toString(); } @Override public McR lilinLSCF(Map map) throws IOException { String formInstanceId = String.valueOf(map.get("formInstanceId")); if (formInstanceId == null || formInstanceId.trim().isEmpty()) { return McR.errorParam("formInstanceId 不能为空"); } log.info("开始处理对账单拆分,formInstanceId: {}", formInstanceId); String bankStatementIdStr = String.valueOf(map.get("bankStatementId")); if (bankStatementIdStr == null || bankStatementIdStr.trim().isEmpty()) { return McR.errorParam("bankStatementId 不能为空"); } // 查询表单数据 Map data; try { data = (Map) ydClient.queryData(YDParam.builder() .formInstId(formInstanceId) .appType(ydConf.getAppType()) .systemToken(ydConf.getSystemToken()) .userId(ddConf.getOperator()) .build(), YDConf.FORM_QUERY.retrieve_id).getFormData(); } catch (Exception e) { log.error("查询宜搭表单失败,formInstanceId: {}", formInstanceId, e); return McR.errorParam("查询表单数据失败"); } if (data == null) { log.warn("表单数据为空,formInstanceId: {}", formInstanceId); return McR.errorParam("表单数据为空"); } // 提取字段(安全获取) String userMemo = getStringValue(data, "textField_mdh51nxq"); String transFlag = getStringValue(data, "textField_mdh51nxr"); String catalogName = getStringValue(data, "textField_mdh51nxs"); // 处理子表数据 List> tableField = (List>) data.get("tableField_m9m8zhyy"); List> tableField1 = (List>) data.get("tableField_m8yanvjk"); List> subBankStatementList = new ArrayList<>(); // 统计分布:是否有“以产定销”和“以销定产” boolean hasChanXiao = false; // 以产定销 boolean hasXiaoChan = false; // 以销定产 if (tableField != null) { for (Map row : tableField) { if (row == null) continue; String xmlx = getStringValue(row, "selectField_mfosn87t"); if ("以产定销".equals(xmlx)) { hasChanXiao = true; } else { // 默认按“以销定产”处理(包含“以销定产”及其他未知类型) hasXiaoChan = true; } } } // 根据分布决定处理策略 if (hasChanXiao && !hasXiaoChan) { // 情况1:全是“以产定销” → 使用 tableField1 的所有行 if (tableField1 != null) { for (int i = 0; i < tableField1.size(); i++) { Map row = tableField1.get(i); if (row == null) continue; Map newItem = buildItemForChanXiao(row, i, userMemo, transFlag, catalogName); subBankStatementList.add(newItem); } } } else if (hasXiaoChan && !hasChanXiao) { // 情况2:全是“以销定产” → 使用 tableField 的所有行 if (tableField != null) { for (int i = 0; i < tableField.size(); i++) { Map row = tableField.get(i); if (row == null) continue; Map newItem = buildItemForXiaoChan(row, i, userMemo, transFlag, catalogName); subBankStatementList.add(newItem); } } } else if (hasChanXiao && hasXiaoChan) { // 情况3:混合存在 // a. tableField 中只保留“以销定产”的行 if (tableField != null) { for (int i = 0; i < tableField.size(); i++) { Map row = tableField.get(i); if (row == null) continue; String xmlx = getStringValue(row, "selectField_mfosn87t"); if ("以销定产".equals(xmlx)) { Map newItem = buildItemForXiaoChan(row, i, userMemo, transFlag, catalogName); subBankStatementList.add(newItem); } // “以产定销”的行被舍弃 } } // b. 加入 tableField1 的全部数据(“以产定销”专用) if (tableField1 != null) { for (int i = 0; i < tableField1.size(); i++) { Map row = tableField1.get(i); if (row == null) continue; Map newItem = buildItemForChanXiao(row, i, userMemo, transFlag, catalogName); subBankStatementList.add(newItem); } } } // 构建主请求体 Map requestBody = new HashMap<>(); try { requestBody.put("bankStatementId", Integer.parseInt(bankStatementIdStr)); } catch (NumberFormatException e) { log.error("bankStatementId 格式错误: {}", bankStatementIdStr); return McR.errorParam("bankStatementId 必须为整数"); } requestBody.put("subBankStatementList", subBankStatementList); // 请求参数 String url = "https://x.xencio.com/c4c3/api/sub/bs/splitBankStatement"; String securityCode = String.valueOf(token().getData()); if (securityCode == null || securityCode.isEmpty()) { log.error("获取 securityCode 失败"); return McR.errorParam("认证失败"); } Map headers = new HashMap<>(); headers.put("x-xencio-client-id", "7dc3a31209b94a91ba40a44358fe70eb"); // Map params = new HashMap<>(); headers.put("securityCode", securityCode); // 第一次调用:拆分对账单 String response; try { response = UtilHttp.doPost(url, headers, new HashMap<>(), requestBody); } catch (Exception e) { log.error("调用 splitBankStatement 接口失败", e); return McR.errorParam("接口调用失败: splitBankStatement"); } JSONObject jsonResponse; try { jsonResponse = JSON.parseObject(response); } catch (Exception e) { log.error("响应 JSON 解析失败: {}", response); return McR.errorParam("响应格式错误"); } // 检查响应是否成功(假设返回 { "code": 0, "data": { ... } }) Integer code = jsonResponse.getInteger("code"); if (code == null || code != 200) { String msg = jsonResponse.getString("msg"); log.warn("splitBankStatement 接口调用失败,code: {}, msg: {}", code, msg); return McR.errorParam("接口返回错误: " + msg); } JSONObject dataObj = jsonResponse.getJSONObject("data"); if (dataObj == null) { log.warn("响应中缺少 data 字段: {}", response); return McR.errorParam("响应数据缺失"); } JSONObject subBankStatement = dataObj.getJSONObject("subBankStatement"); if (subBankStatement == null) { log.warn("响应中缺少 subBankStatement 字段"); return McR.errorParam("拆分结果缺失"); } JSONArray subBankStatementList1 = subBankStatement.getJSONArray("subBankStatementList"); if (subBankStatementList1 == null || subBankStatementList1.isEmpty()) { log.info("拆分结果为空"); return McR.success("拆分成功,但无明细"); } // 封装返回结果 List> result = new ArrayList<>(); for (int i = 0; i < subBankStatementList1.size(); i++) { JSONObject item = subBankStatementList1.getJSONObject(i); Map mapItem = new HashMap<>(); mapItem.put("id", item.getInteger("id")); String projectInfo = item.getString("projectInfo"); mapItem.put("projectInfo", projectInfo != null ? projectInfo : ""); String businessSegment = item.getString("businessSegment"); mapItem.put("businessSegment", businessSegment != null ? businessSegment : ""); String businessProjectStatus = item.getString("businessProjectStatus"); mapItem.put("businessProjectStatus", businessProjectStatus != null ? businessProjectStatus : ""); String projectManager = item.getString("projectManager"); mapItem.put("projectManager", projectManager != null ? projectManager : ""); String projectCode = item.getString("projectCode"); mapItem.put("projectCode", projectCode != null ? projectCode : ""); result.add(mapItem); } int successCount = 0, failCount = 0; String updateUrl = "https://x.xencio.com/c4c3/api/sub/bs/updateProjectInfo"; for (Map item : result) { try { String updateResponse = UtilHttp.doPost(updateUrl, headers, new HashMap<>(), item); // 可选:判断 updateResponse 是否成功 successCount++; } catch (Exception e) { log.error("更新 projectInfo 失败,id: {}", item.get("id"), e); failCount++; } } log.info("拆分完成,共 {} 条,更新成功 {},失败 {}", result.size(), successCount, failCount); // 返回结果(可附加统计) return McR.success(result); } // 构建“以产定销”类型的数据(来自 tableField1) private Map buildItemForChanXiao(Map row, int index, String userMemo, String transFlag, String catalogName) { Map item = new HashMap<>(); // amount 取 numberField_md5e3oib BigDecimal amount = getAmountFromMap(row, "numberField_mfq6budd"); // projectInfo = textField_md5e3oih + "-" + textField_md5e3oig String projectCode = getStringValue(row, "textField_md5e3oih"); String businessSegment = getStringValue(row, "selectField_mkamgsc7"); String businessProjectStatus = getStringValue(row, "selectField_mkamgsc5"); String projectManager = getStringValue(row, "employeeField_mkamgscb").replace("[\"", "").replace("\"]", "").trim(); String projectInfo = getStringValue(row, "textField_md5e3oig"); // String projectInfo = (part1 != null ? part1 : "") + "-" + (part2 != null ? part2 : ""); item.put("itemIndex", index + 1); item.put("amount", amount != null ? amount.doubleValue() : 0.0); item.put("projectInfo", projectInfo); item.put("projectCode", projectCode); item.put("businessSegment", businessSegment); item.put("businessProjectStatus", businessProjectStatus); item.put("projectManager", projectManager); item.put("userMemo", userMemo); item.put("trxFlag", transFlag); item.put("catalogName", catalogName); return item; } // 构建“以销定产”类型的数据(来自 tableField) private Map buildItemForXiaoChan(Map row, int index, String userMemo, String transFlag, String catalogName) { Map item = new HashMap<>(); String projectCode = getStringValue(row, "textField_m9i9k5cl"); String projectInfo = getStringValue(row, "textField_m8yedujm"); // String projectInfo = (part1 != null ? part1 : "") + "-" + (part2 != null ? part2 : ""); String businessSegment = getStringValue(row, "selectField_mjqhty52"); String businessProjectStatus = getStringValue(row, "selectField_m9ks0c66"); String projectManager = getStringValue(row, "employeeField_m8yedujw").replace("[\"", "").replace("\"]", "").trim(); // amount 取 numberField_m9u2a5tf BigDecimal amount = getAmountFromMap(row, "numberField_m9u2a5tf"); item.put("itemIndex", index + 1); item.put("amount", amount != null ? amount.doubleValue() : 0.0); item.put("projectInfo", projectInfo); item.put("projectCode", projectCode); item.put("businessSegment", businessSegment); item.put("businessProjectStatus", businessProjectStatus); item.put("projectManager", projectManager); item.put("userMemo", userMemo); item.put("trxFlag", transFlag); item.put("catalogName", catalogName); return item; } @Override public McR taskPLJG() { List list = (List) ydClient.queryData(YDParam.builder() .formUuid("FORM-754586D31BF6414586E5C20DB3774A7320CV") .searchFieldJson(JSONObject.toJSONString(Arrays.asList( new YDSearch("selectField_ma0w9yrb", "已审批已付款", "SelectField", YDSearch.Type.RADIO_FIELD, YDSearch.Operator.EQ), new YDSearch("radioField_mimhsd0h", "否", "是否创建付款通知", YDSearch.Type.RADIO_FIELD, YDSearch.Operator.EQ) ))) .build(), YDConf.FORM_QUERY.retrieve_list_all).getData(); if (list == null || list.isEmpty()) { log.info("没有找到需要处理的单据"); return McR.success("无待处理数据"); } int successCount = 0; int failCount = 0; for (Map item : list) { try { String formInstanceId = getStringValue(item, "formInstanceId"); if (formInstanceId == null || formInstanceId.isEmpty()) { log.warn("跳过:formInstanceId 为空"); continue; } Map data = (Map) item.get("formData"); if (data == null) { log.warn("formInstanceId={} 的 formData 为空,跳过", formInstanceId); continue; } String fklx = getStringValue(data, "selectField_m9ze3rjf"); // 付款类型 String mainInstructionId = getStringValue(data, "serialNumberField_m9ze3rjd"); // 主表流水号 // 查询目标表单是否已存在该 mainInstructionId 的记录 List list1 = (List) ydClient.queryData( YDParam.builder() .formUuid("FORM-6B8A683A23524D3596C8C6CA13327EF3552K") .appType("APP_RPH7R3LF3SMXLRDY1ZJW") .systemToken("7M866K91D4LVACB4EADAZ5UJG7IN3OGA33WAMNT") .searchCondition(JSON.toJSONString(UtilMap.map("textField_mdsk7rlm", mainInstructionId))) .build(), YDConf.FORM_QUERY.retrieve_list_all ).getData(); // 如果目标表单中已存在该流水号,则跳过,不再新增 if (list1 != null && !list1.isEmpty()) { log.info("已存在重复数据,跳过插入:mainInstructionId={}", mainInstructionId); updateSourceBillStatus(formInstanceId, "是"); successCount++; continue; } // 继续提取其他字段 String note = getStringValue(data, "textField_m9ze3rk3"); // 付款用途 String toAccountCode = getStringValue(data, "textField_m9ze3rjs"); // 收款账号 String toAccountName = getStringValue(data, "textField_m9ze3rjl"); // 收款户名 List sqr = UtilMap.getList(data, "employeeField_madmj9kw_id");// 申请人 String fklsh = getStringValue(data, "textField_ma13ih7u"); // 付款流程编号 String toBank = getStringValue(data, "textField_m9ze3rjr"); // 收款银行支行 String cghtbh = getStringValue(data, "textField_madmzxcf"); // 采购合同编号 String fkqs = getStringValue(data, "radioField_m9rva5bm"); // 付款期数 // long zfsj = System.currentTimeMillis();//支付时间 // String zfsj = getStringValue(data, "dateField_me2m3mmd");//支付时间 BigDecimal PayAmount; List> updateList = new ArrayList<>(); if ("物流付款单".equals(fklx)) { List> tableField = (List>) data.get("tableField_m986c5os"); PayAmount = BigDecimal.ZERO; // 初始化累加器 if (tableField != null) { for (Map row : tableField) { String instructionId = getStringValue(row, "textField_mdnuob9a"); String xmbh = getStringValue(row, "textField_m9lfmh1p"); String payAmountStr = getStringValue(row, "numberField_m8yf6gn1"); BigDecimal payAmount1 = BigDecimal.ZERO; if (payAmountStr != null && !payAmountStr.trim().isEmpty()) { try { payAmount1 = new BigDecimal(payAmountStr.trim()); PayAmount = PayAmount.add(payAmount1); } catch (NumberFormatException e) { // 处理转换失败的情况(可选:记录日志或忽略) System.err.println("Invalid number format: " + payAmountStr); } } Map tablemap = new HashMap<>(); tablemap.put("associationFormField_ma13k7v2", Arrays.asList(getAss(mainInstructionId, formInstanceId))); tablemap.put("selectField_m9ze3rjf", fklx); tablemap.put("numberField_m9ze3rk4", payAmountStr); tablemap.put("textField_m9ze3rk3", note); tablemap.put("employeeField_maopzwym", sqr); tablemap.put("textField_m9ze3rjl", toAccountName); tablemap.put("textField_m9ze3rjr", toBank); tablemap.put("textField_m9ze3rjs", toAccountCode); tablemap.put("textField_ma13k7v3", instructionId); tablemap.put("textField_ma13k7v4", fklsh); tablemap.put("textField_madmzxce", xmbh); tablemap.put("textField_madmzxcf", cghtbh); tablemap.put("radioField_m9rva5bm", fkqs); updateList.add(tablemap); } } } else { String instructionId = mainInstructionId; PayAmount = safeGetBigDecimal(data, "numberField_m9ze3rk4"); String xmbh = getStringValue(data, "textField_madmzxce"); Map tablemap = new HashMap<>(); tablemap.put("associationFormField_ma13k7v2", Arrays.asList(getAss(mainInstructionId, formInstanceId))); tablemap.put("selectField_m9ze3rjf", fklx); tablemap.put("numberField_m9ze3rk4", PayAmount); tablemap.put("textField_m9ze3rk3", note); tablemap.put("employeeField_maopzwym", sqr); tablemap.put("textField_m9ze3rjl", toAccountName); tablemap.put("textField_m9ze3rjr", toBank); tablemap.put("textField_m9ze3rjs", toAccountCode); tablemap.put("textField_ma13k7v3", instructionId); tablemap.put("textField_ma13k7v4", fklsh); tablemap.put("textField_madmzxce", xmbh); tablemap.put("textField_madmzxcf", cghtbh); tablemap.put("radioField_m9rva5bm", fkqs); updateList.add(tablemap); } // 构建目标数据 Map formData = new HashMap<>(); formData.put("tableField_ma13k7v1", updateList); formData.put("dateField_me2m2oeu", data.get("dateField_me2m3mmd")); formData.put("selectField_megv3ask", "接口创建"); formData.put("numberField_mac3ccn8", PayAmount); formData.put("textField_mdsk7rlm", mainInstructionId); // 主流水号用于去重 formData.put("employeeField_m8yf6gkl", Arrays.asList("275412081437800471")); try { ydClient.operateData(YDParam.builder() .formUuid("FORM-6B8A683A23524D3596C8C6CA13327EF3552K") .formDataJson(JSON.toJSONString(formData)) // .userId("275412081437800471") .build(), YDConf.FORM_OPERATION.create); ydClient.operateData(YDParam.builder() .formInstId(formInstanceId) .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("radioField_mimhsd0h","是"))) .build(), YDConf.FORM_OPERATION.update); log.info("成功插入新数据:mainInstructionId={}, 付款类型={}", mainInstructionId, fklx); successCount++; } catch (Exception e) { log.info("处理单据异常:mainInstructionId={}, error={}", mainInstructionId, e.getMessage(), e); failCount++; } } catch (Exception e) { log.error("处理单据时发生异常", e); } } return McR.success(); } @Async @Override public McR lilinBatchUpdate(Map map) throws IOException { String formInstanceId = String.valueOf(map.get("formInstanceId")); log.info("formInstanceId:{}", formInstanceId); // 根据实例ID获取表单数据 Map data = (Map) ydClient.queryData(YDParam.builder() .formInstId(formInstanceId) .appType(ydConf.getAppType()) .systemToken(ydConf.getSystemToken()) .userId(ddConf.getOperator()) .build(), YDConf.FORM_QUERY.retrieve_id).getFormData(); if (data == null) { log.warn("formData 为空, formInstanceId:{}", formInstanceId); return McR.errorParam("formData 为空"); } List list = (List) data.get("tableField_ma13k7v1"); if (list == null || list.isEmpty()) { return McR.errorParam("表格数据为空"); } long timestamp = System.currentTimeMillis(); String gszh = (String) data.get("textField_megowhuu");//公司账号 Map formData = new HashMap<>(); formData.put("selectField_ma0w9yrb", "已审批待付款"); formData.put("dateField_maw6ci79", timestamp); formData.put("textField_mdfnuyl9", gszh); // 4. 处理每行数据,提取instanceId for (Map row : list) { try { // 获取associationFormField_ma13k7v2_id字段 String associationField = (String) row.get("associationFormField_ma13k7v2_id"); if (associationField == null) { continue; } // 清理JSON字符串 String cleanedJson = associationField .replaceAll("^\"|\"$", "") .replace("\\\"", "\""); // 解析JSON数组 JSONArray innerArray = JSON.parseArray(cleanedJson); if (innerArray == null || innerArray.isEmpty()) { continue; } // 提取instanceId JSONObject firstItem = innerArray.getJSONObject(0); String instanceId = firstItem.getString("instanceId"); if (instanceId != null && !instanceId.isEmpty()) { ydClient.operateData(YDParam.builder() .formInstanceId(instanceId) .updateFormDataJson(JSON.toJSONString(formData)) .build(), YDConf.FORM_OPERATION.update); log.debug("成功更新instanceId: {}", instanceId); } } catch (Exception e) { log.error("处理行数据异常, row: {}, 错误: {}", row, e.getMessage(), e); } } return McR.success(); } private void updateSourceBillStatus(String formInstanceId, String status) { try { ydClient.operateData(YDParam.builder() .formInstId(formInstanceId) .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("radioField_mimhsd0h", status))) .build(), YDConf.FORM_OPERATION.update); } catch (Exception e) { log.error("更新源单据状态失败:formInstanceId={}", formInstanceId, e); throw e; // 抛出异常让上层处理 } } private Object getAss(String title, String id) { return UtilMap.map("appType, formUuid, formType, instanceId, title, subTitle", "APP_RPH7R3LF3SMXLRDY1ZJW", "FORM-754586D31BF6414586E5C20DB3774A7320CV", "receipt", id, title, ""); } private Object getkhAss(String title, String id) { return UtilMap.map("appType, formUuid, formType, instanceId, title, subTitle", "APP_RPH7R3LF3SMXLRDY1ZJW", "FORM-E18CC7F3495B45BB852CB386F325BF03IAS3", "receipt", id, title, ""); } // 工具方法:安全获取字符串 private String getStringValue(Map data, String key) { Object val = data.get(key); return val == null ? "" : val.toString().trim(); } // 工具方法:安全获取金额(默认 0) private static BigDecimal getAmountFromMap(Map map, String key) { Object value = map.get(key); if (value == null) { log.debug("金额字段为空,key: {}", key); return BigDecimal.ZERO; } if (value instanceof Number) { // 优先处理数值类型 try { return BigDecimal.valueOf(((Number) value).doubleValue()); } catch (Exception e) { log.warn("Number 转换为 BigDecimal 失败,key: {}, value: {}", key, value, e); return BigDecimal.ZERO; } } // 尝试字符串解析 String strValue = value.toString().trim(); if (strValue.isEmpty()) { return BigDecimal.ZERO; } try { return new BigDecimal(strValue); } catch (NumberFormatException e) { log.warn("金额字符串格式错误,key: {}, value: {}", key, value); return BigDecimal.ZERO; } } private static McR token() { String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String s = SecureUtil.md5("}bH5%t4_)6e3#" + today); return McR.success(s); } // 安全获取字符串值 private String safeGetString(Map formData, String key) { Object val = formData.get(key); return val == null ? "" : String.valueOf(val); } // 安全获取 double 值 private double getDoubleSafe(Map item, String key) { try { Object val = item.get(key); if (val instanceof Number) { return ((Number) val).doubleValue(); } else if (val instanceof String) { return Double.parseDouble((String) val); } return 0.0; } catch (Exception e) { return 0.0; } } private BigDecimal safeGetBigDecimal(Map formData, String key) { Object value = formData.get(key); if (value == null) return BigDecimal.ZERO; try { return new BigDecimal(value.toString()); } catch (NumberFormatException e) { return BigDecimal.ZERO; } } }