gongchunyi
2 天以前 fe64e0bbc83ab7e89cbe0d6a9f779a4ac3919608
fix: 销售订单未下发/发货则可以进行编辑
已修改6个文件
127 ■■■■ 文件已修改
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -14,6 +14,7 @@
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerEditFlagDto;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.service.ICommonFileService;
import com.ruoyi.sales.service.ISalesLedgerService;
@@ -246,23 +247,20 @@
        //  获取当前页所有台账记录的 ID 集合
        List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList());
        //  转换回款数据, key 为台账ID, value 为该台账的总回款金额
        Map<Long, BigDecimal> receiptTotals = new HashMap<>();
        //  批量查询每个台账的编辑限制标记:是否含需要生产的产品、生产计划是否已下发、是否已发货
        Map<Long, SalesLedgerEditFlagDto> editFlags = salesLedgerService.getEditFlags(salesLedgerIds);
        for (SalesLedgerVo salesLedgerVo : iPage.getRecords()) {
            Long ledgerId = salesLedgerVo.getId();
            // 合同总金额
            BigDecimal contractAmount = salesLedgerVo.getContractAmount() == null ? BigDecimal.ZERO : salesLedgerVo.getContractAmount();
            // 开票总额和回款总额
            BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
            SalesLedgerEditFlagDto editFlag = editFlags.get(ledgerId);
            boolean needsProduction = isFlagTrue(editFlag == null ? null : editFlag.getNeedsProduction());
            boolean planIssued = isFlagTrue(editFlag == null ? null : editFlag.getPlanIssued());
            boolean shipped = isFlagTrue(editFlag == null ? null : editFlag.getShipped());
            //  如果已经有过开票或回款操作,则不允许编辑
            boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0;
            salesLedgerVo.setIsEdit(hasReceiptOperation);
            //  需要生产的订单:生产计划已下发(含部分下发)则不允许编辑
            //  走库存的订单:已发货则不允许编辑,否则可以编辑
            salesLedgerVo.setIsEdit(needsProduction ? !planIssued : !shipped);
            salesLedgerVo.setHasProductionRecord(planIssued);
            salesLedgerVo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, ledgerId));
        }
@@ -291,4 +289,8 @@
        }
        return AjaxResult.success(data);
    }
    private boolean isFlagTrue(Integer flag) {
        return flag != null && flag == 1;
    }
}
src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -8,6 +8,7 @@
import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
import com.ruoyi.purchase.vo.PurchaseReportVo;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerEditFlagDto;
import com.ruoyi.sales.dto.SalesTrendDto;
import com.ruoyi.sales.dto.StatisticsTableDto;
import com.ruoyi.sales.pojo.SalesLedger;
@@ -91,4 +92,12 @@
    IPage<PurchaseReportVo> selectPurchaseReportVoPage(Page page, @Param("customerName") String customerName);
    /**
     * 批量查询销售台账的编辑限制标记
     *
     * @param ids 销售台账id集合
     * @return 每个台账的需要生产/生产计划已下发/已发货标记
     */
    List<SalesLedgerEditFlagDto> selectEditFlags(@Param("ids") List<Long> ids);
}
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -9,6 +9,7 @@
import com.ruoyi.sales.dto.LossProductModelDto;
import com.ruoyi.sales.dto.MonthlyAmountDto;
import com.ruoyi.sales.dto.SalesLedgerDto;
import com.ruoyi.sales.dto.SalesLedgerEditFlagDto;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.vo.SalesLedgerVo;
@@ -58,4 +59,12 @@
    IPage<SalesLedgerDto> listSalesLedger(SalesLedgerDto salesLedgerDto, Page page);
    Map<String, Object> getPrintData(Long id);
    /**
     * 批量查询销售台账的编辑限制标记,key为销售台账id
     *
     * @param ids 销售台账id集合
     * @return 编辑限制标记
     */
    Map<Long, SalesLedgerEditFlagDto> getEditFlags(List<Long> ids);
}
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.exception.ServiceException;
import com.ruoyi.common.utils.AmountUtils;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -38,6 +39,7 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -177,12 +179,9 @@
            result = salesLedgerProductMapper.insert(salesLedgerProduct);
            addProductionData(salesLedgerProduct);
        } else {
            //查询原本的产品型号id
            result = salesLedgerProductMapper.updateById(salesLedgerProduct);
            /*删除对应的生产数据并重新新增*/
            deleteProductionData(Arrays.asList(salesLedgerProduct.getId()));
            addProductionData(salesLedgerProduct);
            /*同步对应的生产数据:计划未下发时原地更新需求数量,保留生产计划号*/
            syncProductionData(salesLedgerProduct);
        }
        // 如果插入或更新成功,并且有 salesLedgerId,才继续更新主表金额
