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.