Subversion Repositories SmartDukaan

Rev

Show changed files | Details | Compare with Previous | Blame | RSS feed

Filtering Options

Rev Age Author Path Log message Diff
37737 13 h 53 m vikas /trunk/ LMS checklist for call  
37729 14 h 21 m amit /trunk/ lead: one workable lead per mobile, with a 6-month supersede and an L2+ override

There was no choke point for lead creation. Ten sites did `new Lead()` across four
modules -- three in web's LeadController, two in V2FofoLeadController, three in fofo's
LeadController, one in TrialServiceImpl and one in the cron LeadSyncRunner -- and only
ONE of them (fofo /createLead) checked for an existing lead at all. Result on live data:
5,137 mobiles carrying duplicate leads over 12,156 rows, worst case 29 on one number,
and two agents unknowingly working the same shop.

THE RULE, in new LeadCreationService, which all ten now route through:

no active lead on the number -> create
active, last activity >= 6 months -> retire the old one, create the new one, SILENTLY
active, last activity < 6 months -> BLOCK; only an L2+ user may override

Active = status in (pending, followUp) AND the assignee is still an active auth_user.
Last activity = GREATEST(lead.updated/created, MAX(lead_activity.created)).

The stale branch is deliberately quiet. A shop enquiring again after six months is a
handover, not a clash, and mailing on it would train the desk to ignore the alert -- so
only a genuine collision notifies. Live split: 195 stale against 1,241 fresh, and roughly
three blocks a month.

WHY "ACTIVE" ALSO MEANS A LIVE OWNER

331 open leads are assigned to 11 DEACTIVATED accounts (157 to sm@smartdukaan.com alone,
whose newest lead is from 2022). Counting them as active would block fresh enquiries
behind an account nobody can log in to and therefore nobody can close. Requiring a live
owner defuses all 331 without retiring a single row. Retirement here is only ever
REACTIVE -- triggered by a new entry on the same number. Nothing runs on a schedule.

ASSUMPTION worth flagging: a superseded lead becomes status=notInterested (stage DROPPED)
with closure_timestamp and reason 'Superseded after 6 months inactivity', rather than a
new `expired` status. "Closed" is an explicit allow-list in the UI --
Arrays.asList(notInterested, finalized) at V2FofoLeadController:150 and fofo
LeadController:313 -- and there are ~107 references to specific LeadStatus values, so a
new enum value would make these leads vanish from BOTH the open and closed screens.
Stage DROPPED keeps the nuance (the shop never said no) and still maps to notInterested
via LeadStage.toLegacyStatus().

OVERRIDE is L2+ in ANY team, not Call Center only: Sales L1 owns 1,063 of the 1,776 open
leads, so a Call-Center-only gate would funnel every team's collisions through three
people. The MAIL still goes to Call Center L2+, resolved from cs.position at send time
rather than hardcoded. An override is a TAKEOVER -- it closes the existing lead -- because
a second live lead is the exact thing the rule exists to prevent.

UNATTENDED CALLERS (cron sync, CSV upload, trial registration, AI intake) have nobody to
offer an override to, so they use createUnattended: skip the colliding row and mail the
desk rather than throwing. CSV reports imported/duplicateSkipped/duplicateMobiles back to
the operator instead of failing the whole file over one number.

ALSO FIXES selectByMobileNumber, which called getSingleResult and therefore threw
NonUniqueResultException on any mobile with more than one lead -- GlitchTip #99 and #1359,
both still firing. It now prefers the open lead, then the most recently touched.

NOT INCLUDED, deliberately: no DB unique constraint. 10 mobiles already carry more than
one open lead and would have to be resolved by hand first, which conflicts with the
no-auto-retirement rule. The service enforces the invariant going forward.

NEEDS A DBA STEP: user.lead.mobile is unindexed on 37,580 rows, so this check is a full
scan on every create. Index DDL is in the accompanying note; it has NOT been applied.
 
37630 6 d 13 h amit /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/ feat(mail): wire inactive-recipient filter and clean hardcoded addresses

Wire MailRecipientFilter into googleMailSender and gmailRelaySender. Remove inactive/unknown addresses from recipient and access lists, bulk uploader gate to akhil.kumar.
 
37558 12 d 9 h ranu /trunk/ system generated leak bgc l2 can assign to l1 without any geo location  
37557 12 d 11 h ranu /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ system generated leak bgc l2 can assign to l1 without any geo location  
37355 33 d 13 h aman /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ AI lead intake (fofo, live): assign new leads to a random active BGC L1 instead of the hardcoded Khushbu/Archana round-robin  
37324 35 d 10 h aman /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ Lead Management: restrict lead view to field-level sales only (L1-L3). Any SALES position at any level previously forced the own+reportees lead filter, so senior sales heads (L4+ BM/RSM/NSM/co-founder L7) lost visibility of all leads and their dashboard charts collapsed. hasCategory check replaced with isFieldSales() at both view-filter sites; assignee validation untouched.  
37287 42 d 8 h ranu /trunk/ warehouse access  
37048 74 d 8 h ranu /trunk/profitmandi-fofo/src/main/ serching work globally lead management  
37047 74 d 8 h ranu /trunk/profitmandi-fofo/src/main/ targeted calling count on today po rbm  
37036 75 d 8 h aman /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ AI lead intake: round-robin auto-assignment between Khushbu Saxena (authId 134) and Archana Ramola (authId 126), one lead at a time, instead of the hardcoded Shankar Mushran (53). Toggle advances only on a real create (not dedup hits).  
37035 76 d 9 h aman /trunk/profitmandi-fofo/src/main/ AI lead intake in fofo app (deployable via fofo_deploy): add POST /add/lead to fofo LeadController mirroring the profitmandi-web contract (Auth-Token->401, dedup by mobile, NOT-NULL coalesced, stores state+recordingUrl, status=pending, SUCCESS envelope); exclude /add/lead from auth/role/post interceptors in WebConfig; add ai.lead.intake.token to dev/staging/prod (same values as profitmandi-web). Bot repoints host apis.smartdukaan.com -> partners.smartdukaan.com, same path/token/payload.  
37003 80 d 15 h ranu /trunk/profitmandi-fofo/src/main/ positions without partner  
36984 82 d 8 h aman /trunk/ Lead Management: (1) fix date-range CSV download to mirror the on-screen view - all statuses in range PLUS follow-ups - so it no longer returns empty or 500s on empty windows; guard empty result set. (2) Add global lead search (name/mobile/outlet/city across ALL leads, any status/date) wired to the existing lead-table search box (Enter = search all). Bump JS cache version to 369.  
36982 82 d 9 h aman /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ Lead download (downloadDateWiseLead): date-range export now returns all selected statuses including follow-up within From-To. Previously follow-ups ignored the date range and selecting All dropped the other statuses.  
36818 103 d 11 h ranu /trunk/profitmandi-fofo/src/main/java/com/spice/profitmandi/web/controller/ code commit for agenda fill time stamp  
36792 108 d 7 h ranu /trunk/profitmandi-fofo/src/main/ some enhancement and bug fixes  
36789 108 d 15 h ranu /trunk/profitmandi-fofo/src/main/ some enhancement and bug fixes  
36787 108 d 16 h ranu /trunk/ some enhancement and bug fixes  
36761 111 d 6 h ranu /trunk/profitmandi-fofo/src/main/ some Enhancements or changes  

Show All