Commit 27b24b48759b63f3a30e87aa19e6eb619783df73

Authored by YunaiV
1 parent 55f86d4e

feat(mes): implement stock management by adding increaseStock method and composi…

…te key selection for material stock
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java
... ... @@ -46,4 +46,14 @@ public interface MesWmMaterialStockMapper extends BaseMapperX<MesWmMaterialStock
46 46 return selectByIds(ids);
47 47 }
48 48  
  49 + default MesWmMaterialStockDO selectByCompositeKey(Long itemId, Long warehouseId, Long locationId,
  50 + Long areaId, Long batchId) {
  51 + return selectOne(new LambdaQueryWrapperX<MesWmMaterialStockDO>()
  52 + .eqIfPresent(MesWmMaterialStockDO::getItemId, itemId)
  53 + .eqIfPresent(MesWmMaterialStockDO::getWarehouseId, warehouseId)
  54 + .eqIfPresent(MesWmMaterialStockDO::getLocationId, locationId)
  55 + .eqIfPresent(MesWmMaterialStockDO::getAreaId, areaId)
  56 + .eqIfPresent(MesWmMaterialStockDO::getBatchId, batchId));
  57 + }
  58 +
49 59 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
... ... @@ -44,5 +44,7 @@ public interface DictTypeConstants {
44 44 String MES_PRO_FEEDBACK_STATUS = "mes_pro_feedback_status"; // MES 生产报工状态
45 45 String MES_PRO_FEEDBACK_TYPE = "mes_pro_feedback_type"; // MES 生产报工类型
46 46 String MES_PRO_FEEDBACK_CHANNEL = "mes_pro_feedback_channel"; // MES 生产报工途径
  47 + String MES_WM_ARRIVAL_NOTICE_STATUS = "mes_wm_arrival_notice_status"; // MES 到货通知单状态
  48 + String MES_WM_ITEM_RECEIPT_STATUS = "mes_wm_item_receipt_status"; // MES 采购入库单状态
47 49  
48 50 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -318,4 +318,26 @@ public interface ErrorCodeConstants {
318 318 // ========== MES 仓库管理-库存(1-040-703-000) ==========
319 319 ErrorCode WM_MATERIAL_STOCK_NOT_EXISTS = new ErrorCode(1_040_703_000, "库存记录不存在");
320 320  
  321 + // ========== MES 仓库管理-到货通知单(1-040-704-000) ==========
  322 + ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在");
  323 + ErrorCode WM_ARRIVAL_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_704_001, "到货通知单编码已存在");
  324 + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE = new ErrorCode(1_040_704_002, "只有草稿状态才允许此操作");
  325 + ErrorCode WM_ARRIVAL_NOTICE_IQC_PENDING = new ErrorCode(1_040_704_003, "存在待检验行,无法审批通过");
  326 + ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_704_100, "到货通知单行不存在");
  327 +
  328 + // ========== MES 仓库管理-采购入库单(1-040-705-000) ==========
  329 + ErrorCode WM_ITEM_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_705_000, "采购入库单不存在");
  330 + ErrorCode WM_ITEM_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_705_001, "采购入库单编码已存在");
  331 + ErrorCode WM_ITEM_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_705_002, "只有草稿状态才允许此操作");
  332 + ErrorCode WM_ITEM_RECEIPT_NO_LINE = new ErrorCode(1_040_705_003, "至少需要一条行项目");
  333 + ErrorCode WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_705_004, "明细上架总数与行入库数量不匹配");
  334 + ErrorCode WM_ITEM_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_705_005, "入库单状态不正确");
  335 + ErrorCode WM_ITEM_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_705_100, "采购入库单行不存在");
  336 + ErrorCode WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_705_200, "采购入库明细不存在");
  337 +
  338 + // ========== MES 仓库管理-领料申请单(1-040-706-000) ==========
  339 + ErrorCode WM_MATERIAL_REQUEST_NOT_EXISTS = new ErrorCode(1_040_706_000, "领料申请单不存在");
  340 + ErrorCode WM_MATERIAL_REQUEST_STATUS_INVALID = new ErrorCode(1_040_706_001, "领料申请单状态不正确,无法执行该操作");
  341 + ErrorCode WM_MATERIAL_REQUEST_LINE_NOT_EXISTS = new ErrorCode(1_040_706_100, "领料申请单行不存在");
  342 +
