From 261cc998fd23daa6877035d07c10390919aca758 Mon Sep 17 00:00:00 2001
From: Bhoomi Vaishnani
Date: Thu, 30 Jan 2020 18:20:31 -0500
Subject: [PATCH] IMP `l10n_us_hr_payroll` Port `l10n_us_mn_hr_payroll` MN
Minnesota including migration
---
l10n_us_hr_payroll/__manifest__.py | 1 +
l10n_us_hr_payroll/data/final.xml | 3 +
.../data/state/mn_minnesota.xml | 137 +++++++++++++++
l10n_us_hr_payroll/migrations/data.py | 16 ++
l10n_us_hr_payroll/models/hr_payslip.py | 2 +
.../models/state/mn_minnesota.py | 43 +++++
.../models/us_payroll_config.py | 7 +
l10n_us_hr_payroll/tests/__init__.py | 3 +
.../test_us_mn_minnesota_payslip_2019.py | 159 ++++++++++++++++++
.../test_us_mn_minnesota_payslip_2020.py | 36 ++++
.../views/us_payroll_config_views.xml | 6 +
11 files changed, 413 insertions(+)
create mode 100644 l10n_us_hr_payroll/data/state/mn_minnesota.xml
create mode 100644 l10n_us_hr_payroll/models/state/mn_minnesota.py
create mode 100755 l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2019.py
create mode 100755 l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2020.py
diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py
index 99a4b04e..e6bb1b7e 100755
--- a/l10n_us_hr_payroll/__manifest__.py
+++ b/l10n_us_hr_payroll/__manifest__.py
@@ -31,6 +31,7 @@ USA Payroll Rules.
'data/state/fl_florida.xml',
'data/state/ga_georgia.xml',
'data/state/mi_michigan.xml',
+ 'data/state/mn_minnesota.xml',
'data/state/mo_missouri.xml',
'data/state/ms_mississippi.xml',
'data/state/mt_montana.xml',
diff --git a/l10n_us_hr_payroll/data/final.xml b/l10n_us_hr_payroll/data/final.xml
index ccfa82fe..e18d015e 100644
--- a/l10n_us_hr_payroll/data/final.xml
+++ b/l10n_us_hr_payroll/data/final.xml
@@ -21,6 +21,9 @@
ref('hr_payroll_rule_er_us_ga_suta'),
ref('hr_payroll_rule_ee_us_ga_sit'),
+ ref('hr_payroll_rule_er_us_mn_suta'),
+ ref('hr_payroll_rule_ee_us_mn_sit'),
+
ref('hr_payroll_rule_er_us_mi_suta'),
ref('hr_payroll_rule_ee_us_mi_sit'),
diff --git a/l10n_us_hr_payroll/data/state/mn_minnesota.xml b/l10n_us_hr_payroll/data/state/mn_minnesota.xml
new file mode 100644
index 00000000..d21874cc
--- /dev/null
+++ b/l10n_us_hr_payroll/data/state/mn_minnesota.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+ US MN Minnesota SUTA Wage Base
+ us_mn_suta_wage_base
+ 34000.0
+
+
+
+ US MN Minnesota SUTA Wage Base
+ us_mn_suta_wage_base
+ 35000.0
+
+
+
+
+
+
+
+ US MN Minnesota SUTA Rate
+ us_mn_suta_rate
+ 1.11
+
+
+
+ US MN Minnesota SUTA Rate
+ us_mn_suta_rate
+ 1.11
+
+
+
+
+
+
+ US MN Minnesota SIT Tax Rate
+ us_mn_sit_tax_rate
+ {
+ 'single': [
+ ( 28920, 2400, 5.35, 0.00),
+ ( 89510, 28920, 7.05, 1418.82),
+ (166290, 89510, 7.85, 5690.42),
+ ( 'inf', 166290, 9.85, 11717.65),
+ ],
+ 'married': [
+ ( 47820, 9050, 5.35, 0.00),
+ ( 163070, 47820, 7.05, 2074.20),
+ ( 282200, 163070, 7.85, 10199.33),
+ ( 'inf', 282200, 9.85, 19551.04),
+ ],
+ }
+
+
+
+ US MN Minnesota SIT Tax Rate
+ us_mn_sit_tax_rate
+ {
+ 'single': [
+ ( 30760, 3800, 5.35, 0.00),
+ ( 92350, 30760, 6.80, 1442.36),
+ (168200, 92350, 7.85, 5630.48),
+ ( 'inf', 168200, 9.85, 11584.71),
+ ],
+ 'married': [
+ ( 51310, 11900, 5.35, 0.00),
+ ( 168470, 51310, 6.80, 2108.44),
+ ( 285370, 168470, 7.85, 10075.32),
+ ( 'inf', 285370, 9.85, 19251.97),
+ ],
+ }
+
+
+
+
+
+
+ US MN Minnesota Allowances Rate
+ us_mn_sit_allowances_rate
+ 4250.0
+
+
+
+ US MN Minnesota Allowances Rate
+ us_mn_sit_allowances_rate
+ 4300.0
+
+
+
+
+
+
+ US Minnesota - Unemployment Insurance Agency - Unemployment Tax
+
+
+ US Minnesota - Unemployment Insurance Agency - Unemployment Tax
+
+
+
+
+ US Minnesota - Department of Treasury - Income Tax
+
+
+ US Minnesota - Department of Treasury - Income Tax
+
+
+
+
+
+
+
+
+
+ ER: US MN Minnesota State Unemployment
+ ER_US_MN_SUTA
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_mn_suta_wage_base', rate='us_mn_suta_rate', state_code='MN')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_mn_suta_wage_base', rate='us_mn_suta_rate', state_code='MN')
+
+
+
+
+
+
+
+ EE: US MN Minnesota State Income Tax Withholding
+ EE_US_MN_SIT
+ python
+ result, _ = mn_minnesota_state_income_withholding(payslip, categories, worked_days, inputs)
+ code
+ result, result_rate = mn_minnesota_state_income_withholding(payslip, categories, worked_days, inputs)
+
+
+
+
+
\ No newline at end of file
diff --git a/l10n_us_hr_payroll/migrations/data.py b/l10n_us_hr_payroll/migrations/data.py
index e11a5f12..432b3680 100644
--- a/l10n_us_hr_payroll/migrations/data.py
+++ b/l10n_us_hr_payroll/migrations/data.py
@@ -18,6 +18,10 @@ FIELDS_CONTRACT_TO_US_PAYROLL_FORMS_2020 = {
'mi_w4_tax_exempt': 'state_income_tax_exempt',
'mi_w4_additional_wh': 'state_income_tax_additional_withholding',
+ 'mn_w4mn_filing_status': 'mn_w4mn_sit_filing_status',
+ 'mn_w4mn_allowances': 'mn_w4mn_sit_allowances',
+ 'mn_w4mn_additional_wh': 'state_income_tax_additional_withholding',
+
'mo_mow4_filing_status': 'mo_mow4_sit_filing_status',
'mo_mow4_additional_withholding': 'state_income_tax_additional_withholding',
@@ -78,6 +82,11 @@ XMLIDS_TO_REMOVE_2020 = [
'l10n_us_mi_hr_payroll.hr_payroll_mi_income_withhold',
'l10n_us_mi_hr_payroll.hr_payroll_rules_mi_unemp_wages',
+ 'l10n_us_mn_hr_payroll.hr_payroll_mn_unemp_wages',
+ 'l10n_us_mn_hr_payroll.hr_payroll_mn_unemp',
+ 'l10n_us_mn_hr_payroll.hr_payroll_mn_income_withhold',
+ 'l10n_us_mn_hr_payroll.hr_payroll_rules_mn_unemp_wages',
+
'l10n_us_mo_hr_payroll.hr_payroll_mo_unemp_wages',
'l10n_us_mo_hr_payroll.hr_payroll_mo_unemp',
'l10n_us_mo_hr_payroll.hr_payroll_mo_income_withhold',
@@ -191,6 +200,13 @@ XMLIDS_TO_RENAME_2020 = {
'l10n_us_mi_hr_payroll.hr_payroll_rules_mi_unemp': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_mi_suta',
'l10n_us_mi_hr_payroll.hr_payroll_rules_mi_inc_withhold': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_mi_sit',
+ 'l10n_us_mn_hr_payrol.res_partner_mn_ui_unemp': 'l10n_us_hr_payroll.res_partner_us_mn_dor',
+ 'l10n_us_mn_hr_payrol.res_partner_mn_dor_withhold': 'l10n_us_hr_payroll.res_partner_us_mn_dor_sit',
+ 'l10n_us_mn_hr_payrol.contrib_register_mn_ui_unemp': 'l10n_us_hr_payroll.contrib_register_us_mn_dor',
+ 'l10n_us_mn_hr_payrol.contrib_register_mn_dor_withhold': 'l10n_us_hr_payroll.contrib_register_us_mn_dor_sit',
+ 'l10n_us_mn_hr_payrol.hr_payroll_rules_mn_unemp': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_mn_suta',
+ 'l10n_us_mn_hr_payrol.hr_payroll_rules_mn_inc_withhold': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_mn_sit',
+
'l10n_us_mo_hr_payroll.res_partner_modor_unemp': 'l10n_us_hr_payroll.res_partner_us_mo_dor',
'l10n_us_mo_hr_payroll.res_partner_modor_withhold': 'l10n_us_hr_payroll.res_partner_us_mo_dor_sit',
'l10n_us_mo_hr_payroll.contrib_register_modor_unemp': 'l10n_us_hr_payroll.contrib_register_us_mo_dor',
diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py
index f699a59b..c2174f97 100644
--- a/l10n_us_hr_payroll/models/hr_payslip.py
+++ b/l10n_us_hr_payroll/models/hr_payslip.py
@@ -16,6 +16,7 @@ from .state.general import general_state_unemployment, \
is_us_state
from .state.ga_georgia import ga_georgia_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
from .state.ms_mississippi import ms_mississippi_state_income_withholding
from .state.mt_montana import mt_montana_state_income_withholding
@@ -59,6 +60,7 @@ class HRPayslip(models.Model):
'is_us_state': is_us_state,
'ga_georgia_state_income_withholding': ga_georgia_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,
'ms_mississippi_state_income_withholding': ms_mississippi_state_income_withholding,
'mt_montana_state_income_withholding': mt_montana_state_income_withholding,
diff --git a/l10n_us_hr_payroll/models/state/mn_minnesota.py b/l10n_us_hr_payroll/models/state/mn_minnesota.py
new file mode 100644
index 00000000..f640b36a
--- /dev/null
+++ b/l10n_us_hr_payroll/models/state/mn_minnesota.py
@@ -0,0 +1,43 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .general import _state_applies
+
+
+def mn_minnesota_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 = 'MN'
+ if not _state_applies(payslip, state_code):
+ return 0.0, 0.0
+
+ filing_status = payslip.dict.contract_id.us_payroll_config_value('mn_w4mn_sit_filing_status')
+ if not filing_status:
+ return 0.0, 0.0
+
+ # Determine Wage
+ wage = categories.GROSS + categories.DED_FIT_EXEMPT
+ pay_periods = payslip.dict.get_pay_periods_in_year()
+ additional = payslip.dict.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
+ sit_tax_rate = payslip.dict.rule_parameter('us_mn_sit_tax_rate')[filing_status]
+ allowances_rate = payslip.dict.rule_parameter('us_mn_sit_allowances_rate')
+ allowances = payslip.dict.contract_id.us_payroll_config_value('mn_w4mn_sit_allowances')
+ if wage == 0.0:
+ return 0.0, 0.0
+
+ taxable_income = (wage * pay_periods) - (allowances * allowances_rate)
+ withholding = 0.0
+ for row in sit_tax_rate:
+ cap, subtract_amt, rate, flat_fee = row
+ cap = float(cap)
+ if cap > taxable_income:
+ withholding = ((rate / 100.00) * (taxable_income - subtract_amt)) + flat_fee
+ break
+ withholding = round(withholding / 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 c60d2f6f..fd21e0d2 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -66,6 +66,13 @@ class HRContractUSPayrollConfig(models.Model):
mi_w4_sit_exemptions = fields.Integer(string='Michigan MI W-4 Exemptions', help='MI-W4 6.')
+ mn_w4mn_sit_filing_status = fields.Selection([
+ ('', 'Exempt'),
+ ('single', 'Single'),
+ ('married', 'Married'),
+ ], string='Minnesota W-4MN Marital Status', help='W-4MN')
+ mn_w4mn_sit_allowances = fields.Integer(string='Minnesota Allowances', help='W-4MN 1.')
+
mo_mow4_sit_filing_status = fields.Selection([
('', 'Exempt'),
('single', 'Single or Married Spouse Works or Married Filing Separate'),
diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py
index 65616a6a..711bb35c 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_ga_georgia_payslip_2020
from . import test_us_mi_michigan_payslip_2019
from . import test_us_mi_michigan_payslip_2020
+from . import test_us_mn_minnesota_payslip_2019
+from . import test_us_mn_minnesota_payslip_2020
+
from . import test_us_mo_missouri_payslip_2019
from . import test_us_mo_missouri_payslip_2020
diff --git a/l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2019.py
new file mode 100755
index 00000000..2a64b57d
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2019.py
@@ -0,0 +1,159 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .common import TestUsPayslip, process_payslip
+
+
+class TestUsMNPayslip(TestUsPayslip):
+ # TAXES AND RATES
+ MN_UNEMP_MAX_WAGE = 34000.0
+ MN_UNEMP = -1.11 / 100.0
+
+ def test_taxes_weekly(self):
+ salary = 30000.0
+ # Hand Calculated Amount to Test
+ # Step 1 -> 30000.00 for wages per period Step 2 -> 52.0 for weekly -> 30000 * 52 -> 1560000
+ # Step 3 -> allowances * 4250.0 -> 4250.00 in this case.
+ # Step 4 -> Step 2 - Step 3 -> 1560000 - 4250.00 -> 1555750
+ # Step 5 -> using chart -> we have last row -> ((1555750 - 166290) * (9.85 / 100)) + 11717.65 -> 148579.46
+ # Step 6 -> Convert back to pay period amount and round - > 2857.297 - > 2857.0
+ # wh = 2857.0
+ wh = -2857.0
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status='single',
+ state_income_tax_additional_withholding=0.0,
+ mn_w4mn_sit_allowances=1.0,
+ schedule_pay='weekly')
+
+ self._log('2019 Minnesota tax first payslip weekly:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], salary * self.MN_UNEMP)
+ self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh) # Test numbers are off by 1 penny
+
+ process_payslip(payslip)
+
+ # Make a new payslip, this one will have maximums
+ remaining_MN_UNEMP_wages = self.MN_UNEMP_MAX_WAGE - salary if (self.MN_UNEMP_MAX_WAGE - 2*salary < salary) \
+ else salary
+
+ self._log('2019 Minnesota tax second payslip weekly:')
+ payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_MN_UNEMP_wages * self.MN_UNEMP)
+
+ def test_taxes_married(self):
+ salary = 5000.00
+
+ # Hand Calculated Amount to Test
+ # Step 1 -> 5000.0 for wages per period Step 2 -> 52.0 for weekly -> 5000 * 52 -> 260,000
+ # Step 3 -> allowances * 4250.0 -> 4250.00 in this case.
+ # Step 4 -> Step 2 - Step 3 -> 260,000 - 4250.00 -> 255750.0
+ # For step five we used the married section
+ # Step 5 -> using chart -> we have 2nd last row -> ((255750 - 163070) * (7.85 / 100)) + 10199.33 ->
+ # Step 6 -> Convert back to pay period amount and round
+ # wh = 336.0
+ wh = -336.0
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status='married',
+ state_income_tax_additional_withholding=0.0,
+ mn_w4mn_sit_allowances=1.0,
+ schedule_pay='weekly')
+
+ self._log('2019 Minnesota tax first payslip married:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], salary * self.MN_UNEMP)
+ self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh)
+
+ def test_taxes_semimonthly(self):
+ salary = 6500.00
+ # Hand Calculated Amount to Test
+ # Step 1 -> 6500.00 for wages per period Step 2 -> 24 for semi-monthly -> 6500.00 * 24 -> 156000.00
+ # Step 3 -> allowances * 4250.0 -> 4250.00 in this case.
+ # Step 4 -> Step 2 - Step 3 -> 156000.00 - 4250.00 -> 151750.0
+ # Step 5 -> using chart -> we have 2nd last row -> ((151750.0- 89510) * (7.85 / 100)) + 5690.42 -> 10576.26
+ # Step 6 -> Convert back to pay period amount and round
+ # wh = -441
+ wh = -441.00
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status='single',
+ state_income_tax_additional_withholding=0.0,
+ mn_w4mn_sit_allowances=1.0,
+ schedule_pay='semi-monthly')
+
+
+ self._log('2019 Minnesota tax first payslip semimonthly:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], salary * self.MN_UNEMP)
+ self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh)
+
+ def test_tax_exempt(self):
+ salary = 5500.00
+ wh = 0
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status='',
+ state_income_tax_additional_withholding=0.0,
+ mn_w4mn_sit_allowances=2.0,
+ schedule_pay='weekly')
+
+ self._log('2019 Minnesota tax first payslip exempt:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], salary * self.MN_UNEMP)
+ self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh)
+
+ def test_additional_withholding(self):
+ salary = 5500.0
+ # Hand Calculated Amount to Test
+ # Step 1 -> 5500 for wages per period Step 2 -> 52 for weekly -> 5500 * 52 -> 286000.00
+ # Step 3 -> allowances * 4250.0 -> 8500 in this case.
+ # Step 4 -> Step 2 - Step 3 -> 286000.00 - 8500 -> 277500
+ # Step 5 -> using chart -> we have last row -> ((277500- 166290) * (9.85 / 100)) + 11717.65 -> 22671.835
+ # Step 6 -> Convert back to pay period amount and round
+ # wh = -436.0
+ # Add additional_withholding
+ # wh = -436.0 + 40.0
+ wh = -476.0
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status='single',
+ state_income_tax_additional_withholding=40.0,
+ mn_w4mn_sit_allowances=2.0,
+ schedule_pay='weekly')
+
+ self._log('2019 Minnesota tax first payslip additional withholding:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['ER_US_SUTA'], salary * self.MN_UNEMP)
+ self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh)
diff --git a/l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_mn_minnesota_payslip_2020.py
new file mode 100755
index 00000000..c91fa2a8
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_mn_minnesota_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 TestUsMNPayslip(TestUsPayslip):
+ # TAXES AND RATES
+ MN_UNEMP_MAX_WAGE = 35000.0
+ MN_UNEMP = 1.11
+
+ def _test_sit(self, wage, filing_status, allowances, additional_withholding, schedule_pay, date_start, expected_withholding):
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('MN'),
+ mn_w4mn_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional_withholding,
+ mn_w4mn_sit_allowances=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('MN', self.MN_UNEMP, date(2020, 1, 1), wage_base=self.MN_UNEMP_MAX_WAGE)
+ self._test_sit(5000.0, 'single', 1.0, 0.0, 'weekly', date(2020, 1, 1), 389.0)
+ self._test_sit(30000.0, 'single', 1.0, 0.0, 'weekly', date(2020, 1, 1), 2850.99)
+ self._test_sit(5000.0, 'married', 1.0, 0.0, 'weekly', date(2020, 1, 1), 325.0)
+ self._test_sit(6500.0, 'single', 1.0, 0.0, 'semi-monthly', date(2020, 1, 1), 429.0)
+ self._test_sit(5500.0, '', 2.0, 0.0, 'weekly', date(2020, 1, 1), 0.0)
+ self._test_sit(5500.0, 'single', 2.0, 40.0, 'weekly', date(2020, 1, 1), 470.0)
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 47ef9272..12e5c507 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 W-4MN - State Income Tax
+
+
+
+
Form MO W-4 - State Income Tax