From db06b944e7886832d20b8e3ae62b2cb70bcba30f Mon Sep 17 00:00:00 2001
From: 1 <1@123>
Date: 星期五, 17 四月 2026 13:59:50 +0800
Subject: [PATCH] lsh#订单完结
---
rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java | 262 +++++++++++++++++++++++++++++++++++++++------------
1 files changed, 198 insertions(+), 64 deletions(-)
diff --git a/rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java b/rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java
index 7c96629..d62a7be 100644
--- a/rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java
+++ b/rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java
@@ -14,7 +14,6 @@
import com.vincent.rsf.openApi.entity.app.OpenApiOrder;
import com.vincent.rsf.openApi.entity.app.OpenApiOrderItem;
import com.vincent.rsf.openApi.entity.app.OpenApiOrderItemMap;
-import com.vincent.rsf.openApi.entity.app.OpenApiOrderReportEvent;
import com.vincent.rsf.openApi.entity.constant.WmsConstant;
import com.vincent.rsf.openApi.entity.dto.CommonResponse;
import com.vincent.rsf.openApi.entity.phyz.*;
@@ -23,7 +22,6 @@
import com.vincent.rsf.openApi.mapper.OpenApiOrderItemMapMapper;
import com.vincent.rsf.openApi.mapper.OpenApiOrderItemMapper;
import com.vincent.rsf.openApi.mapper.OpenApiOrderMapper;
-import com.vincent.rsf.openApi.mapper.OpenApiOrderReportEventMapper;
import com.vincent.rsf.openApi.service.WmsErpService;
import com.vincent.rsf.openApi.service.phyz.ErpReportService;
import com.vincent.rsf.openApi.utils.ParamsMapUtils;
@@ -83,8 +81,6 @@
private OpenApiOrderItemMapper openApiOrderItemMapper;
@Resource
private OpenApiOrderItemMapMapper openApiOrderItemMapMapper;
- @Resource
- private OpenApiOrderReportEventMapper openApiOrderReportEventMapper;
private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
@@ -442,62 +438,185 @@
}
JSONObject root = JSONObject.parseObject(JSON.toJSONString(params));
- String eventId = pickString(root, "eventId", "EventId");
- String taskNo = pickString(root, "taskNo", "TaskNo");
- String reportNo = pickString(root, "reportNo", "ReportNo");
- if (StringUtils.isBlank(eventId) && StringUtils.isBlank(taskNo) && StringUtils.isBlank(reportNo)) {
- throw new CoolException("骞傜瓑閿笉鑳戒负绌猴紙eventId/taskNo/reportNo锛�");
+ String orderNo = pickString(root, "orderNo", "OrderNo", "WMSNO", "wmsno");
+ if (StringUtils.isBlank(orderNo)) {
+ return CommonResponse.error("orderNo涓嶈兘涓虹┖");
}
- if (existsReportEvent(eventId, taskNo, reportNo)) {
- return CommonResponse.ok("閲嶅鍥炰紶宸插拷鐣�");
+ // 瑙f瀽鏄庣粏锛氫紭鍏堝彇 orderItems锛圤rder鏍煎紡锛夛紝鍏煎 Data/data锛圧eportParams鏍煎紡锛�
+ JSONArray dataArray = pickArray(root, "orderItems", "orderItems");
+ if (Objects.isNull(dataArray) || dataArray.isEmpty()) {
+ dataArray = pickArray(root, "Data", "data");
}
- OpenApiOrderReportEvent reportEvent = saveReportEvent(eventId, taskNo, reportNo, pickString(root, "orderNo", "WMSNO"), root.toJSONString());
-
- JSONArray dataArray = pickArray(root, "Data", "data");
if (Objects.isNull(dataArray) || dataArray.isEmpty()) {
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, "orderItems", "orderItems");
+ if (Objects.isNull(mappedDataArray) || mappedDataArray.isEmpty()) {
+ 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);
- String orderNo = pickString(row, "WMSNO", "wmsNo", "orderNo", "OrderNo");
- String matnrCode = pickString(row, "ItemCode", "itemCode", "matNr", "MatNr");
- String batch = pickString(row, "Batch", "batch", "GoodsNO", "goodsNo");
- BigDecimal doneQty = pickDecimal(row, "qty", "doneQty", "InQty", "OutQty");
- if (StringUtils.isBlank(orderNo) || StringUtils.isBlank(matnrCode) || doneQty.compareTo(ZERO) <= 0) {
- errors.add("绗�" + (i + 1) + "琛岀己灏戝繀瑕佸瓧娈碉紙WMSNO/ItemCode/鏁伴噺锛�");
+ 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 matnrCode = pickString(row, "matNr", "MatNr", "ItemCode", "itemCode");
+ String batch = pickString(row, "batch", "Batch", "GoodsNO", "goodsNo");
+ String lineId = pickString(row, "lineId", "LineId", "sourceLineId");
+ BigDecimal doneQty = pickDecimal(row, "doneQty", "anfme", "qty", "InQty", "inQty", "OutQty", "outQty", "pdqty", "PDQty");
+ if (StringUtils.isBlank(matnrCode) || doneQty.compareTo(ZERO) <= 0) {
+ errors.add("绗�" + (i + 1) + "琛岀己灏戝繀瑕佸瓧娈碉紙matNr/鏁伴噺锛�");
continue;
}
doneQty = doneQty.setScale(2, RoundingMode.HALF_UP);
try {
- int singleAllocated = allocateMergedDoneQty(orderNo, matnrCode, batch, doneQty);
+ int singleAllocated = allocateMergedDoneQty(orderNo, matnrCode, batch, lineId, doneQty, orderCache);
allocateCount += singleAllocated;
- erpReportCount += reportReadyLinesToErp(orderNo);
- refreshOrderFinishStatus(orderNo);
+ affectedOrderNos.add(orderNo);
} catch (Exception e) {
- log.error("澶勭悊鍥炰紶澶辫触锛宱rderNo={}, matnr={}, batch={}", orderNo, matnrCode, batch, e);
+ log.error("澶勭悊鍥炰紶澶辫触锛宱rderNo={}, matnr={}, batch={}, lineId={}", orderNo, matnrCode, batch, lineId, e);
errors.add("绗�" + (i + 1) + "琛屽鐞嗗け璐ワ細" + e.getMessage());
}
}
+ // 寰幆缁撴潫鍚庯紝姣忎釜鍙楀奖鍝嶈鍗曞彧鍒锋柊涓�娆$姸鎬�
+ for (String no : affectedOrderNos) {
+ refreshOrderFinishStatus(no);
+ }
+
if (!errors.isEmpty()) {
- reportEvent.setStatus(2);
- openApiOrderReportEventMapper.updateById(reportEvent);
return CommonResponse.error("澶勭悊瀹屾垚锛屼絾瀛樺湪寮傚父锛�" + String.join(" | ", errors));
}
- reportEvent.setStatus(1);
- openApiOrderReportEventMapper.updateById(reportEvent);
Map<String, Object> result = new HashMap<>();
result.put("allocatedCount", allocateCount);
- result.put("erpReportCount", erpReportCount);
return CommonResponse.ok(result);
+ }
+
+ /**
+ * 鏌ヨ宸插畬鎴愪絾鏈笂鎶RP鐨勮鍗曪紝缁勮ReportParams涓婃姤ERP
+ * 鐢盿srs-schedule瀹氭椂浠诲姟瑙﹀彂
+ */
+ @Override
+ public CommonResponse reportOrdersToErp() {
+ List<OpenApiOrder> pendingOrders = openApiOrderMapper.selectList(new LambdaQueryWrapper<OpenApiOrder>()
+ .eq(OpenApiOrder::getExceStatus, 2)
+ .eq(OpenApiOrder::getNtyStatus, 0)
+ .last("limit 50"));
+ if (pendingOrders.isEmpty()) {
+ return CommonResponse.ok("鏃犲緟涓婃姤ERP鐨勮鍗�");
+ }
+
+ List<String> errors = new ArrayList<>();
+ int successCount = 0;
+ for (OpenApiOrder order : pendingOrders) {
+ try {
+ List<OpenApiOrderItem> items = openApiOrderItemMapper.selectList(new LambdaQueryWrapper<OpenApiOrderItem>()
+ .eq(OpenApiOrderItem::getOrderId, order.getId()));
+ if (items.isEmpty()) {
+ log.warn("璁㈠崟鏃犳槑缁嗭紝璺宠繃涓婃姤ERP锛宱rderNo={}", order.getCode());
+ continue;
+ }
+
+ ReportParams erpParams = buildReportParams(order, items);
+ CommonResponse erpResp = wmsErpService.reportOrders(erpParams);
+ if (Objects.nonNull(erpResp) && Objects.equals(erpResp.getCode(), 200)) {
+ order.setNtyStatus(1);
+ openApiOrderMapper.updateById(order);
+ successCount++;
+ log.info("涓婃姤ERP鎴愬姛锛宱rderNo={}", order.getCode());
+ } else {
+ String msg = Objects.isNull(erpResp) ? "ERP鍝嶅簲涓虹┖" : erpResp.getMsg();
+ log.warn("涓婃姤ERP澶辫触锛宱rderNo={}锛宮sg={}", order.getCode(), msg);
+ errors.add(order.getCode() + ":" + msg);
+ }
+ } catch (Exception e) {
+ log.error("涓婃姤ERP寮傚父锛宱rderNo={}", order.getCode(), e);
+ errors.add(order.getCode() + ":" + e.getMessage());
+ }
+ }
+
+ if (!errors.isEmpty()) {
+ Map<String, Object> result = new HashMap<>();
+ result.put("successCount", successCount);
+ result.put("totalCount", pendingOrders.size());
+ return CommonResponse.error("閮ㄥ垎璁㈠崟涓婃姤ERP澶辫触锛�" + String.join(" | ", errors));
+ }
+
+ Map<String, Object> result = new HashMap<>();
+ result.put("successCount", successCount);
+ result.put("totalCount", pendingOrders.size());
+ return CommonResponse.ok(result);
+ }
+
+ /**
+ * 浠嶰penApiOrder+OpenApiOrderItem缁勮ReportParams
+ */
+ private ReportParams buildReportParams(OpenApiOrder order, List<OpenApiOrderItem> items) {
+ String erpOrderType = resolveErpOrderType(order.getType(), order.getWkType());
+
+ List<ReportDataParam> reportDataList = new ArrayList<>();
+ for (OpenApiOrderItem item : items) {
+ BigDecimal qty = defaultQty(item.getQty());
+ if (qty.compareTo(ZERO) <= 0) {
+ continue;
+ }
+
+ ReportDataParam dataParam = new ReportDataParam()
+ .setWMSNO(order.getCode())
+ .setPONO(order.getPoCode())
+ .setOrderNO(order.getCode())
+ .setGoodsNO(item.getBatch())
+ .setItemCode(item.getMatnrCode())
+ .setEditUser("schedule")
+ .setEditDate(new Date())
+ .setMemoDtl(item.getMemo());
+
+ if ("in".equalsIgnoreCase(order.getType())) {
+ dataParam.setInQty(qty.doubleValue());
+ } else {
+ dataParam.setOutQty(qty.doubleValue());
+ }
+
+ reportDataList.add(dataParam);
+ }
+
+ return new ReportParams()
+ .setOrderType(erpOrderType)
+ .setAction("Update")
+ .setData(reportDataList);
+ }
+
+ /**
+ * 鏍规嵁type鍜寃kType瑙f瀽ERP涓婃姤鐨勮鍗曠被鍨�
+ */
+ private String resolveErpOrderType(String type, String wkType) {
+ if (StringUtils.isBlank(wkType)) {
+ return "in".equalsIgnoreCase(type) ? "PO_Instock" : "WO_Outstock";
+ }
+ switch (wkType) {
+ case "PUR_ReceiveBill": return "PO_Instock";
+ case "PUR_MRB": return "PR_Outstock";
+ case "PRD_ReturnMtrl": return "WR_Instock";
+ case "PRD_PickMtrl": return "WO_Outstock";
+ case "PRD_FeedMtrl": return "WR_Instock_BL";
+ case "PRD_INSTOCK":
+ case "PRD_MORPT": return "WO_Outstock";
+ case "STK_MISCELLANEOUS": return "In_Instock";
+ case "STK_MisDelivery": return "Io_Outstock";
+ default:
+ return "in".equalsIgnoreCase(type) ? "PO_Instock" : "WO_Outstock";
+ }
}
private OpenApiOrder saveOpenApiOrder(Order order) {
@@ -515,6 +634,7 @@
.setQty(ZERO)
.setWorkQty(ZERO)
.setExceStatus(0)
+ .setNtyStatus(0)
.setStatus(1)
.setBusinessTime(businessTime)
.setOrderInternalCode(order.getOrderInternalCode())
@@ -678,43 +798,43 @@
return merged;
}
- private boolean existsReportEvent(String eventId, String taskNo, String reportNo) {
- return openApiOrderReportEventMapper.selectCount(new LambdaQueryWrapper<OpenApiOrderReportEvent>()
- .eq(OpenApiOrderReportEvent::getEventId, defaultString(eventId))
- .eq(OpenApiOrderReportEvent::getTaskNo, defaultString(taskNo))
- .eq(OpenApiOrderReportEvent::getReportNo, defaultString(reportNo))
- .eq(OpenApiOrderReportEvent::getStatus, 1)) > 0;
- }
-
- private OpenApiOrderReportEvent saveReportEvent(String eventId, String taskNo, String reportNo, String orderCode, String payload) {
- OpenApiOrderReportEvent event = new OpenApiOrderReportEvent()
- .setEventId(defaultString(eventId))
- .setTaskNo(defaultString(taskNo))
- .setReportNo(defaultString(reportNo))
- .setOrderCode(orderCode)
- .setPayload(payload)
- .setStatus(0);
- openApiOrderReportEventMapper.insert(event);
- 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, String lineId, 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);
}
LambdaQueryWrapper<OpenApiOrderItemMap> queryWrapper = new LambdaQueryWrapper<OpenApiOrderItemMap>()
.eq(OpenApiOrderItemMap::getOrderId, order.getId())
- .eq(OpenApiOrderItemMap::getMergeMatnrCode, defaultString(matnrCode))
.orderByAsc(OpenApiOrderItemMap::getSeqNo)
.orderByAsc(OpenApiOrderItemMap::getId);
- if (StringUtils.isNotBlank(batch)) {
- queryWrapper.eq(OpenApiOrderItemMap::getMergeBatch, batch);
+
+ // 浼樺厛鐢╨ineId绮剧‘鍖归厤鍘熷琛�
+ if (StringUtils.isNotBlank(lineId)) {
+ queryWrapper.eq(OpenApiOrderItemMap::getSourceLineId, lineId);
+ } else {
+ queryWrapper.eq(OpenApiOrderItemMap::getMergeMatnrCode, defaultString(matnrCode));
+ if (StringUtils.isNotBlank(batch)) {
+ queryWrapper.eq(OpenApiOrderItemMap::getMergeBatch, batch);
+ }
}
+
List<OpenApiOrderItemMap> mappingRows = openApiOrderItemMapMapper.selectList(queryWrapper);
+ if (mappingRows.isEmpty() && StringUtils.isNotBlank(lineId)) {
+ // lineId鍖归厤涓嶅埌鏃讹紝鍥為��鍒癿atNr+batch鍖归厤
+ queryWrapper = new LambdaQueryWrapper<OpenApiOrderItemMap>()
+ .eq(OpenApiOrderItemMap::getOrderId, order.getId())
+ .eq(OpenApiOrderItemMap::getMergeMatnrCode, defaultString(matnrCode))
+ .orderByAsc(OpenApiOrderItemMap::getSeqNo)
+ .orderByAsc(OpenApiOrderItemMap::getId);
+ if (StringUtils.isNotBlank(batch)) {
+ queryWrapper.eq(OpenApiOrderItemMap::getMergeBatch, batch);
+ }
+ mappingRows = openApiOrderItemMapMapper.selectList(queryWrapper);
+ }
if (mappingRows.isEmpty()) {
throw new CoolException("鏈壘鍒版槧灏勫叧绯伙紝璁㈠崟锛�" + orderNo + "锛岀墿鏂欙細" + matnrCode);
}
@@ -740,7 +860,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 +882,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 +906,7 @@
continue;
}
- OpenApiOrderItem item = openApiOrderItemMapper.selectById(mapping.getSourceItemId());
+ OpenApiOrderItem item = itemMap.get(mapping.getSourceItemId());
if (Objects.isNull(item)) {
continue;
}
--
Gitblit v1.9.1