94 lines
3.7 KiB
JavaScript
94 lines
3.7 KiB
JavaScript
// ==============================|| Skill: High-Value COD Escort ||============================== //
|
|
|
|
const OPEN_STATUSES = new Set(['pending', 'accepted', 'arrived', 'picked', 'active', 'skipped']);
|
|
const isOpen = (row) => OPEN_STATUSES.has(String(row?.orderstatus || '').toLowerCase());
|
|
const ref = (row) => row?.orderid || row?.bookingno || (row?.bookingid ? `#${row.bookingid}` : '—');
|
|
|
|
export const HighValueCodSkill = {
|
|
id: 'skill_high_value_cod',
|
|
name: 'High-Value Cash Guardian',
|
|
description: 'Audits large Cash-on-Delivery consignments to prevent loss, fraud, or unverified deliveries.',
|
|
category: 'loss_prevention',
|
|
icon: 'ShieldCheck',
|
|
// OFF by default (2026-09-29): the rows this rule reads carry no payment amount or payment mode: /admin/bookings does not preload bookingpayments.
|
|
// Enabled, it would read undefined on every row and report an all-clear board —
|
|
// the silent failure normalise.js warns about. Turn it on only once the data exists.
|
|
dataGap: 'no payment amount or payment mode: /admin/bookings does not preload bookingpayments',
|
|
defaultEnabled: false,
|
|
|
|
thresholds: {
|
|
codRiskThresholdAmount: {
|
|
label: 'High-Value COD Threshold (₹)',
|
|
description: 'Cash-on-Delivery amount above which an order is classified as high-risk cash asset.',
|
|
value: 3000,
|
|
min: 1000,
|
|
max: 20000,
|
|
step: 500,
|
|
unit: '₹'
|
|
}
|
|
},
|
|
|
|
instructions: `
|
|
- High-value COD consignments must require OTP verification at the doorstep and verified senior rider assignment.
|
|
`,
|
|
|
|
tools: [
|
|
{
|
|
name: 'enforce_otp_verification',
|
|
description: 'Flags an order as strictly requiring consignee OTP delivery confirmation before handover.',
|
|
parameters: {
|
|
type: 'object',
|
|
properties: {
|
|
bookingId: { type: 'number', description: 'Target booking ID' }
|
|
},
|
|
required: ['bookingId']
|
|
},
|
|
handler: async (args) => ({
|
|
success: true,
|
|
proposal: {
|
|
action: 'require_otp',
|
|
bookingId: args.bookingId,
|
|
blastRadius: `Enables mandatory OTP confirmation on mobile app for parcel #${args.bookingId}.`
|
|
}
|
|
})
|
|
}
|
|
],
|
|
|
|
evaluate: (rows = [], now, currentThresholds = {}) => {
|
|
const minAmount = currentThresholds.codRiskThresholdAmount ?? 3000;
|
|
const safeRows = Array.isArray(rows) ? rows : [];
|
|
|
|
const highValueCod = safeRows.filter((r) => {
|
|
if (!isOpen(r)) return false;
|
|
const isCod = String(r.paymenttype || r.payment_mode || '').toLowerCase().includes('cod') ||
|
|
String(r.paymentstatus || '').toLowerCase() === 'pending';
|
|
const amount = Number(r.orderamount || r.totalamount || r.price || 0);
|
|
return isCod && amount >= minAmount;
|
|
});
|
|
|
|
if (!highValueCod.length) return [];
|
|
|
|
return [
|
|
{
|
|
id: 'high_value_cod_alert',
|
|
skillId: 'skill_high_value_cod',
|
|
severity: 'watch',
|
|
title: `${highValueCod.length} high-value COD consignment${highValueCod.length === 1 ? '' : 's'} (≥ ₹${minAmount.toLocaleString()}) active`,
|
|
why: `Large cash collection in transit requires mandatory OTP handover verification.`,
|
|
count: highValueCod.length,
|
|
rows: highValueCod,
|
|
detail: highValueCod.slice(0, 8).map((r) => {
|
|
const amt = Number(r.orderamount || r.totalamount || r.price || 0);
|
|
return `${ref(r)} — ₹${amt.toLocaleString()} (${r.orderstatus || 'active'})`;
|
|
}),
|
|
proposal: {
|
|
label: 'Verify OTP requirements',
|
|
tool: 'enforce_otp_verification',
|
|
scope: highValueCod,
|
|
blastRadius: 'Sets strict OTP delivery guard on high-value cash deliveries.'
|
|
}
|
|
}
|
|
];
|
|
}
|
|
};
|