:feat: 新增项目金蝶同步结果回调并回填金蝶ID

- 新增 /hcs/projectLegal/result 免登回调端点(D902),按项目编号定位回填金蝶项目ID/编号,原文留痕 blade_hcs_check_log
- 合同 contractLegal/result 回调成功分支回填金蝶合同ID
- 项目/合同金蝶回调成功与失败均追加变更记录(changeRecordJson)
- 项目立项/合同列表支持按是否同步金蝶、是否同步合规筛选
- 新增增量SQL:blade_project_apply.kingdee_id/kingdee_number、blade_contract_manage.kingdee_id
This commit is contained in:
刘泉佳
2026-10-20 11:05:11 +08:00
parent 6e6e5913ba
commit fac4c112aa
13 changed files with 394 additions and 4 deletions
@@ -262,4 +262,7 @@ public class ContractManage extends TenantEntity {
@Schema(description = "特批申请材料+内部审批附件JSON(含C103-2 合规附件ID)")
private String hcsSpecFilesJson;
@Schema(description = "金蝶合同ID(contractLegal/result 合同特批金蝶同步结果回调回填)")
private String kingdeeId;
}
@@ -215,4 +215,10 @@ public class ProjectApply extends TenantEntity {
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
private String hcsSyncMsg;
@Schema(description = "金蝶项目ID(D902 项目金蝶同步结果回调回填)")
private String kingdeeId;
@Schema(description = "金蝶项目编号(D902 项目金蝶同步结果回调回填)")
private String kingdeeNumber;
}
@@ -55,6 +55,14 @@ public class ContractManageVO extends ContractManage {
@Schema(description = "到期快捷筛选")
private String expireScope;
@TableField(exist = false)
@Schema(description = "是否已同步金蝶(金蝶合同ID是否已回填)")
private Boolean kingdeeSynced;
@TableField(exist = false)
@Schema(description = "是否已同步合规(合规同步状态是否为 synced)")
private Boolean hcsSynced;
@TableField(exist = false)
@Schema(description = "生效类型筛选")
private String effectiveType;
@@ -86,6 +86,14 @@ public class ProjectApplyVO extends ProjectApply {
@Schema(description = "是否仅查询可用于合同选择的项目(含临时项目与正式审批通过项目)")
private Boolean contractSelectable;
@TableField(exist = false)
@Schema(description = "是否已同步金蝶(金蝶项目ID是否已回填)")
private Boolean kingdeeSynced;
@TableField(exist = false)
@Schema(description = "是否已同步合规(合规同步状态是否为 synced)")
private Boolean hcsSynced;
@TableField(exist = false)
@Schema(description = "资金使用风险等级:high、medium、none")
private String fundUseRisk;
@@ -89,6 +89,11 @@ public final class HcsSyncConstant {
*/
public static final String CHECK_TYPE_SPEC = "spec";
/**
* 校验类型:项目金蝶同步结果回调(D902,projectLegal/result 推送留痕)
*/
public static final String CHECK_TYPE_KINGDEE = "kingdee";
/**
* 校验结果:通过
*/
@@ -36,11 +36,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.hcs.dto.HcsAttachmentRefDTO;
import org.springblade.hcs.dto.HcsContractLegalResultDTO;
import org.springblade.hcs.dto.HcsCurrencyVO;
import org.springblade.hcs.dto.HcsLegalResultDTO;
import org.springblade.hcs.dto.HcsProjectLegalResultDTO;
import org.springblade.hcs.dto.HcsTemplateVO;
import org.springblade.transport.constant.HcsSyncConstant;
import org.springblade.transport.pojo.vo.CustomerRiskVO;
@@ -223,6 +225,17 @@ public class HcsSyncController {
return R.data(hcsCreditCheckSupport.queryCustomerRisk(customerCode));
}
/**
* 客商风险批量查询(C101-1,客商列表页展示用,前端接入设计 §3.3):
* 按客商编号集合逐个查询(口径同 /risk),展示用不作为安全边界,单个失败跳过不阻断整页
*/
@GetMapping("/risk/batch")
@ApiOperationSupport(order = 13)
@Operation(summary = "客商风险批量查询", description = "C101-1 按客商编号集合批量查询风险等级与黑名单状态(展示用),口径同单个查询,单个失败跳过不阻断")
public R<List<CustomerRiskVO>> riskBatch(@Parameter(description = "客商编号集合,逗号分隔", required = true) @RequestParam String customerCodes) {
return R.data(hcsCreditCheckSupport.queryCustomerRiskBatch(Func.toStrList(customerCodes)));
}
/**
* 附件上传到合同系统(C103-2 代理,前端接入设计 §3.2),返回合规附件ID
*/
@@ -293,4 +306,19 @@ public class HcsSyncController {
public R<String> paymentLegalResult(@RequestBody(required = false) HcsLegalResultDTO param) {
return R.data(hcsPaymentSyncSupport.handleLegalResult(param));
}
/**
* 项目金蝶同步结果回传接收(合规系统 projectLegal/result 推送,D902,原文留痕)
* <p>
* 免登免授权:blade.secure skip-url + auth permitAll 放行(doc/nacos/blade.yaml);
* iPaaS 网关注册映射:/gwzh/HTHG/projectLegal/result → /hcs/projectLegal/result;
* 报文 {sourceSystem, projectCode, requestId, success, kingdeeId, projectNumber, reason},
* 按 projectCode=TMS 项目编号定位,success=true 回填金蝶项目ID/编号,success=false 记录失败原因。
*/
@PostMapping("/projectLegal/result")
@ApiOperationSupport(order = 18)
@Operation(summary = "项目金蝶同步结果回传接收", description = "合规系统推送项目金蝶同步结果(D902),按项目编号定位并回填金蝶ID,原文留痕")
public R<String> projectLegalResult(@RequestBody(required = false) HcsProjectLegalResultDTO param) {
return R.data(hcsProjectSyncSupport.handleLegalResult(param));
}
}
@@ -482,9 +482,29 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
.orderByDesc(ContractManage::getCreateTime);
applyEffectiveType(queryWrapper, contractManage.getEffectiveType());
applyExpireScope(queryWrapper, contractManage.getExpireScope());
// 是否同步金蝶(kingdee_id 是否已回填)/ 是否同步合规(hcs_sync_status 是否 synced)
applySyncFlagFilter(queryWrapper, contractManage.getKingdeeSynced(), contractManage.getHcsSynced());
return queryWrapper;
}
/**
* 金蝶/合规同步与否筛选(列表搜索:kingdeeSynced 按 kingdee_id 空值判断,hcsSynced 按 hcs_sync_status=synced 判断)
*/
private void applySyncFlagFilter(LambdaQueryWrapper<ContractManage> queryWrapper, Boolean kingdeeSynced, Boolean hcsSynced) {
if (Boolean.TRUE.equals(kingdeeSynced)) {
queryWrapper.isNotNull(ContractManage::getKingdeeId).ne(ContractManage::getKingdeeId, "");
} else if (Boolean.FALSE.equals(kingdeeSynced)) {
queryWrapper.and(wrapper -> wrapper.isNull(ContractManage::getKingdeeId)
.or().eq(ContractManage::getKingdeeId, ""));
}
if (Boolean.TRUE.equals(hcsSynced)) {
queryWrapper.eq(ContractManage::getHcsSyncStatus, HcsSyncConstant.HCS_STATUS_SYNCED);
} else if (Boolean.FALSE.equals(hcsSynced)) {
queryWrapper.and(wrapper -> wrapper.isNull(ContractManage::getHcsSyncStatus)
.or().ne(ContractManage::getHcsSyncStatus, HcsSyncConstant.HCS_STATUS_SYNCED));
}
}
private void applyEffectiveType(LambdaQueryWrapper<ContractManage> queryWrapper, String effectiveType) {
if (Func.isEmpty(effectiveType)) {
return;
@@ -406,9 +406,29 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
.toList();
queryWrapper.in(ProjectApply::getId, matchedIds.isEmpty() ? List.of(-1L) : matchedIds);
}
// 是否同步金蝶(kingdee_id 是否已回填)/ 是否同步合规(hcs_sync_status 是否 synced)
applySyncFlagFilter(queryWrapper, projectApply.getKingdeeSynced(), projectApply.getHcsSynced());
return queryWrapper;
}
/**
* 金蝶/合规同步与否筛选(列表搜索:kingdeeSynced 按 kingdee_id 空值判断,hcsSynced 按 hcs_sync_status=synced 判断)
*/
private void applySyncFlagFilter(LambdaQueryWrapper<ProjectApply> queryWrapper, Boolean kingdeeSynced, Boolean hcsSynced) {
if (Boolean.TRUE.equals(kingdeeSynced)) {
queryWrapper.isNotNull(ProjectApply::getKingdeeId).ne(ProjectApply::getKingdeeId, "");
} else if (Boolean.FALSE.equals(kingdeeSynced)) {
queryWrapper.and(wrapper -> wrapper.isNull(ProjectApply::getKingdeeId)
.or().eq(ProjectApply::getKingdeeId, ""));
}
if (Boolean.TRUE.equals(hcsSynced)) {
queryWrapper.eq(ProjectApply::getHcsSyncStatus, HcsSyncConstant.HCS_STATUS_SYNCED);
} else if (Boolean.FALSE.equals(hcsSynced)) {
queryWrapper.and(wrapper -> wrapper.isNull(ProjectApply::getHcsSyncStatus)
.or().ne(ProjectApply::getHcsSyncStatus, HcsSyncConstant.HCS_STATUS_SYNCED));
}
}
private void fillFundUseRisk(List<ProjectApplyVO> records) {
if (records == null || records.isEmpty()) {
return;
@@ -45,8 +45,12 @@ import org.springblade.transport.pojo.entity.HcsContractCheckLog;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* HCS 合同特批同步支撑组件(合规特批结果接收:contractLegal/result 推送 + C103-4 定时查询兜底 + 人工确认)。
@@ -169,7 +173,7 @@ public class HcsContractSpecSyncSupport {
* 合同特批结果接收处理(合规 contractLegal/result 推送,2026-10-13 按合规方最新字段表修正报文结构):
* 特批完成后合规侧同步金蝶并回调,报文 {contractType, contractCode, requestId, success, reason, kingdeeId, sourceSystem=WCCK};
* sourceSystem 须为 WCCK(不符抛"来源系统标识错误"异常);contractCode=TMS 合同编号定位(requestId 仅请求头回显不可定位);
* success=true 联动恢复"审批通过"(kingdeeId 随留痕保存);success=false 联动合同审批驳回走重新提交闭环(reason 随原文留痕)
* success=true 联动恢复"审批通过"(金蝶合同ID回填 kingdee_id);success=false 联动合同审批驳回走重新提交闭环(reason 随原文留痕)
*
* @param param 合规推送报文
* @return 处理结果描述
@@ -193,9 +197,11 @@ public class HcsContractSpecSyncSupport {
return "已留痕:success 字段缺失(contractNo=" + contractManage.getContractNo() + ")";
}
boolean success = param.getSuccess();
// 成功:特批完成且金蝶同步成功,恢复"审批通过";kingdeeId 随 hcs_spec_msg/留痕保存
// 成功:特批完成且金蝶同步成功,恢复"审批通过";金蝶合同ID回填 kingdee_id 留痕保存
if (success) {
syncContractOnSpecResult(contractManage, true);
contractManage.setKingdeeId(param.getKingdeeId());
appendKingdeeResultRecord(contractManage, "金蝶同步成功:金蝶合同ID=" + param.getKingdeeId());
markSpec(contractManage, HcsSyncConstant.SPEC_STATUS_APPROVED,
"合同特批结果推送:金蝶同步成功,kingdeeId=" + param.getKingdeeId());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_PASS, "合同特批结果推送:" + raw);
@@ -204,12 +210,49 @@ public class HcsContractSpecSyncSupport {
}
// 失败:特批流程已完成但金蝶同步失败,联动合同审批驳回,走重新编辑→提交→审批→重新特批闭环(失败单独重试机制待联调确认)
syncContractOnSpecResult(contractManage, false);
appendKingdeeResultRecord(contractManage, "金蝶同步失败:" + param.getReason());
markSpec(contractManage, HcsSyncConstant.SPEC_STATUS_REJECTED, "合同特批结果推送:金蝶同步失败:" + param.getReason());
writeCallbackLog(contractManage, HcsSyncConstant.CHECK_RESULT_FAIL, "合同特批结果推送:" + raw);
log.info("合同特批结果推送处理完成:contractNo={},结果=rejected,reason={}", contractManage.getContractNo(), param.getReason());
return "特批结果已处理:rejected";
}
/**
* 金蝶同步结果回填变更记录(changeRecordJson 追加一条;系统回调无登录用户,操作人记来源标识)
*/
private void appendKingdeeResultRecord(ContractManage contractManage, String changeContent) {
List<Object> records = StringUtil.isBlank(contractManage.getChangeRecordJson())
? new ArrayList<>() : new ArrayList<>(JSONUtil.toList(contractManage.getChangeRecordJson(), Object.class));
Map<String, Object> record = new LinkedHashMap<>();
record.put("changeDate", LocalDate.now().toString());
record.put("handlerUserName", "合规系统回调");
record.put("changeType", "金蝶同步结果");
record.put("changeContent", changeContent);
record.put("status", contractManage.getApprovalStatus());
record.put("statusName", approvalStatusName(contractManage.getApprovalStatus()));
records.add(record);
contractManage.setChangeRecordJson(JSONUtil.toJsonStr(records));
}
/**
* 审批状态中文名(变更记录展示用,未匹配回退原值)
*/
private String approvalStatusName(String approvalStatus) {
if (StringUtil.isBlank(approvalStatus)) {
return null;
}
return switch (approvalStatus) {
case "draft" -> "草稿";
case "reviewing" -> "审批中";
case "withdrawn" -> "已撤回";
case "approved" -> "审批通过";
case "rejected" -> "已驳回";
case "change_reviewing" -> "变更审批中";
case "change_approved" -> "变更审批通过";
default -> approvalStatus;
};
}
/**
* 按 ERP 合同编号定位合同(合规推送 contractCode,合同编号唯一)
*/
@@ -25,6 +25,8 @@
*/
package org.springblade.transport.support.hcs;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
@@ -36,6 +38,7 @@ import org.springblade.hcs.dto.HcsPageQueryDTO;
import org.springblade.hcs.dto.HcsPageVO;
import org.springblade.hcs.dto.HcsProjectAddDTO;
import org.springblade.hcs.dto.HcsProjectFormDataDTO;
import org.springblade.hcs.dto.HcsProjectLegalResultDTO;
import org.springblade.hcs.dto.HcsProjectPropsDTO;
import org.springblade.hcs.dto.HcsProjectUpdateDTO;
import org.springblade.hcs.dto.HcsProjectVO;
@@ -47,12 +50,17 @@ import org.springblade.hcs.exception.HcsException;
import org.springblade.hcs.feign.IHcsClient;
import org.springblade.transport.constant.HcsFieldConstant;
import org.springblade.transport.constant.HcsSyncConstant;
import org.springblade.transport.mapper.HcsContractCheckLogMapper;
import org.springblade.transport.mapper.ProjectApplyMapper;
import org.springblade.transport.pojo.entity.HcsContractCheckLog;
import org.springblade.transport.pojo.entity.ProjectApply;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -76,9 +84,15 @@ public class HcsProjectSyncSupport {
*/
private static final BigDecimal WAN_TO_YUAN = BigDecimal.valueOf(10000);
/**
* 项目金蝶同步结果回传来源系统标识(合规方接口文档约定固定传 WCCK)
*/
private static final String LEGAL_CALLBACK_SRC_SYSTEM = "WCCK";
private final IHcsClient hcsClient;
private final HcsProperties hcsProperties;
private final ProjectApplyMapper projectApplyMapper;
private final HcsContractCheckLogMapper hcsContractCheckLogMapper;
/**
* 推送项目立项到 HCS:判重 → 新建(C102-1)/ 更新(C102-2)→ 回填合规 fdId 置 synced
@@ -257,6 +271,125 @@ public class HcsProjectSyncSupport {
return page.getContent().get(0).getFdId();
}
/**
* 项目金蝶同步结果接收处理(合规 projectLegal/result 推送,D902):
* sourceSystem 须为 WCCK(不符抛"来源系统标识错误"异常);projectCode=TMS 项目编号定位(requestId 仅 X-ERP-Request-Id 回显不可定位);
* success=true 回填金蝶项目ID/编号(kingdeeId/kingdeeNumber);success=false 记录失败原因;原文留痕 blade_hcs_check_log
*
* @param param 合规推送报文
* @return 处理结果描述
*/
public String handleLegalResult(HcsProjectLegalResultDTO param) {
// 来源系统校验:仅接受合规方约定的 WCCK,防伪造回传
if (!LEGAL_CALLBACK_SRC_SYSTEM.equalsIgnoreCase(param == null ? null : param.getSourceSystem())) {
log.warn("项目金蝶同步结果推送来源系统标识错误:sourceSystem={}", param == null ? null : param.getSourceSystem());
throw new ServiceException("来源系统标识错误");
}
String raw = JSONUtil.toJsonStr(param);
ProjectApply projectApply = locateProjectByCode(param.getProjectCode());
if (projectApply == null) {
log.warn("项目金蝶同步结果推送未定位到项目:projectCode={},报文已留痕", param.getProjectCode());
writeCallbackLog(null, HcsSyncConstant.CHECK_RESULT_SKIP, "项目金蝶同步结果推送未定位到项目:" + raw);
return "已留痕:未定位到项目(projectCode=" + param.getProjectCode() + ")";
}
if (param.getSuccess() == null) {
log.warn("项目金蝶同步结果推送 success 字段缺失:projectCode={},报文已留痕", projectApply.getProjectCode());
writeCallbackLog(projectApply, HcsSyncConstant.CHECK_RESULT_SKIP, "项目金蝶同步结果推送 success 字段缺失:" + raw);
return "已留痕:success 字段缺失(projectCode=" + projectApply.getProjectCode() + ")";
}
if (param.getSuccess()) {
// 成功:回填金蝶项目ID/编号,同步结果信息随 hcs_sync_msg 留痕
projectApply.setKingdeeId(param.getKingdeeId());
projectApply.setKingdeeNumber(param.getProjectNumber());
projectApply.setHcsSyncMsg(HcsSyncConstant.truncateMsg("项目金蝶同步结果回调:金蝶同步成功,kingdeeId=" + param.getKingdeeId()
+ ",projectNumber=" + param.getProjectNumber()));
appendKingdeeResultRecord(projectApply, "金蝶同步成功:金蝶项目ID=" + param.getKingdeeId()
+ ",金蝶项目编号=" + param.getProjectNumber());
projectApplyMapper.updateById(projectApply);
writeCallbackLog(projectApply, HcsSyncConstant.CHECK_RESULT_PASS, "项目金蝶同步结果推送:" + raw);
log.info("项目金蝶同步结果推送处理完成:projectCode={},结果=success,kingdeeId={}", projectApply.getProjectCode(), param.getKingdeeId());
return "金蝶同步结果已处理:success";
}
// 失败:记录失败原因(金蝶同步在合规侧完成,TMS 不重推,失败重试由合规侧负责)
projectApply.setHcsSyncMsg(HcsSyncConstant.truncateMsg("项目金蝶同步结果回调:金蝶同步失败:" + param.getReason()));
appendKingdeeResultRecord(projectApply, "金蝶同步失败:" + param.getReason());
projectApplyMapper.updateById(projectApply);
writeCallbackLog(projectApply, HcsSyncConstant.CHECK_RESULT_FAIL, "项目金蝶同步结果推送:" + raw);
log.info("项目金蝶同步结果推送处理完成:projectCode={},结果=fail,reason={}", projectApply.getProjectCode(), param.getReason());
return "金蝶同步结果已处理:fail";
}
/**
* 金蝶同步结果回填变更记录(changeRecordJson 追加一条;系统回调无登录用户,操作人记来源标识)
*/
private void appendKingdeeResultRecord(ProjectApply projectApply, String changeContent) {
List<Object> records = StringUtil.isBlank(projectApply.getChangeRecordJson())
? new ArrayList<>() : new ArrayList<>(JSONUtil.toList(projectApply.getChangeRecordJson(), Object.class));
Map<String, Object> record = new LinkedHashMap<>();
record.put("changeDate", LocalDate.now().toString());
record.put("handlerUserName", "合规系统回调");
record.put("changeType", "金蝶同步结果");
record.put("changeContent", changeContent);
record.put("status", projectApply.getApprovalStatus());
record.put("statusName", approvalStatusName(projectApply.getApprovalStatus()));
records.add(record);
projectApply.setChangeRecordJson(JSONUtil.toJsonStr(records));
}
/**
* 审批状态中文名(变更记录展示用,未匹配回退原值)
*/
private String approvalStatusName(String approvalStatus) {
if (StringUtil.isBlank(approvalStatus)) {
return null;
}
return switch (approvalStatus) {
case "draft" -> "草稿";
case "reviewing" -> "审批中";
case "withdrawn" -> "已撤回";
case "approved" -> "审批通过";
case "rejected" -> "已驳回";
case "change_reviewing" -> "变更审批中";
case "change_rejected" -> "变更驳回";
case "change_approved" -> "变更审批通过";
case "voided" -> "已作废";
default -> approvalStatus;
};
}
/**
* 按 ERP 项目编号定位项目(合规推送 projectCode,对应 C102 fd_num)
*/
private ProjectApply locateProjectByCode(String projectCode) {
if (StringUtil.isBlank(projectCode)) {
return null;
}
return projectApplyMapper.selectOne(Wrappers.<ProjectApply>lambdaQuery()
.eq(ProjectApply::getProjectCode, projectCode.trim())
.last("limit 1"));
}
/**
* 项目金蝶同步结果推送留痕(blade_hcs_check_log,biz_type=project,项目未定位到时 bizId 为空,异常不影响主流程)
*/
private void writeCallbackLog(ProjectApply projectApply, String result, String msg) {
try {
HcsContractCheckLog checkLog = new HcsContractCheckLog();
if (projectApply != null) {
checkLog.setTenantId(projectApply.getTenantId());
checkLog.setBizId(projectApply.getId());
}
checkLog.setBizType(HcsSyncConstant.BIZ_TYPE_PROJECT);
checkLog.setCheckType(HcsSyncConstant.CHECK_TYPE_KINGDEE);
checkLog.setResult(result);
checkLog.setMsg(StringUtil.left(msg, HcsSyncConstant.SYNC_MSG_MAX_LENGTH));
checkLog.setCreateTime(LocalDateTime.now());
hcsContractCheckLogMapper.insert(checkLog);
} catch (Exception exception) {
log.error("项目金蝶同步结果推送留痕写入失败:projectCode={}", projectApply == null ? null : projectApply.getProjectCode(), exception);
}
}
/**
* 单条手动重推:重置为待同步并清零重试计数后立即推送(页面"推送合规/重推"按钮入口)
*
@@ -0,0 +1,78 @@
/**
* 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.hcs.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 项目金蝶同步完成后合规系统回传 TMS 的结果报文(D902,POST /hcs/projectLegal/result,iPaaS 网关 /gwzh/HTHG/projectLegal/result)
* <p>
* 定位项目用 projectCode(ERP 项目编号,对应 C102 请求中的 fd_num),
* requestId 仅是 C102 请求头 X-ERP-Request-Id 原样回传、不能用于定位;
* 未知或过期的 requestId 合规侧返回失败。
*
* @author Chill
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class HcsProjectLegalResultDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ERP 项目编号(TMS blade_project_apply.project_code,对应 C102 请求中的 fd_num,定位项目用)
*/
private String projectCode;
/**
* C102 请求头 X-ERP-Request-Id 的值,原样返回(不用于定位)
*/
private String requestId;
/**
* 金蝶同步成功传 true,失败传 false
*/
private Boolean success;
/**
* 金蝶项目 ID;成功时用于回填保存
*/
private String kingdeeId;
/**
* 金蝶项目编号;成功时用于回填保存
*/
private String projectNumber;
/**
* 金蝶同步失败原因;失败时建议填写
*/
private String reason;
/**
* 来源系统标识,约定传 WCCK(最长 64 字符)
*/
private String sourceSystem;
}
+10 -2
View File
@@ -237,11 +237,13 @@ blade:
- /feign/client/businessProcess/getProcessInfo
- /feign/client/customerArchive/syncProcessNode
- /feign/client/mkProcess/**
# HCS 合同/付款特批结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
# HCS 合同/付款特批结果回传 + 项目金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
- /blade-transport/hcs/contractLegal/result
- /hcs/contractLegal/result
- /blade-transport/hcs/paymentLegal/result
- /hcs/paymentLegal/result
- /blade-transport/hcs/projectLegal/result
- /hcs/projectLegal/result
#授权认证配置
auth:
- method: ALL
@@ -269,7 +271,7 @@ blade:
- method: POST
pattern: /kingdee-bfi/**
expression: "permitAll()"
# HCS 合同/付款特批结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
# HCS 合同/付款特批结果回传 + 项目金蝶同步结果回传:合规系统经 iPaaS 网关无令牌调用,免登免授权
- method: POST
pattern: /blade-transport/hcs/contractLegal/result
expression: "permitAll()"
@@ -282,6 +284,12 @@ blade:
- method: POST
pattern: /hcs/paymentLegal/result
expression: "permitAll()"
- method: POST
pattern: /blade-transport/hcs/projectLegal/result
expression: "permitAll()"
- method: POST
pattern: /hcs/projectLegal/result
expression: "permitAll()"
#基础认证配置
basic:
- method: ALL
@@ -0,0 +1,30 @@
-- HCS 金蝶同步结果回调回填字段:
-- blade_project_apply 追加金蝶项目ID/编号(D902 项目金蝶同步结果回调 projectLegal/result 回填);
-- blade_contract_manage 追加金蝶合同ID(合同特批金蝶同步结果回调 contractLegal/result 回填)。
-- 通过 information_schema 判断字段是否存在,可重复执行。
SET @db_name = DATABASE();
-- ==================== blade_project_apply(D902 项目金蝶同步结果回填) ====================
SET @sql = IF(
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = @db_name AND table_name = 'blade_project_apply' AND column_name = 'kingdee_id'),
'SELECT 1',
'ALTER TABLE blade_project_apply ADD COLUMN kingdee_id varchar(64) DEFAULT NULL COMMENT ''金蝶项目ID(D902 回调回填)'''
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @sql = IF(
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = @db_name AND table_name = 'blade_project_apply' AND column_name = 'kingdee_number'),
'SELECT 1',
'ALTER TABLE blade_project_apply ADD COLUMN kingdee_number varchar(64) DEFAULT NULL COMMENT ''金蝶项目编号(D902 回调回填)'''
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ==================== blade_contract_manage(contractLegal/result 金蝶同步结果回填) ====================
SET @sql = IF(
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = @db_name AND table_name = 'blade_contract_manage' AND column_name = 'kingdee_id'),
'SELECT 1',
'ALTER TABLE blade_contract_manage ADD COLUMN kingdee_id varchar(64) DEFAULT NULL COMMENT ''金蝶合同ID(contractLegal/result 回调回填)'''
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;