demand: TMS系统 - 客户账单管理 - 收款明细查询 - 优化查询性能,通过多线程处理将复杂字段的关联查询性能从5s优化到1s

committer: heyu
This commit is contained in:
aike 2025-09-08 14:37:44 +08:00
parent cc3e27371d
commit e23709bc86
4 changed files with 431 additions and 134 deletions

View File

@ -1,10 +1,10 @@
/**
/**
* @Project: emis
* @Title: EmisSettlePayRecordMapper.java
* @author linfso
* @date 2024-07-21 13:31:24
* @Copyright: ShangHai Doitinfo 2022 All rights reserved.
* @version v1.0
* @version v1.0
* @Description: <p> 账单收退款记录 Mapper 接口 </p>
* <span style='color:red'> Warning : This file is generate by ai tools,don't edit!!! </span>
*/
@ -29,20 +29,19 @@ public interface EmisSettlePayRecordMapper extends BaseMapper<EmisSettlePayRecor
/**
* 主键查询
* @param id
* @return
* @return
*/
public EmisSettlePayRecord selectEmisSettlePayRecordById(Long id);
/**
* 查询列表
*
* @param emisSettlePayRecord
*
* @param emisSettlePayRecord
* @return 集合
*/
public List<EmisSettlePayRecord> selectEmisSettlePayRecordList(EmisSettlePayRecord emisSettlePayRecord);
public Map getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord);
public Map<String, Object> getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord);
public List<EmisSettlePayRecord> selectSettlePayRecordListBySettleBillNo(String settleBillNo);
@ -52,32 +51,32 @@ public interface EmisSettlePayRecordMapper extends BaseMapper<EmisSettlePayRecor
/**
* 检查是否重复
*
* @param emisSettlePayRecord
*
* @param emisSettlePayRecord
* @return 数量
*/
public int checkUnique(EmisSettlePayRecord emisSettlePayRecord);
/**
* 新增
*
* 新增
*
* @param emisSettlePayRecord
* @return
* @return
*/
public int insertEmisSettlePayRecord(EmisSettlePayRecord emisSettlePayRecord);
/**
* 修改
*
* @param emisSettlePayRecord
* @return
*
* @param emisSettlePayRecord
* @return
*/
public int updateEmisSettlePayRecord(EmisSettlePayRecord emisSettlePayRecord);
/**
* 删除
*
*
* @param id 主键
* @return 结果
*/
@ -85,7 +84,7 @@ public interface EmisSettlePayRecordMapper extends BaseMapper<EmisSettlePayRecor
/**
* 批量删除
*
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
@ -98,5 +97,46 @@ public interface EmisSettlePayRecordMapper extends BaseMapper<EmisSettlePayRecor
* @param endTime 结束时间
* @return 每天的已收款金额统计
*/
List<Map<String, Object>> calculateRecedMoney(@Param("beginTime") String beginTime, @Param("endTime") String endTime);
List<Map<String, Object>> calculateRecedMoney(@Param("beginTime") String beginTime,
@Param("endTime") String endTime);
/**
* 根据支付ID列表获取运单号
*
* @param payIds 支付ID列表
* @return 运单号映射
*/
List<Map<String, Object>> getWaybillCodesByPayIds(@Param("list") List<String> payIds);
/**
* 根据支付ID列表获取账单金额
*
* @param payIds 支付ID列表
* @return 账单金额映射
*/
List<Map<String, Object>> getBillAmountsByPayIds(@Param("list") List<String> payIds);
/**
* 根据支付ID列表获取开票金额
*
* @param payIds 支付ID列表
* @return 开票金额映射
*/
List<Map<String, Object>> getInvoiceAmountsByPayIds(@Param("list") List<String> payIds);
/**
* 根据支付ID列表获取开票状态
*
* @param payIds 支付ID列表
* @return 开票状态映射
*/
List<Map<String, Object>> getInvoiceStatusByPayIds(@Param("list") List<String> payIds);
/**
* 根据支付ID列表获取发票申请备注
*
* @param payIds 支付ID列表
* @return 发票申请备注映射
*/
List<Map<String, Object>> getInvoiceRemarksByPayIds(@Param("list") List<String> payIds);
}

View File

