| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.production.bean.dto.ProductionOrderPickDto; |
| | |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInventory; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | List<String> batchNoList = resolveBatchNoList(resolvedDto); |
| | | String inventoryBatchNo = pickInventoryBatchNo(batchNoList); |
| | | String storedBatchNo = formatBatchNoStorage(batchNoList); |
| | | subtractInventory(resolvedDto.getProductModelId(), inventoryBatchNo, resolvedDto.getPickQuantity(), rowNo); |
| | | subtractInventory(resolvedDto.getProductModelId(), storedBatchNo, resolvedDto.getPickQuantity(), rowNo); |
| | | |
| | | ProductionOrderPick orderPick = new ProductionOrderPick(); |
| | | orderPick.setProductionOrderId(resolvedDto.getProductionOrderId()); |
| | |
| | | List<String> batchNoList = resolveBatchNoList(dto); |
| | | String inventoryBatchNo = pickInventoryBatchNo(batchNoList); |
| | | String storedBatchNo = formatBatchNoStorage(batchNoList); |
| | | subtractInventory(dto.getProductModelId(), inventoryBatchNo, dto.getPickQuantity(), rowNo); |
| | | subtractInventory(dto.getProductModelId(), storedBatchNo, dto.getPickQuantity(), rowNo); |
| | | |
| | | ProductionOrderPick orderPick = new ProductionOrderPick(); |
| | | orderPick.setProductionOrderId(dto.getProductionOrderId()); |
| | |
| | | List<String> batchNoList = resolveBatchNoList(dto); |
| | | String inventoryBatchNo = batchNoList.isEmpty() |
| | | ? resolveInventoryBatchNoFromStored(oldPick.getBatchNo()) |
| | | : pickInventoryBatchNo(batchNoList); |
| | | : formatBatchNoStorage(batchNoList); |
| | | BigDecimal feedingQuantity = dto.getFeedingQuantity(); |
| | | |
| | | subtractInventory(productModelId, inventoryBatchNo, feedingQuantity, rowNo); |
| | |
| | | if (sameStockKey) { |
| | | BigDecimal delta = newQuantity.subtract(oldQuantity); |
| | | if (delta.compareTo(BigDecimal.ZERO) > 0) { |
| | | subtractInventory(newProductModelId, newBatchNo, delta, rowNo); |
| | | subtractInventory(newProductModelId, newStoredBatchNo, delta, rowNo); |
| | | } else if (delta.compareTo(BigDecimal.ZERO) < 0) { |
| | | addInventory(oldProductModelId, oldBatchNo, delta.abs()); |
| | | } |
| | | } else { |
| | | addInventory(oldProductModelId, oldBatchNo, oldQuantity); |
| | | subtractInventory(newProductModelId, newBatchNo, newQuantity, rowNo); |
| | | subtractInventory(newProductModelId, newStoredBatchNo, newQuantity, rowNo); |
| | | } |
| | | |
| | | oldPick.setProductModelId(newProductModelId); |
| | |
| | | } |
| | | |
| | | private void subtractInventory(Long productModelId, String batchNo, BigDecimal quantity, int rowNo) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo)); |
| | | if (stockInventory == null) { |
| | | throw new ServiceException("第" + rowNo + "条领料对应库存不存在"); |
| | | BigDecimal deductQuantity = defaultDecimal(quantity); |
| | | if (deductQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | BigDecimal availableQuantity = defaultDecimal(stockInventory.getQualitity()) |
| | | |
| | | List<String> batchNoList = parseBatchNoValue(batchNo); |
| | | if (batchNoList.isEmpty()) { |
| | | batchNoList = Collections.singletonList(null); |
| | | } |
| | | |
| | | Map<String, BigDecimal> availableQuantityMap = new LinkedHashMap<>(); |
| | | BigDecimal totalAvailableQuantity = BigDecimal.ZERO; |
| | | for (String currentBatchNo : batchNoList) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, currentBatchNo)); |
| | | BigDecimal availableQuantity = BigDecimal.ZERO; |
| | | if (stockInventory != null) { |
| | | availableQuantity = defaultDecimal(stockInventory.getQualitity()) |
| | | .subtract(defaultDecimal(stockInventory.getLockedQuantity())); |
| | | if (quantity.compareTo(availableQuantity) > 0) { |
| | | throw new ServiceException("第" + rowNo + "条领料可用库存不足"); |
| | | if (availableQuantity.compareTo(BigDecimal.ZERO) < 0) { |
| | | availableQuantity = BigDecimal.ZERO; |
| | | } |
| | | } |
| | | availableQuantityMap.put(currentBatchNo, availableQuantity); |
| | | totalAvailableQuantity = totalAvailableQuantity.add(availableQuantity); |
| | | } |
| | | |
| | | if (deductQuantity.compareTo(totalAvailableQuantity) > 0) { |
| | | BigDecimal shortQuantity = deductQuantity.subtract(totalAvailableQuantity); |
| | | throw new ServiceException("领料可用库存不足,可用库存为" + formatQuantity(totalAvailableQuantity) |
| | | + ",还差" + formatQuantity(shortQuantity)); |
| | | } |
| | | |
| | | BigDecimal remainingQuantity = deductQuantity; |
| | | for (Map.Entry<String, BigDecimal> entry : availableQuantityMap.entrySet()) { |
| | | if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | break; |
| | | } |
| | | BigDecimal availableQuantity = defaultDecimal(entry.getValue()); |
| | | if (availableQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | BigDecimal currentDeductQuantity = remainingQuantity.min(availableQuantity); |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setProductModelId(productModelId); |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | stockInventoryDto.setQualitity(quantity); |
| | | stockInventoryDto.setBatchNo(entry.getKey()); |
| | | stockInventoryDto.setQualitity(currentDeductQuantity); |
| | | int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto); |
| | | if (affected <= 0) { |
| | | throw new ServiceException("第" + rowNo + "条领料扣减库存失败"); |
| | | } |
| | | remainingQuantity = remainingQuantity.subtract(currentDeductQuantity); |
| | | } |
| | | |
| | | if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) { |
| | | throw new ServiceException("第" + rowNo + "条领料扣减库存失败,剩余待扣减数量为" + formatQuantity(remainingQuantity)); |
| | | } |
| | | } |
| | | |
| | |
| | | if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo)); |
| | | if (stockInventory == null) { |
| | | StockInventory newStockInventory = new StockInventory(); |
| | | newStockInventory.setProductModelId(productModelId); |
| | | newStockInventory.setBatchNo(batchNo); |
| | | newStockInventory.setQualitity(addQuantity); |
| | | newStockInventory.setLockedQuantity(BigDecimal.ZERO); |
| | | newStockInventory.setVersion(1); |
| | | stockInventoryMapper.insert(newStockInventory); |
| | | return; |
| | | } |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setProductModelId(productModelId); |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | stockInventoryDto.setQualitity(addQuantity); |
| | | int affected = stockInventoryMapper.updateAddStockInventory(stockInventoryDto); |
| | | if (affected <= 0) { |
| | | throw new ServiceException("库存回退失败,产品规格ID=" + productModelId); |
| | | } |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PICK_RETURN_IN.getCode())); |
| | | stockInventoryDto.setRecordId(0L); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | |
| | | private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) { |
| | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private String formatQuantity(BigDecimal value) { |
| | | return defaultDecimal(value).stripTrailingZeros().toPlainString(); |
| | | } |
| | | } |