Merge pull request #1129 from Tria-plc/lastmilerequest

feat(rule-engine): add yard_locations table, seed 5 facility yard GPS…
This commit is contained in:
Hagernesh Tadesse
2026-08-05 23:19:10 +03:00
committed by GitHub
3 changed files with 81 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Creates freight.yard_locations (GPS per yard, decimal degrees WGS84) and
* seeds the five facility yards: Sebeta, GMP/Indode (KALITY), Mojo, Adama,
* Dire Dawa. Also normalizes has_facility — only those five load/unload cargo.
*
* Coordinates are approximate — adjust rows directly if surveyed values arrive.
*/
export class YardGpsLocation3270000000000 implements MigrationInterface {
name = 'YardGpsLocation3270000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE IF NOT EXISTS freight.yard_locations (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
yard_id uuid NOT NULL UNIQUE REFERENCES freight.yards(id) ON DELETE CASCADE,
latitude double precision NOT NULL,
longitude double precision NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
)
`);
// LEGACY_DEST is the historical code for Sebeta in some environments.
await queryRunner.query(`
INSERT INTO freight.yard_locations (yard_id, latitude, longitude)
SELECT y.id, v.lat, v.lng
FROM (VALUES
('SEBETA', 8.9096, 38.6360),
('LEGACY_DEST', 8.9096, 38.6360),
('KALITY', 8.7386, 38.7913),
('MOJO', 8.5794, 39.1200),
('ADAMA', 8.5622, 39.2440),
('DIRE_DAWA', 9.6009, 41.8103)
) AS v(code, lat, lng)
JOIN freight.yards y ON y.code = v.code AND y.deleted_at IS NULL
ON CONFLICT (yard_id) DO NOTHING
`);
await queryRunner.query(`
UPDATE freight.yards
SET has_facility = (code IN ('SEBETA', 'LEGACY_DEST', 'KALITY', 'MOJO', 'ADAMA', 'DIRE_DAWA'))
WHERE deleted_at IS NULL
AND has_facility <> (code IN ('SEBETA', 'LEGACY_DEST', 'KALITY', 'MOJO', 'ADAMA', 'DIRE_DAWA'))
`);
}
public async down(): Promise<void> {
// Additive table + data normalization; no rollback.
}
}

View File

@@ -0,0 +1,26 @@
import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, OneToOne } from 'typeorm';
import { Yard } from './yard.entity';
/**
* GPS position of a yard (decimal degrees, WGS84). One record per yard;
* today only the five facility yards (Sebeta, GMP/Indode, Mojo, Adama,
* Dire Dawa) are seeded.
*/
@Entity({ schema: 'freight', name: 'yard_locations' })
@Index(['yardId'], { unique: true })
export class YardLocation extends BaseEntity {
@Column({ name: 'yard_id', type: 'uuid' })
yardId!: string;
@OneToOne(() => Yard, { nullable: false, onDelete: 'CASCADE' })
@JoinColumn({ name: 'yard_id' })
yard?: Yard;
@Column({ name: 'latitude', type: 'double precision' })
latitude!: number;
@Column({ name: 'longitude', type: 'double precision' })
longitude!: number;
}

View File

@@ -27,6 +27,7 @@ import { WeightLimitRule } from './entities/weight-limit-rule.entity';
import { Yard } from './entities/yard.entity';
import { YardDistance } from './entities/yard-distance.entity';
import { YardFacility } from './entities/yard-facility.entity';
import { YardLocation } from './entities/yard-location.entity';
import { APPROVAL_RULES_REPOSITORY } from './interfaces/approval-rules.repository.interface';
import { CARGO_TYPES_REPOSITORY } from './interfaces/cargo-types.repository.interface';
@@ -88,6 +89,7 @@ import { BookingRateSnapshot } from '../bookings/entities/booking-rate-snapshot.
Yard,
YardDistance,
YardFacility,
YardLocation,
ShippingLine,
Rate,
ApprovalRule,