70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import type { RowDataPacket } from "mysql2/promise";
|
|
import { getPool } from "./db";
|
|
import { normalizePhone } from "./phone";
|
|
import { sqlDateToIso } from "./time";
|
|
import { NO_BIKE, pickWorkshopJob, stageLabel, type BikeStatus, type StatusResult } from "./workshop";
|
|
|
|
export async function lookupBikes(rawPhone: string): Promise<StatusResult> {
|
|
const phone = normalizePhone(rawPhone);
|
|
if (!phone) return { message: NO_BIKE, error: null, bikes: [] };
|
|
|
|
const pool = getPool();
|
|
const [customers] = await pool.query<RowDataPacket[]>(
|
|
`SELECT id FROM customers WHERE phone = ? AND deleted_at IS NULL`,
|
|
[phone],
|
|
);
|
|
if (customers.length === 0) return { message: NO_BIKE, error: null, bikes: [] };
|
|
|
|
const customerIds = customers.map((row) => String(row.id));
|
|
const [vehicles] = await pool.query<RowDataPacket[]>(
|
|
`SELECT id, registration, make, model_name FROM vehicles
|
|
WHERE customer_id IN (${customerIds.map(() => "?").join(", ")}) AND deleted_at IS NULL
|
|
ORDER BY registration ASC, id ASC`,
|
|
customerIds,
|
|
);
|
|
if (vehicles.length === 0) return { message: NO_BIKE, error: null, bikes: [] };
|
|
|
|
const bikes: BikeStatus[] = [];
|
|
for (const vehicle of vehicles) {
|
|
const [jobs] = await pool.query<RowDataPacket[]>(
|
|
`SELECT id, stage, created_at FROM job_cards WHERE vehicle_id = ? AND deleted_at IS NULL`,
|
|
[vehicle.id],
|
|
);
|
|
const picked = pickWorkshopJob(
|
|
jobs.map((job) => ({
|
|
id: String(job.id),
|
|
stage: String(job.stage),
|
|
createdAt: sqlDateToIso(job.created_at) ?? "",
|
|
})),
|
|
);
|
|
const registration = String(vehicle.registration ?? "");
|
|
const make = String(vehicle.make ?? "");
|
|
const model = String(vehicle.model_name ?? "");
|
|
if (!picked) {
|
|
bikes.push({
|
|
registration,
|
|
make,
|
|
model,
|
|
inWorkshop: false,
|
|
stageLabel: null,
|
|
stageAt: null,
|
|
});
|
|
continue;
|
|
}
|
|
const [events] = await pool.query<RowDataPacket[]>(
|
|
"SELECT `at` FROM job_card_events WHERE job_card_id = ? AND deleted_at IS NULL ORDER BY `at` DESC, id DESC LIMIT 1",
|
|
[picked.id],
|
|
);
|
|
bikes.push({
|
|
registration,
|
|
make,
|
|
model,
|
|
inWorkshop: true,
|
|
stageLabel: stageLabel(picked.stage),
|
|
stageAt: events[0] ? sqlDateToIso(events[0].at) : null,
|
|
});
|
|
}
|
|
|
|
return { message: null, error: null, bikes };
|
|
}
|