diff --git a/l10n_us_hr_payroll/data/state/nd_north_dakota.xml b/l10n_us_hr_payroll/data/state/nd_north_dakota.xml
index d778c3aa..9c7fdd69 100644
--- a/l10n_us_hr_payroll/data/state/nd_north_dakota.xml
+++ b/l10n_us_hr_payroll/data/state/nd_north_dakota.xml
@@ -12,6 +12,12 @@
+
+
+ 38500.0
+
+
+
@@ -21,12 +27,15 @@
+
+
1.02
+
US ND North Dakota SIT Tax Rate
@@ -214,6 +223,189 @@
+
+
+
+ {
+ 'single': {
+ 'weekly': (
+ ( 121, 0.00, 0.00),
+ ( 900, 0.00, 1.10),
+ ( 2007, 8.57, 2.04),
+ ( 4057, 31.15, 2.27),
+ ( 8678, 77.69, 2.64),
+ ('inf', 199.68, 2.90),
+ ),
+ 'bi-weekly': (
+ ( 241, 0.00, 0.00),
+ ( 1800, 0.00, 1.10),
+ ( 4014, 17.15, 2.04),
+ ( 8113, 62.31, 2.27),
+ ( 17357, 155.36, 2.64),
+ ( 'inf', 399.40, 2.90),
+ ),
+ 'semi-monthly': (
+ ( 261, 0.00, 0.00),
+ ( 1950, 0.00, 1.10),
+ ( 4349, 18.58, 2.04),
+ ( 8790, 67.52, 2.27),
+ ( 18790, 168.33, 2.64),
+ ( 'inf', 432.67, 2.90),
+ ),
+ 'monthly': (
+ ( 523, 0.00, 0.00),
+ ( 3900, 0.00, 1.10),
+ ( 8698, 37.15, 2.04),
+ ( 17579, 135.03, 2.27),
+ ( 37606, 336.62, 2.64),
+ ( 'inf', 865.34, 2.90),
+ ),
+ 'quarterly': (
+ ( 1569, 0.00, 0.00),
+ ( 11700, 0.00, 1.10),
+ ( 26094, 111.44, 2.04),
+ ( 52738, 405.08, 2.27),
+ ( 112819, 1009.90, 2.64),
+ ( 'inf', 2596.04, 2.90),
+ ),
+ 'semi-annual': (
+ ( 3138, 0.00, 0.00),
+ ( 23400, 0.00, 1.10),
+ ( 52188, 222.88, 2.04),
+ ( 105475, 810.16, 2.27),
+ ( 225638, 2019.77, 2.64),
+ ( 'inf', 5192.08, 2.90),
+ ),
+ 'annual': (
+ ( 6275, 0.00, 0.00),
+ ( 46800, 0.00, 1.10),
+ ( 104375, 445.78, 2.04),
+ ( 210950, 1620.31, 2.27),
+ ( 451275, 4039.56, 2.64),
+ ( 'inf', 10384.14, 2.90),
+ ),
+ },
+ 'married': {
+ 'weekly': (
+ ( 241, 0.00, 0.00),
+ ( 892, 0.00, 1.10),
+ ( 1814, 7.16, 2.04),
+ ( 2637, 25.97, 2.27),
+ ( 4520, 44.65, 2.64),
+ ('inf', 94.36, 2.90),
+ ),
+ 'bi-weekly': (
+ ( 483, 0.00, 0.00),
+ ( 1785, 0.00, 1.10),
+ ( 3628, 14.32, 2.04),
+ ( 5274, 51.92, 2.27),
+ ( 9040, 89.28, 2.64),
+ ( 'inf', 188.71, 2.90),
+ ),
+ 'semi-monthly': (
+ ( 523, 0.00, 0.00),
+ ( 1933, 0.00, 1.10),
+ ( 3930, 15.51, 2.04),
+ ( 5714, 56.25, 2.27),
+ ( 9794, 96.75, 2.64),
+ ( 'inf', 204.46, 2.90),
+ ),
+ 'monthly': (
+ ( 1046, 0.00, 0.00),
+ ( 3867, 0.00, 1.10),
+ ( 7860, 31.03, 2.04),
+ ( 11427, 112.49, 2.27),
+ ( 19588, 193.46, 2.64),
+ ( 'inf', 408.91, 2.90),
+ ),
+ 'quarterly': (
+ ( 3138, 0.00, 0.00),
+ ( 11600, 0.00, 1.10),
+ ( 23581, 93.08, 2.04),
+ ( 34281, 337.49, 2.27),
+ ( 58763, 580.38, 2.64),
+ ( 'inf', 1226.71, 2.90),
+ ),
+ 'semi-annual': (
+ ( 6275, 0.00, 0.00),
+ ( 23200, 0.00, 1.10),
+ ( 47163, 186.18, 2.04),
+ ( 68563, 675.02, 2.27),
+ ( 117525, 1160.80, 2.64),
+ ( 'inf', 2453.40, 2.90),
+ ),
+ 'annual': (
+ ( 12550, 0.00, 0.00),
+ ( 46400, 0.00, 1.10),
+ ( 94325, 372.35, 2.04),
+ ( 137125, 1350.02, 2.27),
+ ( 235050, 2321.58, 2.64),
+ ( 'inf', 4906.80, 2.90),
+ ),
+ },
+ 'head_household':{
+ 'weekly': (
+ ( 121, 0.00, 0.00),
+ ( 900, 0.00, 1.10),
+ ( 2007, 8.57, 2.04),
+ ( 4057, 31.15, 2.27),
+ ( 8678, 77.69, 2.64),
+ ('inf', 199.68, 2.90),
+ ),
+ 'bi-weekly': (
+ ( 241, 0.00, 0.00),
+ ( 1800, 0.00, 1.10),
+ ( 4014, 17.15, 2.04),
+ ( 8113, 62.31, 2.27),
+ ( 17357, 155.36, 2.64),
+ ( 'inf', 399.40, 2.90),
+ ),
+ 'semi-monthly': (
+ ( 261, 0.00, 0.00),
+ ( 1950, 0.00, 1.10),
+ ( 4349, 18.58, 2.04),
+ ( 8790, 67.52, 2.27),
+ ( 18790, 168.33, 2.64),
+ ( 'inf', 432.67, 2.90),
+ ),
+ 'monthly': (
+ ( 523, 0.00, 0.00),
+ ( 3900, 0.00, 1.10),
+ ( 8698, 37.15, 2.04),
+ ( 17579, 135.03, 2.27),
+ ( 37606, 336.62, 2.64),
+ ( 'inf', 865.34, 2.90),
+ ),
+ 'quarterly': (
+ ( 1569, 0.00, 0.00),
+ ( 11700, 0.00, 1.10),
+ ( 26094, 111.44, 2.04),
+ ( 52738, 405.08, 2.27),
+ ( 112819, 1009.90, 2.64),
+ ( 'inf', 2596.04, 2.90),
+ ),
+ 'semi-annual': (
+ ( 3138, 0.00, 0.00),
+ ( 23400, 0.00, 1.10),
+ ( 52188, 222.88, 2.04),
+ ( 105475, 810.16, 2.27),
+ ( 225638, 2019.77, 2.64),
+ ( 'inf', 5192.08, 2.90),
+ ),
+ 'annual': (
+ ( 6275, 0.00, 0.00),
+ ( 46800, 0.00, 1.10),
+ ( 104375, 445.78, 2.04),
+ ( 210950, 1620.31, 2.27),
+ ( 451275, 4039.56, 2.64),
+ ( 'inf', 10384.14, 2.90),
+ ),
+ },
+ }
+
+
+
@@ -222,6 +414,7 @@
+
{
'weekly' : 83.00,
diff --git a/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2021.py b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2021.py
new file mode 100644
index 00000000..c4dfaeb5
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2021.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 TestUsNDPayslip(TestUsPayslip):
+ ###
+ # 2021 Taxes and Rates
+ ###
+ ND_UNEMP_MAX_WAGE = 38500.0
+ ND_UNEMP = 1.02
+ # Calculation based on this file page.47 https://www.nd.gov/tax/data/upfiles/media/rates-and-instructions.pdf?20210110115917
+
+ def _test_sit(self, wage, filing_status, additional_withholding, allowances, schedule_pay, date_start, expected_withholding):
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('ND'),
+ nd_w4_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional_withholding,
+ nd_w4_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.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding)
+
+ def test_2021_taxes_example(self):
+ self._test_er_suta('ND', self.ND_UNEMP, date(2021, 1, 1), wage_base=self.ND_UNEMP_MAX_WAGE)
+ self._test_sit(700.0, 'single', 0.0, 0.0, 'weekly', date(2021, 1, 1), 6.0)
+ self._test_sit(5000.0, 'married', 0.0, 2.0, 'bi-weekly', date(2021, 1, 1), 76.0)
+ self._test_sit(25000.0, 'head_household', 0.0, 0.0, 'monthly', date(2021, 1, 1), 533.0)
+ self._test_sit(25000.0, 'head_household', 10.0, 2.0, 'monthly', date(2021, 1, 1), 524.0)
+ self._test_sit(3000.0, '', 10.0, 2.0, 'monthly', date(2021, 1, 1), 0.0)