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,
|
||||
contact_name, contact_email, contact_phone, contact_company,
|
||||
stakeholder_type,
|
||||
heat_score, status, credit_cost, token, created_at)
|
||||
VALUES (?, 'quote', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
heat_score, status, credit_cost, token, created_at, visible_from)
|
||||
VALUES (?, 'quote', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', '+2 hours'))""",
|
||||
(
|
||||
user_id,
|
||||
form.get("court_count", 0),
|
||||
@@ -522,7 +522,7 @@ async def verify_quote():
|
||||
credit_cost = compute_credit_cost(dict(lead))
|
||||
now = utcnow_iso()
|
||||
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"]),
|
||||
)
|
||||
|
||||
|
||||
@@ -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):
|
||||
"""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 = []
|
||||
|
||||
if country:
|
||||
|
||||
@@ -567,7 +567,7 @@ async def handle_notify_matching_suppliers(payload: dict) -> None:
|
||||
lang = payload.get("lang", "en")
|
||||
|
||||
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,),
|
||||
)
|
||||
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
|
||||
FROM lead_requests
|
||||
WHERE lead_type = 'quote' AND status = 'new' AND verified_at IS NOT NULL
|
||||
AND visible_from <= datetime('now')
|
||||
AND country IN ({placeholders})
|
||||
AND created_at >= datetime('now', '-7 days')
|
||||
AND NOT EXISTS (
|
||||
|
||||
Reference in New Issue
Block a user