feat(oms,wms): 出库业务单反审——已出库/已审核单据回退已创建
- 新增 POST /reservationStockOutOrderApi/reverseAudit,按issueStatus(2-已审核/4-已出库)判断可反审 - 主单回退已创建并打reverseStatus标记,进【已反审】tab(list status=-2),重新审核通过自动复位 - 执行单/明细软删+reverseFlag=1,预约库存调整记录软删 - WMS新增/stockOutOrderApi/omsReverseExecutionOrder:已出库还原实物库存+推OMS,未出库仅还原分配占用,WMS无数据幂等成功 - W出库/拣货/复核/交接单软删+reverseFlag=1,列表支持delFlag=2&reverseFlag=1【已反审】tab - 四页面新增归档详情接口getReverseInfo* - 生成出库异常记录【反审记录】(abnormalType=3,前缀FSYC) - 需先执行SQL: 20260908两个反审脚本(OMS库+WMS库)
This commit is contained in:
+4
-1
@@ -518,4 +518,7 @@ public class ExecutionOutMaterialDetail extends BaseVOEntity {
|
||||
private String inLineNumGw;
|
||||
private String opWhLocGw;
|
||||
private String warehouseGw;
|
||||
}
|
||||
|
||||
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
|
||||
private Integer reverseFlag;
|
||||
}
|
||||
|
||||
+4
-1
@@ -516,4 +516,7 @@ public class ExecutionStockOutOrder extends BaseVOEntity {
|
||||
@ApiModelProperty("折扣")
|
||||
private BigDecimal discount;
|
||||
|
||||
}
|
||||
|
||||
@ApiModelProperty("反审标记: 0-无 1-已反审(业务单反审时软删del_flag=2并打标记)")
|
||||
private Integer reverseFlag;
|
||||
}
|
||||
|
||||
+17
@@ -515,4 +515,21 @@ public class ReservationStockOutOrder extends BaseVOEntity {
|
||||
@ApiModelProperty("折扣")
|
||||
private BigDecimal discount;
|
||||
|
||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
||||
private Integer reverseStatus;
|
||||
|
||||
@ApiModelProperty("反审人id")
|
||||
private Long reverseBy;
|
||||
|
||||
@ApiModelProperty("反审人姓名")
|
||||
private String reverseByName;
|
||||
|
||||
@ApiModelProperty("反审时间")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date reverseTime;
|
||||
|
||||
@ApiModelProperty("反审原因")
|
||||
private String reverseRemark;
|
||||
|
||||
}
|
||||
+17
@@ -538,4 +538,21 @@ public class ReservationStockOutOrderPO extends BaseVOEntity {
|
||||
@ApiModelProperty("折扣")
|
||||
private BigDecimal discount;
|
||||
|
||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
||||
private Integer reverseStatus;
|
||||
|
||||
@ApiModelProperty("反审人id")
|
||||
private Long reverseBy;
|
||||
|
||||
@ApiModelProperty("反审人姓名")
|
||||
private String reverseByName;
|
||||
|
||||
@ApiModelProperty("反审时间")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date reverseTime;
|
||||
|
||||
@ApiModelProperty("反审原因")
|
||||
private String reverseRemark;
|
||||
|
||||
}
|
||||
+15
@@ -591,4 +591,19 @@ public class ReservationStockOutOrderDO extends BaseVOEntity {
|
||||
@ApiModelProperty("折扣")
|
||||
private BigDecimal discount;
|
||||
|
||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
||||
private Integer reverseStatus;
|
||||
|
||||
@ApiModelProperty("反审人id")
|
||||
private Long reverseBy;
|
||||
|
||||
@ApiModelProperty("反审人姓名")
|
||||
private String reverseByName;
|
||||
|
||||
@ApiModelProperty("反审时间")
|
||||
private Date reverseTime;
|
||||
|
||||
@ApiModelProperty("反审原因")
|
||||
private String reverseRemark;
|
||||
|
||||
}
|
||||
+17
@@ -580,4 +580,21 @@ public class ReservationStockOutOrderDTO extends ReservationStockOutOrderBaseDTO
|
||||
@ApiModelProperty("折扣")
|
||||
private BigDecimal discount;
|
||||
|
||||
@ApiModelProperty("反审状态: 0-无 1-已反审(反审后status回退为1-已创建,重新审核通过自动复位0)")
|
||||
private Integer reverseStatus;
|
||||
|
||||
@ApiModelProperty("反审人id")
|
||||
private Long reverseBy;
|
||||
|
||||
@ApiModelProperty("反审人姓名")
|
||||
private String reverseByName;
|
||||
|
||||
@ApiModelProperty("反审时间")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date reverseTime;
|
||||
|
||||
@ApiModelProperty("反审原因")
|
||||
private String reverseRemark;
|
||||
|
||||
}
|
||||
+8
@@ -881,6 +881,14 @@ public class ReservationStockOutOrderApplicationService {
|
||||
return stockOutOrderDomainService.cancelIssueOrder(stockOutOrderDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 反审出库业务单(已出库/已复核单据回退到已创建, WMS库存还原并生成反审异常记录)
|
||||
* @date 2026/9/8
|
||||
*/
|
||||
public Boolean reverseAudit(ReservationStockOutOrderDO stockOutOrderDO){
|
||||
return stockOutOrderDomainService.reverseAudit(stockOutOrderDO);
|
||||
}
|
||||
|
||||
public Boolean executeAndIssue(ReservationStockOutOrderDO stockOutOrderDO){
|
||||
return stockOutOrderDomainService.executeAndIssue(stockOutOrderDO);
|
||||
}
|
||||
|
||||
+124
-2
@@ -48,6 +48,8 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationS
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
|
||||
import com.mhd.oms.domain.reservationInventoryAdjustmentRecord.entity.ReservationInventoryAdjustmentRecord;
|
||||
import com.mhd.oms.domain.reservationInventoryAdjustmentRecord.repository.mapper.ReservationInventoryAdjustmentRecordMapper;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.po.ReservationStockOutOrderPO;
|
||||
@@ -118,6 +120,8 @@ public class ReservationStockOutOrderDomainService {
|
||||
private ReserveStockOutOrderMapper reserveStockOutOrderMapper;
|
||||
@Autowired
|
||||
private MaterialBaseInfoResolveService materialBaseInfoResolveService;
|
||||
@Resource
|
||||
private ReservationInventoryAdjustmentRecordMapper inventoryAdjustmentRecordMapper;
|
||||
|
||||
/**
|
||||
* 分页查询出库单列表
|
||||
@@ -409,7 +413,8 @@ public class ReservationStockOutOrderDomainService {
|
||||
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
||||
? loginUser.getUserPo().getUserName()
|
||||
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
|
||||
boolean updateResult = stockOutOrderService.update(null, new UpdateWrapper<ReservationStockOutOrder>().lambda()
|
||||
boolean updateResult;
|
||||
LambdaUpdateWrapper<ReservationStockOutOrder> auditUpdateWrapper = new UpdateWrapper<ReservationStockOutOrder>().lambda()
|
||||
.set(ReservationStockOutOrder::getReservationAuditId, loginUser.getUserid())
|
||||
.set(ReservationStockOutOrder::getReservationAuditName, userRealName)
|
||||
.set(ReservationStockOutOrder::getReservationAuditTime, new Date())
|
||||
@@ -417,7 +422,12 @@ public class ReservationStockOutOrderDomainService {
|
||||
.set(ReservationStockOutOrder::getUpdateByName, userRealName)
|
||||
.set(ReservationStockOutOrder::getUpdateTime, new Date())
|
||||
.set(ReservationStockOutOrder::getIssueStatus, issueStatus)
|
||||
.in(ReservationStockOutOrder::getOutOrderId, stockOutOrderDO.getOutOrderIds()));
|
||||
.in(ReservationStockOutOrder::getOutOrderId, stockOutOrderDO.getOutOrderIds());
|
||||
// 重新审核通过时复位反审标记: 单据离开【已反审】页签回到正常流转
|
||||
if (issueStatus == 2) {
|
||||
auditUpdateWrapper.set(ReservationStockOutOrder::getReverseStatus, 0);
|
||||
}
|
||||
updateResult = stockOutOrderService.update(null, auditUpdateWrapper);
|
||||
|
||||
//审核通过时同步线路/车次到关联的运输业务单
|
||||
if (issueStatus == 2) {
|
||||
@@ -662,6 +672,118 @@ public class ReservationStockOutOrderDomainService {
|
||||
return update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 反审出库业务单(按前端展示字段 issueStatus 判断可反审范围: 2-已审核(未出库) / 4-已出库 均可反审;
|
||||
* 0-已创建无需反审、3-已驳回可直接编辑; status 字段在出库完成后不一定同步为9, 故不作为判断依据,
|
||||
* 仅兜底排除 10-已取消/11-已关闭)。
|
||||
* 反审将单据回退到最原始状态(1-已创建, issueStatus=0)并打上反审标记:
|
||||
* WMS 侧按出库单实际状态分支还原库存(已出库: 实物库存还原+推OMS; 未出库: 仅还原分配/冻结占用)、
|
||||
* 清理执行单据(出库单/明细/拣货/复核/交接/配送, 软删+reverseFlag=1 划归【已反审】tab)、
|
||||
* 每个执行出库单生成1条出库异常记录【反审记录】(out_order_abnormal, abnormalType=3);
|
||||
* OMS 侧软删执行出库单及明细、软删预约库存调整记录。
|
||||
* 反审后单据进入【已反审】页签(status=1 且 reverse_status=1), 可继续编辑/审核/撤销;
|
||||
* 重新审核通过时 reverse_status 自动复位 0(见 auditState)。
|
||||
* @date 2026/9/8
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean reverseAudit(ReservationStockOutOrderDO stockOutOrderDO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
// 获取用户姓名(优先从UserPo获取,如果为空则使用realname,最后使用username作为兜底)
|
||||
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
||||
? loginUser.getUserPo().getUserName()
|
||||
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
|
||||
List<Long> outOrderIds = stockOutOrderDO.getOutOrderIds();
|
||||
if (outOrderIds == null || outOrderIds.isEmpty()) {
|
||||
throw new ServiceException("请选择需要反审的出库单");
|
||||
}
|
||||
String reverseRemark = stockOutOrderDO.getReverseRemark();
|
||||
|
||||
for (Long outOrderId : outOrderIds) {
|
||||
ReservationStockOutOrder byId = stockOutOrderService.getById(outOrderId);
|
||||
if (byId == null) {
|
||||
throw new ServiceException("出库单不存在, outOrderId=" + outOrderId);
|
||||
}
|
||||
Integer status = byId.getStatus();
|
||||
if (status != null && (status == 10 || status == 11)) {
|
||||
throw new ServiceException("出库单[" + byId.getOutOrderNumber() + "]已取消/已关闭, 不能反审");
|
||||
}
|
||||
// 反审条件按前端展示字段 issueStatus 判断: 2-已审核(未出库) / 4-已出库 均可反审
|
||||
Integer issueStatus = byId.getIssueStatus();
|
||||
if (!Integer.valueOf(2).equals(issueStatus) && !Integer.valueOf(4).equals(issueStatus)) {
|
||||
throw new ServiceException("出库单[" + byId.getOutOrderNumber() + "]当前状态(issueStatus=" + issueStatus
|
||||
+ ")不支持反审, 仅已审核/已出库状态可反审");
|
||||
}
|
||||
// 逐个执行出库单调 WMS 反审: 还原实物库存+推送OMS库存、清理WMS单据、生成反审异常记录;
|
||||
// 任一失败抛异常整体回滚, 避免单边反审
|
||||
List<ExecutionStockOutOrder> executionOrders = executionStockOutOrderService.list(new QueryWrapper<ExecutionStockOutOrder>().lambda()
|
||||
.eq(ExecutionStockOutOrder::getBusinessOutOrderNumber, byId.getOutOrderNumber())
|
||||
.eq(ExecutionStockOutOrder::getDelFlag, 1));
|
||||
for (ExecutionStockOutOrder executionStockOutOrder : executionOrders) {
|
||||
String executionOutOrderNumber = executionStockOutOrder.getOutOrderNumber();
|
||||
StockOutOrder wmsOutOrder = new StockOutOrder();
|
||||
wmsOutOrder.setOutOrderNumber(executionOutOrderNumber);
|
||||
// 反审原因经 remark 透传 WMS, 记入反审异常记录备注
|
||||
wmsOutOrder.setRemark("业务单号:" + byId.getOutOrderNumber()
|
||||
+ (reverseRemark != null && !reverseRemark.isEmpty() ? ",反审原因:" + reverseRemark : ""));
|
||||
AjaxResult wmsResult = wmsServiceFeign.omsReverseExecutionOrder(wmsOutOrder);
|
||||
if (wmsResult == null || !"200".equals(String.valueOf(wmsResult.get("code")))) {
|
||||
throw new ServiceException("执行出库单[" + executionOutOrderNumber + "]WMS反审失败:"
|
||||
+ (wmsResult == null ? "WMS服务不可用" : wmsResult.get("msg")));
|
||||
}
|
||||
// 软删执行出库单明细 + 执行出库单(与取消下发 cancelIssueOrder 一致)
|
||||
List<ExecutionOutMaterialDetail> materialDetails = executionOutMaterialDetailService.list(new QueryWrapper<ExecutionOutMaterialDetail>().lambda()
|
||||
.eq(ExecutionOutMaterialDetail::getOutOrderNumber, executionOutOrderNumber)
|
||||
.eq(ExecutionOutMaterialDetail::getDelFlag, 1));
|
||||
materialDetails.forEach(executionOutMaterialDetail -> {
|
||||
executionOutMaterialDetailService.update(null, new UpdateWrapper<ExecutionOutMaterialDetail>().lambda()
|
||||
.set(ExecutionOutMaterialDetail::getDelFlag, 2)
|
||||
.set(ExecutionOutMaterialDetail::getReverseFlag, 1)
|
||||
.eq(ExecutionOutMaterialDetail::getMaterialDetailId, executionOutMaterialDetail.getMaterialDetailId()));
|
||||
});
|
||||
executionStockOutOrderService.update(null, new UpdateWrapper<ExecutionStockOutOrder>().lambda()
|
||||
.set(ExecutionStockOutOrder::getDelFlag, 2)
|
||||
.set(ExecutionStockOutOrder::getReverseFlag, 1)
|
||||
.eq(ExecutionStockOutOrder::getOutOrderNumber, executionOutOrderNumber));
|
||||
// 软删预约库存调整记录(下发分配时生成): 仅软删留痕, 库存数量由 WMS omsEdit 推送还原
|
||||
inventoryAdjustmentRecordMapper.update(null, new UpdateWrapper<ReservationInventoryAdjustmentRecord>().lambda()
|
||||
.set(ReservationInventoryAdjustmentRecord::getDelFlag, 2)
|
||||
.eq(ReservationInventoryAdjustmentRecord::getExecutionOrderNumber, executionOutOrderNumber)
|
||||
.eq(ReservationInventoryAdjustmentRecord::getDelFlag, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// 主单回退到已创建并打反审标记; 更新条件带 issueStatus in (2,4) + 排除已取消/已关闭 兜底防并发重复反审
|
||||
// issueStatus 回退到 0-已创建(前端展示映射: 0-已创建 2-已审核 3-已驳回 4-已出库)
|
||||
return stockOutOrderService.update(null, new UpdateWrapper<ReservationStockOutOrder>().lambda()
|
||||
.set(ReservationStockOutOrder::getStatus, 1)
|
||||
.set(ReservationStockOutOrder::getIssueStatus, 0)
|
||||
.set(ReservationStockOutOrder::getIssueId, null)
|
||||
.set(ReservationStockOutOrder::getIssueName, null)
|
||||
.set(ReservationStockOutOrder::getIssueTime, null)
|
||||
.set(ReservationStockOutOrder::getReservationAuditId, null)
|
||||
.set(ReservationStockOutOrder::getReservationAuditName, null)
|
||||
.set(ReservationStockOutOrder::getReservationAuditTime, null)
|
||||
.set(ReservationStockOutOrder::getAllocationQuantity, BigDecimal.ZERO)
|
||||
.set(ReservationStockOutOrder::getAlreadyAllocationQuantity, BigDecimal.ZERO)
|
||||
.set(ReservationStockOutOrder::getPickingQuantity, BigDecimal.ZERO)
|
||||
.set(ReservationStockOutOrder::getCheckQuantity, BigDecimal.ZERO)
|
||||
.set(ReservationStockOutOrder::getCheckStatus, 1)
|
||||
.set(ReservationStockOutOrder::getCheckTaskDistribution, 2)
|
||||
.set(ReservationStockOutOrder::getCompleteTime, null)
|
||||
.set(ReservationStockOutOrder::getOutboundTime, null)
|
||||
.set(ReservationStockOutOrder::getReverseStatus, 1)
|
||||
.set(ReservationStockOutOrder::getReverseBy, loginUser.getUserid())
|
||||
.set(ReservationStockOutOrder::getReverseByName, userRealName)
|
||||
.set(ReservationStockOutOrder::getReverseTime, new Date())
|
||||
.set(ReservationStockOutOrder::getReverseRemark, reverseRemark)
|
||||
.set(ReservationStockOutOrder::getUpdateBy, loginUser.getUserid())
|
||||
.set(ReservationStockOutOrder::getUpdateByName, userRealName)
|
||||
.set(ReservationStockOutOrder::getUpdateTime, new Date())
|
||||
.in(ReservationStockOutOrder::getOutOrderId, outOrderIds)
|
||||
.in(ReservationStockOutOrder::getIssueStatus, 2, 4)
|
||||
.notIn(ReservationStockOutOrder::getStatus, 10, 11));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean executeAndIssue(ReservationStockOutOrderDO stockOutOrderDO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
|
||||
+11
@@ -159,6 +159,17 @@ public class ReservationStockOutOrderApi extends BaseController {
|
||||
return AjaxResult.success(stockOutOrderApplicationService.cancelIssueOrder(stockOutOrderDO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 反审出库单: 已出库/已复核(issueStatus=2已审核)的单据回退到已创建并打反审标记,
|
||||
* WMS还原实物库存并生成出库异常记录【反审记录】, 单据划归【已反审】页签
|
||||
*/
|
||||
@ApiOperation("反审出库单")
|
||||
@PostMapping(value = "/reverseAudit")
|
||||
public AjaxResult reverseAudit(@RequestBody ReservationStockOutOrderDTO stockOutOrderDTO) {
|
||||
ReservationStockOutOrderDO stockOutOrderDO = stockOutOrderAssembler.toDO(stockOutOrderDTO);
|
||||
return AjaxResult.success(stockOutOrderApplicationService.reverseAudit(stockOutOrderDO));
|
||||
}
|
||||
|
||||
@ApiOperation("下发出库单")
|
||||
@PostMapping(value = "/executeAndIssue")
|
||||
public AjaxResult executeAndIssue(@RequestBody ReservationStockOutOrderDTO stockOutOrderDTO) {
|
||||
|
||||
Reference in New Issue
Block a user