2 天以前 5f73eb1fb9d04040fe6ba377d5ae582024429f2f
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
import com.ruoyi.approve.pojo.ApprovalInstance;
@@ -15,17 +16,20 @@
import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
import com.ruoyi.basic.enums.ApplicationTypeEnum;
import com.ruoyi.basic.enums.RecordTypeEnum;
import com.ruoyi.basic.mapper.OilDepotMapper;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.mapper.SupplierManageMapper;
import com.ruoyi.basic.pojo.OilDepot;
import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.basic.utils.FileUtil;
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.enums.TypeEnums;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
@@ -33,6 +37,10 @@
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRecord;
import com.ruoyi.measuringinstrumentledger.service.SparePartsRecordService;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
@@ -92,6 +100,11 @@
@RequiredArgsConstructor
public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService {
    /**
     * 明细类型:采购(sales_ledger_product.type)。仅采购明细才回写备件库存
     */
    private static final Integer LEDGER_TYPE_PURCHASE = 2;
    private final PurchaseLedgerMapper purchaseLedgerMapper;
    private final SalesLedgerMapper salesLedgerMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
@@ -116,6 +129,9 @@
    private final StockInRecordService stockInRecordService;
    private final StockUtils stockUtils;
    private final ApprovalTemplateMapper approvalTemplateMapper;
    private final OilDepotMapper oilDepotMapper;
    private final SparePartsMapper sparePartsMapper;
    private final SparePartsRecordService sparePartsRecordService;
    @Override
    public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) {
@@ -129,7 +145,15 @@
        if (purchaseLedger.getApprovalStatus() != null) {
            queryWrapper.eq(PurchaseLedger::getApprovalStatus, purchaseLedger.getApprovalStatus());
        }
        // 只查询入库已审批通过的采购台账
        queryWrapper.inSql(PurchaseLedger::getId,
                "SELECT DISTINCT record_id FROM stock_in_record WHERE approval_status = 1");
        return purchaseLedgerMapper.selectList(queryWrapper);
    }
    @Override
    public List<PurchaseLedger> selectReturnablePurchaseLedgerList(PurchaseLedger purchaseLedger) {
        return purchaseLedgerMapper.selectReturnablePurchaseLedgerList(purchaseLedger);
    }
    @Override
@@ -161,29 +185,24 @@
        purchaseLedger.setSupplierName(supplierManage.getSupplierName());
        purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId());
        // 采购油库:根据油库id回填油库名称
        if (purchaseLedgerDto.getOilDepotId() != null) {
            OilDepot oilDepot = oilDepotMapper.selectById(purchaseLedgerDto.getOilDepotId());
            if (oilDepot != null) {
                purchaseLedger.setOilDepotName(oilDepot.getDepotName());
            }
        }
        purchaseLedger.setApprovalStatus(1);
        // 新增时初始化实际合同金额
        if (purchaseLedger.getId() == null) {
            purchaseLedger.setNetContractAmount(purchaseLedger.getContractAmount());
        }
        // 实际合同金额始终等于合同金额
        purchaseLedger.setNetContractAmount(purchaseLedger.getContractAmount());
        // 3. 新增或更新主表
        if (purchaseLedger.getId() == null) {
            if (!StringUtils.hasText(purchaseLedger.getPurchaseContractNumber())) {
                purchaseLedger.setPurchaseContractNumber(generatePurchaseContractNo(purchaseLedger.getEntryDate()));
            }
            purchaseLedgerMapper.insert(purchaseLedger);
        } else {
            // 删除采购审核,重新提交
            ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
                    .eq(ApproveProcess::getApproveType, 5)
                    .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber())
                    .eq(ApproveProcess::getApproveDelete, 0)
                    .last("limit 1"));
            if (one != null) {
                approveProcessService.delByIds(Collections.singletonList(one.getId()));
            }
            purchaseLedgerMapper.updateById(purchaseLedger);
        if (purchaseLedger.getId() == null && !StringUtils.hasText(purchaseLedger.getPurchaseContractNumber())) {
            purchaseLedger.setPurchaseContractNumber(generatePurchaseContractNo(purchaseLedger.getEntryDate()));
        }
        this.saveOrUpdate(purchaseLedger);
        // 回写主键,供调用方(如采购申请转订单)获取新生成的采购台账id
        purchaseLedgerDto.setId(purchaseLedger.getId());
        // 4. 处理子表数据
        List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData();
