From f9a7107740a874aa35def75917e4ea44d1a35b01 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 28 May 2020 10:26:14 -0400 Subject: [PATCH] [IMP] l10n_us_hr_payroll: For Wisconsin 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/wi_wisconsin.xml | 100 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/wi_wisconsin.py | 47 ++++++++ .../models/us_payroll_config.py | 6 ++ l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_wi_wisconsin_payslip_2020.py | 37 +++++++ .../views/us_payroll_config_views.xml | 7 ++ 8 files changed, 202 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/wi_wisconsin.xml create mode 100644 l10n_us_hr_payroll/models/state/wi_wisconsin.py create mode 100755 l10n_us_hr_payroll/tests/test_us_wi_wisconsin_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 2bfe77fc..a9420613 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -68,6 +68,7 @@ United States of America - Payroll Rules. 'data/state/vt_vermont.xml', 'data/state/va_virginia.xml', 'data/state/wa_washington.xml', + 'data/state/wi_wisconsin.xml', 'data/state/wy_wyoming.xml', 'views/hr_contract_views.xml', 'views/us_payroll_config_views.xml', diff --git a/l10n_us_hr_payroll/data/state/wi_wisconsin.xml b/l10n_us_hr_payroll/data/state/wi_wisconsin.xml new file mode 100644 index 00000000..baff6b3a --- /dev/null +++ b/l10n_us_hr_payroll/data/state/wi_wisconsin.xml @@ -0,0 +1,100 @@ + + + + + US WI Wisconsin SUTA Wage Base + us_wi_suta_wage_base + + + + + 14000.00 + + + + + + + + US WI Wisconsin SUTA Rate + us_wi_suta_rate + + + + + 3.05 + + + + + + + US WI Wisconsin Exemption Rate + us_wi_sit_exemption_rate + + + + + 22 + + + + + + + US WI Wisconsin SIT Tax Rate + us_wi_sit_tax_rate + + + + + { + 'single': ((5730, 0.0000, 0.0), (15200, 4.0000, 0.0), (16486, 4.4800, 378.80), (26227, 6.5408, 436.41), (62950, 7.0224, 1073.55), (240190, 6.2700, 3652.39), ('inf', 7.6500, 14765.34)), + 'married': ((7870, 0.0000, 0.0), (18780, 4.0000, 0.0), (21400, 5.8400, 436.40), (28308, 7.0080, 589.41), (60750, 7.5240, 1073.52), (240190, 6.2700, 3514.46), ('inf', 7.6500, 14765.35)), + } + + + + + + + + US Wisconsin - Department of Workforce Development - Unemployment Tax + + + + US Wisconsin - Department of Revenue - Income Tax + + + + + + + + + + ER: US WI Wisconsin State Unemployment + ER_US_WI_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wi_suta_wage_base', rate='us_wi_suta_rate', state_code='WI') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wi_suta_wage_base', rate='us_wi_suta_rate', state_code='WI') + + + + + + + + + EE: US WI Wisconsin State Income Tax Withholding + EE_US_WI_SIT + python + result, _ = wi_wisconsin_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = wi_wisconsin_state_income_withholding(payslip, categories, worked_days, inputs) + + + + + diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py index e8f10cd0..2eff7feb 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -48,6 +48,7 @@ from .state.vt_vermont import vt_vermont_state_income_withholding from .state.va_virginia import va_virginia_state_income_withholding from .state.wa_washington import wa_washington_fml_er, \ wa_washington_fml_ee +from .state.wi_wisconsin import wi_wisconsin_state_income_withholding class HRPayslip(models.Model): @@ -115,6 +116,7 @@ class HRPayslip(models.Model): 'va_virginia_state_income_withholding': va_virginia_state_income_withholding, 'wa_washington_fml_er': wa_washington_fml_er, 'wa_washington_fml_ee': wa_washington_fml_ee, + 'wi_wisconsin_state_income_withholding': wi_wisconsin_state_income_withholding, }) return res diff --git a/l10n_us_hr_payroll/models/state/wi_wisconsin.py b/l10n_us_hr_payroll/models/state/wi_wisconsin.py new file mode 100644 index 00000000..c1d53bbb --- /dev/null +++ b/l10n_us_hr_payroll/models/state/wi_wisconsin.py @@ -0,0 +1,47 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def wi_wisconsin_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'WI' + if not _state_applies(payslip, state_code): + return 0.0, 0.0 + + # Determine Wage + wage = sit_wage(payslip, categories) + if not wage: + return 0.0, 0.0 + + if payslip.contract_id.us_payroll_config_value('state_income_tax_exempt'): + return 0.0, 0.0 + + filing_status = payslip.contract_id.us_payroll_config_value('wi_wt4_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + pay_periods = payslip.dict.get_pay_periods_in_year() + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + exemptions = payslip.contract_id.us_payroll_config_value('wi_wt4_sit_exemptions') + exemption_amt = payslip.rule_parameter('us_wi_sit_exemption_rate') + tax_table = payslip.rule_parameter('us_wi_sit_tax_rate')[filing_status] + + taxable_income = wage * pay_periods + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, rate, flat_fee = row + if taxable_income <= float(amt): + withholding = (((taxable_income - last) * (rate / 100)) + flat_fee) - (exemptions * exemption_amt) + break + last = amt + + withholding = max(withholding, 0.0) + withholding /= pay_periods + withholding += additional + return wage, -((withholding / wage) * 100.0) diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 12f6177e..edb813b9 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -261,3 +261,9 @@ class HRContractUSPayrollConfig(models.Model): help='VA-4(P) 1(a)') va_va4_sit_other_exemptions = fields.Integer(string='Virginia VA-4(P) Age & Blindness Exemptions', help='VA-4(P) 1(b)') + + wi_wt4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ], string='Wisconsin WT-4 Filing Status', help='WI WT-4') + wi_wt4_sit_exemptions = fields.Integer(string='Wisconsin Exemptions', help='WI WT-4 1.(d)') \ No newline at end of file diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index a7957e5e..d75e6da7 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -117,5 +117,7 @@ from . import test_us_va_virginia_payslip_2020 from . import test_us_wa_washington_payslip_2019 from . import test_us_wa_washington_payslip_2020 +from . import test_us_wi_wisconsin_payslip_2020 + from . import test_us_wy_wyoming_payslip_2019 from . import test_us_wy_wyoming_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_wi_wisconsin_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_wi_wisconsin_payslip_2020.py new file mode 100755 index 00000000..8241e4c1 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_wi_wisconsin_payslip_2020.py @@ -0,0 +1,37 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date, timedelta +from .common import TestUsPayslip + + +class TestUsWIPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + WI_UNEMP_MAX_WAGE = 14000.0 + WI_UNEMP = 3.05 + # Calculation based on example https://www.revenue.wi.gov/DOR%20Publications/pb166.pdf + + def _test_sit(self, wage, filing_status, exemption, additional_withholding, exempt, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('WI'), + wi_wt4_sit_filing_status=filing_status, + wi_wt4_sit_exemptions=exemption, + state_income_tax_additional_withholding=additional_withholding, + state_income_tax_exempt=exempt, + schedule_pay=schedule_pay) + payslip = self._createPayslip(employee, date_start, date_start + timedelta(days=7)) + payslip.compute_sheet() + cats = self._getCategories(payslip) + + self._log('Computed period tax: ' + str(expected_withholding)) + self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + + def test_2020_taxes_example(self): + self._test_er_suta('WI', self.WI_UNEMP, date(2020, 1, 1), wage_base=self.WI_UNEMP_MAX_WAGE) + self._test_sit(300, 'single', 1, 0, False,'weekly', date(2020, 1, 1), 7.21) + self._test_sit(700, 'married', 3, 0, False, 'bi-weekly', date(2020, 1, 1), 13.35) + self._test_sit(1300, 'single', 1, 10, True, 'bi-weekly', date(2020, 1, 1), 0.00) + self._test_sit(700, 'married', 3, 10, False, 'bi-weekly', date(2020, 1, 1), 23.35) diff --git a/l10n_us_hr_payroll/views/us_payroll_config_views.xml b/l10n_us_hr_payroll/views/us_payroll_config_views.xml index ca572a0c..9312360d 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -274,6 +274,13 @@

No additional fields.

Ensure that your Employee and Employer workers' comp code fields are filled in for WA LNI withholding.

+ +

Form WT-4 - State Income Tax

+ + + + +

No additional fields.