feat: 金蝶锁单失败摘要拼入同步返回供页面提示,重推重置补偿计数并新增手动补偿端点
This commit is contained in:
+9
@@ -36,6 +36,7 @@ import org.springblade.transport.excel.FormalSettlementExcel;
|
||||
import org.springblade.transport.pojo.vo.PreSettlementVO;
|
||||
import org.springblade.transport.service.IFormalSettlementService;
|
||||
import org.springblade.transport.service.IInvoiceReceiptService;
|
||||
import org.springblade.transport.service.IKingdeeBillLockService;
|
||||
import org.springblade.transport.service.IPreSettlementService;
|
||||
import org.springblade.transport.service.IReceiptFlowService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -62,6 +63,7 @@ import java.math.RoundingMode;
|
||||
@Tag(name = "正式结算单", description = "正式结算单管理")
|
||||
public class FormalSettlementController extends BladeController {
|
||||
private final IFormalSettlementService formalSettlementService;
|
||||
private final IKingdeeBillLockService kingdeeBillLockService;
|
||||
private final IPreSettlementService preSettlementService;
|
||||
private final IReceiptFlowService receiptFlowService;
|
||||
private final IInvoiceReceiptService invoiceReceiptService;
|
||||
@@ -216,6 +218,13 @@ public class FormalSettlementController extends BladeController {
|
||||
@Operation(summary = "手动勾稽金蝶应收单(A302-4 回写纠偏)")
|
||||
public R<String> syncKingdeeArResult() { return R.data(formalSettlementService.syncKingdeeArResult()); }
|
||||
|
||||
@PostMapping("/retry-kingdee-bill-lock")
|
||||
@ApiOperationSupport(order = 17)
|
||||
@Operation(summary = "手动补偿金蝶单据锁定(扫锁定失败锁记录重调lockBusiData,应付/应收/开票通用)")
|
||||
public R<String> retryKingdeeBillLock() {
|
||||
return R.data(kingdeeBillLockService.retryFailedLocks());
|
||||
}
|
||||
|
||||
@GetMapping("/detail-fees")
|
||||
@ApiOperationSupport(order = 16)
|
||||
@Operation(summary = "正式结算货物费用快照")
|
||||
|
||||
+3
-2
@@ -24,7 +24,7 @@ public interface IKingdeeBillLockService extends IService<KingdeeBillLock> {
|
||||
/**
|
||||
* 推送金蝶成功后锁单(由各推送链路在主单事务提交后调用):
|
||||
* 每张金蝶目标单一行锁记录(先落 failed 再调 lockBusiData,成功翻 locked);
|
||||
* 同源单的目标单合并为一次调用(编号逗号拼接批量传参);已 locked 幂等跳过,failed 原地重锁;
|
||||
* 同源单的目标单合并为一次调用(编号逗号拼接批量传参);已 locked 幂等跳过,failed 原地重锁并重置补偿计数;
|
||||
* 异常独立捕获,不影响主单同步状态
|
||||
*
|
||||
* @param sourceBillType WLTMS 单据类型(SETTLEMENT/INVOICE_APPLY)
|
||||
@@ -32,8 +32,9 @@ public interface IKingdeeBillLockService extends IService<KingdeeBillLock> {
|
||||
* @param sourceBillNo WLTMS 单号
|
||||
* @param targetBillType 金蝶目标单据类型
|
||||
* @param targetBillNos 金蝶单据编号集合(开票申请为多张)
|
||||
* @return 锁定失败的金蝶单号摘要(逗号拼接),全部锁定成功返回 null;调用方可拼入页面提示
|
||||
*/
|
||||
void lockAfterPush(String sourceBillType, Long sourceBillId, String sourceBillNo, String targetBillType, List<String> targetBillNos);
|
||||
String lockAfterPush(String sourceBillType, Long sourceBillId, String sourceBillNo, String targetBillType, List<String> targetBillNos);
|
||||
|
||||
/**
|
||||
* 金蝶解锁回调(unLockNotifyBusiData):校验来源/目标系统与 lockAction,
|
||||
|
||||
+11
-7
@@ -600,11 +600,13 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
public String syncKingdee(Long id) {
|
||||
// 单据级事务经自代理调用:单条失败只回滚自身
|
||||
String billNo = SpringUtil.getBean(IFormalSettlementService.class).doSyncKingdee(id);
|
||||
// 主单事务提交后锁定金蝶单据(lockBusiData):失败只留 failed 锁记录由补偿任务重锁,不污染主单同步状态
|
||||
lockKingdeeBillAfterPush(id, billNo);
|
||||
// 主单事务提交后锁定金蝶单据(lockBusiData):失败只留 failed 锁记录由补偿任务重锁,不污染主单同步状态;
|
||||
// 锁定失败摘要拼入返回值,页面直接可见
|
||||
String lockFailSummary = lockKingdeeBillAfterPush(id, billNo);
|
||||
// 主单事务提交后联带上传附件(A902):失败只记附件同步状态,不回滚不污染主单同步状态,重推自动补传
|
||||
syncAttachmentsAfterPush(id);
|
||||
return billNo;
|
||||
return Func.isBlank(lockFailSummary) ? billNo
|
||||
: billNo + ";注意:金蝶单据锁定未成功(" + lockFailSummary + "),系统将自动补偿重锁,重推同步金蝶可立即补锁";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -613,22 +615,24 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
||||
*
|
||||
* @param id 正式结算单id
|
||||
* @param billNo 金蝶单据编号
|
||||
* @return 锁定失败的金蝶单号摘要,全部锁定成功返回 null
|
||||
*/
|
||||
private void lockKingdeeBillAfterPush(Long id, String billNo) {
|
||||
private String lockKingdeeBillAfterPush(Long id, String billNo) {
|
||||
try {
|
||||
if (Func.isBlank(billNo)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
FormalSettlement settlement = getById(id);
|
||||
if (settlement == null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
kingdeeBillLockService.lockAfterPush(KingdeeLockConstant.SOURCE_SETTLEMENT, id, settlement.getFormalSettlementNo(),
|
||||
return kingdeeBillLockService.lockAfterPush(KingdeeLockConstant.SOURCE_SETTLEMENT, id, settlement.getFormalSettlementNo(),
|
||||
"receivable".equals(settlement.getSettlementType())
|
||||
? KingdeeLockConstant.TARGET_AR_BILL : KingdeeLockConstant.TARGET_AP_BILL,
|
||||
Func.toStrList(billNo));
|
||||
} catch (Exception exception) {
|
||||
log.error("正式结算单[{}]金蝶单据锁定联带动作异常(锁记录已落库待补偿)", id, exception);
|
||||
return "锁定动作异常,已留档待补偿";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -547,11 +547,12 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
||||
// 单据级事务经自代理调用:单条失败只回滚自身
|
||||
String billNo = SpringUtil.getBean(IInvoiceApplicationService.class).doSyncKingdee(id);
|
||||
// 主单事务提交后锁定金蝶开票单(lockBusiData):每张发票张次一张金蝶单,多张逗号拼接批量锁定;
|
||||
// 失败只留 failed 锁记录由补偿任务重锁,不污染主单同步状态
|
||||
lockKingdeeBillAfterPush(id, billNo);
|
||||
// 失败只留 failed 锁记录由补偿任务重锁,不污染主单同步状态;锁定失败摘要拼入返回值,页面直接可见
|
||||
String lockFailSummary = lockKingdeeBillAfterPush(id, billNo);
|
||||
// 主单事务提交后联带上传附件(A902):失败只记附件同步状态,不回滚不污染主单同步状态,重推自动补传
|
||||
syncAttachmentsAfterPush(id);
|
||||
return billNo;
|
||||
return Func.isBlank(lockFailSummary) ? billNo
|
||||
: billNo + ";注意:金蝶单据锁定未成功(" + lockFailSummary + "),系统将自动补偿重锁,重推同步金蝶可立即补锁";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,20 +561,22 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
||||
*
|
||||
* @param id 开票申请id
|
||||
* @param billNo 金蝶开票单编号(多张逗号拼接)
|
||||
* @return 锁定失败的金蝶单号摘要,全部锁定成功返回 null
|
||||
*/
|
||||
private void lockKingdeeBillAfterPush(Long id, String billNo) {
|
||||
private String lockKingdeeBillAfterPush(Long id, String billNo) {
|
||||
try {
|
||||
if (Func.isBlank(billNo)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
InvoiceApplication entity = getById(id);
|
||||
if (entity == null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
kingdeeBillLockService.lockAfterPush(KingdeeLockConstant.SOURCE_INVOICE_APPLY, id, entity.getApplicationNo(),
|
||||
return kingdeeBillLockService.lockAfterPush(KingdeeLockConstant.SOURCE_INVOICE_APPLY, id, entity.getApplicationNo(),
|
||||
KingdeeLockConstant.TARGET_INVOICE_BILL, Func.toStrList(billNo));
|
||||
} catch (Exception exception) {
|
||||
log.error("开票申请[{}]金蝶单据锁定联带动作异常(锁记录已落库待补偿)", id, exception);
|
||||
return "锁定动作异常,已留档待补偿";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-5
@@ -67,9 +67,9 @@ public class KingdeeBillLockServiceImpl extends ServiceImpl<KingdeeBillLockMappe
|
||||
private final InvoiceApplicationMapper invoiceApplicationMapper;
|
||||
|
||||
@Override
|
||||
public void lockAfterPush(String sourceBillType, Long sourceBillId, String sourceBillNo, String targetBillType, List<String> targetBillNos) {
|
||||
public String lockAfterPush(String sourceBillType, Long sourceBillId, String sourceBillNo, String targetBillType, List<String> targetBillNos) {
|
||||
if (Func.isEmpty(targetBillNos)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
String operator = operatorName();
|
||||
// 待锁目标单:已 locked 幂等跳过(人工重推「同步金蝶」幂等命中路径不会重复锁);
|
||||
@@ -80,7 +80,7 @@ public class KingdeeBillLockServiceImpl extends ServiceImpl<KingdeeBillLockMappe
|
||||
if (lockRecord != null && KingdeeLockConstant.STATUS_LOCKED.equals(lockRecord.getLockStatus())) {
|
||||
continue;
|
||||
}
|
||||
if (lockRecord == null || KingdeeLockConstant.STATUS_UNLOCKED.equals(lockRecord.getLockStatus())) {
|
||||
if (lockRecord == null) {
|
||||
lockRecord = new KingdeeBillLock();
|
||||
lockRecord.setSourceBillType(sourceBillType);
|
||||
lockRecord.setSourceBillId(sourceBillId);
|
||||
@@ -92,11 +92,18 @@ public class KingdeeBillLockServiceImpl extends ServiceImpl<KingdeeBillLockMappe
|
||||
lockRecord.setTryCount(0);
|
||||
lockRecord.setLockOperator(operator);
|
||||
this.save(lockRecord);
|
||||
} else {
|
||||
// 人工重推触发的补锁:重置补偿计数重新起算(定时补偿烧完上限后,人工动作可重新接管自动补偿)
|
||||
KingdeeBillLock resetRecord = new KingdeeBillLock();
|
||||
resetRecord.setId(lockRecord.getId());
|
||||
resetRecord.setTryCount(0);
|
||||
this.updateById(resetRecord);
|
||||
lockRecord.setTryCount(0);
|
||||
}
|
||||
pendingRecords.add(lockRecord);
|
||||
}
|
||||
if (pendingRecords.isEmpty()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
// 同源单目标单合并一次调用:编号逗号拼接批量传参,整批同成败(应答仅聚合 updateCount)
|
||||
try {
|
||||
@@ -111,6 +118,7 @@ public class KingdeeBillLockServiceImpl extends ServiceImpl<KingdeeBillLockMappe
|
||||
}
|
||||
log.info("金蝶单据批量锁定成功:源单[{}:{}],金蝶单{}张[{}]", sourceBillType, sourceBillNo,
|
||||
pendingRecords.size(), String.join(",", pendingRecords.stream().map(KingdeeBillLock::getTargetBillNo).toList()));
|
||||
return null;
|
||||
} catch (Exception exception) {
|
||||
String failReason = limitText(exception.getMessage(), 500);
|
||||
for (KingdeeBillLock lockRecord : pendingRecords) {
|
||||
@@ -118,7 +126,9 @@ public class KingdeeBillLockServiceImpl extends ServiceImpl<KingdeeBillLockMappe
|
||||
lockRecord.setFailReason(failReason);
|
||||
this.updateById(lockRecord);
|
||||
}
|
||||
log.error("金蝶单据批量锁定失败(待补偿重锁):源单[{}:{}],金蝶单{}张", sourceBillType, sourceBillNo, pendingRecords.size(), exception);
|
||||
String failedNos = pendingRecords.stream().map(KingdeeBillLock::getTargetBillNo).collect(Collectors.joining(","));
|
||||
log.error("金蝶单据批量锁定失败(待补偿重锁):源单[{}:{}],金蝶单{}张[{}]", sourceBillType, sourceBillNo, pendingRecords.size(), failedNos, exception);
|
||||
return failedNos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user