From 74ad846852f42b4e2258bfddd5c2a33cc1ce9847 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 29 八月 2026 18:03:46 +0800
Subject: [PATCH] feat(mes): 新增工序等待时长和报工数量配置功能
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 157 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
index 100627f..a7bf199 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java
@@ -8,18 +8,29 @@
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptStockReqVO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptLineDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptDetailMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptLineMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptMapper;
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
+import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductReceiptStatusEnum;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
+import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
+import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
+import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
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;
@@ -31,7 +42,9 @@
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
+import java.time.LocalDateTime;
import java.util.List;
+import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
@@ -45,6 +58,10 @@
@Resource
private MesWmProductReceiptMapper productReceiptMapper;
+ @Resource
+ private MesWmProductReceiptLineMapper productReceiptLineMapper;
+ @Resource
+ private MesWmProductReceiptDetailMapper productReceiptDetailMapper;
@Resource
private MesWmProductReceiptLineService productReceiptLineService;
@@ -60,6 +77,14 @@
private MesWmWarehouseLocationService locationService;
@Resource
private MesWmWarehouseAreaService areaService;
+ @Resource
+ private MesWmProductProduceMapper productProduceMapper;
+ @Resource
+ private MesWmProductProduceLineService productProduceLineService;
+ @Resource
+ private MesProFeedbackService feedbackService;
+ @Resource
+ private MesMdAutoCodeRecordService autoCodeRecordService;
@Override
public Long createProductReceipt(MesWmProductReceiptSaveReqVO createReqVO) {
@@ -166,6 +191,8 @@
if (ObjUtil.notEqual(MesWmProductReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) {
throw exception(WM_PRODUCT_RECPT_STATUS_ERROR);
}
+ // 鏈嬀閫夊叆搴撴垨鏈垎閰嶅畬鐨勬暟閲忛粯璁よˉ鍒颁笉鍚堟牸浠撳簱
+ supplementDefectDetails(receipt);
// 鏍¢獙鏄庣粏闈炵┖
List<MesWmProductReceiptDetailDO> details = productReceiptDetailService.getProductReceiptDetailListByRecptId(id);
if (CollUtil.isEmpty(details)) {
@@ -180,6 +207,136 @@
.setId(id).setStatus(MesWmProductReceiptStatusEnum.FINISHED.getStatus()));
}
+ /**
+ * 涓烘湭鍕鹃�夊叆搴擄紙is_stock=false/绌猴級鎴栧垎閰嶆暟閲忎笉瓒崇殑琛岃ˉ涓�鏉′笉鍚堟牸浠撳簱鏄庣粏
+ *
+ * <p>姣忚鍓╀綑鏁伴噺 = 琛屾敹璐ф暟閲� - 宸插垎閰嶆槑缁嗘暟閲忎箣鍜岋紝鍓╀綑 > 0 鏃惰嚜鍔ㄦ彃鍏ヤ笉鍚堟牸浠撳簱涓夌骇鏄庣粏锛�
+ * 淇濊瘉鎵ц鍏ュ簱鏃朵竴涓暟閲忓搴斾竴鏉℃祦姘淬��
+ */
+ private void supplementDefectDetails(MesWmProductReceiptDO receipt) {
+ List<MesWmProductReceiptLineDO> lines = productReceiptLineService.getProductReceiptLineListByRecptId(receipt.getId());
+ for (MesWmProductReceiptLineDO line : lines) {
+ List<MesWmProductReceiptDetailDO> details = productReceiptDetailService.getProductReceiptDetailListByLineId(line.getId());
+ BigDecimal sumDetailQty = CollectionUtils.getSumValue(details,
+ MesWmProductReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO);
+ BigDecimal remaining = line.getQuantity().subtract(sumDetailQty);
+ if (remaining.compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ // 鏌ヨ涓嶅悎鏍间粨搴撲笁绾э紙鎸夌紪鐮佺害瀹氳瘑鍒級
+ MesWmWarehouseDO defectWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.DEFECT_WAREHOUSE);
+ MesWmWarehouseLocationDO defectLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.DEFECT_LOCATION);
+ MesWmWarehouseAreaDO defectArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.DEFECT_AREA);
+ if (defectWarehouse == null || defectLocation == null || defectArea == null) {
+ throw exception(WM_PRODUCT_RECPT_NO_DEFECT_WAREHOUSE);
+ }
+ productReceiptDetailMapper.insert(new MesWmProductReceiptDetailDO()
+ .setLineId(line.getId())
+ .setReceiptId(receipt.getId())
+ .setItemId(line.getItemId())
+ .setQuantity(remaining)
+ .setBatchId(line.getBatchId())
+ .setWarehouseId(defectWarehouse.getId())
+ .setLocationId(defectLocation.getId())
+ .setAreaId(defectArea.getId()));
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Long createProductReceiptByFeedback(Long feedbackId) {
+ // 骞傜瓑锛氫竴娆℃姤宸ュ彧鐢熸垚涓�鏉′骇鍝佸叆搴撳崟
+ MesWmProductReceiptDO existing = productReceiptMapper.selectByFeedbackId(feedbackId);
+ if (existing != null) {
+ return existing.getId();
+ }
+ // 鏍¢獙鎶ュ伐瀛樺湪
+ MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(feedbackId);
+ // 鐢熸垚缂栫爜骞舵彃鍏ュ叆搴撳崟
+ MesWmProductReceiptDO receipt = new MesWmProductReceiptDO()
+ .setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRODUCTRECPT_CODE.getCode()))
+ .setName("浜у搧鍏ュ簱-" + feedback.getCode())
+ .setWorkOrderId(feedback.getWorkOrderId())
+ .setItemId(feedback.getItemId())
+ .setFeedbackId(feedbackId)
+ .setReceiptDate(LocalDateTime.now())
+ .setStatus(MesWmProductReceiptStatusEnum.PREPARE.getStatus());
+ productReceiptMapper.insert(receipt);
+ // 浠庝骇鍑哄崟浜у嚭琛岀敓鎴愬叆搴撳崟琛岋紙鍚堟牸/涓嶅悎鏍煎垎琛岋紝璐ㄩ噺鐘舵�佸師鏍峰甫鍏ワ級
+ MesWmProductProduceDO produce = productProduceMapper.selectByFeedbackId(feedbackId);
+ if (produce != null) {
+ List<MesWmProductProduceLineDO> produceLines = productProduceLineService.getProductProduceLineListByProduceId(produce.getId());
+ for (MesWmProductProduceLineDO produceLine : produceLines) {
+ if (produceLine.getQuantity() == null || produceLine.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+ continue;
+ }
+ productReceiptLineMapper.insert(new MesWmProductReceiptLineDO()
+ .setReceiptId(receipt.getId())
+ .setItemId(produceLine.getItemId())
+ .setQuantity(produceLine.getQuantity())
+ .setBatchId(produceLine.getBatchId())
+ .setBatchCode(produceLine.getBatchCode())
+ .setQualityStatus(produceLine.getQualityStatus())
+ .setIsStock(Boolean.FALSE));
+ }
+ }
+ return receipt.getId();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void submitStock(MesWmProductReceiptStockReqVO reqVO) {
+ // 鏍¢獙鍏ュ簱鍗曞瓨鍦ㄤ笖涓哄緟涓婃灦锛圓PPROVING锛�
+ MesWmProductReceiptDO receipt = validateProductReceiptExists(reqVO.getReceiptId());
+ if (ObjUtil.notEqual(MesWmProductReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) {
+ throw exception(WM_PRODUCT_RECPT_STATUS_ERROR);
+ }
+ List<MesWmProductReceiptStockReqVO.Row> rows = reqVO.getRows();
+ if (CollUtil.isEmpty(rows)) {
+ throw exception(WM_PRODUCT_RECPT_NO_LINE);
+ }
+ // 閫愯澶勭悊锛氭洿鏂版槸鍚﹀叆搴� + 閲嶅缓涓婃灦鏄庣粏
+ for (MesWmProductReceiptStockReqVO.Row row : rows) {
+ MesWmProductReceiptLineDO line = productReceiptLineMapper.selectById(row.getLineId());
+ if (line == null || !ObjUtil.equal(line.getReceiptId(), receipt.getId())) {
+ throw exception(WM_PRODUCT_RECPT_LINE_NOT_EXISTS);
+ }
+ Boolean isStock = Boolean.TRUE.equals(row.getIsStock());
+ productReceiptLineMapper.updateById(new MesWmProductReceiptLineDO()
+ .setId(line.getId()).setIsStock(isStock));
+ // 鍒犻櫎璇ヨ鏃ф槑缁嗭紝閲嶅缓鍒嗛厤
+ productReceiptDetailService.deleteProductReceiptDetailByLineId(line.getId());
+ if (!isStock) {
+ continue; // 鏈嬀閫夛細涓嶅垎閰嶏紝鎵ц鍏ュ簱鏃惰嚜鍔ㄨ繘涓嶅悎鏍间粨搴�
+ }
+ // 鍕鹃�夊叆搴擄細鍒嗛厤鏁伴噺涔嬪拰蹇呴』绛変簬琛屾敹璐ф暟閲�
+ List<MesWmProductReceiptStockReqVO.Detail> details = row.getDetails();
+ if (CollUtil.isEmpty(details)) {
+ throw exception(WM_PRODUCT_RECPT_STOCK_QUANTITY_MISMATCH);
+ }
+ BigDecimal sumDetailQty = details.stream()
+ .map(MesWmProductReceiptStockReqVO.Detail::getQuantity)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ if (line.getQuantity() == null || sumDetailQty.compareTo(line.getQuantity()) != 0) {
+ throw exception(WM_PRODUCT_RECPT_STOCK_QUANTITY_MISMATCH);
+ }
+ // 鏍¢獙浠撳簱灞傜骇鍏崇郴骞舵彃鍏ユ槑缁�
+ for (MesWmProductReceiptStockReqVO.Detail detail : details) {
+ areaService.validateWarehouseAreaExists(detail.getWarehouseId(), detail.getLocationId(), detail.getAreaId());
+ productReceiptDetailMapper.insert(new MesWmProductReceiptDetailDO()
+ .setLineId(line.getId())
+ .setReceiptId(receipt.getId())
+ .setItemId(line.getItemId())
+ .setQuantity(detail.getQuantity())
+ .setBatchId(line.getBatchId())
+ .setWarehouseId(detail.getWarehouseId())
+ .setLocationId(detail.getLocationId())
+ .setAreaId(detail.getAreaId()));
+ }
+ }
+ }
+
private void createTransactionList(MesWmProductReceiptDO receipt, List<MesWmProductReceiptDetailDO> details) {
// 1. 鏌ヨ铏氭嫙绾胯竟搴�
MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE);
--
Gitblit v1.9.3