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:
Deeman
2026-02-25 09:53:19 +01:00
parent 607dc35a9d
commit 3c0f57c0fd
4 changed files with 15 additions and 5 deletions

View File

@@ -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"]),
)

View File

@@ -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"
)

View File

@@ -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:

View File

@@ -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 (