mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 11:08:12 +00:00
Merge remote-tracking branch 'origin/dev' into Truckdetantion
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Vehicle Compliance & Expiry Alerts.
|
||||
* - Adds expiry-tracking columns to freight.vehicles.
|
||||
* - Creates freight.compliance_records for per-document compliance tracking.
|
||||
*/
|
||||
export class AddVehicleCompliance1950000000000 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Vehicle expiry / compliance columns.
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.vehicles
|
||||
ADD COLUMN IF NOT EXISTS vin VARCHAR,
|
||||
ADD COLUMN IF NOT EXISTS ownership VARCHAR,
|
||||
ADD COLUMN IF NOT EXISTS insurance_expiry DATE,
|
||||
ADD COLUMN IF NOT EXISTS registration_expiry DATE,
|
||||
ADD COLUMN IF NOT EXISTS next_inspection_date DATE;
|
||||
`);
|
||||
|
||||
// Compliance records table.
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.compliance_records (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
vehicle_id UUID NOT NULL REFERENCES freight.vehicles(id),
|
||||
type VARCHAR NOT NULL,
|
||||
document_number VARCHAR,
|
||||
issued_date DATE,
|
||||
expiry_date DATE NOT NULL,
|
||||
status VARCHAR NOT NULL DEFAULT 'VALID',
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS idx_compliance_records_vehicle_id ON freight.compliance_records(vehicle_id);`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS idx_compliance_records_expiry_date ON freight.compliance_records(expiry_date);`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS idx_compliance_records_type ON freight.compliance_records(type);`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.compliance_records CASCADE;`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.vehicles
|
||||
DROP COLUMN IF EXISTS vin,
|
||||
DROP COLUMN IF EXISTS ownership,
|
||||
DROP COLUMN IF EXISTS insurance_expiry,
|
||||
DROP COLUMN IF EXISTS registration_expiry,
|
||||
DROP COLUMN IF EXISTS next_inspection_date;
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* In-app notification inbox. One row per recipient per logical notification;
|
||||
* producers fan out by inserting many rows. Indexed for the two hot queries:
|
||||
* unread-count (recipient + is_read) and the newest-first list (recipient +
|
||||
* created_at). Enum-like columns are stored as varchar to avoid PG enum churn.
|
||||
*/
|
||||
export class CreateNotifications1950000000000 implements MigrationInterface {
|
||||
name = "CreateNotifications1950000000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.notifications (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
recipient_user_id uuid NOT NULL,
|
||||
audience varchar(20) NOT NULL,
|
||||
type varchar(48) NOT NULL DEFAULT 'GENERIC',
|
||||
title varchar(200) NOT NULL,
|
||||
body text NOT NULL,
|
||||
link varchar,
|
||||
data jsonb,
|
||||
priority varchar(12) NOT NULL DEFAULT 'NORMAL',
|
||||
is_read boolean NOT NULL DEFAULT false,
|
||||
read_at timestamptz,
|
||||
channels_sent jsonb,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_NOTIFICATIONS_RECIPIENT_UNREAD"
|
||||
ON freight.notifications (recipient_user_id, is_read)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_NOTIFICATIONS_RECIPIENT_CREATED"
|
||||
ON freight.notifications (recipient_user_id, created_at)
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS freight."IDX_NOTIFICATIONS_RECIPIENT_CREATED"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS freight."IDX_NOTIFICATIONS_RECIPIENT_UNREAD"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.notifications`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Accident & Incident register for the fleet. Tracks accidents, breakdowns,
|
||||
* traffic violations, thefts and other incidents against a vehicle, driver
|
||||
* and/or booking, with severity, damage estimate, insurance claim tracking and
|
||||
* a lifecycle status. Queried by driver_id for per-driver incident history.
|
||||
*/
|
||||
export class AddIncidents1960000000000 implements MigrationInterface {
|
||||
name = 'AddIncidents1960000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.incidents (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz,
|
||||
vehicle_id uuid,
|
||||
driver_id uuid,
|
||||
booking_id uuid,
|
||||
type varchar NOT NULL,
|
||||
severity varchar NOT NULL,
|
||||
occurred_at timestamptz NOT NULL,
|
||||
location varchar,
|
||||
description text NOT NULL,
|
||||
damage_estimate numeric(14,2),
|
||||
status varchar NOT NULL DEFAULT 'REPORTED',
|
||||
insurance_claim_number varchar,
|
||||
reported_by varchar
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_INCIDENTS_DRIVER"
|
||||
ON freight.incidents (driver_id, occurred_at)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_INCIDENTS_VEHICLE"
|
||||
ON freight.incidents (vehicle_id, occurred_at)
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.incidents`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddMaintenanceDepth1970000000000 implements MigrationInterface {
|
||||
name = 'AddMaintenanceDepth1970000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE SCHEMA IF NOT EXISTS freight`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.work_orders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
vehicle_id UUID NOT NULL,
|
||||
title VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
status VARCHAR NOT NULL DEFAULT 'OPEN',
|
||||
priority VARCHAR NOT NULL DEFAULT 'MEDIUM',
|
||||
assigned_to VARCHAR,
|
||||
opened_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
closed_at TIMESTAMPTZ,
|
||||
labor_cost NUMERIC(14, 2),
|
||||
parts_cost NUMERIC(14, 2),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.parts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR NOT NULL,
|
||||
sku VARCHAR,
|
||||
category VARCHAR,
|
||||
quantity_in_stock INT NOT NULL DEFAULT 0,
|
||||
reorder_level INT NOT NULL DEFAULT 0,
|
||||
unit_cost NUMERIC(14, 2),
|
||||
location VARCHAR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.warranties (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
vehicle_id UUID NOT NULL,
|
||||
component VARCHAR NOT NULL,
|
||||
provider VARCHAR,
|
||||
start_date DATE,
|
||||
expiry_date DATE NOT NULL,
|
||||
coverage_notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_work_orders_vehicle_id_status" ON freight.work_orders (vehicle_id, status)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_parts_category" ON freight.parts (category)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_warranties_vehicle_id_expiry_date" ON freight.warranties (vehicle_id, expiry_date)`,
|
||||
);
|
||||
|
||||
await queryRunner.query(`
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE freight.work_orders
|
||||
ADD CONSTRAINT "FK_work_orders_vehicle_id"
|
||||
FOREIGN KEY (vehicle_id) REFERENCES freight.vehicles(id) ON DELETE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL;
|
||||
END $$;
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE freight.warranties
|
||||
ADD CONSTRAINT "FK_warranties_vehicle_id"
|
||||
FOREIGN KEY (vehicle_id) REFERENCES freight.vehicles(id) ON DELETE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL;
|
||||
END $$;
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.warranties CASCADE`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.parts CASCADE`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.work_orders CASCADE`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddProcurement1980000000000 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.vendors (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz,
|
||||
name varchar NOT NULL,
|
||||
type varchar,
|
||||
contact_person varchar,
|
||||
phone varchar,
|
||||
email varchar,
|
||||
address varchar,
|
||||
is_active boolean NOT NULL DEFAULT true
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.asset_acquisitions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz,
|
||||
vehicle_id uuid,
|
||||
vendor_id uuid,
|
||||
acquisition_type varchar NOT NULL,
|
||||
acquisition_date date NOT NULL,
|
||||
cost numeric(14,2),
|
||||
useful_life_months integer,
|
||||
salvage_value numeric(14,2),
|
||||
lease_start date,
|
||||
lease_end date,
|
||||
monthly_payment numeric(14,2),
|
||||
status varchar NOT NULL DEFAULT 'ACTIVE',
|
||||
notes text
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_asset_acquisitions_vehicle_date
|
||||
ON freight.asset_acquisitions(vehicle_id, acquisition_date);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.asset_disposals (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz,
|
||||
vehicle_id uuid NOT NULL,
|
||||
disposal_date date NOT NULL,
|
||||
method varchar NOT NULL,
|
||||
sale_price numeric(14,2),
|
||||
buyer varchar,
|
||||
notes text
|
||||
);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_asset_disposals_vehicle_date
|
||||
ON freight.asset_disposals(vehicle_id, disposal_date);
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.asset_disposals CASCADE;`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.asset_acquisitions CASCADE;`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.vendors CASCADE;`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Yard country becomes a two-value enum (Ethiopia | Djibouti) and every route
|
||||
* freezes its trade direction from the yard countries:
|
||||
* Ethiopia → Djibouti = EXPORT, Djibouti → Ethiopia = IMPORT,
|
||||
* same country = DOMESTIC (shown as "Intercity"; disabled for scheduling
|
||||
* and contracts for now).
|
||||
*
|
||||
* Existing yard rows are normalized case-insensitively; anything mentioning
|
||||
* Djibouti maps there, everything else maps to Ethiopia (the line only serves
|
||||
* these two countries). A CHECK constraint keeps future writes honest.
|
||||
*/
|
||||
export class YardCountryEnumAndRouteDirection1980000000000 implements MigrationInterface {
|
||||
name = 'YardCountryEnumAndRouteDirection1980000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.yards
|
||||
SET country = CASE
|
||||
WHEN lower(trim(country)) LIKE '%djib%' THEN 'Djibouti'
|
||||
ELSE 'Ethiopia'
|
||||
END
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.yards
|
||||
DROP CONSTRAINT IF EXISTS chk_yards_country,
|
||||
ADD CONSTRAINT chk_yards_country CHECK (country IN ('Ethiopia', 'Djibouti'))
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.routes
|
||||
ADD COLUMN IF NOT EXISTS direction varchar(10)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.routes r
|
||||
SET direction = CASE
|
||||
WHEN o.country = 'Djibouti' AND d.country = 'Ethiopia' THEN 'IMPORT'
|
||||
WHEN o.country = 'Ethiopia' AND d.country = 'Djibouti' THEN 'EXPORT'
|
||||
ELSE 'DOMESTIC'
|
||||
END
|
||||
FROM freight.yards o, freight.yards d
|
||||
WHERE o.id = r.origin_yard_id
|
||||
AND d.id = r.destination_yard_id
|
||||
`);
|
||||
// Orphan origin/destination (deleted yard) — no way to classify; park as
|
||||
// DOMESTIC, which is blocked everywhere, so nothing can schedule on it.
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.routes SET direction = 'DOMESTIC' WHERE direction IS NULL
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.routes
|
||||
ALTER COLUMN direction SET NOT NULL,
|
||||
DROP CONSTRAINT IF EXISTS chk_routes_direction,
|
||||
ADD CONSTRAINT chk_routes_direction CHECK (direction IN ('IMPORT', 'EXPORT', 'DOMESTIC'))
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.routes
|
||||
DROP CONSTRAINT IF EXISTS chk_routes_direction,
|
||||
DROP COLUMN IF EXISTS direction
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.yards DROP CONSTRAINT IF EXISTS chk_yards_country
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* Per-km haulage rate on a vehicle (mainly trucks) plus the currency it's
|
||||
* quoted in (ETB | USD, default ETB).
|
||||
*/
|
||||
export class AddVehiclePricePerKm1990000000000 implements MigrationInterface {
|
||||
name = "AddVehiclePricePerKm1990000000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.vehicles
|
||||
ADD COLUMN IF NOT EXISTS price_per_km numeric(14,2),
|
||||
ADD COLUMN IF NOT EXISTS currency varchar(8) NOT NULL DEFAULT 'ETB'
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.vehicles
|
||||
DROP COLUMN IF EXISTS price_per_km,
|
||||
DROP COLUMN IF EXISTS currency
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* GPS tracking: physical trackers (gps_devices, one denormalized latest fix per
|
||||
* device for the live map) + append-only fix history (gps_positions).
|
||||
*/
|
||||
export class AddGpsTracking2000000000000 implements MigrationInterface {
|
||||
name = "AddGpsTracking2000000000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.gps_devices (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
imei varchar(20) NOT NULL UNIQUE,
|
||||
name varchar,
|
||||
vehicle_id uuid REFERENCES freight.vehicles(id),
|
||||
status varchar(16) NOT NULL DEFAULT 'REGISTERED',
|
||||
last_seen_at timestamptz,
|
||||
last_lat numeric(10,6),
|
||||
last_lng numeric(10,6),
|
||||
last_speed numeric(6,2),
|
||||
last_course int,
|
||||
last_fix_at timestamptz,
|
||||
voltage_level int,
|
||||
gsm_level int,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_GPS_DEVICES_VEHICLE"
|
||||
ON freight.gps_devices (vehicle_id)
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.gps_positions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
device_id uuid NOT NULL,
|
||||
imei varchar(20) NOT NULL,
|
||||
vehicle_id uuid,
|
||||
lat numeric(10,6) NOT NULL,
|
||||
lng numeric(10,6) NOT NULL,
|
||||
speed numeric(6,2) NOT NULL DEFAULT 0,
|
||||
course int NOT NULL DEFAULT 0,
|
||||
satellites int NOT NULL DEFAULT 0,
|
||||
positioned boolean NOT NULL DEFAULT false,
|
||||
gps_time timestamptz NOT NULL,
|
||||
alarm int NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_GPS_POSITIONS_DEVICE_TIME"
|
||||
ON freight.gps_positions (device_id, gps_time)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_GPS_POSITIONS_VEHICLE_TIME"
|
||||
ON freight.gps_positions (vehicle_id, gps_time)
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.gps_positions`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.gps_devices`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user