From dad1716a976a91b904ef6a2e9b1ec043ef6d75fe Mon Sep 17 00:00:00 2001
From: Bhoomi Vaishnani
Date: Tue, 11 Feb 2020 10:11:30 -0500
Subject: [PATCH] IMP `l10n_us_hr_payroll` Port `l10n_us_il_hr_payroll` IL
Illinois including migration
---
l10n_us_hr_payroll/__manifest__.py | 1 +
l10n_us_hr_payroll/data/state/il_illinois.xml | 117 ++++++++++++++++++
l10n_us_hr_payroll/models/hr_payslip.py | 2 +
.../models/state/il_illinois.py | 35 ++++++
.../models/us_payroll_config.py | 3 +
l10n_us_hr_payroll/tests/__init__.py | 3 +
.../tests/test_us_il_illinois_payslip_2019.py | 71 +++++++++++
.../tests/test_us_il_illinois_payslip_2020.py | 36 ++++++
.../views/us_payroll_config_views.xml | 6 +
9 files changed, 274 insertions(+)
create mode 100644 l10n_us_hr_payroll/data/state/il_illinois.xml
create mode 100644 l10n_us_hr_payroll/models/state/il_illinois.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2019.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2020.py
diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py
index 0be1d505..7a007cc4 100644
--- a/l10n_us_hr_payroll/__manifest__.py
+++ b/l10n_us_hr_payroll/__manifest__.py
@@ -28,6 +28,7 @@ United States of America - Payroll Rules.
'data/state/ar_arkansas.xml',
'data/state/fl_florida.xml',
'data/state/ga_georgia.xml',
+ 'data/state/il_illinois.xml',
'data/state/mi_michigan.xml',
'data/state/mn_minnesota.xml',
'data/state/mo_missouri.xml',
diff --git a/l10n_us_hr_payroll/data/state/il_illinois.xml b/l10n_us_hr_payroll/data/state/il_illinois.xml
new file mode 100644
index 00000000..7fe9108e
--- /dev/null
+++ b/l10n_us_hr_payroll/data/state/il_illinois.xml
@@ -0,0 +1,117 @@
+
+
+
+
+ US IL Illinois SUTA Wage Base
+ us_il_suta_wage_base
+
+
+
+
+ 12960.0
+
+
+
+
+ 12740.0
+
+
+
+
+
+
+
+ US IL Illinois SUTA Rate
+ us_il_suta_rate
+
+
+
+
+ 3.175
+
+
+
+
+ 3.130
+
+
+
+
+
+
+ US IL Illinois Basic Allowances Rate
+ us_il_sit_basic_allowances_rate
+
+
+
+
+ 2275.0
+
+
+
+
+ 2325.0
+
+
+
+
+
+
+ US IL Illinois Additional Allowances Rate
+ us_il_sit_additional_allowances_rate
+
+
+
+
+ 1000.0
+
+
+
+
+ 1000.0
+
+
+
+
+
+
+
+ US Illinois - Department of Economic Security (IDES) - Unemployment Tax
+
+
+
+ US Illinois - Department of Revenue (IDOR) - Income Tax
+
+
+
+
+
+
+
+
+
+ ER: US IL Illinois State Unemployment
+ ER_US_IL_SUTA
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_il_suta_wage_base', rate='us_il_suta_rate', state_code='IL')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_il_suta_wage_base', rate='us_il_suta_rate', state_code='IL')
+
+
+
+
+
+
+
+
+ EE: US IL Illinois State Income Tax Withholding
+ EE_US_IL_SIT
+ python
+ result, _ = il_illinois_state_income_withholding(payslip, categories, worked_days, inputs)
+ code
+ result, result_rate = il_illinois_state_income_withholding(payslip, categories, worked_days, inputs)
+
+
+
+
+
\ No newline at end of file
diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py
index 1a24442c..8de8bfe9 100644
--- a/l10n_us_hr_payroll/models/hr_payslip.py
+++ b/l10n_us_hr_payroll/models/hr_payslip.py
@@ -14,6 +14,7 @@ from .state.general import general_state_unemployment, \
is_us_state
from .state.ar_arkansas import ar_arkansas_state_income_withholding
from .state.ga_georgia import ga_georgia_state_income_withholding
+from .state.il_illinois import il_illinois_state_income_withholding
from .state.mi_michigan import mi_michigan_state_income_withholding
from .state.mn_minnesota import mn_minnesota_state_income_withholding
from .state.mo_missouri import mo_missouri_state_income_withholding
@@ -58,6 +59,7 @@ class HRPayslip(models.Model):
'is_us_state': is_us_state,
'ar_arkansas_state_income_withholding': ar_arkansas_state_income_withholding,
'ga_georgia_state_income_withholding': ga_georgia_state_income_withholding,
+ 'il_illinois_state_income_withholding': il_illinois_state_income_withholding,
'mi_michigan_state_income_withholding': mi_michigan_state_income_withholding,
'mn_minnesota_state_income_withholding': mn_minnesota_state_income_withholding,
'mo_missouri_state_income_withholding': mo_missouri_state_income_withholding,
diff --git a/l10n_us_hr_payroll/models/state/il_illinois.py b/l10n_us_hr_payroll/models/state/il_illinois.py
new file mode 100644
index 00000000..6c8919c4
--- /dev/null
+++ b/l10n_us_hr_payroll/models/state/il_illinois.py
@@ -0,0 +1,35 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .general import _state_applies, sit_wage
+
+
+def il_illinois_state_income_withholding(payslip, categories, worked_days, inputs):
+ """
+ Returns SIT eligible wage and rate.
+ WAGE = GROSS + DED_FIT_EXEMPT
+
+ :return: result, result_rate (wage, percent)
+ """
+ state_code = 'IL'
+ 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
+
+ pay_periods = payslip.dict.get_pay_periods_in_year()
+ additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
+ basic_allowances_rate = payslip.rule_parameter('us_il_sit_basic_allowances_rate')
+ additional_allowances_rate = payslip.rule_parameter('us_il_sit_additional_allowances_rate')
+ basic_allowances = payslip.contract_id.us_payroll_config_value('il_w4_sit_basic_allowances')
+ additional_allowances = payslip.contract_id.us_payroll_config_value('il_w4_sit_additional_allowances')
+
+ rate = 4.95 / 100.0
+ withholding = rate * (wage - (((basic_allowances * basic_allowances_rate) + (additional_allowances *
+ additional_allowances_rate)) / pay_periods))
+ if withholding < 0.0:
+ withholding = 0.0
+ 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 06a18b6e..6edfd76d 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -66,6 +66,9 @@ class HRContractUSPayrollConfig(models.Model):
ga_g4_sit_additional_allowances = fields.Integer(string='Georgia G-4 Additional Allowances',
help='G-4 5.')
+ il_w4_sit_basic_allowances = fields.Integer(string='Illinois IL-W-4 Number of Basic Allowances', help='IL-W-4 Step 1.')
+ il_w4_sit_additional_allowances = fields.Integer(string='Illinois IL-W-4 Number of Additional Allowances', help='IL-W-4 Step 2.')
+
mi_w4_sit_exemptions = fields.Integer(string='Michigan MI W-4 Exemptions', help='MI-W4 6.')
mn_w4mn_sit_filing_status = fields.Selection([
diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py
index 83e839d9..56d2a837 100755
--- a/l10n_us_hr_payroll/tests/__init__.py
+++ b/l10n_us_hr_payroll/tests/__init__.py
@@ -13,6 +13,9 @@ from . import test_us_fl_florida_payslip_2020
from . import test_us_ga_georgia_payslip_2019
from . import test_us_ga_georgia_payslip_2020
+from . import test_us_il_illinois_payslip_2019
+from . import test_us_il_illinois_payslip_2020
+
from . import test_us_mi_michigan_payslip_2019
from . import test_us_mi_michigan_payslip_2020
diff --git a/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2019.py
new file mode 100644
index 00000000..ba633607
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2019.py
@@ -0,0 +1,71 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .common import TestUsPayslip, process_payslip
+
+
+class TestUsILPayslip(TestUsPayslip):
+ # TAXES AND RATES
+ IL_UNEMP_MAX_WAGE = 12960.00
+ IL_UNEMP = -(3.175 / 100.0)
+
+ def test_taxes_monthly(self):
+ salary = 15000.00
+ schedule_pay = 'monthly'
+ basic_allowances = 1
+ additional_allowances = 1
+ flat_rate = (4.95 / 100)
+ wh_to_test = -(flat_rate * (salary - ((basic_allowances * 2275 + additional_allowances * 1000) / 12.0)))
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('IL'),
+ state_income_tax_additional_withholding=0.0,
+ il_w4_sit_basic_allowances=1.0,
+ il_w4_sit_additional_allowances=1.0,
+ schedule_pay='monthly')
+
+ self._log('2019 Illinois tax first payslip monthly:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], self.IL_UNEMP_MAX_WAGE * self.IL_UNEMP)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh_to_test)
+
+ process_payslip(payslip)
+
+ remaining_IL_UNEMP_wages = 0.0 # We already reached max unemployment wages.
+
+ self._log('2019 Illinois tax second payslip monthly:')
+ payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_IL_UNEMP_wages * self.IL_UNEMP)
+
+ def test_taxes_with_additional_wh(self):
+ salary = 15000.00
+ schedule_pay = 'monthly'
+ basic_allowances = 1
+ additional_allowances = 1
+ additional_wh = 15.0
+ flat_rate = (4.95 / 100)
+ wh_to_test = -(flat_rate * (salary - ((basic_allowances * 2275 + additional_allowances * 1000) / 12.0)) + additional_wh)
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('IL'),
+ state_income_tax_additional_withholding=15.0,
+ il_w4_sit_basic_allowances=1.0,
+ il_w4_sit_additional_allowances=1.0,
+ schedule_pay='monthly')
+
+ self._log('2019 Illinois tax first payslip monthly:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], self.IL_UNEMP_MAX_WAGE * self.IL_UNEMP)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh_to_test)
diff --git a/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2020.py
new file mode 100644
index 00000000..244c383c
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_il_illinois_payslip_2020.py
@@ -0,0 +1,36 @@
+# 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 TestUsILPayslip(TestUsPayslip):
+ # Taxes and Rates
+ MI_UNEMP_MAX_WAGE = 12740.0
+ MI_UNEMP = 3.130
+
+ def _test_sit(self, wage, additional_withholding, basic_allowances, additional_allowances, schedule_pay, date_start, expected_withholding):
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('IL'),
+ state_income_tax_additional_withholding=additional_withholding,
+ il_w4_sit_basic_allowances=basic_allowances,
+ il_w4_sit_additional_allowances=additional_allowances,
+ 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('IL', self.MI_UNEMP, date(2020, 1, 1), wage_base=self.MI_UNEMP_MAX_WAGE)
+ self._test_sit(800.0, 0.0, 2, 2, 'weekly', date(2020, 1, 1), 33.27)
+ self._test_sit(800.0, 10.0, 2, 2, 'weekly', date(2020, 1, 1), 43.27)
+ self._test_sit(2500.0, 0.0, 1, 1, 'monthly', date(2020, 1, 1), 110.04)
+ self._test_sit(2500.0, 0.0, 0, 0, 'monthly', date(2020, 1, 1), 123.75)
+ self._test_sit(3000.0, 15.0, 0, 0, 'quarterly', date(2020, 1, 1), 163.50)
+
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 33eb7323..143d6d5a 100644
--- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml
+++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
@@ -61,6 +61,12 @@
+
+ Form IL-W-4 - State Income Tax
+
+
+
+
Form MI-W4 - State Income Tax