/* How far do the agent's numbers drift from the CRM dashboard? The dashboard resolves a lead's stage by looking up `leadstages` and taking the furthest stage across pipelines; the CRM's own code comments say `Lead.current_stage` is "stale and never written". The agent's lead tools read that stale field, so this measures the resulting gap. */ import jwt from 'jsonwebtoken'; import dotenv from 'dotenv'; import { connectMongo } from '../src/data/mongo.js'; import { Lead } from '../src/data/models/index.js'; dotenv.config(); const CRM = process.env.CRM_PUBLIC_URL || 'https://crm.wele.in'; const token = jwt.sign({ id: '6a00cefe524bebd27037a968' }, process.env.CRM_JWT_SECRET, { expiresIn: '15m' }); await connectMongo(); // ── what the AGENT currently reports (stale field) ────────────────────────── const agentStages = await Lead.aggregate([ { $group: { _id: '$current_stage', n: { $sum: 1 } } }, { $sort: { n: -1 } }, ]); const agent = Object.fromEntries(agentStages.map((r) => [r._id || 'unset', r.n])); const agentTotal = agentStages.reduce((s, r) => s + r.n, 0); // ── what the DASHBOARD reports (leadstages lookup, workshop excluded) ─────── // parseRange takes from/to as YYYY-MM-DD in IST and DEFAULTS TO TODAY — a // missing range silently returns one day, which is the first trap here. const today = new Date(Date.now() + 5.5 * 3600e3).toISOString().slice(0, 10); const res = await fetch(`${CRM}/api/dashboard/leads?from=2020-01-01&to=${today}`, { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(60000), }); if (!res.ok) { console.log(`dashboard call failed: ${res.status} ${(await res.text()).slice(0, 200)}`); process.exit(1); } const dash = await res.json(); console.log('=== DASHBOARD response shape ==='); console.log(' ', Object.keys(dash).join(', ')); const d = dash.data ?? dash; console.log(' data keys:', Object.keys(d).join(', ')); console.log('\n=== TOTAL LEADS ==='); console.log(` agent (Lead collection) ${agentTotal}`); console.log(` dashboard totalLeads ${d.totalLeads ?? d.total ?? '(not found)'}`); console.log('\n=== STAGE DISTRIBUTION ==='); console.log(` ${'stage'.padEnd(24)} ${'agent'.padStart(7)} ${'dashboard'.padStart(10)} gap`); console.log(` dashboard cards.total_leads ${d.cards?.total_leads}`); console.log(` dashboard range ${d.range?.from} → ${d.range?.to}`); const funnel = d.funnel || d.stages || {}; const dashStages = Array.isArray(funnel) ? Object.fromEntries(funnel.map((f) => [f._id || f.stage || f.name, f.count ?? f.total])) : funnel; const keys = [...new Set([...Object.keys(agent), ...Object.keys(dashStages)])]; for (const k of keys) { const a = agent[k] ?? 0; const b = dashStages[k] ?? 0; const gap = b - a; console.log(` ${String(k).padEnd(24)} ${String(a).padStart(7)} ${String(b).padStart(10)} ${gap === 0 ? '—' : (gap > 0 ? '+' : '') + gap}`); } console.log('\nRaw dashboard payload (first 900 chars) for field mapping:'); console.log(JSON.stringify(d).slice(0, 900)); process.exit(0);