mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 13:05:44 +00:00
feat: ( iam ) add Station Master and Ticket Officer roles with positions
This commit is contained in:
@@ -42,6 +42,7 @@ export class EdrPassengerOrgSeeder {
|
|||||||
await this.ensureRoles(manager, EDR_PASSENGER_ROLES);
|
await this.ensureRoles(manager, EDR_PASSENGER_ROLES);
|
||||||
await this.ensureRolePermissions(manager, EDR_PASSENGER_ROLES);
|
await this.ensureRolePermissions(manager, EDR_PASSENGER_ROLES);
|
||||||
await this.ensureSuperAdminPermissions(manager);
|
await this.ensureSuperAdminPermissions(manager);
|
||||||
|
await this.ensurePositions(manager, organization.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.logger.log(`Ensured EDR passenger organization seed for '${EDR_ORG_KEY}'`);
|
this.logger.log(`Ensured EDR passenger organization seed for '${EDR_ORG_KEY}'`);
|
||||||
@@ -122,21 +123,51 @@ export class EdrPassengerOrgSeeder {
|
|||||||
const roleByKey = new Map(roles.map((r) => [r.key, r]));
|
const roleByKey = new Map(roles.map((r) => [r.key, r]));
|
||||||
const permByKey = new Map(permissions.map((p) => [p.key, p]));
|
const permByKey = new Map(permissions.map((p) => [p.key, p]));
|
||||||
|
|
||||||
const links = seedRoles.flatMap((seedRole) => {
|
let totalUpserted = 0;
|
||||||
|
let totalPruned = 0;
|
||||||
|
|
||||||
|
for (const seedRole of seedRoles) {
|
||||||
const role = roleByKey.get(seedRole.key);
|
const role = roleByKey.get(seedRole.key);
|
||||||
if (!role) throw new Error(`missing_role:${seedRole.key}`);
|
if (!role) throw new Error(`missing_role:${seedRole.key}`);
|
||||||
|
|
||||||
return seedRole.permissionKeys.map((key) => {
|
const desiredPermissionIds = new Set(
|
||||||
const perm = permByKey.get(key);
|
seedRole.permissionKeys.map((key) => {
|
||||||
if (!perm) throw new Error(`missing_permission:${key}`);
|
const perm = permByKey.get(key);
|
||||||
return { roleId: role.id, permissionId: perm.id };
|
if (!perm) throw new Error(`missing_permission:${key}`);
|
||||||
});
|
return perm.id as string;
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
await manager.getRepository(RolePermission).upsert(links, {
|
// Remove links that are no longer in this role's preset
|
||||||
conflictPaths: { roleId: true, permissionId: true },
|
const existing = await manager.getRepository(RolePermission).find({
|
||||||
});
|
where: { roleId: role.id as string },
|
||||||
this.logger.log(`Ensured ${links.length} passenger role-permission links`);
|
select: { permissionId: true },
|
||||||
|
});
|
||||||
|
const toRemove = existing
|
||||||
|
.map((rp) => rp.permissionId as string)
|
||||||
|
.filter((permId) => !desiredPermissionIds.has(permId));
|
||||||
|
|
||||||
|
if (toRemove.length > 0) {
|
||||||
|
await manager.getRepository(RolePermission).delete(
|
||||||
|
toRemove.map((permissionId) => ({ roleId: role.id as string, permissionId })),
|
||||||
|
);
|
||||||
|
totalPruned += toRemove.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upsert the full desired set
|
||||||
|
const links = [...desiredPermissionIds].map((permissionId) => ({
|
||||||
|
roleId: role.id as string,
|
||||||
|
permissionId,
|
||||||
|
}));
|
||||||
|
await manager.getRepository(RolePermission).upsert(links, {
|
||||||
|
conflictPaths: { roleId: true, permissionId: true },
|
||||||
|
});
|
||||||
|
totalUpserted += links.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`Synced passenger role-permission links: ${totalUpserted} upserted, ${totalPruned} pruned`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ensureSuperAdminPermissions(manager: EntityManager) {
|
private async ensureSuperAdminPermissions(manager: EntityManager) {
|
||||||
@@ -163,4 +194,34 @@ export class EdrPassengerOrgSeeder {
|
|||||||
);
|
);
|
||||||
this.logger.log(`Ensured ${permissions.length} passenger permissions on super_admin`);
|
this.logger.log(`Ensured ${permissions.length} passenger permissions on super_admin`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ensurePositions(manager: EntityManager, organizationId: string) {
|
||||||
|
const positions = [
|
||||||
|
{ key: 'edr_passenger_director', name: { en: 'Director', am: 'ዳይሬክተር' }, rank: 1 },
|
||||||
|
{ key: 'edr_passenger_finance_manager', name: { en: 'Finance Manager', am: 'የፋይናንስ ሥራ አስኪያጅ' }, rank: 2 },
|
||||||
|
{ key: 'edr_passenger_finance_officer', name: { en: 'Finance Officer', am: 'የፋይናንስ ኦፊሰር' }, rank: 3 },
|
||||||
|
{ key: 'edr_passenger_team_leader', name: { en: 'Team Leader', am: 'ቡድን መሪ' }, rank: 4 },
|
||||||
|
{ key: 'edr_passenger_station_master', name: { en: 'Station Master', am: 'ጣቢያ ሃላፊ' }, rank: 5 },
|
||||||
|
{ key: 'edr_passenger_station_supervisor', name: { en: 'Station Supervisor', am: 'ጣቢያ ተቆጣጣሪ' }, rank: 6 },
|
||||||
|
{ key: 'edr_passenger_ticket_officer', name: { en: 'Passenger Ticket Officer', am: 'የተሳፋሪ ቲኬት ኦፊሰር' }, rank: 7 },
|
||||||
|
{ key: 'edr_passenger_operational_staff', name: { en: 'Operational Staff', am: 'ስራ ሰራተኛ' }, rank: 8 },
|
||||||
|
];
|
||||||
|
|
||||||
|
let created = 0;
|
||||||
|
for (const pos of positions) {
|
||||||
|
const existing = await manager.query<Array<{ id: string }>>(
|
||||||
|
`SELECT id FROM iam.positions WHERE key = $1 AND organization_id = $2 LIMIT 1`,
|
||||||
|
[pos.key, organizationId],
|
||||||
|
);
|
||||||
|
if (existing.length === 0) {
|
||||||
|
await manager.query(
|
||||||
|
`INSERT INTO iam.positions (id, name, key, rank, organization_id, unit_id, position_type_id, created_at, updated_at)
|
||||||
|
VALUES (gen_random_uuid(), $1::jsonb, $2, $3, $4::uuid, NULL, NULL, NOW(), NOW())`,
|
||||||
|
[JSON.stringify(pos.name), pos.key, pos.rank, organizationId],
|
||||||
|
);
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.logger.log(`Ensured ${positions.length} passenger positions (${created} newly created)`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,15 +30,25 @@ export const EDR_PASSENGER_ROLES: PassengerSeedRole[] = [
|
|||||||
permissionKeys: [...ROLE_PERMISSION_PRESETS.backofficeAdmin],
|
permissionKeys: [...ROLE_PERMISSION_PRESETS.backofficeAdmin],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'edr_passenger_backoffice_staff',
|
key: 'edr_passenger_station_master',
|
||||||
name: { en: 'EDR Passenger Backoffice Staff' },
|
name: { en: 'EDR Passenger Station Master' },
|
||||||
permissionKeys: [...ROLE_PERMISSION_PRESETS.backofficeStaff],
|
permissionKeys: [...ROLE_PERMISSION_PRESETS.stationMaster],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'edr_passenger_ticket_officer',
|
||||||
|
name: { en: 'EDR Passenger Ticket Officer' },
|
||||||
|
permissionKeys: [...ROLE_PERMISSION_PRESETS.ticketOfficer],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'edr_passenger_agent',
|
key: 'edr_passenger_agent',
|
||||||
name: { en: 'EDR Passenger Agent' },
|
name: { en: 'EDR Passenger Agent' },
|
||||||
permissionKeys: [...ROLE_PERMISSION_PRESETS.agent],
|
permissionKeys: [...ROLE_PERMISSION_PRESETS.agent],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'edr_passenger_backoffice_staff',
|
||||||
|
name: { en: 'EDR Passenger Backoffice Staff' },
|
||||||
|
permissionKeys: [...ROLE_PERMISSION_PRESETS.backofficeStaff],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'edr_passenger_finance',
|
key: 'edr_passenger_finance',
|
||||||
name: { en: 'EDR Passenger Finance' },
|
name: { en: 'EDR Passenger Finance' },
|
||||||
|
|||||||
@@ -87,29 +87,42 @@ export const PASSENGER_PERMS = {
|
|||||||
export const ROLE_PERMISSION_PRESETS = {
|
export const ROLE_PERMISSION_PRESETS = {
|
||||||
backofficeAdmin: [...PASSENGER_PERMISSION_KEYS],
|
backofficeAdmin: [...PASSENGER_PERMISSION_KEYS],
|
||||||
|
|
||||||
backofficeStaff: [
|
stationMaster: [
|
||||||
PASSENGER_PERMS.bookings.view,
|
PASSENGER_PERMS.bookings.view,
|
||||||
PASSENGER_PERMS.bookings.manage,
|
PASSENGER_PERMS.bookings.manage,
|
||||||
PASSENGER_PERMS.bookings.cancel,
|
|
||||||
PASSENGER_PERMS.passengers.view,
|
|
||||||
PASSENGER_PERMS.passengers.manage,
|
|
||||||
PASSENGER_PERMS.tickets.view,
|
PASSENGER_PERMS.tickets.view,
|
||||||
PASSENGER_PERMS.tickets.manage,
|
PASSENGER_PERMS.tickets.manage,
|
||||||
PASSENGER_PERMS.payments.viewAll,
|
PASSENGER_PERMS.passengers.view,
|
||||||
PASSENGER_PERMS.reports.view,
|
|
||||||
PASSENGER_PERMS.dashboard.view,
|
|
||||||
PASSENGER_PERMS.notifications.send,
|
|
||||||
PASSENGER_PERMS.agents.view,
|
PASSENGER_PERMS.agents.view,
|
||||||
PASSENGER_PERMS.fraud.view,
|
|
||||||
PASSENGER_PERMS.audit.view,
|
PASSENGER_PERMS.audit.view,
|
||||||
|
PASSENGER_PERMS.notifications.send,
|
||||||
|
PASSENGER_PERMS.dashboard.view,
|
||||||
|
],
|
||||||
|
|
||||||
|
ticketOfficer: [
|
||||||
|
PASSENGER_PERMS.tickets.view,
|
||||||
|
PASSENGER_PERMS.tickets.manage,
|
||||||
|
PASSENGER_PERMS.bookings.view,
|
||||||
|
PASSENGER_PERMS.passengers.view,
|
||||||
|
PASSENGER_PERMS.dashboard.view,
|
||||||
],
|
],
|
||||||
|
|
||||||
agent: [
|
agent: [
|
||||||
PASSENGER_PERMS.bookings.view,
|
PASSENGER_PERMS.bookings.view,
|
||||||
PASSENGER_PERMS.bookings.manage,
|
PASSENGER_PERMS.bookings.manage,
|
||||||
|
PASSENGER_PERMS.bookings.cancel,
|
||||||
PASSENGER_PERMS.passengers.view,
|
PASSENGER_PERMS.passengers.view,
|
||||||
PASSENGER_PERMS.tickets.view,
|
PASSENGER_PERMS.tickets.view,
|
||||||
|
PASSENGER_PERMS.tickets.manage,
|
||||||
PASSENGER_PERMS.payments.refund,
|
PASSENGER_PERMS.payments.refund,
|
||||||
|
PASSENGER_PERMS.dashboard.view,
|
||||||
|
],
|
||||||
|
|
||||||
|
backofficeStaff: [
|
||||||
|
PASSENGER_PERMS.bookings.view,
|
||||||
|
PASSENGER_PERMS.passengers.view,
|
||||||
|
PASSENGER_PERMS.tickets.view,
|
||||||
|
PASSENGER_PERMS.dashboard.view,
|
||||||
],
|
],
|
||||||
|
|
||||||
finance: [
|
finance: [
|
||||||
|
|||||||
Reference in New Issue
Block a user