出入库优化
This commit is contained in:
@@ -9,6 +9,7 @@ import com.gear.common.core.page.TableDataInfo;
|
||||
import com.gear.common.core.validate.AddGroup;
|
||||
import com.gear.common.core.validate.EditGroup;
|
||||
import com.gear.common.enums.BusinessType;
|
||||
import com.gear.common.utils.poi.ExcelUtil;
|
||||
import com.gear.oa.domain.bo.GearStockIoOrderBo;
|
||||
import com.gear.oa.domain.bo.GearStockIoOrderWithDetailBo;
|
||||
import com.gear.oa.domain.vo.GearStockIoOrderVo;
|
||||
@@ -18,9 +19,11 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Validated
|
||||
@@ -36,6 +39,13 @@ public class GearStockIoOrderController extends BaseController {
|
||||
return stockIoOrderService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(GearStockIoOrderBo bo, HttpServletResponse response) {
|
||||
List<GearStockIoOrderVo> list = stockIoOrderService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "出入库单据", GearStockIoOrderVo.class, response);
|
||||
}
|
||||
|
||||
@GetMapping("/{orderId}")
|
||||
public R<GearStockIoOrderVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
return R.ok(stockIoOrderService.queryById(orderId));
|
||||
@@ -68,57 +78,19 @@ public class GearStockIoOrderController extends BaseController {
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/submit/{orderId}")
|
||||
public R<Void> submit(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.submitOrder(orderId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/audit/{orderId}")
|
||||
public R<Void> audit(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.auditOrder(orderId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/execute/{orderId}")
|
||||
public R<Void> execute(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.executeOrder(orderId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/arrival/{orderId}")
|
||||
public R<Void> arrival(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.confirmArrival(orderId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/finish/{orderId}")
|
||||
public R<Void> finish(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.finishOrder(orderId);
|
||||
@PostMapping("/confirmIn/{orderId}")
|
||||
public R<Void> confirmIn(@NotNull(message = "主键不能为空") @PathVariable Long orderId) {
|
||||
stockIoOrderService.confirmIn(orderId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit
|
||||
@PostMapping("/cancel/{orderId}")
|
||||
public R<Void> cancel(@NotNull(message = "主键不能为空") @PathVariable Long orderId,
|
||||
@PostMapping("/revoke/{orderId}")
|
||||
public R<Void> revoke(@NotNull(message = "主键不能为空") @PathVariable Long orderId,
|
||||
@RequestBody(required = false) Map<String, Object> payload) {
|
||||
String reason = payload == null ? "" : String.valueOf(payload.getOrDefault("reason", ""));
|
||||
stockIoOrderService.cancelOrder(orderId, reason);
|
||||
stockIoOrderService.revoke(orderId, reason);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "出入库单据", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit
|
||||
@PostMapping("/reverse/{orderId}")
|
||||
public R<Long> reverse(@NotNull(message = "主键不能为空") @PathVariable Long orderId,
|
||||
@RequestBody(required = false) Map<String, Object> payload) {
|
||||
String reason = payload == null ? "" : String.valueOf(payload.getOrDefault("reason", ""));
|
||||
return R.ok(stockIoOrderService.reverseOrder(orderId, reason));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,18 @@ public class GearStockIoOrder extends BaseEntity {
|
||||
|
||||
private String execFlag;
|
||||
|
||||
private String confirmInFlag;
|
||||
|
||||
private String confirmInBy;
|
||||
|
||||
private Date confirmInTime;
|
||||
|
||||
private String revokeFlag;
|
||||
|
||||
private String revokeBy;
|
||||
|
||||
private Date revokeTime;
|
||||
|
||||
private String reversalFlag;
|
||||
|
||||
private Long reversalOrderId;
|
||||
@@ -89,4 +101,3 @@ public class GearStockIoOrder extends BaseEntity {
|
||||
@TableLogic(value = "0", delval = "2")
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ public class GearStockIoOrderDetail extends BaseEntity {
|
||||
|
||||
private Long itemId;
|
||||
|
||||
private Integer materialTypeSnapshot;
|
||||
|
||||
private String itemName;
|
||||
|
||||
private String specName;
|
||||
@@ -54,4 +56,3 @@ public class GearStockIoOrderDetail extends BaseEntity {
|
||||
@TableLogic(value = "0", delval = "2")
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ public class GearStockIoOrderBo extends BaseEntity {
|
||||
|
||||
private String execFlag;
|
||||
|
||||
private String confirmInFlag;
|
||||
|
||||
private String revokeFlag;
|
||||
|
||||
private String reversalFlag;
|
||||
|
||||
private Long reversalOrderId;
|
||||
@@ -87,4 +91,3 @@ public class GearStockIoOrderBo extends BaseEntity {
|
||||
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ public class GearStockIoOrderDetailBo extends BaseEntity {
|
||||
@NotNull(message = "物料ID不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
private Long itemId;
|
||||
|
||||
private Integer materialTypeSnapshot;
|
||||
|
||||
private String itemName;
|
||||
|
||||
private String specName;
|
||||
@@ -53,4 +55,3 @@ public class GearStockIoOrderDetailBo extends BaseEntity {
|
||||
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ public class GearStockIoOrderDetailVo extends BaseEntity {
|
||||
|
||||
private Long itemId;
|
||||
|
||||
private Integer materialTypeSnapshot;
|
||||
|
||||
@ExcelProperty(value = "物料名称")
|
||||
private String itemName;
|
||||
|
||||
@@ -49,4 +51,3 @@ public class GearStockIoOrderDetailVo extends BaseEntity {
|
||||
|
||||
private String remark;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,18 @@ public class GearStockIoOrderVo extends BaseEntity {
|
||||
|
||||
private String execFlag;
|
||||
|
||||
private String confirmInFlag;
|
||||
|
||||
private String confirmInBy;
|
||||
|
||||
private Date confirmInTime;
|
||||
|
||||
private String revokeFlag;
|
||||
|
||||
private String revokeBy;
|
||||
|
||||
private Date revokeTime;
|
||||
|
||||
private String reversalFlag;
|
||||
|
||||
private Long reversalOrderId;
|
||||
|
||||
@@ -26,18 +26,7 @@ public interface IGearStockIoOrderService {
|
||||
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
void submitOrder(Long orderId);
|
||||
void confirmIn(Long orderId);
|
||||
|
||||
void auditOrder(Long orderId);
|
||||
|
||||
void executeOrder(Long orderId);
|
||||
|
||||
void confirmArrival(Long orderId);
|
||||
|
||||
void finishOrder(Long orderId);
|
||||
|
||||
void cancelOrder(Long orderId, String reason);
|
||||
|
||||
Long reverseOrder(Long orderId, String reason);
|
||||
void revoke(Long orderId, String reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,8 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getBizType()), GearStockIoOrder::getBizType, bo.getBizType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), GearStockIoOrder::getStatus, bo.getStatus());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getExecFlag()), GearStockIoOrder::getExecFlag, bo.getExecFlag());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getConfirmInFlag()), GearStockIoOrder::getConfirmInFlag, bo.getConfirmInFlag());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getRevokeFlag()), GearStockIoOrder::getRevokeFlag, bo.getRevokeFlag());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getReversalFlag()), GearStockIoOrder::getReversalFlag, bo.getReversalFlag());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSourceNo()), GearStockIoOrder::getSourceNo, bo.getSourceNo());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getResponsibleName()), GearStockIoOrder::getResponsibleName, bo.getResponsibleName());
|
||||
@@ -144,6 +146,8 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
order.setStatus("0");
|
||||
order.setExecFlag("0");
|
||||
order.setConfirmInFlag("0");
|
||||
order.setRevokeFlag("0");
|
||||
order.setReversalFlag("0");
|
||||
order.setDelayMinutes(0);
|
||||
order.setDelayStatus("0");
|
||||
@@ -158,19 +162,17 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
|
||||
insertDetails(order.getOrderId(), bo.getDetails());
|
||||
|
||||
if ("O".equalsIgnoreCase(order.getIoType())) {
|
||||
List<GearStockIoOrderDetail> details = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
.eq(GearStockIoOrderDetail::getOrderId, order.getOrderId())
|
||||
.orderByAsc(GearStockIoOrderDetail::getLineNo));
|
||||
applyMaterialStockChange(order.getIoType(), details);
|
||||
applyMaterialStockChange("O", details, "原料库存不足,无法出库");
|
||||
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(order.getOrderId());
|
||||
update.setExecFlag("1");
|
||||
update.setExecuteBy(LoginHelper.getNickName());
|
||||
update.setExecuteTime(new Date());
|
||||
update.setStatus("1");
|
||||
update.setActualFinishTime(new Date());
|
||||
baseMapper.updateById(update);
|
||||
}
|
||||
return order.getOrderId();
|
||||
@@ -285,66 +287,16 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitOrder(Long orderId) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
Long cnt = detailMapper.selectCount(Wrappers.<GearStockIoOrderDetail>lambdaQuery().eq(GearStockIoOrderDetail::getOrderId, orderId));
|
||||
if (cnt == null || cnt <= 0) {
|
||||
throw new ServiceException("单据明细不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void auditOrder(Long orderId) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
if (order.getAuditTime() != null) {
|
||||
return;
|
||||
}
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(orderId);
|
||||
update.setAuditBy(LoginHelper.getNickName());
|
||||
update.setAuditTime(new Date());
|
||||
baseMapper.updateById(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void executeOrder(Long orderId) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
if ("1".equals(order.getExecFlag())) {
|
||||
return;
|
||||
}
|
||||
List<GearStockIoOrderDetail> details = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
.eq(GearStockIoOrderDetail::getOrderId, orderId)
|
||||
.orderByAsc(GearStockIoOrderDetail::getLineNo));
|
||||
if (details == null || details.isEmpty()) {
|
||||
throw new ServiceException("单据明细不能为空");
|
||||
}
|
||||
applyMaterialStockChange(order.getIoType(), details);
|
||||
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(orderId);
|
||||
update.setExecFlag("1");
|
||||
update.setExecuteBy(LoginHelper.getNickName());
|
||||
update.setExecuteTime(new Date());
|
||||
update.setStatus("1");
|
||||
update.setActualFinishTime(new Date());
|
||||
baseMapper.updateById(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void confirmArrival(Long orderId) {
|
||||
public void confirmIn(Long orderId) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
ensureNotRevoked(order);
|
||||
if (!"I".equalsIgnoreCase(order.getIoType())) {
|
||||
throw new ServiceException("仅入库单支持到货确认");
|
||||
throw new ServiceException("仅入库单支持确认入库");
|
||||
}
|
||||
if ("1".equals(order.getExecFlag())) {
|
||||
if ("1".equals(order.getConfirmInFlag())) {
|
||||
return;
|
||||
}
|
||||
List<GearStockIoOrderDetail> details = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
@@ -353,146 +305,54 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
if (details == null || details.isEmpty()) {
|
||||
throw new ServiceException("单据明细不能为空");
|
||||
}
|
||||
applyMaterialStockChange("I", details);
|
||||
for (GearStockIoOrderDetail d : details) {
|
||||
if (d == null) {
|
||||
continue;
|
||||
}
|
||||
if (d.getItemId() == null) {
|
||||
throw new ServiceException("原料ID不能为空");
|
||||
}
|
||||
if (d.getQuantity() == null || d.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new ServiceException("入库数量必须大于0");
|
||||
}
|
||||
fillMaterialSnapshotIfNeeded(d);
|
||||
detailMapper.updateById(d);
|
||||
}
|
||||
applyMaterialStockChange("I", details, "确认入库失败");
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(orderId);
|
||||
update.setConfirmInFlag("1");
|
||||
update.setConfirmInBy(LoginHelper.getNickName());
|
||||
update.setConfirmInTime(new Date());
|
||||
update.setActualArrivalTime(new Date());
|
||||
update.setExecFlag("1");
|
||||
update.setExecuteBy(LoginHelper.getNickName());
|
||||
update.setExecuteTime(new Date());
|
||||
baseMapper.updateById(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void finishOrder(Long orderId) {
|
||||
public void revoke(Long orderId, String reason) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
if ("1".equals(order.getStatus())) {
|
||||
return;
|
||||
}
|
||||
Date finishTime = order.getActualFinishTime() != null ? order.getActualFinishTime() : new Date();
|
||||
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(orderId);
|
||||
update.setStatus("1");
|
||||
update.setActualFinishTime(finishTime);
|
||||
fillDelayOnFinish(order, update, finishTime);
|
||||
baseMapper.updateById(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void cancelOrder(Long orderId, String reason) {
|
||||
GearStockIoOrder order = requireOrder(orderId);
|
||||
ensureNotCanceled(order);
|
||||
if ("1".equals(order.getExecFlag())) {
|
||||
throw new ServiceException("已执行单据不允许作废");
|
||||
}
|
||||
if ("1".equals(order.getStatus())) {
|
||||
throw new ServiceException("已完成单据不允许作废");
|
||||
}
|
||||
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(orderId);
|
||||
update.setCancelReason(StringUtils.isBlank(reason) ? "" : reason);
|
||||
update.setCancelTime(new Date());
|
||||
update.setDelFlag("2");
|
||||
baseMapper.updateById(update);
|
||||
|
||||
detailMapper.delete(Wrappers.<GearStockIoOrderDetail>lambdaQuery().eq(GearStockIoOrderDetail::getOrderId, orderId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long reverseOrder(Long orderId, String reason) {
|
||||
GearStockIoOrder original = requireOrder(orderId);
|
||||
ensureNotCanceled(original);
|
||||
if ("1".equals(original.getReversalFlag())) {
|
||||
throw new ServiceException("冲销单不允许再冲销");
|
||||
}
|
||||
if (!"1".equals(original.getExecFlag())) {
|
||||
throw new ServiceException("原单未执行,无法冲销");
|
||||
}
|
||||
|
||||
Long exists = baseMapper.selectCount(Wrappers.<GearStockIoOrder>lambdaQuery()
|
||||
.eq(GearStockIoOrder::getReversalFlag, "1")
|
||||
.eq(GearStockIoOrder::getReversalOrderId, orderId));
|
||||
if (exists != null && exists > 0) {
|
||||
throw new ServiceException("该单据已创建冲销单");
|
||||
}
|
||||
|
||||
List<GearStockIoOrderDetail> originalDetails = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
ensureNotRevoked(order);
|
||||
List<GearStockIoOrderDetail> details = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
.eq(GearStockIoOrderDetail::getOrderId, orderId)
|
||||
.orderByAsc(GearStockIoOrderDetail::getLineNo));
|
||||
if (originalDetails == null || originalDetails.isEmpty()) {
|
||||
throw new ServiceException("原单明细为空,无法冲销");
|
||||
|
||||
if ("O".equalsIgnoreCase(order.getIoType()) && "1".equals(order.getExecFlag())) {
|
||||
applyMaterialStockChange("I", details, "撤回出库失败");
|
||||
}
|
||||
|
||||
GearStockIoOrder reversal = new GearStockIoOrder();
|
||||
reversal.setOrderCode("SIOO_R_" + IdUtil.getSnowflakeNextIdStr());
|
||||
reversal.setIoType(reverseIoType(original.getIoType()));
|
||||
reversal.setBizType(original.getBizType());
|
||||
reversal.setSourceType("reversal");
|
||||
reversal.setSourceNo(original.getOrderCode());
|
||||
reversal.setSourceOrderId(original.getOrderId());
|
||||
reversal.setResponsibleId(original.getResponsibleId());
|
||||
reversal.setResponsibleName(original.getResponsibleName());
|
||||
reversal.setWarehouseId(original.getWarehouseId());
|
||||
reversal.setFromWarehouseId(original.getFromWarehouseId());
|
||||
reversal.setToWarehouseId(original.getToWarehouseId());
|
||||
reversal.setStatus("0");
|
||||
reversal.setExecFlag("0");
|
||||
reversal.setReversalFlag("1");
|
||||
reversal.setReversalOrderId(original.getOrderId());
|
||||
reversal.setReversalReason(StringUtils.isBlank(reason) ? "" : reason);
|
||||
reversal.setReversalTime(new Date());
|
||||
reversal.setDelayMinutes(0);
|
||||
reversal.setDelayStatus("0");
|
||||
reversal.setDelFlag("0");
|
||||
reversal.setTotalQty(original.getTotalQty());
|
||||
reversal.setRemark(original.getRemark());
|
||||
baseMapper.insert(reversal);
|
||||
|
||||
int lineNo = 1;
|
||||
for (GearStockIoOrderDetail od : originalDetails) {
|
||||
GearStockIoOrderDetail rd = new GearStockIoOrderDetail();
|
||||
rd.setOrderId(reversal.getOrderId());
|
||||
rd.setLineNo(od.getLineNo() == null ? lineNo++ : od.getLineNo());
|
||||
rd.setItemType(od.getItemType());
|
||||
rd.setItemId(od.getItemId());
|
||||
rd.setItemName(od.getItemName());
|
||||
rd.setSpecName(od.getSpecName());
|
||||
rd.setWarehouseId(od.getWarehouseId());
|
||||
rd.setFromWarehouseId(od.getFromWarehouseId());
|
||||
rd.setQuantity(od.getQuantity());
|
||||
rd.setUnit(od.getUnit());
|
||||
rd.setBatchNo(od.getBatchNo());
|
||||
rd.setUnitPrice(od.getUnitPrice());
|
||||
rd.setAmount(od.getAmount());
|
||||
rd.setSourceDetailNo(od.getSourceDetailNo());
|
||||
rd.setReversalDetailId(od.getDetailId());
|
||||
rd.setRemark(od.getRemark());
|
||||
rd.setDelFlag("0");
|
||||
detailMapper.insert(rd);
|
||||
if ("I".equalsIgnoreCase(order.getIoType()) && "1".equals(order.getConfirmInFlag()) && "1".equals(order.getExecFlag())) {
|
||||
applyMaterialStockChange("O", details, "原料库存不足,无法撤回入库");
|
||||
}
|
||||
|
||||
List<GearStockIoOrderDetail> reversalDetails = detailMapper.selectList(Wrappers.<GearStockIoOrderDetail>lambdaQuery()
|
||||
.eq(GearStockIoOrderDetail::getOrderId, reversal.getOrderId())
|
||||
.orderByAsc(GearStockIoOrderDetail::getLineNo));
|
||||
applyMaterialStockChange(reversal.getIoType(), reversalDetails);
|
||||
|
||||
GearStockIoOrder update = new GearStockIoOrder();
|
||||
update.setOrderId(reversal.getOrderId());
|
||||
update.setAuditBy(LoginHelper.getNickName());
|
||||
update.setAuditTime(new Date());
|
||||
update.setExecFlag("1");
|
||||
update.setExecuteBy(LoginHelper.getNickName());
|
||||
update.setExecuteTime(new Date());
|
||||
update.setStatus("1");
|
||||
update.setActualFinishTime(new Date());
|
||||
update.setOrderId(orderId);
|
||||
update.setRevokeFlag("1");
|
||||
update.setRevokeBy(LoginHelper.getNickName());
|
||||
update.setRevokeTime(new Date());
|
||||
update.setExecFlag("0");
|
||||
baseMapper.updateById(update);
|
||||
return reversal.getOrderId();
|
||||
}
|
||||
|
||||
private GearStockIoOrder requireOrder(Long orderId) {
|
||||
@@ -512,13 +372,23 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureNotRevoked(GearStockIoOrder order) {
|
||||
if ("1".equals(order.getRevokeFlag())) {
|
||||
throw new ServiceException("单据已撤回");
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureEditable(GearStockIoOrder order) {
|
||||
ensureNotCanceled(order);
|
||||
ensureNotRevoked(order);
|
||||
if ("1".equals(order.getConfirmInFlag())) {
|
||||
throw new ServiceException("已确认入库单据不允许修改");
|
||||
}
|
||||
if ("1".equals(order.getStatus())) {
|
||||
throw new ServiceException("已完成单据不允许修改");
|
||||
}
|
||||
if ("1".equals(order.getExecFlag())) {
|
||||
throw new ServiceException("已执行单据不允许修改");
|
||||
throw new ServiceException("已影响库存单据不允许修改");
|
||||
}
|
||||
if (order.getAuditTime() != null) {
|
||||
throw new ServiceException("已审核单据不允许修改");
|
||||
@@ -578,46 +448,6 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDelayOnFinish(GearStockIoOrder dbOrder, GearStockIoOrder update, Date finishTime) {
|
||||
if ("2".equals(dbOrder.getDelayStatus())) {
|
||||
return;
|
||||
}
|
||||
Date planFinish = dbOrder.getPlanFinishTime();
|
||||
if (planFinish == null || finishTime == null) {
|
||||
update.setDelayMinutes(0);
|
||||
update.setDelayStatus("0");
|
||||
return;
|
||||
}
|
||||
long diffMs = finishTime.getTime() - planFinish.getTime();
|
||||
int minutes = (int) Math.max(0, diffMs / (60_000L));
|
||||
update.setDelayMinutes(minutes);
|
||||
update.setDelayStatus(minutes > 0 ? "1" : "0");
|
||||
}
|
||||
|
||||
private void applyMaterialStockChange(String ioType, List<GearStockIoOrderDetail> details) {
|
||||
if (!"I".equalsIgnoreCase(ioType) && !"O".equalsIgnoreCase(ioType)) {
|
||||
throw new ServiceException("仅支持入库/出库类型");
|
||||
}
|
||||
if (details == null || details.isEmpty()) {
|
||||
throw new ServiceException("单据明细不能为空");
|
||||
}
|
||||
for (GearStockIoOrderDetail d : details) {
|
||||
if (d == null) {
|
||||
continue;
|
||||
}
|
||||
if (!"material".equals(d.getItemType())) {
|
||||
throw new ServiceException("仅支持原料(主材/辅材)出入库");
|
||||
}
|
||||
fillMaterialSnapshotIfNeeded(d);
|
||||
BigDecimal qty = d.getQuantity() == null ? BigDecimal.ZERO : d.getQuantity();
|
||||
if (qty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal delta = "I".equalsIgnoreCase(ioType) ? qty : qty.negate();
|
||||
adjustMaterialStock(d.getItemId(), delta);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveUnit(String preferred, String itemType, Long itemId) {
|
||||
if (StringUtils.isNotBlank(preferred)) {
|
||||
return preferred;
|
||||
@@ -642,6 +472,14 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
if (snapshot == null) {
|
||||
throw new ServiceException("原料不存在:" + d.getItemId());
|
||||
}
|
||||
if (d.getMaterialTypeSnapshot() == null) {
|
||||
Object materialType = snapshot.get("materialType");
|
||||
if (materialType instanceof Number) {
|
||||
d.setMaterialTypeSnapshot(((Number) materialType).intValue());
|
||||
} else if (materialType != null && StringUtils.isNotBlank(String.valueOf(materialType))) {
|
||||
d.setMaterialTypeSnapshot(Integer.parseInt(String.valueOf(materialType)));
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(d.getItemName())) {
|
||||
Object name = snapshot.get("materialName");
|
||||
if (name != null) {
|
||||
@@ -656,7 +494,31 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustMaterialStock(Long materialId, BigDecimal delta) {
|
||||
private void applyMaterialStockChange(String ioType, List<GearStockIoOrderDetail> details, String insufficientMessage) {
|
||||
if (!"I".equalsIgnoreCase(ioType) && !"O".equalsIgnoreCase(ioType)) {
|
||||
throw new ServiceException("仅支持入库/出库类型");
|
||||
}
|
||||
if (details == null || details.isEmpty()) {
|
||||
throw new ServiceException("单据明细不能为空");
|
||||
}
|
||||
for (GearStockIoOrderDetail d : details) {
|
||||
if (d == null) {
|
||||
continue;
|
||||
}
|
||||
if (!"material".equals(d.getItemType())) {
|
||||
throw new ServiceException("仅支持原料(主材/辅材)出入库");
|
||||
}
|
||||
fillMaterialSnapshotIfNeeded(d);
|
||||
BigDecimal qty = d.getQuantity() == null ? BigDecimal.ZERO : d.getQuantity();
|
||||
if (qty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal delta = "I".equalsIgnoreCase(ioType) ? qty : qty.negate();
|
||||
adjustMaterialStock(d.getItemId(), delta, insufficientMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustMaterialStock(Long materialId, BigDecimal delta, String insufficientMessage) {
|
||||
if (delta == null || delta.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -673,24 +535,11 @@ public class GearStockIoOrderServiceImpl implements IGearStockIoOrderService {
|
||||
}
|
||||
BigDecimal after = currentStock.add(delta);
|
||||
if (after.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new ServiceException("原料库存不足,无法出库");
|
||||
throw new ServiceException(StringUtils.isBlank(insufficientMessage) ? "原料库存不足" : insufficientMessage);
|
||||
}
|
||||
matMaterialMapper.updateStockDelta(materialId, delta);
|
||||
}
|
||||
|
||||
private String reverseIoType(String ioType) {
|
||||
if ("I".equalsIgnoreCase(ioType)) {
|
||||
return "O";
|
||||
}
|
||||
if ("O".equalsIgnoreCase(ioType)) {
|
||||
return "I";
|
||||
}
|
||||
if ("T".equalsIgnoreCase(ioType)) {
|
||||
return "T";
|
||||
}
|
||||
return ioType;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static <T> T firstNonNull(T... values) {
|
||||
if (values == null) {
|
||||
|
||||
Reference in New Issue
Block a user