feat: expose readable submission choices
This commit is contained in:
+62
-2
@@ -5,7 +5,7 @@ import { deflateRawSync } from "node:zlib";
|
||||
import type { AppConfig } from "../src/config.js";
|
||||
import { UnifiedApprovalService } from "../src/unified-approval.js";
|
||||
import type { ApprovalService } from "../src/approval-service.js";
|
||||
import type { XftApprovalProvider, XftSubmissionTemplate } from "../src/xft.js";
|
||||
import type { XftApprovalProvider, XftSubmissionField, XftSubmissionTemplate } from "../src/xft.js";
|
||||
|
||||
function config(): AppConfig {
|
||||
return {
|
||||
@@ -1131,10 +1131,70 @@ test("Xft preparation reports standard and live custom required fields together"
|
||||
const templateId = String((await service.listSubmissionTemplates(user, "xft", 10)).items[0]?.templateId);
|
||||
await assert.rejects(
|
||||
service.prepareSubmission(user, { templateId, values: {} }),
|
||||
/业务字段:applyExpenses;自定义字段:招待事由(C1)、招待日期(C2)/,
|
||||
/业务字段:事前申请费用;自定义字段:招待事由、招待日期/,
|
||||
);
|
||||
});
|
||||
|
||||
test("Xft preparation blocks fields whose user-readable choices cannot be resolved", async () => {
|
||||
const template: XftSubmissionTemplate = {
|
||||
eventSeqId: "1", eventNumber: "XFT-E", eventName: "费用申请单",
|
||||
eventType: "EXPENSE_APPLY", kind: "expense_apply",
|
||||
};
|
||||
let fields: XftSubmissionField[] = [{
|
||||
fieldNumber: "P1", name: "参与人员", type: "PERSON", required: true,
|
||||
selectionCapability: { status: "client_only", reason: "没有按姓名查询人员的安全接口" },
|
||||
}];
|
||||
const xft = {
|
||||
async listSubmissionTemplates() { return [template]; },
|
||||
async getSubmissionSchema() { return { template, fields, inputContract: {}, diagnostics: {} }; },
|
||||
async validateSubmissionIdentity() { return { validated: true, diagnostics: {} }; },
|
||||
};
|
||||
const service = new UnifiedApprovalService(config(), {} as ApprovalService, xft as never);
|
||||
const user = { userId: "user-1" };
|
||||
const templateId = String((await service.listSubmissionTemplates(user, "xft", 10)).items[0]?.templateId);
|
||||
const schema = await service.getSubmissionSchema(user, templateId);
|
||||
assert.equal(schema.submissionCapability.status, "client_only");
|
||||
assert.match(String(schema.submissionCapability.reason), /参与人员/);
|
||||
await assert.rejects(service.prepareSubmission(user, {
|
||||
templateId, values: { applyExpenses: [{ expenseNumber: "MEAL", amount: 10 }] },
|
||||
}), /无法安全填写的必填项:参与人员.*薪福通客户端/);
|
||||
|
||||
fields = [{
|
||||
fieldNumber: "P1", name: "参与人员", type: "PERSON", required: false,
|
||||
selectionCapability: { status: "client_only", reason: "没有按姓名查询人员的安全接口" },
|
||||
}];
|
||||
await assert.rejects(service.prepareSubmission(user, {
|
||||
templateId,
|
||||
values: {
|
||||
applyExpenses: [{ expenseNumber: "MEAL", amount: 10 }],
|
||||
customFieldValues: [{ fieldNumber: "P1", fieldValue: "[\"EMP-1\"]" }],
|
||||
},
|
||||
}), /参与人员.*无法通过 MCP.*薪福通客户端/);
|
||||
});
|
||||
|
||||
test("Xft preparation refuses optional internal-value fields instead of asking the user for codes", async () => {
|
||||
const template: XftSubmissionTemplate = {
|
||||
eventSeqId: "1", eventNumber: "XFT-T", eventName: "出差申请单",
|
||||
eventType: "TRAVEL_APPLY", kind: "travel_apply",
|
||||
};
|
||||
const xft = {
|
||||
async listSubmissionTemplates() { return [template]; },
|
||||
async getSubmissionSchema() { return { template, fields: [], inputContract: {}, diagnostics: {} }; },
|
||||
};
|
||||
const service = new UnifiedApprovalService(config(), {} as ApprovalService, xft as never);
|
||||
const user = { userId: "user-1" };
|
||||
const templateId = String((await service.listSubmissionTemplates(user, "xft", 10)).items[0]?.templateId);
|
||||
await assert.rejects(service.prepareSubmission(user, {
|
||||
templateId,
|
||||
values: {
|
||||
businessTrip: { businessTripDetails: [{
|
||||
departCityCode: "1", destinationCityCode: "2", beginTime: "2026-08-12 09:00", endTime: "2026-08-12 18:00",
|
||||
}] },
|
||||
peerEmpNumbers: ["EMP-1"],
|
||||
},
|
||||
}), /同行人员.*不要提供内部编码或 ID/);
|
||||
});
|
||||
|
||||
test("submission rejects caller-supplied applicant identity", async () => {
|
||||
const ding = {
|
||||
async listSubmissionTemplates() { return [{ processCode: "PROC-1", name: "出差申请单_北极大", dirName: "北极大_人事假勤" }]; },
|
||||
|
||||
Reference in New Issue
Block a user