dispatch page
This commit is contained in:
89
scripts/checkOptimiser.ts
Normal file
89
scripts/checkOptimiser.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* The route-plan chain, run against the live optimiser.
|
||||
*
|
||||
* Not a test — the unit tests pin `routePlan.ts` against a frozen fixture. This
|
||||
* calls the real service with real order rows and pushes the answer through the
|
||||
* same functions the drawer uses, which is the only way to notice the service
|
||||
* changing shape under us.
|
||||
*
|
||||
* npm run check:optimiser
|
||||
*/
|
||||
|
||||
import { optimiserApi } from '../src/api/optimiser';
|
||||
import type { OrderRow, RiderInfo } from '../src/api/types';
|
||||
import {
|
||||
applyReconcile,
|
||||
commitProblem,
|
||||
dirtyRiders,
|
||||
planFromSequence,
|
||||
splitRoutable,
|
||||
planKms,
|
||||
reorderStops,
|
||||
unplaced,
|
||||
} from '../src/features/store-admin/routePlan';
|
||||
|
||||
const line = (s = '') => console.log(s);
|
||||
|
||||
/** Real Suriya Store geography: the RS Puram branch out to four drops. */
|
||||
const ORDERS: OrderRow[] = [
|
||||
{ orderheaderid: 1, orderid: 'N-1', pickuplat: '11.0118', pickuplong: '76.9456', deliverylat: '11.0284', deliverylong: '77.0120', deliverycustomer: 'Peelamedu' },
|
||||
{ orderheaderid: 2, orderid: 'N-2', pickuplat: '11.0118', pickuplong: '76.9456', deliverylat: '11.0050', deliverylong: '76.9508', deliverycustomer: 'RS Puram' },
|
||||
{ orderheaderid: 3, orderid: 'N-3', pickuplat: '11.0118', pickuplong: '76.9456', deliverylat: '10.9877', deliverylong: '76.9620', deliverycustomer: 'Ukkadam' },
|
||||
{ orderheaderid: 4, orderid: 'N-4', pickuplat: '11.0118', pickuplong: '76.9456', deliverylat: '11.0183', deliverylong: '76.9724', deliverycustomer: 'Gandhipuram' },
|
||||
// No coordinates — must come back as unplaced rather than vanishing.
|
||||
{ orderheaderid: 5, orderid: 'N-5', deliverycustomer: 'No location on file' },
|
||||
] as OrderRow[];
|
||||
|
||||
const RIDER: RiderInfo = { userid: 9701, fullname: 'Meera Raj', contactno: '9000000001' };
|
||||
|
||||
line('─'.repeat(74));
|
||||
line('1 · SEQUENCE — send in a deliberately bad order, see what comes back');
|
||||
line('─'.repeat(74));
|
||||
|
||||
const { routable, unroutable } = splitRoutable(ORDERS);
|
||||
const stops = await optimiserApi.sequence(routable);
|
||||
let plan = planFromSequence(stops, RIDER);
|
||||
|
||||
for (const stop of plan.riders[0]?.orders ?? []) {
|
||||
line(
|
||||
` ${String(stop.step).padStart(2)} ${(stop.orderid ?? '').padEnd(5)} ` +
|
||||
`${(stop.deliverycustomer ?? '').padEnd(22)} ` +
|
||||
`${String(stop.previouskms ?? '').padStart(5)} km ` +
|
||||
`cum ${String(stop.cumulativekms ?? '').padStart(5)} km ` +
|
||||
`eta ${stop.eta ?? '-'}m actualkms ${stop.actualkms ?? '-'}`,
|
||||
);
|
||||
}
|
||||
line(` total ${planKms(plan).toFixed(1)} km`);
|
||||
|
||||
const missed = [...unroutable, ...unplaced(routable, stops)];
|
||||
line(` unplaced: ${missed.length ? missed.map((o) => o.orderid).join(', ') : 'none'}`);
|
||||
line(` commit allowed? ${commitProblem(plan) === '' ? 'YES' : 'no — ' + commitProblem(plan)}`);
|
||||
|
||||
line();
|
||||
line('─'.repeat(74));
|
||||
line('2 · EDIT — move the first stop to last, which breaks the step numbers');
|
||||
line('─'.repeat(74));
|
||||
|
||||
plan = reorderStops(plan, RIDER.userid, 0, (plan.riders[0]?.orders.length ?? 1) - 1);
|
||||
line(` dirty rounds: ${[...plan.dirty].join(', ')}`);
|
||||
line(` steps now: ${plan.riders[0]?.orders.map((s) => s.step).join(' → ')} <- out of order`);
|
||||
line(` commit allowed? ${commitProblem(plan) === '' ? 'YES' : 'NO'}`);
|
||||
line(` reason: ${commitProblem(plan)}`);
|
||||
|
||||
line();
|
||||
line('─'.repeat(74));
|
||||
line('3 · RECONCILE — the service repairs the step numbers');
|
||||
line('─'.repeat(74));
|
||||
|
||||
try {
|
||||
const response = await optimiserApi.reconcile(dirtyRiders(plan));
|
||||
plan = applyReconcile(plan, response);
|
||||
line(` steps now: ${plan.riders[0]?.orders.map((s) => s.step).join(' → ')}`);
|
||||
line(` dirty rounds: ${plan.dirty.size === 0 ? 'none' : [...plan.dirty].join(', ')}`);
|
||||
line(` commit allowed? ${commitProblem(plan) === '' ? 'YES' : 'no — ' + commitProblem(plan)}`);
|
||||
} catch (error) {
|
||||
line(` reconcile failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
line(` commit still blocked? ${commitProblem(plan) !== '' ? 'YES — correct' : 'NO — WRONG'}`);
|
||||
}
|
||||
|
||||
line();
|
||||
Reference in New Issue
Block a user