mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 09:00:57 +00:00
fix
This commit is contained in:
@@ -48,13 +48,33 @@ export class FirstMileService {
|
||||
private readonly history: FleetHistoryService,
|
||||
) { }
|
||||
|
||||
/** Resolve the driver currently assigned to a vehicle, for stamping mile
|
||||
* events onto that driver's timeline. Best-effort — never throws. */
|
||||
private async resolveDriverId(vehicleId?: string | null): Promise<string | null> {
|
||||
if (!vehicleId) return null;
|
||||
/** Resolve a vehicle's driver + human labels, for stamping mile events onto
|
||||
* the driver's timeline and naming the vehicle. Best-effort — never throws. */
|
||||
private async vehicleInfo(
|
||||
vehicleId?: string | null,
|
||||
): Promise<{ driverId: string | null; plate: string | null; driverName: string | null }> {
|
||||
if (!vehicleId) return { driverId: null, plate: null, driverName: null };
|
||||
try {
|
||||
const vehicle = await this.vehiclesService.findById(vehicleId);
|
||||
return vehicle.assignedDriverId ?? null;
|
||||
const v = await this.vehiclesService.findById(vehicleId);
|
||||
return {
|
||||
driverId: v.assignedDriverId ?? null,
|
||||
plate: v.plateNumber ?? v.code ?? null,
|
||||
driverName: v.assignedDriverName ?? null,
|
||||
};
|
||||
} catch {
|
||||
return { driverId: null, plate: null, driverName: null };
|
||||
}
|
||||
}
|
||||
|
||||
/** Human booking reference for a first-mile record, for the history timeline. */
|
||||
private async resolveBookingRef(record: FirstMile): Promise<string | null> {
|
||||
const loaded = (record as FirstMile & { booking?: { reference?: string } })
|
||||
.booking?.reference;
|
||||
if (loaded) return loaded;
|
||||
if (!record.bookingId) return null;
|
||||
try {
|
||||
const b = await this.bookingsRepository.findById(record.bookingId);
|
||||
return (b as { reference?: string } | null)?.reference ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -225,13 +245,19 @@ export class FirstMileService {
|
||||
|
||||
if (dto.vehicleId) {
|
||||
await this.vehiclesService.setAvailability(dto.vehicleId, VehicleAvailability.BUSY);
|
||||
const info = await this.vehicleInfo(dto.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_ASSIGNED,
|
||||
vehicleId: dto.vehicleId,
|
||||
firstMileId: record.id,
|
||||
driverId: await this.resolveDriverId(dto.vehicleId),
|
||||
driverId: info.driverId,
|
||||
label: record.status,
|
||||
metadata: { mile: 'FIRST' },
|
||||
metadata: {
|
||||
mile: 'FIRST',
|
||||
bookingRef: await this.resolveBookingRef(record),
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -302,23 +328,36 @@ export class FirstMileService {
|
||||
await this.vehiclesService.releaseIfUnused([existing.vehicleId]);
|
||||
}
|
||||
// Audit the mile↔vehicle (re)assignment on both vehicle and driver lines.
|
||||
const bookingRef = await this.resolveBookingRef(existing);
|
||||
if (existing.vehicleId) {
|
||||
const info = await this.vehicleInfo(existing.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_RELEASED,
|
||||
vehicleId: existing.vehicleId,
|
||||
firstMileId: id,
|
||||
driverId: await this.resolveDriverId(existing.vehicleId),
|
||||
metadata: { mile: 'FIRST' },
|
||||
driverId: info.driverId,
|
||||
metadata: {
|
||||
mile: 'FIRST',
|
||||
bookingRef,
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (dto.vehicleId) {
|
||||
const info = await this.vehicleInfo(dto.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_ASSIGNED,
|
||||
vehicleId: dto.vehicleId,
|
||||
firstMileId: id,
|
||||
driverId: await this.resolveDriverId(dto.vehicleId),
|
||||
driverId: info.driverId,
|
||||
label: updated.status,
|
||||
metadata: { mile: 'FIRST' },
|
||||
metadata: {
|
||||
mile: 'FIRST',
|
||||
bookingRef,
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -330,14 +369,20 @@ export class FirstMileService {
|
||||
|
||||
if (dto.status !== undefined && dto.status !== existing.status) {
|
||||
const vehicleId = updated.vehicleId ?? existing.vehicleId ?? null;
|
||||
const info = await this.vehicleInfo(vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_STATUS_CHANGED,
|
||||
firstMileId: id,
|
||||
vehicleId,
|
||||
driverId: await this.resolveDriverId(vehicleId),
|
||||
driverId: info.driverId,
|
||||
fromValue: existing.status,
|
||||
toValue: dto.status,
|
||||
metadata: { mile: 'FIRST' },
|
||||
metadata: {
|
||||
mile: 'FIRST',
|
||||
bookingRef: await this.resolveBookingRef(existing),
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -359,14 +404,20 @@ export class FirstMileService {
|
||||
|
||||
if (status !== existing.status) {
|
||||
const vehicleId = updated.vehicleId ?? existing.vehicleId ?? null;
|
||||
const info = await this.vehicleInfo(vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_STATUS_CHANGED,
|
||||
firstMileId: id,
|
||||
vehicleId,
|
||||
driverId: await this.resolveDriverId(vehicleId),
|
||||
driverId: info.driverId,
|
||||
fromValue: existing.status,
|
||||
toValue: status,
|
||||
metadata: { mile: 'FIRST' },
|
||||
metadata: {
|
||||
mile: 'FIRST',
|
||||
bookingRef: await this.resolveBookingRef(existing),
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -46,15 +46,21 @@ export class LastMileService {
|
||||
private readonly history: FleetHistoryService,
|
||||
) {}
|
||||
|
||||
/** Resolve the driver currently assigned to a vehicle, for stamping mile
|
||||
* events onto that driver's timeline. Best-effort — never throws. */
|
||||
private async resolveDriverId(vehicleId?: string | null): Promise<string | null> {
|
||||
if (!vehicleId) return null;
|
||||
/** Resolve a vehicle's driver + human labels, for stamping mile events onto
|
||||
* the driver's timeline and naming the vehicle. Best-effort — never throws. */
|
||||
private async vehicleInfo(
|
||||
vehicleId?: string | null,
|
||||
): Promise<{ driverId: string | null; plate: string | null; driverName: string | null }> {
|
||||
if (!vehicleId) return { driverId: null, plate: null, driverName: null };
|
||||
try {
|
||||
const vehicle = await this.vehiclesService.findById(vehicleId);
|
||||
return vehicle.assignedDriverId ?? null;
|
||||
const v = await this.vehiclesService.findById(vehicleId);
|
||||
return {
|
||||
driverId: v.assignedDriverId ?? null,
|
||||
plate: v.plateNumber ?? v.code ?? null,
|
||||
driverName: v.assignedDriverName ?? null,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
return { driverId: null, plate: null, driverName: null };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,13 +182,19 @@ export class LastMileService {
|
||||
});
|
||||
|
||||
if (dto.vehicleId) {
|
||||
const info = await this.vehicleInfo(dto.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_ASSIGNED,
|
||||
vehicleId: dto.vehicleId,
|
||||
lastMileId: record.id,
|
||||
driverId: await this.resolveDriverId(dto.vehicleId),
|
||||
driverId: info.driverId,
|
||||
label: record.status,
|
||||
metadata: { mile: 'LAST', bookingRef: await this.resolveBookingRef(record) },
|
||||
metadata: {
|
||||
mile: 'LAST',
|
||||
bookingRef: await this.resolveBookingRef(record),
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -229,36 +241,54 @@ export class LastMileService {
|
||||
const bookingRef = await this.resolveBookingRef(existing);
|
||||
if (dto.vehicleId !== undefined && dto.vehicleId !== existing.vehicleId) {
|
||||
if (existing.vehicleId) {
|
||||
const info = await this.vehicleInfo(existing.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_RELEASED,
|
||||
vehicleId: existing.vehicleId,
|
||||
lastMileId: id,
|
||||
driverId: await this.resolveDriverId(existing.vehicleId),
|
||||
metadata: { mile: 'LAST', bookingRef },
|
||||
driverId: info.driverId,
|
||||
metadata: {
|
||||
mile: 'LAST',
|
||||
bookingRef,
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (dto.vehicleId) {
|
||||
const info = await this.vehicleInfo(dto.vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_VEHICLE_ASSIGNED,
|
||||
vehicleId: dto.vehicleId,
|
||||
lastMileId: id,
|
||||
driverId: await this.resolveDriverId(dto.vehicleId),
|
||||
driverId: info.driverId,
|
||||
label: updated.status,
|
||||
metadata: { mile: 'LAST', bookingRef },
|
||||
metadata: {
|
||||
mile: 'LAST',
|
||||
bookingRef,
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (dto.status !== undefined && dto.status !== existing.status) {
|
||||
const vehicleId = updated.vehicleId ?? existing.vehicleId ?? null;
|
||||
const info = await this.vehicleInfo(vehicleId);
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.MILE_STATUS_CHANGED,
|
||||
lastMileId: id,
|
||||
vehicleId,
|
||||
driverId: await this.resolveDriverId(vehicleId),
|
||||
driverId: info.driverId,
|
||||
fromValue: existing.status,
|
||||
toValue: dto.status,
|
||||
metadata: { mile: 'LAST', bookingRef },
|
||||
metadata: {
|
||||
mile: 'LAST',
|
||||
bookingRef,
|
||||
vehiclePlate: info.plate,
|
||||
driverName: info.driverName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@ export class VehiclesService {
|
||||
vehicleId: saved.id,
|
||||
driverId: saved.assignedDriverId,
|
||||
label: saved.assignedDriverName ?? null,
|
||||
metadata: {
|
||||
vehiclePlate: saved.plateNumber ?? saved.code ?? null,
|
||||
driverName: saved.assignedDriverName ?? null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -133,12 +137,14 @@ export class VehiclesService {
|
||||
dto.assignedDriverId !== undefined &&
|
||||
dto.assignedDriverId !== prev.assignedDriverId
|
||||
) {
|
||||
const vehiclePlate = saved.plateNumber ?? saved.code ?? null;
|
||||
if (prev.assignedDriverId) {
|
||||
await this.history.record({
|
||||
eventType: FleetEventType.DRIVER_UNASSIGNED,
|
||||
vehicleId: id,
|
||||
driverId: prev.assignedDriverId,
|
||||
label: prev.assignedDriverName ?? null,
|
||||
metadata: { vehiclePlate, driverName: prev.assignedDriverName ?? null },
|
||||
});
|
||||
}
|
||||
if (saved.assignedDriverId) {
|
||||
@@ -147,6 +153,7 @@ export class VehiclesService {
|
||||
vehicleId: id,
|
||||
driverId: saved.assignedDriverId,
|
||||
label: saved.assignedDriverName ?? null,
|
||||
metadata: { vehiclePlate, driverName: saved.assignedDriverName ?? null },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user