"""Generador del reporte de texto completo.""" from __future__ import annotations from datetime import datetime def build_report( geo: dict, sub_results: dict, scores: dict, overall_score: int, narratives: dict, exec_summary: dict, ) -> dict: """Construye el dict completo del reporte con todas las secciones.""" now = datetime.now() report = { "address": geo.get("address", ""), "lat": geo.get("lat"), "lon": geo.get("lon"), "analysis_date": now.strftime("%Y-%m-%d %H:%M"), "overall_score": overall_score, "scores": scores, "sections": {}, "exec_summary": exec_summary, } # Sección 1: Resumen ejecutivo (construido arriba) report["sections"]["executive"] = { "title": "Resumen Ejecutivo", "score": overall_score, "summary": exec_summary.get("summary", ""), "strengths": exec_summary.get("strengths", []), "weaknesses": exec_summary.get("weaknesses", []), } # Sección 2: Criminalidad crime_data = sub_results.get("crime", {}) report["sections"]["crime"] = { "title": "Criminalidad", "score": scores.get("crime", 0), "total_crimes_30d": crime_data.get("score_input", {}).get("total_crimes_30d", "N/A"), "crime_types": crime_data.get("crime_types", {}), "has_violent": crime_data.get("score_input", {}).get("has_violent", False), "sources": crime_data.get("sources", []), "errors": crime_data.get("errors", []), "narrative": narratives.get("crime", ""), } # Sección 3: Valoración inmobiliaria prop_data = sub_results.get("property", {}) report["sections"]["property"] = { "title": "Valoración y Mercado Inmobiliario", "score": scores.get("property", 0), "estimated_value": prop_data.get("estimated_value"), "price_per_sqft": prop_data.get("price_per_sqft"), "appreciation_1y": prop_data.get("appreciation_1y"), "appreciation_3y": prop_data.get("appreciation_3y"), "days_on_market": prop_data.get("days_on_market"), "median_list_price": prop_data.get("median_list_price"), "inventory": prop_data.get("inventory"), "county_assessed_value": prop_data.get("county_assessed_value"), "sources": prop_data.get("sources", []), "errors": prop_data.get("errors", []), "narrative": narratives.get("property", ""), } # Sección 4: Escuelas school_data = sub_results.get("schools", {}) report["sections"]["schools"] = { "title": "Escuelas", "score": scores.get("schools", 0), "avg_rating": school_data.get("avg_rating"), "schools": school_data.get("schools", []), "best_elementary": school_data.get("best_elementary"), "best_middle": school_data.get("best_middle"), "best_high": school_data.get("best_high"), "sources": school_data.get("sources", []), "errors": school_data.get("errors", []), "narrative": narratives.get("schools", ""), } # Sección 5: Amenities amenity_data = sub_results.get("amenities", {}) report["sections"]["amenities"] = { "title": "Amenities y Walkability", "score": scores.get("amenities", 0), "walk_score": amenity_data.get("walk_score_estimate"), "total_amenities": amenity_data.get("total_amenities", 0), "categories": amenity_data.get("categories", {}), "nearest": amenity_data.get("nearest", {}), "sources": amenity_data.get("sources", []), "errors": amenity_data.get("errors", []), "narrative": narratives.get("amenities", ""), } # Sección 6: Demografía demo_data = sub_results.get("demographics", {}) report["sections"]["demographics"] = { "title": "Demografía", "score": scores.get("demographics", 0), "median_household_income": demo_data.get("median_household_income"), "median_age": demo_data.get("median_age"), "unemployment_rate": demo_data.get("unemployment_rate"), "education_bachelors_pct": demo_data.get("education_bachelors_pct"), "ethnicity": demo_data.get("ethnicity", {}), "total_population": demo_data.get("total_population"), "sources": demo_data.get("sources", []), "errors": demo_data.get("errors", []), "narrative": narratives.get("demographics", ""), } # Sección 7: Mercado marítimo maritime_data = sub_results.get("maritime", {}) report["sections"]["maritime"] = { "title": "Mercado Laboral Marítimo", "score": scores.get("maritime", 0), "shipyards": maritime_data.get("shipyards", []), "marinas_with_jobs": maritime_data.get("marinas_with_jobs", []), "maritime_employers": maritime_data.get("maritime_employers", []), "bls_employment": maritime_data.get("bls_employment", {}), "sources": maritime_data.get("sources", []), "errors": maritime_data.get("errors", []), "narrative": narratives.get("maritime", ""), } # Sección 8: Lifestyle náutico life_data = sub_results.get("lifestyle", {}) report["sections"]["lifestyle"] = { "title": "Estilo de Vida Náutico", "score": scores.get("lifestyle", 0), "marinas": life_data.get("marinas", []), "boat_ramps": life_data.get("boat_ramps", []), "beaches": life_data.get("beaches", []), "nearest_marina": life_data.get("nearest_marina"), "nearest_beach": life_data.get("nearest_beach"), "ocean_access": life_data.get("ocean_access", False), "waterway_nearby": life_data.get("waterway_nearby", False), "sources": life_data.get("sources", []), "errors": life_data.get("errors", []), "narrative": narratives.get("lifestyle", ""), } # Texto plano del reporte para guardar en BD report["report_text"] = _build_text(report) return report def _build_text(report: dict) -> str: lines = [ f"AR-HOUSE LOCATION INTELLIGENCE REPORT", f"Dirección: {report['address']}", f"Fecha: {report['analysis_date']}", f"Score General: {report['overall_score']}/100", "", ] for key, sec in report["sections"].items(): lines.append(f"=== {sec['title'].upper()} ===") if sec.get("score") is not None: lines.append(f"Score: {sec['score']}/100") if sec.get("narrative"): lines.append(sec["narrative"]) lines.append("") return "\n".join(lines)