| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.Assert; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ErrorCode; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockAdjustReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockFreezeReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockImportExcelVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockImportRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockMoveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO; |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; |
| | | 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.materialstock.MesWmMaterialStockMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | |
| | | 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 cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.PlatformTransactionManager; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.support.TransactionTemplate; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | |
| | | private MesWmWarehouseAreaService areaService; |
| | | @Resource |
| | | @Lazy |
| | | private MesWmWarehouseLocationService locationService; |
| | | @Resource |
| | | @Lazy |
| | | private MesWmWarehouseService warehouseService; |
| | | @Resource |
| | | @Lazy |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesWmBatchService batchService; |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | @Resource |
| | | private SrmSupplierApi srmSupplierApi; |
| | | @Resource |
| | | private PlatformTransactionManager transactionManager; |
| | | |
| | | @Override |
| | | public MesWmMaterialStockDO getMaterialStock(Long id) { |
| | |
| | | } |
| | | |
| | | // 2. 不存在则新建 |
| | | return createMaterialStock(itemId, warehouseId, locationId, areaId, batchId, batchCode, vendorId, receiptTime); |
| | | } |
| | | |
| | | @Override |
| | | public MesWmMaterialStockDO createMaterialStock(Long itemId, Long warehouseId, Long locationId, Long areaId, |
| | | Long batchId, String batchCode, Long vendorId, LocalDateTime receiptTime) { |
| | | // 始终创建新库存记录 |
| | | MesMdmItemDO item = mdmItemService.validateItemExists(itemId); |
| | | MesWmMaterialStockDO newStock = MesWmMaterialStockDO.builder() |
| | | .itemId(itemId).itemTypeId(item.getCategoryId()) |
| | |
| | | .frozen(false) |
| | | .build(); |
| | | materialStockMapper.insert(newStock); |
| | | // 3. 重新查询,确保拿到数据库生成的完整记录(id、createTime 等) |
| | | // 重新查询,确保拿到数据库生成的完整记录(id、createTime 等) |
| | | MesWmMaterialStockDO inserted = materialStockMapper.selectById(newStock.getId()); |
| | | return inserted != null ? inserted : newStock; |
| | | } |
| | |
| | | throw exception(WM_MATERIAL_STOCK_REQUIRED); |
| | | } |
| | | MesWmMaterialStockDO stock = validateMaterialStockExists(materialStockId); |
| | | // 2. 校验库存记录的物料、批次、仓库、库区、库位等信息与前端选择的一致,避免串单或越权提交 |
| | | if (ObjUtil.notEqual(stock.getItemId(), itemId) |
| | | || ObjUtil.notEqual(stock.getBatchId(), batchId) |
| | | || (batchCode != null && ObjUtil.notEqual(stock.getBatchCode(), batchCode)) |
| | | || ObjUtil.notEqual(stock.getWarehouseId(), warehouseId) |
| | | || ObjUtil.notEqual(stock.getLocationId(), locationId) |
| | | || ObjUtil.notEqual(stock.getAreaId(), areaId)) { |
| | | throw exception(WM_MATERIAL_STOCK_SELECTION_MISMATCH); |
| | | // 2. 校验库存记录的物料、批次、仓库、库区、库位等信息与单据一致,避免串单或越权提交。 |
| | | // 逐个维度比对,命中时提示具体差异(库存侧 vs 单据侧)并给出处理办法,避免笼统报"信息不一致" |
| | | String mismatch = buildSelectedStockMismatch( |
| | | stock, itemId, batchId, batchCode, warehouseId, locationId, areaId); |
| | | if (mismatch != null) { |
| | | throw new ServiceException(WM_MATERIAL_STOCK_SELECTION_MISMATCH.getCode(), |
| | | "所选库存记录与单据不一致:" + mismatch + "。请重新选择该物料正确的库存;若仓库/库区/库位/批次被禁用无法修改,请删除本条明细后重新添加。"); |
| | | } |
| | | // 3. 校验库存数量充足(如果前端传了 quantity,则必须保证库存数量 >= quantity) |
| | | if (quantity != null && stock.getQuantity() != null && stock.getQuantity().compareTo(quantity) < 0) { |
| | | throw exception(WM_MATERIAL_STOCK_INSUFFICIENT); |
| | | } |
| | | return stock; |
| | | } |
| | | |
| | | /** |
| | | * 逐维度比对待选库存与单据传入的信息,返回第一个不一致维度的可读描述;全部一致返回 null |
| | | */ |
| | | private String buildSelectedStockMismatch(MesWmMaterialStockDO stock, Long itemId, Long batchId, String batchCode, |
| | | Long warehouseId, Long locationId, Long areaId) { |
| | | if (ObjUtil.notEqual(stock.getItemId(), itemId)) { |
| | | return "所选库存归属物料[" + itemIdText(itemId) + "],单据物料为[" + itemIdText(stock.getItemId()) + "]"; |
| | | } |
| | | if (ObjUtil.notEqual(stock.getBatchId(), batchId)) { |
| | | return "所选库存批次[" + batchText(stock.getBatchId(), stock.getBatchCode()) |
| | | + "],单据批次为[" + batchText(batchId, batchCode) + "]"; |
| | | } |
| | | if (batchCode != null && ObjUtil.notEqual(stock.getBatchCode(), batchCode)) { |
| | | return "所选库存批次号[" + stock.getBatchCode() + "],单据批次号为[" + batchCode + "]"; |
| | | } |
| | | if (ObjUtil.notEqual(stock.getWarehouseId(), warehouseId)) { |
| | | return "所选库存仓库[" + warehouseText(stock.getWarehouseId()) |
| | | + "],单据仓库为[" + warehouseText(warehouseId) + "]"; |
| | | } |
| | | if (ObjUtil.notEqual(stock.getLocationId(), locationId)) { |
| | | return "所选库存库区[" + locationText(stock.getLocationId()) |
| | | + "],单据库区为[" + locationText(locationId) + "]"; |
| | | } |
| | | if (ObjUtil.notEqual(stock.getAreaId(), areaId)) { |
| | | return "所选库存库位[" + areaText(stock.getAreaId()) |
| | | + "],单据库位为[" + areaText(areaId) + "]"; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private String itemIdText(Long itemId) { |
| | | return itemId == null ? "未选择" : ("物料ID=" + itemId); |
| | | } |
| | | |
| | | private String batchText(Long batchId, String batchCode) { |
| | | if (StrUtil.isNotBlank(batchCode)) { |
| | | return batchCode; |
| | | } |
| | | return batchId == null ? "未选择" : ("批次ID=" + batchId); |
| | | } |
| | | |
| | | private String warehouseText(Long warehouseId) { |
| | | if (warehouseId == null) { |
| | | return "未选择"; |
| | | } |
| | | MesWmWarehouseDO warehouse = warehouseService.getWarehouse(warehouseId); |
| | | return warehouse != null && StrUtil.isNotBlank(warehouse.getName()) |
| | | ? warehouse.getName() : ("仓库ID=" + warehouseId); |
| | | } |
| | | |
| | | private String locationText(Long locationId) { |
| | | if (locationId == null) { |
| | | return "未选择"; |
| | | } |
| | | MesWmWarehouseLocationDO location = locationService.getWarehouseLocation(locationId); |
| | | return location != null && StrUtil.isNotBlank(location.getName()) |
| | | ? location.getName() : ("库区ID=" + locationId); |
| | | } |
| | | |
| | | private String areaText(Long areaId) { |
| | | if (areaId == null) { |
| | | return "未选择"; |
| | | } |
| | | MesWmWarehouseAreaDO area = areaService.getWarehouseArea(areaId); |
| | | return area != null && StrUtil.isNotBlank(area.getName()) |
| | | ? area.getName() : ("库位ID=" + areaId); |
| | | } |
| | | |
| | | @Override |
| | |
| | | wmTransactionService.createTransaction(inTransaction); |
| | | } |
| | | |
| | | @Override |
| | | public MesWmMaterialStockImportRespVO importMaterialStockList(List<MesWmMaterialStockImportExcelVO> importList) { |
| | | // 操作类型取值:增加 / 减少 / 覆盖 |
| | | final String OP_ADD = "增加"; |
| | | final String OP_REDUCE = "减少"; |
| | | final String OP_COVER = "覆盖"; |
| | | // 1. 过滤全空行 |
| | | importList = filterList(importList, item -> StrUtil.isNotBlank(item.getItemCode()) |
| | | || StrUtil.isNotBlank(item.getBatchCode()) || item.getQuantity() != null); |
| | | if (CollUtil.isEmpty(importList)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | // 2. 预加载 编码/名称 -> 实体 映射(编码优先,名称兜底) |
| | | Map<String, MdmItemRespDTO> itemMap = mdmItemApi.getItemListByStatus(null).getCheckedData().stream() |
| | | .collect(Collectors.toMap(MdmItemRespDTO::getCode, item -> item, (v1, v2) -> v1)); |
| | | Map<String, MesWmWarehouseDO> warehouseCodeMap = new HashMap<>(); |
| | | Map<String, MesWmWarehouseDO> warehouseNameMap = new HashMap<>(); |
| | | for (MesWmWarehouseDO warehouse : warehouseService.getWarehouseList()) { |
| | | warehouseCodeMap.putIfAbsent(warehouse.getCode(), warehouse); |
| | | warehouseNameMap.putIfAbsent(warehouse.getName(), warehouse); |
| | | } |
| | | Map<String, MesWmWarehouseLocationDO> locationCodeMap = new HashMap<>(); |
| | | Map<String, MesWmWarehouseLocationDO> locationNameMap = new HashMap<>(); |
| | | for (MesWmWarehouseLocationDO location : locationService.getWarehouseLocationList((Long) null)) { |
| | | locationCodeMap.putIfAbsent(location.getCode(), location); |
| | | locationNameMap.putIfAbsent(location.getName(), location); |
| | | } |
| | | Map<String, MesWmWarehouseAreaDO> areaCodeMap = new HashMap<>(); |
| | | Map<String, MesWmWarehouseAreaDO> areaNameMap = new HashMap<>(); |
| | | for (MesWmWarehouseAreaDO area : areaService.getWarehouseAreaList((Long) null)) { |
| | | areaCodeMap.putIfAbsent(area.getCode(), area); |
| | | areaNameMap.putIfAbsent(area.getName(), area); |
| | | } |
| | | Map<String, SrmSupplierRespDTO> supplierCodeMap = new HashMap<>(); |
| | | Map<String, SrmSupplierRespDTO> supplierNameMap = new HashMap<>(); |
| | | for (SrmSupplierRespDTO supplier : srmSupplierApi.getSupplierSimpleList().getCheckedData()) { |
| | | supplierCodeMap.putIfAbsent(supplier.getCode(), supplier); |
| | | supplierNameMap.putIfAbsent(supplier.getName(), supplier); |
| | | } |
| | | // 3. 逐条处理 |
| | | MesWmMaterialStockImportRespVO respVO = MesWmMaterialStockImportRespVO.builder() |
| | | .createNames(new ArrayList<>()) |
| | | .updateNames(new ArrayList<>()) |
| | | .failureNames(new LinkedHashMap<>()) |
| | | .build(); |
| | | TransactionTemplate importTxTemplate = new TransactionTemplate(transactionManager); |
| | | for (MesWmMaterialStockImportExcelVO importStock : importList) { |
| | | String key = StrUtil.blankToDefault(importStock.getItemCode(), "") + "-" |
| | | + StrUtil.blankToDefault(importStock.getWarehouse(), ""); |
| | | try { |
| | | importTxTemplate.executeWithoutResult(status -> { |
| | | // 3.1 物料 |
| | | MdmItemRespDTO item = resolveImportItem(itemMap, importStock.getItemCode()); |
| | | // 3.2 仓库/库区/库位(编码优先、名称兜底,含父子关系校验) |
| | | MesWmWarehouseDO warehouse = resolveImportWarehouse(warehouseCodeMap, warehouseNameMap, |
| | | importStock.getWarehouse()); |
| | | Long locationId = null; |
| | | if (StrUtil.isNotBlank(importStock.getLocation())) { |
| | | MesWmWarehouseLocationDO location = resolveImportLocationOrArea(locationCodeMap, |
| | | locationNameMap, importStock.getLocation(), WM_MATERIAL_STOCK_IMPORT_LOCATION_NOT_EXISTS); |
| | | if (ObjUtil.notEqual(location.getWarehouseId(), warehouse.getId())) { |
| | | throw exception(WM_WAREHOUSE_AREA_WAREHOUSE_MISMATCH); |
| | | } |
| | | locationId = location.getId(); |
| | | } |
| | | Long areaId = null; |
| | | if (StrUtil.isNotBlank(importStock.getArea())) { |
| | | MesWmWarehouseAreaDO area = resolveImportLocationOrArea(areaCodeMap, |
| | | areaNameMap, importStock.getArea(), WM_MATERIAL_STOCK_IMPORT_AREA_NOT_EXISTS); |
| | | if (ObjUtil.notEqual(area.getLocationId(), |
| | | locationId != null ? locationId : null)) { |
| | | throw exception(WM_WAREHOUSE_AREA_RELATION_INVALID); |
| | | } |
| | | areaId = area.getId(); |
| | | } |
| | | // 3.3 批次(物料启用批次管理时必填,且批次需归属该物料) |
| | | Long batchId = null; |
| | | String batchCode = null; |
| | | if (Boolean.TRUE.equals(item.getIsBatchManaged())) { |
| | | if (StrUtil.isBlank(importStock.getBatchCode())) { |
| | | throw exception(WM_TRANSACTION_BATCH_REQUIRED); |
| | | } |
| | | MesWmBatchDO batch = batchService.getBatchByCode(importStock.getBatchCode().trim()); |
| | | if (batch == null || ObjUtil.notEqual(batch.getItemId(), item.getId())) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_BATCH_NOT_EXISTS, |
| | | importStock.getBatchCode().trim()); |
| | | } |
| | | batchId = batch.getId(); |
| | | batchCode = batch.getCode(); |
| | | } |
| | | // 3.4 供应商(可选) |
| | | Long vendorId = resolveImportVendor(supplierCodeMap, supplierNameMap, importStock.getVendor()); |
| | | // 3.5 操作类型(必填:增加/减少/覆盖) |
| | | String operationType = importStock.getOperationType() == null |
| | | ? null : importStock.getOperationType().trim(); |
| | | if (StrUtil.isBlank(operationType)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_FIELD_REQUIRED, "操作类型"); |
| | | } |
| | | if (!OP_ADD.equals(operationType) && !OP_REDUCE.equals(operationType) |
| | | && !OP_COVER.equals(operationType)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_OPERATION_INVALID, operationType); |
| | | } |
| | | // 3.6 数量校验:增加/减少为变动量须为正数;覆盖为目标现有量须 >= 0 |
| | | BigDecimal quantity = importStock.getQuantity(); |
| | | boolean cover = OP_COVER.equals(operationType); |
| | | if (quantity == null || quantity.compareTo(BigDecimal.ZERO) < 0 |
| | | || (!cover && quantity.compareTo(BigDecimal.ZERO) == 0)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_QUANTITY_INVALID, |
| | | quantity == null ? "空" : quantity); |
| | | } |
| | | // 3.7 按操作类型定位并处理库存记录(不存在则创建,存在则调整数量) |
| | | MesWmMaterialStockDO existStock = materialStockMapper.selectByCompositeKey( |
| | | item.getId(), warehouse.getId(), locationId, areaId, batchId, vendorId); |
| | | Long wId = warehouse.getId(); |
| | | if (OP_REDUCE.equals(operationType)) { |
| | | // 减少:库存必须存在,扣减不足时由出库流水校验并失败 |
| | | if (existStock == null) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_STOCK_NOT_EXISTS); |
| | | } |
| | | createImportTransaction(existStock, item.getId(), batchId, batchCode, |
| | | wId, locationId, areaId, vendorId, quantity.negate()); |
| | | respVO.getUpdateNames().add(key); |
| | | } else if (OP_ADD.equals(operationType)) { |
| | | // 增加:不存在则建库存再入库;已存在则直接追加变动量 |
| | | if (existStock == null) { |
| | | MesWmMaterialStockDO newStock = getOrCreateMaterialStock( |
| | | item.getId(), wId, locationId, areaId, |
| | | batchId, batchCode, vendorId, LocalDateTime.now()); |
| | | createImportTransaction(newStock, item.getId(), batchId, batchCode, |
| | | wId, locationId, areaId, vendorId, quantity); |
| | | respVO.getCreateNames().add(key); |
| | | } else { |
| | | createImportTransaction(existStock, item.getId(), batchId, batchCode, |
| | | wId, locationId, areaId, vendorId, quantity); |
| | | respVO.getUpdateNames().add(key); |
| | | } |
| | | } else { |
| | | // 覆盖:数量为目标现有量;不存在则新建并置量,已存在按差额出入库 |
| | | if (existStock == null) { |
| | | MesWmMaterialStockDO newStock = getOrCreateMaterialStock( |
| | | item.getId(), wId, locationId, areaId, |
| | | batchId, batchCode, vendorId, LocalDateTime.now()); |
| | | if (quantity.compareTo(BigDecimal.ZERO) > 0) { |
| | | createImportTransaction(newStock, item.getId(), batchId, batchCode, |
| | | wId, locationId, areaId, vendorId, quantity); |
| | | } |
| | | respVO.getCreateNames().add(key); |
| | | } else { |
| | | BigDecimal currentQty = existStock.getQuantity() != null |
| | | ? existStock.getQuantity() : BigDecimal.ZERO; |
| | | BigDecimal diff = quantity.subtract(currentQty); |
| | | if (diff.compareTo(BigDecimal.ZERO) != 0) { |
| | | createImportTransaction(existStock, item.getId(), batchId, batchCode, |
| | | wId, locationId, areaId, vendorId, diff); |
| | | } |
| | | respVO.getUpdateNames().add(key); |
| | | } |
| | | } |
| | | }); |
| | | } catch (Exception ex) { |
| | | respVO.getFailureNames().put(key, ex.getMessage()); |
| | | } |
| | | } |
| | | return respVO; |
| | | } |
| | | |
| | | private MdmItemRespDTO resolveImportItem(Map<String, MdmItemRespDTO> itemMap, String itemCode) { |
| | | if (StrUtil.isBlank(itemCode)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_FIELD_REQUIRED, "物料编码"); |
| | | } |
| | | MdmItemRespDTO item = itemMap.get(itemCode.trim()); |
| | | if (item == null) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_ITEM_NOT_EXISTS, itemCode.trim()); |
| | | } |
| | | return item; |
| | | } |
| | | |
| | | private MesWmWarehouseDO resolveImportWarehouse(Map<String, MesWmWarehouseDO> codeMap, |
| | | Map<String, MesWmWarehouseDO> nameMap, String value) { |
| | | if (StrUtil.isBlank(value)) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_FIELD_REQUIRED, "仓库"); |
| | | } |
| | | String trimmed = value.trim(); |
| | | MesWmWarehouseDO warehouse = codeMap.get(trimmed) != null ? codeMap.get(trimmed) : nameMap.get(trimmed); |
| | | if (warehouse == null) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_WAREHOUSE_NOT_EXISTS, trimmed); |
| | | } |
| | | return warehouse; |
| | | } |
| | | |
| | | private <T> T resolveImportLocationOrArea(Map<String, T> codeMap, Map<String, T> nameMap, |
| | | String value, ErrorCode errorCode) { |
| | | String trimmed = value.trim(); |
| | | T result = codeMap.get(trimmed) != null ? codeMap.get(trimmed) : nameMap.get(trimmed); |
| | | if (result == null) { |
| | | throw exception(errorCode, trimmed); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Long resolveImportVendor(Map<String, SrmSupplierRespDTO> codeMap, |
| | | Map<String, SrmSupplierRespDTO> nameMap, String value) { |
| | | if (StrUtil.isBlank(value)) { |
| | | return null; |
| | | } |
| | | String trimmed = value.trim(); |
| | | SrmSupplierRespDTO supplier = codeMap.get(trimmed) != null ? codeMap.get(trimmed) : nameMap.get(trimmed); |
| | | if (supplier == null) { |
| | | throw exception(WM_MATERIAL_STOCK_IMPORT_VENDOR_NOT_EXISTS, trimmed); |
| | | } |
| | | return supplier.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 创建导入产生的库存事务流水(复用库存调整的流水模式) |
| | | * |
| | | * @param quantity 变动数量(正数=入库,负数=出库) |
| | | */ |
| | | private void createImportTransaction(MesWmMaterialStockDO stock, Long itemId, Long batchId, String batchCode, |
| | | Long warehouseId, Long locationId, Long areaId, Long vendorId, |
| | | BigDecimal quantity) { |
| | | boolean inbound = quantity.compareTo(BigDecimal.ZERO) > 0; |
| | | MesWmTransactionSaveReqDTO transaction = new MesWmTransactionSaveReqDTO() |
| | | .setType(inbound ? MesWmTransactionTypeEnum.IN.getType() : MesWmTransactionTypeEnum.OUT.getType()) |
| | | .setBizType(inbound ? MesBizTypeConstants.WM_STOCK_ADJUST_IN : MesBizTypeConstants.WM_STOCK_ADJUST_OUT) |
| | | .setBizId(stock.getId()) |
| | | .setBizCode("STOCK_IMPORT_" + stock.getId()) |
| | | .setBizLineId(stock.getId()) |
| | | .setItemId(itemId) |
| | | .setQuantity(quantity.abs()) |
| | | .setBatchId(batchId) |
| | | .setBatchCode(batchCode) |
| | | .setWarehouseId(warehouseId) |
| | | .setLocationId(locationId) |
| | | .setAreaId(areaId) |
| | | .setVendorId(vendorId) |
| | | .setReceiptTime(LocalDateTime.now()) |
| | | .setCheckFlag(!inbound); |
| | | wmTransactionService.createTransaction(transaction); |
| | | } |
| | | |
| | | } |