Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1/3] Migrate Will's town close QC reports to dbt models #554

Merged
merged 42 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b8674b3
Migrate 0 land value QC report
jeancochrane Jul 17, 2024
42f6950
Sketch out town close QC queries based on asmt prior year values
jeancochrane Jul 18, 2024
f47872d
Migrate "Res parcels not set to cost approach" QC report
jeancochrane Jul 18, 2024
7e16513
Migrate "OVRRCNLDs discrepancy checks" QC report
jeancochrane Jul 18, 2024
f694913
Move qc_vw_incorrect_val_method_revcode_eq_1 data test to new cost ap…
jeancochrane Jul 18, 2024
d234235
Migrate "Bldg parcel class mismatch" QC report
jeancochrane Jul 18, 2024
7f2a4cf
Add docs to QC report town close models, with TODO Inquire query numbers
jeancochrane Jul 19, 2024
74edc74
Migrate "289s" QC report
jeancochrane Jul 19, 2024
100993c
Migrate "500k increase, 1m decrease" QC report
jeancochrane Jul 19, 2024
589f46a
Migrate "Res multicodes" QC report
jeancochrane Jul 19, 2024
97a0899
Migrate "Card code 5s possibly not at 100%" QC report for comdat
jeancochrane Jul 22, 2024
2d36d11
Migrate all "Card code 5s possibly not at 100%" QC reports
jeancochrane Jul 22, 2024
e9c3e88
Factor out vw_iasworld_sales_latest_sale_since_2021 QC view
jeancochrane Jul 22, 2024
af7f3a5
Migrate "Res edit" QC report with some TODOs
jeancochrane Jul 23, 2024
1d5cd26
Add export templates and complete migration of QC reports
jeancochrane Jul 23, 2024
663dede
Fix "Possibly not at 100%" QC reports
jeancochrane Jul 24, 2024
493063a
Fix formatting of "Possibly not at 100%" percent change columns
jeancochrane Jul 24, 2024
bb3403c
Fix "500k increase, 1m decrease" QC report formatting
jeancochrane Jul 24, 2024
b13206b
Fix "Bldg parcel class mismatch" QC report formatting
jeancochrane Jul 24, 2024
4de1200
Fix "OVRRCNLD discrepancy checks" QC report formatting
jeancochrane Jul 24, 2024
10f2b61
Fix "Res multicodes" QC report formatting
jeancochrane Jul 24, 2024
6ec6bd6
Fix "Res parcels not set to Cost Approach" formatting
jeancochrane Jul 24, 2024
36d5a10
Fix "Res edit" QC report formatting
jeancochrane Jul 24, 2024
32a7ea2
Document QC report models ahead of review
jeancochrane Jul 25, 2024
3ed53a2
Add docs for intermediate QC models
jeancochrane Jul 25, 2024
93792f1
Remove unused vw_incorrect_val_method docs
jeancochrane Jul 25, 2024
0251a70
More reader-friendly description for res_parcels_not_set_to_cost_appr…
jeancochrane Jul 25, 2024
7d22a9d
Refactor qc.vw_report_town_close_500k_increase_1m_decrease to use sha…
jeancochrane Jul 26, 2024
5e4bc7b
Rollback QC report models that will be added in third PR
jeancochrane Jul 26, 2024
5b86b18
Rollback QC report models that will be added in second PR
jeancochrane Jul 26, 2024
60026b8
Format parids as numbers in QC reports to avoid scientific notation
jeancochrane Jul 30, 2024
1f04f90
Filter out leasehold properties from 0 land value QC report
jeancochrane Jul 31, 2024
a4c4d4a
Merge branch 'master' into jeancochrane/migrate-more-will-qc-reports
jeancochrane Aug 5, 2024
0e41f3e
Remove unnecessary flake8 config now that we're using ruff
jeancochrane Aug 5, 2024
ac37578
Only convert QC reports to data tables if the result set is non-empty
jeancochrane Aug 5, 2024
3744e48
Reorder qc schema docs alphanumerically
jeancochrane Aug 5, 2024
49363b7
Append reason code descriptions to aprval.reascd in QC reports
jeancochrane Aug 5, 2024
4faba2f
Fix edge case bug in export_models.py script that can raise an error …
jeancochrane Aug 5, 2024
2ebab55
Document card code 5s query in 500k_increase_1m_decrease QC report
jeancochrane Aug 5, 2024
3af51f0
Format PINs as explicitly 14-digit numbers in export_models.py script
jeancochrane Aug 5, 2024
0b3fc92
Remove stray docs block artifact from qc/docs.md
jeancochrane Aug 6, 2024
10e033f
Reorder qc/schema.yml alphanumerically
jeancochrane Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[flake8]
ignore=
# Whitespace before ':', incompatible with black
E203,
# Line break before binary operator, incompatible with black
W503
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point should probably just switch this project over to ruff, but in the meantime this flake8 config change is necessary to fix some conflicts between black and flake8.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops I think I just biffed this with #564. Will probably need a run through with ruff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Ruff seems to make this config unnecessary so I removed it in 0e41f3e.

