package com.zy.asrs.task.kingdee.handler; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.asrs.entity.*; import com.zy.asrs.service.ApiLogService; import com.zy.asrs.service.DocTypeService; import com.zy.asrs.service.OrderService; import com.zy.asrs.service.impl.ErpSecretServiceImpl; import com.zy.asrs.service.impl.OrderDetlPakinServiceImpl; import com.zy.asrs.service.impl.OrderDetlServiceImpl; import com.zy.asrs.task.AbstractHandler; import com.zy.asrs.task.core.ReturnT; import com.zy.asrs.utils.OrderInAndOutUtil; import com.zy.common.utils.HttpHandler; import com.zy.erp.kingdee.enums.KingDeeUtilType; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.SimpleDateFormat; import java.util.*; /** * Created by Monkey D. Luffy on 2023.10.21 */ @Slf4j @Service public class SaveOrderSyncHandler extends AbstractHandler { @Value("${erp.address.URL}") private String URL; @Value("${erp.address.imPurinbillAdd}") private String imPurinbillAdd; @Autowired private OrderService orderService; @Autowired private ApiLogService apiLogService; @Autowired private DocTypeService docTypeService; @Autowired private LoginAuthenticationHandler loginAuthenticationHandler; @Autowired private ErpSecretServiceImpl erpSecretService; @Autowired private OrderDetlPakinServiceImpl orderDetlPakinService; @Autowired private OrderDetlServiceImpl orderDetlService; @Value("${erp.login.accountId}") private String accountId; @Value("${erp.login.xAcfwIdentity}") private String xAcfwIdentity; String path; @Transactional public ReturnT start(Order order) { SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd"); // 获取 Token ErpSecret erpSecret = erpSecretService.selectOne(new EntityWrapper().eq("account_id", accountId)); // 获取 DocType DocType docType = docTypeService.selectById(order.getDocType()); if (docType == null) return SUCCESS; // 获取 KingDee 类型 KingDeeUtilType kingDeeUtilType = KingDeeUtilType.get(docType.getDocName()); // 构建请求参数 JSONObject add = buildRequestParams(order, kingDeeUtilType, sdf1, sdf2); if (add == null) return FAIL.setMsg("请求参数构建失败"); // 发送请求并处理响应 return sendRequestAndProcessResponse(order, erpSecret, add); } private JSONObject buildRequestParams(Order order, KingDeeUtilType kingDeeUtilType, SimpleDateFormat sdf1, SimpleDateFormat sdf2) { List orderDetlList = orderDetlService.selectList(new EntityWrapper().eq("order_no",order.getOrderNo())); switch (kingDeeUtilType.formId) { case "PUR_RECEIVEBIll": // 进仓通知单 path = imPurinbillAdd; JSONArray billentryLkArray = new JSONArray(); JSONArray billentryArray = new JSONArray(); // 用于存储 billentry 对象 String suppCode = null; // 供应商 String boxType2 = null; // 货主/货源 // 遍历订单详情 for (OrderDetl orderDetl : orderDetlList) { suppCode = orderDetl.getSuppCode(); boxType2 = orderDetl.getBoxType2(); if (orderDetl.getQty() == 0) { continue; } // 创建 billentry_lk 对象 JSONObject billentryLk = new JSONObject() .fluentPut("id", Long.parseLong(orderDetl.getThreeCode())) .fluentPut("seq", orderDetl.getLineNumber()) .fluentPut("billentry_lk_stableid", 677270092232273922L) .fluentPut("billentry_lk_sbillid", Long.parseLong(order.getItemName())) // 主单ID .fluentPut("billentry_lk_sid", Long.parseLong(orderDetl.getThreeCode())) // 明细ID .fluentPut("billentry_lk_baseqty_old", orderDetl.getErpAnfme()) // ERP数量 .fluentPut("billentry_lk_baseqty", orderDetl.getQty()); // 作业数量 billentryLkArray.add(billentryLk); // 创建 billentry 对象,填充缺失的字段 JSONObject billentry = new JSONObject() .fluentPut("id", Long.parseLong(orderDetl.getThreeCode())) .fluentPut("warehouse_number", orderDetl.getManu()) // 仓库编号 .fluentPut("invstatus_number", "110") // 库存状态 .fluentPut("invtype_number", "110") // 库存类型 .fluentPut("outinvstatus_number", "110") .fluentPut("linetype_number", "010") // 行号类型 .fluentPut("qty", orderDetl.getQty()) // 数量 .fluentPut("material_number", orderDetl.getMatnr()) // 物料编号 .fluentPut("billentry_lk", billentryLkArray); // 将 billentry_lk 添加到 billentry billentryArray.add(billentry); } Date now = new Date(); // 生成 INR 相关请求参数 return new JSONObject() .fluentPut("data", new JSONArray(Arrays.asList( new JSONObject() .fluentPut("billno", order.getOrderNo()) .fluentPut("trdbillno", UUID.randomUUID().toString().replace("-", "")) .fluentPut("billtype_number", "im_PurInBill_STD_BT_S") .fluentPut("biztime", sdf1.format(now)) .fluentPut("exratedate", sdf1.format(now)) .fluentPut("bizorg_number", boxType2) .fluentPut("biztype_number", "110") // 货主/货源 .fluentPut("org_number", boxType2) // 货主/货源 .fluentPut("paymode", "CREDIT") .fluentPut("invscheme_number", "110") .fluentPut("billtype_number", "im_PurInBill_STD_BT_S") .fluentPut("supplier_number", suppCode) // 供应商编号 .fluentPut("billno", order.getOrderNo()) .fluentPut("billentry", billentryArray) // 将 billentry 数组添加到请求参数 ))); default: // 默认处理:可以抛出异常或返回空对象 throw new IllegalArgumentException("Unsupported formId: " + kingDeeUtilType.formId); } } private ReturnT sendRequestAndProcessResponse(Order order, ErpSecret erpSecret, JSONObject add) { String response = ""; boolean success = false; try { // 设置请求头 HashMap headers = buildRequestHeaders(erpSecret); // 发送请求,将 JSONObject 转换为 String response = new HttpHandler.Builder() .setHeaders(headers) .setUri(URL) .setPath(path) .setJson(add.toJSONString()) // 将 JSONObject 转换为 String .build() .doPost(); // 解析响应 JSONObject jsonResponse = JSON.parseObject(response); // 判断是否因为 token 过期 (errorCode = 401) if ("401".equals(jsonResponse.getString("errorCode"))) { log.error("认证失败,尝试重新获取 Token"); loginAuthenticationHandler.start(); // 刷新 token // 重新获取新的 token erpSecret = erpSecretService.selectOne(new EntityWrapper().eq("account_id", accountId)); // 重新从数据库获取新的 token // 使用新的 token 重试请求 headers.put("accesstoken", erpSecret.getAccessToken()); response = new HttpHandler.Builder() .setHeaders(headers) .setUri(URL) .setPath(path) .setJson(add.toJSONString()) // 将 JSONObject 转换为 String .build() .doPost(); } // 解析返回的响应 JSONObject data = jsonResponse.getJSONObject("data"); String errorCode = jsonResponse.getString("errorCode"); boolean status = jsonResponse.getBooleanValue("status"); // 检查接口调用的整体状态 if ("0".equals(errorCode) && status) { // 获取成功与失败的数量 int successCount = data.getInteger("successCount"); int failCount = data.getInteger("failCount"); if (failCount == 0) { success = true; log.info("接口调用成功,成功的操作数量: {}", successCount); // 获取返回的单据号和ID JSONArray resultArray = data.getJSONArray("result"); for (int i = 0; i < resultArray.size(); i++) { JSONObject resultItem = resultArray.getJSONObject(i); String billNo = resultItem.getString("number"); // 获取返回的单据号 String billId = resultItem.getString("id"); // 获取返回的ID // 判断返回的单据号与订单号是否一致 if (billNo != null && billNo.equals(order.getOrderNo())) { // 如果一致,设置订单的 number order.setNumber(billId); log.info("订单号 {} 与返回的单据号匹配,设置订单 ID 为 {}", order.getOrderNo(), billId); } } } else { log.error("接口调用失败,失败的操作数量: {}", failCount); // 如果有失败的单据,遍历 result 数组查看失败的详细信息 JSONArray resultArray = data.getJSONArray("result"); for (int i = 0; i < resultArray.size(); i++) { JSONObject resultItem = resultArray.getJSONObject(i); if (!resultItem.getBoolean("billStatus")) { // 单据处理失败,记录错误信息 String billNo = resultItem.getString("billno"); JSONArray errors = resultItem.getJSONArray("errors"); log.error("单据号: {}, 错误信息: {}", billNo, errors); } } } order.setSettle(10L); // 更新状态为 "已上报" orderService.updateById(order); } else { log.error("接口调用失败,错误信息: {}", jsonResponse.getString("message")); } } catch (Exception e) { log.error("请求失败", e); return FAIL.setMsg(e.getMessage()); } finally { // 保存接口日志 saveApiLog(add, response, success); } return success ? SUCCESS : FAIL; } private HashMap buildRequestHeaders(ErpSecret erpSecret) { HashMap headers = new HashMap<>(); headers.put("accesstoken", erpSecret.getAccessToken()); headers.put("x-acgw-identity", xAcfwIdentity); // 自定义请求头 return headers; } private void saveApiLog(JSONObject add, String response, boolean success) { try { apiLogService.save( "进仓通知单上报新增", URL + path, null, "127.0.0.1", add.toJSONString(), response, success ); } catch (Exception e) { log.error("接口日志保存失败", e); } } }