feat: 查看页重推认领收票单并校验匹配金额
This commit is contained in:
+3
@@ -43,4 +43,7 @@ public class FormalSettlementInvoice extends TenantEntity {
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "收票单金蝶推送状态(unsynced未推送/pushed已保存收票单/assigned已指定应付/failed推送失败),详情回显用")
|
||||
private String kingdeePushStatus;
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "收票单金蝶推送失败原因(详情失败行悬浮展示用)")
|
||||
private String kingdeePushMsg;
|
||||
}
|
||||
|
||||
+7
@@ -239,6 +239,13 @@ public class FormalSettlementController extends BladeController {
|
||||
return R.data(formalSettlementService.pushInvoiceAssignKingdee(id));
|
||||
}
|
||||
|
||||
@PostMapping("/repush-claimed-invoice")
|
||||
@ApiOperationSupport(order = 16)
|
||||
@Operation(summary = "重推认领收票单(查看页入口:收票单A303-2+指定应付A302-6 一步式,failed/pushed 通吃)")
|
||||
public R<String> repushClaimedInvoice(@RequestParam Long id, @RequestParam String invoiceNo) {
|
||||
return R.data(formalSettlementService.repushClaimedInvoice(id, invoiceNo));
|
||||
}
|
||||
|
||||
@PostMapping("/sync-kingdee-ar-result")
|
||||
@ApiOperationSupport(order = 15)
|
||||
@Operation(summary = "手动勾稽金蝶应收单(A302-4 回写纠偏)")
|
||||
|
||||
+11
@@ -72,6 +72,17 @@ public interface IFormalSettlementService extends BaseService<FormalSettlement>
|
||||
*/
|
||||
String pushInvoiceAssignKingdee(Long settlementId);
|
||||
|
||||
/**
|
||||
* 重推本单认领的收票登记(查看页「重新推送」入口,failed/pushed 通吃,assigned 拦截):
|
||||
* 前置付款结算单 + 审批通过 + 财务应付单已同步;先复用收票推送状态机重推金蝶收票单(A303-2,
|
||||
* A801-3 幂等预检防重复保存),再组装应付单防重键逐单 A302-6 指定应付(幂等)
|
||||
*
|
||||
* @param id 正式结算单id
|
||||
* @param invoiceNo 认领发票号
|
||||
* @return 重推结果描述
|
||||
*/
|
||||
String repushClaimedInvoice(Long id, String invoiceNo);
|
||||
|
||||
/**
|
||||
* 独立事务落"生成失败"状态并记失败原因(在推送事务回滚、行锁释放后执行,与付款/收票口径统一);
|
||||
* 仅更新审批通过且未同步的单据,未审批/已同步/已删除单据自动跳过,保持原状态
|
||||
|
||||
+69
@@ -488,6 +488,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
InvoiceReceipt receipt = receiptByInvoiceNo.get(invoice.getInvoiceNo());
|
||||
if (receipt != null) {
|
||||
invoice.setKingdeePushStatus(receipt.getKingdeePushStatus());
|
||||
invoice.setKingdeePushMsg(receipt.getKingdeePushMsg());
|
||||
}
|
||||
}
|
||||
for (int index = 0; index < invoices.size(); index++) {
|
||||
@@ -1103,6 +1104,65 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
return "发票登记推送金蝶成功:认领收票单已指定应付";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String repushClaimedInvoice(Long id, String invoiceNo) {
|
||||
FormalSettlement settlement = lockedExisting(id);
|
||||
if (!"payable".equals(settlement.getSettlementType())) {
|
||||
throw new ServiceException("仅付款结算单允许重推认领收票单");
|
||||
}
|
||||
if (!TransportBusiConstant.APPROVED.equals(settlement.getApprovalStatus())) {
|
||||
throw new ServiceException("仅审批通过的付款结算单允许重推认领收票单");
|
||||
}
|
||||
if (!KingdeeBfiConstant.KINGDEE_STATUS_SYNCED.equals(settlement.getKingdeeSyncStatus())) {
|
||||
throw new ServiceException("请先同步金蝶财务应付单后再重推认领收票单");
|
||||
}
|
||||
String trimmedInvoiceNo = requiredText(invoiceNo, "发票号");
|
||||
InvoiceReceipt receipt = invoiceReceiptMapper.selectOne(Wrappers.<InvoiceReceipt>lambdaQuery()
|
||||
.eq(InvoiceReceipt::getInvoiceNo, trimmedInvoiceNo).last("LIMIT 1"));
|
||||
if (receipt == null || Objects.equals(receipt.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("收票登记不存在:发票" + trimmedInvoiceNo);
|
||||
}
|
||||
// 认领关系校验:该票必须认领在本单名下,防止跨结算单误推
|
||||
Long relationCount = invoiceReceiptSettlementMapper.selectCount(Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
.eq(InvoiceReceiptSettlement::getFormalSettlementId, id)
|
||||
.eq(InvoiceReceiptSettlement::getInvoiceReceiptId, receipt.getId()));
|
||||
if (relationCount == null || relationCount == 0) {
|
||||
throw new ServiceException("发票" + trimmedInvoiceNo + "未认领在本结算单名下,不允许重推");
|
||||
}
|
||||
String pushStatus = Func.toStrWithEmpty(receipt.getKingdeePushStatus(), KingdeeBfiConstant.RECEIVED_PUSH_UNSYNCED);
|
||||
if (KingdeeBfiConstant.RECEIVED_PUSH_ASSIGNED.equals(pushStatus)) {
|
||||
throw new ServiceException("发票" + trimmedInvoiceNo + "已指定应付,无需重复推送");
|
||||
}
|
||||
// 第一步:复用收票推送状态机重推金蝶收票单(A303-2,A801-3 幂等预检防重复保存,单笔事务独立回滚)
|
||||
String pushResult = invoiceReceiptService.pushKingdeeReceivedInvoice(List.of(receipt.getId()));
|
||||
// 第二步:收票单就绪后按应付单防重键 A302-6 指定应付(幂等,已指定的跳过)
|
||||
List<FormalSettlementDetail> details = detailMapper.selectList(Wrappers.<FormalSettlementDetail>lambdaQuery()
|
||||
.eq(FormalSettlementDetail::getFormalSettlementId, id)
|
||||
.eq(FormalSettlementDetail::getIsDeleted, 0)
|
||||
.orderByAsc(FormalSettlementDetail::getLineNo));
|
||||
if (Func.isEmpty(details)) {
|
||||
throw new ServiceException("推送失败:正式结算单无结算明细,无法组装财务应付单防重键");
|
||||
}
|
||||
String apBillSrcCode = kingdeeApBillSyncSupport.apBillSrcCode(settlement, details);
|
||||
String assignFailures = invoiceReceiptService.assignClaimedReceipts(id, apBillSrcCode);
|
||||
// 复读最新状态组装结果:assigned 即成功;收票单仍未推送成功按失败报因;pushed 未指定报因可重试
|
||||
InvoiceReceipt latest = invoiceReceiptMapper.selectById(receipt.getId());
|
||||
String latestStatus = Func.toStrWithEmpty(latest.getKingdeePushStatus(), KingdeeBfiConstant.RECEIVED_PUSH_UNSYNCED);
|
||||
if (KingdeeBfiConstant.RECEIVED_PUSH_ASSIGNED.equals(latestStatus)) {
|
||||
log.info("正式结算单[{}]认领发票[{}]重推完成:已指定应付", settlement.getFormalSettlementNo(), trimmedInvoiceNo);
|
||||
return "发票" + trimmedInvoiceNo + "重推成功:已指定应付";
|
||||
}
|
||||
if (!KingdeeBfiConstant.RECEIVED_PUSH_PUSHED.equals(latestStatus)) {
|
||||
throw new ServiceException("发票" + trimmedInvoiceNo + "重推收票单失败:" + pushResult);
|
||||
}
|
||||
if (Func.isNotBlank(assignFailures)) {
|
||||
throw new ServiceException("发票" + trimmedInvoiceNo + "收票单已推送金蝶,指定应付失败:" + assignFailures
|
||||
+ "(已指定的自动跳过,可重试)");
|
||||
}
|
||||
log.info("正式结算单[{}]认领发票[{}]重推完成:收票单已推送金蝶并指定应付", settlement.getFormalSettlementNo(), trimmedInvoiceNo);
|
||||
return "发票" + trimmedInvoiceNo + "重推成功:已指定应付";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String syncKingdeeArResult() {
|
||||
return kingdeeSyncLockSupport.runSingleFlight(AR_RESULT_SYNC_LOCK_PREFIX, bfiProperties.getArResult().getLockLeaseSeconds(),
|
||||
@@ -1243,6 +1303,15 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
for (FormalSettlementSaveRequest.Invoice item : invoices) {
|
||||
String invoiceNo = item == null ? "" : requiredText(item.getInvoiceNo(), "发票号");
|
||||
if (!invoiceNumbers.add(invoiceNo)) throw new ServiceException("发票号" + invoiceNo + "重复");
|
||||
// 匹配结算单金额支持手动修改:后端兜底校验 0 ≤ 匹配金额 ≤ 发票金额(匹配合计不设上限,两个口径)
|
||||
BigDecimal matched = money(item.getMatchedAmount());
|
||||
BigDecimal invoiceAmount = money(item.getInvoiceAmount());
|
||||
if (matched.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new ServiceException("发票" + invoiceNo + "匹配结算单金额不能为负数");
|
||||
}
|
||||
if (matched.compareTo(invoiceAmount) > 0) {
|
||||
throw new ServiceException("发票" + invoiceNo + "匹配结算单金额不能超过发票金额" + invoiceAmount);
|
||||
}
|
||||
}
|
||||
// 认领闸门:确认前按票号重查金蝶复核可用性,选中到确认之间票被认领/使用/红冲在此拦截
|
||||
invoiceReceiptService.assertInvoicesClaimable(invoiceNumbers);
|
||||
|
||||
Reference in New Issue
Block a user