feat(plan): listPlanUsers with role/permission filter
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest";
|
import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest";
|
||||||
import prisma from "../config/database";
|
import prisma from "../config/database";
|
||||||
import { resolveCell, resolveGrid } from "../services/plan.service";
|
import {
|
||||||
|
resolveCell,
|
||||||
|
resolveGrid,
|
||||||
|
listPlanUsers,
|
||||||
|
} from "../services/plan.service";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Test fixtures
|
// Test fixtures
|
||||||
@@ -170,3 +174,16 @@ describe("plan.service.resolveGrid", () => {
|
|||||||
expect(cells[adminUserId]["2099-06-03"]?.note).toBe(`${N}A`);
|
expect(cells[adminUserId]["2099-06-03"]?.note).toBe(`${N}A`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// listPlanUsers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe("plan.service.listPlanUsers", () => {
|
||||||
|
it("returns at least the admin user", async () => {
|
||||||
|
const users = await listPlanUsers();
|
||||||
|
const found = users.find((u) => u.id === adminUserId);
|
||||||
|
expect(found).toBeDefined();
|
||||||
|
expect(found?.has_attendance_record).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -195,3 +195,53 @@ export async function resolveGrid(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PlanUser {
|
||||||
|
id: number;
|
||||||
|
full_name: string;
|
||||||
|
username: string;
|
||||||
|
role_name: string | null;
|
||||||
|
is_active: boolean;
|
||||||
|
has_attendance_record: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return users that should appear as columns in the plan grid:
|
||||||
|
* everyone with the `attendance.record` permission, ordered by
|
||||||
|
* role/team name then full_name. Admins are included by default.
|
||||||
|
*
|
||||||
|
* The `users` model uses the relation field name `roles` (NOT `role`)
|
||||||
|
* for the foreign key to `roles.id`. The roles-to-permissions join
|
||||||
|
* table is `role_permissions`, which has a relation `permissions`.
|
||||||
|
*/
|
||||||
|
export async function listPlanUsers(): Promise<PlanUser[]> {
|
||||||
|
const rows = await prisma.users.findMany({
|
||||||
|
where: {
|
||||||
|
is_active: true,
|
||||||
|
roles: {
|
||||||
|
role_permissions: {
|
||||||
|
some: { permissions: { name: "attendance.record" } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
roles: {
|
||||||
|
select: { name: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orderBy: [
|
||||||
|
{ roles: { name: "asc" } },
|
||||||
|
{ last_name: "asc" },
|
||||||
|
{ first_name: "asc" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return rows.map((u) => ({
|
||||||
|
id: u.id,
|
||||||
|
full_name: `${u.first_name} ${u.last_name}`.trim(),
|
||||||
|
username: u.username,
|
||||||
|
role_name: u.roles?.name ?? null,
|
||||||
|
is_active: u.is_active ?? true,
|
||||||
|
has_attendance_record: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user