gongchunyi
9 小时以前 23c88fa6c103225e1cff8909a6d12e4d0eb20124
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1006,7 +1006,15 @@
        if (!updateList.isEmpty()) {
            for (SalesLedgerProduct product : updateList) {
                product.setType(type.getCode());
                product.setProductStockStatus(0);
                SalesLedgerProduct db = salesLedgerProductMapper.selectById(product.getId());
                if (db != null) {
                    BigDecimal stockedQty = product.getStockedQuantity() != null ? product.getStockedQuantity() : db.getStockedQuantity();
                    BigDecimal orderQty = product.getQuantity() != null ? product.getQuantity() : db.getQuantity();
                    product.setStockedQuantity(stockedQty);
                    product.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
                } else {
                    product.setProductStockStatus(0);
                }
                product.fillRemainingQuantity();
                salesLedgerProductMapper.updateById(product);
                //  清空销售产品绑定的加工
@@ -1020,7 +1028,9 @@
                salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setProductStockStatus(0);
                BigDecimal stockedQty = salesLedgerProduct.getStockedQuantity();
                BigDecimal orderQty = salesLedgerProduct.getQuantity();
                salesLedgerProduct.setProductStockStatus(calculateProductStockStatus(stockedQty, orderQty));
                salesLedgerProduct.fillRemainingQuantity();
                salesLedgerProductMapper.insert(salesLedgerProduct);
                //  绑定产品额外加工
@@ -1030,6 +1040,41 @@
//                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
            }
        }
        refreshSalesLedgerStockStatus(salesLedgerId);
    }
    private int calculateProductStockStatus(BigDecimal stockedQty, BigDecimal orderQty) {
        BigDecimal stocked = stockedQty == null ? BigDecimal.ZERO : stockedQty;
        BigDecimal order = orderQty == null ? BigDecimal.ZERO : orderQty;
        if (stocked.compareTo(BigDecimal.ZERO) <= 0) {
            return 0;
        }
        if (order.compareTo(BigDecimal.ZERO) > 0 && stocked.compareTo(order) < 0) {
            return 1;
        }
        return 2;
    }
    private void refreshSalesLedgerStockStatus(Long salesLedgerId) {
        if (salesLedgerId == null) return;
        SalesLedger ledger = baseMapper.selectById(salesLedgerId);
        if (ledger == null) return;
        List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(
                Wrappers.<SalesLedgerProduct>lambdaQuery()
                        .eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId)
                        .eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
        if (CollectionUtils.isEmpty(allProducts)) {
            ledger.setStockStatus(0);
            baseMapper.updateById(ledger);
            return;
        }
        boolean anyInbound = allProducts.stream().anyMatch(p -> {
            BigDecimal sq = p.getStockedQuantity();
            return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
        });
        boolean allFull = allProducts.stream().allMatch(p -> Objects.equals(p.getProductStockStatus(), 2));
        ledger.setStockStatus(allFull ? 2 : (anyInbound ? 1 : 0));
        baseMapper.updateById(ledger);
    }
    private SalesLedger convertToEntity(SalesLedgerDto dto) {
@@ -1453,58 +1498,87 @@
        //  查询所有产品
        List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(
                new LambdaQueryWrapper<SalesLedgerProduct>().in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds));
                new LambdaQueryWrapper<SalesLedgerProduct>()
                        .in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds)
                        .eq(SalesLedgerProduct::getType, 1));
        if (CollectionUtils.isNotEmpty(allProducts)) {
            Map<Long, SalesLedger> ledgerMap = ledgers.stream()
                    .collect(Collectors.toMap(SalesLedger::getId, Function.identity()));
            Map<Long, List<SalesLedgerProduct>> groupedData = new LinkedHashMap<>();
            for (SalesLedgerProduct p : allProducts) {
                groupedData.computeIfAbsent(p.getSalesLedgerId(), k -> new ArrayList<>()).add(p);
            }
            List<SalesInvoicesDto.InvoiceOrderGroupDto> groups = new ArrayList<>();
            BigDecimal totalQty = BigDecimal.ZERO;
            BigDecimal totalArea = BigDecimal.ZERO;
            for (Map.Entry<Long, List<SalesLedgerProduct>> ledgerEntry : groupedData.entrySet()) {
                SalesLedger ledger = ledgerMap.get(ledgerEntry.getKey());
                String orderNo = ledger != null ? ledger.getSalesContractNo() : "";
                List<SalesLedgerProduct> products = ledgerEntry.getValue();
            Map<String, List<SalesLedgerProduct>> groupedData = new LinkedHashMap<>();
            Map<String, Set<String>> groupOrderNos = new LinkedHashMap<>();
            for (SalesLedgerProduct p : allProducts) {
                String productCategory = StringUtils.defaultString(p.getProductCategory(), "");
                String specificationModel = StringUtils.defaultString(p.getSpecificationModel(), "");
                String groupKey = productCategory + "||" + specificationModel;
                groupedData.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(p);
                SalesLedger ledger = ledgerMap.get(p.getSalesLedgerId());
                String orderNo = ledger != null ? StringUtils.defaultString(ledger.getSalesContractNo(), "") : "";
                if (StringUtils.isNotEmpty(orderNo)) {
                    groupOrderNos.computeIfAbsent(groupKey, k -> new LinkedHashSet<>()).add(orderNo);
                }
            }
            for (Map.Entry<String, List<SalesLedgerProduct>> productEntry : groupedData.entrySet()) {
                String key = productEntry.getKey();
                String[] parts = key.split("\\|\\|", -1);
                String productName = parts.length > 0 ? parts[0] : "";
                String specificationModel = parts.length > 1 ? parts[1] : "";
                List<SalesLedgerProduct> products = productEntry.getValue();
                SalesInvoicesDto.InvoiceOrderGroupDto group = new SalesInvoicesDto.InvoiceOrderGroupDto();
                group.setSalesContractNo(orderNo);
                if (CollectionUtils.isNotEmpty(products)) {
                    group.setProductName(products.get(0).getProductCategory());
                }
                Set<String> orderNos = groupOrderNos.getOrDefault(key, Collections.emptySet());
                group.setSalesContractNo(String.join(",", orderNos));
                group.setProductName(productName);
                List<SalesInvoicesDto.InvoiceItemDto> itemDtos = new ArrayList<>();
                Map<String, SalesInvoicesDto.InvoiceItemDto> mergedItems = new LinkedHashMap<>();
                BigDecimal groupQty = BigDecimal.ZERO;
                BigDecimal groupArea = BigDecimal.ZERO;
                for (SalesLedgerProduct p : products) {
                    SalesInvoicesDto.InvoiceItemDto item = new SalesInvoicesDto.InvoiceItemDto();
                    item.setFloorCode(p.getFloorCode());
                    item.setWidthHeight((p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") +
                            " * " + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0"));
                    item.setQuantity(p.getQuantity());
                    String widthHeight = (p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") +
                            " * " + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0");
                    String floorCode = StringUtils.defaultString(p.getFloorCode(), "");
                    String remark = StringUtils.defaultString(p.getRemark(), "");
                    String processReq = StringUtils.defaultString(p.getProcessRequirement(), "");
                    String itemKey = floorCode + "||" + widthHeight + "||" + remark + "||" + processReq;
                    BigDecimal qty = p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO;
                    // 面积
                    BigDecimal area = p.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea();
                    if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) {
                        area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
                    }
                    item.setArea(area);
                    item.setRemark(p.getRemark());
                    item.setProcessRequirement(p.getProcessRequirement());
                    area = area != null ? area : BigDecimal.ZERO;
                    itemDtos.add(item);
                    groupQty = groupQty.add(p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO);
                    groupArea = groupArea.add(area != null ? area : BigDecimal.ZERO);
                    SalesInvoicesDto.InvoiceItemDto item = mergedItems.get(itemKey);
                    if (item == null) {
                        item = new SalesInvoicesDto.InvoiceItemDto();
                        item.setFloorCode(floorCode);
                        item.setWidthHeight(widthHeight);
                        item.setSpecificationModel(p.getSpecificationModel());
                        item.setQuantity(qty);
                        item.setArea(area);
                        item.setRemark(remark);
                        item.setProcessRequirement(processReq);
                        mergedItems.put(itemKey, item);
                    } else {
                        item.setQuantity((item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO).add(qty));
                        item.setArea((item.getArea() != null ? item.getArea() : BigDecimal.ZERO).add(area));
                    }
                    groupQty = groupQty.add(qty);
                    groupArea = groupArea.add(area);
                }
                group.setItems(itemDtos);
                group.setItems(new ArrayList<>(mergedItems.values()));
                group.setGroupTotalQuantity(groupQty);
                group.setGroupTotalArea(groupArea.setScale(2, RoundingMode.HALF_UP));
                groups.add(group);
@@ -1565,7 +1639,7 @@
                SalesLabelDto dto = new SalesLabelDto();
                dto.setCustomerName(salesLedger.getCustomerName());
                dto.setSalesContractNo(salesLedger.getSalesContractNo());
                dto.setProductName(p.getProductCategory());
                dto.setProductName(p.getSpecificationModel());
                // 宽*高=数量
                String specification = (p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") + "*" +
@@ -1690,22 +1764,55 @@
            throw new ServiceException("入库失败,未查询到该销售订单的销售产品");
        }
        for (SalesLedgerProduct product : salesLedgerProducts) {
            if (!Objects.equals(product.getSalesLedgerId(), ledger.getId())) {
                throw new ServiceException("入库失败,存在不属于当前销售订单的产品");
            }
            if (product.getProductModelId() == null) {
                continue;
            }
            BigDecimal orderQty = product.getQuantity() == null ? BigDecimal.ZERO : product.getQuantity();
            BigDecimal oldStocked = product.getStockedQuantity() == null ? BigDecimal.ZERO : product.getStockedQuantity();
            BigDecimal inboundQty = orderQty.subtract(oldStocked);
            if (inboundQty.compareTo(BigDecimal.ZERO) < 0) {
                inboundQty = BigDecimal.ZERO;
            }
            if (inboundQty.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setRecordId(product.getId());
            stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode());
            stockInventoryDto.setQualitity(product.getQuantity());
            stockInventoryDto.setQualitity(inboundQty);
            stockInventoryDto.setProductModelId(product.getProductModelId());
            stockInventoryDto.setSalesLedgerId(ledger.getId());
            stockInventoryDto.setSalesLedgerProductId(product.getId());
            stockInventoryService.addstockInventory(stockInventoryDto);
            BigDecimal newStocked = oldStocked.add(inboundQty);
            int lineStockStatus;
            if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
                lineStockStatus = 0;
            } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
                lineStockStatus = 1;
            } else {
                lineStockStatus = 2;
            }
            product.setStockedQuantity(newStocked);
            product.setProductStockStatus(lineStockStatus);
            product.fillRemainingQuantity();
            salesLedgerProductMapper.updateById(product);
        }
        //  按销售订单产品入库情况更新主单入库状态:1-部分入库,2-已入库
        List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()));
        boolean hasStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().anyMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        boolean allStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().allMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        boolean hasStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().anyMatch(item -> {
            BigDecimal sq = item.getStockedQuantity();
            return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
        });
        boolean allStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().allMatch(item -> {
            BigDecimal orderQty = item.getQuantity() == null ? BigDecimal.ZERO : item.getQuantity();
            BigDecimal stockedQty = item.getStockedQuantity() == null ? BigDecimal.ZERO : item.getStockedQuantity();
            return orderQty.compareTo(BigDecimal.ZERO) <= 0 || stockedQty.compareTo(orderQty) >= 0;
        });
        ledger.setStockStatus(allStocked ? 2 : (hasStocked ? 1 : 0));
        baseMapper.updateById(ledger);
    }
