implemenation on the bot
This commit is contained in:
@@ -46,9 +46,14 @@ import {
|
||||
// right after an assign-miler call — see orders.js's ORDERS_STATUS_TABS
|
||||
// comment) are confirmed; the rest of this mapping is still a best-effort
|
||||
// guess. Unmapped statuses pass through lowercased, which the page's own
|
||||
// fallback renders as an "unknown" badge rather than crashing. There's no
|
||||
// confirmed equivalent for arrived/picked/skipped at all, so those tabs will
|
||||
// show a 0 count until the real enum is confirmed.
|
||||
// fallback renders as an "unknown" badge rather than crashing, AND the
|
||||
// Deliveries page now surfaces those rows under an "Other" tab that names the
|
||||
// unmapped enum — previously such a row was counted nowhere and shown nowhere.
|
||||
// `picked` now has a confirmed source (Converted_To_Consignment, below).
|
||||
// `arrived` and `skipped` still have none: the rider actions that produce them
|
||||
// (POST /miler/bookings/:id/reached, POST /miler/consignments/:id/skip) have no
|
||||
// booking-status equivalent in the confirmed enum, so those two tabs stay at 0
|
||||
// until the backend is confirmed to expose them.
|
||||
//
|
||||
// Miler_Assigned is deliberately kept on 'pending', NOT bumped to 'accepted'.
|
||||
// Assigning a rider is an OPERATOR action (POST /admin/bookings/:id/assign-miler
|
||||
@@ -62,11 +67,20 @@ import {
|
||||
// accepted" in the currently-confirmed enum, so that one maps to 'accepted'.
|
||||
// If the backend turns out to have a distinct status specifically for the
|
||||
// accept action, add it here rather than reusing Miler_Assigned for it.
|
||||
// Converted_To_Consignment is PICKED, not accepted. doormile-flow.md §5 is
|
||||
// explicit: `POST /miler/bookings/:bookingid/pickup-complete` "converts the
|
||||
// booking into a consignment" — so the status is written at the moment the
|
||||
// rider completes pickup, and the parcel is in their hands. deliveries.js says
|
||||
// the same thing from the other side ("this order hasn't been picked up yet —
|
||||
// status can only be updated once it becomes a consignment").
|
||||
//
|
||||
// It sat on 'accepted', which held a picked-up parcel in the Accepted tab and
|
||||
// left Picked permanently empty — nothing else in the enum maps to it.
|
||||
const BOOKING_STATUS_TO_DELIVERY_STATUS = {
|
||||
pending_pickup: 'pending',
|
||||
miler_assigned: 'pending',
|
||||
pickup_scheduled: 'accepted',
|
||||
converted_to_consignment: 'accepted',
|
||||
converted_to_consignment: 'picked',
|
||||
out_for_delivery: 'active',
|
||||
delivered: 'delivered',
|
||||
cancelled: 'cancelled'
|
||||
@@ -135,7 +149,10 @@ export const getRiderPeriodicLogs = async (userid) => {
|
||||
// seeing every hub, unchanged. Fails open (full list) whenever the tenant's
|
||||
// city can't be determined or nothing matches, rather than ever locking an
|
||||
// operator out with an empty picker.
|
||||
const normCity = (s) => String(s || '').trim().toLowerCase();
|
||||
const normCity = (s) =>
|
||||
String(s || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
export const fetchAppLocations = async () => {
|
||||
try {
|
||||
@@ -202,7 +219,16 @@ export const fetchPercentageData = async ({ queryKey }) => {
|
||||
};
|
||||
} catch (err) {
|
||||
OpenToast(err.response?.data?.message || err.message || 'Failed to load order percentages', 'error', 2000);
|
||||
return { created: '0', uncoveredOrders: '0', coveredOrders: '0', cancelled: '0', percentage1: '0', percentage2: '0', percentage3: '0', percentage4: '0' };
|
||||
return {
|
||||
created: '0',
|
||||
uncoveredOrders: '0',
|
||||
coveredOrders: '0',
|
||||
cancelled: '0',
|
||||
percentage1: '0',
|
||||
percentage2: '0',
|
||||
percentage3: '0',
|
||||
percentage4: '0'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -327,7 +353,10 @@ export const fetchBatchEfficiency = async ({ batch, tenantId }) => {
|
||||
// jupiter2doormile.md comparison). Falls back to matching the rider's NAME
|
||||
// (also echoed by the solver, see flattenRiders' rider_name) against each
|
||||
// miler's displayname/authname — the only other correlatable field.
|
||||
const normMilerName = (s) => String(s || '').trim().toLowerCase();
|
||||
const normMilerName = (s) =>
|
||||
String(s || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
export const buildMilerLookup = (milers) => {
|
||||
const byUserId = new Map((milers || []).map((m) => [String(m.userid), m]));
|
||||
@@ -348,10 +377,10 @@ export const resolveMilerForOrder = (order, lookup) => {
|
||||
const matchedVia = lookup.byUserId.has(String(riderUserId))
|
||||
? 'userid'
|
||||
: lookup.byProfileId.has(String(riderUserId))
|
||||
? 'milerprofileid'
|
||||
: lookup.byName.has(normMilerName(riderName))
|
||||
? 'name'
|
||||
: null;
|
||||
? 'milerprofileid'
|
||||
: lookup.byName.has(normMilerName(riderName))
|
||||
? 'name'
|
||||
: null;
|
||||
const rider =
|
||||
lookup.byUserId.get(String(riderUserId)) ?? lookup.byProfileId.get(String(riderUserId)) ?? lookup.byName.get(normMilerName(riderName));
|
||||
return rider?.milerprofileid ? { rider, matchedVia } : null;
|
||||
@@ -407,7 +436,11 @@ export const finalCreatedeliveries = async (deliveryData) => {
|
||||
realBookingIds = new Set(realBookings.map((b) => String(b.bookingid)));
|
||||
logger.debug(`finalCreatedeliveries: ${realBookingIds.size} real booking id(s) fetched for validation`);
|
||||
} catch (err) {
|
||||
logger.error('finalCreatedeliveries: GET /admin/bookings failed — cannot validate booking ids', err.response?.status, err.response?.data || err.message);
|
||||
logger.error(
|
||||
'finalCreatedeliveries: GET /admin/bookings failed — cannot validate booking ids',
|
||||
err.response?.status,
|
||||
err.response?.data || err.message
|
||||
);
|
||||
}
|
||||
|
||||
const results = await Promise.allSettled(
|
||||
@@ -464,11 +497,7 @@ export const finalCreatedeliveries = async (deliveryData) => {
|
||||
if (failed.length) {
|
||||
OpenToast(`${failed.length} of ${deliveries.length} order(s) couldn't be assigned — check Orders/Deliveries`, 'warning', 4000);
|
||||
}
|
||||
const resolvedMilerProfileIds = [
|
||||
...new Set(
|
||||
results.filter((r) => r.status === 'fulfilled').map((r) => r.value.milerprofileid)
|
||||
)
|
||||
];
|
||||
const resolvedMilerProfileIds = [...new Set(results.filter((r) => r.status === 'fulfilled').map((r) => r.value.milerprofileid))];
|
||||
return { success: true, assigned: deliveries.length - failed.length, failed: failed.length, resolvedMilerProfileIds };
|
||||
};
|
||||
// ==============================|| createAutomationDeliveries (orders) Auto rider Assign ||============================== //
|
||||
@@ -536,7 +565,11 @@ export const fetchDeliveries = async ({ pageParam = 1, queryKey }) => {
|
||||
// parameter is documented in express-console-api.md and guessing one risks a
|
||||
// silent 400 or, worse, a silently-ignored filter), so the range is applied
|
||||
// client-side below, after the rows are normalised.
|
||||
const [, , , , startdate, enddate, rowsPerPage] = queryKey;
|
||||
// queryKey[11] is an OPT-IN date basis. Four pages share this function
|
||||
// (deliveries, Dispatch, reports/ordersDetails, reports/profitability) and
|
||||
// three of them genuinely want "created in this window", so the default is
|
||||
// unchanged and only the Deliveries page passes 'activity'.
|
||||
const [, , , , startdate, enddate, rowsPerPage, , , , , dateBasis] = queryKey;
|
||||
// Unlike the 3 joins below (customers/milers/tenants — each individually
|
||||
// guarded so a failed join just degrades a display field, not the whole
|
||||
// page), a failed bookings call is the one thing this function can't
|
||||
@@ -665,14 +698,23 @@ export const fetchDeliveries = async ({ pageParam = 1, queryKey }) => {
|
||||
//
|
||||
// A missing/blank bound means "unbounded on that side", which preserves the
|
||||
// old behaviour for any caller that doesn't pass real dates.
|
||||
//
|
||||
// 'activity' additionally keeps a row whose LAST UPDATE falls in the window.
|
||||
// Scoping the Deliveries page purely by creation date meant an order created
|
||||
// yesterday and picked or delivered today was invisible today — which is
|
||||
// exactly why every tab past Accepted read 0 while the day's fresh orders
|
||||
// filled Pending and Accepted. A delivery board has to show what is moving
|
||||
// now, not only what was booked now.
|
||||
const dayOf = (value) => {
|
||||
const t = parseDoormileTimestamp(value);
|
||||
return t.isValid() ? t.format('YYYY-MM-DD') : null;
|
||||
};
|
||||
|
||||
const inRange = (row) => {
|
||||
if (!startdate && !enddate) return true;
|
||||
const t = parseDoormileTimestamp(row.orderdate);
|
||||
if (!t.isValid()) return false;
|
||||
const day = t.format('YYYY-MM-DD');
|
||||
if (startdate && day < String(startdate)) return false;
|
||||
if (enddate && day > String(enddate)) return false;
|
||||
return true;
|
||||
const days = [dayOf(row.orderdate), dateBasis === 'activity' ? dayOf(row.assigntime) : null].filter(Boolean);
|
||||
if (!days.length) return false;
|
||||
return days.some((day) => (!startdate || day >= String(startdate)) && (!enddate || day <= String(enddate)));
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -815,9 +857,7 @@ export const getallridersummary = async () => {
|
||||
// silently inflating one of the two new buckets.
|
||||
const active = milers.filter((m) => !['offline', 'blocked'].includes(String(m.availabilitystatus || '').toLowerCase())).length;
|
||||
const available = milers.filter((m) => String(m.availabilitystatus || '').toLowerCase() === 'available').length;
|
||||
const onDelivery = milers.filter((m) =>
|
||||
['assigned', 'on_pickup'].includes(String(m.availabilitystatus || '').toLowerCase())
|
||||
).length;
|
||||
const onDelivery = milers.filter((m) => ['assigned', 'on_pickup'].includes(String(m.availabilitystatus || '').toLowerCase())).length;
|
||||
return { total: milers.length, active, inactive: milers.length - active, available, onDelivery };
|
||||
} catch (err) {
|
||||
OpenToast(err.response?.data?.message || err.message || 'Failed to load rider summary', 'error', 2000);
|
||||
|
||||
Reference in New Issue
Block a user