:feat: 审批通过自动创建履约计划行,C103-9同步前置至特批挂起之前
This commit is contained in:
+37
@@ -212,6 +212,43 @@ public final class HcsSyncConstant {
|
||||
*/
|
||||
public static final String SPEC_REVIEW_NODE = "特批审核";
|
||||
|
||||
// ==================== 履约计划行(blade_contract_exe_stage,C103-9) ====================
|
||||
|
||||
/**
|
||||
* 行级同步操作:无(同步成功后清除标记)
|
||||
*/
|
||||
public static final String ROW_OP_NONE = "none";
|
||||
|
||||
/**
|
||||
* 行级同步操作:新增
|
||||
*/
|
||||
public static final String ROW_OP_ADD = "add";
|
||||
|
||||
/**
|
||||
* 行级同步操作:更新
|
||||
*/
|
||||
public static final String ROW_OP_UPDATE = "update";
|
||||
|
||||
/**
|
||||
* 行级同步操作:删除
|
||||
*/
|
||||
public static final String ROW_OP_DELETE = "delete";
|
||||
|
||||
/**
|
||||
* 履约类型:付款
|
||||
*/
|
||||
public static final String PERFORM_TYPE_PAYMENT = "payment";
|
||||
|
||||
/**
|
||||
* 履约类型:收款
|
||||
*/
|
||||
public static final String PERFORM_TYPE_COLLECTION = "collection";
|
||||
|
||||
/**
|
||||
* 款项性质:进度款
|
||||
*/
|
||||
public static final String FUND_NATURE_PROGRESS = "progress";
|
||||
|
||||
// ==================== Redis 缓存 key(照 BFI blade:third: 前缀惯例) ====================
|
||||
|
||||
/**
|
||||
|
||||
+9
@@ -26,6 +26,7 @@
|
||||
package org.springblade.transport.service;
|
||||
|
||||
import org.springblade.core.mp.base.BaseService;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.HcsContractExeStage;
|
||||
|
||||
import java.util.List;
|
||||
@@ -45,6 +46,14 @@ public interface IContractExeStageService extends BaseService<HcsContractExeStag
|
||||
*/
|
||||
List<HcsContractExeStage> listByContractId(Long contractId);
|
||||
|
||||
/**
|
||||
* 审批通过自动创建默认履约计划行(合同下无规则行时):承运商合同=付款进度款(收票规则取合同结算模式),
|
||||
* 客户合同=收款进度款;金额/资金日期留空,随合同链路推 C103-9
|
||||
*
|
||||
* @param contractManage 合同单(审批通过)
|
||||
*/
|
||||
void createDefaultRowOnApprove(ContractManage contractManage);
|
||||
|
||||
/**
|
||||
* 保存合同履约规则行(按行差异置同步标记:新行/未同步行 add,已同步行 update)
|
||||
*
|
||||
|
||||
+46
-9
@@ -57,11 +57,6 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeStageMapper, HcsContractExeStage> implements IContractExeStageService {
|
||||
|
||||
/**
|
||||
* 行级同步操作:无
|
||||
*/
|
||||
private static final String ROW_OP_NONE = "none";
|
||||
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
private final HcsProperties hcsProperties;
|
||||
|
||||
@@ -87,7 +82,7 @@ public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeS
|
||||
row.setContractId(contractId);
|
||||
if (row.getId() == null) {
|
||||
// 新行:待随合同链路首推(row_op=add)
|
||||
row.setRowOp("add");
|
||||
row.setRowOp(HcsSyncConstant.ROW_OP_ADD);
|
||||
row.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
row.setHcsSyncMsg("待随合同链路同步(C103-9)");
|
||||
row.setFundType(StringUtil.isBlank(row.getFundType()) ? hcsProperties.getExeStage().getFundType() : row.getFundType());
|
||||
@@ -99,7 +94,7 @@ public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeS
|
||||
throw new ServiceException("履约规则行不属于该合同:" + row.getId());
|
||||
}
|
||||
// 已同步行编辑 → update;未同步行保持 add
|
||||
String rowOp = StringUtil.isBlank(existing.getHcsStageFdId()) ? "add" : "update";
|
||||
String rowOp = StringUtil.isBlank(existing.getHcsStageFdId()) ? HcsSyncConstant.ROW_OP_ADD : HcsSyncConstant.ROW_OP_UPDATE;
|
||||
existing.setPerformType(row.getPerformType());
|
||||
existing.setFundNature(row.getFundNature());
|
||||
existing.setFundAmount(row.getFundAmount());
|
||||
@@ -127,7 +122,7 @@ public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeS
|
||||
}
|
||||
if (StringUtil.isNotBlank(row.getHcsStageFdId())) {
|
||||
// 已同步行:软删+标记 delete,由 C103-9 凭合规阶段ID 上报删除(ADR-0002,不可物理删除)
|
||||
row.setRowOp("delete");
|
||||
row.setRowOp(HcsSyncConstant.ROW_OP_DELETE);
|
||||
row.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
row.setHcsSyncMsg("待随合同链路同步(C103-9 delete)");
|
||||
updateById(row);
|
||||
@@ -137,6 +132,48 @@ public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeS
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createDefaultRowOnApprove(ContractManage contractManage) {
|
||||
Long contractId = contractManage.getId();
|
||||
if (count(Wrappers.<HcsContractExeStage>lambdaQuery().eq(HcsContractExeStage::getContractId, contractId)) > 0) {
|
||||
return;
|
||||
}
|
||||
HcsContractExeStage row = new HcsContractExeStage();
|
||||
row.setContractId(contractId);
|
||||
if ("承运商合同".equals(contractManage.getContractCategory())) {
|
||||
row.setPerformType(HcsSyncConstant.PERFORM_TYPE_PAYMENT);
|
||||
row.setInvoiceRule(mapInvoiceRule(contractManage.getSettlementMode()));
|
||||
} else if ("客户合同".equals(contractManage.getContractCategory())) {
|
||||
row.setPerformType(HcsSyncConstant.PERFORM_TYPE_COLLECTION);
|
||||
} else {
|
||||
log.info("合同类别非承运商/客户,不自动创建履约计划行:contractNo={},contractCategory={}", contractManage.getContractNo(), contractManage.getContractCategory());
|
||||
return;
|
||||
}
|
||||
// 默认进度款计划行:金额/资金日期留空,随合同链路推 C103-9
|
||||
row.setFundNature(HcsSyncConstant.FUND_NATURE_PROGRESS);
|
||||
row.setFundType(hcsProperties.getExeStage().getFundType());
|
||||
row.setIsFinish(0);
|
||||
row.setRowOp(HcsSyncConstant.ROW_OP_ADD);
|
||||
row.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
row.setHcsSyncMsg("审批通过自动创建,待随合同链路同步(C103-9)");
|
||||
save(row);
|
||||
log.info("审批通过自动创建履约计划行:contractNo={},contractCategory={},performType={},invoiceRule={}",
|
||||
contractManage.getContractNo(), contractManage.getContractCategory(), row.getPerformType(), row.getInvoiceRule());
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算模式文本映射 C103-9 开票规则:先款后票=payFirst、先票后款=invoiceFirst,其余(月结/现结等)不传
|
||||
*/
|
||||
private String mapInvoiceRule(String settlementMode) {
|
||||
if ("先款后票".equals(settlementMode)) {
|
||||
return "payFirst";
|
||||
}
|
||||
if ("先票后款".equals(settlementMode)) {
|
||||
return "invoiceFirst";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 行字段校验
|
||||
*/
|
||||
@@ -144,7 +181,7 @@ public class ContractExeStageServiceImpl extends BaseServiceImpl<HcsContractExeS
|
||||
if (StringUtil.isBlank(row.getPerformType())) {
|
||||
throw new ServiceException("履约类型不能为空(payment/collection)");
|
||||
}
|
||||
if (!List.of("payment", "collection").contains(row.getPerformType())) {
|
||||
if (!List.of(HcsSyncConstant.PERFORM_TYPE_PAYMENT, HcsSyncConstant.PERFORM_TYPE_COLLECTION).contains(row.getPerformType())) {
|
||||
throw new ServiceException("履约类型非法:" + row.getPerformType());
|
||||
}
|
||||
if (row.getFundAmount() != null && row.getFundAmount().signum() < 0) {
|
||||
|
||||
+4
@@ -42,6 +42,7 @@ import org.springblade.transport.mapper.HcsContractExeStageMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.HcsContractExeStage;
|
||||
import org.springblade.transport.pojo.vo.ContractManageVO;
|
||||
import org.springblade.transport.service.IContractExeStageService;
|
||||
import org.springblade.transport.service.IContractManageService;
|
||||
import org.springblade.transport.support.TransportBusinessSupport;
|
||||
import org.springblade.transport.support.hcs.HcsCreditCheckSupport;
|
||||
@@ -76,6 +77,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
private final HcsContractExeStageMapper hcsContractExeStageMapper;
|
||||
private final HcsImmediatePushSupport hcsImmediatePushSupport;
|
||||
private final HcsCreditCheckSupport hcsCreditCheckSupport;
|
||||
private final IContractExeStageService contractExeStageService;
|
||||
|
||||
private static final String STAGE_DRAFT = "draft";
|
||||
private static final String STAGE_TEMPORARY = "temporary";
|
||||
@@ -236,6 +238,8 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
// HCS 推送:审批通过(含变更通过)置待同步状态,事务提交后即时推送,扫描任务保留兜底(ADR-0001 修订,前端接入设计 §6)
|
||||
contractManage.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
// 合同审批通过:履约规则未同步行统一置待同步标记,随合同链路调 C103-9(ADR-0002)
|
||||
// 审批通过自动创建默认履约计划行(承运商=付款进度款/客户=收款进度款),已有规则行时不重复创建
|
||||
contractExeStageService.createDefaultRowOnApprove(contractManage);
|
||||
hcsContractExeStageMapper.update(null, Wrappers.<HcsContractExeStage>lambdaUpdate()
|
||||
.eq(HcsContractExeStage::getContractId, contractManage.getId())
|
||||
.isNull(HcsContractExeStage::getHcsStageFdId)
|
||||
|
||||
+23
-13
@@ -72,9 +72,9 @@ import java.util.Objects;
|
||||
* <p>
|
||||
* 扫描任务按序执行:⓪ 特批挂起门禁 → ① 客商风险校验(可配开关,仅留痕,高风险不再阻断)→
|
||||
* ② 附件转传(v4 挂载点 fdFieldJson.attachment,随 C103-1 挂载)→ ③ C103-3 判重(§9-U4 查询能力联调确认)→
|
||||
* ④ C103-1 起草 / 变更单 C103-11 更新(§9-U5 定位方式待联调)→ ⑤ 高风险/黑名单挂起"特批审核"
|
||||
* (外部客商管控:报文随 fdSepcailContract=true 在合规侧走特批,{@link HcsContractSpecSyncSupport} 接收结果)→
|
||||
* ⑥ 履约规则 C103-9 行级同步({@link HcsExeStageSyncSupport})。
|
||||
* ④ C103-1 起草 / 变更单 C103-11 更新(§9-U5 定位方式待联调)→ ⑤ 履约计划 C103-9 行级同步({@link HcsExeStageSyncSupport},
|
||||
* 仅依赖 hcs_fd_id,先于特批挂起执行,失败补偿不被特批门禁阻塞)→ ⑥ 高风险/黑名单挂起"特批审核"
|
||||
* (外部客商管控:报文随 fdSepcailContract=true 在合规侧走特批,{@link HcsContractSpecSyncSupport} 接收结果)。
|
||||
* 结果留痕:风险校验写 blade_hcs_check_log 与合同 hcs_risk_* 字段;推送结果回填 hcs_fd_id/hcs_sync_status。
|
||||
*
|
||||
* @author Chill
|
||||
@@ -94,6 +94,11 @@ public class HcsContractSyncSupport {
|
||||
*/
|
||||
private static final String BLACK_STATUS_YES = "yes";
|
||||
|
||||
/**
|
||||
* signer 相对方单位类型:暂统一传 customer(客户,2026-10-14 联调确认,§9-U6 后续细化)
|
||||
*/
|
||||
private static final String SIGNER_FD_TYPE_CUSTOMER = "customer";
|
||||
|
||||
private final IHcsClient hcsClient;
|
||||
private final HcsProperties hcsProperties;
|
||||
private final ContractManageMapper contractManageMapper;
|
||||
@@ -105,7 +110,7 @@ public class HcsContractSyncSupport {
|
||||
|
||||
/**
|
||||
* 推送合同到 HCS:特批挂起门禁 → 风险校验(仅留痕,高风险不再阻断)→ 附件转传 → 判重 → 起草/更新 → 回填合规 fdId 置 synced
|
||||
* → 高风险/黑名单客商合同挂起"特批审核"等待合规特批结果(报文随 fdSepcailContract=true,外部客商管控)
|
||||
* → 履约计划行级同步(C103-9,先于特批挂起)→ 高风险/黑名单客商合同挂起"特批审核"等待合规特批结果(报文随 fdSepcailContract=true,外部客商管控)
|
||||
*
|
||||
* @param contractManage 合同单(approvalStatus 须为 approved/change_approved)
|
||||
* @return 推送结果描述(供任务汇总与 hcs_sync_msg 落库)
|
||||
@@ -145,17 +150,17 @@ public class HcsContractSyncSupport {
|
||||
markSynced(contractManage, contractManage.getHcsFdId(), "C103-11 合同更新成功");
|
||||
resultMessage = "C103-11 合同更新成功";
|
||||
}
|
||||
// ⑤ 高风险/黑名单客商(外部客商管控):起草/更新报文已随 fdSepcailContract=true 在合规侧发起特批流程,
|
||||
// ⑤ 履约规则 C103-9 行级同步(随合同链路,§5.3;仅依赖 hcs_fd_id 与特批无关,先于特批挂起执行——
|
||||
// 失败抛出落 failed 时特批未挂起,修复后可直接重推补偿,不被特批门禁阻塞)
|
||||
if (hcsProperties.getExeStage().isSyncEnabled()) {
|
||||
resultMessage = resultMessage + ";" + hcsExeStageSyncSupport.syncExeStages(contractManage);
|
||||
}
|
||||
// ⑥ 高风险/黑名单客商(外部客商管控):起草/更新报文已随 fdSepcailContract=true 在合规侧发起特批流程,
|
||||
// 此处挂起"特批审核"等待结果(合规推送 contractLegal/result 或定时 C103-4 查询联动恢复/驳回)
|
||||
if (risky) {
|
||||
hangSpecReview(contractManage);
|
||||
}
|
||||
// ⑥ 履约规则 C103-9 行级同步(随合同链路,§5.3;一期暂不对接默认关,打开后失败抛出由任务落 failed,下轮凭 hcs_fd_id 走更新补偿)
|
||||
if (!hcsProperties.getExeStage().isSyncEnabled()) {
|
||||
return resultMessage;
|
||||
}
|
||||
String exeStageResult = hcsExeStageSyncSupport.syncExeStages(contractManage);
|
||||
return resultMessage + ";" + exeStageResult;
|
||||
return resultMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -361,7 +366,10 @@ public class HcsContractSyncSupport {
|
||||
settlementType = HcsContractFieldConstant.SETTLEMENT_TYPE_COLLECTION;
|
||||
}
|
||||
if (StringUtil.isNotBlank(settlementType)) {
|
||||
fields.add(field(HcsContractFieldConstant.FIELD_FD_SETTLEMENT_TYPE, "合同结算类型", settlementType));
|
||||
HcsXformFieldDTO settlementField = field(HcsContractFieldConstant.FIELD_FD_SETTLEMENT_TYPE, "合同结算类型", settlementType);
|
||||
// 字典类字段需带 fdIsSystem=true(合规侧按系统字典值解析,2026-10-14 联调确认)
|
||||
settlementField.setFdIsSystem("true");
|
||||
fields.add(settlementField);
|
||||
} else {
|
||||
log.warn("HCS合同结算类型无法确定:contractCategory=[{}] 非承运商合同/客户合同,fdSettlementType 不传", contractManage.getContractCategory());
|
||||
}
|
||||
@@ -409,7 +417,7 @@ public class HcsContractSyncSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* signer 相对方(签署方):甲/乙双方,fdType(inner/外部)判定规则待联调(§9-U6)暂不传
|
||||
* signer 相对方(签署方):甲/乙双方,fdType 暂统一传 customer(客户,2026-10-14 联调确认)
|
||||
*/
|
||||
private List<HcsSignerDTO> buildSigners(ContractManage contractManage) {
|
||||
List<HcsSignerDTO> signers = new ArrayList<>();
|
||||
@@ -431,6 +439,8 @@ public class HcsContractSyncSupport {
|
||||
signer.setFdName(partyName);
|
||||
// 相对方编号:按名称反查 CustomerArchive 客商编码,反查不到留空(§9-U6)
|
||||
signer.setFdNumber(queryCustomerCode(partyName));
|
||||
// 单位类型:暂统一传 customer(客户),inner/外部判定规则后续联调细化(§9-U6)
|
||||
signer.setFdType(SIGNER_FD_TYPE_CUSTOMER);
|
||||
return signer;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user