@@ -1874,6 +1981,11 @@
            }
            stockUtils.addUnStock(ledgerId, dbProduct.getId(), dbProduct.getProductModelId(), inboundThisLine,
                    StockInUnQualifiedRecordTypeEnum.SALES_SCAN_UNSTOCK_IN.getCode(), dbProduct.getId());
            BigDecimal oldUnStocked = dbProduct.getUnqualifiedStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedStockedQuantity();
            dbProduct.setUnqualifiedStockedQuantity(oldUnStocked.add(inboundThisLine));
            dbProduct.fillRemainingQuantity();
            salesLedgerProductMapper.updateById(dbProduct);
        }
    }
@@ -1927,12 +2039,6 @@
            }
            stockUtils.assertQualifiedAvailable(dbProduct.getProductModelId(), outboundThisLine);
            BigDecimal oldStocked = dbProduct.getStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getStockedQuantity();
            BigDecimal newStocked = oldStocked.subtract(outboundThisLine);
            if (newStocked.compareTo(BigDecimal.ZERO) < 0) {
                newStocked = BigDecimal.ZERO;
            }
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setRecordId(dbProduct.getId());
            stockInventoryDto.setRecordType(StockOutQualifiedRecordTypeEnum.SALE_SCAN_STOCK_OUT.getCode());
