Skip to content

Commit 9b59760

Browse files
andreas-homewardamartinson193chase-jonesaneiderhiser
authored
Add columns to HCC recapture (#1355)
* updating row number to rank * updating end date * updating coalesce for end dates * split end date update into separate PR * fix missing comma * Updating yml config * formatting * formatting * Normalizing the facility NPI field * removing claim start date * Updating tests to use test prefix + normalizing facility NPI * Adding data source constraint * remove suspect hcc flag from output * updating suspect hcc flag * updating suspect hcc flag * removing suspect hcc flag from gaps * adding reason * fixing bug with duplicate as * adding uniqueness test * adding distinct * adding distinct * adding data source col * updating pk * fixing coded hccs * updating coded hccs pk check * updating pk * adding hcc type and source * fixing stray comma * updating aliases * including suspects * using external hccs as a name instead * updating gap status * adding year lookback variable * updating hcc hier group * fixing bug * updating recap rates logic * adding lookback period variable --------- Co-authored-by: Andreas Martinson <amartinson193@gmail.com> Co-authored-by: Chase Jones <60072797+chase-jones@users.noreply.github.com> Co-authored-by: Aaron Neiderhiser <anneiderhiser@gmail.com>
1 parent 434ff3f commit 9b59760

16 files changed

Lines changed: 157 additions & 91 deletions

docs/docs/data-marts/hcc-recapture.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The HCC recapture data mart enables organizations to track HCCs which have been
1010
- It affects that patient's risk score
1111
- The risk score affects reimbursement for value-based care contracts
1212

13-
This mart not only tracks HCCs which were previously coded, but also automatically includes any suspect HCCs from the suspect HCC mart and flags them using the `suspect_hcc_flag`.
13+
This mart not only tracks HCCs which were previously coded, but also automatically includes any suspect HCCs from the suspect HCC mart.
1414

1515
Additionally, the mart provides recapture rates and a lot of detail into the type of gap closure.
1616

@@ -44,8 +44,12 @@ The following options are customizable in the HCC recapture mart to provide grea
4444

4545
### HCC Suspect Lists
4646

47-
The `hcc_recapture_suspect_list` variable defaults to `false` and can be set to `true` in the `dbt_project.yml` in order to provide your own HCC suspect list from a payer or clinical source. The data needs to be input into a model called `suspect_hccs`. The required fields can be found in the `hcc_recapture__stg_suspect_hccs` model.
47+
The `hcc_recapture_external_suspect_list` variable defaults to `false` and can be set to `true` in the `dbt_project.yml` in order to provide your own HCC suspect list from a payer or clinical source. The data needs to be input into a model called `suspect_hccs`. The required fields can be found in the `hcc_recapture__stg_suspect_hccs` model.
4848

4949
### Chronic HCCs
5050

51-
The `hcc_recapture_chronic_hccs` variable defaults to `false` and can be set to `true` in the `dbt_project.yml` in order to provide your own custom chronic HCC definition instead of using the CMS chronic HCC definitions already provided. The data needs to be input into a model called `chronic_hccs`. The required fields can be found in the `hcc_recapture__stg_chronic_hccs` model.
51+
The `hcc_recapture_external_chronic_hccs` variable defaults to `false` and can be set to `true` in the `dbt_project.yml` in order to provide your own custom chronic HCC definition instead of using the CMS chronic HCC definitions already provided. The data needs to be input into a model called `chronic_hccs`. The required fields can be found in the `hcc_recapture__stg_chronic_hccs` model.
52+
53+
### Lookback Period
54+
55+
The `hcc_recapture_year_lookback` variable defaults to 1 and can be changed to determine the number of years to lookback to find coded HCCs.

models/data_marts/hcc_recapture/final/hcc_recapture__gap_status.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ select distinct
1414
, recapturable_flag
1515
, hcc_type
1616
, hcc_source
17+
, hcc_gap_type
18+
, hcc_gap_source
1719
, gap_status
18-
, suspect_hcc_flag
19-
from {{ ref('hcc_recapture__int_gap_status')}}
20+
from {{ ref('hcc_recapture__int_gap_status') }}
2021
-- Apply hierarchies
2122
where filtered_by_hierarchy_flag = 0

models/data_marts/hcc_recapture/final/hcc_recapture__hcc_status.sql

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ select distinct
1616
, hccs.hcc_description
1717
, hccs.hcc_hierarchy_group
1818
, hccs.hcc_hierarchy_group_rank
19-
, coalesce(gap.suspect_hcc_flag, hccs.suspect_hcc_flag) as suspect_hcc_flag
19+
, hccs.external_hcc_flag
20+
, hccs.reason
2021
-- Latest risk_model_code per person/year/model_version based on recorded_date
2122
, first_value(hccs.risk_model_code) over (
2223
partition by
@@ -27,13 +28,15 @@ select distinct
2728
) as risk_model_code
2829
, hccs.hcc_type
2930
, hccs.hcc_source
31+
, gap.hcc_gap_type
32+
, gap.hcc_gap_source
3033
, coalesce(gap.gap_status,'ineligible for recapture') as gap_status
3134
-- Filters that may lead to an 'ineligible for recapture' gap status
3235
, hccs.hcc_chronic_flag
3336
, hccs.recapturable_flag
3437
, hccs.eligible_claim_flag
3538
, hccs.eligible_bene_flag
36-
, coalesce(gap.filtered_by_hierarchy_flag, recap.filtered_by_hierarchy_flag,0) as filtered_by_hierarchy_flag
39+
, coalesce(gap.filtered_by_hierarchy_flag, recap.filtered_by_hierarchy_flag, 0) as filtered_by_hierarchy_flag
3740
from {{ ref('hcc_recapture__int_all_hccs') }} as hccs
3841
left join {{ ref('hcc_recapture__int_recapturable_hccs') }} as recap
3942
on hccs.person_id = recap.person_id
@@ -55,4 +58,4 @@ left join {{ ref('hcc_recapture__int_gap_status') }} as gap
5558
when gap.gap_status = 'open' and hccs.hcc_type = 'coded' then hccs.collection_year + 2
5659
else hccs.collection_year + 1
5760
end) = gap.payment_year
58-
where hccs.eligible_bene_flag = 1
61+
where hccs.eligible_bene_flag = 1

