feat(project): 实现合同模板导出功能并优化页面交互

- 在项目订单信息中新增“partnerAddress”字段,并在 Mapper 中关联查询该字段
- 增加导出填充订单信息的合同模板接口与实现逻辑,支持根据 orderId 动态生成 docx 文件
- 修改前端页面:
  - 当 POC 选择“否”时,默认选中第一个 tab(工作进度)
  - 注释掉订单编辑页中的“合同信息”tab 项
  - 调整导出逻辑,通过 orderId 获取数据并传递给后端生成文件
- 完善产品信息实体类及 Mapper,增加 vendorName 字段支持- 优化前端下载请求逻辑,使用 orderId 替代固定文件名方式

```
dev_1.0.0
chenhao 2025-09-22 16:37:59 +08:00
parent 92218dac59
commit 940fe11624
11 changed files with 387 additions and 13 deletions

View File

@ -357,6 +357,11 @@
let val = $('#poc').val(); let val = $('#poc').val();
if (val==='0'){ if (val==='0'){
$('#pocLogTab').attr('style','display:none') $('#pocLogTab').attr('style','display:none')
// 当POC=否时选中第一个tab页工作进度
$('.layui-tab-title li').removeClass('layui-this');
$('.layui-tab-title li:first').addClass('layui-this');
$('.layui-tab-content .layui-tab-item').removeClass('layui-show');
$('.layui-tab-content .layui-tab-item:first').addClass('layui-show');
}else{ }else{
$('#pocLogTab').attr('style','display:inline') $('#pocLogTab').attr('style','display:inline')
} }

View File

@ -421,6 +421,11 @@
console.log(val) console.log(val)
if (val==='0'){ if (val==='0'){
$('#pocLogTab').attr('style','display:none') $('#pocLogTab').attr('style','display:none')
// 当POC=否时选中第一个tab页工作进度
$('.layui-tab-title li').removeClass('layui-this');
$('.layui-tab-title li:first').addClass('layui-this');
$('.layui-tab-content .layui-tab-item').removeClass('layui-show');
$('.layui-tab-content .layui-tab-item:first').addClass('layui-show');
}else{ }else{
$('#pocLogTab').attr('style','display:inline') $('#pocLogTab').attr('style','display:inline')
} }

View File

@ -337,7 +337,7 @@
<li lay-id="22">流转过程</li> <li lay-id="22">流转过程</li>
<li lay-id="33">备货信息</li> <li lay-id="33">备货信息</li>
<li lay-id="44">物流信息</li> <li lay-id="44">物流信息</li>
<li lay-id="55">合同信息</li> <!-- <li lay-id="55">合同信息</li>-->
</ul> </ul>
<div class="layui-tab-content"> <div class="layui-tab-content">
<div class="layui-tab-item layui-show"> <div class="layui-tab-item layui-show">

View File

@ -1165,14 +1165,15 @@
function downloadTem() { function downloadTem() {
var xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象
let orderId= $('[name="id"]').val()
if (!$('[name="orderChannel"]').val()) { if (!$('[name="orderChannel"]').val()) {
$.modal.alertWarning("请先选择下单通路"); $.modal.alertWarning("请先选择下单通路");
return return
} }
if ($('[name="orderChannel"]').val() == 1) { if ($('[name="orderChannel"]').val() == 1) {
window.location.href = prefix + "/contract/export?fileName=文件111.xlsx" window.location.href = prefix + "/contract/export?orderId="+orderId
} else { } else {
window.location.href = prefix + "/contract/export?fileName=文件222.xlsx" window.location.href = prefix + "/contract/export?orderId="+orderId
} }
$.modal.closeLoading() $.modal.closeLoading()

View File

@ -399,15 +399,35 @@ public class ProjectOrderInfoController extends BaseController
@GetMapping("/contract/export") @GetMapping("/contract/export")
public void contractExport(String fileName, HttpServletRequest request, HttpServletResponse response) { public void contractExport(@RequestParam(required = false) String fileName,
@RequestParam(required = false) Long orderId,
HttpServletRequest request, HttpServletResponse response) {
try { try {
// 本地资源路径 if (orderId != null) {
// 获取订单信息
ProjectOrderInfo orderInfo = projectOrderInfoService.selectProjectOrderInfoById(orderId);
if (orderInfo == null) {
throw new ServiceException("订单信息不存在");
}
// 新逻辑:生成填充了订单信息的合同模板
byte[] fileBytes = projectOrderInfoService.exportContractTemplate(orderInfo);
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
String downloadFileName = StringUtils.isEmpty(fileName) ? "合同模板_" + orderInfo.getProjectName() + ".docx" : fileName;
FileUtils.setAttachmentResponseHeader(response, downloadFileName);
// 写入响应流
response.getOutputStream().write(fileBytes);
response.getOutputStream().flush();
} else {
// 原逻辑:直接下载模板文件
String localPath = RuoYiConfig.getExcelTemplate(); String localPath = RuoYiConfig.getExcelTemplate();
// 下载名称 String downloadPath = localPath + File.separator + (StringUtils.isEmpty(fileName) ? "orderDownloadTemplate.docx" : fileName);
String downloadPath = localPath + File.separator + fileName;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, fileName); FileUtils.setAttachmentResponseHeader(response, StringUtils.isEmpty(fileName) ? "orderDownloadTemplate.docx" : fileName);
FileUtils.writeBytes(downloadPath, response.getOutputStream()); FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
} catch (Exception e) { } catch (Exception e) {
log.error("下载文件失败", e); log.error("下载文件失败", e);
} }

View File

@ -133,6 +133,7 @@ public class ProjectOrderInfo extends BaseEntity {
private String partnerCode; private String partnerCode;
@Excel(name = "进货商") @Excel(name = "进货商")
private String partnerName; private String partnerName;
private String partnerAddress;
private String projectPartnerName; private String projectPartnerName;
private List<String> productCodeList; private List<String> productCodeList;

View File

@ -71,6 +71,7 @@ public class ProjectProductInfo extends BaseEntity
// @Excel(name = "指导折扣") // @Excel(name = "指导折扣")
private BigDecimal guidanceDiscount; private BigDecimal guidanceDiscount;
private String vendorCode; private String vendorCode;
private String vendorName;
/** 折扣 */ /** 折扣 */
// @Excel(name = "折扣") // @Excel(name = "折扣")

View File

@ -89,4 +89,11 @@ public interface IProjectOrderInfoService
// Boolean foldOnFold(ProjectOrderInfo info); // Boolean foldOnFold(ProjectOrderInfo info);
List<OrderInfoVo> getOrderInfo(ApiDataQueryDto dto); List<OrderInfoVo> getOrderInfo(ApiDataQueryDto dto);
/**
*
* @param orderId ID
* @return
*/
byte[] exportContractTemplate(ProjectOrderInfo orderInfo);
} }

View File

@ -1,6 +1,9 @@
package com.ruoyi.sip.service.impl; package com.ruoyi.sip.service.impl;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
@ -8,6 +11,7 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
@ -19,6 +23,7 @@ import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
@ -46,6 +51,7 @@ import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xwpf.usermodel.*;
import org.flowable.engine.ManagementService; import org.flowable.engine.ManagementService;
import org.flowable.engine.TaskService; import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
@ -58,6 +64,8 @@ import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import static com.ruoyi.common.utils.ShiroUtils.getSysUser; import static com.ruoyi.common.utils.ShiroUtils.getSysUser;
import static com.ruoyi.sip.service.impl.ProjectInfoServiceImpl.*; import static com.ruoyi.sip.service.impl.ProjectInfoServiceImpl.*;
@ -1273,4 +1281,329 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
log.error("处理订单审批通过失败,订单编号:{}", businessKey, e); log.error("处理订单审批通过失败,订单编号:{}", businessKey, e);
} }
} }
@Override
public byte[] exportContractTemplate( ProjectOrderInfo orderInfo) {
try {
// 加载模板文件 - 模板文件位于 ruoyi-admin/src/main/resources/wordTemplate/
String localPath = RuoYiConfig.getExcelTemplate() + File.separator + "orderDownloadTemplate.docx" ;
InputStream templateStream = Files.newInputStream(Paths.get(localPath));
if (templateStream == null) {
throw new ServiceException("模板文件不存在,请确认 wordTemplate/orderDownloadTemplate.docx 文件是否在资源目录中");
}
XWPFDocument document = new XWPFDocument(templateStream);
// 替换文档中的占位符
replaceTextInDocument(document, orderInfo);
// 将文档写入字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.write(baos);
document.close();
templateStream.close();
return baos.toByteArray();
} catch (Exception e) {
log.error("导出合同模板失败", e);
throw new ServiceException("导出合同模板失败: " + e.getMessage());
}
}
private void replaceTextInDocument(XWPFDocument document, ProjectOrderInfo orderInfo) {
// 替换段落中的文本
for (XWPFParagraph paragraph : document.getParagraphs()) {
replaceTextInParagraph(paragraph, orderInfo);
}
// 替换表格中的文本,并处理产品列表
for (XWPFTable table : document.getTables()) {
replaceProductTableContent(table, orderInfo);
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
replaceTextInParagraph(paragraph, orderInfo);
}
}
}
}
}
private void replaceTextInParagraph(XWPFParagraph paragraph, ProjectOrderInfo orderInfo) {
String text = paragraph.getText();
if (text != null && text.contains("${")) {
// 创建替换映射
Map<String, String> replacements = createReplacementMap(orderInfo);
// 替换文本
for (Map.Entry<String, String> entry : replacements.entrySet()) {
String placeholder = "${" + entry.getKey() + "}";
if (text.contains(placeholder)) {
text = text.replace(placeholder, entry.getValue() != null ? entry.getValue() : "");
}
}
// 清除原有运行并设置新文本
for (int i = paragraph.getRuns().size() - 1; i >= 0; i--) {
paragraph.removeRun(i);
}
XWPFRun run = paragraph.createRun();
run.setText(text);
}
}
private Map<String, String> createReplacementMap(ProjectOrderInfo orderInfo) {
Map<String, String> replacements = new HashMap<>();
// 基本订单信息
replacements.put("orderCode", orderInfo.getOrderCode());
replacements.put("projectName", orderInfo.getProjectName());
// 金额信息
replacements.put("shipmentAmount", orderInfo.getShipmentAmount() != null ? orderInfo.getShipmentAmount().toString() : "");
replacements.put("shipmentAmountChinese", orderInfo.getShipmentAmount() != null ?NumberChineseFormatter.format(orderInfo.getShipmentAmount().doubleValue(),true,true) : "");
BigDecimal shipmentAmountNotTax=BigDecimal.ZERO;
BigDecimal taxAmount=BigDecimal.ZERO;
if (orderInfo.getShipmentAmount() != null){
shipmentAmountNotTax = orderInfo.getShipmentAmount().divide(new BigDecimal("1.13"), 2, RoundingMode.HALF_UP);
taxAmount=orderInfo.getShipmentAmount().subtract(shipmentAmountNotTax);
}
replacements.put("shipmentAmountNotTax", shipmentAmountNotTax.toString());
replacements.put("taxAmount", taxAmount.toString());
// 日期信息
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
replacements.put("updateTime", orderInfo.getUpdateTime() != null ? dateFormat.format(orderInfo.getUpdateTime()) : "");
// 责任人信息
replacements.put("dutyName", orderInfo.getDutyName());
replacements.put("dutyPhone", orderInfo.getDutyPhone());
// 进货商信息
replacements.put("partnerName", orderInfo.getPartnerName());
replacements.put("partnerCode", orderInfo.getPartnerCode());
replacements.put("partnerEmail", orderInfo.getPartnerEmail());
replacements.put("partnerUserName", orderInfo.getPartnerUserName());
replacements.put("partnerPhone", orderInfo.getPartnerPhone());
replacements.put("partnerAddress", orderInfo.getPartnerAddress());
// 其他信息
replacements.put("supplier", orderInfo.getSupplier());
replacements.put("paymentMethod", orderInfo.getPaymentMethod());
replacements.put("paymentDescription", orderInfo.getPaymentDescription());
replacements.put("paymentRatio", orderInfo.getPaymentRatio() != null ? orderInfo.getPaymentRatio().toString() : "");
replacements.put("discountFold", orderInfo.getDiscountFold() != null ? orderInfo.getDiscountFold().toString() : "");
replacements.put("paymentMethodNum",(orderInfo.getPaymentMethod()!=null && orderInfo.getPaymentMethod().endsWith("1"))?"1":"3");
replacements.put("paymentDay",(orderInfo.getPaymentMethod()!=null && orderInfo.getPaymentMethod().endsWith("1"))?"3":"");
// 添加产品信息占位符
addProductReplacements(replacements, orderInfo);
return replacements;
}
private void addProductReplacements(Map<String, String> replacements, ProjectOrderInfo orderInfo) {
// 软件产品信息
if (CollUtil.isNotEmpty(orderInfo.getSoftwareProjectProductInfoList())) {
for (int i = 0; i < orderInfo.getSoftwareProjectProductInfoList().size(); i++) {
ProjectProductInfo product = orderInfo.getSoftwareProjectProductInfoList().get(i);
String prefix = "software" + (i + 1);
addSingleProductReplacement(replacements, product, prefix);
}
}
// 硬件产品信息
if (CollUtil.isNotEmpty(orderInfo.getHardwareProjectProductInfoList())) {
for (int i = 0; i < orderInfo.getHardwareProjectProductInfoList().size(); i++) {
ProjectProductInfo product = orderInfo.getHardwareProjectProductInfoList().get(i);
String prefix = "hardware" + (i + 1);
addSingleProductReplacement(replacements, product, prefix);
}
}
// 维保产品信息
if (CollUtil.isNotEmpty(orderInfo.getMaintenanceProjectProductInfoList())) {
for (int i = 0; i < orderInfo.getMaintenanceProjectProductInfoList().size(); i++) {
ProjectProductInfo product = orderInfo.getMaintenanceProjectProductInfoList().get(i);
String prefix = "maintenance" + (i + 1);
addSingleProductReplacement(replacements, product, prefix);
}
}
}
private void addSingleProductReplacement(Map<String, String> replacements, ProjectProductInfo product, String prefix) {
if (product == null) {
return;
}
replacements.put(prefix + "BomCode", product.getProductBomCode());
replacements.put(prefix + "Name", product.getProductName());
replacements.put(prefix + "Model", product.getModel());
replacements.put(prefix + "Code", product.getProductCode());
replacements.put(prefix + "Desc", product.getProductDesc());
replacements.put(prefix + "Quantity", product.getQuantity() != null ? product.getQuantity().toString() : "");
replacements.put(prefix + "CataloguePrice", product.getCataloguePrice() != null ? product.getCataloguePrice().toString() : "");
replacements.put(prefix + "CatalogueAllPrice", product.getCatalogueAllPrice() != null ? product.getCatalogueAllPrice().toString() : "");
replacements.put(prefix + "Price", product.getPrice() != null ? product.getPrice().toString() : "");
replacements.put(prefix + "AllPrice", product.getAllPrice() != null ? product.getAllPrice().toString() : "");
replacements.put(prefix + "AllPriceDisCount", product.getAllPriceDisCount() != null ? product.getAllPriceDisCount().toString() : "");
replacements.put(prefix + "GuidanceDiscount", product.getGuidanceDiscount() != null ? product.getGuidanceDiscount().toString() : "");
replacements.put(prefix + "VendorCode", product.getVendorCode());
replacements.put(prefix + "Discount", product.getDiscount() != null ? product.getDiscount().toString() : "");
replacements.put(prefix + "Type", product.getType());
replacements.put(prefix + "Value", product.getValue());
replacements.put(prefix + "TaxRate", product.getTaxRate() != null ? product.getTaxRate().toString() : "");
}
private void replaceProductTableContent(XWPFTable table, ProjectOrderInfo orderInfo) {
// 查找包含产品占位符的行(如 ${productList} 或 ${softwareList} 等)
for (int rowIndex = 0; rowIndex < table.getRows().size(); rowIndex++) {
XWPFTableRow row = table.getRow(rowIndex);
String rowText = getRowText(row);
// 检查是否包含产品列表占位符
if (rowText.contains("${softwareList}")) {
replaceProductListInTable(table, rowIndex, orderInfo.getSoftwareProjectProductInfoList(), "软件");
} else if (rowText.contains("${hardwareList}")) {
replaceProductListInTable(table, rowIndex, orderInfo.getHardwareProjectProductInfoList(), "硬件");
} else if (rowText.contains("${maintenanceList}")) {
replaceProductListInTable(table, rowIndex, orderInfo.getMaintenanceProjectProductInfoList(), "维保");
} else if (rowText.contains("${productList}")) {
// 处理所有产品的列表
List<ProjectProductInfo> allProducts = new ArrayList<>();
if (CollUtil.isNotEmpty(orderInfo.getSoftwareProjectProductInfoList())) {
allProducts.addAll(orderInfo.getSoftwareProjectProductInfoList());
}
if (CollUtil.isNotEmpty(orderInfo.getHardwareProjectProductInfoList())) {
allProducts.addAll(orderInfo.getHardwareProjectProductInfoList());
}
if (CollUtil.isNotEmpty(orderInfo.getMaintenanceProjectProductInfoList())) {
allProducts.addAll(orderInfo.getMaintenanceProjectProductInfoList());
}
replaceProductListInTable(table, rowIndex, allProducts, "产品");
}
}
}
private String getRowText(XWPFTableRow row) {
StringBuilder text = new StringBuilder();
for (XWPFTableCell cell : row.getTableCells()) {
text.append(cell.getText()).append(" ");
}
return text.toString();
}
private void replaceProductListInTable(XWPFTable table, int templateRowIndex, List<ProjectProductInfo> products, String productType) {
if (CollUtil.isEmpty(products)) {
// 如果没有产品,清空模板行
XWPFTableRow templateRow = table.getRow(templateRowIndex);
clearRow(templateRow);
return;
}
XWPFTableRow templateRow = table.getRow(templateRowIndex);
// 为每个产品创建一行
for (int i = 0; i < products.size(); i++) {
ProjectProductInfo product = products.get(i);
XWPFTableRow productRow;
if (i == 0) {
// 第一个产品使用模板行
productRow = templateRow;
} else {
// 后续产品插入新行
productRow = table.insertNewTableRow(templateRowIndex + i);
copyRowStyle(templateRow, productRow);
}
// 填充产品信息到行中
fillProductRow(productRow, product, i + 1);
}
}
private void clearRow(XWPFTableRow row) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (int i = paragraph.getRuns().size() - 1; i >= 0; i--) {
paragraph.removeRun(i);
}
paragraph.createRun().setText("");
}
}
}
private void copyRowStyle(XWPFTableRow sourceRow, XWPFTableRow targetRow) {
// 确保目标行有足够的单元格
while (targetRow.getTableCells().size() < sourceRow.getTableCells().size()) {
targetRow.createCell();
}
// 复制每个单元格的样式
for (int i = 0; i < sourceRow.getTableCells().size(); i++) {
XWPFTableCell sourceCell = sourceRow.getCell(i);
XWPFTableCell targetCell = targetRow.getCell(i);
// 复制单元格文本和样式
for (XWPFParagraph sourcePara : sourceCell.getParagraphs()) {
XWPFParagraph targetPara = targetCell.addParagraph();
targetPara.setAlignment(sourcePara.getAlignment());
}
}
}
private void fillProductRow(XWPFTableRow row, ProjectProductInfo product, int index) {
List<XWPFTableCell> cells = row.getTableCells();
if (cells.size() >= 7) {
// 假设表格列顺序:序号、产品编码、产品名称、型号、数量、单价、总价
setCellText(cells.get(0), String.valueOf(index));
setCellText(cells.get(1), product.getVendorName());
setCellText(cells.get(2), product.getProductBomCode());
setCellText(cells.get(3), product.getProductDesc());
setCellText(cells.get(4), product.getModel());
setCellText(cells.get(5), product.getQuantity() != null ? product.getQuantity().toString() : "");
setCellText(cells.get(6), product.getPrice() != null ? product.getPrice().toString() : "");
setCellText(cells.get(7), product.getAllPrice() != null ? product.getAllPrice().toString() : "");
}
}
private void setCellText(XWPFTableCell cell, String text) {
// 清除原有内容
for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) {
if (i > 0) { // 保留第一个段落
cell.removeParagraph(i);
}
}
XWPFParagraph paragraph = cell.getParagraphs().get(0);
for (int i = paragraph.getRuns().size() - 1; i >= 0; i--) {
paragraph.removeRun(i);
}
XWPFRun run = paragraph.createRun();
run.setText(text != null ? text : "");
}
} }

View File

@ -57,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description
,t2.project_code,t2.project_name,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time ,t2.project_code,t2.project_name,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time
,t2.customer_phone,t2.customer_user_name,t2.agent_code,t2.customer_code,t2.partner_name project_partner_name ,t2.customer_phone,t2.customer_user_name,t2.agent_code,t2.customer_code,t2.partner_name project_partner_name
,t3.partner_name,t3.level,t3.system_user_id ,t3.partner_name,t3.level,t3.system_user_id,t3.address partner_address
,t4.agent_name ,t4.agent_name
,t5.user_name as duty_name ,t5.user_name as duty_name
from project_order_info t1 from project_order_info t1

View File

@ -27,9 +27,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<sql id="selectProjectProductRelationInfoVo"> <sql id="selectProjectProductRelationInfoVo">
select t1.id, t1.project_id, t1.product_bom_code, t1.model, t1.product_code, t1.product_desc, t1.quantity, t1.catalogue_price, select t1.id, t1.project_id, t1.product_bom_code, t1.model, t1.product_code, t1.product_desc, t1.quantity, t1.catalogue_price,
t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark,t1.tax_rate,t2.type,t2.product_name,t2.vendor_code,t2.value t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark,t1.tax_rate,t2.type,t2.product_name,t2.vendor_code,t2.value,t3.vendor_name
from project_product_info t1 from project_product_info t1
left join product_info t2 on t1.product_bom_code = t2.product_code left join product_info t2 on t1.product_bom_code = t2.product_code
left join oms_vendor_info t3 on t2.vendor_code = t3.vendor_code
</sql> </sql>