diff --git a/hugo/layouts/ineligible.html b/hugo/layouts/ineligible.html index d7a38b20..e702e9aa 100644 --- a/hugo/layouts/ineligible.html +++ b/hugo/layouts/ineligible.html @@ -25,10 +25,10 @@

Report not available

{{ else if eq .Params.reason_report_ineligible "non_regression_class" }}

- This property has class code {{ .Params.parcel_class }}. - {{ if .Params.parcel_class_description }} + This property has class code {{ .Params.char_class }}. + {{ if .Params.char_class_desc }} Properties with this code should fit the description - "{{ .Params.parcel_class_description }}". + "{{ .Params.char_class_desc }}". {{ end }}

@@ -41,7 +41,7 @@

Report not available

The Assessor did not reassess this home in {{ .Params.assessment_year }}. In {{ .Params.assessment_year }}, the Assessor reassessed the {{ title .Params.assessment_triad_name }} - triad, but this home is in the {{ title .Params.parcel_triad_name }} + triad, but this home is in the {{ title .Params.meta_triad_name }} triad.

{{ else if eq .Params.reason_report_ineligible "missing_card" }} diff --git a/hugo/layouts/report.html b/hugo/layouts/report.html index 955f0d8a..256d3bc7 100644 --- a/hugo/layouts/report.html +++ b/hugo/layouts/report.html @@ -181,7 +181,7 @@
What information does this report contain?
> {{ template "card-content" (dict "card" $card - "var_labels" $.Params.var_labels + "Params" $.Params "is_multicard" true)}} {{ end }} @@ -192,7 +192,7 @@
What information does this report contain?
{{ $card := index .Params.cards 0 }} {{ template "card-content" (dict "card" $card - "var_labels" .Params.var_labels + "Params" .Params "is_multicard" false) }} {{ end }} @@ -356,7 +356,7 @@

Top 5 Most Important Sales

{{ range $char := .card.predictors }} - {{ index $.var_labels $char }} + {{ index $.Params.var_labels $char }} {{ index $.card.chars $char }} {{ range $comp := $.card.comps }} diff --git a/scripts/generate_pinval/constants.py b/scripts/generate_pinval/constants.py index ac7a2793..b1a6e9ff 100644 --- a/scripts/generate_pinval/constants.py +++ b/scripts/generate_pinval/constants.py @@ -1,5 +1,13 @@ """Constants that are shared between scripts in this module""" # Temporary solution for run_id mapping, a problem that occurs when the model run_id -# differs between the model values and the comps -RUN_ID_MAP = {"2025-02-11-charming-eric": "2025-04-25-fancy-free-billy"} +# differs between the model values and the comps. +# Currently we don't need more than one run because comps and cards are using the same +# final run ID, but we're keeping this map around with the expectation that we may +# need it for a more permanent fix +RUN_ID_MAP = {"2025-02-11-charming-eric": "2025-02-11-charming-eric"} + +# It's helpful to factor these tables out into shared constants because we often +# need to switch to dev tables for testing +PINVAL_ASSESSMENT_CARD_TABLE = "pinval.vw_assessment_card" +PINVAL_COMP_TABLE = "pinval.vw_comp" diff --git a/scripts/generate_pinval/generate_pinval.py b/scripts/generate_pinval/generate_pinval.py index 4a4d28f1..14881833 100644 --- a/scripts/generate_pinval/generate_pinval.py +++ b/scripts/generate_pinval/generate_pinval.py @@ -36,7 +36,7 @@ from pyathena import connect from pyathena.pandas.cursor import PandasCursor -from constants import RUN_ID_MAP +import constants # Argparse interface @@ -54,7 +54,7 @@ def parse_args() -> argparse.Namespace: "--run-id", required=True, choices=list( - RUN_ID_MAP.keys() + constants.RUN_ID_MAP.keys() ), # Temporarily limits run_ids to those in the map help="Model run‑ID used by the Athena PINVAL tables (e.g. 2025-02-11-charming-eric)", ) @@ -172,8 +172,8 @@ def build_front_matter( "final_model_run_date": pd.to_datetime(tp["final_model_run_date"]).strftime( "%B %d, %Y" ), - "pin": tp["pin"], - "pin_pretty": pin_pretty(tp["pin"]), + "pin": tp["meta_pin"], + "pin_pretty": pin_pretty(tp["meta_pin"]), "pred_pin_final_fmv_round": tp["pred_pin_final_fmv_round"], "cards": [], "var_labels": {k: pretty_fn(k) for k in preds_cleaned}, @@ -183,11 +183,14 @@ def build_front_matter( # will pass the doc some info to help explain why the parcel is ineligible if not tp["is_report_eligible"]: front["layout"] = "ineligible" - front["reason_report_ineligible"] = tp["reason_report_ineligible"] - front["assessment_triad_name"] = tp["assessment_triad_name"] - front["parcel_class"] = tp["parcel_class"] - front["parcel_class_description"] = tp["parcel_class_description"] - front["parcel_triad_name"] = tp["parcel_triad_name"] + for attr in [ + "reason_report_ineligible", + "assessment_triad_name", + "char_class", + "char_class_desc", + "meta_triad_name", + ]: + front[attr] = tp[attr] return front # Per card @@ -252,7 +255,7 @@ def build_front_matter( for k, v in { "property_address": card_df["property_address"], "municipality": card_df.get("loc_tax_municipality_name"), - "township": tp["parcel_township_name"], + "township": tp["meta_township_name"], "meta_nbhd_code": card_df["meta_nbhd_code"], "loc_school_elementary_district_name": card_df.get( "school_elementary_district_name" @@ -505,18 +508,12 @@ def main() -> None: assessment_year = assessment_year_df.iloc[0]["assessment_year"] - # Use `model_run_id` instead of `run_id` because `run_id` comes from - # `model.assessment_card` and so is not present for ineligible PINs, - # but we want to query those PINs so we can generate error pages for them - assessment_clauses = ["model_run_id = %(run_id)s"] + assessment_clauses = ["run_id = %(run_id)s"] params_assessment = {"run_id": args.run_id} # Shard by township **only** in the assessment query if args.township: - # Similar to `model_run_id` above, use `parcel_township_code` here - # instead of `meta_township_code` because the latter will be null - # for ineligible PINs - assessment_clauses.append("parcel_township_code = %(township)s") + assessment_clauses.append("meta_township_code = %(township)s") params_assessment["township"] = args.township if args.pin: @@ -524,14 +521,14 @@ def main() -> None: pin_params = {f"pin{i}": p for i, p in enumerate(pins)} placeholders = ",".join(f"%({k})s" for k in pin_params) - assessment_clauses.append(f"pin IN ({placeholders})") + assessment_clauses.append(f"meta_pin IN ({placeholders})") params_assessment = {**params_assessment, **pin_params} where_assessment = " AND ".join(assessment_clauses) assessment_sql = f""" SELECT * - FROM pinval.vw_assessment_card + FROM {constants.PINVAL_ASSESSMENT_CARD_TABLE} WHERE {where_assessment} """ @@ -548,18 +545,18 @@ def main() -> None: ) # Get the comps - if (comps_run_id := RUN_ID_MAP.get(args.run_id)) is None: + if (comps_run_id := constants.RUN_ID_MAP.get(args.run_id)) is None: raise ValueError(f"No comps run ID found for assessment run ID {args.run_id}") comps_sql = f""" SELECT comp.* - FROM pinval.vw_comp AS comp + FROM {constants.PINVAL_COMP_TABLE} AS comp INNER JOIN ( - SELECT DISTINCT pin - FROM pinval.vw_assessment_card + SELECT DISTINCT meta_pin + FROM {constants.PINVAL_ASSESSMENT_CARD_TABLE} WHERE {where_assessment} ) AS card - ON comp.pin = card.pin + ON comp.pin = card.meta_pin WHERE comp.run_id = %(comps_run_id)s """ @@ -606,7 +603,7 @@ def pretty(k: str) -> str: start_time_dict_groupby = time.time() # Group dfs by PIN in dict for theoretically faster access - df_assessments_by_pin = df_assessment_all.groupby("pin") + df_assessments_by_pin = df_assessment_all.groupby("meta_pin") df_comps_by_pin = ( {} if df_comps_all.empty else dict(tuple(df_comps_all.groupby("pin"))) ) diff --git a/scripts/generate_pinval/resolve_model_metadata.py b/scripts/generate_pinval/resolve_model_metadata.py index 80db7465..3b736ce6 100644 --- a/scripts/generate_pinval/resolve_model_metadata.py +++ b/scripts/generate_pinval/resolve_model_metadata.py @@ -15,6 +15,8 @@ from pyathena import connect from pyathena.cursor import DictCursor +import constants + def parse_args() -> argparse.Namespace: """Parse command‑line arguments and perform basic validation""" @@ -104,11 +106,11 @@ def get_township_codes( for row in connect(region_name="us-east-1") .cursor() .execute( - """ - SELECT DISTINCT parcel_township_code - FROM pinval.vw_assessment_card - WHERE model_run_id = %(run_id)s - ORDER BY parcel_township_code + f""" + SELECT DISTINCT meta_township_code + FROM {constants.PINVAL_ASSESSMENT_CARD_TABLE} + WHERE run_id = %(run_id)s + ORDER BY meta_township_code """, {"run_id": run_id}, )