| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.zy.asrs.entity.DocType; |
| | | import com.zy.asrs.entity.Order; |
| | | 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.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Set; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * Created by Monkey D. Luffy on 2023.10.21 |
| | |
| | | @Service |
| | | public class SaveOrderSyncHandler extends AbstractHandler<String> { |
| | | @Value("${erp.address.URL}") |
| | | //端口 |
| | | private String URL; |
| | | |
| | | @Value("${erp.address.outaddressSave}") |
| | | //审核地址 |
| | | private String outaddressSave; |
| | | @Value("${erp.address.imPurinbillAdd}") |
| | | private String imPurinbillAdd; |
| | | |
| | | @Autowired |
| | | private OrderService orderService; |
| | |
| | | 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<String> start(Order order) { |
| | | //登录金蝶r |
| | | ReturnT<String> start = loginAuthenticationHandler.start(); |
| | | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd"); |
| | | |
| | | // 获取 Token |
| | | ErpSecret erpSecret = erpSecretService.selectOne(new EntityWrapper<ErpSecret>().eq("account_id", accountId)); |
| | | |
| | | // 获取 DocType |
| | | DocType docType = docTypeService.selectById(order.getDocType()); |
| | | if (null == docType) { |
| | | return SUCCESS; |
| | | } |
| | | if (docType == null) return SUCCESS; |
| | | |
| | | // 获取 KingDee 类型 |
| | | KingDeeUtilType kingDeeUtilType = KingDeeUtilType.get(docType.getDocName()); |
| | | |
| | | //条件拼接 |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("Numbers",order.getOrderNo()); |
| | | JSONObject jsonObject1 = new JSONObject(); |
| | | jsonObject1.put("data", jsonObject); |
| | | jsonObject1.put("FormId",kingDeeUtilType.correspondingFormId); |
| | | String add = jsonObject1.toJSONString(); |
| | | //上报 |
| | | // 构建请求参数 |
| | | 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<OrderDetl> orderDetlList = orderDetlService.selectList(new EntityWrapper<OrderDetl>().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<String> sendRequestAndProcessResponse(Order order, ErpSecret erpSecret, JSONObject add) { |
| | | String response = ""; |
| | | boolean success = false; |
| | | |
| | | try { |
| | | //获取Cookie值 |
| | | HashMap<String, Object> headers = new HashMap<>(); |
| | | headers.put("Cookie", start.getContent()); |
| | | // 设置请求头 |
| | | HashMap<String, Object> headers = buildRequestHeaders(erpSecret); |
| | | |
| | | // 发送请求,将 JSONObject 转换为 String |
| | | response = new HttpHandler.Builder() |
| | | .setHeaders(headers) |
| | | .setUri(URL) |
| | | .setPath(outaddressSave) |
| | | .setJson(add) |
| | | .setPath(path) |
| | | .setJson(add.toJSONString()) // 将 JSONObject 转换为 String |
| | | .build() |
| | | .doPost(); |
| | | JSONObject data = JSON.parseObject(response); |
| | | Object IsSuccess = findValueByKey(JSON.parseObject(response), "IsSuccess"); |
| | | String bool=IsSuccess.toString(); |
| | | //保存完成原订单8转6 |
| | | if(bool.equals("true")){ |
| | | success = true; |
| | | order.setSettle(6L); |
| | | orderService.update(order,new EntityWrapper<Order>().eq("order_no",order.getOrderNo())); |
| | | |
| | | // 解析响应 |
| | | 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<ErpSecret>().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(); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("fail", e); |
| | | // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg(e.getMessage()); |
| | | } finally { |
| | | try { |
| | | // 保存接口日志 |
| | | apiLogService.save( |
| | | "保存", |
| | | URL+ outaddressSave, |
| | | null, |
| | | "127.0.0.1", |
| | | add, |
| | | response, |
| | | success |
| | | ); |
| | | } catch (Exception e) { |
| | | log.error("", e); |
| | | } |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | public static Object findValueByKey(JSONObject json, String key) { |
| | | Set<String> keySet = json.keySet(); |
| | | for (String k : keySet) { |
| | | Object v = json.get(k); |
| | | if (k.equals(key)) { |
| | | return v; |
| | | } else if (v instanceof JSONArray) { |
| | | int size = ((JSONArray) v).size(); |
| | | for (int i = 0; i <= size - 1; i++) { |
| | | Object result = findValueByKey((JSONObject) ((JSONArray) v).get(i), key); |
| | | if (result != null){ |
| | | return result; |
| | | |
| | | // 解析返回的响应 |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } else if (v instanceof JSONObject){ |
| | | Object result = findValueByKey((JSONObject) v, key); |
| | | if (result != null){ |
| | | return result; |
| | | } |
| | | 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 null; |
| | | |
| | | return success ? SUCCESS : FAIL; |
| | | } |
| | | |
| | | |
| | | private HashMap<String, Object> buildRequestHeaders(ErpSecret erpSecret) { |
| | | HashMap<String, Object> 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); |
| | | } |
| | | } |
| | | } |