initial commit
This commit is contained in:
@@ -20,11 +20,11 @@ import {
|
||||
getConsignmentLogs,
|
||||
getAdminTenant,
|
||||
getTenantLocations
|
||||
} from '@/api/doormile/endpoints';
|
||||
import { getAdminTenants } from '@/api/doormile/endpoints';
|
||||
import { parseDoormileTimestamp } from '@/lib/doormileTimestamp';
|
||||
import { getRowBatchId, getBatchLabel, BATCHES } from '@/lib/batchBucket';
|
||||
|
||||
} from 'pages/api/doormileApi';
|
||||
import { getalltenants, getallridersummary } from 'pages/api/api';
|
||||
import { parseDoormileTimestamp } from 'utils/doormileTimestamp';
|
||||
import { getRowBatchId, getBatchLabel, BATCHES } from 'utils/batchBucket';
|
||||
import { STATUS } from 'themes/dt/tokens';
|
||||
// Only the read-only half of actions.js belongs here. Tenant resolution,
|
||||
// payload building and execution live in the panel's submit handler — an
|
||||
// intent must have no route to a write.
|
||||
@@ -34,7 +34,7 @@ import { ASSIGN_TRIGGER } from './assignActions';
|
||||
import { REPEAT_TRIGGER } from './repeatRuns';
|
||||
import { CREATE_BULK_TRIGGER } from './bulkOrderActions';
|
||||
import { routeQuestion, isRouteTrustworthy, askDocs } from './ragRouter';
|
||||
import { ORDER_STATUS_LABELS, ORDER_STATUS_ORDER, groupForBookingStatus, isInGroup, statusesInGroup } from '@/lib/orderStatusGroups';
|
||||
import { ORDER_STATUS_LABELS, ORDER_STATUS_ORDER, groupForBookingStatus, isInGroup, statusesInGroup } from 'utils/orderStatusGroups';
|
||||
|
||||
// ==============================|| Doormile Bot — intent catalog ||============================== //
|
||||
//
|
||||
@@ -279,7 +279,7 @@ const batchFromWords = (text) => {
|
||||
// "done"/"completed" alongside "delivered", "declined"/"rejected" alongside
|
||||
// "cancelled". Order matters: more specific phrases are checked before the
|
||||
// broader "delivered" pattern so "undelivered" doesn't false-match it.
|
||||
// Returns an ORDER STATUS GROUP key (@/lib/orderStatusGroups.js) — the same
|
||||
// Returns an ORDER STATUS GROUP key (utils/orderStatusGroups.js) — the same
|
||||
// taxonomy the Orders page's tabs count with. It previously returned api.js's
|
||||
// delivery-status buckets, which is the Deliveries page's rider-centric view,
|
||||
// so "how many assigned orders" never agreed with the Assigned tab.
|
||||
@@ -460,15 +460,6 @@ const summarizeStatuses = (rows) => {
|
||||
// STATUS is the raw palette and has no 'assigned' key; the group taxonomy and
|
||||
// the colour palette are separate concerns and shouldn't be forced to match
|
||||
// names.
|
||||
const STATUS = {
|
||||
pending: '#f59e0b',
|
||||
accepted: '#6366f1',
|
||||
active: '#14b8a6',
|
||||
delivered: '#10b981',
|
||||
cancelled: '#ef4444',
|
||||
muted: '#94a3b8'
|
||||
};
|
||||
|
||||
const GROUP_COLOR = {
|
||||
pending: STATUS.pending,
|
||||
assigned: STATUS.accepted,
|
||||
@@ -512,7 +503,7 @@ const summarizeByField = (rows, field) => {
|
||||
};
|
||||
|
||||
const resolveTenant = async (text) => {
|
||||
const tenants = (await getAdminTenants()) || [];
|
||||
const tenants = (await getalltenants()) || [];
|
||||
const lower = text.toLowerCase();
|
||||
return tenants.find((t) => t.tenantname && lower.includes(String(t.tenantname).toLowerCase()));
|
||||
};
|
||||
@@ -737,7 +728,7 @@ const ABOUT_TRIGGER =
|
||||
// (in-transit) — statusBreakdown's match used to fire on that word alone and
|
||||
// never returns null on a match (it always finds *some* count, even 0), so
|
||||
// it never yielded to riderCounts and every rider question silently called
|
||||
// getBookings instead of getMilerSummary. Fixed two ways, deliberately
|
||||
// getBookings instead of getallridersummary. Fixed two ways, deliberately
|
||||
// redundant: riderCounts/tenantList are ordered ahead of the generic
|
||||
// intents below (INTENTS is checked in order, first match wins), AND the
|
||||
// generic intents explicitly refuse to match when "rider" is mentioned, so
|
||||
@@ -1175,7 +1166,7 @@ const INTENTS = [
|
||||
return name ? { name } : null;
|
||||
},
|
||||
run: async ({ name }) => {
|
||||
const tenants = (await getAdminTenants()) || [];
|
||||
const tenants = (await getalltenants()) || [];
|
||||
const match = bestNameMatch(name, tenants, (t) => t.tenantname);
|
||||
if (!match) return null;
|
||||
const [detail, locations] = await Promise.all([
|
||||
@@ -1194,7 +1185,7 @@ const INTENTS = [
|
||||
? { title: 'Locations', items: sites.map((l) => ({ label: l.locationname || `Location ${l.locationid}`, meta: l.pincode })) }
|
||||
: undefined,
|
||||
sourceCalls: [
|
||||
{ name: 'getAdminTenants', target: '/admin/tenants', status: 'complete', stats: `matched ${t.tenantname}` },
|
||||
{ name: 'getalltenants', target: '/admin/tenants', status: 'complete', stats: `matched ${t.tenantname}` },
|
||||
{ name: 'getAdminTenant', target: `/admin/tenants/${match.tenantid}`, status: detail ? 'complete' : 'error' },
|
||||
{
|
||||
name: 'getTenantLocations',
|
||||
@@ -1339,8 +1330,8 @@ const INTENTS = [
|
||||
let tenant = null;
|
||||
let tenants = null;
|
||||
if (tenantName || ranking?.groupBy === 'tenant') {
|
||||
tenants = (await getAdminTenants()) || [];
|
||||
sourceCalls.push({ name: 'getAdminTenants', target: '/admin/tenants', status: 'complete', stats: `${tenants.length} tenants` });
|
||||
tenants = (await getalltenants()) || [];
|
||||
sourceCalls.push({ name: 'getalltenants', target: '/admin/tenants', status: 'complete', stats: `${tenants.length} tenants` });
|
||||
if (tenantName) {
|
||||
tenant = bestNameMatch(tenantName, tenants, (t) => t.tenantname);
|
||||
// Unrecognised name — don't quietly drop the filter and answer a
|
||||
@@ -1457,13 +1448,13 @@ const INTENTS = [
|
||||
label: 'Rider availability — e.g. "how many riders are active"',
|
||||
match: (text) => (mentionsRiders(text) ? {} : null),
|
||||
run: async () => {
|
||||
const summary = await getMilerSummary();
|
||||
const summary = await getallridersummary();
|
||||
return {
|
||||
headline: `${summary?.active ?? 0} active riders (${summary?.available ?? 0} available, ${
|
||||
summary?.onDelivery ?? 0
|
||||
} on a delivery) out of ${summary?.total ?? 0} total.`,
|
||||
detail: `${summary?.inactive ?? 0} inactive/offline.`,
|
||||
sourceCalls: [{ name: 'getMilerSummary', target: '/admin/milers', status: 'complete', stats: `${summary?.total ?? 0} riders` }]
|
||||
sourceCalls: [{ name: 'getallridersummary', target: '/admin/milers', status: 'complete', stats: `${summary?.total ?? 0} riders` }]
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -1472,7 +1463,7 @@ const INTENTS = [
|
||||
label: 'Tenant count — e.g. "how many tenants do we have"',
|
||||
match: (text) => (/\btenants?\b/i.test(text) && /\bhow many\b|\blist\b|\ball\b/i.test(text) ? {} : null),
|
||||
run: async () => {
|
||||
const tenants = (await getAdminTenants()) || [];
|
||||
const tenants = (await getalltenants()) || [];
|
||||
return {
|
||||
headline: `${tenants.length} tenant${tenants.length === 1 ? '' : 's'} total.`,
|
||||
metric: { value: tenants.length, label: 'Tenants' },
|
||||
@@ -1484,7 +1475,7 @@ const INTENTS = [
|
||||
.filter((t) => t.tenantname)
|
||||
.map((t) => ({ label: t.tenantname, meta: t.tenantid != null ? `#${t.tenantid}` : undefined }))
|
||||
},
|
||||
sourceCalls: [{ name: 'getAdminTenants', target: '/admin/tenants', status: 'complete', stats: `${tenants.length} tenants` }]
|
||||
sourceCalls: [{ name: 'getalltenants', target: '/admin/tenants', status: 'complete', stats: `${tenants.length} tenants` }]
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -1870,7 +1861,7 @@ const INTENTS = [
|
||||
// rather than failing the whole answer.
|
||||
const scan = await fetchBookingsInRange(start, end);
|
||||
const rows = scan.rows;
|
||||
const riders = await getMilerSummary().catch(() => null);
|
||||
const riders = await getallridersummary().catch(() => null);
|
||||
return {
|
||||
headline: `${countPhrase(scan, rows.length)} order${rows.length === 1 ? '' : 's'} ${rangeLabel}.`,
|
||||
metric: { value: rows.length, label: `Orders ${rangeLabel}${scan.truncated ? ' (at least)' : ''}` },
|
||||
@@ -1885,8 +1876,8 @@ const INTENTS = [
|
||||
sourceCalls: [
|
||||
scanCall(scan, `${rows.length} orders ${rangeLabel}`),
|
||||
riders
|
||||
? { name: 'getMilerSummary', target: '/admin/milers', status: 'complete', stats: `${riders.total} riders` }
|
||||
: { name: 'getMilerSummary', target: '/admin/milers', status: 'error', errorMessage: 'Rider summary unavailable' }
|
||||
? { name: 'getallridersummary', target: '/admin/milers', status: 'complete', stats: `${riders.total} riders` }
|
||||
: { name: 'getallridersummary', target: '/admin/milers', status: 'error', errorMessage: 'Rider summary unavailable' }
|
||||
]
|
||||
};
|
||||
}
|
||||
@@ -2019,7 +2010,7 @@ const INTENTS = [
|
||||
stats: statusStats(matched),
|
||||
detail: `Out of ${rows.length} orders created ${describeDay(day)} across all tenants.` + truncationNote(scan),
|
||||
sourceCalls: [
|
||||
{ name: 'getAdminTenants', target: '/admin/tenants', status: 'complete' },
|
||||
{ name: 'getalltenants', target: '/admin/tenants', status: 'complete' },
|
||||
scanCall(scan, `${rows.length} total → ${matched.length} for ${tenant.tenantname}`)
|
||||
]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user