Files
edr-platform/apps/edr-freight-api/src/migrations/3850000000000-TrainCrewMembers.ts
marshalyordanos 8437a6d5f1 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.
2026-09-04 20:45:41 +03:00

69 lines
2.8 KiB
TypeScript

import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Roster of people assignable to a train (ITLMS Rolling Stock §1.2 crew
* composition). Separate from freight.drivers, which registers road/last-mile
* truck drivers and shares none of these fields.
*
* Role and nationality are stored as varchar rather than PG enums so adding a
* crew role later is an application change, not a type migration. The partial
* unique index keys on name + role — the roster has no employee number yet, so
* that is the only identity available to block an accidental re-entry; it is
* scoped to live rows so a soft-deleted member does not hold the name hostage.
*/
export class TrainCrewMembers3850000000000 implements MigrationInterface {
name = 'TrainCrewMembers3850000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE IF NOT EXISTS freight.train_crew_members (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
first_name varchar(100) NOT NULL,
last_name varchar(100) NOT NULL,
role varchar(32) NOT NULL,
nationality varchar(16) NOT NULL,
status varchar(16) NOT NULL DEFAULT 'ACTIVE',
is_active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz,
CONSTRAINT chk_train_crew_role CHECK (role IN (
'TRAIN_DRIVER','FEDERAL_POLICE','TECHNICIAN','REEFER_TECHNICIAN',
'HAZMAT_ESCORT','LASHING_INSPECTOR','LIVESTOCK_HANDLER'
)),
CONSTRAINT chk_train_crew_nationality CHECK (nationality IN (
'ETHIOPIAN','DJIBOUTIAN'
)),
CONSTRAINT chk_train_crew_status CHECK (status IN (
'ACTIVE','INACTIVE','SUSPENDED','ON_LEAVE'
))
)
`);
await queryRunner.query(`
CREATE INDEX IF NOT EXISTS idx_train_crew_members_role
ON freight.train_crew_members (role)
`);
await queryRunner.query(`
CREATE INDEX IF NOT EXISTS idx_train_crew_members_nationality
ON freight.train_crew_members (nationality)
`);
await queryRunner.query(`
CREATE INDEX IF NOT EXISTS idx_train_crew_members_status
ON freight.train_crew_members (status)
`);
await queryRunner.query(`
CREATE INDEX IF NOT EXISTS idx_train_crew_members_is_active
ON freight.train_crew_members (is_active)
`);
await queryRunner.query(`
CREATE UNIQUE INDEX IF NOT EXISTS uq_train_crew_members_name_role
ON freight.train_crew_members (lower(first_name), lower(last_name), role)
WHERE deleted_at IS NULL
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE IF EXISTS freight.train_crew_members`);
}
}