feat: 7-module VINchecker v2 — NICB, auction history, Florida DMV, theft stats, odometer fraud, safety ratings, risk score expansion
New modules: nicb.py, auction_history.py, dmv_florida.py, theft_stats.py, odometer_validator.py Expanded risk.py with 8 new factors (NICB alert, safety rating, auction flags, odo validation, theft level, odo fraud, DMV lien, open VIN recalls) PDF now has 11 sections including NICB check, theft stats, odometer fraud, odometer validation, auction history, Florida HSMV AI prompt enriched with all new data fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,10 +21,15 @@ from src.ai.ollama_analyzer import analyze_vehicle
|
||||
from src.api.epa import fetch_epa_data
|
||||
from src.api.nhtsa import (
|
||||
decode_vin, fetch_complaints, fetch_investigations, fetch_recalls,
|
||||
fetch_vin_recalls, fetch_safety_ratings,
|
||||
fetch_vin_recalls, fetch_safety_ratings, check_odometer_complaints,
|
||||
)
|
||||
from src.api.nicb import check_nicb
|
||||
from src.api.auction_history import search_auction_history
|
||||
from src.api.dmv_florida import check_florida_dmv
|
||||
from src.api.theft_stats import get_theft_risk
|
||||
from src.report.pdf import generate_pdf
|
||||
from src.utils.risk import calculate_risk, compute_extended_fields
|
||||
from src.utils.odometer_validator import validate_odometer
|
||||
from src.utils.validator import validate_vin
|
||||
|
||||
Path("output").mkdir(exist_ok=True)
|
||||
@@ -117,31 +122,44 @@ async def fetch(
|
||||
yield evt(f"✅ Vehículo: {year} {make} {model}", "success")
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
# 3 — Recalls + Complaints + Investigations + VIN check + Safety (paralelo)
|
||||
yield evt("⏳ Consultando NHTSA: recalls, quejas, VIN check, seguridad...", "progress")
|
||||
recalls, complaints, invests, vin_recalls, safety_ratings = await asyncio.gather(
|
||||
# 3 — NHTSA + EPA + NICB + Subastas + DMV (todo en paralelo)
|
||||
yield evt("⏳ Consultando NHTSA, EPA, NICB, historial web, Florida DMV...", "progress")
|
||||
(
|
||||
recalls, complaints, invests,
|
||||
vin_recalls, safety_ratings, epa,
|
||||
nicb, auction_hist, dmv_fl,
|
||||
) = await asyncio.gather(
|
||||
fetch_recalls(make, model, year),
|
||||
fetch_complaints(make, model, year),
|
||||
fetch_investigations(make, model, year),
|
||||
fetch_vin_recalls(vin_clean),
|
||||
fetch_safety_ratings(year, make, model),
|
||||
fetch_epa_data(year, make, model),
|
||||
check_nicb(vin_clean),
|
||||
search_auction_history(vin_clean),
|
||||
check_florida_dmv(vin_clean),
|
||||
)
|
||||
open_count = len(vin_recalls)
|
||||
|
||||
# Local enrichment (no I/O)
|
||||
theft_info = get_theft_risk(make, model)
|
||||
odo_check = validate_odometer(year, odometer or "0")
|
||||
odo_fraud = check_odometer_complaints(complaints)
|
||||
|
||||
open_vin_recalls = len([
|
||||
r for r in vin_recalls
|
||||
if not (r.get("RemedyAvailability") or "").lower().startswith("remedy")
|
||||
])
|
||||
stars = safety_ratings.get("overall", "")
|
||||
stars_txt = f" · {stars}★ seguridad" if stars and stars != "NR" else ""
|
||||
nicb_status = nicb.get("status", "NO_DISPONIBLE")
|
||||
yield evt(
|
||||
f"✅ {len(recalls)} recalls · {len(complaints)} quejas · {open_count} VIN-recalls{stars_txt}",
|
||||
f"✅ {len(recalls)} recalls · {len(complaints)} quejas · "
|
||||
f"NICB: {nicb_status} · "
|
||||
f"{stars+'★' if stars and stars != 'NR' else 'seg. N/A'}",
|
||||
"success",
|
||||
)
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
# 4 — EPA
|
||||
yield evt("⏳ Consultando EPA FuelEconomy...", "progress")
|
||||
epa = await fetch_epa_data(year, make, model)
|
||||
yield evt(f"✅ Eficiencia: {epa.get('mpg_combined', 'N/A')}", "success")
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
# 5 — Photo
|
||||
# 4 — Photo
|
||||
photo_bytes = None
|
||||
if photo_url and photo_url.strip():
|
||||
yield evt("⏳ Descargando foto del vehículo...", "progress")
|
||||
@@ -166,6 +184,15 @@ async def fetch(
|
||||
secondary_damage=secondary_damage or "",
|
||||
complaints=complaints,
|
||||
odometer=odometer or "0",
|
||||
nicb_status=nicb_status,
|
||||
safety_overall=stars,
|
||||
auction_flags=auction_hist.get("flags", []),
|
||||
auction_pts=auction_hist.get("extra_points", 0),
|
||||
odo_extra_pts=odo_check.get("extra_points", 0),
|
||||
theft_level=theft_info.get("level", ""),
|
||||
odo_fraud_count=odo_fraud.get("count", 0),
|
||||
dmv_has_lien=dmv_fl.get("has_lien", False),
|
||||
open_vin_recalls=open_vin_recalls,
|
||||
)
|
||||
extended = compute_extended_fields(
|
||||
title=title or "",
|
||||
@@ -195,6 +222,12 @@ async def fetch(
|
||||
"complaints": complaints,
|
||||
"vin_recalls": vin_recalls,
|
||||
"safety_ratings": safety_ratings,
|
||||
"nicb": nicb,
|
||||
"auction_hist": auction_hist,
|
||||
"dmv_fl": dmv_fl,
|
||||
"theft_info": theft_info,
|
||||
"odo_check": odo_check,
|
||||
"odo_fraud": odo_fraud,
|
||||
"critical_recall_count": extended["critical_recall_count"],
|
||||
"engine_complaints": extended["engine_complaints"],
|
||||
"transmission_complaints": extended["transmission_complaints"],
|
||||
@@ -224,6 +257,12 @@ async def fetch(
|
||||
"investigations": invests,
|
||||
"vin_recalls": vin_recalls,
|
||||
"safety_ratings": safety_ratings,
|
||||
"nicb": nicb,
|
||||
"auction_hist": auction_hist,
|
||||
"dmv_fl": dmv_fl,
|
||||
"theft_info": theft_info,
|
||||
"odo_check": odo_check,
|
||||
"odo_fraud": odo_fraud,
|
||||
"epa": epa,
|
||||
"risk": risk,
|
||||
"ai_analysis": ai_analysis,
|
||||
|
||||
Reference in New Issue
Block a user