yuan
10 小时以前 816e5b54488621cf3bf57b770641f167190b5b43
feat: 添加采购订单导出Word文档功能
已添加1个文件
已修改4个文件
120 ■■■■■ 文件已修改
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/purchase-order-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
@@ -250,4 +250,13 @@
    public AjaxResult createPurchaseNo() {
        return AjaxResult.success("生成成功",purchaseLedgerService.getPurchaseNo());
    }
    /**
     * 导出采购订单Word文档
     */
    @Log(title = "采购台账", businessType = BusinessType.EXPORT)
    @PostMapping("/exportDocx")
    public void exportDocx(HttpServletResponse response, @RequestParam Long id) {
        purchaseLedgerService.exportPurchaseOrderDocx(response, id);
    }
}
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
@@ -7,6 +7,7 @@
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@@ -44,4 +45,6 @@
    AjaxResult importData(MultipartFile file);
    PurchaseLedgerDto getPurchaseByCode(PurchaseLedgerDto purchaseLedgerDto);
    void exportPurchaseOrderDocx(HttpServletResponse response, Long id);
}
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -20,6 +20,7 @@
import com.ruoyi.basic.utils.FileUtil;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -51,6 +52,10 @@
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -60,8 +65,11 @@
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -647,4 +655,102 @@
        }
        return sb.toString();
    }
    @Override
    public void exportPurchaseOrderDocx(HttpServletResponse response, Long id) {
        // 1. 查询主表数据
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
        if (purchaseLedger == null) {
            throw new BaseException("采购台账不存在");
        }
        // 2. 查询产品列表
        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
                .eq(SalesLedgerProduct::getType, 2);
        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
        // 3. 查询供应商信息
        SupplierManage supplier = null;
        if (purchaseLedger.getSupplierId() != null) {
            supplier = supplierManageMapper.selectById(purchaseLedger.getSupplierId());
        }
        // 4. 计算合计金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (SalesLedgerProduct product : products) {
            if (product.getTaxInclusiveTotalPrice() != null) {
                totalAmount = totalAmount.add(product.getTaxInclusiveTotalPrice());
            }
        }
        // 5. 加载模板
        InputStream inputStream = this.getClass().getResourceAsStream("/static/purchase-order-template.docx");
        if (inputStream == null) {
            throw new BaseException("采购订单模板文件不存在");
        }
        // 6. 配置 poi-tl(产品列表使用 HackLoopTableRenderPolicy,onSameLine=true 因为标签和字段在同一行)
        Configure configure = Configure.builder()
                .bind("productList", new HackLoopTableRenderPolicy(true))
                .build();
        // 7. 格式化日期
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String orderDate = "";
        String signDate = "";
        if (purchaseLedger.getExecutionDate() != null) {
            orderDate = dateFormatter.format(purchaseLedger.getExecutionDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            signDate = orderDate;
        } else if (purchaseLedger.getEntryDate() != null) {
            orderDate = dateFormatter.format(purchaseLedger.getEntryDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            signDate = orderDate;
        }
        // 8. 组装模板数据
        Map<String, Object> data = new HashMap<>();
        data.put("orderDate", orderDate);
        data.put("purchaseContractNumber", purchaseLedger.getPurchaseContractNumber() != null ? purchaseLedger.getPurchaseContractNumber() : "");
        data.put("supplierName", purchaseLedger.getSupplierName() != null ? purchaseLedger.getSupplierName() : "");
        data.put("contactUserName", supplier != null && supplier.getContactUserName() != null ? supplier.getContactUserName() : "");
        data.put("contactPhone", supplier != null && supplier.getContactUserPhone() != null ? supplier.getContactUserPhone() : "");
        data.put("fax", supplier != null && supplier.getCompanyPhone() != null ? supplier.getCompanyPhone() : "");
        data.put("supplierAddress", supplier != null && supplier.getCompanyAddress() != null ? supplier.getCompanyAddress() : "");
        // 给产品列表添加序号
        List<Map<String, Object>> productList = new ArrayList<>();
        int seq = 1;
        for (SalesLedgerProduct p : products) {
            Map<String, Object> map = new HashMap<>();
            map.put("index", seq++);
            map.put("productCategory", p.getProductCategory());
            map.put("specificationModel", p.getSpecificationModel());
            map.put("unit", p.getUnit());
            map.put("quantity", p.getQuantity());
            map.put("taxInclusiveUnitPrice", p.getTaxInclusiveUnitPrice());
            map.put("taxInclusiveTotalPrice", p.getTaxInclusiveTotalPrice());
            productList.add(map);
        }
        data.put("productList", productList);
        data.put("totalAmount", totalAmount.setScale(2, RoundingMode.HALF_UP).toString());
        data.put("totalAmountChinese", Convert.digitUppercase(totalAmount.doubleValue()));
        data.put("signDate", signDate);
        // 9. 渲染模板并输出
        XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(data);
        try {
            response.setContentType("application/msword");
            String fileName = URLEncoder.encode("采购订单", StandardCharsets.UTF_8);
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
            OutputStream os = response.getOutputStream();
            template.write(os);
            os.flush();
            os.close();
            template.close();
            inputStream.close();
        } catch (Exception e) {
            log.error("导出采购订单失败", e);
            throw new BaseException("导出采购订单失败:" + e.getMessage());
        }
    }
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -215,7 +215,7 @@
     */
    public void addProductionData(SalesLedgerProduct salesLedgerProduct) {
        //先判断该产品是否需要生产
        if (salesLedgerProduct.getIsProduction()) {
        if (Boolean.TRUE.equals(salesLedgerProduct.getIsProduction())) {
            SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerProduct.getSalesLedgerId());
            ProductionPlan productionPlan = new ProductionPlan();
            productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
src/main/resources/static/purchase-order-template.docx
Binary files differ