Commit e081a59949f26002bc51c4f3638081c31ebc52b9

Authored by YunaiV
1 parent ce7b88c2

✨ feat(mes): 新增根据行ID删除明细功能,优化数据校验逻辑

yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java
... ... @@ -64,4 +64,11 @@ public interface MesWmProductIssueDetailService {
64 64 */
65 65 void deleteProductIssueDetailByIssueId(Long issueId);
66 66  
  67 + /**
  68 + * 根据行ID删除明细
  69 + *
  70 + * @param lineId 行ID
  71 + */
  72 + void deleteProductIssueDetailByLineId(Long lineId);
  73 +
67 74 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.wm.productissue;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
4 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailSaveReqVO;
5 7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO;
6 10 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueDetailMapper;
  11 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum;
7 12 import jakarta.annotation.Resource;
8 13 import org.springframework.context.annotation.Lazy;
9 14 import org.springframework.stereotype.Service;
... ... @@ -12,7 +17,7 @@ import org.springframework.validation.annotation.Validated;
12 17 import java.util.List;
13 18  
14 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
15   -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
16 21  
17 22 /**
18 23 * MES 领料出库明细 Service 实现类
... ... @@ -26,12 +31,15 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta
26 31  
27 32 @Resource
28 33 @Lazy
  34 + private MesWmProductIssueService issueService;
  35 + @Resource
  36 + @Lazy
29 37 private MesWmProductIssueLineService issueLineService;
30 38  
31 39 @Override
32 40 public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) {
33   - // 校验父数据存在
34   - issueLineService.validateProductIssueLineExists(createReqVO.getLineId());
  41 + // 校验数据
  42 + validateProductIssueDetailSaveData(createReqVO);
35 43  
36 44 // 插入
37 45 MesWmProductIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductIssueDetailDO.class);
... ... @@ -43,8 +51,8 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta
43 51 public void updateProductIssueDetail(MesWmProductIssueDetailSaveReqVO updateReqVO) {
44 52 // 校验存在
45 53 validateProductIssueDetailExists(updateReqVO.getId());
46   - // 校验父数据存在
47   - issueLineService.validateProductIssueLineExists(updateReqVO.getLineId());
  54 + // 校验数据
  55 + validateProductIssueDetailSaveData(updateReqVO);
48 56  
49 57 // 更新
50 58 MesWmProductIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDetailDO.class);
... ... @@ -54,7 +62,19 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta
54 62 @Override
55 63 public void deleteProductIssueDetail(Long id) {
56 64 // 校验存在
57   - validateProductIssueDetailExists(id);
  65 + MesWmProductIssueDetailDO detail = issueDetailMapper.selectById(id);
  66 + if (detail == null) {
  67 + throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS);
  68 + }
  69 + // 校验主单状态为草稿或待拣货(允许在拣货模式删除明细)
  70 + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(detail.getLineId());
  71 + MesWmProductIssueDO issue = issueService.validateProductIssueExists(line.getIssueId());
  72 + if (!ObjectUtils.equalsAny(issue.getStatus(),
  73 + MesWmProductIssueStatusEnum.PREPARE.getStatus(),
  74 + MesWmProductIssueStatusEnum.APPROVING.getStatus())) {
  75 + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID);
  76 + }
  77 +
58 78 // 删除
59 79 issueDetailMapper.deleteById(id);
60 80 }
... ... @@ -79,10 +99,35 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta
79 99 issueDetailMapper.deleteByIssueId(issueId);
80 100 }
81 101  
  102 + @Override
  103 + public void deleteProductIssueDetailByLineId(Long lineId) {
  104 + issueDetailMapper.deleteByLineId(lineId);
  105 + }
  106 +
82 107 private void validateProductIssueDetailExists(Long id) {
83 108 if (issueDetailMapper.selectById(id) == null) {
84 109 throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS);
85 110 }
86 111 }
87 112  
  113 + /**
  114 + * 校验保存时的关联数据
  115 + */
  116 + private void validateProductIssueDetailSaveData(MesWmProductIssueDetailSaveReqVO reqVO) {
  117 + // 校验父数据存在
  118 + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(reqVO.getLineId());
  119 + // 校验物料匹配(明细 itemId 必须与行 itemId 一致)
  120 + validateDetailItemMatch(reqVO.getItemId(), line.getItemId());
  121 + }
  122 +
  123 + /**
  124 + * 校验明细物料与行物料一致
  125 + */
  126 + private void validateDetailItemMatch(Long detailItemId, Long lineItemId) {
  127 + if (ObjUtil.notEqual(detailItemId, lineItemId)) {
  128 + throw exception(WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH);
  129 + }
  130 + }
  131 +
88 132 }
  133 +
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java
... ... @@ -39,13 +39,13 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe
39 39 private MesMdItemService itemService;
40 40 @Resource
41 41 private MesProWorkOrderBomService workOrderBomService;
  42 + @Resource
  43 + @Lazy
  44 + private MesWmProductIssueDetailService issueDetailService;
