liding
10 天以前 6305d0c86c23e9a583e8ca798645885d167f4dc5
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -78,11 +78,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;
@@ -3640,4 +3642,289 @@
                .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));
            }
            List<SalesLedger> ledgerList = salesLedgerMapper.selectList(page, queryWrapper);
            // 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());
        }
    }
    /**
     * 手动填充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 "进行中";
        }
    }
}