WARCH2 增加企微审批历史只读查询
这个提交包含在:
@@ -1,5 +1,6 @@
|
||||
const {
|
||||
normalizeApprovalDetailPayload,
|
||||
listApprovalArchives,
|
||||
persistApprovalDetail,
|
||||
publicArchiveSummary,
|
||||
recordApprovalCallbackEvent,
|
||||
@@ -132,6 +133,78 @@ describe("wecomApprovalArchive", () => {
|
||||
expect(JSON.stringify(summary)).not.toContain(SENSITIVE_TEMPLATE_ID);
|
||||
});
|
||||
|
||||
it("lists query archives with whitelist-only DTO fields", async () => {
|
||||
const archive = {
|
||||
id: "archive-1",
|
||||
sp_no: SENSITIVE_SP_NO,
|
||||
template_id: SENSITIVE_TEMPLATE_ID,
|
||||
template_type: "leave",
|
||||
sp_name: "OA-POC-请假",
|
||||
normalized_status: "approved",
|
||||
applicant_employee_id: null,
|
||||
applicant_external_user_id: SENSITIVE_USER_ID,
|
||||
applied_at: new Date("2026-05-19T08:00:00.000Z"),
|
||||
submitted_at: new Date("2026-05-19T08:00:00.000Z"),
|
||||
completed_at: new Date("2026-05-19T09:00:00.000Z"),
|
||||
status_observed_at: new Date("2026-05-19T09:00:00.000Z"),
|
||||
last_callback_at: null,
|
||||
last_compensation_at: new Date("2026-05-19T10:00:00.000Z"),
|
||||
last_source: "compensation_pull",
|
||||
readability_status: "PASS_READABLE",
|
||||
single_tap_approve_risk: true,
|
||||
template_adjustment_required: false,
|
||||
source_summary: { raw: "raw payload should not leak" },
|
||||
applicant: null,
|
||||
participants: [],
|
||||
actions: [],
|
||||
field_summaries: [{
|
||||
id: "field-1",
|
||||
field_key: "reason",
|
||||
field_index: 1,
|
||||
field_name: "请假原因",
|
||||
field_type: "Textarea",
|
||||
normalized_value: SENSITIVE_REASON,
|
||||
value_preview: SENSITIVE_REASON.slice(0, 8),
|
||||
sensitive_level: "restricted",
|
||||
display_allowed: false,
|
||||
}],
|
||||
reconcile_findings: [{
|
||||
id: "finding-1",
|
||||
finding_type: "callback_missing_for_pulled_detail",
|
||||
status: "open",
|
||||
severity: "info",
|
||||
source: "compensation_compare",
|
||||
description: SENSITIVE_REASON,
|
||||
detected_at: new Date("2026-05-19T11:00:00.000Z"),
|
||||
resolved_at: null,
|
||||
}],
|
||||
};
|
||||
const prisma = {
|
||||
employee: { findMany: vi.fn(async () => []) },
|
||||
wecomApprovalArchive: {
|
||||
count: vi.fn(async () => 1),
|
||||
findMany: vi.fn(async () => [archive]),
|
||||
},
|
||||
};
|
||||
|
||||
const result = await listApprovalArchives({
|
||||
prisma,
|
||||
actor: { id: "hr-1", roleCodes: ["hr"], permissionCodes: [] },
|
||||
query: { scope: "all" },
|
||||
});
|
||||
|
||||
expect(result.items).toHaveLength(1);
|
||||
const text = JSON.stringify(result);
|
||||
expect(text).not.toContain(SENSITIVE_SP_NO);
|
||||
expect(text).not.toContain(SENSITIVE_TEMPLATE_ID);
|
||||
expect(text).not.toContain(SENSITIVE_USER_ID);
|
||||
expect(text).not.toContain(SENSITIVE_REASON);
|
||||
expect(text).not.toContain("normalized_value");
|
||||
expect(text).not.toContain("value_preview");
|
||||
expect(text).not.toContain("source_summary");
|
||||
expect(text).not.toContain("description");
|
||||
});
|
||||
|
||||
it("persists full keys internally but returns redacted output", async () => {
|
||||
const prisma = buildMockPrisma();
|
||||
const result = await persistApprovalDetail({
|
||||
|
||||
在新工单中引用
屏蔽一个用户