import { BaseEntity } from '@edr/api-common'; import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm'; import { Vehicle } from '../../vehicles/entities/vehicle.entity'; /** * A physical GPS tracker (GT06). Identified by IMEI, optionally bound to a * vehicle. Carries the denormalized latest fix so the live map reads one row * per device without scanning position history. */ @Entity({ name: 'gps_devices', schema: 'freight' }) @Index(['vehicleId']) export class GpsDevice extends BaseEntity { @Column({ name: 'imei', type: 'varchar', length: 20, unique: true }) imei!: string; @Column({ name: 'name', type: 'varchar', nullable: true }) name?: string | null; @Column({ name: 'vehicle_id', type: 'uuid', nullable: true }) vehicleId?: string | null; @ManyToOne(() => Vehicle, { nullable: true, eager: false }) @JoinColumn({ name: 'vehicle_id' }) vehicle?: Vehicle | null; /** ONLINE once a packet arrives; OFFLINE when stale (derived on read). */ @Column({ name: 'status', type: 'varchar', length: 16, default: 'REGISTERED' }) status!: string; @Column({ name: 'last_seen_at', type: 'timestamptz', nullable: true }) lastSeenAt?: Date | null; // ── Denormalized latest fix ── @Column({ name: 'last_lat', type: 'numeric', precision: 10, scale: 6, nullable: true }) lastLat?: number | null; @Column({ name: 'last_lng', type: 'numeric', precision: 10, scale: 6, nullable: true }) lastLng?: number | null; @Column({ name: 'last_speed', type: 'numeric', precision: 6, scale: 2, nullable: true }) lastSpeed?: number | null; @Column({ name: 'last_course', type: 'int', nullable: true }) lastCourse?: number | null; @Column({ name: 'last_fix_at', type: 'timestamptz', nullable: true }) lastFixAt?: Date | null; @Column({ name: 'voltage_level', type: 'int', nullable: true }) voltageLevel?: number | null; @Column({ name: 'gsm_level', type: 'int', nullable: true }) gsmLevel?: number | null; }