feat(train-crew): implement train crew management module

- Added DTOs for creating, querying, and updating train crew members.
- Created entity for train crew members with relevant fields and enums for role, nationality, and status.
- Developed service for handling CRUD operations and ensuring no duplicate crew members.
- Implemented controller to manage API endpoints for train crew operations.
- Integrated permissions for viewing, creating, updating, and deleting train crew members.
- Added frontend components for displaying, adding, editing, and deleting train crew members.
- Established API service for interacting with the train crew backend.
- Updated routing and sidebar to include train crew management section.
This commit is contained in:
marshalyordanos
2026-09-04 20:45:41 +03:00
parent ca84aac456
commit 8437a6d5f1
18 changed files with 1086 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
import { Column, Entity, Index } from 'typeorm';
import { BaseEntity } from '@edr/api-common';
/**
* On-board role a crew member is rostered for. Mirrors the crew composition
* rules in ITLMS Rolling Stock §1.2: driving crew, the federal police security
* detail, technical maintenance, and the four specialized cargo roles.
*/
export enum TrainCrewRole {
TRAIN_DRIVER = 'TRAIN_DRIVER',
FEDERAL_POLICE = 'FEDERAL_POLICE',
TECHNICIAN = 'TECHNICIAN',
REEFER_TECHNICIAN = 'REEFER_TECHNICIAN',
HAZMAT_ESCORT = 'HAZMAT_ESCORT',
LASHING_INSPECTOR = 'LASHING_INSPECTOR',
LIVESTOCK_HANDLER = 'LIVESTOCK_HANDLER',
}
/**
* Employing country. Drives the territorial boundary in §1.1 — Djibouti train
* drivers operate only on the Dire Dawa Nagad segment — and the crewing
* cases in §2 (Case 1 pairs 2 Ethiopian with 2 Djiboutian drivers).
*/
export enum TrainCrewNationality {
ETHIOPIAN = 'ETHIOPIAN',
DJIBOUTIAN = 'DJIBOUTIAN',
}
export enum TrainCrewStatus {
ACTIVE = 'ACTIVE',
INACTIVE = 'INACTIVE',
SUSPENDED = 'SUSPENDED',
ON_LEAVE = 'ON_LEAVE',
}
/**
* Roster of people assignable to a train. Distinct from `freight.drivers`,
* which is the road/last-mile truck driver register (licences, vehicle types,
* trip counts) — a train driver shares none of those fields.
*/
@Entity({ schema: 'freight', name: 'train_crew_members' })
@Index(['role'])
@Index(['nationality'])
@Index(['status'])
@Index(['isActive'])
export class TrainCrewMember extends BaseEntity {
@Column({ name: 'first_name', type: 'varchar', length: 100 })
firstName!: string;
@Column({ name: 'last_name', type: 'varchar', length: 100 })
lastName!: string;
@Column({ name: 'role', type: 'varchar', length: 32 })
role!: TrainCrewRole;
@Column({ name: 'nationality', type: 'varchar', length: 16 })
nationality!: TrainCrewNationality;
@Column({
name: 'status',
type: 'varchar',
length: 16,
default: TrainCrewStatus.ACTIVE,
})
status!: TrainCrewStatus;
@Column({ name: 'is_active', type: 'boolean', default: true })
isActive!: boolean;
}