From 5c7c9e639775ff30fb531fee23feb5257059f2cf Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Sun, 5 Jan 2020 14:07:26 -0800 Subject: [PATCH] NEW `l10n_us_hr_payroll` Initiall commit for Odoo 13 (rewrite) and 2020 Federal Rates (including new W4) --- l10n_us_hr_payroll/__init__.py | 3 + l10n_us_hr_payroll/__manifest__.py | 35 ++ l10n_us_hr_payroll/data/base.xml | 20 + .../data/federal/fed_940_futa_parameters.xml | 38 ++ .../data/federal/fed_940_futa_rules.xml | 34 ++ .../data/federal/fed_941_fica_parameters.xml | 88 +++ .../data/federal/fed_941_fica_rules.xml | 100 ++++ .../data/federal/fed_941_fit_parameters.xml | 504 ++++++++++++++++++ .../data/federal/fed_941_fit_rules.xml | 29 + l10n_us_hr_payroll/data/integration_rules.xml | 29 + l10n_us_hr_payroll/models/__init__.py | 5 + l10n_us_hr_payroll/models/federal/__init__.py | 1 + l10n_us_hr_payroll/models/federal/fed_940.py | 37 ++ l10n_us_hr_payroll/models/federal/fed_941.py | 239 +++++++++ l10n_us_hr_payroll/models/hr_contract.py | 28 + l10n_us_hr_payroll/models/hr_payslip.py | 48 ++ .../models/us_payroll_config.py | 45 ++ .../security/ir.model.access.csv | 2 + .../static/description/icon.png | Bin 0 -> 8776 bytes l10n_us_hr_payroll/tests/__init__.py | 5 + l10n_us_hr_payroll/tests/common.py | 150 ++++++ .../tests/test_us_payslip_2019.py | 338 ++++++++++++ .../tests/test_us_payslip_2020.py | 302 +++++++++++ .../views/hr_contract_views.xml | 19 + .../views/us_payroll_config_views.xml | 75 +++ 25 files changed, 2174 insertions(+) create mode 100644 l10n_us_hr_payroll/__init__.py create mode 100644 l10n_us_hr_payroll/__manifest__.py create mode 100644 l10n_us_hr_payroll/data/base.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_940_futa_parameters.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_940_futa_rules.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_941_fica_parameters.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_941_fica_rules.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_941_fit_parameters.xml create mode 100644 l10n_us_hr_payroll/data/federal/fed_941_fit_rules.xml create mode 100644 l10n_us_hr_payroll/data/integration_rules.xml create mode 100644 l10n_us_hr_payroll/models/__init__.py create mode 100644 l10n_us_hr_payroll/models/federal/__init__.py create mode 100644 l10n_us_hr_payroll/models/federal/fed_940.py create mode 100644 l10n_us_hr_payroll/models/federal/fed_941.py create mode 100644 l10n_us_hr_payroll/models/hr_contract.py create mode 100644 l10n_us_hr_payroll/models/hr_payslip.py create mode 100644 l10n_us_hr_payroll/models/us_payroll_config.py create mode 100644 l10n_us_hr_payroll/security/ir.model.access.csv create mode 100644 l10n_us_hr_payroll/static/description/icon.png create mode 100755 l10n_us_hr_payroll/tests/__init__.py create mode 100755 l10n_us_hr_payroll/tests/common.py create mode 100644 l10n_us_hr_payroll/tests/test_us_payslip_2019.py create mode 100644 l10n_us_hr_payroll/tests/test_us_payslip_2020.py create mode 100644 l10n_us_hr_payroll/views/hr_contract_views.xml create mode 100644 l10n_us_hr_payroll/views/us_payroll_config_views.xml diff --git a/l10n_us_hr_payroll/__init__.py b/l10n_us_hr_payroll/__init__.py new file mode 100644 index 00000000..09434554 --- /dev/null +++ b/l10n_us_hr_payroll/__init__.py @@ -0,0 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from . import models diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py new file mode 100644 index 00000000..a748aae6 --- /dev/null +++ b/l10n_us_hr_payroll/__manifest__.py @@ -0,0 +1,35 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +{ + 'name': 'United States of America - Payroll', + 'author': 'Hibou Corp. ', + 'version': '13.0.2020.0.0', + 'category': 'Payroll Localization', + 'depends': [ + 'hr_payroll', + 'hr_contract_reports', + ], + 'description': """ +United States of America - Payroll Rules. +========================================= + + """, + + 'data': [ + 'security/ir.model.access.csv', + 'data/base.xml', + 'data/integration_rules.xml', + 'data/federal/fed_940_futa_parameters.xml', + 'data/federal/fed_940_futa_rules.xml', + 'data/federal/fed_941_fica_parameters.xml', + 'data/federal/fed_941_fica_rules.xml', + 'data/federal/fed_941_fit_parameters.xml', + 'data/federal/fed_941_fit_rules.xml', + 'views/hr_contract_views.xml', + 'views/us_payroll_config_views.xml', + ], + 'demo': [ + ], + 'auto_install': False, + 'license': 'OPL-1', +} diff --git a/l10n_us_hr_payroll/data/base.xml b/l10n_us_hr_payroll/data/base.xml new file mode 100644 index 00000000..6838f283 --- /dev/null +++ b/l10n_us_hr_payroll/data/base.xml @@ -0,0 +1,20 @@ + + + + + USA Employee + + + + + + USA Employee Standard + + + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_940_futa_parameters.xml b/l10n_us_hr_payroll/data/federal/fed_940_futa_parameters.xml new file mode 100644 index 00000000..9c34afb6 --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_940_futa_parameters.xml @@ -0,0 +1,38 @@ + + + + + Federal 940 FUTA Wage Base + fed_940_futa_wage_base + + + + 7000.00 + + + + + + + Federal 940 FUTA Rate Basic + fed_940_futa_rate_basic + + + + 6.0 + + + + + + Federal 940 FUTA Rate Normal + fed_940_futa_rate_normal + + + + 0.6 + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_940_futa_rules.xml b/l10n_us_hr_payroll/data/federal/fed_940_futa_rules.xml new file mode 100644 index 00000000..5b315100 --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_940_futa_rules.xml @@ -0,0 +1,34 @@ + + + + + US Federal 940 - EFTPS + + + + ER: Federal 940 FUTA + ER_US_940_FUTA + + + + + + WAGE: Federal 940 FUTA Exempt + WAGE_US_940_FUTA_EXEMPT + + + + + + + ER: US FUTA Federal Unemployment + ER_US_940_FUTA + python + result, _ = er_us_940_futa(payslip, categories, worked_days, inputs) + code + result, result_rate = er_us_940_futa(payslip, categories, worked_days, inputs) + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_941_fica_parameters.xml b/l10n_us_hr_payroll/data/federal/fed_941_fica_parameters.xml new file mode 100644 index 00000000..1be404bb --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_941_fica_parameters.xml @@ -0,0 +1,88 @@ + + + + + + Federal 941 FICA Social Security Wage Base + fed_941_fica_ss_wage_base + + + + 128400.0 + + + + + 132900.0 + + + + + 137700.0 + + + + + + + Federal 941 FICA Rate + fed_941_fica_ss_rate + + + + 6.2 + + + + + + + + Federal 941 FICA Medicare Wage Base + fed_941_fica_m_wage_base + + + + "inf" + + + + + + + Federal 941 FICA Rate + fed_941_fica_m_rate + + + + 1.45 + + + + + + + + Federal 941 FICA Medicare Additional Wage Start + fed_941_fica_m_add_wage_start + + + + 200000.0 + + + + + + + Federal 941 FICA Medicare Additional Rate + fed_941_fica_m_add_rate + + + + 0.9 + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_941_fica_rules.xml b/l10n_us_hr_payroll/data/federal/fed_941_fica_rules.xml new file mode 100644 index 00000000..324958a4 --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_941_fica_rules.xml @@ -0,0 +1,100 @@ + + + + + US Federal 941 - EFTPS + + + + EE: Federal 941 FICA + EE_US_941_FICA + + + + + ER: Federal 941 FICA + ER_US_941_FICA + + + + + + WAGE: Federal 941 FICA Exempt + WAGE_US_941_FICA_EXEMPT + + + + + + + + + EE: US FICA Social Security + EE_US_941_FICA_SS + python + result, _ = ee_us_941_fica_ss(payslip, categories, worked_days, inputs) + code + result, result_rate = ee_us_941_fica_ss(payslip, categories, worked_days, inputs) + + + + + + + + + ER: US FICA Social Security + ER_US_941_FICA_SS + python + result, _ = er_us_941_fica_ss(payslip, categories, worked_days, inputs) + code + result, result_rate = er_us_941_fica_ss(payslip, categories, worked_days, inputs) + + + + + + + + + + EE: US FICA Medicare + EE_US_941_FICA_M + python + result, _ = ee_us_941_fica_m(payslip, categories, worked_days, inputs) + code + result, result_rate = ee_us_941_fica_m(payslip, categories, worked_days, inputs) + + + + + + + + + ER: US FICA Medicare + ER_US_941_FICA_M + python + result, _ = er_us_941_fica_m(payslip, categories, worked_days, inputs) + code + result, result_rate = er_us_941_fica_m(payslip, categories, worked_days, inputs) + + + + + + + + + + EE: US FICA Medicare Additional + EE_US_941_FICA_M_ADD + python + result, _ = ee_us_941_fica_m_add(payslip, categories, worked_days, inputs) + code + result, result_rate = ee_us_941_fica_m_add(payslip, categories, worked_days, inputs) + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_941_fit_parameters.xml b/l10n_us_hr_payroll/data/federal/fed_941_fit_parameters.xml new file mode 100644 index 00000000..97753e5a --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_941_fit_parameters.xml @@ -0,0 +1,504 @@ + + + + + + Federal 941 FIT Allowance + fed_941_fit_allowance + + + + + { + 'weekly': 80.80, + 'bi-weekly': 161.50, + 'semi-monthly': 175.00, + 'monthly': 350.00, + 'quarterly': 1050.00, + 'semi-annually': 2100.00, + 'annually': 4200.00, + } + + + + + { + 'weekly': 80.80, + 'bi-weekly': 161.50, + 'semi-monthly': 175.00, + 'monthly': 350.00, + 'quarterly': 1050.00, + 'semi-annually': 2100.00, + 'annually': 4200.00, + } + + + + + + 4300.0 + + + + + + Federal 941 FIT NRA Additional + fed_941_fit_nra_additional + + + + + { + 'weekly': 153.80, + 'bi-weekly': 307.70, + 'semi-monthly': 333.30, + 'monthly': 666.70, + 'quarterly': 2000.00, + 'semi-annually': 4000.00, + 'annually': 8000.00, + } + + + + + { + 'weekly': 153.80, + 'bi-weekly': 307.70, + 'semi-monthly': 333.30, + 'monthly': 666.70, + 'quarterly': 2000.00, + 'semi-annually': 4000.00, + 'annually': 8000.00, + } + + + + + { + 'weekly': 238.50, + 'bi-weekly': 476.90, + 'semi-monthly': 516.70, + 'monthly': 1033.30, + 'quarterly': 3100.00, + 'semi-annually': 6200.00, + 'annually': 12400.00, + } + + + + + + + Federal 941 FIT Table Single + fed_941_fit_table_single + + + + + + { + 'weekly': [ + ( 73.00, 0.00, 0), + ( 260.00, 0.00, 10), + ( 832.00, 18.70, 12), + ( 1692.00, 87.34, 22), + ( 3164.00, 276.54, 24), + ( 3998.00, 629.82, 32), + ( 9887.00, 896.70, 35), + ( 'inf', 2957.85, 37), + ], + 'bi-weekly': [ + ( 146.00, 0.00, 0), + ( 519.00, 0.00, 10), + ( 1664.00, 37.30, 12), + ( 3385.00, 174.70, 22), + ( 6328.00, 553.32, 24), + ( 7996.00, 1259.64, 32), + ( 19773.00, 1793.40, 35), + ( 'inf', 5915.35, 37), + ], + 'semi-monthly': [ + ( 158.00, 0.00, 0), + ( 563.00, 0.00, 10), + ( 1803.00, 40.50, 12), + ( 3667.00, 189.30, 22), + ( 6855.00, 599.38, 24), + ( 8663.00, 1364.50, 32), + ( 21421.00, 1943.06, 35), + ( 'inf', 6408.36, 37), + ], + 'monthly': [ + ( 317.00, 0.00, 0), + ( 1125.00, 0.00, 10), + ( 3606.00, 80.80, 12), + ( 7333.00, 378.52, 22), + ( 13710.00, 1198.46, 24), + ( 17325.00, 2728.94, 32), + ( 42842.00, 3885.74, 35), + ( 'inf', 12816.69, 37), + ], + 'quarterly': [ + ( 950.00, 0.00, 0), + ( 3375.00, 0.00, 10), + ( 10819.00, 242.50, 12), + ( 22000.00, 1135.78, 22), + ( 41131.00, 3595.60, 24), + ( 51975.00, 8187.04, 32), + ( 128525.00, 11657.12, 35), + ( 'inf', 38449.62, 37), + ], + 'semi-annually': [ + ( 1900.00, 0.00, 0), + ( 6750.00, 0.00, 10), + ( 21638.00, 485.00, 12), + ( 44000.00, 2271.56, 22), + ( 82263.00, 7191.20, 24), + ( 103950.00, 16374.32, 32), + ( 257050.00, 23314.16, 35), + ( 'inf', 76899.16, 37), + ], + 'annually': [ + ( 3800.00, 0.00, 0), + ( 13500.00, 0.00, 10), + ( 43275.00, 970.00, 12), + ( 88000.00, 4543.00, 22), + ( 164525.00, 14382.50, 24), + ( 207900.00, 32748.50, 32), + ( 514100.00, 46628.50, 35), + ( 'inf', 153798.50, 37), + ], + } + + + + + + { + 'weekly': [ + ( 73.00, 0.00, 0), + ( 260.00, 0.00, 10), + ( 832.00, 18.70, 12), + ( 1692.00, 87.34, 22), + ( 3164.00, 276.54, 24), + ( 3998.00, 629.82, 32), + ( 9887.00, 896.70, 35), + ( 'inf', 2957.85, 37), + ], + 'bi-weekly': [ + ( 146.00, 0.00, 0), + ( 519.00, 0.00, 10), + ( 1664.00, 37.30, 12), + ( 3385.00, 174.70, 22), + ( 6328.00, 553.32, 24), + ( 7996.00, 1259.64, 32), + ( 19773.00, 1793.40, 35), + ( 'inf', 5915.35, 37), + ], + 'semi-monthly': [ + ( 158.00, 0.00, 0), + ( 563.00, 0.00, 10), + ( 1803.00, 40.50, 12), + ( 3667.00, 189.30, 22), + ( 6855.00, 599.38, 24), + ( 8663.00, 1364.50, 32), + ( 21421.00, 1943.06, 35), + ( 'inf', 6408.36, 37), + ], + 'monthly': [ + ( 317.00, 0.00, 0), + ( 1125.00, 0.00, 10), + ( 3606.00, 80.80, 12), + ( 7333.00, 378.52, 22), + ( 13710.00, 1198.46, 24), + ( 17325.00, 2728.94, 32), + ( 42842.00, 3885.74, 35), + ( 'inf', 12816.69, 37), + ], + 'quarterly': [ + ( 950.00, 0.00, 0), + ( 3375.00, 0.00, 10), + ( 10819.00, 242.50, 12), + ( 22000.00, 1135.78, 22), + ( 41131.00, 3595.60, 24), + ( 51975.00, 8187.04, 32), + ( 128525.00, 11657.12, 35), + ( 'inf', 38449.62, 37), + ], + 'semi-annually': [ + ( 1900.00, 0.00, 0), + ( 6750.00, 0.00, 10), + ( 21638.00, 485.00, 12), + ( 44000.00, 2271.56, 22), + ( 82263.00, 7191.20, 24), + ( 103950.00, 16374.32, 32), + ( 257050.00, 23314.16, 35), + ( 'inf', 76899.16, 37), + ], + 'annually': [ + ( 3800.00, 0.00, 0), + ( 13500.00, 0.00, 10), + ( 43275.00, 970.00, 12), + ( 88000.00, 4543.00, 22), + ( 164525.00, 14382.50, 24), + ( 207900.00, 32748.50, 32), + ( 514100.00, 46628.50, 35), + ( 'inf', 153798.50, 37), + ], + } + + + + + + + { + 'standard': [ + ( 0.00, 0.00, 0.00), + ( 3800.00, 0.00, 0.10), + ( 13675.00, 987.50, 0.12), + ( 43925.00, 4617.50, 0.22), + ( 89325.00, 14605.50, 0.24), + ( 167100.00, 33271.50, 0.32), + ( 211150.00, 47367.50, 0.35), + ( 522200.00, 156235.00, 0.37), + ], + 'higher': [ + ( 0.00, 0.00, 0.00), + ( 6200.00, 0.00, 0.10), + ( 11138.00, 493.75, 0.12), + ( 26263.00, 2308.75, 0.22), + ( 48963.00, 7302.75, 0.24), + ( 87850.00, 16635.75, 0.32), + ( 109875.00, 23683.75, 0.35), + ( 265400.00, 78117.50, 0.37), + ], + } + + + + + + + Federal 941 FIT Table Married + fed_941_fit_table_married + + + + + + { + 'weekly': [ + ( 227.00, 0.00, 0), + ( 600.00, 0.00, 10), + ( 1745.00, 37.30, 12), + ( 3465.00, 174.70, 22), + ( 6409.00, 553.10, 24), + ( 8077.00, 1259.66, 32), + ( 12003.00, 1793.42, 35), + ( 'inf', 3167.52, 37), + ], + 'bi-weekly': [ + ( 454.00, 0.00, 0), + ( 1200.00, 0.00, 10), + ( 3490.00, 74.60, 12), + ( 6931.00, 349.40, 22), + ( 12817.00, 1106.42, 24), + ( 16154.00, 2519.06, 32), + ( 24006.00, 3586.90, 35), + ( 'inf', 6335.10, 37), + ], + 'semi-monthly': [ + ( 492.00, 0.00, 0), + ( 1300.00, 0.00, 10), + ( 3781.00, 80.80, 12), + ( 7508.00, 378.52, 22), + ( 13885.00, 1198.46, 24), + ( 17500.00, 2728.94, 32), + ( 26006.00, 3885.74, 35), + ( 'inf', 6862.84, 37), + ], + 'monthly': [ + ( 983.00, 0.00, 0), + ( 2600.00, 0.00, 10), + ( 7563.00, 161.70, 12), + ( 15017.00, 757.26, 22), + ( 27771.00, 2397.14, 24), + ( 35000.00, 5458.10, 32), + ( 52013.00, 7771.38, 35), + ( 'inf', 13725.93, 37), + ], + 'quarterly': [ + ( 2950.00, 0.00, 0), + ( 7800.00, 0.00, 10), + ( 22688.00, 485.00, 12), + ( 45050.00, 2271.56, 22), + ( 83313.00, 7191.20, 24), + ( 105000.00, 16374.32, 32), + ( 156038.00, 23314.16, 35), + ( 'inf', 41177.46, 37), + ], + 'semi-annually': [ + ( 5900.00, 0.00, 0), + ( 15600.00, 0.00, 10), + ( 45375.00, 970.00, 12), + ( 90100.00, 4543.00, 22), + ( 166625.00, 14382.50, 24), + ( 210000.00, 32748.50, 32), + ( 312075.00, 46628.50, 35), + ( 'inf', 82354.75, 37), + ], + 'annually': [ + ( 11800.00, 0.00, 0), + ( 31200.00, 0.00, 10), + ( 90750.00, 1940.00, 12), + ( 180200.00, 9086.00, 22), + ( 333250.00, 28765.00, 24), + ( 420000.00, 65497.00, 32), + ( 624150.00, 93257.00, 35), + ( 'inf', 164709.50, 37), + ], + } + + + + + + { + 'weekly': [ + ( 227.00, 0.00, 0), + ( 600.00, 0.00, 10), + ( 1745.00, 37.30, 12), + ( 3465.00, 174.70, 22), + ( 6409.00, 553.10, 24), + ( 8077.00, 1259.66, 32), + ( 12003.00, 1793.42, 35), + ( 'inf', 3167.52, 37), + ], + 'bi-weekly': [ + ( 454.00, 0.00, 0), + ( 1200.00, 0.00, 10), + ( 3490.00, 74.60, 12), + ( 6931.00, 349.40, 22), + ( 12817.00, 1106.42, 24), + ( 16154.00, 2519.06, 32), + ( 24006.00, 3586.90, 35), + ( 'inf', 6335.10, 37), + ], + 'semi-monthly': [ + ( 492.00, 0.00, 0), + ( 1300.00, 0.00, 10), + ( 3781.00, 80.80, 12), + ( 7508.00, 378.52, 22), + ( 13885.00, 1198.46, 24), + ( 17500.00, 2728.94, 32), + ( 26006.00, 3885.74, 35), + ( 'inf', 6862.84, 37), + ], + 'monthly': [ + ( 983.00, 0.00, 0), + ( 2600.00, 0.00, 10), + ( 7563.00, 161.70, 12), + ( 15017.00, 757.26, 22), + ( 27771.00, 2397.14, 24), + ( 35000.00, 5458.10, 32), + ( 52013.00, 7771.38, 35), + ( 'inf', 13725.93, 37), + ], + 'quarterly': [ + ( 2950.00, 0.00, 0), + ( 7800.00, 0.00, 10), + ( 22688.00, 485.00, 12), + ( 45050.00, 2271.56, 22), + ( 83313.00, 7191.20, 24), + ( 105000.00, 16374.32, 32), + ( 156038.00, 23314.16, 35), + ( 'inf', 41177.46, 37), + ], + 'semi-annually': [ + ( 5900.00, 0.00, 0), + ( 15600.00, 0.00, 10), + ( 45375.00, 970.00, 12), + ( 90100.00, 4543.00, 22), + ( 166625.00, 14382.50, 24), + ( 210000.00, 32748.50, 32), + ( 312075.00, 46628.50, 35), + ( 'inf', 82354.75, 37), + ], + 'annually': [ + ( 11800.00, 0.00, 0), + ( 31200.00, 0.00, 10), + ( 90750.00, 1940.00, 12), + ( 180200.00, 9086.00, 22), + ( 333250.00, 28765.00, 24), + ( 420000.00, 65497.00, 32), + ( 624150.00, 93257.00, 35), + ( 'inf', 164709.50, 37), + ], + } + + + + + + + { + 'standard': [ + ( 0.00, 0.00, 0.00), + ( 11900.00, 0.00, 0.10), + ( 31650.00, 1975.00, 0.12), + ( 92150.00, 9235.00, 0.22), + ( 182950.00, 29211.00, 0.24), + ( 338500.00, 66543.00, 0.32), + ( 426600.00, 94735.00, 0.35), + ( 633950.00, 167307.50, 0.37), + ], + 'higher': [ + ( 0.00, 0.00, 0.00), + ( 12400.00, 0.00, 0.10), + ( 22275.00, 987.50, 0.12), + ( 52525.00, 4617.50, 0.22), + ( 97925.00, 14605.50, 0.24), + ( 175700.00, 33271.50, 0.32), + ( 219750.00, 47367.50, 0.35), + ( 323425.00, 83653.75, 0.37), + ], + } + + + + + + Federal 941 FIT Table Head of Household + fed_941_fit_table_hh + + + + + + { + 'standard': [ + ( 0.00, 0.00, 0.00), + ( 10050.00, 0.00, 0.10), + ( 24150.00, 1410.00, 0.12), + ( 63750.00, 6162.00, 0.22), + ( 95550.00, 13158.00, 0.24), + ( 173350.00, 31830.00, 0.32), + ( 217400.00, 45926.00, 0.35), + ( 528450.00, 154793.50, 0.37), + ], + 'higher': [ + ( 0.00, 0.00, 0.00), + ( 9325.00, 0.00, 0.10), + ( 16375.00, 705.00, 0.12), + ( 36175.00, 3081.00, 0.22), + ( 52075.00, 6579.00, 0.24), + ( 90975.00, 15915.00, 0.32), + ( 113000.00, 22963.00, 0.35), + ( 268525.00, 77396.75, 0.37), + ], + } + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/federal/fed_941_fit_rules.xml b/l10n_us_hr_payroll/data/federal/fed_941_fit_rules.xml new file mode 100644 index 00000000..a7751adf --- /dev/null +++ b/l10n_us_hr_payroll/data/federal/fed_941_fit_rules.xml @@ -0,0 +1,29 @@ + + + + + WAGE: Federal 941 Income Tax Exempt + WAGE_US_941_FIT_EXEMPT + + + + EE: Federal 941 Income Tax Withholding + EE_US_941_FIT + + + + + + + + EE: US Federal Income Tax Withholding + EE_US_941_FIT + python + result, _ = ee_us_941_fit(payslip, categories, worked_days, inputs) + code + result, result_rate = ee_us_941_fit(payslip, categories, worked_days, inputs) + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/data/integration_rules.xml b/l10n_us_hr_payroll/data/integration_rules.xml new file mode 100644 index 00000000..9991a3aa --- /dev/null +++ b/l10n_us_hr_payroll/data/integration_rules.xml @@ -0,0 +1,29 @@ + + + + + python + result = inputs.COMMISSION.amount > 0.0 if inputs.COMMISSION else False + code + result = inputs.COMMISSION.amount if inputs.COMMISSION else 0 + BASIC_COM + + Commissions + + + + + + + python + result = inputs.BADGES.amount > 0.0 if inputs.BADGES else False + code + result = inputs.BADGES.amount if inputs.BADGES else 0 + BASIC_BADGES + + Badges + + + + + \ No newline at end of file diff --git a/l10n_us_hr_payroll/models/__init__.py b/l10n_us_hr_payroll/models/__init__.py new file mode 100644 index 00000000..c6d607ff --- /dev/null +++ b/l10n_us_hr_payroll/models/__init__.py @@ -0,0 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from . import hr_contract +from . import hr_payslip +from . import us_payroll_config diff --git a/l10n_us_hr_payroll/models/federal/__init__.py b/l10n_us_hr_payroll/models/federal/__init__.py new file mode 100644 index 00000000..0358305d --- /dev/null +++ b/l10n_us_hr_payroll/models/federal/__init__.py @@ -0,0 +1 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. diff --git a/l10n_us_hr_payroll/models/federal/fed_940.py b/l10n_us_hr_payroll/models/federal/fed_940.py new file mode 100644 index 00000000..1cf042c7 --- /dev/null +++ b/l10n_us_hr_payroll/models/federal/fed_940.py @@ -0,0 +1,37 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +def er_us_940_futa(payslip, categories, worked_days, inputs): + """ + Returns FUTA eligible wage and rate. + WAGE = GROSS - WAGE_US_940_FUTA_EXEMPT + :return: result, result_rate (wage, percent) + """ + + # Determine Rate. + if payslip.contract_id.futa_type == payslip.contract_id.FUTA_TYPE_EXEMPT: + # Exit early + return 0.0, 0.0 + elif payslip.contract_id.futa_type == payslip.contract_id.FUTA_TYPE_BASIC: + result_rate = -payslip.rule_parameter('fed_940_futa_rate_basic') + else: + result_rate = -payslip.rule_parameter('fed_940_futa_rate_normal') + + # Determine Wage + year = payslip.dict.get_year() + ytd_wage = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage -= payslip.sum_category('WAGE_US_940_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage += payslip.contract_id.external_wages + + wage_base = payslip.rule_parameter('fed_940_futa_wage_base') + remaining = wage_base - ytd_wage + + wage = categories.GROSS - categories.WAGE_US_940_FUTA_EXEMPT + + if remaining < 0.0: + result = 0.0 + elif remaining < wage: + result = remaining + else: + result = wage + + return result, result_rate diff --git a/l10n_us_hr_payroll/models/federal/fed_941.py b/l10n_us_hr_payroll/models/federal/fed_941.py new file mode 100644 index 00000000..e6288f88 --- /dev/null +++ b/l10n_us_hr_payroll/models/federal/fed_941.py @@ -0,0 +1,239 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +# import logging +# _logger = logging.getLogger(__name__) + + +def ee_us_941_fica_ss(payslip, categories, worked_days, inputs): + """ + Returns FICA Social Security eligible wage and rate. + WAGE = GROSS - WAGE_US_941_FICA_EXEMPT + :return: result, result_rate (wage, percent) + """ + exempt = payslip.contract_id.us_payroll_config_value('fed_941_fica_exempt') + if exempt: + return 0.0, 0.0 + + # Determine Rate. + result_rate = -payslip.rule_parameter('fed_941_fica_ss_rate') + + # Determine Wage + year = payslip.dict.get_year() + ytd_wage = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage -= payslip.sum_category('WAGE_US_941_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage += payslip.contract_id.external_wages + + wage_base = payslip.rule_parameter('fed_941_fica_ss_wage_base') + remaining = wage_base - ytd_wage + + wage = categories.GROSS - categories.WAGE_US_941_FICA_EXEMPT + + if remaining < 0.0: + result = 0.0 + elif remaining < wage: + result = remaining + else: + result = wage + + return result, result_rate + + +er_us_941_fica_ss = ee_us_941_fica_ss + + +def ee_us_941_fica_m(payslip, categories, worked_days, inputs): + """ + Returns FICA Medicare eligible wage and rate. + WAGE = GROSS - WAGE_US_941_FICA_EXEMPT + :return: result, result_rate (wage, percent) + """ + exempt = payslip.contract_id.us_payroll_config_value('fed_941_fica_exempt') + if exempt: + return 0.0, 0.0 + + # Determine Rate. + result_rate = -payslip.rule_parameter('fed_941_fica_m_rate') + + # Determine Wage + year = payslip.dict.get_year() + ytd_wage = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage -= payslip.sum_category('WAGE_US_941_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage += payslip.contract_id.external_wages + + wage_base = float(payslip.rule_parameter('fed_941_fica_m_wage_base')) # inf + remaining = wage_base - ytd_wage + + wage = categories.GROSS - categories.WAGE_US_941_FICA_EXEMPT + + if remaining < 0.0: + result = 0.0 + elif remaining < wage: + result = remaining + else: + result = wage + + return result, result_rate + + +er_us_941_fica_m = ee_us_941_fica_m + + +def ee_us_941_fica_m_add(payslip, categories, worked_days, inputs): + """ + Returns FICA Medicare Additional eligible wage and rate. + Note that this wage is not capped like the above rules. + WAGE = GROSS - WAGE_FICA_EXEMPT + :return: result, result_rate (wage, percent) + """ + exempt = payslip.contract_id.us_payroll_config_value('fed_941_fica_exempt') + if exempt: + return 0.0, 0.0 + + # Determine Rate. + result_rate = -payslip.rule_parameter('fed_941_fica_m_add_rate') + + # Determine Wage + year = payslip.dict.get_year() + ytd_wage = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage -= payslip.sum_category('WAGE_US_941_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + ytd_wage += payslip.contract_id.external_wages + + wage_start = payslip.rule_parameter('fed_941_fica_m_add_wage_start') + existing_wage = ytd_wage - wage_start + + wage = categories.GROSS - categories.WAGE_US_941_FICA_EXEMPT + + if existing_wage >= 0.0: + result = wage + elif wage + existing_wage > 0.0: + result = wage + existing_wage + else: + result = 0.0 + + return result, result_rate + + +# Federal Income Tax +def ee_us_941_fit(payslip, categories, worked_days, inputs): + """ + Returns Wage and rate that is computed given the amount to withhold. + WAGE = GROSS - WAGE_US_941_FIT_EXEMPT + :return: result, result_rate (wage, percent) + """ + filing_status = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_filing_status') + if not filing_status: + return 0.0, 0.0 + + schedule_pay = payslip.contract_id.schedule_pay + wage = categories.GROSS - categories.WAGE_US_941_FIT_EXEMPT + #_logger.warn('initial gross wage: ' + str(wage)) + year = payslip.dict.get_year() + if year >= 2020: + # Large changes in Federal Income Tax in 2020 and the W4 + # We will assume that your W4 is the 2020 version + # Steps are from IRS Publication 15-T + # + # Step 1 + working_wage = wage + is_nra = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_is_nonresident_alien') + if is_nra: + nra_table = payslip.rule_parameter('fed_941_fit_nra_additional') + working_wage += nra_table.get(schedule_pay, 0.0) + #_logger.warn(' is_nrm after wage: ' + str(working_wage)) + + pay_periods = payslip.dict.get_pay_periods_in_year() + wage_annual = pay_periods * working_wage + #_logger.warn('annual wage: ' + str(wage_annual)) + wage_annual += payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_other_income') + #_logger.warn(' after other income: ' + str(wage_annual)) + + deductions = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_deductions') + #_logger.warn('deductions from W4: ' + str(deductions)) + + higher_rate_type = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_multiple_jobs_higher') + if not higher_rate_type: + deductions += 12900.0 if filing_status == 'married' else 8600.0 + #_logger.warn(' deductions after standard deduction: ' + str(deductions)) + + adjusted_wage_annual = wage_annual - deductions + if adjusted_wage_annual < 0.0: + adjusted_wage_annual = 0.0 + #_logger.warn('adusted annual wage: ' + str(adjusted_wage_annual)) + + # Step 2 + if filing_status == 'single': + tax_tables = payslip.rule_parameter('fed_941_fit_table_single') + elif filing_status == 'married': + tax_tables = payslip.rule_parameter('fed_941_fit_table_married') + else: + # married_as_single for historic reasons + tax_tables = payslip.rule_parameter('fed_941_fit_table_hh') + + if higher_rate_type: + tax_table = tax_tables['higher'] + else: + tax_table = tax_tables['standard'] + + selected_row = None + for row in tax_table: + if row[0] <= adjusted_wage_annual: + selected_row = row + else: + # First row where wage is higher than adjusted_wage_annual + break + + wage_threshold, base_withholding_amount, marginal_rate = selected_row + #_logger.warn(' selected row: ' + str(selected_row)) + working_wage = adjusted_wage_annual - wage_threshold + tentative_withholding_amount = (working_wage * marginal_rate) + base_withholding_amount + tentative_withholding_amount = tentative_withholding_amount / pay_periods + #_logger.warn('tenative withholding amount: ' + str(tentative_withholding_amount)) + + # Step 3 + dependent_credit = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_dependent_credit') + dependent_credit = dependent_credit / pay_periods + #_logger.warn('dependent credit (per period): ' + str(dependent_credit)) + tentative_withholding_amount -= dependent_credit + if tentative_withholding_amount < 0.0: + tentative_withholding_amount = 0.0 + + # Step 4 + withholding_amount = tentative_withholding_amount + payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_additional_withholding') + #_logger.warn('final withholding amount: ' + str(withholding_amount)) + # Ideally we would set the 'taxable wage' as the result and compute the percentage tax. + # This is off by 1 penny across our tests, but I feel like it is worth it for the added reporting. + # - Jared Kipe 2019 during Odoo 13.0 rewrite. + # + # return -withholding_amount, 100.0 + return wage, -(withholding_amount / wage * 100.0) + else: + working_wage = wage + is_nra = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_is_nonresident_alien') + if is_nra: + nra_table = payslip.rule_parameter('fed_941_fit_nra_additional') + working_wage += nra_table[schedule_pay] + + allowance_table = payslip.rule_parameter('fed_941_fit_allowance') + allowances = payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_allowances') + working_wage -= allowance_table[schedule_pay] * allowances + tax = 0.0 + last_limit = 0.0 + if filing_status == 'married': + tax_table = payslip.rule_parameter('fed_941_fit_table_married') + else: + tax_table = payslip.rule_parameter('fed_941_fit_table_single') + for row in tax_table[schedule_pay]: + limit, base, percent = row + limit = float(limit) # 'inf' + if working_wage <= limit: + tax = base + ((working_wage - last_limit) * (percent / 100.0)) + break + last_limit = limit + + tax += payslip.contract_id.us_payroll_config_value('fed_941_fit_w4_additional_withholding') + # Ideally we would set the 'taxable wage' as the result and compute the percentage tax. + # This is off by 1 penny across our tests, but I feel like it is worth it for the added reporting. + # - Jared Kipe 2019 during Odoo 13.0 rewrite. + # + # return -tax, 100.0 + return wage, -(tax / wage * 100.0) diff --git a/l10n_us_hr_payroll/models/hr_contract.py b/l10n_us_hr_payroll/models/hr_contract.py new file mode 100644 index 00000000..46bc42b7 --- /dev/null +++ b/l10n_us_hr_payroll/models/hr_contract.py @@ -0,0 +1,28 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from odoo import api, fields, models +from .us_payroll_config import FUTA_TYPE_NORMAL, \ + FUTA_TYPE_BASIC, \ + FUTA_TYPE_EXEMPT + + +class HrPayrollStructure(models.Model): + _inherit = 'hr.payroll.structure' + schedule_pay = fields.Selection(selection_add=[('semi-monthly', 'Semi-monthly')]) + + +class USHRContract(models.Model): + _inherit = 'hr.contract' + + FUTA_TYPE_NORMAL = FUTA_TYPE_NORMAL + FUTA_TYPE_BASIC = FUTA_TYPE_BASIC + FUTA_TYPE_EXEMPT = FUTA_TYPE_EXEMPT + + us_payroll_config_id = fields.Many2one('hr.contract.us_payroll_config', 'Payroll Forms') + external_wages = fields.Float(string='External Existing Wages') + + # Simplified fields for easier rules, state code will exempt based on contract's futa_type + futa_type = fields.Selection(related='us_payroll_config_id.fed_940_type') + + def us_payroll_config_value(self, name): + return self.us_payroll_config_id[name] diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py new file mode 100644 index 00000000..92a1e0fd --- /dev/null +++ b/l10n_us_hr_payroll/models/hr_payslip.py @@ -0,0 +1,48 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from odoo import api, fields, models + +from .federal.fed_940 import er_us_940_futa +from .federal.fed_941 import ee_us_941_fica_ss, \ + ee_us_941_fica_m, \ + ee_us_941_fica_m_add,\ + er_us_941_fica_ss, \ + er_us_941_fica_m, \ + ee_us_941_fit + + +class HRPayslip(models.Model): + _inherit = 'hr.payslip' + + # From IRS Publication 15-T or logically (annually, bi-monthly) + PAY_PERIODS_IN_YEAR = { + 'annually': 1, + 'semi-annually': 2, + 'quarterly': 4, + 'bi-monthly': 6, + 'monthly': 12, + 'semi-monthly': 24, + 'bi-weekly': 26, + 'weekly': 52, + 'daily': 260, + } + + def _get_base_local_dict(self): + res = super()._get_base_local_dict() + res.update({ + 'er_us_940_futa': er_us_940_futa, + 'ee_us_941_fica_ss': ee_us_941_fica_ss, + 'ee_us_941_fica_m': ee_us_941_fica_m, + 'ee_us_941_fica_m_add': ee_us_941_fica_m_add, + 'er_us_941_fica_ss': er_us_941_fica_ss, + 'er_us_941_fica_m': er_us_941_fica_m, + 'ee_us_941_fit': ee_us_941_fit, + }) + return res + + def get_year(self): + # Helper method to get the year (normalized between Odoo Versions) + return self.date_to.year + + def get_pay_periods_in_year(self): + return self.PAY_PERIODS_IN_YEAR.get(self.contract_id.schedule_pay, 0) diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py new file mode 100644 index 00000000..ed0e6d73 --- /dev/null +++ b/l10n_us_hr_payroll/models/us_payroll_config.py @@ -0,0 +1,45 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + +from odoo import api, fields, models + +FUTA_TYPE_EXEMPT = 'exempt' +FUTA_TYPE_BASIC = 'basic' +FUTA_TYPE_NORMAL = 'normal' + + +class HRContractUSPayrollConfig(models.Model): + _name = 'hr.contract.us_payroll_config' + _description = 'Contract US Payroll Forms' + + name = fields.Char(string="Description") + employee_id = fields.Many2one('hr.employee', string="Employee", required=True) + state_id = fields.Many2one('res.country.state', string="Applied State") + + fed_940_type = fields.Selection([ + (FUTA_TYPE_EXEMPT, 'Exempt (0%)'), + (FUTA_TYPE_NORMAL, 'Normal Net Rate (0.6%)'), + (FUTA_TYPE_BASIC, 'Basic Rate (6%)'), + ], string="Federal Unemployment Tax Type (FUTA)", default='normal') + + fed_941_fica_exempt = fields.Boolean(string='FICA Exempt', help="Exempt from Social Security and " + "Medicare e.g. F1 Student Visa") + + fed_941_fit_w4_filing_status = fields.Selection([ + ('', 'Exempt'), + ('single', 'Single or Married filing separately'), + ('married', 'Married filing jointly'), + ('married_as_single', 'Head of Household'), + ], string='Federal W4 Filing Status [1(c)]', default='single') + fed_941_fit_w4_allowances = fields.Integer(string='Federal W4 Allowances (before 2020)') + fed_941_fit_w4_is_nonresident_alien = fields.Boolean(string='Federal W4 Is Nonresident Alien') + fed_941_fit_w4_multiple_jobs_higher = fields.Boolean(string='Federal W4 Multiple Jobs Higher [2(c)]', + help='Form W4 (2020+) 2(c) Checkbox. ' + 'Uses Higher Withholding tables.') + fed_941_fit_w4_dependent_credit = fields.Float(string='Federal W4 Dependent Credit [3]', + help='Form W4 (2020+) Line 3') + fed_941_fit_w4_other_income = fields.Float(string='Federal W4 Other Income [4(a)]', + help='Form W4 (2020+) 4(a)') + fed_941_fit_w4_deductions = fields.Float(string='Federal W4 Deductions [4(b)]', + help='Form W4 (2020+) 4(b)') + fed_941_fit_w4_additional_withholding = fields.Float(string='Federal W4 Additional Withholding [4(c)]', + help='Form W4 (2020+) 4(c)') diff --git a/l10n_us_hr_payroll/security/ir.model.access.csv b/l10n_us_hr_payroll/security/ir.model.access.csv new file mode 100644 index 00000000..67a8fa2a --- /dev/null +++ b/l10n_us_hr_payroll/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_hr_contract_us_payroll_config,hr.contract.us_payroll_config,model_hr_contract_us_payroll_config,hr_payroll.group_hr_payroll_manager,1,1,1,1 diff --git a/l10n_us_hr_payroll/static/description/icon.png b/l10n_us_hr_payroll/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2a58a38132bd0b9a86324caa86d0cc6fc145fd4c GIT binary patch literal 8776 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 X4vqDeFsl6h0f@TtV + + + + hr.contract.form.inherit + hr.contract + + + + + + + + + \ 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 new file mode 100644 index 00000000..dfe0e301 --- /dev/null +++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml @@ -0,0 +1,75 @@ + + + + hr.contract.us_payroll_config.tree + hr.contract.us_payroll_config + + + + + + + + + + + + + hr.contract.us_payroll_config.form + hr.contract.us_payroll_config + +
+ + + + + + + + +

Form 940 - Federal Unemployment

+ +

Form 941 / W4 - Federal Income Tax

+ + + + + + + + + +
+
+
+
+
+
+ + + hr.contract.us_payroll_config.search + hr.contract.us_payroll_config + + + + + + + + + + + Employee Payroll Forms + hr.contract.us_payroll_config + tree,form + +

+ No Forms +

+
+
+ + +