dispatch page

This commit is contained in:
2026-09-05 15:01:16 +05:30
parent 37b0833328
commit 5006a4f0d4
8 changed files with 1120 additions and 1 deletions

89
scripts/checkOptimiser.ts Normal file
View 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();