@@ -191,7 +210,17 @@
            handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType());
        }
        // 6.采购审核新增;审批管理未配置采购审批人时,审批服务会自动置为审批通过。
        addApproveByPurchase(loginUser, purchaseLedger);
        //查询当前采购合同号是否已添加审批,如果有且不是驳回状态,则不重复添加
        ApprovalInstance oldApprovalInstance = approvalInstanceService.getOne(Wrappers.<ApprovalInstance>lambdaQuery()
                .eq(ApprovalInstance::getDeleted, 0)
                .eq(ApprovalInstance::getBusinessType, TypeEnums.PURCHASE_APPROVAL.getCode())
                .eq(ApprovalInstance::getBusinessId, purchaseLedger.getId())
                .ne(ApprovalInstance::getStatus,"REJECTED")
                .last("limit 1")
        );
        if(Objects.isNull(oldApprovalInstance)){
            addApproveByPurchase(loginUser, purchaseLedger, productList);
        }
        // 5. 迁移临时文件到正式目录
        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId(), purchaseLedgerDto.getStorageBlobDTOS());
        return 1;
@@ -690,6 +719,10 @@
                salesLedgerProduct.setRegisterDate(localDateTime);
                salesLedgerProductMapper.insert(salesLedgerProduct);
            }
            // 仅新增明细回写备件,编辑走 update 分支天然不重复计数
            if (LEDGER_TYPE_PURCHASE.equals(ledgerType)) {
                recordSparePartsInbound(insertList, purchaseLedger);
            }
        }
        // 计算总含税金额
@@ -702,6 +735,47 @@
        if (salesLedgerId != null) {
            // 直接更新指定ID的记录的contractAmount字段为totalTaxInclusiveAmount
            purchaseLedgerMapper.updateContractAmountById(salesLedgerId, totalTaxInclusiveAmount);
        }
    }
    /**
     * 采购台账新增明细按规格匹配备件:累加备件库存并记一条入库流水。
     * 未维护规格的备件不参与,静默跳过。
     */
    private void recordSparePartsInbound(List<SalesLedgerProduct> insertList, PurchaseLedger purchaseLedger) {
        List<Long> modelIds = insertList.stream()
                .map(SalesLedgerProduct::getProductModelId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (modelIds.isEmpty()) {
            return;
        }
        List<SpareParts> sparePartsList = sparePartsMapper.selectList(new LambdaQueryWrapper<SpareParts>()
                .in(SpareParts::getProductModelId, modelIds));
        if (CollectionUtils.isEmpty(sparePartsList)) {
            return;
        }
        Map<Long, SpareParts> sparePartsByModelId = sparePartsList.stream()
                .collect(Collectors.toMap(SpareParts::getProductModelId, s -> s, (a, b) -> a));
        for (SalesLedgerProduct product : insertList) {
            SpareParts spareParts = sparePartsByModelId.get(product.getProductModelId());
            if (spareParts == null || product.getQuantity() == null
                    || product.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            BigDecimal quantity = product.getQuantity();
            spareParts.setQuantity((spareParts.getQuantity() == null ? BigDecimal.ZERO : spareParts.getQuantity()).add(quantity));
            sparePartsMapper.updateById(spareParts);
            SparePartsRecord record = new SparePartsRecord();
            record.setSparePartsId(spareParts.getId());
            record.setDirection(1);
            record.setQuantity(quantity);
            record.setSourceType(1);
            record.setSourceId(purchaseLedger.getId());
            record.setSourceNo(purchaseLedger.getPurchaseContractNumber());
            sparePartsRecordService.save(record);
        }
    }
@@ -758,13 +832,30 @@
        for (Long id : ids) {
            PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
            if(purchaseLedger != null){
                ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
                List<ApprovalInstance> approvalInstances = approvalInstanceService.list(new LambdaQueryWrapper<ApprovalInstance>()
                        .eq(ApprovalInstance::getBusinessId, purchaseLedger.getId())
                        .eq(ApprovalInstance::getBusinessType, 5L)
                        .eq(ApprovalInstance::getDeleted, 0));
                if (CollectionUtils.isNotEmpty(approvalInstances)) {
                    approvalInstanceService.delete(
                            approvalInstances.stream()
                                    .map(ApprovalInstance::getId)
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toList())
                    );
                }
                List<ApproveProcess> approveProcesses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
                        .eq(ApproveProcess::getApproveType, 5)
                        .eq(ApproveProcess::getApproveDelete, 0)
                        .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber())
                        .last("limit 1"));
                if (one != null) {
                    approveProcessService.delByIds(Collections.singletonList(one.getId()));
                        .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber()));
                if (CollectionUtils.isNotEmpty(approveProcesses)) {
                    approveProcessService.delByIds(
                            approveProcesses.stream()
                                    .map(ApproveProcess::getId)
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toList())
                    );
                }
            }
        }
