demand: TMS系统 - 客户账单管理 - 航信开票记录 - 新增加“定制导出” 详细查看附件。

committer: heyu
This commit is contained in:
aike 2025-05-20 17:06:28 +08:00
parent 2a0888cfec
commit 40a30b5cb8
6 changed files with 396 additions and 9 deletions

View File

@ -1,4 +1,3 @@
/**
* @Project: emis
* @Title: EmisSettleInvoiceChRecordController.java
@ -11,15 +10,21 @@
package com.xdadan.erp.web.emis;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.xdadan.erp.emis.domain.EmisSettleInvoiceChRecord;
import com.xdadan.erp.emis.domain.EmisSettleInvoiceChRecordExportVO;
import com.xdadan.erp.emis.domain.EmisSettleInvoiceRecord;
import com.xdadan.erp.emis.domain.EmisWaybill;
import com.xdadan.erp.emis.domain.exception.EmisBizError;
import com.xdadan.erp.emis.service.IEmisSettleInvoiceChRecordService;
import com.xdadan.erp.emis.service.excelCellStrategy.InvoiceExportHelper;
import com.xdadan.erp.emis.service.excelCellStrategy.InvoicePoiExportUtil;
import com.xdadan.erp.emis.utils.WaybillHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -93,11 +98,47 @@ public class EmisSettleInvoiceChRecordController extends BaseController
@PreAuthorize("@ss.hasPermi('emis:emisSettleInvoiceChRecord:export')")
@Log(title = "渠道开票记录表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, EmisSettleInvoiceChRecord emisSettleInvoiceChRecord)
{
List<EmisSettleInvoiceChRecord> list = emisSettleInvoiceChRecordService.selectEmisSettleInvoiceChRecordList(emisSettleInvoiceChRecord);
ExcelUtil<EmisSettleInvoiceChRecord> util = new ExcelUtil<EmisSettleInvoiceChRecord>(EmisSettleInvoiceChRecord.class);
util.exportExcel(response, list, "渠道开票记录表数据");
public void export(HttpServletResponse response, EmisSettleInvoiceChRecord emisSettleInvoiceChRecord) {
List<EmisSettleInvoiceChRecord> list = emisSettleInvoiceChRecordService
.selectEmisSettleInvoiceChRecordList(emisSettleInvoiceChRecord);
List<EmisSettleInvoiceChRecordExportVO> exportList = new ArrayList<>();
for (EmisSettleInvoiceChRecord record : list) {
EmisSettleInvoiceChRecordExportVO vo = new EmisSettleInvoiceChRecordExportVO();
// 开票日期
if (record.getCreateTime() != null) {
vo.setInvoiceDate(new SimpleDateFormat("M月d日").format(record.getCreateTime()));
}
// 公司抬头
vo.setCompanyTitle(InvoiceExportHelper.cleanCompanyTitle(record.getCompanyName()));
// 发票号
vo.setInvoiceNo(record.getInvoiceNo());
// 时间
vo.setSendMonth(record.getSendMonth());
// 开票金额
vo.setOpenMoney(record.getOpenMoney().stripTrailingZeros().toPlainString());
// 开票公司
vo.setInvoiceCompany(InvoiceExportHelper.mapInvoiceCompany(record.getSalerCompanyName()));
// 备注
vo.setRemark(InvoiceExportHelper.processRemark(record));
// 付款日期
vo.setPayDate(InvoiceExportHelper.processPayDate(record.getExportPayDays()));
// 业务员
vo.setSalesmen(record.getSalesmen());
// 快递公司
vo.setExpressCompany(record.getSalesmen());
// 面单单号
vo.setBillCode("1".equals(record.getSettleType()) ? record.getBillCode() : "");
// 结算类型
vo.setSettleType(record.getSettleType());
// 申请备注
vo.setApplyRemark(record.getApplyRemark());
exportList.add(vo);
}
try {
InvoicePoiExportUtil.export(response, exportList);
} catch (Exception e) {
e.printStackTrace();
}
}
/**

View File

@ -134,5 +134,7 @@ public class EmisSettleInvoiceChRecord extends BaseEntity
private String openBillRemark;
// 付款天数
private String payDays;
// 付款日期
private String exportPayDays;
}

View File

@ -0,0 +1,40 @@
package com.xdadan.erp.emis.domain;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class EmisSettleInvoiceChRecordExportVO {
// 开票日期(如5月15日)
private String invoiceDate;
// 公司抬头(去除有限公司/有限责任公司/Co/LTD等)
private String companyTitle;
// 发票号
private String invoiceNo;
// 时间(sendMonth)
private String sendMonth;
// 开票金额
private String openMoney;
// 折让
private BigDecimal discount;
// 赔偿等杂费
private BigDecimal compensation;
// 实际运费
private BigDecimal actualFreight;
// 开票公司(映射)
private String invoiceCompany;
// 备注
private String remark;
// 付款日期
private String payDate;
// 业务员
private String salesmen;
// 快递公司
private String expressCompany;
// 面单单号
private String billCode;
// 结算类型
private String settleType;
// 申请备注
private String applyRemark;
}

View File

@ -0,0 +1,188 @@
package com.xdadan.erp.emis.service.excelCellStrategy;
import com.xdadan.erp.emis.domain.EmisSettleInvoiceChRecord;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashMap;
import java.util.Map;
public class InvoiceExportHelper {
// 公司抬头处理
public static String cleanCompanyTitle(String companyName) {
if (companyName == null)
return "";
// 去除结尾的 Co., CO., LTD, Ltd, co., CO, co, ltd, LTD 等
String result = companyName.replaceAll(
"(?i)[,,\u3001.。;\\s]*(co\\.?|ltd\\.?|co|ltd)[,,\u3001.。;\\s]*(co\\.?|ltd\\.?|co|ltd)?[,,\u3001.。;\\s]*$",
"").trim();
// 去除有限公司和有限责任公司
result = result.replaceAll("(有限公司|有限责任公司)$", "").trim();
return result;
}
// 金额提取
public static BigDecimal extractAmount(String remark, String... keys) {
if (remark == null)
return null;
for (String key : keys) {
Pattern p = Pattern.compile(key + "([\\d\\.]+)");
Matcher m = p.matcher(remark);
if (m.find()) {
try {
BigDecimal val = new BigDecimal(m.group(1));
if (val.compareTo(BigDecimal.ZERO) == 0)
return null;
return val;
} catch (Exception e) {
// ignore
}
}
}
return null;
}
// 开票公司映射(支持不同发票类型)
// 外层key为公司名,内层key为发票类型(1-4),value为开票公司
private static final Map<String, Map<Integer, String>> COMPANY_TYPE_MAP = new HashMap<>();
static {
// 江苏探路者国际物流有限公司
Map<Integer, String> jstlz = new HashMap<>();
jstlz.put(1, "探路者电子专用发票");
jstlz.put(2, "探路者电子发票");
jstlz.put(3, "探路者纸质发票");
jstlz.put(4, "探路者纸质专用发票");
COMPANY_TYPE_MAP.put("江苏探路者国际物流有限公司", jstlz);
// 广西陆陆达国际物流有限公司
Map<Integer, String> gxll = new HashMap<>();
gxll.put(1, "广西陆陆达电子专用发票");
gxll.put(2, "广西陆陆达电子发票");
gxll.put(3, "广西陆陆达纸质发票");
gxll.put(4, "广西陆陆达纸质专用发票");
COMPANY_TYPE_MAP.put("广西陆陆达国际物流有限公司", gxll);
// 探路供应链(上海)有限公司
Map<Integer, String> tls = new HashMap<>();
tls.put(1, "探路供应链(上海)电子专用发票");
tls.put(2, "探路供应链(上海)电子发票");
tls.put(3, "探路供应链(上海)纸质发票");
tls.put(4, "探路供应链(上海)纸质专用发票");
COMPANY_TYPE_MAP.put("探路供应链(上海)有限公司", tls);
// 探路供应链(江苏)有限公司
Map<Integer, String> tlj = new HashMap<>();
tlj.put(1, "探路供应链(江苏)电子专用发票");
tlj.put(2, "探路供应链(江苏)电子发票");
tlj.put(3, "探路供应链(江苏)纸质发票");
tlj.put(4, "探路供应链(江苏)纸质专用发票");
COMPANY_TYPE_MAP.put("探路供应链(江苏)有限公司", tlj);
}
/**
* 根据开票主体和发票类型返回开票公司
*
* @param salerCompanyName 开票主体
* @param invoiceType 发票类型(1-4)
* @return 开票公司
*/
public static String mapInvoiceCompany(String salerCompanyName, int invoiceType) {
if (salerCompanyName == null)
return "";
for (Map.Entry<String, Map<Integer, String>> entry : COMPANY_TYPE_MAP.entrySet()) {
if (salerCompanyName.contains(entry.getKey())) {
String mapped = entry.getValue().get(invoiceType);
if (mapped != null)
return mapped;
}
}
return salerCompanyName;
}
/**
* 兼容旧逻辑,默认按普通发票(数电)类型(2)处理
*/
public static String mapInvoiceCompany(String salerCompanyName) {
return mapInvoiceCompany(salerCompanyName, 2);
}
// 处理备注
public static String processRemark(EmisSettleInvoiceChRecord record) {
String remark = record.getOpenBillRemark();
String applyRemark = record.getApplyRemark();
if (remark == null) {
return "";
}
// 只去除与 LTD 直接相邻的符号
String finalResult = remark.replaceAll(
"(?i)([,,\u3001.。;\\s]*(co\\.?|ltd\\.?|co|ltd)(?![,,\u3001.。;\\s]*$)[,,\u3001.。;\\s]*(co\\.?|ltd\\.?|co|ltd)?[,,\u3001.。;\\s]*)|(?i)\\s+(co\\.?|ltd\\.?|co|ltd)(?![,,\u3001.。;\\s]*$)[,,\u3001.。;\\s]*(co\\.?|ltd\\.?|co|ltd)?[,,\u3001.。;\\s]*|(?i)\\s+(co\\.?|ltd\\.?|co|ltd)$",
"").trim();
// 处理 CO., LTD 这样的组合
finalResult = finalResult.replaceAll("(?i)(CO\\.?\\s*,\\s*LTD\\.?)", "").trim();
finalResult = finalResult.replaceAll("(有限公司|有限责任公司)$", "").trim();
if("2".equals(record.getSettleType())){
return finalResult.replaceAll("-", ",").replaceAll("(\\d+)\\s+", "$1").trim();
}
// 处理多个日期的情况
String[] dateParts = finalResult.split("-");
if (dateParts.length > 0) {
String lastPart = dateParts[dateParts.length - 1].trim();
// 去除日期和公司名之间的空格
lastPart = lastPart.replaceAll("(\\d+)\\s+", "$1");
finalResult = "现金-" + lastPart;
// 只有当applyRemark不为空时才拼接
if (applyRemark != null && !applyRemark.trim().isEmpty()) {
finalResult += "-" + applyRemark;
}
}
return finalResult;
}
// 处理付款日期
public static String processPayDate(String payDate) {
if (payDate == null) {
return "";
}
StringBuilder result = new StringBuilder();
String[] parts = payDate.split(",");
for (int i = 0; i < parts.length; i++) {
String part = parts[i].trim();
String[] dateAndAmount = part.split("-");
if (dateAndAmount.length == 2) {
String datePart = dateAndAmount[0];
String amountPart = dateAndAmount[1];
try {
// 使用BigDecimal去除多余的0
BigDecimal amount = new BigDecimal(amountPart);
amount = amount.stripTrailingZeros();
if (i > 0) {
result.append(",");
}
result.append(datePart).append("-").append(amount.toPlainString());
} catch (NumberFormatException e) {
// 如果金额解析失败,保持原样
if (i > 0) {
result.append(",");
}
result.append(part);
}
} else {
// 如果没有金额部分,保持原样
if (i > 0) {
result.append(",");
}
result.append(part);
}
}
return result.toString();
}
}

