src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.AmountUtils;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.mapper.*;
@@ -35,7 +36,6 @@
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
@@ -90,7 +90,9 @@
    @Override
    public SalesLedgerProduct selectSalesLedgerProductById(Long id) {
        return salesLedgerProductMapper.selectById(id);
        SalesLedgerProduct product = salesLedgerProductMapper.selectById(id);
        AmountUtils.normalizeSalesLedgerProduct(product);
        return product;
    }
    @Override
@@ -98,6 +100,7 @@
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectSalesLedgerProductList(salesLedgerProduct);
        if(!CollectionUtils.isEmpty(salesLedgerProducts)){
            salesLedgerProducts.forEach(item -> {
                AmountUtils.normalizeSalesLedgerProduct(item);
                // 发货信息
                ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
                        .eq(ShippingInfo::getSalesLedgerProductId, item.getId())
@@ -165,6 +168,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addOrUpdateSalesLedgerProduct(SalesLedgerProduct salesLedgerProduct) {
        AmountUtils.normalizeSalesLedgerProduct(salesLedgerProduct);
        int result;
        Long salesLedgerId = salesLedgerProduct.getSalesLedgerId();
@@ -216,23 +220,20 @@
     */
    public void addProductionData(SalesLedgerProduct salesLedgerProduct) {
        //先判断该产品是否需要生产
        if (!salesLedgerProduct.getIsProduction()) {
            return;
        if (Boolean.TRUE.equals(salesLedgerProduct.getIsProduction())) {
            SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerProduct.getSalesLedgerId());
            ProductionPlan productionPlan = new ProductionPlan();
            productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
            productionPlan.setSalesLedgerProductId(salesLedgerProduct.getId());
            productionPlan.setMpsNo(generateNextPlanNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
            productionPlan.setProductModelId(salesLedgerProduct.getProductModelId());
            productionPlan.setQtyRequired(salesLedgerProduct.getQuantity());
            productionPlan.setSource("销售");
            productionPlan.setStatus(0);
            productionPlan.setRequiredDate(salesLedger.getDeliveryDate());//需求日期=交货日期
            productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate());//承诺日期=交货日期
            productionPlanMapper.insert(productionPlan);
        }
        SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerProduct.getSalesLedgerId());
        ProductionPlan productionPlan = new ProductionPlan();
        productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
        productionPlan.setSalesLedgerProductId(salesLedgerProduct.getId());
        productionPlan.setMpsNo(generateNextPlanNo(salesLedger.getEntryDate().toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
        productionPlan.setProductModelId(salesLedgerProduct.getProductModelId());
        productionPlan.setQtyRequired(salesLedgerProduct.getQuantity());
        productionPlan.setSource("销售");
        productionPlan.setStatus(0);
        productionPlan.setRequiredDate(salesLedger.getDeliveryDate());//需求日期=交货日期
        productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate());//承诺日期=交货日期
        productionPlanMapper.insert(productionPlan);
    }
@@ -284,7 +285,7 @@
            Field amountField = mainEntityClass.getDeclaredField("contractAmount");
            amountField.setAccessible(true);
            amountField.set(entity, totalAmount);
            amountField.set(entity, AmountUtils.scaleAmount(totalAmount));
            mainMapper.updateById(entity);
        } catch (Exception e) {
@@ -307,29 +308,30 @@
        }
        int count = 0;
        StringBuilder stringBuffer = new StringBuilder();
        // 扁平BOM只维护“物料规格 + 消耗工序”,不配置用量,
        // 因此这里只校验每个物料是否有可用库存,不再按单位用量核算需求数量。
        for (TechnologyBomStructureVo structure : structureList) {
            if (structure.getParentId() == null) {
            if (structure == null || structure.getProductModelId() == null) {
                continue;
            }
            StockInventory stockInventory = stockInventoryMapper.selectOne(
                    new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, structure.getProductModelId()));
            if (stockInventory == null) {
                count++;
                stringBuffer.append(structure.getProductName()).append("-").append(structure.getModel()).append("库存不足").append(System.lineSeparator());
                continue;
            List<StockInventory> stockList = stockInventoryMapper.selectList(
                    new QueryWrapper<StockInventory>().lambda()
                            .eq(StockInventory::getProductModelId, structure.getProductModelId()));
            BigDecimal available = BigDecimal.ZERO;
            for (StockInventory stockInventory : stockList) {
                if (stockInventory == null) {
                    continue;
                }
                BigDecimal quantity = stockInventory.getQualitity() == null ? BigDecimal.ZERO : stockInventory.getQualitity();
                BigDecimal locked = stockInventory.getLockedQuantity() == null ? BigDecimal.ZERO : stockInventory.getLockedQuantity();
                available = available.add(quantity.subtract(locked));
            }
            BigDecimal required = salesLedgerProduct.getQuantity().multiply(structure.getUnitQuantity() == null ? BigDecimal.ZERO : structure.getUnitQuantity());
            BigDecimal remain = stockInventory.getQualitity()
                    .subtract(stockInventory.getLockedQuantity())
                    .subtract(required)
                    .divide(BigDecimal.ONE, 2, RoundingMode.CEILING);
            if (remain.compareTo(BigDecimal.ZERO) < 0) {
            if (available.compareTo(BigDecimal.ZERO) <= 0) {
                count++;
                stringBuffer.append(structure.getProductName())
                        .append("-")
                        .append(structure.getModel())
                        .append("库存不足,少")
                        .append(remain.abs())
                        .append("无可用库存")
                        .append(System.lineSeparator());
            }
        }