321 343 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java
... ... @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMat
6 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
7 7 import jakarta.validation.Valid;
8 8  
  9 +import java.math.BigDecimal;
  10 +import java.time.LocalDateTime;
9 11 import java.util.Collection;
10 12 import java.util.List;
11 13 import java.util.Map;
... ... @@ -84,4 +86,24 @@ public interface MesWmMaterialStockService {
84 86 return convertMap(getMaterialStockList(ids), MesWmMaterialStockDO::getId);
85 87 }
86 88  
  89 + /**
  90 + * 增加库存
  91 + *
  92 + * 按 itemId + warehouseId + locationId + areaId + batchId 查找已有库存,
  93 + * 存在则增加 quantityOnhand;不存在则新建记录。
  94 + *
  95 + * @param itemId 物料编号
  96 + * @param warehouseId 仓库编号
  97 + * @param locationId 库区编号
  98 + * @param areaId 库位编号
  99 + * @param batchId 批次编号
  100 + * @param quantity 增加数量
  101 + * @param vendorId 供应商编号
  102 + * @param productionDate 生产日期
  103 + * @param expireDate 过期日期
  104 + */
  105 + void increaseStock(Long itemId, Long warehouseId, Long locationId, Long areaId,
  106 + Long batchId, BigDecimal quantity, Long vendorId,
  107 + LocalDateTime productionDate, LocalDateTime expireDate);
  108 +
87 109 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java
... ... @@ -5,14 +5,18 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
6 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO;
7 7 import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockSaveReqVO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
8 9 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO;
9 10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
10 11 import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
  12 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
11 13 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService;
12 14 import jakarta.annotation.Resource;
13 15 import org.springframework.stereotype.Service;
14 16 import org.springframework.validation.annotation.Validated;
15 17  
  18 +import java.math.BigDecimal;
  19 +import java.time.LocalDateTime;
16 20 import java.util.*;
17 21  
18 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -30,6 +34,9 @@ public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService
30 34 private MesWmMaterialStockMapper materialStockMapper;
31 35  
32 36 @Resource
  37 + private MesMdItemService itemService;
  38 +
  39 + @Resource
33 40 private MesMdItemTypeService itemTypeService;
34 41  
35 42 @Override
... ... @@ -100,4 +107,34 @@ public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService
100 107 return materialStockMapper.selectListByIds(ids);
101 108 }
102 109  
  110 + // TODO @AI:MaterialStock
  111 + @Override
  112 + public void increaseStock(Long itemId, Long warehouseId, Long locationId, Long areaId,
  113 + Long batchId, BigDecimal quantity, Long vendorId,
  114 + LocalDateTime productionDate, LocalDateTime expireDate) {
  115 + // 1. 查找已有库存记录
  116 + MesWmMaterialStockDO stock = materialStockMapper.selectByCompositeKey(
  117 + itemId, warehouseId, locationId, areaId, batchId);
  118 +
  119 + // 2a. 存在则增加数量
  120 + if (stock != null) {
  121 + // TODO @AI:mapper 里,增加一个 incr 方法;
  122 + MesWmMaterialStockDO updateObj = new MesWmMaterialStockDO();
  123 + updateObj.setId(stock.getId());
  124 + updateObj.setQuantityOnhand(stock.getQuantityOnhand().add(quantity));
  125 + materialStockMapper.updateById(updateObj);
  126 + return;
  127 + }
  128 +
  129 + // 2. 不存在则新建
  130 + MesMdItemDO item = itemService.validateItemExists(itemId);
  131 + MesWmMaterialStockDO newStock = MesWmMaterialStockDO.builder()
  132 + .itemId(itemId).itemTypeId(item.getItemTypeId()).unitMeasureId(item.getUnitMeasureId())
  133 + .warehouseId(warehouseId).locationId(locationId).areaId(areaId)
  134 + .batchId(batchId).vendorId(vendorId).quantityOnhand(quantity)
  135 + .recptDate(LocalDateTime.now()).productionDate(productionDate).expireDate(expireDate).frozen(false)
  136 + .build();
  137 + materialStockMapper.insert(newStock);
  138 + }
  139 +
103 140 }
... ...