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.mdm.MesMdmItemDO; 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 cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.List; import cn.iocoder.yudao.framework.common.exception.ServiceException; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 领料出库明细 Service 实现类 */ @Service @Validated public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDetailService { @Resource private MesWmProductIssueDetailMapper issueDetailMapper; @Resource @Lazy private MesWmProductIssueService issueService; @Resource @Lazy private MesWmProductIssueLineService issueLineService; @Resource private MesWmWarehouseAreaService warehouseAreaService; @Resource private MesWmMaterialStockService materialStockService; @Resource private MesMdmItemService mdmItemService; @Override public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) { // 校验数据 validateProductIssueDetailSaveData(createReqVO); // 插入 MesWmProductIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductIssueDetailDO.class); issueDetailMapper.insert(detail); return detail.getId(); } @Override public void updateProductIssueDetail(MesWmProductIssueDetailSaveReqVO updateReqVO) { // 校验存在 validateProductIssueDetailExists(updateReqVO.getId()); // 校验数据 validateProductIssueDetailSaveData(updateReqVO); // 更新 MesWmProductIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDetailDO.class); issueDetailMapper.updateById(updateObj); } @Override public void deleteProductIssueDetail(Long 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); } @Override public MesWmProductIssueDetailDO getProductIssueDetail(Long id) { return issueDetailMapper.selectById(id); } @Override public List getProductIssueDetailListByLineId(Long lineId) { return issueDetailMapper.selectListByLineId(lineId); } @Override public List getProductIssueDetailListByIssueId(Long issueId) { return issueDetailMapper.selectListByIssueId(issueId); } @Override public void deleteProductIssueDetailByIssueId(Long issueId) { 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()); if (ObjUtil.notEqual(line.getIssueId(), reqVO.getIssueId())) { throw exception(WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH); } // 校验主单状态为待拣货(只有 APPROVING 状态才允许新增/修改明细) MesWmProductIssueDO issue = issueService.validateProductIssueExists(line.getIssueId()); if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); } // 校验物料匹配(明细 itemId 必须与行 itemId 一致,两者都是 MDM 物料主数据 mdm_item.id) validateDetailItemMatch(reqVO.getItemId(), line.getItemId()); // 校验仓库、库区、库位的关联关系 warehouseAreaService.validateWarehouseAreaExists( reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); // 校验库存记录 materialStockService.validateSelectedStock( reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); } /** * 校验明细物料与行物料一致 */ private void validateDetailItemMatch(Long detailItemId, Long lineItemId) { if (ObjUtil.notEqual(detailItemId, lineItemId)) { // 名称解析放在异常分支,避免正常保存时多查表 throw new ServiceException(WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH.getCode(), "拣货明细的物料与领料出库单行的物料不一致:明细物料[" + describeItem(detailItemId) + "],单据行物料[" + describeItem(lineItemId) + "]。" + "请重新选择该行的物料后重试,或删除本条明细后重新添加。"); } } /** * 描述物料,用于异常提示:优先给出「编码 名称」,查不到时回退为物料编号 */ private String describeItem(Long itemId) { if (itemId == null) { return "未选择"; } MesMdmItemDO item = mdmItemService.getItem(itemId); return item != null ? item.getCode() + " " + item.getName() : "物料编号 ID=" + itemId; } }