diff --git a/l10n_us_hr_payroll/data/state/ia_iowa.xml b/l10n_us_hr_payroll/data/state/ia_iowa.xml
index dcc90009..67328363 100644
--- a/l10n_us_hr_payroll/data/state/ia_iowa.xml
+++ b/l10n_us_hr_payroll/data/state/ia_iowa.xml
@@ -7,16 +7,16 @@
-
- 30600.0
-
-
-
31600.0
+
+ 32400.0
+
+
+
@@ -26,11 +26,6 @@
-
- 1.0
-
-
-
1.0
@@ -44,78 +39,6 @@
-
- {
- 'daily': (
- ( 5.13, 0.0033, 0.00),
- ( 10.25, 0.0067, 0.02),
- ( 20.50, 0.0225, 0.05),
- ( 46.13, 0.0414, 0.28),
- ( 76.89, 0.0563, 1.34),
- (102.52, 0.0596, 3.07),
- (153.78, 0.0625, 4.60),
- (230.68, 0.0744, 7.80),
- ( 'inf', 0.0853, 13.52),
- ),
- 'weekly': (
- ( 25.63, 0.0033, 0.00),
- ( 51.27, 0.0067, 0.08),
- ( 102.52, 0.0225, 0.25),
- ( 230.67, 0.0414, 1.40),
- ( 384.46, 0.0563, 6.71),
- ( 512.62, 0.0596, 15.37),
- ( 768.92, 0.0625, 23.01),
- (1153.38, 0.0744, 39.03),
- ( 'inf', 0.0853, 67.63),
- ),
- 'bi-weekly': (
- ( 51.27, 0.0033, 0.00),
- ( 102.54, 0.0067, 0.17),
- ( 205.04, 0.0225, 0.51),
- ( 461.35, 0.0414, 2.82),
- ( 768.92, 0.0563, 13.43),
- (1025.23, 0.0596, 30.75),
- (1537.85, 0.0625, 46.03),
- (2306.77, 0.0744, 78.07),
- ( 'inf', 0.0853, 135.28),
- ),
- 'semi-monthly': (
- ( 55.54, 0.0033, 0.00),
- ( 111.08, 0.0067, 0.18),
- ( 222.13, 0.0225, 0.55),
- ( 499.79, 0.0414, 3.05),
- ( 833.00, 0.0563, 14.59),
- (1110.67, 0.0596, 33.31),
- (1666.00, 0.0625, 49.86),
- (2499.00, 0.0744, 84.57),
- ( 'inf', 0.0853, 146.55),
- ),
- 'monthly': (
- ( 111.08, 0.0033, 0.00),
- ( 222.17, 0.0067, 0.37),
- ( 444.25, 0.0225, 1.11),
- ( 999.58, 0.0414, 6.11),
- (1666.00, 0.0563, 29.10),
- (2221.33, 0.0596, 62.66),
- (3332.00, 0.0625, 99.72),
- (4998.00, 0.0744, 169.14),
- ( 'inf', 0.0853, 293.09),
- ),
- 'annual': (
- ( 1333.00, 0.0033, 0.00),
- ( 2666.00, 0.0067, 4.40),
- ( 5331.00, 0.0225, 13.33),
- (11995.00, 0.0414, 73.29),
- (19992.00, 0.0563, 349.19),
- (26656.00, 0.0596, 799.41),
- (39984.00, 0.0625, 1196.58),
- (59976.00, 0.0744, 2029.58),
- ( 'inf', 0.0853, 3516.98),
- ),
- }
-
-
-
@@ -190,6 +113,69 @@
+
+
+
+ {
+ 'weekly': (
+ ( 32.23, 0.0033, 0.00),
+ ( 64.46, 0.0067, 0.11),
+ ( 128.92, 0.0225, 0.33),
+ ( 290.08, 0.0414, 1.78),
+ ( 483.46, 0.0563, 8.45),
+ ( 644.62, 0.0596, 19.34),
+ ( 966.92, 0.0625, 28.95),
+ (1450.38, 0.0744, 49.09),
+ ( 'inf', 0.0853, 85.06),
+ ),
+ 'bi-weekly': (
+ ( 64.46, 0.0033, 0.00),
+ ( 128.92, 0.0067, 0.21),
+ ( 257.85, 0.0225, 0.64),
+ ( 580.15, 0.0414, 3.54),
+ ( 966.92, 0.0563, 16.88),
+ (1289.23, 0.0596, 38.66),
+ (1933.85, 0.0625, 57.87),
+ (2900.77, 0.0744, 98.16),
+ ( 'inf', 0.0853, 170.10),
+ ),
+ 'semi-monthly': (
+ ( 69.83, 0.0033, 0.00),
+ ( 139.67, 0.0067, 0.23),
+ ( 279.33, 0.0225, 0.70),
+ ( 628.50, 0.0414, 3.84),
+ (1047.50, 0.0563, 18.30),
+ (1396.67, 0.0596, 41.89),
+ (2095.00, 0.0625, 62.70),
+ (3142.50, 0.0744, 106.35),
+ ( 'inf', 0.0853, 184.28),
+ ),
+ 'monthly': (
+ ( 139.67, 0.0033, 0.00),
+ ( 279.33, 0.0067, 0.46),
+ ( 558.67, 0.0225, 1.40),
+ (1257.00, 0.0414, 7.69),
+ (2095.00, 0.0563, 36.60),
+ (2793.33, 0.0596, 83.78),
+ (4190.00, 0.0625, 125.40),
+ (6285.00, 0.0744, 212.69),
+ ( 'inf', 0.0853, 368.56),
+ ),
+ 'annual': (
+ ( 1676.00, 0.0033, 0.00),
+ ( 3352.00, 0.0067, 5.53),
+ ( 6704.00, 0.0225, 16.76),
+ (15084.00, 0.0414, 92.18),
+ (25140.00, 0.0563, 439.11),
+ (33520.00, 0.0596, 1005.26),
+ (50280.00, 0.0625, 1504.71),
+ (75420.00, 0.0744, 2552.21),
+ ( 'inf', 0.0853, 4422.63),
+ ),
+ }
+
+
+
@@ -198,18 +184,6 @@
-
- {
- 'daily': ( 6.50, 16.00),
- 'weekly': ( 32.50, 80.00),
- 'bi-weekly': ( 65.00, 160.00),
- 'semi-monthly': ( 70.42, 173.33),
- 'monthly': ( 140.83, 346.67),
- 'annually': (1690.00, 4160.00),
- }
-
-
-
@@ -224,6 +198,19 @@
+
+
+
+ {
+ 'weekly': ( 40.96, 100.77),
+ 'bi-weekly': ( 81.92, 201.54),
+ 'semi-monthly': ( 88.75, 218.33),
+ 'monthly': ( 177.50, 436.67),
+ 'annually': (2130.00, 5240.00),
+ }
+
+
+
@@ -232,18 +219,6 @@
-
- {
- 'daily': 0.15,
- 'weekly': 0.77,
- 'bi-weekly': 1.54,
- 'semi-monthly': 1.67,
- 'monthly': 3.33,
- 'annually': 40.00,
- }
-
-
-
@@ -258,6 +233,19 @@
+
+
+
+ {
+ 'weekly': 0.77,
+ 'bi-weekly': 1.54,
+ 'semi-monthly': 1.67,
+ 'monthly': 3.33,
+ 'annually': 40.00,
+ }
+
+
+
diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py
index 9254cbf3..a1944823 100755
--- a/l10n_us_hr_payroll/tests/__init__.py
+++ b/l10n_us_hr_payroll/tests/__init__.py
@@ -40,8 +40,8 @@ from . import test_us_ga_georgia_payslip_2020
from . import test_us_hi_hawaii_payslip_2019
from . import test_us_hi_hawaii_payslip_2020
-from . import test_us_ia_iowa_payslip_2019
from . import test_us_ia_iowa_payslip_2020
+from . import test_us_ia_iowa_payslip_2021
from . import test_us_id_idaho_payslip_2019
from . import test_us_id_idaho_payslip_2020
diff --git a/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2019.py
deleted file mode 100644
index cb3bccfd..00000000
--- a/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2019.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
-
-from .common import TestUsPayslip, process_payslip
-
-
-class TestUsIAPayslip(TestUsPayslip):
- IA_UNEMP_MAX_WAGE = 30600
- IA_UNEMP = -1.0 / 100.0
- IA_INC_TAX = -0.0535
-
- def test_taxes_weekly(self):
- wages = 30000.00
- schedule_pay = 'weekly'
- allowances = 1
- additional_wh = 0.00
- employee = self._createEmployee()
- contract = self._createContract(employee,
- wage=wages,
- state_id=self.get_us_state('IA'),
- state_income_tax_additional_withholding=additional_wh,
- ia_w4_sit_allowances=allowances,
- schedule_pay=schedule_pay)
-
- self._log('2019 Iowa tax first payslip weekly:')
- payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
- payslip.compute_sheet()
- cats = self._getCategories(payslip)
-
- # T1 is the gross taxable wages for the pay period minus the Federal withholding amount. We add the federal
- # withholding amount because it is calculated in the base US payroll module as a negative
- # t1 = 30000 - (10399.66) = 19600.34
- t1_to_test = wages + cats['EE_US_941_FIT']
- self.assertPayrollAlmostEqual(t1_to_test, 19600.34)
-
- # T2 is T1 minus our standard deduction which is a table of flat rates dependent on the number of allowances.
- # In our case, we have a weekly period which on the table has a std deduct. of $32.50 for 0 or 1 allowances,
- # and 80.00 of 2 or more allowances.
- standard_deduction = 32.50 # The allowance tells us what standard_deduction amount to use.
- # t2 = 19600.34 - 32.50 = 19567.84
- t2_to_test = t1_to_test - standard_deduction
- self.assertPayrollAlmostEqual(t2_to_test, 19567.84)
- # T3 is T2 multiplied by the income rates in the large table plus a flat fee for that bracket.
- # 1153.38 is the bracket floor. 8.53 is the rate, and 67.63 is the flat fee.
- # t3 = 1638.38
- t3_to_test = ((t2_to_test - 1153.38) * (8.53 / 100)) + 67.63
- self.assertPayrollAlmostEqual(t3_to_test, 1638.38)
- # T4 is T3 minus a flat amount determined by pay period * the number of deductions. For 2019, our weekly
- # deduction amount per allowance is 0.77
- # t4 = 1638.38 - 0.77 = 155.03
- t4_to_test = t3_to_test - (0.77 * allowances)
- self.assertPayrollAlmostEqual(t4_to_test, 1637.61)
- # t5 is our T4 plus the additional withholding per period
- # t5 = 1637.61 + 0.0
- # Convert to negative as well.
- t5_to_test = -t4_to_test - additional_wh
- self.assertPayrollAlmostEqual(t5_to_test, -1637.61)
-
- self.assertPayrollEqual(cats['ER_US_SUTA'], wages * self.IA_UNEMP)
- self.assertPayrollEqual(cats['EE_US_SIT'], t5_to_test)
-
-
- # Make a new payslip, this one will have maximums
-
- remaining_IA_UNEMP_wages = self.IA_UNEMP_MAX_WAGE - wages if (self.IA_UNEMP_MAX_WAGE - 2*wages < wages) \
- else wages
-
- self._log('2019 Iowa 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'], wages * self.IA_UNEMP)
-
- def test_taxes_biweekly(self):
- wages = 3000.00
- schedule_pay = 'bi-weekly'
- allowances = 1
- additional_wh = 0.00
- employee = self._createEmployee()
- contract = self._createContract(employee,
- wage=wages,
- state_id=self.get_us_state('IA'),
- state_income_tax_additional_withholding=additional_wh,
- ia_w4_sit_allowances=allowances,
- schedule_pay=schedule_pay)
-
- self._log('2019 Iowa tax first payslip bi-weekly:')
- payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
- payslip.compute_sheet()
- cats = self._getCategories(payslip)
-
- # T1 is the gross taxable wages for the pay period minus the Federal withholding amount. We add the federal
- # withholding amount because it is calculated in the base US payroll module as a negative
- t1_to_test = wages + cats['EE_US_941_FIT']
- # T2 is T1 minus our standard deduction which is a table of flat rates dependent on the number of allowances.
- # In our case, we have a biweekly period which on the table has a std deduct. of $65.00 for 0 or 1 allowances,
- # and $160.00 of 2 or more allowances.
- standard_deduction = 65.00 # The allowance tells us what standard_deduction amount to use.
- t2_to_test = t1_to_test - standard_deduction
- # T3 is T2 multiplied by the income rates in the large table plus a flat fee for that bracket.
- t3_to_test = ((t2_to_test - 2306.77) * (8.53 / 100)) + 135.28
- # T4 is T3 minus a flat amount determined by pay period * the number of deductions. For 2019, our weekly
- # deduction amount per allowance is 0.77
- t4_to_test = t3_to_test - (1.54 * allowances)
- # t5 is our T4 plus the additional withholding per period
- t5_to_test = -t4_to_test - additional_wh
-
- self.assertPayrollEqual(cats['ER_US_SUTA'], wages * self.IA_UNEMP)
- self.assertPayrollEqual(cats['EE_US_SIT'], t5_to_test - additional_wh)
-
- process_payslip(payslip)
-
- def test_taxes_with_external_weekly(self):
- wages = 2500.00
- schedule_pay = 'weekly'
- allowances = 1
- additional_wh = 0.00
-
- employee = self._createEmployee()
- contract = self._createContract(employee,
- wage=wages,
- state_id=self.get_us_state('IA'),
- state_income_tax_additional_withholding=additional_wh,
- ia_w4_sit_allowances=allowances,
- schedule_pay=schedule_pay)
-
- self._log('2019 Iowa external tax first payslip external weekly:')
- payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
- payslip.compute_sheet()
- cats = self._getCategories(payslip)
-
-
- # T1 is the gross taxable wages for the pay period minus the Federal withholding amount. We add the federal
- # withholding amount because it is calculated in the base US payroll module as a negative
- t1_to_test = wages + cats['EE_US_941_FIT']
- # T2 is T1 minus our standard deduction which is a table of flat rates dependent on the number of allowances.
- # In our case, we have a weekly period which on the table has a std deduct. of $32.50 for 0 or 1 allowances,
- # and 80.00 of 2 or more allowances.
- standard_deduction = 32.50 # The allowance tells us what standard_deduction amount to use.
- t2_to_test = t1_to_test - standard_deduction
- # T3 is T2 multiplied by the income rates in the large table plus a flat fee for that bracket.
- t3_to_test = ((t2_to_test - 1153.38) * (8.53 / 100)) + 67.63
- # T4 is T3 minus a flat amount determined by pay period * the number of deductions. For 2019, our weekly
- # deduction amount per allowance is 0.77
- t4_to_test = t3_to_test - (0.77 * allowances)
- # t5 is our T4 plus the additional withholding per period
- t5_to_test = -t4_to_test - additional_wh
-
- self.assertPayrollEqual(cats['ER_US_SUTA'], wages * self.IA_UNEMP)
- self.assertPayrollAlmostEqual(cats['EE_US_SIT'], t5_to_test)
-
- process_payslip(payslip)
\ No newline at end of file
diff --git a/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2021.py b/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2021.py
new file mode 100755
index 00000000..df169186
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2021.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 TestUsIAPayslip(TestUsPayslip):
+ ###
+ # 2021 Taxes and Rates
+ ###
+ IA_UNEMP_MAX_WAGE = 32400.0
+ IA_UNEMP = 1.0
+
+ def _test_sit(self, wage, exempt, additional_withholding, allowances, schedule_pay, date_start, expected_withholding):
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('IA'),
+ state_income_tax_exempt=exempt,
+ state_income_tax_additional_withholding=additional_withholding,
+ ia_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('IA', self.IA_UNEMP, date(2021, 1, 1), wage_base=self.IA_UNEMP_MAX_WAGE)
+ self._test_sit(2100.0, False, 0.0, 3.0, 'bi-weekly', date(2021, 1, 1), 79.13)
+ self._test_sit(3000.0, True, 10.0, 1.0, 'bi-weekly', date(2021, 1, 1), 0.00)
+ self._test_sit(300.0, False, 0.0, 1.0, 'weekly', date(2021, 1, 1), 6.14)
+ self._test_sit(5000.0, False, 0.0, 1.0, 'monthly', date(2021, 1, 1), 217.60)
+ self._test_sit(7500.0, False, 10.0, 2.0, 'semi-monthly', date(2021, 1, 1), 420.87)