demand: TMS系统 - 运输管理 - 漏组批次统计 - 查询漏组批次统计列表、导出漏组详细数据、导出漏组批次统计查询接口数据支持同时选择多个月份查询/导出 TMS系统 - 客户账单管理 - 发票收款针对相同账单不同发票合并收款特殊逻辑特殊处理

committer: heyu
This commit is contained in:
aike 2025-09-28 16:12:44 +08:00
parent c6c73b0aba
commit 7fd45c391a
5 changed files with 95 additions and 51 deletions

View File

@ -1,10 +1,10 @@
/**
/**
* @Project: emis
* @Title: EmisSettlePayRel.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>
*/
@ -44,6 +44,8 @@ public class EmisSettlePayRel extends BaseEntity
private String billNo;
/* 金额 */
private BigDecimal payMoney;
/* 发票申请序号 */
private String applySeqNo;
// 扩展参数
private EmisWaybill waybillDetail;

View File

@ -5,6 +5,7 @@ import com.xdadan.erp.common.core.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 漏组批次统计查询结果DTO
@ -27,4 +28,10 @@ public class EmisTmsSiteBatchMissStatistics extends BaseEntity {
/** 票数 */
private Integer ticketCount;
/** 多个寄件月份,逗号分隔,例如:2025-06,2025-07 */
private String billMonths;
/** 解析后的月份列表(yyyy-MM) */
private List<String> billMonthList;
}

View File

