mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 19:58:11 +00:00
Service/Controller/Module: - scheduleMaintenanceAsync: schedule work - recordMaintenanceCost: log expenses - getUpcomingMaintenance: due items - getVehicleMaintenanceStats: cost aggregation Endpoints: - POST /maintenance/schedules - POST /maintenance/costs - PATCH /maintenance/schedules/:id - GET /maintenance/upcoming/:vehicleId - GET /maintenance/history/:vehicleId - GET /maintenance/stats/:vehicleId Migration: idempotent maintenance tables creation Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
83 lines
3.1 KiB
TypeScript
83 lines
3.1 KiB
TypeScript
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
|
|
export class CreateMaintenanceTables1850000000000 implements MigrationInterface {
|
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
// Create maintenance_schedules table
|
|
const scheduleTableExists = await queryRunner.query(`
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM information_schema.tables
|
|
WHERE table_schema = 'freight' AND table_name = 'maintenance_schedules'
|
|
)
|
|
`);
|
|
|
|
if (!scheduleTableExists[0].exists) {
|
|
await queryRunner.query(`
|
|
CREATE TABLE "freight"."maintenance_schedules" (
|
|
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
"vehicle_id" uuid NOT NULL,
|
|
"maintenance_type" varchar NOT NULL,
|
|
"description" varchar NOT NULL,
|
|
"scheduled_date" timestamptz NOT NULL,
|
|
"completed_date" timestamptz,
|
|
"estimated_cost" numeric(14,2),
|
|
"actual_cost" numeric(14,2),
|
|
"status" varchar NOT NULL DEFAULT 'SCHEDULED',
|
|
"odometer_reading" numeric,
|
|
"service_provider" varchar,
|
|
"notes" text,
|
|
"next_due_km" numeric,
|
|
"next_due_date" timestamptz,
|
|
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
"deleted_at" timestamptz,
|
|
PRIMARY KEY ("id")
|
|
)
|
|
`);
|
|
|
|
await queryRunner.query(
|
|
`CREATE INDEX "idx_maintenance_schedules_vehicle_date" ON "freight"."maintenance_schedules" ("vehicle_id", "scheduled_date")`
|
|
);
|
|
}
|
|
|
|
// Create maintenance_costs table
|
|
const costsTableExists = await queryRunner.query(`
|
|
SELECT EXISTS(
|
|
SELECT 1 FROM information_schema.tables
|
|
WHERE table_schema = 'freight' AND table_name = 'maintenance_costs'
|
|
)
|
|
`);
|
|
|
|
if (!costsTableExists[0].exists) {
|
|
await queryRunner.query(`
|
|
CREATE TABLE "freight"."maintenance_costs" (
|
|
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
"vehicle_id" uuid NOT NULL,
|
|
"maintenance_schedule_id" uuid,
|
|
"incurred_date" timestamptz NOT NULL,
|
|
"cost_amount" numeric(14,2) NOT NULL,
|
|
"cost_type" varchar NOT NULL,
|
|
"description" varchar NOT NULL,
|
|
"service_provider" varchar,
|
|
"invoice_number" varchar,
|
|
"notes" text,
|
|
"created_at" timestamptz NOT NULL DEFAULT now(),
|
|
"updated_at" timestamptz NOT NULL DEFAULT now(),
|
|
"deleted_at" timestamptz,
|
|
PRIMARY KEY ("id"),
|
|
CONSTRAINT "fk_maintenance_schedule" FOREIGN KEY ("maintenance_schedule_id")
|
|
REFERENCES "freight"."maintenance_schedules" ("id") ON DELETE SET NULL
|
|
)
|
|
`);
|
|
|
|
await queryRunner.query(
|
|
`CREATE INDEX "idx_maintenance_costs_vehicle_date" ON "freight"."maintenance_costs" ("vehicle_id", "incurred_date")`
|
|
);
|
|
}
|
|
}
|
|
|
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
await queryRunner.query(`DROP TABLE IF EXISTS "freight"."maintenance_costs"`);
|
|
await queryRunner.query(`DROP TABLE IF EXISTS "freight"."maintenance_schedules"`);
|
|
}
|
|
}
|