feat(wms): 出库报关流程改造

1. 交接环节增加 needDeclareFlag 判断:需报关单置为「已交接(13)」不扣库存,
   不需报关单维持原逻辑直接「已出库(9)」扣库存。
2. 新增定时任务每小时调 sendDec 查报关结果,dec_status=P(海关已放行) 时
   状态 13→9 并扣库存+推OMS。
3. 新增 /stockOutOrderApi/customsConfirmOut 接口支持人工触发报关确认出库。
4. 出库单状态枚举新增 13-已交接。
5. WMS 启动类新增 @EnableScheduling 开启定时任务支持。
This commit is contained in:
rcx
2026-08-13 15:06:08 +08:00
parent da31a81415
commit 3d3036cebf
8 changed files with 303 additions and 173 deletions
@@ -50,8 +50,8 @@ public class StockOutOrder extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 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-已复核") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableRyFeignClients @EnableRyFeignClients
@@ -15,6 +16,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
@MapperScan("com.mhd.wms.domain.**.mapper") @MapperScan("com.mhd.wms.domain.**.mapper")
@EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache") @EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache")
@EnableAsync @EnableAsync
@EnableScheduling
@ComponentScan(basePackages = { @ComponentScan(basePackages = {
"com.mhd.wms", "com.mhd.wms",
"com.mhd.system.api.factory" "com.mhd.system.api.factory"
@@ -270,10 +270,13 @@ public class HandoverTaskOrderApplicationService {
.eq(HandoverTaskOrder::getOrderNumber, orderNumber) .eq(HandoverTaskOrder::getOrderNumber, orderNumber)
.set(HandoverTaskOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(HandoverTaskOrder::getBillingJson, handoverTaskOrderDO.getBillingJson())
.set(HandoverTaskOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); .set(HandoverTaskOrder::getPictureApp, handoverTaskOrderDO.getPictureApp()));
// 2. PDA上传图片插入出库管理,状态改为已出库 // 2. 状态按是否报关:需报关→已交接(13),否则→已出库(9)
StockOutOrder soo = stockOutOrderService.getOne(new LambdaQueryWrapper<StockOutOrder>()
.eq(StockOutOrder::getOutOrderNumber, orderNumber));
int targetStatus = (soo != null && "1".equals(soo.getNeedDeclareFlag())) ? 13 : 9;
stockOutOrderService.update(new LambdaUpdateWrapper<StockOutOrder>() stockOutOrderService.update(new LambdaUpdateWrapper<StockOutOrder>()
.eq(StockOutOrder::getOutOrderNumber, orderNumber) .eq(StockOutOrder::getOutOrderNumber, orderNumber)
.set(StockOutOrder::getStatus, "9") .set(StockOutOrder::getStatus, targetStatus)
.set(StockOutOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(StockOutOrder::getBillingJson, handoverTaskOrderDO.getBillingJson())
.set(StockOutOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); .set(StockOutOrder::getPictureApp, handoverTaskOrderDO.getPictureApp()));
// 3. 参考PC端完成交接:根据orderNumber查询交接单ID,执行库存扣减+交接状态更新 // 3. 参考PC端完成交接:根据orderNumber查询交接单ID,执行库存扣减+交接状态更新
@@ -1,5 +1,18 @@
package com.mhd.wms.domain.handoverTaskOrder.service; 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.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -86,6 +99,17 @@ public class HandoverTaskOrderDomainService {
private CopyCodeReferenceDomainService copyCodeReferenceDomainService; private CopyCodeReferenceDomainService copyCodeReferenceDomainService;
@Autowired @Autowired
private OmsServiceFeign omsServiceFeign; 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(); LoginUser loginUser = SecurityUtils.getLoginUser();
//修改库存 //修改库存
xgkc(handoverTaskOrderIds,loginUser); xgkc(handoverTaskOrderIds,loginUser);
//推送oms //推送oms(需报关的单子等海关确认放行后再推)
for (Long handoverTaskOrderId : handoverTaskOrderIds) { for (Long handoverTaskOrderId : handoverTaskOrderIds) {
HandoverTaskOrder hto = handoverTaskOrderService.getById(handoverTaskOrderId);
if (hto == null) {
continue;
}
StockOutOrder soo = stockOutOrderMapper.selectOne(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, hto.getOrderNumber()));
if (soo != null && "1".equals(soo.getNeedDeclareFlag())) {
continue; // 需报关,跳过
}
pushOms(handoverTaskOrderId); pushOms(handoverTaskOrderId);
} }
HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderIds.get(0)); HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderIds.get(0));
@@ -339,178 +372,261 @@ public class HandoverTaskOrderDomainService {
if (stockOutOrder == null) { if (stockOutOrder == null) {
continue; continue;
} }
//完成交接状态改为已出库 // 需要报关:交接时只改状态为「已交接(13)」,不扣库存/不推OMS,等海关确认放行后再处理
if ("1".equals(stockOutOrder.getNeedDeclareFlag())) {
stockOutOrder.setStatus(13);
stockOutOrderMapper.updateById(stockOutOrder);
continue; // 跳过下方扣库存逻辑(B/C/D/E 全部延后到海关确认)
}
// 不需要报关:维持原逻辑,状态改「已出库(9)」+ 扣库存
stockOutOrder.setStatus(9); stockOutOrder.setStatus(9);
stockOutOrderMapper.updateById(stockOutOrder); stockOutOrderMapper.updateById(stockOutOrder);
List<OutMaterialDetail> outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper<OutMaterialDetail>().lambda() doStockOutDeduct(orderNumber, stockOutOrder, loginUser);
.eq(OutMaterialDetail::getOutOrderNumber, orderNumber) }
.eq(OutMaterialDetail::getDelFlag, 1)); }
Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null;
for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { /**
//oms详情同步 * 出库扣减:同步OMS明细 + 联单状态 + 扣实物库存 + 推OMS库存
OMSWarehouseEntryDetails(outMaterialDetail); * (从 xgkc 抽取,供「不需报关交接」和「海关确认」两处复用)
if (outMaterialDetail.getCopyCodeReferenceIds() != null){ */
List<Integer> copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(",")) private void doStockOutDeduct(String orderNumber, StockOutOrder stockOutOrder, LoginUser loginUser) {
.map(Integer::parseInt).collect(Collectors.toList()); List<OutMaterialDetail> outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper<OutMaterialDetail>().lambda()
copyCodeReferenceService.lambdaUpdate() .eq(OutMaterialDetail::getOutOrderNumber, orderNumber)
.set(CopyCodeReference::getMaterialStatusCode, 3) .eq(OutMaterialDetail::getDelFlag, 1));
.set(CopyCodeReference::getMaterialStatusName, "已出库") Integer review = stockOutOrder.getReview();
.in(CopyCodeReference::getId, copyCodeReferenceIds); for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) {
} // === 以下把原 L349-513 的循环体【原样】搬进来,一行不改 ===
Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); // oms详情同步
// 复核什么扣减什么:需要复核用check_quantity,不需要复核用picking_quantity OMSWarehouseEntryDetails(outMaterialDetail);
BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review) if (outMaterialDetail.getCopyCodeReferenceIds() != null) {
? outMaterialDetail.getCheckQuantity() List<Integer> copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(","))
: (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity()); .map(Integer::parseInt).collect(Collectors.toList());
if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) { 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<String> outOrderNumbers) {
// 1. 确定处理范围(只处理 status=13 且需要报关的出库单)
LambdaQueryWrapper<StockOutOrder> qw = new LambdaQueryWrapper<StockOutOrder>()
.eq(StockOutOrder::getStatus, 13)
.eq(StockOutOrder::getNeedDeclareFlag, "1");
if (outOrderNumbers != null && !outOrderNumbers.isEmpty()) {
qw.in(StockOutOrder::getOutOrderNumber, outOrderNumbers);
}
List<StockOutOrder> 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; continue;
} }
BigDecimal checkQuantity = effectiveQuantity;
BigDecimal checkArea = outMaterialDetail.getCheckArea();
BigDecimal checkVolume = outMaterialDetail.getCheckVolume();
BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight();
BigDecimal checkNetWeight = outMaterialDetail.getCheckNetWeight();
// 初始化检查数据,避免空指针 // 3. 判断状态(遍历全部明细,任一命中放行即整单放行)
checkQuantity = checkQuantity != null ? checkQuantity : BigDecimal.ZERO; String decStatus = null;
checkArea = checkArea != null ? checkArea : BigDecimal.ZERO; boolean passed = false, failed = false;
checkVolume = checkVolume != null ? checkVolume : BigDecimal.ZERO; for (int i = 0; i < decData.size(); i++) {
checkGrossWeight = checkGrossWeight != null ? checkGrossWeight : BigDecimal.ZERO; JSONObject item = decData.getJSONObject(i);
checkNetWeight = checkNetWeight != null ? checkNetWeight : BigDecimal.ZERO; 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<String, Object> r = new HashMap<>();
r.put("pass", pass);
r.put("pending", pending);
r.put("fail", fail);
return AjaxResult.success(r);
}
//oms库存同步 /**
//OMSInventorySynchronization(outMaterialDetail,checkQuantity); * sendDec 查询报关回写(参考 PickingOrderApplicationService.java:771-818 模板)
if (materialInventoryPO != null) { * 关键改造:① erpBillNo 传出库单号 ② 返回整个 data 数组(不只第0条) ③ 不在这里处理 dec_status
MaterialInventoryParamDO materialInventoryParamDO = new MaterialInventoryParamDO(); */
//更新库存数量 private JSONArray queryCustomsDeclaration(String erpBillNo, Long organizationId, String organizationName) throws Exception {
Map<String, Object> 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<Map<String, Object>> body = new ArrayList<>();
body.add(param);
// //库存数量 // 多租户 URL(保证查的地址和推 save_order_e 的地址一致)
// BigDecimal oldInventoryQuantity = materialInventoryPO.getInventoryQuantity(); String ncUrl = pickingMaterialDetailMapper.getNcUrl("gw", organizationName, organizationId);
// oldInventoryQuantity = oldInventoryQuantity != null ? oldInventoryQuantity : BigDecimal.ZERO; String url = (ncUrl != null) ? ncUrl : CUSTOMS_PUSH_API_URL;
// //可用数量
// BigDecimal oldAllocationQuantity = materialInventoryPO.getAllocationQuantity(); HttpPost post = new HttpPost(url);
// oldAllocationQuantity = oldAllocationQuantity != null ? oldAllocationQuantity : BigDecimal.ZERO; post.setEntity(new StringEntity(JSONObject.toJSONString(body), "UTF-8"));
// //冻结数量(出库交接不变动冻结数量) post.setHeader("Content-type", "application/json");
// BigDecimal oldFreezeQuantity = materialInventoryPO.getFreezeQuantity(); post.setHeader("apiName", "sendDec");
// oldFreezeQuantity = oldFreezeQuantity != null ? oldFreezeQuantity : BigDecimal.ZERO; post.setHeader("verify", CUSTOMS_VERIFY);
// //扣减后库存数量 log.info("sendDec 请求 erpBillNo={} url={} body={}", erpBillNo, url,body);
// BigDecimal newInventoryQuantity = oldInventoryQuantity.subtract(checkQuantity);
// //扣减后可用数量 try (CloseableHttpClient client = HttpClients.createDefault();
// BigDecimal newAllocationQuantity = oldAllocationQuantity.subtract(checkQuantity); CloseableHttpResponse resp = client.execute(post)) {
// BigDecimal newFreezeQuantity = oldFreezeQuantity; String respStr = EntityUtils.toString(resp.getEntity());
// log.info("sendDec 响应 erpBillNo={} resp={}", erpBillNo, respStr);
// if (resp.getStatusLine().getStatusCode() == 200) {
// JSONObject json = JSONObject.parseObject(respStr);
// BigDecimal oldArea = materialInventoryPO.getArea(); Integer code = json.getInteger("code");
// BigDecimal oldVolume = materialInventoryPO.getVolume(); if (code != null && code == 200) {
// BigDecimal oldGrossWeight = materialInventoryPO.getGrossWeight(); return json.getJSONArray("data");
// 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);
} }
} }
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 推 OMSpushOms 入参是 handoverTaskOrderId,这里包一层) */
private void pushOmsByOrderNumber(String orderNumber) {
List<HandoverTaskOrder> htoList = handoverTaskOrderService.list(
new LambdaQueryWrapper<HandoverTaskOrder>()
.eq(HandoverTaskOrder::getOrderNumber, orderNumber));
for (HandoverTaskOrder hto : htoList) {
pushOms(hto.getHandoverTaskOrderId());
} }
} }
@@ -53,8 +53,8 @@ public class StockOutOrderPO extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 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-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -49,8 +49,8 @@ public class StockOutOrderDO extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 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-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -47,8 +47,8 @@ public class StockOutOrderDTO extends StockOutOrderBaseDTO {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 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-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -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.copyCodeReference.repository.po.CopyCodeReferencePO;
import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder; import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder;
import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrderService; 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.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO; import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail;
@@ -68,6 +69,8 @@ public class StockOutOrderApi extends BaseController {
private IStockOutOrderService stockOutOrderService; private IStockOutOrderService stockOutOrderService;
@Autowired @Autowired
private ExcelParseService excelParseService; private ExcelParseService excelParseService;
@Autowired
private HandoverTaskOrderDomainService handoverTaskOrderDomainService;
/** /**
* 提货单大标题未选时为提货单可传副标题如谷丰--营销部或与弹窗一致传整段提货单--谷丰--营销部后者原样作标题并将 -- 规范为 * 提货单大标题未选时为提货单可传副标题如谷丰--营销部或与弹窗一致传整段提货单--谷丰--营销部后者原样作标题并将 -- 规范为
@@ -107,6 +110,12 @@ public class StockOutOrderApi extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
@ApiOperation("海关确认出库(人工批量触发,参数为空则扫全部已交接状态)")
@PostMapping("/customsConfirmOut")
public AjaxResult customsConfirmOut(@RequestBody(required = false) List<String> outOrderNumbers) {
return handoverTaskOrderDomainService.customsConfirmOut(outOrderNumbers);
}
/** /**
* 上传并解析出仓委托单Excel * 上传并解析出仓委托单Excel
*/ */