diff --git a/changelog.d/issue-8136-wa-pfml.added.md b/changelog.d/issue-8136-wa-pfml.added.md new file mode 100644 index 00000000000..bee359f9567 --- /dev/null +++ b/changelog.d/issue-8136-wa-pfml.added.md @@ -0,0 +1 @@ +Add a Washington Paid Family and Medical Leave eligibility and maximum benefit calculator. diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml new file mode 100644 index 00000000000..fe7adca840d --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits combined family and medical leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 16 + +metadata: + unit: week + period: year + label: Washington PFML combined leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(c) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml new file mode 100644 index 00000000000..775f8858b3b --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/combined_max_weeks_with_pregnancy_incapacity.yaml @@ -0,0 +1,12 @@ +description: Washington limits combined family and medical leave to this number of weeks when a serious health condition with pregnancy results in incapacity under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 18 + +metadata: + unit: week + period: year + label: Washington PFML combined leave maximum weeks with pregnancy incapacity + reference: + - title: RCW 50A.15.020(3)(c) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml new file mode 100644 index 00000000000..8398c594937 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/family_leave_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits family leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 12 + +metadata: + unit: week + period: year + label: Washington PFML family leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml new file mode 100644 index 00000000000..9e9ee1d6416 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks.yaml @@ -0,0 +1,12 @@ +description: Washington limits medical leave to this number of weeks under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 12 + +metadata: + unit: week + period: year + label: Washington PFML medical leave maximum weeks + reference: + - title: RCW 50A.15.020(3)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml new file mode 100644 index 00000000000..84e76298b05 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/duration/medical_leave_weeks_with_pregnancy_incapacity.yaml @@ -0,0 +1,12 @@ +description: Washington limits medical leave to this number of weeks when a serious health condition with pregnancy results in incapacity under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 14 + +metadata: + unit: week + period: year + label: Washington PFML medical leave maximum weeks with pregnancy incapacity + reference: + - title: RCW 50A.15.020(3)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml b/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml new file mode 100644 index 00000000000..7a410479653 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/hours_threshold.yaml @@ -0,0 +1,12 @@ +description: Washington requires this many hours worked in the qualifying period for eligibility under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 820 + +metadata: + unit: hour + period: year + label: Washington PFML qualifying hours threshold + reference: + - title: RCW 50A.15.010 Employee eligibility + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml b/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml new file mode 100644 index 00000000000..e7cba1a2119 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/lower_benefit_rate.yaml @@ -0,0 +1,12 @@ +description: Washington replaces this share of the employee's average weekly wage below the benefit tier threshold under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.9 + +metadata: + unit: /1 + period: year + label: Washington PFML lower tier benefit rate + reference: + - title: RCW 50A.15.020(5)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml b/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml new file mode 100644 index 00000000000..3bf2c63f90d --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/lower_threshold_fraction.yaml @@ -0,0 +1,12 @@ +description: Washington uses this share of the state average weekly wage as the breakpoint between benefit tiers under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: Washington PFML lower benefit tier threshold fraction + reference: + - title: RCW 50A.15.020(5) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml b/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..a27d50e6e28 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/max_weekly_benefit_amount.yaml @@ -0,0 +1,20 @@ +description: Washington limits the weekly benefit to this amount under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 1_000 + 2021-01-01: 1_206 + 2022-01-01: 1_327 + 2023-01-01: 1_427 + 2024-01-01: 1_456 + 2025-01-01: 1_542 + 2026-01-01: 1_647 + +metadata: + unit: currency-USD + period: week + label: Washington PFML maximum weekly benefit amount + reference: + - title: RCW 50A.15.020(6)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 + - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert + href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf diff --git a/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml b/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..3971b2b39c1 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/min_weekly_benefit_amount.yaml @@ -0,0 +1,12 @@ +description: Washington sets the minimum weekly benefit to this amount under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 100 + +metadata: + unit: currency-USD + period: week + label: Washington PFML minimum weekly benefit amount + reference: + - title: RCW 50A.15.020(6)(b) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml b/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml new file mode 100644 index 00000000000..b6235e0fe30 --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/state_average_weekly_wage.yaml @@ -0,0 +1,22 @@ +description: Washington uses this state average weekly wage to determine weekly benefits under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 1_111 + 2021-01-01: 1_340 + 2022-01-01: 1_474 + 2023-01-01: 1_586 + 2024-01-01: 1_618 + 2025-01-01: 1_714 + 2026-01-01: 1_830 + +metadata: + unit: currency-USD + period: week + label: Washington PFML state average weekly wage + reference: + - title: RCW 50A.05.010(26) State average weekly wage + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010 + - title: RCW 50A.15.020(6)(a) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 + - title: Washington Paid Family and Medical Leave 2026 Paycheck Insert + href: https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf diff --git a/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml b/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml new file mode 100644 index 00000000000..42de004e4ff --- /dev/null +++ b/policyengine_us/parameters/gov/states/wa/pfml/upper_benefit_rate.yaml @@ -0,0 +1,12 @@ +description: Washington replaces this share of the employee's average weekly wage above the benefit tier threshold under the Paid Family and Medical Leave program. + +values: + 2020-01-01: 0.5 + +metadata: + unit: /1 + period: year + label: Washington PFML upper tier benefit rate + reference: + - title: RCW 50A.15.020(5)(b)(ii) Benefit—Amount and duration + href: https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml new file mode 100644 index 00000000000..09febab4c17 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml.yaml @@ -0,0 +1,114 @@ +- name: Case 1, eligible worker with combined leave facts gets the maximum annual benefit. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: COMBINED + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_eligible: true + wa_pfml_weekly_benefit_amount: 866 + wa_pfml_max_leave_weeks: 16 + wa_pfml: 13_856 + +- name: Case 2, no leave type selected produces no maximum benefit estimate. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_eligible: true + wa_pfml_max_leave_weeks: 0 + wa_pfml: 0 + +- name: Case 3, family leave estimate uses the 12 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: FAMILY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + wa_pfml: 10_392 + +- name: Case 4, medical leave estimate uses the 12 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: MEDICAL + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + wa_pfml: 10_392 + +- name: Case 5, pregnancy-related medical leave estimate uses the 14 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: MEDICAL_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 14 + wa_pfml: 12_124 + +- name: Case 6, combined leave with pregnancy incapacity estimate uses the 18 week cap. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + employment_income: 52_000 + wa_pfml_leave_type: COMBINED_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 18 + wa_pfml: 15_588 + +- name: Case 7, ineligible workers get no leave or benefit estimate. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 15 + employment_income: 52_000 + wa_pfml_leave_type: COMBINED + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_eligible: false + wa_pfml_max_leave_weeks: 0 + wa_pfml: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml new file mode 100644 index 00000000000..8a68b7e9219 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_eligible.yaml @@ -0,0 +1,59 @@ +- name: Case 1, non-Washington worker with sufficient hours is ineligible. + period: 2026 + input: + state_code: CA + weekly_hours_worked: 20 + output: + # Benefit only available to Washington workers (defined_for StateCode.WA). + wa_pfml_eligible: false + +- name: Case 2, part-time Washington worker below the hours threshold is ineligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 15 + output: + # annual_hours = 15 * 52 = 780 hours + # 780 < 820 threshold per RCW 50A.15.010, so ineligible. + wa_pfml_eligible: false + +- name: Case 3, Washington worker just above the hours threshold is eligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 16 + output: + # annual_hours = 16 * 52 = 832 hours + # 832 >= 820 threshold per RCW 50A.15.010, so eligible. + wa_pfml_eligible: true + +- name: Case 4, Washington worker with zero hours is ineligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 0 + output: + # annual_hours = 0 < 820, so ineligible. + wa_pfml_eligible: false + +- name: Case 5, qualifying-period hours override can make a worker eligible. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 0 + wa_pfml_qualifying_period_hours_worked: 900 + output: + # Override replaces the weekly-hours proxy for eligibility. + # 900 >= 820 threshold, so eligible. + wa_pfml_eligible: true + +- name: Case 6, qualifying-period hours override takes precedence over weekly-hours proxy. + period: 2026 + input: + state_code: WA + weekly_hours_worked: 20 + wa_pfml_qualifying_period_hours_worked: 800 + output: + # Override replaces the weekly-hours proxy for eligibility. + # 800 < 820 threshold, so ineligible. + wa_pfml_eligible: false diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml new file mode 100644 index 00000000000..eccb2b21c35 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_max_leave_weeks.yaml @@ -0,0 +1,82 @@ +- name: Case 1, family leave is limited to 12 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: FAMILY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + +- name: Case 2, medical leave is limited to 12 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: MEDICAL + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 12 + +- name: Case 3, combined leave is limited to 16 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: COMBINED + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 16 + +- name: Case 4, pregnancy-related medical leave is limited to 14 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: MEDICAL_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 14 + +- name: Case 5, combined leave with pregnancy incapacity is limited to 18 weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + wa_pfml_leave_type: COMBINED_WITH_PREGNANCY_INCAPACITY + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 18 + +- name: Case 6, no selected leave type returns zero maximum leave weeks. + period: 2026 + input: + people: + person1: + weekly_hours_worked: 20 + households: + household: + members: [person1] + state_code: WA + output: + wa_pfml_max_leave_weeks: 0 diff --git a/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml new file mode 100644 index 00000000000..d3aff64f0e8 --- /dev/null +++ b/policyengine_us/tests/policy/baseline/gov/states/wa/pfml/test_wa_pfml_weekly_benefit_amount.yaml @@ -0,0 +1,128 @@ +- name: Case 1, low earner below the SAWW breakpoint receives 90 percent of AWW. + period: 2026 + input: + state_code: WA + employment_income: 26_000 + output: + # AWW = 26,000 / 52 = 500 + # SAWW 2026 = 1,830; breakpoint H = 0.5 * 1,830 = 915 + # AWW (500) <= H (915), so benefit = 0.90 * 500 = 450 + wa_pfml_weekly_benefit_amount: 450 + +- name: Case 2, AWW exactly at the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_580 + output: + # AWW = 47,580 / 52 = 915 + # AWW (915) <= H (915), so benefit = 0.90 * 915 = 823.50, rounded down to 823 + wa_pfml_weekly_benefit_amount: 823 + +- name: Case 3, AWW above the SAWW breakpoint uses two-tier formula. + period: 2026 + input: + state_code: WA + employment_income: 78_000 + output: + # AWW = 78,000 / 52 = 1,500 + # AWW (1,500) > H (915), so benefit = 0.90 * 915 + 0.50 * (1,500 - 915) + # = 823.50 + 0.50 * 585 + # = 823.50 + 292.50 + # = 1,116 + wa_pfml_weekly_benefit_amount: 1_116 + +- name: Case 4, high earner with benefit capped at the maximum weekly benefit. + period: 2026 + input: + state_code: WA + employment_income: 156_000 + output: + # AWW = 156,000 / 52 = 3,000 + # Raw = 0.90 * 915 + 0.50 * (3,000 - 915) + # = 823.50 + 0.50 * 2,085 + # = 823.50 + 1,042.50 + # = 1,866 + # Max weekly benefit 2026 = 0.90 * 1,830 = 1,647 + # Benefit = min(1,866, 1,647) = 1,647 + wa_pfml_weekly_benefit_amount: 1_647 + +- name: Case 5, AWW below 100 dollars returns full AWW per RCW 50A.15.020(6)(b). + period: 2026 + input: + state_code: WA + employment_income: 4_160 + output: + # AWW = 4,160 / 52 = 80 + # AWW < 100 per RCW 50A.15.020(6)(b), so benefit = AWW = 80 + # (not the 100 minimum; uses employee's full wage) + wa_pfml_weekly_benefit_amount: 80 + +- name: Case 6, zero employment income produces zero benefit. + period: 2026 + input: + state_code: WA + employment_income: 0 + output: + # AWW = 0 / 52 = 0 + # Per RCW 50A.15.020(6)(b), if AWW < 100 the benefit equals AWW; + # with no wages there is no benefit. + wa_pfml_weekly_benefit_amount: 0 + +- name: Case 7, AWW one dollar below the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_528 + output: + # AWW = 47,528 / 52 = 914 + # AWW (914) <= H (915), so benefit = 0.90 * 914 = 822.60, rounded down to 822 + wa_pfml_weekly_benefit_amount: 822 + +- name: Case 8, AWW one dollar above the SAWW breakpoint. + period: 2026 + input: + state_code: WA + employment_income: 47_632 + output: + # AWW = 47,632 / 52 = 916 + # AWW (916) > H (915), so benefit = 0.90 * 915 + 0.50 * (916 - 915) + # = 823.50 + 0.50 + # = 824.00, rounded down to 824 + wa_pfml_weekly_benefit_amount: 824 + +- name: Case 9, AWW exactly at the maximum weekly benefit threshold. + period: 2026 + input: + state_code: WA + employment_income: 133_224 + output: + # AWW = 133,224 / 52 = 2,562 + # Raw = 0.90 * 915 + 0.50 * (2,562 - 915) + # = 823.50 + 0.50 * 1,647 + # = 823.50 + 823.50 + # = 1,647 + # Equal to max weekly benefit (0.90 * 1,830 = 1,647), so benefit = 1,647 + wa_pfml_weekly_benefit_amount: 1_647 + +- name: Case 10, non-integer AWW is rounded down before applying the benefit formula. + period: 2026 + input: + state_code: WA + employment_income: 47_579 + output: + # Raw AWW approximation = 47,579 / 52 = 914.98... + # RCW 50A.05.010(6) rounds AWW down to the next lower dollar, so AWW = 914. + # Benefit = 0.90 * 914 = 822.60, rounded down to 822. + wa_pfml_weekly_benefit_amount: 822 + +- name: Case 11, average weekly wage override replaces the annual-income proxy. + period: 2026 + input: + state_code: WA + employment_income: 78_000 + wa_pfml_average_weekly_wage_override: 800.75 + output: + # Override AWW is rounded down to 800 before applying the formula. + # AWW (800) <= H (915), so benefit = 0.90 * 800 = 720. + wa_pfml_weekly_benefit_amount: 720 diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py new file mode 100644 index 00000000000..7596da1186f --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml.py @@ -0,0 +1,24 @@ +from policyengine_us.model_api import * + + +class wa_pfml(Variable): + value_type = float + entity = Person + label = "Washington PFML maximum annual benefit" + documentation = ( + "Maximum annual Washington Paid Family and Medical Leave benefit for " + "the selected leave type. Computed as the weekly benefit amount " + "multiplied by the maximum eligible leave duration." + ) + unit = USD + definition_period = YEAR + defined_for = "wa_pfml_eligible" + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010", + ) + + def formula(person, period, parameters): + weekly_benefit = person("wa_pfml_weekly_benefit_amount", period) + max_leave_weeks = person("wa_pfml_max_leave_weeks", period) + return weekly_benefit * max_leave_weeks diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py new file mode 100644 index 00000000000..ba99bf46bcb --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class wa_pfml_average_weekly_wage(Variable): + value_type = float + entity = Person + label = "Washington PFML average weekly wage" + documentation = ( + "Employee's average weekly wage for Washington Paid Family and " + "Medical Leave. Simplified as annual employment income divided by " + "the number of weeks in a year and rounded down to the next lower " + "dollar." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + ) + + def formula(person, period, parameters): + override = person("wa_pfml_average_weekly_wage_override", period) + proxy_aww = np.floor(person("employment_income", period) / WEEKS_IN_YEAR) + return where(override >= 0, np.floor(override), proxy_aww) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py new file mode 100644 index 00000000000..52ddc2a0792 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_average_weekly_wage_override.py @@ -0,0 +1,19 @@ +from policyengine_us.model_api import * + + +class wa_pfml_average_weekly_wage_override(Variable): + value_type = float + entity = Person + label = "Washington PFML average weekly wage override" + documentation = ( + "Optional override for Washington PFML average weekly wage. Set to a " + "non-negative dollar amount to replace the annual-income proxy." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + default_value = -1 + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.05.010", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + ) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py new file mode 100644 index 00000000000..4bb0f7dd8e6 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_eligible.py @@ -0,0 +1,25 @@ +from policyengine_us.model_api import * + + +class wa_pfml_eligible(Variable): + value_type = bool + entity = Person + label = "Washington PFML eligible" + documentation = ( + "Eligibility for Washington Paid Family and Medical Leave " + "benefits. Requires working at least the qualifying hours " + "threshold in the qualifying period per RCW 50A.15.010. " + "If no qualifying-period hours override is provided, annual hours " + "worked are approximated as weekly hours worked multiplied by the " + "number of weeks in a year." + ) + definition_period = YEAR + defined_for = StateCode.WA + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010" + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + hours_override = person("wa_pfml_qualifying_period_hours_worked", period) + annual_hours = person("weekly_hours_worked", period) * WEEKS_IN_YEAR + qualifying_hours = where(hours_override >= 0, hours_override, annual_hours) + return qualifying_hours >= p.hours_threshold diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py new file mode 100644 index 00000000000..cee4f9da9e3 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_leave_type.py @@ -0,0 +1,21 @@ +from policyengine_us.model_api import * + + +class WAPFMLLeaveType(Enum): + FAMILY = "Family" + MEDICAL = "Medical" + COMBINED = "Combined" + MEDICAL_WITH_PREGNANCY_INCAPACITY = "Medical with pregnancy incapacity" + COMBINED_WITH_PREGNANCY_INCAPACITY = "Combined with pregnancy incapacity" + NONE = "None" + + +class wa_pfml_leave_type(Variable): + value_type = Enum + entity = Person + label = "Washington PFML selected leave type" + definition_period = YEAR + possible_values = WAPFMLLeaveType + default_value = WAPFMLLeaveType.NONE + defined_for = StateCode.WA + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py new file mode 100644 index 00000000000..d6f1ee934a3 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_max_leave_weeks.py @@ -0,0 +1,40 @@ +from policyengine_us.model_api import * + + +class wa_pfml_max_leave_weeks(Variable): + value_type = float + entity = Person + label = "Washington PFML maximum leave weeks" + documentation = ( + "Maximum Washington Paid Family and Medical Leave duration in weeks " + "for the selected leave type." + ) + unit = "week" + definition_period = YEAR + defined_for = "wa_pfml_eligible" + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + leave_type = person("wa_pfml_leave_type", period) + leave_type_values = leave_type.possible_values + return select( + [ + leave_type == leave_type_values.FAMILY, + leave_type == leave_type_values.MEDICAL, + leave_type == leave_type_values.COMBINED, + leave_type == leave_type_values.MEDICAL_WITH_PREGNANCY_INCAPACITY, + leave_type == leave_type_values.COMBINED_WITH_PREGNANCY_INCAPACITY, + ], + [ + p.duration.family_leave_weeks, + p.duration.medical_leave_weeks, + p.duration.combined_max_weeks, + p.duration.medical_leave_weeks_with_pregnancy_incapacity, + p.duration.combined_max_weeks_with_pregnancy_incapacity, + ], + default=0, + ) diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py new file mode 100644 index 00000000000..e56ea68cca1 --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_qualifying_period_hours_worked.py @@ -0,0 +1,17 @@ +from policyengine_us.model_api import * + + +class wa_pfml_qualifying_period_hours_worked(Variable): + value_type = float + entity = Person + label = "Washington PFML qualifying-period hours worked override" + documentation = ( + "Optional override for hours worked in the Washington PFML " + "qualifying period. Set to a non-negative number of hours to replace " + "the annualized weekly-hours proxy used for eligibility." + ) + unit = "hour" + definition_period = YEAR + defined_for = StateCode.WA + default_value = -1 + reference = "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.010" diff --git a/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py new file mode 100644 index 00000000000..0d0f77be48b --- /dev/null +++ b/policyengine_us/variables/gov/states/wa/pfml/wa_pfml_weekly_benefit_amount.py @@ -0,0 +1,39 @@ +from policyengine_us.model_api import * + + +class wa_pfml_weekly_benefit_amount(Variable): + value_type = float + entity = Person + label = "Washington PFML weekly benefit amount" + documentation = ( + "Weekly benefit amount under Washington Paid Family and Medical " + "Leave. Applies the two-tier replacement formula in " + "RCW 50A.15.020(5), rounds down to the next lower dollar, and clips " + "the result to the statutory minimum and maximum weekly benefit " + "amounts. Despite the YEAR definition period, this variable " + "represents a weekly dollar amount." + ) + unit = USD + definition_period = YEAR + defined_for = StateCode.WA + reference = ( + "https://app.leg.wa.gov/rcw/default.aspx?cite=50A.15.020", + "https://paidleave.wa.gov/app/uploads/2025/12/Paycheck-insert-2026-1.pdf", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.states.wa.pfml + aww = person("wa_pfml_average_weekly_wage", period) + lower_threshold = p.lower_threshold_fraction * p.state_average_weekly_wage + lower_benefit = p.lower_benefit_rate * min_(aww, lower_threshold) + upper_benefit = p.upper_benefit_rate * max_(aww - lower_threshold, 0) + raw_benefit = np.floor(lower_benefit + upper_benefit) + # Per RCW 50A.15.020(6)(b): minimum is $100, or AWW if AWW < $100. + # Using min_(min_amount, aww) as the floor naturally handles zero AWW + # (no employment → floor=0 → benefit=0) and low AWW (floor=AWW). + effective_min = min_(p.min_weekly_benefit_amount, aww) + return clip( + raw_benefit, + effective_min, + p.max_weekly_benefit_amount, + )