PC6 完善 PC 工作台与审批信息架构
这个提交包含在:
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
在新工单中引用
屏蔽一个用户