@@ -1942,17 +2048,8 @@
            stockInventoryDto.setSalesLedgerProductId(dbProduct.getId());
            stockInventoryService.subtractStockInventory(stockInventoryDto);
            BigDecimal orderQty = dbProduct.getQuantity() == null ? BigDecimal.ZERO : dbProduct.getQuantity();
            int lineStockStatus;
            if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
                lineStockStatus = 0;
            } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
                lineStockStatus = 1;
            } else {
                lineStockStatus = 2;
            }
            dbProduct.setStockedQuantity(newStocked);
            dbProduct.setProductStockStatus(lineStockStatus);
            BigDecimal oldShipped = dbProduct.getShippedQuantity() == null ? BigDecimal.ZERO : dbProduct.getShippedQuantity();
            dbProduct.setShippedQuantity(oldShipped.add(outboundThisLine));
            dbProduct.fillRemainingQuantity();
            salesLedgerProductMapper.updateById(dbProduct);
        }
@@ -2015,9 +2112,19 @@
            if (dbProduct.getProductModelId() == null) {
                throw new ServiceException("不合格出库失败,产品规格未维护,无法出库");
            }
            BigDecimal unStocked = dbProduct.getUnqualifiedStockedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedStockedQuantity();
            BigDecimal unShipped = dbProduct.getUnqualifiedShippedQuantity() == null ? BigDecimal.ZERO : dbProduct.getUnqualifiedShippedQuantity();
            BigDecimal canUnShip = unStocked.subtract(unShipped);
            if (outboundThisLine.compareTo(canUnShip) > 0) {
                throw new ServiceException("不合格出库失败,出库数量不能大于不合格入库数量");
            }
            stockUtils.assertUnqualifiedAvailable(dbProduct.getProductModelId(), outboundThisLine);
            stockUtils.subtractUnStock(ledgerId, dbProduct.getId(), dbProduct.getProductModelId(), outboundThisLine,
                    StockOutUnQualifiedRecordTypeEnum.SALE_SCAN_UNSTOCK_OUT.getCode(), dbProduct.getId());
            dbProduct.setUnqualifiedShippedQuantity(unShipped.add(outboundThisLine));
            dbProduct.fillRemainingQuantity();
            salesLedgerProductMapper.updateById(dbProduct);
        }
    }
}