feat: HCS收票单同步与任务端点接线(C109-1/2含合同回溯与人工补录/扫描编排扩展开票收票/重推端点)
This commit is contained in:
+10
@@ -64,6 +64,16 @@ public final class HcsSyncConstant {
|
||||
*/
|
||||
public static final String BIZ_TYPE_PAYMENT = "payment";
|
||||
|
||||
/**
|
||||
* 推送业务类型:开票申请(C111 开票登记)
|
||||
*/
|
||||
public static final String BIZ_TYPE_INVOICE_APPLICATION = "invoice-application";
|
||||
|
||||
/**
|
||||
* 推送业务类型:收票单(C109)
|
||||
*/
|
||||
public static final String BIZ_TYPE_INVOICE_RECEIPT = "invoice-receipt";
|
||||
|
||||
/**
|
||||
* 校验类型:客商风险(C101-1)
|
||||
*/
|
||||
|
||||
+2
@@ -34,7 +34,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.transport.constant.HcsSyncConstant;
|
||||
import org.springblade.transport.support.hcs.HcsContractSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsInvoiceRegSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsPaymentSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsReceiptBillSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsMasterDataSupport;
|
||||
import org.springblade.transport.support.hcs.HcsProjectSyncSupport;
|
||||
import org.springblade.transport.task.HcsPushTask;
|
||||
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.support.hcs;
|
||||
|
||||
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.tool.utils.StringUtil;
|
||||
import org.springblade.hcs.config.HcsProperties;
|
||||
import org.springblade.hcs.dto.HcsAttachmentRefDTO;
|
||||
import org.springblade.hcs.dto.HcsFormSaveVO;
|
||||
import org.springblade.hcs.dto.HcsMechanismsDTO;
|
||||
import org.springblade.hcs.dto.HcsReceiptBillFormDataDTO;
|
||||
import org.springblade.hcs.dto.HcsReceiptBillPropsDTO;
|
||||
import org.springblade.hcs.dto.HcsReceiptBillSaveDTO;
|
||||
import org.springblade.hcs.dto.HcsResult;
|
||||
import org.springblade.hcs.exception.HcsException;
|
||||
import org.springblade.hcs.feign.IHcsClient;
|
||||
import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.system.pojo.entity.User;
|
||||
import org.springblade.transport.constant.HcsSyncConstant;
|
||||
import org.springblade.transport.mapper.ContractManageMapper;
|
||||
import org.springblade.transport.mapper.FormalSettlementMapper;
|
||||
import org.springblade.transport.mapper.InvoiceReceiptMapper;
|
||||
import org.springblade.transport.mapper.InvoiceReceiptSettlementMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.InvoiceReceipt;
|
||||
import org.springblade.transport.pojo.entity.InvoiceReceiptSettlement;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* HCS 收票单同步支撑组件(C109-1 新建 / C109-2 更新,设计文档 §5.8,D13)
|
||||
* <p>
|
||||
* 审批通过 → C109-1;票据变更 → C109-2(顶层 fdId=hcs_fd_id 必填,只传变更字段、不带文档状态;
|
||||
* v4 无作废字段,作废推送待联调确认)。合同关联:应付结算链路回溯(收票 → 应收/应付结算关联 → 结算单合同),
|
||||
* 回溯不到时取页面人工补录的 hcs_contract_id/hcs_contract_no(D13)。
|
||||
* fd_ap_bill_src_subject(认领应付单号键)待联调(§9-U11),一期不传。
|
||||
* 返回双层嵌套 data.data.fdId → hcs_fd_id。
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class HcsReceiptBillSyncSupport {
|
||||
|
||||
/**
|
||||
* 收票单附件字段标识
|
||||
*/
|
||||
private static final String RECEIPT_ATTACH_ENTITY_KEY = "fd_attach";
|
||||
|
||||
/**
|
||||
* 收票日期格式(fd_bill_date 为 YYYY-MM-DD 字符串,非毫秒时间戳)
|
||||
*/
|
||||
private static final DateTimeFormatter BILL_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
private final IHcsClient hcsClient;
|
||||
private final HcsProperties hcsProperties;
|
||||
private final InvoiceReceiptMapper invoiceReceiptMapper;
|
||||
private final InvoiceReceiptSettlementMapper invoiceReceiptSettlementMapper;
|
||||
private final FormalSettlementMapper formalSettlementMapper;
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
private final HcsAttachmentSupport hcsAttachmentSupport;
|
||||
|
||||
/**
|
||||
* 推送收票单:无合规ID 走 C109-1 新建,有合规ID 走 C109-2 更新;整体状态由调用方回写
|
||||
*
|
||||
* @param invoiceReceipt 收票单(approvalStatus=approved)
|
||||
* @return 推送结果描述
|
||||
*/
|
||||
public String pushReceiptBill(InvoiceReceipt invoiceReceipt) {
|
||||
String operatorLoginName = resolveLoginName(invoiceReceipt);
|
||||
if (StringUtil.isBlank(invoiceReceipt.getHcsFdId())) {
|
||||
HcsReceiptBillSaveDTO param = buildSaveParam(invoiceReceipt, operatorLoginName, true);
|
||||
log.info("HCS收票单新建开始:invoiceNo={}", invoiceReceipt.getInvoiceNo());
|
||||
HcsResult<HcsResult<HcsFormSaveVO>> result = hcsClient.addReceiveBill(param);
|
||||
String fdId = extractNestedFdId(invoiceReceipt, result);
|
||||
// 收票单ID 立即持久化(调用方必须保存)
|
||||
invoiceReceipt.setHcsFdId(fdId);
|
||||
invoiceReceiptMapper.updateById(invoiceReceipt);
|
||||
log.info("HCS收票单新建成功:invoiceNo={},fdId={}", invoiceReceipt.getInvoiceNo(), fdId);
|
||||
return "C109-1 收票单新建成功";
|
||||
}
|
||||
// C109-2 更新:顶层 fdId 必填,只传变更字段、不带文档状态
|
||||
HcsReceiptBillSaveDTO param = buildSaveParam(invoiceReceipt, operatorLoginName, false);
|
||||
log.info("HCS收票单更新开始:invoiceNo={},fdId={}", invoiceReceipt.getInvoiceNo(), invoiceReceipt.getHcsFdId());
|
||||
HcsResult<HcsResult<Void>> result = hcsClient.updateReceiveBill(param);
|
||||
if (result == null || !result.isSuccess()) {
|
||||
log.error("HCS收票单更新失败响应:{},invoiceNo={}", result == null ? "无响应" : result.getMsg(), invoiceReceipt.getInvoiceNo());
|
||||
throw new HcsException("C109-2 收票单更新失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
return "C109-2 收票单更新成功";
|
||||
}
|
||||
|
||||
/**
|
||||
* 单条手动重推:重置为待同步并清零重试计数后立即推送
|
||||
*
|
||||
* @param id 收票单ID
|
||||
* @return 推送结果描述
|
||||
*/
|
||||
public String repushReceiptBill(Long id) {
|
||||
InvoiceReceipt invoiceReceipt = invoiceReceiptMapper.selectById(id);
|
||||
if (invoiceReceipt == null) {
|
||||
throw new ServiceException("收票单不存在:" + id);
|
||||
}
|
||||
if (!"approved".equals(invoiceReceipt.getApprovalStatus())) {
|
||||
throw new ServiceException("仅审批通过的收票单可推送合规(当前状态:" + invoiceReceipt.getApprovalStatus() + ")");
|
||||
}
|
||||
invoiceReceipt.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
invoiceReceipt.setHcsRetryCount(0);
|
||||
invoiceReceiptMapper.updateById(invoiceReceipt);
|
||||
try {
|
||||
return pushReceiptBill(invoiceReceipt);
|
||||
} catch (Exception exception) {
|
||||
String message = StringUtil.isBlank(exception.getMessage()) ? "推送异常" : exception.getMessage();
|
||||
markFailed(invoiceReceipt, message);
|
||||
throw new ServiceException("HCS收票单推送失败:" + message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装 C109-1/C109-2 入参(字段标注照 §3.4 规范,映射表见设计文档 §5.8)
|
||||
*/
|
||||
private HcsReceiptBillSaveDTO buildSaveParam(InvoiceReceipt invoiceReceipt, String operatorLoginName, boolean add) {
|
||||
HcsReceiptBillSaveDTO param = new HcsReceiptBillSaveDTO();
|
||||
// 收票单主键:新建不传,更新必填(顶层 fdId)
|
||||
param.setFdId(invoiceReceipt.getHcsFdId());
|
||||
// 【必填】操作人登录名:收票单创建人登录名(§9-U2)
|
||||
param.setFdLoginName(operatorLoginName);
|
||||
HcsReceiptBillFormDataDTO formData = new HcsReceiptBillFormDataDTO();
|
||||
HcsReceiptBillPropsDTO props = new HcsReceiptBillPropsDTO();
|
||||
// 发票号码:invoiceNo
|
||||
props.setFdInvoiceCode(invoiceReceipt.getInvoiceNo());
|
||||
// 开票/收票日期:invoiceDate(YYYY-MM-DD 字符串)
|
||||
props.setFdBillDate(formatBillDate(invoiceReceipt.getInvoiceDate()));
|
||||
// 开票方(销方):issuerName
|
||||
props.setFdInvoicer(invoiceReceipt.getIssuerName());
|
||||
// 收票方(购方):receiverName
|
||||
props.setFdBuyer(invoiceReceipt.getReceiverName());
|
||||
// 价税合计金额:invoiceAmount
|
||||
props.setFdInvoiceAmtTaxIncl(invoiceReceipt.getInvoiceAmount());
|
||||
// 税率(小数):TMS taxRate(如 13)÷ 100 → 0.13
|
||||
props.setFdTaxRate(toTaxRate(invoiceReceipt.getTaxRate()));
|
||||
// 发票类型:receipt-bill.invoice-type-mapping 字典映射(§9-U3,未配置不传)
|
||||
props.setFdInvoiceType(hcsProperties.getReceiptBill().getInvoiceTypeMapping().get(invoiceReceipt.getInvoiceType()));
|
||||
// 合同主题/编号:应付结算链路回溯,回溯不到取人工补录(D13)
|
||||
ContractReference contractReference = resolveContract(invoiceReceipt);
|
||||
props.setFdContractSubject(contractReference.subject());
|
||||
props.setFdContractNo(contractReference.contractNo());
|
||||
// TODO 待联调(§9-U11):fd_ap_bill_src_subject 关联结算付款单的编号体系(应付单号键)v4 未明确,一期不传
|
||||
// 备注:remark
|
||||
props.setFdRemark(invoiceReceipt.getRemark());
|
||||
formData.setDynamicProps(props);
|
||||
param.setFormData(formData);
|
||||
// 附件挂载(发票扫描件):fdEntityKey=fd_attach,发起带 fdBindType=ADD,更新不带
|
||||
if (hcsProperties.getAttachment().isTransferEnabled() && StringUtil.isNotBlank(invoiceReceipt.getAttachmentsJson())) {
|
||||
List<String> attachmentFdIds = hcsAttachmentSupport.transferAttachments(invoiceReceipt.getAttachmentsJson(), operatorLoginName);
|
||||
if (!attachmentFdIds.isEmpty()) {
|
||||
HcsMechanismsDTO mechanisms = new HcsMechanismsDTO();
|
||||
mechanisms.setAttachment(attachmentFdIds.stream().map(fdId -> {
|
||||
HcsAttachmentRefDTO attachment = new HcsAttachmentRefDTO();
|
||||
// 附件ID(C103-2 转传返回)
|
||||
attachment.setFdId(fdId);
|
||||
// 收票单附件字段标识
|
||||
attachment.setFdEntityKey(RECEIPT_ATTACH_ENTITY_KEY);
|
||||
// 绑定类型:仅发起传 ADD
|
||||
attachment.setFdBindType(add ? "ADD" : null);
|
||||
return attachment;
|
||||
}).toList());
|
||||
param.setMechanisms(mechanisms);
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 C109-1 双层嵌套返回 data.data.fdId
|
||||
*/
|
||||
private String extractNestedFdId(InvoiceReceipt invoiceReceipt, HcsResult<HcsResult<HcsFormSaveVO>> result) {
|
||||
if (result == null || !result.isSuccess() || result.getData() == null || !result.getData().isSuccess()
|
||||
|| result.getData().getData() == null || StringUtil.isBlank(result.getData().getData().getFdId())) {
|
||||
log.error("HCS收票单新建失败响应:{},invoiceNo={}", result == null ? "无响应" : result.getMsg(), invoiceReceipt.getInvoiceNo());
|
||||
throw new HcsException("C109-1 收票单新建失败:" + (result == null ? "响应为空" : result.getMsg()));
|
||||
}
|
||||
return result.getData().getData().getFdId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同引用解析:收票 → 应收结算关联 → 结算单合同 → 合同已推送传合规ID,否则传人工补录值(D13)
|
||||
*/
|
||||
private ContractReference resolveContract(InvoiceReceipt invoiceReceipt) {
|
||||
// ① 人工补录兜底优先可直接用;先走链路回溯
|
||||
InvoiceReceiptSettlement relation = invoiceReceiptSettlementMapper.selectOne(Wrappers.<InvoiceReceiptSettlement>lambdaQuery()
|
||||
.eq(InvoiceReceiptSettlement::getInvoiceReceiptId, invoiceReceipt.getId())
|
||||
.last("limit 1"));
|
||||
if (relation != null && relation.getFormalSettlementId() != null) {
|
||||
FormalSettlement settlement = formalSettlementMapper.selectById(relation.getFormalSettlementId());
|
||||
if (settlement != null && settlement.getContractId() != null) {
|
||||
ContractManage contractManage = contractManageMapper.selectById(settlement.getContractId());
|
||||
if (contractManage != null) {
|
||||
// 合同已推送传合规合同ID(fd_contract_subject 支持 ID 引用),编号传 TMS 合同编号
|
||||
String subject = StringUtil.isNotBlank(contractManage.getHcsFdId()) ? contractManage.getHcsFdId() : contractManage.getContractName();
|
||||
return new ContractReference(subject, contractManage.getContractNo());
|
||||
}
|
||||
}
|
||||
}
|
||||
// ② 回溯不到:页面人工补录(hcs_contract_id/hcs_contract_no,D13)
|
||||
if (invoiceReceipt.getHcsContractId() != null) {
|
||||
ContractManage contractManage = contractManageMapper.selectById(invoiceReceipt.getHcsContractId());
|
||||
if (contractManage != null) {
|
||||
String subject = StringUtil.isNotBlank(contractManage.getHcsFdId()) ? contractManage.getHcsFdId() : contractManage.getContractName();
|
||||
return new ContractReference(subject, StringUtil.isNotBlank(invoiceReceipt.getHcsContractNo()) ? invoiceReceipt.getHcsContractNo() : contractManage.getContractNo());
|
||||
}
|
||||
}
|
||||
if (StringUtil.isNotBlank(invoiceReceipt.getHcsContractNo())) {
|
||||
return new ContractReference(null, invoiceReceipt.getHcsContractNo());
|
||||
}
|
||||
log.warn("HCS收票单合同关联缺失:invoiceNo={},应付结算回溯与人工补录均为空,fd_contract_* 不传", invoiceReceipt.getInvoiceNo());
|
||||
return new ContractReference(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回填整体同步状态置 synced
|
||||
*/
|
||||
public void markSynced(InvoiceReceipt invoiceReceipt, String message) {
|
||||
invoiceReceipt.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_SYNCED);
|
||||
invoiceReceipt.setHcsRetryCount(0);
|
||||
invoiceReceipt.setHcsSyncTime(LocalDateTime.now());
|
||||
invoiceReceipt.setHcsSyncMsg(message);
|
||||
invoiceReceiptMapper.updateById(invoiceReceipt);
|
||||
log.info("HCS收票单推送成功:invoiceNo={},{}", invoiceReceipt.getInvoiceNo(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送失败回写:failed + 重试次数+1 + 失败原因
|
||||
*/
|
||||
public void markFailed(InvoiceReceipt invoiceReceipt, String message) {
|
||||
invoiceReceipt.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_FAILED);
|
||||
invoiceReceipt.setHcsRetryCount(invoiceReceipt.getHcsRetryCount() == null ? 1 : invoiceReceipt.getHcsRetryCount() + 1);
|
||||
invoiceReceipt.setHcsSyncTime(LocalDateTime.now());
|
||||
invoiceReceipt.setHcsSyncMsg(message);
|
||||
invoiceReceiptMapper.updateById(invoiceReceipt);
|
||||
log.error("HCS收票单推送失败:invoiceNo={},retryCount={},{}", invoiceReceipt.getInvoiceNo(), invoiceReceipt.getHcsRetryCount(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作人登录名(收票单创建人,§9-U2)
|
||||
*/
|
||||
private String resolveLoginName(InvoiceReceipt invoiceReceipt) {
|
||||
if (invoiceReceipt.getCreateUser() == null) {
|
||||
throw new HcsException("C109 收票单推送失败,收票单创建人未维护(invoiceNo=" + invoiceReceipt.getInvoiceNo() + ")");
|
||||
}
|
||||
User user = UserCache.getUser(invoiceReceipt.getCreateUser());
|
||||
if (user == null || StringUtil.isBlank(user.getAccount())) {
|
||||
throw new HcsException("C109 收票单推送失败,创建人登录名解析不到(createUser=" + invoiceReceipt.getCreateUser() + ")");
|
||||
}
|
||||
return user.getAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 收票日期格式化(fd_bill_date 为 YYYY-MM-DD 字符串)
|
||||
*/
|
||||
private String formatBillDate(LocalDate invoiceDate) {
|
||||
return invoiceDate == null ? null : invoiceDate.format(BILL_DATE_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 税率换算:TMS 整数值(如 13)÷ 100 → 小数(0.13)
|
||||
*/
|
||||
private BigDecimal toTaxRate(BigDecimal taxRate) {
|
||||
return taxRate == null ? null : taxRate.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同引用(fd_contract_subject / fd_contract_no)
|
||||
*/
|
||||
private record ContractReference(String subject, String contractNo) {
|
||||
}
|
||||
}
|
||||
+76
-1
@@ -33,14 +33,20 @@ import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.hcs.config.HcsProperties;
|
||||
import org.springblade.transport.constant.HcsSyncConstant;
|
||||
import org.springblade.transport.mapper.ContractManageMapper;
|
||||
import org.springblade.transport.mapper.InvoiceApplicationMapper;
|
||||
import org.springblade.transport.mapper.InvoiceReceiptMapper;
|
||||
import org.springblade.transport.mapper.PaymentApplicationMapper;
|
||||
import org.springblade.transport.mapper.ProjectApplyMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.InvoiceApplication;
|
||||
import org.springblade.transport.pojo.entity.InvoiceReceipt;
|
||||
import org.springblade.transport.pojo.entity.PaymentApplication;
|
||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||
import org.springblade.transport.support.hcs.HcsContractSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsInvoiceRegSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsPaymentSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsProjectSyncSupport;
|
||||
import org.springblade.transport.support.hcs.HcsReceiptBillSyncSupport;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -81,9 +87,13 @@ public class HcsPushTask {
|
||||
private final ProjectApplyMapper projectApplyMapper;
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
private final PaymentApplicationMapper paymentApplicationMapper;
|
||||
private final InvoiceApplicationMapper invoiceApplicationMapper;
|
||||
private final InvoiceReceiptMapper invoiceReceiptMapper;
|
||||
private final HcsProjectSyncSupport hcsProjectSyncSupport;
|
||||
private final HcsContractSyncSupport hcsContractSyncSupport;
|
||||
private final HcsPaymentSyncSupport hcsPaymentSyncSupport;
|
||||
private final HcsInvoiceRegSyncSupport hcsInvoiceRegSyncSupport;
|
||||
private final HcsReceiptBillSyncSupport hcsReceiptBillSyncSupport;
|
||||
private final BladeRedis bladeRedis;
|
||||
|
||||
/**
|
||||
@@ -109,10 +119,12 @@ public class HcsPushTask {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 任务顺序(设计文档 §5.0):项目 → 合同 → 付款;各类互不影响
|
||||
// 任务顺序(设计文档 §5.0):项目 → 合同 → 付款 → 开票 → 收票;各类互不影响
|
||||
log.info("定时推送HCS项目立项:{}", pushUnsyncedProjects());
|
||||
log.info("定时推送HCS合同:{}", pushUnsyncedContracts());
|
||||
log.info("定时推送HCS付款链:{}", pushUnsyncedPayments());
|
||||
log.info("定时推送HCS开票登记:{}", pushUnsyncedInvoiceApplications());
|
||||
log.info("定时推送HCS收票单:{}", pushUnsyncedInvoiceReceipts());
|
||||
} finally {
|
||||
if (lockHolder.equals(bladeRedis.get(HcsSyncConstant.PUSH_TASK_LOCK_KEY))) {
|
||||
bladeRedis.del(HcsSyncConstant.PUSH_TASK_LOCK_KEY);
|
||||
@@ -212,4 +224,67 @@ public class HcsPushTask {
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描并推送待同步/待补偿的开票申请(C111 开票登记,含金蝶开票完成后回填),返回结果汇总
|
||||
*
|
||||
* @return 汇总描述
|
||||
*/
|
||||
public String pushUnsyncedInvoiceApplications() {
|
||||
int maxRetry = hcsProperties.getPush().getMaxRetry();
|
||||
List<InvoiceApplication> applicationList = invoiceApplicationMapper.selectList(Wrappers.<InvoiceApplication>lambdaQuery()
|
||||
.eq(InvoiceApplication::getApprovalStatus, "approved")
|
||||
.in(InvoiceApplication::getHcsSyncStatus, List.of(HcsSyncConstant.HCS_STATUS_UNSYNCED, HcsSyncConstant.HCS_STATUS_FAILED))
|
||||
.and(wrapper -> wrapper.isNull(InvoiceApplication::getHcsRetryCount).or().lt(InvoiceApplication::getHcsRetryCount, maxRetry))
|
||||
.last("limit " + hcsProperties.getPush().getBatchSize()));
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
for (InvoiceApplication application : applicationList) {
|
||||
try {
|
||||
hcsInvoiceRegSyncSupport.pushInvoiceRegistration(application);
|
||||
successCount++;
|
||||
} catch (Exception exception) {
|
||||
String message = StringUtil.isBlank(exception.getMessage()) ? "推送异常" : exception.getMessage();
|
||||
hcsInvoiceRegSyncSupport.markFailed(application, message);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
String summary = String.format("扫描 %d 条,成功 %d 条,失败 %d 条(重试上限 %d)", applicationList.size(), successCount, failCount, maxRetry);
|
||||
if (failCount > 0) {
|
||||
log.warn("HCS开票登记推送存在失败:{}", summary);
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描并推送待同步/待补偿的收票单(C109),返回结果汇总
|
||||
*
|
||||
* @return 汇总描述
|
||||
*/
|
||||
public String pushUnsyncedInvoiceReceipts() {
|
||||
int maxRetry = hcsProperties.getPush().getMaxRetry();
|
||||
List<InvoiceReceipt> receiptList = invoiceReceiptMapper.selectList(Wrappers.<InvoiceReceipt>lambdaQuery()
|
||||
.eq(InvoiceReceipt::getApprovalStatus, "approved")
|
||||
.in(InvoiceReceipt::getHcsSyncStatus, List.of(HcsSyncConstant.HCS_STATUS_UNSYNCED, HcsSyncConstant.HCS_STATUS_FAILED))
|
||||
.and(wrapper -> wrapper.isNull(InvoiceReceipt::getHcsRetryCount).or().lt(InvoiceReceipt::getHcsRetryCount, maxRetry))
|
||||
.last("limit " + hcsProperties.getPush().getBatchSize()));
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
for (InvoiceReceipt invoiceReceipt : receiptList) {
|
||||
try {
|
||||
hcsReceiptBillSyncSupport.pushReceiptBill(invoiceReceipt);
|
||||
hcsReceiptBillSyncSupport.markSynced(invoiceReceipt, "C109 收票单推送成功");
|
||||
successCount++;
|
||||
} catch (Exception exception) {
|
||||
String message = StringUtil.isBlank(exception.getMessage()) ? "推送异常" : exception.getMessage();
|
||||
hcsReceiptBillSyncSupport.markFailed(invoiceReceipt, message);
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
String summary = String.format("扫描 %d 条,成功 %d 条,失败 %d 条(重试上限 %d)", receiptList.size(), successCount, failCount, maxRetry);
|
||||
if (failCount > 0) {
|
||||
log.warn("HCS收票单推送存在失败:{}", summary);
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user