dfsnow marked this conversation as resolved.
Show resolved Hide resolved
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
121 changes: 110 additions & 11 deletions dbt/models/qc/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,41 @@ investigated.

{% enddocs %}

# vw_report_neg_asmt_value
# vw_sale_mydec_null_values

{% docs view_vw_sale_mydec_null_values %}
Test that deed, buyer, seller, address and price `sale.mydec` columns are not
null.

{% enddocs %}

# vw_iasworld_asmt_all_joined_to_legdat

{% docs view_vw_iasworld_asmt_all_joined_to_legdat %}
View that joins `iasworld.asmt_all` to `iasworld.legdat` to augment `asmt_all`
with parcel legal descriptions and addresses.

Both views are already filtered for current active records.
{% enddocs %}
jeancochrane marked this conversation as resolved.
Show resolved Hide resolved

# vw_iasworld_asmt_all_with_prior_year_values

{% docs view_vw_report_neg_asmt_value %}
{% docs view_vw_iasworld_asmt_all_with_prior_year_values %}
View that joins `iasworld.asmt_all` to its prior year values for comparison.
Also pulls parcel data from `LEGDAT`, `PARDAT`, `OWNDAT`, and `APRVAL`
for context.

This view is used as the basis for a number of town close QC reports.
{% enddocs %}

# vw_report_town_close_neg_asmt_value

