From 006c26ae759c1c43f77aaa99c7f0a89f051cee64 Mon Sep 17 00:00:00 2001 From: Jean Cochrane Date: Wed, 7 Aug 2024 14:42:25 -0500 Subject: [PATCH] [3/3] Migrate Will's town close QC reports to dbt models (#557) * Migrate 0 land value QC report * Sketch out town close QC queries based on asmt prior year values * Migrate "Res parcels not set to cost approach" QC report * Migrate "OVRRCNLDs discrepancy checks" QC report * Move qc_vw_incorrect_val_method_revcode_eq_1 data test to new cost approach model * Migrate "Bldg parcel class mismatch" QC report * Add docs to QC report town close models, with TODO Inquire query numbers * Migrate "289s" QC report * Migrate "500k increase, 1m decrease" QC report * Migrate "Res multicodes" QC report * Migrate "Card code 5s possibly not at 100%" QC report for comdat * Migrate all "Card code 5s possibly not at 100%" QC reports * Factor out vw_iasworld_sales_latest_sale_since_2021 QC view * Migrate "Res edit" QC report with some TODOs * Add export templates and complete migration of QC reports * Fix "Possibly not at 100%" QC reports * Fix formatting of "Possibly not at 100%" percent change columns * Fix "500k increase, 1m decrease" QC report formatting * Fix "Bldg parcel class mismatch" QC report formatting * Fix "OVRRCNLD discrepancy checks" QC report formatting * Fix "Res multicodes" QC report formatting * Fix "Res parcels not set to Cost Approach" formatting * Fix "Res edit" QC report formatting * Document QC report models ahead of review * Add docs for intermediate QC models * Remove unused vw_incorrect_val_method docs * More reader-friendly description for res_parcels_not_set_to_cost_approach view * Refactor qc.vw_report_town_close_500k_increase_1m_decrease to use shared asmt view * Rollback QC report models that will be added in third PR * Rollback QC report models that will be added in second PR * [2/3] Migrate Will's town close QC reports to dbt models This reverts commit 5b86b187b1eb5883b8a4c82479515da948e6a8eb. * [3/3] Migrate Will's town close QC reports to dbt models This reverts commit 5e4bc7bd409ee1b96a768fd83df6b986db8d168c. * Oops, forgot to filter for current records in Res Multicodes QC report * Filter parcels from "Bldg parcel class mismatch" if at least one card has a matching class * Format parids as numbers in QC reports to avoid scientific notation * Filter out leasehold properties from 0 land value QC report * Simplify bldg_parcel_class_mismatch report and make filtering match Will's * Remove land.sf IS NOT NULL condition from "Res Edit" QC file * Remove unnecessary flake8 config now that we're using ruff * Only convert QC reports to data tables if the result set is non-empty * Reorder qc schema docs alphanumerically * Append reason code descriptions to aprval.reascd in QC reports * Fix edge case bug in export_models.py script that can raise an error when result set has only 1 row * Document card code 5s query in 500k_increase_1m_decrease QC report * Format PINs as explicitly 14-digit numbers in export_models.py script * Fix typos in comments in card code 5 reports * Consolidate and flesh out docs for prior_year_card_code_5s reports * Remove stray docs block artifact from qc/docs.md * Reorder qc/schema.yml alphanumerically * Re-alphabetize QC docs and schema for latest QC models * Make some small fixes to QC reports based on Dan's feedback * Pull num_dwellings from dweldat instead of subquery in qc.vw_report_town_close_res_edit * Remove stray whitespace in qc/docs.md --- .../qc.vw_report_town_close_289s.xlsx | Bin 0 -> 9115 bytes ...town_close_bldg_parcel_class_mismatch.xlsx | Bin 0 -> 12381 bytes ...report_town_close_ovrrcnlds_to_review.xlsx | Bin 0 -> 9449 bytes .../qc.vw_report_town_close_res_edit.xlsx | Bin 0 -> 15142 bytes ...c.vw_report_town_close_res_multicodes.xlsx | Bin 0 -> 12680 bytes ..._res_parcels_not_set_to_cost_approach.xlsx | Bin 0 -> 8642 bytes dbt/models/qc/docs.md | 112 +++++++++- .../qc/qc.vw_iasworld_sales_latest_sale.sql | 21 ++ dbt/models/qc/qc.vw_incorrect_val_method.sql | 25 --- .../qc/qc.vw_report_town_close_289s.sql | 14 ++ ..._town_close_bldg_parcel_class_mismatch.sql | 65 ++++++ ..._report_town_close_ovrrcnlds_to_review.sql | 116 +++++++++++ .../qc/qc.vw_report_town_close_res_edit.sql | 194 ++++++++++++++++++ ...qc.vw_report_town_close_res_multicodes.sql | 49 +++++ ...e_res_parcels_not_set_to_cost_approach.sql | 30 +++ dbt/models/qc/schema.yml | 119 ++++++++--- 16 files changed, 682 insertions(+), 63 deletions(-) create mode 100755 dbt/export/templates/qc.vw_report_town_close_289s.xlsx create mode 100755 dbt/export/templates/qc.vw_report_town_close_bldg_parcel_class_mismatch.xlsx create mode 100755 dbt/export/templates/qc.vw_report_town_close_ovrrcnlds_to_review.xlsx create mode 100755 dbt/export/templates/qc.vw_report_town_close_res_edit.xlsx create mode 100755 dbt/export/templates/qc.vw_report_town_close_res_multicodes.xlsx create mode 100755 dbt/export/templates/qc.vw_report_town_close_res_parcels_not_set_to_cost_approach.xlsx create mode 100644 dbt/models/qc/qc.vw_iasworld_sales_latest_sale.sql delete mode 100644 dbt/models/qc/qc.vw_incorrect_val_method.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_289s.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_bldg_parcel_class_mismatch.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_ovrrcnlds_to_review.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_res_edit.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_res_multicodes.sql create mode 100644 dbt/models/qc/qc.vw_report_town_close_res_parcels_not_set_to_cost_approach.sql diff --git a/dbt/export/templates/qc.vw_report_town_close_289s.xlsx b/dbt/export/templates/qc.vw_report_town_close_289s.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..7d844f275768a0c9fbaec55e5a30823d2da34441 GIT binary patch literal 9115 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 A6aWAK literal 0 HcmV?d00001 diff --git a/dbt/export/templates/qc.vw_report_town_close_bldg_parcel_class_mismatch.xlsx b/dbt/export/templates/qc.vw_report_town_close_bldg_parcel_class_mismatch.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..612b8aa5e368d1136346f54eff5f49996bbfc796 GIT binary patch literal 12381 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 Sx&Xj^#4iM)-`ey)|NS3|P>q!U literal 0 HcmV?d00001 diff --git a/dbt/export/templates/qc.vw_report_town_close_res_edit.xlsx b/dbt/export/templates/qc.vw_report_town_close_res_edit.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..88dd8a7d3bc56b4feff78b898257cf7b6146509c GIT binary patch literal 15142 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 1 +) AS ranked_sales +WHERE row_num = 1 diff --git a/dbt/models/qc/qc.vw_incorrect_val_method.sql b/dbt/models/qc/qc.vw_incorrect_val_method.sql deleted file mode 100644 index c397b5d3b..000000000 --- a/dbt/models/qc/qc.vw_incorrect_val_method.sql +++ /dev/null @@ -1,25 +0,0 @@ -SELECT - pardat.taxyr, - pardat.parid, - pardat.class, - legdat.user1 AS township_code, - aprval.aprbldg, - aprval.aprland, - aprval.aprtot, - aprval.revcode, - aprval.reascd AS reason_for_change, - aprval.wen, - aprval.who -FROM {{ source('iasworld', 'pardat') }} AS pardat -LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat - ON pardat.taxyr = legdat.taxyr - AND pardat.parid = legdat.parid - AND legdat.cur = 'Y' - AND legdat.deactivat IS NULL -LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval - ON pardat.taxyr = aprval.taxyr - AND pardat.parid = aprval.parid - AND aprval.cur = 'Y' - AND aprval.deactivat IS NULL -WHERE pardat.cur = 'Y' - AND pardat.deactivat IS NULL diff --git a/dbt/models/qc/qc.vw_report_town_close_289s.sql b/dbt/models/qc/qc.vw_report_town_close_289s.sql new file mode 100644 index 000000000..dd529249e --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_289s.sql @@ -0,0 +1,14 @@ +SELECT + oby.parid, + oby.taxyr, + legdat.user1 AS township_code, + oby.class +FROM {{ source('iasworld', 'oby') }} AS oby +LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat + ON oby.parid = legdat.parid + AND oby.taxyr = legdat.taxyr + AND legdat.cur = 'Y' + AND legdat.deactivat IS NULL +WHERE oby.cur = 'Y' + AND oby.deactivat IS NULL + AND oby.class = '289' diff --git a/dbt/models/qc/qc.vw_report_town_close_bldg_parcel_class_mismatch.sql b/dbt/models/qc/qc.vw_report_town_close_bldg_parcel_class_mismatch.sql new file mode 100644 index 000000000..94f81503b --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_bldg_parcel_class_mismatch.sql @@ -0,0 +1,65 @@ +{% set comparison_tables = ['comdat', 'dweldat', 'oby'] %} + +SELECT + legdat.parid, + legdat.taxyr, + legdat.user1 AS township_code, + pardat.class AS parcel_class, +{% for tablename in comparison_tables %} + ARRAY_JOIN({{ tablename }}.classes, ', ') + AS {{ tablename }}_classes{% if not loop.last %}, {% endif %} +{% endfor %} +FROM {{ source('iasworld', 'pardat') }} AS pardat +LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat + ON pardat.parid = legdat.parid + AND pardat.taxyr = legdat.taxyr + AND legdat.cur = 'Y' + AND legdat.deactivat IS NULL +{% for tablename in comparison_tables %} + LEFT JOIN ( + SELECT + {{ tablename }}.parid, + {{ tablename }}.taxyr, + ARRAY_AGG(DISTINCT {{ tablename }}.class) AS classes + FROM {{ source('iasworld', tablename) }} AS {{ tablename }} + WHERE {{ tablename }}.cur = 'Y' + AND {{ tablename }}.deactivat IS NULL + GROUP BY {{ tablename }}.parid, {{ tablename }}.taxyr + ) AS {{ tablename }} + ON pardat.parid = {{ tablename }}.parid + AND pardat.taxyr = {{ tablename }}.taxyr +{% endfor %} +WHERE pardat.cur = 'Y' + AND pardat.deactivat IS NULL + AND pardat.class NOT IN ( + '100', '200', '239', '240', '241', '300', '400', '500', '535', '550' + ) + AND SUBSTR(pardat.class, 1, 3) NOT IN ( + '637', '700', '742', '800', '900' + ) + -- Parcels fail the check if one of the comparison tables has classes + -- that A) exist (aka are not null) and B) have no match to the + -- parcel class + AND ( + {% for tablename in comparison_tables %} + ( + -- Only run this check if the column is not null, since + -- otherwise CONTAINS() will return null as well + {{ tablename }}.classes IS NULL + OR NOT CONTAINS({{ tablename }}.classes, pardat.class) + ) + {% if not loop.last %}AND{% endif %} + {% endfor %} + ) + -- Check for the edge case where a parcel is exempt and none of the + -- comparison tables exist, which should not be returned but can pass + -- the conditional above due to all table joins returning nulls + AND NOT ( + pardat.class IN ('EX', 'RR') + AND + {% for tablename in comparison_tables %} + {{ tablename }}.classes IS NULL + {% if not loop.last %}AND{% endif %} + {% endfor %} + + ) diff --git a/dbt/models/qc/qc.vw_report_town_close_ovrrcnlds_to_review.sql b/dbt/models/qc/qc.vw_report_town_close_ovrrcnlds_to_review.sql new file mode 100644 index 000000000..5dc5f993c --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_ovrrcnlds_to_review.sql @@ -0,0 +1,116 @@ +-- Combine DWELDAT, COMDAT, and OBY and pull calculated fields from each +WITH combined_calc AS ( + SELECT + 'DWELDAT' AS table_name, + dweldat.parid, + dweldat.card, + -- DWELDAT doesn't have lline but we need it for the union with OBY + NULL AS lline, + dweldat.taxyr, + dweldat.external_rcnld, + dweldat.external_occpct, + dweldat.external_propct, + dweldat.external_calc_rcnld, + dweldat.ovrrcnld, + dweldat.external_calc_rcnld - dweldat.ovrrcnld AS value_difference, + dweldat.mktrsn AS card_code, + dweldat.user16 AS alt_cdu, + dweldat.who, + DATE_FORMAT( + DATE_PARSE(dweldat.wen, '%Y-%m-%d %H:%i:%S.%f'), '%c/%e/%Y %H:%i' + ) AS wen + FROM {{ source('iasworld', 'dweldat') }} AS dweldat + WHERE dweldat.cur = 'Y' + AND dweldat.deactivat IS NULL + UNION ALL + SELECT + 'COMDAT' AS table_name, + comdat.parid, + comdat.card, + NULL AS lline, + comdat.taxyr, + comdat.external_rcnld, + comdat.external_occpct, + comdat.external_propct, + comdat.external_calc_rcnld, + comdat.ovrrcnld, + comdat.external_calc_rcnld - comdat.ovrrcnld AS value_difference, + comdat.chgrsn AS card_code, + comdat.user16 AS alt_cdu, + comdat.who, + DATE_FORMAT( + DATE_PARSE(comdat.wen, '%Y-%m-%d %H:%i:%S.%f'), '%c/%e/%Y %H:%i' + ) AS wen + FROM {{ source('iasworld', 'comdat') }} AS comdat + WHERE comdat.cur = 'Y' + AND comdat.deactivat IS NULL + UNION ALL + SELECT + 'OBY' AS table_name, + oby.parid, + oby.card, + oby.lline, + oby.taxyr, + oby.external_rcnld, + oby.external_occpct, + oby.external_propct, + oby.external_calc_rcnld, + oby.ovrrcnld, + oby.external_calc_rcnld - oby.ovrrcnld AS value_difference, + oby.chgrsn AS card_code, + oby.user16 AS alt_cdu, + oby.who, + DATE_FORMAT( + DATE_PARSE(oby.wen, '%Y-%m-%d %H:%i:%S.%f'), '%c/%e/%Y %H:%i' + ) AS wen + FROM {{ source('iasworld', 'oby') }} AS oby + WHERE oby.cur = 'Y' + AND oby.deactivat IS NULL +) + +SELECT + calc.parid, + calc.taxyr, + legdat.user1 AS township_code, + pardat.class, + aprval.reascd AS reason_for_change, + DATE_FORMAT(DATE_PARSE(aprval.revdt, '%Y-%m-%d %H:%i:%S.%f'), '%c/%e/%Y') + AS revdt, + aprval.aprbldg, + aprval_prev.aprbldg AS aprbldg_prev, + calc.table_name, + calc.card, + calc.lline, + calc.external_rcnld, + calc.external_occpct, + calc.external_propct, + calc.external_calc_rcnld, + calc.ovrrcnld, + calc.value_difference, + calc.card_code, + calc.alt_cdu, + calc.who, + calc.wen +FROM combined_calc AS calc +LEFT JOIN {{ source('iasworld', 'pardat') }} AS pardat + ON calc.parid = pardat.parid + AND calc.taxyr = pardat.taxyr + AND pardat.cur = 'Y' + AND pardat.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat + ON calc.parid = legdat.parid + AND calc.taxyr = legdat.taxyr + AND legdat.cur = 'Y' + AND legdat.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval + ON calc.parid = aprval.parid + AND calc.taxyr = aprval.taxyr + AND aprval.cur = 'Y' + AND aprval.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval_prev + ON aprval.parid = aprval_prev.parid + AND CAST(aprval.taxyr AS INT) = CAST(aprval_prev.taxyr AS INT) + 1 + AND aprval_prev.cur = 'Y' + AND aprval_prev.deactivat IS NULL +WHERE calc.value_difference != 0 + AND (aprval.reascd IS NULL OR aprval.reascd != '22') diff --git a/dbt/models/qc/qc.vw_report_town_close_res_edit.sql b/dbt/models/qc/qc.vw_report_town_close_res_edit.sql new file mode 100644 index 000000000..3315752d4 --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_res_edit.sql @@ -0,0 +1,194 @@ +-- Get up to the first five DWELDAT cards for each parcel +WITH first_five_dwellings AS ( + SELECT + parid, + taxyr, + card, + yrblt, + sfla, + stories, + rmbed, + fixbath, + fixhalf, + bsmt, + user12 AS bsmt_fin, + external_propct, + user16 AS alt_cdu, + row_num + FROM ( + SELECT + *, + ROW_NUMBER() + OVER (PARTITION BY parid, taxyr ORDER BY card ASC) + AS row_num + FROM {{ source('iasworld', 'dweldat') }} + WHERE cur = 'Y' + AND deactivat IS NULL + ) AS ranked_dwellings + WHERE row_num <= 5 +), + +-- Pivot the dwelling chars using the MAP_AGG function and key access +-- as recommended here: +-- https://gist.github.com/shotahorii/6b710c902a8a6ef184987ca787d329d9 +first_five_dwellings_pivoted AS ( + SELECT + parid, + taxyr, + {% for idx in range(1, 6) %} + yrblt_kv[{{ idx }}] AS yrblt_{{ idx }}, + sfla_kv[{{ idx }}] AS sfla_{{ idx }}, + stories_kv[{{ idx }}] AS stories_{{ idx }}, + rmbed_kv[{{ idx }}] AS rmbed_{{ idx }}, + fixbath_kv[{{ idx }}] AS fixbath_{{ idx }}, + fixhalf_kv[{{ idx }}] AS fixhalf_{{ idx }}, + bsmt_kv[{{ idx }}] AS bsmt_{{ idx }}, + bsmt_fin_kv[{{ idx }}] AS bsmt_fin_{{ idx }}, + external_propct_kv[{{ idx }}] AS external_propct_{{ idx }}, + alt_cdu_kv[{{ idx }}] AS alt_cdu_{{ idx }}{% if not loop.last %} + , + {% endif %} + {% endfor %} + FROM ( + SELECT + parid, + taxyr, + MAP_AGG(row_num, yrblt) AS yrblt_kv, + MAP_AGG(row_num, sfla) AS sfla_kv, + MAP_AGG(row_num, stories) AS stories_kv, + MAP_AGG(row_num, rmbed) AS rmbed_kv, + MAP_AGG(row_num, fixbath) AS fixbath_kv, + MAP_AGG(row_num, fixhalf) AS fixhalf_kv, + MAP_AGG(row_num, bsmt) AS bsmt_kv, + MAP_AGG(row_num, bsmt_fin) AS bsmt_fin_kv, + MAP_AGG(row_num, external_propct) AS external_propct_kv, + MAP_AGG(row_num, alt_cdu) AS alt_cdu_kv + FROM first_five_dwellings + GROUP BY parid, taxyr + ) AS agg_dwellings +), + +num_dwellings AS ( + SELECT + parid, + taxyr, + COUNT(*) AS num_dwellings + FROM {{ source('iasworld', 'dweldat') }} + WHERE cur = 'Y' + AND deactivat IS NULL + GROUP BY parid, taxyr +) + +SELECT + pardat.parid, + pardat.taxyr, + legdat.user1 AS township_code, + pardat.nbhd, + pardat.class, + legdat.adrno, + legdat.adradd, + legdat.adrdir, + legdat.adrstr, + legdat.adrsuf, + legdat.adrsuf2, + legdat.unitdesc, + legdat.unitno, + legdat.cityname, + aprval.aprland, + aprval.aprbldg, + aprval.aprtot, + aprval_prev.aprland AS aprland_prev, + aprval_prev.aprbldg AS aprbldg_prev, + aprval_prev.aprtot AS aprtot_prev, + CONCAT( + CAST( + ROUND( + ( + (aprval.aprtot - aprval_prev.aprtot) + / CAST(aprval_prev.aprtot AS DOUBLE) + ) + * 100, + 2 + ) + AS VARCHAR + ), + '%' + ) AS aprtot_percent_change, + aprval.dwelval, + aprval.dwelval + aprval.aprland AS dweltot, + aprval_prev.dwelval AS dwelval_prev, + aprval_prev.dwelval + aprval_prev.aprland AS dweltot_prev, + CONCAT( + CAST( + ROUND( + ( + ( + (aprval.dwelval + aprval.aprland) + - (aprval_prev.dwelval + aprval_prev.aprland) + ) + / CAST( + (aprval_prev.dwelval + aprval_prev.aprland) AS DOUBLE + ) + ) + * 100, + 2 + ) + AS VARCHAR + ), + '%' + ) AS dweltot_percent_change, + sale.saledt_fmt, + sale.price, + sale.instruno, + COALESCE(pardat.tiebldgpct, 0) AS tiebldgpct, + aprval.reascd, + aprval.obyval, + land.sf, + num_dwellings.num_dwellings, +{% for idx in range(1, 6) %} + dweldat.yrblt_{{ idx }}, + dweldat.sfla_{{ idx }}, + dweldat.stories_{{ idx }}, + dweldat.rmbed_{{ idx }}, + dweldat.fixbath_{{ idx }}, + dweldat.fixhalf_{{ idx }}, + dweldat.bsmt_{{ idx }}, + dweldat.bsmt_fin_{{ idx }}, + dweldat.external_propct_{{ idx }}, + dweldat.alt_cdu_{{ idx }}{% if not loop.last %},{% endif %} +{% endfor %} +FROM {{ source('iasworld', 'pardat') }} AS pardat +LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat + ON pardat.parid = legdat.parid + AND pardat.taxyr = legdat.taxyr + AND legdat.cur = 'Y' + AND legdat.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval + ON pardat.parid = aprval.parid + AND pardat.taxyr = aprval.taxyr + AND aprval.cur = 'Y' + AND aprval.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval_prev + ON aprval.parid = aprval_prev.parid + AND CAST(aprval.taxyr AS INT) = CAST(aprval_prev.taxyr AS INT) + 1 + AND aprval_prev.cur = 'Y' + AND aprval_prev.deactivat IS NULL +LEFT JOIN num_dwellings + ON pardat.parid = num_dwellings.parid + AND pardat.taxyr = num_dwellings.taxyr +LEFT JOIN first_five_dwellings_pivoted AS dweldat + ON pardat.parid = dweldat.parid + AND pardat.taxyr = dweldat.taxyr +-- Pull land SF from vw_pin_land rather than the source iasworld.land table +-- since SF aggregation is complicated +LEFT JOIN {{ ref('default.vw_pin_land') }} AS land + ON pardat.parid = land.pin + AND pardat.taxyr = land.year +LEFT JOIN {{ ref('qc.vw_iasworld_sales_latest_sale') }} AS sale + ON pardat.parid = sale.parid + -- Filter for only sales starting in 2021 + AND sale.saledt >= '2021-01-01' +WHERE pardat.cur = 'Y' + AND pardat.deactivat IS NULL + -- Filter for only residential parcels + AND SUBSTR(pardat.class, 1, 1) = '2' diff --git a/dbt/models/qc/qc.vw_report_town_close_res_multicodes.sql b/dbt/models/qc/qc.vw_report_town_close_res_multicodes.sql new file mode 100644 index 000000000..6f7859f8f --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_res_multicodes.sql @@ -0,0 +1,49 @@ +SELECT + asmt.parid, + asmt.taxyr, + asmt.township_code, + asmt.class AS parcel_class, + asmt.nbhd, + dweldat.card, + dweldat.class AS dweldat_class, + dweldat.sfla, + dweldat.adjrcnld, + dweldat_prev.adjrcnld AS adjrcnld_prev, + asmt.valapr1, + asmt.valapr2, + asmt.valapr3, + asmt.valapr1_prev, + asmt.valapr2_prev, + asmt.valapr3_prev, + sale.saledt_fmt, + sale.price +FROM {{ source('iasworld', 'dweldat') }} AS dweldat +-- Filter for only dwellings on multicard parcels +INNER JOIN ( + SELECT + parid, + taxyr + FROM {{ source('iasworld', 'dweldat') }} + WHERE cur = 'Y' + AND deactivat IS NULL + GROUP BY parid, taxyr + HAVING COUNT(*) > 1 +) AS multicard_parcel + ON dweldat.parid = multicard_parcel.parid + AND dweldat.taxyr = multicard_parcel.taxyr +-- Join to the prior year of dweldat data to pull the prior building value +LEFT JOIN {{ source('iasworld', 'dweldat') }} AS dweldat_prev + ON dweldat.parid = dweldat_prev.parid + AND dweldat.card = dweldat_prev.card + AND CAST(dweldat.taxyr AS INT) = CAST(dweldat_prev.taxyr AS INT) + 1 + AND dweldat_prev.cur = 'Y' + AND dweldat_prev.deactivat IS NULL +LEFT JOIN {{ ref('qc.vw_iasworld_asmt_all_with_prior_year_values') }} AS asmt + ON dweldat.parid = asmt.parid + AND dweldat.taxyr = asmt.taxyr +LEFT JOIN {{ ref('qc.vw_iasworld_sales_latest_sale') }} AS sale + ON dweldat.parid = sale.parid + -- Filter for only sales starting in 2021 + AND sale.saledt >= '2021-01-01' +WHERE dweldat.cur = 'Y' + AND dweldat.deactivat IS NULL diff --git a/dbt/models/qc/qc.vw_report_town_close_res_parcels_not_set_to_cost_approach.sql b/dbt/models/qc/qc.vw_report_town_close_res_parcels_not_set_to_cost_approach.sql new file mode 100644 index 000000000..5bbd79125 --- /dev/null +++ b/dbt/models/qc/qc.vw_report_town_close_res_parcels_not_set_to_cost_approach.sql @@ -0,0 +1,30 @@ +SELECT + pardat.parid, + pardat.taxyr, + legdat.user1 AS township_code, + pardat.class, + aprval.revcode, + aprval.reascd AS reason_for_change, + aprval.aprland, + aprval.aprbldg, + aprval.aprtot, + aprval.who, + DATE_FORMAT( + DATE_PARSE(aprval.wen, '%Y-%m-%d %H:%i:%S.%f'), '%c/%e/%Y %H:%i' + ) AS wen +FROM {{ source('iasworld', 'aprval') }} AS aprval +LEFT JOIN {{ source('iasworld', 'pardat') }} AS pardat + ON aprval.parid = pardat.parid + AND aprval.taxyr = pardat.taxyr + AND pardat.cur = 'Y' + AND pardat.deactivat IS NULL +LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat + ON aprval.parid = legdat.parid + AND aprval.taxyr = legdat.taxyr + AND legdat.cur = 'Y' + AND legdat.deactivat IS NULL +WHERE aprval.cur = 'Y' + AND aprval.deactivat IS NULL + -- Filter for residential parcels not set to cost approach + AND pardat.class LIKE '2%' + AND (aprval.revcode IS NULL OR aprval.revcode != '1') diff --git a/dbt/models/qc/schema.yml b/dbt/models/qc/schema.yml index f5f63d2ca..bd0f28eea 100644 --- a/dbt/models/qc/schema.yml +++ b/dbt/models/qc/schema.yml @@ -101,6 +101,9 @@ models: category: sales_issues description: price should be <= $20m + - name: qc.vw_iasworld_sales_latest_sale + description: '{{ doc("view_vw_iasworld_sales_latest_sale") }}' + - name: qc.vw_iasworld_sales_null_values description: '{{ doc("view_vw_iasworld_sales_null_values") }}' config: @@ -218,33 +221,6 @@ models: category: sales_issues description: iasworld should not have >1000 sales that are not in mydec - - name: qc.vw_incorrect_val_method - description: '{{ doc("view_vw_incorrect_val_method") }}' - config: - tags: - - test_qc_inquire - columns: - - name: revcode - data_tests: - # Equivalent to Res parcels not set to Cost Approach from FP Checklist - - accepted_values: - name: qc_vw_incorrect_val_method_revcode_eq_1 - values: ['1'] - additional_select_columns: - - taxyr - - parid - - class - - township_code - - who - - wen - config: - where: | - CAST(taxyr AS int) BETWEEN {{ var('test_qc_year_start') }} AND {{ var('test_qc_year_end') }} - AND class LIKE '2%' - meta: - table_name: aprval - description: revcode should be '1' for 200-class parcels - - name: qc.vw_neg_asmt_value description: '{{ doc("view_vw_neg_asmt_value") }}' config: @@ -849,6 +825,14 @@ models: export_name: 0 value export_template: assessed_and_market_values.xlsx + - name: qc.vw_report_town_close_289s + description: '{{ doc("view_vw_report_town_close_289s") }}' + config: + tags: + - qc_report_town_close + meta: + export_name: 289s + - name: qc.vw_report_town_close_500k_increase_1m_decrease description: '{{ doc("view_vw_report_town_close_500k_increase_1m_decrease") }}' config: @@ -862,6 +846,14 @@ models: index: M horizontal_align: right + - name: qc.vw_report_town_close_bldg_parcel_class_mismatch + description: '{{ doc("view_vw_report_town_close_bldg_parcel_class_mismatch") }}' + config: + tags: + - qc_report_town_close + meta: + export_name: Bldg parcel class mismatch + - name: qc.vw_report_town_close_class_does_not_equal_luc description: '{{ doc("view_vw_report_town_close_class_does_not_equal_luc") }}' config: @@ -887,6 +879,14 @@ models: meta: export_name: Negative ASMT values + - name: qc.vw_report_town_close_ovrrcnlds_to_review + description: '{{ doc("view_vw_report_town_close_ovrrcnlds_to_review") }}' + config: + tags: + - qc_report_town_close + meta: + export_name: OVRRCNLD discrepancy checks + - name: qc.vw_report_town_close_prior_year_card_code_5s_comdat description: '{{ doc("view_vw_report_town_close_prior_year_card_code_5s") }}' config: @@ -911,6 +911,71 @@ models: meta: export_name: Card code 5s possibly not at 100% (OBY) + - name: qc.vw_report_town_close_res_edit + description: '{{ doc("view_vw_report_town_close_res_edit") }}' + config: + tags: + - qc_report_town_close + meta: + export_name: Res edit + export_format: + columns: + - name: Total % Change + index: U + horizontal_align: right + - name: Dwelling % Change + index: Z + horizontal_align: right + - name: Sale Date + index: AA + horizontal_align: right + + - name: qc.vw_report_town_close_res_multicodes + description: '{{ doc("view_vw_report_town_close_res_multicodes") }}' + config: + tags: + - qc_report_town_close + meta: + export_name: Res multicodes + export_format: + columns: + - name: Sale Date + index: Q + horizontal_align: right + + - name: qc.vw_report_town_close_res_parcels_not_set_to_cost_approach + description: '{{ doc("view_vw_report_town_close_res_parcels_not_set_to_cost_approach") }}' + config: + tags: + - qc_report_town_close + - test_qc_inquire + meta: + export_name: Res parcels not set to cost approach + columns: + - name: revcode + data_tests: + # Equivalent to Res parcels not set to Cost Approach from FP Checklist. + # The is_null test works here because the view is already filtered for + # rows where revcode is null or != '1', and since this test is not + # interested in nulls, checking is_null will effectively return all + # rows where revcode != '1' + - is_null: + name: qc_vw_incorrect_val_method_revcode_eq_1 + additional_select_columns: + - taxyr + - parid + - class + - township_code + - who + - wen + config: + where: | + CAST(taxyr AS int) BETWEEN {{ var('test_qc_year_start') }} AND {{ var('test_qc_year_end') }} + meta: + table_name: aprval + description: revcode should be '1' for 200-class parcels + category: incorrect_values + - name: qc.vw_report_town_close_vacant_class_with_bldg_value description: '{{ doc("view_vw_report_town_close_vacant_class_with_bldg_value") }}' config: