diff --git a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/domain/StockOutOrder.java b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/domain/StockOutOrder.java index f94c49b5d..2ac0c76e6 100644 --- a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/domain/StockOutOrder.java +++ b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/domain/StockOutOrder.java @@ -50,8 +50,8 @@ public class StockOutOrder extends BaseVOEntity { @Excel(name = "出库单号") private String outOrderNumber; - @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核") - @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核") + @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") + @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") private Integer status; @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") diff --git a/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java b/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java index a848debd3..92f286e66 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java +++ b/mhd_wms/src/main/java/com/mhd/wms/MhdWmsApplication.java @@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableRyFeignClients @@ -15,6 +16,7 @@ import org.springframework.scheduling.annotation.EnableAsync; @MapperScan("com.mhd.wms.domain.**.mapper") @EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache") @EnableAsync +@EnableScheduling @ComponentScan(basePackages = { "com.mhd.wms", "com.mhd.system.api.factory" diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java index 4b4a8aaf5..4c9775cd2 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java @@ -270,10 +270,13 @@ public class HandoverTaskOrderApplicationService { .eq(HandoverTaskOrder::getOrderNumber, orderNumber) .set(HandoverTaskOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(HandoverTaskOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); - // 2. PDA上传图片插入出库管理,状态改为已出库 + // 2. 状态按是否报关:需报关→已交接(13),否则→已出库(9) + StockOutOrder soo = stockOutOrderService.getOne(new LambdaQueryWrapper() + .eq(StockOutOrder::getOutOrderNumber, orderNumber)); + int targetStatus = (soo != null && "1".equals(soo.getNeedDeclareFlag())) ? 13 : 9; stockOutOrderService.update(new LambdaUpdateWrapper() .eq(StockOutOrder::getOutOrderNumber, orderNumber) - .set(StockOutOrder::getStatus, "9") + .set(StockOutOrder::getStatus, targetStatus) .set(StockOutOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(StockOutOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); // 3. 参考PC端完成交接:根据orderNumber查询交接单ID,执行库存扣减+交接状态更新 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java index 1d409b159..504e379fe 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java @@ -1,5 +1,18 @@ package com.mhd.wms.domain.handoverTaskOrder.service; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.mhd.common.core.web.domain.AjaxResult; +import com.mhd.wms.domain.customsDeclarationDetail.repository.todo.CustomsDeclarationDetailDO; +import com.mhd.wms.domain.customsDeclarationDetail.repository.facade.ICustomsDeclarationDetailService; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.scheduling.annotation.Scheduled; +import java.text.SimpleDateFormat; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; @@ -86,6 +99,17 @@ public class HandoverTaskOrderDomainService { private CopyCodeReferenceDomainService copyCodeReferenceDomainService; @Autowired private OmsServiceFeign omsServiceFeign; + @Autowired + private ICustomsDeclarationDetailService customsDeclarationDetailService; + + // 报关回写相关常量 + private static final String CUSTOMS_PUSH_API_URL = "http://10.102.192.15/nagu-erp-api/transfer/pushData"; + private static final String CUSTOMS_VERIFY = "ESLuxAmB6VXCgbqP1eFzxTPVRagkQ62BUkfhElrgQ6XmE/g2reHVflY/SiCSU7JD"; + // 视为「海关已放行/结关」的状态码(建议做成 @Value("${gw.customs.pass-status:P,I,R,F,K,B}")) + // 视为「海关已放行」的状态码(ERP 确认:只有 P=海关已放行 才表示货物可出库) + private static final String[] CUSTOMS_PASS_STATUS = {"P"}; + // 退单/失败状态码(记告警用) + private static final String[] CUSTOMS_FAIL_STATUS = {"E", "A", "D", "Z", "c", "H"}; /** @@ -293,8 +317,17 @@ public class HandoverTaskOrderDomainService { LoginUser loginUser = SecurityUtils.getLoginUser(); //修改库存 xgkc(handoverTaskOrderIds,loginUser); - //推送oms + //推送oms(需报关的单子等海关确认放行后再推) for (Long handoverTaskOrderId : handoverTaskOrderIds) { + HandoverTaskOrder hto = handoverTaskOrderService.getById(handoverTaskOrderId); + if (hto == null) { + continue; + } + StockOutOrder soo = stockOutOrderMapper.selectOne(new QueryWrapper().lambda() + .eq(StockOutOrder::getOutOrderNumber, hto.getOrderNumber())); + if (soo != null && "1".equals(soo.getNeedDeclareFlag())) { + continue; // 需报关,跳过 + } pushOms(handoverTaskOrderId); } HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderIds.get(0)); @@ -339,178 +372,261 @@ public class HandoverTaskOrderDomainService { if (stockOutOrder == null) { continue; } - //完成交接状态改为已出库 + // 需要报关:交接时只改状态为「已交接(13)」,不扣库存/不推OMS,等海关确认放行后再处理 + if ("1".equals(stockOutOrder.getNeedDeclareFlag())) { + stockOutOrder.setStatus(13); + stockOutOrderMapper.updateById(stockOutOrder); + continue; // 跳过下方扣库存逻辑(B/C/D/E 全部延后到海关确认) + } + // 不需要报关:维持原逻辑,状态改「已出库(9)」+ 扣库存 stockOutOrder.setStatus(9); stockOutOrderMapper.updateById(stockOutOrder); - List outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper().lambda() - .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) - .eq(OutMaterialDetail::getDelFlag, 1)); - Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null; - for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { - //oms详情同步 - OMSWarehouseEntryDetails(outMaterialDetail); - if (outMaterialDetail.getCopyCodeReferenceIds() != null){ - List copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(",")) - .map(Integer::parseInt).collect(Collectors.toList()); - copyCodeReferenceService.lambdaUpdate() - .set(CopyCodeReference::getMaterialStatusCode, 3) - .set(CopyCodeReference::getMaterialStatusName, "已出库") - .in(CopyCodeReference::getId, copyCodeReferenceIds); - } - Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); - // 复核什么扣减什么:需要复核用check_quantity,不需要复核用picking_quantity - BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review) - ? outMaterialDetail.getCheckQuantity() - : (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity()); - if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) { + doStockOutDeduct(orderNumber, stockOutOrder, loginUser); + } + } + + /** + * 出库扣减:同步OMS明细 + 联单状态 + 扣实物库存 + 推OMS库存 + * (从 xgkc 抽取,供「不需报关交接」和「海关确认」两处复用) + */ + private void doStockOutDeduct(String orderNumber, StockOutOrder stockOutOrder, LoginUser loginUser) { + List outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper().lambda() + .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) + .eq(OutMaterialDetail::getDelFlag, 1)); + Integer review = stockOutOrder.getReview(); + for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { + // === 以下把原 L349-513 的循环体【原样】搬进来,一行不改 === + // oms详情同步 + OMSWarehouseEntryDetails(outMaterialDetail); + if (outMaterialDetail.getCopyCodeReferenceIds() != null) { + List copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(",")) + .map(Integer::parseInt).collect(Collectors.toList()); + copyCodeReferenceService.lambdaUpdate() + .set(CopyCodeReference::getMaterialStatusCode, 3) + .set(CopyCodeReference::getMaterialStatusName, "已出库") + .in(CopyCodeReference::getId, copyCodeReferenceIds); + } + Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); + BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review) + ? outMaterialDetail.getCheckQuantity() + : (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity()); + if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + BigDecimal checkQuantity = effectiveQuantity; + BigDecimal checkArea = outMaterialDetail.getCheckArea(); + BigDecimal checkVolume = outMaterialDetail.getCheckVolume(); + BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight(); + BigDecimal checkNetWeight = outMaterialDetail.getCheckNetWeight(); + checkQuantity = checkQuantity != null ? checkQuantity : BigDecimal.ZERO; + checkArea = checkArea != null ? checkArea : BigDecimal.ZERO; + checkVolume = checkVolume != null ? checkVolume : BigDecimal.ZERO; + checkGrossWeight = checkGrossWeight != null ? checkGrossWeight : BigDecimal.ZERO; + checkNetWeight = checkNetWeight != null ? checkNetWeight : BigDecimal.ZERO; + + MaterialInventory materialInventoryPO = materialInventoryMapper.selectById(materialInventoryId); + if (materialInventoryPO != null) { + MaterialInventoryParamDO materialInventoryParamDO = new MaterialInventoryParamDO(); + materialInventoryParamDO.setArea(checkArea); + materialInventoryParamDO.setVolume(checkVolume); + materialInventoryParamDO.setGrossWeight(checkGrossWeight); + materialInventoryParamDO.setNetWeight(checkNetWeight); + materialInventoryParamDO.setQuantity(checkQuantity); + materialInventoryParamDO.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId()); + materialInventoryParamDO.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId()); + materialInventoryParamDO.setLotNumber(outMaterialDetail.getLotNo()); + materialInventoryParamDO.setBatchNumber(outMaterialDetail.getBatchNumber()); + materialInventoryParamDO.setInOrderNumber(materialInventoryPO.getInOrderNumber()); + materialInventoryParamDO.setProductionDate(materialInventoryPO.getProductionDate()); + materialInventoryParamDO.setExpiryDate(materialInventoryPO.getExpiryDate()); + materialInventoryParamDO.setType("4"); + materialInventoryParamDO.setWarehouseId(materialInventoryPO.getWarehouseId()); + materialInventoryService.kctzjl(materialInventoryParamDO, "出库", loginUser); + materialInventoryService.xgkc(materialInventoryParamDO); + MaterialInventoryOmsParamDO materialInventoryOmsParamDO = new MaterialInventoryOmsParamDO(); + BeanUtils.copyProperties(materialInventoryParamDO, materialInventoryOmsParamDO); + materialInventoryOmsParamDO.setKctzType("出库"); + materialInventoryOmsParamDO.setLoginUser(loginUser); + omsServiceFeign.omsEdit(materialInventoryOmsParamDO); + } + } + } + + /** + * 定时任务入口:每小时整点扫描「已交接(13)」状态的需报关出库单,调 sendDec 查报关结果, + * 放行/结关的 → 状态 13→9 + 扣库存 + 推OMS;未放行 → 跳过下次再查。 + * 由 @Scheduled 触发,无需在 sys_job 表配置。 + */ + @Scheduled(cron = "0 0 * * * ?") + public void scheduledCustomsConfirm() { + log.info("【报关确认出库】定时任务开始执行"); + try { + AjaxResult result = customsConfirmOut(null); + log.info("【报关确认出库】定时任务执行完成 result={}", result); + } catch (Exception e) { + log.error("【报关确认出库】定时任务执行异常", e); + } + } + + /** + * 海关确认出库(轮询/手动入口) + * 对 status=13(已交接)的需报关出库单,调 sendDec 查报关状态: + * ✅ 放行/结关 → 状态 13→9 + 扣库存 + 推OMS + * ❌ 退单 → 保持13,记告警 + * ⏳ 进行中 → 跳过,下次再查 + * @param outOrderNumbers 传空则扫全部 status=13;传值则按指定单号处理 + */ + @Transactional(rollbackFor = Exception.class) + public AjaxResult customsConfirmOut(List outOrderNumbers) { + // 1. 确定处理范围(只处理 status=13 且需要报关的出库单) + LambdaQueryWrapper qw = new LambdaQueryWrapper() + .eq(StockOutOrder::getStatus, 13) + .eq(StockOutOrder::getNeedDeclareFlag, "1"); + if (outOrderNumbers != null && !outOrderNumbers.isEmpty()) { + qw.in(StockOutOrder::getOutOrderNumber, outOrderNumbers); + } + List list = stockOutOrderService.list(qw); + + int pass = 0, pending = 0, fail = 0; + LoginUser loginUser = SecurityUtils.getLoginUser(); + + for (StockOutOrder soo : list) { + try { + // 2. 调 sendDec 查报关状态 + JSONArray decData = queryCustomsDeclaration( + soo.getOutOrderNumber(), + soo.getOrganizationId(), + soo.getOrganizationName()); + if (decData == null || decData.isEmpty()) { + pending++; // ERP 里还没报关单,下次再查 continue; } - BigDecimal checkQuantity = effectiveQuantity; - BigDecimal checkArea = outMaterialDetail.getCheckArea(); - BigDecimal checkVolume = outMaterialDetail.getCheckVolume(); - BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight(); - BigDecimal checkNetWeight = outMaterialDetail.getCheckNetWeight(); - // 初始化检查数据,避免空指针 - checkQuantity = checkQuantity != null ? checkQuantity : BigDecimal.ZERO; - checkArea = checkArea != null ? checkArea : BigDecimal.ZERO; - checkVolume = checkVolume != null ? checkVolume : BigDecimal.ZERO; - checkGrossWeight = checkGrossWeight != null ? checkGrossWeight : BigDecimal.ZERO; - checkNetWeight = checkNetWeight != null ? checkNetWeight : BigDecimal.ZERO; + // 3. 判断状态(遍历全部明细,任一命中放行即整单放行) + String decStatus = null; + boolean passed = false, failed = false; + for (int i = 0; i < decData.size(); i++) { + JSONObject item = decData.getJSONObject(i); + decStatus = item.getString("dec_status"); + if (isInList(decStatus, CUSTOMS_PASS_STATUS)) { + passed = true; + // 报关单号写入 customs_declaration_detail(补全出库单关联) + saveCustomsDetail(soo, item); + break; + } + if (isInList(decStatus, CUSTOMS_FAIL_STATUS)) { + failed = true; + } + } - MaterialInventory materialInventoryPO = materialInventoryMapper.selectById(materialInventoryId); + if (passed) { + // ✅ 放行:状态 13→9 + 扣库存 + 推 OMS + soo.setStatus(9); + stockOutOrderMapper.updateById(soo); + doStockOutDeduct(soo.getOutOrderNumber(), soo, loginUser); + pushOmsByOrderNumber(soo.getOutOrderNumber()); + pass++; + } else if (failed) { + // ❌ 退单:保持13,记告警日志(暂留人工处理) + log.warn("报关退单,请人工处理 outOrderNumber={} decStatus={}", + soo.getOutOrderNumber(), decStatus); + fail++; + } else { + pending++; // 进行中 + } + } catch (Exception e) { + log.error("海关确认出库异常 outOrderNumber={}", soo.getOutOrderNumber(), e); + fail++; + } + } + Map r = new HashMap<>(); + r.put("pass", pass); + r.put("pending", pending); + r.put("fail", fail); + return AjaxResult.success(r); + } - //oms库存同步 - //OMSInventorySynchronization(outMaterialDetail,checkQuantity); - if (materialInventoryPO != null) { - MaterialInventoryParamDO materialInventoryParamDO = new MaterialInventoryParamDO(); - //更新库存数量 + /** + * sendDec 查询报关回写(参考 PickingOrderApplicationService.java:771-818 模板) + * 关键改造:① erpBillNo 传出库单号 ② 返回整个 data 数组(不只第0条) ③ 不在这里处理 dec_status + */ + private JSONArray queryCustomsDeclaration(String erpBillNo, Long organizationId, String organizationName) throws Exception { + Map param = new HashMap<>(); + param.put("beginDate", "2020-01-01"); + param.put("endDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + param.put("erpBillNo", erpBillNo); + param.put("pageIndex", 1); + param.put("pageSize", 100); + List> body = new ArrayList<>(); + body.add(param); -// //库存数量 -// BigDecimal oldInventoryQuantity = materialInventoryPO.getInventoryQuantity(); -// oldInventoryQuantity = oldInventoryQuantity != null ? oldInventoryQuantity : BigDecimal.ZERO; -// //可用数量 -// BigDecimal oldAllocationQuantity = materialInventoryPO.getAllocationQuantity(); -// oldAllocationQuantity = oldAllocationQuantity != null ? oldAllocationQuantity : BigDecimal.ZERO; -// //冻结数量(出库交接不变动冻结数量) -// BigDecimal oldFreezeQuantity = materialInventoryPO.getFreezeQuantity(); -// oldFreezeQuantity = oldFreezeQuantity != null ? oldFreezeQuantity : BigDecimal.ZERO; -// //扣减后库存数量 -// BigDecimal newInventoryQuantity = oldInventoryQuantity.subtract(checkQuantity); -// //扣减后可用数量 -// BigDecimal newAllocationQuantity = oldAllocationQuantity.subtract(checkQuantity); -// BigDecimal newFreezeQuantity = oldFreezeQuantity; -// -// -// -// BigDecimal oldArea = materialInventoryPO.getArea(); -// BigDecimal oldVolume = materialInventoryPO.getVolume(); -// BigDecimal oldGrossWeight = materialInventoryPO.getGrossWeight(); -// BigDecimal oldNetWeight = materialInventoryPO.getNetWeight(); -// -// // 初始化旧数据,避免空指针 -// oldArea = oldArea != null ? oldArea : BigDecimal.ZERO; -// oldVolume = oldVolume != null ? oldVolume : BigDecimal.ZERO; -// oldGrossWeight = oldGrossWeight != null ? oldGrossWeight : BigDecimal.ZERO; -// oldNetWeight = oldNetWeight != null ? oldNetWeight : BigDecimal.ZERO; -// -// BigDecimal newArea = oldArea.subtract(checkArea); -// BigDecimal newVolume = oldVolume.subtract(checkVolume); -// BigDecimal newGrossWeight = oldGrossWeight.subtract(checkGrossWeight); -// BigDecimal newNetWeight = oldNetWeight.subtract(checkNetWeight); -// -// materialInventoryPO.setInventoryQuantity(newInventoryQuantity); -// materialInventoryPO.setAllocationQuantity(materialInventoryPO.getAllocationQuantity()); -// materialInventoryPO.setFreezeQuantity(materialInventoryPO.getFreezeQuantity().subtract(outMaterialDetail.getCheckQuantity()) ); -// materialInventoryPO.setArea(newArea); -// materialInventoryPO.setVolume(newVolume); -// materialInventoryPO.setGrossWeight(newGrossWeight); -// materialInventoryPO.setNetWeight(newNetWeight); -// MaterialInventory materialInventory = new MaterialInventory(); -// BeanUtils.copyProperties(materialInventoryPO, materialInventory); - //materialInventoryMapper.updateById(materialInventory); - materialInventoryParamDO.setArea(checkArea); - materialInventoryParamDO.setVolume(checkVolume); - materialInventoryParamDO.setGrossWeight(checkGrossWeight); - materialInventoryParamDO.setNetWeight(checkNetWeight); - materialInventoryParamDO.setQuantity(checkQuantity); - materialInventoryParamDO.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId()); - materialInventoryParamDO.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId()); - materialInventoryParamDO.setLotNumber(outMaterialDetail.getLotNo()); - materialInventoryParamDO.setBatchNumber(outMaterialDetail.getBatchNumber()); - materialInventoryParamDO.setInOrderNumber(materialInventoryPO.getInOrderNumber()); - materialInventoryParamDO.setProductionDate(materialInventoryPO.getProductionDate()); - materialInventoryParamDO.setExpiryDate(materialInventoryPO.getExpiryDate()); - materialInventoryParamDO.setType("4"); - materialInventoryParamDO.setWarehouseId(materialInventoryPO.getWarehouseId()); - materialInventoryService.kctzjl(materialInventoryParamDO,"出库",loginUser); - materialInventoryService.xgkc(materialInventoryParamDO); - MaterialInventoryOmsParamDO materialInventoryOmsParamDO = new MaterialInventoryOmsParamDO(); - BeanUtils.copyProperties(materialInventoryParamDO, materialInventoryOmsParamDO); - materialInventoryOmsParamDO.setKctzType("出库"); - materialInventoryOmsParamDO.setLoginUser(loginUser); - //库存推送oms - omsServiceFeign.omsEdit(materialInventoryOmsParamDO); - //库存调整记录 -// InventoryAdjustmentRecord inventoryAdjustmentRecord = new InventoryAdjustmentRecord(); -// inventoryAdjustmentRecord.setAdjustAction("出库"); -// inventoryAdjustmentRecord.setRelateNo(orderNumber); -// inventoryAdjustmentRecord.setAdjustAfterStatusCode(materialInventory.getMaterialStatusCode() == null ? "" : materialInventory.getMaterialStatusCode()); -// inventoryAdjustmentRecord.setAdjustBeforeStatusCode(materialInventory.getMaterialStatusCode() == null ? "" : materialInventory.getMaterialStatusCode()); -// inventoryAdjustmentRecord.setAdjustAfterStatusName(materialInventory.getMaterialStatusName() == null ? "" : materialInventory.getMaterialStatusName()); -// inventoryAdjustmentRecord.setAdjustBeforeStatusName(materialInventory.getMaterialStatusName() == null ? "" : materialInventory.getMaterialStatusName()); -//// inventoryAdjustmentRecord.setAdjustBeforeStatusCode("he_ge"); -//// inventoryAdjustmentRecord.setAdjustBeforeStatusName("合格"); -// inventoryAdjustmentRecord.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId()); -// inventoryAdjustmentRecord.setMaterialCode(outMaterialDetail.getMaterialNo()); -// inventoryAdjustmentRecord.setMaterialName(outMaterialDetail.getCommodityName()); -// inventoryAdjustmentRecord.setBarCode(outMaterialDetail.getBarCode()); -// if (inventoryAdjustmentRecord.getBarCode() == null || inventoryAdjustmentRecord.getBarCode().isEmpty()){ -// getBarCode(materialInventoryPO, inventoryAdjustmentRecord); -// } -// inventoryAdjustmentRecord.setMaterialBaseInfoId(outMaterialDetail.getMaterialBaseInfoId()); -// inventoryAdjustmentRecord.setAdjustType(1L); -// inventoryAdjustmentRecord.setOrganizationId(stockOutOrder.getOrganizationId()); -// inventoryAdjustmentRecord.setOrganizationName(stockOutOrder.getOrganizationName()); -// inventoryAdjustmentRecord.setTopOrganizationId(stockOutOrder.getTopOrganizationId()); -// inventoryAdjustmentRecord.setWarehouseCode(stockOutOrder.getWarehouseCode()); -// inventoryAdjustmentRecord.setWarehouseName(stockOutOrder.getWarehouseName()); -// inventoryAdjustmentRecord.setWarehouseId(stockOutOrder.getWarehouseId()); -// inventoryAdjustmentRecord.setStorageCode(materialInventoryPO.getStorageCode()); -// inventoryAdjustmentRecord.setStorageName(materialInventoryPO.getStorageName()); -// inventoryAdjustmentRecord.setStorageLocationId(materialInventoryPO.getStorageLocationId()); -// inventoryAdjustmentRecord.setStorageLocationCode(materialInventoryPO.getStorageLocationCode()); -// inventoryAdjustmentRecord.setStorageLocationName(materialInventoryPO.getStorageLocationName()); -// inventoryAdjustmentRecord.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId()); -// inventoryAdjustmentRecord.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId()); -// inventoryAdjustmentRecord.setShipperId(stockOutOrder.getShipperId()); -// inventoryAdjustmentRecord.setShipperName(stockOutOrder.getShipperName()); -// inventoryAdjustmentRecord.setStorageSectionId(materialInventoryPO.getStorageSectionId()); -// inventoryAdjustmentRecord.setStorageLocationId(materialInventoryPO.getStorageLocationId()); -// inventoryAdjustmentRecord.setCreateBy(loginUser.getUserid()); -// UserPo userPo = loginUser.getUserPo(); -// if (userPo != null) inventoryAdjustmentRecord.setCreateByName(userPo.getUserName()); -// inventoryAdjustmentRecord.setCreateTime(new Date()); -// inventoryAdjustmentRecord.setAllocationBeforeQuantity(oldAllocationQuantity); -// inventoryAdjustmentRecord.setAllocationAfterQuantity(oldAllocationQuantity); -// inventoryAdjustmentRecord.setFreezeBeforeQuantity(oldFreezeQuantity); -// inventoryAdjustmentRecord.setFreezeAfterQuantity(newFreezeQuantity.subtract(outMaterialDetail.getCheckQuantity()));//调整后 冻结-出库 -// inventoryAdjustmentRecord.setInventoryBeforeQuantity(oldInventoryQuantity); -// inventoryAdjustmentRecord.setInventoryAfterQuantity(newInventoryQuantity); -// // 调整前:库存数量(净重、毛重、体积、面积) -// inventoryAdjustmentRecord.setNetWeight(oldNetWeight); -// inventoryAdjustmentRecord.setGrossWeight(oldGrossWeight); -// inventoryAdjustmentRecord.setVolume(oldVolume); -// inventoryAdjustmentRecord.setArea(oldArea); -// // 调整后:库存数量 - 复核时填写的数量 -// inventoryAdjustmentRecord.setAdjustedNetWeight(newNetWeight); -// inventoryAdjustmentRecord.setAdjustedGrossWeight(newGrossWeight); -// inventoryAdjustmentRecord.setAdjustedVolume(newVolume); -// inventoryAdjustmentRecord.setAdjustedArea(newArea); -// -// inventoryAdjustmentRecordMapper.insert(inventoryAdjustmentRecord); + // 多租户 URL(保证查的地址和推 save_order_e 的地址一致) + String ncUrl = pickingMaterialDetailMapper.getNcUrl("gw", organizationName, organizationId); + String url = (ncUrl != null) ? ncUrl : CUSTOMS_PUSH_API_URL; + + HttpPost post = new HttpPost(url); + post.setEntity(new StringEntity(JSONObject.toJSONString(body), "UTF-8")); + post.setHeader("Content-type", "application/json"); + post.setHeader("apiName", "sendDec"); + post.setHeader("verify", CUSTOMS_VERIFY); + log.info("sendDec 请求 erpBillNo={} url={} body={}", erpBillNo, url,body); + + try (CloseableHttpClient client = HttpClients.createDefault(); + CloseableHttpResponse resp = client.execute(post)) { + String respStr = EntityUtils.toString(resp.getEntity()); + log.info("sendDec 响应 erpBillNo={} resp={}", erpBillNo, respStr); + if (resp.getStatusLine().getStatusCode() == 200) { + JSONObject json = JSONObject.parseObject(respStr); + Integer code = json.getInteger("code"); + if (code != null && code == 200) { + return json.getJSONArray("data"); } } + return null; + } + } + + private boolean isInList(String v, String[] arr) { + if (v == null) return false; + for (String s : arr) { + if (s.equalsIgnoreCase(v)) return true; + } + return false; + } + + /** + * 报关明细写入 customs_declaration_detail + * (补 set outOrderNumber/outOrderId,原 PickingOrder 代码这两字段漏 set 了) + */ + private void saveCustomsDetail(StockOutOrder soo, JSONObject item) { + try { + CustomsDeclarationDetailDO d = new CustomsDeclarationDetailDO(); + d.setDocumentNumber(soo.getOutOrderNumber()); + d.setBondInvtNo(item.getString("entry_id")); + Object erpGNo = item.get("erp_g_no"); + if (erpGNo != null) { + d.setInvtRow(erpGNo instanceof Number + ? ((Number) erpGNo).intValue() + : Integer.parseInt(erpGNo.toString())); + } + d.setOutOrderNumber(soo.getOutOrderNumber()); + d.setOutOrderId(soo.getOutOrderId()); + d.setOrganizationId(soo.getOrganizationId()); + d.setOrganizationName(soo.getOrganizationName()); + d.setTopOrganizationId(soo.getTopOrganizationId()); + customsDeclarationDetailService.insert(d); + } catch (Exception e) { + log.error("写报关明细失败 outOrderNumber={}", soo.getOutOrderNumber(), e); + } + } + + /** 按 orderNumber 推 OMS(pushOms 入参是 handoverTaskOrderId,这里包一层) */ + private void pushOmsByOrderNumber(String orderNumber) { + List htoList = handoverTaskOrderService.list( + new LambdaQueryWrapper() + .eq(HandoverTaskOrder::getOrderNumber, orderNumber)); + for (HandoverTaskOrder hto : htoList) { + pushOms(hto.getHandoverTaskOrderId()); } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/po/StockOutOrderPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/po/StockOutOrderPO.java index 552da5d76..52bb67a96 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/po/StockOutOrderPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/po/StockOutOrderPO.java @@ -53,8 +53,8 @@ public class StockOutOrderPO extends BaseVOEntity { @Excel(name = "出库单号") private String outOrderNumber; - @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") - @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") + @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") + @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") private Integer status; @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/todo/StockOutOrderDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/todo/StockOutOrderDO.java index b7ae141d7..2b036c595 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/todo/StockOutOrderDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/repository/todo/StockOutOrderDO.java @@ -49,8 +49,8 @@ public class StockOutOrderDO extends BaseVOEntity { @Excel(name = "出库单号") private String outOrderNumber; - @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") - @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") + @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") + @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") private Integer status; @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutOrder/StockOutOrderDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutOrder/StockOutOrderDTO.java index a81b2a649..278b10162 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutOrder/StockOutOrderDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockOutOrder/StockOutOrderDTO.java @@ -47,8 +47,8 @@ public class StockOutOrderDTO extends StockOutOrderBaseDTO { @Excel(name = "出库单号") private String outOrderNumber; - @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") - @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") + @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") + @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接") private Integer status; @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java index e35ddf4e5..b10e122ef 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockOutOrder/StockOutOrderApi.java @@ -12,6 +12,7 @@ import com.mhd.wms.domain.copyCodeReference.entity.CopyCodeReference; import com.mhd.wms.domain.copyCodeReference.repository.po.CopyCodeReferencePO; import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder; import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrderService; +import com.mhd.wms.domain.handoverTaskOrder.service.HandoverTaskOrderDomainService; import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail; import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; @@ -68,6 +69,8 @@ public class StockOutOrderApi extends BaseController { private IStockOutOrderService stockOutOrderService; @Autowired private ExcelParseService excelParseService; + @Autowired + private HandoverTaskOrderDomainService handoverTaskOrderDomainService; /** * 提货单大标题:未选时为「提货单」;可传副标题如「谷丰--营销部」,或与弹窗一致传整段「提货单--谷丰--营销部」(后者原样作标题,并将 -- 规范为 ——)。 @@ -107,6 +110,12 @@ public class StockOutOrderApi extends BaseController { return getDataTable(list); } + @ApiOperation("海关确认出库(人工批量触发,参数为空则扫全部已交接状态)") + @PostMapping("/customsConfirmOut") + public AjaxResult customsConfirmOut(@RequestBody(required = false) List outOrderNumbers) { + return handoverTaskOrderDomainService.customsConfirmOut(outOrderNumbers); + } + /** * 上传并解析出仓委托单Excel */