Add complete dispatch module for incident assignment: Entities (7): - DispatchBoard: Board configuration - UnitStatus: Real-time unit state - TechnicianSkill: Skills and certifications - TechnicianShift: Shift schedules - DispatchRule: Assignment rules - EscalationRule: Escalation rules - DispatchLog: Audit trail Services (4): - DispatchService: Unit management, assignments, suggestions - SkillService: Skill CRUD, validation, matrix - ShiftService: Shift management, availability - RuleService: Dispatch and escalation rules Controllers (4): - DispatchController: /api/v1/dispatch - SkillController: /api/v1/dispatch/skills - ShiftController: /api/v1/dispatch/shifts - RuleController: /api/v1/dispatch/rules Integrated in main.ts with routes and documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
/**
|
|
* UnitStatus Entity
|
|
* Mecanicas Diesel - ERP Suite
|
|
*
|
|
* Real-time status of fleet units for dispatch.
|
|
* Module: MMD-011 Dispatch Center
|
|
*/
|
|
|
|
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
UpdateDateColumn,
|
|
Index,
|
|
} from 'typeorm';
|
|
|
|
export enum UnitStatusEnum {
|
|
AVAILABLE = 'available',
|
|
ASSIGNED = 'assigned',
|
|
EN_ROUTE = 'en_route',
|
|
ON_SITE = 'on_site',
|
|
RETURNING = 'returning',
|
|
OFFLINE = 'offline',
|
|
MAINTENANCE = 'maintenance',
|
|
}
|
|
|
|
export enum UnitCapacity {
|
|
LIGHT = 'light',
|
|
MEDIUM = 'medium',
|
|
HEAVY = 'heavy',
|
|
}
|
|
|
|
@Entity({ name: 'unit_statuses', schema: 'dispatch' })
|
|
@Index('idx_unit_statuses_tenant_unit', ['tenantId', 'unitId'], { unique: true })
|
|
@Index('idx_unit_statuses_status', ['tenantId', 'status'])
|
|
export class UnitStatus {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ name: 'tenant_id', type: 'uuid' })
|
|
tenantId: string;
|
|
|
|
// Unit reference
|
|
@Column({ name: 'unit_id', type: 'uuid' })
|
|
unitId: string;
|
|
|
|
@Column({ name: 'unit_code', type: 'varchar', length: 50, nullable: true })
|
|
unitCode?: string;
|
|
|
|
@Column({ name: 'unit_name', type: 'varchar', length: 100, nullable: true })
|
|
unitName?: string;
|
|
|
|
// Status
|
|
@Column({
|
|
type: 'varchar',
|
|
length: 20,
|
|
default: UnitStatusEnum.OFFLINE,
|
|
})
|
|
status: UnitStatusEnum;
|
|
|
|
// Current assignment
|
|
@Column({ name: 'current_incident_id', type: 'uuid', nullable: true })
|
|
currentIncidentId?: string;
|
|
|
|
@Column({ name: 'current_technician_ids', type: 'uuid', array: true, default: [] })
|
|
currentTechnicianIds: string[];
|
|
|
|
// Location (cached from GPS)
|
|
@Column({ name: 'last_position_id', type: 'uuid', nullable: true })
|
|
lastPositionId?: string;
|
|
|
|
@Column({ name: 'last_known_lat', type: 'decimal', precision: 10, scale: 7, nullable: true })
|
|
lastKnownLat?: number;
|
|
|
|
@Column({ name: 'last_known_lng', type: 'decimal', precision: 10, scale: 7, nullable: true })
|
|
lastKnownLng?: number;
|
|
|
|
@Column({ name: 'last_location_update', type: 'timestamptz', nullable: true })
|
|
lastLocationUpdate?: Date;
|
|
|
|
// Timing
|
|
@Column({ name: 'last_status_change', type: 'timestamptz', default: () => 'NOW()' })
|
|
lastStatusChange: Date;
|
|
|
|
@Column({ name: 'estimated_available_at', type: 'timestamptz', nullable: true })
|
|
estimatedAvailableAt?: Date;
|
|
|
|
// Capacity and capabilities
|
|
@Column({
|
|
name: 'unit_capacity',
|
|
type: 'varchar',
|
|
length: 20,
|
|
default: UnitCapacity.LIGHT,
|
|
})
|
|
unitCapacity: UnitCapacity;
|
|
|
|
@Column({ name: 'can_tow', type: 'boolean', default: false })
|
|
canTow: boolean;
|
|
|
|
@Column({ name: 'max_tow_weight_kg', type: 'integer', nullable: true })
|
|
maxTowWeightKg?: number;
|
|
|
|
@Column({ type: 'text', nullable: true })
|
|
notes?: string;
|
|
|
|
@Column({ type: 'jsonb', default: {} })
|
|
metadata: Record<string, any>;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
updatedAt: Date;
|
|
}
|