View File

@ -0,0 +1,76 @@
package com.xdadan.erp.emis.service.excelCellStrategy;
import com.xdadan.erp.emis.domain.EmisSettleInvoiceChRecordExportVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.List;
public class InvoicePoiExportUtil {
public static void export(HttpServletResponse response, List<EmisSettleInvoiceChRecordExportVO> data)
throws Exception {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("渠道开票记录表");
// 设置行高、字体、边框
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 10);
style.setFont(font);
style.setBorderTop(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
// 表头
String[] headers = { "开票日期", "公司抬头", "发票号", "时间", "开票金额", "开票公司", "备注", "付款日期", "业务员", "快递公司", "面单单号" };
Row headRow = sheet.createRow(0);
headRow.setHeightInPoints(30);
for (int i = 0; i < headers.length; i++) {
Cell cell = headRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(style);
}
// 设置列宽
double[] columnWidths = { 8.38, 31, 34.5, 9.13, 8.75, 22.75, 90.5, 29.13, 8.38, 8.38, 41.5 };
for (int i = 0; i < columnWidths.length; i++) {
sheet.setColumnWidth(i, (int) (columnWidths[i] * 256));
}
// 数据
int rowIdx = 1;
for (EmisSettleInvoiceChRecordExportVO vo : data) {
Row row = sheet.createRow(rowIdx++);
row.setHeightInPoints(30);
int col = 0;
row.createCell(col++).setCellValue(vo.getInvoiceDate());
row.createCell(col++).setCellValue(vo.getCompanyTitle());
row.createCell(col++).setCellValue(vo.getInvoiceNo());
row.createCell(col++).setCellValue(vo.getSendMonth());
row.createCell(col++).setCellValue(vo.getOpenMoney() == null ? "" : vo.getOpenMoney().toString());
row.createCell(col++).setCellValue(vo.getInvoiceCompany());
row.createCell(col++).setCellValue(vo.getRemark());
row.createCell(col++).setCellValue(vo.getPayDate());
row.createCell(col++).setCellValue(vo.getSalesmen());
row.createCell(col++).setCellValue(vo.getExpressCompany());
row.createCell(col++).setCellValue(vo.getBillCode());
for (int i = 0; i < headers.length; i++) {
row.getCell(i).setCellStyle(style);
}
}
// 输出
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=invoice_export.xlsx");
OutputStream os = response.getOutputStream();
wb.write(os);
os.flush();
wb.close();
}
}

