✨ 付款申请同步接入金蝶付款申请保存接口并记录返回单据id

This commit is contained in:
刘泉佳
2026-09-16 16:51:59 +08:00
parent 3c4425659e
commit afcac91620
@@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
@@ -31,6 +32,11 @@ import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.cache.DictBizCache;
import org.springblade.system.pojo.entity.DictBiz;
import org.springblade.thirdparty.bfi.pojo.dto.BfiPayApplySaveDTO;
import org.springblade.thirdparty.bfi.pojo.dto.BfiPayApplySaveEntryDTO;
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.transport.mapper.FormalSettlementMapper;
import org.springblade.transport.mapper.FormalSettlementPaymentMapper;
import org.springblade.transport.mapper.BillLedgerMapper;
@@ -71,6 +77,7 @@ import org.springblade.transport.service.IPaymentApplicationService;
import org.springblade.transport.service.IFormalSettlementService;
import org.springblade.transport.wrapper.PaymentApplicationWrapper;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
@@ -84,6 +91,7 @@ import java.util.Objects;
import java.util.stream.Collectors;
/** 付款申请服务实现。 @author Chill */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplicationMapper, PaymentApplication>
@@ -93,6 +101,11 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
private static final String APPROVED = "approved";
private static final String RETURNED = "returned";
private static final String VOIDED = "voided";
private static final String BFI_SUPPLIER_ASSTACT_TYPE = "bd_supplier";
private static final String BFI_CONTRACT_SRC_BT = "awrp_contract_info";
private static final String BFI_PROJECT_NUMBER_NONE = "999";
private static final String BFI_PAYMENT_TYPE_FORMAL = "201";
private static final String BFI_PAYMENT_TYPE_PREPAY = "202";
private final PaymentApplicationInvoiceMapper invoiceMapper;
private final PaymentApplicationRecordMapper recordMapper;
private final PaymentApplicationSettlementMapper settlementRelationMapper;
@@ -108,6 +121,19 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
private final BillLedgerUsageMapper billLedgerUsageMapper;
private final TemporaryCreditLimitMapper temporaryCreditLimitMapper;
private final IFormalSettlementService formalSettlementService;
private final IBfiService bfiService;
@Value("${thirdParty.bfi.payApply.srcSys:TMS}")
private String bfiPayApplySrcSys;
@Value("${thirdParty.bfi.payApply.billtype:ap_payapply_BT_S}")
private String bfiPayApplyBilltype;
@Value("${thirdParty.bfi.payApply.orgNumber:}")
private String bfiPayApplyOrgNumber;
@Value("${thirdParty.bfi.payApply.currency:CNY}")
private String bfiPayApplyCurrency;
@Value("${thirdParty.bfi.payApply.exratetable:01}")
private String bfiPayApplyExratetable;
@Value("${thirdParty.bfi.payApply.srcType:TMS付款申请}")
private String bfiPayApplySrcType;
@Override
public IPage<PaymentApplicationVO> selectPage(IPage<PaymentApplication> page, PaymentApplicationVO query) {
@@ -307,15 +333,25 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
PaymentApplication entity = lockedPayment(id);
if (!APPROVED.equals(entity.getApprovalStatus())) throw new ServiceException("仅审批通过的付款申请允许生成金蝶单据");
if ("synced".equals(entity.getKingdeeStatus())) return entity.getKingdeeBillNo();
String no = "FKD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + String.format("%05d", count(Wrappers.<PaymentApplication>lambdaQuery().likeRight(PaymentApplication::getKingdeeBillNo, "FKD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE))) + 1);
entity.setKingdeeBillNo(no);
String kingdeeBillId;
try {
kingdeeBillId = pushBfiPayApply(entity);
} catch (ServiceException exception) {
markSyncFailed(entity);
throw exception;
} catch (Exception exception) {
log.error("付款申请[{}]推送金蝶付款申请单异常", entity.getPaymentNo(), exception);
markSyncFailed(entity);
throw new ServiceException("推送金蝶付款申请失败:" + exception.getMessage());
}
entity.setKingdeeBillNo(kingdeeBillId);
entity.setKingdeeStatus("synced");
entity.setPaidAmount(money(entity.getAppliedAmount()).setScale(2, RoundingMode.HALF_UP));
mockPaymentRecords(entity);
updateById(entity);
syncPreSettlementAdvance(entity);
syncFormalSettlementPayments(entity);
return no;
return kingdeeBillId;
}
@Override
@@ -325,10 +361,106 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
List<Long> distinctIds = ids.stream().filter(Objects::nonNull).distinct().toList();
if (distinctIds.isEmpty()) throw new ServiceException("请至少选择一条审批通过的付款申请");
List<String> result = new ArrayList<>();
for (Long id : distinctIds) result.add(syncKingdee(id));
for (Long id : distinctIds) {
try {
result.add(syncKingdee(id));
} catch (Exception exception) {
result.add("付款申请[" + id + "]同步失败:" + exception.getMessage());
}
}
return result;
}
/**
* 推送金蝶付款申请单(A103-3 付款申请保存),返回金蝶单据id
*
* @param entity 付款申请实体
* @return 金蝶付款申请单id
*/
private String pushBfiPayApply(PaymentApplication entity) {
if (Func.isBlank(bfiPayApplyOrgNumber)) throw new ServiceException("推送金蝶付款申请失败,请配置thirdParty.bfi.payApply.orgNumber");
String applyDateText = (entity.getApplyDate() == null ? LocalDate.now() : entity.getApplyDate()).format(DateTimeFormatter.BASIC_ISO_DATE);
BigDecimal applyAmount = money(entity.getAppliedAmount()).setScale(2, RoundingMode.HALF_UP);
BfiPayApplySaveDTO param = new BfiPayApplySaveDTO();
param.setAwrpSrcCode(entity.getPaymentNo());
param.setAwrpSrcSys(bfiPayApplySrcSys);
param.setSettleorgNumber(bfiPayApplyOrgNumber);
param.setBilltypeNumber(bfiPayApplyBilltype);
param.setApplydate(applyDateText);
param.setApplyorgNumber(bfiPayApplyOrgNumber);
param.setPayorgNumber(bfiPayApplyOrgNumber);
param.setPurorgNumber(bfiPayApplyOrgNumber);
param.setApplycause(bfiApplyCause(entity.getPaymentType()));
param.setPaycurrencyNumber(bfiPayApplyCurrency);
param.setSettlecurrencyNumber(bfiPayApplyCurrency);
param.setAwrpSrcType(bfiPayApplySrcType);
param.setExratetableNumber(bfiPayApplyExratetable);
param.setExratedate(applyDateText);
param.setAwrpTextfield1(bfiPaymentMethodLabel(entity.getPaymentMethod()));
if (entity.getContractId() != null) {
param.setAwrpSrcBt(BFI_CONTRACT_SRC_BT);
param.setAwrpSrcConNo(entity.getContractNo());
}
BfiPayApplySaveEntryDTO entry = new BfiPayApplySaveEntryDTO();
entry.setEPaymenttypeNumber("settlement_payment".equals(entity.getPaymentType()) ? BFI_PAYMENT_TYPE_FORMAL : BFI_PAYMENT_TYPE_PREPAY);
entry.setEAsstacttype(BFI_SUPPLIER_ASSTACT_TYPE);
entry.setEAsstactNumber(bfiSupplierCode(entity));
entry.setEAssacct(entity.getBankAccount());
entry.setEBebankNumber(entity.getBankName());
entry.setEPayamount(applyAmount);
entry.setEApplyamount(applyAmount);
entry.setEExpaydate(applyDateText);
entry.setProjectNumber(bfiProjectNumber(entity));
entry.setAwrpEntryCode(entity.getPaymentNo() + "-1");
entry.setERemark(entity.getRemark());
param.setEntry(List.of(entry));
BfiBillSaveResultVO saveResult = bfiService.savePrePayApply(param);
if (saveResult == null || Func.isEmpty(saveResult.getResult())) {
throw new ServiceException("推送金蝶付款申请失败,金蝶未返回单据结果");
}
BfiBillSaveResultItemVO item = saveResult.getResult().get(0);
if (!Boolean.TRUE.equals(item.getBillStatus()) || item.getId() == null) {
String errorText = Func.isEmpty(item.getErrors()) ? "未知错误" : String.join(";", item.getErrors());
throw new ServiceException("推送金蝶付款申请失败:" + errorText);
}
return String.valueOf(item.getId());
}
private void markSyncFailed(PaymentApplication entity) {
entity.setKingdeeStatus("failed");
updateById(entity);
}
private String bfiApplyCause(String paymentType) {
return switch (paymentType == null ? "" : paymentType) {
case "project_advance" -> "项目预付款申请";
case "progress_advance" -> "进度预付款申请";
case "settlement_payment" -> "结算付款申请";
default -> "付款申请";
};
}
private String bfiPaymentMethodLabel(String paymentMethod) {
if (Func.isEmpty(paymentMethod)) return null;
return DictBizCache.getList("pay_method").stream()
.filter(item -> paymentMethod.equals(item.getDictKey()) || paymentMethod.equals(item.getDictValue()))
.map(DictBiz::getDictValue).findFirst().orElse(paymentMethod);
}
private String bfiSupplierCode(PaymentApplication entity) {
if (Func.isEmpty(entity.getPayeeName())) throw new ServiceException("推送金蝶付款申请失败,收款方不能为空");
CustomerArchive customer = customerArchiveMapper.selectOne(Wrappers.<CustomerArchive>lambdaQuery()
.and(wrapper -> wrapper.eq(CustomerArchive::getFullName, entity.getPayeeName()).or().eq(CustomerArchive::getShortName, entity.getPayeeName()))
.eq(CustomerArchive::getIsDeleted, 0).last("limit 1"));
return customer == null || Func.isEmpty(customer.getCustomerCode()) ? entity.getPayeeName() : customer.getCustomerCode();
}
private String bfiProjectNumber(PaymentApplication entity) {
if (entity.getProjectId() == null) return BFI_PROJECT_NUMBER_NONE;
ProjectApply project = projectApplyMapper.selectById(entity.getProjectId());
return project == null || Func.isEmpty(project.getProjectCode()) ? BFI_PROJECT_NUMBER_NONE : project.getProjectCode();
}
private void mockPaymentRecords(PaymentApplication entity) {
recordMapper.delete(Wrappers.<PaymentApplicationRecord>lambdaQuery()
.eq(PaymentApplicationRecord::getPaymentApplicationId, entity.getId()));