fix(bms):科目编码重复致新增账单失败,税率查询按编码+名称取唯一;复制账单改生成新计费流水

- getTaxRate 增加 SUBJECT_NAME 匹配,费用科目编码重复(如1003同时有运输处理费/报关费3)时不再抛 TooManyResultsException,查不到税率兜底0
- addBill、开票/NC推送共4处调用点同步调整;计费流水号为空时只处理自身明细,防空指针
- copyBill 明细清空计费流水id并按原流水映射生成新JFLS流水号,防止复制提交后把原账单的流水改挂到新账单(原账单明细丢失)
- insertAndReturnId 币种空值兜底CNY(与addCost对齐)
This commit is contained in:
rcx
2026-08-19 18:02:23 +08:00
parent b859aa99d3
commit 362f1b5e2f
5 changed files with 58 additions and 18 deletions
@@ -472,7 +472,11 @@ public class BillManageApplicationService {
BeanUtils.copyProperties(billDetailDTO, billingStatementDTO);
String firstSubjectCode = billDetailDTO.getFirstSubjectCode();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
// 科目编码可能重复,按编码+名称取唯一税率;科目删除/停用时兜底0,避免空指针
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode, billDetailDTO.getFirstSubjectName());
if (taxRate == null) {
taxRate = 0.0;
}
BigDecimal amount = billingStatementDTO.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
@@ -484,16 +488,26 @@ public class BillManageApplicationService {
billingStatementDTO.setBillManageId(billManageDO.getBillManageId());
billingStatementDTO.setBillingState(3);
Long billingStatementId = billingStatementApplicationService.insertAndReturnId(billingStatementDTO);
//遍历billDetailDTOList集合,将计费流水号相同的,赋值计费流水id
billDetailDTOList.stream().filter(item -> item.getBillingFlow().equals(billDetailDTO.getBillingFlow())).forEach(item -> {
item.setBillingStatementId(billingStatementId);
item.setBillType(billManageDTO.getBillType());
item.setBillManageId(billManageDO.getBillManageId());
item.setBillNumber(billNumber);
item.setInvoiceItem(item.getFirstSubjectCode());
item.setInvoiceItemName(item.getFirstSubjectName());
item.setFeeType(item.getServiceItemsName());
});
//遍历billDetailDTOList集合,将计费流水号相同的,赋值计费流水id(流水号为空时只处理自身)
if (StringUtils.isNotBlank(billDetailDTO.getBillingFlow())) {
billDetailDTOList.stream().filter(item -> billDetailDTO.getBillingFlow().equals(item.getBillingFlow())).forEach(item -> {
item.setBillingStatementId(billingStatementId);
item.setBillType(billManageDTO.getBillType());
item.setBillManageId(billManageDO.getBillManageId());
item.setBillNumber(billNumber);
item.setInvoiceItem(item.getFirstSubjectCode());
item.setInvoiceItemName(item.getFirstSubjectName());
item.setFeeType(item.getServiceItemsName());
});
} else {
billDetailDTO.setBillingStatementId(billingStatementId);
billDetailDTO.setBillType(billManageDTO.getBillType());
billDetailDTO.setBillManageId(billManageDO.getBillManageId());
billDetailDTO.setBillNumber(billNumber);
billDetailDTO.setInvoiceItem(billDetailDTO.getFirstSubjectCode());
billDetailDTO.setInvoiceItemName(billDetailDTO.getFirstSubjectName());
billDetailDTO.setFeeType(billDetailDTO.getServiceItemsName());
}
}
//同步更新已有计费流水(新增账单时可修改已有费用)
List<BillDetailDTO> billDetailDTOListHasBillingStatementId = billDetailDTOList.stream()
@@ -514,7 +528,11 @@ public class BillManageApplicationService {
BigDecimal allTaxFreeFee = BigDecimal.ZERO;
for (BillDetailDTO item : billDetailDTOList) {
String firstSubjectCode = item.getFirstSubjectCode();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
// 同上:编码+名称取唯一税率,查不到兜底0
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode, item.getFirstSubjectName());
if (taxRate == null) {
taxRate = 0.0;
}
BigDecimal amount = item.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
@@ -584,11 +602,20 @@ public class BillManageApplicationService {
originalBill.setInvoiceMakeTime(null);
originalBill.setNcId(null);
originalBill.setSkNcId(null);
// 明细清空id
// 明细清空id;同时清空计费流水id并按"原流水→新流水"映射生成新流水号,
// 否则提交addBill会走"更新已有流水"分支,把原账单的流水改挂到新账单上(原账单明细丢失)
Map<String, String> flowMapping = new HashMap<>();
for (BillDetailPO detail : originalDetails) {
detail.setBillDetailId(null);
detail.setBillManageId(null);
detail.setBillNumber(null);
detail.setBillingStatementId(null);
String oldFlow = detail.getBillingFlow();
if (StringUtils.isNotBlank(oldFlow)) {
detail.setBillingFlow(flowMapping.computeIfAbsent(oldFlow, k -> OrderSequence.getOrderCode("JFLS")));
} else {
detail.setBillingFlow(null);
}
}
originalBill.setBillDetailPOList(originalDetails);
return originalBill;
@@ -568,6 +568,10 @@ public class BillingStatementApplicationService {
handleDate(billingStatementDO);
billingStatementDO.setDataSources(2);
// 币种为空时兜底CNY(与addCost一致;NC推送时该值作pk_currtype,空值会推送失败)
if (StringUtils.isEmpty(billingStatementDO.getSettlementCurrency())) {
billingStatementDO.setSettlementCurrency("CNY");
}
if(StringUtils.isEmpty(billingStatementDO.getBillingFlow())){
billingStatementDO.setBillingFlow(OrderSequence.getOrderCode("JFLS"));
}
@@ -21,5 +21,5 @@ public interface BillDetailMapper extends BaseMapper<BillDetail>
List<BillDetail> getDetailsByBillManageIdAndGroup(@Param("billManageId") Long billManageId);
Double getTaxRate(@Param("code") String code);
Double getTaxRate(@Param("code") String code, @Param("name") String name);
}
@@ -211,7 +211,11 @@ public class BillManageImpl extends ServiceImpl<BillManageMapper, BillManage> im
BigDecimal allTaxFreeFee = BigDecimal.ZERO;
for (BillDetail item : billDetails) {
String firstSubjectCode = item.getInvoiceItem();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
// 科目编码可能重复,按编码+名称取唯一税率;查不到兜底0,避免空指针
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode, item.getInvoiceItemName());
if (taxRate == null) {
taxRate = 0.0;
}
BigDecimal amount = item.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
@@ -853,7 +857,11 @@ public class BillManageImpl extends ServiceImpl<BillManageMapper, BillManage> im
BigDecimal allTaxFreeFee = BigDecimal.ZERO;
for (BillDetail item : billDetails) {
String firstSubjectCode = item.getInvoiceItem();
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode);
// 科目编码可能重复,按编码+名称取唯一税率;查不到兜底0,避免空指针
Double taxRate = billDetailMapper.getTaxRate(firstSubjectCode, item.getInvoiceItemName());
if (taxRate == null) {
taxRate = 0.0;
}
BigDecimal amount = item.getBillingAmount();
BigDecimal taxAmount = amount.divide(BigDecimal.ONE.add(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))),10, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(taxRate).divide(BigDecimal.valueOf(100))).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal taxFreeFee = amount.subtract(taxAmount);
@@ -49,7 +49,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND bill_manage_id = #{billManageId} GROUP BY INVOICE_ITEM,INVOICE_ITEM_NAME,FEE_TYPE
</select>
<select id="getTaxRate" resultType="java.lang.Double" parameterType="java.lang.String">
<!-- 科目编码存在重复(主数据未做唯一校验,如1003同时有"运输处理费/报关费3"),按编码+名称取唯一一条 -->
<select id="getTaxRate" resultType="java.lang.Double">
SELECT
rate
FROM
@@ -57,7 +58,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE
del_flag = 1
AND SUBJECT_CODE = #{code}
AND SUBJECT_NAME = #{name}
</select>
</mapper>