Merge remote-tracking branch 'origin/feature/20261104-bfi-apbill-preentry' into feature/20261104-bfi-project-contract-ref-v2
# Conflicts: # blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeApBillSyncSupport.java # doc/sql/transport/lqj/20261102/23_blade_payment_application_record_kingdee_bill_id_20261104.sql
This commit is contained in:
+2
@@ -1146,6 +1146,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
||||
}
|
||||
record.setPaidDate(this.parseKingdeeDate(payBill.getPaydate()));
|
||||
record.setKingdeeBillNo(billNo);
|
||||
// 金蝶付款处理单内码(cas_paybill.id)落库:财务应付单 preentry 预付抵扣(y_billid)取数用
|
||||
record.setKingdeeBillId(payBill.getId() == null ? null : String.valueOf(payBill.getId()));
|
||||
// 付款处理单查询结果整体留档(凭证号、银行流水、电子回单等信息),便于追溯
|
||||
record.setVoucherJson(JsonUtil.toJson(payBill));
|
||||
if (isNew) {
|
||||
|
||||
+190
-10
@@ -39,26 +39,39 @@ import org.springblade.system.pojo.entity.FeeItem;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillQueryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillSaveDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillSaveEntryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiApBillSavePreEntryDTO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiApBillVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultItemVO;
|
||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiBillSaveResultVO;
|
||||
import org.springblade.thirdparty.bfi.service.IBfiService;
|
||||
import org.springblade.thirdparty.bfi.util.BfiUtil;
|
||||
import org.springblade.thirdparty.bfi.constant.BfiConstant;
|
||||
import org.springblade.transport.config.BfiProperties;
|
||||
import org.springblade.transport.constant.KingdeeBfiConstant;
|
||||
import org.springblade.transport.constant.TransportBusiConstant;
|
||||
import org.springblade.transport.mapper.ContractManageMapper;
|
||||
import org.springblade.transport.mapper.CustomerArchiveMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementSourceMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementSummaryFeeMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationRecordMapper;
|
||||
import org.springblade.transport.mapper.PreSettlementAdvanceMapper;
|
||||
import org.springblade.transport.mapper.ProjectApplyMapper;
|
||||
import org.springblade.transport.mapper.SettlementProjectAdvanceWriteOffMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.CustomerArchive;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSource;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlementSummaryFee;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplicationRecord;
|
||||
import org.springblade.transport.pojo.entity.PreSettlementAdvance;
|
||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||
import org.springblade.transport.pojo.entity.SettlementProjectAdvanceWriteOff;
|
||||
import org.springblade.transport.service.KingdeeSyncContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -73,6 +86,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -86,6 +100,10 @@ import java.util.stream.Collectors;
|
||||
* + 结算合计费用项(手动添加的每行一条);
|
||||
* 物料编码按装卸大类/项目业务模式/运单运输方式映射,编码维护在 Nacos 配置 thirdparty.bfi.material.*(见 {@link #resolveMaterialNumber});
|
||||
* 运输类分录数量取运输量(按税率拆行时每行都取运输量)、装卸类默认 1;单价按结算金额/数量反算。</p>
|
||||
* <p>预付信息分录(preentry,见 {@link #resolvePreEntries}):存在预付款抵扣(进度预付/项目预付核销)时,
|
||||
* 按金蝶付款处理单(cas_paybill)逐笔送出 y_billtype/y_billid/y_settleamt,同 y_billid 合并求和;
|
||||
* 任一笔应抵扣预付无法定位金蝶付款处理单内码(未付款/内码未回写/实付不足)时抛异常拦截应付单推送,
|
||||
* 失败落 kingdee_fail_reason,付款结果回写后由重推任务自动续推。</p>
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@@ -100,6 +118,8 @@ public class KingdeeApBillSyncSupport {
|
||||
private static final int PAY_RESULT_PAGE_SIZE = 200;
|
||||
/** 结算明细行(运费)计费方案匹配费用项(运输类无税率残差组标识用) */
|
||||
private static final String FREIGHT_FEE_ITEM = "运输费";
|
||||
/** 预付抵扣拦截提示最多列出的预付单笔数(超出部分汇总"等N笔",kingdee_fail_reason 列长 500 截断兜底) */
|
||||
private static final int PREPAY_BLOCK_REASON_LIMIT = 3;
|
||||
/** 费用大类编码(业务字典 fee_category 键值):运输 */
|
||||
public static final String FEE_CATEGORY_FREIGHT = "A01";
|
||||
/** 费用大类编码(业务字典 fee_category 键值):装卸 */
|
||||
@@ -138,7 +158,12 @@ public class KingdeeApBillSyncSupport {
|
||||
private final FormalSettlementDetailFeeMapper formalSettlementDetailFeeMapper;
|
||||
private final FormalSettlementSummaryFeeMapper formalSettlementSummaryFeeMapper;
|
||||
private final FormalSettlementMapper formalSettlementMapper;
|
||||
private final FormalSettlementSourceMapper formalSettlementSourceMapper;
|
||||
private final PaymentApplicationMapper paymentApplicationMapper;
|
||||
private final PaymentApplicationRecordMapper paymentApplicationRecordMapper;
|
||||
private final PreSettlementAdvanceMapper preSettlementAdvanceMapper;
|
||||
private final ProjectApplyMapper projectApplyMapper;
|
||||
private final SettlementProjectAdvanceWriteOffMapper projectAdvanceWriteOffMapper;
|
||||
private final ISysClient sysClient;
|
||||
private final BfiProperties bfiProperties;
|
||||
|
||||
@@ -277,7 +302,9 @@ public class KingdeeApBillSyncSupport {
|
||||
* 幂等跳过保存并返回已有单据编号(说明上次同步已保存成功、在后续环节中断,应续推而非拦截报错)。
|
||||
* 明细分录取页面结算明细(每行按 货物→费用大类→税率 拆分)+ 结算合计费用项(每行一条),结算金额逐行直送;
|
||||
* 汇率日期/汇率取结算单页面维护值;付款计划 planentity 暂不传(启用方案见方法内注释),
|
||||
* 当前由金蝶按明细自动汇总生成
|
||||
* 当前由金蝶按明细自动汇总生成;
|
||||
* 预付信息分录 preentry 仅在真正新建应付单时解析(幂等跳过路径不做预付校验),
|
||||
* 每条对应一张金蝶付款处理单(cas_paybill),取数口径见 {@link #resolvePreEntries}
|
||||
*
|
||||
* @param apBillSrcCode 财务应付单防重键(正式结算单号_结算明细单据号拼接)
|
||||
* @param settlement 正式结算单(合同/汇率日期/汇率取数来源)
|
||||
@@ -293,7 +320,7 @@ public class KingdeeApBillSyncSupport {
|
||||
String existBillNo = context.apBillNoCache().computeIfAbsent(apBillSrcCode, code ->
|
||||
queryApBillExistNos(List.of(code)).getOrDefault(code, ""));
|
||||
if (Func.isNotEmpty(existBillNo)) {
|
||||
log.info("正式结算单[{}]金蝶财务应付单已生成(单据编号[{}]),幂等跳过 A102-2 保存", subject, existBillNo);
|
||||
log.info("正式结算单[{}]金蝶财务应付单已生成(单据编号[{}]), 幂等跳过 A102-2 保存", subject, existBillNo);
|
||||
return new BfiApBillPushOutcome(existBillNo, null, true);
|
||||
}
|
||||
ContractManage contract = requireContract(settlement.getContractId(), context);
|
||||
@@ -399,22 +426,175 @@ public class KingdeeApBillSyncSupport {
|
||||
// 付款计划 planentity 暂不传(联调待确认后启用):启用后送正式结算单下绑定、单据状态为审核通过(approved)
|
||||
// 的付款信息,每条付款信息一行,awrp_entry_code_p 取付款单号(A103-1 下推 awrp_finapbill_entryid 勾稽此值);
|
||||
// 当前不传由金蝶按明细自动汇总生成,A103-1 推送前经 A102-4 反查金蝶生成的 awrp_entry_code_p
|
||||
// TODO 待业务确认:存在预付款抵扣时是否需传预付信息 preentry(y_billtype/y_billid/y_settleamt),本期不传、后续迭代
|
||||
// 预付信息分录 preentry:存在预付款抵扣(进度预付/项目预付核销)时按金蝶付款处理单逐笔送出,
|
||||
// 任一笔无法定位金蝶付款处理单内码(未付款/内码未回写/实付不足)时拦截推送(见 resolvePreEntries)
|
||||
List<BfiApBillSavePreEntryDTO> preEntries = this.resolvePreEntries(settlement);
|
||||
if (!preEntries.isEmpty()) {
|
||||
param.setPreentry(preEntries);
|
||||
}
|
||||
|
||||
// 推送入参摘要(联调排查:防重键、分录条数、页面维护的汇率口径)
|
||||
log.info("推送金蝶财务应付单:正式结算单[{}],防重键[{}],明细分录{}条,汇率日期[{}],汇率[{}]",
|
||||
subject, apBillSrcCode, detailentry.size(), param.getExratedate(), param.getExchangerate());
|
||||
log.info("推送金蝶财务应付单: 正式结算单[{}], 防重键[{}], 明细分录{}条, 预付信息{}条, 汇率日期[{}], 汇率[{}]",
|
||||
subject, apBillSrcCode, detailentry.size(), preEntries.size(), param.getExratedate(), param.getExchangerate());
|
||||
|
||||
BfiBillSaveResultVO saveResult = bfiService.saveApBill(param);
|
||||
// 应付单id不落库,后续如需可经 A102-4 按防重键(awrp_src_sys + awrp_src_code)查询
|
||||
requireBfiSaveSuccess(saveResult, "推送金蝶财务应付单");
|
||||
String billNo = saveResult.getResult().get(0).getNumber();
|
||||
log.info("金蝶财务应付单保存成功:正式结算单[{}],单据编号[{}],明细分录{}条", subject, billNo, detailentry.size());
|
||||
log.info("金蝶财务应付单保存成功: 正式结算单[{}], 单据编号[{}], 明细分录{}条", subject, billNo, detailentry.size());
|
||||
// 星瀚应付单内码随结果返回(A902 附件上传定位用)
|
||||
BfiBillSaveResultItemVO savedItem = saveResult.getResult().get(0);
|
||||
return new BfiApBillPushOutcome(savedItem.getNumber(), savedItem.getId() == null ? null : String.valueOf(savedItem.getId()), false);
|
||||
}
|
||||
|
||||
// ==================== 预付信息分录(A102-2 preentry,预付抵扣) ====================
|
||||
|
||||
/**
|
||||
* 解析正式结算单预付信息分录(A102-2 preentry):每条对应一张金蝶付款处理单(cas_paybill),
|
||||
* 项目预付取核销行核销金额、进度预付取预付记录已付金额,按付款处理单实付占比分摊后同 y_billid 合并求和。
|
||||
* 任一笔应抵扣预付无法定位金蝶付款处理单(付款申请不存在/未付款/内码未回写/实付不足)时抛异常拦截应付单推送,
|
||||
* 失败落 kingdee_fail_reason,付款结果回写后由重推任务自动续推
|
||||
*
|
||||
* @param settlement 正式结算单(应付)
|
||||
* @return 预付信息分录列表(按 y_billid 合并后),无预付抵扣返回空列表
|
||||
*/
|
||||
private List<BfiApBillSavePreEntryDTO> resolvePreEntries(FormalSettlement settlement) {
|
||||
// 应抵扣需求按底层付款申请归集:付款申请id -> (本次抵扣金额, 来源描述)
|
||||
Map<Long, BigDecimal> demandAmounts = new LinkedHashMap<>();
|
||||
Map<Long, String> demandSources = new LinkedHashMap<>();
|
||||
// 项目预付:核销行核销金额即本次抵扣金额(核销保存校验已要求预付金蝶已付款)
|
||||
List<SettlementProjectAdvanceWriteOff> writeOffs = this.projectAdvanceWriteOffMapper.selectList(
|
||||
Wrappers.<SettlementProjectAdvanceWriteOff>lambdaQuery()
|
||||
.eq(SettlementProjectAdvanceWriteOff::getSettlementType, TransportBusiConstant.SETTLEMENT_BILL_FORMAL)
|
||||
.eq(SettlementProjectAdvanceWriteOff::getSettlementId, settlement.getId())
|
||||
.eq(SettlementProjectAdvanceWriteOff::getIsDeleted, 0));
|
||||
for (SettlementProjectAdvanceWriteOff writeOff : writeOffs) {
|
||||
if (writeOff.getPaymentApplicationId() == null || this.money(writeOff.getWriteOffAmount()).signum() <= 0) {
|
||||
continue;
|
||||
}
|
||||
demandAmounts.merge(writeOff.getPaymentApplicationId(), this.money(writeOff.getWriteOffAmount()), BigDecimal::add);
|
||||
demandSources.putIfAbsent(writeOff.getPaymentApplicationId(), "项目预付[" + Func.toStr(writeOff.getPaymentNo()) + "]");
|
||||
}
|
||||
// 进度预付:来源预结算的预付记录已付金额即本次抵扣金额(syncOnePreSettlementAdvance 已按预结算关联行分摊)
|
||||
List<FormalSettlementSource> sources = this.formalSettlementSourceMapper.selectList(
|
||||
Wrappers.<FormalSettlementSource>lambdaQuery()
|
||||
.eq(FormalSettlementSource::getFormalSettlementId, settlement.getId())
|
||||
.eq(FormalSettlementSource::getIsDeleted, 0));
|
||||
List<Long> preSettlementIds = sources.stream().map(FormalSettlementSource::getPreSettlementId)
|
||||
.filter(Objects::nonNull).distinct().toList();
|
||||
if (!preSettlementIds.isEmpty()) {
|
||||
List<PreSettlementAdvance> advances = this.preSettlementAdvanceMapper.selectList(
|
||||
Wrappers.<PreSettlementAdvance>lambdaQuery()
|
||||
.in(PreSettlementAdvance::getPreSettlementId, preSettlementIds)
|
||||
.eq(PreSettlementAdvance::getIsDeleted, 0)
|
||||
.ne(PreSettlementAdvance::getBillStatus, TransportBusiConstant.VOIDED));
|
||||
// 预付记录 advanceNo 即付款申请单号,按单号批量定位底层付款申请(避免循环内逐单查询)
|
||||
List<String> advanceNos = advances.stream().map(PreSettlementAdvance::getAdvanceNo)
|
||||
.filter(Func::isNotBlank).distinct().toList();
|
||||
Map<String, PaymentApplication> applicationsByNo = advanceNos.isEmpty() ? Map.of()
|
||||
: this.paymentApplicationMapper.selectList(Wrappers.<PaymentApplication>lambdaQuery()
|
||||
.in(PaymentApplication::getPaymentNo, advanceNos)
|
||||
.eq(PaymentApplication::getIsDeleted, 0))
|
||||
.stream().collect(Collectors.toMap(PaymentApplication::getPaymentNo, Function.identity(),
|
||||
(first, second) -> first));
|
||||
for (PreSettlementAdvance advance : advances) {
|
||||
if (this.money(advance.getPaidAmount()).signum() <= 0) {
|
||||
continue;
|
||||
}
|
||||
PaymentApplication application = applicationsByNo.get(advance.getAdvanceNo());
|
||||
if (application == null) {
|
||||
throw new ServiceException("推送金蝶财务应付单失败:预付单[" + Func.toStr(advance.getAdvanceNo())
|
||||
+ "]不存在付款申请,无法解析预付信息");
|
||||
}
|
||||
demandAmounts.merge(application.getId(), this.money(advance.getPaidAmount()), BigDecimal::add);
|
||||
demandSources.putIfAbsent(application.getId(), "进度预付[" + Func.toStr(advance.getAdvanceNo()) + "]");
|
||||
}
|
||||
}
|
||||
if (demandAmounts.isEmpty()) {
|
||||
// 无预付抵扣(无核销行且预付记录已付金额均为0):不送 preentry,保持报文字段缺省
|
||||
log.info("应付单预付信息归集: 正式结算单[{}], 无预付抵扣, 不送预付信息分录", settlement.getFormalSettlementNo());
|
||||
return List.of();
|
||||
}
|
||||
// 预付抵扣归集摘要(联调排查: 项目预付按核销行、进度预付按预付记录已付金额归集到底层付款申请)
|
||||
log.info("应付单预付信息归集: 正式结算单[{}], 应抵扣付款申请{}笔, 合计金额{}",
|
||||
settlement.getFormalSettlementNo(), demandAmounts.size(),
|
||||
demandAmounts.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
// 批量取付款申请与付款处理记录(仅保留带回金蝶付款处理单内码的记录),逐笔校验并分摊
|
||||
Map<Long, PaymentApplication> applications = this.paymentApplicationMapper.selectBatchIds(demandAmounts.keySet()).stream()
|
||||
.collect(Collectors.toMap(PaymentApplication::getId, Function.identity(), (first, second) -> first));
|
||||
Map<Long, List<PaymentApplicationRecord>> recordsByApplicationId = this.paymentApplicationRecordMapper.selectList(
|
||||
Wrappers.<PaymentApplicationRecord>lambdaQuery()
|
||||
.in(PaymentApplicationRecord::getPaymentApplicationId, demandAmounts.keySet())
|
||||
.eq(PaymentApplicationRecord::getIsDeleted, 0))
|
||||
.stream().filter(record -> Func.isNotBlank(record.getKingdeeBillId()))
|
||||
.collect(Collectors.groupingBy(PaymentApplicationRecord::getPaymentApplicationId));
|
||||
Map<String, BigDecimal> settleAmountsByBillId = new LinkedHashMap<>();
|
||||
Map<String, String> sourcesByBillId = new LinkedHashMap<>();
|
||||
List<String> blockReasons = new ArrayList<>();
|
||||
demandAmounts.forEach((applicationId, demandAmount) -> {
|
||||
String source = demandSources.get(applicationId);
|
||||
PaymentApplication application = applications.get(applicationId);
|
||||
if (application == null) {
|
||||
blockReasons.add(source + "不存在付款申请");
|
||||
return;
|
||||
}
|
||||
List<PaymentApplicationRecord> records = recordsByApplicationId.getOrDefault(applicationId, List.of());
|
||||
if (records.isEmpty()) {
|
||||
blockReasons.add(source + (KingdeeBfiConstant.KINGDEE_STATUS_PAID.equals(application.getKingdeeStatus())
|
||||
? "金蝶付款处理单内码未回写,请先在付款管理执行[同步付款结果]后再推送应付单"
|
||||
: "尚未付款完成,预付须金蝶付款完成后方可抵扣"));
|
||||
return;
|
||||
}
|
||||
BigDecimal recordTotal = records.stream().map(record -> this.money(record.getPaidAmount()))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
if (recordTotal.compareTo(demandAmount) < 0) {
|
||||
blockReasons.add(source + "付款处理单实付金额不足");
|
||||
return;
|
||||
}
|
||||
// 按付款处理单实付占比分摊(末条取剩余补差保证合计精确),同 y_billid 合并求和
|
||||
BigDecimal remaining = demandAmount;
|
||||
for (int index = 0; index < records.size(); index++) {
|
||||
PaymentApplicationRecord record = records.get(index);
|
||||
BigDecimal settleAmount = index == records.size() - 1 ? remaining
|
||||
: demandAmount.multiply(this.money(record.getPaidAmount()))
|
||||
.divide(recordTotal, 2, RoundingMode.HALF_UP)
|
||||
.min(remaining);
|
||||
settleAmount = settleAmount.setScale(2, RoundingMode.HALF_UP);
|
||||
if (settleAmount.signum() <= 0) {
|
||||
continue;
|
||||
}
|
||||
remaining = remaining.subtract(settleAmount);
|
||||
settleAmountsByBillId.merge(record.getKingdeeBillId(), settleAmount, BigDecimal::add);
|
||||
sourcesByBillId.putIfAbsent(record.getKingdeeBillId(), source);
|
||||
}
|
||||
});
|
||||
if (!blockReasons.isEmpty()) {
|
||||
String summary = blockReasons.size() > PREPAY_BLOCK_REASON_LIMIT
|
||||
? String.join(";", blockReasons.subList(0, PREPAY_BLOCK_REASON_LIMIT)) + ";等" + blockReasons.size() + "笔预付无法抵扣"
|
||||
: String.join(";", blockReasons);
|
||||
// 拦截关键日志:原因落盘供排查(异常文案同步落 kingdee_fail_reason,付款结果回写后由重推任务自动续推)
|
||||
log.warn("应付单预付信息校验未通过, 拦截应付单推送: 正式结算单[{}], 应抵扣付款申请{}笔, 原因: {}",
|
||||
settlement.getFormalSettlementNo(), demandAmounts.size(), summary);
|
||||
throw new ServiceException("推送金蝶财务应付单失败:" + summary);
|
||||
}
|
||||
List<BfiApBillSavePreEntryDTO> preEntries = new ArrayList<>();
|
||||
settleAmountsByBillId.forEach((billId, settleAmount) -> {
|
||||
BfiApBillSavePreEntryDTO preEntry = new BfiApBillSavePreEntryDTO();
|
||||
preEntry.setYBilltype(BfiConstant.PREPAY_BILL_TYPE_PAY_BILL);
|
||||
preEntry.setYBillid(billId);
|
||||
preEntry.setYSettleamt(settleAmount);
|
||||
preEntries.add(preEntry);
|
||||
log.info("应付单预付信息分录: 正式结算单[{}], 来源[{}], y_billid={}, y_settleamt={}",
|
||||
settlement.getFormalSettlementNo(), sourcesByBillId.get(billId), billId, settleAmount);
|
||||
});
|
||||
// 分录解析摘要:同一付款申请跨多预结算分摊后落在同一付款处理单的金额已按 y_billid 合并
|
||||
log.info("应付单预付信息解析完成: 正式结算单[{}], 应抵扣付款申请{}笔, 生成分录{}条, 合计金额{}",
|
||||
settlement.getFormalSettlementNo(), demandAmounts.size(), preEntries.size(),
|
||||
preEntries.stream().map(BfiApBillSavePreEntryDTO::getYSettleamt)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
return preEntries;
|
||||
}
|
||||
|
||||
// ==================== 结算明细分录解析(结算明细行 + 结算合计费用项) ====================
|
||||
|
||||
/**
|
||||
@@ -493,7 +673,7 @@ public class KingdeeApBillSyncSupport {
|
||||
+ "]无结算明细与结算合计费用项,无法解析分录");
|
||||
}
|
||||
// 分录解析摘要(联调排查:分录数=结算明细拆分行+手动添加的结算合计费用项,物料/分录标识逐条见下方分录生成日志)
|
||||
log.info("金蝶应付单分录解析完成:正式结算单[{}],结算明细{}条 + 手工结算合计{}条 = 共{}条分录",
|
||||
log.info("金蝶应付单分录解析完成: 正式结算单[{}], 结算明细{}条 + 手工结算合计{}条 = 共{}条分录",
|
||||
settlement.getFormalSettlementNo(), settlementDetails.size(), manualSummaryFees.size(), entryGroups.size());
|
||||
return entryGroups;
|
||||
}
|
||||
@@ -538,7 +718,7 @@ public class KingdeeApBillSyncSupport {
|
||||
context.taxRateByRule(), rowAmount);
|
||||
if (splits.isEmpty()) {
|
||||
// 0元货物行(费用项与结算金额均为0)跳过不生成0元分录
|
||||
log.info("金蝶应付单分录生成:来源[{}],费用项与结算金额均为0,跳过该货物行", sourceDesc);
|
||||
log.info("金蝶应付单分录生成: 来源[{}], 费用项与结算金额均为0, 跳过该货物行", sourceDesc);
|
||||
return;
|
||||
}
|
||||
// 运输类数量:取运单运输量(未维护兜底 1)
|
||||
@@ -720,7 +900,7 @@ public class KingdeeApBillSyncSupport {
|
||||
} catch (RuntimeException ignored) {
|
||||
// 计费方案 JSON 兼容历史数据,解析失败按未配置处理
|
||||
}
|
||||
log.info("合同[{}]计费方案解析:{}项费用类型/费用项配置税率{}", contract.getContractNo(), taxRateByRule.size(), taxRateByRule);
|
||||
log.info("合同[{}]计费方案解析: {}项费用类型/费用项配置税率{}", contract.getContractNo(), taxRateByRule.size(), taxRateByRule);
|
||||
return taxRateByRule;
|
||||
}
|
||||
|
||||
@@ -973,7 +1153,7 @@ public class KingdeeApBillSyncSupport {
|
||||
}
|
||||
loaded.putIfAbsent(feeItem.getName().trim(), feeItem.getFeeCategory().trim());
|
||||
}
|
||||
log.info("费用项档案加载:{}项(费用项名称 -> 费用大类编码)", loaded.size());
|
||||
log.info("费用项档案加载: {}项(费用项名称 -> 费用大类编码)", loaded.size());
|
||||
cache.putAll(loaded);
|
||||
return cache;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user