42 45  
43 46 @Override
44 47 public Long createProductIssueLine(MesWmProductIssueLineSaveReqVO createReqVO) {
45   - // 校验父数据存在 + 校验物料在工单 BOM 中
46   - validateItemInWorkOrderBom(createReqVO.getIssueId(), createReqVO.getItemId());
47   - // 校验物料存在
48   - itemService.validateItemExists(createReqVO.getItemId());
  48 + validateProductIssueLineSaveData(createReqVO);
49 49  
50 50 // 插入
51 51 MesWmProductIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmProductIssueLineDO.class);
... ... @@ -57,10 +57,7 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe
57 57 public void updateProductIssueLine(MesWmProductIssueLineSaveReqVO updateReqVO) {
58 58 // 校验存在
59 59 validateProductIssueLineExists(updateReqVO.getId());
60   - // 校验父数据存在 + 校验物料在工单 BOM 中
61   - validateItemInWorkOrderBom(updateReqVO.getIssueId(), updateReqVO.getItemId());
62   - // 校验物料存在
63   - itemService.validateItemExists(updateReqVO.getItemId());
  60 + validateProductIssueLineSaveData(updateReqVO);
64 61  
65 62 // 更新
66 63 MesWmProductIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueLineDO.class);
... ... @@ -70,8 +67,12 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe
70 67 @Override
71 68 public void deleteProductIssueLine(Long id) {
72 69 // 校验存在
73   - validateProductIssueLineExists(id);
74   - // 删除
  70 + MesWmProductIssueLineDO line = validateProductIssueLineExists(id);
  71 + // 校验主单为草稿状态才允许删除行
  72 + issueService.validateProductIssueExistsAndPrepare(line.getIssueId());
  73 + // 级联删除该行的明细
  74 + issueDetailService.deleteProductIssueDetailByLineId(id);
  75 + // 删除行
75 76 issueLineMapper.deleteById(id);
76 77 }
77 78  
... ... @@ -104,6 +105,16 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe
104 105 return line;
105 106 }
106 107  
  108 + /**
  109 + * 校验保存时的关联数据
  110 + */
  111 + private void validateProductIssueLineSaveData(MesWmProductIssueLineSaveReqVO reqVO) {
  112 + // 校验父数据存在 + 校验物料在工单 BOM 中
  113 + validateItemInWorkOrderBom(reqVO.getIssueId(), reqVO.getItemId());
  114 + // 校验物料存在
  115 + itemService.validateItemExists(reqVO.getItemId());
  116 + }
  117 +