@ -1,10 +1,10 @@
/**
/**
* @Project: emis
* @Title: EmisSettlePayRecordService.java
* @author linfso
* @date 2024-07-21 13:31:24
* @Copyright: ShangHai Duta 2022 All rights reserved.
* @version v1.0
* @version v1.0
* @Description: <p> 账单收退款记录 服务类接口 </p>
*/
package com.xdadan.erp.emis.service;
@ -23,24 +23,24 @@ import com.xdadan.erp.emis.domain.stat.PayBackRecordDtl;
* @author linfso
* @date 2024-07-21 13:31:24
*/
public interface IEmisSettlePayRecordService
public interface IEmisSettlePayRecordService
{
/**
* 主键查询
* @param id
* @return
* @return
*/
public EmisSettlePayRecord selectEmisSettlePayRecordById(Long id);
/**
* 查询账单收退款记录列表
*
*
* @param emisSettlePayRecord 账单收退款记录
* @return 账单收退款记录集合
*/
public List<EmisSettlePayRecord> selectEmisSettlePayRecordList(EmisSettlePayRecord emisSettlePayRecord);
public Map getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord);
public Map<String, Object> getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord);
public List<PayBackRecordDtl> queryPayBackRecordList(EmisSettlePayRecord emisSettlePayRecord);
@ -48,15 +48,15 @@ public interface IEmisSettlePayRecordService
/**
* 检查是否重复
*
* @param emisSettlePayRecord
*
* @param emisSettlePayRecord
* @return 数量
*/
public int checkUnique(EmisSettlePayRecord emisSettlePayRecord);
/**
* 新增账单收退款记录
*
*
* @param emisSettlePayRecord 账单收退款记录
* @return 结果
*/
@ -64,7 +64,7 @@ public interface IEmisSettlePayRecordService
/**
* 修改账单收退款记录
*
*
* @param emisSettlePayRecord 账单收退款记录
* @return 结果
*/
@ -72,7 +72,7 @@ public interface IEmisSettlePayRecordService
/**
* 批量删除账单收退款记录
*
*
* @param ids 需要删除的账单收退款记录主键集合
* @return 结果
*/
@ -80,7 +80,7 @@ public interface IEmisSettlePayRecordService
/**
* 删除账单收退款记录信息
*
*
* @param id 账单收退款记录主键
* @return 结果
*/

View File

