diff --git a/src/__tests__/plan.test.ts b/src/__tests__/plan.test.ts index a73853b..0135a83 100644 --- a/src/__tests__/plan.test.ts +++ b/src/__tests__/plan.test.ts @@ -1,6 +1,10 @@ import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest"; import prisma from "../config/database"; -import { resolveCell, resolveGrid } from "../services/plan.service"; +import { + resolveCell, + resolveGrid, + listPlanUsers, +} from "../services/plan.service"; // --------------------------------------------------------------------------- // Test fixtures @@ -170,3 +174,16 @@ describe("plan.service.resolveGrid", () => { 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); + }); +}); diff --git a/src/services/plan.service.ts b/src/services/plan.service.ts index f6adc95..0cf1fad 100644 --- a/src/services/plan.service.ts +++ b/src/services/plan.service.ts @@ -195,3 +195,53 @@ export async function resolveGrid( 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 { + 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, + })); +}