diff --git a/changelog.d/ok-ui.added.md b/changelog.d/ok-ui.added.md new file mode 100644 index 00000000000..95dae71528a --- /dev/null +++ b/changelog.d/ok-ui.added.md @@ -0,0 +1 @@ +Add Oklahoma Unemployment Insurance. diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_taxable_wages.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_taxable_wages.yaml new file mode 100644 index 00000000000..655a9f9d1d0 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_taxable_wages.yaml @@ -0,0 +1,12 @@ +description: Oklahoma sets the minimum taxable base period wages at this amount for monetary eligibility under the Unemployment Insurance program. + +values: + 1980-07-01: 1_500 + +metadata: + unit: currency-USD + period: year + label: Oklahoma UI minimum taxable base period wages + reference: + - title: 40 O.S. §2-207(A)(1) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_total_wages_multiplier.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_total_wages_multiplier.yaml new file mode 100644 index 00000000000..2a796aad83a --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/eligibility/min_total_wages_multiplier.yaml @@ -0,0 +1,12 @@ +description: Oklahoma uses this share of high quarter wages as the minimum total base period wages for monetary eligibility under the Unemployment Insurance program. + +values: + 1980-07-01: 1.5 + +metadata: + unit: /1 + period: year + label: Oklahoma UI minimum total wages multiplier + reference: + - title: 40 O.S. §2-207(A)(2) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/index.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/index.yaml new file mode 100644 index 00000000000..cb39cde8a79 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/index.yaml @@ -0,0 +1,4 @@ +metadata: + propagate_metadata_to_children: true + economy: false + household: true diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/base_period_wages_share.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/base_period_wages_share.yaml new file mode 100644 index 00000000000..bb7dc88a817 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/base_period_wages_share.yaml @@ -0,0 +1,22 @@ +description: Oklahoma limits unemployment compensation benefits to this share of base period wages under the Unemployment Insurance program. + +values: + 1980-07-01: 1 + 2023-01-01: 0.4 + 2026-01-01: 0.475 + +metadata: + unit: /1 + period: year + label: Oklahoma UI maximum benefit base period wages share + reference: + - title: 40 O.S. §2-106(3) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51 + - title: OESC Important Numbers for 2023 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2023.pdf#page=1 + - title: OESC Important Numbers for 2024 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2024.pdf#page=1 + - title: OESC Important Numbers for 2025 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2025.pdf#page=1 + - title: OESC Important Numbers for 2026 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Improtant-Numbers-2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_amount.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_amount.yaml new file mode 100644 index 00000000000..1d520e18df8 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_amount.yaml @@ -0,0 +1,26 @@ +description: Oklahoma limits unemployment compensation benefits to this amount within a benefit year under the Unemployment Insurance program. + +values: + 2022-01-01: 9_900 + 2023-01-01: 7_888 + 2024-01-01: 8_304 + 2025-01-01: 8_656 + 2026-01-01: 10_384 + +metadata: + unit: currency-USD + period: year + label: Oklahoma UI maximum benefit amount + reference: + - title: 40 O.S. §2-106 + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51 + - title: Oklahoma UI Tax Rates by Industry, Size, and County, 2021, page 2 + href: https://www.oklahoma.gov/content/dam/ok/en/oesc/documents/labor-market/publications/special-reports/oklahoma-ui-tax-rates-industry-size-county-2021.pdf#page=2 + - title: OESC Important Numbers for 2023 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2023.pdf#page=1 + - title: OESC Important Numbers for 2024 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2024.pdf#page=1 + - title: OESC Important Numbers for 2025 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2025.pdf#page=1 + - title: OESC Important Numbers for 2026 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Improtant-Numbers-2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_weeks.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_weeks.yaml new file mode 100644 index 00000000000..72952e0bb3d --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/mba/max_weeks.yaml @@ -0,0 +1,17 @@ +description: Oklahoma limits unemployment compensation benefits to this number of weeks within a benefit year under the Unemployment Insurance program. + +values: + 1980-07-01: 26 + 2023-01-01: 16 + +metadata: + unit: week + period: year + label: Oklahoma UI maximum benefit weeks + reference: + - title: 40 O.S. §1-231 + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=48 + - title: 40 O.S. §2-106 + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51 + - title: Oklahoma House Bill 1933 (2022) + href: https://www.oklegislature.gov/cf_pdf/2021-22%20ENR/hB/HB1933%20ENR.PDF diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/partial/disregard.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/partial/disregard.yaml new file mode 100644 index 00000000000..376f12c2813 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/partial/disregard.yaml @@ -0,0 +1,12 @@ +description: Oklahoma disregards this amount of weekly earnings before reducing the partial weekly benefit under the Unemployment Insurance program. + +values: + 1994-07-01: 100 + +metadata: + unit: currency-USD + period: week + label: Oklahoma UI partial benefit earnings disregard + reference: + - title: 40 O.S. §2-105 + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/divisor.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/divisor.yaml new file mode 100644 index 00000000000..121e9932471 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/divisor.yaml @@ -0,0 +1,12 @@ +description: Oklahoma uses this divisor on taxable high quarter wages to compute the weekly benefit amount under the Unemployment Insurance program. + +values: + 1980-07-01: 23 + +metadata: + unit: /1 + period: year + label: Oklahoma UI weekly benefit divisor + reference: + - title: 40 O.S. §2-104(A) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/max_amount.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/max_amount.yaml new file mode 100644 index 00000000000..d52e11fe3d6 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/max_amount.yaml @@ -0,0 +1,30 @@ +description: Oklahoma sets the maximum weekly benefit amount at this amount under the Unemployment Insurance program. + +values: + 2022-01-01: 476 + 2023-01-01: 493 + 2024-01-01: 519 + 2025-01-01: 541 + 2026-01-01: 649 + +metadata: + unit: currency-USD + period: week + label: Oklahoma UI maximum weekly benefit amount + reference: + - title: 40 O.S. §2-104(B) (OESC Board determines maximum weekly benefit annually) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50 + - title: Oklahoma UI Tax Rates by Industry, Size, and County, 2021, page 2 + href: https://www.oklahoma.gov/content/dam/ok/en/oesc/documents/labor-market/publications/special-reports/oklahoma-ui-tax-rates-industry-size-county-2021.pdf#page=2 + - title: OESC Important Numbers for 2023 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2023.pdf#page=1 + - title: OESC Important Numbers for 2024 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2024.pdf#page=1 + - title: OESC Important Numbers for 2025 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2025.pdf#page=1 + - title: OESC Claimant Handbook OES-339 (Rev. 05-2025), page 4 + href: https://oklahoma.gov/content/dam/ok/en/oesc/documents/forms/OES-339.pdf#page=4 + - title: Oklahoma Employment Security Commission + href: https://oklahoma.gov/oesc.html + - title: OESC Important Numbers for 2026 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Improtant-Numbers-2026.pdf#page=1 diff --git a/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/min_amount.yaml b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/min_amount.yaml new file mode 100644 index 00000000000..7ab58a396e7 --- /dev/null +++ b/policyengine_us/parameters/gov/states/ok/oesc/unemployment_insurance/wba/min_amount.yaml @@ -0,0 +1,12 @@ +description: Oklahoma sets the minimum weekly benefit amount at this amount under the Unemployment Insurance program. + +values: + 1980-07-01: 16 + +metadata: + unit: currency-USD + period: week + label: Oklahoma UI minimum weekly benefit amount + reference: + - title: 40 O.S. §2-104(A) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50 diff --git a/policyengine_us/parameters/gov/states/ok/tax/payroll/unemployment/taxable_wage_base.yaml b/policyengine_us/parameters/gov/states/ok/tax/payroll/unemployment/taxable_wage_base.yaml index aeec506fd45..8aacbe0b4ae 100644 --- a/policyengine_us/parameters/gov/states/ok/tax/payroll/unemployment/taxable_wage_base.yaml +++ b/policyengine_us/parameters/gov/states/ok/tax/payroll/unemployment/taxable_wage_base.yaml @@ -1,15 +1,32 @@ -description: Employer-side unemployment insurance taxable wage base for Oklahoma. +description: Oklahoma sets the annual unemployment insurance taxable wage base at this amount under the Unemployment Insurance program. + values: - 0000-01-01: 27_000 + 2022-01-01: 24_800 + 2023-01-01: 25_700 + 2024-01-01: 27_000 + 2025-01-01: 28_200 + 2026-01-01: 25_000 metadata: period: year unit: currency-USD label: Oklahoma unemployment taxable wage base reference: - - title: Oklahoma Statutes Title 40 Section 1-223 - href: https://oksenate.gov/sites/default/files/2022-05/os40.pdf#page=32 - - title: Oklahoma Employment Security Commission important numbers for 2026 + - title: 40 O.S. §1-201(48) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=23 + - title: 40 O.S. §1-223 + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=44 + - title: 40 O.S. §2-207(B) + href: https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56 + - title: Oklahoma UI Tax Rates by Industry, Size, and County, 2021, page 2 + href: https://www.oklahoma.gov/content/dam/ok/en/oesc/documents/labor-market/publications/special-reports/oklahoma-ui-tax-rates-industry-size-county-2021.pdf#page=2 + - title: OESC Important Numbers for 2023 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2023.pdf#page=1 + - title: OESC Important Numbers for 2024 + href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Important-Numbers-2024.pdf#page=1 + - title: Oklahoma OMES 2025 Rates and Maximums for FICA and Unemployment + href: https://oklahoma.gov/content/dam/ok/en/omes/documents/2025RatesMaximumsFICAUnemployment.pdf#page=1 + - title: Oklahoma Employment Security Commission Important Numbers for 2026 href: https://oklahoma.gov/content/dam/ok/en/oesc/images/misc/Employer-Improtant-Numbers-2026.pdf#page=1 - title: Tax Measures of State Unemployment Insurance Tax Systems, CY 2024 href: https://oui.doleta.gov/unemploy/pdf/sigmeasures/sigmeasuitaxsys24.pdf#page=46 diff --git a/policyengine_us/programs.yaml b/policyengine_us/programs.yaml index 76b5377b5f3..a52c5c18de5 100644 --- a/policyengine_us/programs.yaml +++ b/policyengine_us/programs.yaml @@ -1126,6 +1126,17 @@ programs: variable: ny_drive_clean_rebate parameter_prefix: gov.states.ny.nyserda.drive_clean + - id: ok_ui + name: Oklahoma UI + full_name: Oklahoma Unemployment Insurance + category: Benefits + agency: Oklahoma Employment Security Commission + status: complete + coverage: OK + variable: ok_ui + parameter_prefix: gov.states.ok.oesc.unemployment_insurance + verified_years: "2022-2026" + - id: tx_fpp_benefit name: Texas FPP full_name: Texas Family Planning Program diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/edge_cases.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/edge_cases.yaml new file mode 100644 index 00000000000..6ec94da98c9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/edge_cases.yaml @@ -0,0 +1,530 @@ +# Edge case tests for Oklahoma Unemployment Insurance (OK UI). +# Boundary conditions for the monetary eligibility tests (§ 2-207), +# the WBA clamp (§ 2-104), the partial-benefit subtraction (§ 2-105), +# the MBA lesser-of caps / max_weeks transition (§ 2-106, HB 1933), and the +# defined_for state gate. + +# --- Test A boundary (§ 2-207(A)): taxable >= $1,500 AND total >= 1.5 * HQW --- + +- name: Case 1, Test A taxable wages exactly at $1,500 threshold. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 1_000 + ok_ui_base_period_taxable_wages: 1_500 + ok_ui_base_period_total_wages: 1_500 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A taxable prong: $1,500 >= $1,500 -> passes (>= operator). + # Test A multiplier prong: $1,500 >= 1.5 * $1,000 = $1,500 -> passes (>=). + # Test A: both prongs pass. + ok_ui_meets_high_quarter_test: true + # Test B: total $1,500 < $27,000 (2024 wage base) -> fails. + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: true + +- name: Case 2, Test A taxable wages one dollar below threshold. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 1_000 + ok_ui_base_period_taxable_wages: 1_499 + ok_ui_base_period_total_wages: 1_500 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A taxable prong: $1,499 < $1,500 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: $1,499 > 0 but total $1,500 < $27,000 -> fails. + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: false + +- name: Case 3, Test A total wages exactly at 1.5x HQW boundary. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 5_000 + ok_ui_base_period_total_wages: 15_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A multiplier prong: $15,000 >= 1.5 * $10,000 = $15,000 -> passes (>= operator). + # Test A taxable prong: $5,000 >= $1,500 -> passes. + ok_ui_meets_high_quarter_test: true + ok_ui_monetarily_eligible: true + +- name: Case 4, Test A total wages one dollar below 1.5x HQW boundary. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 5_000 + ok_ui_base_period_total_wages: 14_999 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A multiplier prong: $14,999 < 1.5 * $10,000 = $15,000 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: total $14,999 < $27,000 -> fails. + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: false + +# --- Test B boundary (§ 2-207(B)): taxable > 0 AND total >= wage base --- + +- name: Case 5, Test B total wages exactly at 2025 taxable wage base. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 20_000 + ok_ui_base_period_taxable_wages: 2_000 + ok_ui_base_period_total_wages: 28_200 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: $28,200 < 1.5 * $20,000 = $30,000 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: taxable $2,000 > $0 AND $28,200 >= $28,200 (2025 wage base) -> passes (>=). + ok_ui_meets_alternate_wages_test: true + ok_ui_monetarily_eligible: true + +- name: Case 6, Test B total wages one dollar below 2025 taxable wage base. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 20_000 + ok_ui_base_period_taxable_wages: 2_000 + ok_ui_base_period_total_wages: 28_199 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: $28,199 < $30,000 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: $28,199 < $28,200 -> fails. + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: false + +# --- WBA clamp boundaries (§ 2-104(A): floor(HQW / 23), clamped to [$16, max]) --- + +- name: Case 7, WBA below minimum - HQW $367 clamped up to $16 floor. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 367 + ok_ui_base_period_taxable_wages: 1_500 + ok_ui_base_period_total_wages: 2_250 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($367 / 23) = floor($15.957) = $15 -> below $16 minimum -> clamped to $16. + ok_ui_weekly_benefit_rate: 16 + +- name: Case 8, WBA exactly at minimum - HQW $368 yields $16. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 368 + ok_ui_base_period_taxable_wages: 1_500 + ok_ui_base_period_total_wages: 2_250 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($368 / 23) = floor($16.0) = $16 -> exactly at minimum. + ok_ui_weekly_benefit_rate: 16 + +- name: Case 9, WBA exactly at 2024 maximum - HQW $11,937 yields $519. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_937 + ok_ui_base_period_taxable_wages: 11_937 + ok_ui_base_period_total_wages: 30_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # 519 * 23 = $11,937 exactly; floor($11,937 / 23) = $519. + # 2024 max is $519 -> no clamp needed, exactly at boundary. + ok_ui_weekly_benefit_rate: 519 + +- name: Case 10, WBA still at 2024 max - HQW $11,938 yields $519. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_938 + ok_ui_base_period_taxable_wages: 11_938 + ok_ui_base_period_total_wages: 30_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($11,938 / 23) = floor($519.043) = $519 -> at 2024 max, no clamp. + ok_ui_weekly_benefit_rate: 519 + +- name: Case 11, WBA clamped down at 2024 max - HQW $11,960 yields $520 raw, clamped to $519. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_960 + ok_ui_base_period_taxable_wages: 11_960 + ok_ui_base_period_total_wages: 30_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # 520 * 23 = $11,960 exactly; floor($11,960 / 23) = $520. + # $520 > $519 (2024 max) -> clamped down to $519. + ok_ui_weekly_benefit_rate: 519 + +- name: Case 12, very high HQW clamped to 2025 max $541. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 100_000 + ok_ui_base_period_taxable_wages: 100_000 + ok_ui_base_period_total_wages: 300_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($100,000 / 23) = floor($4,347.83) = $4,347 -> far above $541 (2025 max) -> clamped to $541. + ok_ui_weekly_benefit_rate: 541 + +# --- Zero income / zero weeks --- + +- name: Case 13, all wages zero - both tests fail, no benefit. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 0 + ok_ui_base_period_taxable_wages: 0 + ok_ui_base_period_total_wages: 0 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: $0 < $1,500 -> fails. Test B: $0 not > 0 -> fails. + ok_ui_monetarily_eligible: false + # defined_for gate -> $0. + ok_ui: 0 + +- name: Case 14, eligible but zero weeks unemployed - annual benefit zero. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 0 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_monetarily_eligible: true + # WBA: floor($9,200 / 23) = $400. + ok_ui_weekly_benefit_rate: 400 + # MBA = $400 * 16 = $6,400 (defined regardless of weeks worked). + ok_ui_maximum_benefit_amount: 6_400 + # Annual: min($400 * 0, $6,400) = $0. + ok_ui: 0 + +# --- Partial benefit edge cases (§ 2-105) --- + +- name: Case 15, weekly earnings exactly at $100 disregard - full WBA paid. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 100 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # earnings_reduction = max(0, $100 - $100) = $0; payable = max(0, $400 - 0) = $400. + ok_ui_weekly_payable: 400 + +- name: Case 16, weekly earnings one dollar above disregard - WBA reduced by $1. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 101 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # earnings_reduction = max(0, $101 - $100) = $1; payable = max(0, $400 - $1) = $399. + ok_ui_weekly_payable: 399 + +- name: Case 17, weekly earnings exactly at WBA + disregard - payable zero. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 500 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # earnings_reduction = max(0, $500 - $100) = $400; payable = max(0, $400 - $400) = $0. + ok_ui_weekly_payable: 0 + +- name: Case 18, weekly earnings above WBA + disregard - payable floored at zero. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 501 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # earnings_reduction = max(0, $501 - $100) = $401; raw payable = $400 - $401 = -$1 -> max(0, -1) = $0. + ok_ui_weekly_payable: 0 + +# --- max_weeks transition (§ 2-106, HB 1933): 26 pre-2023, 16 from 2023-01-01 --- + +- name: Case 19, year 2022 - pre-2023 max_weeks of 26. + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $6,900 -> floor($6,900 / 23) = $300. + ok_ui_high_quarter_taxable_wages: 6_900 + ok_ui_base_period_taxable_wages: 6_900 + ok_ui_base_period_total_wages: 20_700 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 300 + # 2022 max_weeks = 26; MBA = $300 * 26 = $7,800. + ok_ui_maximum_benefit_amount: 7_800 + +- name: Case 20, year 2024 - post-2023 max_weeks of 16. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # Same HQW as Case 19 to isolate the max_weeks change. + ok_ui_high_quarter_taxable_wages: 6_900 + ok_ui_base_period_taxable_wages: 6_900 + ok_ui_base_period_total_wages: 20_700 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 300 + # 2024 max_weeks = 16; MBA = $300 * 16 = $4,800. + ok_ui_maximum_benefit_amount: 4_800 + +# --- State gate (defined_for = "ok_ui_monetarily_eligible" with StateCode.OK) --- + +- name: Case 21, non-OK state with otherwise eligible inputs - benefit zeroed. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_500 + ok_ui_base_period_taxable_wages: 11_500 + ok_ui_base_period_total_wages: 35_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: TX + output: + people: + person1: + # state_code TX: StateCode.OK gate on upstream variables and the + # ok_ui_monetarily_eligible defined_for cascade returns $0. + ok_ui: 0 + +- name: Case 22, OK state with same inputs as Case 21 - benefit positive. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_500 + ok_ui_base_period_taxable_wages: 11_500 + ok_ui_base_period_total_wages: 35_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_monetarily_eligible: true + # WBA: floor($11,500 / 23) = $500; within 2024 [$16, $519] -> $500. + ok_ui_weekly_benefit_rate: 500 + # MBA = $500 * 16 = $8,000; annual = min($500 * 16, $8,000) = $8,000. + ok_ui: 8_000 + +- name: Case 23, base-period wages share caps annual benefit. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 10_000 + ok_ui_base_period_total_wages: 15_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_monetarily_eligible: true + ok_ui_weekly_benefit_rate: 434 + # Lesser of $434 * 16 = $6,944, statewide $8,656, and 40% * $15,000 = $6,000. + ok_ui_maximum_benefit_amount: 6_000 + ok_ui: 6_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/integration.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/integration.yaml new file mode 100644 index 00000000000..589cf24b50c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/integration.yaml @@ -0,0 +1,210 @@ +# Integration tests for Oklahoma Unemployment Insurance (OK UI). +# End-to-end scenarios checking ok_ui together with intermediate variables. +# References: 40 O.S. §§1-202, 1-218, 1-223, 1-231, 2-102, 2-104, 2-105, 2-106, 2-207; +# OESC Claimant Handbook OES-339 (Rev. 05-2025); OESC Important Numbers 2024/2025/2026. + +- name: Case 1, eligible single claimant with mid-range wages in 2024. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_500 + ok_ui_base_period_taxable_wages: 11_500 + ok_ui_base_period_total_wages: 35_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $11,500 >= $1,500 (ok); total $35,000 >= 1.5 * $11,500 = $17,250 -> passes. + ok_ui_meets_high_quarter_test: true + ok_ui_monetarily_eligible: true + # WBA: floor($11,500 / 23) = $500; within 2024 [$16, $519] -> $500. + ok_ui_weekly_benefit_rate: 500 + # Earnings $0 -> full WBA paid. + ok_ui_weekly_payable: 500 + # 2024 max_weeks = 16 (post-2023); MBA = $500 * 16 = $8,000. + ok_ui_maximum_benefit_amount: 8_000 + # Annual: min($500 * 16, $8,000) = $8,000. + ok_ui: 8_000 + unemployment_compensation: 8_000 + +- name: Case 2, ineligible claimant - wages too low in 2024. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + ok_ui_high_quarter_taxable_wages: 5_000 + ok_ui_base_period_taxable_wages: 500 + ok_ui_base_period_total_wages: 5_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 12 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $500 < $1,500 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: total $5,000 < $27,000 (2024 wage base) -> fails. + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: false + # defined_for gate -> $0. + ok_ui: 0 + +- name: Case 3, high earner in 2025 capped at $541 max WBA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 45 + ok_ui_high_quarter_taxable_wages: 30_000 + ok_ui_base_period_taxable_wages: 30_000 + ok_ui_base_period_total_wages: 90_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $30,000 >= $1,500; total $90,000 >= 1.5 * $30,000 = $45,000 -> passes. + ok_ui_monetarily_eligible: true + # WBA: floor($30,000 / 23) = floor($1,304.35) = $1,304; clamped to $541 (2025 max). + ok_ui_weekly_benefit_rate: 541 + ok_ui_weekly_payable: 541 + # MBA = $541 * 16 = $8,656. + ok_ui_maximum_benefit_amount: 8_656 + # Annual: min($541 * 16, $8,656) = $8,656. + ok_ui: 8_656 + +- name: Case 4, partial benefit week - claimant works part-time. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 32 + # HQW $9,200 -> WBA = $400. + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 200 + weeks_unemployed: 10 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $9,200 >= $1,500; total $30,000 >= 1.5 * $9,200 = $13,800 -> passes. + ok_ui_monetarily_eligible: true + # WBA: floor($9,200 / 23) = $400; within 2025 [$16, $541] -> $400. + ok_ui_weekly_benefit_rate: 400 + # Earnings offset: max(0, $200 - $100) = $100. + # Partial: max(0, $400 - $100) = $300. + ok_ui_weekly_payable: 300 + # MBA = $400 * 16 = $6,400. + ok_ui_maximum_benefit_amount: 6_400 + # Annual: min($300 * 10, $6,400) = min($3,000, $6,400) = $3,000. + ok_ui: 3_000 + +- name: Case 5, pre-2023 regime - 26-week max_weeks doubles MBA. + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 38 + # HQW $6,900 -> WBA = $300. + ok_ui_high_quarter_taxable_wages: 6_900 + ok_ui_base_period_taxable_wages: 6_900 + ok_ui_base_period_total_wages: 20_700 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 26 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $6,900 >= $1,500; total $20,700 >= 1.5 * $6,900 = $10,350 -> passes. + ok_ui_monetarily_eligible: true + # WBA: floor($6,900 / 23) = $300. + ok_ui_weekly_benefit_rate: 300 + ok_ui_weekly_payable: 300 + # Pre-2023 max_weeks = 26; MBA = $300 * 26 = $7,800. + ok_ui_maximum_benefit_amount: 7_800 + # Annual: min($300 * 26, $7,800) = $7,800. + ok_ui: 7_800 + +- name: Case 6, Test B prong - low taxable but high total wages in 2025. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 50 + ok_ui_high_quarter_taxable_wages: 20_000 + ok_ui_base_period_taxable_wages: 2_000 + ok_ui_base_period_total_wages: 28_500 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $2,000 >= $1,500 (ok); total $28,500 < 1.5 * $20,000 = $30,000 -> fails. + ok_ui_meets_high_quarter_test: false + # Test B: taxable $2,000 > $0 (ok); total $28,500 >= $28,200 (2025 wage base) -> passes. + ok_ui_meets_alternate_wages_test: true + ok_ui_monetarily_eligible: true + # WBA: floor($20,000 / 23) = floor($869.57) = $869; clamped to $541 (2025 max). + ok_ui_weekly_benefit_rate: 541 + ok_ui_weekly_payable: 541 + # MBA = $541 * 16 = $8,656. + ok_ui_maximum_benefit_amount: 8_656 + # Annual: min($541 * 16, $8,656) = $8,656. + ok_ui: 8_656 + +- name: Case 7, out-of-state claimant - state gate yields zero benefit. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 11_500 + ok_ui_base_period_taxable_wages: 11_500 + ok_ui_base_period_total_wages: 35_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: TX + output: + people: + person1: + # state_code TX != OK -> defined_for = StateCode.OK gate -> $0. + # Note: intermediate variables (eligibility, WBA, etc.) may still + # compute, but the top-level ok_ui is gated to OK households only. + ok_ui: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui.yaml new file mode 100644 index 00000000000..79bf70b11bc --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui.yaml @@ -0,0 +1,83 @@ +# Tests for Oklahoma UI annual benefit (top-level variable). +# Annual benefit = min(partial_weekly_benefit * weeks_unemployed, MBA). +# Gated by ok_ui_monetarily_eligible (defined_for) and StateCode.OK. +# Reference: 40 O.S. §2-105, §2-106. + +- name: Case 1, eligible claimant - 10 weeks unemployed yields partial of MBA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $9,200 -> WBA = $400 (within 2025 [$16, $541] range). + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 10 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $9,200 >= $1,500 AND total $30,000 >= 1.5 * $9,200 = $13,800 -> passes. + ok_ui_monetarily_eligible: true + ok_ui_weekly_benefit_rate: 400 + ok_ui_weekly_payable: 400 + # MBA = $400 * 16 weeks = $6,400. + ok_ui_maximum_benefit_amount: 6_400 + # Annual = min($400 * 10, $6,400) = min($4,000, $6,400) = $4,000. + ok_ui: 4_000 + +- name: Case 2, eligible claimant - weeks exceed max_weeks - capped at MBA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 20 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_monetarily_eligible: true + ok_ui_weekly_benefit_rate: 400 + ok_ui_maximum_benefit_amount: 6_400 + # Annual = min($400 * 20, $6,400) = min($8,000, $6,400) = $6,400 (capped at MBA). + ok_ui: 6_400 + +- name: Case 3, monetarily ineligible - zero benefit regardless of weeks. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 1_000 + ok_ui_base_period_total_wages: 12_000 + ok_ui_gross_weekly_earnings: 0 + weeks_unemployed: 16 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $1,000 < $1,500 -> fails. + # Test B: total $12,000 < $28,200 (2025 wage base) -> fails. + ok_ui_monetarily_eligible: false + # defined_for gate -> $0. + ok_ui: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.yaml new file mode 100644 index 00000000000..ad503f630d9 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.yaml @@ -0,0 +1,67 @@ +# Tests for Oklahoma UI maximum benefit amount (40 O.S. §2-106). +# MBA = min(WBA * max_weeks, statewide max benefit amount, base-period wages share cap). +# max_weeks: 26 before 2023-01-01, 16 from 2023-01-01. +# Reference: 40 O.S. §2-106; HB 1933 (2022). + +- name: Case 1, 2024 - WBA $400 yields MBA $6,400 over 16 weeks. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $9,200 -> floor($9,200 / 23) = $400 (within 2024 [$16, $519] range). + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # 2024 max_weeks = 16; MBA = $400 * 16 = $6,400. + ok_ui_maximum_benefit_amount: 6_400 + +- name: Case 2, pre-2023 - WBA $300 yields MBA $7,800 over 26 weeks. + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $6,900 -> floor($6,900 / 23) = $300. + ok_ui_high_quarter_taxable_wages: 6_900 + ok_ui_base_period_total_wages: 20_700 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 300 + # Pre-2023 max_weeks = 26; MBA = $300 * 26 = $7,800. + ok_ui_maximum_benefit_amount: 7_800 + +- name: Case 3, 2025 - base-period wages share caps marginal Test A claimant. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $10,000 -> floor($10,000 / 23) = $434. + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_total_wages: 15_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 434 + # Lesser of $434 * 16 = $6,944, statewide $8,656, and 40% * $15,000 = $6,000. + ok_ui_maximum_benefit_amount: 6_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.yaml new file mode 100644 index 00000000000..f1a9d1cf37c --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.yaml @@ -0,0 +1,65 @@ +# Tests for Oklahoma UI monetary eligibility Test B (40 O.S. §2-207(B)). +# Both conditions must be met: +# 1. Base-period taxable wages > 0. +# 2. Total base-period wages >= annual taxable wage base for the claim year. +# 2025 taxable wage base = $28,200 (gov.states.ok.tax.payroll.unemployment.taxable_wage_base). +# Reference: 40 O.S. §2-207(B); 40 O.S. §1-223. + +- name: Case 1, both prongs pass with minimal taxable and total at wage base. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 7_050 + ok_ui_base_period_taxable_wages: 1 + ok_ui_base_period_total_wages: 28_200 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $1 > $0 (passes prong 1). + # Total $28,200 >= $28,200 (2025 wage base) -> passes prong 2. + ok_ui_meets_alternate_wages_test: true + +- name: Case 2, fails taxable wages prong - zero taxable wages. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 0 + ok_ui_base_period_taxable_wages: 0 + ok_ui_base_period_total_wages: 50_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $0 is not > $0 -> fails prong 1. + ok_ui_meets_alternate_wages_test: false + +- name: Case 3, fails total-wages prong by one dollar below 2025 wage base. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 7_000 + ok_ui_base_period_taxable_wages: 1_000 + ok_ui_base_period_total_wages: 28_199 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $1,000 > 0 (passes prong 1). + # Total $28,199 < $28,200 (2025 wage base) -> fails prong 2. + ok_ui_meets_alternate_wages_test: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.yaml new file mode 100644 index 00000000000..973dce5260f --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.yaml @@ -0,0 +1,84 @@ +# Tests for Oklahoma UI monetary eligibility Test A (40 O.S. §2-207(A)). +# Both conditions must be met: +# 1. Base-period taxable wages >= $1,500. +# 2. Total base-period wages >= 1.5 x high-quarter taxable wages. +# Reference: 40 O.S. §2-207(A). + +- name: Case 1, both prongs pass with margin. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 1_500 + ok_ui_base_period_total_wages: 15_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $1,500 >= $1,500 (passes prong 1). + # Total $15,000 >= 1.5 * $10,000 = $15,000 (passes prong 2). + ok_ui_meets_high_quarter_test: true + +- name: Case 2, fails taxable wages floor by one dollar. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 1_499 + ok_ui_base_period_total_wages: 15_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $1,499 < $1,500 -> fails prong 1. + ok_ui_meets_high_quarter_test: false + +- name: Case 3, fails 1.5x high-quarter multiplier by one dollar. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 2_000 + ok_ui_base_period_total_wages: 14_999 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable $2,000 >= $1,500 (passes prong 1). + # Total $14,999 < 1.5 * $10,000 = $15,000 -> fails prong 2. + ok_ui_meets_high_quarter_test: false + +- name: Case 4, boundary - taxable exactly at floor and total exactly at 1.5 x HQW. + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 1_500 + ok_ui_base_period_total_wages: 15_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Taxable exactly $1,500 (passes prong 1; >= test). + # Total exactly $15,000 = 1.5 * $10,000 (passes prong 2; >= test). + ok_ui_meets_high_quarter_test: true diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.yaml new file mode 100644 index 00000000000..08c5f4c8c68 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.yaml @@ -0,0 +1,74 @@ +# Tests for Oklahoma UI overall monetary eligibility (40 O.S. §2-207). +# Eligible if Test A OR Test B passes: +# Test A (§2-207(A)): taxable >= $1,500 AND total >= 1.5 x HQW. +# Test B (§2-207(B)): taxable > 0 AND total >= annual taxable wage base. +# Reference: 40 O.S. §2-207. + +- name: Case 1, Test A passes alone (Test B fails on total below wage base). + period: 2024 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 5_000 + ok_ui_base_period_total_wages: 20_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $5,000 >= $1,500 AND $20,000 >= 1.5 * $10,000 = $15,000 -> passes. + # Test B: total $20,000 < $27,000 (2024 wage base) -> fails. + # Overall: A OR B = true. + ok_ui_meets_high_quarter_test: true + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: true + +- name: Case 2, Test B passes alone (Test A fails on 1.5x prong). + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 20_000 + ok_ui_base_period_taxable_wages: 2_000 + ok_ui_base_period_total_wages: 28_500 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $2,000 >= $1,500 (ok); total $28,500 < 1.5 * $20,000 = $30,000 -> fails. + # Test B: taxable $2,000 > $0 (ok); total $28,500 >= $28,200 (2025 wage base) -> passes. + # Overall: A OR B = true. + ok_ui_meets_high_quarter_test: false + ok_ui_meets_alternate_wages_test: true + ok_ui_monetarily_eligible: true + +- name: Case 3, both tests fail. + period: 2025 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + ok_ui_base_period_taxable_wages: 1_000 + ok_ui_base_period_total_wages: 12_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # Test A: taxable $1,000 < $1,500 -> fails. + # Test B: total $12,000 < $28,200 (2025 wage base) -> fails. + # Overall: A OR B = false. + ok_ui_meets_high_quarter_test: false + ok_ui_meets_alternate_wages_test: false + ok_ui_monetarily_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.yaml new file mode 100644 index 00000000000..abb3d5247eb --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.yaml @@ -0,0 +1,120 @@ +# Tests for Oklahoma UI weekly benefit amount (40 O.S. §2-104(A), §2-102). +# Formula: WBA = clamp(floor(HQW_taxable / 23), [min=$16, max=annual_cap]). +# Annual max WBA: 2022=$476, 2023=$493, 2024=$519, 2025=$541, 2026=$649. +# Min WBA $16 has been the statutory floor since 1980. +# Reference: 40 O.S. §2-104(A), §2-102; OESC Important Numbers. + +- name: Case 1, handbook example - HQW $14,000 in 2024 clamped to max $519. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 14_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($14,000 / 23) = floor($608.69) = $608. + # $608 > $519 (2024 max) -> clamped to $519. + # Matches OES-339 Rev. 05-2025 page 4 worked example. + ok_ui_weekly_benefit_rate: 519 + +- name: Case 2, low HQW lifted to statutory minimum $16. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 200 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($200 / 23) = floor($8.70) = $8. + # $8 < $16 -> lifted to $16 minimum. + ok_ui_weekly_benefit_rate: 16 + +- name: Case 3, mid HQW within 2025 range. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($10,000 / 23) = floor($434.78) = $434. + # $16 <= $434 <= $541 (2025 max) -> WBA = $434. + ok_ui_weekly_benefit_rate: 434 + +- name: Case 4, mid HQW within 2026 range. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 10_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($10,000 / 23) = $434. + # $16 <= $434 <= $649 (2026 max) -> WBA = $434. + ok_ui_weekly_benefit_rate: 434 + +- name: Case 5, high HQW clamped to 2026 maximum. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + ok_ui_high_quarter_taxable_wages: 20_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($20,000 / 23) = floor($869.57) = $869. + # $869 > $649 (2026 max) -> clamped to $649. + ok_ui_weekly_benefit_rate: 649 + +- name: Case 6, high HQW clamped to 2022 maximum. + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + ok_ui_high_quarter_taxable_wages: 20_000 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + # floor($20,000 / 23) = floor($869.57) = $869. + # $869 > $476 (2022 max) -> clamped to $476. + ok_ui_weekly_benefit_rate: 476 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.yaml b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.yaml new file mode 100644 index 00000000000..101e2c51e51 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.yaml @@ -0,0 +1,98 @@ +# Tests for Oklahoma UI partial weekly benefit (40 O.S. §2-105). +# Formula: weekly_payable = max(0, WBA - max(0, weekly_earnings - $100)). +# The first $100 of weekly earnings is disregarded; every dollar above $100 +# reduces WBA dollar-for-dollar; result is floored at $0. +# Reference: 40 O.S. §2-105. + +- name: Case 1, weekly earnings below disregard - full WBA paid. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + # HQW $9,200 -> floor($9,200 / 23) = $400 WBA (within 2025 range). + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 50 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # Earnings $50 < $100 disregard -> earnings_offset = max(0, 50 - 100) = $0. + # Payable = max(0, $400 - $0) = $400. + ok_ui_weekly_payable: 400 + +- name: Case 2, weekly earnings exactly at disregard - full WBA paid. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 100 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # Earnings $100 = $100 disregard -> earnings_offset = max(0, 100 - 100) = $0. + # Payable = max(0, $400 - $0) = $400. + ok_ui_weekly_payable: 400 + +- name: Case 3, weekly earnings above disregard - dollar-for-dollar reduction. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 150 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # Earnings $150 > $100 -> earnings_offset = $150 - $100 = $50. + # Payable = max(0, $400 - $50) = $350. + ok_ui_weekly_payable: 350 + +- name: Case 4, weekly earnings so high payable would be negative - floored at zero. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 35 + ok_ui_high_quarter_taxable_wages: 9_200 + ok_ui_base_period_taxable_wages: 9_200 + ok_ui_base_period_total_wages: 30_000 + ok_ui_gross_weekly_earnings: 600 + households: + household: + members: [person1] + state_code: OK + output: + people: + person1: + ok_ui_weekly_benefit_rate: 400 + # Earnings $600 > $100 -> earnings_offset = $600 - $100 = $500. + # Raw payable = $400 - $500 = -$100; max(0, -$100) = $0. + ok_ui_weekly_payable: 0 diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui.py new file mode 100644 index 00000000000..aa008c6e789 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui.py @@ -0,0 +1,36 @@ +from policyengine_us.model_api import * + + +class ok_ui(Variable): + """Annual Oklahoma Unemployment Insurance benefit. Implements the + monetary eligibility tests (§ 2-207), weekly benefit rate (§ 2-104), + partial benefit subtraction (§ 2-105), and benefit duration cap + (§ 2-106 / § 1-231). + + Not modeled: § 1-202.1 / § 1-202.2 alternative and extended base + periods; § 2-104(B) max-WBA percentage derivation by fund condition + (only the resulting maximum dollar amount is parameterized); § 1-231(A) + claim-volume duration escalation to 20 or 26 weeks; § 2-107 portion- + of-a-week proration; § 2-108 approved training waiver; § 2-202 / + § 2-205.1 able-available-seeking-work; § 2-206 one-week waiting period; + § 2-208 alien-status rules; § 2-109 10x WBA requalification; all + § 2-404 through § 2-422 disqualifications. + """ + + value_type = float + entity = Person + label = "Oklahoma unemployment insurance" + unit = USD + definition_period = YEAR + defined_for = "ok_ui_monetarily_eligible" + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51", + ) + + def formula(person, period, parameters): + weekly_payable = person("ok_ui_weekly_payable", period) + maximum_benefit_amount = person("ok_ui_maximum_benefit_amount", period) + weeks_unemployed = person("weeks_unemployed", period) + annual_benefit = weekly_payable * weeks_unemployed + return min_(annual_benefit, maximum_benefit_amount) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_taxable_wages.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_taxable_wages.py new file mode 100644 index 00000000000..3529d41dc1c --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_taxable_wages.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ok_ui_base_period_taxable_wages(Variable): + """Sum of taxable wages (capped at the Oklahoma taxable wage base per + quarter) across all four quarters of the base period, per 40 O.S. § 1-223 + and § 1-201(4). Used in the monetary-eligibility tests in § 2-207(A) and + § 2-207(B). PolicyEngine cannot derive quarterly wages from annual data, + so this is a direct input rather than a computed value; populate via test + fixtures or reform. + """ + + value_type = float + entity = Person + label = "Oklahoma UI base period taxable wages" + unit = USD + definition_period = YEAR + default_value = 0 + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=20", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=44", + ) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_total_wages.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_total_wages.py new file mode 100644 index 00000000000..76554a296bd --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_base_period_total_wages.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class ok_ui_base_period_total_wages(Variable): + """Sum of total (uncapped) gross wages across all four quarters of the + base period, per 40 O.S. § 1-218 (wages definition), § 1-201(4) (base + period definition), and § 2-207 (where "total wages" is used). Used in + the monetary-eligibility tests in § 2-207(A) and § 2-207(B). PolicyEngine + cannot derive quarterly wages from annual data, so this is a direct input + rather than a computed value; populate via test fixtures or reform. + """ + + value_type = float + entity = Person + label = "Oklahoma UI base period total wages" + unit = USD + definition_period = YEAR + default_value = 0 + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=20", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=42", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56", + ) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_gross_weekly_earnings.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_gross_weekly_earnings.py new file mode 100644 index 00000000000..748f9479071 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_gross_weekly_earnings.py @@ -0,0 +1,20 @@ +from policyengine_us.model_api import * + + +class ok_ui_gross_weekly_earnings(Variable): + """Gross earnings during a week of partial unemployment, used to compute + the partial weekly benefit reduction per 40 O.S. § 2-105. Stored at the + annual definition period to match other UI inputs; populate via test + fixtures or reform. + """ + + value_type = float + entity = Person + label = "Oklahoma UI gross weekly earnings" + unit = USD + definition_period = YEAR + default_value = 0 + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50", + ) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_high_quarter_taxable_wages.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_high_quarter_taxable_wages.py new file mode 100644 index 00000000000..86e26658d8e --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_high_quarter_taxable_wages.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ok_ui_high_quarter_taxable_wages(Variable): + """Wages paid in the claimant's highest base-period quarter, capped at the + Oklahoma taxable wage base per quarter. Used as the input to the weekly + benefit amount formula per 40 O.S. § 2-104(A). PolicyEngine cannot derive + quarterly wages from annual data, so this is a direct input rather than a + computed value; populate via test fixtures or reform. + """ + + value_type = float + entity = Person + label = "Oklahoma UI high quarter taxable wages" + unit = USD + definition_period = YEAR + default_value = 0 + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=44", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=49", + ) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.py new file mode 100644 index 00000000000..e9e238918ca --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_maximum_benefit_amount.py @@ -0,0 +1,26 @@ +from policyengine_us.model_api import * + + +class ok_ui_maximum_benefit_amount(Variable): + value_type = float + entity = Person + label = "Oklahoma UI maximum benefit amount" + unit = USD + definition_period = YEAR + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=48", + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=51", + ) + + def formula(person, period, parameters): + # § 2-106 caps benefits in a benefit year at the lesser of the + # duration cap, the statewide maximum benefit amount, and the + # applicable share of base-period wages. + p = parameters(period).gov.states.ok.oesc.unemployment_insurance.mba + weekly_benefit_rate = person("ok_ui_weekly_benefit_rate", period) + base_period_total_wages = person("ok_ui_base_period_total_wages", period) + return min_( + min_(weekly_benefit_rate * p.max_weeks, p.max_amount), + base_period_total_wages * p.base_period_wages_share, + ) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.py new file mode 100644 index 00000000000..c4e30b7ce6f --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_alternate_wages_test.py @@ -0,0 +1,22 @@ +from policyengine_us.model_api import * + + +class ok_ui_meets_alternate_wages_test(Variable): + value_type = bool + entity = Person + label = "Meets the Oklahoma UI alternate monetary eligibility test" + definition_period = YEAR + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56", + ) + + def formula(person, period, parameters): + base_period_taxable_wages = person("ok_ui_base_period_taxable_wages", period) + base_period_total_wages = person("ok_ui_base_period_total_wages", period) + taxable_wage_base = parameters( + period + ).gov.states.ok.tax.payroll.unemployment.taxable_wage_base + has_taxable_wages = base_period_taxable_wages > 0 + meets_wage_base = base_period_total_wages >= taxable_wage_base + return has_taxable_wages & meets_wage_base diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.py new file mode 100644 index 00000000000..74104cad394 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_meets_high_quarter_test.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ok_ui_meets_high_quarter_test(Variable): + value_type = bool + entity = Person + label = "Meets the Oklahoma UI high-quarter monetary eligibility test" + definition_period = YEAR + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.ok.oesc.unemployment_insurance.eligibility + base_period_taxable_wages = person("ok_ui_base_period_taxable_wages", period) + base_period_total_wages = person("ok_ui_base_period_total_wages", period) + high_quarter_taxable_wages = person("ok_ui_high_quarter_taxable_wages", period) + meets_taxable_minimum = base_period_taxable_wages >= p.min_taxable_wages + meets_multiplier = base_period_total_wages >= ( + p.min_total_wages_multiplier * high_quarter_taxable_wages + ) + return meets_taxable_minimum & meets_multiplier diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.py new file mode 100644 index 00000000000..0e931a3566f --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_monetarily_eligible.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class ok_ui_monetarily_eligible(Variable): + value_type = bool + entity = Person + label = "Monetarily eligible for Oklahoma Unemployment Insurance" + definition_period = YEAR + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=56", + ) + + def formula(person, period, parameters): + high_quarter = person("ok_ui_meets_high_quarter_test", period) + alternate = person("ok_ui_meets_alternate_wages_test", period) + return high_quarter | alternate diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.py new file mode 100644 index 00000000000..5e209ca17da --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_benefit_rate.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ok_ui_weekly_benefit_rate(Variable): + value_type = float + entity = Person + label = "Oklahoma UI weekly benefit rate" + unit = USD + definition_period = YEAR + defined_for = StateCode.OK + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=49", + ) + + def formula(person, period, parameters): + # § 2-104(A): WBA = floor(high quarter taxable wages / divisor), + # clamped to the statutory minimum and the annual maximum set under + # § 2-104(B). § 2-102 specifies that fractional results are rounded + # down to the next lower whole dollar. + p = parameters(period).gov.states.ok.oesc.unemployment_insurance.wba + high_quarter_taxable_wages = person("ok_ui_high_quarter_taxable_wages", period) + raw_weekly_benefit_rate = np.floor(high_quarter_taxable_wages / p.divisor) + return min_(max_(raw_weekly_benefit_rate, p.min_amount), p.max_amount) diff --git a/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.py b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.py new file mode 100644 index 00000000000..1763d12ef47 --- /dev/null +++ b/policyengine_us/variables/gov/states/ok/oesc/unemployment_insurance/ok_ui_weekly_payable.py @@ -0,0 +1,23 @@ +from policyengine_us.model_api import * + + +class ok_ui_weekly_payable(Variable): + value_type = float + entity = Person + label = "Oklahoma UI weekly payable amount" + unit = USD + definition_period = YEAR + defined_for = "ok_ui_monetarily_eligible" + reference = ( + "https://www.oklegislature.gov/OK_Statutes/CompleteTitles/os40.pdf#page=50", + ) + + def formula(person, period, parameters): + # § 2-105: weekly payable amount = WBR minus the portion of weekly + # earnings that exceeds the statutory earnings disregard, floored at + # zero. + p = parameters(period).gov.states.ok.oesc.unemployment_insurance.partial + weekly_benefit_rate = person("ok_ui_weekly_benefit_rate", period) + gross_weekly_earnings = person("ok_ui_gross_weekly_earnings", period) + earnings_reduction = max_(gross_weekly_earnings - p.disregard, 0) + return max_(weekly_benefit_rate - earnings_reduction, 0) diff --git a/policyengine_us/variables/gov/states/unemployment_compensation.py b/policyengine_us/variables/gov/states/unemployment_compensation.py index 0857864ab17..2bdaeeac571 100644 --- a/policyengine_us/variables/gov/states/unemployment_compensation.py +++ b/policyengine_us/variables/gov/states/unemployment_compensation.py @@ -9,3 +9,4 @@ class unemployment_compensation(Variable): documentation = "Income from unemployment compensation programs." definition_period = YEAR uprating = "calibration.gov.irs.soi.unemployment_compensation" + adds = ["ok_ui"]