@@ -945,6 +1036,7 @@
                salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
                        .map(PurchaseLedgerProductImportDto::getTaxInclusiveTotalPrice)
                        .reduce(BigDecimal.ZERO,BigDecimal::add));
                salesLedger.setNetContractAmount(salesLedger.getContractAmount());
                // 通过销售单号绑定销售
                SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
                        .eq(SalesLedger::getSalesContractNo, salesLedger.getSalesContractNo())
@@ -994,7 +1086,12 @@
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                }
                // 采购审核
                addApproveByPurchase(loginUser,salesLedger);
                List<SalesLedgerProduct> snapshotProducts = salesLedgerProductMapper.selectList(
                        new LambdaQueryWrapper<SalesLedgerProduct>()
                                .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId())
                                .eq(SalesLedgerProduct::getType, 2)
                );
                addApproveByPurchase(loginUser, salesLedger, snapshotProducts);
            }
            return AjaxResult.success("导入成功");
@@ -1006,21 +1103,91 @@
    @Override
    public PurchaseLedgerDto getPurchaseByCode(PurchaseLedgerDto purchaseLedgerDto) {
        // 1. 查询主表
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
                .eq(PurchaseLedger::getPurchaseContractNumber, purchaseLedgerDto.getPurchaseContractNumber())
                .last("LIMIT 1"));
        if (purchaseLedger == null) {
            throw new BaseException("采购台账不存在");
        PurchaseLedger purchaseLedger = null;
        ApprovalInstance approvalSnapshotInstance = null;
        // 1. 优先按当前审批实例查询快照
        if (purchaseLedgerDto.getApprovalInstanceId() != null) {
            approvalSnapshotInstance = approvalInstanceService.getById(purchaseLedgerDto.getApprovalInstanceId());
            if (approvalSnapshotInstance != null && approvalSnapshotInstance.getBusinessId() != null) {
                purchaseLedger = purchaseLedgerMapper.selectById(approvalSnapshotInstance.getBusinessId());
            }
        }
        // 2. 查询子表
        // 2. 没传审批实例ID时,退回到按采购合同号查询
        if (purchaseLedger == null) {
            purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
                    .eq(PurchaseLedger::getPurchaseContractNumber, purchaseLedgerDto.getPurchaseContractNumber())
                    .last("LIMIT 1"));
            if (purchaseLedger == null) {
                throw new BaseException("采购台账不存在");
            }
        }
        // 3. 查询当前采购单对应的审批快照
        if (approvalSnapshotInstance == null) {
            approvalSnapshotInstance = approvalInstanceService.getOne(new LambdaQueryWrapper<ApprovalInstance>()
                    .eq(ApprovalInstance::getBusinessId, purchaseLedger.getId())
                    .eq(ApprovalInstance::getBusinessType, 5L)
                    .eq(ApprovalInstance::getDeleted, 0)
                    .orderByDesc(ApprovalInstance::getId)
                    .last("LIMIT 1"));
        }
        if (approvalSnapshotInstance != null && StringUtils.hasText(approvalSnapshotInstance.getFormConfig())) {
            try {
                PurchaseLedgerDto snapshot = JSON.parseObject(approvalSnapshotInstance.getFormConfig(), PurchaseLedgerDto.class);
                if (snapshot != null) {
                    snapshot.setId(purchaseLedger.getId());
                    if (snapshot.getPurchaseContractNumber() == null) {
                        snapshot.setPurchaseContractNumber(purchaseLedger.getPurchaseContractNumber());
                    }
                    if (snapshot.getSupplierId() == null) {
                        snapshot.setSupplierId(purchaseLedger.getSupplierId());
                    }
                    if (snapshot.getSupplierName() == null) {
                        snapshot.setSupplierName(purchaseLedger.getSupplierName());
                    }
                    if (snapshot.getSalesContractNo() == null) {
                        snapshot.setSalesContractNo(purchaseLedger.getSalesContractNo());
                    }
                    if (snapshot.getSalesContractNoId() == null) {
                        snapshot.setSalesContractNoId(purchaseLedger.getSalesLedgerId());
                    }
                    if (snapshot.getProjectName() == null) {
                        snapshot.setProjectName(purchaseLedger.getProjectName());
                    }
                    if (snapshot.getEntryDate() == null) {
                        snapshot.setEntryDate(purchaseLedger.getEntryDate());
                    }
                    if (snapshot.getExecutionDate() == null) {
                        snapshot.setExecutionDate(purchaseLedger.getExecutionDate());
                    }
                    if (snapshot.getRemarks() == null) {
                        snapshot.setRemarks(purchaseLedger.getRemarks());
                    }
                    if (snapshot.getRecorderId() == null) {
                        snapshot.setRecorderId(purchaseLedger.getRecorderId());
                    }
                    if (snapshot.getRecorderName() == null) {
                        snapshot.setRecorderName(purchaseLedger.getRecorderName());
                    }
                    snapshot.setProductData(snapshot.getProductData() == null ? Collections.emptyList() : snapshot.getProductData());
                    snapshot.setHasChildren(CollectionUtils.isNotEmpty(snapshot.getProductData()));
                    return snapshot;
                }
            } catch (Exception e) {
                log.warn("解析采购审批快照失败: {}", e.getMessage());
            }
        }
        // 4. 查询子表
        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
                .eq(SalesLedgerProduct::getType, 2);
        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
        // 4. 转换 DTO
        // 5. 转换 DTO
        PurchaseLedgerDto resultDto = new PurchaseLedgerDto();
        BeanUtils.copyProperties(purchaseLedger, resultDto);
        if (!products.isEmpty()) {
@@ -1030,7 +1197,7 @@
        return resultDto;
    }
    public void addApproveByPurchase(LoginUser loginUser,PurchaseLedger purchaseLedger) throws Exception {
    public void addApproveByPurchase(LoginUser loginUser, PurchaseLedger purchaseLedger, List<SalesLedgerProduct> productList) {
        if (loginUser == null) {
            return;
        }
@@ -1055,6 +1222,10 @@
        approvalInstance.setTitle(purchaseLedger.getPurchaseContractNumber()+"审批");
        approvalInstance.setApplicantName(loginUser.getNickName());
        approvalInstance.setApplyTime(LocalDateTime.now());
        PurchaseLedgerDto snapshot = new PurchaseLedgerDto();
        BeanUtils.copyProperties(purchaseLedger, snapshot);
        snapshot.setProductData(productList == null ? Collections.emptyList() : new ArrayList<>(productList));
        approvalInstance.setFormConfig(JSON.toJSONString(snapshot));
        approvalInstanceService.add(approvalInstance);
    }