PC6 完善 PC 工作台与审批信息架构

这个提交包含在:
2026-05-12 02:34:15 +08:00
父节点 e7bf57380e
当前提交 aec660a8fe
共修改 13 个文件,包含 518 行新增和 74 行删除
+71 -1
查看文件
@@ -164,6 +164,7 @@ async function buildApp(options = {}) {
);
const travelRows = options.travelRows ?? [];
const permissionCodes = options.permissionCodes ?? ["expense.view_own"];
const roleCodes = options.roleCodes ?? [];
const employeeId = options.employeeId ?? "employee-1";
resolvePresenceForEmployee.mockImplementation(async (_prisma, targetEmployeeId) => {
@@ -189,6 +190,15 @@ async function buildApp(options = {}) {
assetCard: {
count: vi.fn(async () => 1),
},
paymentBatch: {
count: vi.fn(async () => options.pendingFinanceBatchCount ?? 0),
},
paymentBatchItem: {
count: vi.fn(async () => options.failedFinanceItemCount ?? 0),
},
entityRiskFlag: {
count: vi.fn(async () => options.financeRiskCount ?? 0),
},
employee: {
count: vi.fn(async () => employees.length),
findMany: vi.fn(async () => employees),
@@ -295,7 +305,7 @@ async function buildApp(options = {}) {
name: "测试用户",
department_id: "department-1",
permissionCodes,
roleCodes: [],
roleCodes,
};
});
app.decorate(
@@ -472,4 +482,64 @@ describe("portal routes", () => {
await app.close();
});
it("returns roleCapabilities and financeSummary only for finance roles", async () => {
featureFlagState.paymentBatch = true;
const { app } = await buildApp({
roleCodes: ["employee", "finance"],
permissionCodes: ["expense.view_own", "payment.batch.manage", "expense.finance.pay", "expense.approve"],
pendingFinanceBatchCount: 3,
failedFinanceItemCount: 2,
});
const response = await app.inject({
method: "GET",
url: "/api/portal/home",
headers: { authorization: "Bearer test" },
});
expect(response.statusCode).toBe(200);
const payload = response.json().data;
expect(payload.roleCapabilities).toMatchObject({
canApproveTasks: true,
canUseFinance: true,
canManageSystem: false,
});
expect(payload.financeSummary).toEqual({
pendingBatchCount: 3,
failedItemCount: 2,
riskCount: 0,
href: "/ap-operations",
});
await app.close();
});
it("does not expose financeSummary to admin-only accounts", async () => {
featureFlagState.paymentBatch = true;
const { app } = await buildApp({
roleCodes: ["admin"],
permissionCodes: ["*"],
pendingFinanceBatchCount: 3,
failedFinanceItemCount: 2,
});
const response = await app.inject({
method: "GET",
url: "/api/portal/home",
headers: { authorization: "Bearer test" },
});
expect(response.statusCode).toBe(200);
const payload = response.json().data;
expect(payload.roleCapabilities).toMatchObject({
canManageSystem: true,
canUseFinance: false,
isAdminOnly: true,
});
expect(payload.financeSummary).toBeNull();
expect(payload.cards.map((card) => card.key)).not.toContain("pending_approvals");
await app.close();
});
});