feat(project): 新增订单财务数据导出功能

- 在IProjectOrderInfoService接口中添加financeExport方法
- 在ProjectOrderInfoServiceImpl中实现financeExport方法,支持导出两个sheet
- 第一个sheet包含订单数据明细,第二个sheet包含产品数据
- 更新前端页面导出URL指向新的财务导出接口
- 新增财务导出接口/controller方法,权限控制与原有导出一致
dev_1.0.0
chenhao 2025-10-30 14:38:51 +08:00
parent ecff189fe2
commit ad219353c6
4 changed files with 257 additions and 6 deletions

View File

@ -214,7 +214,7 @@
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
exportUrl: prefix + "/finance/export",
modalName: "订单管理",
fixedColumns: true,
sortable: true,

View File

@ -180,6 +180,18 @@ public class ProjectOrderInfoController extends BaseController
return AjaxResult.success(projectOrderInfoService.exportList(projectOrderInfo));
}
/**
*
*/
@RequiresPermissions("project:order:export")
@Log(title = "订单管理", businessType = BusinessType.EXPORT)
@PostMapping("/finance/export")
@ResponseBody
public AjaxResult financeExport(ProjectOrderInfo projectOrderInfo)
{
return AjaxResult.success(projectOrderInfoService.financeExport(projectOrderInfo));
}
/**
*

View File

@ -100,4 +100,7 @@ public interface IProjectOrderInfoService
List<ProjectOrderInfo> listByCodeList(List<String> businessKeyList);
void updateFinance(ProjectOrderInfo projectOrderInfo);
String financeExport(ProjectOrderInfo projectOrderInfo);
}

View File

@ -16,14 +16,16 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.bigdecimal.BigDecimalNumberConverter;
import com.alibaba.excel.converters.string.StringNumberConverter;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.config.RuoYiConfig;
@ -34,15 +36,12 @@ import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.ApiDataQueryDto;
import com.alibaba.fastjson.JSONArray;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.dto.HomepageQueryDto;
import com.ruoyi.sip.dto.OrderExcelNumStaticsDto;
import com.ruoyi.sip.dto.StatisticsDetailDto;
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
import com.ruoyi.sip.mapper.OmsStockInfoMapper;
import com.ruoyi.sip.mapper.ProjectInfoMapper;
import com.ruoyi.sip.service.*;
@ -1470,6 +1469,243 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
projectOrderInfoMapper.updateProjectOrderInfo(projectOrderInfo);
}
@Override
public String financeExport(ProjectOrderInfo projectOrderInfo) {
try {
// 获取项目信息列表
List<ProjectOrderInfo> projectInfos = fetchProjectInfos(projectOrderInfo);
// 补充项目详细数据
enrichProjectData(projectInfos);
ExcelUtil<ProjectInfo> util = new ExcelUtil<>(ProjectInfo.class);
String fileName = util.encodingFilename("订单数据汇总");
String filePath = util.getAbsoluteFile(fileName);
ExcelWriter excelWriter = EasyExcel.write(filePath).registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)).build();
try {
// 准备第一个sheet的数据
List<List<Object>> data1 = generateData1(projectInfos);
List<List<String>> head1 = generateHead1();
// 创建第一个sheet
WriteSheet writeSheet1 = EasyExcel.writerSheet(0, "订单数据明细")
.build();
// 创建第一个表格(可以理解为数据区域)
WriteTable writeTable1 = EasyExcel.writerTable(0)
.head(head1)
.build();
// 写入第一个sheet
excelWriter.write(data1, writeSheet1, writeTable1);
// 准备第二个sheet的数据
List<List<Object>> data2 = generateData2(projectInfos);
List<List<String>> head2 = generateHead2();
// 创建第二个sheet
WriteSheet writeSheet2 = EasyExcel.writerSheet(1, "产品数据")
.build();
// 创建第二个表格
WriteTable writeTable2 = EasyExcel.writerTable(1)
.head(head2)
.build();
// 写入第二个sheet
excelWriter.write(data2, writeSheet2, writeTable2);
} finally {
if (excelWriter != null) {
excelWriter.finish();
}
}
return fileName;
} catch (Exception e) {
log.error("导出项目信息失败", e);
throw new ServiceException("导出项目信息失败,请稍后重试");
}
}
/**
* sheet
*
* @return
*/
private List<List<Object>> generateData1(List<ProjectOrderInfo> projectInfos) {
List<List<Object>> dataList = new ArrayList<>();
for (ProjectOrderInfo info : projectInfos) {
List<Object> row = new ArrayList<>();
// 添加基础字段
row.add(info.getProjectCode());
row.add(info.getProjectName());
row.add(info.getOrderCode());
row.add(StringUtils.isEmpty(info.getOrderChannel()) ? "" :
ProjectOrderInfo.OrderChannelEnum.TOTAL_GENERATION.getCode().equals(info.getOrderChannel()) ? "总代" : "直签");
row.add(info.getSupplier());
row.add(info.getPartnerName());
row.add(info.getShipmentAmount() != null ? info.getShipmentAmount() : "");
row.add(info.getDiscountFold());
BigDecimal softPrice = info.getSoftwareProjectProductInfoList() == null ? BigDecimal.ZERO :
info.getSoftwareProjectProductInfoList().stream().map(ProjectProductInfo::getAllPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal hardPrice = info.getHardwareProjectProductInfoList() == null ? BigDecimal.ZERO :
info.getHardwareProjectProductInfoList().stream().map(ProjectProductInfo::getAllPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal mainPrice = info.getMaintenanceProjectProductInfoList() == null ? BigDecimal.ZERO :
info.getMaintenanceProjectProductInfoList().stream().map(ProjectProductInfo::getAllPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
row.add(softPrice.add(hardPrice).add(mainPrice));
row.add(softPrice);
row.add(hardPrice);
row.add(mainPrice);
row.add(DateUtil.format(info.getApproveTime(), "yyyy-MM-dd HH:mm:ss"));
row.add(DateUtil.format(info.getOrderEndTime(), "yyyy-MM-dd"));
row.add(info.getAgentName());
row.add(info.getDutyName());
row.add(info.getCustomerName());
row.add(DictUtils.getDictLabel("bg_type", info.getBgProperty()));
row.add(info.getIndustryType());
row.add(info.getProjectPartnerName());
row.add(info.getBusinessPerson());
// row.add(info.getBusinessEmail());
row.add(info.getBusinessPhone());
row.add(DictUtils.getDictLabel("currency_type", info.getCurrencyType()));
row.add(DictUtils.getDictLabel("identify_level", info.getLevel()));
row.add(info.getPartnerUserName());
// row.add(info.getPartnerEmail());
row.add(info.getPartnerPhone());
dataList.add(row);
}
return dataList;
}
/**
* sheet
*
* @return
*/
private List<List<String>> generateHead1() {
List<List<String>> headerList = new ArrayList<>();
headerList.add(Collections.singletonList("项目编号"));
headerList.add(Collections.singletonList("项目名称"));
headerList.add(Collections.singletonList("合同编号"));
headerList.add(Collections.singletonList("下单通路"));
headerList.add(Collections.singletonList("供货商"));
headerList.add(Collections.singletonList("进货商"));
headerList.add(Collections.singletonList("总价合计"));
headerList.add(Collections.singletonList("商务折扣"));
headerList.add(Collections.singletonList("折后总价合计"));
headerList.add(Collections.singletonList("软件折后小计"));
headerList.add(Collections.singletonList("硬件折后小计"));
headerList.add(Collections.singletonList("服务折后小计"));
headerList.add(Collections.singletonList("归档时间"));
headerList.add(Collections.singletonList("执行单截至时间"));
headerList.add(Collections.singletonList("代表处"));
headerList.add(Collections.singletonList("汇智责任人"));
headerList.add(Collections.singletonList("最终客户"));
headerList.add(Collections.singletonList("BG"));
headerList.add(Collections.singletonList("行业"));
headerList.add(Collections.singletonList("运作方"));
headerList.add(Collections.singletonList("进货商接口人"));
// headerList.add(Collections.singletonList("Email"));
headerList.add(Collections.singletonList("联系方式"));
headerList.add(Collections.singletonList("币种"));
// headerList.add(Collections.singletonList("要求到货时间"));
// headerList.add(Collections.singletonList("公司直发"));
// headerList.add(Collections.singletonList("供货商"));
// headerList.add(Collections.singletonList("Email"));
// headerList.add(Collections.singletonList("联系方式"));
// headerList.add(Collections.singletonList("进货商代码"));
headerList.add(Collections.singletonList("进货商类型"));
headerList.add(Collections.singletonList("进货商联系人"));
// headerList.add(Collections.singletonList("Email"));
headerList.add(Collections.singletonList("联系方式"));
// headerList.add(Collections.singletonList("其他特别说明"));
// headerList.add(Collections.singletonList("订单状态"));
return headerList;
}
/**
* sheet
*
* @return
*/
private List<List<Object>> generateData2(List<ProjectOrderInfo> projectInfos) {
List<List<Object>> data = new ArrayList<>();
for (ProjectOrderInfo orderInfo : projectInfos) {
fillProductFinanceData(orderInfo, "软件", data, orderInfo.getSoftwareProjectProductInfoList());
fillProductFinanceData(orderInfo, "硬件", data, orderInfo.getHardwareProjectProductInfoList());
fillProductFinanceData(orderInfo, "服务", data, orderInfo.getMaintenanceProjectProductInfoList());
}
return data;
}
private static void fillProductFinanceData(ProjectOrderInfo orderInfo, String type, List<List<Object>> data, List<ProjectProductInfo> productInfoList) {
if (CollUtil.isNotEmpty(productInfoList)) {
for (ProjectProductInfo productInfo : productInfoList) {
List<Object> row = new ArrayList<>();
row.add(orderInfo.getProjectCode());
row.add(type);
row.add(productInfo.getProductBomCode());
row.add(productInfo.getModel());
row.add(productInfo.getProductDesc());
row.add(productInfo.getQuantity() == null ? "" : productInfo.getQuantity());
row.add(productInfo.getCataloguePrice() == null ? "" : productInfo.getCataloguePrice());
row.add(productInfo.getDiscount() == null ? "" : productInfo.getDiscount());
row.add(productInfo.getPrice() == null ? "" : productInfo.getPrice());
row.add(orderInfo.getDiscountFold() == null ? "" : orderInfo.getDiscountFold());
row.add(productInfo.getAllPrice() == null ? "" : productInfo.getAllPrice());
row.add(productInfo.getTaxRate() == null ? "" : productInfo.getTaxRate());
data.add(row);
}
}
}
/**
* sheet
*
* @return
*/
private List<List<String>> generateHead2() {
List<List<String>> headerList = new ArrayList<>();
headerList.add(Collections.singletonList("项目编号"));
headerList.add(Collections.singletonList("产品类型"));
headerList.add(Collections.singletonList("产品编码"));
headerList.add(Collections.singletonList("产品型号"));
headerList.add(Collections.singletonList("描述"));
headerList.add(Collections.singletonList("数量"));
headerList.add(Collections.singletonList("目录单价(¥)"));
headerList.add(Collections.singletonList("折扣"));
headerList.add(Collections.singletonList("单价(¥)"));
headerList.add(Collections.singletonList("商务折扣"));
headerList.add(Collections.singletonList("折后总价(¥)"));
headerList.add(Collections.singletonList("税率(%)"));
return headerList;
}
private void replaceTextInDocument(XWPFDocument document, ProjectOrderInfo orderInfo) {
// 替换段落中的文本
for (XWPFParagraph paragraph : document.getParagraphs()) {