fix: remove XFT use-car submissions

This commit is contained in:
2026-08-20 01:21:59 +00:00
parent 7fbd13bf20
commit dc86130711
9 changed files with 45 additions and 28 deletions
+18 -10
View File
@@ -18,12 +18,18 @@ const DINGTALK_SUBMISSION_TEMPLATES = {
"捷康_费用报销": ["差旅费用报销_捷康", "业务招待费用报销_捷康", "业务招待申请_捷康"],
} as const;
const DINGTALK_SUBMISSION_CATEGORIES = Object.keys(DINGTALK_SUBMISSION_TEMPLATES);
const ALLOWED_XFT_SUBMISSION_KINDS = new Set<XftSubmissionKind>([
"travel_apply", "expense_apply", "entertainment_apply", "common_apply",
"common_reimburse", "travel_reimburse",
]);
function assertXftSubmissionTemplateAllowed(template: XftSubmissionTemplate): void {
if (!ALLOWED_XFT_SUBMISSION_KINDS.has(template.kind)) {
throw new ApprovalSafetyError("该薪福通模板不在 MCP 支持的发起范围内,请重新列出可发起模板");
}
}
function xftSubmissionCapability(kind: XftSubmissionKind): Record<string, unknown> {
if (kind === "use_car_apply") return {
status: "client_only",
reason: "正式创建接口要求用车信息对象,但当前文档与实时模板未提供可验证的业务字段结构",
kind,
};
return {
status: "api_supported_with_constraints",
finalValidation: "薪福通创建接口会在正式提交时完成预算、权限和流程业务校验;创建后网关实时核验结果,流程可能进入待审批,也可能按企业规则即时完成",
@@ -370,7 +376,8 @@ export class UnifiedApprovalService {
if (source !== "dingtalk") {
if (!this.xft) sourceStatus.xft = { status: "disabled" };
else tasks.push(this.xft.listSubmissionTemplates(user, limit, query).then((templates) => {
xftItems = templates.map((template) => ({
const supported = templates.filter((template) => ALLOWED_XFT_SUBMISSION_KINDS.has(template.kind));
xftItems = supported.map((template) => ({
templateId: this.signer.sign({
kind: "submission_template", userId: user.userId, source: "xft", xftTemplate: template,
exp: expiresInMinutes(30),
@@ -380,7 +387,7 @@ export class UnifiedApprovalService {
kind: template.kind,
eventType: template.eventType,
}));
sourceStatus.xft = { status: "ok", count: templates.length };
sourceStatus.xft = { status: "ok", count: supported.length };
}).catch((error) => { sourceStatus.xft = { status: "unavailable", message: errorMessage(error) }; }));
}
await Promise.all(tasks);
@@ -394,6 +401,7 @@ export class UnifiedApprovalService {
const template = this.decodeSubmissionTemplate(user, templateId);
if (template.source === "xft") {
if (!this.xft || !template.xftTemplate) throw new ApprovalSafetyError("薪福通提单源未启用");
assertXftSubmissionTemplateAllowed(template.xftTemplate);
const schema = await this.xft.getSubmissionSchema(user, template.xftTemplate);
const requiredClientOnly = schema.fields.filter(requiredXftFieldNeedsNativeClient);
const capability = requiredClientOnly.length ? {
@@ -445,6 +453,7 @@ export class UnifiedApprovalService {
if (template.source !== "xft" || !this.xft || !template.xftTemplate) {
throw new ApprovalSafetyError("实时提单选项查询当前仅用于薪福通模板");
}
assertXftSubmissionTemplateAllowed(template.xftTemplate);
return {
templateId,
source: "xft" as const,
@@ -464,6 +473,7 @@ export class UnifiedApprovalService {
let fingerprint: string;
if (template.source === "xft") {
if (!this.xft || !template.xftTemplate) throw new ApprovalSafetyError("薪福通提单源未启用");
assertXftSubmissionTemplateAllowed(template.xftTemplate);
const schema = await this.xft.getSubmissionSchema(user, template.xftTemplate);
validateXftSubmissionValues(template.xftTemplate.kind, input.values, schema.fields);
const identityValidation = await this.xft.validateSubmissionIdentity(user);
@@ -558,6 +568,7 @@ export class UnifiedApprovalService {
try {
if (confirmation.source === "xft") {
if (!this.xft || !confirmation.xftTemplate) throw new ApprovalSafetyError("薪福通提单源未启用");
assertXftSubmissionTemplateAllowed(confirmation.xftTemplate);
const schema = await this.xft.getSubmissionSchema(user, confirmation.xftTemplate);
if (hashJson({ template: schema.template, fields: schema.fields }) !== confirmation.templateFingerprint) {
throw new ApprovalSafetyError("薪福通表单在确认后发生变化,请重新准备并确认");
@@ -2026,9 +2037,6 @@ function validateXftSubmissionValues(
values: Record<string, unknown>,
customFields: XftSubmissionField[],
): void {
if (kind === "use_car_apply") {
throw new ApprovalSafetyError("用车申请的正式接口字段结构当前无法可靠构造,请在薪福通客户端发起");
}
const required: Record<XftSubmissionKind, string[]> = {
travel_apply: ["businessTrip"], expense_apply: ["applyExpenses"],
entertainment_apply: ["entertainmentApplyApiCreateDTO"], common_apply: [], use_car_apply: ["useCarInfo"],
+1 -1
View File
@@ -329,7 +329,7 @@ export class XftOpenApiClient implements XftApprovalProvider {
for (const item of list) {
if (stringAt(item, ["eventStatus"]) !== "1") continue;
const template = normalizeSubmissionTemplate(item);
if (!template || !filterQuery([template], search).length) continue;
if (!template || template.kind === "use_car_apply" || !filterQuery([template], search).length) continue;
output.push(template);
if (output.length >= limit) break;
}