| | |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.pojo.SupplierManage; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.enums.ApprovalStatusEnum; |
| | | import com.ruoyi.common.enums.ReviewStatusEnum; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.FreightUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.sales.service.impl.CommonFileServiceImpl; |
| | | import com.ruoyi.stock.dto.StockInRecordDto; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import lombok.RequiredArgsConstructor; |
| | |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockUtils stockUtils; |
| | | private final ApprovalTemplateMapper approvalTemplateMapper; |
| | | private final StockUtils stockUtils; |
| | | |
| | | @Override |
| | | public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { |
| | |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (!pendingIds.isEmpty()) { |
| | | stockInRecordService.batchApprove(pendingIds, ReviewStatusEnum.APPROVED.getCode()); |
| | | List<StockInRecordDto.StockInRecordApproveItemDto> approveItems = pendingIds.stream() |
| | | .map(id -> { |
| | | StockInRecordDto.StockInRecordApproveItemDto item = new StockInRecordDto.StockInRecordApproveItemDto(); |
| | | item.setId(id); |
| | | return item; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | stockInRecordService.batchApprove(ReviewStatusEnum.APPROVED.getCode(), approveItems); |
| | | } |
| | | } |
| | | |
| | |
| | | // 执行更新操作 |
| | | if (!updateList.isEmpty()) { |
| | | for (SalesLedgerProduct product : updateList) { |
| | | FreightUtils.fillFreightAmount(product); |
| | | product.setType(ledgerType); |
| | | salesLedgerProductMapper.updateById(product); |
| | | } |
| | |
| | | // 执行插入操作 |
| | | if (!insertList.isEmpty()) { |
| | | for (SalesLedgerProduct salesLedgerProduct : insertList) { |
| | | FreightUtils.fillFreightAmount(salesLedgerProduct); |
| | | salesLedgerProduct.setType(ledgerType); |
| | | Date entryDate = purchaseLedger.getEntryDate(); |
| | | |
| | |
| | | for (PurchaseLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) { |
| | | SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct(); |
| | | BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct); |
| | | FreightUtils.fillFreightAmount(salesLedgerProduct); |
| | | salesLedgerProduct.setSalesLedgerId(salesLedger.getId()); |
| | | salesLedgerProduct.setType(2); |
| | | // 计算不含税总价 |
| | |
| | | if (salesLedgerProduct == null) { |
| | | throw new BaseException("采购产品不存在"); |
| | | } |
| | | if (!purchaseLedger.getId().equals(salesLedgerProduct.getSalesLedgerId()) || !Integer.valueOf(2).equals(salesLedgerProduct.getType())) { |
| | | throw new BaseException("采购产品与采购台账不匹配"); |
| | | } |
| | | |
| | | // 获取理论入库数量(前端传入的inboundQuantity) |
| | | ProductModel productModel = productModelMapper.selectById(salesLedgerProduct.getProductModelId()); |
| | | if (Boolean.TRUE.equals(salesLedgerProduct.getIsChecked())) { |
| | | throw new BaseException("产品【" + productModel.getModel() + "】需要质检,请走质检入库流程"); |
| | | } |
| | | |
| | | BigDecimal theoryStockInNum = item.getInboundQuantity(); |
| | | if (theoryStockInNum == null) { |
| | | theoryStockInNum = salesLedgerProduct.getQuantity(); |
| | | } |
| | | // 空值和非正数校验 |
| | | if (theoryStockInNum == null || theoryStockInNum.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new BaseException("理论入库数量必须大于0"); |
| | | } |
| | | |
| | | // 获取实际入库数量(前端传入的actualInboundQuantity) |
| | | BigDecimal actualStockInNum = item.getActualInboundQuantity(); |
| | | if (actualStockInNum == null) { |
| | | actualStockInNum = theoryStockInNum; |
| | | BigDecimal approvedStockInNum = getApprovedPurchaseStockInNum( |
| | | purchaseLedger.getId(), |
| | | purchaseLedger.getPurchaseContractNumber(), |
| | | salesLedgerProduct.getId(), |
| | | salesLedgerProduct.getProductModelId() |
| | | ); |
| | | BigDecimal remainingStockInNum = salesLedgerProduct.getQuantity().subtract(approvedStockInNum); |
| | | if (remainingStockInNum.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new BaseException("产品【" + productModel.getModel() + "】已完成入库"); |
| | | } |
| | | // 非正数校验 |
| | | if (theoryStockInNum.compareTo(remainingStockInNum) > 0) { |
| | | throw new BaseException("产品【" + productModel.getModel() + "】理论入库数量不能大于待入库数量" + remainingStockInNum.stripTrailingZeros().toPlainString()); |
| | | } |
| | | |
| | | Boolean isContainsWater = Boolean.TRUE.equals(item.getIsContainsWater()); |
| | | BigDecimal waterContent = normalizeWaterContent(isContainsWater, item.getWaterContent()); |
| | | BigDecimal actualStockInNum = calculateActualStockInNum(theoryStockInNum, isContainsWater, waterContent); |
| | | if (actualStockInNum.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new BaseException("实际入库数量必须大于0"); |
| | | } |
| | | |
| | | // 获取是否含水和含水量 |
| | | Boolean isContainsWater = item.getIsContainsWater(); |
| | | BigDecimal waterContent = item.getWaterContent(); |
| | | if (waterContent == null) { |
| | | waterContent = BigDecimal.ZERO; |
| | | } |
| | | |
| | | // 调用StockUtils进行入库(带含水量信息) |
| | | stockUtils.addStockWithBatchNo( |
| | | salesLedgerProduct.getProductModelId(), |
| | | actualStockInNum, |
| | |
| | | return count; |
| | | } |
| | | |
| | | private BigDecimal getApprovedPurchaseStockInNum(Long purchaseLedgerId, String purchaseContractNumber, Long productId, Long productModelId) { |
| | | if (purchaseLedgerId == null || productId == null || productModelId == null || !StringUtils.hasText(purchaseContractNumber)) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | List<StockInRecord> stockRecords = findDirectStockRecords(purchaseLedgerId, purchaseContractNumber, productModelId, productId); |
| | | return stockRecords.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(item -> ReviewStatusEnum.APPROVED.getCode().equals(item.getApprovalStatus())) |
| | | .map(StockInRecord::getStockInNum) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | } |
| | | |
| | | private BigDecimal normalizeWaterContent(Boolean isContainsWater, BigDecimal waterContent) { |
| | | if (!Boolean.TRUE.equals(isContainsWater)) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | if (waterContent == null) { |
| | | throw new BaseException("含水时必须填写含水量"); |
| | | } |
| | | if (waterContent.compareTo(BigDecimal.ZERO) < 0 || waterContent.compareTo(new BigDecimal("100")) >= 0) { |
| | | throw new BaseException("含水量必须在0到100之间"); |
| | | } |
| | | return waterContent; |
| | | } |
| | | |
| | | private BigDecimal calculateActualStockInNum(BigDecimal theoryStockInNum, Boolean isContainsWater, BigDecimal waterContent) { |
| | | if (!Boolean.TRUE.equals(isContainsWater)) { |
| | | return theoryStockInNum; |
| | | } |
| | | BigDecimal percent = waterContent.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP); |
| | | BigDecimal actualStockInNum = theoryStockInNum.multiply(BigDecimal.ONE.subtract(percent)); |
| | | return actualStockInNum.setScale(4, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | /** |
| | | * 下划线命名转驼峰命名 |
| | | */ |