107 118 private void validateItemInWorkOrderBom(Long issueId, Long itemId) {
108 119 // 校验领料单存在,并获取工单编号
109 120 MesWmProductIssueDO issue = issueService.validateProductIssueExists(issueId);
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java
... ... @@ -31,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional;
31 31 import org.springframework.validation.annotation.Validated;
32 32  
33 33 import java.math.BigDecimal;
  34 +import java.time.LocalDateTime;
34 35 import java.util.List;
35 36  
36 37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -67,10 +68,7 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService {
67 68 @Transactional(rollbackFor = Exception.class)
68 69 public Long createProductIssue(MesWmProductIssueSaveReqVO createReqVO) {
69 70 // 1. 校验关联数据
70   - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId());
71   - if (createReqVO.getWorkstationId() != null) {
72   - workstationService.validateWorkstationExists(createReqVO.getWorkstationId());
73   - }
  71 + validateProductIssueSaveData(createReqVO);
74 72  
75 73 // 2. 插入主表
76 74 MesWmProductIssueDO issue = BeanUtils.toBean(createReqVO, MesWmProductIssueDO.class);
... ... @@ -85,10 +83,7 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService {
85 83 // 1.1 校验存在 + 准备中状态
86 84 validateProductIssueExistsAndPrepare(updateReqVO.getId());
87 85 // 1.2 校验关联数据
88   - workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId());
89   - if (updateReqVO.getWorkstationId() != null) {
90   - workstationService.validateWorkstationExists(updateReqVO.getWorkstationId());
91   - }
  86 + validateProductIssueSaveData(updateReqVO);
92 87  
93 88 // 2. 更新主表
94 89 MesWmProductIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDO.class);
... ... @@ -160,9 +155,10 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService {
160 155 // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水)
161 156 createTransactionList(issue);
162 157  
163   - // 3. 更新出库单状态
  158 + // 3. 更新出库单状态 + 领料日期
164 159 issueMapper.updateById(new MesWmProductIssueDO()
165   - .setId(id).setStatus(MesWmProductIssueStatusEnum.FINISHED.getStatus()));
  160 + .setId(id).setStatus(MesWmProductIssueStatusEnum.FINISHED.getStatus())
  161 + .setIssueDate(LocalDateTime.now()));
166 162 }
167 163  
168 164 private void createTransactionList(MesWmProductIssueDO issue) {
... ... @@ -237,7 +233,8 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService {
237 233 /**
238 234 * 校验领料出库单存在且为准备中状态
239 235 */
240   - private MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id) {
  236 + @Override
  237 + public MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id) {
241 238 MesWmProductIssueDO issue = validateProductIssueExists(id);
242 239 if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) {
243 240 throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID);
... ... @@ -245,4 +242,28 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService {
245 242 return issue;
246 243 }
247 244  
  245 + /**
  246 + * 校验编码唯一性
  247 + */
  248 + private void validateCodeUnique(Long id, String code) {
  249 + MesWmProductIssueDO issue = issueMapper.selectByCode(code);
  250 + if (issue == null) {
  251 + return;
  252 + }
  253 + if (ObjUtil.notEqual(id, issue.getId())) {
  254 + throw exception(WM_PRODUCT_ISSUE_CODE_DUPLICATE);
  255 + }
  256 + }
  257 +
  258 + /**
  259 + * 校验保存时的关联数据
  260 + */
  261 + private void validateProductIssueSaveData(MesWmProductIssueSaveReqVO reqVO) {
  262 + validateCodeUnique(reqVO.getId(), reqVO.getCode());
  263 + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId());
  264 + if (reqVO.getWorkstationId() != null) {
  265 + workstationService.validateWorkstationExists(reqVO.getWorkstationId());
  266 + }
  267 + }
  268 +
248 269 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java
... ... @@ -73,10 +73,7 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService {
73 73 @Transactional(rollbackFor = Exception.class)
74 74 public Long createReturnIssue(MesWmReturnIssueSaveReqVO createReqVO) {
75 75 // 1. 校验关联数据
76   - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId());
77   - if (createReqVO.getWorkstationId() != null) {
78   - workstationService.validateWorkstationExists(createReqVO.getWorkstationId());
79   - }
  76 + validateReturnIssueSaveData(createReqVO);
80 77  
81 78 // 2. 插入主表
82 79 MesWmReturnIssueDO issue = BeanUtils.toBean(createReqVO, MesWmReturnIssueDO.class);
... ... @@ -91,10 +88,7 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService {
91 88 // 1.1 校验存在 + 准备中状态
92 89 MesWmReturnIssueDO oldIssue = validateReturnIssueExistsAndPrepare(updateReqVO.getId());
93 90 // 1.2 校验关联数据
94   - workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId());
95   - if (updateReqVO.getWorkstationId() != null) {
96   - workstationService.validateWorkstationExists(updateReqVO.getWorkstationId());
97   - }
  91 + validateReturnIssueSaveData(updateReqVO);
98 92  
99 93 // 2. 更新主表
100 94 MesWmReturnIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnIssueDO.class);
... ... @@ -274,4 +268,14 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService {
274 268 issueMapper.updateById(new MesWmReturnIssueDO().setId(id).setStatus(status));
275 269 }
276 270  
  271 + /**
  272 + * 校验保存时的关联数据
  273 + */
  274 + private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) {
  275 + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId());
  276 + if (reqVO.getWorkstationId() != null) {
  277 + workstationService.validateWorkstationExists(reqVO.getWorkstationId());
  278 + }
  279 + }
  280 +
277 281 }
... ...