R23-1/R23-2/R23-4:完成项目沟通回填与收口治理后端
这个提交包含在:
@@ -117,6 +117,61 @@ describe("IM enqueue", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("redacts project follow-up notifications under public security hardening", async () => {
|
||||
const tx = {
|
||||
employeeRole: {
|
||||
findMany: vi.fn().mockResolvedValue([{ role_code: "manager" }]),
|
||||
},
|
||||
notificationChannel: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "channel-project",
|
||||
channel_type: "wecom",
|
||||
name: "project-workflow",
|
||||
enabled: true,
|
||||
config_json: {
|
||||
routing: {
|
||||
roleCodes: ["manager"],
|
||||
domainScopes: ["workflow"],
|
||||
allowedTypes: ["workflow.task_assigned"],
|
||||
},
|
||||
},
|
||||
template_json: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
integrationOutbox: {
|
||||
findUnique: vi.fn().mockResolvedValue(null),
|
||||
create: vi.fn().mockImplementation(async ({ data }) => ({ id: `${data.dedupe_key}-id`, status: "pending" })),
|
||||
},
|
||||
};
|
||||
|
||||
const result = await enqueueImNotifications(tx, {
|
||||
config: {
|
||||
imNotifierEnabled: true,
|
||||
integrationOutboxMaxAttempts: 5,
|
||||
appOrigin: "https://app.example.com",
|
||||
jwtSecret: "test-secret",
|
||||
publicSecurityHardeningEnabled: true,
|
||||
},
|
||||
logger: { warn: vi.fn() },
|
||||
recipientEmployeeIds: ["employee-1"],
|
||||
type: "workflow.task_assigned",
|
||||
title: "项目收口提醒:合同与沟通记录待补齐",
|
||||
body: "请补齐沟通摘要、收口备注与合同要点。",
|
||||
targetType: "workflow_task",
|
||||
targetId: "task-project-1",
|
||||
targetPath: "/projects/11111111-1111-4111-8111-111111111111",
|
||||
entityType: "project",
|
||||
entityId: "11111111-1111-4111-8111-111111111111",
|
||||
actorId: "actor-1",
|
||||
});
|
||||
|
||||
expect(result.queued).toBe(1);
|
||||
expect(tx.integrationOutbox.create.mock.calls[0][0].data.payload.title).toBe("有项目待收口");
|
||||
expect(tx.integrationOutbox.create.mock.calls[0][0].data.payload.body).toBe("");
|
||||
});
|
||||
|
||||
it("safely skips when no channel matches", async () => {
|
||||
const tx = {
|
||||
employeeRole: {
|
||||
|
||||
在新工单中引用
屏蔽一个用户