@ -1,10 +1,10 @@
/**
/**
* @Project: emis
* @Title: EmisSettlePayRecordServiceImpl.java
* @author linfso
* @date 2024-07-21 13:31:24
* @Copyright: ShangHai Duta 2022 All rights reserved.
* @version v1.0
* @version v1.0
* @Description: <p> 账单收退款记录 实体类 </p>
*/
@ -16,6 +16,9 @@ import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.xdadan.erp.emis.domain.*;
import com.xdadan.erp.emis.domain.enumtype.EmisBizErrorType;
@ -24,12 +27,10 @@ import com.xdadan.erp.emis.domain.stat.PayBackRecordDtl;
import com.xdadan.erp.emis.mapper.*;
import com.xdadan.erp.emis.service.EmisBaseService;
import com.xdadan.erp.emis.service.IEmisSettleBillService;
import com.xdadan.erp.emis.service.IEmisSettleSubBillService;
import com.xdadan.erp.emis.utils.WaybillHelper;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -37,14 +38,17 @@ import com.xdadan.erp.emis.service.IEmisSettlePayRecordService;
/**
* 账单收退款记录Service业务层处理
*
*
* @author linfso
* @date 2024-07-21 13:31:24
*/
@Slf4j
@Service
public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements IEmisSettlePayRecordService
{
public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements IEmisSettlePayRecordService {
// 创建线程池用于并行查询
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
@Autowired
private EmisSettlePayRecordMapper emisSettlePayRecordMapper;
@ -57,23 +61,18 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
@Autowired
private EmisSettleBillMapper emisSettleBillMapper;
@Autowired
private EmisSettleSubBillMapper emisSettleSubBillMapper;
@Autowired
private IEmisSettleBillService emisSettleBillService;
@Autowired
private EmisSettleInvoiceRecordMapper emisSettleInvoiceRecordMapper;
@Autowired
private EmisSettlePayInvoiceRelMapper emisSettlePayInvoiceRelMapper;
/**
* 查询账单收退款记录
*
*
* @param id 账单收退款记录主键
* @return 账单收退款记录
*/
@ -83,22 +82,202 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
return emisSettlePayRecordMapper.selectEmisSettlePayRecordById(id);
}
/**
* 查询账单收退款记录列表
*
* 查询账单收退款记录列表(带扩展信息)
*
* @param emisSettlePayRecord 账单收退款记录
* @return 账单收退款记录
*/
@Override
public List<EmisSettlePayRecord> selectEmisSettlePayRecordList(EmisSettlePayRecord emisSettlePayRecord)
{
return emisSettlePayRecordMapper.selectEmisSettlePayRecordList(emisSettlePayRecord);
public List<EmisSettlePayRecord> selectEmisSettlePayRecordList(EmisSettlePayRecord emisSettlePayRecord) {
// 先查询基础数据
List<EmisSettlePayRecord> baseList = emisSettlePayRecordMapper
.selectEmisSettlePayRecordList(emisSettlePayRecord);
if (CollectionUtils.isEmpty(baseList)) {
return baseList;
}
// 提取支付ID列表
List<String> payIds = baseList.stream()
.map(EmisSettlePayRecord::getPayId)
.filter(StringUtils::isNotBlank)
.distinct()
.collect(java.util.stream.Collectors.toList());
if (CollectionUtils.isEmpty(payIds)) {
return baseList;
}
// 并行查询扩展信息
CompletableFuture<Map<String, Object>> waybillCodesFuture = CompletableFuture
.supplyAsync(() -> getWaybillCodesMap(payIds), executorService);
CompletableFuture<Map<String, Object>> billAmountsFuture = CompletableFuture
.supplyAsync(() -> getBillAmountsMap(payIds), executorService);
CompletableFuture<Map<String, Object>> invoiceAmountsFuture = CompletableFuture
.supplyAsync(() -> getInvoiceAmountsMap(payIds), executorService);
CompletableFuture<Map<String, Object>> invoiceStatusFuture = CompletableFuture
.supplyAsync(() -> getInvoiceStatusMap(payIds), executorService);
CompletableFuture<Map<String, Object>> invoiceRemarksFuture = CompletableFuture
.supplyAsync(() -> getInvoiceRemarksMap(payIds), executorService);
try {
// 等待所有查询完成并获取结果
Map<String, Object> waybillCodesMap = waybillCodesFuture.join();
Map<String, Object> billAmountsMap = billAmountsFuture.join();
Map<String, Object> invoiceAmountsMap = invoiceAmountsFuture.join();
Map<String, Object> invoiceStatusMap = invoiceStatusFuture.join();
Map<String, Object> invoiceRemarksMap = invoiceRemarksFuture.join();
// 组装数据
for (EmisSettlePayRecord record : baseList) {
String payId = record.getPayId();
// 设置运单号
if (waybillCodesMap.containsKey(payId)) {
record.setBillCodes((String) waybillCodesMap.get(payId));
}
// 设置账单金额
if (billAmountsMap.containsKey(payId)) {
record.setBillAmount((BigDecimal) billAmountsMap.get(payId));
}
// 设置开票金额
if (invoiceAmountsMap.containsKey(payId)) {
record.setInvoiceAmount((BigDecimal) invoiceAmountsMap.get(payId));
}
// 设置开票状态
if (invoiceStatusMap.containsKey(payId)) {
record.setInvoiceStatus((String) invoiceStatusMap.get(payId));
}
// 设置备注(发票申请备注)
if (invoiceRemarksMap.containsKey(payId)) {
record.setRemark((String) invoiceRemarksMap.get(payId));
}
}
} catch (Exception e) {
log.error("并行查询扩展信息时发生异常", e);
// 如果并行查询失败,回退到串行查询
Map<String, Object> waybillCodesMap = getWaybillCodesMap(payIds);
Map<String, Object> billAmountsMap = getBillAmountsMap(payIds);
Map<String, Object> invoiceAmountsMap = getInvoiceAmountsMap(payIds);
Map<String, Object> invoiceStatusMap = getInvoiceStatusMap(payIds);
Map<String, Object> invoiceRemarksMap = getInvoiceRemarksMap(payIds);
// 组装数据
for (EmisSettlePayRecord record : baseList) {
String payId = record.getPayId();
// 设置运单号
if (waybillCodesMap.containsKey(payId)) {
record.setBillCodes((String) waybillCodesMap.get(payId));
}
// 设置账单金额
if (billAmountsMap.containsKey(payId)) {
record.setBillAmount((BigDecimal) billAmountsMap.get(payId));
}
// 设置开票金额
if (invoiceAmountsMap.containsKey(payId)) {
record.setInvoiceAmount((BigDecimal) invoiceAmountsMap.get(payId));
}
// 设置开票状态
if (invoiceStatusMap.containsKey(payId)) {
record.setInvoiceStatus((String) invoiceStatusMap.get(payId));
}
// 设置备注(发票申请备注)
if (invoiceRemarksMap.containsKey(payId)) {
record.setRemark((String) invoiceRemarksMap.get(payId));
}
}
}
return baseList;
}
/**
* 获取运单号映射
*/
private Map<String, Object> getWaybillCodesMap(List<String> payIds) {
List<Map<String, Object>> waybillCodesList = emisSettlePayRecordMapper.getWaybillCodesByPayIds(payIds);
Map<String, Object> result = new java.util.HashMap<>();
for (Map<String, Object> map : waybillCodesList) {
String payId = (String) map.get("pay_id");
if (payId != null) {
result.put(payId, map.get("bill_codes"));
}
}
return result;
}
/**
* 获取账单金额映射
*/
private Map<String, Object> getBillAmountsMap(List<String> payIds) {
List<Map<String, Object>> billAmountsList = emisSettlePayRecordMapper.getBillAmountsByPayIds(payIds);
Map<String, Object> result = new java.util.HashMap<>();
for (Map<String, Object> map : billAmountsList) {
String payId = (String) map.get("pay_id");
if (payId != null) {
result.put(payId, map.get("rec_money"));
}
}
return result;
}
/**
* 获取开票金额映射
*/
private Map<String, Object> getInvoiceAmountsMap(List<String> payIds) {
List<Map<String, Object>> invoiceAmountsList = emisSettlePayRecordMapper.getInvoiceAmountsByPayIds(payIds);
Map<String, Object> result = new java.util.HashMap<>();
for (Map<String, Object> map : invoiceAmountsList) {
String payId = (String) map.get("pay_id");
if (payId != null) {
result.put(payId, map.get("total_amount"));
}
}
return result;
}
/**
* 获取开票状态映射
*/
private Map<String, Object> getInvoiceStatusMap(List<String> payIds) {
List<Map<String, Object>> invoiceStatusList = emisSettlePayRecordMapper.getInvoiceStatusByPayIds(payIds);
Map<String, Object> result = new java.util.HashMap<>();
for (Map<String, Object> map : invoiceStatusList) {
String payId = (String) map.get("pay_id");
if (payId != null) {
result.put(payId, map.get("status"));
}
}
return result;
}
/**
* 获取发票申请备注映射
*/
private Map<String, Object> getInvoiceRemarksMap(List<String> payIds) {
List<Map<String, Object>> invoiceRemarksList = emisSettlePayRecordMapper.getInvoiceRemarksByPayIds(payIds);
Map<String, Object> result = new java.util.HashMap<>();
for (Map<String, Object> map : invoiceRemarksList) {
String payId = (String) map.get("pay_id");
if (payId != null) {
result.put(payId, map.get("invoice_remark"));
}
}
return result;
}
@Override
public Map getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord)
{
public Map<String, Object> getSettlePayStatInfoMap(EmisSettlePayRecord emisSettlePayRecord) {
return emisSettlePayRecordMapper.getSettlePayStatInfoMap(emisSettlePayRecord);
}
@ -117,8 +296,8 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
/**
* 检查是否重复
*
* @param emisSettlePayRecord
*
* @param emisSettlePayRecord
* @return 数量
*/
@Override
@ -129,7 +308,7 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
/**
* 新增账单收退款记录
*
*
* @param emisSettlePayRecord 账单收退款记录
* @return 结果
*/
@ -310,7 +489,7 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
/**
* 修改账单收退款记录
*
*
* @param emisSettlePayRecord 账单收退款记录
* @return 结果
*/
@ -322,7 +501,7 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
/**
* 批量删除账单收退款记录
*
*
* @param ids 需要删除的账单收退款记录主键
* @return 结果
*/
@ -334,7 +513,7 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
/**
* 删除账单收退款记录信息
*
*
* @param id 账单收退款记录主键
* @return 结果
*/

View File

@ -95,83 +95,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.refund_remark, a.refund_op_man_code, a.refund_register_site_code,
a.refund_register_man_code, a.satisfy_money, a.satisfy_reason, a.allowance_money,
a.allowance_reason, a.deduction_money, a.deduction_reason, a.other_money,
a.other_reason, a.trade_date,
-- 重新赋值备注字段:财务开票备注+账单备注
CONCAT_WS(';',
COALESCE(invoice_remarks.invoice_remark, ''),
COALESCE(bill_remark.remark, '')
) as remark,
a.del_flag, a.create_by, a.create_time, a.update_by, a.update_time, a.create_site, a.update_site,
-- 运单号(多个用逗号分隔)
COALESCE(waybill_codes.bill_codes, '') as bill_codes,
-- 账单金额
COALESCE(bill_amount.rec_money, 0) as bill_amount,
-- 开票金额
COALESCE(invoice_amount.total_amount, 0) as invoice_amount,
-- 开票状态
COALESCE(invoice_status.status, '0') as invoice_status
a.other_reason, a.trade_date, a.remark,
a.del_flag, a.create_by, a.create_time, a.update_by, a.update_time, a.create_site, a.update_site
from emis_settle_pay_record a
-- 关联获取运单号
left join (
select
espbr.pay_id,
GROUP_CONCAT(essb.bill_code SEPARATOR ',') as bill_codes
from emis_settle_pay_bill_rel espbr
left join emis_settle_sub_bill essb on espbr.settle_bill_no = essb.settle_bill_no
where espbr.del_flag = '0' and essb.del_flag = '0'
group by espbr.pay_id
) waybill_codes on a.pay_id = waybill_codes.pay_id
-- 关联获取账单金额
left join (
select
espbr.pay_id,
esb.rec_money
from emis_settle_pay_bill_rel espbr
left join emis_settle_bill esb on espbr.settle_bill_no = esb.settle_bill_no
where espbr.del_flag = '0' and esb.del_flag = '0'
group by espbr.pay_id
) bill_amount on a.pay_id = bill_amount.pay_id
-- 关联获取开票金额
left join (
select
espir.pay_id,
SUM(esir.open_money) as total_amount
from emis_settle_pay_invoice_rel espir
left join emis_settle_invoice_record esir on espir.apply_seq_no = esir.apply_seq_no
where espir.del_flag = '0' and esir.del_flag = '0' and esir.invoice_status = '1'
group by espir.pay_id
) invoice_amount on a.pay_id = invoice_amount.pay_id
-- 关联获取开票状态
left join (
select
espir.pay_id,
esir.invoice_status as status
from emis_settle_pay_invoice_rel espir
left join emis_settle_invoice_record esir on espir.apply_seq_no = esir.apply_seq_no
where espir.del_flag = '0' and esir.del_flag = '0'
group by espir.pay_id
) invoice_status on a.pay_id = invoice_status.pay_id
-- 关联获取财务开票备注
left join (
select
espir.pay_id,
GROUP_CONCAT(esir.invioce_remark SEPARATOR ';') as invoice_remark
from emis_settle_pay_invoice_rel espir
left join emis_settle_invoice_record esir on espir.apply_seq_no = esir.apply_seq_no
where espir.del_flag = '0' and esir.del_flag = '0'
and esir.invioce_remark is not null and esir.invioce_remark != ''
group by espir.pay_id
) invoice_remarks on a.pay_id = invoice_remarks.pay_id
-- 关联获取账单备注
left join (
select
espbr.pay_id,
esb.remark
from emis_settle_pay_bill_rel espbr
left join emis_settle_bill esb on espbr.settle_bill_no = esb.settle_bill_no
where espbr.del_flag = '0' and esb.del_flag = '0'
group by espbr.pay_id
) bill_remark on a.pay_id = bill_remark.pay_id
</sql>
<select id="getSettlePayStatInfoMap" parameterType="EmisSettlePayRecord" resultType="map">
@ -694,4 +620,156 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY
tradeDay
</select>
<!-- 根据支付ID列表获取运单号 -->
<select id="getWaybillCodesByPayIds" parameterType="java.util.List" resultType="map">
select
espbr.pay_id,
GROUP_CONCAT(essb.bill_code SEPARATOR ',') as bill_codes
from emis_settle_pay_bill_rel espbr
left join emis_settle_sub_bill essb on espbr.settle_bill_no = essb.settle_bill_no
where espbr.del_flag = '0' and essb.del_flag = '0'
and espbr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espbr.pay_id
</select>
<!-- 根据支付ID列表获取账单金额 -->
<select id="getBillAmountsByPayIds" parameterType="java.util.List" resultType="map">
select
espbr.pay_id,
esb.rec_money
from emis_settle_pay_bill_rel espbr
left join emis_settle_bill esb on espbr.settle_bill_no = esb.settle_bill_no
where espbr.del_flag = '0' and esb.del_flag = '0'
and espbr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espbr.pay_id
</select>
<!-- 根据支付ID列表获取开票金额 -->
<select id="getInvoiceAmountsByPayIds" parameterType="java.util.List" resultType="map">
select
espr.pay_id,
SUM(esir.apply_money) as total_amount
from emis_settle_pay_record espr
left join emis_settle_invoice_record esir on espr.settle_bill_no = esir.settle_bill_no
where espr.del_flag = '0' and esir.del_flag = '0' and esir.invoice_status = '2'
and espr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espr.pay_id
</select>
<!-- 根据支付ID列表获取开票状态 -->
<select id="getInvoiceStatusByPayIds" parameterType="java.util.List" resultType="map">
select
pay_id,
CONCAT_WS(';',
-- 1. 已开票记录(若存在则拼接,否则为NULL)
GROUP_CONCAT(
CASE WHEN op_date IS NOT NULL THEN -- 只拼接明细行
CONCAT(
DATE_FORMAT(op_date, '%m%d'),
'已开票',
CASE
WHEN total_amount = FLOOR(total_amount) THEN CAST(FLOOR(total_amount) AS CHAR)
ELSE TRIM(TRAILING '0' FROM TRIM(TRAILING '.' FROM CAST(total_amount AS CHAR)))
END,
' ',
company_name
)
END
ORDER BY op_date
SEPARATOR ';'
),
-- 2. 剩余未开金额(从汇总行提取计算)
CASE
WHEN (MAX(bill_amount) - MAX(invoice_amount)) > 0
THEN CONCAT('剩余未开',
CASE
WHEN (MAX(bill_amount) - MAX(invoice_amount)) = FLOOR(MAX(bill_amount) - MAX(invoice_amount))
THEN CAST(FLOOR(MAX(bill_amount) - MAX(invoice_amount)) AS CHAR)
ELSE TRIM(TRAILING '0' FROM TRIM(TRAILING '.' FROM CAST((MAX(bill_amount) - MAX(invoice_amount)) AS CHAR)))
END, '元')
ELSE ''
END
) as status
from (
-- 子查询1:已开票明细行(按日期分组)
select
espr.pay_id,
esir.op_date,
SUM(esir.apply_money) as total_amount,
GROUP_CONCAT(DISTINCT esir.company_name SEPARATOR ' ') as company_name,
0 as total_invoiced_amount, -- 明细行不参与汇总计算
0 as bill_amount,
0 as invoice_amount
from emis_settle_pay_record espr
left join emis_settle_pay_bill_rel espbr on espr.pay_id = espbr.pay_id
left join emis_settle_invoice_record esir on espbr.settle_bill_no = esir.settle_bill_no
where espr.del_flag = '0'
and espbr.del_flag = '0'
and esir.del_flag = '0'
and esir.invoice_status = '2'
and espr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espr.pay_id, esir.op_date
UNION ALL
-- 子查询2:汇总行(计算总开票金额和账单金额)
select
espr.pay_id,
NULL as op_date, -- 汇总行无日期,用于区分
0 as total_amount,
'' as company_name,
SUM(CASE WHEN esir.invoice_status = '2' THEN esir.apply_money ELSE 0 END) as total_invoiced_amount,
MAX(esb.rec_money) as bill_amount,
SUM(CASE WHEN esir.invoice_status = '2' THEN esir.apply_money ELSE 0 END) as invoice_amount
from emis_settle_pay_record espr
left join emis_settle_pay_bill_rel espbr on espr.pay_id = espbr.pay_id
left join emis_settle_bill esb on espbr.settle_bill_no = esb.settle_bill_no
left join emis_settle_invoice_record esir on espbr.settle_bill_no = esir.settle_bill_no
where espr.del_flag = '0'
and espbr.del_flag = '0'
and esb.del_flag = '0'
and esir.del_flag = '0'
and espr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espr.pay_id
) invoice_summary
group by pay_id
</select>
<!-- 根据支付ID列表获取发票申请备注 -->
<select id="getInvoiceRemarksByPayIds" parameterType="java.util.List" resultType="map">
select
espr.pay_id,
GROUP_CONCAT(
CONCAT('(', esir.remark, ')')
SEPARATOR ';'
) as invoice_remark
from emis_settle_pay_record espr
left join emis_settle_invoice_record esir on espr.settle_bill_no = esir.settle_bill_no
where espr.del_flag = '0' and esir.del_flag = '0'
and esir.remark is not null and esir.remark != ''
and esir.invoice_status = '2'
and espr.pay_id in
<foreach collection="list" item="payId" open="(" separator="," close=")">
#{payId}
</foreach>
group by espr.pay_id
</select>
</mapper>