diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java index 18ed610..61dd3a0 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateDetailService; import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -56,6 +57,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @Resource private MesWmArrivalNoticeService arrivalNoticeService; @Resource + private MesWmOutsourceReceiptService outsourceReceiptService; + @Resource private MesMdVendorService vendorService; @Resource private MesMdItemService itemService; @@ -147,8 +150,10 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(iqc.getSourceDocId(), iqc.getSourceLineId(), iqc.getId(), iqc.getQualifiedQuantity()); + } else if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_OUTSOURCE_RECPT)) { + outsourceReceiptService.approveOutsourceReceiptWhenIqcComplete(iqc.getSourceDocId(), iqc.getSourceLineId(), + iqc.getId(), iqc.getQualifiedQuantity(), iqc.getUnqualifiedQuantity()); } - // TODO 外协入库单:未实现,占位 } @Override diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java index 22a11e0..278ee01 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java @@ -51,10 +51,32 @@ public interface MesWmOutsourceReceiptLineService { PageResult getOutsourceReceiptLinePage(MesWmOutsourceReceiptLinePageReqVO pageReqVO); /** - * 删除委外收货单行(根据收货单编号) + * 获得外协入库单行列表(根据入库单编号) * - * @param receiptId 收货单编号 + * @param receiptId 入库单编号 + * @return 外协入库单行列表 + */ + List getOutsourceReceiptLineListByReceiptId(Long receiptId); + + /** + * 删除外协入库单行(根据入库单编号) + * + * @param receiptId 入库单编号 */ void deleteOutsourceReceiptLineByReceiptId(Long receiptId); + /** + * 直接更新外协入库单行 DO(用于 IQC 回写) + * + * @param line 行 DO + */ + void updateOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line); + + /** + * 直接插入外协入库单行 DO(用于 QC 按质量拆分行) + * + * @param line 行 DO + */ + void createOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java index 1df2a22..d60aaf0 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java @@ -12,6 +12,8 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; 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_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS; @@ -82,6 +84,11 @@ public class MesWmOutsourceReceiptLineServiceImpl implements MesWmOutsourceRecei } @Override + public List getOutsourceReceiptLineListByReceiptId(Long receiptId) { + return lineMapper.selectListByReceiptId(receiptId); + } + + @Override public void deleteOutsourceReceiptLineByReceiptId(Long receiptId) { lineMapper.deleteByReceiptId(receiptId); } @@ -92,4 +99,14 @@ public class MesWmOutsourceReceiptLineServiceImpl implements MesWmOutsourceRecei } } + @Override + public void updateOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line) { + lineMapper.updateById(line); + } + + @Override + public void createOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line) { + lineMapper.insert(line); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java index 6c19274..d9600df 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWm import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; import jakarta.validation.Valid; +import java.math.BigDecimal; + /** * MES 外协入库单 Service 接口 */ @@ -77,4 +79,16 @@ public interface MesWmOutsourceReceiptService { */ void cancelOutsourceReceipt(Long id); + /** + * IQC 检验完成后回写外协入库单(拆分行 + 推进主表状态) + * + * @param receiptId 外协入库单编号 + * @param lineId 入库单行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格品数量 + * @param unqualifiedQuantity 不合格品数量 + */ + void approveOutsourceReceiptWhenIqcComplete(Long receiptId, Long lineId, Long iqcId, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java index d612684..c082838 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java @@ -6,14 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; -import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptDetailMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptLineMapper; + import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptMapper; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceReceiptStatusEnum; @@ -23,7 +22,6 @@ import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,23 +46,16 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe private MesWmOutsourceReceiptMapper outsourceReceiptMapper; @Resource - private MesWmOutsourceReceiptLineMapper outsourceReceiptLineMapper; - + private MesWmOutsourceReceiptLineService outsourceReceiptLineService; @Resource - private MesWmOutsourceReceiptDetailMapper outsourceReceiptDetailMapper; - + private MesWmOutsourceReceiptDetailService outsourceReceiptDetailService; @Resource private MesWmTransactionService wmTransactionService; - @Resource private MesMdVendorService vendorService; - @Resource private MesMdItemService itemService; - @Resource - private MesWmWarehouseAreaService warehouseAreaService; - @Override public Long createOutsourceReceipt(MesWmOutsourceReceiptSaveReqVO createReqVO) { // 校验编码唯一 @@ -100,8 +91,8 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe validateOutsourceReceiptExistsAndDraft(id); // 级联删除明细和行 - outsourceReceiptDetailMapper.deleteByReceiptId(id); - outsourceReceiptLineMapper.deleteByReceiptId(id); + outsourceReceiptDetailService.deleteOutsourceReceiptDetailByReceiptId(id); + outsourceReceiptLineService.deleteOutsourceReceiptLineByReceiptId(id); // 删除 outsourceReceiptMapper.deleteById(id); } @@ -122,7 +113,7 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe // 校验存在 + 草稿状态 validateOutsourceReceiptExistsAndDraft(id); // 校验至少有一条行 - List lines = outsourceReceiptLineMapper.selectListByReceiptId(id); + List lines = outsourceReceiptLineService.getOutsourceReceiptLineListByReceiptId(id); if (CollUtil.isEmpty(lines)) { throw exception(WM_OUTSOURCE_RECEIPT_NO_LINE); } @@ -146,10 +137,10 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); } // 1.2 检查每个行的明细数量是否完成上架 - List lines = outsourceReceiptLineMapper.selectListByReceiptId(id); + List lines = outsourceReceiptLineService.getOutsourceReceiptLineListByReceiptId(id); if (CollUtil.isNotEmpty(lines)) { // 批量查询所有明细 - List allDetails = outsourceReceiptDetailMapper.selectListByReceiptId(id); + List allDetails = outsourceReceiptDetailService.getOutsourceReceiptDetailListByReceiptId(id); Map> detailMap = CollectionUtils.convertMultiMap( allDetails, MesWmOutsourceReceiptDetailDO::getLineId); // 检查每行的明细数量 @@ -189,7 +180,7 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe } private void createTransactionList(MesWmOutsourceReceiptDO receipt) { - List details = outsourceReceiptDetailMapper.selectListByReceiptId(receipt.getId()); + List details = outsourceReceiptDetailService.getOutsourceReceiptDetailListByReceiptId(receipt.getId()); wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) .setQuantity(detail.getQuantity()) // 入库数量为正数 @@ -216,6 +207,41 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.CANCELED.getStatus())); } + @Override + @Transactional(rollbackFor = Exception.class) + public void approveOutsourceReceiptWhenIqcComplete(Long receiptId, Long lineId, Long iqcId, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { + // 1.1 校验入库单存在 + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(receiptId); + // 1.2 校验状态为待检验 + if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus(), receipt.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); + } + // 1.3 校验行存在 + MesWmOutsourceReceiptLineDO line = outsourceReceiptLineService.getOutsourceReceiptLine(lineId); + if (line == null) { + throw exception(WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + + // 2.1 合格品处理:更新原行(new 一个 DO,避免覆盖更新) + if (qualifiedQuantity != null && qualifiedQuantity.compareTo(BigDecimal.ZERO) > 0) { + outsourceReceiptLineService.updateOutsourceReceiptLineDO(new MesWmOutsourceReceiptLineDO() + .setId(lineId).setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .setIqcId(iqcId).setQuantity(qualifiedQuantity)); + } + // 2.2 不合格品处理:拷贝原行全部属性,新增一行 + if (unqualifiedQuantity != null && unqualifiedQuantity.compareTo(BigDecimal.ZERO) > 0) { + MesWmOutsourceReceiptLineDO unqualifiedLine = BeanUtils.toBean(line, MesWmOutsourceReceiptLineDO.class) + .setId(null).setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .setIqcId(iqcId).setQuantity(unqualifiedQuantity); + outsourceReceiptLineService.createOutsourceReceiptLineDO(unqualifiedLine); + } + + // 3. 直接更新主表状态为"待上架"(对齐 KTG:IQC 完成后直接推进状态) + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(receiptId).setStatus(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus())); + } + private MesWmOutsourceReceiptDO validateOutsourceReceiptExists(Long id) { MesWmOutsourceReceiptDO receipt = outsourceReceiptMapper.selectById(id); if (receipt == null) {