Merge branch 'dev-ty1.2' into dev

This commit is contained in:
王奎兴
2026-09-07 16:57:14 +08:00
163 changed files with 7167 additions and 202 deletions
@@ -19,6 +19,9 @@ import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMat
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.ExecutionInMaterialDetailBaseDO;
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.ExecutionInMaterialDetailDO;
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.InventoryAdjustmentRecordPO;
import com.mhd.oms.domain.electronicSignature.entity.ElectronicSignature;
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureMaterialDetailService;
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureService;
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
import com.mhd.oms.domain.executionStockInOrder.repository.facade.IExecutionStockInOrderService;
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
@@ -94,6 +97,10 @@ public class ExecutionStockInOrderDomainService {
private ReservationStockInOrderMapper stockInOrderMapper;
@Autowired
private ReserveStockInOrderMapper reserveStockInOrderMapper;
@Autowired
private IElectronicSignatureService electronicSignatureService;
@Autowired
private IElectronicSignatureMaterialDetailService electronicSignatureMaterialDetailService;
/**
* 分页查询入库单列表
*/
@@ -523,25 +530,34 @@ public class ExecutionStockInOrderDomainService {
@Transactional(rollbackFor = Exception.class)
public Boolean cancelAuditState(ExecutionStockInOrderDO stockInOrderDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Integer issueStatus = stockInOrderDO.getIssueStatus();
// 获取用户姓名(优先从UserPo获取,如果为空则使用realname,最后使用username作为兜底)
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
? loginUser.getUserPo().getUserName()
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
//逻辑删除w入库单信息
//回退下发在WMS产生的数据:调用WMS清理接口,与下发链路(omsInOrderAdd→omsInOrderAddDetail→自动审核
//生成收货单/收货任务/收货作业单/质检单/电子签名)对称,WMS侧一个事务内逻辑删除全部数据。
//此前OMS直接跨库UPDATE仅清理入库单/明细/收货单/收货明细4张表,收货任务、收货作业单、质检单、
//电子签名记录残留;且按入库单号取收货单号(getWShOrder返回String)在重复下发产生多张同号收货单时
//抛TooManyResultsException,取消下发整体回滚失败——正是"下发产生2条数据后取消下发阻断"的直接原因。
//清理失败时抛错整体回滚(OMS保持已下发状态),WMS清理幂等,取消下发可安全重试
List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
if (inOrderIds != null && !inOrderIds.isEmpty()) {
for (Long inOrderId : inOrderIds) {
ExecutionStockInOrder executionStockInOrder = reservationStockInOrderMapper.selectById(inOrderId);
if (executionStockInOrder != null) {
String inOrderNumber = executionStockInOrder.getInOrderNumber();
reservationStockInOrderMapper.delWOrder(inOrderNumber);
reservationStockInOrderMapper.delWOrderDetail(inOrderNumber);
String wShOrder = reservationStockInOrderMapper.getWShOrder(inOrderNumber);
reservationStockInOrderMapper.delWShOrder(inOrderNumber);
reservationStockInOrderMapper.delWShOrderDetail(wShOrder);
if (executionStockInOrder == null) {
continue;
}
String inOrderNumber = executionStockInOrder.getInOrderNumber();
StockInOrder cancelParam = new StockInOrder();
cancelParam.setInOrderNumber(inOrderNumber);
AjaxResult cancelResult = wmsServiceFeign.omsCancelInOrder(cancelParam);
if (cancelResult == null || !"200".equals(String.valueOf(cancelResult.get("code")))) {
throw new ServiceException("取消下发失败:入库单[" + inOrderNumber + "]WMS数据清理失败:"
+ (cancelResult == null ? "WMS服务不可用或已降级" : cancelResult.get("msg")));
}
//清理下发自动审核时生成的待签名电子签名记录(已签名记录保留作凭证,不阻断主流程)
cancelPendingSignature(inOrderNumber);
}
}
@@ -556,6 +572,29 @@ public class ExecutionStockInOrderDomainService {
.in(ExecutionStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds()));
}
/**
* 取消下发时清理下发自动审核生成的待签名电子签名记录(signatureStatus=1)及其明细
*/
private void cancelPendingSignature(String inOrderNumber) {
try {
List<ElectronicSignature> signatures = electronicSignatureService.list(
new LambdaQueryWrapper<ElectronicSignature>()
.eq(ElectronicSignature::getOrderNumber, inOrderNumber)
.eq(ElectronicSignature::getOrderType, "IN")
.eq(ElectronicSignature::getSignatureStatus, 1)
.eq(ElectronicSignature::getDelFlag, 1));
for (ElectronicSignature signature : signatures) {
electronicSignatureMaterialDetailService.deleteBySignatureId(signature.getSignatureId());
electronicSignatureService.update(new UpdateWrapper<ElectronicSignature>().lambda()
.set(ElectronicSignature::getDelFlag, 2)
.eq(ElectronicSignature::getSignatureId, signature.getSignatureId()));
}
} catch (Exception e) {
//WMS数据已清理成功,签名属附属记录,清理失败仅记日志,不回滚取消下发主流程
log.error("取消下发清理电子签名记录失败,入库单号:{}", inOrderNumber, e);
}
}
/**
* @description 审核入库单
* @author ZhouGY
@@ -574,9 +613,15 @@ public class ExecutionStockInOrderDomainService {
}
// 入参去重:同一请求内重复ID会导致同一执行单被多次推送WMS
List<Long> distinctInOrderIds = inOrderIds.stream().distinct().collect(Collectors.toList());
// 只校验有效单据:已删除(软删)执行单混入ID(过期页面提交)时在此拦截,
// 此前list/getById均不过滤del_flag,软删单照样被推到WMS形成"幽灵单"
List<ExecutionStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ExecutionStockInOrder>().lambda()
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds));
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds)
.eq(ExecutionStockInOrder::getDelFlag, 1));
if (checkOrders.size() != distinctInOrderIds.size()) {
throw new ServiceException("下发失败:存在已删除的单据,请刷新后重新选择");
}
for (ExecutionStockInOrder order : checkOrders) {
if (order.getIssueTime() != null) {
throw new ServiceException("下发失败:单据[" + order.getInOrderNumber() + "]已下发,不可重复下发;如需重新下发请先取消下发");
@@ -589,6 +634,9 @@ public class ExecutionStockInOrderDomainService {
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
? loginUser.getUserPo().getUserName()
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
//下发标记改为条件更新(issue_time IS NULL):前置list校验与update之间存在并发窗口,
//双击/并发请求会同时通过校验各自推一遍WMS(WMS侧同号入库单/明细翻倍的根源之一);
//加上条件后,后到的事务影响行数为0,在此拦截,保证同一执行单只会推送WMS一次
boolean update = stockInOrderService.update(null, new UpdateWrapper<ExecutionStockInOrder>().lambda()
.set(ExecutionStockInOrder::getIssueId, loginUser.getUserid())
.set(ExecutionStockInOrder::getIssueName, userRealName)
@@ -597,7 +645,11 @@ public class ExecutionStockInOrderDomainService {
.set(ExecutionStockInOrder::getUpdateBy, loginUser.getUserid())
.set(ExecutionStockInOrder::getUpdateByName, userRealName)
.set(ExecutionStockInOrder::getUpdateTime, new Date())
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds));
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds)
.isNull(ExecutionStockInOrder::getIssueTime));
if (!update) {
throw new ServiceException("下发失败:单据已被并发下发,请刷新后查看");
}
//todo下发推送到wms
for (Long inOrderId : distinctInOrderIds) {
@@ -612,7 +664,13 @@ public class ExecutionStockInOrderDomainService {
stockInOrder.setOrganizationId(orgId);
stockInOrder.setOrganizationName(orgName);
stockInOrder.setTopOrganizationId(topOrgId);
wmsServiceFeign.omsInOrderAdd(stockInOrder);
//WMS保存结果必须校验:此前接口返回void、Feign降级被静默吞掉,OMS标记已下发但WMS无数据/缺明细,
//收货流程无从进行(流程阻断);失败抛错回滚下发标记,WMS侧幂等(主单/明细判重),重下发安全
AjaxResult addResult = wmsServiceFeign.omsInOrderAdd(stockInOrder);
if (addResult == null || !"200".equals(String.valueOf(addResult.get("code")))) {
throw new ServiceException("下发失败:入库单[" + stockInOrder.getInOrderNumber() + "]推送WMS保存主单失败:"
+ (addResult == null ? "WMS服务不可用或已降级" : addResult.get("msg")));
}
String inOrderNumber = stockInOrder.getInOrderNumber();
// 只推有效明细(del_flag=1),软删旧行不推WMS,防止WMS侧计划数量虚高
List<ExecutionInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ExecutionInMaterialDetail>().lambda()
@@ -633,7 +691,11 @@ public class ExecutionStockInOrderDomainService {
}
inMaterialDetailList.add(inMaterialDetail);
}
wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList);
AjaxResult detailResult = wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList);
if (detailResult == null || !"200".equals(String.valueOf(detailResult.get("code")))) {
throw new ServiceException("下发失败:入库单[" + inOrderNumber + "]推送WMS保存明细失败:"
+ (detailResult == null ? "WMS服务不可用或已降级" : detailResult.get("msg")));
}
}
return update;
}
@@ -504,4 +504,16 @@ public class ExecutionStockOutOrder extends BaseVOEntity {
@Excel(name = "车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -516,4 +516,16 @@ public class ExecutionStockOutOrderPO extends BaseVOEntity {
@ApiModelProperty("车次")
@Excel(name = "车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -576,4 +576,16 @@ public class ExecutionStockOutOrderDO extends BaseVOEntity {
@ApiModelProperty("车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -564,4 +564,16 @@ public class ExecutionStockOutOrderDTO extends ExecutionStockOutOrderBaseDTO {
@ApiModelProperty("车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -381,6 +381,10 @@ public class ReservationInMaterialDetail extends BaseVOEntity {
private Date drinkDate;
@ApiModelProperty("火险保费")
private BigDecimal fireInsureFee;
@ApiModelProperty("夫力费")
private BigDecimal manpowerFee;
@ApiModelProperty("仓租费")
private BigDecimal totalWarehouseRent;
//订单行号
@@ -483,6 +483,10 @@ public class ReservationInMaterialDetailPO extends ReservationStockInOrderBasePO
private String lotNumber;
@ApiModelProperty("火险保费")
private BigDecimal fireInsureFee;
@ApiModelProperty("夫力费")
private BigDecimal manpowerFee;
@ApiModelProperty("仓租费")
private BigDecimal totalWarehouseRent;
//订单行号
private String lineNumGw;
@@ -448,6 +448,10 @@ public class ReservationInMaterialDetailDO extends ReservationStockInOrderBaseDO
private BigDecimal unitPrice;
@ApiModelProperty("火险保费")
private BigDecimal fireInsureFee;
@ApiModelProperty("夫力费")
private BigDecimal manpowerFee;
@ApiModelProperty("仓租费")
private BigDecimal totalWarehouseRent;
//订单行号
private String lineNumGw;
@@ -455,6 +455,10 @@ public class ReservationInMaterialDetailDTO extends BaseVOEntity {
private String productionDate;
@ApiModelProperty("火险保费")
private BigDecimal fireInsureFee;
@ApiModelProperty("夫力费")
private BigDecimal manpowerFee;
@ApiModelProperty("仓租费")
private BigDecimal totalWarehouseRent;
//订单行号
private String lineNumGw;
@@ -501,6 +501,9 @@ public class ReservationOutMaterialDetail extends BaseVOEntity {
@Excel(name = "库存数量")
private BigDecimal stockQuantity;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
//订单行号
private String lineNumGw;
@@ -519,6 +519,9 @@ public class ReservationOutMaterialDetailPO extends ReservationStockOutOrderBase
@Excel(name = "库存数量")
private BigDecimal stockQuantity;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("出库异常明细:计划数量(复核异常场景=拣货数量)")
@TableField(exist = false)
private BigDecimal abnormalPlanQuantity;
@@ -477,6 +477,8 @@ public class ReservationOutMaterialDetailDO extends BaseVOEntity {
@Excel(name = "库存数量")
private BigDecimal stockQuantity;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("调整前库存数量")
@Excel(name = "调整前库存数量")
@@ -469,6 +469,8 @@ public class ReservationOutMaterialDetailDTO extends BaseVOEntity {
@Excel(name = "库存数量")
private BigDecimal stockQuantity;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("调整前库存数量")
@Excel(name = "调整前库存数量")
@@ -70,4 +70,7 @@ public interface IReservationStockInOrderService extends IService<ReservationSto
* @throws Exception 解析异常
*/
List<SheetImportResultDTO> parseStockInExcel(MultipartFile file, String sheetName) throws Exception;
//StockInDataDTO parseStockInExcel(MultipartFile file, String sheetName) throws Exception;
public List<ReservationStockInOrderPO> queryPushBmsList();
}
@@ -79,4 +79,6 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
int existsByOrderNumber(@Param("inOrderNumber") String inOrderNumber);
int existsByBusinessOrderNo(@Param("businessOrderNo") String businessOrderNo);
public List<ReservationStockInOrderPO> queryPushBmsList();
}
@@ -336,6 +336,12 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
if (productDetailList.isEmpty()) {
throw new Exception("未解析到产品明细数据,请检查模板中是否填写了產品編號");
}
// 行级必填校验支数缺失的行直接给出明确提示避免后续 new BigDecimal(null) 抛无信息的NPE
for (ProductDetail productDetail : productDetailList) {
if (productDetail.getPieceCount() == null) {
throw new Exception("产品[" + productDetail.getProductCode() + "]的【支/件数】未填写,请补全后重新导入");
}
}
LOGGER.info("页签[{}]解析完成,货品明细{}条,客户配送明细{}条",
sheetName, productDetailList.size(), customerDeliveryDetailList.size());
@@ -658,6 +664,9 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
preparedOrders.add(prepared); // null=空页签跳过
}
} catch (Exception e) {
// 完整堆栈进服务端日志便于定位页签内解析异常的具体行号
LOGGER.error("页签[{}]入库导入解析失败", name, e);
// 非模板页签的解析异常如NPEmessage 可能为空兜底用异常类名避免报错显示"页签[x]null"
sheetProblems.add("页签[" + name + "]" + (e.getMessage() == null ? e.toString() : e.getMessage()));
}
}
@@ -710,6 +719,15 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
if (productDetailList == null || productDetailList.isEmpty()) {
return null;
}
// 行级必填校验编号/支数缺失的行直接给出明确提示避免后续 new BigDecimal(null) 抛无信息的NPE
for (StockInProductDetail productDetail : productDetailList) {
if (productDetail.getProductCode() == null || productDetail.getProductCode().trim().isEmpty()) {
throw new ServiceException("存在未填写【產品編號】的明细行,请补全后重新导入");
}
if (productDetail.getPieceCount() == null) {
throw new ServiceException("产品[" + productDetail.getProductCode() + "]的【支/件数】未填写,请补全后重新导入");
}
}
StockInHeader stockInHeader = resultDTO.getStockInHeader();
// ====== 第一步物料编号存在性校验模板只填物料编号即可名称按编号自动匹配 ======
// 查询结果为空说明库中没有该物料先收集全部缺失编号不立即报错
@@ -1091,5 +1109,9 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
}
}
public List<ReservationStockInOrderPO> queryPushBmsList() {
return stockInOrderMapper.queryPushBmsList();
}
}
@@ -18,6 +18,8 @@ import com.mhd.oms.domain.gwLog.repository.mapper.GwLogMapper;
import com.mhd.oms.domain.reservationInMaterialDetail.entity.ReservationInMaterialDetail;
import com.mhd.oms.domain.reservationInMaterialDetail.repository.mapper.ReservationInMaterialDetailMapper;
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
import com.mhd.oms.domain.reservationMaterialInventory.repository.facade.IReservationMaterialInventoryService;
import com.mhd.oms.domain.reservationMaterialInventory.repository.mapper.ReservationMaterialInventoryMapper;
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
@@ -76,6 +78,8 @@ public class ReservationStockInOrderApplicationService {
private ReservationStockInOrderMapper reservationStockInOrderMapper;
@Autowired
private ReservationInMaterialDetailMapper reservationInMaterialDetailMapper;
@Autowired
private IReservationMaterialInventoryService reservationMaterialInventoryService;
// @Autowired
// private IMaterialBaseInfoService materialBaseInfoService;
private static final String PUSH_API_URL = "http://10.102.192.15/nagu-erp-api/transfer/pushData";
@@ -2285,4 +2289,23 @@ public class ReservationStockInOrderApplicationService {
public String generateReserveOrderNumber1() {
return stockInOrderDomainService.generateReserveOrderNumber1();
}
public List<ReservationStockInOrderPO> queryPushBmsList() {
return stockInOrderDomainService.queryPushBmsList();
}
public void pushBillingRecord() {
//reservationMaterialInventoryService
// 当天应该推送的数据
List<ReservationStockInOrderPO> reservationStockInOrderPOS = stockInOrderDomainService.queryPushBmsList();
if (reservationStockInOrderPOS!=null&&reservationStockInOrderPOS.size()>0){
for (ReservationStockInOrderPO reservationStockInOrderPO : reservationStockInOrderPOS) {
String inOrderNumber = reservationStockInOrderPO.getInOrderNumber();
ReservationInMaterialDetail reservationInMaterialDetail = reservationInMaterialDetailMapper.selectOne(new LambdaQueryWrapper<ReservationInMaterialDetail>()
.eq(ReservationInMaterialDetail::getInOrderNumber, inOrderNumber)
.eq(ReservationInMaterialDetail::getDelFlag, 0));
}
}
}
}
@@ -525,9 +525,14 @@ public class ReservationStockInOrderDomainService {
if (inOrderIds == null || inOrderIds.isEmpty()) {
throw new ServiceException("下发失败:未选择单据");
}
// 只校验有效单据软删单混入ID过期页面提交时在此拦截
List<ReservationStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ReservationStockInOrder>().lambda()
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
.in(ReservationStockInOrder::getInOrderId, inOrderIds)
.eq(ReservationStockInOrder::getDelFlag, 1));
if (checkOrders.size() != inOrderIds.stream().distinct().count()) {
throw new ServiceException("下发失败:存在已删除的单据,请刷新后重新选择");
}
for (ReservationStockInOrder order : checkOrders) {
// 校验1必须已审核issueStatus==2 表示审核成功
if (order.getIssueStatus() == null || order.getIssueStatus() != 2) {
@@ -560,40 +565,12 @@ public class ReservationStockInOrderDomainService {
.set(ReservationStockInOrder::getUpdateTime, new Date())
.in(ReservationStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds()));
//todo下发推送到wms
for (Long inOrderId : inOrderIds) {
ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
StockInOrder stockInOrder = new StockInOrder();
BeanUtils.copyProperties(byId, stockInOrder, "inOrderId");
stockInOrder.setOmsStockInOrderId(String.valueOf(byId.getInOrderId()));
// 业务链路2026-09与业务确认生产验证预约单下发生成执行单执行单下发时才推送WMS
// 预约单下发此前会先把预约单自身推到WMSomsInOrderAdd/omsInOrderAddDetail执行单下发又推一次
// 导致WMS入库管理出现预约单号(R260907001)+执行单号(RK260907001)两张单仓库收两道货
// 已移除预约单的WMS推送WMS推送唯一入口收敛到 ExecutionStockInOrderDomainService.issueOrder
// 历史已推送的预约单数据由"取消下发"cancelIssueOrderomsCancelInOrder幂等负责清理
try {
wmsServiceFeign.omsInOrderAdd(stockInOrder); // 推主单
String inOrderNumber = stockInOrder.getInOrderNumber();
List<ReservationInMaterialDetail> materialDetailList = materialDetailService.list(
new QueryWrapper<ReservationInMaterialDetail>().lambda()
.eq(ReservationInMaterialDetail::getInOrderNumber, inOrderNumber)
.eq(ReservationInMaterialDetail::getDelFlag, 1));
List<InMaterialDetail> inMaterialDetailList = new ArrayList<>();
for (ReservationInMaterialDetail reservationInMaterialDetail : materialDetailList) {
InMaterialDetail inMaterialDetail = new InMaterialDetail();
BeanUtils.copyProperties(reservationInMaterialDetail, inMaterialDetail, "materialDetailId");
inMaterialDetail.setOmsInMaterialDetail(String.valueOf(reservationInMaterialDetail.getMaterialDetailId()));
// 过期日期为空且饮用日期有值时用饮用日期补齐过期日期食品业务饮用日期即效期
// 确保下发WMS后入库/收货/库存链路的过期日期能正常回显
if (inMaterialDetail.getExpiryDate() == null && inMaterialDetail.getDrinkDate() != null) {
inMaterialDetail.setExpiryDate(inMaterialDetail.getDrinkDate());
}
inMaterialDetailList.add(inMaterialDetail);
}
wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); // 推明细会触发WMS自动审核
log.info("下发到WMS成功,单据号:{}", byId.getInOrderNumber());
} catch (Exception e) {
log.error("下发到WMS失败,单据号:{}", byId.getInOrderNumber(), e);
throw new ServiceException("下发到WMS失败:" + e.getMessage());
}
}
//todo下发推送到入库业务单
for (Long inOrderId : inOrderIds) {
// Long inOrderId = stockInOrderDO.getInOrderId();
@@ -748,11 +725,17 @@ public class ReservationStockInOrderDomainService {
for (Long inOrderId : inOrderIds) {
ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
String inOrderNumber = byId.getInOrderNumber();
//清理预约单自身下发到WMS的数据下发时omsInOrderAdd推过主单/明细并自动审核生成收货链路
cancelWmsInOrder(inOrderNumber);
List<ExecutionStockInOrder> list = executionStockInOrderService.list(new QueryWrapper<ExecutionStockInOrder>().lambda()
.eq(ExecutionStockInOrder::getBusinessInOrderNumber, inOrderNumber)
.eq(ExecutionStockInOrder::getDelFlag, 1));
for (ExecutionStockInOrder executionStockInOrder : list) {
String inOrderNumber1 = executionStockInOrder.getInOrderNumber();
//已下发的执行单同步清理WMS侧数据与执行单取消下发同一清理接口未下发则WMS无数据幂等跳过
if (executionStockInOrder.getIssueTime() != null) {
cancelWmsInOrder(inOrderNumber1);
}
List<ExecutionInMaterialDetail> materialDetails = executionInMaterialDetailService.list(new QueryWrapper<ExecutionInMaterialDetail>().lambda()
.eq(ExecutionInMaterialDetail::getInOrderNumber, inOrderNumber1)
.eq(ExecutionInMaterialDetail::getDelFlag, 1));
@@ -770,6 +753,20 @@ public class ReservationStockInOrderDomainService {
return update;
}
/**
* 调用WMS清理接口回退下发产生的数据入库单/明细收货单/明细收货任务收货作业单/明细质检单
* WMS侧已开始收货会返回错误在此抛出保证不会误删真实收货数据
*/
private void cancelWmsInOrder(String inOrderNumber) {
StockInOrder cancelParam = new StockInOrder();
cancelParam.setInOrderNumber(inOrderNumber);
AjaxResult cancelResult = wmsServiceFeign.omsCancelInOrder(cancelParam);
if (cancelResult == null || !"200".equals(String.valueOf(cancelResult.get("code")))) {
throw new ServiceException("取消下发失败:入库单[" + inOrderNumber + "]WMS数据清理失败:"
+ (cancelResult == null ? "WMS服务不可用或已降级" : cancelResult.get("msg")));
}
}
@Transactional(rollbackFor = Exception.class)
public Boolean executeAndIssue(ReservationStockInOrderDO stockInOrderDO) {
// 防重复执行校验 issueOrder 的防重逻辑对齐issueTime 有值表示已下发/执行过
@@ -778,9 +775,14 @@ public class ReservationStockInOrderDomainService {
if (inOrderIds == null || inOrderIds.isEmpty()) {
throw new ServiceException("执行失败:未选择单据");
}
// 只校验有效单据软删单混入ID过期页面提交时在此拦截 issueOrder 校验口径一致
List<ReservationStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ReservationStockInOrder>().lambda()
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
.in(ReservationStockInOrder::getInOrderId, inOrderIds)
.eq(ReservationStockInOrder::getDelFlag, 1));
if (checkOrders.size() != inOrderIds.stream().distinct().count()) {
throw new ServiceException("执行失败:存在已删除的单据,请刷新后重新选择");
}
for (ReservationStockInOrder order : checkOrders) {
if (order.getIssueTime() != null) {
throw new ServiceException("执行失败:单据[" + order.getInOrderNumber() + "]已下发,不可重复执行;如需重新下发请先取消下发");
@@ -1493,4 +1495,8 @@ public class ReservationStockInOrderDomainService {
// generateReserveOrderNumber 收敛为同一套跨表取号逻辑,避免两份实现日后分叉
return generateReserveOrderNumber();
}
public List<ReservationStockInOrderPO> queryPushBmsList() {
return stockInOrderService.queryPushBmsList();
}
}
@@ -503,4 +503,16 @@ public class ReservationStockOutOrder extends BaseVOEntity {
@Excel(name = "车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -526,4 +526,16 @@ public class ReservationStockOutOrderPO extends BaseVOEntity {
@Excel(name = "车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -579,4 +579,16 @@ public class ReservationStockOutOrderDO extends BaseVOEntity {
@ApiModelProperty("车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -568,4 +568,16 @@ public class ReservationStockOutOrderDTO extends ReservationStockOutOrderBaseDTO
@ApiModelProperty("车次")
private String shuttleNo;
@ApiModelProperty("总仓租")
private BigDecimal totalWarehouseRent;
@ApiModelProperty("业务计价类型")
private String businessChargeType;
@ApiModelProperty("业务计价方式")
private String businessPriceWay;
@ApiModelProperty("折扣")
private BigDecimal discount;
}
@@ -22,7 +22,7 @@ import java.util.Map;
/**
* 三方服务 Feign
*/
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.102.192.30:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.33.0.129:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
public interface ThirdPartyServiceFeign {
//查询当前组织所有三方接口信息
@@ -17,6 +17,8 @@ import com.mhd.system.api.domain.InMaterialDetail;
import com.mhd.system.api.domain.InMaterialDetailTZPD;
import com.mhd.system.api.domain.StockInOrder;
import com.mhd.system.api.domain.StockInOrderTZPD;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@@ -313,4 +315,24 @@ public class ReservationStockInOrderApi extends BaseController {
return AjaxResult.success(stockInOrderApplicationService.generateReserveOrderNumber1());
}
/**
* 1. 简单任务示例Bean模式
* 这里的 demoJobHandler 必须和调度中心配置一致
*/
// @XxlJob("pushBillingRecord")
public void pushBillingRecord() {
// 获取任务参数
String param = XxlJobHelper.getJobParam();
logger.info("XXL-JOB 开始入库业务单推送bms计费流水,参数:{}", param);
try {
stockInOrderApplicationService.pushBillingRecord();
// 设置任务执行结果
XxlJobHelper.handleSuccess("入库业务单推送bms计费流水执行成功");
} catch (Exception e) {
logger.error("XXL-JOB 执行失败", e);
XxlJobHelper.handleFail("入库业务单推送bms计费流水执行失败:" + e.getMessage());
}
}
}