diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py index f2d7f78d..7c651472 100755 --- a/l10n_us_hr_payroll/__manifest__.py +++ b/l10n_us_hr_payroll/__manifest__.py @@ -32,6 +32,7 @@ USA Payroll Rules. 'data/state/mt_montana.xml', 'data/state/oh_ohio.xml', 'data/state/pa_pennsylvania.xml', + 'data/state/tx_texas.xml', 'data/state/wa_washington.xml', 'data/final.xml', 'views/hr_contract_views.xml', diff --git a/l10n_us_hr_payroll/data/final.xml b/l10n_us_hr_payroll/data/final.xml index 6e855bd4..146fb073 100644 --- a/l10n_us_hr_payroll/data/final.xml +++ b/l10n_us_hr_payroll/data/final.xml @@ -29,6 +29,10 @@ ref('hr_payroll_rule_ee_us_pa_suta'), ref('hr_payroll_rule_ee_us_pa_sit'), + ref('hr_payroll_rule_er_us_tx_suta'), + ref('hr_payroll_rule_er_us_tx_suta_oa'), + ref('hr_payroll_rule_er_us_tx_suta_etia'), + ref('hr_payroll_rule_er_us_wa_suta'), ref('hr_payroll_rule_er_us_wa_fml'), ref('hr_payroll_rule_ee_us_wa_fml'), diff --git a/l10n_us_hr_payroll/data/state/tx_texas.xml b/l10n_us_hr_payroll/data/state/tx_texas.xml new file mode 100644 index 00000000..f8bed825 --- /dev/null +++ b/l10n_us_hr_payroll/data/state/tx_texas.xml @@ -0,0 +1,117 @@ + + + + + + US TX Texas SUTA Wage Base + us_tx_suta_wage_base + 9000.0 + + + + US TX Texas SUTA Wage Base + us_tx_suta_wage_base + 9000.0 + + + + + + + + US TX Texas SUTA Rate + us_tx_suta_rate + 2.7 + + + + US TX Texas SUTA Rate + us_tx_suta_rate + 2.7 + + + + + + + US TX Texas Obligation Assessment Rate + us_tx_suta_oa_rate + 0.0 + + + + US TX Texas Obligation Assessment Rate + us_tx_suta_oa_rate + 0.0 + + + + + + + US TX Texas Employment & Training Investment Assessment Rate + us_tx_suta_etia_rate + 0.1 + + + + US TX Texas Employment & Training Investment Assessment Rate + us_tx_suta_etia_rate + 0.1 + + + + + + + US Texas - Workforce Commission (Unemployment) + + + + US Texas - Workforce Commission (Unemployment) + + + + + + + + + + ER: US TX Texas State Unemployment (C-3) + ER_US_TX_SUTA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_rate', state_code='TX') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_rate', state_code='TX') + + + + + + + + ER: US TX Texas Obligation Assessment (C-3) + ER_US_TX_SUTA_OA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_oa_rate', state_code='TX') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_oa_rate', state_code='TX') + + + + + + + + ER: US TX Texas Employment & Training Investment Assessment (C-3) + ER_US_TX_SUTA_ETIA + python + result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_etia_rate', state_code='TX') + code + result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_tx_suta_wage_base', rate='us_tx_suta_etia_rate', state_code='TX') + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/migrations/data.py b/l10n_us_hr_payroll/migrations/data.py index c15c3749..02b90af2 100644 --- a/l10n_us_hr_payroll/migrations/data.py +++ b/l10n_us_hr_payroll/migrations/data.py @@ -59,6 +59,13 @@ XMLIDS_TO_REMOVE_2020 = [ 'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_unemp_wages_2018', 'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_inc_withhold_add', + 'l10n_us_tx_hr_payroll.contrib_register_txdor', + 'l10n_us_tx_hr_payroll.hr_payroll_tx_unemp_wages', + 'l10n_us_tx_hr_payroll.hr_payroll_tx_unemp', + 'l10n_us_tx_hr_payroll.hr_payroll_tx_oa', + 'l10n_us_tx_hr_payroll.hr_payroll_tx_etia', + 'l10n_us_tx_hr_payroll.hr_payroll_rules_tx_unemp_wages_2018', + 'l10n_us_wa_hr_payroll.hr_payroll_wa_unemp_wages', 'l10n_us_wa_hr_payroll.hr_payroll_wa_unemp', 'l10n_us_wa_hr_payroll.hr_payroll_wa_lni', @@ -107,6 +114,12 @@ XMLIDS_TO_RENAME_2020 = { 'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_unemp_company_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_pa_suta', 'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_inc_withhold_2018': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_pa_sit', + 'l10n_us_tx_hr_payroll.res_partner_txdor': 'l10n_us_hr_payroll.res_partner_us_tx_dor', + 'l10n_us_tx_hr_payroll.contrib_register_txdor': 'l10n_us_hr_payroll.contrib_register_us_tx_dor', + 'l10n_us_tx_hr_payroll.hr_payroll_rules_tx_unemp_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_tx_suta', + 'l10n_us_tx_hr_payroll.hr_payroll_rules_tx_oa_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_tx_suta_oa', + 'l10n_us_tx_hr_payroll.hr_payroll_rules_tx_etia_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_tx_suta_etia', + 'l10n_us_wa_hr_payroll.res_partner_wador_unemp': 'l10n_us_hr_payroll.res_partner_us_wa_dor', 'l10n_us_wa_hr_payroll.res_partner_wador_lni': 'l10n_us_hr_payroll.res_partner_us_wa_dor_lni', 'l10n_us_wa_hr_payroll.contrib_register_wador_unemp': 'l10n_us_hr_payroll.contrib_register_us_wa_dor', diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py index 7ffc630a..90d6dfef 100755 --- a/l10n_us_hr_payroll/tests/__init__.py +++ b/l10n_us_hr_payroll/tests/__init__.py @@ -16,5 +16,8 @@ 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_tx_texas_payslip_2019 +from . import test_us_tx_texas_payslip_2020 + from . import test_us_wa_washington_payslip_2019 from . import test_us_wa_washington_payslip_2020 diff --git a/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2019.py new file mode 100755 index 00000000..15e657ae --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2019.py @@ -0,0 +1,100 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from .common import TestUsPayslip, process_payslip +from odoo.addons.l10n_us_hr_payroll.models.hr_contract import USHRContract + +class TestUsTXPayslip(TestUsPayslip): + ### + # 2019 Taxes and Rates + ### + TX_UNEMP_MAX_WAGE = 9000.0 + TX_UNEMP = -2.7 / 100.0 + TX_OA = 0.0 + TX_ETIA = -0.1 / 100.0 + + def test_2019_taxes(self): + salary = 5000.0 + + employee = self._createEmployee() + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('TX'), + ) + + self._log('2019 Texas tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + rules = self._getRules(payslip) + + self.assertPayrollEqual(rules['ER_US_TX_SUTA'], salary * self.TX_UNEMP) + self.assertPayrollEqual(rules['ER_US_TX_SUTA_OA'], salary * self.TX_OA) + self.assertPayrollEqual(rules['ER_US_TX_SUTA_ETIA'], salary * self.TX_ETIA) + + process_payslip(payslip) + + # Make a new payslip, this one will have maximums + + remaining_tx_unemp_wages = self.TX_UNEMP_MAX_WAGE - salary if (self.TX_UNEMP_MAX_WAGE - 2*salary < salary) \ + else salary + + self._log('2019 Texas tax second payslip:') + payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + rules = self._getRules(payslip) + + self.assertPayrollEqual(rules['ER_US_TX_SUTA'], remaining_tx_unemp_wages * self.TX_UNEMP) + + def test_2019_taxes_with_external(self): + salary = 5000.0 + external_wages = 6000.0 + + employee = self._createEmployee() + + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('TX'), + external_wages=external_wages, + ) + + self._log('2019 Texas_external tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + rules = self._getRules(payslip) + + expected_wage = self.TX_UNEMP_MAX_WAGE - external_wages + self.assertPayrollEqual(rules['ER_US_TX_SUTA'], expected_wage * self.TX_UNEMP) + self.assertPayrollEqual(rules['ER_US_TX_SUTA_OA'], expected_wage * self.TX_OA) + self.assertPayrollEqual(rules['ER_US_TX_SUTA_ETIA'], expected_wage * self.TX_ETIA) + + def test_2019_taxes_with_state_exempt(self): + salary = 5000.0 + external_wages = 6000.0 + + employee = self._createEmployee() + + contract = self._createContract(employee, + wage=salary, + state_id=self.get_us_state('TX'), + external_wages=external_wages, + futa_type=USHRContract.FUTA_TYPE_BASIC) + + self._log('2019 Texas_external tax first payslip:') + payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + rules = self._getRules(payslip) + + self.assertPayrollEqual(rules.get('ER_US_TX_SUTA', 0.0), 0.0) + self.assertPayrollEqual(rules.get('ER_US_TX_SUTA_OA', 0.0), 0.0) + self.assertPayrollEqual(rules.get('ER_US_TX_SUTA_ETIA', 0.0), 0.0) diff --git a/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2020.py new file mode 100755 index 00000000..8dba312c --- /dev/null +++ b/l10n_us_hr_payroll/tests/test_us_tx_texas_payslip_2020.py @@ -0,0 +1,17 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from datetime import date +from .common import TestUsPayslip + +class TestUsTXPayslip(TestUsPayslip): + ### + # 2020 Taxes and Rates + ### + TX_UNEMP_MAX_WAGE = 9000.0 + TX_UNEMP = 2.7 + TX_OA = 0.0 + TX_ETIA = 0.1 + + def test_2020_taxes(self): + combined_rate = self.TX_UNEMP + self.TX_OA + self.TX_ETIA + self._test_er_suta('TX', combined_rate, date(2020, 1, 1), wage_base=self.TX_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 f47e18fe..fefcc61e 100644 --- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -63,6 +63,9 @@ + +

No additional fields.

+

No additional fields.

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