rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/CloudWmsReportServiceImpl.java
@@ -104,16 +104,18 @@ private DapIlcwmsCompletionLine buildInOutLine(InOutResultReportParam param, boolean inbound) { RemotesInfoProperties.Dap dap = erpApi.getDap(); CloudMatnrParts matnrParts = parseCloudMatnr(param.getMatNr()); DapIlcwmsCompletionLine line = new DapIlcwmsCompletionLine() .setOrgNo(dap.getOrgNo()) .setDocType(inbound ? dap.getDocTypeIn() : dap.getDocTypeOut()) .setDocNo(param.getOrderNo()) .setDocSeqNo(StringUtils.isNotBlank(param.getLineId()) ? param.getLineId() : "1") .setItemNo(param.getMatNr()) // 按云仓规则拆分物料编码 .setItemNo(matnrParts.getItemNo()) .setQty(parseQty(param.getQty())) .setUnitNo(dap.getUnitNo()) .setCombinationLotNo(param.getBatch()) .setBarcode(resolveBarcode(param)); .setCombinationLotNo(matnrParts.getCombinationLotNo()) .setBarcode(matnrParts.getBarcode()); if (inbound) { line.setInWarehouseNo(param.getWareHouseId()).setInCellNo(param.getLocId()); } else { @@ -134,16 +136,18 @@ String docSeq = docSeqOverride != null ? docSeqOverride : (StringUtils.isNotBlank(param.getDocSeqNo()) ? param.getDocSeqNo() : "1"); String unit = StringUtils.isNotBlank(param.getUnitNo()) ? param.getUnitNo() : dap.getUnitNo(); CloudMatnrParts matnrParts = parseCloudMatnr(param.getMatNr()); DapIlcwmsCompletionLine line = new DapIlcwmsCompletionLine() .setOrgNo(dap.getOrgNo()) .setDocType(docType) .setDocNo(docNo) .setDocSeqNo(docSeq) .setItemNo(param.getMatNr()) // 按云仓规则拆分物料编码 .setItemNo(matnrParts.getItemNo()) .setQty(parseQty(param.getQty())) .setUnitNo(unit) .setCombinationLotNo(param.getBatch()) .setBarcode(resolveAdjustBarcode(param)); .setCombinationLotNo(matnrParts.getCombinationLotNo()) .setBarcode(matnrParts.getBarcode()); if (fillIn) { line.setInWarehouseNo(param.getWareHouseId()); line.setInCellNo(StringUtils.isNotBlank(param.getTargetLocId()) ? param.getTargetLocId() : param.getSourceLocId()); @@ -169,27 +173,65 @@ return dap.getDocTypeIn(); } private static String resolveBarcode(InOutResultReportParam param) { if (StringUtils.isNotBlank(param.getBarcode())) { return param.getBarcode(); // private static String resolveBarcode(InOutResultReportParam param) { // if (StringUtils.isNotBlank(param.getBarcode())) { // return param.getBarcode(); // } // if (StringUtils.isNotBlank(param.getPalletId())) { // return param.getPalletId(); // } // if (param.getMatNr() != null && param.getLocId() != null) { // return param.getMatNr() + ":" + param.getLocId(); // } // return param.getMatNr(); // } // // private static String resolveAdjustBarcode(InventoryAdjustReportParam param) { // if (StringUtils.isNotBlank(param.getBarcode())) { // return param.getBarcode(); // } // if (StringUtils.isNotBlank(param.getPalletId())) { // return param.getPalletId(); // } // return param.getMatNr(); // } /** * 云仓回报字段映射:三段式取前两段,barcode 保留原串。 */ private static CloudMatnrParts parseCloudMatnr(String matNr) { if (StringUtils.isBlank(matNr)) { return new CloudMatnrParts(null, null, null); } if (StringUtils.isNotBlank(param.getPalletId())) { return param.getPalletId(); String[] arr = matNr.split("#", -1); if (arr.length >= 3) { return new CloudMatnrParts(arr[0], arr[1], matNr); } if (param.getMatNr() != null && param.getLocId() != null) { return param.getMatNr() + ":" + param.getLocId(); } return param.getMatNr(); return new CloudMatnrParts(matNr, null, matNr); } private static String resolveAdjustBarcode(InventoryAdjustReportParam param) { if (StringUtils.isNotBlank(param.getBarcode())) { return param.getBarcode(); private static class CloudMatnrParts { private final String itemNo; private final String combinationLotNo; private final String barcode; private CloudMatnrParts(String itemNo, String combinationLotNo, String barcode) { this.itemNo = itemNo; this.combinationLotNo = combinationLotNo; this.barcode = barcode; } if (StringUtils.isNotBlank(param.getPalletId())) { return param.getPalletId(); public String getItemNo() { return itemNo; } return param.getMatNr(); public String getCombinationLotNo() { return combinationLotNo; } public String getBarcode() { return barcode; } } private static Double parseQty(String q) { rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CloudWmsNotifyLogController.java
New file @@ -0,0 +1,49 @@ package com.vincent.rsf.server.manager.controller; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.vincent.rsf.framework.common.R; import com.vincent.rsf.server.common.domain.BaseParam; import com.vincent.rsf.server.common.domain.PageParam; import com.vincent.rsf.server.manager.entity.CloudWmsNotifyLog; import com.vincent.rsf.server.manager.service.CloudWmsNotifyLogService; import com.vincent.rsf.server.system.controller.BaseController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.Map; /** * 云仓上报待办/记录查询(请求体、最近一次响应见表字段) */ @RestController @Api(tags = "云仓上报记录") public class CloudWmsNotifyLogController extends BaseController { @Autowired private CloudWmsNotifyLogService cloudWmsNotifyLogService; @ApiOperation("分页查询(可选 bizRefLike:按业务关联模糊匹配,如单号)") @PreAuthorize("hasAuthority('manager:task:list')") @PostMapping("/cloudWmsNotifyLog/page") public R page(@RequestBody Map<String, Object> map) { BaseParam baseParam = buildParam(map, BaseParam.class); PageParam<CloudWmsNotifyLog, BaseParam> pageParam = new PageParam<>(baseParam, CloudWmsNotifyLog.class); QueryWrapper<CloudWmsNotifyLog> qw = pageParam.buildWrapper(true); Object bizRefLike = map.get("bizRefLike"); if (bizRefLike != null && StringUtils.isNotBlank(String.valueOf(bizRefLike))) { qw.like("biz_ref", String.valueOf(bizRefLike).trim()); } return R.ok().add(cloudWmsNotifyLogService.page(pageParam, qw)); } @ApiOperation("详情") @PreAuthorize("hasAuthority('manager:task:list')") @GetMapping("/cloudWmsNotifyLog/{id}") public R get(@PathVariable Long id) { return R.ok().add(cloudWmsNotifyLogService.getById(id)); } } rsf-server/src/main/java/com/vincent/rsf/server/manager/service/TaskService.java
@@ -29,6 +29,11 @@ Task operateComplete(Long id, Long loginUserId); /** * 管理后台「完成任务」事务提交后,立即执行与定时任务相同的库存收尾(含云仓上报待办);失败则由定时任务重试。 */ void runStockFinishAfterManualComplete(Long taskId); /** * @param notifyRcsFromAdmin true:管理后台「全板出库完结」接口调用时通知 RCS;false:定时/PDA 等同源不通知 */ Task completeFullOutStock(Long id, Long loginUserId, boolean notifyRcsFromAdmin); rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/TaskServiceImpl.java
@@ -55,6 +55,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestTemplate; @@ -597,7 +599,36 @@ if (StringUtils.isNotBlank(task.getTaskCode())) { rcsBusTaskNoticeService.notifyTaskStatus(task.getTaskCode(), task.getTaskStatus()); } final Long taskIdForFinish = task.getId(); if (TransactionSynchronizationManager.isSynchronizationActive()) { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { taskService.runStockFinishAfterManualComplete(taskIdForFinish); } }); } return task; } @Override public void runStockFinishAfterManualComplete(Long taskId) { if (taskId == null) { return; } try { Task t = taskService.getById(taskId); if (t == null) { return; } if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_IN.id)) { taskService.complateInTask(Collections.singletonList(t)); } else if (Objects.equals(t.getTaskStatus(), TaskStsType.COMPLETE_OUT.id)) { taskService.completeTask(Collections.singletonList(t)); } } catch (Exception e) { log.warn("手动完结后立即库存收尾失败,将由定时任务重试,taskId={}:{}", taskId, e.getMessage()); } } /** @@ -2817,19 +2848,16 @@ } } } // 出库仅云仓来源单据参与上报 if (!isInbound) { // 入/出库均仅云仓来源单据参与上报(明细需带 platOrderCode 或 platWorkCode) boolean hasCloudSource = taskItems.stream().anyMatch(this::hasCloudOrderRef); if (!hasCloudSource) { // log.info("入/出库结果上报待办跳过:无云仓来源单据,taskId={}", task.getId()); log.info("入/出库结果上报待办跳过:手动创建出库单据不通知云仓,taskId={}", task.getId()); log.info("入/出库结果上报待办跳过:无云仓来源单据,taskId={}", task.getId()); return; } } ObjectMapper om = new ObjectMapper(); Date now = new Date(); for (TaskItem item : taskItems) { if (!isInbound && !hasCloudOrderRef(item)) { if (!hasCloudOrderRef(item)) { continue; } String orderNo = isInbound ? sourceToOrderNo.get(item.getSource()) : (item.getPlatOrderCode() != null ? item.getPlatOrderCode() : item.getPlatWorkCode());