huminmin
8 天以前 7b8b2456bb15aa733b8599fce2ada5d9549ba881
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -53,6 +53,7 @@
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProcessRouteService;
import com.ruoyi.sales.service.ISalesLedgerProcessRouteRecordService;
import com.ruoyi.sales.service.ISalesLedgerProductProcessBindService;
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.ruoyi.sales.service.ISalesLedgerService;
@@ -78,11 +79,13 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -150,6 +153,7 @@
    private final ISalesLedgerProductProcessBindService salesLedgerProductProcessBindService;
    private final ISalesLedgerProcessRouteService salesLedgerProcessRouteService;
    private final ISalesLedgerProcessRouteRecordService salesLedgerProcessRouteRecordService;
    private final StockInventoryService stockInventoryService;
    private final StockInRecordMapper stockInRecordMapper;
@@ -158,6 +162,8 @@
    private final StockInRecordService stockInRecordService;
    private final StockOutRecordService stockOutRecordService;
    private final StockUtils stockUtils;
    private final ShipmentApprovalMapper shipmentApprovalMapper;
    @Autowired
    private IApproveProcessService approveProcessService;
@@ -331,7 +337,9 @@
    public List getTopFiveList() {
        // 查询原始数据
        LambdaQueryWrapper<SalesLedger> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(SalesLedger::getCustomerId, SalesLedger::getCustomerName, SalesLedger::getContractAmount).orderByDesc(SalesLedger::getContractAmount);
        queryWrapper.select(SalesLedger::getCustomerId, SalesLedger::getCustomerName, SalesLedger::getContractAmount)
                .orderByDesc(SalesLedger::getContractAmount)
                .ne(SalesLedger::getReviewStatus, 2); // 排除反审核数据
        List<SalesLedger> records = salesLedgerMapper.selectList(queryWrapper);
        // 按客户ID分组并聚合金额
@@ -748,21 +756,22 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saleProcessBind(SalesLedgerProcessRoute salesLedgerProcessRoute) {
        if (salesLedgerProcessRoute == null) {
    public void saleProcessBind(SalesLedgerProcessRouteDto salesLedgerProcessRouteDto) {
        if (salesLedgerProcessRouteDto == null) {
            throw new ServiceException("绑定失败,数据不能为空");
        }
        SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRoute.getSalesLedgerId());
        SalesLedger salesLedger = baseMapper.selectById(salesLedgerProcessRouteDto.getSalesLedgerId());
        if (salesLedger == null) {
            throw new ServiceException("绑定失败,销售订单不存在");
        }
        ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRoute.getProcessRouteId());
        ProcessRoute processRoute = processRouteMapper.selectById(salesLedgerProcessRouteDto.getProcessRouteId());
        if (processRoute == null) {
            throw new ServiceException("绑定失败,工艺路线不存在");
        }
        //  清除已绑定的数据
        salesLedgerProcessRouteService.remove(new LambdaQueryWrapper<SalesLedgerProcessRoute>().eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId()));
        salesLedgerProcessRouteRecordService.remove(new LambdaQueryWrapper<SalesLedgerProcessRouteRecord>().eq(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedger.getId()));
        //  将数据迁移到sales_ledger_process_route
        List<ProcessRouteItem> routeItems = processRouteItemMapper.selectList(new LambdaQueryWrapper<ProcessRouteItem>().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
@@ -777,6 +786,39 @@
            salesLedgerProcessRouteList.add(ledgerProcessRoute);
        }
        salesLedgerProcessRouteService.saveBatch(salesLedgerProcessRouteList);
        List<SalesLedgerProcessRoute> savedRoutes = salesLedgerProcessRouteService.list(new LambdaQueryWrapper<SalesLedgerProcessRoute>()
            .eq(SalesLedgerProcessRoute::getSalesLedgerId, salesLedger.getId())
            .eq(SalesLedgerProcessRoute::getProcessRouteId, processRoute.getId()));
        Map<Long, SalesLedgerProcessRoute> routeMap = savedRoutes.stream()
            .filter(item -> item.getProcessRouteItemId() != null)
            .collect(Collectors.toMap(SalesLedgerProcessRoute::getProcessRouteItemId, item -> item, (a, b) -> a));
        Map<Long, SalesLedgerProcessRouteRecord> inputRecordMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(salesLedgerProcessRouteDto.getRecordList())) {
            for (SalesLedgerProcessRouteRecord record : salesLedgerProcessRouteDto.getRecordList()) {
                if (record != null && record.getProcessRouteItemId() != null) {
                    inputRecordMap.put(record.getProcessRouteItemId(), record);
                }
            }
        }
        List<SalesLedgerProcessRouteRecord> routeRecordList = new ArrayList<>();
        for (ProcessRouteItem routeItem : routeItems) {
            SalesLedgerProcessRoute route = routeMap.get(routeItem.getId());
            if (route == null || route.getId() == null) {
                continue;
            }
            SalesLedgerProcessRouteRecord inputRecord = inputRecordMap.get(routeItem.getId());
            SalesLedgerProcessRouteRecord record = new SalesLedgerProcessRouteRecord();
            record.setSalesLedgerId(salesLedger.getId());
            record.setSalesLedgerProcessRouteId(route.getId());
            Integer isCompleted = inputRecord != null && inputRecord.getIsCompleted() != null ? inputRecord.getIsCompleted() : 0;
            record.setIsCompleted(isCompleted);
            record.setCompletedTime(Objects.equals(isCompleted, 1) ? LocalDateTime.now() : null);
            routeRecordList.add(record);
        }
        salesLedgerProcessRouteRecordService.saveBatch(routeRecordList);
    }
    /**
@@ -807,6 +849,13 @@
        List<Long> idList = Arrays.stream(ids).filter(Objects::nonNull).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(idList)) {
            return 0;
        }
        // 校验:已审核的订单不能删除
        List<SalesLedger> ledgers = salesLedgerMapper.selectBatchIds(idList);
        for (SalesLedger ledger : ledgers) {
            if (ledger.getReviewStatus() != null && ledger.getReviewStatus() == 1) {
                throw new ServiceException("已审核的订单不能删除:" + ledger.getSalesContractNo());
            }
        }
        // 删除销售管理数据
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
@@ -902,11 +951,25 @@
                if (salesLedger.getDeliveryStatus() == 5) {
                    throw new ServiceException("订单已发货,禁止编辑");
                }
                // 查询数据库中的原始记录用于校验
                SalesLedger existingLedger = salesLedgerMapper.selectById(salesLedger.getId());
                if (salesLedger.getReviewStatus() != null && salesLedger.getReviewStatus() == 1) {
                    // 审核操作:校验审核人不能是录入人(仅对未审核→已审核的转换)
                    if (existingLedger != null && existingLedger.getReviewStatus() != null && existingLedger.getReviewStatus() == 0) {
                        Long currentUserId = SecurityUtils.getUserId();
                        String entryPerson = existingLedger.getEntryPerson();
                        if (entryPerson != null && entryPerson.equals(String.valueOf(currentUserId))) {
                            throw new ServiceException("不能审核本人录入的订单");
                        }
                    }
                    salesLedger.setReviewStatus(salesLedgerDto.getReviewStatus());
                } else if (salesLedger.getReviewStatus() != null && salesLedger.getReviewStatus() == 2) {
                    handleCounterReview(salesLedger);
                } else {
                    // 未审核状态的编辑操作:校验已审核的订单不能编辑
                    if (existingLedger != null && existingLedger.getReviewStatus() != null && existingLedger.getReviewStatus() == 1) {
                        throw new ServiceException("已审核的订单不能编辑");
                    }
                    salesLedger.setReviewStatus(0);
                }
                salesLedgerMapper.updateById(salesLedger);
@@ -1148,6 +1211,11 @@
    public SalesLedgerProcessRouteDto salesProcess(Long salesLedgerId) {
        SalesLedgerProcessRouteDto dto = new SalesLedgerProcessRouteDto();
        List<SalesLedgerProcessRoute> list = baseMapper.selectSalesProcess(salesLedgerId);
        List<SalesLedgerProcessRouteRecord> recordList = salesLedgerProcessRouteRecordService.list(
            new LambdaQueryWrapper<SalesLedgerProcessRouteRecord>()
                .eq(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedgerId)
                .orderByAsc(SalesLedgerProcessRouteRecord::getId)
        );
        if (CollectionUtils.isNotEmpty(list)) {
            Long processRouteId = list.get(0).getProcessRouteId();
            ProcessRoute processRoute = processRouteMapper.selectById(processRouteId);
@@ -1174,6 +1242,17 @@
            }
        }
        dto.setList(list);
        if (CollectionUtils.isNotEmpty(list) && CollectionUtils.isNotEmpty(recordList)) {
            Map<Long, Long> routeItemIdMap = list.stream()
                .filter(item -> item.getId() != null && item.getProcessRouteItemId() != null)
                .collect(Collectors.toMap(SalesLedgerProcessRoute::getId, SalesLedgerProcessRoute::getProcessRouteItemId, (a, b) -> a));
            recordList.forEach(record -> {
                if (record != null && record.getSalesLedgerProcessRouteId() != null) {
                    record.setProcessRouteItemId(routeItemIdMap.get(record.getSalesLedgerProcessRouteId()));
                }
            });
        }
        dto.setRecordList(recordList);
        return dto;
    }
@@ -3332,6 +3411,97 @@
     * 2. 复制原销售台账及产品数据,生成新的台账
     * 3. 对原台账的库存数据进行反向操作
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> counterReview(CounterReviewDto dto) {
        if (dto == null || CollectionUtils.isEmpty(dto.getIds())) {
            throw new ServiceException("请选择要反审核的订单");
        }
        if (dto.getCounterReviewType() == null || (dto.getCounterReviewType() != 1 && dto.getCounterReviewType() != 2)) {
            throw new ServiceException("请选择反审核类型:作废或重新生成");
        }
        if (dto.getCounterReviewDesc() == null || dto.getCounterReviewDesc().trim().isEmpty()) {
            throw new ServiceException("请输入反审核描述");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<Long> newLedgerIds = new ArrayList<>();
        for (Long id : dto.getIds()) {
            SalesLedger originalLedger = salesLedgerMapper.selectById(id);
            if (originalLedger == null) {
                throw new ServiceException("订单不存在,无法反审核");
            }
            if (originalLedger.getReviewStatus() == null || originalLedger.getReviewStatus() != 1) {
                throw new ServiceException("订单" + originalLedger.getSalesContractNo() + "不是已审核状态,无法反审核");
            }
            // 1. 标记原订单为已反审
            originalLedger.setReviewStatus(2);
            originalLedger.setCounterReviewTime(LocalDateTime.now());
            originalLedger.setCounterReviewPerson(loginUser.getUser().getNickName());
            originalLedger.setCounterReviewPersonId(loginUser.getUserId());
            originalLedger.setCounterReviewType(dto.getCounterReviewType());
            originalLedger.setCounterReviewDesc(dto.getCounterReviewDesc());
            salesLedgerMapper.updateById(originalLedger);
            // 2. 作废库存:入库扣减、出库增加、删除记录
            processOriginalOrderStock(id);
            // 3. 清除质检记录
            clearQualityInspectRecords(id);
            // 4. 清除发货信息和发货审批记录
            clearShippingAndApprovalRecords(id);
            // 5. 取消审批流程
            cancelApproveProcesses(id, originalLedger.getSalesContractNo());
            // 6. 重新生成:创建新台账副本
            if (dto.getCounterReviewType() == 2) {
                SalesLedger newLedger = new SalesLedger();
                BeanUtils.copyProperties(originalLedger, newLedger);
                newLedger.setId(null);
                newLedger.setSalesContractNo(generateSalesContractNo());
                newLedger.setDeliveryStatus(1);
                newLedger.setStockStatus(0);
                newLedger.setReviewStatus(0);
                newLedger.setCounterReviewTime(null);
                newLedger.setCounterReviewPerson(null);
                newLedger.setCounterReviewPersonId(null);
                newLedger.setCounterReviewType(null);
                newLedger.setCounterReviewDesc(null);
                salesLedgerMapper.insert(newLedger);
                // 复制产品到新台账
                List<SalesLedgerProduct> originalProducts = salesLedgerProductMapper.selectList(
                    Wrappers.<SalesLedgerProduct>lambdaQuery()
                        .eq(SalesLedgerProduct::getSalesLedgerId, id)
                );
                for (SalesLedgerProduct originalProduct : originalProducts) {
                    SalesLedgerProduct newProduct = new SalesLedgerProduct();
                    BeanUtils.copyProperties(originalProduct, newProduct);
                    newProduct.setId(null);
                    newProduct.setSalesLedgerId(newLedger.getId());
                    newProduct.setStockedQuantity(BigDecimal.ZERO);
                    newProduct.setShippedQuantity(BigDecimal.ZERO);
                    newProduct.setUnqualifiedStockedQuantity(BigDecimal.ZERO);
                    newProduct.setUnqualifiedShippedQuantity(BigDecimal.ZERO);
                    newProduct.setReturnQuality(BigDecimal.ZERO);
                    newProduct.setAvailableQuality(newProduct.getQuantity().subtract(newProduct.getReturnQuality()));
                    newProduct.setProductStockStatus(0);
                    newProduct.fillRemainingQuantity();
                    salesLedgerProductMapper.insert(newProduct);
                }
                newLedgerIds.add(newLedger.getId());
            }
        }
        return newLedgerIds;
    }
    /**
     * 旧版反审处理(兼容 addOrUpdateSalesLedger 中 reviewStatus=2 的调用)
     */
    private void handleCounterReview(SalesLedger salesLedger) {
        // 1. 设置反审相关信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
@@ -3390,13 +3560,96 @@
        
        // 6. 处理原订单的库存数据(生成反审出入库记录)
        processOriginalOrderStock(originalSalesLedgerId);
        // 7. 清除原订单的质检记录
        clearQualityInspectRecords(originalSalesLedgerId);
        // 8. 清除原订单的发货信息和发货审批记录
        clearShippingAndApprovalRecords(originalSalesLedgerId);
        // 9. 取消原订单相关的审批流程
        cancelApproveProcesses(originalSalesLedgerId, originalLedger.getSalesContractNo());
    }
    /**
     * 清除原订单的质检记录
     */
    private void clearQualityInspectRecords(Long originalSalesLedgerId) {
        // 删除与原订单关联的质检记录
        qualityInspectMapper.delete(
            Wrappers.<QualityInspect>lambdaQuery()
                .eq(QualityInspect::getPurchaseLedgerId, originalSalesLedgerId)
        );
    }
    /**
     * 清除原订单的发货信息和发货审批记录
     */
    private void clearShippingAndApprovalRecords(Long originalSalesLedgerId) {
        // 1. 查询原订单的所有发货信息
        List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(
            Wrappers.<ShippingInfo>lambdaQuery()
                .eq(ShippingInfo::getSalesLedgerId, originalSalesLedgerId)
        );
        // 2. 删除发货审批记录
        if (!CollectionUtils.isEmpty(shippingInfos)) {
            List<Long> shippingInfoIds = shippingInfos.stream()
                .map(ShippingInfo::getId)
                .collect(Collectors.toList());
            shipmentApprovalMapper.delete(
                Wrappers.<ShipmentApproval>lambdaQuery()
                    .eq(ShipmentApproval::getSalesLedgerId, originalSalesLedgerId)
                    .or()
                    .in(ShipmentApproval::getShippingInfoId, shippingInfoIds)
            );
            // 3. 删除发货信息记录
            shippingInfoMapper.delete(
                Wrappers.<ShippingInfo>lambdaQuery()
                    .eq(ShippingInfo::getSalesLedgerId, originalSalesLedgerId)
            );
        }
    }
    /**
     * 取消原订单相关的审批流程
     */
    private void cancelApproveProcesses(Long originalSalesLedgerId, String originalSalesContractNo) {
        // 取消入库审批流程
        List<ApproveProcess> stockInApproveProcesses = approveProcessService.list(
            new LambdaQueryWrapper<ApproveProcess>()
                .eq(ApproveProcess::getApproveType, ApproveTypeEnum.STOCK_IN.getCode())
                .like(ApproveProcess::getApproveRemark, "salesStock:" + originalSalesLedgerId + ":")
                .eq(ApproveProcess::getApproveDelete, 0)
        );
        for (ApproveProcess process : stockInApproveProcesses) {
            process.setApproveStatus(3); // 设置为审批失败状态
            process.setApproveDelete(1); // 标记为已删除
            approveProcessService.updateById(process);
        }
        // 取消发货审批流程
        List<ApproveProcess> deliveryApproveProcesses = approveProcessService.list(
            new LambdaQueryWrapper<ApproveProcess>()
                .eq(ApproveProcess::getApproveType, 7) // 发货审批类型
                .like(ApproveProcess::getApproveReason, "发货审批:" + originalSalesContractNo)
                .eq(ApproveProcess::getApproveDelete, 0)
        );
        for (ApproveProcess process : deliveryApproveProcesses) {
            process.setApproveStatus(3); // 设置为审批失败状态
            process.setApproveDelete(1); // 标记为已删除
            approveProcessService.updateById(process);
        }
    }
    /**
     * 处理原订单的库存数据
     * 1. 对原订单的入库数据生成反审出库记录(销售-反审出库)
     * 2. 对原订单的出库数据生成反审入库记录(销售-反审入库)
     * 3. 更新库存表数据
     * 1. 删除原订单的所有入库记录,并扣减库存
     * 2. 删除原订单的所有出库记录,并增加库存
     */
    private void processOriginalOrderStock(Long originalSalesLedgerId) {
        // 1. 查询原订单的所有入库记录
@@ -3405,58 +3658,565 @@
                .eq(StockInRecord::getSalesLedgerId, originalSalesLedgerId)
        );
        
        // 2. 对每条入库记录生成对应的反审出库记录
        // 2. 删除入库记录并扣减库存
        for (StockInRecord stockInRecord : stockInRecords) {
            // 2.1 创建反审出库记录
            StockOutRecord stockOutRecord = new StockOutRecord();
            stockOutRecord.setOutboundBatches(OrderUtils.countTodayByCreateTime(stockOutRecordMapper, "CK")); // 生成出库批次号
            stockOutRecord.setStockOutNum(stockInRecord.getStockInNum()); // 出库数量等于原入库数量
            stockOutRecord.setRecordId(stockInRecord.getId()); // 记录原入库记录ID
            stockOutRecord.setRecordType(StockOutQualifiedRecordTypeEnum.SALE_COUNTER_REVIEW_STOCK_OUT.getCode()); // 设置为销售反审出库类型
            stockOutRecord.setProductModelId(stockInRecord.getProductModelId()); // 产品规格ID
            stockOutRecord.setRemark("销售-反审出库"); // 备注
            stockOutRecord.setType(stockInRecord.getType()); // 类型(合格/不合格)
            stockOutRecord.setSalesLedgerId(stockInRecord.getSalesLedgerId()); // 销售订单ID
            stockOutRecord.setSalesLedgerProductId(stockInRecord.getSalesLedgerProductId()); // 销售订单产品ID
            // 2.2 插入反审出库记录
            stockOutRecordMapper.insert(stockOutRecord);
            // 2.3 从库存表中扣减相应数量
            // 从库存表中扣减相应数量
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
            stockInventoryDto.setQualitity(stockOutRecord.getStockOutNum());
            stockInventoryDto.setProductModelId(stockInRecord.getProductModelId());
            stockInventoryDto.setQualitity(stockInRecord.getStockInNum());
            stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
        }
        
        // 3. 查询原订单的所有出库记录
        // 3. 删除所有入库记录
        stockInRecordMapper.delete(
            Wrappers.<StockInRecord>lambdaQuery()
                .eq(StockInRecord::getSalesLedgerId, originalSalesLedgerId)
        );
        // 4. 查询原订单的所有出库记录
        List<StockOutRecord> stockOutRecords = stockOutRecordMapper.selectList(
            Wrappers.<StockOutRecord>lambdaQuery()
                .eq(StockOutRecord::getSalesLedgerId, originalSalesLedgerId)
        );
        
        // 4. 对每条出库记录生成对应的反审入库记录
        // 5. 删除出库记录并增加库存
        for (StockOutRecord stockOutRecord : stockOutRecords) {
            // 4.1 创建反审入库记录
            StockInRecord stockInRecord = new StockInRecord();
            stockInRecord.setInboundBatches(OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK")); // 生成入库批次号
            stockInRecord.setStockInNum(stockOutRecord.getStockOutNum()); // 入库数量等于原出库数量
            stockInRecord.setRecordId(stockOutRecord.getId()); // 记录原出库记录ID
            stockInRecord.setRecordType(StockInQualifiedRecordTypeEnum.SALE_COUNTER_REVIEW_STOCK_IN.getCode()); // 设置为销售反审入库类型
            stockInRecord.setProductModelId(stockOutRecord.getProductModelId()); // 产品规格ID
            stockInRecord.setRemark("销售-反审入库"); // 备注
            stockInRecord.setType(stockOutRecord.getType()); // 类型(合格/不合格)
            stockInRecord.setSalesLedgerId(stockOutRecord.getSalesLedgerId()); // 销售订单ID
            stockInRecord.setSalesLedgerProductId(stockOutRecord.getSalesLedgerProductId()); // 销售订单产品ID
            // 4.2 插入反审入库记录
            stockInRecordMapper.insert(stockInRecord);
            // 4.3 向库存表中增加相应数量
            // 向库存表中增加相应数量
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setProductModelId(stockInRecord.getProductModelId());
            stockInventoryDto.setQualitity(stockInRecord.getStockInNum());
            stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
            stockInventoryDto.setQualitity(stockOutRecord.getStockOutNum());
            stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
        }
        // 6. 删除所有出库记录
        stockOutRecordMapper.delete(
            Wrappers.<StockOutRecord>lambdaQuery()
                .eq(StockOutRecord::getSalesLedgerId, originalSalesLedgerId)
        );
    }
}
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markOrderCompleted(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("请选择要标记完成的订单");
        }
        for (Long id : ids) {
            SalesLedger ledger = salesLedgerMapper.selectById(id);
            if (ledger == null) {
                throw new ServiceException("订单不存在,无法标记完成");
            }
            if (ledger.getReviewStatus() == null || ledger.getReviewStatus() != 1) {
                throw new ServiceException("订单" + ledger.getSalesContractNo() + "不是已审核状态,无法标记完成");
            }
            if (ledger.getOrderStatus() != null && ledger.getOrderStatus() == 1) {
                throw new ServiceException("订单" + ledger.getSalesContractNo() + "已完成,无需重复标记");
            }
        }
        salesLedgerMapper.update(null,
            Wrappers.<SalesLedger>lambdaUpdate()
                .in(SalesLedger::getId, ids)
                .set(SalesLedger::getOrderStatus, 1)
        );
    }
    @Override
    public void incrementPrintCount(Long id, String printType) {
        if (id == null) {
            throw new ServiceException("销售台账ID不能为空");
        }
        if (printType == null || (!"label".equals(printType) && !"document".equals(printType))) {
            throw new ServiceException("打印类型必须为 label 或 document");
        }
        SalesLedger ledger = salesLedgerMapper.selectById(id);
        if (ledger == null) {
            throw new ServiceException("销售台账不存在");
        }
        if ("label".equals(printType)) {
            int currentCount = ledger.getLabelPrintCount() == null ? 0 : ledger.getLabelPrintCount();
            salesLedgerMapper.update(null,
                Wrappers.<SalesLedger>lambdaUpdate()
                    .eq(SalesLedger::getId, id)
                    .set(SalesLedger::getLabelPrintCount, currentCount + 1)
            );
        } else {
            int currentCount = ledger.getDocumentPrintCount() == null ? 0 : ledger.getDocumentPrintCount();
            salesLedgerMapper.update(null,
                Wrappers.<SalesLedger>lambdaUpdate()
                    .eq(SalesLedger::getId, id)
                    .set(SalesLedger::getDocumentPrintCount, currentCount + 1)
            );
        }
    }
    @Override
    public void exportWithProducts(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
        try {
            // 1. 查询销售台账列表(导出使用升序排序)
            Page<SalesLedger> page = new Page<>(-1, -1);
            // 使用 Wrappers 构建升序查询
            LambdaQueryWrapper<SalesLedger> queryWrapper = Wrappers.<SalesLedger>lambdaQuery()
                .orderByAsc(SalesLedger::getEntryDate)
                .orderByAsc(SalesLedger::getId);
            // 添加查询条件
            if (salesLedgerDto.getCustomerName() != null && !salesLedgerDto.getCustomerName().isEmpty()) {
                queryWrapper.like(SalesLedger::getCustomerName, salesLedgerDto.getCustomerName());
            }
            if (salesLedgerDto.getSalesContractNo() != null && !salesLedgerDto.getSalesContractNo().isEmpty()) {
                queryWrapper.like(SalesLedger::getSalesContractNo, salesLedgerDto.getSalesContractNo());
            }
            if (salesLedgerDto.getProjectName() != null && !salesLedgerDto.getProjectName().isEmpty()) {
                queryWrapper.like(SalesLedger::getProjectName, salesLedgerDto.getProjectName());
            }
            if (salesLedgerDto.getEntryDateStart() != null && !salesLedgerDto.getEntryDateStart().isEmpty()) {
                queryWrapper.ge(SalesLedger::getEntryDate, salesLedgerDto.getEntryDateStart());
            }
            if (salesLedgerDto.getEntryDateEnd() != null && !salesLedgerDto.getEntryDateEnd().isEmpty()) {
                queryWrapper.le(SalesLedger::getEntryDate, salesLedgerDto.getEntryDateEnd());
            }
            if (salesLedgerDto.getDeliveryStatus() != null) {
                queryWrapper.eq(SalesLedger::getDeliveryStatus, salesLedgerDto.getDeliveryStatus());
            }
            if (salesLedgerDto.getStockStatus() != null) {
                queryWrapper.eq(SalesLedger::getStockStatus, salesLedgerDto.getStockStatus());
            }
            if (salesLedgerDto.getReviewStatus() != null) {
                queryWrapper.eq(SalesLedger::getReviewStatus, salesLedgerDto.getReviewStatus());
            }
            if (salesLedgerDto.getOrderStatus() != null) {
                queryWrapper.eq(SalesLedger::getOrderStatus, salesLedgerDto.getOrderStatus());
            }
            if (salesLedgerDto.getReviewStatusList() != null && !salesLedgerDto.getReviewStatusList().isEmpty()) {
                queryWrapper.and(w -> w.in(SalesLedger::getReviewStatus, salesLedgerDto.getReviewStatusList())
                    .or().isNull(SalesLedger::getReviewStatus));
            }
            IPage<SalesLedger> ledgerPage = salesLedgerMapper.selectPage(page, queryWrapper);
            List<SalesLedger> ledgerList = ledgerPage.getRecords();
            // 2. 收集数据
            List<SalesLedgerExportDto> ledgerExportList = new ArrayList<>();
            List<SalesLedgerProductExportDto> productExportList = new ArrayList<>();
            for (SalesLedger ledger : ledgerList) {
                // 转换台账数据
                SalesLedgerExportDto ledgerDto = new SalesLedgerExportDto();
                ledgerDto.setSalesContractNo(ledger.getSalesContractNo());
                ledgerDto.setCustomerContractNo(ledger.getCustomerContractNo());
                ledgerDto.setProjectName(ledger.getProjectName());
                ledgerDto.setCustomerName(ledger.getCustomerName());
                ledgerDto.setSalesman(ledger.getSalesman());
                ledgerDto.setEntryPersonName(ledger.getEntryPersonName());
                ledgerDto.setEntryDate(ledger.getEntryDate());
                ledgerDto.setExecutionDate(ledger.getExecutionDate() != null ?
                    java.sql.Date.valueOf(ledger.getExecutionDate()) : null);
                ledgerDto.setDeliveryDate(ledger.getDeliveryDate() != null ?
                    java.sql.Date.valueOf(ledger.getDeliveryDate()) : null);
                ledgerDto.setContractAmount(ledger.getContractAmount());
                ledgerDto.setRemarks(ledger.getRemarks());
                ledgerDto.setCustomerRemarks(ledger.getCustomerRemarks());
                ledgerDto.setDeliveryStatusText(getDeliveryStatusText(ledger.getDeliveryStatus()));
                ledgerDto.setStockStatusText(getStockStatusText(ledger.getStockStatus()));
                ledgerDto.setReviewStatusText(getReviewStatusText(ledger.getReviewStatus()));
                ledgerDto.setOrderStatusText(getOrderStatusText(ledger.getOrderStatus()));
                ledgerExportList.add(ledgerDto);
                // 查询该台账的产品列表
                List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(
                    Wrappers.<SalesLedgerProduct>lambdaQuery()
                        .eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId())
                        .eq(SalesLedgerProduct::getType, 1)
                );
                for (SalesLedgerProduct product : products) {
                    SalesLedgerProductExportDto productDto = new SalesLedgerProductExportDto();
                    productDto.setSalesContractNo(ledger.getSalesContractNo());
                    productDto.setProductCategory(product.getProductCategory());
                    productDto.setSpecificationModel(product.getSpecificationModel());
                    productDto.setThickness(product.getThickness());
                    productDto.setFloorCode(product.getFloorCode());
                    productDto.setWidth(product.getWidth());
                    productDto.setHeight(product.getHeight());
                    productDto.setQuantity(product.getQuantity());
                    productDto.setSettlePieceArea(product.getSettlePieceArea());
                    productDto.setSettleTotalArea(product.getSettleTotalArea());
                    productDto.setTaxInclusiveUnitPrice(product.getTaxInclusiveUnitPrice());
                    productDto.setTaxRate(product.getTaxRate());
                    productDto.setTaxInclusiveTotalPrice(product.getTaxInclusiveTotalPrice());
                    productDto.setTaxExclusiveTotalPrice(product.getTaxExclusiveTotalPrice());
                    productDto.setInvoiceType(product.getInvoiceType());
                    productDto.setProcessRequirement(product.getProcessRequirement());
                    productDto.setRemark(product.getRemark());
                    productExportList.add(productDto);
                }
            }
            // 3. 使用ExcelUtil导出(内部会创建Workbook并写入响应)
            // 先创建临时文件,再合并两个sheet
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("销售台账.xlsx", "utf-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            org.apache.poi.xssf.usermodel.XSSFWorkbook workbook = new org.apache.poi.xssf.usermodel.XSSFWorkbook();
            // Sheet1: 销售台账 - 手动填充
            fillSheetWithData(workbook, "销售台账", SalesLedgerExportDto.class, ledgerExportList);
            // Sheet2: 产品明细 - 手动填充
            fillSheetWithData(workbook, "产品明细", SalesLedgerProductExportDto.class, productExportList);
            workbook.write(response.getOutputStream());
            workbook.close();
        } catch (Exception e) {
            log.error("导出销售台账失败", e);
            throw new ServiceException("导出失败:" + e.getMessage());
        }
    }
    @Override
    public void exportProcessRoute(HttpServletResponse response, List<Long> salesLedgerIds, String completedTimeStart, String completedTimeEnd) {
        try {
            if (CollectionUtils.isEmpty(salesLedgerIds)) {
                throw new ServiceException("请选择要导出的销售台账");
            }
            LocalDateTime startTime = parseCompletedTime(completedTimeStart);
            LocalDateTime endTime = parseCompletedTime(completedTimeEnd);
            if (startTime == null && endTime == null) {
                startTime = LocalDate.now().atStartOfDay();
                endTime = LocalDateTime.now();
            } else {
                if (startTime == null) {
                    startTime = LocalDate.now().atStartOfDay();
                }
                if (endTime == null) {
                    endTime = LocalDateTime.now();
                }
            }
            LambdaQueryWrapper<SalesLedgerProcessRouteRecord> queryWrapper = Wrappers.<SalesLedgerProcessRouteRecord>lambdaQuery()
                .eq(SalesLedgerProcessRouteRecord::getIsCompleted, 1)
                .ge(SalesLedgerProcessRouteRecord::getCompletedTime, startTime)
                .le(SalesLedgerProcessRouteRecord::getCompletedTime, endTime)
                .orderByAsc(SalesLedgerProcessRouteRecord::getCompletedTime)
                .orderByAsc(SalesLedgerProcessRouteRecord::getId);
            if (CollectionUtils.isNotEmpty(salesLedgerIds)) {
                queryWrapper.in(SalesLedgerProcessRouteRecord::getSalesLedgerId, salesLedgerIds);
            }
            List<SalesLedgerProcessRouteRecord> completedRoutes = salesLedgerProcessRouteRecordService.list(queryWrapper);
            Map<Long, SalesLedger> salesLedgerMap = Collections.emptyMap();
            Map<Long, SalesLedgerProcessRoute> routeMap = Collections.emptyMap();
            Map<Long, ProcessRouteItem> processRouteItemMap = Collections.emptyMap();
            Map<Long, List<SalesLedgerProduct>> productMap = Collections.emptyMap();
            if (CollectionUtils.isNotEmpty(completedRoutes)) {
                List<Long> routeSalesLedgerIds = completedRoutes.stream()
                    .map(SalesLedgerProcessRouteRecord::getSalesLedgerId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
                List<Long> salesLedgerProcessRouteIds = completedRoutes.stream()
                    .map(SalesLedgerProcessRouteRecord::getSalesLedgerProcessRouteId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(routeSalesLedgerIds)) {
                    salesLedgerMap = salesLedgerMapper.selectBatchIds(routeSalesLedgerIds).stream()
                        .filter(Objects::nonNull)
                        .collect(Collectors.toMap(SalesLedger::getId, item -> item, (a, b) -> a));
                    List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
                        .in(SalesLedgerProduct::getSalesLedgerId, routeSalesLedgerIds)
                        .eq(SalesLedgerProduct::getType, 1)
                        .orderByAsc(SalesLedgerProduct::getSalesLedgerId)
                        .orderByAsc(SalesLedgerProduct::getId));
                    productMap = products.stream().collect(Collectors.groupingBy(
                        SalesLedgerProduct::getSalesLedgerId,
                        LinkedHashMap::new,
                        Collectors.toList()
                    ));
                }
                if (CollectionUtils.isNotEmpty(salesLedgerProcessRouteIds)) {
                    routeMap = salesLedgerProcessRouteService.listByIds(salesLedgerProcessRouteIds).stream()
                        .filter(Objects::nonNull)
                        .collect(Collectors.toMap(SalesLedgerProcessRoute::getId, item -> item, (a, b) -> a));
                    List<Long> processRouteItemIds = routeMap.values().stream()
                        .map(SalesLedgerProcessRoute::getProcessRouteItemId)
                        .filter(Objects::nonNull)
                        .distinct()
                        .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(processRouteItemIds)) {
                        processRouteItemMap = processRouteItemMapper.selectBatchIds(processRouteItemIds).stream()
                            .filter(Objects::nonNull)
                            .collect(Collectors.toMap(ProcessRouteItem::getId, item -> item, (a, b) -> a));
                    }
                }
            }
            Map<Long, List<SalesLedgerProcessRouteRecord>> routeGroupMap = new LinkedHashMap<>();
            for (SalesLedgerProcessRouteRecord record : completedRoutes) {
                SalesLedgerProcessRoute route = routeMap.get(record.getSalesLedgerProcessRouteId());
                if (route == null || route.getProcessRouteItemId() == null) {
                    continue;
                }
                routeGroupMap.computeIfAbsent(route.getProcessRouteItemId(), k -> new ArrayList<>()).add(record);
            }
            final Map<Long, ProcessRouteItem> finalProcessRouteItemMap = processRouteItemMap;
            LinkedHashMap<String, List<List<Object>>> sheetMap = new LinkedHashMap<>();
            List<Long> orderedProcessRouteItemIds = routeGroupMap.keySet().stream()
                .sorted((left, right) -> compareProcessRouteItem(left, right, finalProcessRouteItemMap))
                .collect(Collectors.toList());
            for (Long processRouteItemId : orderedProcessRouteItemIds) {
                ProcessRouteItem processRouteItem = finalProcessRouteItemMap.get(processRouteItemId);
                String sheetName = buildUniqueSheetName(sheetMap, processRouteItem, processRouteItemId);
                List<List<Object>> sheetData = new ArrayList<>();
                sheetData.add(buildProcessRouteHeader());
                for (SalesLedgerProcessRouteRecord route : routeGroupMap.getOrDefault(processRouteItemId, Collections.emptyList())) {
                    SalesLedger salesLedger = salesLedgerMap.get(route.getSalesLedgerId());
                    if (salesLedger == null) {
                        continue;
                    }
                    List<SalesLedgerProduct> products = productMap.getOrDefault(salesLedger.getId(), Collections.emptyList());
                    if (CollectionUtils.isEmpty(products)) {
                        sheetData.add(buildProcessRouteRow(salesLedger, null, route));
                        continue;
                    }
                    for (SalesLedgerProduct product : products) {
                        sheetData.add(buildProcessRouteRow(salesLedger, product, route));
                    }
                }
                if (sheetData.size() == 1) {
                    sheetData.add(Arrays.asList("", "", "", "", "", "", "", "", ""));
                }
                sheetMap.put(sheetName, sheetData);
            }
            if (sheetMap.isEmpty()) {
                List<List<Object>> sheetData = new ArrayList<>();
                sheetData.add(buildProcessRouteHeader());
                sheetData.add(Arrays.asList("", "", "", "", "", "", ""));
                sheetMap.put("工艺路线", sheetData);
            }
            com.ruoyi.common.utils.excel.ExcelUtils.exportManySheet(response, "销售台账工艺路线导出", sheetMap);
        } catch (Exception e) {
            log.error("导出售后台账工艺路线失败", e);
            throw new ServiceException("导出售后台账工艺路线失败:" + e.getMessage());
        }
    }
    private LocalDateTime parseCompletedTime(String value) {
        if (!StringUtils.hasText(value)) {
            return null;
        }
        String text = value.trim();
        try {
            return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (Exception ex) {
            try {
                return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
            } catch (Exception ignored) {
                return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
            }
        }
    }
    private int compareProcessRouteItem(Long left, Long right, Map<Long, ProcessRouteItem> processRouteItemMap) {
        ProcessRouteItem leftItem = processRouteItemMap.get(left);
        ProcessRouteItem rightItem = processRouteItemMap.get(right);
        int leftSort = leftItem != null && leftItem.getDragSort() != null ? leftItem.getDragSort() : Integer.MAX_VALUE;
        int rightSort = rightItem != null && rightItem.getDragSort() != null ? rightItem.getDragSort() : Integer.MAX_VALUE;
        if (leftSort != rightSort) {
            return Integer.compare(leftSort, rightSort);
        }
        String leftName = leftItem != null && StringUtils.hasText(leftItem.getProcessName()) ? leftItem.getProcessName() : "";
        String rightName = rightItem != null && StringUtils.hasText(rightItem.getProcessName()) ? rightItem.getProcessName() : "";
        int nameCompare = leftName.compareTo(rightName);
        if (nameCompare != 0) {
            return nameCompare;
        }
        return Long.compare(left, right);
    }
    private List<Object> buildProcessRouteHeader() {
        return Arrays.asList("日期", "订单编号", "客户名称", "规格", "数量", "面积", "是否是工程");
    }
    private List<Object> buildProcessRouteRow(SalesLedger salesLedger, SalesLedgerProduct product, SalesLedgerProcessRouteRecord route) {
        List<Object> row = new ArrayList<>();
        row.add(salesLedger.getEntryDate() == null ? "" : DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, salesLedger.getEntryDate()));
        row.add(salesLedger.getSalesContractNo());
        row.add(salesLedger.getCustomerName());
        row.add(product == null ? "" : product.getSpecificationModel());
        row.add(product == null ? "" : product.getQuantity());
        row.add(product == null ? "" : resolveExportArea(product));
        row.add("");
        return row;
    }
    private BigDecimal resolveExportArea(SalesLedgerProduct product) {
        if (product == null) {
            return BigDecimal.ZERO;
        }
        if (product.getSettleTotalArea() != null) {
            return product.getSettleTotalArea();
        }
        if (product.getActualTotalArea() != null) {
            return product.getActualTotalArea();
        }
        BigDecimal qty = product.getQuantity() == null ? BigDecimal.ONE : product.getQuantity();
        if (product.getSettlePieceArea() != null) {
            return product.getSettlePieceArea().multiply(qty).setScale(2, RoundingMode.HALF_UP);
        }
        if (product.getActualPieceArea() != null) {
            return product.getActualPieceArea().multiply(qty).setScale(2, RoundingMode.HALF_UP);
        }
        if (product.getWidth() != null && product.getHeight() != null) {
            BigDecimal area = product.getWidth().multiply(product.getHeight())
                .divide(new BigDecimal("1000000"), 2, RoundingMode.HALF_UP);
            return area.multiply(qty).setScale(2, RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }
    private String buildUniqueSheetName(Map<String, List<List<Object>>> sheetMap, ProcessRouteItem processRouteItem, Long processRouteItemId) {
        String baseName = processRouteItem != null && StringUtils.hasText(processRouteItem.getProcessName())
            ? processRouteItem.getProcessName()
            : "工序" + processRouteItemId;
        baseName = sanitizeSheetName(baseName);
        String sheetName = baseName;
        int suffix = 2;
        while (sheetMap.containsKey(sheetName)) {
            String suffixText = "_" + suffix++;
            int maxBaseLength = 31 - suffixText.length();
            String trimmedBase = baseName.length() > maxBaseLength ? baseName.substring(0, maxBaseLength) : baseName;
            sheetName = trimmedBase + suffixText;
        }
        return sheetName;
    }
    private String sanitizeSheetName(String sheetName) {
        if (!StringUtils.hasText(sheetName)) {
            return "工艺路线";
        }
        String sanitized = sheetName.replaceAll("[\\\\/?*\\[\\]:]", "_").trim();
        if (sanitized.isEmpty()) {
            sanitized = "工艺路线";
        }
        return sanitized.length() > 31 ? sanitized.substring(0, 31) : sanitized;
    }
    /**
     * 手动填充Sheet数据
     */
    private <T> void fillSheetWithData(org.apache.poi.xssf.usermodel.XSSFWorkbook workbook, String sheetName, Class<T> clazz, List<T> dataList) throws Exception {
        org.apache.poi.ss.usermodel.Sheet sheet = workbook.createSheet(sheetName);
        // 获取字段上的@Excel注解
        java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
        List<java.lang.reflect.Field> excelFields = new ArrayList<>();
        for (java.lang.reflect.Field field : fields) {
            com.ruoyi.framework.aspectj.lang.annotation.Excel excel = field.getAnnotation(com.ruoyi.framework.aspectj.lang.annotation.Excel.class);
            if (excel != null) {
                excelFields.add(field);
            }
        }
        // 创建表头
        org.apache.poi.ss.usermodel.Row headerRow = sheet.createRow(0);
        org.apache.poi.ss.usermodel.CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.GREY_50_PERCENT.getIndex());
        headerStyle.setFillPattern(org.apache.poi.ss.usermodel.FillPatternType.SOLID_FOREGROUND);
        headerStyle.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
        org.apache.poi.ss.usermodel.Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        for (int i = 0; i < excelFields.size(); i++) {
            java.lang.reflect.Field field = excelFields.get(i);
            field.setAccessible(true);
            com.ruoyi.framework.aspectj.lang.annotation.Excel excel = field.getAnnotation(com.ruoyi.framework.aspectj.lang.annotation.Excel.class);
            org.apache.poi.ss.usermodel.Cell cell = headerRow.createCell(i);
            cell.setCellValue(excel.name());
            cell.setCellStyle(headerStyle);
            sheet.setColumnWidth(i, 20 * 256);
        }
        // 创建数据行
        org.apache.poi.ss.usermodel.CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
        for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
            T data = dataList.get(rowIndex);
            org.apache.poi.ss.usermodel.Row row = sheet.createRow(rowIndex + 1);
            for (int colIndex = 0; colIndex < excelFields.size(); colIndex++) {
                java.lang.reflect.Field field = excelFields.get(colIndex);
                field.setAccessible(true);
                Object value = field.get(data);
                org.apache.poi.ss.usermodel.Cell cell = row.createCell(colIndex);
                if (value == null) {
                    cell.setCellValue("");
                } else if (value instanceof Number) {
                    cell.setCellValue(((Number) value).doubleValue());
                } else if (value instanceof Date) {
                    cell.setCellValue(new java.text.SimpleDateFormat("yyyy-MM-dd").format((Date) value));
                } else {
                    cell.setCellValue(value.toString());
                }
                cell.setCellStyle(dataStyle);
            }
        }
    }
    private String getDeliveryStatusText(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 1: return "未发货";
            case 2: return "审批中";
            case 3: return "审批不通过";
            case 4: return "审批通过";
            case 5: return "已发货";
            case 6: return "部分发货";
            default: return "未知";
        }
    }
    private String getStockStatusText(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 0: return "未入库";
            case 1: return "部分入库";
            case 2: return "已入库";
            case 3: return "审批中";
            default: return "未知";
        }
    }
    private String getReviewStatusText(Integer status) {
        if (status == null) return "待审核";
        switch (status) {
            case 0: return "待审核";
            case 1: return "已审核";
            case 2: return "已反审";
            default: return "待审核";
        }
    }
    private String getOrderStatusText(Integer status) {
        if (status == null || status == 0) return "进行中";
        switch (status) {
            case 0: return "进行中";
            case 1: return "已完成";
            default: return "进行中";
        }
    }
}