feat: 认领作废同步合规并下线金蝶认领结果回写
This commit is contained in:
+1
-8
@@ -83,16 +83,9 @@ public class ReceiptClaimRecordController extends BladeController {
|
|||||||
|
|
||||||
@PostMapping("/void")
|
@PostMapping("/void")
|
||||||
@ApiOperationSupport(order = 4)
|
@ApiOperationSupport(order = 4)
|
||||||
@Operation(summary = "作废认领记录并生成金蝶认领冲单")
|
@Operation(summary = "作废认领记录(作废后同步合同合规系统)")
|
||||||
public R<Void> voidClaim(@RequestParam Long id) {
|
public R<Void> voidClaim(@RequestParam Long id) {
|
||||||
receiptClaimRecordService.voidClaim(id);
|
receiptClaimRecordService.voidClaim(id);
|
||||||
return R.success("作废成功");
|
return R.success("作废成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/query-kingdee-result")
|
|
||||||
@ApiOperationSupport(order = 5)
|
|
||||||
@Operation(summary = "查询金蝶认领结果(A301-1 收款单查询回写)")
|
|
||||||
public R<Integer> queryKingdeeResult() {
|
|
||||||
return R.data(receiptClaimRecordService.refreshKingdeeResult());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-7
@@ -46,11 +46,4 @@ public interface IReceiptClaimRecordService extends BaseService<ReceiptClaim> {
|
|||||||
void updateAttachments(ReceiptClaimAttachmentsRequest request);
|
void updateAttachments(ReceiptClaimAttachmentsRequest request);
|
||||||
|
|
||||||
void voidClaim(Long id);
|
void voidClaim(Long id);
|
||||||
|
|
||||||
/**
|
|
||||||
* A301-1 收款单查询回写认领结果:按来源单据编码匹配金蝶收款单,推进金蝶单据状态
|
|
||||||
*
|
|
||||||
* @return 回写条数
|
|
||||||
*/
|
|
||||||
int refreshKingdeeResult();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-136
@@ -33,12 +33,6 @@ import org.springblade.core.log.exception.ServiceException;
|
|||||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||||
import org.springblade.core.secure.utils.AuthUtil;
|
import org.springblade.core.secure.utils.AuthUtil;
|
||||||
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.tool.utils.Func;
|
||||||
import org.springblade.thirdparty.bfi.constant.BfiConstant;
|
|
||||||
import org.springblade.thirdparty.bfi.pojo.dto.BfiRecBillQueryDTO;
|
|
||||||
import org.springblade.thirdparty.bfi.pojo.vo.BfiRecBillVO;
|
|
||||||
import org.springblade.thirdparty.bfi.service.IBfiService;
|
|
||||||
import org.springblade.thirdparty.bfi.util.BfiUtil;
|
|
||||||
import org.springblade.transport.constant.KingdeeBfiConstant;
|
|
||||||
import org.springblade.transport.mapper.FormalSettlementMapper;
|
import org.springblade.transport.mapper.FormalSettlementMapper;
|
||||||
import org.springblade.transport.mapper.KingdeeReceiptFlowMapper;
|
import org.springblade.transport.mapper.KingdeeReceiptFlowMapper;
|
||||||
import org.springblade.transport.mapper.ReceiptClaimMapper;
|
import org.springblade.transport.mapper.ReceiptClaimMapper;
|
||||||
@@ -53,20 +47,21 @@ import org.springblade.transport.pojo.entity.ReceiptFlowRecord;
|
|||||||
import org.springblade.transport.pojo.vo.ReceiptClaimRecordVO;
|
import org.springblade.transport.pojo.vo.ReceiptClaimRecordVO;
|
||||||
import org.springblade.transport.service.IReceiptClaimRecordService;
|
import org.springblade.transport.service.IReceiptClaimRecordService;
|
||||||
import org.springblade.transport.service.IFormalSettlementService;
|
import org.springblade.transport.service.IFormalSettlementService;
|
||||||
|
import org.springblade.transport.support.hcs.HcsClaimSyncSupport;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -84,21 +79,13 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
private static final String CLAIMED = "claimed";
|
private static final String CLAIMED = "claimed";
|
||||||
private static final String VOIDED = "voided";
|
private static final String VOIDED = "voided";
|
||||||
private static final String APPROVED = "approved";
|
private static final String APPROVED = "approved";
|
||||||
/**
|
|
||||||
* A301-1 收款单查询回看窗口天数(金蝶约束业务日期范围不可超过1个月)
|
|
||||||
*/
|
|
||||||
private static final int RESULT_WINDOW_DAYS = 30;
|
|
||||||
/**
|
|
||||||
* A301-1 收款单查询分页大小
|
|
||||||
*/
|
|
||||||
private static final int RESULT_PAGE_SIZE = 200;
|
|
||||||
|
|
||||||
private final ReceiptClaimSettlementMapper claimSettlementMapper;
|
private final ReceiptClaimSettlementMapper claimSettlementMapper;
|
||||||
private final IFormalSettlementService formalSettlementService;
|
private final IFormalSettlementService formalSettlementService;
|
||||||
private final KingdeeReceiptFlowMapper receiptFlowMapper;
|
private final KingdeeReceiptFlowMapper receiptFlowMapper;
|
||||||
private final FormalSettlementMapper formalSettlementMapper;
|
private final FormalSettlementMapper formalSettlementMapper;
|
||||||
private final ReceiptFlowRecordMapper recordMapper;
|
private final ReceiptFlowRecordMapper recordMapper;
|
||||||
private final IBfiService bfiService;
|
private final HcsClaimSyncSupport hcsClaimSyncSupport;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<ReceiptClaimRecordVO> selectPage(IPage<ReceiptClaimRecordVO> page,
|
public IPage<ReceiptClaimRecordVO> selectPage(IPage<ReceiptClaimRecordVO> page,
|
||||||
@@ -203,10 +190,6 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
if (flow == null || Objects.equals(flow.getIsDeleted(), 1)) {
|
if (flow == null || Objects.equals(flow.getIsDeleted(), 1)) {
|
||||||
throw new ServiceException("关联收款流水不存在");
|
throw new ServiceException("关联收款流水不存在");
|
||||||
}
|
}
|
||||||
// 已推送金蝶的认领不允许作废:金蝶收款单已生成,冲销/调整由人工在金蝶处置
|
|
||||||
if (KingdeeBfiConstant.RECEIPT_CLAIM_PUSH_PUSHED.equals(flow.getPushStatus())) {
|
|
||||||
throw new ServiceException("该认领已推送金蝶,不允许作废,请在金蝶侧人工处置");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ReceiptClaimSettlement> relations = claimSettlementMapper.selectList(
|
List<ReceiptClaimSettlement> relations = claimSettlementMapper.selectList(
|
||||||
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
@@ -256,9 +239,8 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
flow.setClaimStatus(amountClaimStatus(flowClaimedAfter, claimCeiling(flow)));
|
flow.setClaimStatus(amountClaimStatus(flowClaimedAfter, claimCeiling(flow)));
|
||||||
receiptFlowMapper.updateById(flow);
|
receiptFlowMapper.updateById(flow);
|
||||||
|
|
||||||
// 作废不生成金蝶认领冲单:金蝶单号/状态保留原值(未推送为空,已推送为真实收款单信息),
|
// 作废不生成金蝶认领冲单:金蝶单号/状态保留原值(金蝶收款单已在 A301-1 同步落库),
|
||||||
// 金蝶侧冲销/红冲由人工处置;冲单逻辑后续迭代如需恢复,放开下行调用即可
|
// 金蝶侧冲销/红冲由人工处置
|
||||||
// String kingdeeBillNo = buildKingdeeBillNo(claim.getId());
|
|
||||||
claim.setClaimStatus(VOIDED);
|
claim.setClaimStatus(VOIDED);
|
||||||
claim.setVoidedBy(AuthUtil.getUserId());
|
claim.setVoidedBy(AuthUtil.getUserId());
|
||||||
claim.setVoidedByName(Func.isEmpty(AuthUtil.getUserName()) ? claim.getClaimerName()
|
claim.setVoidedByName(Func.isEmpty(AuthUtil.getUserName()) ? claim.getClaimerName()
|
||||||
@@ -278,108 +260,14 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
: AuthUtil.getUserName());
|
: AuthUtil.getUserName());
|
||||||
operationRecord.setContent("作废认领,回退认领金额 " + money(claim.getClaimAmount()));
|
operationRecord.setContent("作废认领,回退认领金额 " + money(claim.getClaimAmount()));
|
||||||
recordMapper.insert(operationRecord);
|
recordMapper.insert(operationRecord);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// 作废事务提交后同步合规 C107-3(fdStatus=1 已作废,失败仅记日志不回滚作废)
|
||||||
* A301-1 收款单查询回写认领结果:按来源单据编码匹配金蝶收款单,推进流水金蝶回写状态
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
* <p>
|
@Override
|
||||||
* 回写口径:A301-1 契约本身不支持按来源单号过滤,故按近 30 天业务日期窗口全量翻页后,
|
public void afterCommit() {
|
||||||
* 以金蝶收款单 sourcebillnumber == 流水 awrp_src_code(A301-3 推送时按流水生成、重试复用)在本地匹配;
|
hcsClaimSyncSupport.voidClaimToHcs(claim.getId());
|
||||||
* 仅推进金蝶回写状态与补登收款单号,不改本地认领金额/分摊;名下未作废认领主单冗余展示字段级联刷新。
|
}
|
||||||
*
|
|
||||||
* @return 回写条数
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int refreshKingdeeResult() {
|
|
||||||
List<KingdeeReceiptFlow> pending = receiptFlowMapper.selectList(
|
|
||||||
Wrappers.<KingdeeReceiptFlow>lambdaQuery()
|
|
||||||
.eq(KingdeeReceiptFlow::getPushStatus, KingdeeBfiConstant.RECEIPT_CLAIM_PUSH_PUSHED)
|
|
||||||
.in(KingdeeReceiptFlow::getKingdeeBillStatus,
|
|
||||||
List.of(KingdeeBfiConstant.KINGDEE_STATUS_PUSHED, APPROVED))
|
|
||||||
.eq(KingdeeReceiptFlow::getStatus, 1)
|
|
||||||
.orderByAsc(KingdeeReceiptFlow::getId));
|
|
||||||
if (pending.isEmpty()) {
|
|
||||||
log.info("金蝶认领结果回写:无待回写流水(已推送/已审核且未终态)");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Set<String> srcCodes = pending.stream()
|
|
||||||
.map(KingdeeReceiptFlow::getAwrpSrcCode)
|
|
||||||
.filter(Func::isNotEmpty)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if (srcCodes.isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
log.info("金蝶认领结果回写:待回写流水 {} 条", pending.size());
|
|
||||||
|
|
||||||
LocalDate end = LocalDate.now();
|
|
||||||
LocalDate begin = end.minusDays(RESULT_WINDOW_DAYS);
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
log.info("调用BFI接口 收款单查询开始,业务日期窗口 {} ~ {}", begin, end);
|
|
||||||
List<BfiRecBillVO> rows = BfiUtil.queryAllPages(pageNo -> {
|
|
||||||
BfiRecBillQueryDTO dto = new BfiRecBillQueryDTO();
|
|
||||||
dto.setPageNo(pageNo);
|
|
||||||
dto.setPageSize(RESULT_PAGE_SIZE);
|
|
||||||
dto.setBeginBizdate(begin.format(DateTimeFormatter.ISO_LOCAL_DATE));
|
|
||||||
dto.setEndBizdate(end.format(DateTimeFormatter.ISO_LOCAL_DATE));
|
|
||||||
return bfiService.queryRecBill(dto);
|
|
||||||
});
|
});
|
||||||
log.info("调用BFI接口 收款单查询结束 耗时:{}ms,拉取 {} 条", System.currentTimeMillis() - start, rows.size());
|
|
||||||
|
|
||||||
// 窗口内收款单按 sourcebillnumber 匹配待回写来源编码,同键多单取首条
|
|
||||||
Map<String, BfiRecBillVO> matched = rows.stream()
|
|
||||||
.filter(row -> Func.isNotEmpty(row.getSourcebillnumber()))
|
|
||||||
.filter(row -> srcCodes.contains(row.getSourcebillnumber()))
|
|
||||||
.collect(Collectors.toMap(BfiRecBillVO::getSourcebillnumber, Function.identity(),
|
|
||||||
(first, second) -> first, HashMap::new));
|
|
||||||
int updated = 0;
|
|
||||||
for (KingdeeReceiptFlow flow : pending) {
|
|
||||||
BfiRecBillVO bill = matched.get(flow.getAwrpSrcCode());
|
|
||||||
if (bill == null) {
|
|
||||||
// 窗口内未查到:金蝶回单延迟/状态未同步,不改状态,由下次回写或人工处置兜底
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 推送成功时金蝶收款单号先以来源编码占位(A301-3 响应 number 为空,取回执 keys.awrp_src_code),
|
|
||||||
// 回写命中后以金蝶真实收款单号覆盖
|
|
||||||
if (Func.isNotEmpty(bill.getBillno())) {
|
|
||||||
flow.setKingdeeBillNo(bill.getBillno());
|
|
||||||
}
|
|
||||||
flow.setKingdeeBillStatus(billStatusOf(bill.getBillstatus()));
|
|
||||||
receiptFlowMapper.updateById(flow);
|
|
||||||
// 级联刷新名下未作废认领主单的冗余展示字段
|
|
||||||
baseMapper.update(null, Wrappers.<ReceiptClaim>lambdaUpdate()
|
|
||||||
.eq(ReceiptClaim::getReceiptFlowId, flow.getId())
|
|
||||||
.eq(ReceiptClaim::getClaimStatus, CLAIMED)
|
|
||||||
.set(ReceiptClaim::getKingdeeBillNo, flow.getKingdeeBillNo())
|
|
||||||
.set(ReceiptClaim::getKingdeeBillStatus, flow.getKingdeeBillStatus()));
|
|
||||||
updated++;
|
|
||||||
log.info("金蝶认领结果回写 flowId:{},awrpSrcCode:{},金蝶收款单号:{},状态:{} → {}",
|
|
||||||
flow.getId(), flow.getAwrpSrcCode(), bill.getBillno(), bill.getBillstatus(),
|
|
||||||
flow.getKingdeeBillStatus());
|
|
||||||
}
|
|
||||||
log.info("金蝶认领结果回写完成:匹配 {} 条,更新 {} 条", matched.size(), updated);
|
|
||||||
return updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 金蝶收款单单据状态 → 本地认领金蝶状态
|
|
||||||
*
|
|
||||||
* @param billStatus 金蝶 billstatus(A暂存/B已提交/C已审核/D已收款/G已退单)
|
|
||||||
* @return 本地状态
|
|
||||||
*/
|
|
||||||
private String billStatusOf(String billStatus) {
|
|
||||||
if (BfiConstant.BILL_STATUS_RECEIVED.equals(billStatus)) {
|
|
||||||
return KingdeeBfiConstant.KINGDEE_STATUS_RECEIVED;
|
|
||||||
}
|
|
||||||
if (BfiConstant.BILL_STATUS_AUDITED.equals(billStatus)) {
|
|
||||||
return APPROVED;
|
|
||||||
}
|
|
||||||
if (BfiConstant.BILL_STATUS_DRAFT.equals(billStatus)
|
|
||||||
|| BfiConstant.BILL_STATUS_SUBMITTED.equals(billStatus)) {
|
|
||||||
return KingdeeBfiConstant.KINGDEE_STATUS_PUSHED;
|
|
||||||
}
|
|
||||||
// 其余状态(含 G 已退单)按处理失败回收,提示人工在金蝶核查
|
|
||||||
log.warn("金蝶收款单状态[{}]未匹配映射,认领回写按 failed 处理", billStatus);
|
|
||||||
return KingdeeBfiConstant.KINGDEE_STATUS_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillStatusNames(ReceiptClaimRecordVO record) {
|
private void fillStatusNames(ReceiptClaimRecordVO record) {
|
||||||
@@ -399,17 +287,6 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
return VOIDED.equals(claimStatus) ? VOIDED : CLAIMED;
|
return VOIDED.equals(claimStatus) ? VOIDED : CLAIMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成本地金蝶认领冲单号(KDCX + 时间戳 + 认领id尾号6位)。
|
|
||||||
* 当前作废流程不生成冲单(调用点已注释保留),后续迭代接金蝶冲销时放开即可。
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private String buildKingdeeBillNo(Long claimId) {
|
|
||||||
String time = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
|
|
||||||
String suffix = String.valueOf(claimId);
|
|
||||||
return "KDCX" + time + suffix.substring(Math.max(0, suffix.length() - 6));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 累计认领金额 → 流水认领状态:对照可认领上限判定(与收款流水侧口径一致)
|
* 累计认领金额 → 流水认领状态:对照可认领上限判定(与收款流水侧口径一致)
|
||||||
*/
|
*/
|
||||||
@@ -421,7 +298,7 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可认领上限:公告未认领金额与收款金额取较小正值(与收款流水侧口径一致)
|
* 可认领上限:未匹配收款金额(A301-1 unmatchamountrec)与收款金额取较小正值(与收款流水侧口径一致)
|
||||||
*/
|
*/
|
||||||
private BigDecimal claimCeiling(KingdeeReceiptFlow flow) {
|
private BigDecimal claimCeiling(KingdeeReceiptFlow flow) {
|
||||||
BigDecimal unclaimed = money(flow.getUnclaimedAmount());
|
BigDecimal unclaimed = money(flow.getUnclaimedAmount());
|
||||||
|
|||||||
Reference in New Issue
Block a user