feat(plan): listPlanUsers with role/permission filter

This commit is contained in:
BOHA
2026-06-05 12:13:16 +02:00
parent f79967d433
commit 42f9561337
2 changed files with 68 additions and 1 deletions

View File

@@ -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);
});
});

View File

@@ -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<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,
}));
}