View File

@ -47,6 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="settleType" column="settle_type" />
<result property="openBillRemark" column="open_bill_remark" />
<result property="payDays" column="pay_days" />
<result property="exportPayDays" column="export_pay_days" />
<association property="billMonth" column="apply_seq_no" select="com.xdadan.erp.emis.mapper.EmisBaseMapper.selectBillMonthByApplySeqNo"/>
<association property="billCode" column="apply_seq_no" select="com.xdadan.erp.emis.mapper.EmisBaseMapper.selectBillCodeByApplySeqNo"/>
@ -87,7 +88,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
CONCAT(
CONCAT(SUBSTRING(DATE_FORMAT(w.send_date, '%Y'), 3, 2), DATE_FORMAT(w.send_date, '%m ')),
b.cust_name
)
) SEPARATOR '-'
)
FROM emis_waybill w
INNER JOIN emis_settle_invoice_rel ir ON w.bill_code = ir.bill_no
@ -100,7 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
CONCAT(
DATE_FORMAT(w.send_date, '%m%d '),
w.send_company
)
) SEPARATOR '-'
)
FROM emis_waybill w
INNER JOIN emis_settle_invoice_rel ir ON w.bill_code = ir.bill_no
@ -126,7 +127,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
FROM emis_settle_pay_record pr
INNER JOIN emis_settle_pay_bill_rel pbr ON pr.pay_id = pbr.pay_id
INNER JOIN emis_settle_invoice_bill_rel ibr ON ibr.settle_bill_no = pbr.settle_bill_no
WHERE ibr.apply_seq_no = a.apply_seq_no) as pay_days
WHERE ibr.apply_seq_no = a.apply_seq_no) as pay_days,
(SELECT
CASE
WHEN COUNT(*) = 1 THEN
CONCAT(
DATE_FORMAT(pr.trade_date, '%m/%d'),
'已付',
CASE pr.pay_type
WHEN '1' THEN '企业微信'
WHEN '2' THEN '对公'
WHEN '3' THEN '微信支付'
WHEN '4' THEN '支付宝'
WHEN '5' THEN '其他'
WHEN '6' THEN '招行付款'
ELSE pr.pay_type
END
)
ELSE
GROUP_CONCAT(DISTINCT
CONCAT(
DATE_FORMAT(pr.trade_date, '%m/%d'),
'已付',
CASE pr.pay_type
WHEN '1' THEN '企业微信'
WHEN '2' THEN '对公'
WHEN '3' THEN '微信支付'
WHEN '4' THEN '支付宝'
WHEN '5' THEN '其他'
WHEN '6' THEN '招行付款'
ELSE pr.pay_type
END,
'-',
pr.pay_money
)
)
END
FROM emis_settle_pay_record pr
INNER JOIN emis_settle_pay_bill_rel pbr ON pr.pay_id = pbr.pay_id
INNER JOIN emis_settle_invoice_bill_rel ibr ON ibr.settle_bill_no = pbr.settle_bill_no
WHERE ibr.apply_seq_no = a.apply_seq_no) as export_pay_days
FROM emis_settle_invoice_ch_record a
<where>
del_flag='0'