自动化立体仓库 - WMS系统
1
21 小时以前 9126e6315288e1ea50e74c70b099974522d6b172
src/main/java/com/zy/asrs/task/kingdee/handler/SaveOrderSyncHandler.java
@@ -4,13 +4,16 @@
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;
@@ -19,8 +22,8 @@
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
@@ -29,12 +32,10 @@
@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;
@@ -44,90 +45,227 @@
    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);
        }
    }
}