mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 17:38:12 +00:00
49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
import { DataSource } from 'typeorm';
|
|
|
|
/** Great-circle distance in km between two WGS84 points (haversine). */
|
|
export function haversineKm(lat1: number, lng1: number, lat2: number, lng2: number): number {
|
|
const toRad = (d: number) => (d * Math.PI) / 180;
|
|
const dLat = toRad(lat2 - lat1);
|
|
const dLng = toRad(lng2 - lng1);
|
|
const a =
|
|
Math.sin(dLat / 2) ** 2 + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLng / 2) ** 2;
|
|
return 2 * 6371 * Math.asin(Math.sqrt(a));
|
|
}
|
|
|
|
/**
|
|
* Estimated road-leg distance for a booking's first/last mile: straight-line km
|
|
* from the yard (freight.yard_locations) to the customer's pickup/delivery GPS
|
|
* point on the booking. FIRST = origin yard → pickup point, LAST = destination
|
|
* yard → delivery point. Null when either end has no coordinates.
|
|
*
|
|
* ponytail: haversine straight-line, not road routing — plug a routing API in
|
|
* here if real road km is ever required.
|
|
*/
|
|
export async function estimateMileKm(
|
|
dataSource: DataSource,
|
|
bookingId: string,
|
|
mile: 'FIRST' | 'LAST',
|
|
): Promise<number | null> {
|
|
const [row] = await dataSource.query(
|
|
mile === 'LAST'
|
|
? `SELECT b.last_mile_delivery_lat AS lat, b.last_mile_delivery_lng AS lng,
|
|
l.latitude AS yard_lat, l.longitude AS yard_lng
|
|
FROM freight.bookings b
|
|
LEFT JOIN freight.yard_locations l
|
|
ON l.yard_id = b.destination_yard_id AND l.deleted_at IS NULL
|
|
WHERE b.id = $1 AND b.deleted_at IS NULL`
|
|
: `SELECT b.first_mile_pickup_lat AS lat, b.first_mile_pickup_lng AS lng,
|
|
l.latitude AS yard_lat, l.longitude AS yard_lng
|
|
FROM freight.bookings b
|
|
LEFT JOIN freight.yard_locations l
|
|
ON l.yard_id = b.origin_yard_id AND l.deleted_at IS NULL
|
|
WHERE b.id = $1 AND b.deleted_at IS NULL`,
|
|
[bookingId],
|
|
);
|
|
if (!row || row.lat == null || row.lng == null || row.yard_lat == null || row.yard_lng == null) {
|
|
return null;
|
|
}
|
|
const km = haversineKm(Number(row.yard_lat), Number(row.yard_lng), Number(row.lat), Number(row.lng));
|
|
return Math.round(km * 100) / 100;
|
|
}
|