models/data_marts/hcc_recapture/final/hcc_recapture__recapture_rates_monthly.sql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ select distinct
2020
, model_version
2121
, hcc_code
2222
, gap_status
23+
, case when hcc_type = 'suspect' then 1 else 0 end as suspect_hcc_flag
2324
, recapturable_flag
24-
, suspect_hcc_flag
25-
, row_number() over (partition by person_id, payer, payment_year, model_version, hcc_code order by recorded_date asc) as earliest_hcc_code
25+
, row_number() over (partition by person_id, payer, payment_year, model_version, hcc_code
26+
order by case hcc_type when 'coded' then 1 when 'captured' then 2 else 3 end, recorded_date asc) as earliest_hcc_code
2627
from {{ ref('hcc_recapture__hcc_status')}}
2728
where 1=1
2829
and gap_status not in ('ineligible for recapture', 'new')
29-
and hcc_type in ('captured', 'coded')
30+
and hcc_type in ('captured', 'coded', 'suspect')
3031
and recapturable_flag = 1
3132
and filtered_by_hierarchy_flag = 0
3233
)

models/data_marts/hcc_recapture/final_models.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,6 @@ models:
301301
- model_version
302302
- hcc_hierarchy_group
303303
- hcc_hierarchy_group_rank
304-
- suspect_hcc_flag
305304
- filtered_by_hierarchy_flag
306305
- hcc_type
307306
- hcc_source
@@ -396,9 +395,8 @@ models:
396395
meta:
397396
data_type: integer
398397
is_primary_key: true
399-
- name: suspect_hcc_flag
400-
description: Flag indicating whether the HCC comes from suspecting logic rather
401-
than a billed diagnosis.
398+
- name: external_hcc_flag
399+
description: "These HCCs are not based on claims, but based on data provided from clinical or additional payer HCC lists."
402400
config:
403401
meta:
404402
data_type: integer
@@ -594,9 +592,4 @@ models:
594592
config:
595593
meta:
596594
data_type: varchar
597-
- name: suspect_hcc_flag
598-
description: Flag indicating whether the HCC comes from suspecting logic rather
599-
than a billed diagnosis.
600-
config:
601-
meta:
602-
data_type: integer
595+

models/data_marts/hcc_recapture/intermediate/hcc_recapture__int_determine_gap_status.sql

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
)
44
}}
55