{% docs view_vw_report_town_close_neg_asmt_value %}
Check for `ASMT.val*` columns that are negative.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Negative ASMT Values` (#1569) - Will C.
Expand All @@ -117,19 +147,88 @@ In contrast to `qc.vw_neg_asmt_value`, this view directly performs filtering
for negative values.
{% enddocs %}

# vw_sale_mydec_null_values
# vw_report_town_close_0_land_value
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the docs blocks for the new reports are listed in the order that Will runs them, which made it easier for me to track my progress during development, but I can rearrange them to be in alphabetical order if we have a strong preference for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just quickly order them alphanumerically yeah, for consistency with the other docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, done in 3744e48! Remind me whether we normally also order the schema files this way?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schema files should be alphanumerically ordered. The docs files are kind of a mixed bag (some are broken up by section), but are usually alphanumeric also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I also reordered the schema file in 10e033f. Sorry for the annoying diff! I didn't change anything and checked with a dbt compile that the graph still compiles correctly, which should hopefully rule out any obvious copy/paste errors.


{% docs view_vw_sale_mydec_null_values %}
Test that deed, buyer, seller, address and price `sale.mydec` columns are not
null.
{% docs view_vw_report_town_close_0_land_value %}
Check for parcels that have 0 land value in the `ASMT` table.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Non-EX, RR parcels with 0 land value` (#1578) - Will C.
{% enddocs %}

# vw_iasworld_asmt_all_joined_to_legdat
# vw_report_town_close_0_value

{% docs view_vw_iasworld_asmt_all_joined_to_legdat %}
View that joins `iasworld.asmt_all` to `iasworld.legdat` to augment `asmt_all`
with parcel legal descriptions and addresses.
{% docs view_vw_report_town_close_0_value %}
Check for parcels that have 0 total value in the `ASMT` table.

Both views are already filtered for current active records.
This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Non-EX, RR parcels with 0 value` (#1570) - Will C.
{% enddocs %}

# vw_report_town_close_vacant_class_with_bldg_value

{% docs view_vw_report_town_close_vacant_class_with_bldg_value %}
Check for parcels that have a vacant class in the `PARDAT` table, but a
building value in the `ASMT` table.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Vacant Class, bldg value` (#1577) - Will C.
{% enddocs %}

# vw_report_town_close_improved_class_without_bldg_value

{% docs view_vw_report_town_close_improved_class_without_bldg_value %}
Check for parcels that have a non-vacant class in the `PARDAT` table, but no
building value in the `ASMT` table.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Improved Class, no bldg value` (#1047) - Will C.
{% enddocs %}

# vw_report_town_close_class_does_not_equal_luc

{% docs view_vw_report_town_close_class_does_not_equal_luc %}
Check for parcels where the class does not match the land use code in
the `PARDAT` table.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - Class does not equal LUC` (#2046) - Will C.
{% enddocs %}

# vw_report_town_close_500k_increase_1m_decrease

{% docs view_vw_report_town_close_500k_increase_1m_decrease %}
Check for rows in the `ASMT` table where the total market value has increased
by more than $500k or decreased by more than $1m in the past year.

This view is exported as part of the QC report to check values prior to town
closings.

Pulled from the following Inquire queries:

- `FP Checklist - 500k increase, 1m decrease` (#1673) - Will C.
- `FP Checklist - Card Code Info` (#2160) - Will C.
{% enddocs %}

- `FP Checklist - Prior Yr Card Code 5s OBY` (#1585) - Will C.
{% enddocs %}
3 changes: 0 additions & 3 deletions dbt/models/qc/qc.vw_change_in_ahsap_values.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,3 @@ WHERE ahsap.ahsap
OR hist.certified_tot > hist.mailed_tot * 1.2
OR hist.board_tot > hist.certified_tot * 1.2
)
AND CAST(
hist.year AS INT
) BETWEEN {{ var('test_qc_year_start') }} AND {{ var('test_qc_year_end') }}
jeancochrane marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
SELECT
jeancochrane marked this conversation as resolved.
Show resolved Hide resolved
legdat.parid,
asmt.taxyr,
legdat.user1 AS township_code,
pardat.nbhd,
pardat.class,
pardat.luc,
owndat.own1,
aprval.reascd,
jeancochrane marked this conversation as resolved.
Show resolved Hide resolved
aprval.who,
asmt_prev.valapr1 AS valapr1_prev,
asmt_prev.valapr2 AS valapr2_prev,
asmt_prev.valapr3 AS valapr3_prev,
asmt_prev.valasm1 AS valasm1_prev,
asmt_prev.valasm2 AS valasm2_prev,
asmt_prev.valasm3 AS valasm3_prev,
asmt.valapr1,
asmt.valapr2,
asmt.valapr3,
asmt.valasm1,
asmt.valasm2,
asmt.valasm3
FROM {{ source('iasworld', 'asmt_all') }} AS asmt
LEFT JOIN {{ source('iasworld', 'asmt_all') }} AS asmt_prev
ON asmt.parid = asmt_prev.parid
AND CAST(asmt.taxyr AS INT) = CAST(asmt_prev.taxyr AS INT) + 1
AND asmt_prev.cur = 'Y'
AND asmt_prev.deactivat IS NULL
AND asmt_prev.valclass IS NULL
LEFT JOIN {{ source('iasworld', 'legdat') }} AS legdat
ON asmt.taxyr = legdat.taxyr
AND asmt.parid = legdat.parid
AND legdat.cur = 'Y'
AND legdat.deactivat IS NULL
LEFT JOIN {{ source('iasworld', 'pardat') }} AS pardat
ON asmt.taxyr = pardat.taxyr
AND asmt.parid = pardat.parid
AND pardat.cur = 'Y'
AND pardat.deactivat IS NULL
LEFT JOIN {{ source('iasworld', 'owndat') }} AS owndat
ON asmt.taxyr = owndat.taxyr
AND asmt.parid = owndat.parid
AND owndat.cur = 'Y'
AND owndat.deactivat IS NULL
LEFT JOIN {{ source('iasworld', 'aprval') }} AS aprval
ON asmt.taxyr = aprval.taxyr
AND asmt.parid = aprval.parid
AND aprval.cur = 'Y'
AND aprval.deactivat IS NULL
WHERE asmt.cur = 'Y'
AND asmt.deactivat IS NULL
AND asmt.valclass IS NULL
28 changes: 28 additions & 0 deletions dbt/models/qc/qc.vw_report_town_close_0_land_value.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
SELECT
parid,
taxyr,
township_code,
class,
own1,
reascd,
who,
valapr1_prev,
valapr2_prev,
valapr3_prev,
valasm1_prev,
valasm2_prev,
valasm3_prev,
valapr1,
valapr2,
valapr3,
valasm1,
valasm2,
valasm3
FROM {{ ref('qc.vw_iasworld_asmt_all_with_prior_year_values') }}
WHERE valasm1 = 0
AND class NOT IN ('EX', 'RR')
-- Filter out leasehold parcels. We are not yet sure if there is a
-- definitive field for marking leasehold parcels, but in the meantime
-- the reports have historically followed the heuristic of filtering out
-- parcel IDs where the 11th digit is an 8
AND SUBSTR(parid, 11, 1) != '8'
23 changes: 23 additions & 0 deletions dbt/models/qc/qc.vw_report_town_close_0_value.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
SELECT
parid,
taxyr,
township_code,
class,
own1,
reascd,
who,
valapr1_prev,
valapr2_prev,
valapr3_prev,
valasm1_prev,
valasm2_prev,
valasm3_prev,
valapr1,
valapr2,
valapr3,
valasm1,
valasm2,
valasm3
FROM {{ ref('qc.vw_iasworld_asmt_all_with_prior_year_values') }}
WHERE valasm3 = 0
AND class NOT IN ('EX', 'RR')
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
WITH card_code_info AS (
SELECT
pardat.parid,
pardat.taxyr,
CASE
WHEN
CONTAINS(
ARRAY_AGG(SUBSTRING(COALESCE(dweldat.mktrsn, ''), 1, 1)),
'5'
)
jeancochrane marked this conversation as resolved.
Show resolved Hide resolved
THEN 'Y'
ELSE ''
END AS dweldat_code_5,
CASE
WHEN
CONTAINS(
ARRAY_AGG(SUBSTRING(COALESCE(comdat.chgrsn, ''), 1, 1)), '5'
)
THEN 'Y'
ELSE ''
END AS comdat_code_5,
CASE
WHEN
CONTAINS(
ARRAY_AGG(SUBSTRING(COALESCE(oby.chgrsn, ''), 1, 1)), '5'
)
THEN 'Y'
ELSE ''
END AS oby_code_5
FROM {{ source('iasworld', 'pardat') }} AS pardat
LEFT JOIN {{ source('iasworld', 'dweldat') }} AS dweldat
ON pardat.parid = dweldat.parid
AND pardat.taxyr = dweldat.taxyr
AND dweldat.cur = 'Y'
AND dweldat.deactivat IS NULL
LEFT JOIN {{ source('iasworld', 'comdat') }} AS comdat
ON pardat.parid = comdat.parid
AND pardat.taxyr = comdat.taxyr
AND comdat.cur = 'Y'
AND comdat.deactivat IS NULL
LEFT JOIN {{ source('iasworld', 'oby') }} AS oby
ON pardat.parid = oby.parid
AND pardat.taxyr = oby.taxyr
AND oby.cur = 'Y'
AND oby.deactivat IS NULL
WHERE pardat.cur = 'Y'
AND pardat.deactivat IS NULL
GROUP BY pardat.parid, pardat.taxyr
)

SELECT
asmt.parid,
asmt.taxyr,
asmt.township_code,
asmt.class,
asmt.reascd,
asmt.valapr1_prev,
asmt.valapr2_prev,
asmt.valapr3_prev,
asmt.valapr1,
asmt.valapr2,
asmt.valapr3,
asmt.valapr3 - asmt.valapr3_prev AS difference,
CASE
WHEN asmt.valapr3_prev != 0
THEN CONCAT(
CAST(
ROUND(
(
(asmt.valapr3 - asmt.valapr3_prev)
/ CAST(asmt.valapr3_prev AS DOUBLE)
)
* 100,
2
) AS VARCHAR
),
'%'
)
END AS percent_change,
code.dweldat_code_5,
code.comdat_code_5,
code.oby_code_5
FROM {{ ref('qc.vw_iasworld_asmt_all_with_prior_year_values') }} AS asmt
LEFT JOIN card_code_info AS code
ON asmt.parid = code.parid
-- Join to prior year card code info, since we want to know the code value
-- last year
AND CAST(CAST(asmt.taxyr AS INT) - 1 AS VARCHAR) = code.taxyr
WHERE (
asmt.valapr3 - asmt.valapr3_prev >= 500000
OR asmt.valapr3 - asmt.valapr3_prev <= -1000000
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
SELECT
parid,
taxyr,
township_code,
class,
luc,
own1,
reascd,
who,
valapr1_prev,
valapr2_prev,
valapr3_prev,
valasm1_prev,
valasm2_prev,
valasm3_prev,
valapr1,
valapr2,
valapr3,
valasm1,
valasm2,
valasm3
FROM {{ ref('qc.vw_iasworld_asmt_all_with_prior_year_values') }}
WHERE class != luc
Loading
Loading