1
6 天以前 59d63f694e9f0e726820ca5f79483ec74e108e3f
rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java
@@ -459,12 +459,20 @@
            return CommonResponse.error("回传明细为空");
        }
        int allocateCount = 0;
        int erpReportCount = 0;
        List<String> errors = new ArrayList<>();
        // 对回传数据做反映射(WMS字段名 → ERP字段名)
        JSONObject mappedRoot = ParamsMapUtils.reverseApiMaps("erp", "orderId", root);
        JSONArray mappedDataArray = pickArray(mappedRoot, "Data", "data");
        if (Objects.isNull(mappedDataArray) || mappedDataArray.isEmpty()) {
            mappedDataArray = dataArray;
        }
        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject row = dataArray.getJSONObject(i);
        int allocateCount = 0;
        List<String> errors = new ArrayList<>();
        Set<String> affectedOrderNos = new HashSet<>();
        Map<String, OpenApiOrder> orderCache = new HashMap<>();
        for (int i = 0; i < mappedDataArray.size(); i++) {
            JSONObject row = mappedDataArray.getJSONObject(i);
            String orderNo = pickString(row, "WMSNO", "wmsNo", "orderNo", "OrderNo");
            String matnrCode = pickString(row, "ItemCode", "itemCode", "matNr", "MatNr");
            String batch = pickString(row, "Batch", "batch", "GoodsNO", "goodsNo");
@@ -476,14 +484,33 @@
            doneQty = doneQty.setScale(2, RoundingMode.HALF_UP);
            try {
                int singleAllocated = allocateMergedDoneQty(orderNo, matnrCode, batch, doneQty);
                int singleAllocated = allocateMergedDoneQty(orderNo, matnrCode, batch, doneQty, orderCache);
                allocateCount += singleAllocated;
                erpReportCount += reportReadyLinesToErp(orderNo);
                refreshOrderFinishStatus(orderNo);
                affectedOrderNos.add(orderNo);
            } catch (Exception e) {
                log.error("处理回传失败,orderNo={}, matnr={}, batch={}", orderNo, matnrCode, batch, e);
                errors.add("第" + (i + 1) + "行处理失败:" + e.getMessage());
            }
        }
        // 循环结束后,每个受影响订单只刷新一次状态
        for (String orderNo : affectedOrderNos) {
            refreshOrderFinishStatus(orderNo);
        }
        // 反映射后组装ReportParams,参照旧链路上报ERP(一次性整单上报)
        try {
            ReportParams erpReportParams = buildReportParamsFromMappedData(mappedRoot, mappedDataArray);
            CommonResponse erpResp = wmsErpService.reportOrders(erpReportParams);
            if (Objects.nonNull(erpResp) && Objects.equals(erpResp.getCode(), 200)) {
                log.info("反映射上报ERP成功,orderNo={}", pickString(root, "orderNo", "WMSNO"));
            } else {
                String msg = Objects.isNull(erpResp) ? "ERP响应为空" : erpResp.getMsg();
                errors.add("上报ERP失败:" + msg);
            }
        } catch (Exception e) {
            log.error("反映射上报ERP异常", e);
            errors.add("上报ERP异常:" + e.getMessage());
        }
        if (!errors.isEmpty()) {
@@ -496,8 +523,43 @@
        Map<String, Object> result = new HashMap<>();
        result.put("allocatedCount", allocateCount);
        result.put("erpReportCount", erpReportCount);
        return CommonResponse.ok(result);
    }
    /**
     * 根据反映射后的数据组装ReportParams,参照旧链路wmsErpService.reportOrders格式上报ERP
     */
    private ReportParams buildReportParamsFromMappedData(JSONObject root, JSONArray dataArray) {
        String orderType = pickString(root, "OrderType", "orderType", "type", "wkType");
        List<ReportDataParam> reportDataList = new ArrayList<>();
        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject row = dataArray.getJSONObject(i);
            ReportDataParam dataParam = new ReportDataParam()
                    .setWMSNO(pickString(row, "WMSNO", "wmsNo", "orderNo", "OrderNo"))
                    .setPONO(pickString(row, "PONO", "poNo"))
                    .setOrderNO(pickString(row, "OrderNO", "orderNo"))
                    .setGoodsNO(pickString(row, "GoodsNO", "goodsNo", "batch", "Batch"))
                    .setItemCode(pickString(row, "ItemCode", "itemCode", "matNr", "MatNr"))
                    .setEditUser(pickString(row, "EditUser", "editUser"))
                    .setMemoDtl(pickString(row, "MemoDtl", "memoDtl", "memo"));
            BigDecimal inQty = pickDecimal(row, "InQty", "inQty");
            BigDecimal outQty = pickDecimal(row, "OutQty", "outQty");
            if (Objects.nonNull(inQty) && inQty.compareTo(ZERO) > 0) {
                dataParam.setInQty(inQty.doubleValue());
            }
            if (Objects.nonNull(outQty) && outQty.compareTo(ZERO) > 0) {
                dataParam.setOutQty(outQty.doubleValue());
            }
            reportDataList.add(dataParam);
        }
        return new ReportParams()
                .setOrderType(orderType)
                .setAction("Update")
                .setData(reportDataList);
    }
    private OpenApiOrder saveOpenApiOrder(Order order) {
@@ -698,10 +760,11 @@
        return event;
    }
    private int allocateMergedDoneQty(String orderNo, String matnrCode, String batch, BigDecimal mergedDoneQty) {
        OpenApiOrder order = openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
                .eq(OpenApiOrder::getCode, orderNo)
                .last("limit 1"));
    private int allocateMergedDoneQty(String orderNo, String matnrCode, String batch, BigDecimal mergedDoneQty, Map<String, OpenApiOrder> orderCache) {
        OpenApiOrder order = orderCache.computeIfAbsent(orderNo, k ->
                openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
                        .eq(OpenApiOrder::getCode, k)
                        .last("limit 1")));
        if (Objects.isNull(order)) {
            throw new CoolException("未找到订单:" + orderNo);
        }
