diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java index 430958b..757fa16 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java @@ -64,4 +64,11 @@ public interface MesWmProductIssueDetailService { */ void deleteProductIssueDetailByIssueId(Long issueId); + /** + * 根据行ID删除明细 + * + * @param lineId 行ID + */ + void deleteProductIssueDetailByLineId(Long lineId); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java index 4de03d7..be75e99 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java @@ -1,9 +1,14 @@ package cn.iocoder.yudao.module.mes.service.wm.productissue; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueDetailMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -12,7 +17,7 @@ import org.springframework.validation.annotation.Validated; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 领料出库明细 Service 实现类 @@ -26,12 +31,15 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta @Resource @Lazy + private MesWmProductIssueService issueService; + @Resource + @Lazy private MesWmProductIssueLineService issueLineService; @Override public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) { - // 校验父数据存在 - issueLineService.validateProductIssueLineExists(createReqVO.getLineId()); + // 校验数据 + validateProductIssueDetailSaveData(createReqVO); // 插入 MesWmProductIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductIssueDetailDO.class); @@ -43,8 +51,8 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta public void updateProductIssueDetail(MesWmProductIssueDetailSaveReqVO updateReqVO) { // 校验存在 validateProductIssueDetailExists(updateReqVO.getId()); - // 校验父数据存在 - issueLineService.validateProductIssueLineExists(updateReqVO.getLineId()); + // 校验数据 + validateProductIssueDetailSaveData(updateReqVO); // 更新 MesWmProductIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDetailDO.class); @@ -54,7 +62,19 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta @Override public void deleteProductIssueDetail(Long id) { // 校验存在 - validateProductIssueDetailExists(id); + MesWmProductIssueDetailDO detail = issueDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS); + } + // 校验主单状态为草稿或待拣货(允许在拣货模式删除明细) + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(detail.getLineId()); + MesWmProductIssueDO issue = issueService.validateProductIssueExists(line.getIssueId()); + if (!ObjectUtils.equalsAny(issue.getStatus(), + MesWmProductIssueStatusEnum.PREPARE.getStatus(), + MesWmProductIssueStatusEnum.APPROVING.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } + // 删除 issueDetailMapper.deleteById(id); } @@ -79,10 +99,35 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta issueDetailMapper.deleteByIssueId(issueId); } + @Override + public void deleteProductIssueDetailByLineId(Long lineId) { + issueDetailMapper.deleteByLineId(lineId); + } + private void validateProductIssueDetailExists(Long id) { if (issueDetailMapper.selectById(id) == null) { throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS); } } + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueDetailSaveData(MesWmProductIssueDetailSaveReqVO reqVO) { + // 校验父数据存在 + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(reqVO.getLineId()); + // 校验物料匹配(明细 itemId 必须与行 itemId 一致) + validateDetailItemMatch(reqVO.getItemId(), line.getItemId()); + } + + /** + * 校验明细物料与行物料一致 + */ + private void validateDetailItemMatch(Long detailItemId, Long lineItemId) { + if (ObjUtil.notEqual(detailItemId, lineItemId)) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH); + } + } + } + diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java index 9b9d187..4612b60 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java +++ b/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 private MesMdItemService itemService; @Resource private MesProWorkOrderBomService workOrderBomService; + @Resource + @Lazy + private MesWmProductIssueDetailService issueDetailService; @Override public Long createProductIssueLine(MesWmProductIssueLineSaveReqVO createReqVO) { - // 校验父数据存在 + 校验物料在工单 BOM 中 - validateItemInWorkOrderBom(createReqVO.getIssueId(), createReqVO.getItemId()); - // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); + validateProductIssueLineSaveData(createReqVO); // 插入 MesWmProductIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmProductIssueLineDO.class); @@ -57,10 +57,7 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe public void updateProductIssueLine(MesWmProductIssueLineSaveReqVO updateReqVO) { // 校验存在 validateProductIssueLineExists(updateReqVO.getId()); - // 校验父数据存在 + 校验物料在工单 BOM 中 - validateItemInWorkOrderBom(updateReqVO.getIssueId(), updateReqVO.getItemId()); - // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); + validateProductIssueLineSaveData(updateReqVO); // 更新 MesWmProductIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueLineDO.class); @@ -70,8 +67,12 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe @Override public void deleteProductIssueLine(Long id) { // 校验存在 - validateProductIssueLineExists(id); - // 删除 + MesWmProductIssueLineDO line = validateProductIssueLineExists(id); + // 校验主单为草稿状态才允许删除行 + issueService.validateProductIssueExistsAndPrepare(line.getIssueId()); + // 级联删除该行的明细 + issueDetailService.deleteProductIssueDetailByLineId(id); + // 删除行 issueLineMapper.deleteById(id); } @@ -104,6 +105,16 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe return line; } + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueLineSaveData(MesWmProductIssueLineSaveReqVO reqVO) { + // 校验父数据存在 + 校验物料在工单 BOM 中 + validateItemInWorkOrderBom(reqVO.getIssueId(), reqVO.getItemId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + private void validateItemInWorkOrderBom(Long issueId, Long itemId) { // 校验领料单存在,并获取工单编号 MesWmProductIssueDO issue = issueService.validateProductIssueExists(issueId); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java index 67de831..ea45bf3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java +++ b/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; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -67,10 +68,7 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { @Transactional(rollbackFor = Exception.class) public Long createProductIssue(MesWmProductIssueSaveReqVO createReqVO) { // 1. 校验关联数据 - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); - if (createReqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); - } + validateProductIssueSaveData(createReqVO); // 2. 插入主表 MesWmProductIssueDO issue = BeanUtils.toBean(createReqVO, MesWmProductIssueDO.class); @@ -85,10 +83,7 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { // 1.1 校验存在 + 准备中状态 validateProductIssueExistsAndPrepare(updateReqVO.getId()); // 1.2 校验关联数据 - workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId()); - if (updateReqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(updateReqVO.getWorkstationId()); - } + validateProductIssueSaveData(updateReqVO); // 2. 更新主表 MesWmProductIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDO.class); @@ -160,9 +155,10 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) createTransactionList(issue); - // 3. 更新出库单状态 + // 3. 更新出库单状态 + 领料日期 issueMapper.updateById(new MesWmProductIssueDO() - .setId(id).setStatus(MesWmProductIssueStatusEnum.FINISHED.getStatus())); + .setId(id).setStatus(MesWmProductIssueStatusEnum.FINISHED.getStatus()) + .setIssueDate(LocalDateTime.now())); } private void createTransactionList(MesWmProductIssueDO issue) { @@ -237,7 +233,8 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { /** * 校验领料出库单存在且为准备中状态 */ - private MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id) { + @Override + public MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id) { MesWmProductIssueDO issue = validateProductIssueExists(id); if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); @@ -245,4 +242,28 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { return issue; } + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmProductIssueDO issue = issueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_PRODUCT_ISSUE_CODE_DUPLICATE); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueSaveData(MesWmProductIssueSaveReqVO reqVO) { + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + if (reqVO.getWorkstationId() != null) { + workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + } + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java index 9632717..ef7db2c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java +++ b/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 { @Transactional(rollbackFor = Exception.class) public Long createReturnIssue(MesWmReturnIssueSaveReqVO createReqVO) { // 1. 校验关联数据 - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); - if (createReqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); - } + validateReturnIssueSaveData(createReqVO); // 2. 插入主表 MesWmReturnIssueDO issue = BeanUtils.toBean(createReqVO, MesWmReturnIssueDO.class); @@ -91,10 +88,7 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { // 1.1 校验存在 + 准备中状态 MesWmReturnIssueDO oldIssue = validateReturnIssueExistsAndPrepare(updateReqVO.getId()); // 1.2 校验关联数据 - workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId()); - if (updateReqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(updateReqVO.getWorkstationId()); - } + validateReturnIssueSaveData(updateReqVO); // 2. 更新主表 MesWmReturnIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnIssueDO.class); @@ -274,4 +268,14 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { issueMapper.updateById(new MesWmReturnIssueDO().setId(id).setStatus(status)); } + /** + * 校验保存时的关联数据 + */ + private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) { + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + if (reqVO.getWorkstationId() != null) { + workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + } + } + }