From 90f2b232c666879abb187bce863354c1f46ea3fd Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 1 Apr 2020 12:51:28 -0400 Subject: [PATCH 01/63] IMP `l10n_us_hr_payroll` for Indiana 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/in_indiana.xml | 122 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + l10n_us_hr_payroll/models/state/in_indiana.py | 34 +++++ .../models/us_payroll_config.py | 2 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_in_indiana_payslip_2020.py | 36 ++++++ .../views/us_payroll_config_views.xml | 6 + 8 files changed, 205 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/in_indiana.xml create mode 100644 l10n_us_hr_payroll/models/state/in_indiana.py create mode 100755 l10n_us_hr_payroll/tests/test_us_in_indiana_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 2785d47b..f6aec784 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -39,6 +39,7 @@ United States of America - Payroll Rules. 'data/state/ia_iowa.xml', 'data/state/id_idaho.xml', 'data/state/il_illinois.xml', + 'data/state/in_indiana.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/in_indiana.xml b/l10n_us_hr_payroll/data/state/in_indiana.xml new file mode 100644 index 00000000..9bda9b1e --- /dev/null +++ b/l10n_us_hr_payroll/data/state/in_indiana.xml @@ -0,0 +1,122 @@ + + + + + US IN Indiana SUTA Wage Base + us_in_suta_wage_base + + + + + 9500.00 + + + + + + + + US IN Indiana SUTA Rate + us_in_suta_rate + + + + + 2.5 + + + + + + + US IN Indiana SUTA Income Rate + us_in_suta_income_rate + + + + + 3.23 + + + + + + + US IN Indiana SIT Personal Exemption Rate + us_in_sit_personal_exemption_rate + + + + + { + 'daily': ( 2.74, 5.48, 8.22, 10.96, 13.70, 16.44), + 'weekly': ( 19.23, 38.46, 57.69, 76.92, 96.15, 115.38), + 'bi-weekly': ( 38.46, 76.92, 115.38, 153.85, 192.31, 230.77), + 'semi-monthly': ( 41.67, 83.33, 125.00, 166.67, 208.33, 250.00), + 'monthly': ( 83.33, 166.67, 250.00, 333.33, 416.67, 500.00), + } + + + + + + + US IN Indiana SIT Dependent Exemption Rate + us_in_sit_dependent_exemption_rate + + + + + { + 'daily': ( 4.11, 8.22, 12.33, 16.44, 20.55), + 'weekly': ( 28.85, 57.69, 86.54, 115.38, 144.23), + 'bi-weekly': ( 57.69, 115.38, 173.08, 230.77, 288.46), + 'semi-monthly': ( 62.50, 125.00, 187.50, 250.00, 312.50), + 'monthly': (125.00, 250.00, 375.00, 500.00, 625.00), + } + + + + + + + + US Indiana - Department of Workforce Development - Unemployment Tax + + + + US Indiana - Department of Revenue - Income Tax + + + + + + + + + + ER: US IN Indiana State Unemployment + ER_US_IN_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_in_suta_wage_base', rate='us_in_suta_rate', state_code='IN') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_in_suta_wage_base', rate='us_in_suta_rate', state_code='IN') + + + + + + + + + EE: US IN Indiana State Income Tax Withholding + EE_US_IN_SIT + python + result, _ = in_indiana_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = in_indiana_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 888a9ebc..91dc4352 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -24,6 +24,7 @@ from .state.hi_hawaii import hi_hawaii_state_income_withholding from .state.ia_iowa import ia_iowa_state_income_withholding from .state.id_idaho import id_idaho_state_income_withholding from .state.il_illinois import il_illinois_state_income_withholding +from .state.in_indiana import in_indiana_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 @@ -79,6 +80,7 @@ class HRPayslip(models.Model): 'ia_iowa_state_income_withholding': ia_iowa_state_income_withholding, 'id_idaho_state_income_withholding': id_idaho_state_income_withholding, 'il_illinois_state_income_withholding': il_illinois_state_income_withholding, + 'in_indiana_state_income_withholding': in_indiana_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/in_indiana.py b/l10n_us_hr_payroll/models/state/in_indiana.py new file mode 100644 index 00000000..0b6bd03e --- /dev/null +++ b/l10n_us_hr_payroll/models/state/in_indiana.py @@ -0,0 +1,34 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def in_indiana_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'IN' + 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 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + personal_exemption = payslip.contract_id.us_payroll_config_value('in_w4_sit_personal_exemption') + personal_exemption_rate = payslip.rule_parameter('us_in_sit_personal_exemption_rate')[schedule_pay][personal_exemption - 1] + dependent_exemption = payslip.contract_id.us_payroll_config_value('in_w4_sit_dependent_exemption') + dependent_exemption_rate = payslip.rule_parameter('us_in_sit_dependent_exemption_rate')[schedule_pay][dependent_exemption - 1] + income_tax_rate = payslip.rule_parameter('us_in_suta_income_rate') + + taxable_income = wage - (personal_exemption_rate + dependent_exemption_rate) + withholding = taxable_income * (income_tax_rate / 100.0) + + withholding = max(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 b1aa0699..cf5a7c81 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -124,6 +124,8 @@ class HRContractUSPayrollConfig(models.Model): 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.') + in_w4_sit_personal_exemption = fields.Integer(string='Indiana In-W-4 Number of Personal Exemption', help='IN-W-4 5.') + in_w4_sit_dependent_exemption = fields.Integer(string='Indiana In-W-4 Number of Dependent Exemption', help='IN-W-4 6.') 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 11a045e2..aa4fc5ab 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -44,6 +44,8 @@ from . import test_us_id_idaho_payslip_2020 from . import test_us_il_illinois_payslip_2019 from . import test_us_il_illinois_payslip_2020 +from . import test_us_in_indiana_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_in_indiana_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_in_indiana_payslip_2020.py new file mode 100755 index 00000000..53b7ddf3 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_in_indiana_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 TestUsINPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + IN_UNEMP_MAX_WAGE = 9500.0 + IN_UNEMP = 2.5 + # Calculation based on https://www.in.gov/dor/files/dn01.pdf + + def _test_sit(self, wage, additional_withholding, personal_exemption, dependent_exemption, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('IN'), + state_income_tax_additional_withholding=additional_withholding, + in_w4_sit_personal_exemption=personal_exemption, + in_w4_sit_dependent_exemption=dependent_exemption, + 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('IN', self.IN_UNEMP, date(2020, 1, 1), wage_base=self.IN_UNEMP_MAX_WAGE) + self._test_sit(800.0, 0.0, 5.0, 3.0, 'weekly', date(2020, 1, 1), 19.94) + self._test_sit(800.0, 10.0, 5.0, 3.0, 'weekly', date(2020, 1, 1), 29.94) + self._test_sit(9000.0, 0.0, 4.0, 3.0, 'monthly', date(2020, 1, 1), 267.82) + self._test_sit(10000.0, 0.0, 2.0, 2.0, 'bi-weekly', date(2020, 1, 1), 316.79) 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 a91f80e4..a294fa51 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -119,6 +119,12 @@ + +

Form IN W-4 - State Income Tax

+ + + +

Form MI-W4 - State Income Tax

From 7c9158dfd2162a3af6f8b994c0b61dc3f9837364 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 1 Apr 2020 14:04:11 -0400 Subject: [PATCH 02/63] IMP `l10n_us_hr_payroll` Port `l10n_us_la_hr_payroll` LA Louisiana including migration --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/la_louisiana.xml | 141 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/la_louisiana.py | 60 ++++++++ .../models/us_payroll_config.py | 8 + l10n_us_hr_payroll/tests/__init__.py | 3 + .../test_us_la_louisiana_payslip_2019.py | 87 +++++++++++ .../test_us_la_louisiana_payslip_2020.py | 34 +++++ .../views/us_payroll_config_views.xml | 6 + 9 files changed, 342 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/la_louisiana.xml create mode 100644 l10n_us_hr_payroll/models/state/la_louisiana.py create mode 100644 l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py create mode 100755 l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index f6aec784..fee61b48 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -40,6 +40,7 @@ United States of America - Payroll Rules. 'data/state/id_idaho.xml', 'data/state/il_illinois.xml', 'data/state/in_indiana.xml', + 'data/state/la_louisiana.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/la_louisiana.xml b/l10n_us_hr_payroll/data/state/la_louisiana.xml new file mode 100644 index 00000000..5f23bea4 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/la_louisiana.xml @@ -0,0 +1,141 @@ + + + + + US LA Louisiana SUTA Wage Base + us_la_suta_wage_base + + + + + 7700.0 + + + + + 7700.0 + + + + + + + + US LA Louisiana SUTA Rate + us_la_suta_rate + + + + + 6.20 + + + + + 6.20 + + + + + + + US LA Louisiana SIT Tax Rate + us_la_sit_tax_rate + + + + + { + 'single': ((12500.00, 2.10), (50000.00, 1.60), ('inf', 1.35)), + 'married': ((25000.00, 2.10), (100000.00, 1.65), ('inf', 1.35)), + } + + + + + { + 'single': ((12500.00, 2.10), (50000.00, 1.60), ('inf', 1.35)), + 'married': ((25000.00, 2.10), (100000.00, 1.65), ('inf', 1.35)), + } + + + + + + + US LA Louisiana Personal Exemption Rate + us_la_sit_personal_exemption_rate + + + + + 4500 + + + + + 4500 + + + + + + + US LA Louisiana Dependent Rate + us_la_sit_dependent_rate + + + + + 1000.0 + + + + + 1000.0 + + + + + + + + US Louisiana - Workforce Commission (LWC) - Unemployment Tax + + + + US Louisiana - Department of Revenue (LDOR) - Income Tax + + + + + + + + + + ER: US LA Louisiana State Unemployment + ER_US_LA_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_la_suta_wage_base', rate='us_la_suta_rate', state_code='LA') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_la_suta_wage_base', rate='us_la_suta_rate', state_code='LA') + + + + + + + + + EE: US LA Louisiana State Income Tax Withholding + EE_US_LA_SIT + python + result, _ = la_louisiana_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = la_louisiana_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 91dc4352..bf663242 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -25,6 +25,7 @@ from .state.ia_iowa import ia_iowa_state_income_withholding from .state.id_idaho import id_idaho_state_income_withholding from .state.il_illinois import il_illinois_state_income_withholding from .state.in_indiana import in_indiana_state_income_withholding +from .state.la_louisiana import la_louisiana_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 @@ -81,6 +82,7 @@ class HRPayslip(models.Model): 'id_idaho_state_income_withholding': id_idaho_state_income_withholding, 'il_illinois_state_income_withholding': il_illinois_state_income_withholding, 'in_indiana_state_income_withholding': in_indiana_state_income_withholding, + 'la_louisiana_state_income_withholding': la_louisiana_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/la_louisiana.py b/l10n_us_hr_payroll/models/state/la_louisiana.py new file mode 100644 index 00000000..0697d696 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/la_louisiana.py @@ -0,0 +1,60 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def la_louisiana_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'LA' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('la_l4_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + pay_periods = payslip.dict.get_pay_periods_in_year() + personal_exemptions = payslip.contract_id.us_payroll_config_value('la_l4_sit_exemptions') + dependent_exemptions = payslip.contract_id.us_payroll_config_value('la_l4_sit_dependents') + tax_table = payslip.rule_parameter('us_la_sit_tax_rate')[filing_status] + exemption_rate = payslip.rule_parameter('us_la_sit_personal_exemption_rate') + dependent_rate = payslip.rule_parameter('us_la_sit_dependent_rate') + + annual_wage = wage * pay_periods + + effect_cap = 0.0 + multiplier = 0.0 + if filing_status == 'single': + effect_cap = 12500.00 + multiplier = 1.60 + elif filing_status == 'married': + effect_cap = 25000.00 + multiplier = 1.65 + + after_credits_under = (2.100 / 100) * (((personal_exemptions * exemption_rate) + + (dependent_exemptions * dependent_rate)) / pay_periods) + after_credits_over = 0.00 + if after_credits_under > effect_cap: + after_credits_under = effect_cap + after_credits_over_check = ((personal_exemptions * exemption_rate) + (dependent_exemptions * dependent_rate)) - effect_cap + after_credits_over = (multiplier / 100.00) * (after_credits_over_check / pay_periods) if after_credits_over_check > 0 else 0.00 + withholding = 0.0 + last = 0.0 + for amt, rate in tax_table: + withholding = withholding + ((rate / 100.0) * (wage - (last / pay_periods))) + if annual_wage <= float(amt): + break + last = amt + + withholding = withholding - (after_credits_under + after_credits_over) + withholding = round(withholding, 2) + 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 cf5a7c81..d548e87c 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -126,6 +126,14 @@ class HRContractUSPayrollConfig(models.Model): in_w4_sit_personal_exemption = fields.Integer(string='Indiana In-W-4 Number of Personal Exemption', help='IN-W-4 5.') in_w4_sit_dependent_exemption = fields.Integer(string='Indiana In-W-4 Number of Dependent Exemption', help='IN-W-4 6.') + + la_l4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ], string='Louisiana LA L-4 Filing Status', help='LA L-4 3.') + la_l4_sit_exemptions = fields.Integer(string='Louisiana LA L-4 Number of Exemptions', help='LA L-4 6.') + la_l4_sit_dependents = fields.Integer(string='Louisiana LA L-4 Number of Dependents', help='LA L-4 7.') + 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 aa4fc5ab..526762c3 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -46,6 +46,9 @@ from . import test_us_il_illinois_payslip_2020 from . import test_us_in_indiana_payslip_2020 +from . import test_us_la_louisiana_payslip_2019 +from . import test_us_la_louisiana_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_la_louisiana_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py new file mode 100644 index 00000000..f723744a --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py @@ -0,0 +1,87 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .common import TestUsPayslip, process_payslip + + +class TestUsLAPayslip(TestUsPayslip): + + # TAXES AND RATES + LA_UNEMP_MAX_WAGE = 7700.00 + LA_UNEMP = -(6.20 / 100.0) + + def test_taxes_single_weekly(self): + salary = 700.00 + schedule_pay = 'weekly' + filing_status = 'single' + exemptions = 1 + dependents = 2 + # SEE http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf for example calculations + # wh_to test is 19.42 + # Our algorithm correctly rounds whereas theirs does it prematurely. + wh_to_check = -19.43 + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('LA'), + la_l4_sit_filing_status=filing_status, + la_l4_sit_exemptions=exemptions, + la_l4_sit_dependents=dependents, + schedule_pay=schedule_pay) + + self._log('2019 Louisiana 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.LA_UNEMP) + self.assertPayrollEqual(cats['EE_US_SIT'], wh_to_check) + + process_payslip(payslip) + + remaining_la_unemp_wages = self.LA_UNEMP_MAX_WAGE - salary if (self.LA_UNEMP_MAX_WAGE - 2*salary < salary) \ + else salary + + self._log('2019 Louisiana 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_la_unemp_wages * self.LA_UNEMP) + + def test_taxes_married_biweekly(self): + salary = 4600.00 + schedule_pay = 'bi-weekly' + filing_status = 'married' + exemptions = 2 + dependents = 3 + # SEE http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf for example calculations + # wh_to test is 157.12 + wh_to_check = -157.12 + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('LA'), + la_l4_sit_filing_status=filing_status, + la_l4_sit_exemptions=exemptions, + la_l4_sit_dependents=dependents, + schedule_pay=schedule_pay) + + self._log('2019 Louisiana tax first payslip bi-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.LA_UNEMP) + self.assertPayrollEqual(cats['EE_US_SIT'], wh_to_check) + + process_payslip(payslip) + + remaining_la_unemp_wages = self.LA_UNEMP_MAX_WAGE - salary if (self.LA_UNEMP_MAX_WAGE - 2*salary < salary) \ + else salary + + self._log('2019 Louisiana tax second payslip bi-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_la_unemp_wages * self.LA_UNEMP) diff --git a/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py new file mode 100755 index 00000000..14dde5bf --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py @@ -0,0 +1,34 @@ +# 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 TestUsLAPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + LA_UNEMP_MAX_WAGE = 7700.0 + LA_UNEMP = 6.20 + # Calculation based on http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf + + def _test_sit(self, wage, filing_status, exemptions, dependents, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('LA'), + la_l4_sit_filing_status=filing_status, + la_l4_sit_exemptions=exemptions, + la_l4_sit_dependents=dependents, + 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('LA', self.LA_UNEMP, date(2020, 1, 1), wage_base=self.LA_UNEMP_MAX_WAGE) + self._test_sit(700.0, 'single', 1.0, 2.0, 'weekly', date(2020, 1, 1), 19.43) + self._test_sit(4600.0, 'married', 2.0, 3.0, 'bi-weekly', date(2020, 1, 1), 157.12) 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 a294fa51..7865d1f8 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -125,6 +125,12 @@
+ +

Form LA L-4 - State Income Tax

+ + + +

Form MI-W4 - State Income Tax

From e96ae2dde4b855ff27b507513b40400fb200e021 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 1 Apr 2020 14:05:09 -0400 Subject: [PATCH 03/63] IMP `l10n_us_hr_payroll` Port `l10n_us_sc_hr_payroll` SC South Carolina including migration --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/sc_south_carolina.xml | 149 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/sc_south_carolina.py | 48 ++++++ .../models/us_payroll_config.py | 1 + l10n_us_hr_payroll/tests/__init__.py | 3 + .../test_us_sc_south_carolina_payslip_2019.py | 97 ++++++++++++ .../test_us_sc_south_carolina_payslip_2020.py | 34 ++++ .../views/us_payroll_config_views.xml | 5 + 9 files changed, 340 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/sc_south_carolina.xml create mode 100644 l10n_us_hr_payroll/models/state/sc_south_carolina.py create mode 100644 l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2019.py create mode 100644 l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index fee61b48..c8a0acaf 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -52,6 +52,7 @@ United States of America - Payroll Rules. 'data/state/nm_new_mexico.xml', 'data/state/oh_ohio.xml', 'data/state/pa_pennsylvania.xml', + 'data/state/sc_south_carolina.xml', 'data/state/tx_texas.xml', 'data/state/va_virginia.xml', 'data/state/wa_washington.xml', diff --git a/l10n_us_hr_payroll/data/state/sc_south_carolina.xml b/l10n_us_hr_payroll/data/state/sc_south_carolina.xml new file mode 100644 index 00000000..95867646 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/sc_south_carolina.xml @@ -0,0 +1,149 @@ + + + + + US SC South Carolina SUTA Wage Base + us_sc_suta_wage_base + + + + + 14000.0 + + + + + 14000.0 + + + + + + + + US SC South Carolina SUTA Rate + us_sc_suta_rate + + + + + 1.09 + + + + + 1.09 + + + + + + + US SC South Carolina SIT Tax Rate + us_sc_sit_tax_rate + + + + + [ + ( 2450, 1.1, 0.0), + ( 4900, 3.0, 26.95), + ( 7350, 4.0, 100.45), + ( 9800, 5.0, 198.45), + (12250, 6.0, 320.95), + ('inf', 7.0, 467.95), + ] + + + + + [ + ( 2620, 0.8, 0.0), + ( 5240, 3.0, 57.64), + ( 7860, 4.0, 110.04), + (10490, 5.0, 188.64), + (13110, 6.0, 293.54), + ('inf', 7.0, 424.64), + ] + + + + + + + US SC South Carolina Personal Exemption Rate + us_sc_sit_personal_exemption_rate + + + + + 2510 + + + + + 2590 + + + + + + + US SC South Carolina Standard Deduction Rate + us_sc_sit_standard_deduction_rate + + + + + 3470.0 + + + + + 3820.0 + + + + + + + + US South Carolina - Department of Labor and Industrial Relations - Unemployment Tax + + + + US South Carolina - Department of Taxation - Income Tax + + + + + + + + + + ER: US SC South Carolina State Unemployment + ER_US_SC_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_sc_suta_wage_base', rate='us_sc_suta_rate', state_code='SC') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_sc_suta_wage_base', rate='us_sc_suta_rate', state_code='SC') + + + + + + + + + EE: US SC South Carolina State Income Tax Withholding + EE_US_SC_SIT + python + result, _ = sc_south_carolina_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = sc_south_carolina_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 bf663242..a35f3b38 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -35,6 +35,7 @@ from .state.nc_northcarolina import nc_northcarolina_state_income_withholding from .state.nj_newjersey import nj_newjersey_state_income_withholding from .state.nm_new_mexico import nm_new_mexico_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding +from .state.sc_south_carolina import sc_south_carolina_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 @@ -92,6 +93,7 @@ class HRPayslip(models.Model): 'nj_newjersey_state_income_withholding': nj_newjersey_state_income_withholding, 'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding, 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, + 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, '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, diff --git a/l10n_us_hr_payroll/models/state/sc_south_carolina.py b/l10n_us_hr_payroll/models/state/sc_south_carolina.py new file mode 100644 index 00000000..169961eb --- /dev/null +++ b/l10n_us_hr_payroll/models/state/sc_south_carolina.py @@ -0,0 +1,48 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def sc_south_carolina_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 = 'SC' + if not _state_applies(payslip, state_code): + return 0.0, 0.0 + + personal_exempt = payslip.contract_id.us_payroll_config_value('state_income_tax_exempt') + if personal_exempt: + 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() + allowances = payslip.contract_id.us_payroll_config_value('sc_w4_sit_allowances') + tax_rate = payslip.rule_parameter('us_sc_sit_tax_rate') + personal_exemption = payslip.rule_parameter('us_sc_sit_personal_exemption_rate') + deduction = payslip.rule_parameter('us_sc_sit_standard_deduction_rate') + + annual_wage = wage * pay_periods + personal_exemption_amt = allowances * personal_exemption + standard_deduction = 0.0 + if allowances > 0: + if (annual_wage * 0.1) > deduction: + standard_deduction = deduction + else: + standard_deduction = annual_wage * (10 / 100) + taxable_income = annual_wage - personal_exemption_amt - standard_deduction + withholding = 0.0 + last = 0.0 + for cap, rate, flat_amt in tax_rate: + if float(cap) > taxable_income: + withholding = (taxable_income * (rate / 100.0) - flat_amt) + break + withholding /= pay_periods + 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 d548e87c..5abc4759 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -202,6 +202,7 @@ class HRContractUSPayrollConfig(models.Model): # Ohio will use generic SIT exempt and additional fields oh_it4_sit_exemptions = fields.Integer(string='Ohio IT-4 Exemptions', help='Line 4') + sc_w4_sit_allowances = fields.Integer(string='South Carolina SC W-4 Allowances', help='SC W-4 5.') va_va4_sit_exemptions = fields.Integer(string='Virginia VA-4(P) Personal Exemptions', help='VA-4(P) 1(a)') diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 526762c3..85be27cb 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -80,6 +80,9 @@ from . import test_us_oh_ohio_payslip_2020 from . import test_us_pa_pennsylvania_payslip_2019 from . import test_us_pa_pennsylvania_payslip_2020 +from . import test_us_sc_south_carolina_payslip_2019 +from . import test_us_sc_south_carolina_payslip_2020 + from . import test_us_tx_texas_payslip_2019 from . import test_us_tx_texas_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2019.py new file mode 100644 index 00000000..793f84c4 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2019.py @@ -0,0 +1,97 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .common import TestUsPayslip, process_payslip + + +class TestUsSCPayslip(TestUsPayslip): + + # Taxes and Rates + SC_UNEMP_MAX_WAGE = 14000.0 + US_SC_UNEMP = -1.09 / 100 + US_SC_exemption_amount = 2510.00 + + def test_2019_taxes_weekly(self): + # We will hand calculate the amount to test for state withholding. + schedule_pay = 'weekly' + salary = 50000.00 # Employee is paid 50000 per week to be in top tax bracket + allowances = 2 + # Calculate annual wages + annual = 50000 * 52.0 + # From our annual we deduct personal exemption amounts. + # We deduct 2510.00 per exemption. Since we have two exemptions: + personal_exemption = self.US_SC_exemption_amount * allowances # 5020.0 + # From annual, we will also deduct a standard_deduction of 3470.00 or .1 of salary, which ever + # is small -> if 1 or more exemptions, else 0 + standard_deduction = 3470.00 + taxable_income = annual - personal_exemption - standard_deduction # 2591510.0 + # We then calculate the amounts off the SC tax pdf tables. + # 2591478.0 is in the highest bracket + test_amt = (taxable_income * (7.0 / 100.0)) - 467.95 + test_amt = 180935.51 + # Make it per period then negative + test_amt = (test_amt / 52.0) # Divided by 52 since it is weekly. + # test_amt = 3479.52 + test_amt = -test_amt + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('SC'), + state_income_tax_exempt=False, + sc_w4_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self._log('2019 South Carolina tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + payslip.compute_sheet() + cats = self._getCategories(payslip) + + self.assertPayrollAlmostEqual(cats['ER_US_SUTA'], self.SC_UNEMP_MAX_WAGE * self.US_SC_UNEMP) + self.assertPayrollAlmostEqual(cats['EE_US_SIT'], test_amt) + + process_payslip(payslip) + + remaining_SC_UNEMP_wages = self.SC_UNEMP_MAX_WAGE - annual if (annual < self.SC_UNEMP_MAX_WAGE) \ + else 0.00 + + self._log('2019 South Carolina tax second payslip:') + + payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28') + payslip.compute_sheet() + cats = self._getCategories(payslip) + + self.assertEqual(0.0, remaining_SC_UNEMP_wages) + self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_SC_UNEMP_wages * self.US_SC_UNEMP) + + def test_2019_taxes_filing_status(self): + salary = 20000.00 # Wages per pay period + schedule_pay = 'monthly' + annual = salary * 12 + allowances = 1 + # Hand Calculations + personal_exemption = 2510.00 + standard_deduction = min(3470.00, .1 * annual) # 3470.0 but min is shown for the process + taxable = annual - personal_exemption - standard_deduction + # taxable = 234020 + test_amt = ((taxable) * (7.0 / 100.0)) - 467.95 # 15991.850000000002 + test_amt = test_amt / 12.0 # Put it into monthly -> 1332.654166666667 + # Make it negative + test_amt = -test_amt + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('SC'), + state_income_tax_exempt=False, + sc_w4_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self._log('2019 South Carolina tax first payslip: ') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + payslip.compute_sheet() + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['ER_US_SUTA'], self.SC_UNEMP_MAX_WAGE * self.US_SC_UNEMP) + self.assertPayrollAlmostEqual(cats['EE_US_SIT'], test_amt) + + process_payslip(payslip) diff --git a/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py new file mode 100644 index 00000000..e17a8052 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py @@ -0,0 +1,34 @@ +# 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 TestUsSCPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + SC_UNEMP_MAX_WAGE = 14000.0 + SC_UNEMP = 1.09 + # Calculation based on https://dor.sc.gov/forms-site/Forms/WH1603F_2020.pdf + + def _test_sit(self, wage, exempt, allowances, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('SC'), + state_income_tax_exempt=exempt, + sc_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.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + + def test_2020_taxes_example(self): + self._test_er_suta('SC', self.SC_UNEMP, date(2020, 1, 1), wage_base=self.SC_UNEMP_MAX_WAGE) + self._test_sit(750.0, False, 3.0, 'weekly', date(2020, 1, 1), 28.73) + self._test_sit(800.0, True, 0.0, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(9000.0, False, 0.0, 'monthly', date(2020, 1, 1), 594.61) 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 7865d1f8..a517bdb4 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -191,6 +191,11 @@
+ +

Form SC W-4 - State Income Tax

+ + +

No additional fields.

From ef25f0c3ebe2a1985bed6d127157459884f19f6d Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 14 Apr 2020 12:44:08 -0400 Subject: [PATCH 04/63] IMP `l10n_us_hr_payroll` for Nebraska 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ne_nebraska.xml | 125 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/ne_nebraska.py | 49 +++++++ .../models/us_payroll_config.py | 6 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_ne_nebraska_payslip_2020.py | 37 ++++++ .../views/us_payroll_config_views.xml | 7 + 8 files changed, 229 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ne_nebraska.xml create mode 100644 l10n_us_hr_payroll/models/state/ne_nebraska.py create mode 100644 l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index c8a0acaf..65318ff4 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -47,6 +47,7 @@ United States of America - Payroll Rules. 'data/state/ms_mississippi.xml', 'data/state/mt_montana.xml', 'data/state/nc_northcarolina.xml', + 'data/state/ne_nebraska.xml', 'data/state/nh_new_hampshire.xml', 'data/state/nj_newjersey.xml', 'data/state/nm_new_mexico.xml', diff --git a/l10n_us_hr_payroll/data/state/ne_nebraska.xml b/l10n_us_hr_payroll/data/state/ne_nebraska.xml new file mode 100644 index 00000000..4db292ba --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ne_nebraska.xml @@ -0,0 +1,125 @@ + + + + + US NE Nebraska SUTA Wage Base + us_ne_suta_wage_base + + + + + 9000.0 + + + + + + + + US NE Nebraska SUTA Rate + us_ne_suta_rate + + + + + 1.25 + + + + + + + US NE Nebraska SIT Tax Rate + us_ne_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((57, 0.00, 0.0), (105, 0.00, 2.26), (342, 1.08, 3.22), (496, 8.71, 4.91), (629, 16.27, 6.20), (1182, 24.52, 6.59), ('inf', 60.96, 6.95)), + 'bi-weekly': ((114, 0.00, 0.0), (211, 0.00, 2.26), (684, 2.19, 3.22), (992, 17.42, 4.91), (1259, 32.54, 6.20), (2364, 49.09, 6.59), ('inf', 121.91, 6.95)), + 'semi-monthly': ((124, 0.00, 0.0), (228, 0.00, 2.26), (741, 2.35, 3.22), (1074, 18.87, 4.91), (1364, 35.22, 6.20), (2561, 53.20, 6.59), ('inf', 132.08, 6.95)), + 'monthly': ((248, 0.00, 0.0), (457, 0.00, 2.26), (1483, 4.72, 3.22), (2148, 37.76, 4.91), (2728, 70.41, 6.20), (5123, 106.37, 6.59), ('inf', 264.20, 6.95)), + 'quarterly': ((744, 0.00, 0.0), (1370, 0.00, 2.26), (4448, 14.15, 3.22), (6445, 113.26, 4.91), (8183, 211.31, 6.20), (15368, 319.07, 6.59), ('inf', 792.56, 6.95)), + 'semi-annual': ((1488, 0.00, 0.0), (2740, 0.00, 2.26), (8895, 28.30, 3.22), (12890, 226.49, 4.91), (16365, 422.64, 6.20), (30735, 638.09, 6.59), ('inf', 1585.07, 6.95)), + 'annually': ((2975, 0.00, 0.0), (5480, 0.00, 2.26), (17790, 56.61, 3.22), (25780, 452.99, 4.91), (32730, 845.30, 6.20), (61470, 1276.20, 6.59), ('inf', 3170.17, 6.95)), + }, + 'married': { + 'weekly': ((137, 0.00, 0.0), (204, 0.00, 2.26), (508, 1.51, 3.22), (790, 11.30, 4.91), (981, 25.15, 6.20), (1300, 36.99, 6.59), ('inf', 58.01, 6.95)), + 'bi-weekly': ((273, 0.00, 0.0), (408, 0.00, 2.26), (1016, 3.05, 3.22), (1581, 22.63, 4.91), (1961, 50.37, 6.20), (2601, 73.93, 6.59), ('inf', 116.11, 6.95)), + 'semi-monthly': ((296, 0.00, 0.0), (442, 0.00, 2.26), (1101, 3.30, 3.22), (1713, 24.52, 4.91), (2125, 54.57, 6.20), (2818, 80.11, 6.59), ('inf', 125.78, 6.95)), + 'monthly': ((592, 0.00, 0.0), (884, 0.00, 2.26), (2202, 6.60, 3.22), (3425, 49.04, 4.91), (4249, 109.09, 6.20), (5635, 160.18, 6.59), ('inf', 251.52, 6.95)), + 'quarterly': ((1775, 0.00, 0.0), (2653, 0.00, 2.26), (6605, 19.84, 3.22), (10275, 147.09, 4.91), (12748, 327.29, 6.20), (16905, 480.62, 6.59), ('inf', 754.57, 6.95)), + 'semi-annual': ((3550, 0.00, 0.0), (5305, 0.00, 2.26), (13210, 39.66, 3.22), (20550, 294.20, 4.91), (25495, 654.59, 6.20), (33810, 961.18, 6.59), ('inf', 1509.14, 6.95)), + 'annually': ((7100, 0.00, 0.0), (10610, 0.00, 2.26), (26420, 79.33, 3.22), (41100, 588.41, 4.91), (50990, 1309.20, 6.20), (67620, 1992.38, 6.59), ('inf', 3018.30, 6.95)), + }, + } + + + + + + + US NE Nebraska Allowances Rate + us_ne_sit_allowances_rate + + + + + { + 'weekly' : 37.69, + 'bi-weekly' : 75.38, + 'semi-monthly': 81.67, + 'monthly' : 163.33, + 'quarterly' : 490.00, + 'semi-annual': 980.00, + 'annually': 1960.00, + } + + + + + + + + + US Nebraska - Nebraska Department of Labor - Unemployment Tax + + + + US Nebraska - Nebraska Department of Revenue - Income Tax + + + + + + + + + + ER: US NE Nebraska State Unemployment + ER_US_NE_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ne_suta_wage_base', rate='us_ne_suta_rate', state_code='NE') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ne_suta_wage_base', rate='us_ne_suta_rate', state_code='NE') + + + + + + + + + EE: US NE Nebraska State Income Tax Withholding + EE_US_NE_SIT + python + result, _ = ne_nebraska_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ne_nebraska_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 a35f3b38..a45a9613 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -32,6 +32,7 @@ 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 from .state.nc_northcarolina import nc_northcarolina_state_income_withholding +from .state.ne_nebraska import ne_nebraska_state_income_withholding from .state.nj_newjersey import nj_newjersey_state_income_withholding from .state.nm_new_mexico import nm_new_mexico_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding @@ -90,6 +91,7 @@ class HRPayslip(models.Model): 'ms_mississippi_state_income_withholding': ms_mississippi_state_income_withholding, 'mt_montana_state_income_withholding': mt_montana_state_income_withholding, 'nc_northcarolina_state_income_withholding': nc_northcarolina_state_income_withholding, + 'ne_nebraska_state_income_withholding': ne_nebraska_state_income_withholding, 'nj_newjersey_state_income_withholding': nj_newjersey_state_income_withholding, 'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding, 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/ne_nebraska.py b/l10n_us_hr_payroll/models/state/ne_nebraska.py new file mode 100644 index 00000000..9b360778 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ne_nebraska.py @@ -0,0 +1,49 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ne_nebraska_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 = 'NE' + if not _state_applies(payslip, state_code): + return 0.0, 0.0 + + personal_exempt = payslip.contract_id.us_payroll_config_value('state_income_tax_exempt') + if personal_exempt: + return 0.0, 0.0 + + # Determine Wage + wage = sit_wage(payslip, categories) + if not wage: + return 0.0, 0.0 + + filing_status = payslip.contract_id.us_payroll_config_value('ne_w4n_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + allowances = payslip.contract_id.us_payroll_config_value('ne_w4n_sit_allowances') + tax_rate = payslip.rule_parameter('us_ne_sit_tax_rate')[filing_status].get(schedule_pay) + sit_allowance = payslip.rule_parameter('us_ne_sit_allowances_rate')[schedule_pay] + + allowance_amt = allowances * sit_allowance + taxable_income = wage - allowance_amt + withholding = 0.0 + last = 0.0 + for row in tax_rate: + amt, flat_fee, rate = row + if taxable_income < float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(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 5abc4759..3677d3e2 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -182,6 +182,12 @@ class HRContractUSPayrollConfig(models.Model): ], string='North Carolina NC-4 Filing Status', help='NC-4') nc_nc4_sit_allowances = fields.Integer(string='North Carolina NC-4 Allowances', help='NC-4 1.') + ne_w4n_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ], string='Nebraska NE W-4N Filing Status', help='NE W-4N') + ne_w4n_sit_allowances = fields.Integer(string='Nebraska NE W-4N Allowances', help='NE W-4N 1.') + nj_njw4_sit_filing_status = fields.Selection([ ('', 'Exempt'), ('single', 'Single'), diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 85be27cb..06c618b6 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -67,6 +67,8 @@ from . import test_us_mt_montana_payslip_2020 from . import test_us_nc_northcarolina_payslip_2019 from . import test_us_nc_northcarolina_payslip_2020 +from . import test_us_ne_nebraska_payslip_2020 + from . import test_us_nh_new_hampshire_payslip_2020 from . import test_us_nj_newjersey_payslip_2019 diff --git a/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py new file mode 100644 index 00000000..bbf2b7b0 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ne_nebraska_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 TestUsNEPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + NE_UNEMP_MAX_WAGE = 9000.0 + NE_UNEMP = 1.25 + + def _test_sit(self, wage, filing_status, 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('NE'), + ne_w4n_sit_filing_status=filing_status, + state_income_tax_exempt=exempt, + state_income_tax_additional_withholding=additional_withholding, + ne_w4n_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('NE', self.NE_UNEMP, date(2020, 1, 1), wage_base=self.NE_UNEMP_MAX_WAGE) + self._test_sit(750.0, 'single', False, 0.0, 2, 'weekly', date(2020, 1, 1), 27.53) + self._test_sit(9500.0, 'single', False, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 612.63) + self._test_sit(10500.0, 'married', False, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 659.85) + self._test_sit(9500.0, 'single', True, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 0.0) + self._test_sit(10500.0, 'single', False, 10.0, 2, 'monthly', date(2020, 1, 1), 625.2) \ No newline at end of file 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 a517bdb4..9c95f730 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -167,6 +167,13 @@ + +

Form NC-4 - State Income Tax

+ + + + +

No additional fields.

From 45e589ba0ad5940867b9019754d4d2a5a748ea18 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 14 Apr 2020 12:49:34 -0400 Subject: [PATCH 05/63] IMP `l10n_us_hr_payroll` Port `l10n_us_ny_hr_payroll` NY New York including migration --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ny_new_york.xml | 279 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/ny_new_york.py | 54 ++++ .../models/us_payroll_config.py | 7 + l10n_us_hr_payroll/tests/__init__.py | 3 + .../tests/test_us_ny_new_york_payslip_2019.py | 106 +++++++ .../tests/test_us_ny_new_york_payslip_2020.py | 38 +++ .../views/us_payroll_config_views.xml | 6 + 9 files changed, 496 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ny_new_york.xml create mode 100644 l10n_us_hr_payroll/models/state/ny_new_york.py create mode 100644 l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py create mode 100644 l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 65318ff4..f49d1257 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -51,6 +51,7 @@ United States of America - Payroll Rules. 'data/state/nh_new_hampshire.xml', 'data/state/nj_newjersey.xml', 'data/state/nm_new_mexico.xml', + 'data/state/ny_new_york.xml', 'data/state/oh_ohio.xml', 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', diff --git a/l10n_us_hr_payroll/data/state/ny_new_york.xml b/l10n_us_hr_payroll/data/state/ny_new_york.xml new file mode 100644 index 00000000..d3f4cc10 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ny_new_york.xml @@ -0,0 +1,279 @@ + + + + + US NY New York SUTA Wage Base + us_ny_suta_wage_base + + + + + 14000.0 + + + + + 14000.0 + + + + + + + + US NY New York SUTA Rate + us_ny_suta_rate + + + + + 1.09 + + + + + 3.295 + + + + + + + US NY New York SUTA RSF Rate + us_ny_suta_rsf_rate + + + + + 0.075 + + + + + 0.075 + + + + + + + US NY New York SUTA MCTMT Rate + us_ny_suta_mctmt_rate + + + + + 0.0 + + + + + 0.0 + + + + + + + US NY New York SIT Tax Rate + us_ny_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0758, 112.58), (3032, 0.0808, 128.38), (4142, 0.0707, 206.08), (5104, 0.0856, 284.60), (20722, 0.0735, 366.90), (21684, 0.5208, 1514.85), ('inf', 0.0962, 2015.62)), + 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0758, 225.15), (6063, 0.0808, 256.77), (8285, 0.0707, 412.15), (10208, 0.0856, 569.19), (41444, 0.0735, 733.81), (43367, 0.5208, 3029.69), ('inf', 0.0962, 4021.23)), + 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0758, 243.92), (6569, 0.0808, 278.17), (8975, 0.0707, 446.50), (11058, 0.0856, 616.63), (44898, 0.0735, 794.96), (46981, 0.5208, 3282.17), ('inf', 0.0962, 4367.17)), + 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0758, 487.83), (13138, 0.0808, 556.33), (17950, 0.0707, 893.00), (22117, 0.0856, 1233.25), (89796, 0.0735, 1589.92), (93963, 0.5208, 6564.33), ('inf', 0.0962, 8734.33)), + 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0758, 5854.00), (157650, 0.0808, 6676.00), (215400, 0.0707, 10716.00), (265400, 0.0856, 14799.00), (1077550, 0.0735, 19079.00), (1127550, 0.5208, 78772.00), ('inf', 0.0962, 104812.00)), + }, + 'married': { + 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0783, 112.58), (3032, 0.0833, 128.90), (4068, 0.0785, 209.00), (6215, 0.0707, 290.37), (7177, 0.0916, 442.17), (20722, 0.0735, 530.25), (41449, 0.0765, 1525.83), (42411, 0.9454, 3111.42), ('inf', 0.0962, 4020.46)), + 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0783, 225.15), (6063, 0.0833, 257.81), (8137, 0.0785, 418.00), (12431, 0.0707, 580.73), (14354, 0.0916, 884.35), (41444, 0.0735, 1060.50), (82898, 0.0765, 3051.65), (84821, 0.9454, 6222.85), ('inf', 0.0962, 8040.92)), + 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0783, 243.92), (6569, 0.0833, 279.29), (8815, 0.0785, 452.83), (13476, 0.0707, 629.13), (15550, 0.0916, 958.04), (44898, 0.0735, 1148.88), (89806, 0.0765, 3305.96), (91890, 0.9454, 6741.42), ('inf', 0.0962, 8711.00)), + 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0783, 487.83), (13138, 0.0833, 558.58), (17629, 0.0785, 905.67), (26933, 0.0707, 1258.25), (31100, 0.0916, 1916.08), (89796, 0.0735, 2297.75), (179613, 0.0765, 6611.92), (183779, 0.9454, 13482.83), ('inf', 0.0962, 17422.00)), + 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0783, 5854.00), (157650, 0.0833, 6703.00), (211550, 0.0785, 10868.00), (323200, 0.0707, 15099.00), (373200, 0.0916, 22993.00), (1077550, 0.0735, 27573.00), (2155350, 0.0765, 79343.00), (2205350, 0.9454, 161794.00), ('inf', 0.0962, 209064.00)), + } + } + + + + + { + 'single': { + 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0758, 112.58), (3032, 0.0808, 128.38), (4142, 0.0707, 206.08), (5104, 0.0856, 284.60), (20722, 0.0735, 366.90), (21684, 0.5208, 1514.85), ('inf', 0.0962, 2015.62)), + 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0758, 225.15), (6063, 0.0808, 256.77), (8285, 0.0707, 412.15), (10208, 0.0856, 569.19), (41444, 0.0735, 733.81), (43367, 0.5208, 3029.69), ('inf', 0.0962, 4021.23)), + 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0758, 243.92), (6569, 0.0808, 278.17), (8975, 0.0707, 446.50), (11058, 0.0856, 616.63), (44898, 0.0735, 794.96), (46981, 0.5208, 3282.17), ('inf', 0.0962, 4367.17)), + 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0758, 487.83), (13138, 0.0808, 556.33), (17950, 0.0707, 893.00), (22117, 0.0856, 1233.25), (89796, 0.0735, 1589.92), (93963, 0.5208, 6564.33), ('inf', 0.0962, 8734.33)), + 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0758, 5854.00), (157650, 0.0808, 6676.00), (215400, 0.0707, 10716.00), (265400, 0.0856, 14799.00), (1077550, 0.0735, 19079.00), (1127550, 0.5208, 78772.00), ('inf', 0.0962, 104812.00)), + }, + 'married': { + 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0783, 112.58), (3032, 0.0833, 128.90), (4068, 0.0785, 209.00), (6215, 0.0707, 290.37), (7177, 0.0916, 442.17), (20722, 0.0735, 530.25), (41449, 0.0765, 1525.83), (42411, 0.9454, 3111.42), ('inf', 0.0962, 4020.46)), + 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0783, 225.15), (6063, 0.0833, 257.81), (8137, 0.0785, 418.00), (12431, 0.0707, 580.73), (14354, 0.0916, 884.35), (41444, 0.0735, 1060.50), (82898, 0.0765, 3051.65), (84821, 0.9454, 6222.85), ('inf', 0.0962, 8040.92)), + 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0783, 243.92), (6569, 0.0833, 279.29), (8815, 0.0785, 452.83), (13476, 0.0707, 629.13), (15550, 0.0916, 958.04), (44898, 0.0735, 1148.88), (89806, 0.0765, 3305.96), (91890, 0.9454, 6741.42), ('inf', 0.0962, 8711.00)), + 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0783, 487.83), (13138, 0.0833, 558.58), (17629, 0.0785, 905.67), (26933, 0.0707, 1258.25), (31100, 0.0916, 1916.08), (89796, 0.0735, 2297.75), (179613, 0.0765, 6611.92), (183779, 0.9454, 13482.83), ('inf', 0.0962, 17422.00)), + 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0783, 5854.00), (157650, 0.0833, 6703.00), (211550, 0.0785, 10868.00), (323200, 0.0707, 15099.00), (373200, 0.0916, 22993.00), (1077550, 0.0735, 27573.00), (2155350, 0.0765, 79343.00), (2205350, 0.9454, 161794.00), ('inf', 0.0962, 209064.00)), + } + } + + + + + + + US NY New York Over 10 Exemption Rate + us_ny_sit_over_10_exemption_rate + + + + + { + 'weekly': (142.30, 152.90, 19.25), + 'bi-weekly': (284.60, 305.80, 38.50), + 'semi-monthly': (308.35, 331.25, 41.65), + 'monthly': (616.70, 662.50, 83.30), + 'annual': (7400, 7950, 1000), + } + + + + + { + 'weekly': (142.30, 152.90, 19.25), + 'bi-weekly': (284.60, 305.80, 38.50), + 'semi-monthly': (308.35, 331.25, 41.65), + 'monthly': (616.70, 662.50, 83.30), + 'annual': (7400, 7950, 1000), + } + + + + + + + US NY New York Deduction Exemption Rate + us_ny_sit_deduction_exemption_rate + + + + + { + 'single': { + 'weekly': (142.30, 161.55, 180.80, 200.05, 219.30, 238.55, 257.80, 277.05, 296.30, 315.55, 334.80), + 'bi-weekly': (284.60, 323.10, 361.60, 400.10, 438.60, 477.10, 515.60, 544.10, 592.60, 631.10, 669.60), + 'semi-monthly': (308.35, 350.0, 391.65, 433.30, 474.95, 516.60, 558.25, 599.90, 641.55, 683.20, 724.85), + 'monthly': (616.70, 700, 783.30, 866.60, 949.90, 1033.20, 1116.50, 1199.80, 1283.10, 1366.40, 1449.70), + 'annually': (7400, 8400, 9400, 10400, 11400, 12400, 13400, 14400, 15400, 16400, 17400), + }, + 'married': { + 'weekly': (152.90, 172.15, 191.40, 210.65, 229.90, 249.15, 268.40, 287.65, 306.90, 326.15, 345.40), + 'bi-weekly': (305.80, 344.30, 382.80, 421.30, 459.80, 498.30, 536.80, 575.30, 613.80, 652.30, 690.80), + 'semi-monthly': (331.25, 372.90, 414.55, 456.20, 497.85, 539.50, 581.15, 622.80, 664.45, 706.10, 747.75), + 'monthly': (662.50, 745.80, 829.10, 912.40, 995.70, 1079.00, 1162.30, 1245.60, 1328.90, 1412.20, 1495.50), + 'annually': (7950, 8950, 9950, 10950, 11950, 12950, 13950, 14950, 15950, 16950, 17950), + }, + } + + + + + { + 'single': { + 'weekly': (142.30, 161.55, 180.80, 200.05, 219.30, 238.55, 257.80, 277.05, 296.30, 315.55, 334.80), + 'bi-weekly': (284.60, 323.10, 361.60, 400.10, 438.60, 477.10, 515.60, 544.10, 592.60, 631.10, 669.60), + 'semi-monthly': (308.35, 350.0, 391.65, 433.30, 474.95, 516.60, 558.25, 599.90, 641.55, 683.20, 724.85), + 'monthly': (616.70, 700, 783.30, 866.60, 949.90, 1033.20, 1116.50, 1199.80, 1283.10, 1366.40, 1449.70), + 'annually': (7400, 8400, 9400, 10400, 11400, 12400, 13400, 14400, 15400, 16400, 17400), + }, + 'married': { + 'weekly': (152.90, 172.15, 191.40, 210.65, 229.90, 249.15, 268.40, 287.65, 306.90, 326.15, 345.40), + 'bi-weekly': (305.80, 344.30, 382.80, 421.30, 459.80, 498.30, 536.80, 575.30, 613.80, 652.30, 690.80), + 'semi-monthly': (331.25, 372.90, 414.55, 456.20, 497.85, 539.50, 581.15, 622.80, 664.45, 706.10, 747.75), + 'monthly': (662.50, 745.80, 829.10, 912.40, 995.70, 1079.00, 1162.30, 1245.60, 1328.90, 1412.20, 1495.50), + 'annually': (7950, 8950, 9950, 10950, 11950, 12950, 13950, 14950, 15950, 16950, 17950), + }, + } + + + + + + + + US New York - Department of Taxation and Finance - Unemployment Tax + + + + US New York - Department of Taxation and Finance - Re-employment Service Fund + + + + US New York - Department of Taxation and Finance - Metropolitan Commuter Transportation Mobility Tax + + + + US New York - Department of Taxation and Finance - Income Tax + + + + + + + + + + ER: US NY New York State Unemployment + ER_US_NY_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rate', state_code='NY') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rate', state_code='NY') + + + + + + + + + ER: US NY New York State Re-employment Service Fund + ER_US_NY_SUTA_RSF + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rsf_rate', state_code='NY') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rsf_rate', state_code='NY') + + + + + + + + + ER: US NY New York State Metropolitan Commuter Transportation Mobility Tax + ER_US_NY_SUTA_MCTMT + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_mctmt_rate', state_code='NY') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_mctmt_rate', state_code='NY') + + + + + + + + + EE: US NY New York State Income Tax Withholding + EE_US_NY_SIT + python + result, _ = ny_new_york_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ny_new_york_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 a45a9613..08207043 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -35,6 +35,7 @@ from .state.nc_northcarolina import nc_northcarolina_state_income_withholding from .state.ne_nebraska import ne_nebraska_state_income_withholding from .state.nj_newjersey import nj_newjersey_state_income_withholding from .state.nm_new_mexico import nm_new_mexico_state_income_withholding +from .state.ny_new_york import ny_new_york_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding from .state.sc_south_carolina import sc_south_carolina_state_income_withholding from .state.va_virginia import va_virginia_state_income_withholding @@ -94,6 +95,7 @@ class HRPayslip(models.Model): 'ne_nebraska_state_income_withholding': ne_nebraska_state_income_withholding, 'nj_newjersey_state_income_withholding': nj_newjersey_state_income_withholding, 'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding, + 'ny_new_york_state_income_withholding': ny_new_york_state_income_withholding, 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, 'va_virginia_state_income_withholding': va_virginia_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/ny_new_york.py b/l10n_us_hr_payroll/models/state/ny_new_york.py new file mode 100644 index 00000000..1a710b32 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ny_new_york.py @@ -0,0 +1,54 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ny_new_york_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'NY' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('ny_it2104_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + tax_table = payslip.rule_parameter('us_ny_sit_tax_rate')[filing_status].get(schedule_pay) + allowances = payslip.contract_id.us_payroll_config_value('ny_it2104_sit_allowances') + over_10_deduction = payslip.rule_parameter('us_ny_sit_over_10_exemption_rate')[schedule_pay] + deduction_exemption = payslip.rule_parameter('us_ny_sit_deduction_exemption_rate')[filing_status].get(schedule_pay) + + if allowances > 10: + if filing_status == 'single': + wage -= over_10_deduction[0] + over_10_deduction[2] * allowances + elif filing_status == 'married': + wage -= over_10_deduction[1] + over_10_deduction[2] * allowances + + else: + if filing_status == 'single': + wage -= deduction_exemption[allowances] + elif filing_status == 'married': + wage -= deduction_exemption[allowances] + last = 0.0 + withholding = 0.0 + for row in tax_table: + amt, rate, flat_fee = row + if wage <= float(amt): + withholding = ((wage - last) * rate) + flat_fee + break + last = amt + + withholding = max(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 3677d3e2..1e03673e 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -205,6 +205,13 @@ class HRContractUSPayrollConfig(models.Model): ('E', 'E') ], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.') + ny_it2104_sit_filing_status = fields.Selection([ + ('', 'Exempt'), + ('single', 'Single'), + ('married', 'Married'), + ], string='New York NY IT-2104 Filing Status', help='NY IT-2104') + ny_it2104_sit_allowances = fields.Integer(string="New York IT-2104 Allowances", help="NY IT-2104 1. 2.") + # Ohio will use generic SIT exempt and additional fields oh_it4_sit_exemptions = fields.Integer(string='Ohio IT-4 Exemptions', help='Line 4') diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 06c618b6..6a153fbf 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -76,6 +76,9 @@ from . import test_us_nj_newjersey_payslip_2020 from . import test_us_nm_new_mexico_payslip_2020 +from . import test_us_ny_new_york_payslip_2019 +from . import test_us_ny_new_york_payslip_2020 + from . import test_us_oh_ohio_payslip_2019 from . import test_us_oh_ohio_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py new file mode 100644 index 00000000..d3e146de --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py @@ -0,0 +1,106 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .common import TestUsPayslip, process_payslip + + +class TestUsNYPayslip(TestUsPayslip): + ### + # Taxes and Rates + ### + NY_UNEMP_MAX_WAGE = 14000 + NY_UNEMP = 3.295 + NY_RSF = 0.075 + NY_MCTMT = 0.0 + + def test_single_example1(self): + salary = 400 + schedule_pay = 'weekly' + allowances = 3 + additional_withholding = 0 + filing_status = 'single' + additional = 0.0 + wh = -8.20 + + employee = self._createEmployee() + + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('NY'), + ny_it2104_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional, + ny_it2104_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self.assertEqual(contract.schedule_pay, 'weekly') + self._log('2018 New York tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * self.NY_UNEMP) + self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * self.NY_RSF) + self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * self.NY_MCTMT) + self.assertPayrollEqual(cats['EE_US_SIT'], wh) + + process_payslip(payslip) + + def test_married_example2(self): + salary = 5000 + schedule_pay = 'semi-monthly' + allowances = 3 + additional = 0 + filing_status = 'married' + wh = -284.19 + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('NY'), + ny_it2104_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional, + ny_it2104_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self._log('2019 New York tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * self.NY_UNEMP) + self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * self.NY_RSF) + self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * self.NY_MCTMT) + self.assertPayrollEqual(cats['EE_US_SIT'], wh) + + process_payslip(payslip) + + def test_single_example3(self): + salary = 50000 + schedule_pay = 'monthly' + allowances = 3 + additional = 0 + filing_status = 'single' + wh = -3575.63 + + employee = self._createEmployee() + + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('NY'), + ny_it2104_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional, + ny_it2104_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self._log('2019 New York tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['EE_US_SIT'], wh) + diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py new file mode 100644 index 00000000..29fbc0cb --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py @@ -0,0 +1,38 @@ +# 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 TestUsNYPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + NY_UNEMP_MAX_WAGE = 14000.0 + NY_UNEMP = 3.295 + NY_RSF = 0.075 + NY_MCTMT = 0.0 + + 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('NY'), + ny_it2104_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, + ny_it2104_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): + combined_er_rate = self.NY_UNEMP + self.NY_RSF + self.NY_MCTMT + self._test_er_suta('NY', combined_er_rate, date(2020, 1, 1), wage_base=self.NY_UNEMP_MAX_WAGE, relaxed=True) + self._test_sit(400.0, 'single', 0.0, 3, 'weekly', date(2020, 1, 1), 8.20) + self._test_sit(50000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 3575.63) + self._test_sit(50000.0, 'married', 0.0, 3, 'monthly', date(2020, 1, 1), 3619.82) + self._test_sit(50000.0, 'married', 10.0, 3, 'monthly', date(2020, 1, 1), 3629.83) 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 9c95f730..9abb2c5f 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -188,6 +188,12 @@

Form NM W-4 - State Income Tax

+ +

Form NY IT-2104 - State Income Tax

+ + + +

Form IT-4 - State Income Tax

From 0b3ba3d3b6fed33d2d263df22b8960d5b628e73f Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 28 Apr 2020 15:01:09 -0400 Subject: [PATCH 06/63] [IMP] l10n_us_hr_payroll: For North Dakota 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/nd_north_dakota.xml | 110 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/nd_north_dakota.py | 43 +++++++ .../models/us_payroll_config.py | 6 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_nd_north_dakota_payslip_2020.py | 35 ++++++ .../views/us_payroll_config_views.xml | 5 + 8 files changed, 204 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/nd_north_dakota.xml create mode 100644 l10n_us_hr_payroll/models/state/nd_north_dakota.py create mode 100644 l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index f49d1257..62667473 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -47,6 +47,7 @@ United States of America - Payroll Rules. 'data/state/ms_mississippi.xml', 'data/state/mt_montana.xml', 'data/state/nc_northcarolina.xml', + 'data/state/nd_north_dakota.xml', 'data/state/ne_nebraska.xml', 'data/state/nh_new_hampshire.xml', 'data/state/nj_newjersey.xml', diff --git a/l10n_us_hr_payroll/data/state/nd_north_dakota.xml b/l10n_us_hr_payroll/data/state/nd_north_dakota.xml new file mode 100644 index 00000000..6ab1c168 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/nd_north_dakota.xml @@ -0,0 +1,110 @@ + + + + + US ND North Dakota SUTA Wage Base + us_nd_suta_wage_base + + + + + 37900.0 + + + + + + + + US ND North Dakota SUTA Rate + us_nd_suta_rate + + + + + 1.02 + + + + + + + US ND North Dakota SIT Tax Rate + us_nd_sit_tax_rate + + + + + { + 'single': ( + ( 6200, 0.00, 0.00), + ( 46325, 0.00, 1.10), + ( 103350, 441.38, 2.04), + ( 208850, 1604.69, 2.27), + ( 446800, 3999.54, 2.64), + ( 'inf',10281.42, 2.90), + ), + 'married': ( + ( 12400, 0.00, 0.00), + ( 45925, 0.00, 1.10), + ( 93375, 368.78, 2.04), + ( 135750, 1336.76, 2.27), + ( 232700, 2298.67, 2.64), + ( 'inf', 4858.15, 2.90), + ), + 'head_household': ( + ( 9325, 0.00, 0.00), + ( 63075, 0.00, 1.10), + ( 148125, 591.25, 2.04), + ( 234025, 2326.27, 2.27), + ( 449925, 4276.20, 2.64), + ( 'inf', 9975.96, 2.90), + ), + } + + + + + + + + + US North Dakota - Office of State Tax Commissioner - Unemployment Tax + + + + US North Dakota - Taxpayer Access Point - Income Tax + + + + + + + + + + ER: US ND North Dakota State Unemployment + ER_US_ND_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_nd_suta_wage_base', rate='us_nd_suta_rate', state_code='ND') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_nd_suta_wage_base', rate='us_nd_suta_rate', state_code='ND') + + + + + + + + + EE: US ND North Dakota State Income Tax Withholding + EE_US_ND_SIT + python + result, _ = nd_north_dakota_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = nd_north_dakota_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 08207043..7eaed9bf 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -32,6 +32,7 @@ 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 from .state.nc_northcarolina import nc_northcarolina_state_income_withholding +from .state.nd_north_dakota import nd_north_dakota_state_income_withholding from .state.ne_nebraska import ne_nebraska_state_income_withholding from .state.nj_newjersey import nj_newjersey_state_income_withholding from .state.nm_new_mexico import nm_new_mexico_state_income_withholding @@ -92,6 +93,7 @@ class HRPayslip(models.Model): 'ms_mississippi_state_income_withholding': ms_mississippi_state_income_withholding, 'mt_montana_state_income_withholding': mt_montana_state_income_withholding, 'nc_northcarolina_state_income_withholding': nc_northcarolina_state_income_withholding, + 'nd_north_dakota_state_income_withholding': nd_north_dakota_state_income_withholding, 'ne_nebraska_state_income_withholding': ne_nebraska_state_income_withholding, 'nj_newjersey_state_income_withholding': nj_newjersey_state_income_withholding, 'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/nd_north_dakota.py b/l10n_us_hr_payroll/models/state/nd_north_dakota.py new file mode 100644 index 00000000..81136d6e --- /dev/null +++ b/l10n_us_hr_payroll/models/state/nd_north_dakota.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, sit_wage + + +def nd_north_dakota_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 = 'ND' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('nd_w4_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') + tax_rate = payslip.rule_parameter('us_nd_sit_tax_rate')[filing_status] + + taxable_income = wage * pay_periods + withholding = 0.0 + last = 0.0 + for row in tax_rate: + amt, flat_fee, rate = row + if taxable_income < float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = round(withholding / pay_periods) + withholding = max(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 1e03673e..2ff8e211 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -182,6 +182,12 @@ class HRContractUSPayrollConfig(models.Model): ], string='North Carolina NC-4 Filing Status', help='NC-4') nc_nc4_sit_allowances = fields.Integer(string='North Carolina NC-4 Allowances', help='NC-4 1.') + nd_w4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head_household', 'Head of Household') + ], string='North Dakota ND W-4 Filing Status', help='ND W-4') + ne_w4n_sit_filing_status = fields.Selection([ ('single', 'Single'), ('married', 'Married'), diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 6a153fbf..9b6763a3 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -67,6 +67,8 @@ from . import test_us_mt_montana_payslip_2020 from . import test_us_nc_northcarolina_payslip_2019 from . import test_us_nc_northcarolina_payslip_2020 +from . import test_us_nd_north_dakota_payslip_2020 + from . import test_us_ne_nebraska_payslip_2020 from . import test_us_nh_new_hampshire_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py new file mode 100644 index 00000000..3bde5bee --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py @@ -0,0 +1,35 @@ +# 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): + ### + # 2020 Taxes and Rates + ### + ND_UNEMP_MAX_WAGE = 37900.0 + ND_UNEMP = 1.02 + # Calculation based on this file page.47 https://www.nd.gov/tax/data/upfiles/media/rates-and-instructions.pdf?20200110115917 + + def _test_sit(self, wage, filing_status, additional_withholding, 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, + 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('ND', self.ND_UNEMP, date(2020, 1, 1), wage_base=self.ND_UNEMP_MAX_WAGE) + self._test_sit(700.0, 'single', 0.0, 'weekly', date(2020, 1, 1), 6.0) + self._test_sit(2500.0, 'married', 0.0, 'bi-weekly', date(2020, 1, 1), 29.0) + self._test_sit(25000.0, 'head_household', 0.0, 'monthly', date(2020, 1, 1), 501.0) + self._test_sit(25000.0, 'head_household', 10.0, 'monthly', date(2020, 1, 1), 511.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 9abb2c5f..77c2856c 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -167,6 +167,11 @@
+ +

Form ND W-4 - State Income Tax

+ + +

Form NC-4 - State Income Tax

From e151fc8548beba42d4d62eb812ed8c61b1cb16f2 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 28 Apr 2020 15:04:49 -0400 Subject: [PATCH 07/63] [IMP] l10n_us_hr_payroll: For Maine 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/me_maine.xml | 125 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + l10n_us_hr_payroll/models/state/me_maine.py | 64 +++++++++ .../models/us_payroll_config.py | 7 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_me_maine_payslip_2020.py | 38 ++++++ .../views/us_payroll_config_views.xml | 7 + 8 files changed, 246 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/me_maine.xml create mode 100644 l10n_us_hr_payroll/models/state/me_maine.py create mode 100644 l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 62667473..2c76ca97 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -41,6 +41,7 @@ United States of America - Payroll Rules. 'data/state/il_illinois.xml', 'data/state/in_indiana.xml', 'data/state/la_louisiana.xml', + 'data/state/me_maine.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/me_maine.xml b/l10n_us_hr_payroll/data/state/me_maine.xml new file mode 100644 index 00000000..290781f9 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/me_maine.xml @@ -0,0 +1,125 @@ + + + + + US ME Maine SUTA Wage Base + us_me_suta_wage_base + + + + + 12000.0 + + + + + + + + US ME Maine SUTA Rate + us_me_suta_rate + + + + + 1.92 + + + + + + + US ME Maine SIT Tax Rate + us_me_sit_tax_rate + + + + + { + 'single': ( + ( 22200, 0, 5.80), + ( 52600, 1288, 6.75), + ( 'inf', 3340, 7.15), + ), + 'married': ( + ( 44450, 0, 0.00), + ( 105200, 2578, 6.75), + ( 'inf', 6679, 7.15), + ), + } + + + + + + + US ME Maine Standard Deduction Rate + us_me_sit_standard_deduction_rate + + + + + { + 'single': (( 82900, 9550), (157900, 75000)), + 'married': ((165800, 21950), (315800, 150000)), + } + + + + + + + US ME Maine Personal Exemption Rate + us_me_sit_personal_exemption_rate + + + + + 4300 + + + + + + + + + US Maine - Department Of Labor | ReEmploy - Unemployment Tax + + + + US Maine - Department Of Revenue Services - Income Tax + + + + + + + + + + ER: US ME Maine State Unemployment + ER_US_ME_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_me_suta_wage_base', rate='us_me_suta_rate', state_code='ME') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_me_suta_wage_base', rate='us_me_suta_rate', state_code='ME') + + + + + + + + + EE: US ME Maine State Income Tax Withholding + EE_US_ME_SIT + python + result, _ = me_maine_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = me_maine_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 7eaed9bf..47156de9 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -26,6 +26,7 @@ from .state.id_idaho import id_idaho_state_income_withholding from .state.il_illinois import il_illinois_state_income_withholding from .state.in_indiana import in_indiana_state_income_withholding from .state.la_louisiana import la_louisiana_state_income_withholding +from .state.me_maine import me_maine_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 @@ -87,6 +88,7 @@ class HRPayslip(models.Model): 'il_illinois_state_income_withholding': il_illinois_state_income_withholding, 'in_indiana_state_income_withholding': in_indiana_state_income_withholding, 'la_louisiana_state_income_withholding': la_louisiana_state_income_withholding, + 'me_maine_state_income_withholding': me_maine_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/me_maine.py b/l10n_us_hr_payroll/models/state/me_maine.py new file mode 100644 index 00000000..d2f4d36b --- /dev/null +++ b/l10n_us_hr_payroll/models/state/me_maine.py @@ -0,0 +1,64 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def me_maine_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 = 'ME' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('me_w4me_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + exempt = payslip.contract_id.us_payroll_config_value('state_income_tax_exempt') + if exempt: + 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') + allowances = payslip.contract_id.us_payroll_config_value('me_w4me_sit_allowances') + tax_rate = payslip.rule_parameter('us_me_sit_tax_rate')[filing_status] + personal_exemption = payslip.rule_parameter('us_me_sit_personal_exemption_rate') + standard_deduction = payslip.rule_parameter('us_me_sit_standard_deduction_rate')[filing_status] + + taxable_income = wage * pay_periods + exemption_amt = allowances * personal_exemption + last = 0.0 + standard_deduction_amt = 0.0 + for row in standard_deduction: + amt, flat_amt = row + if taxable_income < 82900: + standard_deduction_amt = flat_amt + break + elif taxable_income < amt: + standard_deduction_amt = last * (amt - taxable_income) / flat_amt + break + last = flat_amt + + annual_income = taxable_income - (exemption_amt + standard_deduction_amt) + withholding = 0.0 + for row in tax_rate: + amt, flat_fee, rate = row + if annual_income < float(amt): + withholding = ((annual_income - last) * (rate / 100)) + flat_fee + break + last = amt + + if withholding < 0.0: + withholding = 0.0 + withholding = round(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 2ff8e211..152ea877 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -134,6 +134,13 @@ class HRContractUSPayrollConfig(models.Model): la_l4_sit_exemptions = fields.Integer(string='Louisiana LA L-4 Number of Exemptions', help='LA L-4 6.') la_l4_sit_dependents = fields.Integer(string='Louisiana LA L-4 Number of Dependents', help='LA L-4 7.') + me_w4me_sit_filing_status = fields.Selection([ + ('', 'Exempt'), + ('single', 'Single'), + ('married', 'Married'), + ], string='Maine W-4ME Filing Status', help='ME W-4ME 3.') + me_w4me_sit_allowances = fields.Integer(string='Maine Allowances', help='W-4ME 4.') + 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 9b6763a3..32ad72b9 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -49,6 +49,8 @@ from . import test_us_in_indiana_payslip_2020 from . import test_us_la_louisiana_payslip_2019 from . import test_us_la_louisiana_payslip_2020 +from . import test_us_me_maine_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_me_maine_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py new file mode 100644 index 00000000..b5f0ca87 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py @@ -0,0 +1,38 @@ +# 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 TestUsMEPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + ME_UNEMP_MAX_WAGE = 12000.0 + ME_UNEMP = 1.92 + # Calculation based on this file page.6 and 7 https://www.maine.gov/revenue/forms/with/2020/20_WH_Tab&Instructions.pdf + + def _test_sit(self, wage, filing_status, additional_withholding, exempt, allowances, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('ME'), + me_w4me_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, + state_income_tax_exempt=exempt, + me_w4me_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('ME', self.ME_UNEMP, date(2020, 1, 1), wage_base=self.ME_UNEMP_MAX_WAGE) + self._test_sit(300.0, 'single', 0.0, False, 2, 'weekly', date(2020, 1, 1), 0.0) + self._test_sit(800.0, 'single', 0.0, False, 2, 'weekly', date(2020, 1, 1), 26.00) + self._test_sit(4500.0, 'married', 0.0, False, 2, 'weekly', date(2020, 1, 1), 277.00) + self._test_sit(4500.0, 'married', 0.0, True, 2, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(4500.0, 'married', 10.0, False, 2, 'weekly', date(2020, 1, 1), 287.00) 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 77c2856c..dfdc6094 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -131,6 +131,13 @@
+ +

Form W-4ME - State Income Tax

+ + + + +

Form MI-W4 - State Income Tax

From 03892ea82f1873e5d3fad79c51cdc065169ade89 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 1 May 2020 18:01:33 -0400 Subject: [PATCH 08/63] [IMP] l10n_us_hr_payroll: For Nevada 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/nv_nevada.xml | 53 +++++++++++++++++++ l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_nv_nevada_payslip_2020.py | 16 ++++++ .../views/us_payroll_config_views.xml | 3 ++ 5 files changed, 75 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/nv_nevada.xml create mode 100755 l10n_us_hr_payroll/tests/test_us_nv_nevada_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 2c76ca97..76b404b8 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -53,6 +53,7 @@ United States of America - Payroll Rules. 'data/state/nh_new_hampshire.xml', 'data/state/nj_newjersey.xml', 'data/state/nm_new_mexico.xml', + 'data/state/nv_nevada.xml', 'data/state/ny_new_york.xml', 'data/state/oh_ohio.xml', 'data/state/pa_pennsylvania.xml', diff --git a/l10n_us_hr_payroll/data/state/nv_nevada.xml b/l10n_us_hr_payroll/data/state/nv_nevada.xml new file mode 100644 index 00000000..46e3c2d5 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/nv_nevada.xml @@ -0,0 +1,53 @@ + + + + + US NV Nevada SUTA Wage Base + us_nv_suta_wage_base + + + + + 32500.00 + + + + + + + + US NV Nevada SUTA Rate + us_nv_suta_rate + + + + + 2.95 + + + + + + + + US Nevada - Department of Employment, Training, and Rehabilitation, Employment Security Division - Unemployment Tax + + + + + + + + + + ER: US NV Nevada State Unemployment (RT-6) + ER_US_NV_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_nv_suta_wage_base', rate='us_nv_suta_rate', state_code='NV') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_nv_suta_wage_base', rate='us_nv_suta_rate', state_code='NV') + + + + + \ 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 32ad72b9..72a7b5d5 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -80,6 +80,8 @@ from . import test_us_nj_newjersey_payslip_2020 from . import test_us_nm_new_mexico_payslip_2020 +from . import test_us_nv_nevada_payslip_2020 + from . import test_us_ny_new_york_payslip_2019 from . import test_us_ny_new_york_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_nv_nevada_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nv_nevada_payslip_2020.py new file mode 100755 index 00000000..52c2114b --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_nv_nevada_payslip_2020.py @@ -0,0 +1,16 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip + + +class TestUsNVPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + NV_UNEMP_MAX_WAGE = 32500.0 + NV_UNEMP = 2.95 + + def test_2020_taxes(self): + # Only has state unemployment + self._test_er_suta('NV', self.NV_UNEMP, date(2020, 1, 1), wage_base=self.NV_UNEMP_MAX_WAGE) 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 dfdc6094..fdd49599 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -200,6 +200,9 @@

Form NM W-4 - State Income Tax

+ +

No additional fields.

+

Form NY IT-2104 - State Income Tax

From 9441ac01b43a3f3d273438bad49adb99dd72588d Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 15 May 2020 09:59:18 -0400 Subject: [PATCH 09/63] [IMP] l10n_us_hr_payroll: For Kansas 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ks_kansas.xml | 133 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + l10n_us_hr_payroll/models/state/ks_kansas.py | 44 ++++++ .../models/us_payroll_config.py | 7 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_ks_kansas_payslip_2020.py | 35 +++++ .../views/us_payroll_config_views.xml | 7 + 8 files changed, 231 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ks_kansas.xml create mode 100644 l10n_us_hr_payroll/models/state/ks_kansas.py create mode 100755 l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 76b404b8..27d836ba 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -40,6 +40,7 @@ United States of America - Payroll Rules. 'data/state/id_idaho.xml', 'data/state/il_illinois.xml', 'data/state/in_indiana.xml', + 'data/state/ks_kansas.xml', 'data/state/la_louisiana.xml', 'data/state/me_maine.xml', 'data/state/mi_michigan.xml', diff --git a/l10n_us_hr_payroll/data/state/ks_kansas.xml b/l10n_us_hr_payroll/data/state/ks_kansas.xml new file mode 100644 index 00000000..539d9490 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ks_kansas.xml @@ -0,0 +1,133 @@ + + + + + US KS Kasas SUTA Wage Base + us_ks_suta_wage_base + + + + + 14000.0 + + + + + + + + US KS Kasas SUTA Rate + us_ks_suta_rate + + + + + 2.7 + + + + + + + US KS Kansas Allowances Rate + us_ks_sit_allowances_rate + + + + + { + 'weekly' : 43.27, + 'bi-weekly' : 86.54, + 'semi-monthly': 93.75, + 'monthly' : 187.50, + 'quarterly' : 562.50, + 'semi-annual': 1125.00, + 'annually': 2250.00, + } + + + + + + + US KS Kasas SIT Tax Rate + us_ks_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((58, 0.00, 0.00), (346, 3.10, 0.00), (635, 5.25, 8.94), ('inf', 5.70, 24.09)), + 'bi-weekly': ((115, 0.00, 0.00), (692, 3.10, 0.00), (1269, 5.25, 17.88), ('inf', 5.70, 48.17)), + 'semi-monthly': ((125, 0.00, 0.00), (750, 3.10, 0.00), (1375, 5.25, 19.38), ('inf', 5.70, 52.19)), + 'monthly': ((250, 0.00, 0.00), (1500, 3.10, 0.00), (2750, 5.25, 38.75), ('inf', 5.70, 104.38)), + 'quarterly': ((750, 0.00, 0.00), (4500, 3.10, 0.00), (8250, 5.25, 116.25), ('inf', 5.70, 313.13)), + 'semi-annual': ((1500, 0.00, 0.00), (9000, 3.10, 0.00), (16500, 5.25, 232.50), ('inf', 5.70, 626.25)), + 'annually': ((3000, 0.00, 0.00), (18000, 3.10, 0.00), (33000, 5.25, 465.00), ('inf', 5.70, 1252.50)), + }, + 'married': { + 'weekly': ((144, 0.00, 0.00), (721, 3.10, 0.00), (1298, 5.25, 17.88), ('inf', 5.70, 48.17)), + 'bi-weekly': ((288, 0.00, 0.00), (1442, 3.10, 0.00), (2596, 5.25, 35.77), ('inf', 5.70, 96.35)), + 'semi-monthly': ((313, 0.00, 0.00), (1563, 3.10, 0.00), (2813, 5.25, 38.75), ('inf', 5.70, 104.38)), + 'monthly': ((625, 0.00, 0.00), (3125, 3.10, 0.00), (5625, 5.25, 77.50), ('inf', 5.70, 208.75)), + 'quarterly': ((1875, 0.00, 0.00), (9375, 3.10, 0.00), (16875, 5.25, 232.50), ('inf', 5.70, 626.25)), + 'semi-annual': ((3750, 0.00, 0.00), (18750, 3.10, 0.00), (33750, 5.25, 465.00), ('inf', 5.70, 1252.50)), + 'annually': ((7500, 0.00, 0.00), (37500, 3.10, 0.00), (67500, 5.25, 930.00), ('inf', 5.70, 2505.00)), + }, + 'head_household': { + 'weekly': ((58, 0.00, 0.00), (346, 3.10, 0.00), (635, 5.25, 8.94), ('inf', 5.70, 24.09)), + 'bi-weekly': ((115, 0.00, 0.00), (692, 3.10, 0.00), (1269, 5.25, 17.88), ('inf', 5.70, 48.17)), + 'semi-monthly': ((125, 0.00, 0.00), (750, 3.10, 0.00), (1375, 5.25, 19.38), ('inf', 5.70, 52.19)), + 'monthly': ((250, 0.00, 0.00), (1500, 3.10, 0.00), (2750, 5.25, 38.75), ('inf', 5.70, 104.38)), + 'quarterly': ((750, 0.00, 0.00), (4500, 3.10, 0.00), (8250, 5.25, 116.25), ('inf', 5.70, 313.13)), + 'semi-annual': ((1500, 0.00, 0.00), (9000, 3.10, 0.00), (16500, 5.25, 232.50), ('inf', 5.70, 626.25)), + 'annually': ((3000, 0.00, 0.00), (18000, 3.10, 0.00), (33000, 5.25, 465.00), ('inf', 5.70, 1252.50)), + }, + } + + + + + + + + US Kansas - Department of Labor - Unemployment Tax + + + + US Kansas - Department of Revenue - Income Tax + + + + + + + + + + ER: US KS Kasas State Unemployment + ER_US_KS_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ks_suta_wage_base', rate='us_ks_suta_rate', state_code='KS') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ks_suta_wage_base', rate='us_ks_suta_rate', state_code='KS') + + + + + + + + + EE: US KS Kasas State Income Tax Withholding + EE_US_KS_SIT + python + result, _ = ks_kansas_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ks_kansas_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 47156de9..aff10e65 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -25,6 +25,7 @@ from .state.ia_iowa import ia_iowa_state_income_withholding from .state.id_idaho import id_idaho_state_income_withholding from .state.il_illinois import il_illinois_state_income_withholding from .state.in_indiana import in_indiana_state_income_withholding +from .state.ks_kansas import ks_kansas_state_income_withholding from .state.la_louisiana import la_louisiana_state_income_withholding from .state.me_maine import me_maine_state_income_withholding from .state.mi_michigan import mi_michigan_state_income_withholding @@ -87,6 +88,7 @@ class HRPayslip(models.Model): 'id_idaho_state_income_withholding': id_idaho_state_income_withholding, 'il_illinois_state_income_withholding': il_illinois_state_income_withholding, 'in_indiana_state_income_withholding': in_indiana_state_income_withholding, + 'ks_kansas_state_income_withholding': ks_kansas_state_income_withholding, 'la_louisiana_state_income_withholding': la_louisiana_state_income_withholding, 'me_maine_state_income_withholding': me_maine_state_income_withholding, 'mi_michigan_state_income_withholding': mi_michigan_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/ks_kansas.py b/l10n_us_hr_payroll/models/state/ks_kansas.py new file mode 100644 index 00000000..1e7398d0 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ks_kansas.py @@ -0,0 +1,44 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ks_kansas_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'KS' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('ks_k4_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + allowances = payslip.contract_id.us_payroll_config_value('ks_k4_sit_allowances') + allowances_amt = payslip.rule_parameter('us_ks_sit_allowances_rate')[schedule_pay] + tax_table = payslip.rule_parameter('us_ks_sit_tax_rate')[filing_status].get(schedule_pay) + + taxable_income = wage - (allowances * allowances_amt) + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, rate, flat_fee = row + if wage <= float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(withholding, 0.0) + withholding += additional + withholding = round(withholding) + 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 152ea877..e4552626 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -127,6 +127,13 @@ class HRContractUSPayrollConfig(models.Model): in_w4_sit_personal_exemption = fields.Integer(string='Indiana In-W-4 Number of Personal Exemption', help='IN-W-4 5.') in_w4_sit_dependent_exemption = fields.Integer(string='Indiana In-W-4 Number of Dependent Exemption', help='IN-W-4 6.') + ks_k4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head of household', 'Head of Household'), + ], string='Kansas K-4 Filing Status', help='KS K-4 3.') + ks_k4_sit_allowances = fields.Integer(string='Kansas KS K-4 Number of Allowances', help='KS K-4 Step 4.') + la_l4_sit_filing_status = fields.Selection([ ('single', 'Single'), ('married', 'Married'), diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 72a7b5d5..24359a1e 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -46,6 +46,8 @@ from . import test_us_il_illinois_payslip_2020 from . import test_us_in_indiana_payslip_2020 +from . import test_us_ks_kansas_payslip_2020 + from . import test_us_la_louisiana_payslip_2019 from . import test_us_la_louisiana_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py new file mode 100755 index 00000000..61416613 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py @@ -0,0 +1,35 @@ +# 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 TestUsKSPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + KS_UNEMP_MAX_WAGE = 14000.0 + KS_UNEMP = 2.7 + # Calculation based on example https://revenue.ky.gov/Forms/42A003(T)%20(12-2019)%202020%20Tax%20Tables.pdf + + 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('KS'), + ks_k4_sit_filing_status=filing_status, + ks_k4_sit_allowances=allowances, + state_income_tax_additional_withholding=additional_withholding, + 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('KS', self.KS_UNEMP, date(2020, 1, 1), wage_base=self.KS_UNEMP_MAX_WAGE) + self._test_sit(625, 'married', 2, 0, 'semi-monthly', date(2020, 1, 1), 4.00) + # self._test_sit(1500, 'single', 0, 0, 'bi-weekly', date(2020, 1, 1), 69.90) + # self._test_sit(1500, 'single', 0, 0, 'bi-weekly', date(2020, 1, 1), 79.90) 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 fdd49599..56ef6921 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -125,6 +125,13 @@
+ +

Form KS K-4 - State Income Tax

+ + + + +

Form LA L-4 - State Income Tax

From 8f42717f3daa0e29d6cdcd982ad61c7ddfbf1c1f Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 15 May 2020 10:01:03 -0400 Subject: [PATCH 10/63] [IMP] l10n_us_hr_payroll: For Kentucky 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ky_kentucky.xml | 97 +++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/ky_kentucky.py | 32 ++++++ l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_ky_kentucky_payslip_2020.py | 33 +++++++ .../views/us_payroll_config_views.xml | 4 + 7 files changed, 171 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ky_kentucky.xml create mode 100644 l10n_us_hr_payroll/models/state/ky_kentucky.py create mode 100755 l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 27d836ba..fcbe1dad 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -41,6 +41,7 @@ United States of America - Payroll Rules. 'data/state/il_illinois.xml', 'data/state/in_indiana.xml', 'data/state/ks_kansas.xml', + 'data/state/ky_kentucky.xml', 'data/state/la_louisiana.xml', 'data/state/me_maine.xml', 'data/state/mi_michigan.xml', diff --git a/l10n_us_hr_payroll/data/state/ky_kentucky.xml b/l10n_us_hr_payroll/data/state/ky_kentucky.xml new file mode 100644 index 00000000..cab38f00 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ky_kentucky.xml @@ -0,0 +1,97 @@ + + + + + US KY Kentucky SUTA Wage Base + us_ky_suta_wage_base + + + + + 10800.0 + + + + + + + + US KY Kentucky SUTA Rate + us_ky_suta_rate + + + + + 2.4 + + + + + + + US KY Kentucky Standard Deduction Rate + us_ky_sit_standard_deduction_rate + + + + + 2650 + + + + + + + US KY Kentucky SIT Tax Rate + us_ky_sit_tax_rate + + + + + 5.0 + + + + + + + + US Kentucky - Office of Unemployment Insurance - Unemployment Tax + + + + US Kentucky - Department of Revenue - Income Tax + + + + + + + + + + ER: US KY Kentucky State Unemployment + ER_US_KY_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ky_suta_wage_base', rate='us_ky_suta_rate', state_code='KY') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ky_suta_wage_base', rate='us_ky_suta_rate', state_code='KY') + + + + + + + + + EE: US KY Kentucky State Income Tax Withholding + EE_US_KY_SIT + python + result, _ = ky_kentucky_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ky_kentucky_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 aff10e65..9b68835a 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -26,6 +26,7 @@ from .state.id_idaho import id_idaho_state_income_withholding from .state.il_illinois import il_illinois_state_income_withholding from .state.in_indiana import in_indiana_state_income_withholding from .state.ks_kansas import ks_kansas_state_income_withholding +from .state.ky_kentucky import ky_kentucky_state_income_withholding from .state.la_louisiana import la_louisiana_state_income_withholding from .state.me_maine import me_maine_state_income_withholding from .state.mi_michigan import mi_michigan_state_income_withholding @@ -89,6 +90,7 @@ class HRPayslip(models.Model): 'il_illinois_state_income_withholding': il_illinois_state_income_withholding, 'in_indiana_state_income_withholding': in_indiana_state_income_withholding, 'ks_kansas_state_income_withholding': ks_kansas_state_income_withholding, + 'ky_kentucky_state_income_withholding':ky_kentucky_state_income_withholding, 'la_louisiana_state_income_withholding': la_louisiana_state_income_withholding, 'me_maine_state_income_withholding': me_maine_state_income_withholding, 'mi_michigan_state_income_withholding': mi_michigan_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/ky_kentucky.py b/l10n_us_hr_payroll/models/state/ky_kentucky.py new file mode 100644 index 00000000..ab580880 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ky_kentucky.py @@ -0,0 +1,32 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ky_kentucky_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'KY' + 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') + tax_rate = payslip.rule_parameter('us_ky_sit_tax_rate') + standard_deduction = payslip.rule_parameter('us_ky_sit_standard_deduction_rate') + + taxable_income = (wage * pay_periods) - standard_deduction + withholding = taxable_income * (tax_rate / 100) + + withholding = max(withholding, 0.0) + withholding /= pay_periods + withholding += additional + return wage, -((withholding / wage) * 100.0) diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 24359a1e..43afe830 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -46,6 +46,8 @@ from . import test_us_il_illinois_payslip_2020 from . import test_us_in_indiana_payslip_2020 +from . import test_us_ky_kentucky_payslip_2020 + from . import test_us_ks_kansas_payslip_2020 from . import test_us_la_louisiana_payslip_2019 diff --git a/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py new file mode 100755 index 00000000..c1102efc --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py @@ -0,0 +1,33 @@ +# 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 TestUsKYPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + KY_UNEMP_MAX_WAGE = 10800.0 + KY_UNEMP = 2.4 + # Calculation based on example https://revenue.ky.gov/Forms/42A003(T)%20(12-2019)%202020%20Tax%20Tables.pdf + + def _test_sit(self, wage, additional_withholding, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('KY'), + state_income_tax_additional_withholding=additional_withholding, + 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('KY', self.KY_UNEMP, date(2020, 1, 1), wage_base=self.KY_UNEMP_MAX_WAGE) + self._test_sit(3020, 0.0, 'monthly', date(2020, 1, 1), 139.96) + self._test_sit(1500, 0.0, 'bi-weekly', date(2020, 1, 1), 69.90) + self._test_sit(1500, 10.0, 'bi-weekly', date(2020, 1, 1), 79.90) 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 56ef6921..e844905d 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -132,6 +132,10 @@
+ +

No additional fields.

+ +

Form LA L-4 - State Income Tax

From 0f004c6f1562a1fff6856fc7ba766f21ec948dfe Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 15 May 2020 13:00:43 -0400 Subject: [PATCH 11/63] [FIX]l10n_us_hr_payroll: Spell mistake on Kansas state payroll. --- l10n_us_hr_payroll/data/state/ks_kansas.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ks_kansas.xml b/l10n_us_hr_payroll/data/state/ks_kansas.xml index 539d9490..ea4d5672 100644 --- a/l10n_us_hr_payroll/data/state/ks_kansas.xml +++ b/l10n_us_hr_payroll/data/state/ks_kansas.xml @@ -2,7 +2,7 @@ - US KS Kasas SUTA Wage Base + US KS Kansas SUTA Wage Base us_ks_suta_wage_base @@ -16,7 +16,7 @@ - US KS Kasas SUTA Rate + US KS Kansas SUTA Rate us_ks_suta_rate @@ -50,7 +50,7 @@ - US KS Kasas SIT Tax Rate + US KS Kansas SIT Tax Rate us_ks_sit_tax_rate @@ -106,7 +106,7 @@ - ER: US KS Kasas State Unemployment + ER: US KS Kansas State Unemployment ER_US_KS_SUTA python result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ks_suta_wage_base', rate='us_ks_suta_rate', state_code='KS') @@ -120,7 +120,7 @@ - EE: US KS Kasas State Income Tax Withholding + EE: US KS Kansas State Income Tax Withholding EE_US_KS_SIT python result, _ = ks_kansas_state_income_withholding(payslip, categories, worked_days, inputs) From a7fc00b0f37f48cf7ee2705062a8f379788d2ece Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Mon, 18 May 2020 11:23:03 -0400 Subject: [PATCH 12/63] [IMP] l10n_us_hr_payroll: For Oklahoma 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ok_oklahoma.xml | 133 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/ok_oklahoma.py | 47 +++++++ .../models/us_payroll_config.py | 7 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_ok_oklahoma_payslip_2020.py | 37 +++++ .../views/us_payroll_config_views.xml | 7 + 8 files changed, 236 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ok_oklahoma.xml create mode 100644 l10n_us_hr_payroll/models/state/ok_oklahoma.py create mode 100755 l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index fcbe1dad..d18c9903 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -58,6 +58,7 @@ United States of America - Payroll Rules. 'data/state/nv_nevada.xml', 'data/state/ny_new_york.xml', 'data/state/oh_ohio.xml', + 'data/state/ok_oklahoma.xml', 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', 'data/state/tx_texas.xml', diff --git a/l10n_us_hr_payroll/data/state/ok_oklahoma.xml b/l10n_us_hr_payroll/data/state/ok_oklahoma.xml new file mode 100644 index 00000000..f4ec8269 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ok_oklahoma.xml @@ -0,0 +1,133 @@ + + + + + US OK Oklahoma SUTA Wage Base + us_ok_suta_wage_base + + + + + 18700.0 + + + + + + + + US OK Oklahoma SUTA Rate + us_ok_suta_rate + + + + + 1.5 + + + + + + + US OK Oklahoma Allowances Rate + us_ok_sit_allowances_rate + + + + + { + 'weekly' : 19.23, + 'bi-weekly' : 38.46, + 'semi-monthly': 41.67, + 'monthly' : 83.33, + 'quarterly' : 250.00, + 'semi-annual': 500.00, + 'annually': 1000.00, + } + + + + + + + US OK Oklahoma SIT Tax Rate + us_ok_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((122, 0.00, 0.00), (141, 0.50, 0.00), (170, 1.00, 0.10), (194, 2.00, 0.38), (216, 3.00, 0.87), (261, 4.00, 1.53), ('inf', 5.00, 3.30)), + 'bi-weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (521, 4.00, 3.06), ('inf', 5.00, 6.60)), + 'semi-monthly': ((265, 0.00, 0.00), (306, 0.50, 0.00), (369, 1.00, 0.21), (421, 2.00, 0.83), (469, 3.00, 1.88), (565, 4.00, 3.31), ('inf', 5.00, 7.15)), + 'monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1129, 4.00, 6.63), ('inf', 5.00, 14.29)), + 'quarterly': ((1588, 0.00, 0.00), (1838, 0.50, 0.00), (2213, 1.00, 1.25), (2525, 2.00, 5.00), (2813, 3.00, 11.25), (3388, 4.00, 19.88), ('inf', 5.00, 42.88)), + 'semi-annual': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6775, 4.00, 39.75), ('inf', 5.00, 85.75)), + 'annually': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (13550, 4.00, 79.50), ('inf', 5.00, 171.50)), + }, + 'married': { + 'weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (479, 4.00, 3.06), ('inf', 5.00, 4.90)), + 'bi-weekly': ((488, 0.00, 0.00), (565, 0.50, 0.00), (681, 1.00, 0.38), (777, 2.00, 1.54), (865, 3.00, 3.46), (958, 4.00, 6.12), ('inf', 5.00, 9.81)), + 'semi-monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1038, 4.00, 6.63), ('inf', 5.00, 10.63)), + 'monthly': ((1058, 0.00, 0.00), (1225, 0.50, 0.00), (1475, 1.00, 0.83), (1683, 2.00, 3.33), (1875, 3.00, 7.50), (2075, 4.00, 13.25), ('inf', 5.00, 21.25)), + 'quarterly': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6225, 4.00, 39.75), ('inf', 5.00, 63.75)), + 'semi-annual': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (12450, 4.00, 79.50), ('inf', 5.00, 127.50)), + 'annually': ((12700, 0.00, 0.00), (14700, 0.50, 0.00), (17700, 1.00, 10.00), (20200, 2.00, 40.00), (22500, 3.00, 90.00), (24900, 4.00, 159.00), ('inf', 5.00, 255.00)), + }, + 'head_household': { + 'weekly': ((122, 0.00, 0.00), (141, 0.50, 0.00), (170, 1.00, 0.10), (194, 2.00, 0.38), (216, 3.00, 0.87), (261, 4.00, 1.53), ('inf', 5.00, 3.30)), + 'bi-weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (521, 4.00, 3.06), ('inf', 5.00, 6.60)), + 'semi-monthly': ((265, 0.00, 0.00), (306, 0.50, 0.00), (369, 1.00, 0.21), (421, 2.00, 0.83), (469, 3.00, 1.88), (565, 4.00, 3.31), ('inf', 5.00, 7.15)), + 'monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1129, 4.00, 6.63), ('inf', 5.00, 14.29)), + 'quarterly': ((1588, 0.00, 0.00), (1838, 0.50, 0.00), (2213, 1.00, 1.25), (2525, 2.00, 5.00), (2813, 3.00, 11.25), (3388, 4.00, 19.88), ('inf', 5.00, 42.88)), + 'semi-annual': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6775, 4.00, 39.75), ('inf', 5.00, 85.75)), + 'annually': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (13550, 4.00, 79.50), ('inf', 5.00, 171.50)), + }, + } + + + + + + + + US Oklahoma - Employment Security Commission - Unemployment Tax + + + + US Oklahoma - Tax Commission - Income Tax + + + + + + + + + + ER: US OK Oklahoma State Unemployment + ER_US_OK_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ok_suta_wage_base', rate='us_ok_suta_rate', state_code='OK') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ok_suta_wage_base', rate='us_ok_suta_rate', state_code='OK') + + + + + + + + + EE: US OK Oklahoma State Income Tax Withholding + EE_US_OK_SIT + python + result, _ = ok_oklahoma_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ok_oklahoma_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 9b68835a..13e92312 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -41,6 +41,7 @@ from .state.nj_newjersey import nj_newjersey_state_income_withholding from .state.nm_new_mexico import nm_new_mexico_state_income_withholding from .state.ny_new_york import ny_new_york_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding +from .state.ok_oklahoma import ok_oklahoma_state_income_withholding from .state.sc_south_carolina import sc_south_carolina_state_income_withholding from .state.va_virginia import va_virginia_state_income_withholding from .state.wa_washington import wa_washington_fml_er, \ @@ -105,6 +106,7 @@ class HRPayslip(models.Model): 'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding, 'ny_new_york_state_income_withholding': ny_new_york_state_income_withholding, 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, + 'ok_oklahoma_state_income_withholding': ok_oklahoma_state_income_withholding, 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, 'va_virginia_state_income_withholding': va_virginia_state_income_withholding, 'wa_washington_fml_er': wa_washington_fml_er, diff --git a/l10n_us_hr_payroll/models/state/ok_oklahoma.py b/l10n_us_hr_payroll/models/state/ok_oklahoma.py new file mode 100644 index 00000000..bc0ecc24 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ok_oklahoma.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 ok_oklahoma_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'OK' + 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('ok_w4_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + allowances = payslip.contract_id.us_payroll_config_value('ok_w4_sit_allowances') + allowances_amt = payslip.rule_parameter('us_ok_sit_allowances_rate')[schedule_pay] + tax_table = payslip.rule_parameter('us_ok_sit_tax_rate')[filing_status].get(schedule_pay) + + taxable_income = wage - (allowances * allowances_amt) + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, rate, flat_fee = row + if wage <= float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(withholding, 0.0) + withholding += additional + withholding = round(withholding) + 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 e4552626..d50f4040 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -235,6 +235,13 @@ class HRContractUSPayrollConfig(models.Model): # Ohio will use generic SIT exempt and additional fields oh_it4_sit_exemptions = fields.Integer(string='Ohio IT-4 Exemptions', help='Line 4') + + ok_w4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head_household', 'Head of Household') + ], string='Oklahoma OK-W-4 Filing Status', help='OK-W-4') + ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 1.2.3.') sc_w4_sit_allowances = fields.Integer(string='South Carolina SC W-4 Allowances', help='SC W-4 5.') va_va4_sit_exemptions = fields.Integer(string='Virginia VA-4(P) Personal Exemptions', diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 43afe830..cc2bfff6 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -92,6 +92,8 @@ from . import test_us_ny_new_york_payslip_2020 from . import test_us_oh_ohio_payslip_2019 from . import test_us_oh_ohio_payslip_2020 +from . import test_us_ok_oklahoma_payslip_2020 + from . import test_us_pa_pennsylvania_payslip_2019 from . import test_us_pa_pennsylvania_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py new file mode 100755 index 00000000..03297065 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_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 TestUsOKPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + OK_UNEMP_MAX_WAGE = 18700.0 + OK_UNEMP = 1.5 + # Calculation based on example https://www.ok.gov/tax/documents/2020WHTables.pdf + + def _test_sit(self, wage, filing_status, allowances, additional_withholding, exempt, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('OK'), + ok_w4_sit_filing_status=filing_status, + ok_w4_sit_allowances=allowances, + 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('OK', self.OK_UNEMP, date(2020, 1, 1), wage_base=self.OK_UNEMP_MAX_WAGE) + self._test_sit(1825, 'married', 2, 0, False, 'semi-monthly', date(2020, 1, 1), 46.00) + self._test_sit(1825, 'married', 2, 0, True, 'monthly', date(2020, 1, 1), 0.00) + self._test_sit(1000, 'single', 1, 0, False, 'weekly', date(2020, 1, 1), 39.00) + self._test_sit(1000, 'single', 1, 10, False, 'weekly', date(2020, 1, 1), 49.00) 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 e844905d..eae427c3 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -226,6 +226,13 @@
+ +

Form OK-W-4 - State Income Tax

+ + + + +
From e868c703fcb29ba5cea91eec6223296b429978f5 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Mon, 18 May 2020 11:26:43 -0400 Subject: [PATCH 13/63] [IMP] l10n_us_hr_payroll: Port `l10n_us_wy_hr_payroll` WY Wyoming including migration. --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/wy_wyoming.xml | 61 +++++++++++++++++++ l10n_us_hr_payroll/tests/__init__.py | 3 + .../tests/test_us_wy_wyoming_payslip_2019.py | 58 ++++++++++++++++++ .../tests/test_us_wy_wyoming_payslip_2020.py | 13 ++++ .../views/us_payroll_config_views.xml | 3 + 6 files changed, 139 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/wy_wyoming.xml create mode 100644 l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2019.py create mode 100644 l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index d18c9903..8a60b569 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -64,6 +64,7 @@ United States of America - Payroll Rules. 'data/state/tx_texas.xml', 'data/state/va_virginia.xml', 'data/state/wa_washington.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/wy_wyoming.xml b/l10n_us_hr_payroll/data/state/wy_wyoming.xml new file mode 100644 index 00000000..cfcfcd3c --- /dev/null +++ b/l10n_us_hr_payroll/data/state/wy_wyoming.xml @@ -0,0 +1,61 @@ + + + + + US WY Wyoming SUTA Wage Base + us_wy_suta_wage_base + + + + + 25400.00 + + + + + 26400.00 + + + + + + + + US WY Wyoming SUTA Rate + us_wy_suta_rate + + + + + 2.10 + + + + + 2.10 + + + + + + + + US Wyoming - Department of Workforce Services (WDWS) - Unemployment Tax + + + + + + + + ER: US WY Wyoming State Unemployment + ER_US_WY_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wy_suta_wage_base', rate='us_wy_suta_rate', state_code='WY') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wy_suta_wage_base', rate='us_wy_suta_rate', state_code='WY') + + + + + diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index cc2bfff6..85218b71 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -108,3 +108,6 @@ 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_wy_wyoming_payslip_2019 +from . import test_us_wy_wyoming_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2019.py new file mode 100644 index 00000000..a8fa3df8 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2019.py @@ -0,0 +1,58 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip, process_payslip + + +class TestUsWYPayslip(TestUsPayslip): + + # TAXES AND RATES + WY_UNEMP_MAX_WAGE = 25400 + WY_UNEMP = -2.10 / 100.0 + + def test_2019_taxes(self): + salary = 15000.00 + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('WY')) + + self._log('2019 Wyoming tax first payslip:') + 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.WY_UNEMP) + + process_payslip(payslip) + + # Make a new payslip, this one will have maximums + + remaining_wy_unemp_wages = self.WY_UNEMP_MAX_WAGE - salary if (self.WY_UNEMP_MAX_WAGE - 2*salary < salary) \ + else salary + + self._log('2019 Wyoming tax second payslip:') + payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28') + payslip.compute_sheet() + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_wy_unemp_wages * self.WY_UNEMP) + + def test_2019_taxes_with_external(self): + # Wage is the cap itself, 25400 + # so salary is equal to self.WY_UNEMP + salary = 25400 + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('WY')) + + self._log('2019 Wyoming External tax first payslip:') + 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.WY_UNEMP) diff --git a/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py new file mode 100644 index 00000000..51a89a74 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py @@ -0,0 +1,13 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip + + +class TestUsWYPayslip(TestUsPayslip): + # TAXES AND RATES + WY_UNEMP_MAX_WAGE = 26400.00 + WY_UNEMP = 2.10 + + def test_2020_taxes(self): + self._test_er_suta('WY', self.WY_UNEMP, date(2020, 1, 1), wage_base=self.WY_UNEMP_MAX_WAGE) 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 eae427c3..192120cd 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -256,6 +256,9 @@

No additional fields.

Ensure that your Employee and Employer workers' comp code fields are filled in for WA LNI withholding.

+ +

No additional fields.

+
From 92df007ad0c0b0307c5a29492fdaef170a4ee9cf Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 20 May 2020 17:11:18 -0400 Subject: [PATCH 14/63] [IMP] l10n_us_hr_payroll: For Vermont 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/vt_vermont.xml | 121 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + l10n_us_hr_payroll/models/state/vt_vermont.py | 46 +++++++ .../models/us_payroll_config.py | 7 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_vt_vermont_payslip_2020.py | 37 ++++++ .../views/us_payroll_config_views.xml | 7 + 8 files changed, 223 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/vt_vermont.xml create mode 100644 l10n_us_hr_payroll/models/state/vt_vermont.py create mode 100755 l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 8a60b569..617ec04b 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -62,6 +62,7 @@ United States of America - Payroll Rules. 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', 'data/state/tx_texas.xml', + 'data/state/vt_vermont.xml', 'data/state/va_virginia.xml', 'data/state/wa_washington.xml', 'data/state/wy_wyoming.xml', diff --git a/l10n_us_hr_payroll/data/state/vt_vermont.xml b/l10n_us_hr_payroll/data/state/vt_vermont.xml new file mode 100644 index 00000000..6223b420 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/vt_vermont.xml @@ -0,0 +1,121 @@ + + + + + US VT Vermont SUTA Wage Base + us_vt_suta_wage_base + + + + + 16000.0 + + + + + + + + US VT Vermont SUTA Rate + us_vt_suta_rate + + + + + 1.0 + + + + + + + US VT Vermont Allowances Rate + us_vt_sit_allowances_rate + + + + + { + 'weekly' : 83.65, + 'bi-weekly' : 167.31, + 'semi-monthly': 181.25, + 'monthly' : 362.50, + 'quarterly' : 1087.50, + 'annually': 4350.00, + } + + + + + + + US VT Vermont SIT Tax Rate + us_vt_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((60, 0.00, 0.00), (836, 0.00, 3.35), (1941, 26.00, 6.60), (3983, 98.93, 7.60), ('inf', 254.12, 8.75)), + 'bi-weekly': ((120, 0.00, 0.00), (1672, 0.00, 3.35), (3882, 51.99, 6.60), (7966, 197.85, 7.60), ('inf', 508.24, 8.75)), + 'semi-monthly': ((130, 0.00, 0.00), (1811, 0.00, 3.35), (4205, 56.31, 6.60), (8630, 214.32, 7.60), ('inf', 550.62, 8.75)), + 'monthly': ((260, 0.00, 0.00), (3623, 0.00, 3.35), (8410, 112.66, 6.60), (17260, 428.60, 7.60), ('inf', 1101.20, 8.75)), + 'quarterly': ((781, 0.00, 0.00), (10869, 0.00, 3.35), (25231, 337.95, 6.60), (51781, 1285.84, 7.60), ('inf', 3303.64, 8.75)), + 'annually': ((3125, 0.00, 0.00), (43475, 0.00, 3.35), (100925, 1351.73, 6.60), (207125, 5143.43, 7.60), ('inf', 13214.63, 8.75)), + }, + 'married': { + 'weekly': ((180, 0.00, 0.00), (1477, 0.00, 3.35), (3315, 43.45, 6.60), (4956, 164.76, 7.60), ('inf', 289.47, 8.75)), + 'bi-weekly': ((361, 0.00, 0.00), (2955, 0.00, 3.35), (6630, 86.90, 6.60), (9913, 329.45, 7.60), ('inf', 578.96, 8.75)), + 'semi-monthly': ((391, 0.00, 0.00), (3201, 0.00, 3.35), (7182, 94.14, 6.60), (10739, 356.88, 7.60), ('inf', 627.21, 8.75)), + 'monthly': ((781, 0.00, 0.00), (6402, 0.00, 3.35), (14365, 188.30, 6.60), (21477, 713.86, 7.60), ('inf', 1254.37, 8.75)), + 'quarterly': ((2344, 0.00, 0.00), (19206, 0.00, 3.35), (43094, 564.88, 6.60), (64431, 2141.49, 7.60), ('inf', 3763.10, 8.75)), + 'annually': ((9375, 0.00, 0.00), (76825, 0.00, 3.35), (172375, 2259.58, 6.60), (257725, 8565.88, 7.60), ('inf', 15052.48, 8.75)), + }, + } + + + + + + + + US Vermont - Employment Security Commission - Unemployment Tax + + + + US Vermont - Tax Commission - Income Tax + + + + + + + + + + ER: US VT Vermont State Unemployment + ER_US_VT_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_vt_suta_wage_base', rate='us_vt_suta_rate', state_code='VT') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_vt_suta_wage_base', rate='us_vt_suta_rate', state_code='VT') + + + + + + + + + EE: US VT Vermont State Income Tax Withholding + EE_US_VT_SIT + python + result, _ = vt_vermont_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = vt_vermont_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 13e92312..76bc6637 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -43,6 +43,7 @@ from .state.ny_new_york import ny_new_york_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding from .state.ok_oklahoma import ok_oklahoma_state_income_withholding from .state.sc_south_carolina import sc_south_carolina_state_income_withholding +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 @@ -108,6 +109,7 @@ class HRPayslip(models.Model): 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, 'ok_oklahoma_state_income_withholding': ok_oklahoma_state_income_withholding, 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, + 'vt_vermont_state_income_withholding': vt_vermont_state_income_withholding, '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, diff --git a/l10n_us_hr_payroll/models/state/vt_vermont.py b/l10n_us_hr_payroll/models/state/vt_vermont.py new file mode 100644 index 00000000..463e007c --- /dev/null +++ b/l10n_us_hr_payroll/models/state/vt_vermont.py @@ -0,0 +1,46 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def vt_vermont_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'VT' + 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('vt_w4vt_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + allowances = payslip.contract_id.us_payroll_config_value('vt_w4vt_sit_allowances') + allowance_amt = payslip.rule_parameter('us_vt_sit_allowances_rate')[schedule_pay] + tax_table = payslip.rule_parameter('us_vt_sit_tax_rate')[filing_status].get(schedule_pay) + + taxable_income = wage - (allowances * allowance_amt) + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, flat_fee, rate = row + if wage <= float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(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 d50f4040..de2e82df 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -244,6 +244,13 @@ class HRContractUSPayrollConfig(models.Model): ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 1.2.3.') sc_w4_sit_allowances = fields.Integer(string='South Carolina SC W-4 Allowances', help='SC W-4 5.') + vt_w4vt_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head_household', 'Head of Household') + ], string='Vermont VT W-4VT Filing Status', help='VT W-4VT') + vt_w4vt_sit_allowances = fields.Integer(string='Vermont VT W-4VT Allowances', help='VT W-4VT 1.') + va_va4_sit_exemptions = fields.Integer(string='Virginia VA-4(P) Personal Exemptions', help='VA-4(P) 1(a)') va_va4_sit_other_exemptions = fields.Integer(string='Virginia VA-4(P) Age & Blindness Exemptions', diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 85218b71..1948f1e3 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -103,6 +103,8 @@ from . import test_us_sc_south_carolina_payslip_2020 from . import test_us_tx_texas_payslip_2019 from . import test_us_tx_texas_payslip_2020 +from . import test_us_vt_vermont_payslip_2020 + from . import test_us_va_virginia_payslip_2019 from . import test_us_va_virginia_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py new file mode 100755 index 00000000..c26d8f52 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_vt_vermont_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 TestUsVTPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + VT_UNEMP_MAX_WAGE = 16000.0 + VT_UNEMP = 1.0 + # Calculation based on example https://tax.vermont.gov/sites/tax/files/documents/WithholdingInstructions.pdf + + def _test_sit(self, wage, filing_status, allowances, additional_withholding, exempt, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('VT'), + vt_w4vt_sit_filing_status=filing_status, + vt_w4vt_sit_allowances=allowances, + 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('VT', self.VT_UNEMP, date(2020, 1, 1), wage_base=self.VT_UNEMP_MAX_WAGE) + self._test_sit(1800, 'married', 2, 0, False, 'weekly', date(2020, 1, 1), 53.73) + self._test_sit(1800, 'married', 2, 10, False, 'weekly', date(2020, 1, 1), 63.73) + self._test_sit(1000, 'single', 1, 0, True, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(8000, 'single', 1, 10, False, 'bi-weekly', date(2020, 1, 1), 506.58) 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 192120cd..21d3b5d0 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -245,6 +245,13 @@

No additional fields.

+ +

Form VT W-4VT - State Income Tax

+ + + + +

Form VA-4/VA-4P - State Income Tax

From d903820f11884e336124f3b00e3ee4ba0c98bcad Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 20 May 2020 17:12:55 -0400 Subject: [PATCH 15/63] [IMP] l10n_us_hr_payroll: For Utah 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + l10n_us_hr_payroll/data/state/ut_utah.xml | 157 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + l10n_us_hr_payroll/models/state/ut_utah.py | 39 +++++ .../models/us_payroll_config.py | 6 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../tests/test_us_us_utah_payslip_2020.py | 37 +++++ .../views/us_payroll_config_views.xml | 5 + 8 files changed, 249 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ut_utah.xml create mode 100644 l10n_us_hr_payroll/models/state/ut_utah.py create mode 100755 l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 617ec04b..9194230c 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -62,6 +62,7 @@ United States of America - Payroll Rules. 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', 'data/state/tx_texas.xml', + 'data/state/ut_utah.xml', 'data/state/vt_vermont.xml', 'data/state/va_virginia.xml', 'data/state/wa_washington.xml', diff --git a/l10n_us_hr_payroll/data/state/ut_utah.xml b/l10n_us_hr_payroll/data/state/ut_utah.xml new file mode 100644 index 00000000..f3622248 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ut_utah.xml @@ -0,0 +1,157 @@ + + + + + US UT Utah SUTA Wage Base + us_ut_suta_wage_base + + + + + 36600.0 + + + + + + + + US UT Utah SUTA Rate + us_ut_suta_rate + + + + + 1.5 + + + + + + + US UT Utah TAX Rate + us_ut_tax_rate + + + + + 0.0495 + + + + + + + US UT Utah Allowances Rate + us_ut_sit_allowances_rate + + + + + { + 'single': { + 'weekly' : 7, + 'bi-weekly' : 14, + 'semi-monthly': 15, + 'monthly' : 30, + 'quarterly' : 90, + 'semi-annual': 180, + 'annually': 360, + }, + 'married': { + 'weekly' : 14, + 'bi-weekly' : 28, + 'semi-monthly': 30, + 'monthly' : 60, + 'quarterly' : 180, + 'semi-annual': 360, + 'annually': 720, + }, + } + + + + + + + US UT Utah SIT Tax Rate + us_ut_sit_tax_rate + + + + + { + 'single': { + 'weekly': ((137, 1.3)), + 'bi-weekly': ((274, 1.3)), + 'semi-monthly': ((297, 1.3)), + 'monthly': ((594, 1.3)), + 'quarterly': ((1782, 1.3)), + 'semi-annual': ((3564, 1.3)), + 'annually': ((7128, 1.3)), + }, + 'married': { + 'weekly': ((274, 1.3)), + 'bi-weekly': (548, 1.3), + 'semi-monthly': ((594, 1.3)), + 'monthly': ((1188, 1.3)), + 'quarterly': ((3564, 1.3)), + 'semi-annual': ((7128, 1.3)), + 'annually': ((14256, 1.3)), + }, + 'head_household': { + 'weekly': ((137, 1.3)), + 'bi-weekly': ((274, 1.3)), + 'semi-monthly': ((297, 1.3)), + 'monthly': ((594, 1.3)), + 'quarterly': ((1782, 1.3)), + 'semi-annual': ((3564, 1.3)), + 'annually': ((7128, 1.3)), + }, + } + + + + + + + + US Utah - Employment Security Commission - Unemployment Tax + + + + US Utah - Tax Commission - Income Tax + + + + + + + + + + ER: US UT Utah State Unemployment + ER_US_UT_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ut_suta_wage_base', rate='us_ut_suta_rate', state_code='UT') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ut_suta_wage_base', rate='us_ut_suta_rate', state_code='UT') + + + + + + + + + EE: US UT Utah State Income Tax Withholding + EE_US_UT_SIT + python + result, _ = ut_utah_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ut_utah_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 76bc6637..e8f10cd0 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -43,6 +43,7 @@ from .state.ny_new_york import ny_new_york_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding from .state.ok_oklahoma import ok_oklahoma_state_income_withholding from .state.sc_south_carolina import sc_south_carolina_state_income_withholding +from .state.ut_utah import ut_utah_state_income_withholding 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, \ @@ -109,6 +110,7 @@ class HRPayslip(models.Model): 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, 'ok_oklahoma_state_income_withholding': ok_oklahoma_state_income_withholding, 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, + 'ut_utah_state_income_withholding': ut_utah_state_income_withholding, 'vt_vermont_state_income_withholding': vt_vermont_state_income_withholding, 'va_virginia_state_income_withholding': va_virginia_state_income_withholding, 'wa_washington_fml_er': wa_washington_fml_er, diff --git a/l10n_us_hr_payroll/models/state/ut_utah.py b/l10n_us_hr_payroll/models/state/ut_utah.py new file mode 100644 index 00000000..9e6b26f9 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ut_utah.py @@ -0,0 +1,39 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ut_utah_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'UT' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('ut_w4_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + tax_rate = payslip.rule_parameter('us_ut_tax_rate') + allowances = payslip.rule_parameter('us_ut_sit_allowances_rate')[filing_status].get(schedule_pay) + tax_table = payslip.rule_parameter('us_ut_sit_tax_rate')[filing_status].get(schedule_pay) + + taxable_income = wage * tax_rate + withholding = 0.0 + amt, rate = tax_table + withholding = taxable_income - (allowances - ((wage - amt) * (rate / 100))) + + withholding = max(withholding, 0.0) + withholding += additional + withholding = round(withholding) + 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 de2e82df..12f6177e 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -244,6 +244,12 @@ class HRContractUSPayrollConfig(models.Model): ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 1.2.3.') sc_w4_sit_allowances = fields.Integer(string='South Carolina SC W-4 Allowances', help='SC W-4 5.') + ut_w4_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head_household', 'Head of Household') + ], string='Utah UT W-4 Filing Status', help='UT W-4 C.') + vt_w4vt_sit_filing_status = fields.Selection([ ('single', 'Single'), ('married', 'Married'), diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 1948f1e3..aee2a839 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -103,6 +103,8 @@ from . import test_us_sc_south_carolina_payslip_2020 from . import test_us_tx_texas_payslip_2019 from . import test_us_tx_texas_payslip_2020 +from . import test_us_us_utah_payslip_2020 + from . import test_us_vt_vermont_payslip_2020 from . import test_us_va_virginia_payslip_2019 diff --git a/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py new file mode 100755 index 00000000..0518fb79 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_us_utah_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 TestUsUTPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + UT_UNEMP_MAX_WAGE = 36600.0 + UT_UNEMP = 1.5 + # Calculation based on example https://src.bna.com/MSO + + def _test_sit(self, wage, filing_status, additional_withholding, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('UT'), + ut_w4_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, + 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('UT', self.UT_UNEMP, date(2020, 1, 1), wage_base=self.UT_UNEMP_MAX_WAGE) + self._test_sit(400, 'single', 0, 'weekly', date(2020, 1, 1), 16.00) + self._test_sit(1000, 'single', 0, 'bi-weekly', date(2020, 1, 1), 45.00) + self._test_sit(855, 'married', 0, 'semi-monthly', date(2020, 1, 1), 16.00) + self._test_sit(2500, 'married', 0, 'monthly', date(2020, 1, 1), 81.00) + self._test_sit(8000, 'single', 0, 'quarterly', date(2020, 1, 1), 387.00) + self._test_sit(8000, 'single', 10, 'quarterly', date(2020, 1, 1), 397.00) 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 21d3b5d0..a012ff3d 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -245,6 +245,11 @@

No additional fields.

+ +

Form UT W-4 - State Income Tax

+ + +

Form VT W-4VT - State Income Tax

From 4e03be0c9f456a1ec34bbf4dfffac8b446706f92 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 20 May 2020 17:14:27 -0400 Subject: [PATCH 16/63] [IMP] l10n_us_hr_payroll: For Tennessee 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/tn_tennessee.xml | 51 +++++++++++++++++++ l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_tn_tennessee_payslip_2020.py | 13 +++++ .../views/us_payroll_config_views.xml | 3 ++ 5 files changed, 70 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/tn_tennessee.xml create mode 100644 l10n_us_hr_payroll/tests/test_us_tn_tennessee_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 9194230c..06600f37 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -61,6 +61,7 @@ United States of America - Payroll Rules. 'data/state/ok_oklahoma.xml', 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', + 'data/state/tn_tennessee.xml', 'data/state/tx_texas.xml', 'data/state/ut_utah.xml', 'data/state/vt_vermont.xml', diff --git a/l10n_us_hr_payroll/data/state/tn_tennessee.xml b/l10n_us_hr_payroll/data/state/tn_tennessee.xml new file mode 100644 index 00000000..31465dee --- /dev/null +++ b/l10n_us_hr_payroll/data/state/tn_tennessee.xml @@ -0,0 +1,51 @@ + + + + + US TN Tennessee SUTA Wage Base + us_tn_suta_wage_base + + + + + 7000.00 + + + + + + + + US TN Tennessee SUTA Rate + us_tn_suta_rate + + + + + 2.7 + + + + + + + + US Tennessee - Department of Revenue - Unemployment Tax + + + + + + + + ER: US TN Tennessee State Unemployment + ER_US_TN_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tn_suta_wage_base', rate='us_tn_suta_rate', state_code='TN') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tn_suta_wage_base', rate='us_tn_suta_rate', state_code='TN') + + + + + diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index aee2a839..6c84a352 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -100,6 +100,8 @@ from . import test_us_pa_pennsylvania_payslip_2020 from . import test_us_sc_south_carolina_payslip_2019 from . import test_us_sc_south_carolina_payslip_2020 +from . import test_us_tn_tennessee_payslip_2020 + from . import test_us_tx_texas_payslip_2019 from . import test_us_tx_texas_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_tn_tennessee_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_tn_tennessee_payslip_2020.py new file mode 100644 index 00000000..54acfa9a --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_tn_tennessee_payslip_2020.py @@ -0,0 +1,13 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip + + +class TestUsTNPayslip(TestUsPayslip): + # TAXES AND RATES + TN_UNEMP_MAX_WAGE = 7000.00 + TN_UNEMP = 2.7 + + def test_2020_taxes(self): + self._test_er_suta('TN', self.TN_UNEMP, date(2020, 1, 1), wage_base=self.TN_UNEMP_MAX_WAGE) 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 a012ff3d..f9043feb 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -242,6 +242,9 @@
+ +

No additional fields.

+

No additional fields.

From d3555d7e704534f4a6d2f826fda45ee20b86fa79 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 20 May 2020 17:15:33 -0400 Subject: [PATCH 17/63] [IMP] l10n_us_hr_payroll: For South Dakota 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/sd_south_dakota.xml | 51 +++++++++++++++++++ l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_sd_south_dakota_payslip_2020.py | 13 +++++ .../views/us_payroll_config_views.xml | 3 ++ 5 files changed, 70 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/sd_south_dakota.xml create mode 100644 l10n_us_hr_payroll/tests/test_us_sd_south_dakota_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 06600f37..2bfe77fc 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -61,6 +61,7 @@ United States of America - Payroll Rules. 'data/state/ok_oklahoma.xml', 'data/state/pa_pennsylvania.xml', 'data/state/sc_south_carolina.xml', + 'data/state/sd_south_dakota.xml', 'data/state/tn_tennessee.xml', 'data/state/tx_texas.xml', 'data/state/ut_utah.xml', diff --git a/l10n_us_hr_payroll/data/state/sd_south_dakota.xml b/l10n_us_hr_payroll/data/state/sd_south_dakota.xml new file mode 100644 index 00000000..95165ae5 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/sd_south_dakota.xml @@ -0,0 +1,51 @@ + + + + + US SD South Dakota SUTA Wage Base + us_sd_suta_wage_base + + + + + 15000.00 + + + + + + + + US SD South Dakota SUTA Rate + us_sd_suta_rate + + + + + 1.75 + + + + + + + + US South Dakota - Department of Labor - Unemployment Tax + + + + + + + + ER: US SD South Dakota State Unemployment + ER_US_SD_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_sd_suta_wage_base', rate='us_sd_suta_rate', state_code='SD') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_sd_suta_wage_base', rate='us_sd_suta_rate', state_code='SD') + + + + + diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 6c84a352..a7957e5e 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -100,6 +100,8 @@ from . import test_us_pa_pennsylvania_payslip_2020 from . import test_us_sc_south_carolina_payslip_2019 from . import test_us_sc_south_carolina_payslip_2020 +from . import test_us_sd_south_dakota_payslip_2020 + from . import test_us_tn_tennessee_payslip_2020 from . import test_us_tx_texas_payslip_2019 diff --git a/l10n_us_hr_payroll/tests/test_us_sd_south_dakota_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_sd_south_dakota_payslip_2020.py new file mode 100644 index 00000000..bdbb7858 --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_sd_south_dakota_payslip_2020.py @@ -0,0 +1,13 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip + + +class TestUsSDPayslip(TestUsPayslip): + # TAXES AND RATES + SD_UNEMP_MAX_WAGE = 15000.00 + SD_UNEMP = 1.75 + + def test_2020_taxes(self): + self._test_er_suta('SD', self.SD_UNEMP, date(2020, 1, 1), wage_base=self.SD_UNEMP_MAX_WAGE) 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 f9043feb..ca572a0c 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -242,6 +242,9 @@
+ +

No additional fields.

+

No additional fields.

From f9a7107740a874aa35def75917e4ea44d1a35b01 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 28 May 2020 10:26:14 -0400 Subject: [PATCH 18/63] [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.

From f4916a0af5668385d1c4fe186446989870280c03 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 28 May 2020 15:08:30 -0400 Subject: [PATCH 19/63] [IMP] l10n_us_hr_payroll: For West Virginia 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/wv_west_virginia.xml | 125 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/wv_west_virginia.py | 44 ++++++ .../models/us_payroll_config.py | 9 +- l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_wv_west_virginia_payslip_2020.py | 36 +++++ .../views/us_payroll_config_views.xml | 6 + 8 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 l10n_us_hr_payroll/data/state/wv_west_virginia.xml create mode 100644 l10n_us_hr_payroll/models/state/wv_west_virginia.py create mode 100755 l10n_us_hr_payroll/tests/test_us_wv_west_virginia_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index a9420613..962a9609 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -69,6 +69,7 @@ United States of America - Payroll Rules. 'data/state/va_virginia.xml', 'data/state/wa_washington.xml', 'data/state/wi_wisconsin.xml', + 'data/state/wv_west_virginia.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/wv_west_virginia.xml b/l10n_us_hr_payroll/data/state/wv_west_virginia.xml new file mode 100644 index 00000000..c91b03b8 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/wv_west_virginia.xml @@ -0,0 +1,125 @@ + + + + + US WV West Virginia SUTA Wage Base + us_wv_suta_wage_base + + + + + 12000.0 + + + + + + + + US WV West Virginia SUTA Rate + us_wv_suta_rate + + + + + 2.7 + + + + + + + US WV West Virginia Exemption Rate + us_wv_sit_exemption_rate + + + + + { + 'weekly' : 38.46, + 'bi-weekly' : 76.92, + 'semi-monthly': 83.33, + 'monthly' : 166.67, + 'annually': 2000.00, + } + + + + + + + US WV West Virginia SIT Tax Rate + us_wv_sit_tax_rate + + + + + { + 'single': { + 'weekly':((192, 0.00, 3.0), (481, 5.76, 4.0), (769, 17.32, 4.5), (1154, 30.28, 6.0), ('inf', 53.38, 6.5)), + 'bi-weekly':((385, 0.00, 3.0), (962, 11.55, 4.0), (1538, 34.63, 4.5), (2308, 60.55, 6.0), ('inf', 106.75, 6.5)), + 'semi-monthly':((417, 0.00, 3.0), (1042, 12.51, 4.0), (1667, 37.51, 4.5), (2500, 65.64, 6.0), ('inf', 115.62, 6.5)), + 'monthly':((833, 0.00, 3.0), (2083, 24.99, 4.0), (3333, 74.99, 4.5), (5000, 131.24, 6.0), ('inf', 231.26, 6.5)), + 'annually':((10000, 0.00, 3.0), (25000, 300.00, 4.0), (40000, 900.00, 4.5), (60000, 1575.00, 6.0), ('inf', 2775.00, 6.5)), + }, + 'married': { + 'weekly':((115, 0.00, 3.0), (288, 3.45, 4.0), (462, 10.37, 4.5), (692, 18.20, 6.0), ('inf', 32.00, 6.5)), + 'bi-weekly':((231, 0.00, 3.0), (577, 6.93, 4.0), (923, 20.77, 4.5), (1385, 36.34, 6.0), ('inf', 64.06, 6.5)), + 'semi-monthly':((250, 0.00, 3.0), (625, 7.50, 4.0), (1000, 22.50, 4.5), (1500, 39.38, 6.0), ('inf', 69.38, 6.5)), + 'monthly':((500, 0.00, 3.0), (1250, 15.00, 4.0), (2000, 45.00, 4.5), (3000, 78.75, 6.0), ('inf', 138.75, 6.5)), + 'annually':((6000, 0.00, 3.0), (15000, 180.00, 4.0), (24000, 540.00, 4.5), (36000, 945.00, 6.0), ('inf', 1665.00, 6.5)), + }, + 'head_household': { + 'weekly':((192, 0.00, 3.0), (481, 5.76, 4.0), (769, 17.32, 4.5), (1154, 30.28, 6.0), ('inf', 53.38, 6.5)), + 'bi-weekly':((385, 0.00, 3.0), (962, 11.55, 4.0), (1538, 34.63, 4.5), (2308, 60.55, 6.0), ('inf', 106.75, 6.5)), + 'semi-monthly':((417, 0.00, 3.0), (1042, 12.51, 4.0), (1667, 37.51, 4.5), (2500, 65.64, 6.0), ('inf', 115.62, 6.5)), + 'monthly':((833, 0.00, 3.0), (2083, 24.99, 4.0), (3333, 74.99, 4.5), (5000, 131.24, 6.0), ('inf', 231.26, 6.5)), + 'annually':((10000, 0.00, 3.0), (25000, 300.00, 4.0), (40000, 900.00, 4.5), (60000, 1575.00, 6.0), ('inf', 2775.00, 6.5)), + }, + } + + + + + + + + US West Virginia - WorkForce - Unemployment Tax + + + + US West Virginia - Department of Revenue - Income Tax + + + + + + + + + + ER: US WV West Virginia State Unemployment + ER_US_WV_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wv_suta_wage_base', rate='us_wv_suta_rate', state_code='WV') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_wv_suta_wage_base', rate='us_wv_suta_rate', state_code='WV') + + + + + + + + + EE: US WV West Virginia State Income Tax Withholding + EE_US_WV_SIT + python + result, _ = wv_west_virginia_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = wv_west_virginia_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 2eff7feb..24025a39 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -49,6 +49,7 @@ 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 +from .state.wv_west_virginia import wv_west_virginia_state_income_withholding class HRPayslip(models.Model): @@ -117,6 +118,7 @@ class HRPayslip(models.Model): '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, + 'wv_west_virginia_state_income_withholding': wv_west_virginia_state_income_withholding, }) return res diff --git a/l10n_us_hr_payroll/models/state/wv_west_virginia.py b/l10n_us_hr_payroll/models/state/wv_west_virginia.py new file mode 100644 index 00000000..34031eb0 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/wv_west_virginia.py @@ -0,0 +1,44 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def wv_west_virginia_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'WV' + 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 + + filing_status = payslip.contract_id.us_payroll_config_value('wv_it104_sit_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + exemptions = payslip.contract_id.us_payroll_config_value('wv_it104_sit_exemptions') + exemption_amt = payslip.rule_parameter('us_wv_sit_exemption_rate')[schedule_pay] + tax_table = payslip.rule_parameter('us_wv_sit_tax_rate')[filing_status].get(schedule_pay) + + taxable_income = wage - (exemptions * exemption_amt) + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, flat_fee, rate = row + if taxable_income <= float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(withholding, 0.0) + withholding += additional + withholding = round(withholding) + 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 edb813b9..6bb6f8dd 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -266,4 +266,11 @@ class HRContractUSPayrollConfig(models.Model): ('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 + wi_wt4_sit_exemptions = fields.Integer(string='Wisconsin Exemptions', help='WI WT-4 1.(d)') + + wv_it104_sit_filing_status = fields.Selection([ + ('single', 'Single'), + ('married', 'Married'), + ('head_household', 'Head of Household') + ], string='West Virginia WV/IT-104 Filing Status', help='WV WV/IT-104') + wv_it104_sit_exemptions = fields.Integer(string='West Virginia Exemptions', help='WV WV/IT-104 4.') diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index d75e6da7..77c30221 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -117,6 +117,8 @@ 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_wv_west_virginia_payslip_2020 + from . import test_us_wi_wisconsin_payslip_2020 from . import test_us_wy_wyoming_payslip_2019 diff --git a/l10n_us_hr_payroll/tests/test_us_wv_west_virginia_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_wv_west_virginia_payslip_2020.py new file mode 100755 index 00000000..acef111e --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_wv_west_virginia_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 TestUsWVPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + WV_UNEMP_MAX_WAGE = 12000.0 + WV_UNEMP = 2.7 + # Calculation based on example https://tax.wv.gov/Documents/TaxForms/it100.1a.pdf + + def _test_sit(self, wage, filing_status, exemption, additional_withholding, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('WV'), + wv_it104_sit_filing_status=filing_status, + wv_it104_sit_exemptions=exemption, + state_income_tax_additional_withholding=additional_withholding, + 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('WV', self.WV_UNEMP, date(2020, 1, 1), wage_base=self.WV_UNEMP_MAX_WAGE) + self._test_sit(1250, 'married', 2, 0, 'semi-monthly', date(2020, 1, 1), 44.00) + self._test_sit(1300, 'single', 1, 0, 'bi-weekly', date(2020, 1, 1), 46.00) + self._test_sit(1300, 'single', 1, 10, 'bi-weekly', date(2020, 1, 1), 56.00) + self._test_sit(15000, 'single', 2, 0, 'monthly', date(2020, 1, 1), 860.00) 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 9312360d..4d2c6d98 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,12 @@

No additional fields.

Ensure that your Employee and Employer workers' comp code fields are filled in for WA LNI withholding.

+ +

Form WV/IT-104 - State Income Tax

+ + + +

Form WT-4 - State Income Tax

From ff094dba6489d90045df9d1ab117aec337a607d3 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 2 Jun 2020 15:31:01 -0400 Subject: [PATCH 20/63] [IMP] l10n_us_hr_payroll: For Rhode Island 13.0 --- l10n_us_hr_payroll/__manifest__.py | 1 + .../data/state/ri_rhode_island.xml | 113 ++++++++++++++++++ l10n_us_hr_payroll/models/hr_payslip.py | 2 + .../models/state/ri_rhode_island.py | 48 ++++++++ .../models/us_payroll_config.py | 3 + l10n_us_hr_payroll/tests/__init__.py | 2 + .../test_us_ri_rhode_island_payslip_2020.py | 37 ++++++ .../views/us_payroll_config_views.xml | 6 + 8 files changed, 212 insertions(+) create mode 100644 l10n_us_hr_payroll/data/state/ri_rhode_island.xml create mode 100644 l10n_us_hr_payroll/models/state/ri_rhode_island.py create mode 100755 l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index 962a9609..758287af 100644 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -60,6 +60,7 @@ United States of America - Payroll Rules. 'data/state/oh_ohio.xml', 'data/state/ok_oklahoma.xml', 'data/state/pa_pennsylvania.xml', + 'data/state/ri_rhode_island.xml', 'data/state/sc_south_carolina.xml', 'data/state/sd_south_dakota.xml', 'data/state/tn_tennessee.xml', diff --git a/l10n_us_hr_payroll/data/state/ri_rhode_island.xml b/l10n_us_hr_payroll/data/state/ri_rhode_island.xml new file mode 100644 index 00000000..de004eca --- /dev/null +++ b/l10n_us_hr_payroll/data/state/ri_rhode_island.xml @@ -0,0 +1,113 @@ + + + + + US RI Rhode Island SUTA Wage Base + us_ri_suta_wage_base + + + + + 24000.0 + + + + + + + + US RI Rhode Island SUTA Rate + us_ri_suta_rate + + + + + 1.3 + + + + + + + US RI Rhode Island Exemption Rate + us_ri_sit_exemption_rate + + + + + { + 'weekly' : (( 0.00, 19.23), ( 4451.92, 0.00)), + 'bi-weekly' : (( 0.00, 38.46), ( 8903.85, 0.00)), + 'semi-monthly': (( 0.00, 41.67), ( 9645.83, 0.00)), + 'monthly' : (( 0.00, 83.33), ( 19291.67, 0.00)), + 'quarterly' : (( 0.00, 250.00), ( 57875.00, 0.00)), + 'semi-annually': (( 0.00, 500.00), ( 115750.00, 0.00)), + 'annually': (( 0.00, 1000.0), ( 231500.00, 0000)), + } + + + + + + + US RI Rhode Island SIT Tax Rate + us_ri_sit_tax_rate + + + + + { + 'weekly': ((1255, 0.00, 3.75), (2853, 47.06, 4.75), ('inf', 122.97, 5.99)), + 'bi-weekly': ((2510, 0.00, 3.75), (5706, 94.13, 4.75), ('inf', 245.94, 5.99)), + 'semi-monthly': ((2719, 0.00, 3.75), (6181, 101.96, 4.75), ('inf', 266.41, 5.99)), + 'monthly': ((5438, 0.00, 3.75), (12363, 203.93, 4.75), ('inf', 532.87, 5.99)), + 'quarterly': ((16313, 0.00, 3.75), (37088, 611.74, 4.75), ('inf', 1598.55, 5.99)), + 'semi-annually': ((32625, 0.00, 3.75), (74175, 1223.44, 4.75), ('inf', 3197.07, 5.99)), + 'annually': ((65250, 0.00, 3.75), (148350, 2446.88, 4.75), ('inf', 6394.13, 5.99)), + } + + + + + + + + US Rhode Island - Department of Labor and Training - Unemployment Tax + + + + US Rhode Island - Division of Taxations - Income Tax + + + + + + + + + + ER: US RI Rhode Island State Unemployment + ER_US_RI_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ri_suta_wage_base', rate='us_ri_suta_rate', state_code='RI') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ri_suta_wage_base', rate='us_ri_suta_rate', state_code='RI') + + + + + + + + + EE: US RI Rhode Island State Income Tax Withholding + EE_US_RI_SIT + python + result, _ = ri_rhode_island_state_income_withholding(payslip, categories, worked_days, inputs) + code + result, result_rate = ri_rhode_island_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 24025a39..e5a728f2 100644 --- a/l10n_us_hr_payroll/models/hr_payslip.py +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -42,6 +42,7 @@ from .state.nm_new_mexico import nm_new_mexico_state_income_withholding from .state.ny_new_york import ny_new_york_state_income_withholding from .state.oh_ohio import oh_ohio_state_income_withholding from .state.ok_oklahoma import ok_oklahoma_state_income_withholding +from .state.ri_rhode_island import ri_rhode_island_state_income_withholding from .state.sc_south_carolina import sc_south_carolina_state_income_withholding from .state.ut_utah import ut_utah_state_income_withholding from .state.vt_vermont import vt_vermont_state_income_withholding @@ -111,6 +112,7 @@ class HRPayslip(models.Model): 'ny_new_york_state_income_withholding': ny_new_york_state_income_withholding, 'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding, 'ok_oklahoma_state_income_withholding': ok_oklahoma_state_income_withholding, + 'ri_rhode_island_state_income_withholding': ri_rhode_island_state_income_withholding, 'sc_south_carolina_state_income_withholding': sc_south_carolina_state_income_withholding, 'ut_utah_state_income_withholding': ut_utah_state_income_withholding, 'vt_vermont_state_income_withholding': vt_vermont_state_income_withholding, diff --git a/l10n_us_hr_payroll/models/state/ri_rhode_island.py b/l10n_us_hr_payroll/models/state/ri_rhode_island.py new file mode 100644 index 00000000..454bde47 --- /dev/null +++ b/l10n_us_hr_payroll/models/state/ri_rhode_island.py @@ -0,0 +1,48 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .general import _state_applies, sit_wage + + +def ri_rhode_island_state_income_withholding(payslip, categories, worked_days, inputs): + """ + Returns SIT eligible wage and rate. + + :return: result, result_rate (wage, percent) + """ + state_code = 'RI' + 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 + + schedule_pay = payslip.contract_id.schedule_pay + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') + allowances = payslip.contract_id.us_payroll_config_value('ri_w4_sit_allowances') + exemption_rate = payslip.rule_parameter('us_ri_sit_exemption_rate')[schedule_pay] + tax_table = payslip.rule_parameter('us_ri_sit_tax_rate')[schedule_pay] + + exemption_amt = 0.0 + for row in exemption_rate: + amt, flat_fee = row + if wage > amt: + exemption_amt = flat_fee + + taxable_income = wage - (allowances * exemption_amt) + withholding = 0.0 + last = 0.0 + for row in tax_table: + amt, flat_fee, rate = row + if wage <= float(amt): + withholding = ((taxable_income - last) * (rate / 100)) + flat_fee + break + last = amt + + withholding = max(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 6bb6f8dd..baceae6c 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -242,6 +242,9 @@ class HRContractUSPayrollConfig(models.Model): ('head_household', 'Head of Household') ], string='Oklahoma OK-W-4 Filing Status', help='OK-W-4') ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 1.2.3.') + + ri_w4_sit_allowances = fields.Integer(string='Rhode Island RI W-4 Allowances', help='RI W-4 1.') + sc_w4_sit_allowances = fields.Integer(string='South Carolina SC W-4 Allowances', help='SC W-4 5.') ut_w4_sit_filing_status = fields.Selection([ diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 77c30221..f3baeecb 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -97,6 +97,8 @@ from . import test_us_ok_oklahoma_payslip_2020 from . import test_us_pa_pennsylvania_payslip_2019 from . import test_us_pa_pennsylvania_payslip_2020 +from . import test_us_ri_rhode_island_payslip_2020 + from . import test_us_sc_south_carolina_payslip_2019 from . import test_us_sc_south_carolina_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py new file mode 100755 index 00000000..6d4b35dd --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_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 TestUsRIPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + RI_UNEMP_MAX_WAGE = 24000.0 + RI_UNEMP = 1.3 + # Calculation based on example http://www.tax.ri.gov/forms/2020/Withholding/2020%20Withhholding%20Tax%20Booklet.pdf + + def _test_sit(self, wage, allowances, additional_withholding, exempt, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('RI'), + ri_w4_sit_allowances=allowances, + 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('RI', self.RI_UNEMP, date(2020, 1, 1), wage_base=self.RI_UNEMP_MAX_WAGE) + self._test_sit(2195, 1, 0, False, 'weekly', date(2020, 1, 1), 90.80) + self._test_sit(1800, 2, 10, True, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(10000, 1, 0, False, 'bi-weekly', date(2020, 1, 1), 503.15) + self._test_sit(18000, 2, 0, False, 'monthly', date(2020, 1, 1), 860.54) + self._test_sit(18000, 2, 10, False, 'monthly', date(2020, 1, 1), 870.55) 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 4d2c6d98..eb01c155 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -237,6 +237,12 @@
+ +

Form RI W-4 - State Income Tax

+ + + +

Form SC W-4 - State Income Tax

From c7180ae5b95a29b4c3c7ccfac2c557ddedd4bf35 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 7 Aug 2020 08:07:20 -0400 Subject: [PATCH 21/63] [IMP] l10n_us_hr_payroll: Changed suta rate and added exempt. H2816 --- l10n_us_hr_payroll/data/state/ky_kentucky.xml | 2 +- l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py | 2 +- l10n_us_hr_payroll/views/us_payroll_config_views.xml | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ky_kentucky.xml b/l10n_us_hr_payroll/data/state/ky_kentucky.xml index cab38f00..d596bb10 100644 --- a/l10n_us_hr_payroll/data/state/ky_kentucky.xml +++ b/l10n_us_hr_payroll/data/state/ky_kentucky.xml @@ -22,7 +22,7 @@ - 2.4 + 2.7 diff --git a/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py index c1102efc..4e652898 100755 --- a/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py @@ -9,7 +9,7 @@ class TestUsKYPayslip(TestUsPayslip): # 2020 Taxes and Rates ### KY_UNEMP_MAX_WAGE = 10800.0 - KY_UNEMP = 2.4 + KY_UNEMP = 2.7 # Calculation based on example https://revenue.ky.gov/Forms/42A003(T)%20(12-2019)%202020%20Tax%20Tables.pdf def _test_sit(self, wage, additional_withholding, schedule_pay, date_start, expected_withholding): 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 eb01c155..bc055559 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -134,7 +134,8 @@

No additional fields.

- + +

Form LA L-4 - State Income Tax

From b56083178e35b0fcc6a9548416170bb00ab73c13 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 7 Aug 2020 13:09:03 -0400 Subject: [PATCH 22/63] [IMP] l10n_us_hr_payroll: Changed suta rate for WY Wyoming 2020. H2914 --- l10n_us_hr_payroll/data/state/wy_wyoming.xml | 2 +- l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/wy_wyoming.xml b/l10n_us_hr_payroll/data/state/wy_wyoming.xml index cfcfcd3c..247603c5 100644 --- a/l10n_us_hr_payroll/data/state/wy_wyoming.xml +++ b/l10n_us_hr_payroll/data/state/wy_wyoming.xml @@ -32,7 +32,7 @@ - 2.10 + 8.5 diff --git a/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py index 51a89a74..b6ca4482 100644 --- a/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_wy_wyoming_payslip_2020.py @@ -7,7 +7,7 @@ from .common import TestUsPayslip class TestUsWYPayslip(TestUsPayslip): # TAXES AND RATES WY_UNEMP_MAX_WAGE = 26400.00 - WY_UNEMP = 2.10 + WY_UNEMP = 8.5 def test_2020_taxes(self): self._test_er_suta('WY', self.WY_UNEMP, date(2020, 1, 1), wage_base=self.WY_UNEMP_MAX_WAGE) From 4d704f17b195f74318b4142f6954b1e306f9f1d4 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 11 Aug 2020 11:59:55 -0400 Subject: [PATCH 23/63] [IMP] l10n_us_hr_payroll: Changed wage base and suta rate for NY New York 2019/2020. --- l10n_us_hr_payroll/data/state/ny_new_york.xml | 8 ++++---- l10n_us_hr_payroll/models/us_payroll_config.py | 1 - .../tests/test_us_ny_new_york_payslip_2019.py | 4 ++-- .../tests/test_us_ny_new_york_payslip_2020.py | 4 ++-- l10n_us_hr_payroll/views/us_payroll_config_views.xml | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ny_new_york.xml b/l10n_us_hr_payroll/data/state/ny_new_york.xml index d3f4cc10..e53f83e8 100644 --- a/l10n_us_hr_payroll/data/state/ny_new_york.xml +++ b/l10n_us_hr_payroll/data/state/ny_new_york.xml @@ -8,12 +8,12 @@ - 14000.0 + 11400.0 - 14000.0 + 11600.0 @@ -27,12 +27,12 @@ - 1.09 + 2.5 - 3.295 + 2.5 diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index baceae6c..8e85f7e1 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -226,7 +226,6 @@ class HRContractUSPayrollConfig(models.Model): ], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.') ny_it2104_sit_filing_status = fields.Selection([ - ('', 'Exempt'), ('single', 'Single'), ('married', 'Married'), ], string='New York NY IT-2104 Filing Status', help='NY IT-2104') diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py index d3e146de..973ea5ba 100644 --- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py @@ -7,8 +7,8 @@ class TestUsNYPayslip(TestUsPayslip): ### # Taxes and Rates ### - NY_UNEMP_MAX_WAGE = 14000 - NY_UNEMP = 3.295 + NY_UNEMP_MAX_WAGE = 11400.0 + NY_UNEMP = 2.5 NY_RSF = 0.075 NY_MCTMT = 0.0 diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py index 29fbc0cb..763bd67d 100644 --- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py @@ -8,8 +8,8 @@ class TestUsNYPayslip(TestUsPayslip): ### # 2020 Taxes and Rates ### - NY_UNEMP_MAX_WAGE = 14000.0 - NY_UNEMP = 3.295 + NY_UNEMP_MAX_WAGE = 11600.0 + NY_UNEMP = 2.5 NY_RSF = 0.075 NY_MCTMT = 0.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 bc055559..8c05dbd3 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -219,7 +219,7 @@

Form NY IT-2104 - State Income Tax

- +

Form IT-4 - State Income Tax

From 1e90e11f650051d36099fe0e85aad357fb03ee8e Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 12 Aug 2020 13:25:15 -0400 Subject: [PATCH 24/63] [FIX] l10n_us_hr_payroll: Added exempt on filing status for NY. --- .../models/us_payroll_config.py | 1 + .../tests/test_us_ny_new_york_payslip_2019.py | 27 +++++++++++++++++++ .../tests/test_us_ny_new_york_payslip_2020.py | 1 + 3 files changed, 29 insertions(+) diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 8e85f7e1..baceae6c 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -226,6 +226,7 @@ class HRContractUSPayrollConfig(models.Model): ], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.') ny_it2104_sit_filing_status = fields.Selection([ + ('', 'Exempt'), ('single', 'Single'), ('married', 'Married'), ], string='New York NY IT-2104 Filing Status', help='NY IT-2104') diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py index 973ea5ba..2c3b9306 100644 --- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py @@ -104,3 +104,30 @@ class TestUsNYPayslip(TestUsPayslip): self.assertPayrollEqual(cats['EE_US_SIT'], wh) + def test_exempt_example3(self): + salary = 50000 + schedule_pay = 'monthly' + allowances = 3 + additional = 0 + filing_status = '' + wh = 0.0 + + employee = self._createEmployee() + + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('NY'), + ny_it2104_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional, + ny_it2104_sit_allowances=allowances, + schedule_pay=schedule_pay) + + self._log('2019 New York tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['EE_US_SIT'], wh) + diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py index 763bd67d..b2b039b5 100644 --- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py @@ -36,3 +36,4 @@ class TestUsNYPayslip(TestUsPayslip): self._test_sit(50000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 3575.63) self._test_sit(50000.0, 'married', 0.0, 3, 'monthly', date(2020, 1, 1), 3619.82) self._test_sit(50000.0, 'married', 10.0, 3, 'monthly', date(2020, 1, 1), 3629.83) + self._test_sit(50000.0, '', 0.0, 0, 'monthly', date(2020, 1, 1), 0.00) From c4368cadbbdf7b57d9aa6170253ab7227d8a34c6 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 12 Aug 2020 13:47:06 -0700 Subject: [PATCH 25/63] [FIX] l10n_us_hr_payroll: Updated NY New York 2020 rates and tests. --- l10n_us_hr_payroll/data/state/ny_new_york.xml | 170 ++++++++++++++++-- .../tests/test_us_ny_new_york_payslip_2020.py | 8 +- 2 files changed, 164 insertions(+), 14 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ny_new_york.xml b/l10n_us_hr_payroll/data/state/ny_new_york.xml index e53f83e8..a6f17a70 100644 --- a/l10n_us_hr_payroll/data/state/ny_new_york.xml +++ b/l10n_us_hr_payroll/data/state/ny_new_york.xml @@ -103,18 +103,168 @@ { 'single': { - 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0758, 112.58), (3032, 0.0808, 128.38), (4142, 0.0707, 206.08), (5104, 0.0856, 284.60), (20722, 0.0735, 366.90), (21684, 0.5208, 1514.85), ('inf', 0.0962, 2015.62)), - 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0758, 225.15), (6063, 0.0808, 256.77), (8285, 0.0707, 412.15), (10208, 0.0856, 569.19), (41444, 0.0735, 733.81), (43367, 0.5208, 3029.69), ('inf', 0.0962, 4021.23)), - 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0758, 243.92), (6569, 0.0808, 278.17), (8975, 0.0707, 446.50), (11058, 0.0856, 616.63), (44898, 0.0735, 794.96), (46981, 0.5208, 3282.17), ('inf', 0.0962, 4367.17)), - 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0758, 487.83), (13138, 0.0808, 556.33), (17950, 0.0707, 893.00), (22117, 0.0856, 1233.25), (89796, 0.0735, 1589.92), (93963, 0.5208, 6564.33), ('inf', 0.0962, 8734.33)), - 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0758, 5854.00), (157650, 0.0808, 6676.00), (215400, 0.0707, 10716.00), (265400, 0.0856, 14799.00), (1077550, 0.0735, 19079.00), (1127550, 0.5208, 78772.00), ('inf', 0.0962, 104812.00)), + 'weekly': ( + ( 163, 0.0400, 0.00), + ( 225, 0.0450, 6.54), + ( 267, 0.0525, 9.31), + ( 412, 0.0590, 11.54), + ( 1551, 0.0609, 20.04), + ( 1862, 0.0641, 89.42), + ( 2070, 0.0745, 109.35), + ( 3032, 0.0795, 124.88), + ( 4142, 0.0691, 201.33), + ( 5104, 0.0925, 278.06), + (20722, 0.0735, 367.00), + (21684, 0.5208, 1514.94), + ('inf', 0.0962, 2015.71), + ), + 'bi-weekly': ( + ( 327, 0.0400, 0.00), + ( 450, 0.0450, 13.08), + ( 535, 0.0525, 18.62), + ( 823, 0.0590, 23.08), + ( 3102, 0.0609, 40.08), + ( 3723, 0.0641, 178.85), + ( 4140, 0.0745, 218.69), + ( 6063, 0.0795, 249.77), + ( 8285, 0.0691, 402.65), + (10208, 0.0925, 556.12), + (41444, 0.0735, 734.00), + (43367, 0.5208, 3029.88), + ('inf', 0.0962, 4031.42), + ), + 'semi-monthly': ( + ( 354, 0.0400, 0.00), + ( 488, 0.0450, 14.17), + ( 579, 0.0525, 20.17), + ( 892, 0.0590, 25.00), + ( 3360, 0.0609, 43.42), + ( 4033, 0.0641, 193.75), + ( 4485, 0.0745, 236.92), + ( 6569, 0.0795, 270.58), + ( 8975, 0.0691, 436.21), + (11058, 0.0925, 602.46), + (44898, 0.0735, 795.17), + (46981, 0.5208, 3282.38), + ('inf', 0.0962, 4367.38), + ), + 'monthly': ( + ( 708, 0.0400, 0.00), + ( 975, 0.0450, 28.33), + ( 1158, 0.0525, 40.33), + ( 1783, 0.0590, 50.00), + ( 6721, 0.0609, 86.83), + ( 8067, 0.0641, 387.50), + ( 8971, 0.0745, 473.83), + (13138, 0.0795, 541.17), + (17950, 0.0691, 872.42), + (22117, 0.0925, 1204.92), + (89796, 0.0735, 1590.33), + (93963, 0.5208, 6564.75), + ('inf', 0.0962, 8734.75), + ), + 'annually': ( + ( 8500, 0.0400, 0.00), + ( 11700, 0.0450, 340.00), + ( 13900, 0.0525, 484.00), + ( 21400, 0.0590, 600.00), + ( 80650, 0.0609, 1042.00), + ( 96800, 0.0641, 4650.00), + ( 107650, 0.0745, 5686.00), + ( 157650, 0.0795, 6494.00), + ( 215400, 0.0691, 10469.00), + ( 265400, 0.0925, 14459.00), + (1077550, 0.0735, 19084.00), + (1127550, 0.5208, 78777.00), + ( 'inf', 0.0962, 104817.00), + ), }, 'married': { - 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0783, 112.58), (3032, 0.0833, 128.90), (4068, 0.0785, 209.00), (6215, 0.0707, 290.37), (7177, 0.0916, 442.17), (20722, 0.0735, 530.25), (41449, 0.0765, 1525.83), (42411, 0.9454, 3111.42), ('inf', 0.0962, 4020.46)), - 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0783, 225.15), (6063, 0.0833, 257.81), (8137, 0.0785, 418.00), (12431, 0.0707, 580.73), (14354, 0.0916, 884.35), (41444, 0.0735, 1060.50), (82898, 0.0765, 3051.65), (84821, 0.9454, 6222.85), ('inf', 0.0962, 8040.92)), - 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0783, 243.92), (6569, 0.0833, 279.29), (8815, 0.0785, 452.83), (13476, 0.0707, 629.13), (15550, 0.0916, 958.04), (44898, 0.0735, 1148.88), (89806, 0.0765, 3305.96), (91890, 0.9454, 6741.42), ('inf', 0.0962, 8711.00)), - 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0783, 487.83), (13138, 0.0833, 558.58), (17629, 0.0785, 905.67), (26933, 0.0707, 1258.25), (31100, 0.0916, 1916.08), (89796, 0.0735, 2297.75), (179613, 0.0765, 6611.92), (183779, 0.9454, 13482.83), ('inf', 0.0962, 17422.00)), - 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0783, 5854.00), (157650, 0.0833, 6703.00), (211550, 0.0785, 10868.00), (323200, 0.0707, 15099.00), (373200, 0.0916, 22993.00), (1077550, 0.0735, 27573.00), (2155350, 0.0765, 79343.00), (2205350, 0.9454, 161794.00), ('inf', 0.0962, 209064.00)), + 'weekly': ( + ( 163, 0.0400, 0.00), + ( 225, 0.0450, 6.54), + ( 267, 0.0525, 9.31), + ( 412, 0.0590, 11.54), + ( 1551, 0.0609, 20.04), + ( 1862, 0.0641, 89.42), + ( 2070, 0.0746, 109.35), + ( 3032, 0.0796, 124.90), + ( 4068, 0.0794, 201.44), + ( 6215, 0.0691, 283.75), + ( 7177, 0.1019, 432.12), + (20722, 0.0735, 530.10), + (41449, 0.0765, 1525.65), + (42411, 0.9454, 3111.27), + ('inf', 0.0962, 4020.31), + ), + 'bi-weekly': ( + ( 327, 0.0400, 0.00), + ( 450, 0.0450, 13.08), + ( 535, 0.0525, 18.62), + ( 823, 0.0590, 23.08), + ( 3102, 0.0609, 40.08), + ( 3723, 0.0641, 178.85), + ( 4140, 0.0746, 218.69), + ( 6063, 0.0796, 249.81), + ( 8137, 0.0794, 402.88), + (12431, 0.0691, 567.50), + (14354, 0.1019, 864.23), + (41444, 0.0735, 1060.19), + (82898, 0.0765, 3051.31), + (84821, 0.9454, 6222.54), + ('inf', 0.0962, 8040.62), + ), + 'semi-monthly': ( + ( 354, 0.0400, 0.00), + ( 488, 0.0450, 14.17), + ( 579, 0.0525, 20.17), + ( 892, 0.0590, 25.00), + ( 3360, 0.0609, 43.42), + ( 4033, 0.0641, 193.75), + ( 4485, 0.0746, 236.92), + ( 6569, 0.0796, 270.63), + ( 8815, 0.0794, 436.46), + (13467, 0.0691, 614.79), + (15550, 0.1019, 936.25), + (44898, 0.0735, 1148.54), + (89806, 0.0765, 3305.58), + (91890, 0.9454, 6741.08), + ('inf', 0.0962, 8710.67), + ), + 'monthly': ( + ( 708, 0.0400, 0.00), + ( 975, 0.0450, 28.33), + ( 1158, 0.0525, 40.33), + ( 1783, 0.0590, 50.00), + ( 6721, 0.0609, 86.83), + ( 8067, 0.0641, 387.50), + ( 8971, 0.0746, 473.83), + ( 13138, 0.0796, 541.25), + ( 17629, 0.0794, 872.92), + ( 26933, 0.0691, 1229.58), + ( 31100, 0.1019, 1872.50), + ( 89796, 0.0735, 2297.08), + (179613, 0.0765, 6611.17), + (183779, 0.9454, 13482.17), + ( 'inf', 0.0962, 17421.33), + ), + 'annually': ( + ( 8500, 0.0400, 0.00), + ( 11700, 0.0450, 340.00), + ( 13900, 0.0525, 484.00), + ( 21400, 0.0590, 600.00), + ( 80650, 0.0609, 1042.00), + ( 96800, 0.0641, 4650.00), + ( 107650, 0.0746, 5686.00), + ( 157650, 0.0796, 6495.00), + ( 211550, 0.0794, 10475.00), + ( 323200, 0.0691, 14755.00), + ( 373200, 0.1019, 22470.00), + (1077550, 0.0735, 27565.00), + (2155350, 0.0765, 79334.00), + (2205350, 0.9454, 161786.00), + ( 'inf', 0.0962, 209056.00), + ), } } diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py index b2b039b5..05e50792 100644 --- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py @@ -27,13 +27,13 @@ class TestUsNYPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): combined_er_rate = self.NY_UNEMP + self.NY_RSF + self.NY_MCTMT self._test_er_suta('NY', combined_er_rate, date(2020, 1, 1), wage_base=self.NY_UNEMP_MAX_WAGE, relaxed=True) self._test_sit(400.0, 'single', 0.0, 3, 'weekly', date(2020, 1, 1), 8.20) - self._test_sit(50000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 3575.63) - self._test_sit(50000.0, 'married', 0.0, 3, 'monthly', date(2020, 1, 1), 3619.82) - self._test_sit(50000.0, 'married', 10.0, 3, 'monthly', date(2020, 1, 1), 3629.83) + self._test_sit(10000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 554.09) + self._test_sit(8000.0, 'married', 0.0, 5, 'monthly', date(2020, 1, 1), 400.32) + self._test_sit(4500.0, 'married', 10.0, 3, 'semi-monthly', date(2020, 1, 1), 247.69) self._test_sit(50000.0, '', 0.0, 0, 'monthly', date(2020, 1, 1), 0.00) From a02766da6c504b9537e4b9c993818bb90ef5eebb Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Mon, 17 Aug 2020 11:38:40 -0400 Subject: [PATCH 26/63] [IMP] l10n_us_hr_payroll: Improved test and restructured table for WI Wisconsin 2020. --- .../data/state/wi_wisconsin.xml | 22 +++++++++++++++++-- .../test_us_wi_wisconsin_payslip_2020.py | 10 +++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/wi_wisconsin.xml b/l10n_us_hr_payroll/data/state/wi_wisconsin.xml index baff6b3a..b62dc3f4 100644 --- a/l10n_us_hr_payroll/data/state/wi_wisconsin.xml +++ b/l10n_us_hr_payroll/data/state/wi_wisconsin.xml @@ -15,6 +15,7 @@ + US WI Wisconsin SUTA Rate us_wi_suta_rate @@ -41,6 +42,7 @@ + US WI Wisconsin SIT Tax Rate us_wi_sit_tax_rate @@ -49,8 +51,24 @@ { - '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)), + 'single': ( + ( 5730, 0.0000, 0.00), + ( 15200, 4.0000, 0.00), + ( 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.00), + ( 18780, 4.0000, 0.00), + ( 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), + ), } 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 index 8241e4c1..32bdfa30 100755 --- 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 @@ -27,11 +27,13 @@ class TestUsWIPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(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(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) + self._test_sit(7000, 'single', 1, 10, True, 'bi-weekly', date(2020, 1, 1), 0.00) + self._test_sit(10000, 'married', 3, 10, False, 'bi-weekly', date(2020, 1, 1), 633.65) + # ((48000 - 26227) * (7.0224 /100) + 1073.55 - 44) / 12 + self._test_sit(4000, 'single', 2, 0, False, 'monthly', date(2020, 1, 1), 213.21) From 3610239b50df32bc2d4c7992309f76c331847ed0 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 12:12:41 -0400 Subject: [PATCH 27/63] [IMP] l10n_us_hr_payroll: Added additional withholding, changed suta rate for 2020 and Improved test for SC South Carolina 2020. --- .../data/state/sc_south_carolina.xml | 4 +++- .../models/state/sc_south_carolina.py | 2 ++ .../test_us_sc_south_carolina_payslip_2020.py | 14 ++++++++------ .../views/us_payroll_config_views.xml | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/sc_south_carolina.xml b/l10n_us_hr_payroll/data/state/sc_south_carolina.xml index 95867646..b2a46192 100644 --- a/l10n_us_hr_payroll/data/state/sc_south_carolina.xml +++ b/l10n_us_hr_payroll/data/state/sc_south_carolina.xml @@ -31,8 +31,9 @@ + - 1.09 + 0.55 @@ -56,6 +57,7 @@ + [ ( 2620, 0.8, 0.0), diff --git a/l10n_us_hr_payroll/models/state/sc_south_carolina.py b/l10n_us_hr_payroll/models/state/sc_south_carolina.py index 169961eb..e877f8f9 100644 --- a/l10n_us_hr_payroll/models/state/sc_south_carolina.py +++ b/l10n_us_hr_payroll/models/state/sc_south_carolina.py @@ -24,6 +24,7 @@ def sc_south_carolina_state_income_withholding(payslip, categories, worked_days, 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') allowances = payslip.contract_id.us_payroll_config_value('sc_w4_sit_allowances') tax_rate = payslip.rule_parameter('us_sc_sit_tax_rate') personal_exemption = payslip.rule_parameter('us_sc_sit_personal_exemption_rate') @@ -45,4 +46,5 @@ def sc_south_carolina_state_income_withholding(payslip, categories, worked_days, withholding = (taxable_income * (rate / 100.0) - flat_amt) break withholding /= pay_periods + withholding += additional return wage, -((withholding / wage) * 100.0) diff --git a/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py index e17a8052..170c3bf5 100644 --- a/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_sc_south_carolina_payslip_2020.py @@ -9,14 +9,15 @@ class TestUsSCPayslip(TestUsPayslip): # 2020 Taxes and Rates ### SC_UNEMP_MAX_WAGE = 14000.0 - SC_UNEMP = 1.09 + SC_UNEMP = 0.55 # Calculation based on https://dor.sc.gov/forms-site/Forms/WH1603F_2020.pdf - def _test_sit(self, wage, exempt, allowances, schedule_pay, date_start, expected_withholding): + def _test_sit(self, wage, additional_withholding, exempt, allowances, schedule_pay, date_start, expected_withholding): employee = self._createEmployee() contract = self._createContract(employee, wage=wage, state_id=self.get_us_state('SC'), + state_income_tax_additional_withholding=additional_withholding, state_income_tax_exempt=exempt, sc_w4_sit_allowances=allowances, schedule_pay=schedule_pay) @@ -25,10 +26,11 @@ class TestUsSCPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('SC', self.SC_UNEMP, date(2020, 1, 1), wage_base=self.SC_UNEMP_MAX_WAGE) - self._test_sit(750.0, False, 3.0, 'weekly', date(2020, 1, 1), 28.73) - self._test_sit(800.0, True, 0.0, 'weekly', date(2020, 1, 1), 0.00) - self._test_sit(9000.0, False, 0.0, 'monthly', date(2020, 1, 1), 594.61) + self._test_sit(750.0, 0.0, False, 3.0, 'weekly', date(2020, 1, 1), 28.73) + self._test_sit(800.0, 0.0, True, 0.0, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(9000.0, 0.0, False, 0.0, 'monthly', date(2020, 1, 1), 594.61) + self._test_sit(5000.0, 10.0, False, 2.0, 'semi-monthly', date(2020, 1, 1), 316.06) 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 8c05dbd3..5a2c6da1 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -247,6 +247,7 @@

Form SC W-4 - State Income Tax

+
From b6823e6caaa22750a38c5af72d669aaf98a41b76 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 12:32:41 -0400 Subject: [PATCH 28/63] [IMP] l10n_us_hr_payroll: Changed Form name and additional withholding field string for IN Indiana 2020. --- l10n_us_hr_payroll/views/us_payroll_config_views.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 5a2c6da1..d2b5ced5 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -120,10 +120,10 @@ -

Form IN W-4 - State Income Tax

+

Form IN WH-4 - State Income Tax

- +

Form KS K-4 - State Income Tax

From 14aa5f89a3eb268795d7ba7757a05547ba9111fa Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 14:26:24 -0400 Subject: [PATCH 29/63] [IMP] l10n_us_hr_payroll: Refactored sit rate tax table and added allowance field and apply on calculation. Also Improved test case for for ND North Dakota 2020. --- .../data/state/nd_north_dakota.xml | 220 ++++++++++++++++-- .../models/state/nd_north_dakota.py | 10 +- .../models/us_payroll_config.py | 2 + .../test_us_nd_north_dakota_payslip_2020.py | 14 +- 4 files changed, 211 insertions(+), 35 deletions(-) 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 6ab1c168..d778c3aa 100644 --- a/l10n_us_hr_payroll/data/state/nd_north_dakota.xml +++ b/l10n_us_hr_payroll/data/state/nd_north_dakota.xml @@ -27,7 +27,7 @@
- + US ND North Dakota SIT Tax Rate us_nd_sit_tax_rate @@ -36,36 +36,206 @@ { - 'single': ( - ( 6200, 0.00, 0.00), - ( 46325, 0.00, 1.10), - ( 103350, 441.38, 2.04), - ( 208850, 1604.69, 2.27), - ( 446800, 3999.54, 2.64), - ( 'inf',10281.42, 2.90), - ), - 'married': ( - ( 12400, 0.00, 0.00), - ( 45925, 0.00, 1.10), - ( 93375, 368.78, 2.04), - ( 135750, 1336.76, 2.27), - ( 232700, 2298.67, 2.64), - ( 'inf', 4858.15, 2.90), - ), - 'head_household': ( - ( 9325, 0.00, 0.00), - ( 63075, 0.00, 1.10), - ( 148125, 591.25, 2.04), - ( 234025, 2326.27, 2.27), - ( 449925, 4276.20, 2.64), - ( 'inf', 9975.96, 2.90), - ), + 'single': { + 'weekly': ( + ( 119, 0.00, 0.00), + ( 891, 0.00, 1.10), + ( 1988, 8.49, 2.04), + ( 4016, 30.87, 2.27), + ( 8592, 76.91, 2.64), + ('inf', 197.71, 2.90), + ), + 'bi-weekly': ( + ( 238, 0.00, 0.00), + ( 1782, 0.00, 1.10), + ( 3975, 16.98, 2.04), + ( 8033, 61.72, 2.27), + ( 17185, 153.84, 2.64), + ( 'inf', 395.45, 2.90), + ), + 'semi-monthly': ( + ( 258, 0.00, 0.00), + ( 1930, 0.00, 1.10), + ( 4306, 18.39, 2.04), + ( 8702, 66.86, 2.27), + ( 18617, 166.65, 2.64), + ( 'inf', 428.41, 2.90), + ), + 'monthly': ( + ( 517, 0.00, 0.00), + ( 3860, 0.00, 1.10), + ( 8613, 36.77, 2.04), + ( 17404, 133.73, 2.27), + ( 37233, 333.29, 2.64), + ( 'inf', 856.78, 2.90), + ), + 'quarterly': ( + ( 1550, 0.00, 0.00), + ( 11581, 0.00, 1.10), + ( 25838, 110.34, 2.04), + ( 52213, 401.18, 2.27), + ( 111700, 999.90, 2.64), + ( 'inf', 2570.35, 2.90), + ), + 'semi-annual': ( + ( 3100, 0.00, 0.00), + ( 23163, 0.00, 1.10), + ( 51675, 220.69, 2.04), + ( 104425, 802.34, 2.27), + ( 223400, 1999.76, 2.64), + ( 'inf', 5140.70, 2.90), + ), + 'annual': ( + ( 6200, 0.00, 0.00), + ( 46325, 0.00, 1.10), + ( 103350, 441.38, 2.04), + ( 208850, 1604.69, 2.27), + ( 446800, 3999.54, 2.64), + ( 'inf', 10281.42, 2.90), + ), + }, + 'married': { + 'weekly': ( + ( 238, 0.00, 0.00), + ( 883, 0.00, 1.10), + ( 1796, 7.10, 2.04), + ( 2611, 25.72, 2.27), + ( 4475, 44.22, 2.64), + ('inf', 93.43, 2.90), + ), + 'bi-weekly': ( + ( 477, 0.00, 0.00), + ( 1766, 0.00, 1.10), + ( 3591, 14.18, 2.04), + ( 5221, 51.41, 2.27), + ( 8950, 88.41, 2.64), + ( 'inf', 186.86, 2.90), + ), + 'semi-monthly': ( + ( 517, 0.00, 0.00), + ( 1914, 0.00, 1.10), + ( 3891, 15.37, 2.04), + ( 5656, 55.70, 2.27), + ( 9696, 95.76, 2.64), + ( 'inf', 202.42, 2.90), + ), + 'monthly': ( + ( 1033, 0.00, 0.00), + ( 3827, 0.00, 1.10), + ( 7781, 30.73, 2.04), + ( 11313, 111.40, 2.27), + ( 19392, 191.57, 2.64), + ( 'inf', 404.86, 2.90), + ), + 'quarterly': ( + ( 3100, 0.00, 0.00), + ( 11481, 0.00, 1.10), + ( 23344, 92.19, 2.04), + ( 33938, 334.20, 2.27), + ( 58175, 574.68, 2.64), + ( 'inf', 1214.54, 2.90), + ), + 'semi-annual': ( + ( 6200, 0.00, 0.00), + ( 22963, 0.00, 1.10), + ( 46688, 184.39, 2.04), + ( 67875, 668.38, 2.27), + ( 116350, 1149.33, 2.64), + ( 'inf', 2429.07, 2.90), + ), + 'annual': ( + ( 12400, 0.00, 0.00), + ( 45925, 0.00, 1.10), + ( 93375, 368.78, 2.04), + ( 135750, 1336.76, 2.27), + ( 232700, 2298.67, 2.64), + ( 'inf', 4858.15, 2.90), + ), + }, + 'head_household':{ + 'weekly': ( + ( 119, 0.00, 0.00), + ( 891, 0.00, 1.10), + ( 1988, 8.49, 2.04), + ( 4016, 30.87, 2.27), + ( 8592, 76.91, 2.64), + ('inf', 197.71, 2.90), + ), + 'bi-weekly': ( + ( 238, 0.00, 0.00), + ( 1782, 0.00, 1.10), + ( 3975, 16.98, 2.04), + ( 8033, 61.72, 2.27), + ( 17185, 153.84, 2.64), + ( 'inf', 395.45, 2.90), + ), + 'semi-monthly': ( + ( 258, 0.00, 0.00), + ( 1930, 0.00, 1.10), + ( 4306, 18.39, 2.04), + ( 8702, 66.86, 2.27), + ( 18617, 166.65, 2.64), + ( 'inf', 428.41, 2.90), + ), + 'monthly': ( + ( 517, 0.00, 0.00), + ( 3860, 0.00, 1.10), + ( 8613, 36.77, 2.04), + ( 17404, 133.73, 2.27), + ( 37233, 333.29, 2.64), + ( 'inf', 856.78, 2.90), + ), + 'quarterly': ( + ( 1550, 0.00, 0.00), + ( 11581, 0.00, 1.10), + ( 25838, 110.34, 2.04), + ( 52213, 401.18, 2.27), + ( 111700, 999.90, 2.64), + ( 'inf', 2570.35, 2.90), + ), + 'semi-annual': ( + ( 3100, 0.00, 0.00), + ( 23163, 0.00, 1.10), + ( 51675, 220.69, 2.04), + ( 104425, 802.34, 2.27), + ( 223400, 1999.76, 2.64), + ( 'inf', 5140.70, 2.90), + ), + 'annual': ( + ( 6200, 0.00, 0.00), + ( 46325, 0.00, 1.10), + ( 103350, 441.38, 2.04), + ( 208850, 1604.69, 2.27), + ( 446800, 3999.54, 2.64), + ( 'inf', 10281.42, 2.90), + ), + }, } + + US ND North Dakota Allowances Rate + us_nd_sit_allowances_rate + + + + + { + 'weekly' : 83.00, + 'bi-weekly' : 165.00, + 'semi-monthly': 179.00, + 'monthly' : 358.00, + 'quarterly' : 1075.00, + 'semi-annual': 2150.00, + 'annually': 4300.00, + } + + + + diff --git a/l10n_us_hr_payroll/models/state/nd_north_dakota.py b/l10n_us_hr_payroll/models/state/nd_north_dakota.py index 81136d6e..1ef4ecbd 100644 --- a/l10n_us_hr_payroll/models/state/nd_north_dakota.py +++ b/l10n_us_hr_payroll/models/state/nd_north_dakota.py @@ -23,11 +23,13 @@ def nd_north_dakota_state_income_withholding(payslip, categories, worked_days, i if not filing_status: return 0.0, 0.0 - pay_periods = payslip.dict.get_pay_periods_in_year() + schedule_pay = payslip.contract_id.schedule_pay additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') - tax_rate = payslip.rule_parameter('us_nd_sit_tax_rate')[filing_status] + allowance = payslip.contract_id.us_payroll_config_value('nd_w4_sit_allowances') + allowance_rate = payslip.rule_parameter('us_nd_sit_allowances_rate')[schedule_pay] + tax_rate = payslip.rule_parameter('us_nd_sit_tax_rate')[filing_status].get(schedule_pay) - taxable_income = wage * pay_periods + taxable_income = wage - (allowance * allowance_rate) withholding = 0.0 last = 0.0 for row in tax_rate: @@ -37,7 +39,7 @@ def nd_north_dakota_state_income_withholding(payslip, categories, worked_days, i break last = amt - withholding = round(withholding / pay_periods) + withholding = round(withholding) withholding = max(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 baceae6c..37fe2602 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -197,10 +197,12 @@ class HRContractUSPayrollConfig(models.Model): nc_nc4_sit_allowances = fields.Integer(string='North Carolina NC-4 Allowances', help='NC-4 1.') nd_w4_sit_filing_status = fields.Selection([ + ('', 'Exempt'), ('single', 'Single'), ('married', 'Married'), ('head_household', 'Head of Household') ], string='North Dakota ND W-4 Filing Status', help='ND W-4') + nd_w4_sit_allowances = fields.Integer(string='North Dakota ND W-4') ne_w4n_sit_filing_status = fields.Selection([ ('single', 'Single'), diff --git a/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py index 3bde5bee..903cf816 100644 --- a/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_nd_north_dakota_payslip_2020.py @@ -12,24 +12,26 @@ class TestUsNDPayslip(TestUsPayslip): ND_UNEMP = 1.02 # Calculation based on this file page.47 https://www.nd.gov/tax/data/upfiles/media/rates-and-instructions.pdf?20200110115917 - def _test_sit(self, wage, filing_status, additional_withholding, schedule_pay, date_start, expected_withholding): + 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.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('ND', self.ND_UNEMP, date(2020, 1, 1), wage_base=self.ND_UNEMP_MAX_WAGE) - self._test_sit(700.0, 'single', 0.0, 'weekly', date(2020, 1, 1), 6.0) - self._test_sit(2500.0, 'married', 0.0, 'bi-weekly', date(2020, 1, 1), 29.0) - self._test_sit(25000.0, 'head_household', 0.0, 'monthly', date(2020, 1, 1), 501.0) - self._test_sit(25000.0, 'head_household', 10.0, 'monthly', date(2020, 1, 1), 511.0) + self._test_sit(700.0, 'single', 0.0, 0.0, 'weekly', date(2020, 1, 1), 6.0) + self._test_sit(5000.0, 'married', 0.0, 2.0, 'bi-weekly', date(2020, 1, 1), 76.0) + self._test_sit(25000.0, 'head_household', 0.0, 0.0, 'monthly', date(2020, 1, 1), 534.0) + self._test_sit(25000.0, 'head_household', 10.0, 2.0, 'monthly', date(2020, 1, 1), 525.0) + self._test_sit(3000.0, '', 10.0, 2.0, 'monthly', date(2020, 1, 1), 0.0) From c53ce9ead7e0b757dfb19082eb64280bdfda98e0 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 15:15:37 -0400 Subject: [PATCH 30/63] [IMP] l10n_us_hr_payroll: Refactored Tax table and Improved test case for ME Maine 2020. --- l10n_us_hr_payroll/data/state/me_maine.xml | 24 ++++++++++++------- l10n_us_hr_payroll/models/state/me_maine.py | 4 +--- .../models/us_payroll_config.py | 2 +- .../tests/test_us_me_maine_payslip_2020.py | 9 +++---- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/me_maine.xml b/l10n_us_hr_payroll/data/state/me_maine.xml index 290781f9..2c1aaf71 100644 --- a/l10n_us_hr_payroll/data/state/me_maine.xml +++ b/l10n_us_hr_payroll/data/state/me_maine.xml @@ -27,7 +27,7 @@ - + US ME Maine SIT Tax Rate us_me_sit_tax_rate @@ -37,14 +37,14 @@ { 'single': ( - ( 22200, 0, 5.80), - ( 52600, 1288, 6.75), - ( 'inf', 3340, 7.15), + ( 22200, 0, 5.80), + ( 52600, 1288, 6.75), + ( 'inf', 3340, 7.15), ), 'married': ( - ( 44450, 0, 0.00), - ( 105200, 2578, 6.75), - ( 'inf', 6679, 7.15), + ( 44450, 0, 5.80), + ( 105200, 2578, 6.75), + ( 'inf', 6679, 7.15), ), } @@ -60,8 +60,14 @@ { - 'single': (( 82900, 9550), (157900, 75000)), - 'married': ((165800, 21950), (315800, 150000)), + 'single': { + ( 82900, 9550), + (157900, 75000), + }, + 'married': { + (165800, 21950), + (315800, 150000), + }, } diff --git a/l10n_us_hr_payroll/models/state/me_maine.py b/l10n_us_hr_payroll/models/state/me_maine.py index d2f4d36b..0accc6ff 100644 --- a/l10n_us_hr_payroll/models/state/me_maine.py +++ b/l10n_us_hr_payroll/models/state/me_maine.py @@ -47,7 +47,6 @@ def me_maine_state_income_withholding(payslip, categories, worked_days, inputs): standard_deduction_amt = last * (amt - taxable_income) / flat_amt break last = flat_amt - annual_income = taxable_income - (exemption_amt + standard_deduction_amt) withholding = 0.0 for row in tax_rate: @@ -57,8 +56,7 @@ def me_maine_state_income_withholding(payslip, categories, worked_days, inputs): break last = amt - if withholding < 0.0: - withholding = 0.0 + withholding = max(withholding, 0.0) withholding = round(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 37fe2602..eb84ce65 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -143,7 +143,7 @@ class HRContractUSPayrollConfig(models.Model): me_w4me_sit_filing_status = fields.Selection([ ('', 'Exempt'), - ('single', 'Single'), + ('single', 'Single or Head of Household'), ('married', 'Married'), ], string='Maine W-4ME Filing Status', help='ME W-4ME 3.') me_w4me_sit_allowances = fields.Integer(string='Maine Allowances', help='W-4ME 4.') diff --git a/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py index b5f0ca87..165455ce 100644 --- a/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_me_maine_payslip_2020.py @@ -27,12 +27,13 @@ class TestUsMEPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('ME', self.ME_UNEMP, date(2020, 1, 1), wage_base=self.ME_UNEMP_MAX_WAGE) self._test_sit(300.0, 'single', 0.0, False, 2, 'weekly', date(2020, 1, 1), 0.0) - self._test_sit(800.0, 'single', 0.0, False, 2, 'weekly', date(2020, 1, 1), 26.00) - self._test_sit(4500.0, 'married', 0.0, False, 2, 'weekly', date(2020, 1, 1), 277.00) - self._test_sit(4500.0, 'married', 0.0, True, 2, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(800.0, 'single', 0.0, False, 2, 'bi-weekly', date(2020, 1, 1), 6.00) + self._test_sit(4500.0, 'married', 0.0, True, 0, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(4500.0, 'married', 0.0, False, 2, 'monthly', date(2020, 1, 1), 113.00) self._test_sit(4500.0, 'married', 10.0, False, 2, 'weekly', date(2020, 1, 1), 287.00) + self._test_sit(7000.0, '', 10.0, False, 2, 'weekly', date(2020, 1, 1), 0.00) From f11bbe49f7dc2962c18a457d442415ca8e058b08 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 17:19:27 -0400 Subject: [PATCH 31/63] [IMP] l10n_us_hr_payroll: Refactored Tax table and Improved test case for NE Nebraska 2020. --- l10n_us_hr_payroll/data/state/ne_nebraska.xml | 142 ++++++++++++++++-- .../tests/test_us_ne_nebraska_payslip_2020.py | 5 +- 2 files changed, 130 insertions(+), 17 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ne_nebraska.xml b/l10n_us_hr_payroll/data/state/ne_nebraska.xml index 4db292ba..1951ff2f 100644 --- a/l10n_us_hr_payroll/data/state/ne_nebraska.xml +++ b/l10n_us_hr_payroll/data/state/ne_nebraska.xml @@ -27,7 +27,7 @@ - + US NE Nebraska SIT Tax Rate us_ne_sit_tax_rate @@ -37,22 +37,134 @@ { 'single': { - 'weekly': ((57, 0.00, 0.0), (105, 0.00, 2.26), (342, 1.08, 3.22), (496, 8.71, 4.91), (629, 16.27, 6.20), (1182, 24.52, 6.59), ('inf', 60.96, 6.95)), - 'bi-weekly': ((114, 0.00, 0.0), (211, 0.00, 2.26), (684, 2.19, 3.22), (992, 17.42, 4.91), (1259, 32.54, 6.20), (2364, 49.09, 6.59), ('inf', 121.91, 6.95)), - 'semi-monthly': ((124, 0.00, 0.0), (228, 0.00, 2.26), (741, 2.35, 3.22), (1074, 18.87, 4.91), (1364, 35.22, 6.20), (2561, 53.20, 6.59), ('inf', 132.08, 6.95)), - 'monthly': ((248, 0.00, 0.0), (457, 0.00, 2.26), (1483, 4.72, 3.22), (2148, 37.76, 4.91), (2728, 70.41, 6.20), (5123, 106.37, 6.59), ('inf', 264.20, 6.95)), - 'quarterly': ((744, 0.00, 0.0), (1370, 0.00, 2.26), (4448, 14.15, 3.22), (6445, 113.26, 4.91), (8183, 211.31, 6.20), (15368, 319.07, 6.59), ('inf', 792.56, 6.95)), - 'semi-annual': ((1488, 0.00, 0.0), (2740, 0.00, 2.26), (8895, 28.30, 3.22), (12890, 226.49, 4.91), (16365, 422.64, 6.20), (30735, 638.09, 6.59), ('inf', 1585.07, 6.95)), - 'annually': ((2975, 0.00, 0.0), (5480, 0.00, 2.26), (17790, 56.61, 3.22), (25780, 452.99, 4.91), (32730, 845.30, 6.20), (61470, 1276.20, 6.59), ('inf', 3170.17, 6.95)), + 'weekly': ( + ( 57, 0.00, 0.00), + ( 105, 0.00, 2.26), + ( 342, 1.08, 3.22), + ( 496, 8.71, 4.91), + ( 629, 16.27, 6.20), + ( 1182, 24.52, 6.59), + ('inf', 60.96, 6.95), + ), + 'bi-weekly': ( + ( 114, 0.00, 0.00), + ( 211, 0.00, 2.26), + ( 684, 2.19, 3.22), + ( 992, 17.42, 4.91), + ( 1259, 32.54, 6.20), + ( 2364, 49.09, 6.59), + ('inf', 121.91, 6.95), + ), + 'semi-monthly': ( + ( 124, 0.00, 0.00), + ( 228, 0.00, 2.26), + ( 741, 2.35, 3.22), + ( 1074, 18.87, 4.91), + ( 1364, 35.22, 6.20), + ( 2561, 53.20, 6.59), + ('inf', 132.08, 6.95), + ), + 'monthly': ( + ( 248, 0.00, 0.00), + ( 457, 0.00, 2.26), + ( 1483, 4.72, 3.22), + ( 2148, 37.76, 4.91), + ( 2728, 70.41, 6.20), + ( 5123, 106.37, 6.59), + ('inf', 264.20, 6.95), + ), + 'quarterly': ( + ( 744, 0.00, 0.00), + ( 1370, 0.00, 2.26), + ( 4448, 14.15, 3.22), + ( 6445, 113.26, 4.91), + ( 8183, 211.31, 6.20), + ( 15368, 319.07, 6.59), + ( 'inf', 792.56, 6.95), + ), + 'semi-annual': ( + ( 1488, 0.00, 0.00), + ( 2740, 0.00, 2.26), + ( 8895, 28.30, 3.22), + ( 12890, 226.49, 4.91), + ( 16365, 422.64, 6.20), + ( 30735, 638.09, 6.59), + ( 'inf', 1585.07, 6.95), + ), + 'annually': ( + ( 2975, 0.00, 0.00), + ( 5480, 0.00, 2.26), + ( 17790, 56.61, 3.22), + ( 25780, 452.99, 4.91), + ( 32730, 845.30, 6.20), + ( 61470, 1276.20, 6.59), + ( 'inf', 3170.17, 6.95), + ), }, 'married': { - 'weekly': ((137, 0.00, 0.0), (204, 0.00, 2.26), (508, 1.51, 3.22), (790, 11.30, 4.91), (981, 25.15, 6.20), (1300, 36.99, 6.59), ('inf', 58.01, 6.95)), - 'bi-weekly': ((273, 0.00, 0.0), (408, 0.00, 2.26), (1016, 3.05, 3.22), (1581, 22.63, 4.91), (1961, 50.37, 6.20), (2601, 73.93, 6.59), ('inf', 116.11, 6.95)), - 'semi-monthly': ((296, 0.00, 0.0), (442, 0.00, 2.26), (1101, 3.30, 3.22), (1713, 24.52, 4.91), (2125, 54.57, 6.20), (2818, 80.11, 6.59), ('inf', 125.78, 6.95)), - 'monthly': ((592, 0.00, 0.0), (884, 0.00, 2.26), (2202, 6.60, 3.22), (3425, 49.04, 4.91), (4249, 109.09, 6.20), (5635, 160.18, 6.59), ('inf', 251.52, 6.95)), - 'quarterly': ((1775, 0.00, 0.0), (2653, 0.00, 2.26), (6605, 19.84, 3.22), (10275, 147.09, 4.91), (12748, 327.29, 6.20), (16905, 480.62, 6.59), ('inf', 754.57, 6.95)), - 'semi-annual': ((3550, 0.00, 0.0), (5305, 0.00, 2.26), (13210, 39.66, 3.22), (20550, 294.20, 4.91), (25495, 654.59, 6.20), (33810, 961.18, 6.59), ('inf', 1509.14, 6.95)), - 'annually': ((7100, 0.00, 0.0), (10610, 0.00, 2.26), (26420, 79.33, 3.22), (41100, 588.41, 4.91), (50990, 1309.20, 6.20), (67620, 1992.38, 6.59), ('inf', 3018.30, 6.95)), + 'weekly': ( + ( 137, 0.00, 0.00), + ( 204, 0.00, 2.26), + ( 508, 1.51, 3.22), + ( 790, 11.30, 4.91), + ( 981, 25.15, 6.20), + ( 1300, 36.99, 6.59), + ('inf', 58.01, 6.95), + ), + 'bi-weekly': ( + ( 273, 0.00, 0.00), + ( 408, 0.00, 2.26), + ( 1016, 3.05, 3.22), + ( 1581, 22.63, 4.91), + ( 1961, 50.37, 6.20), + ( 2601, 73.93, 6.59), + ('inf', 116.11, 6.95), + ), + 'semi-monthly': ( + ( 296, 0.00, 0.00), + ( 442, 0.00, 2.26), + ( 1101, 3.30, 3.22), + ( 1713, 24.52, 4.91), + ( 2125, 54.57, 6.20), + ( 2818, 80.11, 6.59), + ('inf', 125.78, 6.95), + ), + 'monthly': ( + ( 592, 0.00, 0.00), + ( 884, 0.00, 2.26), + ( 2202, 6.60, 3.22), + ( 3425, 49.04, 4.91), + ( 4249, 109.09, 6.20), + ( 5635, 160.18, 6.59), + ('inf', 251.52, 6.95), + ), + 'quarterly': ( + ( 1775, 0.00, 0.00), + ( 2653, 0.00, 2.26), + ( 6605, 19.84, 3.22), + ( 10275, 147.09, 4.91), + ( 12748, 327.29, 6.20), + ( 16905, 480.62, 6.59), + ( 'inf', 754.57, 6.95), + ), + 'semi-annual': ( + ( 3550, 0.00, 0.00), + ( 5305, 0.00, 2.26), + ( 13210, 39.66, 3.22), + ( 20550, 294.20, 4.91), + ( 25495, 654.59, 6.20), + ( 33810, 961.18, 6.59), + ( 'inf', 1509.14, 6.95), + ), + 'annually': ( + ( 7100, 0.00, 0.00), + ( 10610, 0.00, 2.26), + ( 26420, 79.33, 3.22), + ( 41100, 588.41, 4.91), + ( 50990, 1309.20, 6.20), + ( 67620, 1992.38, 6.59), + ( 'inf', 3018.30, 6.95), + ), }, } diff --git a/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py index bbf2b7b0..785e4417 100644 --- a/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ne_nebraska_payslip_2020.py @@ -26,7 +26,7 @@ class TestUsNEPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('NE', self.NE_UNEMP, date(2020, 1, 1), wage_base=self.NE_UNEMP_MAX_WAGE) @@ -34,4 +34,5 @@ class TestUsNEPayslip(TestUsPayslip): self._test_sit(9500.0, 'single', False, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 612.63) self._test_sit(10500.0, 'married', False, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 659.85) self._test_sit(9500.0, 'single', True, 0.0, 1, 'bi-weekly', date(2020, 1, 1), 0.0) - self._test_sit(10500.0, 'single', False, 10.0, 2, 'monthly', date(2020, 1, 1), 625.2) \ No newline at end of file + self._test_sit(10500.0, 'single', False, 10.0, 2, 'monthly', date(2020, 1, 1), 625.2) + self._test_sit(4000.0, 'single', False, 0.0, 1, 'monthly', date(2020, 1, 1), 179.44) From 2d4cb3c1dce229ce5b9f4994df6c6b3ecc259c8c Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 18:12:48 -0400 Subject: [PATCH 32/63] [IMP] l10n_us_hr_payroll: Refactored Tax table, changed tax rate and added additional withholding field. Improved test case for ME Maine 2020. --- .../data/state/la_louisiana.xml | 30 ++++++++++++++----- .../models/state/la_louisiana.py | 2 ++ .../test_us_la_louisiana_payslip_2019.py | 6 +++- .../test_us_la_louisiana_payslip_2020.py | 12 ++++---- .../views/us_payroll_config_views.xml | 1 + 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/la_louisiana.xml b/l10n_us_hr_payroll/data/state/la_louisiana.xml index 5f23bea4..7e4f5fe2 100644 --- a/l10n_us_hr_payroll/data/state/la_louisiana.xml +++ b/l10n_us_hr_payroll/data/state/la_louisiana.xml @@ -27,17 +27,17 @@ - 6.20 + 1.14 - 6.20 + 1.14 - + US LA Louisiana SIT Tax Rate us_la_sit_tax_rate @@ -46,16 +46,32 @@ { - 'single': ((12500.00, 2.10), (50000.00, 1.60), ('inf', 1.35)), - 'married': ((25000.00, 2.10), (100000.00, 1.65), ('inf', 1.35)), + 'single': ( + (12500.00, 2.10), + (50000.00, 1.60), + ( 'inf', 1.35), + ), + 'married': ( + ( 25000.00, 2.10), + (100000.00, 1.65), + ( 'inf', 1.35), + ), } { - 'single': ((12500.00, 2.10), (50000.00, 1.60), ('inf', 1.35)), - 'married': ((25000.00, 2.10), (100000.00, 1.65), ('inf', 1.35)), + 'single': ( + (12500.00, 2.10), + (50000.00, 1.60), + ( 'inf', 1.35) + ), + 'married': ( + ( 25000.00, 2.10), + (100000.00, 1.65), + ( 'inf', 1.35) + ), } diff --git a/l10n_us_hr_payroll/models/state/la_louisiana.py b/l10n_us_hr_payroll/models/state/la_louisiana.py index 0697d696..c580d5a2 100644 --- a/l10n_us_hr_payroll/models/state/la_louisiana.py +++ b/l10n_us_hr_payroll/models/state/la_louisiana.py @@ -24,6 +24,7 @@ def la_louisiana_state_income_withholding(payslip, categories, worked_days, inpu pay_periods = payslip.dict.get_pay_periods_in_year() personal_exemptions = payslip.contract_id.us_payroll_config_value('la_l4_sit_exemptions') + additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') dependent_exemptions = payslip.contract_id.us_payroll_config_value('la_l4_sit_dependents') tax_table = payslip.rule_parameter('us_la_sit_tax_rate')[filing_status] exemption_rate = payslip.rule_parameter('us_la_sit_personal_exemption_rate') @@ -57,4 +58,5 @@ def la_louisiana_state_income_withholding(payslip, categories, worked_days, inpu withholding = withholding - (after_credits_under + after_credits_over) withholding = round(withholding, 2) + withholding += additional return wage, -((withholding / wage) * 100.0) diff --git a/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py index f723744a..1d01c618 100644 --- a/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py +++ b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2019.py @@ -7,7 +7,7 @@ class TestUsLAPayslip(TestUsPayslip): # TAXES AND RATES LA_UNEMP_MAX_WAGE = 7700.00 - LA_UNEMP = -(6.20 / 100.0) + LA_UNEMP = -(1.14 / 100.0) def test_taxes_single_weekly(self): salary = 700.00 @@ -15,6 +15,7 @@ class TestUsLAPayslip(TestUsPayslip): filing_status = 'single' exemptions = 1 dependents = 2 + additional_withholding = 0 # SEE http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf for example calculations # wh_to test is 19.42 # Our algorithm correctly rounds whereas theirs does it prematurely. @@ -24,6 +25,7 @@ class TestUsLAPayslip(TestUsPayslip): wage=salary, state_id=self.get_us_state('LA'), la_l4_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, la_l4_sit_exemptions=exemptions, la_l4_sit_dependents=dependents, schedule_pay=schedule_pay) @@ -54,6 +56,7 @@ class TestUsLAPayslip(TestUsPayslip): filing_status = 'married' exemptions = 2 dependents = 3 + additional_withholding = 0 # SEE http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf for example calculations # wh_to test is 157.12 wh_to_check = -157.12 @@ -62,6 +65,7 @@ class TestUsLAPayslip(TestUsPayslip): wage=salary, state_id=self.get_us_state('LA'), la_l4_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, la_l4_sit_exemptions=exemptions, la_l4_sit_dependents=dependents, schedule_pay=schedule_pay) diff --git a/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py index 14dde5bf..d23c3ab3 100755 --- a/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_la_louisiana_payslip_2020.py @@ -9,15 +9,16 @@ class TestUsLAPayslip(TestUsPayslip): # 2020 Taxes and Rates ### LA_UNEMP_MAX_WAGE = 7700.0 - LA_UNEMP = 6.20 + LA_UNEMP = 1.14 # Calculation based on http://revenue.louisiana.gov/TaxForms/1306(1_12)TF.pdf - def _test_sit(self, wage, filing_status, exemptions, dependents, schedule_pay, date_start, expected_withholding): + def _test_sit(self, wage, filing_status, additional_withholding, exemptions, dependents, schedule_pay, date_start, expected_withholding): employee = self._createEmployee() contract = self._createContract(employee, wage=wage, state_id=self.get_us_state('LA'), la_l4_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, la_l4_sit_exemptions=exemptions, la_l4_sit_dependents=dependents, schedule_pay=schedule_pay) @@ -26,9 +27,10 @@ class TestUsLAPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('LA', self.LA_UNEMP, date(2020, 1, 1), wage_base=self.LA_UNEMP_MAX_WAGE) - self._test_sit(700.0, 'single', 1.0, 2.0, 'weekly', date(2020, 1, 1), 19.43) - self._test_sit(4600.0, 'married', 2.0, 3.0, 'bi-weekly', date(2020, 1, 1), 157.12) + self._test_sit(700.0, 'single', 0.0, 1.0, 2.0, 'weekly', date(2020, 1, 1), 19.43) + self._test_sit(4600.0, 'married', 0.0, 2.0, 3.0, 'bi-weekly', date(2020, 1, 1), 157.12) + self._test_sit(6000.0, 'single', 10.0, 2.0, 3.0, 'monthly', date(2020, 1, 1), 219.08) 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 d2b5ced5..022326ea 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -142,6 +142,7 @@ +

Form W-4ME - State Income Tax

From d95efc2b8ce4fe88e0991971e18aaa95f743adcb Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Tue, 18 Aug 2020 20:06:25 -0400 Subject: [PATCH 33/63] [IMP] l10n_us_hr_payroll: Reformat Tax table for WV West Virginia 2020. --- .../data/state/wv_west_virginia.xml | 124 +++++++++++++++--- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/wv_west_virginia.xml b/l10n_us_hr_payroll/data/state/wv_west_virginia.xml index c91b03b8..ee542c4a 100644 --- a/l10n_us_hr_payroll/data/state/wv_west_virginia.xml +++ b/l10n_us_hr_payroll/data/state/wv_west_virginia.xml @@ -27,7 +27,7 @@ - + US WV West Virginia Exemption Rate us_wv_sit_exemption_rate @@ -46,7 +46,7 @@ - + US WV West Virginia SIT Tax Rate us_wv_sit_tax_rate @@ -56,25 +56,115 @@ { 'single': { - 'weekly':((192, 0.00, 3.0), (481, 5.76, 4.0), (769, 17.32, 4.5), (1154, 30.28, 6.0), ('inf', 53.38, 6.5)), - 'bi-weekly':((385, 0.00, 3.0), (962, 11.55, 4.0), (1538, 34.63, 4.5), (2308, 60.55, 6.0), ('inf', 106.75, 6.5)), - 'semi-monthly':((417, 0.00, 3.0), (1042, 12.51, 4.0), (1667, 37.51, 4.5), (2500, 65.64, 6.0), ('inf', 115.62, 6.5)), - 'monthly':((833, 0.00, 3.0), (2083, 24.99, 4.0), (3333, 74.99, 4.5), (5000, 131.24, 6.0), ('inf', 231.26, 6.5)), - 'annually':((10000, 0.00, 3.0), (25000, 300.00, 4.0), (40000, 900.00, 4.5), (60000, 1575.00, 6.0), ('inf', 2775.00, 6.5)), + 'weekly':( + ( 192, 0.00, 3.0), + ( 481, 5.76, 4.0), + ( 769, 17.32, 4.5), + ( 1154, 30.28, 6.0), + ('inf', 53.38, 6.5), + ), + 'bi-weekly':( + ( 385, 0.00, 3.0), + ( 962, 11.55, 4.0), + ( 1538, 34.63, 4.5), + ( 2308, 60.55, 6.0), + ('inf', 106.75, 6.5), + ), + 'semi-monthly':( + ( 417, 0.00, 3.0), + ( 1042 , 12.51, 4.0), + ( 1667, 37.51, 4.5), + ( 2500, 65.64, 6.0), + ('inf', 115.62, 6.5), + ), + 'monthly':( + ( 833, 0.00, 3.0), + ( 2083, 24.99, 4.0), + ( 3333, 74.99, 4.5), + ( 5000, 131.24, 6.0), + ('inf', 231.26, 6.5), + ), + 'annually':( + ( 10000, 0.00, 3.0), + ( 25000, 300.00, 4.0), + ( 40000, 900.00, 4.5), + ( 60000, 1575.00, 6.0), + ( 'inf', 2775.00, 6.5), + ), }, 'married': { - 'weekly':((115, 0.00, 3.0), (288, 3.45, 4.0), (462, 10.37, 4.5), (692, 18.20, 6.0), ('inf', 32.00, 6.5)), - 'bi-weekly':((231, 0.00, 3.0), (577, 6.93, 4.0), (923, 20.77, 4.5), (1385, 36.34, 6.0), ('inf', 64.06, 6.5)), - 'semi-monthly':((250, 0.00, 3.0), (625, 7.50, 4.0), (1000, 22.50, 4.5), (1500, 39.38, 6.0), ('inf', 69.38, 6.5)), - 'monthly':((500, 0.00, 3.0), (1250, 15.00, 4.0), (2000, 45.00, 4.5), (3000, 78.75, 6.0), ('inf', 138.75, 6.5)), - 'annually':((6000, 0.00, 3.0), (15000, 180.00, 4.0), (24000, 540.00, 4.5), (36000, 945.00, 6.0), ('inf', 1665.00, 6.5)), + 'weekly':( + ( 115, 0.00, 3.0), + ( 288, 3.45, 4.0), + ( 462, 10.37, 4.5), + ( 692, 18.20, 6.0), + ('inf', 32.00, 6.5), + ), + 'bi-weekly':( + ( 231, 0.00, 3.0), + ( 577, 6.93, 4.0), + ( 923, 20.77, 4.5), + ( 1385, 36.34, 6.0), + ('inf', 64.06, 6.5), + ), + 'semi-monthly':( + ( 250, 0.00, 3.0), + ( 625, 7.50, 4.0), + ( 1000, 22.50, 4.5), + ( 1500, 39.38, 6.0), + ('inf', 69.38, 6.5), + ), + 'monthly':( + ( 500, 0.00, 3.0), + ( 1250, 15.00, 4.0), + ( 2000, 45.00, 4.5), + ( 3000, 78.75, 6.0), + ('inf', 138.75, 6.5), + ), + 'annually':( + ( 6000, 0.00, 3.0), + (15000, 180.00, 4.0), + (24000, 540.00, 4.5), + (36000, 945.00, 6.0), + ('inf', 1665.00, 6.5), + ), }, 'head_household': { - 'weekly':((192, 0.00, 3.0), (481, 5.76, 4.0), (769, 17.32, 4.5), (1154, 30.28, 6.0), ('inf', 53.38, 6.5)), - 'bi-weekly':((385, 0.00, 3.0), (962, 11.55, 4.0), (1538, 34.63, 4.5), (2308, 60.55, 6.0), ('inf', 106.75, 6.5)), - 'semi-monthly':((417, 0.00, 3.0), (1042, 12.51, 4.0), (1667, 37.51, 4.5), (2500, 65.64, 6.0), ('inf', 115.62, 6.5)), - 'monthly':((833, 0.00, 3.0), (2083, 24.99, 4.0), (3333, 74.99, 4.5), (5000, 131.24, 6.0), ('inf', 231.26, 6.5)), - 'annually':((10000, 0.00, 3.0), (25000, 300.00, 4.0), (40000, 900.00, 4.5), (60000, 1575.00, 6.0), ('inf', 2775.00, 6.5)), + 'weekly':( + ( 192, 0.00, 3.0), + ( 481, 5.76, 4.0), + ( 769, 17.32, 4.5), + ( 1154, 30.28, 6.0), + ('inf', 53.38, 6.5), + ), + 'bi-weekly':( + ( 385, 0.00, 3.0), + ( 962, 11.55, 4.0), + ( 1538, 34.63, 4.5), + ( 2308, 60.55, 6.0), + ('inf', 106.75, 6.5), + ), + 'semi-monthly':( + ( 417, 0.00, 3.0), + ( 1042, 12.51, 4.0), + ( 1667, 37.51, 4.5), + ( 2500, 65.64, 6.0), + ('inf', 115.62, 6.5), + ), + 'monthly':( + ( 833, 0.00, 3.0), + ( 2083, 24.99, 4.0), + ( 3333, 74.99, 4.5), + ( 5000, 131.24, 6.0), + ('inf', 231.26, 6.5), + ), + 'annually':( + ( 10000, 0.00, 3.0), + ( 25000, 300.00, 4.0), + ( 40000, 900.00, 4.5), + ( 60000, 1575.00, 6.0), + ( 'inf', 2775.00, 6.5), + ), }, } From 9a54cbcd7633eb26c2782349a4d0e9c39d1c572e Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 10:23:12 -0400 Subject: [PATCH 34/63] [IMP] l10n_us_hr_payroll: Reformat Tax table, changed field string and improved test case for OK Oklahoma 2020 --- l10n_us_hr_payroll/data/state/ok_oklahoma.xml | 214 ++++++++++++++++-- .../models/us_payroll_config.py | 4 +- .../tests/test_us_ok_oklahoma_payslip_2020.py | 1 + 3 files changed, 194 insertions(+), 25 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ok_oklahoma.xml b/l10n_us_hr_payroll/data/state/ok_oklahoma.xml index f4ec8269..04aa8380 100644 --- a/l10n_us_hr_payroll/data/state/ok_oklahoma.xml +++ b/l10n_us_hr_payroll/data/state/ok_oklahoma.xml @@ -27,7 +27,7 @@ - + US OK Oklahoma Allowances Rate us_ok_sit_allowances_rate @@ -48,7 +48,7 @@ - + US OK Oklahoma SIT Tax Rate us_ok_sit_tax_rate @@ -58,31 +58,199 @@ { 'single': { - 'weekly': ((122, 0.00, 0.00), (141, 0.50, 0.00), (170, 1.00, 0.10), (194, 2.00, 0.38), (216, 3.00, 0.87), (261, 4.00, 1.53), ('inf', 5.00, 3.30)), - 'bi-weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (521, 4.00, 3.06), ('inf', 5.00, 6.60)), - 'semi-monthly': ((265, 0.00, 0.00), (306, 0.50, 0.00), (369, 1.00, 0.21), (421, 2.00, 0.83), (469, 3.00, 1.88), (565, 4.00, 3.31), ('inf', 5.00, 7.15)), - 'monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1129, 4.00, 6.63), ('inf', 5.00, 14.29)), - 'quarterly': ((1588, 0.00, 0.00), (1838, 0.50, 0.00), (2213, 1.00, 1.25), (2525, 2.00, 5.00), (2813, 3.00, 11.25), (3388, 4.00, 19.88), ('inf', 5.00, 42.88)), - 'semi-annual': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6775, 4.00, 39.75), ('inf', 5.00, 85.75)), - 'annually': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (13550, 4.00, 79.50), ('inf', 5.00, 171.50)), + 'weekly': ( + ( 122, 0.00, 0.00), + ( 141, 0.50, 0.00), + ( 170, 1.00, 0.10), + ( 194, 2.00, 0.38), + ( 216, 3.00, 0.87), + ( 261, 4.00, 1.53), + ('inf', 5.00, 3.30), + ), + 'bi-weekly': ( + ( 244, 0.00, 0.00), + ( 283, 0.50, 0.00), + ( 340, 1.00, 0.19), + ( 388, 2.00, 0.77), + ( 433, 3.00, 1.73), + ( 521, 4.00, 3.06), + ('inf', 5.00, 6.60), + ), + 'semi-monthly': ( + ( 265, 0.00, 0.00), + ( 306, 0.50, 0.00), + ( 369, 1.00, 0.21), + ( 421, 2.00, 0.83), + ( 469, 3.00, 1.88), + ( 565, 4.00, 3.31), + ('inf', 5.00, 7.15), + ), + 'monthly': ( + ( 529, 0.00, 0.00), + ( 613, 0.50, 0.00), + ( 738, 1.00, 0.42), + ( 842, 2.00, 1.67), + ( 938, 3.00, 3.75), + (1129, 4.00, 6.63), + ('inf', 5.00, 14.29), + ), + 'quarterly': ( + ( 1588, 0.00, 0.00), + ( 1838, 0.50, 0.00), + ( 2213, 1.00, 1.25), + ( 2525, 2.00, 5.00), + ( 2813, 3.00, 11.25), + ( 3388, 4.00, 19.88), + ('inf', 5.00, 42.88), + ), + 'semi-annual': ( + ( 3175, 0.00, 0.00), + ( 3675, 0.50, 0.00), + ( 4425, 1.00, 2.50), + ( 5050, 2.00, 10.00), + (5625, 3.00, 22.50), + ( 6775, 4.00, 39.75), + ('inf', 5.00, 85.75), + ), + 'annually': ( + ( 6350, 0.00, 0.00), + ( 7350, 0.50, 0.00), + ( 8850, 1.00, 5.00), + (10100, 2.00, 20.00), + (11250, 3.00, 45.00), + (13550, 4.00, 79.50), + ('inf', 5.00, 171.50), + ), }, 'married': { - 'weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (479, 4.00, 3.06), ('inf', 5.00, 4.90)), - 'bi-weekly': ((488, 0.00, 0.00), (565, 0.50, 0.00), (681, 1.00, 0.38), (777, 2.00, 1.54), (865, 3.00, 3.46), (958, 4.00, 6.12), ('inf', 5.00, 9.81)), - 'semi-monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1038, 4.00, 6.63), ('inf', 5.00, 10.63)), - 'monthly': ((1058, 0.00, 0.00), (1225, 0.50, 0.00), (1475, 1.00, 0.83), (1683, 2.00, 3.33), (1875, 3.00, 7.50), (2075, 4.00, 13.25), ('inf', 5.00, 21.25)), - 'quarterly': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6225, 4.00, 39.75), ('inf', 5.00, 63.75)), - 'semi-annual': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (12450, 4.00, 79.50), ('inf', 5.00, 127.50)), - 'annually': ((12700, 0.00, 0.00), (14700, 0.50, 0.00), (17700, 1.00, 10.00), (20200, 2.00, 40.00), (22500, 3.00, 90.00), (24900, 4.00, 159.00), ('inf', 5.00, 255.00)), + 'weekly': ( + ( 244, 0.00, 0.00), + ( 283, 0.50, 0.00), + ( 340, 1.00, 0.19), + ( 388, 2.00, 0.77), + ( 433, 3.00, 1.73), + ( 479, 4.00, 3.06), + ('inf', 5.00, 4.90), + ), + 'bi-weekly': ( + ( 488, 0.00, 0.00), + ( 565, 0.50, 0.00), + ( 681, 1.00, 0.38), + ( 777, 2.00, 1.54), + ( 865, 3.00, 3.46), + ( 958, 4.00, 6.12), + ('inf', 5.00, 9.81), + ), + 'semi-monthly': ( + ( 529, 0.00, 0.00), + ( 613, 0.50, 0.00), + ( 738, 1.00, 0.42), + ( 842, 2.00, 1.67), + ( 938, 3.00, 3.75), + ( 1038, 4.00, 6.63), + ('inf', 5.00, 10.63), + ), + 'monthly': ( + ( 1058, 0.00, 0.00), + ( 1225, 0.50, 0.00), + ( 1475, 1.00, 0.83), + ( 1683, 2.00, 3.33), + ( 1875, 3.00, 7.50), + ( 2075, 4.00, 13.25), + ('inf', 5.00, 21.25), + ), + 'quarterly': ( + ( 3175, 0.00, 0.00), + ( 3675, 0.50, 0.00), + ( 4425, 1.00, 2.50), + ( 5050, 2.00, 10.00), + ( 5625, 3.00, 22.50), + ( 6225, 4.00, 39.75), + ('inf', 5.00, 63.75), + ), + 'semi-annual': ( + ( 6350, 0.00, 0.00), + ( 7350, 0.50, 0.00), + ( 8850, 1.00, 5.00), + ( 10100, 2.00, 20.00), + ( 11250, 3.00, 45.00), + ( 12450, 4.00, 79.50), + ( 'inf', 5.00, 127.50), + ), + 'annually': ( + ( 12700, 0.00, 0.00), + ( 14700, 0.50, 0.00), + ( 17700, 1.00, 10.00), + ( 20200, 2.00, 40.00), + ( 22500, 3.00, 90.00), + ( 24900, 4.00, 159.00), + ( 'inf', 5.00, 255.00), + ), }, 'head_household': { - 'weekly': ((122, 0.00, 0.00), (141, 0.50, 0.00), (170, 1.00, 0.10), (194, 2.00, 0.38), (216, 3.00, 0.87), (261, 4.00, 1.53), ('inf', 5.00, 3.30)), - 'bi-weekly': ((244, 0.00, 0.00), (283, 0.50, 0.00), (340, 1.00, 0.19), (388, 2.00, 0.77), (433, 3.00, 1.73), (521, 4.00, 3.06), ('inf', 5.00, 6.60)), - 'semi-monthly': ((265, 0.00, 0.00), (306, 0.50, 0.00), (369, 1.00, 0.21), (421, 2.00, 0.83), (469, 3.00, 1.88), (565, 4.00, 3.31), ('inf', 5.00, 7.15)), - 'monthly': ((529, 0.00, 0.00), (613, 0.50, 0.00), (738, 1.00, 0.42), (842, 2.00, 1.67), (938, 3.00, 3.75), (1129, 4.00, 6.63), ('inf', 5.00, 14.29)), - 'quarterly': ((1588, 0.00, 0.00), (1838, 0.50, 0.00), (2213, 1.00, 1.25), (2525, 2.00, 5.00), (2813, 3.00, 11.25), (3388, 4.00, 19.88), ('inf', 5.00, 42.88)), - 'semi-annual': ((3175, 0.00, 0.00), (3675, 0.50, 0.00), (4425, 1.00, 2.50), (5050, 2.00, 10.00), (5625, 3.00, 22.50), (6775, 4.00, 39.75), ('inf', 5.00, 85.75)), - 'annually': ((6350, 0.00, 0.00), (7350, 0.50, 0.00), (8850, 1.00, 5.00), (10100, 2.00, 20.00), (11250, 3.00, 45.00), (13550, 4.00, 79.50), ('inf', 5.00, 171.50)), + 'weekly': ( + ( 122, 0.00, 0.00), + ( 141, 0.50, 0.00), + ( 170, 1.00, 0.10), + ( 194, 2.00, 0.38), + ( 216, 3.00, 0.87), + ( 261, 4.00, 1.53), + ('inf', 5.00, 3.30), + ), + 'bi-weekly': ( + ( 244, 0.00, 0.00), + ( 283, 0.50, 0.00), + ( 340, 1.00, 0.19), + ( 388, 2.00, 0.77), + ( 433, 3.00, 1.73), + ( 521, 4.00, 3.06), + ('inf', 5.00, 6.60), + ), + 'semi-monthly': ( + ( 265, 0.00, 0.00), + ( 306, 0.50, 0.00), + ( 369, 1.00, 0.21), + ( 421, 2.00, 0.83), + ( 469, 3.00, 1.88), + ( 565, 4.00, 3.31), + ('inf', 5.00, 7.15), + ), + 'monthly': ( + ( 529, 0.00, 0.00), + ( 613, 0.50, 0.00), + ( 738, 1.00, 0.42), + ( 842, 2.00, 1.67), + ( 938, 3.00, 3.75), + ( 1129, 4.00, 6.63), + ('inf', 5.00, 14.29), + ), + 'quarterly': ( + ( 1588, 0.00, 0.00), + ( 1838, 0.50, 0.00), + ( 2213, 1.00, 1.25), + ( 2525, 2.00, 5.00), + ( 2813, 3.00, 11.25), + ( 3388, 4.00, 19.88), + ('inf', 5.00, 42.88), + ), + 'semi-annual': ( + ( 3175, 0.00, 0.00), + ( 3675, 0.50, 0.00), + ( 4425, 1.00, 2.50), + ( 5050, 2.00, 10.00), + ( 5625, 3.00, 22.50), + ( 6775, 4.00, 39.75), + ('inf', 5.00, 85.75), + ), + 'annually': ( + ( 6350, 0.00, 0.00), + ( 7350, 0.50, 0.00), + ( 8850, 1.00, 5.00), + (10100, 2.00, 20.00), + (11250, 3.00, 45.00), + (13550, 4.00, 79.50), + ('inf', 5.00, 171.50), + ), }, } diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index eb84ce65..8741d81d 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -241,9 +241,9 @@ class HRContractUSPayrollConfig(models.Model): ok_w4_sit_filing_status = fields.Selection([ ('single', 'Single'), ('married', 'Married'), - ('head_household', 'Head of Household') + ('head_household', 'Married, but withhold at higher Single rate') ], string='Oklahoma OK-W-4 Filing Status', help='OK-W-4') - ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 1.2.3.') + ok_w4_sit_allowances = fields.Integer(string='Oklahoma OK-W-4 Allowances', help='OK-W-4 5.') ri_w4_sit_allowances = fields.Integer(string='Rhode Island RI W-4 Allowances', help='RI W-4 1.') diff --git a/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py index 03297065..cacdcc16 100755 --- a/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ok_oklahoma_payslip_2020.py @@ -35,3 +35,4 @@ class TestUsOKPayslip(TestUsPayslip): self._test_sit(1825, 'married', 2, 0, True, 'monthly', date(2020, 1, 1), 0.00) self._test_sit(1000, 'single', 1, 0, False, 'weekly', date(2020, 1, 1), 39.00) self._test_sit(1000, 'single', 1, 10, False, 'weekly', date(2020, 1, 1), 49.00) + self._test_sit(5000, 'head_household', 2, 10, False, 'monthly', date(2020, 1, 1), 210.00) From aafc5c9f3b83223bcf4b2a7f81aee3611c636e41 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 14:42:35 -0400 Subject: [PATCH 35/63] [IMP] l10n_us_hr_payroll: Refactored Tax table, changed filing status string and Improved test case for KS Kansas 2020. --- l10n_us_hr_payroll/data/state/ks_kansas.xml | 109 ++++++++++++++---- .../models/us_payroll_config.py | 3 +- .../tests/test_us_ks_kansas_payslip_2020.py | 9 +- .../views/us_payroll_config_views.xml | 2 +- 4 files changed, 92 insertions(+), 31 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ks_kansas.xml b/l10n_us_hr_payroll/data/state/ks_kansas.xml index ea4d5672..5b59d2b7 100644 --- a/l10n_us_hr_payroll/data/state/ks_kansas.xml +++ b/l10n_us_hr_payroll/data/state/ks_kansas.xml @@ -48,7 +48,7 @@ - + US KS Kansas SIT Tax Rate us_ks_sit_tax_rate @@ -58,31 +58,92 @@ { 'single': { - 'weekly': ((58, 0.00, 0.00), (346, 3.10, 0.00), (635, 5.25, 8.94), ('inf', 5.70, 24.09)), - 'bi-weekly': ((115, 0.00, 0.00), (692, 3.10, 0.00), (1269, 5.25, 17.88), ('inf', 5.70, 48.17)), - 'semi-monthly': ((125, 0.00, 0.00), (750, 3.10, 0.00), (1375, 5.25, 19.38), ('inf', 5.70, 52.19)), - 'monthly': ((250, 0.00, 0.00), (1500, 3.10, 0.00), (2750, 5.25, 38.75), ('inf', 5.70, 104.38)), - 'quarterly': ((750, 0.00, 0.00), (4500, 3.10, 0.00), (8250, 5.25, 116.25), ('inf', 5.70, 313.13)), - 'semi-annual': ((1500, 0.00, 0.00), (9000, 3.10, 0.00), (16500, 5.25, 232.50), ('inf', 5.70, 626.25)), - 'annually': ((3000, 0.00, 0.00), (18000, 3.10, 0.00), (33000, 5.25, 465.00), ('inf', 5.70, 1252.50)), + 'weekly': ( + ( 58, 0.00, 0.00), + ( 346, 3.10, 0.00), + ( 635, 5.25, 8.94), + ('inf', 5.70, 24.09), + ), + 'bi-weekly': ( + ( 115, 0.00, 0.00), + ( 692, 3.10, 0.00), + ( 1269, 5.25, 17.88), + ('inf', 5.70, 48.17), + ), + 'semi-monthly': ( + ( 125, 0.00, 0.00), + ( 750, 3.10, 0.00), + ( 1375, 5.25, 19.38), + ('inf', 5.70, 52.19), + ), + 'monthly': ( + ( 250, 0.00, 0.00), + ( 1500, 3.10, 0.00), + ( 2750, 5.25, 38.75), + ('inf', 5.70, 104.38), + ), + 'quarterly': ( + ( 750, 0.00, 0.00), + ( 4500, 3.10, 0.00), + (8250, 5.25, 116.25), + ('inf', 5.70, 313.13), + ), + 'semi-annual': ( + ( 1500, 0.00, 0.00), + ( 9000, 3.10, 0.00), + (16500, 5.25, 232.50), + ('inf', 5.70, 626.25), + ), + 'annually': ( + ( 3000, 0.00, 0.00), + (18000, 3.10, 0.00), + (33000, 5.25, 465.00), + ('inf', 5.70, 1252.50), + ), }, 'married': { - 'weekly': ((144, 0.00, 0.00), (721, 3.10, 0.00), (1298, 5.25, 17.88), ('inf', 5.70, 48.17)), - 'bi-weekly': ((288, 0.00, 0.00), (1442, 3.10, 0.00), (2596, 5.25, 35.77), ('inf', 5.70, 96.35)), - 'semi-monthly': ((313, 0.00, 0.00), (1563, 3.10, 0.00), (2813, 5.25, 38.75), ('inf', 5.70, 104.38)), - 'monthly': ((625, 0.00, 0.00), (3125, 3.10, 0.00), (5625, 5.25, 77.50), ('inf', 5.70, 208.75)), - 'quarterly': ((1875, 0.00, 0.00), (9375, 3.10, 0.00), (16875, 5.25, 232.50), ('inf', 5.70, 626.25)), - 'semi-annual': ((3750, 0.00, 0.00), (18750, 3.10, 0.00), (33750, 5.25, 465.00), ('inf', 5.70, 1252.50)), - 'annually': ((7500, 0.00, 0.00), (37500, 3.10, 0.00), (67500, 5.25, 930.00), ('inf', 5.70, 2505.00)), - }, - 'head_household': { - 'weekly': ((58, 0.00, 0.00), (346, 3.10, 0.00), (635, 5.25, 8.94), ('inf', 5.70, 24.09)), - 'bi-weekly': ((115, 0.00, 0.00), (692, 3.10, 0.00), (1269, 5.25, 17.88), ('inf', 5.70, 48.17)), - 'semi-monthly': ((125, 0.00, 0.00), (750, 3.10, 0.00), (1375, 5.25, 19.38), ('inf', 5.70, 52.19)), - 'monthly': ((250, 0.00, 0.00), (1500, 3.10, 0.00), (2750, 5.25, 38.75), ('inf', 5.70, 104.38)), - 'quarterly': ((750, 0.00, 0.00), (4500, 3.10, 0.00), (8250, 5.25, 116.25), ('inf', 5.70, 313.13)), - 'semi-annual': ((1500, 0.00, 0.00), (9000, 3.10, 0.00), (16500, 5.25, 232.50), ('inf', 5.70, 626.25)), - 'annually': ((3000, 0.00, 0.00), (18000, 3.10, 0.00), (33000, 5.25, 465.00), ('inf', 5.70, 1252.50)), + 'weekly': ( + ( 144, 0.00, 0.00), + ( 721, 3.10, 0.00), + (1298, 5.25, 17.88), + ('inf', 5.70, 48.17), + ), + 'bi-weekly': ( + ( 288, 0.00, 0.00), + ( 1442, 3.10, 0.00), + ( 2596, 5.25, 35.77), + ('inf', 5.70, 96.35), + ), + 'semi-monthly': ( + ( 313, 0.00, 0.00), + ( 1563, 3.10, 0.00), + ( 2813, 5.25, 38.75), + ('inf', 5.70, 104.38), + ), + 'monthly': ( + ( 625, 0.00, 0.00), + ( 3125, 3.10, 0.00), + ( 5625, 5.25, 77.50), + ('inf', 5.70, 208.75), + ), + 'quarterly': ( + ( 1875, 0.00, 0.00), + ( 9375, 3.10, 0.00), + (16875, 5.25, 232.50), + ('inf', 5.70, 626.25), + ), + 'semi-annual': ( + ( 3750, 0.00, 0.00), + (18750, 3.10, 0.00), + (33750, 5.25, 465.00), + ('inf', 5.70, 1252.50), + ), + 'annually': ( + ( 7500, 0.00, 0.00), + (37500, 3.10, 0.00), + (67500, 5.25, 930.00), + ('inf', 5.70, 2505.00), + ), }, } diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 8741d81d..2707a4b7 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -129,8 +129,7 @@ class HRContractUSPayrollConfig(models.Model): ks_k4_sit_filing_status = fields.Selection([ ('single', 'Single'), - ('married', 'Married'), - ('head of household', 'Head of Household'), + ('married', 'Joint'), ], string='Kansas K-4 Filing Status', help='KS K-4 3.') ks_k4_sit_allowances = fields.Integer(string='Kansas KS K-4 Number of Allowances', help='KS K-4 Step 4.') diff --git a/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py index 61416613..3ed586f8 100755 --- a/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ks_kansas_payslip_2020.py @@ -26,10 +26,11 @@ class TestUsKSPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('KS', self.KS_UNEMP, date(2020, 1, 1), wage_base=self.KS_UNEMP_MAX_WAGE) - self._test_sit(625, 'married', 2, 0, 'semi-monthly', date(2020, 1, 1), 4.00) - # self._test_sit(1500, 'single', 0, 0, 'bi-weekly', date(2020, 1, 1), 69.90) - # self._test_sit(1500, 'single', 0, 0, 'bi-weekly', date(2020, 1, 1), 79.90) + self._test_sit(6250, 'married', 2, 0, 'semi-monthly', date(2020, 1, 1), 290.00) + self._test_sit(5000, 'single', 1, 0, 'monthly', date(2020, 1, 1), 222.00) + self._test_sit(1500, 'married', 0, 0, 'bi-weekly', date(2020, 1, 1), 39.00) + self._test_sit(750, 'single', 2, 10, 'weekly', date(2020, 1, 1), 36.00) 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 022326ea..d9f83626 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -127,7 +127,7 @@

Form KS K-4 - State Income Tax

- + From a94479fcdbfd67716be550e518658e7405bd1950 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 15:35:23 -0400 Subject: [PATCH 36/63] [IMP] l10n_us_hr_payroll: Reformat Tax table, changed SUTA rate and improved test case for UT Utah 2020. --- l10n_us_hr_payroll/data/state/ut_utah.xml | 15 ++++++++++++--- .../tests/test_us_us_utah_payslip_2020.py | 9 ++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ut_utah.xml b/l10n_us_hr_payroll/data/state/ut_utah.xml index f3622248..cb57813c 100644 --- a/l10n_us_hr_payroll/data/state/ut_utah.xml +++ b/l10n_us_hr_payroll/data/state/ut_utah.xml @@ -22,7 +22,7 @@ - 1.5 + 0.1 @@ -40,7 +40,7 @@ - + US UT Utah Allowances Rate us_ut_sit_allowances_rate @@ -67,12 +67,21 @@ 'semi-annual': 360, 'annually': 720, }, + 'head_household': { + 'weekly' : 7, + 'bi-weekly' : 14, + 'semi-monthly': 15, + 'monthly' : 30, + 'quarterly' : 90, + 'semi-annual': 180, + 'annually': 360, + }, } - + US UT Utah SIT Tax Rate us_ut_sit_tax_rate diff --git a/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py index 0518fb79..a6881acb 100755 --- a/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_us_utah_payslip_2020.py @@ -9,8 +9,8 @@ class TestUsUTPayslip(TestUsPayslip): # 2020 Taxes and Rates ### UT_UNEMP_MAX_WAGE = 36600.0 - UT_UNEMP = 1.5 - # Calculation based on example https://src.bna.com/MSO + UT_UNEMP = 0.1 + # Calculation based on example https://tax.utah.gov/forms/pubs/pub-14.pdf def _test_sit(self, wage, filing_status, additional_withholding, schedule_pay, date_start, expected_withholding): employee = self._createEmployee() @@ -25,7 +25,7 @@ class TestUsUTPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('UT', self.UT_UNEMP, date(2020, 1, 1), wage_base=self.UT_UNEMP_MAX_WAGE) @@ -33,5 +33,4 @@ class TestUsUTPayslip(TestUsPayslip): self._test_sit(1000, 'single', 0, 'bi-weekly', date(2020, 1, 1), 45.00) self._test_sit(855, 'married', 0, 'semi-monthly', date(2020, 1, 1), 16.00) self._test_sit(2500, 'married', 0, 'monthly', date(2020, 1, 1), 81.00) - self._test_sit(8000, 'single', 0, 'quarterly', date(2020, 1, 1), 387.00) - self._test_sit(8000, 'single', 10, 'quarterly', date(2020, 1, 1), 397.00) + self._test_sit(8000, 'head_household', 10, 'quarterly', date(2020, 1, 1), 397.00) From 0d89486abb24f28ab4db5cefe97d6f3f09bb8348 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 15:57:28 -0400 Subject: [PATCH 37/63] [IMP] l10n_us_hr_payroll: Reformat Tax table and changed SUTA rate for RI Rhode Island 2020 --- .../data/state/ri_rhode_island.xml | 46 +++++++++++++++---- .../test_us_ri_rhode_island_payslip_2020.py | 2 +- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ri_rhode_island.xml b/l10n_us_hr_payroll/data/state/ri_rhode_island.xml index de004eca..155a2c86 100644 --- a/l10n_us_hr_payroll/data/state/ri_rhode_island.xml +++ b/l10n_us_hr_payroll/data/state/ri_rhode_island.xml @@ -22,12 +22,12 @@ - 1.3 + 1.06 - + US RI Rhode Island Exemption Rate us_ri_sit_exemption_rate @@ -57,13 +57,41 @@ { - 'weekly': ((1255, 0.00, 3.75), (2853, 47.06, 4.75), ('inf', 122.97, 5.99)), - 'bi-weekly': ((2510, 0.00, 3.75), (5706, 94.13, 4.75), ('inf', 245.94, 5.99)), - 'semi-monthly': ((2719, 0.00, 3.75), (6181, 101.96, 4.75), ('inf', 266.41, 5.99)), - 'monthly': ((5438, 0.00, 3.75), (12363, 203.93, 4.75), ('inf', 532.87, 5.99)), - 'quarterly': ((16313, 0.00, 3.75), (37088, 611.74, 4.75), ('inf', 1598.55, 5.99)), - 'semi-annually': ((32625, 0.00, 3.75), (74175, 1223.44, 4.75), ('inf', 3197.07, 5.99)), - 'annually': ((65250, 0.00, 3.75), (148350, 2446.88, 4.75), ('inf', 6394.13, 5.99)), + 'weekly': ( + ( 1255, 0.00, 3.75), + ( 2853, 47.06, 4.75), + ('inf', 122.97, 5.99), + ), + 'bi-weekly': ( + ( 2510, 0.00, 3.75), + ( 5706, 94.13, 4.75), + ('inf', 245.94, 5.99), + ), + 'semi-monthly': ( + ( 2719, 0.00, 3.75), + ( 6181, 101.96, 4.75), + ('inf', 266.41, 5.99), + ), + 'monthly': ( + ( 5438, 0.00, 3.75), + (12363, 203.93, 4.75), + ('inf', 532.87, 5.99), + ), + 'quarterly': ( + (16313, 0.00, 3.75), + (37088, 611.74, 4.75), + ('inf', 1598.55, 5.99), + ), + 'semi-annually': ( + (32625, 0.00, 3.75), + (74175, 1223.44, 4.75), + ('inf', 3197.07, 5.99), + ), + 'annually': ( + ( 65250, 0.00, 3.75), + (148350, 2446.88, 4.75), + ( 'inf', 6394.13, 5.99), + ), } diff --git a/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py index 6d4b35dd..9d92fec1 100755 --- a/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ri_rhode_island_payslip_2020.py @@ -9,7 +9,7 @@ class TestUsRIPayslip(TestUsPayslip): # 2020 Taxes and Rates ### RI_UNEMP_MAX_WAGE = 24000.0 - RI_UNEMP = 1.3 + RI_UNEMP = 1.06 # Calculation based on example http://www.tax.ri.gov/forms/2020/Withholding/2020%20Withhholding%20Tax%20Booklet.pdf def _test_sit(self, wage, allowances, additional_withholding, exempt, schedule_pay, date_start, expected_withholding): From c00409dffe2abd416fae003662b254ab7b18b6c9 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 16:52:50 -0400 Subject: [PATCH 38/63] [IMP] l10n_us_hr_payroll: Reformat Tax table and changed wage for VT Vermont 2020 --- l10n_us_hr_payroll/data/state/vt_vermont.xml | 102 +++++++++++++++--- .../models/us_payroll_config.py | 3 +- .../tests/test_us_vt_vermont_payslip_2020.py | 2 +- .../views/us_payroll_config_views.xml | 2 +- 4 files changed, 90 insertions(+), 19 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/vt_vermont.xml b/l10n_us_hr_payroll/data/state/vt_vermont.xml index 6223b420..74f1a491 100644 --- a/l10n_us_hr_payroll/data/state/vt_vermont.xml +++ b/l10n_us_hr_payroll/data/state/vt_vermont.xml @@ -1,6 +1,6 @@ - + US VT Vermont SUTA Wage Base us_vt_suta_wage_base @@ -8,7 +8,7 @@ - 16000.0 + 16100.0 @@ -47,7 +47,7 @@ - + US VT Vermont SIT Tax Rate us_vt_sit_tax_rate @@ -57,20 +57,92 @@ { 'single': { - 'weekly': ((60, 0.00, 0.00), (836, 0.00, 3.35), (1941, 26.00, 6.60), (3983, 98.93, 7.60), ('inf', 254.12, 8.75)), - 'bi-weekly': ((120, 0.00, 0.00), (1672, 0.00, 3.35), (3882, 51.99, 6.60), (7966, 197.85, 7.60), ('inf', 508.24, 8.75)), - 'semi-monthly': ((130, 0.00, 0.00), (1811, 0.00, 3.35), (4205, 56.31, 6.60), (8630, 214.32, 7.60), ('inf', 550.62, 8.75)), - 'monthly': ((260, 0.00, 0.00), (3623, 0.00, 3.35), (8410, 112.66, 6.60), (17260, 428.60, 7.60), ('inf', 1101.20, 8.75)), - 'quarterly': ((781, 0.00, 0.00), (10869, 0.00, 3.35), (25231, 337.95, 6.60), (51781, 1285.84, 7.60), ('inf', 3303.64, 8.75)), - 'annually': ((3125, 0.00, 0.00), (43475, 0.00, 3.35), (100925, 1351.73, 6.60), (207125, 5143.43, 7.60), ('inf', 13214.63, 8.75)), + 'weekly': ( + ( 60, 0.00, 0.00), + ( 836, 0.00, 3.35), + ( 1941, 26.00, 6.60), + ( 3983, 98.93, 7.60), + ('inf', 254.12, 8.75), + ), + 'bi-weekly': ( + ( 120, 0.00, 0.00), + ( 1672, 0.00, 3.35), + ( 3882, 51.99, 6.60), + ( 7966, 197.85, 7.60), + ('inf', 508.24, 8.75), + ), + 'semi-monthly': ( + ( 130, 0.00, 0.00), + ( 1811, 0.00, 3.35), + ( 4205, 56.31, 6.60), + ( 8630, 214.32, 7.60), + ('inf', 550.62, 8.75), + ), + 'monthly': ( + ( 260, 0.00, 0.00), + ( 3623, 0.00, 3.35), + ( 8410, 112.66, 6.60), + (17260, 428.60, 7.60), + ('inf', 1101.20, 8.75), + ), + 'quarterly': ( + ( 781, 0.00, 0.00), + (10869, 0.00, 3.35), + (25231, 337.95, 6.60), + (51781, 1285.84, 7.60), + ('inf', 3303.64, 8.75), + ), + 'annually': ( + ( 3125, 0.00, 0.00), + ( 43475, 0.00, 3.35), + (100925, 1351.73, 6.60), + (207125, 5143.43, 7.60), + ( 'inf', 13214.63, 8.75), + ), }, 'married': { - 'weekly': ((180, 0.00, 0.00), (1477, 0.00, 3.35), (3315, 43.45, 6.60), (4956, 164.76, 7.60), ('inf', 289.47, 8.75)), - 'bi-weekly': ((361, 0.00, 0.00), (2955, 0.00, 3.35), (6630, 86.90, 6.60), (9913, 329.45, 7.60), ('inf', 578.96, 8.75)), - 'semi-monthly': ((391, 0.00, 0.00), (3201, 0.00, 3.35), (7182, 94.14, 6.60), (10739, 356.88, 7.60), ('inf', 627.21, 8.75)), - 'monthly': ((781, 0.00, 0.00), (6402, 0.00, 3.35), (14365, 188.30, 6.60), (21477, 713.86, 7.60), ('inf', 1254.37, 8.75)), - 'quarterly': ((2344, 0.00, 0.00), (19206, 0.00, 3.35), (43094, 564.88, 6.60), (64431, 2141.49, 7.60), ('inf', 3763.10, 8.75)), - 'annually': ((9375, 0.00, 0.00), (76825, 0.00, 3.35), (172375, 2259.58, 6.60), (257725, 8565.88, 7.60), ('inf', 15052.48, 8.75)), + 'weekly': ( + ( 180, 0.00, 0.00), + ( 1477, 0.00, 3.35), + ( 3315, 43.45, 6.60), + ( 4956, 164.76, 7.60), + ('inf', 289.47, 8.75), + ), + 'bi-weekly': ( + ( 361, 0.00, 0.00), + ( 2955, 0.00, 3.35), + ( 6630, 86.90, 6.60), + (9913, 329.45, 7.60), + ('inf', 578.96, 8.75), + ), + 'semi-monthly': ( + ( 391, 0.00, 0.00), + ( 3201, 0.00, 3.35), + ( 7182, 94.14, 6.60), + (10739, 356.88, 7.60), + ('inf', 627.21, 8.75), + ), + 'monthly': ( + ( 781, 0.00, 0.00), + ( 6402, 0.00, 3.35), + (14365, 188.30, 6.60), + (21477, 713.86, 7.60), + ('inf', 1254.37, 8.75), + ), + 'quarterly': ( + ( 2344, 0.00, 0.00), + (19206, 0.00, 3.35), + (43094, 564.88, 6.60), + (64431, 2141.49, 7.60), + ('inf', 3763.10, 8.75), + ), + 'annually': ( + ( 9375, 0.00, 0.00), + ( 76825, 0.00, 3.35), + (172375, 2259.58, 6.60), + (257725, 8565.88, 7.60), + ( 'inf', 15052.48, 8.75), + ), }, } diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 2707a4b7..7b8fd2ed 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -257,9 +257,8 @@ class HRContractUSPayrollConfig(models.Model): vt_w4vt_sit_filing_status = fields.Selection([ ('single', 'Single'), ('married', 'Married'), - ('head_household', 'Head of Household') ], string='Vermont VT W-4VT Filing Status', help='VT W-4VT') - vt_w4vt_sit_allowances = fields.Integer(string='Vermont VT W-4VT Allowances', help='VT W-4VT 1.') + vt_w4vt_sit_allowances = fields.Integer(string='Vermont VT W-4VT Allowances', help='VT W-4VT 5.') va_va4_sit_exemptions = fields.Integer(string='Virginia VA-4(P) Personal Exemptions', help='VA-4(P) 1(a)') diff --git a/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py index c26d8f52..7807bed7 100755 --- a/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_vt_vermont_payslip_2020.py @@ -8,7 +8,7 @@ class TestUsVTPayslip(TestUsPayslip): ### # 2020 Taxes and Rates ### - VT_UNEMP_MAX_WAGE = 16000.0 + VT_UNEMP_MAX_WAGE = 16100.0 VT_UNEMP = 1.0 # Calculation based on example https://tax.vermont.gov/sites/tax/files/documents/WithholdingInstructions.pdf 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 d9f83626..4b38115f 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -268,7 +268,7 @@

Form VT W-4VT - State Income Tax

- +
From 5d4325d1a0145aefa7a5333d02a0a81b3bdccbd7 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 18:18:03 -0400 Subject: [PATCH 39/63] [IMP] l10n_us_hr_payroll: Comment add for table for VA Virginia 2020 --- l10n_us_hr_payroll/data/state/va_virginia.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l10n_us_hr_payroll/data/state/va_virginia.xml b/l10n_us_hr_payroll/data/state/va_virginia.xml index a07daae7..5d19384a 100644 --- a/l10n_us_hr_payroll/data/state/va_virginia.xml +++ b/l10n_us_hr_payroll/data/state/va_virginia.xml @@ -37,7 +37,7 @@
- + US VA Virginia SIT Rate Table us_va_sit_rate From 8937bde8e88dc59fb5a15d18c851112956b6750c Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 18:52:39 -0400 Subject: [PATCH 40/63] [IMP] l10n_us_hr_payroll: Added Comment, removed one filing status which was not used in calculation and improve test case for exempt for NC North Carolina 2020 --- l10n_us_hr_payroll/data/state/nc_northcarolina.xml | 8 ++++++-- l10n_us_hr_payroll/models/us_payroll_config.py | 1 - .../tests/test_us_nc_northcarolina_payslip_2020.py | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/nc_northcarolina.xml b/l10n_us_hr_payroll/data/state/nc_northcarolina.xml index 597fd543..d09f8e3f 100644 --- a/l10n_us_hr_payroll/data/state/nc_northcarolina.xml +++ b/l10n_us_hr_payroll/data/state/nc_northcarolina.xml @@ -44,6 +44,8 @@ + + { 'weekly': {'allowance': 48.08, 'standard_deduction': 192.31, 'standard_deduction_hh': 288.46}, @@ -54,10 +56,12 @@ + + { - 'weekly': {'allowance': 48.08, 'standard_deduction': 206.73, 'standard_deduction_hh': 310.10}, - 'bi-weekly': {'allowance': 96.15, 'standard_deduction': 413.46, 'standard_deduction_hh': 620.19}, + 'weekly': {'allowance': 48.08, 'standard_deduction': 206.73, 'standard_deduction_hh': 310.10}, + 'bi-weekly': {'allowance': 96.15, 'standard_deduction': 413.46, 'standard_deduction_hh': 620.19}, 'semi-monthly': {'allowance': 104.17, 'standard_deduction': 447.92, 'standard_deduction_hh': 671.88}, 'monthly': {'allowance': 208.33, 'standard_deduction': 895.83, 'standard_deduction_hh': 1343.75}, } diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 7b8fd2ed..82ebe623 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -190,7 +190,6 @@ class HRContractUSPayrollConfig(models.Model): ('', 'Exempt'), ('single', 'Single'), ('married', 'Married'), - ('surviving_spouse', 'Surviving Spouse'), ('head_household', 'Head of Household') ], string='North Carolina NC-4 Filing Status', help='NC-4') nc_nc4_sit_allowances = fields.Integer(string='North Carolina NC-4 Allowances', help='NC-4 1.') diff --git a/l10n_us_hr_payroll/tests/test_us_nc_northcarolina_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nc_northcarolina_payslip_2020.py index 2c484ac4..8e2d69c1 100755 --- a/l10n_us_hr_payroll/tests/test_us_nc_northcarolina_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_nc_northcarolina_payslip_2020.py @@ -11,7 +11,7 @@ class TestUsNCPayslip(TestUsPayslip): NC_UNEMP_MAX_WAGE = 25200.0 NC_UNEMP = 1.0 NC_INC_TAX = 0.0535 - + # Example based on https://files.nc.gov/ncdor/documents/files/NC-30_book_Web_1-16-19_v4_Final.pdf def _test_sit(self, wage, filing_status, allowances, additional_withholding, schedule_pay, date_start, expected_withholding): employee = self._createEmployee() @@ -34,3 +34,4 @@ class TestUsNCPayslip(TestUsPayslip): self._test_sit(20000.0, 'single', 1, 100.0, 'weekly', date(2020, 1, 1), 1156.0) self._test_sit(5000.0, 'married', 1, 0.0, 'weekly', date(2020, 1, 1), 254.0) self._test_sit(4000.0, 'head_household', 1, 5.0, 'semi-monthly', date(2020, 1, 1), 177.0) + self._test_sit(7000.0, '', 1, 5.0, 'monthly', date(2020, 1, 1), 0.0) From 8470d9edc481f7d50931cddc35736425f46eecb5 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 19:32:25 -0400 Subject: [PATCH 41/63] [IMP] l10n_us_hr_payroll: Improved comments and test case for NM New Mexico 2020 --- .../data/state/nm_new_mexico.xml | 232 ++++++++++++++++-- .../test_us_nm_new_mexico_payslip_2020.py | 1 + 2 files changed, 212 insertions(+), 21 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/nm_new_mexico.xml b/l10n_us_hr_payroll/data/state/nm_new_mexico.xml index a823c608..2c4249a0 100644 --- a/l10n_us_hr_payroll/data/state/nm_new_mexico.xml +++ b/l10n_us_hr_payroll/data/state/nm_new_mexico.xml @@ -34,34 +34,224 @@ + { 'single': { - 'weekly': ((119, 0.00, 0.0), (225, 0.00, 1.7), (331, 1.80, 3.2), (427, 5.18, 4.7), (619, 9.70, 4.9), (927, 19.13, 4.9), (1369, 34.20, 4.9), ('inf', 55.88, 4.9)), - 'bi-weekly': ((238, 0.00, 0.0), (450, 0.00, 1.7), (662, 3.60, 3.2), (854, 10.37, 4.7), (1238, 19.40, 4.9), (1854, 38.25, 4.9), (2738, 68.40, 4.9), ('inf', 111.75, 4.9)), - 'semi-monthly': ((258, 0.00, 0.0), (488, 0.00, 1.7), (717, 3.90, 3.2), (925, 11.23, 4.7), (1342, 21.02, 4.9), (2008, 41.44, 4.9), (2967, 74.10, 4.9), ('inf', 121.06, 4.9)), - 'monthly': ((517, 0.00, 0.0), (975, 0.00, 1.7), (1433, 7.79, 3.2), (1850, 22.46, 4.7), (2683, 42.04, 4.9), (4017, 82.88, 4.9), (5933, 148.21, 4.9), ('inf', 242.13, 4.9)), - 'quarterly': ((1550, 0.00, 0.0), (2925, 0.00, 1.7), (4300, 23.38, 3.2), (5550, 67.38, 4.7), (8050, 126.13, 4.9), (12050, 248.63, 4.9), (17800, 444.63, 4.9), ('inf', 726.38, 4.9)), - 'semi-annual': ((3100, 0.00, 0.0), (5850, 0.00, 1.7), (8600, 46.75, 3.2), (11100, 134.75, 4.7), (16100, 252.25, 4.9), (24100, 497.25, 4.9), (35600, 889.25, 4.9), ('inf', 1452.75, 4.9)), - 'annually': ((6200, 0.00, 0.0), (11700, 0.00, 1.7), (17200, 93.50, 3.2), (22200, 269.50, 4.7), (32200, 504.50, 4.9), (48200, 994.50, 4.9), (71200, 1778.50, 4.9), ('inf', 2905.50, 4.9)), + 'weekly': ( + ( 119, 0.00, 0.0), + ( 225, 0.00, 1.7), + ( 331, 1.80, 3.2), + ( 427, 5.18, 4.7), + ( 619, 9.70, 4.9), + ( 927, 19.13, 4.9), + ( 1369, 34.20, 4.9), + ('inf', 55.88, 4.9), + ), + 'bi-weekly': ( + ( 238, 0.00, 0.0), + ( 450, 0.00, 1.7), + ( 662, 3.60, 3.2), + ( 854, 10.37, 4.7), + ( 1238, 19.40, 4.9), + ( 1854, 38.25, 4.9), + ( 2738, 68.40, 4.9), + ('inf', 111.75, 4.9), + ), + 'semi-monthly': ( + ( 258, 0.00, 0.0), + ( 488, 0.00, 1.7), + ( 717, 3.90, 3.2), + ( 925, 11.23, 4.7), + ( 1342, 21.02, 4.9), + ( 2008, 41.44, 4.9), + ( 2967, 74.10, 4.9), + ('inf', 121.06, 4.9), + ), + 'monthly': ( + ( 517, 0.00, 0.0), + ( 975, 0.00, 1.7), + ( 1433, 7.79, 3.2), + ( 1850, 22.46, 4.7), + ( 2683, 42.04, 4.9), + ( 4017, 82.88, 4.9), + ( 5933, 148.21, 4.9), + ('inf', 242.13, 4.9), + ), + 'quarterly': ( + ( 1550, 0.00, 0.0), + ( 2925, 0.00, 1.7), + ( 4300, 23.38, 3.2), + ( 5550, 67.38, 4.7), + ( 8050, 126.13, 4.9), + ( 12050, 248.63, 4.9), + ( 17800, 444.63, 4.9), + ( 'inf', 726.38, 4.9), + ), + 'semi-annual': ( + ( 3100, 0.00, 0.0), + ( 5850, 0.00, 1.7), + ( 8600, 46.75, 3.2), + (11100, 134.75, 4.7), + (16100, 252.25, 4.9), + (24100, 497.25, 4.9), + (35600, 889.25, 4.9), + ('inf', 1452.75, 4.9), + ), + 'annually': ( + ( 6200, 0.00, 0.0), + (11700, 0.00, 1.7), + (17200, 93.50, 3.2), + (22200, 269.50, 4.7), + (32200, 504.50, 4.9), + (48200, 994.50, 4.9), + (71200, 1778.50, 4.9), + ('inf', 2905.50, 4.9), + ), }, 'married': { - 'weekly': ((238, 0.00, 0.0), (392, 0.00, 1.7), (546, 2.62, 3.2), (700, 7.54, 4.7), (1008, 14.77, 4.9), (1469, 29.85, 4.9), (2162, 52.46, 4.9), ('inf', 86.38, 4.9)), - 'bi-weekly': ((477, 0.00, 0.0), (785, 0.00, 1.7), (1092, 5.23, 3.2), (1400, 15.08, 4.7), (2015, 29.54, 4.9), (2938, 59.69, 4.9), (4323, 104.92, 4.9), ('inf', 172.77, 4.9)), - 'semi-monthly': ((517, 0.00, 0.0), (850, 0.00, 1.7), (1183, 5.67, 3.2), (1517, 16.33, 4.7), (2183, 32.00, 4.9), (3183, 64.67, 4.9), (4683, 113.67, 4.9), ('inf', 187.17, 4.9)), - 'monthly': ((1033, 0.00, 0.0), (1700, 0.00, 1.7), (2367, 11.33, 3.2), (3033, 32.67, 4.7), (4367, 64.00, 4.9), (6367, 129.33, 4.9), (9367, 227.33, 4.9), ('inf', 374.33, 4.9)), - 'quarterly': ((3100, 0.00, 0.0), (5100, 0.00, 1.7), (7100, 34.00, 3.2), (9100, 98.00, 4.7), (13100, 192.00, 4.9), (19100, 388.00, 4.9), (28100, 682.00, 4.9), ('inf', 1123.00, 4.9)), - 'semi-annual': ((6200, 0.00, 0.0), (10200, 0.00, 1.7), (14200, 68.00, 3.2), (18200, 196.00, 4.7), (26200, 384.00, 4.9), (38200, 776.00, 4.9), (56200, 1364.00, 4.9), ('inf', 2246.00, 4.9)), - 'annually': ((12400, 0.00, 0.0), (20400, 0.00, 1.7), (28400, 136.00, 3.2), (36400, 392.00, 4.7), (52400, 768.00, 4.9), (76400, 1552.00, 4.9), (112400, 2728.00, 4.9), ('inf', 4492.00, 4.9)), + 'weekly': ( + ( 238, 0.00, 0.0), + ( 392, 0.00, 1.7), + ( 546, 2.62, 3.2), + ( 700, 7.54, 4.7), + ( 1008, 14.77, 4.9), + ( 1469, 29.85, 4.9), + ( 2162, 52.46, 4.9), + ('inf', 86.38, 4.9), + ), + 'bi-weekly': ( + ( 477, 0.00, 0.0), + ( 785, 0.00, 1.7), + ( 1092, 5.23, 3.2), + ( 1400, 15.08, 4.7), + (2015, 29.54, 4.9), + ( 2938, 59.69, 4.9), + ( 4323, 104.92, 4.9), + ('inf', 172.77, 4.9), + ), + 'semi-monthly': ( + ( 517, 0.00, 0.0), + ( 850, 0.00, 1.7), + ( 1183, 5.67, 3.2), + ( 1517, 16.33, 4.7), + ( 2183, 32.00, 4.9), + ( 3183, 64.67, 4.9), + ( 4683, 113.67, 4.9), + ('inf', 187.17, 4.9), + ), + 'monthly': ( + ( 1033, 0.00, 0.0), + ( 1700, 0.00, 1.7), + ( 2367, 11.33, 3.2), + ( 3033, 32.67, 4.7), + ( 4367, 64.00, 4.9), + ( 6367, 129.33, 4.9), + ( 9367, 227.33, 4.9), + ('inf', 374.33, 4.9), + ), + 'quarterly': ( + ( 3100, 0.00, 0.0), + ( 5100, 0.00, 1.7), + ( 7100, 34.00, 3.2), + ( 9100, 98.00, 4.7), + (13100, 192.00, 4.9), + (19100, 388.00, 4.9), + (28100, 682.00, 4.9), + ('inf', 1123.00, 4.9), + ), + 'semi-annual': ( + ( 6200, 0.00, 0.0), + (10200, 0.00, 1.7), + (14200, 68.00, 3.2), + (18200, 196.00, 4.7), + (26200, 384.00, 4.9), + (38200, 776.00, 4.9), + (56200, 1364.00, 4.9), + ('inf', 2246.00, 4.9), + ), + 'annually': ( + ( 12400, 0.00, 0.0), + ( 20400, 0.00, 1.7), + ( 28400, 136.00, 3.2), + ( 36400, 392.00, 4.7), + ( 52400, 768.00, 4.9), + ( 76400, 1552.00, 4.9), + (112400, 2728.00, 4.9), + ( 'inf', 4492.00, 4.9), + ), }, 'married_as_single': { - 'weekly': ((179, 0.00, 0.0), (333, 0.00, 1.7), (487, 2.62, 3.2), (641, 7.54, 4.7), (949, 14.77, 4.9), (1410, 29.85, 4.9), (2102, 52.46, 4.9), ('inf', 86.38, 4.9)), - 'bi-weekly': ((359, 0.00, 0.0), (666, 0.00, 1.7), (974, 5.23, 3.2), (1282, 15.08, 4.7), (1897, 29.54, 4.9), (2820, 59.69, 4.9), (4205, 104.92, 4.9), ('inf', 172.77, 4.9)), - 'semi-monthly': ((389, 0.00, 0.0), (722, 0.00, 1.7), (1055, 5.67, 3.2), (1389, 16.33, 4.7), (2055, 32.00, 4.9), (3055, 64.67, 4.9), (4555, 113.67, 4.9), ('inf', 187.17, 4.9)), - 'monthly': ((777, 0.00, 0.0), (1444, 0.00, 1.7), (2110, 11.33, 3.2), (2777, 32.67, 4.7), (4110, 64.00, 4.9), (6110, 129.33, 4.9), (9110, 227.33, 4.9), ('inf', 374.33, 4.9)), - 'quarterly': ((2331, 0.00, 0.0), (4331, 0.00, 1.7), (6331, 34.00, 3.2), (8331, 98.00, 4.7), (12331, 192.00, 4.9), (18331, 388.00, 4.9), (27331, 682.00, 4.9), ('inf', 1123.00, 4.9)), - 'semi-annual': ((4663, 0.00, 0.0), (8663, 0.00, 1.7), (12663, 68.00, 3.2), (16663, 196.00, 4.7), (24663, 384.00, 4.9), (36663, 776.00, 4.9), (54663, 1364.00, 4.9), ('inf', 2246.00, 4.9)), - 'annually': ((9325, 0.00, 0.0), (17325, 0.00, 1.7), (25325, 136.00, 3.2), (33325, 392.00, 4.7), (49325, 768.00, 4.9), (73325, 1552.00, 4.9), (109325, 2728.00, 4.9), ('inf', 4492.00, 4.9)), + 'weekly': ( + ( 179, 0.00, 0.0), + ( 333, 0.00, 1.7), + ( 487, 2.62, 3.2), + ( 641, 7.54, 4.7), + ( 949, 14.77, 4.9), + ( 1410, 29.85, 4.9), + ( 2102, 52.46, 4.9), + ('inf', 86.38, 4.9), + ), + 'bi-weekly': ( + ( 359, 0.00, 0.0), + ( 666, 0.00, 1.7), + ( 974, 5.23, 3.2), + ( 1282, 15.08, 4.7), + ( 1897, 29.54, 4.9), + ( 2820, 59.69, 4.9), + ( 4205, 104.92, 4.9), + ('inf', 172.77, 4.9), + ), + 'semi-monthly': ( + ( 389, 0.00, 0.0), + ( 722, 0.00, 1.7), + ( 1055, 5.67, 3.2), + ( 1389, 16.33, 4.7), + ( 2055, 32.00, 4.9), + ( 3055, 64.67, 4.9), + ( 4555, 113.67, 4.9), + ('inf', 187.17, 4.9), + ), + 'monthly': ( + ( 777, 0.00, 0.0), + ( 1444, 0.00, 1.7), + ( 2110, 11.33, 3.2), + ( 2777, 32.67, 4.7), + ( 4110, 64.00, 4.9), + ( 6110, 129.33, 4.9), + ( 9110, 227.33, 4.9), + ('inf', 374.33, 4.9), + ), + 'quarterly': ( + ( 2331, 0.00, 0.0), + ( 4331, 0.00, 1.7), + ( 6331, 34.00, 3.2), + ( 8331, 98.00, 4.7), + ( 12331, 192.00, 4.9), + ( 18331, 388.00, 4.9), + ( 27331, 682.00, 4.9), + ( 'inf', 1123.00, 4.9), + ), + 'semi-annual': ( + ( 4663, 0.00, 0.0), + ( 8663, 0.00, 1.7), + ( 12663, 68.00, 3.2), + ( 16663, 196.00, 4.7), + ( 24663, 384.00, 4.9), + ( 36663, 776.00, 4.9), + ( 54663, 1364.00, 4.9), + ( 'inf', 2246.00, 4.9), + ), + 'annually': ( + ( 9325, 0.00, 0.0), + ( 17325, 0.00, 1.7), + ( 25325, 136.00, 3.2), + ( 33325, 392.00, 4.7), + ( 49325, 768.00, 4.9), + ( 73325, 1552.00, 4.9), + (109325, 2728.00, 4.9), + ( 'inf', 4492.00, 4.9), + ), } } diff --git a/l10n_us_hr_payroll/tests/test_us_nm_new_mexico_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nm_new_mexico_payslip_2020.py index 0ab6c321..24f8c5a4 100755 --- a/l10n_us_hr_payroll/tests/test_us_nm_new_mexico_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_nm_new_mexico_payslip_2020.py @@ -33,3 +33,4 @@ class TestUsNMPayslip(TestUsPayslip): self._test_sit(1000.0, 'married', 10.0, 'weekly', date(2020, 1, 1), 39.47) self._test_sit(25000.0, 'single', 0.0, 'bi-weekly', date(2020, 1, 1), 1202.60) self._test_sit(25000.0, 'married_as_single', 0.0, 'monthly', date(2020, 1, 1), 1152.95) + self._test_sit(4400.0, '', 0.0, 'monthly', date(2020, 1, 1), 0.00) From 87e5042522e3dfc816f2e2907ff3caa099edcf4d Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 19 Aug 2020 21:10:21 -0400 Subject: [PATCH 42/63] [IMP] l10n_us_hr_payroll: Improved comments, Tax table, filing status and test case for AL Alabama 2020 --- l10n_us_hr_payroll/data/state/al_alabama.xml | 56 ++++++++++++++----- l10n_us_hr_payroll/models/state/al_alabama.py | 5 +- .../models/us_payroll_config.py | 2 +- .../tests/test_us_al_alabama_payslip_2020.py | 2 +- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/al_alabama.xml b/l10n_us_hr_payroll/data/state/al_alabama.xml index b1a8cfe1..fc3b3af1 100644 --- a/l10n_us_hr_payroll/data/state/al_alabama.xml +++ b/l10n_us_hr_payroll/data/state/al_alabama.xml @@ -46,16 +46,32 @@ { - '0': [(500, 2),( 3000, 4),('inf', 5)], - 'M': [( 1000, 2),( 6000, 4),('inf', 5)], + '0': [ + ( 500, 2), + ( 3000, 4), + ('inf', 5), + ], + 'M': [ + ( 1000, 2), + ( 6000, 4), + ('inf', 5), + ], } { - '0' : [(500, 2),(2500, 4),('inf', 5)], - 'M': [(1000, 2),(5000, 4),('inf', 5)], + '0' : [ + ( 500, 2), + ( 2500, 4), + ('inf', 5), + ], + 'M': [ + ( 1000, 2), + ( 5000, 4), + ('inf', 5), + ], } @@ -68,6 +84,8 @@ + + [ ( 1000, 20000), @@ -77,6 +95,8 @@ + + [ ( 1000, 20000), @@ -94,24 +114,28 @@ + + { - '0': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), - 'S': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), - 'MS': ((10749.0, 3750.0), (15500.0, 3750.0, 88.0, 250.0), ('inf', 2000.0)), - 'M': ((23499.0, 7500.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), - 'H': ((23499.0, 4700.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), + '0': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), + 'S': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), + 'MS': ((10749.0, 3750.0), (15500.0, 3750.0, 88.0, 250.0), ('inf', 2000.0)), + 'M': ((23499.0, 7500.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), + 'H': ((23499.0, 4700.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), } + + { - '0': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), - 'S': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), - 'MS': ((10749.0, 3750.0), (15500.0, 3750.0, 88.0, 250.0), ('inf', 2000.0)), - 'M': ((23499.0, 7500.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), - 'H': ((23499.0, 4700.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), + '0': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), + 'S': ((23499.0, 2500.0), (33000.0, 2500.0, 25.0, 500.0), ('inf', 2000.0)), + 'MS': ((10749.0, 3750.0), (15500.0, 3750.0, 88.0, 250.0), ('inf', 2000.0)), + 'M': ((23499.0, 7500.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), + 'H': ((23499.0, 4700.0), (33000.0, 7500.0, 175.0, 500.0), ('inf', 4000.0)), } @@ -124,6 +148,8 @@ + + { '0' : 0, @@ -135,6 +161,8 @@ + + { '0' : 0, diff --git a/l10n_us_hr_payroll/models/state/al_alabama.py b/l10n_us_hr_payroll/models/state/al_alabama.py index 15740c91..11638b7f 100644 --- a/l10n_us_hr_payroll/models/state/al_alabama.py +++ b/l10n_us_hr_payroll/models/state/al_alabama.py @@ -18,6 +18,10 @@ def al_alabama_state_income_withholding(payslip, categories, worked_days, inputs if not wage: return 0.0, 0.0 + exemptions = payslip.contract_id.us_payroll_config_value('al_a4_sit_exemptions') + if not exemptions: + return 0.0, 0.0 + personal_exempt = payslip.contract_id.us_payroll_config_value('state_income_tax_exempt') if personal_exempt: return 0.0, 0.0 @@ -25,7 +29,6 @@ def al_alabama_state_income_withholding(payslip, categories, worked_days, inputs pay_periods = payslip.dict.get_pay_periods_in_year() additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding') tax_table = payslip.rule_parameter('us_al_sit_tax_rate') - exemptions = payslip.contract_id.us_payroll_config_value('al_a4_sit_exemptions') dependent_rate = payslip.rule_parameter('us_al_sit_dependent_rate') standard_deduction = payslip.rule_parameter('us_al_sit_standard_deduction_rate').get(exemptions, 0.0) personal_exemption = payslip.rule_parameter('us_al_sit_personal_exemption_rate').get(exemptions, 0.0) diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 82ebe623..74bf4915 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -52,7 +52,7 @@ class HRContractUSPayrollConfig(models.Model): help='Form W4 (2020+) 4(c)') al_a4_sit_exemptions = fields.Selection([ - ('0', '0'), + ('', '0'), ('S', 'S'), ('MS', 'MS'), ('M', 'M'), diff --git a/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2020.py index 055c95cb..23865fc7 100644 --- a/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2020.py @@ -33,4 +33,4 @@ class TestUsALPayslip(TestUsPayslip): self._test_sit(850.0, 'M', False, 0.0, 2.0, 'weekly', date(2020, 1, 1), 29.98) self._test_sit(5000.0, 'H', False, 0.0, 2.0, 'bi-weekly', date(2020, 1, 1), 191.15) self._test_sit(20000.0, 'MS', False, 2.0, 0, 'monthly', date(2020, 1, 1), 757.6) - self._test_sit(5500.0, '0', True, 2.0, 150, 'weekly', date(2020, 1, 1), 0) + self._test_sit(5500.0, '', True, 2.0, 150, 'weekly', date(2020, 1, 1), 0.00) From a308b1662fcb0fbd21513ad14511bf000e7eae2b Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 09:59:52 -0400 Subject: [PATCH 43/63] [IMP] l10n_us_hr_payroll: Improved test case for AZ Arizona 2020 --- l10n_us_hr_payroll/tests/test_us_az_arizona_payslip_2020.py | 1 + 1 file changed, 1 insertion(+) diff --git a/l10n_us_hr_payroll/tests/test_us_az_arizona_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_az_arizona_payslip_2020.py index d1d14d80..248648bc 100644 --- a/l10n_us_hr_payroll/tests/test_us_az_arizona_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_az_arizona_payslip_2020.py @@ -31,3 +31,4 @@ class TestUsAZPayslip(TestUsPayslip): self._test_sit(1000.0, 10.0, 2.70, 'monthly', date(2020, 1, 1), 37.0) self._test_sit(15000.0, 0.0, 3.60, 'weekly', date(2020, 1, 1), 540.0) self._test_sit(8000.0, 0.0, 4.20, 'semi-monthly', date(2020, 1, 1), 336.0) + self._test_sit(8000.0, 0.0, 0.00, 'semi-monthly', date(2020, 1, 1), 0.0) From 538a5dd46a3ee2d1cc480b7adef4a6354a968459 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 12:45:38 -0400 Subject: [PATCH 44/63] [IMP] l10n_us_hr_payroll: Improved comments and test case for AR Arkansas 2020 --- l10n_us_hr_payroll/data/state/ar_arkansas.xml | 2 ++ l10n_us_hr_payroll/models/state/ar_arkansas.py | 2 +- .../tests/test_us_ar_arkansas_payslip_2020.py | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ar_arkansas.xml b/l10n_us_hr_payroll/data/state/ar_arkansas.xml index a59e57aa..3e5b8211 100644 --- a/l10n_us_hr_payroll/data/state/ar_arkansas.xml +++ b/l10n_us_hr_payroll/data/state/ar_arkansas.xml @@ -62,6 +62,8 @@ + + [ ( 4599, 0.0, 0.00), diff --git a/l10n_us_hr_payroll/models/state/ar_arkansas.py b/l10n_us_hr_payroll/models/state/ar_arkansas.py index e22c41b3..c1306c94 100644 --- a/l10n_us_hr_payroll/models/state/ar_arkansas.py +++ b/l10n_us_hr_payroll/models/state/ar_arkansas.py @@ -18,7 +18,7 @@ def ar_arkansas_state_income_withholding(payslip, categories, worked_days, input # Determine Wage wage = sit_wage(payslip, categories) - if wage == 0.0: + if not wage: return 0.0, 0.0 pay_periods = payslip.dict.get_pay_periods_in_year() diff --git a/l10n_us_hr_payroll/tests/test_us_ar_arkansas_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ar_arkansas_payslip_2020.py index bf630b6c..6afe3d4d 100644 --- a/l10n_us_hr_payroll/tests/test_us_ar_arkansas_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ar_arkansas_payslip_2020.py @@ -30,6 +30,6 @@ class TestUsARPayslip(TestUsPayslip): self._test_er_suta('AR', self.AR_UNEMP, date(2020, 1, 1), wage_base=self.AR_UNEMP_MAX_WAGE) self._test_sit(5000.0, True, 0.0, 0, 'monthly', date(2020, 1, 1), 0.0) self._test_sit(5000.0, False, 0.0, 0, 'monthly', date(2020, 1, 1), 221.0) - self._test_sit(5000.0, False, 0.0, 150, 'monthly', date(2020, 1, 1), 371.0) - self._test_sit(5000.0, False, 2.0, 0, 'monthly', date(2020, 1, 1), 217) - self._test_sit(5000.0, False, 2.0, 150, 'monthly', date(2020, 1, 1), 367) + self._test_sit(700.0, False, 0.0, 150, 'weekly', date(2020, 1, 1), 175.0) + self._test_sit(7000.0, False, 2.0, 0, 'semi-monthly', date(2020, 1, 1), 420.0) + self._test_sit(3000.0, False, 1.0, 0, 'bi-weekly', date(2020, 1, 1), 142.0) From 68406d428527a5c3cc7e5ff3d9a713bd7a55655b Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 13:34:37 -0400 Subject: [PATCH 45/63] [IMP] l10n_us_hr_payroll: Improved test case for CO Colorado 2020 --- l10n_us_hr_payroll/tests/test_us_co_colorado_payslip_2020.py | 1 + 1 file changed, 1 insertion(+) diff --git a/l10n_us_hr_payroll/tests/test_us_co_colorado_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_co_colorado_payslip_2020.py index 6e24cbb0..0fa45d9c 100755 --- a/l10n_us_hr_payroll/tests/test_us_co_colorado_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_co_colorado_payslip_2020.py @@ -34,3 +34,4 @@ class TestUsCOPayslip(TestUsPayslip): self._test_sit(20000.0, 'married', 0.0, 'quarterly', date(2020, 1, 1), 833.4) self._test_sit(20000.0, 'married', 10.0, 'quarterly', date(2020, 1, 1), 843.4) self._test_sit(20000.0, 'married', 0.0, 'quarterly', date(2020, 1, 1), 0.0, True) + self._test_sit(800.0, '', 0.0, 'weekly', date(2020, 1, 1), 0.00) From 5ccd8a5e9b5a13e5508c29f97731924c018454d5 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 14:14:44 -0400 Subject: [PATCH 46/63] [IMP] l10n_us_hr_payroll: Improved comments and test case for CT Connecticut 2020 --- l10n_us_hr_payroll/data/state/ct_connecticut.xml | 16 +++++++++++++--- .../tests/test_us_ct_connecticut_payslip_2020.py | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ct_connecticut.xml b/l10n_us_hr_payroll/data/state/ct_connecticut.xml index 646b9373..c4bf1dd1 100644 --- a/l10n_us_hr_payroll/data/state/ct_connecticut.xml +++ b/l10n_us_hr_payroll/data/state/ct_connecticut.xml @@ -95,6 +95,8 @@ + + { 'a': [ @@ -226,6 +228,8 @@ + + { 'a': [ @@ -432,6 +436,8 @@ + + { 'a': [ @@ -782,6 +788,8 @@ + + { 'a': [ @@ -824,7 +832,7 @@ (530000, 3000), (535000, 3050), (540000, 3100), - ( 'inf', 200), + ( 'inf', 3150), ], 'b': [ (320000, 0), @@ -950,7 +958,7 @@ (530000, 3000), (535000, 3050), (540000, 3100), - ( 'inf', 200), + ( 'inf', 3150), ], 'f': [ (200000, 0), @@ -992,7 +1000,7 @@ (530000, 3000), (535000, 3050), (540000, 3100), - ( 'inf', 200), + ( 'inf', 3150), ], } @@ -1094,6 +1102,8 @@ + + { 'a' : [ diff --git a/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py index a5db79a6..8ce41d06 100644 --- a/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py @@ -32,3 +32,4 @@ class TestUsCTPayslip(TestUsPayslip): self._test_sit(5000.0, 'f', 15.0, 'monthly', date(2020, 1, 1), 230.25) self._test_sit(15000.0, 'c', 0.0, 'monthly', date(2020, 1, 1), 783.33) self._test_sit(18000.0, 'b', 0.0, 'weekly', date(2020, 1, 1), 1254.35) + self._test_sit(500.0, 'd', 0.0, 'weekly', date(2020, 1, 1), 21.15) From 3e1225a72a6b8a432676c2df56042c6256372995 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 16:30:43 -0400 Subject: [PATCH 47/63] [IMP] l10n_us_hr_payroll: Reformat tax table, improved comments and test case for CA California 2020 --- .../data/state/ca_california.xml | 556 ++++++++++++++++-- .../test_us_ca_california_payslip_2020.py | 1 + 2 files changed, 515 insertions(+), 42 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ca_california.xml b/l10n_us_hr_payroll/data/state/ca_california.xml index e51cb821..2a907b3a 100644 --- a/l10n_us_hr_payroll/data/state/ca_california.xml +++ b/l10n_us_hr_payroll/data/state/ca_california.xml @@ -85,64 +85,528 @@ { 'head_household': { - 'weekly': ((316, 0.011, 0.0), (750, 0.022, 3.48), (967, 0.044, 13.03), (1196, 0.066, 22.58), (1413, 0.088, 37.69), (7212, 0.1023, 56.79), (8654, 0.1133, 650.03), (14423, 0.1243, 813.41), (19231, 0.1353, 1530.50), ('inf', 0.1463, 2181.02)), - 'bi-weekly': ((632, 0.011, 0.0), (1500, 0.022, 6.95), (1934, 0.044, 26.05), (2392, 0.066, 45.15), (2826, 0.088, 75.38), (14424, 0.1023, 113.57), (17308, 0.1133, 1300.05), (28846, 0.1243, 1626.81), (38462, 0.1353, 3060.98), ('inf', 0.1463, 4362.02)), - 'semi-monthly': ((686, 0.011, 0.0), (1625, 0.022, 7.55), (2094, 0.044, 28.21), (2592, 0.066, 48.85), (3062, 0.088, 81.72), (15625, 0.1023, 123.08), (18750, 0.1133, 1408.27), (31250, 0.1243, 1762.33), (41667, 0.1353, 3316.08), ('inf', 0.1463, 4725.50)), - 'monthly': ((1372, 0.011, 0.0), (3250, 0.022, 15.09), (4188, 0.044, 56.41), (5184, 0.066, 97.68), (6124, 0.088, 163.42), (31250, 0.1023, 246.148), (37500, 0.1133, 2816.53), (62500, 0.1243, 3524.66), (83334, 0.1353, 6632.16), ('inf', 0.1463, 9451.00)), - 'quarterly': ((4114, 0.011, 0.0), (9748, 0.022, 45.25), (12566, 0.044, 169.20), (15552, 0.066, 293.19), (18369, 0.088, 490.27), (93751, 0.1023, 738.17), (112501, 0.1133, 8449.75), (187501, 0.1243, 10574.13), (250000, 0.1353, 19896.63), ('inf', 0.1463, 28352.74)), - 'semi-annual': ((8228, 0.011, 0.0), (19496, 0.022, 90.51), (25132, 0.044, 338.41), (31104, 0.066, 586.39), (36738, 0.088, 980.54), (187502, 0.1023, 1476.33), (225002, 0.1133, 16899.49), (375002, 0.1243, 21148.24), (500000, 0.1353, 39793.24), ('inf', 0.1463, 56705.47)), - 'annually': ((16457, 0.011, 0.0), (38991, 0.022, 181.03), (50264, 0.044, 676.78), (62206, 0.066, 1172.79), (73477, 0.088, 1960.96), (375002, 0.1023, 2952.81), (450003, 0.1133, 33798.82), (750003, 0.1243, 42296.43), (1000000, 0.1353, 79586.43), ('inf', 0.1463, 113411.02)), + 'weekly': ( + ( 316, 0.0110, 0.00), + ( 750, 0.0220, 3.48), + ( 967, 0.0440, 13.03), + ( 1196, 0.0660, 22.58), + ( 1413, 0.0880, 37.69), + ( 7212, 0.1023, 56.79), + ( 8654, 0.1133, 650.03), + (14423, 0.1243, 813.41), + (19231, 0.1353, 1530.50), + ('inf', 0.1463, 2181.02), + ), + 'bi-weekly': ( + ( 632, 0.0110, 0.00), + ( 1500, 0.0220, 6.95), + ( 1934, 0.0440, 26.05), + ( 2392, 0.0660, 45.15), + ( 2826, 0.0880, 75.38), + (14424, 0.1023, 113.57), + (17308, 0.1133, 1300.05), + (28846, 0.1243, 1626.81), + (38462, 0.1353, 3060.98), + ('inf', 0.1463, 4362.02), + ), + 'semi-monthly': ( + ( 686, 0.0110, 0.00), + ( 1625, 0.0220, 7.55), + ( 2094, 0.0440, 28.21), + ( 2592, 0.0660, 48.85), + ( 3062, 0.0880, 81.72), + (15625, 0.1023, 123.08), + (18750, 0.1133, 1408.27), + (31250, 0.1243, 1762.33), + (41667, 0.1353, 3316.08), + ('inf', 0.1463, 4725.50), + ), + 'monthly': ( + ( 1372, 0.0110, 0.00), + ( 3250, 0.0220, 15.09), + ( 4188, 0.0440, 56.41), + ( 5184, 0.0660, 97.68), + ( 6124, 0.0880, 163.42), + (31250, 0.1023, 246.14), + (37500, 0.1133, 2816.53), + (62500, 0.1243, 3524.66), + (83334, 0.1353, 6632.16), + ('inf', 0.1463, 9451.00), + ), + 'quarterly': ( + ( 4114, 0.0110, 0.00), + ( 9748, 0.0220, 45.25), + ( 12566, 0.0440, 169.20), + ( 15552, 0.0660, 293.19), + ( 18369, 0.0880, 490.27), + ( 93751, 0.1023, 738.17), + (112501, 0.1133, 8449.75), + (187501, 0.1243, 10574.13), + (250000, 0.1353, 19896.63), + ( 'inf', 0.1463, 28352.74), + ), + 'semi-annual': ( + ( 8228, 0.0110, 0.00), + ( 19496, 0.0220, 90.51), + ( 25132, 0.0440, 338.41), + ( 31104, 0.0660, 586.39), + ( 36738, 0.0880, 980.54), + (187502, 0.1023, 1476.33), + (225002, 0.1133, 16899.49), + (375002, 0.1243, 21148.24), + (500000, 0.1353, 39793.24), + ( 'inf', 0.1463, 56705.47), + ), + 'annually': ( + ( 16457, 0.0110, 0.00), + ( 38991, 0.0220, 181.03), + ( 50264, 0.0440, 676.78), + ( 62206, 0.0660, 1172.79), + ( 73477, 0.0880, 1960.96), + ( 375002, 0.1023, 2952.81), + ( 450003, 0.1133, 33798.82), + ( 750003, 0.1243, 42296.43), + (1000000, 0.1353, 79586.43), + ( 'inf', 0.1463, 113411.02), + ), }, 'married': { - 'weekly': ((316, 0.011, 0.0),(750, 0.022, 3.48),(1184, 0.044, 13.03),(1642, 0.066, 32.13), (2076, 0.088, 62.36),(10606, 0.1023, 100.55),(12726, 0.1133, 973.17),(19231, 0.1243, 1213.37),(21210, 0.1353, 2021.94),('inf', 0.1463, 2289.70)), - 'bi-weekly': ((632, 0.011, 0.0), (1500, 0.022, 6.95), (2368, 0.044, 26.05), (3284, 0.066, 64.24), (4152, 0.088, 124.70), (21212, 0.1023, 201.08), (25452, 0.1133, 1946.32), (38462, 0.1243, 2426.71), (42420, 0.1353, 4043.85), ('inf', 0.1463, 4579.37)), - 'semi-monthly': ((686, 0.011, 0.0), (1624, 0.022, 7.55), (2564, 0.044, 28.19), (3560, 0.066, 69.55), (4498, 0.088, 135.29), (22978, 0.1023, 217.83), (27574, 0.1133, 2108.33), (41667, 0.1243, 2629.06), (45956, 0.1353, 4380.82), ('inf', 0.1463, 4961.12)), - 'monthly': ((1372, 0.011, 0.0), (3248, 0.022, 15.09), (5128, 0.044, 56.36), (7120, 0.066, 139.08), (8996, 0.088, 270.55), (45956, 0.1023, 435.64), (55148, 0.1133, 4216.65), (83334, 0.1243, 5258.10), (91912, 0.1353, 8761.62), ('inf', 0.1463, 9922.22)), - 'quarterly': ((4112, 0.011, 0.0), (9748, 0.022, 45.23), (15384, 0.044, 169.22), (21356, 0.066, 417.20), (26990, 0.088, 811.35), (137870, 0.1023, 1307.14), (165442, 0.1133, 12650.16), (250000, 0.1243, 15774.07), (275736, 0.1353, 26284.63), ('inf', 0.1463, 29766.71)), - 'semi-annual': ((8224, 0.011, 0.0), (19496, 0.022, 90.46), (30768, 0.044, 338.44), (42712, 0.066, 834.41), (53980, 0.088, 1622.71), (275740, 0.1023, 2614.29), (330884, 0.1133, 25300.34), (500000, 0.1243, 31548.16), (551472, 0.1353, 52569.28), ('inf', 0.1463, 59533.44)), - 'annually': ((16446, 0.011, 0.0), (38990, 0.022, 180.91), (61538, 0.044, 676.88), (85422, 0.066, 1668.99), (107960, 0.088, 3245.33), (551476, 0.1023, 5228.67), (661768, 0.1133, 50600.36), (1000000, 0.1243, 63096.44), (1102946, 0.1353, 105138.68), ('inf', 0.1463, 119067.26)), + 'weekly': ( + ( 316, 0.0110, 0.00), + ( 750, 0.0220, 3.48), + ( 1184, 0.0440, 13.03), + ( 1642, 0.0660, 32.13), + ( 2076, 0.0880, 62.36), + (10606, 0.1023, 100.55), + (12726, 0.1133, 973.17), + (19231, 0.1243, 1213.37), + (21210, 0.1353, 2021.94), + ('inf', 0.1463, 2289.70), + ), + 'bi-weekly': ( + ( 632, 0.0110, 0.00), + ( 1500, 0.0220, 6.95), + ( 2368, 0.0440, 26.05), + ( 3284, 0.0660, 64.24), + ( 4152, 0.0880, 124.70), + (21212, 0.1023, 201.08), + (25452, 0.1133, 1946.32), + (38462, 0.1243, 2426.71), + (42420, 0.1353, 4043.85), + ('inf', 0.1463, 4579.37), + ), + 'semi-monthly': ( + ( 686, 0.0110, 0.00), + ( 1624, 0.0220, 7.55), + ( 2564, 0.0440, 28.19), + ( 3560, 0.0660, 69.55), + ( 4498, 0.0880, 135.29), + (22978, 0.1023, 217.83), + (27574, 0.1133, 2108.33), + (41667, 0.1243, 2629.06), + (45956, 0.1353, 4380.82), + ('inf', 0.1463, 4961.12), + ), + 'monthly': ( + ( 1372, 0.0110, 0.00), + ( 3248, 0.0220, 15.09), + ( 5128, 0.0440, 56.36), + ( 7120, 0.0660, 139.08), + ( 8996, 0.0880, 270.55), + (45956, 0.1023, 435.64), + (55148, 0.1133, 4216.65), + (83334, 0.1243, 5258.10), + (91912, 0.1353, 8761.62), + ('inf', 0.1463, 9922.22), + ), + 'quarterly': ( + ( 4112, 0.0110, 0.00), + ( 9748, 0.0220, 45.23), + ( 15384, 0.0440, 169.22), + ( 21356, 0.0660, 417.20), + ( 26990, 0.0880, 811.35), + (137870, 0.1023, 1307.14), + (165442, 0.1133, 12650.16), + (250000, 0.1243, 15774.07), + (275736, 0.1353, 26284.63), + ( 'inf', 0.1463, 29766.71), + ), + 'semi-annual': ( + ( 8224, 0.0110, 0.00), + ( 19496, 0.0220, 90.46), + ( 30768, 0.0440, 338.44), + ( 42712, 0.0660, 834.41), + ( 53980, 0.0880, 1622.71), + (275740, 0.1023, 2614.29), + (330884, 0.1133, 25300.34), + (500000, 0.1243, 31548.16), + (551472, 0.1353, 52569.28), + ( 'inf', 0.1463, 59533.44), + ), + 'annually': ( + ( 16446, 0.0110, 0.00), + ( 38990, 0.0220, 180.91), + ( 61538, 0.0440, 676.88), + ( 85422, 0.0660, 1668.99), + ( 107960, 0.0880, 3245.33), + ( 551476, 0.1023, 5228.67), + ( 661768, 0.1133, 50600.36), + (1000000, 0.1243, 63096.44), + (1102946, 0.1353, 105138.68), + ( 'inf', 0.1463, 119067.26), + ), }, 'single': { - 'weekly': ((158, 0.011, 0.0), (375, 0.022, 1.74), (592, 0.044, 6.51), (821, 0.066, 16.06), (1038, 0.088, 31.17), (5303, 0.1023, 50.27), (6363, 0.1133, 486.58), (10605, 0.1243, 606.68), (19231, 0.1353, 1133.96), ('inf', 0.1463, 2301.06)), - 'bi-weekly': ((316, 0.011, 0.0), (750, 0.022, 3.48), (1184, 0.044, 13.03), (1642, 0.066, 32.13), (2076, 0.088, 62.36), (10606, 0.1023, 100.55), (12726, 0.1133, 973.17), (21210, 0.1243, 1213.37), (38462, 0.1353, 2267.93), ('inf', 0.1463, 4602.13)), - 'semi-monthly': ((343, 0.011, 0.0), (812, 0.022, 3.77), (1282, 0.044, 14.09), (1780, 0.066, 34.77), (2249, 0.088, 67.64), (11489, 0.1023, 108.91), (13787, 0.1133, 1054.16), (22978, 0.1243, 1314.52), (41667, 0.1353, 2456.96),('inf', 0.1463, 4985.58)), - 'monthly': ((686, 0.011, 0.0), (1624, 0.022, 7.55), (2564, 0.044, 28.19), (3560, 0.066, 69.55), (4498, 0.088, 135.29), (22978, 0.1023, 217.83), (27574, 0.1133, 2108.33), (45956, 0.1243, 2629.06), (83334, 0.1353, 4913.94), ('inf', 0.1463, 9971.18)), - 'quarterly': ((2056, 0.011, 0.0), (4874, 0.022, 22.62), (7692, 0.044, 84.62), (10678, 0.066, 208.61), (13495, 0.088, 405.69), (68935, 0.1023, 653.59), (82721, 0.1133, 6325.10), (137868, 0.1243, 7887.05), (250000, 0.1353, 14741.82), ('inf', 0.1463, 29913.28)), - 'semi-annual': ((4112, 0.011, 0.0), (9748, 0.022, 45.23), (15384, 0.044, 169.22), (21356, 0.066, 417.20), (26990, 0.088, 811.35), (137870, 0.1023, 1307.14), (165442, 0.1133, 12650.16), (275736, 0.1243, 15774.07), (500000, 0.1353, 29483.61), ('inf', 0.1463, 59826.53)), - 'annually': ((8223, 0.011, 0.0), (19495, 0.022, 90.45), (30769, 0.044, 338.43), (42711, 0.066, 834.49), (53980, 0.088, 1622.66), (275738, 0.1023, 2614.33), (330884, 0.1133, 25300.17), (551473, 0.1243, 31548.21), (1000000, 0.1353, 58967.42), ('inf', 0.1463, 119653.12)), + 'weekly': ( + ( 158, 0.0110, 0.00), + ( 375, 0.0220, 1.74), + ( 592, 0.0440, 6.51), + ( 821, 0.0660, 16.06), + ( 1038, 0.0880, 31.17), + ( 5303, 0.1023, 50.27), + ( 6363, 0.1133, 486.58), + (10605, 0.1243, 606.68), + (19231, 0.1353, 1133.96), + ('inf', 0.1463, 2301.06), + ), + 'bi-weekly': ( + ( 316, 0.0110, 0.00), + ( 750, 0.0220, 3.48), + ( 1184, 0.0440, 13.03), + ( 1642, 0.066, 32.13), + ( 2076, 0.0880, 62.36), + (10606, 0.1023, 100.55), + (12726, 0.1133, 973.17), + (21210, 0.1243, 1213.37), + (38462, 0.1353, 2267.93), + ('inf', 0.1463, 4602.13), + ), + 'semi-monthly': ( + ( 343, 0.0110, 0.00), + ( 812, 0.0220, 3.77), + ( 1282, 0.0440, 14.09), + ( 1780, 0.0660, 34.77), + ( 2249, 0.0880, 67.64), + (11489, 0.1023, 108.91), + (13787, 0.1133, 1054.16), + (22978, 0.1243, 1314.52), + (41667, 0.1353, 2456.96), + ('inf', 0.1463, 4985.58), + ), + 'monthly': ( + ( 686, 0.0110, 0.00), + ( 1624, 0.0220, 7.55), + ( 2564, 0.0440, 28.19), + ( 3560, 0.0660, 69.55), + ( 4498, 0.0880, 135.29), + (22978, 0.1023, 217.83), + (27574, 0.1133, 2108.33), + (45956, 0.1243, 2629.06), + (83334, 0.1353, 4913.94), + ('inf', 0.1463, 9971.18), + ), + 'quarterly': ( + ( 2056, 0.0110, 0.00), + ( 4874, 0.0220, 22.62), + ( 7692, 0.0440, 84.62), + ( 10678, 0.066, 208.61), + ( 13495, 0.0880, 405.69), + ( 68935, 0.1023, 653.59), + ( 82721, 0.1133, 6325.10), + (137868, 0.1243, 7887.05), + (250000, 0.1353, 14741.82), + ( 'inf', 0.1463, 29913.28), + ), + 'semi-annual': ( + ( 4112, 0.0110, 0.00), + ( 9748, 0.0220, 45.23), + ( 15384, 0.0440, 169.22), + ( 21356, 0.0660, 417.20), + ( 26990, 0.0880, 811.35), + (137870, 0.1023, 1307.14), + (165442, 0.1133, 12650.16), + (275736, 0.1243, 15774.07), + (500000, 0.1353, 29483.61), + ('inf', 0.1463, 59826.53), + ), + 'annually': ( + ( 8223, 0.0110, 0.00), + ( 19495, 0.0220, 90.45), + ( 30769, 0.0440, 338.43), + ( 42711, 0.0660, 834.49), + ( 53980, 0.0880, 1622.66), + ( 275738, 0.1023, 2614.33), + ( 330884, 0.1133, 25300.17), + ( 551473, 0.1243, 31548.21), + (1000000, 0.1353, 58967.42), + ( 'inf', 0.1463, 119653.12), + ), }, } + + { 'head_household': { - 'weekly': ((339, 0.011, 0.0), (803, 0.022, 3.73), (1035, 0.044, 13.93), (1281, 0.066, 24.15), (1514, 0.088, 40.39), (7725, 0.1023, 60.89), (9270, 0.1133, 696.28), (15450, 0.1243, 871.33), (19231, 0.1353, 1639.50), ('inf', 0.1463, 2151.07)), - 'bi-weekly': ((678, 0.011, 0.0), (1606, 0.022, 7.46), (2070, 0.044, 27.88), (2562, 0.066, 48.30), (3028, 0.088, 80.77), (15450, 0.1023, 121.78), (18540, 0.1133, 1392.55), (30900, 0.1243, 1742.65), (38462, 0.1353, 3279.00), ('inf', 0.1463, 4302.14)), - 'semi-monthly': ((735, 0.011, 0.0), (1740, 0.022, 8.09), (2243, 0.044, 30.20), (2777, 0.066, 52.33), (3280, 0.088, 87.57), (16738, 0.1023, 131.83), (20085, 0.1133, 1508.58), (33475, 0.1243, 1887.80), (41667, 0.1353, 3552.18), ('inf', 0.1463, 4660.56)), - 'monthly': ((1470, 0.011, 0.0), (3480, 0.022, 16.17), (4486, 0.044, 60.39), (5554, 0.066, 104.65), (6560, 0.088, 175.14), (33476, 0.1023, 263.67), (40170, 0.1133, 3017.18), (66950, 0.1243, 3775.61), (83334, 0.1353, 7104.36), ('inf', 0.1463, 9321.12)), - 'quarterly': ((4407, 0.011, 0.0), (10442, 0.022, 48.48), (13461, 0.044, 181.25), (16659, 0.066, 314.09), (19678, 0.088, 525.16), (100426, 0.1023, 790.83), (120512, 0.1133, 9051.35), (200853, 0.1243, 11327.09), (250000, 0.1353, 21313.48), ('inf', 0.1463, 27963.07)), - 'semi-annual': ((8814, 0.011, 0.0), (20884, 0.022, 96.95), (26922, 0.044, 362.49), (33318, 0.066, 628.16), (39356, 0.088, 1050.30), (200852, 0.1023, 1581.64), (241024, 0.1133, 18102.68), (401706, 0.1243, 22654.17), (500000, 0.1353, 42626.94), ('inf', 0.1463, 55926.12)), - 'annually': ((17629, 0.011, 0.0), (41768, 0.022, 193.92), (53843, 0.044, 724.98), (66636, 0.066, 1256.28), (78710, 0.088, 2100.62), (401705, 0.1023, 3163.13), (482047, 0.1133, 36205.52), (803410, 0.1243, 45308.27), (1000000, 0.1353, 85253.69), ('inf', 0.1463, 111852.32)), + 'weekly': ( + ( 339, 0.0110, 0.00), + ( 803, 0.0220, 3.73), + ( 1035, 0.0440, 13.93), + ( 1281, 0.0660, 24.15), + ( 1514, 0.0880, 40.39), + ( 7725, 0.1023, 60.89), + ( 9270, 0.1133, 696.28), + (15450, 0.1243, 871.33), + (19231, 0.1353, 1639.50), + ('inf', 0.1463, 2151.07), + ), + 'bi-weekly': ( + ( 678, 0.0110, 0.00), + ( 1606, 0.0220, 7.46), + ( 2070, 0.0440, 27.88), + ( 2562, 0.0660, 48.30), + ( 3028, 0.0880, 80.77), + (15450, 0.1023, 121.78), + (18540, 0.1133, 1392.55), + (30900, 0.1243, 1742.65), + (38462, 0.1353, 3279.00), + ('inf', 0.1463, 4302.14), + ), + 'semi-monthly': ( + ( 735, 0.0110, 0.00), + ( 1740, 0.0220, 8.09), + ( 2243, 0.0440, 30.20), + ( 2777, 0.0660, 52.33), + ( 3280, 0.0880, 87.57), + (16738, 0.1023, 131.83), + (20085, 0.1133, 1508.58), + (33475, 0.1243, 1887.80), + (41667, 0.1353, 3552.18), + ('inf', 0.1463, 4660.56), + ), + 'monthly': ( + ( 1470, 0.0110, 0.00), + ( 3480, 0.0220, 16.17), + ( 4486, 0.0440, 60.39), + ( 5554, 0.0660, 104.65), + ( 6560, 0.0880, 175.14), + (33476, 0.1023, 263.67), + (40170, 0.1133, 3017.18), + (66950, 0.1243, 3775.61), + (83334, 0.1353, 7104.36), + ('inf', 0.1463, 9321.12), + ), + 'quarterly': ( + ( 4407, 0.0110, 0.00), + ( 10442, 0.0220, 48.48), + ( 13461, 0.0440, 181.25), + ( 16659, 0.0660, 314.09), + ( 19678, 0.0880, 525.16), + (100426, 0.1023, 790.83), + (120512, 0.1133, 9051.35), + (200853, 0.1243, 11327.09), + (250000, 0.1353, 21313.48), + ( 'inf', 0.1463, 27963.07), + ), + 'semi-annual': ( + ( 8814, 0.0110, 0.00), + ( 20884, 0.0220, 96.95), + ( 26922, 0.0440, 362.49), + ( 33318, 0.0660, 628.16), + ( 39356, 0.0880, 1050.30), + (200852, 0.1023, 1581.64), + (241024, 0.1133, 18102.68), + (401706, 0.1243, 22654.17), + (500000, 0.1353, 42626.94), + ( 'inf', 0.1463, 55926.12), + ), + 'annually': ( + ( 17629, 0.0110, 0.00), + ( 41768, 0.0220, 193.92), + ( 53843, 0.0440, 724.98), + ( 66636, 0.0660, 1256.28), + ( 78710, 0.0880, 2100.62), + ( 401705, 0.1023, 3163.13), + ( 482047, 0.1133, 36205.52), + ( 803410, 0.1243, 45308.27), + (1000000, 0.1353, 85253.69), + ( 'inf', 0.1463, 111852.32), + ), }, 'married': { - 'weekly': ((338, 0.011, 0.0),(804, 0.022, 3.72),(1268, 0.044, 13.97),(1760, 0.066, 34.39), (2224, 0.088, 66.86),(11360, 0.1023, 107.69),(13632, 0.1133, 1042.30),(19231, 0.1243, 1299.72),(22721, 0.1353, 1995.68),('inf', 0.1463, 2467.88)), - 'bi-weekly': ((676, 0.011, 0.0), (1608, 0.022, 7.44), (2536, 0.044, 27.94), (3520, 0.066, 68.77), (4448, 0.088, 124.70), (21212, 0.1023, 201.08), (25452, 0.1133, 1946.32), (38462, 0.1243, 2426.71), (42420, 0.1353, 4043.85), ('inf', 0.1463, 4579.37)), - 'semi-monthly': ((734, 0.011, 0.0), (1740, 0.022, 8.07), (2746, 0.044, 30.20), (3812, 0.066, 74.46), (4818, 0.088, 144.82), (24614, 0.1023, 233.35), (29538, 0.1133, 2258.48), (41667, 0.1243, 2816.37), (49229, 0.1353, 4324.00), ('inf', 0.1463, 5347.14)), - 'monthly': ((1468, 0.011, 0.0), (3480, 0.022, 16.15), (5492, 0.044, 60.41), (7624, 0.066, 148.94), (9636, 0.088, 2889.65), (49228, 0.1023, 466.71), (59076, 0.1133, 4516.97), (83334, 0.1243, 5632.75), (98458, 0.1353, 8648.02), ('inf', 0.1463, 10694.30)), - 'quarterly': ((4404, 0.011, 0.0), (10442, 0.022, 48.44), (16480, 0.044, 181.28), (22876, 0.066, 446.95), (28912, 0.088, 869.09), (147686, 0.1023, 1400.26), (177222, 0.1133, 13550.84), (250000, 0.1243, 16897.27), (295371, 0.1353, 25943.58), ('inf', 0.1463, 32082.28)), - 'semi-annual': ((8808, 0.011, 0.0), (20884, 0.022, 96.89), (32960, 0.044, 362.56), (45752, 0.066, 893.90), (57824, 0.088, 1738.17), (295372, 0.1023, 2800.51), (354444, 0.1133, 27101.67), (500000, 0.1243, 33794.53), (590742, 0.1353, 51887.14), ('inf', 0.1463, 64164.53)), - 'annually': ((17618, 0.011, 0.0), (41766, 0.022, 193.80), (65920, 0.044, 725.06), (91506, 0.066, 1787.84), (115648, 0.088, 3476.52), (590746, 0.1023, 5601.02), (708890, 0.1133, 54203.55), (1000000, 0.1243, 67589.27), (1181484, 0.1353, 103774.24), ('inf', 0.1463, 128329.03)), + 'weekly': ( + ( 338, 0.0110, 0.00), + ( 804, 0.0220, 3.72), + ( 1268, 0.0440, 13.97), + ( 1760, 0.0660, 34.39), + ( 2224, 0.0880, 66.86), + (11360, 0.1023, 107.69), + (13632, 0.1133, 1042.30), + (19231, 0.1243, 1299.72), + (22721, 0.1353, 1995.68), + ('inf', 0.1463, 2467.88), + ), + 'bi-weekly': ( + ( 676, 0.0110, 0.00), + ( 1608, 0.0220, 7.44), + ( 2536, 0.0440, 27.94), + ( 3520, 0.0660, 68.77), + ( 4448, 0.0880, 124.70), + (21212, 0.1023, 201.08), + (25452, 0.1133, 1946.32), + (38462, 0.1243, 2426.71), + (42420, 0.1353, 4043.85), + ('inf', 0.1463, 4579.37), + ), + 'semi-monthly': ( + ( 734, 0.0110, 0.00), + ( 1740, 0.0220, 8.07), + ( 2746, 0.0440, 30.20), + ( 3812, 0.0660, 74.46), + ( 4818, 0.0880, 144.82), + (24614, 0.1023, 233.35), + (29538, 0.1133, 2258.48), + (41667, 0.1243, 2816.37), + (49229, 0.1353, 4324.00), + ('inf', 0.1463, 5347.14), + ), + 'monthly': ( + ( 1468, 0.0110, 0.00), + ( 3480, 0.0220, 16.15), + ( 5492, 0.0440, 60.41), + ( 7624, 0.0660, 148.94), + ( 9636, 0.0880, 289.65), + (49228, 0.1023, 466.71), + (59076, 0.1133, 4516.97), + (83334, 0.1243, 5632.75), + (98458, 0.1353, 8648.02), + ('inf', 0.1463, 10694.30), + ), + 'quarterly': ( + ( 4404, 0.0110, 0.00), + ( 10442, 0.0220, 48.44), + ( 16480, 0.0440, 181.28), + ( 22876, 0.0660, 446.95), + ( 28912, 0.0880, 869.09), + (147686, 0.1023, 1400.26), + (177222, 0.1133, 13550.84), + (250000, 0.1243, 16897.27), + (295371, 0.1353, 25943.58), + ( 'inf', 0.1463, 32082.28), + ), + 'semi-annual': ( + ( 8808, 0.0110, 0.00), + ( 20884, 0.0220, 96.89), + ( 32960, 0.0440, 362.56), + ( 45752, 0.0660, 893.90), + ( 57824, 0.0880, 1738.17), + (295372, 0.1023, 2800.51), + (354444, 0.1133, 27101.67), + (500000, 0.1243, 33794.53), + (590742, 0.1353, 51887.14), + ( 'inf', 0.1463, 64164.53), + ), + 'annually': ( + ( 17618, 0.0110, 0.00), + ( 41766, 0.0220, 193.80), + ( 65920, 0.0440, 725.06), + ( 91506, 0.0660, 1787.84), + ( 115648, 0.0880, 3476.52), + ( 590746, 0.1023, 5601.02), + ( 708890, 0.1133, 54203.55), + (1000000, 0.1243, 67589.27), + (1181484, 0.1353, 103774.24), + ( 'inf', 0.1463, 128329.03), + ), }, 'single': { - 'weekly': ((169, 0.011, 0.0), (402, 0.022, 1.86), (634, 0.044, 6.99), (880, 0.066, 17.20), (1112, 0.088, 33.44), (5680, 0.1023, 53.86), (6816, 0.1133, 521.17), (11360, 0.1243, 649.88), (19231, 0.1353, 1214.70), ('inf', 0.1463, 2279.65)), - 'bi-weekly': ((338, 0.011, 0.0), (804, 0.022, 3.72), (1268, 0.044, 13.97), (1760, 0.066, 34.39), (2224, 0.088, 66.86), (11360, 0.1023, 107.69), (13632, 0.1133, 1042.30), (22720, 0.1243, 1299.72), (38462, 0.1353, 2429.36), ('inf', 0.1463, 4559.25)), - 'semi-monthly': ((367, 0.011, 0.0), (870, 0.022, 4.04), (1373, 0.044, 15.11), (1906, 0.066, 37.24), (2409, 0.088, 72.42), (12307, 0.1023, 116.68), (14769, 0.1133, 1129.25), (24614, 0.1243, 1408.19), (41667, 0.1353, 2631.92),('inf', 0.1463, 4939.19)), - 'monthly': ((734, 0.011, 0.0), (1740, 0.022, 8.07), (2746, 0.044, 30.20), (3812, 0.066, 74.46), (4818, 0.088, 144.82), (24614, 0.1023, 233.35), (29538, 0.1133, 2258.48), (49228, 0.1243, 2816.37), (83334, 0.1353, 5263.84), ('inf', 0.1463, 9878.38)), - 'quarterly': ((2202, 0.011, 0.0), (5221, 0.022, 24.22), (8240, 0.044, 90.64), (11438, 0.066, 223.48), (14456, 0.088, 434.55), (73843, 0.1023, 700.13), (88611, 0.1133, 6775.42), (147686, 0.1243, 8448.63), (250000, 0.1353, 15791.65), ('inf', 0.1463, 29634.73)), - 'semi-annual': ((4404, 0.011, 0.0), (10442, 0.022, 48.44), (16480, 0.044, 181.28), (22876, 0.066, 446.95), (28912, 0.088, 869.09), (147686, 0.1023, 1400.26), (177222, 0.1133, 13550.84), (295372, 0.1243, 16897.27), (500000, 0.1353, 31583.32), ('inf', 0.1463, 59269.49)), - 'annually': ((8809, 0.011, 0.0), (20883, 0.022, 96.90), (32960, 0.044, 362.53), (45753, 0.066, 893.92), (57824, 0.088, 1738.26), (295373, 0.1023, 2800.51), (354445, 0.1133, 27101.77), (590742, 0.1243, 33794.63), (1000000, 0.1353, 63166.35), ('inf', 0.1463, 118538.96)), + 'weekly': ( + ( 169, 0.0110, 0.00), + ( 402, 0.0220, 1.86), + ( 634, 0.0440, 6.99), + ( 880, 0.0660, 17.20), + ( 1112, 0.0880, 33.44), + ( 5680, 0.1023, 53.86), + ( 6816, 0.1133, 521.17), + (11360, 0.1243, 649.88), + (19231, 0.1353, 1214.70), + ('inf', 0.1463, 2279.65), + ), + 'bi-weekly': ( + ( 338, 0.0110, 0.00), + ( 804, 0.0220, 3.72), + ( 1268, 0.0440, 13.97), + ( 1760, 0.0660, 34.39), + ( 2224, 0.0880, 66.86), + (11360, 0.1023, 107.69), + (13632, 0.1133, 1042.30), + (22720, 0.1243, 1299.72), + (38462, 0.1353, 2429.36), + ('inf', 0.1463, 4559.25), + ), + 'semi-monthly': ( + ( 367, 0.0110, 0.00), + ( 870, 0.0220, 4.04), + ( 1373, 0.0440, 15.11), + ( 1906, 0.0660, 37.24), + ( 2409, 0.0880, 72.42), + (12307, 0.1023, 116.68), + (14769, 0.1133, 1129.25), + (24614, 0.1243, 1408.19), + (41667, 0.1353, 2631.92), + ('inf', 0.1463, 4939.19), + ), + 'monthly': ( + ( 734, 0.0110, 0.00), + ( 1740, 0.0220, 8.07), + ( 2746, 0.0440, 30.20), + ( 3812, 0.0660, 74.46), + ( 4818, 0.0880, 144.82), + (24614, 0.1023, 233.35), + (29538, 0.1133, 2258.48), + (49228, 0.1243, 2816.37), + (83334, 0.1353, 5263.84), + ('inf', 0.1463, 9878.38), + ), + 'quarterly': ( + ( 2202, 0.0110, 0.00), + ( 5221, 0.0220, 24.22), + ( 8240, 0.0440, 90.64), + ( 11438, 0.0660, 223.48), + ( 14456, 0.0880, 434.55), + ( 73843, 0.1023, 700.13), + ( 88611, 0.1133, 6775.42), + (147686, 0.1243, 8448.63), + (250000, 0.1353, 15791.65), + ( 'inf', 0.1463, 29634.73), + ), + 'semi-annual': ( + ( 4404, 0.0110, 0.00), + ( 10442, 0.0220, 48.44), + ( 16480, 0.0440, 181.28), + ( 22876, 0.0660, 446.95), + ( 28912, 0.0880, 869.09), + (147686, 0.1023, 1400.26), + (177222, 0.1133, 13550.84), + (295372, 0.1243, 16897.27), + (500000, 0.1353, 31583.32), + ( 'inf', 0.1463, 59269.49), + ), + 'annually': ( + ( 8809, 0.0110, 0.00), + ( 20883, 0.0220, 96.90), + ( 32960, 0.0440, 362.53), + ( 45753, 0.0660, 893.92), + ( 57824, 0.0880, 1738.26), + ( 295373, 0.1023, 2800.51), + ( 354445, 0.1133, 27101.77), + ( 590742, 0.1243, 33794.63), + (1000000, 0.1353, 63166.35), + ( 'inf', 0.1463, 118538.96), + ), }, } @@ -169,6 +633,8 @@ + + { 'weekly': ( 289, 289, 579, 579), @@ -203,6 +669,8 @@ + + { 'weekly': ( 19, 38, 58, 77, 96, 115, 135, 154, 173, 192), @@ -237,6 +705,8 @@ + + { 'weekly': ( 87, 87, 175, 175), @@ -271,6 +741,8 @@ + + { 'weekly': ( 2.58, 5.16, 7.74, 10.32, 12.90, 15.48, 18.07, 20.65, 23.23, 25.81), diff --git a/l10n_us_hr_payroll/tests/test_us_ca_california_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ca_california_payslip_2020.py index c6c58547..264b115e 100755 --- a/l10n_us_hr_payroll/tests/test_us_ca_california_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ca_california_payslip_2020.py @@ -40,3 +40,4 @@ class TestUsCAPayslip(TestUsPayslip): self._test_sit(1800.0, 'married', 4, 0, 0, 'semi-monthly', date(2020, 1, 1), 0.84) self._test_sit(45000.0, 'married', 4, 0, 0, 'annually', date(2020, 1, 1), 59.78) self._test_sit(45000.0, 'married', 4, 0, 20.0, 'annually', date(2020, 1, 1), 79.78) + self._test_sit(6000.0, '', 4, 0, 20.0, 'annually', date(2020, 1, 1), 0.00) From 002b3e5c5dd85b6d2c50c38657a72fca2f7c6776 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 17:32:49 -0400 Subject: [PATCH 48/63] [IMP] l10n_us_hr_payroll: Added Tax table for 2020 and improved Test case for GA Georgia 2020 --- l10n_us_hr_payroll/data/state/ga_georgia.xml | 734 +++++++++++++++++- l10n_us_hr_payroll/models/state/ga_georgia.py | 2 +- .../models/us_payroll_config.py | 2 +- .../tests/test_us_ga_georgia_payslip_2020.py | 151 +--- 4 files changed, 722 insertions(+), 167 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ga_georgia.xml b/l10n_us_hr_payroll/data/state/ga_georgia.xml index 72844e5e..659515db 100644 --- a/l10n_us_hr_payroll/data/state/ga_georgia.xml +++ b/l10n_us_hr_payroll/data/state/ga_georgia.xml @@ -47,54 +47,597 @@ { 'married filing joint, both spouses working': { - 'weekly': ((9.50, 0.00, 1.00), (29.00, .10, 2.00), (48.00, .48, 3.00), (67.50, 1.06, 4.00), (96.00, 1.83, 5.00), ('inf', 3.27, 5.75)), - 'bi-weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.00, 3.65, 5.00), ('inf', 6.54, 5.75)), - 'semi-monthly': ((21.00, 0.00, 1.00), (62.50, .21, 2.00), (104.00, 1.04, 3.00), (146.00, 2.29, 4.00), (208.00, 3.96, 5.00), ('inf', 7.08, 5.75)), - 'monthly': ((41.50, 0.00, 1.00), (125.50, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)), - 'quarterly': ((125.00, 0.00, 1.00), (375.00, 1.25, 2.00), (625.00, 6.25, 3.00), (875.00, 13.75, 4.00), (1250.00, 23.75, 5.00), ('inf', 42.50, 5.75)), - 'semi-annual': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)), - 'annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)), + 'weekly': ( + ( 9.50, 0.00, 1.00), + (29.00, 0.10, 2.00), + (48.00, 0.48, 3.00), + (67.50, 1.06, 4.00), + (96.00, 1.83, 5.00), + ('inf', 3.27, 5.75), + ), + 'bi-weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.00, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'semi-monthly': ( + ( 21.00, 0.00, 1.00), + ( 62.50, 0.21, 2.00), + (104.00, 1.04, 3.00), + (146.00, 2.29, 4.00), + (208.00, 3.96, 5.00), + ( 'inf', 7.08, 5.75), + ), + 'monthly': ( + ( 41.50, 0.00, 1.00), + (125.50, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'quarterly': ( + ( 125.00, 0.00, 1.00), + ( 375.00, 1.25, 2.00), + ( 625.00, 6.25, 3.00), + ( 875.00, 13.75, 4.00), + (1250.00, 23.75, 5.00), + ( 'inf', 42.50, 5.75), + ), + 'semi-annual': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), }, 'married filing joint, one spouse working': { - 'weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.50, 3.65, 5.00), ('inf', 6.54, 5.75)), - 'bi-weekly': ((38.50, 0.00, 1.00), (115.00, .38, 2.00), (192.00, 1.92, 3.00), (269.00, 4.23, 4.00), (385.00, 7.31, 5.00), ('inf', 13.08, 5.75)), - 'semi-monthly': ((41.50, 0.00, 1.00), (125.00, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)), - 'monthly': ((83.00, 0.00, 1.00), (250.00, .83, 2.00), (417.00, 4.17, 3.00), (583.00, 9.17, 4.00), (833.00, 15.83, 5.00), ('inf', 28.33, 5.75)), - 'quarterly': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)), - 'semi-annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)), - 'annual': ((1000.00, 0.00, 1.00), (3000.00, 10.00, 2.00), (5000.00, 50.00, 3.00), (7000.00, 110.00, 4.00), (10000.00, 190.00, 5.00), ('inf', 340.00, 5.75)), + 'weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.50, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'bi-weekly': ( + ( 38.50, 0.00, 1.00), + (115.00, 0.38, 2.00), + (192.00, 1.92, 3.00), + (269.00, 4.23, 4.00), + (385.00, 7.31, 5.00), + ( 'inf', 13.08, 5.75), + ), + 'semi-monthly': ( + ( 41.50, 0.00, 1.00), + (125.00, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'monthly': ( + ( 83.00, 0.00, 1.00), + (250.00, 0.83, 2.00), + (417.00, 4.17, 3.00), + (583.00, 9.17, 4.00), + (833.00, 15.83, 5.00), + ( 'inf', 28.33, 5.75), + ), + 'quarterly': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'semi-annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + 'annual': ( + ( 1000.00, 0.00, 1.00), + ( 3000.00, 10.00, 2.00), + ( 5000.00, 50.00, 3.00), + ( 7000.00, 110.00, 4.00), + (10000.00, 190.00, 5.00), + ( 'inf', 340.00, 5.75), + ), }, 'single': { - 'weekly': ((14.50, 0.00, 1.00), (43.50, .14, 2.00), (72.00, .72, 3.00), (101.00, 1.59, 4.00), (135.00, 2.74, 5.00), ('inf', 4.42, 5.75)), - 'bi-weekly': ((29.00, 0.00, 1.00), (86.50, .29, 2.00), (144.00, 1.44, 3.00), (202.00, 3.17, 4.00), (269.00, 5.48, 5.00), ('inf', 8.85, 5.75)), - 'semi-monthly': ((31.00, 0.00, 1.00), (93.50, .31, 2.00), (156.00, 1.56, 3.00), (219.00, 3.34, 4.00), (292.00, 5.94, 5.00), ('inf', 9.58, 5.75)), - 'monthly': ((62.50, 0.00, 1.00), (187.00, .62, 2.00), (312.00, 3.12, 3.00), (437.00, 6.87, 4.00), (583.00, 11.87, 5.00), ('inf', 19.17, 5.75)), - 'quarterly': ((187.50, 0.00, 1.00), (562.50, 1.88, 2.00), (937.50, 9.38, 3.00), (1312.00, 20.63, 4.00), (1750.00, 35.63, 5.00), ('inf', 57.50, 5.75)), - 'semi-annual': ((375.00, 0.00, 1.00), (1125.00, 3.75, 2.00), (1875.00, 18.75, 3.00), (2625.00, 41.25, 4.00), (3500.00, 71.25, 5.00), ('inf', 115.00, 5.75)), - 'annual': ((750.00, 0.00, 1.00), (2250.00, 7.50, 2.00), (3750.00, 37.50, 3.00), (5250.00, 82.50, 4.00), (7000.00, 142.50, 5.00), ('inf', 230.00, 5.75)), + 'weekly': ( + ( 14.50, 0.00, 1.00), + ( 43.50, 0.14, 2.00), + ( 72.00, 0.72, 3.00), + (101.00, 1.59, 4.00), + (135.00, 2.74, 5.00), + ( 'inf', 4.42, 5.75), + ), + 'bi-weekly': ( + ( 29.00, 0.00, 1.00), + ( 86.50, 0.29, 2.00), + (144.00, 1.44, 3.00), + (202.00, 3.17, 4.00), + (269.00, 5.48, 5.00), + ( 'inf', 8.85, 5.75), + ), + 'semi-monthly': ( + ( 31.00, 0.00, 1.00), + ( 93.50, 0.31, 2.00), + (156.00, 1.56, 3.00), + (219.00, 3.34, 4.00), + (292.00, 5.94, 5.00), + ( 'inf', 9.58, 5.75), + ), + 'monthly': ( + ( 62.50, 0.00, 1.00), + (187.00, 0.62, 2.00), + (312.00, 3.12, 3.00), + (437.00, 6.87, 4.00), + (583.00, 11.87, 5.00), + ( 'inf', 19.17, 5.75), + ), + 'quarterly': ( + ( 187.50, 0.00, 1.00), + ( 562.50, 1.88, 2.00), + ( 937.50, 9.38, 3.00), + (1312.00, 20.63, 4.00), + (1750.00, 35.63, 5.00), + ( 'inf', 57.50, 5.75), + ), + 'semi-annual': ( + ( 375.00, 0.00, 1.00), + (1125.00, 3.75, 2.00), + (1875.00, 18.75, 3.00), + (2625.00, 41.25, 4.00), + (3500.00, 71.25, 5.00), + ( 'inf', 115.00, 5.75), + ), + 'annual': ( + ( 750.00, 0.00, 1.00), + (2250.00, 7.50, 2.00), + (3750.00, 37.50, 3.00), + (5250.00, 82.50, 4.00), + (7000.00, 142.50, 5.00), + ( 'inf', 230.00, 5.75), + ), }, 'head of household': { - 'weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.50, 3.65, 5.00), ('inf', 6.54, 5.75)), - 'bi-weekly': ((38.50, 0.00, 1.00), (115.00, .38, 2.00), (192.00, 1.92, 3.00), (269.00, 4.23, 4.00), (385.00, 7.31, 5.00), ('inf', 13.08, 5.75)), - 'semi-monthly': ((41.50, 0.00, 1.00), (125.00, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)), - 'monthly': ((83.00, 0.00, 1.00), (250.00, .83, 2.00), (417.00, 4.17, 3.00), (583.00, 9.17, 4.00), (833.00, 15.83, 5.00), ('inf', 28.33, 5.75)), - 'quarterly': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)), - 'semi-annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)), - 'annual': ((1000.00, 0.00, 1.00), (3000.00, 10.00, 2.00), (5000.00, 50.00, 3.00), (7000.00, 110.00, 4.00), (10000.00, 190.00, 5.00), ('inf', 340.00, 5.75)), + 'weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.50, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'bi-weekly': ( + ( 38.50, 0.00, 1.00), + (115.00, 0.38, 2.00), + (192.00, 1.92, 3.00), + (269.00, 4.23, 4.00), + (385.00, 7.31, 5.00), + ( 'inf', 13.08, 5.75), + ), + 'semi-monthly': ( + ( 41.50, 0.00, 1.00), + (125.00, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'monthly': ( + ( 83.00, 0.00, 1.00), + (250.00, 0.83, 2.00), + (417.00, 4.17, 3.00), + (583.00, 9.17, 4.00), + (833.00, 15.83, 5.00), + ( 'inf', 28.33, 5.75), + ), + 'quarterly': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'semi-annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + 'annual': ( + ( 1000.00, 0.00, 1.00), + ( 3000.00, 10.00, 2.00), + ( 5000.00, 50.00, 3.00), + ( 7000.00, 110.00, 4.00), + (10000.00, 190.00, 5.00), + ( 'inf', 340.00, 5.75), + ), }, 'married filing separate': { - 'weekly': ((9.50, 0.00, 1.00), (29.00, .10, 2.00), (48.00, .48, 3.00), (67.50, 1.06, 4.00), (96.00, 1.83, 5.00), ('inf', 3.27, 5.75)), - 'bi-weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.00, 3.65, 5.00), ('inf', 6.54, 5.75)), - 'semi-monthly': ((21.00, 0.00, 1.00), (62.50, .21, 2.00), (104.00, 1.04, 3.00), (146.00, 2.29, 4.00), (208.00, 3.96, 5.00), ('inf', 7.08, 5.75)), - 'monthly': ((41.50, 0.00, 1.00), (125.50, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)), - 'quarterly': ((125.00, 0.00, 1.00), (375.00, 1.25, 2.00), (625.00, 6.25, 3.00), (875.00, 13.75, 4.00), (1250.00, 23.75, 5.00), ('inf', 42.50, 5.75)), - 'semi-annual': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)), - 'annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)), + 'weekly': ( + ( 9.50, 0.00, 1.00), + (29.00, 0.10, 2.00), + (48.00, 0.48, 3.00), + (67.50, 1.06, 4.00), + (96.00, 1.83, 5.00), + ('inf', 3.27, 5.75), + ), + 'bi-weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.00, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'semi-monthly': ( + ( 21.00, 0.00, 1.00), + ( 62.50, 0.21, 2.00), + (104.00, 1.04, 3.00), + (146.00, 2.29, 4.00), + (208.00, 3.96, 5.00), + ( 'inf', 7.08, 5.75), + ), + 'monthly': ( + ( 41.50, 0.00, 1.00), + (125.50, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'quarterly': ( + ( 125.00, 0.00, 1.00), + ( 375.00, 1.25, 2.00), + ( 625.00, 6.25, 3.00), + ( 875.00, 13.75, 4.00), + (1250.00, 23.75, 5.00), + ( 'inf', 42.50, 5.75), + ), + 'semi-annual': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), }, } + + + + { + 'married filing joint, both spouses working': { + 'weekly': ( + ( 9.50, 0.00, 1.00), + (29.00, 0.10, 2.00), + (48.00, 0.48, 3.00), + (67.50, 1.06, 4.00), + (96.00, 1.83, 5.00), + ('inf', 3.27, 5.75), + ), + 'bi-weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.00, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'semi-monthly': ( + ( 21.00, 0.00, 1.00), + ( 62.50, 0.21, 2.00), + (104.00, 1.04, 3.00), + (146.00, 2.29, 4.00), + (208.00, 3.96, 5.00), + ( 'inf', 7.08, 5.75), + ), + 'monthly': ( + ( 41.50, 0.00, 1.00), + (125.50, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'quarterly': ( + ( 125.00, 0.00, 1.00), + ( 375.00, 1.25, 2.00), + ( 625.00, 6.25, 3.00), + ( 875.00, 13.75, 4.00), + (1250.00, 23.75, 5.00), + ( 'inf', 42.50, 5.75), + ), + 'semi-annual': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + }, + 'married filing joint, one spouse working': { + 'weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.50, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'bi-weekly': ( + ( 38.50, 0.00, 1.00), + (115.00, 0.38, 2.00), + (192.00, 1.92, 3.00), + (269.00, 4.23, 4.00), + (385.00, 7.31, 5.00), + ( 'inf', 13.08, 5.75), + ), + 'semi-monthly': ( + ( 41.50, 0.00, 1.00), + (125.00, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'monthly': ( + ( 83.00, 0.00, 1.00), + (250.00, 0.83, 2.00), + (417.00, 4.17, 3.00), + (583.00, 9.17, 4.00), + (833.00, 15.83, 5.00), + ( 'inf', 28.33, 5.75), + ), + 'quarterly': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'semi-annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + 'annual': ( + ( 1000.00, 0.00, 1.00), + ( 3000.00, 10.00, 2.00), + ( 5000.00, 50.00, 3.00), + ( 7000.00, 110.00, 4.00), + (10000.00, 190.00, 5.00), + ( 'inf', 340.00, 5.75), + ), + }, + 'single': { + 'weekly': ( + ( 14.50, 0.00, 1.00), + ( 43.50, 0.14, 2.00), + ( 72.00, 0.72, 3.00), + (101.00, 1.59, 4.00), + (135.00, 2.74, 5.00), + ( 'inf', 4.42, 5.75), + ), + 'bi-weekly': ( + ( 29.00, 0.00, 1.00), + ( 86.50, 0.29, 2.00), + (144.00, 1.44, 3.00), + (202.00, 3.17, 4.00), + (269.00, 5.48, 5.00), + ( 'inf', 8.85, 5.75), + ), + 'semi-monthly': ( + ( 31.00, 0.00, 1.00), + ( 93.50, 0.31, 2.00), + (156.00, 1.56, 3.00), + (219.00, 3.34, 4.00), + (292.00, 5.94, 5.00), + ( 'inf', 9.58, 5.75), + ), + 'monthly': ( + ( 62.50, 0.00, 1.00), + (187.00, 0.62, 2.00), + (312.00, 3.12, 3.00), + (437.00, 6.87, 4.00), + (583.00, 11.87, 5.00), + ( 'inf', 19.17, 5.75), + ), + 'quarterly': ( + ( 187.50, 0.00, 1.00), + ( 562.50, 1.88, 2.00), + ( 937.50, 9.38, 3.00), + (1312.00, 20.63, 4.00), + (1750.00, 35.63, 5.00), + ( 'inf', 57.50, 5.75), + ), + 'semi-annual': ( + ( 375.00, 0.00, 1.00), + (1125.00, 3.75, 2.00), + (1875.00, 18.75, 3.00), + (2625.00, 41.25, 4.00), + (3500.00, 71.25, 5.00), + ( 'inf', 115.00, 5.75), + ), + 'annual': ( + ( 750.00, 0.00, 1.00), + (2250.00, 7.50, 2.00), + (3750.00, 37.50, 3.00), + (5250.00, 82.50, 4.00), + (7000.00, 142.50, 5.00), + ( 'inf', 230.00, 5.75), + ), + }, + 'head of household': { + 'weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.50, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'bi-weekly': ( + ( 38.50, 0.00, 1.00), + (115.00, 0.38, 2.00), + (192.00, 1.92, 3.00), + (269.00, 4.23, 4.00), + (385.00, 7.31, 5.00), + ( 'inf', 13.08, 5.75), + ), + 'semi-monthly': ( + ( 41.50, 0.00, 1.00), + (125.00, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'monthly': ( + ( 83.00, 0.00, 1.00), + (250.00, 0.83, 2.00), + (417.00, 4.17, 3.00), + (583.00, 9.17, 4.00), + (833.00, 15.83, 5.00), + ( 'inf', 28.33, 5.75), + ), + 'quarterly': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'semi-annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + 'annual': ( + ( 1000.00, 0.00, 1.00), + ( 3000.00, 10.00, 2.00), + ( 5000.00, 50.00, 3.00), + ( 7000.00, 110.00, 4.00), + (10000.00, 190.00, 5.00), + ( 'inf', 340.00, 5.75), + ), + }, + 'married filing separate': { + 'weekly': ( + ( 9.50, 0.00, 1.00), + (29.00, 0.10, 2.00), + (48.00, 0.48, 3.00), + (67.50, 1.06, 4.00), + (96.00, 1.83, 5.00), + ('inf', 3.27, 5.75), + ), + 'bi-weekly': ( + ( 19.00, 0.00, 1.00), + ( 57.50, 0.19, 2.00), + ( 96.00, 0.96, 3.00), + (135.00, 2.12, 4.00), + (192.00, 3.65, 5.00), + ( 'inf', 6.54, 5.75), + ), + 'semi-monthly': ( + ( 21.00, 0.00, 1.00), + ( 62.50, 0.21, 2.00), + (104.00, 1.04, 3.00), + (146.00, 2.29, 4.00), + (208.00, 3.96, 5.00), + ( 'inf', 7.08, 5.75), + ), + 'monthly': ( + ( 41.50, 0.00, 1.00), + (125.50, 0.42, 2.00), + (208.00, 2.08, 3.00), + (292.00, 4.58, 4.00), + (417.00, 7.92, 5.00), + ( 'inf', 14.17, 5.75), + ), + 'quarterly': ( + ( 125.00, 0.00, 1.00), + ( 375.00, 1.25, 2.00), + ( 625.00, 6.25, 3.00), + ( 875.00, 13.75, 4.00), + (1250.00, 23.75, 5.00), + ( 'inf', 42.50, 5.75), + ), + 'semi-annual': ( + ( 250.00, 0.00, 1.00), + ( 750.00, 2.50, 2.00), + (1250.00, 12.50, 3.00), + (1750.00, 27.50, 4.00), + (2500.00, 47.50, 5.00), + ( 'inf', 85.00, 5.75), + ), + 'annual': ( + ( 500.00, 0.00, 1.00), + (1500.00, 5.00, 2.00), + (2500.00, 25.00, 3.00), + (3500.00, 55.00, 4.00), + (5000.00, 95.00, 5.00), + ( 'inf', 170.00, 5.75), + ), + }, + } + + + @@ -154,6 +697,59 @@ + + + + { + 'married filing joint, both spouses working': { + 'weekly': 142.30, + 'bi-weekly': 284.62, + 'semi-monthly': 308.33, + 'monthly': 616.67, + 'quarterly': 1850.00, + 'semi-annual': 3700.00, + 'annual': 7400.00, + }, + 'married filing joint, one spouse working': { + 'weekly': 142.30, + 'bi-weekly': 284.62, + 'semi-monthly': 308.33, + 'monthly': 616.67, + 'quarterly': 1850.00, + 'semi-annual': 3700.00, + 'annual': 7400.00, + }, + 'single': { + 'weekly': 51.92, + 'bi-weekly': 103.85, + 'semi-monthly': 112.50, + 'monthly': 225.00, + 'quarterly': 675.00, + 'semi-annual': 1350.00, + 'annual': 2700.00, + }, + 'head of household': { + 'weekly': 51.92, + 'bi-weekly': 103.85, + 'semi-monthly': 112.50, + 'monthly': 225.00, + 'quarterly': 675.00, + 'semi-annual': 1350.00, + 'annual': 2700.00, + }, + 'married filing separate': { + 'weekly': 71.15, + 'bi-weekly': 142.30, + 'semi-monthly': 154.16, + 'monthly': 308.33, + 'quarterly': 925.00, + 'semi-annual': 1850.00, + 'annual': 3700.00, + }, + } + + + @@ -175,6 +771,21 @@ + + + + { + 'weekly': 57.50, + 'bi-weekly': 115.00, + 'semi-monthly': 125.00, + 'monthly': 250.00, + 'quarterly': 750.00, + 'semi-annual': 1500.00, + 'annual': 3000.00, + } + + + @@ -234,6 +845,59 @@ + + + + { + 'married filing joint, both spouses working': { + 'weekly': 115.50, + 'bi-weekly': 230.75, + 'semi-monthly': 250.00, + 'monthly': 500.00, + 'quarterly': 1500.00, + 'semi-annual': 3000.00, + 'annual': 6000.00, + }, + 'married filing joint, one spouse working': { + 'weekly': 115.50, + 'bi-weekly': 230.75, + 'semi-monthly': 250.00, + 'monthly': 500.00, + 'quarterly': 1500.00, + 'semi-annual': 3000.00, + 'annual': 6000.00, + }, + 'single': { + 'weekly': 88.50, + 'bi-weekly': 177.00, + 'semi-monthly': 191.75, + 'monthly': 383.50, + 'quarterly': 1150.00, + 'semi-annual': 2300.00, + 'annual': 4600.00, + }, + 'head of household': { + 'weekly': 88.50, + 'bi-weekly': 177.00, + 'semi-monthly': 191.75, + 'monthly': 383.50, + 'quarterly': 1150.00, + 'semi-annual': 2300.00, + 'annual': 4600.00, + }, + 'married filing separate': { + 'weekly': 57.75, + 'bi-weekly': 115.50, + 'semi-monthly': 125.00, + 'monthly': 250.00, + 'quarterly': 750.00, + 'semi-annual': 1500.00, + 'annual': 3000.00, + }, + } + + + diff --git a/l10n_us_hr_payroll/models/state/ga_georgia.py b/l10n_us_hr_payroll/models/state/ga_georgia.py index 66503e35..77fb0044 100644 --- a/l10n_us_hr_payroll/models/state/ga_georgia.py +++ b/l10n_us_hr_payroll/models/state/ga_georgia.py @@ -13,7 +13,7 @@ def ga_georgia_state_income_withholding(payslip, categories, worked_days, inputs if not _state_applies(payslip, state_code): return 0.0, 0.0 ga_filing_status = payslip.contract_id.us_payroll_config_value('ga_g4_sit_filing_status') - if not ga_filing_status or ga_filing_status == 'exempt': + if not ga_filing_status: return 0.0, 0.0 # Determine Wage diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py index 74bf4915..6687cbeb 100644 --- a/l10n_us_hr_payroll/models/us_payroll_config.py +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -92,7 +92,7 @@ class HRContractUSPayrollConfig(models.Model): de_w4_sit_dependent = fields.Integer(string='Delaware W-4 Dependents', help='DE W-4 4.') ga_g4_sit_filing_status = fields.Selection([ - ('exempt', 'Exempt'), + ('', 'Exempt'), ('single', 'Single'), ('married filing joint, both spouses working', 'Married Filing Joint, both spouses working'), ('married filing joint, one spouse working', 'Married Filing Joint, one spouse working'), diff --git a/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2020.py index 6debc2ca..21a0a810 100755 --- a/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2020.py @@ -1,7 +1,7 @@ # Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. -from datetime import date -from .common import TestUsPayslip, process_payslip +from datetime import date, timedelta +from .common import TestUsPayslip class TestUsGAPayslip(TestUsPayslip): @@ -10,139 +10,30 @@ class TestUsGAPayslip(TestUsPayslip): GA_UNEMP_MAX_WAGE = 9500.00 GA_UNEMP = 2.70 - def _run_test_sit(self, - wage=0.0, - schedule_pay='monthly', - filing_status='single', - dependent_credit=0.0, - other_income=0.0, - deductions=0.0, - additional_withholding=0.0, - is_nonresident_alien=False, - state_income_tax_exempt=False, - state_income_tax_additional_withholding=0.0, - ga_g4_sit_dependent_allowances=0, - ga_g4_sit_additional_allowances=0, - ga_g4_sit_filing_status=None, - expected=0.0, - ): + # Example calculated based on https://dor.georgia.gov/employers-tax-guide 2020_employer tax gauide + + def _test_sit(self, wage, filing_status, additional_withholding, dependent_allowances, additional_allowances, + schedule_pay, date_start, expected_withholding): employee = self._createEmployee() contract = self._createContract(employee, wage=wage, - schedule_pay=schedule_pay, - fed_941_fit_w4_is_nonresident_alien=is_nonresident_alien, - fed_941_fit_w4_filing_status=filing_status, - fed_941_fit_w4_multiple_jobs_higher=False, - fed_941_fit_w4_dependent_credit=dependent_credit, - fed_941_fit_w4_other_income=other_income, - fed_941_fit_w4_deductions=deductions, - fed_941_fit_w4_additional_withholding=additional_withholding, - state_income_tax_exempt=state_income_tax_exempt, - state_income_tax_additional_withholding=state_income_tax_additional_withholding, - ga_g4_sit_dependent_allowances=ga_g4_sit_dependent_allowances, - ga_g4_sit_additional_allowances=ga_g4_sit_additional_allowances, - ga_g4_sit_filing_status=ga_g4_sit_filing_status, state_id=self.get_us_state('GA'), - ) - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') + ga_g4_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, + ga_g4_sit_dependent_allowances=dependent_allowances, + ga_g4_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) - # Instead of PayrollEqual after initial first round of testing. - self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected) - return payslip - def test_taxes_weekly_single_with_additional_wh(self): + self._log('Computed period tax: ' + str(expected_withholding)) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + + def test_2020_taxes_example(self): self._test_er_suta('GA', self.GA_UNEMP, date(2020, 1, 1), wage_base=self.GA_UNEMP_MAX_WAGE) - salary = 15000.00 - schedule_pay = 'weekly' - allowances = 1 - filing_status = 'single' - additional_wh = 12.50 - # Hand Calculated Amount to Test - # Step 1 - Subtract standard deduction from wages. Std Deduct for single weekly is 88.50 - # step1 = 15000.00 - 88.50 = 14911.5 - # Step 2 - Subtract personal allowance from step1. Allowance for single weekly is 51.92 - # step2 = step1 - 51.92 = 14859.58 - # Step 3 - Subtract amount for dependents. Weekly dependent allowance is 57.50 - # step3 = 14859.58 - 57.50 = 14802.08 - # Step 4 -Determine wh amount from tables - # step4 = 4.42 + ((5.75 / 100.00) * (14802.08 - 135.00)) - # Add additional_wh - # wh = 847.7771 + 12.50 = 860.2771 - wh = 860.28 - - self._run_test_sit(wage=salary, - schedule_pay=schedule_pay, - state_income_tax_additional_withholding=additional_wh, - ga_g4_sit_dependent_allowances=allowances, - ga_g4_sit_additional_allowances=0, - ga_g4_sit_filing_status=filing_status, - expected=wh, - ) - - - def test_taxes_monthly_head_of_household(self): - salary = 25000.00 - schedule_pay = 'monthly' - allowances = 2 - filing_status = 'head of household' - additional_wh = 15.00 - # Hand Calculated Amount to Test - # Step 1 - Subtract standard deduction from wages. Std Deduct for head of household monthly is 383.50 - # step1 = 25000.00 - 383.50 = 24616.5 - # Step 2 - Subtract personal allowance from step1. Allowance for head of household monthly is 225.00 - # step2 = 24616.5 - 225.00 = 24391.5 - # Step 3 - Subtract amount for dependents. Weekly dependent allowance is 250.00 - # step3 = 24391.5 - (2 * 250.00) = 23891.5 - # Step 4 - Determine wh amount from tables - # step4 = 28.33 + ((5.75 / 100.00) * (23891.5 - 833.00)) = 1354.19375 - # Add additional_wh - # wh = 1354.19375 + 15.00 = 1369.19375 - wh = 1369.19 - - self._run_test_sit(wage=salary, - schedule_pay=schedule_pay, - state_income_tax_additional_withholding=additional_wh, - ga_g4_sit_dependent_allowances=allowances, - ga_g4_sit_additional_allowances=0, - ga_g4_sit_filing_status=filing_status, - expected=wh, - ) - - # additional from external calculator - self._run_test_sit(wage=425.0, - schedule_pay='weekly', - state_income_tax_additional_withholding=0.0, - ga_g4_sit_dependent_allowances=1, - ga_g4_sit_additional_allowances=0, - ga_g4_sit_filing_status='married filing separate', - expected=11.45, - ) - - self._run_test_sit(wage=3000.0, - schedule_pay='quarterly', - state_income_tax_additional_withholding=0.0, - ga_g4_sit_dependent_allowances=1, - ga_g4_sit_additional_allowances=1, - ga_g4_sit_filing_status='single', - expected=0.0, - ) - - # TODO 'married filing joint, both spouses working' returns lower than calculator - # TODO 'married filing joint, one spouse working' returns lower than calculator - - def test_taxes_exempt(self): - salary = 25000.00 - schedule_pay = 'monthly' - allowances = 2 - filing_status = 'exempt' - additional_wh = 15.00 - - self._run_test_sit(wage=salary, - schedule_pay=schedule_pay, - state_income_tax_additional_withholding=additional_wh, - ga_g4_sit_dependent_allowances=allowances, - ga_g4_sit_additional_allowances=0, - ga_g4_sit_filing_status=filing_status, - expected=0.0, - ) + self._test_sit(15000.0, 'single', 12.50, 1, 0, 'weekly', date(2020, 1, 1), 860.28) + self._test_sit(25000.0, 'head of household', 15.00, 2, 0, 'monthly', date(2020, 1, 1), 1369.19) + self._test_sit(425.0, 'married filing separate', 0.0, 1, 0, 'weekly', date(2020, 1, 1), 11.45) + self._test_sit(3000.0, 'single', 0.00, 1, 1, 'quarterly', date(2020, 1, 1), 0.0) + self._test_sit(2500.0, '', 0.00, 1, 1, 'quarterly', date(2020, 1, 1), 0.0) From 383a1e8f6c121d7ae47ea3dd115ef5172c7c9905 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Thu, 20 Aug 2020 18:51:17 -0400 Subject: [PATCH 49/63] [IMP] l10n_us_hr_payroll: Improved Tax table and Test case for HI Hawaii 2020 --- l10n_us_hr_payroll/data/state/hi_hawaii.xml | 68 +++++++++++++++++-- .../tests/test_us_hi_hawaii_payslip_2020.py | 2 + 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/hi_hawaii.xml b/l10n_us_hr_payroll/data/state/hi_hawaii.xml index 862ca102..798821f2 100644 --- a/l10n_us_hr_payroll/data/state/hi_hawaii.xml +++ b/l10n_us_hr_payroll/data/state/hi_hawaii.xml @@ -46,18 +46,74 @@ { - 'single': ((2400, 0.00, 1.40), (4800, 34.00, 3.20), (9600, 110.00, 5.50), (14400, 374.00, 6.40), (19200, 682.00, 6.80), (24000, 1008.00, 7.20), (36000, 1354.00, 7.60), ('inf', 2266.00, 7.90)), - 'married': ((4800, 0.00, 1.40), (9600, 67.00, 3.20), (19200, 221.00, 5.50), (28800, 749.00, 6.40), (38400, 1363.00, 6.80), (48000, 2016.00, 7.20), (72000, 2707.00, 7.60), ('inf', 4531.00, 7.90)), - 'head_of_household': ((2400, 0.00, 1.40), (4800, 34.00, 3.20), (9600, 110.00, 5.50), (14400, 374.00, 6.40), (19200, 682.00, 6.80), (24000, 1008.00, 7.20), (36000, 1354.00, 7.60), ('inf', 2266.00, 7.90)), + 'single': ( + ( 2400, 0.00, 1.40), + ( 4800, 34.00, 3.20), + ( 9600, 110.00, 5.50), + (14400, 374.00, 6.40), + (19200, 682.00, 6.80), + (24000, 1008.00, 7.20), + (36000, 1354.00, 7.60), + ('inf', 2266.00, 7.90), + ), + 'married': ( + ( 4800, 0.00, 1.40), + ( 9600, 67.00, 3.20), + (19200, 221.00, 5.50), + (28800, 749.00, 6.40), + (38400, 1363.00, 6.80), + (48000, 2016.00, 7.20), + (72000, 2707.00, 7.60), + ('inf', 4531.00, 7.90), + ), + 'head_of_household': ( + ( 2400, 0.00, 1.40), + ( 4800, 34.00, 3.20), + ( 9600, 110.00, 5.50), + (14400, 374.00, 6.40), + (19200, 682.00, 6.80), + (24000, 1008.00, 7.20), + (36000, 1354.00, 7.60), + ('inf', 2266.00, 7.90), + ), } + + { - 'single': ((2400, 0.00, 1.40), (4800, 34.00, 3.20), (9600, 110.00, 5.50), (14400, 374.00, 6.40), (19200, 682.00, 6.80), (24000, 1008.00, 7.20), (36000, 1354.00, 7.60), ('inf', 2266.00, 7.90)), - 'married': ((4800, 0.00, 1.40), (9600, 67.00, 3.20), (19200, 221.00, 5.50), (28800, 749.00, 6.40), (38400, 1363.00, 6.80), (48000, 2016.00, 7.20), (72000, 2707.00, 7.60), ('inf', 4531.00, 7.90)), - 'head_of_household': ((2400, 0.00, 1.40), (4800, 34.00, 3.20), (9600, 110.00, 5.50), (14400, 374.00, 6.40), (19200, 682.00, 6.80), (24000, 1008.00, 7.20), (36000, 1354.00, 7.60), ('inf', 2266.00, 7.90)), + 'single': ( + ( 2400, 0.00, 1.40), + ( 4800, 34.00, 3.20), + ( 9600, 110.00, 5.50), + (14400, 374.00, 6.40), + (19200, 682.00, 6.80), + (24000, 1008.00, 7.20), + (36000, 1354.00, 7.60), + ('inf', 2266.00, 7.90), + ), + 'married': ( + ( 4800, 0.00, 1.40), + ( 9600, 67.00, 3.20), + (19200, 221.00, 5.50), + (28800, 749.00, 6.40), + (38400, 1363.00, 6.80), + (48000, 2016.00, 7.20), + (72000, 2707.00, 7.60), + ('inf', 4531.00, 7.90), + ), + 'head_of_household': ( + ( 2400, 0.00, 1.40), + ( 4800, 34.00, 3.20), + ( 9600, 110.00, 5.50), + (14400, 374.00, 6.40), + (19200, 682.00, 6.80), + (24000, 1008.00, 7.20), + (36000, 1354.00, 7.60), + ('inf', 2266.00, 7.90), + ), } diff --git a/l10n_us_hr_payroll/tests/test_us_hi_hawaii_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_hi_hawaii_payslip_2020.py index 9684c52d..9a746057 100755 --- a/l10n_us_hr_payroll/tests/test_us_hi_hawaii_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_hi_hawaii_payslip_2020.py @@ -33,3 +33,5 @@ class TestUsHIPayslip(TestUsPayslip): self._test_sit(5000.0, 'married', 0.0, 2.0, 'monthly', date(2020, 1, 1), 287.1) self._test_sit(5000.0, 'married', 10.0, 2.0, 'monthly', date(2020, 1, 1), 297.1) self._test_sit(50000.0, 'head_of_household', 0.0, 3.0, 'weekly', date(2020, 1, 1), 3933.65) + self._test_sit(750.0, 'single', 10.0, 3.0, 'bi-weekly', date(2020, 1, 1), 40.59) + self._test_sit(3000.0, '', 0.0, 3.0, 'weekly', date(2020, 1, 1), 0.00) From dfe3fa8f13d2e01f29865acc6cb2e9a7c53df985 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 11:32:35 -0400 Subject: [PATCH 50/63] [IMP] l10n_us_hr_payroll: Reformat tax table, improved comments and test case for IA Iowa 2020 --- l10n_us_hr_payroll/data/state/ia_iowa.xml | 150 ++++++++++++++++-- l10n_us_hr_payroll/models/state/ia_iowa.py | 6 +- .../tests/test_us_ia_iowa_payslip_2020.py | 13 +- 3 files changed, 151 insertions(+), 18 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ia_iowa.xml b/l10n_us_hr_payroll/data/state/ia_iowa.xml index 6a7d060d..dcc90009 100644 --- a/l10n_us_hr_payroll/data/state/ia_iowa.xml +++ b/l10n_us_hr_payroll/data/state/ia_iowa.xml @@ -46,24 +46,146 @@ { - 'daily': [(5.13, 0.0033, 0.0), (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.0), (51.27, 0.0067, 0.08), (102.52, 0.0225, 0.025), (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.00225, 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)], + '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), + ), } + + { - 'daily': [(5.69, 0.0033, 0.0), (11.38, 0.0067, 0.02), (22.76, 0.0225, 0.06), (51.22, 0.0414, 0.32), (85.36, 0.0563, 1.50), (113.81, 0.0596, 3.42), (170.71, 0.0625, 5.12), (256.07, 0.0744, 8.68), ('inf', 0.0853, 15.03)], - 'weekly': [(28.46, 0.0033, 0.0), (56.90, 0.0067, 0.09), (113.81, 0.0225, 0.028), (256.08, 0.0414, 1.56), (426.79, 0.0563, 7.45), (569.04, 0.0596, 17.06), (853.56, 0.0625, 25.54), (1280.35, 0.0744, 43.32), ('inf', 0.0853, 75.07)], - 'bi-weekly': [(56.92, 0.0033, 0.00), (113.81, 0.0067, 0.19), (227.62, 0.00225, 0.57), (512.15, 0.0414, 3.13), (853.58, 0.0563, 14.91), (1138.08, 0.0596, 34.13), (1707.12, 0.0625, 51.09), (2560.69, 0.0744, 86.66), ('inf', 0.0853, 150.17)], - 'semi-monthly': [(61.67, 0.0033, 0.00), (123.29, 0.0067, 0.20), (246.58, 0.0225, 0.61), (554.83, 0.0414, 3.38), (924.71, 0.0563, 16.14), (1232.92, 0.0596, 36.96), (1849.38, 0.0625, 55.33), (2774.08, 0.0744, 93.86), ('inf', 0.0853, 162.66)], - 'monthly': [(123.33, 0.0033, 0.00), (246.58, 0.0067, 0.41), (493.17, 0.0225, 1.24), (1109.67, 0.0414, 6.79), (1849.42, 0.0563, 32.31), (2465.83, 0.0596, 73.96), (3698.75, 0.0625, 110.70), (5548.17, 0.0744, 187.76), ('inf', 0.0853, 325.36)], - 'annual': [(1480.00, 0.0033, 0.00), (2959.00, 0.0067, 4.88), (5918.00, 0.0225, 14.79), (13316.00, 0.0414, 81.37), (22193.00, 0.0563, 387.65), (29590.00, 0.0596, 887.43), (44385.00, 0.0625, 1328.29), (66578.00, 0.0744, 2252.98), ('inf', 0.0853, 3904.14)], + 'daily': ( + ( 5.69, 0.0033, 0.00), + ( 11.38, 0.0067, 0.02), + ( 22.76, 0.0225, 0.06), + ( 51.22, 0.0414, 0.32), + ( 85.36, 0.0563, 1.50), + (113.81, 0.0596, 3.42), + (170.71, 0.0625, 5.12), + (256.07, 0.0744, 8.68), + ( 'inf', 0.0853, 15.03), + ), + 'weekly': ( + ( 28.46, 0.0033, 0.00), + ( 56.90, 0.0067, 0.09), + ( 113.81, 0.0225, 0.28), + ( 256.08, 0.0414, 1.56), + ( 426.79, 0.0563, 7.45), + ( 569.04, 0.0596, 17.06), + ( 853.56, 0.0625, 25.54), + (1280.35, 0.0744, 43.32), + ( 'inf', 0.0853, 75.07), + ), + 'bi-weekly': ( + ( 56.92, 0.0033, 0.00), + ( 113.81, 0.0067, 0.19), + ( 227.62, 0.0225, 0.57), + ( 512.15, 0.0414, 3.13), + ( 853.58, 0.0563, 14.91), + (1138.08, 0.0596, 34.13), + (1707.12, 0.0625, 51.09), + (2560.69, 0.0744, 86.66), + ( 'inf', 0.0853, 150.17), + ), + 'semi-monthly': ( + ( 61.67, 0.0033, 0.00), + ( 23.29, 0.0067, 0.20), + ( 246.58, 0.0225, 0.61), + ( 554.83, 0.0414, 3.38), + ( 924.71, 0.0563, 16.14), + (1232.92, 0.0596, 36.96), + (1849.38, 0.0625, 55.33), + (2774.08, 0.0744, 93.86), + ( 'inf', 0.0853, 162.66), + ), + 'monthly': ( + ( 123.33, 0.0033, 0.00), + ( 246.58, 0.0067, 0.41), + ( 493.17, 0.0225, 1.24), + (1109.67, 0.0414, 6.79), + (1849.42, 0.0563, 32.31), + (2465.83, 0.0596, 73.96), + (3698.75, 0.0625, 110.70), + (5548.17, 0.0744, 187.76), + ( 'inf', 0.0853, 325.36), + ), + 'annual': ( + ( 1480.00, 0.0033, 0.00), + ( 2959.00, 0.0067, 4.88), + ( 5918.00, 0.0225, 14.79), + (13316.00, 0.0414, 81.37), + (22193.00, 0.0563, 387.65), + (29590.00, 0.0596, 887.43), + (44385.00, 0.0625, 1328.29), + (66578.00, 0.0744, 2252.98), + ( 'inf', 0.0853, 3904.14), + ), } @@ -88,6 +210,8 @@ + + { 'daily': ( 7.23, 17.81), @@ -120,6 +244,8 @@ + + { 'daily': 0.15, diff --git a/l10n_us_hr_payroll/models/state/ia_iowa.py b/l10n_us_hr_payroll/models/state/ia_iowa.py index d12adc64..9bb9ac9d 100644 --- a/l10n_us_hr_payroll/models/state/ia_iowa.py +++ b/l10n_us_hr_payroll/models/state/ia_iowa.py @@ -13,6 +13,9 @@ def ia_iowa_state_income_withholding(payslip, categories, worked_days, inputs): if not _state_applies(payslip, state_code): return 0.0, 0.0 + if payslip.contract_id.us_payroll_config_value('state_income_tax_exempt'): + return 0.0, 0.0 + # Determine Wage wage = sit_wage(payslip, categories) if not wage: @@ -27,7 +30,8 @@ def ia_iowa_state_income_withholding(payslip, categories, worked_days, inputs): deduction_per_allowance = payslip.rule_parameter('us_ia_sit_deduction_allowance_rate')[schedule_pay] t1 = wage + fed_withholding - t2 = t1 - standard_deduction[0] if allowances < 2 else standard_deduction[1] + standard_deduction_amt = standard_deduction[0] if allowances < 2 else standard_deduction[1] + t2 = t1 - standard_deduction_amt t3 = 0.0 last = 0.0 for row in tax_table: diff --git a/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2020.py index d5d66b16..eaca0e71 100755 --- a/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ia_iowa_payslip_2020.py @@ -11,11 +11,12 @@ class TestUsIAPayslip(TestUsPayslip): IA_UNEMP_MAX_WAGE = 31600.00 IA_UNEMP = 1.0 - def _test_sit(self, wage, additional_withholding, allowances, schedule_pay, date_start, expected_withholding): + 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) @@ -24,10 +25,12 @@ class TestUsIAPayslip(TestUsPayslip): cats = self._getCategories(payslip) self._log('Computed period tax: ' + str(expected_withholding)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) def test_2020_taxes_example(self): self._test_er_suta('IA', self.IA_UNEMP, date(2020, 1, 1), wage_base=self.IA_UNEMP_MAX_WAGE) - self._test_sit(3000.0, 0.0, 1.0, 'bi-weekly', date(2020, 1, 1), 146.68) - self._test_sit(3000.0, 10.0, 1.0, 'bi-weekly', date(2020, 1, 1), 156.68) - self._test_sit(30000.0, 0.0, 1.0, 'weekly', date(2020, 1, 1), 1640.04) + self._test_sit(2100.0, False, 0.0, 3.0, 'bi-weekly', date(2020, 1, 1), 83.5) + self._test_sit(3000.0, True, 10.0, 1.0, 'bi-weekly', date(2020, 1, 1), 0.00) + self._test_sit(300.0, False, 0.0, 1.0, 'weekly', date(2020, 1, 1), 6.77) + self._test_sit(5000.0, False, 0.0, 1.0, 'monthly', date(2020, 1, 1), 230.76) + self._test_sit(7500.0, False, 10.0, 2.0, 'semi-monthly', date(2020, 1, 1), 432.84) From 4e7eecee52bee489f1cbdcbd91f5f0598862c7d0 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 12:31:02 -0400 Subject: [PATCH 51/63] [IMP] l10n_us_hr_payroll: Added Tax table and improved Test case for KY Kentucky 2020 --- l10n_us_hr_payroll/data/state/ky_kentucky.xml | 2 ++ l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/l10n_us_hr_payroll/data/state/ky_kentucky.xml b/l10n_us_hr_payroll/data/state/ky_kentucky.xml index d596bb10..bcdd2274 100644 --- a/l10n_us_hr_payroll/data/state/ky_kentucky.xml +++ b/l10n_us_hr_payroll/data/state/ky_kentucky.xml @@ -34,6 +34,7 @@ + 2650 @@ -46,6 +47,7 @@ us_ky_sit_tax_rate + 5.0 diff --git a/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py index 4e652898..aa067848 100755 --- a/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ky_kentucky_payslip_2020.py @@ -31,3 +31,5 @@ class TestUsKYPayslip(TestUsPayslip): self._test_sit(3020, 0.0, 'monthly', date(2020, 1, 1), 139.96) self._test_sit(1500, 0.0, 'bi-weekly', date(2020, 1, 1), 69.90) self._test_sit(1500, 10.0, 'bi-weekly', date(2020, 1, 1), 79.90) + self._test_sit(750, 00.0, 'weekly', date(2020, 1, 1), 34.95) + self._test_sit(7000, 0.0, 'semi-monthly', date(2020, 1, 1), 344.48) From 2f5503c0daa7ad7307a1441ff0f99fe24b887678 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 14:36:05 -0400 Subject: [PATCH 52/63] [IMP] l10n_us_hr_payroll: Added Tax table and improved Test case for ID Idaho 2020 --- l10n_us_hr_payroll/data/state/id_idaho.xml | 334 ++++++++++++++++-- .../tests/test_us_id_idaho_payslip_2020.py | 2 +- 2 files changed, 305 insertions(+), 31 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/id_idaho.xml b/l10n_us_hr_payroll/data/state/id_idaho.xml index ef908d13..46dcce9d 100644 --- a/l10n_us_hr_payroll/data/state/id_idaho.xml +++ b/l10n_us_hr_payroll/data/state/id_idaho.xml @@ -47,52 +47,324 @@ { 'single': { - 'weekly': ((235, 0.00, 0.00), (264, 0.00, 1.125), (294, 0.00, 3.125), (324, 1.00, 3.625), (353, 2.00, 4.625), (383, 4.00, 5.625), (457, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 1.00, 3.125), (647, 3.00, 3.625), (706, 5.00, 4.625), (766, 7.00, 5.625), (914, 11.00, 6.625), ('inf', 21.00, 6.925)), - 'semi-monthly': ((508, 0.00, 0.00), (573, 0.00, 1.125), (637, 1.00, 3.125), (701, 3.00, 3.625), (765, 5.00, 4.625), (829, 8.00, 5.625), (990, 12.00, 6.625), ('inf', 22.00, 6.925)), - 'monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'annually': ((12200, 0.00, 0.00), (13741, 0.00, 1.125), (15281, 17.00, 3.125), (16822, 65.00, 3.625), (18362, 121.00, 4.625), (19903, 192.00, 5.625), (23754, 279.00, 6.625), ('inf', 534.00, 6.925)), + 'weekly': ( + ( 235, 0.00, 0.000), + ( 264, 0.00, 1.125), + ( 294, 0.00, 3.125), + ( 324, 1.00, 3.625), + ( 353, 2.00, 4.625), + ( 383, 4.00, 5.625), + ( 457, 5.00, 6.625), + ('inf', 10.00, 6.925), + ), + 'bi-weekly': ( + ( 469, 0.00, 0.000), + ( 529, 0.00, 1.125), + ( 588, 1.00, 3.125), + ( 647, 3.00, 3.625), + ( 706, 5.00, 4.625), + ( 766, 7.00, 5.625), + ( 914, 11.00, 6.625), + ('inf', 21.00, 6.925), + ), + 'semi-monthly': ( + ( 508, 0.00, 0.000), + ( 573, 0.00, 1.125), + ( 637, 1.00, 3.125), + ( 701, 3.00, 3.625), + ( 765, 5.00, 4.625), + ( 829, 8.00, 5.625), + ( 990, 12.00, 6.625), + ('inf', 22.00, 6.925), + ), + 'monthly': ( + ( 1017, 0.00, 0.000), + ( 1145, 0.00, 1.125), + ( 1273, 1.00, 3.125), + ( 1402, 5.00, 3.625), + ( 1530, 10.00, 4.625), + ( 1659, 16.00, 5.625), + ( 1980, 23.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'annually': ( + (12200, 0.00, 0.000), + (13741, 0.00, 1.125), + (15281, 17.00, 3.125), + (16822, 65.00, 3.625), + (18362, 121.00, 4.625), + (19903, 192.00, 5.625), + (23754, 279.00, 6.625), + ('inf', 534.00, 6.925), + ), }, 'married': { - 'weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 0.00, 3.125), (647, 1.00, 3.625), (706, 2.00, 4.625), (766, 4.00, 5.625), (914, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((938, 0.00, 0.00), (1057, 0.00, 1.125), (1175, 1.00, 3.125), (1294, 5.00, 3.625), (1412, 9.00, 4.625), (1531, 15.00, 5.625), (1827, 21.00, 6.625), ('inf', 41.00, 6.925)), - 'semi-monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'monthly': ((2033, 0.00, 0.00), (2290, 0.00, 1.125), (2547, 3.00, 3.125), (2804, 11.00, 3.625), (3060, 20.00, 4.625), (3317, 32.00, 5.625), (3959, 47.00, 6.625), ('inf', 89.00, 6.925)), - 'annually': ((24400, 0.00, 0.00), (27482, 0.00, 1.125), (30562, 35.00, 3.125), (33644, 131.00, 3.625), (36724, 243.00, 4.625), (39806, 385.00, 5.625), (47508, 558.00, 6.625), ('inf', 1068.00, 6.925)), + 'weekly': ( + ( 469, 0.00, 0.000), + ( 529, 0.00, 1.125), + ( 588, 0.00, 3.125), + ( 647, 1.00, 3.625), + ( 706, 2.00, 4.625), + ( 766, 4.00, 5.625), + ( 914, 5.00, 6.625), + ('inf', 10.00, 6.925), + ), + 'bi-weekly': ( + ( 938, 0.00, 0.000), + ( 1057, 0.00, 1.125), + ( 1175, 1.00, 3.125), + ( 1294, 5.00, 3.625), + ( 1412, 9.00, 4.625), + ( 1531, 15.00, 5.625), + ( 1827, 21.00, 6.625), + ('inf', 41.00, 6.925), + ), + 'semi-monthly': ( + ( 1017, 0.00, 0.000), + ( 1145, 0.00, 1.125), + ( 1273, 1.00, 3.125), + ( 1402, 5.00, 3.625), + ( 1530, 10.00, 4.625), + ( 1659, 16.00, 5.625), + ( 1980, 23.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'monthly': ( + ( 2033, 0.00, 0.000), + ( 2290, 0.00, 1.125), + ( 2547, 3.00, 3.125), + ( 2804, 11.00, 3.625), + ( 3060, 20.00, 4.625), + ( 3317, 32.00, 5.625), + ( 3959, 47.00, 6.625), + ('inf', 89.00, 6.925), + ), + 'annually': ( + (24400, 0.00, 0.000), + (27482, 0.00, 1.125), + (30562, 35.00, 3.125), + (33644, 131.00, 3.625), + (36724, 243.00, 4.625), + (39806, 385.00, 5.625), + (47508, 558.00, 6.625), + ('inf', 1068.00, 6.925), + ), }, 'head of household': { - 'weekly': ((235, 0.00, 0.00), (264, 0.00, 1.125), (294, 0.00, 3.125), (324, 1.00, 3.625), (353, 2.00, 4.625), (383, 4.00, 5.625), (457, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 1.00, 3.125), (647, 3.00, 3.625), (706, 5.00, 4.625), (766, 7.00, 5.625), (914, 11.00, 6.625), ('inf', 21.00, 6.925)), - 'semi-monthly': ((508, 0.00, 0.00), (573, 0.00, 1.125), (637, 1.00, 3.125), (701, 3.00, 3.625), (765, 5.00, 4.625), (829, 8.00, 5.625), (990, 12.00, 6.625), ('inf', 22.00, 6.925)), - 'monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'annually': ((12200, 0.00, 0.00), (13741, 0.00, 1.125), (15281, 17.00, 3.125), (16822, 65.00, 3.625), (18362, 121.00, 4.625), (19903, 192.00, 5.625), (23754, 279.00, 6.625), ('inf', 534.00, 6.925)), + 'weekly': ( + ( 235, 0.00, 0.000), + ( 264, 0.00, 1.125), + ( 294, 0.00, 3.125), + ( 324, 1.00, 3.625), + ( 353, 2.00, 4.625), + ( 383, 4.00, 5.625), + ( 457, 5.00, 6.625), + ('inf', 10.00, 6.925), + ), + 'bi-weekly': ( + ( 469, 0.00, 0.000), + ( 529, 0.00, 1.125), + ( 588, 1.00, 3.125), + ( 647, 3.00, 3.625), + ( 706, 5.00, 4.625), + ( 766, 7.00, 5.625), + ( 914, 11.00, 6.625), + ('inf', 21.00, 6.925), + ), + 'semi-monthly': ( + ( 508, 0.00, 0.000), + ( 573, 0.00, 1.125), + ( 637, 1.00, 3.125), + ( 701, 3.00, 3.625), + ( 765, 5.00, 4.625), + ( 829, 8.00, 5.625), + ( 990, 12.00, 6.625), + ('inf', 22.00, 6.925), + ), + 'monthly': ( + ( 1017, 0.00, 0.000), + ( 1145, 0.00, 1.125), + ( 1273, 1.00, 3.125), + ( 1402, 5.00, 3.625), + ( 1530, 10.00, 4.625), + ( 1659, 16.00, 5.625), + ( 1980, 23.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'annually': ( + (12200, 0.00, 0.000), + (13741, 0.00, 1.125), + (15281, 17.00, 3.125), + (16822, 65.00, 3.625), + (18362, 121.00, 4.625), + (19903, 192.00, 5.625), + (23754, 279.00, 6.625), + ('inf', 534.00, 6.925), + ), }, } + + { 'single': { - 'weekly': ((235, 0.00, 0.00), (264, 0.00, 1.125), (294, 0.00, 3.125), (324, 1.00, 3.625), (353, 2.00, 4.625), (383, 4.00, 5.625), (457, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 1.00, 3.125), (647, 3.00, 3.625), (706, 5.00, 4.625), (766, 7.00, 5.625), (914, 11.00, 6.625), ('inf', 21.00, 6.925)), - 'semi-monthly': ((508, 0.00, 0.00), (573, 0.00, 1.125), (637, 1.00, 3.125), (701, 3.00, 3.625), (765, 5.00, 4.625), (829, 8.00, 5.625), (990, 12.00, 6.625), ('inf', 22.00, 6.925)), - 'monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'annually': ((12200, 0.00, 0.00), (13741, 0.00, 1.125), (15281, 17.00, 3.125), (16822, 65.00, 3.625), (18362, 121.00, 4.625), (19903, 192.00, 5.625), (23754, 279.00, 6.625), ('inf', 534.00, 6.925)), + 'weekly': ( + ( 238, 0.00, 0.000), + ( 269, 0.00, 1.125), + ( 299, 0.00, 3.125), + ( 329, 1.00, 3.625), + ( 359, 2.00, 4.625), + ( 389, 4.00, 5.625), + ( 465, 5.00, 6.625), + ('inf', 10.00, 6.925), + ), + 'bi-weekly': ( + ( 477, 0.00, 0.000), + ( 537, 0.00, 1.125), + ( 598, 1.00, 3.125), + ( 658, 3.00, 3.625), + ( 718, 5.00, 4.625), + ( 778, 8.00, 5.625), + ( 929, 11.00, 6.625), + ('inf', 21.00, 6.925), + ), + 'semi-monthly': ( + ( 517, 0.00, 0.000), + ( 582, 0.00, 1.125), + ( 647, 1.00, 3.125), + ( 713, 3.00, 3.625), + ( 778, 5.00, 4.625), + ( 843, 8.00, 5.625), + ( 1007, 12.00, 6.625), + ('inf', 23.00, 6.925), + ), + 'monthly': ( + ( 1033, 0.00, 0.000), + ( 1164, 0.00, 1.125), + ( 1295, 1.00, 3.125), + ( 1425, 6.00, 3.625), + ( 1556, 10.00, 4.625), + ( 1687, 16.00, 5.625), + ( 2013, 24.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'annually': ( + (12400, 0.00, 0.000), + (13968, 0.00, 1.125), + (15536, 18.00, 3.125), + (17104, 67.00, 3.625), + (18672, 124.00, 4.625), + (20240, 197.00, 5.625), + (24160, 285.00, 6.625), + ('inf', 545.00, 6.925), + ), }, 'married': { - 'weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 0.00, 3.125), (647, 1.00, 3.625), (706, 2.00, 4.625), (766, 4.00, 5.625), (914, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((938, 0.00, 0.00), (1057, 0.00, 1.125), (1175, 1.00, 3.125), (1294, 5.00, 3.625), (1412, 9.00, 4.625), (1531, 15.00, 5.625), (1827, 21.00, 6.625), ('inf', 41.00, 6.925)), - 'semi-monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'monthly': ((2033, 0.00, 0.00), (2290, 0.00, 1.125), (2547, 3.00, 3.125), (2804, 11.00, 3.625), (3060, 20.00, 4.625), (3317, 32.00, 5.625), (3959, 47.00, 6.625), ('inf', 89.00, 6.925)), - 'annually': ((24400, 0.00, 0.00), (27482, 0.00, 1.125), (30562, 35.00, 3.125), (33644, 131.00, 3.625), (36724, 243.00, 4.625), (39806, 385.00, 5.625), (47508, 558.00, 6.625), ('inf', 1068.00, 6.925)), + 'weekly': ( + ( 477, 0.00, 0.000), + ( 537, 0.00, 1.125), + ( 598, 0.00, 3.125), + ( 658, 1.00, 3.625), + ( 718, 3.00, 4.625), + ( 778, 5.00, 5.625), + ( 929, 11.00, 6.625), + ('inf', 21.00, 6.925), + ), + 'bi-weekly': ( + ( 954, 0.00, 0.000), + ( 1074, 0.00, 1.125), + ( 1195, 1.00, 3.125), + ( 1316, 5.00, 3.625), + ( 1436, 9.00, 4.625), + ( 1557, 15.00, 5.625), + ( 1858, 22.00, 6.625), + ('inf', 42.00, 6.925), + ), + 'semi-monthly': ( + ( 1033, 0.00, 0.000), + ( 1164, 0.00, 1.125), + ( 1295, 1.00, 3.125), + ( 1425, 6.00, 3.625), + ( 1556, 10.00, 4.625), + ( 1687, 16.00, 5.625), + ( 2013, 24.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'monthly': ( + ( 2067, 0.00, 0.000), + ( 2328, 0.00, 1.125), + ( 2589, 3.00, 3.125), + ( 2851, 11.00, 3.625), + ( 3112, 21.00, 4.625), + ( 3373, 33.00, 5.625), + ( 4027, 47.00, 6.625), + ('inf', 91.00, 6.925), + ), + 'annually': ( + (24400, 0.00, 0.000), + (27482, 0.00, 1.125), + (30562, 35.00, 3.125), + (33644, 131.00, 3.625), + (36724, 243.00, 4.625), + (39806, 385.00, 5.625), + (47508, 558.00, 6.625), + ('inf', 1068.00, 6.925), + ), }, 'head of household': { - 'weekly': ((235, 0.00, 0.00), (264, 0.00, 1.125), (294, 0.00, 3.125), (324, 1.00, 3.625), (353, 2.00, 4.625), (383, 4.00, 5.625), (457, 5.00, 6.625), ('inf', 10.00, 6.925)), - 'bi-weekly': ((469, 0.00, 0.00), (529, 0.00, 1.125), (588, 1.00, 3.125), (647, 3.00, 3.625), (706, 5.00, 4.625), (766, 7.00, 5.625), (914, 11.00, 6.625), ('inf', 21.00, 6.925)), - 'semi-monthly': ((508, 0.00, 0.00), (573, 0.00, 1.125), (637, 1.00, 3.125), (701, 3.00, 3.625), (765, 5.00, 4.625), (829, 8.00, 5.625), (990, 12.00, 6.625), ('inf', 22.00, 6.925)), - 'monthly': ((1017, 0.00, 0.00), (1145, 0.00, 1.125), (1273, 1.00, 3.125), (1402, 5.00, 3.625), (1530, 10.00, 4.625), (1659, 16.00, 5.625), (1980, 23.00, 6.625), ('inf', 45.00, 6.925)), - 'annually': ((12200, 0.00, 0.00), (13741, 0.00, 1.125), (15281, 17.00, 3.125), (16822, 65.00, 3.625), (18362, 121.00, 4.625), (19903, 192.00, 5.625), (23754, 279.00, 6.625), ('inf', 534.00, 6.925)), + 'weekly': ( + ( 238, 0.00, 0.000), + ( 269, 0.00, 1.125), + ( 299, 0.00, 3.125), + ( 329, 1.00, 3.625), + ( 359, 2.00, 4.625), + ( 389, 4.00, 5.625), + ( 465, 5.00, 6.625), + ('inf', 10.00, 6.925), + ), + 'bi-weekly': ( + ( 477, 0.00, 0.000), + ( 537, 0.00, 1.125), + ( 598, 1.00, 3.125), + ( 658, 3.00, 3.625), + ( 718, 5.00, 4.625), + ( 778, 8.00, 5.625), + ( 929, 11.00, 6.625), + ('inf', 21.00, 6.925), + ), + 'semi-monthly': ( + ( 517, 0.00, 0.000), + ( 582, 0.00, 1.125), + ( 647, 1.00, 3.125), + ( 713, 3.00, 3.625), + ( 778, 5.00, 4.625), + ( 843, 8.00, 5.625), + ( 1007, 12.00, 6.625), + ('inf', 23.00, 6.925), + ), + 'monthly': ( + ( 1033, 0.00, 0.000), + ( 1164, 0.00, 1.125), + ( 1295, 1.00, 3.125), + ( 1425, 6.00, 3.625), + ( 1556, 10.00, 4.625), + ( 1687, 16.00, 5.625), + ( 2013, 24.00, 6.625), + ('inf', 45.00, 6.925), + ), + 'annually': ( + (12400, 0.00, 0.000), + (13968, 0.00, 1.125), + (15536, 18.00, 3.125), + (17104, 67.00, 3.625), + (18672, 124.00, 4.625), + (20240, 197.00, 5.625), + (24160, 285.00, 6.625), + ('inf', 545.00, 6.925), + ), }, } @@ -117,6 +389,8 @@ + + { 'weekly': 56.92, diff --git a/l10n_us_hr_payroll/tests/test_us_id_idaho_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_id_idaho_payslip_2020.py index bf687080..eb0da9a7 100755 --- a/l10n_us_hr_payroll/tests/test_us_id_idaho_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_id_idaho_payslip_2020.py @@ -30,6 +30,6 @@ class TestUsIDPayslip(TestUsPayslip): self._test_er_suta('ID', self.ID_UNEMP, date(2020, 1, 1), wage_base=self.ID_UNEMP_MAX_WAGE) self._test_sit(1212.0, 'single', 4.0, 'bi-weekly', date(2020, 1, 1), 10.0) self._test_sit(10000.0, 'married', 1.0, 'annually', date(2020, 1, 1), 0.0) - self._test_sit(52000.0, 'married', 4.0, 'monthly', date(2020, 1, 1), 3348.02) + self._test_sit(52000.0, 'married', 4.0, 'monthly', date(2020, 1, 1), 3345.0) self._test_sit(5000.0, 'head of household', 0.0, 'semi-monthly', date(2020, 1, 1), 300.0) self._test_sit(5900.0, 'single', 5.0, 'weekly', date(2020, 1, 1), 367.0) From 1d45b0bf11d7009dfbf88dfee9bc4d2e9c179198 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 15:48:22 -0400 Subject: [PATCH 53/63] [IMP] l10n_us_hr_payroll: Added Tax table and improved Test case for MT Montana 2020 --- l10n_us_hr_payroll/data/state/mt_montana.xml | 71 ++++++++++++++++--- .../tests/test_us_mt_montana_payslip_2020.py | 30 ++++++-- 2 files changed, 86 insertions(+), 15 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/mt_montana.xml b/l10n_us_hr_payroll/data/state/mt_montana.xml index b420c4fe..b777fb4e 100644 --- a/l10n_us_hr_payroll/data/state/mt_montana.xml +++ b/l10n_us_hr_payroll/data/state/mt_montana.xml @@ -64,40 +64,78 @@ { - 'weekly': [ + 'weekly': ( ( 135.00, 0.0, 1.80), ( 288.00, 2.0, 4.40), ( 2308.00, 9.0, 6.00), ( 'inf', 130.0, 6.60), - ], - 'bi-weekly': [ + ), + 'bi-weekly': ( ( 269.00, 0.0, 1.80), ( 577.00, 5.0, 4.40), ( 4615.00, 18.0, 6.00), ( 'inf', 261.0, 6.60), - ], - 'semi-monthly': [ + ), + 'semi-monthly': ( ( 292.00, 0.0, 1.80), ( 625.00, 5.0, 4.40), ( 5000.00, 20.0, 6.00), ( 'inf', 282.0, 6.60), - ], - 'monthly': [ + ), + 'monthly': ( ( 583.00, 0.0, 1.80), ( 1250.00, 11.0, 4.40), ( 10000.00, 40.0, 6.00), ( 'inf', 565.0, 6.60), - ], - 'annually': [ + ), + 'annually': ( ( 7000.00, 0.0, 1.80), ( 15000.00, 126.0, 4.40), ( 120000.00, 478.0, 6.00), ( 'inf', 6778.0, 6.60), - ], + ), } + + + + { + 'weekly': ( + ( 135.00, 0.0, 1.80), + ( 288.00, 2.0, 4.40), + ( 2308.00, 9.0, 6.00), + ( 'inf', 130.0, 6.60), + ), + 'bi-weekly': ( + ( 269.00, 0.0, 1.80), + ( 577.00, 5.0, 4.40), + ( 4615.00, 18.0, 6.00), + ( 'inf', 261.0, 6.60), + ), + 'semi-monthly': ( + ( 292.00, 0.0, 1.80), + ( 625.00, 5.0, 4.40), + ( 5000.00, 20.0, 6.00), + ( 'inf', 282.0, 6.60), + ), + 'monthly': ( + ( 583.00, 0.0, 1.80), + ( 1250.00, 11.0, 4.40), + ( 10000.00, 40.0, 6.00), + ( 'inf', 565.0, 6.60), + ), + 'annually': ( + ( 7000.00, 0.0, 1.80), + ( 15000.00, 126.0, 4.40), + ( 120000.00, 478.0, 6.00), + ( 'inf', 6778.0, 6.60), + ), + } + + + @@ -117,6 +155,19 @@ + + + + { + 'weekly': 37.0, + 'bi-weekly': 73.0, + 'semi-monthly': 79.0, + 'monthly': 158.0, + 'annually': 1900.0, + } + + + diff --git a/l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py index ec861a0d..13a7e69f 100755 --- a/l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py @@ -1,17 +1,37 @@ # Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. -from datetime import date -from .common import TestUsPayslip, process_payslip +from datetime import date, timedelta +from .common import TestUsPayslip class TestUsMtPayslip(TestUsPayslip): - # Calculations from https://app.mt.gov/myrevenue/Endpoint/DownloadPdf?yearId=705 + ### + # 2020 Taxes and Rates + ### MT_UNEMP_WAGE_MAX = 34100.0 MT_UNEMP = 1.18 MT_UNEMP_AFT = 0.13 + # Calculations from https://app.mt.gov/myrevenue/Endpoint/DownloadPdf?yearId=705 + def _test_sit(self, wage, additional_withholding, exemptions, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('MT'), + state_income_tax_additional_withholding=additional_withholding, + mt_mw4_sit_exemptions=exemptions, + 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_one(self): combined_rate = self.MT_UNEMP + self.MT_UNEMP_AFT # Combined for test as they both go to the same category and have the same cap self._test_er_suta('MT', combined_rate, date(2020, 1, 1), wage_base=self.MT_UNEMP_WAGE_MAX) - - # TODO Montana Incometax rates for 2020 when released + self._test_sit(550.0, 0.0, 5.0, 'semi-monthly', date(2020, 1, 1), 3.0) + self._test_sit(2950.0, 10.0, 2.0, 'bi-weekly', date(2020, 1, 1), 162.0) + self._test_sit(5000.0, 0.0, 1.0, 'monthly', date(2020, 1, 1), 256.0) + self._test_sit(750.0, 0.0, 1.0, 'weekly', date(2020, 1, 1), 34.0) From 4f3f3f6affe2b7903aa58175bf174c7d874bb0fb Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 16:31:27 -0400 Subject: [PATCH 54/63] [IMP] l10n_us_hr_payroll: Added comment and improved Test case for MO Missouri 2020 --- l10n_us_hr_payroll/data/state/mo_missouri.xml | 6 ++ .../tests/test_us_mo_missouri_payslip_2020.py | 97 +++---------------- 2 files changed, 19 insertions(+), 84 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/mo_missouri.xml b/l10n_us_hr_payroll/data/state/mo_missouri.xml index 230e24eb..73ea5109 100644 --- a/l10n_us_hr_payroll/data/state/mo_missouri.xml +++ b/l10n_us_hr_payroll/data/state/mo_missouri.xml @@ -44,6 +44,7 @@ + [ (1053.0, 1.5), @@ -59,6 +60,8 @@ + + [ (1073.0, 1.5), @@ -82,6 +85,7 @@ + { 'single': 12400.0, @@ -91,6 +95,8 @@ + + { 'single': 12400.0, diff --git a/l10n_us_hr_payroll/tests/test_us_mo_missouri_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_mo_missouri_payslip_2020.py index 164b0f0f..ff6a0ca1 100755 --- a/l10n_us_hr_payroll/tests/test_us_mo_missouri_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_mo_missouri_payslip_2020.py @@ -1,5 +1,6 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. -from datetime import date +from datetime import date, timedelta from .common import TestUsPayslip @@ -8,98 +9,26 @@ class TestUsMoPayslip(TestUsPayslip): MO_UNEMP_MAX_WAGE = 11500.0 MO_UNEMP = 2.376 - TAX = [ - (1073.0, 1.5), - (1073.0, 2.0), - (1073.0, 2.5), - (1073.0, 3.0), - (1073.0, 3.5), - (1073.0, 4.0), - (1073.0, 4.5), - (1073.0, 5.0), - ( 'inf', 5.4), - ] - STD_DED = { - '': 0.0, # Exempt - 'single': 12400.0, - 'married': 24800.0, - 'head_of_household': 18650.0, - } - - def _test_sit(self, filing_status, schedule_pay): - wage = 5000.0 + def _test_sit(self, wage, filing_status, additional_withholding, schedule_pay, date_start, expected_withholding): employee = self._createEmployee() contract = self._createContract(employee, wage=wage, state_id=self.get_us_state('MO'), mo_mow4_sit_filing_status=filing_status, - state_income_tax_additional_withholding=0.0, + state_income_tax_additional_withholding=additional_withholding, schedule_pay=schedule_pay) - - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') + payslip = self._createPayslip(employee, date_start, date_start + timedelta(days=7)) payslip.compute_sheet() cats = self._getCategories(payslip) - pp = payslip.get_pay_periods_in_year() - gross_salary = wage * pp - standard_deduction = self.STD_DED[filing_status] + self._log('Computed period tax: ' + str(expected_withholding)) + self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding) - mo_taxable_income = gross_salary - standard_deduction - self._log('%s = %s - %s -' % (mo_taxable_income, gross_salary, standard_deduction)) - - remaining_taxable_income = mo_taxable_income - tax = 0.0 - for amt, rate in self.TAX: - amt = float(amt) - rate = rate / 100.0 - self._log(str(amt) + ' : ' + str(rate) + ' : ' + str(remaining_taxable_income)) - if (remaining_taxable_income - amt) > 0.0 or (remaining_taxable_income - amt) == 0.0: - tax += rate * amt - else: - tax += rate * remaining_taxable_income - break - remaining_taxable_income = remaining_taxable_income - amt - - tax = -tax - self._log('Computed annual tax: ' + str(tax)) - - tax = tax / pp - tax = round(tax) - self._log('Computed period tax: ' + str(tax)) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), tax if filing_status else 0.0) - - contract.us_payroll_config_id.state_income_tax_additional_withholding = 100.0 - payslip.compute_sheet() - cats = self._getCategories(payslip) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), (tax - 100.0) if filing_status else 0.0) - - contract.us_payroll_config_id.mo_mow4_sit_withholding = 200.0 - payslip.compute_sheet() - cats = self._getCategories(payslip) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -200.0 if filing_status else 0.0) - - def test_2020_taxes_single(self): + def test_2020_taxes_example(self): self._test_er_suta('MO', self.MO_UNEMP, date(2020, 1, 1), wage_base=self.MO_UNEMP_MAX_WAGE) - self._test_sit('single', 'weekly') + self._test_sit(750.0, 'single', 0.0, 'weekly', date(2020, 1, 1), 24.00) + self._test_sit(2500.0, 'single', 5.0, 'bi-weekly', date(2020, 1, 1), 107.00) + self._test_sit(7000.0, 'married', 0.0, 'monthly', date(2020, 1, 1), 251.00) + self._test_sit(5000.0, 'married', 10.0, 'semi-monthly', date(2020, 1, 1), 217.00) + self._test_sit(6000.0, '', 0.0, 'monthly', date(2020, 1, 1), 0.00) - def test_2020_spouse_not_employed(self): - self._test_sit('married', 'semi-monthly') - - def test_2020_head_of_household(self): - self._test_sit('head_of_household', 'monthly') - - def test_2020_underflow(self): - # Payroll Period Weekly - salary = 200.0 - - employee = self._createEmployee() - - contract = self._createContract(employee, - wage=salary, - state_id=self.get_us_state('MO')) - - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') - payslip.compute_sheet() - cats = self._getCategories(payslip) - - self.assertPayrollEqual(cats['EE_US_SIT'], 0.0) From b30e024b1d9381af85fb6829aa31ad11439f22bf Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 17:00:16 -0400 Subject: [PATCH 55/63] [IMP] l10n_us_hr_payroll: Added comment for MN Minnesota 2020 --- .../data/state/mn_minnesota.xml | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/mn_minnesota.xml b/l10n_us_hr_payroll/data/state/mn_minnesota.xml index 5a5a0241..d1044752 100644 --- a/l10n_us_hr_payroll/data/state/mn_minnesota.xml +++ b/l10n_us_hr_payroll/data/state/mn_minnesota.xml @@ -46,36 +46,38 @@ { - 'single': [ + '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': [ + ), + '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), - ], + ), } + + { - 'single': [ + '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': [ + ), + '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), - ], + ), } @@ -93,6 +95,8 @@ + + 4300.0 From 9603b7281b67f377e61dc9c0d934f310812abef4 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Fri, 21 Aug 2020 17:59:41 -0400 Subject: [PATCH 56/63] [IMP] l10n_us_hr_payroll: Improved Test case for MI Michigan 2020 --- .../tests/test_us_mi_michigan_payslip_2020.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/l10n_us_hr_payroll/tests/test_us_mi_michigan_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_mi_michigan_payslip_2020.py index 7d178d76..6de7b664 100755 --- a/l10n_us_hr_payroll/tests/test_us_mi_michigan_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_mi_michigan_payslip_2020.py @@ -27,9 +27,9 @@ class TestUsMIPayslip(TestUsPayslip): def test_2020_taxes_example(self): self._test_er_suta('MI', self.MI_UNEMP, date(2020, 1, 1), wage_base=self.MI_UNEMP_MAX_WAGE) - self._test_sit(5000.0, 1, 100.0, 'weekly', date(2020, 1, 1), 308.62) - self._test_sit(5000.0, 1, 0.0, 'weekly', date(2020, 1, 1), 208.62) + self._test_sit(750.0, 1, 100.0, 'weekly', date(2020, 1, 1), 127.99) + self._test_sit(1750.0, 1, 0.0, 'bi-weekly', date(2020, 1, 1), 66.61) self._test_sit(5000.0, 1, 5.0, 'semi-monthly', date(2020, 1, 1), 209.09) - self._test_sit(5000.0, 1, 5.0, 'monthly', date(2020, 1, 1), 200.68) - self._test_sit(5000.0, 200, 0.0, 'monthly', date(2020, 1, 1), 0.0) + self._test_sit(8000.0, 1, 5.0, 'monthly', date(2020, 1, 1), 328.18) + self._test_sit(5000.0, 2, 0.0, 'monthly', date(2020, 1, 1), 178.86) From 669acc5589c61201bee9e9b936f2e9956864222d Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Mon, 24 Aug 2020 11:53:41 -0400 Subject: [PATCH 57/63] [IMP] l10n_us_hr_payroll: Added comment and improved Test case for MS Mississippi 2020 --- .../data/state/ms_mississippi.xml | 14 ++ .../test_us_ms_mississippi_payslip_2020.py | 131 +++--------------- 2 files changed, 37 insertions(+), 108 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/ms_mississippi.xml b/l10n_us_hr_payroll/data/state/ms_mississippi.xml index 97be0112..a3868e8d 100644 --- a/l10n_us_hr_payroll/data/state/ms_mississippi.xml +++ b/l10n_us_hr_payroll/data/state/ms_mississippi.xml @@ -53,6 +53,8 @@ + + [ ( 10000.00, 260.0, 0.05), @@ -80,6 +82,18 @@ + + + + { + 'single': 2300.0, + 'head_of_household': 3400.0, + 'married_dual': 2300.0, + 'married': 4600.0, + } + + + diff --git a/l10n_us_hr_payroll/tests/test_us_ms_mississippi_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ms_mississippi_payslip_2020.py index 5942d7ad..ea0081ca 100755 --- a/l10n_us_hr_payroll/tests/test_us_ms_mississippi_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_ms_mississippi_payslip_2020.py @@ -1,120 +1,35 @@ # Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. -from datetime import date +from datetime import date, timedelta from .common import TestUsPayslip class TestUsMsPayslip(TestUsPayslip): - # Calculations from https://www.dor.ms.gov/Documents/Computer%20Payroll%20Accounting%201-2-19.pdf + # Calculations from https://www.dor.ms.gov/Documents/Computer%20Payroll%20Flowchart.pdf MS_UNEMP = 1.2 MS_UNEMP_MAX_WAGE = 14000.0 - def test_2020_taxes_one(self): + def _test_sit(self, wage, filing_status, additional_withholding, exemption, schedule_pay, date_start, expected_withholding): + employee = self._createEmployee() + contract = self._createContract(employee, + wage=wage, + state_id=self.get_us_state('MS'), + ms_89_350_sit_filing_status=filing_status, + state_income_tax_additional_withholding=additional_withholding, + ms_89_350_sit_exemption_value=exemption, + 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_2020_taxes_example(self): self._test_er_suta('MS', self.MS_UNEMP, date(2020, 1, 1), wage_base=self.MS_UNEMP_MAX_WAGE) + self._test_sit(1250.0, 'head_of_household', 0.0, 11000, 'semi-monthly', date(2020, 1, 1), 22.00) + self._test_sit(500.0, '', 5.0, 0, 'bi-weekly', date(2020, 1, 1), 0.00) + self._test_sit(12000.0, 'single', 0.0, 11000, 'monthly', date(2020, 1, 1), 525.00) + self._test_sit(2500.0, 'married', 5.0, 500, 'bi-weekly', date(2020, 1, 1), 111.00) - salary = 1250.0 - ms_89_350_exemption = 11000.0 - employee = self._createEmployee() - contract = self._createContract(employee, - wage=salary, - state_id=self.get_us_state('MS'), - ms_89_350_sit_filing_status='head_of_household', - ms_89_350_sit_exemption_value=ms_89_350_exemption, - state_income_tax_additional_withholding=0.0, - schedule_pay='semi-monthly') - - self._log('2020 Mississippi tax single first payslip:') - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') - - payslip.compute_sheet() - - cats = self._getCategories(payslip) - - STDED = 3400.0 # Head of Household - AGP = salary * 24 # Semi-Monthly - TI = AGP - (ms_89_350_exemption + STDED) - self.assertPayrollEqual(TI, 15600.0) - TAX = ((TI - 10000) * 0.05) + 260 # Over 10,000 - self.assertPayrollEqual(TAX, 540.0) - - ms_withhold = round(TAX / 24) # Semi-Monthly - self.assertPayrollEqual(cats['EE_US_SIT'], -ms_withhold) - - def test_2020_taxes_one_exempt(self): - salary = 1250.0 - ms_89_350_exemption = 11000.0 - - employee = self._createEmployee() - contract = self._createContract(employee, - wage=salary, - state_id=self.get_us_state('MS'), - ms_89_350_sit_filing_status='', - ms_89_350_sit_exemption_value=ms_89_350_exemption, - state_income_tax_additional_withholding=0.0, - schedule_pay='semi-monthly') - - self._log('2020 Mississippi tax single first payslip:') - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') - - payslip.compute_sheet() - - cats = self._getCategories(payslip) - self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), 0.0) - - def test_2020_taxes_additional(self): - salary = 1250.0 - ms_89_350_exemption = 11000.0 - additional = 40.0 - - employee = self._createEmployee() - contract = self._createContract(employee, - wage=salary, - state_id=self.get_us_state('MS'), - ms_89_350_sit_filing_status='single', - ms_89_350_sit_exemption_value=ms_89_350_exemption, - state_income_tax_additional_withholding=additional, - schedule_pay='monthly') - - self._log('2020 Mississippi tax single first payslip:') - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') - - payslip.compute_sheet() - - cats = self._getCategories(payslip) - - STDED = 2300.0 # Single - AGP = salary * 12 # Monthly - TI = AGP - (ms_89_350_exemption + STDED) - self.assertPayrollEqual(TI, 1700.0) - TAX = ((TI - 3000) * 0.03) - self.assertPayrollEqual(TAX, -39.0) - - ms_withhold = round(TAX / 12) # Monthly - self.assertTrue(ms_withhold <= 0.0) - self.assertPayrollEqual(cats['EE_US_SIT'], -40.0) # only additional - - # Test with higher wage - salary = 1700.0 - employee = self._createEmployee() - contract = self._createContract(employee, - wage=salary, - state_id=self.get_us_state('MS'), - ms_89_350_sit_filing_status='single', - ms_89_350_sit_exemption_value=ms_89_350_exemption, - state_income_tax_additional_withholding=additional, - schedule_pay='monthly') - payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31') - payslip.compute_sheet() - cats = self._getCategories(payslip) - - STDED = 2300.0 # Single - AGP = salary * 12 # Monthly - TI = AGP - (ms_89_350_exemption + STDED) - self.assertPayrollEqual(TI, 7100.0) - TAX = ((TI - 5000) * 0.04) + 60.0 - self.assertPayrollEqual(TAX, 144.0) - - ms_withhold = round(TAX / 12) # Monthly - self.assertPayrollEqual(ms_withhold, 12.0) - self.assertPayrollEqual(cats['EE_US_SIT'], -(ms_withhold + additional)) From 4e1baff4b9d474e9c825fb1039708e03c9797b07 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Mon, 24 Aug 2020 13:42:24 -0400 Subject: [PATCH 58/63] [IMP] l10n_us_hr_payroll: Improved Tax table and improved Test case for NJ New Jersey 2020 --- .../data/state/nj_newjersey.xml | 730 ++++++++++++++++-- .../test_us_nj_newjersey_payslip_2020.py | 3 + 2 files changed, 663 insertions(+), 70 deletions(-) diff --git a/l10n_us_hr_payroll/data/state/nj_newjersey.xml b/l10n_us_hr_payroll/data/state/nj_newjersey.xml index 93d87265..50c72dcd 100644 --- a/l10n_us_hr_payroll/data/state/nj_newjersey.xml +++ b/l10n_us_hr_payroll/data/state/nj_newjersey.xml @@ -178,100 +178,689 @@ { 'A': { - 'weekly': ((385, 0.0, 1.50), (673, 5.77, 2.00), (769, 11.54, 3.90), (1442, 15.29, 6.10), (9615, 56.34, 7.00), (96154, 628.46, 9.90), ('inf', 9195.77, 11.80)), - 'bi-weekly': ((769, 0.00, 1.50), (1346, 12.00, 2.00), (1538, 23.00, 3.90), (2885, 31.00, 6.10), (19231, 113.00, 7.00), (192308, 1257.00, 9.90), ('inf',18392.00, 11.80)), - 'semi-monthly': ((833, 0.00, 1.50), (1458, 13.00, 2.00), (1667, 25.00, 3.90), (3125, 33.00, 6.10), (20833, 122.00, 7.00), (208333, 1362.00, 9.90), ('inf', 19924.00, 11.80)), - 'monthly': ((1667, 0.00, 1.50), (2917, 25.00, 2.00), (3333, 50.00, 3.90), (6250, 66.00, 6.10), (41667, 244.00, 7.00), (416667, 2723.00, 9.90), ('inf', 39848.00, 11.80)), - 'quarterly': ((5000, 0.00, 1.50), (8750, 75.00, 2.00), (10000, 150.00, 3.90), (18750, 198.75, 6.10), (125000, 732.50, 7.00), (1250000, 8170.00, 9.90), ('inf', 119545.00, 11.80)), - 'semi-annual': ((10000, 0.00, 1.50), (17500, 150.00, 2.00), (20000, 300.00, 3.90), (37500, 397.50, 6.10), (250000, 1465.00, 7.00), (2500000, 16340.00, 9.90), ('inf', 239090.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (35000, 300.00, 2.00), (40000, 600.00, 3.90), (75000, 795.00, 6.10), (500000, 2930.00, 7.00), (5000000, 32680.00, 9.90), ('inf', 478180.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 673, 5.77, 2.00), + ( 769, 11.54, 3.90), + ( 1442, 15.29, 6.10), + ( 9615, 56.34, 7.00), + (96154, 628.46, 9.90), + ('inf', 9195.77, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1346, 12.00, 2.00), + ( 1538, 23.00, 3.90), + ( 2885, 31.00, 6.10), + ( 19231, 113.00, 7.00), + (192308, 1257.00, 9.90), + ( 'inf', 18392.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1458, 13.00, 2.00), + ( 1667, 25.00, 3.90), + ( 3125, 33.00, 6.10), + ( 20833, 122.00, 7.00), + (208333, 1362.00, 9.90), + ( 'inf', 19924.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 2917, 25.00, 2.00), + ( 3333, 50.00, 3.90), + ( 6250, 66.00, 6.10), + ( 41667, 244.00, 7.00), + (416667, 2723.00, 9.90), + ( 'inf', 39848.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 8750, 75.00, 2.00), + ( 10000, 150.00, 3.90), + ( 18750, 198.75, 6.10), + ( 125000, 732.50, 7.00), + (1250000, 8170.00, 9.90), + ( 'inf', 119545.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 17500, 150.00, 2.00), + ( 20000, 300.00, 3.90), + ( 37500, 397.50, 6.10), + ( 250000, 1465.00, 7.00), + (2500000, 16340.00, 9.90), + ( 'inf', 239090.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 35000, 300.00, 2.00), + ( 40000, 600.00, 3.90), + ( 75000, 795.00, 6.10), + ( 500000, 2930.00, 7.00), + (5000000, 32680.00, 9.90), + ( 'inf', 478180.00, 11.80), + ), }, 'B': { - 'weekly': ((385, 0.0, 1.50), (962, 5.77, 2.00), (1346, 17.31, 2.70), (1538, 27.69, 3.9), (2885, 35.19, 6.10), (9615, 117.31, 7.00), (96154, 588.46, 9.90), ('inf', 9155.77, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1923, 12.00, 2.00), (2692, 35.00, 2.70), (3076, 55.00, 3.9), (5769, 70.00, 6.10), (19231, 235.00, 700), (192308, 1177.00, 9.90), ('inf', 18312.00, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (2083, 12.50, 2.00), (2917, 37.50, 2.70), (3333, 59.99, 3.9), (6250, 76.25, 6.10), (20833, 254.19, 7.00), (208333, 1275.00, 9.90), ('inf', 19838.00, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (4167, 25.00, 2.00), (5833, 75.00, 2.70), (6667, 120.00, 3.9), (12500, 153.00, 6.10), (41667, 508.00, 7.00), (416667, 2550.00, 9.90), ('inf', 39675.00, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (12500, 75.00, 2.00), (17500, 225.00, 2.70), (20000, 360.00, 3.9), (37500, 397.50, 6.10), (125000, 1525.00, 7.00), (1250000, 7650.00, 9.90), ('inf', 119025.00, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (25000, 150.00, 2.00), (35000, 450.00, 2.70), (40000, 720.00, 3.9), (75000, 915.00, 6.10), (250000, 3050.00, 7.00), (2500000, 15300.00, 9.90), ('inf', 238050.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (50000, 300.00, 2.00), (70000, 900.00, 2.70), (80000, 1440.00, 3.9), (150000, 1830.00, 6.10), (500000, 6100.00, 7.00), (5000000, 30600.00, 9.90), ('inf', 476100.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 962, 5.77, 2.00), + ( 1346, 17.31, 2.70), + ( 1538, 27.69, 3.90), + ( 2885, 35.19, 6.10), + ( 9615, 117.31, 7.00), + (96154, 588.46, 9.90), + ('inf', 9155.77, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1923, 12.00, 2.00), + ( 2692, 35.00, 2.70), + ( 3076, 55.00, 3.90), + ( 5769, 70.00, 6.10), + ( 19231, 235.00, 7.00), + (192308, 1177.00, 9.90), + ( 'inf', 18312.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 2083, 12.50, 2.00), + ( 2917, 37.50, 2.70), + ( 3333, 59.99, 3.90), + ( 6250, 76.25, 6.10), + ( 20833, 254.19, 7.00), + (208333, 1275.00, 9.90), + ( 'inf', 19838.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 4167, 25.00, 2.00), + ( 5833, 75.00, 2.70), + ( 6667, 120.00, 3.90), + ( 12500, 153.00, 6.10), + ( 41667, 508.00, 7.00), + (416667, 2550.00, 9.90), + ( 'inf', 39675.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 12500, 75.00, 2.00), + ( 17500, 225.00, 2.70), + ( 20000, 360.00, 3.90), + ( 37500, 397.50, 6.10), + ( 125000, 1525.00, 7.00), + (1250000, 7650.00, 9.90), + ( 'inf', 119025.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 25000, 150.00, 2.00), + ( 35000, 450.00, 2.70), + ( 40000, 720.00, 3.90), + ( 75000, 915.00, 6.10), + ( 250000, 3050.00, 7.00), + (2500000, 15300.00, 9.90), + ( 'inf', 238050.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 50000, 300.00, 2.00), + ( 70000, 900.00, 2.70), + (80000, 1440.00, 3.90), + ( 150000, 1830.00, 6.10), + ( 500000, 6100.00, 7.00), + (5000000, 30600.00, 9.90), + ( 'inf', 476100.00, 11.80), + ), }, 'C': { - 'weekly': ((385, 0.0, 1.50), (769, 5.77, 2.30), (962, 14.62, 2.80), (1154, 20.00, 3.50), (2885, 26.73, 5.60), (9615, 123.65, 6.60), (96154, 567.88, 9.90), ('inf', 9135.19, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1538, 11.54, 2.30), (1923, 29.23, 2.80), (2308, 40.00, 3.50), (5769, 53.46, 5.60), (19231, 247.31, 6.60), (192308, 1135.77, 9.90), ('inf', 18270.38, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1667, 12.50, 2.30), (2083, 31.67, 2.80), (2500, 43.33, 3.50), (6250, 57.92, 5.60), (20833, 267.92, 6.60), (208333, 1230.42, 9.90), ('inf', 19792.92, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (3333, 25.00, 2.30), (4167, 63.33, 2.80), (5000, 86.67, 3.50), (12500, 115.83, 5.60), (41667, 535.85, 6.60), (416667, 2460.83, 9.90), ('inf', 39585.83, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (10000, 75.00, 2.30), (12500, 190.00, 2.80), (15000, 260.00, 3.50), (37500, 347.50, 5.60), (125000, 1607.50, 6.60), (1250000, 7382.50, 9.90), ('inf', 118757.50, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (20000, 150.00, 2.30), (25000, 380.00, 2.80), (30000, 520.00, 3.50), (75000, 695.00, 5.60), (250000, 3215.00, 6.60), (2500000, 14765.00, 9.90), ('inf', 237515.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (40000, 300.00, 2.30), (50000, 760.00, 2.80), (60000, 1040.00, 3.50), (150000, 1390.00, 5.60), (500000, 6430.00, 6.60), (5000000, 29530.00, 9.90), ('inf', 475030.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 769, 5.77, 2.30), + ( 962, 14.62, 2.80), + ( 1154, 20.00, 3.50), + ( 2885, 26.73, 5.60), + ( 9615, 123.65, 6.60), + (96154, 567.88, 9.90), + ('inf', 9135.19, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1538, 11.54, 2.30), + ( 1923, 29.23, 2.80), + ( 2308, 40.00, 3.50), + ( 5769, 53.46, 5.60), + ( 19231, 247.31, 6.60), + (192308, 1135.77, 9.90), + ( 'inf', 18270.38, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1667, 12.50, 2.30), + ( 2083, 31.67, 2.80), + ( 2500, 43.33, 3.50), + ( 6250, 57.92, 5.60), + ( 20833, 267.92, 6.60), + (208333, 1230.42, 9.90), + ( 'inf', 19792.92, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 3333, 25.00, 2.30), + ( 4167, 63.33, 2.80), + ( 5000, 86.67, 3.50), + ( 12500, 115.83, 5.60), + ( 41667, 535.85, 6.60), + (416667, 2460.83, 9.90), + ( 'inf', 39585.83, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 10000, 75.00, 2.30), + ( 12500, 190.00, 2.80), + ( 15000, 260.00, 3.50), + ( 37500, 347.50, 5.60), + ( 125000, 1607.50, 6.60), + (1250000, 7382.50, 9.90), + ( 'inf', 118757.50, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 20000, 150.00, 2.30), + ( 25000, 380.00, 2.80), + ( 30000, 520.00, 3.50), + ( 75000, 695.00, 5.60), + ( 250000, 3215.00, 6.60), + (2500000, 14765.00, 9.90), + ( 'inf', 237515.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 40000, 300.00, 2.30), + ( 50000, 760.00, 2.80), + ( 60000, 1040.00, 3.50), + ( 150000, 1390.00, 5.60), + ( 500000, 6430.00, 6.60), + (5000000, 29530.00, 9.90), + ( 'inf', 475030.00, 11.80), + ), }, 'D': { - 'weekly': ((385, 0.0, 1.50), (769, 5.77, 2.70), (962, 16.15, 3.40), (1154, 22.69, 4.30), (2885, 30.96, 5.60), (9615, 127.88, 6.50), (96154, 565.38, 9.90), ('inf', 9132.69, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1538, 11.54, 2.70), (1923, 32.31, 3.40), (2308, 45.38, 4.30), (5769, 61.92, 5.60), (19231, 255.77, 6.50), (192308, 1130.77, 9.90), ('inf', 18265.38, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1667, 12.50, 2.70), (2083, 35.00, 3.40), (2500, 49.17, 4.30), (6250, 67.08, 5.60), (20833, 277.08, 6.50), (208333, 1225.00, 9.90), ('inf', 19787.50, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (3333, 25.00, 2.70), (4167, 70.00, 3.40), (5000, 98.33, 4.00), (12500, 134.17, 5.60), (41667, 554.17, 6.50), (416667, 2450.00, 9.90), ('inf', 39575.00, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (10000, 75.00, 2.07), (12500, 210.00, 3.40), (15000, 295.00, 4.30), (37500, 402.50, 5.60), (125000, 1662.50, 6.50), (1250000, 7350.00, 9.90), ('inf', 118725.00, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (20000, 150.00, 2.70), (25000, 420.00, 3.40), (30000, 590.00, 4.30), (75000, 805.00, 5.60), (250000, 3325.00, 6.50), (2500000, 14700.00, 9.90), ('inf', 237450.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (40000, 300.00, 2.70), (50000, 840.00, 3.40), (60000, 1180.00, 4.30), (150000, 1610.00, 5.60), (250000, 6650.00, 6.50), (2500000, 29400.00, 9.90), ('inf', 474900.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 769, 5.77, 2.70), + ( 962, 16.15, 3.40), + ( 1154, 22.69, 4.30), + ( 2885, 30.96, 5.60), + ( 9615, 127.88, 6.50), + ( 96154, 565.38, 9.90), + ( 'inf', 9132.69, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1538, 11.54, 2.70), + ( 1923, 32.31, 3.40), + ( 2308, 45.38, 4.30), + ( 5769, 61.92, 5.60), + ( 19231, 255.77, 6.50), + (192308, 1130.77, 9.90), + ( 'inf', 18265.38, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1667, 12.50, 2.70), + ( 2083, 35.00, 3.40), + ( 2500, 49.17, 4.30), + ( 6250, 67.08, 5.60), + ( 20833, 277.08, 6.50), + (208333, 1225.00, 9.90), + ( 'inf', 19787.50, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 3333, 25.00, 2.70), + ( 4167, 70.00, 3.40), + ( 5000, 98.33, 4.00), + ( 12500, 134.17, 5.60), + ( 41667, 554.17, 6.50), + (416667, 2450.00, 9.90), + ( 'inf', 39575.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 10000, 75.00, 2.07), + ( 12500, 210.00, 3.40), + ( 15000, 295.00, 4.30), + ( 37500, 402.50, 5.60), + ( 125000, 1662.50, 6.50), + (1250000, 7350.00, 9.90), + ( 'inf', 118725.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 20000, 150.00, 2.70), + ( 25000, 420.00, 3.40), + ( 30000, 590.00, 4.30), + ( 75000, 805.00, 5.60), + ( 250000, 3325.00, 6.50), + (2500000, 14700.00, 9.90), + ( 'inf', 237450.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 40000, 300.00, 2.70), + ( 50000, 840.00, 3.40), + ( 60000, 1180.00, 4.30), + ( 150000, 1610.00, 5.60), + ( 250000, 6650.00, 6.50), + (2500000, 29400.00, 9.90), + ( 'inf', 474900.00, 11.80), + ), }, 'E': { - 'weekly': ((385, 0.0, 1.50), (673, 5.77, 2.00), (1923, 11.54, 5.80), (9615, 84.04, 6.50), (96154, 584.04, 9.90), ('inf', 9151.35, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1346, 12.00, 2.00), (3846, 23.00, 5.80), (19231, 168.00, 6.50), (192308, 1168.00, 9.90), ('inf', 18303.00, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1458, 13.00, 2.00), (4167, 25.00, 5.80), (20833, 182.00, 6.50), (208333, 1265.00, 9.90), ('inf', 19828.00, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (2916, 25.00, 2.00), (8333, 50.00, 5.80), (41667, 364.00, 6.50), (416667, 2531.00, 9.90), ('inf', 39656, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (8750, 75.00, 2.00), (25000, 150.00, 5.80), (125000, 1092.50, 6.50), (1250000, 7592.50, 9.90), ('inf', 118967.50, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (17500, 150.00, 2.00), (50000, 300.00, 5.80), (250000, 2185.00, 6.50), (2500000, 15185.00, 9.90), ('inf', 237935.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (35000, 300.00, 2.00), (100000, 600.00, 5.80), (500000, 4370.00, 6.50), (5000000, 30370.00, 9.90), ('inf', 475870.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 673, 5.77, 2.00), + ( 1923, 11.54, 5.80), + ( 9615, 84.04, 6.50), + ( 96154, 584.04, 9.90), + ( 'inf', 9151.35, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1346, 12.00, 2.00), + ( 3846, 23.00, 5.80), + ( 19231, 168.00, 6.50), + (192308, 1168.00, 9.90), + ( 'inf', 18303.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1458, 13.00, 2.00), + ( 4167, 25.00, 5.80), + ( 20833, 182.00, 6.50), + (208333, 1265.00, 9.90), + ( 'inf', 19828.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 2916, 25.00, 2.00), + ( 8333, 50.00, 5.80), + ( 41667, 364.00, 6.50), + (416667, 2531.00, 9.90), + ( 'inf', 39656.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 8750, 75.00, 2.00), + ( 25000, 150.00, 5.80), + ( 125000, 1092.50, 6.50), + (1250000, 7592.50, 9.90), + ( 'inf', 118967.50, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 17500, 150.00, 2.00), + ( 50000, 300.00, 5.80), + ( 250000, 2185.00, 6.50), + (2500000, 15185.00, 9.90), + ( 'inf', 237935.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 35000, 300.00, 2.00), + ( 100000, 600.00, 5.80), + ( 500000, 4370.00, 6.50), + (5000000, 30370.00, 9.90), + ( 'inf', 475870.00, 11.80), + ), }, } + { 'A': { - 'weekly': ((385, 0.0, 1.50), (673, 5.77, 2.00), (769, 11.54, 3.90), (1442, 15.29, 6.10), (9615, 56.34, 7.00), (96154, 628.46, 9.90), ('inf', 9195.77, 11.80)), - 'bi-weekly': ((769, 0.00, 1.50), (1346, 12.00, 2.00), (1538, 23.00, 3.90), (2885, 31.00, 6.10), (19231, 113.00, 7.00), (192308, 1257.00, 9.90), ('inf',18392.00, 11.80)), - 'semi-monthly': ((833, 0.00, 1.50), (1458, 13.00, 2.00), (1667, 25.00, 3.90), (3125, 33.00, 6.10), (20833, 122.00, 57.00), (208333, 1362.00, 9.90), ('inf', 19924.00, 11.80)), - 'monthly': ((1667, 0.00, 1.50), (2917, 25.00, 2.00), (3333, 50.00, 3.90), (6250, 66.00, 6.10), (41667, 244.00, 57.00), (416667, 2723.00, 9.90), ('inf', 39848.00, 11.80)), - 'quarterly': ((5000, 0.00, 1.50), (8750, 75.00, 2.00), (10000, 150.00, 3.90), (18750, 198.75, 6.10), (125000, 732.50, 57.00), (1250000, 8170.00, 9.90), ('inf', 119545.00, 11.80)), - 'semi-annual': ((10000, 0.00, 1.50), (17500, 150.00, 2.00), (20000, 300.00, 3.90), (37500, 397.50, 6.10), (250000, 1465.00, 57.00), (2500000, 16340.00, 9.90), ('inf', 239090.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (35000, 300.00, 2.00), (40000, 600.00, 3.90), (75000, 795.00, 6.10), (500000, 2930.00, 57.00), (5000000, 32680.00, 9.90), ('inf', 478180.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 673, 5.77, 2.00), + ( 769, 11.54, 3.90), + ( 1442, 15.29, 6.10), + ( 9615, 56.34, 7.00), + (96154, 628.46, 9.90), + ('inf', 9195.77, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1346, 12.00, 2.00), + ( 1538, 23.00, 3.90), + ( 2885, 31.00, 6.10), + ( 19231, 113.00, 7.00), + (192308, 1257.00, 9.90), + ( 'inf', 18392.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1458, 13.00, 2.00), + ( 1667, 25.00, 3.90), + ( 3125, 33.00, 6.10), + ( 20833, 122.00, 7.00), + (208333, 1362.00, 9.90), + ( 'inf', 19924.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 2917, 25.00, 2.00), + ( 3333, 50.00, 3.90), + ( 6250, 66.00, 6.10), + ( 41667, 244.00, 7.00), + (416667, 2723.00, 9.90), + ( 'inf', 39848.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 8750, 75.00, 2.00), + ( 10000, 150.00, 3.90), + ( 18750, 198.75, 6.10), + ( 125000, 732.50, 7.00), + (1250000, 8170.00, 9.90), + ( 'inf', 119545.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 17500, 150.00, 2.00), + ( 20000, 300.00, 3.90), + ( 37500, 397.50, 6.10), + ( 250000, 1465.00, 7.00), + (2500000, 16340.00, 9.90), + ( 'inf', 239090.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 35000, 300.00, 2.00), + ( 40000, 600.00, 3.90), + ( 75000, 795.00, 6.10), + ( 500000, 2930.00, 7.00), + (5000000, 32680.00, 9.90), + ( 'inf', 478180.00, 11.80), + ), }, 'B': { - 'weekly': ((385, 0.0, 1.50), (962, 5.77, 2.00), (1346, 17.31, 2.70), (1538, 27.69, 3.9), (2885, 35.19, 6.10), (9615, 117.31, 7.00), (96154, 588.46, 9.90), ('inf', 9155.77, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1923, 12.00, 2.00), (2692, 35.00, 2.70), (3076, 55.00, 3.9), (5769, 70.00, 6.10), (19231, 235.00, 700), (192308, 1177.00, 9.90), ('inf', 18312.00, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (2083, 12.50, 2.00), (2917, 37.50, 2.70), (3333, 59.99, 3.9), (6250, 76.25, 6.10), (20833, 254.19, 7.00), (208333, 1275.00, 9.90), ('inf', 19838.00, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (4167, 25.00, 2.00), (5833, 75.00, 2.70), (6667, 120.00, 3.9), (12500, 153.00, 6.10), (41667, 508.00, 7.00), (416667, 2550.00, 9.90), ('inf', 39675.00, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (12500, 75.00, 2.00), (17500, 225.00, 2.70), (20000, 360.00, 3.9), (37500, 397.50, 6.10), (125000, 1525.00, 7.00), (1250000, 7650.00, 9.90), ('inf', 119025.00, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (25000, 150.00, 2.00), (35000, 450.00, 2.70), (40000, 720.00, 3.9), (75000, 915.00, 6.10), (250000, 3050.00, 7.00), (2500000, 15300.00, 9.90), ('inf', 238050.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (50000, 300.00, 2.00), (70000, 900.00, 2.70), (80000, 1440.00, 3.9), (150000, 1830.00, 6.10), (500000, 6100.00, 7.00), (5000000, 30600.00, 9.90), ('inf', 476100.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 962, 5.77, 2.00), + ( 1346, 17.31, 2.70), + ( 1538, 27.69, 3.90), + ( 2885, 35.19, 6.10), + ( 9615, 117.31, 7.00), + (96154, 588.46, 9.90), + ('inf', 9155.77, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1923, 12.00, 2.00), + ( 2692, 35.00, 2.70), + ( 3076, 55.00, 3.90), + ( 5769, 70.00, 6.10), + ( 19231, 235.00, 7.00), + (192308, 1177.00, 9.90), + ( 'inf', 18312.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 2083, 12.50, 2.00), + ( 2917, 37.50, 2.70), + ( 3333, 59.99, 3.90), + ( 6250, 76.25, 6.10), + ( 20833, 254.19, 7.00), + (208333, 1275.00, 9.90), + ( 'inf', 19838.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 4167, 25.00, 2.00), + ( 5833, 75.00, 2.70), + ( 6667, 120.00, 3.90), + ( 12500, 153.00, 6.10), + ( 41667, 508.00, 7.00), + (416667, 2550.00, 9.90), + ( 'inf', 39675.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 12500, 75.00, 2.00), + ( 17500, 225.00, 2.70), + ( 20000, 360.00, 3.90), + ( 37500, 397.50, 6.10), + ( 125000, 1525.00, 7.00), + (1250000, 7650.00, 9.90), + ( 'inf', 119025.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 25000, 150.00, 2.00), + ( 35000, 450.00, 2.70), + ( 40000, 720.00, 3.90), + ( 75000, 915.00, 6.10), + ( 250000, 3050.00, 7.00), + (2500000, 15300.00, 9.90), + ( 'inf', 238050.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 50000, 300.00, 2.00), + ( 70000, 900.00, 2.70), + (80000, 1440.00, 3.90), + ( 150000, 1830.00, 6.10), + ( 500000, 6100.00, 7.00), + (5000000, 30600.00, 9.90), + ( 'inf', 476100.00, 11.80), + ), }, 'C': { - 'weekly': ((385, 0.0, 1.50), (769, 5.77, 2.30), (962, 14.62, 2.80), (1154, 20.00, 3.50), (2885, 26.73, 5.60), (9615, 123.65, 6.60), (96154, 567.88, 9.90), ('inf', 9135.19, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1538, 11.54, 2.30), (1923, 29.23, 2.80), (2308, 40.00, 3.50), (5769, 53.46, 5.60), (19231, 247.31, 6.60), (192308, 1135.77, 9.90), ('inf', 18270.38, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1667, 12.50, 2.30), (2083, 31.67, 2.80), (2500, 43.33, 3.50), (6250, 57.92, 5.60), (20833, 267.92, 6.60), (208333, 1230.42, 9.90), ('inf', 19792.92, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (3333, 25.00, 2.30), (4167, 63.33, 2.80), (5000, 86.67, 3.50), (12500, 115.83, 5.60), (41667, 535.85, 6.60), (416667, 2460.83, 9.90), ('inf', 39585.83, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (10000, 75.00, 2.30), (12500, 190.00, 2.80), (15000, 260.00, 3.50), (37500, 347.50, 5.60), (125000, 1607.50, 6.60), (1250000, 7382.50, 9.90), ('inf', 118757.50, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (20000, 150.00, 2.30), (25000, 380.00, 2.80), (30000, 520.00, 3.50), (75000, 695.00, 5.60), (250000, 3215.00, 6.60), (2500000, 14765.00, 9.90), ('inf', 237515.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (40000, 300.00, 2.30), (50000, 760.00, 2.80), (60000, 1040.00, 3.50), (150000, 1390.00, 5.60), (500000, 6430.00, 6.60), (5000000, 29530.00, 9.90), ('inf', 475030.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 769, 5.77, 2.30), + ( 962, 14.62, 2.80), + ( 1154, 20.00, 3.50), + ( 2885, 26.73, 5.60), + ( 9615, 123.65, 6.60), + (96154, 567.88, 9.90), + ('inf', 9135.19, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1538, 11.54, 2.30), + ( 1923, 29.23, 2.80), + ( 2308, 40.00, 3.50), + ( 5769, 53.46, 5.60), + ( 19231, 247.31, 6.60), + (192308, 1135.77, 9.90), + ( 'inf', 18270.38, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1667, 12.50, 2.30), + ( 2083, 31.67, 2.80), + ( 2500, 43.33, 3.50), + ( 6250, 57.92, 5.60), + ( 20833, 267.92, 6.60), + (208333, 1230.42, 9.90), + ( 'inf', 19792.92, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 3333, 25.00, 2.30), + ( 4167, 63.33, 2.80), + ( 5000, 86.67, 3.50), + ( 12500, 115.83, 5.60), + ( 41667, 535.85, 6.60), + (416667, 2460.83, 9.90), + ( 'inf', 39585.83, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 10000, 75.00, 2.30), + ( 12500, 190.00, 2.80), + ( 15000, 260.00, 3.50), + ( 37500, 347.50, 5.60), + ( 125000, 1607.50, 6.60), + (1250000, 7382.50, 9.90), + ( 'inf', 118757.50, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 20000, 150.00, 2.30), + ( 25000, 380.00, 2.80), + ( 30000, 520.00, 3.50), + ( 75000, 695.00, 5.60), + ( 250000, 3215.00, 6.60), + (2500000, 14765.00, 9.90), + ( 'inf', 237515.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 40000, 300.00, 2.30), + ( 50000, 760.00, 2.80), + ( 60000, 1040.00, 3.50), + ( 150000, 1390.00, 5.60), + ( 500000, 6430.00, 6.60), + (5000000, 29530.00, 9.90), + ( 'inf', 475030.00, 11.80), + ), }, 'D': { - 'weekly': ((385, 0.0, 1.50), (769, 5.77, 2.70), (962, 16.15, 3.40), (1154, 22.69, 4.30), (2885, 30.96, 5.60), (9615, 127.88, 6.50), (96154, 565.38, 9.90), ('inf', 9132.69, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1538, 11.54, 2.70), (1923, 32.31, 3.40), (2308, 45.38, 4.30), (5769, 61.92, 5.60), (19231, 255.77, 6.50), (192308, 1130.77, 9.90), ('inf', 18265.38, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1667, 12.50, 2.70), (2083, 35.00, 3.40), (2500, 49.17, 4.30), (6250, 67.08, 5.60), (20833, 277.08, 6.50), (208333, 1225.00, 9.90), ('inf', 19787.50, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (3333, 25.00, 2.70), (4167, 70.00, 3.40), (5000, 98.33, 4.00), (12500, 134.17, 5.60), (41667, 554.17, 6.50), (416667, 2450.00, 9.90), ('inf', 39575.00, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (10000, 75.00, 2.07), (12500, 210.00, 3.40), (15000, 295.00, 4.30), (37500, 402.50, 5.60), (125000, 1662.50, 6.50), (1250000, 7350.00, 9.90), ('inf', 118725.00, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (20000, 150.00, 2.70), (25000, 420.00, 3.40), (30000, 590.00, 4.30), (75000, 805.00, 5.60), (250000, 3325.00, 6.50), (2500000, 14700.00, 9.90), ('inf', 237450.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (40000, 300.00, 2.70), (50000, 840.00, 3.40), (60000, 1180.00, 4.30), (150000, 1610.00, 5.60), (250000, 6650.00, 6.50), (2500000, 29400.00, 9.90), ('inf', 474900.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 769, 5.77, 2.70), + ( 962, 16.15, 3.40), + ( 1154, 22.69, 4.30), + ( 2885, 30.96, 5.60), + ( 9615, 127.88, 6.50), + ( 96154, 565.38, 9.90), + ( 'inf', 9132.69, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1538, 11.54, 2.70), + ( 1923, 32.31, 3.40), + ( 2308, 45.38, 4.30), + ( 5769, 61.92, 5.60), + ( 19231, 255.77, 6.50), + (192308, 1130.77, 9.90), + ( 'inf', 18265.38, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1667, 12.50, 2.70), + ( 2083, 35.00, 3.40), + ( 2500, 49.17, 4.30), + ( 6250, 67.08, 5.60), + ( 20833, 277.08, 6.50), + (208333, 1225.00, 9.90), + ( 'inf', 19787.50, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 3333, 25.00, 2.70), + ( 4167, 70.00, 3.40), + ( 5000, 98.33, 4.00), + ( 12500, 134.17, 5.60), + ( 41667, 554.17, 6.50), + (416667, 2450.00, 9.90), + ( 'inf', 39575.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 10000, 75.00, 2.07), + ( 12500, 210.00, 3.40), + ( 15000, 295.00, 4.30), + ( 37500, 402.50, 5.60), + ( 125000, 1662.50, 6.50), + (1250000, 7350.00, 9.90), + ( 'inf', 118725.00, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 20000, 150.00, 2.70), + ( 25000, 420.00, 3.40), + ( 30000, 590.00, 4.30), + ( 75000, 805.00, 5.60), + ( 250000, 3325.00, 6.50), + (2500000, 14700.00, 9.90), + ( 'inf', 237450.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 40000, 300.00, 2.70), + ( 50000, 840.00, 3.40), + ( 60000, 1180.00, 4.30), + ( 150000, 1610.00, 5.60), + ( 250000, 6650.00, 6.50), + (2500000, 29400.00, 9.90), + ( 'inf', 474900.00, 11.80), + ), }, 'E': { - 'weekly': ((385, 0.0, 1.50), (673, 5.77, 2.00), (1923, 11.54, 5.80), (9615, 84.04, 6.50), (96154, 584.04, 9.90), ('inf', 9151.35, 11.80)), - 'bi-weekly': ((769, 0.0, 1.50), (1346, 12.00, 2.00), (3846, 23.00, 5.80), (19231, 168.00, 6.50), (192308, 1168.00, 9.90), ('inf', 18303.00, 11.80)), - 'semi-monthly': ((833, 0.0, 1.50), (1458, 13.00, 2.00), (4167, 25.00, 5.80), (20833, 182.00, 6.50), (208333, 1265.00, 9.90), ('inf', 19828.00, 11.80)), - 'monthly': ((1667, 0.0, 1.50), (2916, 25.00, 2.00), (8333, 50.00, 5.80), (41667, 364.00, 6.50), (416667, 2531.00, 9.90), ('inf', 39656, 11.80)), - 'quarterly': ((5000, 0.0, 1.50), (8750, 75.00, 2.00), (25000, 150.00, 5.80), (125000, 1092.50, 6.50), (1250000, 7592.50, 9.90), ('inf', 118967.50, 11.80)), - 'semi-annual': ((10000, 0.0, 1.50), (17500, 150.00, 2.00), (50000, 300.00, 5.80), (250000, 2185.00, 6.50), (2500000, 15185.00, 9.90), ('inf', 237935.00, 11.80)), - 'annual': ((20000, 0.0, 1.50), (35000, 300.00, 2.00), (100000, 600.00, 5.80), (500000, 4370.00, 6.50), (5000000, 30370.00, 9.90), ('inf', 475870.00, 11.80)), + 'weekly': ( + ( 385, 0.00, 1.50), + ( 673, 5.77, 2.00), + ( 1923, 11.54, 5.80), + ( 9615, 84.04, 6.50), + ( 96154, 584.04, 9.90), + ( 'inf', 9151.35, 11.80), + ), + 'bi-weekly': ( + ( 769, 0.00, 1.50), + ( 1346, 12.00, 2.00), + ( 3846, 23.00, 5.80), + ( 19231, 168.00, 6.50), + (192308, 1168.00, 9.90), + ( 'inf', 18303.00, 11.80), + ), + 'semi-monthly': ( + ( 833, 0.00, 1.50), + ( 1458, 13.00, 2.00), + ( 4167, 25.00, 5.80), + ( 20833, 182.00, 6.50), + (208333, 1265.00, 9.90), + ( 'inf', 19828.00, 11.80), + ), + 'monthly': ( + ( 1667, 0.00, 1.50), + ( 2916, 25.00, 2.00), + ( 8333, 50.00, 5.80), + ( 41667, 364.00, 6.50), + (416667, 2531.00, 9.90), + ( 'inf', 39656.00, 11.80), + ), + 'quarterly': ( + ( 5000, 0.00, 1.50), + ( 8750, 75.00, 2.00), + ( 25000, 150.00, 5.80), + ( 125000, 1092.50, 6.50), + (1250000, 7592.50, 9.90), + ( 'inf', 118967.50, 11.80), + ), + 'semi-annual': ( + ( 10000, 0.00, 1.50), + ( 17500, 150.00, 2.00), + ( 50000, 300.00, 5.80), + ( 250000, 2185.00, 6.50), + (2500000, 15185.00, 9.90), + ( 'inf', 237935.00, 11.80), + ), + 'annual': ( + ( 20000, 0.00, 1.50), + ( 35000, 300.00, 2.00), + ( 100000, 600.00, 5.80), + ( 500000, 4370.00, 6.50), + (5000000, 30370.00, 9.90), + ( 'inf', 475870.00, 11.80), + ), }, } @@ -299,6 +888,7 @@ + { 'weekly': 19.20, diff --git a/l10n_us_hr_payroll/tests/test_us_nj_newjersey_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_nj_newjersey_payslip_2020.py index 79e0b861..1df4af6a 100755 --- a/l10n_us_hr_payroll/tests/test_us_nj_newjersey_payslip_2020.py +++ b/l10n_us_hr_payroll/tests/test_us_nj_newjersey_payslip_2020.py @@ -46,3 +46,6 @@ class TestUsNJPayslip(TestUsPayslip): self._test_sit(300.0, 'single', 1, 'weekly', date(2020, 1, 1), 4.21) self._test_sit(375.0, 'married_separate', 3, 'weekly', date(2020, 1, 1), 4.76) self._test_sit(1400.0, 'head_household', 3, 'weekly', date(2020, 1, 1), 27.60) + self._test_sit(1400.0, '', 3, 'weekly', date(2020, 1, 1), 0.00) + self._test_sit(2500.0, 'single', 3, 'bi-weekly', date(2020, 1, 1), 82.66) + self._test_sit(15000.0, 'married_joint', 2, 'monthly', date(2020, 1, 1), 844.85) From 98d0c5aa39ba7a32538578b20214fa27031f9e81 Mon Sep 17 00:00:00 2001 From: Bhoomi Vaishnani Date: Wed, 26 Aug 2020 15:16:24 -0400 Subject: [PATCH 59/63] [FIX] l10n_us_hr_payroll : Fixed exempt test case for 2019. --- l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2019.py | 2 +- l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2019.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2019.py index 61290314..33ddb2f9 100644 --- a/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2019.py +++ b/l10n_us_hr_payroll/tests/test_us_al_alabama_payslip_2019.py @@ -163,7 +163,7 @@ class TestUsALPayslip(TestUsPayslip): contract = self._createContract(employee, wage=salary, state_id=self.get_us_state('AL'), - al_a4_sit_exemptions='0', + al_a4_sit_exemptions='', state_income_tax_additional_withholding=0.0, state_income_tax_exempt=True, al_a4_sit_dependents=dependents, diff --git a/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2019.py index b407a079..98206965 100755 --- a/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2019.py +++ b/l10n_us_hr_payroll/tests/test_us_ga_georgia_payslip_2019.py @@ -114,7 +114,7 @@ class TestUsGAPayslip(TestUsPayslip): salary = 25000.00 schedule_pay = 'monthly' allowances = 2 - filing_status = 'exempt' + filing_status = '' additional_wh = 15.00 employee = self._createEmployee() From a0fdfbc854f61e66ed3209bd96fdd28d9b205b7a Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Fri, 4 Sep 2020 08:41:32 -0700 Subject: [PATCH 60/63] [IMP] l10n_us_hr_payroll: common test call paramaterize defaults for Structure Type and Resource Calendar --- l10n_us_hr_payroll/tests/common.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/l10n_us_hr_payroll/tests/common.py b/l10n_us_hr_payroll/tests/common.py index df6491a6..07615652 100755 --- a/l10n_us_hr_payroll/tests/common.py +++ b/l10n_us_hr_payroll/tests/common.py @@ -25,6 +25,8 @@ class TestUsPayslip(common.TransactionCase): def setUp(self): super(TestUsPayslip, self).setUp() self.env['ir.config_parameter'].set_param('hr_payroll.payslip.sum_behavior', 'date_to') + self.structure_type_id = self.ref('l10n_us_hr_payroll.structure_type_employee') + self.resource_calendar_id = self.ref('resource.resource_calendar_std') float_info = sys_float_info @@ -93,13 +95,13 @@ class TestUsPayslip(common.TransactionCase): if not contract_values.get('state'): contract_values['state'] = 'open' # Running if not contract_values.get('structure_type_id'): - contract_values['structure_type_id'] = self.ref('l10n_us_hr_payroll.structure_type_employee') + contract_values['structure_type_id'] = self.structure_type_id if not contract_values.get('date_start'): contract_values['date_start'] = '2016-01-01' if not contract_values.get('date_end'): contract_values['date_end'] = '2030-12-31' if not contract_values.get('resource_calendar_id'): - contract_values['resource_calendar_id'] = self.ref('resource.resource_calendar_std') + contract_values['resource_calendar_id'] = self.resource_calendar_id # Compatibility with earlier Odoo versions if not contract_values.get('journal_id') and hasattr(contract_model, 'journal_id'): From dd1c1a0c6d2f41bf2bb2b07d2d1fa603857e9816 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Fri, 18 Sep 2020 10:13:05 -0700 Subject: [PATCH 61/63] [FIX] l10n_us_hr_payroll: add missing `semi-monthly` as a default schedule pay --- l10n_us_hr_payroll/models/hr_contract.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/l10n_us_hr_payroll/models/hr_contract.py b/l10n_us_hr_payroll/models/hr_contract.py index 46bc42b7..68109908 100644 --- a/l10n_us_hr_payroll/models/hr_contract.py +++ b/l10n_us_hr_payroll/models/hr_contract.py @@ -6,6 +6,11 @@ from .us_payroll_config import FUTA_TYPE_NORMAL, \ FUTA_TYPE_EXEMPT +class HrPayrollStructure(models.Model): + _inherit = 'hr.payroll.structure.type' + default_schedule_pay = fields.Selection(selection_add=[('semi-monthly', 'Semi-monthly')]) + + class HrPayrollStructure(models.Model): _inherit = 'hr.payroll.structure' schedule_pay = fields.Selection(selection_add=[('semi-monthly', 'Semi-monthly')]) From dfc20b09ea19824ca5c49a0ce0074a2fdc9830c5 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 29 Sep 2020 14:39:11 -0700 Subject: [PATCH 62/63] [IMP] l10n_us_hr_payroll: Add migration code to handle known issues from Odoo S.A. migrations. --- .../migrations/13.0.0.0.1/post-migration.py | 30 +++++++++++++++++++ .../migrations/13.0.0.0.1/pre-migration.py | 26 ++++++++++++++++ l10n_us_hr_payroll/models/hr_contract.py | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 l10n_us_hr_payroll/migrations/13.0.0.0.1/post-migration.py create mode 100644 l10n_us_hr_payroll/migrations/13.0.0.0.1/pre-migration.py diff --git a/l10n_us_hr_payroll/migrations/13.0.0.0.1/post-migration.py b/l10n_us_hr_payroll/migrations/13.0.0.0.1/post-migration.py new file mode 100644 index 00000000..406055d7 --- /dev/null +++ b/l10n_us_hr_payroll/migrations/13.0.0.0.1/post-migration.py @@ -0,0 +1,30 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +import odoo + + +def migrate(cr, version): + """ + Post-migration no contracts will have any structure types. + Unfortunately, we have no way of knowing if they used USA in the past + so we have to just assume they did (knowing of course that l10n_us_hr_payroll was installed)... + """ + env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {}) + structure_type = env.ref('l10n_us_hr_payroll.structure_type_employee') + cr.execute("UPDATE hr_contract " + "SET structure_type_id = %s " + "WHERE structure_type_id is null AND state in ('draft', 'open')", (structure_type.id, )) + + """ + Additionally, it is known that post-migration databases will have bad + work entry record states (and you will spend time trying to fix them + before you could run a payroll batch). + """ + default_work_entry_type = env.ref('hr_work_entry.work_entry_type_attendance', raise_if_not_found=False) + if default_work_entry_type: + cr.execute("UPDATE hr_work_entry " + "SET work_entry_type_id = %s " + "WHERE work_entry_type_id is null", (default_work_entry_type.id, )) + cr.execute("UPDATE hr_work_entry " + "SET state = 'draft' " + "WHERE state = 'conflict'") diff --git a/l10n_us_hr_payroll/migrations/13.0.0.0.1/pre-migration.py b/l10n_us_hr_payroll/migrations/13.0.0.0.1/pre-migration.py new file mode 100644 index 00000000..e71317a4 --- /dev/null +++ b/l10n_us_hr_payroll/migrations/13.0.0.0.1/pre-migration.py @@ -0,0 +1,26 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +import odoo + + +def migrate(cr, version): + """ + Salary Rules can be archived by Odoo S.A. during migration. + This leaves them archived after the migration, and even un-archiving them + is not enough because they will then be pointed to a "migrated" structure. + """ + env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {}) + xml_refs = env['ir.model.data'].search([ + ('module', '=', 'l10n_us_hr_payroll'), + ('model', '=', 'hr.salary.rule'), + ]) + # I don't know why Odoo makes these non-updatable... + xml_refs.write({'noupdate': False}) + + rule_ids = xml_refs.mapped('res_id') + rules = env['hr.salary.rule'].browse(rule_ids) + rules.write({'active': True}) + + # Cannot add new selection type without fixing missing + cr.execute('UPDATE hr_payroll_structure SET schedule_pay = \'monthly\' WHERE schedule_pay is null;') + cr.execute('UPDATE hr_payroll_structure_type SET default_schedule_pay = \'monthly\' WHERE default_schedule_pay is null;') diff --git a/l10n_us_hr_payroll/models/hr_contract.py b/l10n_us_hr_payroll/models/hr_contract.py index 68109908..ab5772c8 100644 --- a/l10n_us_hr_payroll/models/hr_contract.py +++ b/l10n_us_hr_payroll/models/hr_contract.py @@ -6,7 +6,7 @@ from .us_payroll_config import FUTA_TYPE_NORMAL, \ FUTA_TYPE_EXEMPT -class HrPayrollStructure(models.Model): +class HrPayrollStructureType(models.Model): _inherit = 'hr.payroll.structure.type' default_schedule_pay = fields.Selection(selection_add=[('semi-monthly', 'Semi-monthly')]) From 7c267f9fa415424d6e8002d2ef5656c44dd5d2e3 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 29 Sep 2020 16:11:21 -0700 Subject: [PATCH 63/63] [FIX] l10n_us_hr_payroll: remove overwrite to correct wage calculation above --- l10n_us_hr_payroll/models/state/general.py | 1 - 1 file changed, 1 deletion(-) diff --git a/l10n_us_hr_payroll/models/state/general.py b/l10n_us_hr_payroll/models/state/general.py index 44d2aeb5..8979782f 100644 --- a/l10n_us_hr_payroll/models/state/general.py +++ b/l10n_us_hr_payroll/models/state/general.py @@ -102,7 +102,6 @@ def general_state_unemployment(payslip, categories, worked_days, inputs, wage_ba ytd_wage = suta_wage_ytd(payslip, categories) - wage = categories.GROSS + categories.DED_FUTA_EXEMPT return _general_rate(payslip, wage, ytd_wage, wage_base=wage_base, wage_start=wage_start, rate=rate)