@ -815,8 +815,8 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
BigDecimal previousRecedMoney = invoiceRecord.getRecedMoney() != null ? invoiceRecord.getRecedMoney()
: BigDecimal.ZERO;
// 计算当前收款记录中与该发票相关的运单收款金额
BigDecimal currentInvoicePayMoney = calculateCurrentInvoicePayment(invoiceRecord, payRelList);
// 计算当前收款记录中与该发票相关的运单收款金额(以applySeqNo关联)
BigDecimal currentInvoicePayMoney = calculateCurrentInvoicePayment(applySeqNo, payRelList);
// 计算新的总收款金额 = 之前的收款金额 + 当前收款金额
BigDecimal totalRecedMoney = previousRecedMoney.add(currentInvoicePayMoney);
@ -847,58 +847,27 @@ public class EmisSettlePayRecordServiceImpl extends EmisBaseService implements I
}
/**
* 计算当前收款记录中与该发票相关的运单收款金额
* 计算当前收款记录中与该发票相关的运单收款金额(按applySeqNo关联)
*
* @param invoiceRecord 发票记录
* @param payRelList 当前收款记录中的运单收款列表
* @param applySeqNo 发票申请序号
* @param payRelList 当前收款记录中的运单收款列表
* @return 当前收款金额
*/
private BigDecimal calculateCurrentInvoicePayment(EmisSettleInvoiceRecord invoiceRecord,
List<EmisSettlePayRel> payRelList) {
private BigDecimal calculateCurrentInvoicePayment(String applySeqNo, List<EmisSettlePayRel> payRelList) {
try {
String settleBillNo = invoiceRecord.getSettleBillNo();
if (StringUtils.isEmpty(settleBillNo)) {
if (StringUtils.isEmpty(applySeqNo) || CollectionUtils.isEmpty(payRelList)) {
return BigDecimal.ZERO;
}
// 处理多个账单号的情况(用逗号分隔)
String[] settleBillNos = settleBillNo.split(",");
Set<String> allBillCodes = new HashSet<>();
for (String billNo : settleBillNos) {
String trimmedBillNo = billNo.trim();
if (StringUtils.isNotEmpty(trimmedBillNo)) {
// 通过账单号找到该账单下的所有运单
List<EmisSettleSubBill> subBillList = emisSettleSubBillMapper
.selectSubBillListBySettleBillNo(trimmedBillNo);
if (CollectionUtils.isNotEmpty(subBillList)) {
// 收集该账单下的所有运单号
Set<String> billCodes = subBillList.stream()
.map(EmisSettleSubBill::getBillCode)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
allBillCodes.addAll(billCodes);
}
}
}
if (allBillCodes.isEmpty()) {
return BigDecimal.ZERO;
}
// 计算当前收款记录中属于该发票相关运单的收款金额
BigDecimal currentPayment = BigDecimal.ZERO;
for (EmisSettlePayRel payRel : payRelList) {
if (payRel.getBillNo() != null && allBillCodes.contains(payRel.getBillNo())
&& payRel.getPayMoney() != null) {
if (applySeqNo.equals(payRel.getApplySeqNo()) && payRel.getPayMoney() != null) {
currentPayment = currentPayment.add(payRel.getPayMoney());
}
}
return currentPayment;
} catch (Exception e) {
log.error("计算当前发票收款金额失败,申请序号: {}", invoiceRecord.getApplySeqNo(), e);
log.error("计算当前发票收款金额失败,申请序号: {}", applySeqNo, e);
return BigDecimal.ZERO;
}
}

View File

@ -46,6 +46,7 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa
@Override
public List<EmisTmsSiteBatchMissStatistics> selectStatisticsList(
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) {
normalizeBillMonths(emisTmsSiteBatchMissStatistics);
log.info("查询漏组批次统计列表,startSiteCode: {}, billMonth: {}",
emisTmsSiteBatchMissStatistics.getStartSiteCode(), emisTmsSiteBatchMissStatistics.getBillMonth());
@ -61,6 +62,7 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa
@Override
public void exportStatisticsData(HttpServletResponse response,
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) {
normalizeBillMonths(emisTmsSiteBatchMissStatistics);
try {
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
@ -240,6 +242,7 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa
@Override
public void exportDetailDataByMonthStream(HttpServletResponse response,
EmisTmsSiteBatchMissStatistics emisTmsSiteBatchMissStatistics) {
normalizeBillMonths(emisTmsSiteBatchMissStatistics);
long startTime = System.currentTimeMillis();
try {
// 设置响应头
@ -446,5 +449,36 @@ public class EmisTmsSiteBatchMissStatisticsServiceImpl implements IEmisTmsSiteBa
}
}
/**
* 归一化 billMonths 到 billMonthList,支持逗号分隔的多月份(yyyy-MM)。
*/
private void normalizeBillMonths(EmisTmsSiteBatchMissStatistics query) {
if (query == null) {
return;
}
if (query.getBillMonthList() != null && !query.getBillMonthList().isEmpty()) {
return;
}
List<String> result = new ArrayList<>();
String months = query.getBillMonths();
if (months != null && months.trim().length() > 0) {
String[] parts = months.split(",");
for (String p : parts) {
if (p != null) {
String v = p.trim();
if (v.length() > 0) {
result.add(v);
}
}
}
}
if (result.isEmpty() && query.getBillMonth() != null) {
synchronized (MONTH_FORMAT) {
result.add(MONTH_FORMAT.format(query.getBillMonth()));
}
}
if (!result.isEmpty()) {
query.setBillMonthList(result);
}
}
}

View File

@ -24,8 +24,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="startSiteCode != null and startSiteCode != ''">
AND bm.start_site_code = #{startSiteCode}
</if>
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
<if test="billMonthList != null and billMonthList.size() &gt; 0">
AND DATE_FORMAT(w.send_date, '%Y-%m') IN
<foreach collection="billMonthList" item="bm" open="(" separator="," close=")">
#{bm}
</foreach>
</if>
<if test="billMonthList == null or billMonthList.size() == 0">
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
</if>
</if>
GROUP BY bm.start_site_code, s.site_name, DATE_FORMAT(w.send_date, '%Y-%m')
ORDER BY w.send_date,bm.start_site_code
@ -68,8 +76,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="startSiteCode != null and startSiteCode != ''">
AND m.start_site_code = #{startSiteCode}
</if>
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
<if test="billMonthList != null and billMonthList.size() &gt; 0">
AND DATE_FORMAT(w.send_date, '%Y-%m') IN
<foreach collection="billMonthList" item="bm" open="(" separator="," close=")">
#{bm}
</foreach>
</if>
<if test="billMonthList == null or billMonthList.size() == 0">
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
</if>
</if>
ORDER BY w.send_date DESC, m.bill_code
</select>
@ -112,8 +128,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.startSiteCode != null and query.startSiteCode != ''">
AND m.start_site_code = #{query.startSiteCode}
</if>
<if test="query.billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{query.billMonth}, '%Y-%m')
<if test="query.billMonthList != null and query.billMonthList.size() &gt; 0">
AND DATE_FORMAT(w.send_date, '%Y-%m') IN
<foreach collection="query.billMonthList" item="bm" open="(" separator="," close=")">
#{bm}
</foreach>
</if>
<if test="query.billMonthList == null or query.billMonthList.size() == 0">
<if test="query.billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{query.billMonth}, '%Y-%m')
</if>
</if>
ORDER BY w.send_date DESC, m.bill_code
LIMIT #{offset}, #{limit}
@ -128,8 +152,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="startSiteCode != null and startSiteCode != ''">
AND m.start_site_code = #{startSiteCode}
</if>
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
<if test="billMonthList != null and billMonthList.size() &gt; 0">
AND DATE_FORMAT(w.send_date, '%Y-%m') IN
<foreach collection="billMonthList" item="bm" open="(" separator="," close=")">
#{bm}
</foreach>
</if>
<if test="billMonthList == null or billMonthList.size() == 0">
<if test="billMonth != null">
AND DATE_FORMAT(w.send_date, '%Y-%m') = DATE_FORMAT(#{billMonth}, '%Y-%m')
</if>
</if>
</select>