feat(tradein/lead): POST /api/v1/trade-in/lead — persist contact leads (#2376) #2390

Merged
lekss361 merged 1 commit from feat/tradein-lead-endpoint into main 2026-07-04 07:12:23 +00:00
Owner

Summary

  • Новая таблица trade_in_leads (миграция 172_trade_in_leads.sql): id, estimate_id FK→trade_in_estimates (ON DELETE SET NULL), phone, consent (CHECK IS TRUE), source, user_agent, created_at, notified_at.
  • POST /api/v1/trade-in/lead — валидация estimate_id существует (404 если нет) → INSERT RETURNING → commit → structured log (без PII в логах). consent: Literal[True] — 422 при false/отсутствии.
  • Notification (email/Telegram) — намеренно НЕ строится: нет существующей интеграции нигде в кодовой базе (тот же гэп, что у pilot.py).
  • Подготавливает контракт для frontend sub-issue #2377 (замена mailto-CTA на форму).

Test plan

  • 6 offline тестов (test_trade_in_lead.py) — happy path, consent=false→422, missing consent→422, invalid phone→422, unknown estimate_id→404 (no commit), known estimate_id→200
  • pytest tests/test_trade_in_lead.py tests/test_migrations_manifest.py — 10/10 passed
  • Full backend suite: 3284 passed, 6 skipped, 1 pre-existing unrelated failure (confirmed on clean main)
  • ruff check — clean; CAST(:x AS type) psycopg v3 conventions everywhere
  • code-review: APPROVE (только minor: TOCTOU на несуществующем сейчас delete-flow, unrelated manifest-gap из прошлого PR #2346 — оба не блокеры)

Refs #2376, parent #1971

## Summary - Новая таблица `trade_in_leads` (миграция `172_trade_in_leads.sql`): id, estimate_id FK→trade_in_estimates (ON DELETE SET NULL), phone, consent (CHECK IS TRUE), source, user_agent, created_at, notified_at. - `POST /api/v1/trade-in/lead` — валидация `estimate_id` существует (404 если нет) → INSERT RETURNING → commit → structured log (без PII в логах). `consent: Literal[True]` — 422 при false/отсутствии. - Notification (email/Telegram) — намеренно НЕ строится: нет существующей интеграции нигде в кодовой базе (тот же гэп, что у `pilot.py`). - Подготавливает контракт для frontend sub-issue #2377 (замена mailto-CTA на форму). ## Test plan - [x] 6 offline тестов (`test_trade_in_lead.py`) — happy path, consent=false→422, missing consent→422, invalid phone→422, unknown estimate_id→404 (no commit), known estimate_id→200 - [x] `pytest tests/test_trade_in_lead.py tests/test_migrations_manifest.py` — 10/10 passed - [x] Full backend suite: 3284 passed, 6 skipped, 1 pre-existing unrelated failure (confirmed on clean main) - [x] `ruff check` — clean; `CAST(:x AS type)` psycopg v3 conventions everywhere - [x] code-review: ✅ APPROVE (только minor: TOCTOU на несуществующем сейчас delete-flow, unrelated manifest-gap из прошлого PR #2346 — оба не блокеры) Refs #2376, parent #1971
lekss361 added 1 commit 2026-07-04 07:02:13 +00:00
feat(tradein/lead): POST /api/v1/trade-in/lead — persist contact leads (#2376)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m48s
ada9bb8125
Contact capture (phone + consent) from estimate result / landing page.
New trade_in_leads table (migration 172), estimate_id FK validated
before insert (404 if unknown). Notification (Telegram/email)
intentionally out of scope — no existing SMTP/Telegram integration
anywhere in the codebase (same gap as pilot.py's TODO).
lekss361 merged commit 2538fc02e2 into main 2026-07-04 07:12:23 +00:00
lekss361 deleted branch feat/tradein-lead-endpoint 2026-07-04 07:12:23 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2390
No description provided.