@@ -740,7 +803,7 @@
            openApiOrderItemMapMapper.updateById(row);
            openApiOrderItemMapper.update(null, new LambdaUpdateWrapper<OpenApiOrderItem>()
                    .eq(OpenApiOrderItem::getId, row.getSourceItemId())
                    .setSql("qty = IFNULL(qty,0) + " + toAllocate));
                    .setSql("qty = IFNULL(qty,0) + " + toAllocate.toPlainString()));
            remaining = remaining.subtract(toAllocate).setScale(2, RoundingMode.HALF_UP);
            allocateRows++;
        }
@@ -762,8 +825,22 @@
                .eq(OpenApiOrderItemMap::getOrderId, order.getId())
                .orderByAsc(OpenApiOrderItemMap::getSeqNo)
                .orderByAsc(OpenApiOrderItemMap::getId));
        int successCount = 0;
        // 批量查询所有 sourceItemId 对应的 OpenApiOrderItem,消除 N+1
        List<Long> itemIds = mappings.stream()
                .map(OpenApiOrderItemMap::getSourceItemId)
                .filter(Objects::nonNull)
                .distinct()
                .toList();
        Map<Long, OpenApiOrderItem> itemMap = new HashMap<>();
        if (!itemIds.isEmpty()) {
            List<OpenApiOrderItem> items = openApiOrderItemMapper.selectBatchIds(itemIds);
            for (OpenApiOrderItem item : items) {
                itemMap.put(item.getId(), item);
            }
        }
        int successCount = 0;
        for (OpenApiOrderItemMap mapping : mappings) {
            BigDecimal allocatedQty = defaultQty(mapping.getAllocatedQty());
            BigDecimal reportedQty = defaultQty(mapping.getReportedQty());
@@ -772,7 +849,7 @@
                continue;
            }
            OpenApiOrderItem item = openApiOrderItemMapper.selectById(mapping.getSourceItemId());
            OpenApiOrderItem item = itemMap.get(mapping.getSourceItemId());
            if (Objects.isNull(item)) {
                continue;
            }