diff --git a/ruoyi-modules/ruoyi-wms/pom.xml b/ruoyi-modules/ruoyi-wms/pom.xml index 33416f01..8e2637a6 100644 --- a/ruoyi-modules/ruoyi-wms/pom.xml +++ b/ruoyi-modules/ruoyi-wms/pom.xml @@ -108,6 +108,12 @@ org.dromara ruoyi-common-bus + + + + org.dromara + ruoyi-common-word + diff --git a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/controller/WmsShippingBillController.java b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/controller/WmsShippingBillController.java index cd01df9a..2667ae5d 100644 --- a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/controller/WmsShippingBillController.java +++ b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/controller/WmsShippingBillController.java @@ -15,6 +15,7 @@ import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; +import org.dromara.common.word.util.WordTemplateUtil; import org.dromara.wms.domain.bo.WmsShippingBillBo; import org.dromara.wms.domain.vo.WmsShippingBillVo; import org.dromara.wms.service.IWmsShippingBillService; @@ -22,6 +23,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; /** * 发货单 @@ -125,4 +127,26 @@ public class WmsShippingBillController extends BaseController { return R.ok(wmsShippingBillService.shippingBillSubmitAndFlowStart(bo)); } + /** + * 导出发货单Word文档 + * 使用poi-tl模板引擎,基于发货单模板.docx生成Word文件 + * + * @param shippingBillId 发货单ID + * @param response HttpServletResponse + */ + @SaCheckPermission("wms:wmsShippingBill:export") + @Log(title = "发货单Word导出", businessType = BusinessType.EXPORT) + @GetMapping("/exportWord/{shippingBillId}") + public void exportWord(@NotNull(message = "发货单ID不能为空") + @PathVariable("shippingBillId") Long shippingBillId, + HttpServletResponse response) { + // 组装模板数据 + Map data = wmsShippingBillService.buildWordExportData(shippingBillId); + // 生成文件名(发货单号) + WmsShippingBillVo vo = wmsShippingBillService.queryById(shippingBillId); + String fileName = "发货单_" + (vo != null && vo.getShippingCode() != null ? vo.getShippingCode() : shippingBillId); + // 渲染并输出Word文档(模板路径为classpath根目录) + WordTemplateUtil.renderToResponse("发货单模板.docx", fileName, data, response); + } + } diff --git a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/IWmsShippingBillService.java b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/IWmsShippingBillService.java index b087a551..616f934c 100644 --- a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/IWmsShippingBillService.java +++ b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/IWmsShippingBillService.java @@ -73,4 +73,12 @@ public interface IWmsShippingBillService { * @return 发货单VO */ WmsShippingBillVo shippingBillSubmitAndFlowStart(WmsShippingBillBo bo); + + /** + * 组装发货单Word导出数据 + * + * @param shippingBillId 发货单ID + * @return Word模板数据Map + */ + java.util.Map buildWordExportData(Long shippingBillId); } diff --git a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/impl/WmsShippingBillServiceImpl.java b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/impl/WmsShippingBillServiceImpl.java index 55b244cd..7b7a3dc1 100644 --- a/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/impl/WmsShippingBillServiceImpl.java +++ b/ruoyi-modules/ruoyi-wms/src/main/java/org/dromara/wms/service/impl/WmsShippingBillServiceImpl.java @@ -34,10 +34,8 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.text.SimpleDateFormat; +import java.util.*; import java.util.stream.Collectors; /** @@ -336,4 +334,79 @@ public class WmsShippingBillServiceImpl implements IWmsShippingBillService { baseMapper.updateById(shippingBill); }); } + + /** + * 组装发货单 Word 导出数据。 + *

+ * 根据 {@code word.md} 中定义的模板结构,组装主表字段和明细列表数据,供 poi-tl 渲染使用。 + * 约定如下: + *

    + *
  • 主表字段:如 customerName、receiverName、receiverPhone、shippingDate、contractCode 等,对应 Word 模板中的 + * {{customerName}}、{{receiverName}}、{{receiverPhone}}、{{shippingDate}}、{{contractCode}} 等占位符;
  • + *
  • 明细列表:使用 {@code details} 作为列表占位符,内部每一行包含 seq、materialName、quantity、unit、remark 等字段, + * 对应 Word 模板表格中的 {{seq}}、{{materialName}}、{{quantity}}、{{unit}}、{{remark}}。
  • + *
+ * + * @param shippingBillId 发货单ID + * @return Word 模板数据 Map,建议直接传给 {@link org.dromara.common.word.util.WordTemplateUtil} + */ + @Override + public Map buildWordExportData(Long shippingBillId) { + // 查询发货单(包含明细列表) + WmsShippingBillVo vo = queryById(shippingBillId); + if (vo == null) { + throw new ServiceException("发货单不存在,ID:" + shippingBillId); + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Map data = new HashMap<>(); + + // === 主表字段 === + // 客户名称 + data.put("customerName", StringUtils.blankToDefault(vo.getCustomerName(), "")); + // 收货联系人(客户侧) + data.put("receiverName", StringUtils.blankToDefault(vo.getReceiverName(), "")); + // 收货联系电话(客户侧) + data.put("receiverPhone", StringUtils.blankToDefault(vo.getReceiverPhone(), "")); + // 发货日期(实际发货时间) + data.put("shippingDate", vo.getShippingTime() != null ? sdf.format(vo.getShippingTime()) : ""); + // 合同编号 + data.put("contractCode", StringUtils.blankToDefault(vo.getContractCode(), "")); + // 收货日期(留空,由客户签收时填写) + data.put("receivedDate", ""); + // === 落款信息(供应商/发货方) === + // 发货单位(供应商名称) + data.put("shippingUnit", StringUtils.blankToDefault(vo.getSupplier(), "")); + // 发货人(供应商联系人) + data.put("shipper", StringUtils.blankToDefault(vo.getContactUser(), "")); + // 发货方联系电话 + data.put("contactNumber", StringUtils.blankToDefault(vo.getContactNumber(), "")); + + // === 明细列表 === + // 对应 Word 模板中的 {{#details}}...{{/details}} 循环表格: + // - seq → {{seq}} (行号) + // - materialName → {{materialName}}(物料名称) + // - quantity → {{quantity}} (发货数量) + // - unit → {{unit}} (计量单位) + // - remark → {{remark}} (备注) + // 如需在模板中添加单价、金额、合计行等字段,可在此处扩展 row 中的字段,并在 data 中追加 totalQuantity、totalAmount 等汇总字段。 + List> details = new ArrayList<>(); + List itemsVo = vo.getItemsVo(); + if (CollUtil.isNotEmpty(itemsVo)) { + int seq = 1; + for (WmsShippingDetailsVo item : itemsVo) { + Map row = new HashMap<>(); + row.put("seq", String.valueOf(seq++)); + row.put("materialName", StringUtils.blankToDefault(item.getMaterialName(), "")); + row.put("quantity", item.getShippingStockAmount() != null ? item.getShippingStockAmount().toPlainString() : ""); + row.put("unit", StringUtils.blankToDefault(item.getUnitName(), "")); + row.put("remark", StringUtils.blankToDefault(item.getRemark(), "")); + details.add(row); + } + } + // poi-tl 列表占位符,对应 Word 模板中的 {{#details}}...{{/details}} + data.put("details", details); + + return data; + } } diff --git a/ruoyi-modules/ruoyi-wms/src/main/resources/发货单模板.docx b/ruoyi-modules/ruoyi-wms/src/main/resources/发货单模板.docx new file mode 100644 index 00000000..b2cbd22f Binary files /dev/null and b/ruoyi-modules/ruoyi-wms/src/main/resources/发货单模板.docx differ