feat(leads): 2-hour admin review window before leads appear in supplier feed
New visible_from column on lead_requests set to NOW + 2h on both the
direct insert (logged-in user) and the email verification update.
Supplier feed, notify_matching_suppliers, and send_weekly_lead_digest
all filter on visible_from <= datetime('now'), so no lead surfaces to
suppliers before the window expires.
Migration 0023 adds the column and backfills existing verified leads
with created_at so they remain immediately visible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -346,8 +346,8 @@ async def quote_request():
|
|||||||
previous_supplier_contact, services_needed, additional_info,
|
previous_supplier_contact, services_needed, additional_info,
|
||||||
contact_name, contact_email, contact_phone, contact_company,
|
contact_name, contact_email, contact_phone, contact_company,
|
||||||
stakeholder_type,
|
stakeholder_type,
|
||||||
heat_score, status, credit_cost, token, created_at)
|
heat_score, status, credit_cost, token, created_at, visible_from)
|
||||||
VALUES (?, 'quote', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, 'quote', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', '+2 hours'))""",
|
||||||
(
|
(
|
||||||
user_id,
|
user_id,
|
||||||
form.get("court_count", 0),
|
form.get("court_count", 0),
|
||||||
@@ -522,7 +522,7 @@ async def verify_quote():
|
|||||||
credit_cost = compute_credit_cost(dict(lead))
|
credit_cost = compute_credit_cost(dict(lead))
|
||||||
now = utcnow_iso()
|
now = utcnow_iso()
|
||||||
await execute(
|
await execute(
|
||||||
"UPDATE lead_requests SET status = 'new', verified_at = ?, credit_cost = ? WHERE id = ?",
|
"UPDATE lead_requests SET status = 'new', verified_at = ?, credit_cost = ?, visible_from = datetime('now', '+2 hours') WHERE id = ?",
|
||||||
(now, credit_cost, lead["id"]),
|
(now, credit_cost, lead["id"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
"""Migration 0023: Add visible_from to lead_requests for 2-hour admin review window."""
|
||||||
|
|
||||||
|
|
||||||
|
def up(conn) -> None:
|
||||||
|
conn.execute("ALTER TABLE lead_requests ADD COLUMN visible_from TEXT")
|
||||||
|
# Backfill: existing verified leads are already past review — make them visible immediately
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE lead_requests SET visible_from = created_at WHERE status = 'new' AND verified_at IS NOT NULL"
|
||||||
|
)
|
||||||
@@ -513,7 +513,7 @@ async def signup_success():
|
|||||||
|
|
||||||
async def _get_lead_feed_data(supplier, country="", heat="", timeline="", q="", limit=50):
|
async def _get_lead_feed_data(supplier, country="", heat="", timeline="", q="", limit=50):
|
||||||
"""Shared query for lead feed — used by standalone and dashboard."""
|
"""Shared query for lead feed — used by standalone and dashboard."""
|
||||||
wheres = ["lr.lead_type = 'quote'", "lr.status = 'new'", "lr.verified_at IS NOT NULL"]
|
wheres = ["lr.lead_type = 'quote'", "lr.status = 'new'", "lr.verified_at IS NOT NULL", "lr.visible_from <= datetime('now')"]
|
||||||
params: list = []
|
params: list = []
|
||||||
|
|
||||||
if country:
|
if country:
|
||||||
|
|||||||
@@ -567,7 +567,7 @@ async def handle_notify_matching_suppliers(payload: dict) -> None:
|
|||||||
lang = payload.get("lang", "en")
|
lang = payload.get("lang", "en")
|
||||||
|
|
||||||
lead = await fetch_one(
|
lead = await fetch_one(
|
||||||
"SELECT * FROM lead_requests WHERE id = ? AND status = 'new' AND verified_at IS NOT NULL",
|
"SELECT * FROM lead_requests WHERE id = ? AND status = 'new' AND verified_at IS NOT NULL AND visible_from <= datetime('now')",
|
||||||
(lead_id,),
|
(lead_id,),
|
||||||
)
|
)
|
||||||
if not lead or not lead.get("country"):
|
if not lead or not lead.get("country"):
|
||||||
@@ -652,6 +652,7 @@ async def handle_send_weekly_lead_digest(payload: dict) -> None:
|
|||||||
f"""SELECT id, heat_score, country, court_count, facility_type, timeline, credit_cost, created_at
|
f"""SELECT id, heat_score, country, court_count, facility_type, timeline, credit_cost, created_at
|
||||||
FROM lead_requests
|
FROM lead_requests
|
||||||
WHERE lead_type = 'quote' AND status = 'new' AND verified_at IS NOT NULL
|
WHERE lead_type = 'quote' AND status = 'new' AND verified_at IS NOT NULL
|
||||||
|
AND visible_from <= datetime('now')
|
||||||
AND country IN ({placeholders})
|
AND country IN ({placeholders})
|
||||||
AND created_at >= datetime('now', '-7 days')
|
AND created_at >= datetime('now', '-7 days')
|
||||||
AND NOT EXISTS (
|
AND NOT EXISTS (
|
||||||
|
|||||||
Reference in New Issue
Block a user