6+
{% set lookback = var('hcc_recapture_year_lookback', 1) | int %}
7+
68
-- Get recapturable HCCs within the past 1 year
79
with filtered_hccs as (
810
select *
@@ -11,15 +13,16 @@ with filtered_hccs as (
1113
),
1214

1315
risk_gaps as (
16+
{% for year_offset in range(1, lookback + 1) %}
17+
1418
select distinct
1519
person_id
1620
, payer
17-
, collection_year + 1 as collection_year
21+
, collection_year + {{ year_offset }} as collection_year
1822
, model_version
1923
, hcc_code
2024
, hcc_hierarchy_group
2125
, hcc_hierarchy_group_rank
22-
, suspect_hcc_flag
2326
, recapturable_flag
2427
, hcc_type
2528
, hcc_source
@@ -28,6 +31,10 @@ risk_gaps as (
2831
from filtered_hccs
2932
where hcc_type = 'coded'
3033

34+
{% if not loop.last %} union all {% endif %}
35+
36+
{% endfor %}
37+
3138
union all
3239

3340
-- No need to add +1 to collection year since these are already identified as captured/suspect in the same year identified
@@ -40,7 +47,6 @@ risk_gaps as (
4047
, hcc_code
4148
, hcc_hierarchy_group
4249
, hcc_hierarchy_group_rank
43-
, suspect_hcc_flag
4450
, recapturable_flag
4551
, hcc_type
4652
, hcc_source
@@ -50,7 +56,7 @@ risk_gaps as (
5056
where hcc_type = 'suspect'
5157
),
5258

53-
best_past_rank as (
59+
hcc_rank as (
5460
select distinct
5561
person_id
5662
, payer
@@ -59,25 +65,10 @@ best_past_rank as (
5965
, hcc_code
6066
, hcc_hierarchy_group
6167
, hcc_hierarchy_group_rank
62-
, min(hcc_hierarchy_group_rank) over (partition by person_id, payer, collection_year, model_version, hcc_hierarchy_group) as best_past_rank
68+
, min(hcc_hierarchy_group_rank) over (partition by person_id, payer, collection_year, model_version, hcc_hierarchy_group) as best_hcc_rank
6369
from filtered_hccs
6470
where hcc_type in ('coded', 'captured')
65-
),
66-
67-
68-
best_current_rank as (
69-
select distinct
70-
person_id
71-
, payer
72-
, collection_year
73-
, model_version
74-
, hcc_code
75-
, hcc_hierarchy_group
76-
, hcc_hierarchy_group_rank
77-
, risk_model_code
78-
, eligible_bene_flag
79-
, min(hcc_hierarchy_group_rank) over (partition by person_id, payer, collection_year, model_version, hcc_hierarchy_group) as best_current_rank
80-
from filtered_hccs
71+
and hcc_hierarchy_group != 'no hierarchy'
8172
),
8273

8374
equiv_coef as (
@@ -99,31 +90,30 @@ equiv_coef as (
9990
select
10091
coalesce(base.payer, gap.payer) as payer
10192
, coalesce(base.person_id, gap.person_id) as person_id
102-
, coalesce(base.risk_model_code, gap.risk_model_code, current_year_hier.risk_model_code) as risk_model_code
103-
, coalesce(base.eligible_bene_flag, gap.eligible_bene_flag, current_year_hier.eligible_bene_flag) as eligible_bene_flag
93+
, coalesce(base.risk_model_code, gap.risk_model_code) as risk_model_code
94+
, coalesce(base.eligible_bene_flag, gap.eligible_bene_flag) as eligible_bene_flag
10495
, coalesce(base.hcc_code, gap.hcc_code) as hcc_code
10596
, gap.hcc_code as recaptured_hcc_code
106-
, current_year_hier.hcc_code as current_year_hcc_code
107-
, grp.hcc_code as past_year_hcc_code
108-
, coalesce(greatest(base.suspect_hcc_flag, gap.suspect_hcc_flag), 0) as suspect_hcc_flag
97+
, grp.hcc_code as best_current_year_hcc_code
10998
, coalesce(base.model_version, gap.model_version) as model_version
11099
, coalesce(base.collection_year, gap.collection_year) as collection_year
111100
, coalesce(base.hcc_hierarchy_group, gap.hcc_hierarchy_group) as hcc_hierarchy_group
112101
, coalesce(base.hcc_hierarchy_group_rank, gap.hcc_hierarchy_group_rank) as hcc_hierarchy_group_rank
113102
, coalesce(base.recapturable_flag, gap.recapturable_flag) as recapturable_flag
114-
, coalesce(base.hcc_type, gap.hcc_type) as hcc_type
115-
, coalesce(base.hcc_source, gap.hcc_source) as hcc_source
103+
, base.hcc_type
104+
, gap.hcc_type as hcc_gap_type
105+
, base.hcc_source
106+
, gap.hcc_source as hcc_gap_source
116107
, case
117108
when
118109
gap.hcc_code is not null and base.hcc_code is not null and gap.hcc_code != base.hcc_code and equiv.risk_model_code is not null
119110
then 'closed - equivalent coefficient hcc in hierarchy group'
120111
when
121-
grp.hcc_hierarchy_group is not null and base.hcc_hierarchy_group_rank < grp.best_past_rank
112+
grp.hcc_hierarchy_group is not null and base.hcc_hierarchy_group_rank < grp.best_hcc_rank
122113
then 'closed - higher coefficient hcc in hierarchy group'
123-
when current_year_hier.best_current_rank < gap.hcc_hierarchy_group_rank then 'closed - higher coefficient hcc in hierarchy group'
124114
when gap.hcc_code is not null and base.hcc_code is not null then 'closed'
125115
when
126-
grp.hcc_hierarchy_group is not null and base.hcc_hierarchy_group_rank > grp.best_past_rank
116+
grp.hcc_hierarchy_group is not null and base.hcc_hierarchy_group_rank > grp.best_hcc_rank
127117
then 'closed - lower coefficient hcc in hierarchy group'
128118
when gap.hcc_code is not null and base.hcc_code is null then 'open'
129119
when gap.hcc_code is null and base.hcc_code is not null then 'new'
@@ -142,20 +132,13 @@ left join equiv_coef as equiv
142132
and base.hcc_hierarchy_group = equiv.hcc_hierarchy_group
143133
and base.hcc_code = equiv.hcc_code
144134
and base.risk_model_code = equiv.risk_model_code
145-
left join best_past_rank as grp
135+
left join hcc_rank as grp
146136
on base.person_id = grp.person_id
147137
and base.payer = grp.payer
148138
and base.collection_year = grp.collection_year
149139
and base.model_version = grp.model_version
150140
and base.hcc_hierarchy_group = grp.hcc_hierarchy_group
151-
and grp.best_past_rank = grp.hcc_hierarchy_group_rank
152-
left join best_current_rank as current_year_hier
153-
on gap.person_id = current_year_hier.person_id
154-
and gap.payer = current_year_hier.payer
155-
and gap.collection_year = current_year_hier.collection_year
156-
and gap.model_version = current_year_hier.model_version
157-
and gap.hcc_hierarchy_group = current_year_hier.hcc_hierarchy_group
158-
and current_year_hier.best_current_rank = current_year_hier.hcc_hierarchy_group_rank
141+
and grp.best_hcc_rank = grp.hcc_hierarchy_group_rank
159142
-- Gaps are only eligible to be closed by claims data and the base table here is closing the gap aliased table
160143
-- The or hcc_type is null allows open HCCs to flow through
161144
where base.hcc_type in ('coded', 'captured') or base.hcc_type is null

models/data_marts/hcc_recapture/intermediate/hcc_recapture__int_gap_status.sql

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ with add_rankings as (
99
person_id
1010
, payer
1111
, hcc_code
12-
, suspect_hcc_flag
1312
, model_version
1413
, collection_year + 1 as payment_year
1514
, recapturable_flag
1615
, hcc_type
1716
, hcc_source
17+
, hcc_gap_type
18+
, hcc_gap_source
1819
, eligible_bene_flag
1920
, gap_status
2021
, risk_model_code
@@ -35,14 +36,16 @@ with add_rankings as (
3536

3637
-- Pick the best hcc type
3738
-- 1. Best rank
38-
-- 2. If tie → prefer recapture (suspect_hcc_flag = 0)
39+
-- 2. If tie → prefer recapture
3940
, best_hcc_type as (
4041
select *
4142
, row_number() over (
4243
partition by person_id, payer, hcc_code, model_version, payment_year
4344
order by
4445
hcc_type_rank asc,
45-
suspect_hcc_flag asc -- 0 preferred over 1
46+
-- If it was already coded, prefer coded > suspect
47+
case when hcc_type = 'suspect' then 1 else 0 end asc,
48+
case when hcc_gap_type = 'suspect' then 1 else 0 end asc
4649
) as best_rank
4750
from add_rankings
4851
)
@@ -90,10 +93,11 @@ select distinct
9093
, bgap.recapturable_flag
9194
, bgap.hcc_type
9295
, bgap.hcc_source
96+
, bgap.hcc_gap_type
97+
, bgap.hcc_gap_source
9398
, bgap.gap_status
9499
, bgap.hcc_hierarchy_group
95100
, bgap.hcc_hierarchy_group_rank
96-
, bgap.suspect_hcc_flag
97101
-- Apply hierarchies (i.e. if the hierarchy is not the min hierarchy, then remove it)
98102
, case when bgap.hcc_hierarchy_group is not null and mhier.hcc_hierarchy_group is null then 1 else 0 end as filtered_by_hierarchy_flag
99103
from best_gap_status as bgap

models/data_marts/hcc_recapture/intermediate/hccs/hcc_recapture__int_all_hccs.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ select distinct
5959
, case when elig_bene.person_id is not null then 1 else 0 end as eligible_bene_flag
6060
, eligible_claim_flag
6161
, med.rendering_npi
62-
, suspect_hcc_flag
62+
, sus.external_hcc_flag
63+
, sus.reason
6364
, case when chronic.chronic_flag = 1 and eligible_claim_flag = 1 then 1 else 0 end as recapturable_flag
6465
, hcc_type
6566
, hcc_source

models/data_marts/hcc_recapture/intermediate/hccs/hcc_recapture__int_coded_hccs.sql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ with eligible_claims as (
1212
from {{ ref('cms_hcc__int_eligible_conditions') }}
1313
)
1414

15-
select
15+
select distinct
1616
cond.person_id
1717
, cond.payer
1818
, cond.data_source
@@ -21,11 +21,12 @@ select
2121
, cond.claim_id
2222
, cond.hcc_code
2323
, cond.hcc_description
24-
, 0 as suspect_hcc_flag
24+
, 0 as external_hcc_flag
2525
, case
2626
when elig.claim_id is not null then 1
2727
else 0
2828
end as eligible_claim_flag
29+
, 'prior coding history' as reason
2930
, 'coded' as hcc_type
3031
, 'payer' as hcc_source
3132
-- Not using list_all since it doesn't have claim_id pulled through
@@ -35,4 +36,5 @@ left join eligible_claims as elig
3536
on cond.person_id = elig.person_id
3637
and cond.payer = elig.payer
3738
and cond.claim_id = elig.claim_id
38-
where lower(condition_type) = 'discharge_diagnosis'
39+
where lower(condition_type) = 'discharge_diagnosis'
40+
and hcc_code is not null

models/data_marts/hcc_recapture/intermediate/hccs/hcc_recapture__int_recapturable_hccs.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ select
1818
, model_version
1919
, data_source
2020
, hcc_hierarchy_group
21-
, suspect_hcc_flag
21+
, external_hcc_flag
2222
, hcc_chronic_flag
2323
, min(hcc_hierarchy_group_rank) as min_hcc_hier_group_rank
2424
from base
@@ -29,7 +29,7 @@ group by
2929
, model_version
3030
, data_source
3131
, hcc_hierarchy_group
32-
, suspect_hcc_flag
32+
, external_hcc_flag
3333
, hcc_chronic_flag
3434
)
3535

@@ -49,7 +49,7 @@ select
4949
, base.risk_model_code
5050
, base.eligible_bene_flag
5151
, base.rendering_npi
52-
, base.suspect_hcc_flag
52+
, base.external_hcc_flag
5353
, base.recapturable_flag
5454
, base.hcc_type
5555
, base.hcc_source
@@ -63,5 +63,5 @@ left join min_hierarchy as mhier
6363
and base.data_source = mhier.data_source
6464
and base.hcc_hierarchy_group = mhier.hcc_hierarchy_group
6565
and base.hcc_hierarchy_group_rank = mhier.min_hcc_hier_group_rank
66-
and base.suspect_hcc_flag = mhier.suspect_hcc_flag
66+
and base.external_hcc_flag = mhier.external_hcc_flag
6767
and base.hcc_chronic_flag = mhier.hcc_chronic_flag

0 commit comments

Comments
 (0)