@@ -238,6 +237,38 @@
    }
    /**
     * 同步生产数据
     * 需要生产:生产计划已下发时禁止修改;未下发时原地更新需求数量,保留生产计划号;
     * 改为走库存:删除未下发的生产计划。
     */
    public void syncProductionData(SalesLedgerProduct salesLedgerProduct) {
        if (salesLedgerProduct.getId() == null) {
            return;
        }
        List<ProductionPlan> productionPlans = listProductionData(salesLedgerProduct.getId());
        if (CollectionUtils.isEmpty(productionPlans)) {
            //原来不需要生产,现在改为需要生产,补建生产计划
            if (Boolean.TRUE.equals(salesLedgerProduct.getIsProduction())) {
                addProductionData(salesLedgerProduct);
            }
            return;
        }
        //改为走库存,删除未下发的生产计划
        if (!Boolean.TRUE.equals(salesLedgerProduct.getIsProduction())) {
            deleteProductionData(Collections.singletonList(salesLedgerProduct.getId()));
            return;
        }
        if (productionPlans.stream().anyMatch(plan -> plan.getStatus() != null && plan.getStatus() != 0)) {
            throw new ServiceException("生产计划已下发,不能修改该销售产品");
        }
        for (ProductionPlan productionPlan : productionPlans) {
            productionPlan.setQtyRequired(salesLedgerProduct.getQuantity());
            productionPlan.setProductModelId(salesLedgerProduct.getProductModelId());
            productionPlanMapper.updateById(productionPlan);
        }
    }
    /**
     * 删除生产计划
     */
    public void deleteProductionData(List<Long> productIds) {
@@ -246,12 +277,12 @@
        }
        List<ProductionPlan> productionPlans = productionPlanMapper.selectList(
                new LambdaQueryWrapper<ProductionPlan>()
                        .in(ProductionPlan::getSalesLedgerProductId, productIds.stream().map(Long::intValue).collect(Collectors.toList())));
                        .in(ProductionPlan::getSalesLedgerProductId, productIds));
        if (CollectionUtils.isEmpty(productionPlans)) {
            return;
        }
        //如果生产计划已下发则不能删除
        if (productionPlans.stream().anyMatch(productionPlan -> productionPlan.getStatus() != 0)) {
        if (productionPlans.stream().anyMatch(productionPlan -> productionPlan.getStatus() != null && productionPlan.getStatus() != 0)) {
            throw new RuntimeException("生产计划已下发,不能删除该销售产品");
        }
        List<Long> ids = productionPlans.stream().map(ProductionPlan::getId).collect(Collectors.toList());
@@ -259,6 +290,14 @@
    }
    /**
     * 查询销售产品对应的生产计划
     */
    private List<ProductionPlan> listProductionData(Long productId) {
        return productionPlanMapper.selectList(new LambdaQueryWrapper<ProductionPlan>()
                .eq(ProductionPlan::getSalesLedgerProductId, productId));
    }
    /**
     * 通用方法:根据主表ID和子表列表,更新主表的合同金额
     */
    public <T, S> void updateMainContractAmount(
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -800,4 +800,16 @@
        result.put("ledger", ledger);
        return result;
    }
    @Override
    public Map<Long, SalesLedgerEditFlagDto> getEditFlags(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new HashMap<>();
        }
        List<SalesLedgerEditFlagDto> flags = salesLedgerMapper.selectEditFlags(ids);
        return flags.stream().collect(Collectors.toMap(
                SalesLedgerEditFlagDto::getSalesLedgerId,
                Function.identity(),
                (existing, replacement) -> existing));
    }
}
src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -147,6 +147,22 @@
        order by sl.execution_date desc
    </select>
    <select id="selectEditFlags" resultType="com.ruoyi.sales.dto.SalesLedgerEditFlagDto">
        SELECT T1.id AS salesLedgerId,
        MAX(CASE WHEN T2.is_production = 1 THEN 1 ELSE 0 END) AS needsProduction,
        MAX(CASE WHEN T3.status IS NOT NULL AND T3.status &lt;&gt; 0 THEN 1 ELSE 0 END) AS planIssued,
        MAX(CASE WHEN T4.status IN ('审核通过', '已发货') THEN 1 ELSE 0 END) AS shipped
        FROM sales_ledger T1
        LEFT JOIN sales_ledger_product T2 ON T2.sales_ledger_id = T1.id AND T2.type = 1
        LEFT JOIN production_plan T3 ON T3.sales_ledger_product_id = T2.id
        LEFT JOIN shipping_info T4 ON T4.sales_ledger_product_id = T2.id
        WHERE T1.id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
        GROUP BY T1.id
    </select>
    <select id="selectPurchaseReportVoPage" resultType="com.ruoyi.purchase.vo.PurchaseReportVo">
        select sl.sales_contract_no customerContractNo,
               c.customer_name,