diff --git a/changelog.d/overtime-hourly-wage.fixed.md b/changelog.d/overtime-hourly-wage.fixed.md new file mode 100644 index 00000000000..1eadc8c15bb --- /dev/null +++ b/changelog.d/overtime-hourly-wage.fixed.md @@ -0,0 +1 @@ +Use `hourly_wage` when calculating `fsla_overtime_premium` for hourly workers, while keeping the prior earnings-based fallback when no hourly wage is available. diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/exemptions/fsla_overtime_premium.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/exemptions/fsla_overtime_premium.yaml index de9b7264cdd..6cb21ba2a04 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/exemptions/fsla_overtime_premium.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/exemptions/fsla_overtime_premium.yaml @@ -39,3 +39,33 @@ is_computer_scientist: true output: fsla_overtime_premium: 5105.4545 + +- name: Overtime income premium calculation uses hourly wage for hourly workers + period: 2024 + input: + hours_worked_last_week: 50 + employment_income: 100000 + hourly_wage: 20 + is_paid_hourly: true + has_never_worked: false + is_military: false + is_executive_administrative_professional: true + is_farmer_fisher: false + is_computer_scientist: false + output: + fsla_overtime_premium: 5200 + +- name: Overtime income premium falls back when hourly wage is unavailable + period: 2024 + input: + hours_worked_last_week: 50 + employment_income: 30000 + hourly_wage: 0 + is_paid_hourly: true + has_never_worked: false + is_military: false + is_executive_administrative_professional: true + is_farmer_fisher: false + is_computer_scientist: false + output: + fsla_overtime_premium: 2727.2727 diff --git a/policyengine_us/variables/household/income/person/fsla_overtime_premium.py b/policyengine_us/variables/household/income/person/fsla_overtime_premium.py index 915a9d89163..d92ca320d22 100644 --- a/policyengine_us/variables/household/income/person/fsla_overtime_premium.py +++ b/policyengine_us/variables/household/income/person/fsla_overtime_premium.py @@ -12,14 +12,21 @@ class fsla_overtime_premium(Variable): def formula_2014(person, period, parameters): p = parameters(period).gov.irs.income.exemption.overtime worked_hours = person("hours_worked_last_week", period) + is_paid_hourly = person("is_paid_hourly", period) + hourly_wage = person("hourly_wage", period) weekly_overtime_hours = max_(worked_hours - p.hours_threshold, 0) # Straight-time–equivalent hours in the year hour_equivalents = WEEKS_IN_YEAR * ( p.hours_threshold + weekly_overtime_hours * p.rate_multiplier ) - # Implied straight-time hourly wage - base_rate = person("employment_income", period) / hour_equivalents + implied_base_rate = person("employment_income", period) / hour_equivalents + # Hourly workers can use the ORG-backed straight-time rate directly. + base_rate = where( + is_paid_hourly & (hourly_wage > 0), + hourly_wage, + implied_base_rate, + ) # Return only the overtime premium (e.g. the 50 % in time-and-a-half) return ( base_rate * (p.rate_multiplier - 1) * weekly_overtime_hours * WEEKS_IN_YEAR