R45 A2-A7 员工附件与培训证书管理

这个提交包含在:
2026-03-29 13:31:53 +08:00
父节点 d11f5593d1
当前提交 48f395e18d
共修改 14 个文件,包含 2291 行新增和 22 行删除
@@ -21,6 +21,12 @@ async function buildApp({ permissionCodes = ["system.users"], stats } = {}) {
{ id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", name: "研发部" },
]);
const contractCount = vi.fn().mockResolvedValue(2);
const certificateGroupBy = vi.fn().mockResolvedValue([
{ employee_id: "emp-1" },
{ employee_id: "emp-2" },
{ employee_id: "emp-3" },
]);
const certificateCount = vi.fn().mockResolvedValue(4);
app.decorate("prisma", {
employee: {
@@ -36,6 +42,11 @@ async function buildApp({ permissionCodes = ["system.users"], stats } = {}) {
count: stats?.employeeContractCount ?? contractCount,
findMany: vi.fn().mockResolvedValue([]),
},
employeeCertificate: {
groupBy: stats?.employeeCertificateGroupBy ?? certificateGroupBy,
count: stats?.employeeCertificateCount ?? certificateCount,
findMany: vi.fn().mockResolvedValue([]),
},
});
app.decorate("authenticate", async (request) => {
request.employee = {
@@ -68,12 +79,12 @@ async function buildApp({ permissionCodes = ["system.users"], stats } = {}) {
});
await app.register(employeesRoutes, { prefix: "/api" });
return { app, employeeGroupBy, employeeCount, departmentFindMany, contractCount };
return { app, employeeGroupBy, employeeCount, departmentFindMany, contractCount, certificateGroupBy, certificateCount };
}
describe("employees stats route", () => {
it("returns aggregated employee stats for read-only viewers", async () => {
const { app, employeeGroupBy, employeeCount, departmentFindMany, contractCount } = await buildApp({
const { app, employeeGroupBy, employeeCount, departmentFindMany, contractCount, certificateGroupBy, certificateCount } = await buildApp({
permissionCodes: ["report.dashboard.view"],
});
@@ -92,10 +103,18 @@ describe("employees stats route", () => {
expect(payload.data.recentMovements.hires).toBe(3);
expect(payload.data.recentMovements.departures).toBe(1);
expect(payload.data.expiringContracts.count).toBe(2);
expect(payload.data.certificateSummary).toEqual({
dateFrom: payload.data.asOfDate,
dateTo: expect.any(String),
validHolderCount: 3,
expiringSoonCount: 4,
});
expect(employeeGroupBy).toHaveBeenCalledTimes(2);
expect(employeeCount).toHaveBeenCalledTimes(2);
expect(departmentFindMany).toHaveBeenCalledTimes(1);
expect(contractCount).toHaveBeenCalledTimes(1);
expect(certificateGroupBy).toHaveBeenCalledTimes(1);
expect(certificateCount).toHaveBeenCalledTimes(1);
await app.close();
});