2019 payroll 10.0 backport partial

This commit is contained in:
Jared Kipe
2019-01-06 17:06:37 -08:00
committed by Jared Kipe
parent b7b6f4b562
commit d7ba50f024
30 changed files with 3170 additions and 202 deletions

View File

@@ -0,0 +1,461 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsCAPayslip(TestUsPayslip):
###
# Taxes and Rates
###
CA_UIT_MAX_WAGE = 7000
CA_UIT_MAX_WAGE = 7000
CA_SDI_MAX_WAGE = 114967
# Examples from http://www.edd.ca.gov/pdf_pub_ctr/18methb.pdf
def test_example_a(self):
salary = 210
schedule_pay = 'weekly'
allowances = 1
additional_allowances = 0
wh = 0.00
employee = self._createEmployee()
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_c4_exemptions = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'single'
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
ca_uit = contract.ca_uit_rate(2018) / -100.0
ca_ett = contract.ca_ett_rate(2018) / -100.0
ca_sdi = contract.ca_sdi_rate(2018) / -100.0
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_UIT'], cats['CA_UIT_WAGES'] * ca_uit)
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_ETT'], cats['CA_ETT_WAGES'] * ca_ett)
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
self.assertPayrollEqual(cats['CA_SDI'], cats['CA_SDI_WAGES'] * ca_sdi)
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ca_uit_wages = self.CA_UIT_MAX_WAGE - salary if (self.CA_UIT_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 California tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['CA_UIT'], remaining_ca_uit_wages * ca_uit)
def test_example_b(self):
salary = 1250
schedule_pay = 'bi-weekly'
allowances = 2
additional_allowances = 1
wh = -2.89
# tax rates
ca_uit = 2.6
ca_ett = 0.1
ca_sdi = 1.0
employee = self._createEmployee()
employee.company_id.ca_uit_rate_2018 = ca_uit
employee.company_id.ca_ett_rate_2018 = ca_ett
employee.company_id.ca_sdi_rate_2018 = ca_sdi
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_de4_allowances = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'married'
self.assertEqual(contract.schedule_pay, 'bi-weekly')
self.assertEqual(contract.ca_de4_filing_status, 'married')
self.assertEqual(contract.ca_de4_allowances, 2)
self.assertEqual(contract.ca_additional_allowances, 1)
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ca_uit_wages = self.CA_UIT_MAX_WAGE - salary if (self.CA_UIT_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 California tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
def test_example_c(self):
salary = 3800
schedule_pay = 'monthly'
allowances = 5
additional_allowances = 0.72
wh = -0.72
# tax rates
ca_uit = 2.6
ca_ett = 0.1
ca_sdi = 1.0
employee = self._createEmployee()
employee.company_id.ca_uit_rate_2018 = ca_uit
employee.company_id.ca_ett_rate_2018 = ca_ett
employee.company_id.ca_sdi_rate_2018 = ca_sdi
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_de4_allowances = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'married'
self.assertEqual(contract.schedule_pay, 'monthly')
self.assertEqual(contract.ca_de4_filing_status, 'married')
self.assertEqual(contract.ca_de4_allowances, 5)
self.assertEqual(contract.ca_additional_allowances, 0)
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ca_uit_wages = self.CA_UIT_MAX_WAGE - salary if (self.CA_UIT_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 California tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
def test_example_d(self):
salary = 800
schedule_pay = 'weekly'
allowances = 3
additional_allowances = 0
wh = -3.31
# tax rates
ca_uit = 2.6
ca_ett = 0.1
ca_sdi = 1.0
employee = self._createEmployee()
employee.company_id.ca_uit_rate_2018 = ca_uit
employee.company_id.ca_ett_rate_2018 = ca_ett
employee.company_id.ca_sdi_rate_2018 = ca_sdi
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_de4_allowances = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'head_household'
self.assertEqual(contract.schedule_pay, 'weekly')
self.assertEqual(contract.ca_de4_filing_status, 'head_household')
self.assertEqual(contract.ca_de4_allowances, 3)
self.assertEqual(contract.ca_additional_allowances, 0)
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ca_uit_wages = self.CA_UIT_MAX_WAGE - salary if (self.CA_UIT_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 California tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
def test_example_e(self):
salary = 1800
schedule_pay = 'semi-monthly'
allowances = 4
additional_allowances = 0
wh = -3.39
# tax rates
ca_uit = 2.6
ca_ett = 0.1
ca_sdi = 1.0
employee = self._createEmployee()
employee.company_id.ca_uit_rate_2018 = ca_uit
employee.company_id.ca_ett_rate_2018 = ca_ett
employee.company_id.ca_sdi_rate_2018 = ca_sdi
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_de4_allowances = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'married'
self.assertEqual(contract.schedule_pay, 'semi-monthly')
self.assertEqual(contract.ca_de4_filing_status, 'married')
self.assertEqual(contract.ca_de4_allowances, 4)
self.assertEqual(contract.ca_additional_allowances, 0)
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ca_uit_wages = self.CA_UIT_MAX_WAGE - salary if (self.CA_UIT_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 California tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
def test_example_f(self):
salary = 45000
schedule_pay = 'annually'
allowances = 4
additional_allowances = 0
wh = -121.11
# tax rates
ca_uit = 2.6
ca_ett = 0.1
ca_sdi = 1.0
employee = self._createEmployee()
employee.company_id.ca_uit_rate_2018 = ca_uit
employee.company_id.ca_ett_rate_2018 = ca_ett
employee.company_id.ca_sdi_rate_2018 = ca_sdi
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ca_hr_payroll.hr_payroll_salary_structure_us_ca_employee'),
schedule_pay=schedule_pay)
contract.ca_de4_allowances = allowances
contract.ca_additional_allowances = additional_allowances
contract.ca_de4_filing_status = 'married'
self.assertEqual(contract.schedule_pay, 'annually')
self.assertEqual(contract.ca_de4_filing_status, 'married')
self.assertEqual(contract.ca_de4_allowances, 4)
self.assertEqual(contract.ca_additional_allowances, 0)
self._log('2017 California tax last payslip:')
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2018 California tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
process_payslip(payslip)
def test_estimated_deduction_table(self):
salary = 600
allowances = 5
schedule_pay = 'bi-weekly'
expected_deduction = 192
deduction = 0
taxable_pay = 0
estimated_deduction_table = {
'weekly': (19, 38, 58, 77, 96, 115, 135, 154, 173, 192),
'bi-weekly': (38, 77, 115, 154, 192, 231, 269, 308, 346, 385),
'semi-monthly': (42, 83, 125, 167, 208, 250, 292, 333, 375, 417),
'monthly': (83, 167, 250, 333, 417, 500, 583, 667, 750, 833),
'quarterly': (250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500),
'semi-annual': (500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000),
'annual': (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000),
}
allowance_index = allowances - 1
if allowances > 10:
deduction = (estimated_deduction_table[schedule_pay][0]) * allowances
taxable_pay = salary - deduction
elif allowances > 0:
deduction = estimated_deduction_table[schedule_pay][allowance_index]
taxable_pay = salary - deduction
self.assertEqual(expected_deduction, deduction)
self.assertTrue(taxable_pay < salary)
self.assertEqual(taxable_pay, salary - deduction)
def test_standard_deduction_table(self):
salary = 3000
schedule_pay = 'monthly'
filing_status = 'head_household'
expected_deduction = 706
deduction = 0
taxable_pay = 0
standard_deduction_table = {
'weekly': (81, 81, 163, 163),
'bi-weekly': (163, 163, 326, 326),
'semi-monthly': (177, 177, 353, 353),
'monthly': (353, 352, 706, 706),
'quarterly': (1059, 1059, 2188, 2188),
'semi-annual': (2118, 2118, 4236, 4236),
'annual': (4236, 4236, 8471, 8472),
}
if filing_status == 'head_household':
_, _, _, deduction = standard_deduction_table[schedule_pay]
taxable_pay = salary - deduction
elif filing_status == 'married':
if allowances >= 2:
_, _, deduction, _ = standard_deduction_table[schedule_pay]
taxable_pay = salary - deduction
else:
_, deduction, _, _ = standard_deduction_table[schedule_pay]
taxable_pay = salary - deduction
else:
deduction, _, _, _ = standard_deduction_table[schedule_pay]
taxable_pay = salary - deduction
self.assertEqual(expected_deduction, deduction)
self.assertTrue(taxable_pay < salary)
self.assertEqual(taxable_pay, salary - deduction)

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsFlPayslip(TestUsPayslip):

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsFlPayslip(TestUsPayslip):

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsFlPayslip(TestUsPayslip):

View File

@@ -0,0 +1,77 @@
******************
Hibou - US Payroll
******************
Calculations and contribution registers for United States Payroll.
For more information and add-ons, visit `Hibou.io <https://hibou.io/>`_.
=============
Main Features
=============
* Contribution registers and partners for:
* The Electronic Federal Tax Payment System (EFTPS) - Form 941
* The Electronic Federal Tax Payment System (EFTPS) - Form 940
* The Electronic Federal Tax Payment System (EFTPS) - Form 941 (FICA + Federal Withholding)
* The Electronic Federal Tax Payment System (EFTPS) - Form 940 (FUTA)
* Contract level FICA Social Security
* Contract level FICA Employee Medicare
* Contract level FICA Employee Medicare Additional
* Contract level Federal Income Withholding
* Company level FICA Social Security
* Company level FICA Medicare
* Company level FUTA Federal Unemployment
.. image:: https://user-images.githubusercontent.com/15882954/41485460-76a0060c-7095-11e8-851a-fec562013ce4.png
:alt: 'Employee Contract Detail'
:width: 988
:align: left
USA Employee added to Contract Salary Structure Menu
.. image:: https://user-images.githubusercontent.com/15882954/41485484-880f0816-7095-11e8-9ad0-874b3270c308.png
:alt: 'Computed Pay Slip Detail'
:width: 988
:align: left
Upgrading to 2019
==========================
If you were using this prior to January 2019, then you will need to run the following
migration script.
Odoo Shell code::
def migrate_rule_name(rule_id):
main = env.ref(rule_id)
old_2017 = env.ref(rule_id.replace('2018', '2017'))
old_2016 = env.ref(rule_id.replace('2018', '2016'))
lines = env['hr.payslip.line'].search([('salary_rule_id', 'in', [old_2017.id, old_2016.id,])])
lines.write({'salary_rule_id': main.id})
rules = [
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_ss_wages_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_m_wages_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_m_add_wages_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_ss_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_m_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fica_emp_m_add_2018',
'l10n_us_hr_payroll.hr_payroll_rules_fed_inc_withhold_2018_single',
'l10n_us_hr_payroll.hr_payroll_rules_fed_inc_withhold_2018_married',
'l10n_us_hr_payroll.hr_payroll_rules_futa_wages_2018',
'l10n_us_hr_payroll.hr_payroll_rules_futa_2018',
]
for rule_id in rules:
migrate_rule_name(rule_id)
env.cr.commit()
=======
License
=======
Please see `LICENSE <https://github.com/hibou-io/hibou-odoo-suite/blob/master/LICENSE>`_.
Copyright Hibou Corp. 2018

View File

@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
import l10n_us_hr_payroll
import models

View File

@@ -4,8 +4,8 @@
'author': 'Hibou Corp. <hello@hibou.io>',
'license': 'AGPL-3',
'category': 'Localization',
'depends': ['hr_payroll'],
'version': '2017.0.0',
'depends': ['hr_payroll', 'hr_payroll_rate'],
'version': '10.0.2019.0.0',
'description': """
USA Payroll Rules.
==================
@@ -21,11 +21,10 @@ USA Payroll Rules.
'auto_install': False,
'website': 'https://hibou.io/',
'data': [
'l10n_us_hr_payroll_view.xml',
'views/l10n_us_hr_payroll_view.xml',
'data/base.xml',
'data/rules_2016.xml',
'data/rules_2017.xml',
'data/rules_2018.xml',
'data/rates.xml',
'data/rules.xml',
'data/final.xml',
],
'installable': True

View File

@@ -26,111 +26,58 @@
<!-- HR SALARY RULE CATEGORIES-->
<record id="hr_payroll_fica_emp_ss_wages" model="hr.salary.rule.category">
<field name="name">FICA Employee Social Security - Wages</field>
<field name="code">FICA_EMP_SS_WAGES</field>
<field name="name">Wage: US FICA Social Security</field>
<field name="code">WAGE_US_FICA_SS</field>
</record>
<record id="hr_payroll_fica_emp_m_wages" model="hr.salary.rule.category">
<field name="name">FICA Employee Medicare - Wages</field>
<field name="code">FICA_EMP_M_WAGES</field>
<field name="name">Wage: US FICA Medicare</field>
<field name="code">WAGE_US_FICA_M</field>
</record>
<record id="hr_payroll_fica_emp_m_add_wages" model="hr.salary.rule.category">
<field name="name">FICA Employee Medicare Additional - Wages</field>
<field name="code">FICA_EMP_M_ADD_WAGES</field>
<field name="name">Wage: US FICA Medicare Additional</field>
<field name="code">WAGE_US_FICA_M_ADD</field>
</record>
<record id="hr_payroll_futa_wages" model="hr.salary.rule.category">
<field name="name">FUTA Federal Unemployment - Wages</field>
<field name="code">FUTA_WAGES</field>
<field name="name">Wage: US FUTA Federal Unemployment</field>
<field name="code">WAGE_US_FUTA</field>
</record>
<record id="hr_payroll_fica_emp_ss" model="hr.salary.rule.category">
<field name="name">FICA Employee Social Security</field>
<field name="code">FICA_EMP_SS</field>
<field name="name">EE: US FICA Social Security</field>
<field name="code">EE_US_FICA_SS</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_fica_emp_m" model="hr.salary.rule.category">
<field name="name">FICA Employee Medicare</field>
<field name="code">FICA_EMP_M</field>
<field name="name">EE: US FICA Medicare</field>
<field name="code">EE_US_FICA_M</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_fica_emp_m_add" model="hr.salary.rule.category">
<field name="name">FICA Employee Medicare Additional</field>
<field name="code">FICA_EMP_M_ADD</field>
<field name="name">EE: US FICA Medicare Additional</field>
<field name="code">EE_US_FICA_M_ADD</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_fed_income_withhold" model="hr.salary.rule.category">
<field name="name">Federal Income Withholding</field>
<field name="code">FED_INC_WITHHOLD</field>
<field name="name">EE: US Federal Income Tax Withholding</field>
<field name="code">EE_US_FED_INC_WITHHOLD</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_fica_comp_ss" model="hr.salary.rule.category">
<field name="name">FICA Company Social Security</field>
<field name="code">FICA_COMP_SS</field>
<field name="name">ER: US FICA Social Security</field>
<field name="code">ER_US_FICA_SS</field>
<field name="parent_id" ref="hr_payroll.COMP"/>
</record>
<record id="hr_payroll_fica_comp_m" model="hr.salary.rule.category">
<field name="name">FICA Company Medicare</field>
<field name="code">FICA_COMP_M</field>
<field name="name">ER: US FICA Medicare</field>
<field name="code">ER_US_FICA_M</field>
<field name="parent_id" ref="hr_payroll.COMP"/>
</record>
<record id="hr_payroll_futa" model="hr.salary.rule.category">
<field name="name">FUTA Federal Unemployment</field>
<field name="code">FUTA</field>
<field name="name">ER: US FUTA Federal Unemployment</field>
<field name="code">ER_US_FUTA</field>
<field name="parent_id" ref="hr_payroll.COMP"/>
</record>
<!-- HR SALARY RULES-->
<!-- Employee Deductions and Calculations -->
<!-- Company Contributions -->
<record id="hr_payroll_rules_fica_comp_ss" model="hr.salary.rule">
<field name="sequence" eval="440"/>
<field name="category_id" ref="hr_payroll_fica_comp_ss"/>
<field name="name">FICA Company Social Security</field>
<field name="code">FICA_COMP_SS</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.FICA_EMP_SS</field>
<field name="register_id" ref="contrib_register_eftps_941"/>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_payroll_rules_fica_comp_m" model="hr.salary.rule">
<field name="sequence" eval="441"/>
<field name="category_id" ref="hr_payroll_fica_comp_m"/>
<field name="name">FICA Company Medicare</field>
<field name="code">FICA_COMP_M</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.FICA_EMP_M</field>
<field name="register_id" ref="contrib_register_eftps_941"/>
<field name="appears_on_payslip" eval="False"/>
</record>
<!-- Salary Rules -->
<!-- Company Contributions -->
<record id="hr_payroll_rules_fica_comp_ss" model="hr.salary.rule">
<field name="sequence" eval="440"/>
<field name="category_id" ref="hr_payroll_fica_comp_ss"/>
<field name="name">FICA Company Social Security</field>
<field name="code">FICA_COMP_SS</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.FICA_EMP_SS</field>
<field name="register_id" ref="contrib_register_eftps_941"/>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_payroll_rules_fica_comp_m" model="hr.salary.rule">
<field name="sequence" eval="441"/>
<field name="category_id" ref="hr_payroll_fica_comp_m"/>
<field name="name">FICA Company Medicare</field>
<field name="code">FICA_COMP_M</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.FICA_EMP_M</field>
<field name="register_id" ref="contrib_register_eftps_941"/>
<field name="appears_on_payslip" eval="False"/>
</record>
</data>
</openerp>

View File

@@ -10,28 +10,6 @@
ref('hr_payroll_rules_fica_comp_ss'),
ref('hr_payroll_rules_fica_comp_m'),
ref('hr_payroll_rules_fica_emp_ss_wages_2016'),
ref('hr_payroll_rules_fica_emp_m_wages_2016'),
ref('hr_payroll_rules_fica_emp_m_add_wages_2016'),
ref('hr_payroll_rules_fica_emp_ss_2016'),
ref('hr_payroll_rules_fica_emp_m_2016'),
ref('hr_payroll_rules_fica_emp_m_add_2016'),
ref('hr_payroll_rules_futa_wages_2016'),
ref('hr_payroll_rules_futa_2016'),
ref('hr_payroll_rules_fed_inc_withhold_2016_single'),
ref('hr_payroll_rules_fed_inc_withhold_2016_married'),
ref('hr_payroll_rules_fica_emp_ss_wages_2017'),
ref('hr_payroll_rules_fica_emp_m_wages_2017'),
ref('hr_payroll_rules_fica_emp_m_add_wages_2017'),
ref('hr_payroll_rules_fica_emp_ss_2017'),
ref('hr_payroll_rules_fica_emp_m_2017'),
ref('hr_payroll_rules_fica_emp_m_add_2017'),
ref('hr_payroll_rules_futa_wages_2017'),
ref('hr_payroll_rules_futa_2017'),
ref('hr_payroll_rules_fed_inc_withhold_2017_single'),
ref('hr_payroll_rules_fed_inc_withhold_2017_married'),
ref('hr_payroll_rules_fica_emp_ss_wages_2018'),
ref('hr_payroll_rules_fica_emp_m_wages_2018'),
ref('hr_payroll_rules_fica_emp_m_add_wages_2018'),

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- FUTA -->
<record id="hr_payroll_rates_futa_exempt" model="hr.payroll.rate">
<field name="name">US FUTA Exempt</field>
<field name="code">US_FUTA_EXEMPT</field>
<field name="rate">0.0</field>
<field name="date_from">2016-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_futa_normal" model="hr.payroll.rate">
<field name="name">US FUTA Normal</field>
<field name="code">US_FUTA_NORMAL</field>
<field name="rate">0.6</field>
<field name="date_from">2016-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_futa_basic" model="hr.payroll.rate">
<field name="name">US FUTA Basic</field>
<field name="code">US_FUTA_BASIC</field>
<field name="rate">6.0</field>
<field name="date_from">2016-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<!-- FICA -->
<!-- Social Security -->
<record id="hr_payroll_rates_fica_ss_old" model="hr.payroll.rate">
<field name="name">US FICA Social Security</field>
<field name="code">US_FICA_SS</field>
<field name="rate">6.2</field>
<field name="date_from">2016-01-01</field>
<field name="date_to">2017-12-31</field>
<field name="wage_limit_year" eval="128400.0"/>
</record>
<record id="hr_payroll_rates_fica_ss_2018" model="hr.payroll.rate">
<field name="name">US FICA Social Security</field>
<field name="code">US_FICA_SS</field>
<field name="rate">6.2</field>
<field name="date_from">2018-01-01</field>
<field name="date_to">2018-12-31</field>
<field name="wage_limit_year" eval="128400.0"/>
</record>
<record id="hr_payroll_rates_fica_ss_2019" model="hr.payroll.rate">
<field name="name">US FICA Social Security</field>
<field name="code">US_FICA_SS</field>
<field name="rate">6.2</field>
<field name="date_from">2019-01-01</field>
<field name="date_to">2019-12-31</field>
<field name="wage_limit_year" eval="132900.0"/>
</record>
<!-- Medicare -->
<record id="hr_payroll_rates_fica_m" model="hr.payroll.rate">
<field name="name">US FICA Medicare</field>
<field name="code">US_FICA_M</field>
<field name="rate">1.45</field>
<field name="date_from">2016-01-01</field>
</record>
<!-- Medicare Additional -->
<record id="hr_payroll_rates_fica_m_add" model="hr.payroll.rate">
<field name="name">US FICA Medicare Additional</field>
<field name="code">US_FICA_M_ADD</field>
<field name="rate">0.9</field>
<field name="date_from">2016-01-01</field>
<field name="wage_limit_year">200000.0</field>
</record>
</odoo>

1058
l10n_us_hr_payroll/data/rules.xml Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
from . import l10n_us_hr_payroll

View File

@@ -1,15 +1,24 @@
from openerp import models, fields, api
class Payslip(models.Model):
_inherit = 'hr.payslip'
def get_futa_rate(self, contract):
self.ensure_one()
if contract.futa_type == USHrContract.FUTA_TYPE_EXEMPT:
rate = self.get_rate('US_FUTA_EXEMPT')
elif contract.futa_type == USHrContract.FUTA_TYPE_NORMAL:
rate = self.get_rate('US_FUTA_NORMAL')
else:
rate = self.get_rate('US_FUTA_BASIC')
return rate
class USHrContract(models.Model):
FUTA_TYPE_EXEMPT = 'exempt'
FUTA_TYPE_BASIC = 'basic'
FUTA_TYPE_NORMAL = 'normal'
FUTA_YEARS_VALID = (
2016,
2017,
2018,
)
_inherit = 'hr.contract'
@@ -31,17 +40,3 @@ class USHrContract(models.Model):
(FUTA_TYPE_NORMAL, 'Normal Net Rate (0.6%)'),
(FUTA_TYPE_BASIC, 'Basic Rate (6%)'),
], string="Federal Unemployment Tax Type (FUTA)", default='normal')
@api.multi
def futa_rate(self, year):
self.ensure_one()
if year not in self.FUTA_YEARS_VALID:
raise NotImplemented('FUTA rate for Year: ' + str(year) + ' not known.')
if self.futa_type == self.FUTA_TYPE_EXEMPT:
return 0.0
elif self.futa_type == self.FUTA_TYPE_NORMAL:
return 0.6
else:
return 6.0

View File

@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from . import test_us_payslip
from . import test_us_payslip_2016
from . import test_us_payslip_2017
from . import test_us_payslip_2018
from . import test_us_payslip_2019

View File

@@ -5,7 +5,7 @@ from sys import float_info as sys_float_info
from openerp.tests import common
from openerp.tools.float_utils import float_round as odoo_float_round
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
def process_payslip(payslip):

View File

@@ -1,6 +1,6 @@
from .test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
from sys import float_info
@@ -48,16 +48,16 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_SS_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_SS'], cats['FICA_EMP_SS_WAGES'] * self.FICA_SS)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M'], cats['FICA_EMP_M_WAGES'] * self.FICA_M)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], 0.0)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], 0.0)
self.assertPayrollEqual(cats['FICA_COMP_SS'], cats['FICA_EMP_SS'])
self.assertPayrollEqual(cats['FICA_COMP_M'], cats['FICA_EMP_M'])
self.assertPayrollEqual(cats['FUTA_WAGES'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['FUTA'], cats['FUTA_WAGES'] * self.FUTA)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * self.FUTA)
process_payslip(payslip)
@@ -73,16 +73,16 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_SS_WAGES'], remaining_ss_wages)
self.assertPayrollEqual(cats['FICA_EMP_SS'], cats['FICA_EMP_SS_WAGES'] * self.FICA_SS)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], remaining_m_wages)
self.assertPayrollEqual(cats['FICA_EMP_M'], cats['FICA_EMP_M_WAGES'] * self.FICA_M)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], 0.0)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], 0.0)
self.assertPayrollEqual(cats['FICA_COMP_SS'], cats['FICA_EMP_SS'])
self.assertPayrollEqual(cats['FICA_COMP_M'], cats['FICA_EMP_M'])
self.assertPayrollEqual(cats['FUTA_WAGES'], 0)
self.assertPayrollEqual(cats['FUTA'], 0)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], remaining_ss_wages)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], remaining_m_wages)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], 0)
self.assertPayrollEqual(cats['ER_US_FUTA'], 0)
process_payslip(payslip)
@@ -95,9 +95,9 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], self.FICA_M_ADD_START_WAGE - (salary * 2)) # aka 40k
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], cats['FICA_EMP_M_ADD_WAGES'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], self.FICA_M_ADD_START_WAGE - (salary * 2)) # aka 40k
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
process_payslip(payslip)
@@ -110,9 +110,9 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], cats['FICA_EMP_M_ADD_WAGES'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
process_payslip(payslip)
@@ -136,7 +136,7 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2018_fed_income_withholding_married_as_single(self):
salary = 500.00
@@ -158,7 +158,7 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2018_fed_income_withholding_married(self):
salary = 14000.00
@@ -180,7 +180,7 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2018_taxes_with_external(self):
@@ -199,16 +199,16 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_SS_WAGES'], self.FICA_SS_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['FICA_EMP_SS'], cats['FICA_EMP_SS_WAGES'] * self.FICA_SS)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M'], cats['FICA_EMP_M_WAGES'] * self.FICA_M)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], 0.0)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], cats['FICA_EMP_M_ADD_WAGES'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['FICA_COMP_SS'], cats['FICA_EMP_SS'])
self.assertPayrollEqual(cats['FICA_COMP_M'], cats['FICA_EMP_M'])
self.assertPayrollEqual(cats['FUTA_WAGES'], self.FUTA_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['FUTA'], cats['FUTA_WAGES'] * self.FUTA)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * self.FUTA)
def test_2018_taxes_with_full_futa(self):
futa_rate = self.FUTA_RATE_BASIC / -100.0
@@ -226,16 +226,16 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_SS_WAGES'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['FICA_EMP_SS'], cats['FICA_EMP_SS_WAGES'] * self.FICA_SS)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M'], cats['FICA_EMP_M_WAGES'] * self.FICA_M)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], 0.0)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], cats['FICA_EMP_M_ADD_WAGES'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['FICA_COMP_SS'], cats['FICA_EMP_SS'])
self.assertPayrollEqual(cats['FICA_COMP_M'], cats['FICA_EMP_M'])
self.assertPayrollEqual(cats['FUTA_WAGES'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['FUTA'], cats['FUTA_WAGES'] * futa_rate)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * futa_rate)
def test_2018_taxes_with_futa_exempt(self):
futa_rate = self.FUTA_RATE_EXEMPT / -100.0 # because of exemption
@@ -254,21 +254,21 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FICA_EMP_SS_WAGES'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['FICA_EMP_SS'], cats['FICA_EMP_SS_WAGES'] * self.FICA_SS)
self.assertPayrollEqual(cats['FICA_EMP_M_WAGES'], salary)
self.assertPayrollEqual(cats['FICA_EMP_M'], cats['FICA_EMP_M_WAGES'] * self.FICA_M)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD_WAGES'], 0.0)
self.assertPayrollEqual(cats['FICA_EMP_M_ADD'], cats['FICA_EMP_M_ADD_WAGES'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['FICA_COMP_SS'], cats['FICA_EMP_SS'])
self.assertPayrollEqual(cats['FICA_COMP_M'], cats['FICA_EMP_M'])
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
futa_wages = 0.0
if 'FUTA_WAGES' in cats:
futa_wages = cats['FUTA_WAGES']
if 'WAGE_US_FUTA' in cats:
futa_wages = cats['WAGE_US_FUTA']
futa = 0.0
if 'FUTA' in cats:
futa = cats['FUTA']
if 'ER_US_FUTA' in cats:
futa = cats['ER_US_FUTA']
self.assertPayrollEqual(futa_wages, 0.0)
self.assertPayrollEqual(futa, futa_wages * futa_rate)
@@ -295,7 +295,7 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2018_fed_income_additional_withholding(self):
salary = 50000.00
@@ -322,7 +322,7 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2018_taxes_with_w4_exempt(self):
salary = 6000.0
@@ -339,6 +339,30 @@ class TestUsPayslip2018(TestUsPayslip):
cats = self._getCategories(payslip)
fed_inc_withhold = 0.0
if 'FED_INC_WITHHOLD' in cats:
fed_inc_withhold = cats['FED_INC_WITHHOLD']
if 'EE_US_FED_INC_WITHHOLD' in cats:
fed_inc_withhold = cats['EE_US_FED_INC_WITHHOLD']
self.assertPayrollEqual(fed_inc_withhold, 0.0)
def test_2018_taxes_with_fica_exempt(self):
salary = 6000.0
schedule_pay = 'bi-weekly'
w4_allowances = 2
employee = self._createEmployee()
contract = self._createContract(employee, salary, schedule_pay, w4_allowances)
contract.fica_exempt = True
self._log('2018 tax w4 exempt payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
ss_wages = cats.get('WAGE_US_FICA_SS', 0.0)
med_wages = cats.get('WAGE_US_FICA_M', 0.0)
ss = cats.get('EE_US_FICA_SS', 0.0)
med = cats.get('EE_US_FICA_M', 0.0)
self.assertPayrollEqual(ss_wages, 0.0)
self.assertPayrollEqual(med_wages, 0.0)
self.assertPayrollEqual(ss, 0.0)
self.assertPayrollEqual(med, 0.0)

View File

@@ -0,0 +1,368 @@
from .test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
from sys import float_info
class TestUsPayslip2019(TestUsPayslip):
# FUTA Constants
FUTA_RATE_NORMAL = 0.6
FUTA_RATE_BASIC = 6.0
FUTA_RATE_EXEMPT = 0.0
# Wage caps
FICA_SS_MAX_WAGE = 132900.0
FICA_M_MAX_WAGE = float_info.max
FICA_M_ADD_START_WAGE = 200000.0
FUTA_MAX_WAGE = 7000.0
# Rates
FICA_SS = 6.2 / -100.0
FICA_M = 1.45 / -100.0
FUTA = FUTA_RATE_NORMAL / -100.0
FICA_M_ADD = 0.9 / -100.0
###
# 2019 Taxes and Rates
###
def test_2019_taxes(self):
# salary is high so that second payslip runs over max
# social security salary
salary = 80000.0
employee = self._createEmployee()
self._createContract(employee, salary)
self._log('2018 tax last slip')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 tax first payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * self.FUTA)
process_payslip(payslip)
# Make a new payslip, this one will have maximums for FICA Social Security Wages
remaining_ss_wages = self.FICA_SS_MAX_WAGE - salary if (self.FICA_SS_MAX_WAGE - 2 * salary < salary) else salary
remaining_m_wages = self.FICA_M_MAX_WAGE - salary if (self.FICA_M_MAX_WAGE - 2 * salary < salary) else salary
self._log('2019 tax second payslip:')
payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], remaining_ss_wages)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], remaining_m_wages)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], 0)
self.assertPayrollEqual(cats['ER_US_FUTA'], 0)
process_payslip(payslip)
# Make a new payslip, this one will have reached Medicare Additional (employee only)
self._log('2019 tax third payslip:')
payslip = self._createPayslip(employee, '2019-03-01', '2019-03-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], self.FICA_M_ADD_START_WAGE - (salary * 2)) # aka 40k
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
process_payslip(payslip)
# Make a new payslip, this one will have all salary as Medicare Additional
self._log('2019 tax fourth payslip:')
payslip = self._createPayslip(employee, '2019-04-01', '2019-04-30')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
process_payslip(payslip)
def test_2019_fed_income_withholding_single(self):
salary = 6000.00
schedule_pay = 'monthly'
w4_allowances = 3
w4_allowance_amt = 350.00 * w4_allowances
adjusted_salary = salary - w4_allowance_amt # should be 4962.60, but would work over a wide value for the rate
###
# Single MONTHLY form Publication 15
expected_withholding = self.float_round(-(378.52 + ((adjusted_salary - 3606) * 0.22)), self.payroll_digits)
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, 'single')
self._log('2019 fed income single payslip: adjusted_salary: ' + str(adjusted_salary))
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2019_fed_income_withholding_married_as_single(self):
salary = 500.00
schedule_pay = 'weekly'
w4_allowances = 1
w4_allowance_amt = 80.80 * w4_allowances
adjusted_salary = salary - w4_allowance_amt # should be 420.50, but would work over a wide value for the rate
###
# Single MONTHLY form Publication 15
expected_withholding = self.float_round(-(18.70 + ((adjusted_salary - 260) * 0.12)), self.payroll_digits)
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, 'married_as_single')
self._log('2019 fed income married_as_single payslip: adjusted_salary: ' + str(adjusted_salary))
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2019_fed_income_withholding_married(self):
salary = 14000.00
schedule_pay = 'bi-weekly'
w4_allowances = 2
w4_allowance_amt = 161.50 * w4_allowances
adjusted_salary = salary - w4_allowance_amt # should be 13680.80, but would work over a wide value for the rate
###
# Single MONTHLY form Publication 15
expected_withholding = self.float_round(-(2519.06 + ((adjusted_salary - 12817) * 0.32)), self.payroll_digits)
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, 'married')
self._log('2019 fed income married payslip: adjusted_salary: ' + str(adjusted_salary))
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2019_taxes_with_external(self):
# social security salary
salary = self.FICA_M_ADD_START_WAGE
external_wages = 6000.0
employee = self._createEmployee()
self._createContract(employee, salary, external_wages=external_wages)
self._log('2019 tax first payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * self.FUTA)
def test_2019_taxes_with_full_futa(self):
futa_rate = self.FUTA_RATE_BASIC / -100.0
# social security salary
salary = self.FICA_M_ADD_START_WAGE
employee = self._createEmployee()
self._createContract(employee, salary, futa_type=USHrContract.FUTA_TYPE_BASIC)
self._log('2019 tax first payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
self.assertPayrollEqual(cats['WAGE_US_FUTA'], self.FUTA_MAX_WAGE)
self.assertPayrollEqual(cats['ER_US_FUTA'], cats['WAGE_US_FUTA'] * futa_rate)
def test_2019_taxes_with_futa_exempt(self):
futa_rate = self.FUTA_RATE_EXEMPT / -100.0 # because of exemption
# social security salary
salary = self.FICA_M_ADD_START_WAGE
employee = self._createEmployee()
self._createContract(employee, salary, futa_type=USHrContract.FUTA_TYPE_EXEMPT)
self._log('2019 tax first payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['WAGE_US_FICA_SS'], self.FICA_SS_MAX_WAGE)
self.assertPayrollEqual(cats['EE_US_FICA_SS'], cats['WAGE_US_FICA_SS'] * self.FICA_SS)
self.assertPayrollEqual(cats['WAGE_US_FICA_M'], salary)
self.assertPayrollEqual(cats['EE_US_FICA_M'], cats['WAGE_US_FICA_M'] * self.FICA_M)
self.assertPayrollEqual(cats['WAGE_US_FICA_M_ADD'], 0.0)
self.assertPayrollEqual(cats['EE_US_FICA_M_ADD'], cats['WAGE_US_FICA_M_ADD'] * self.FICA_M_ADD)
self.assertPayrollEqual(cats['ER_US_FICA_SS'], cats['EE_US_FICA_SS'])
self.assertPayrollEqual(cats['ER_US_FICA_M'], cats['EE_US_FICA_M'])
futa_wages = 0.0
if 'WAGE_US_FUTA' in cats:
futa_wages = cats['WAGE_US_FUTA']
futa = 0.0
if 'ER_US_FUTA' in cats:
futa = cats['ER_US_FUTA']
self.assertPayrollEqual(futa_wages, 0.0)
self.assertPayrollEqual(futa, futa_wages * futa_rate)
def test_2019_fed_income_withholding_nonresident_alien(self):
salary = 3500.00
schedule_pay = 'quarterly'
w4_allowances = 1
w4_allowance_amt = 1050.0 * w4_allowances
nra_adjustment = 2000.0 # for quarterly
adjusted_salary = salary - w4_allowance_amt + nra_adjustment # 4425
###
# Single QUARTERLY form Publication 15
expected_withholding = self.float_round(-(242.50 + ((adjusted_salary - 3375) * 0.12)), self.payroll_digits)
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, 'single',
w4_is_nonresident_alien=True)
self._log('2019 fed income single payslip nonresident alien: adjusted_salary: ' + str(adjusted_salary))
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2019_fed_income_additional_withholding(self):
salary = 50000.00
schedule_pay = 'annually'
w4_additional_withholding = 5000.0
w4_allowances = 2
w4_allowance_amt = 4200.0 * w4_allowances
adjusted_salary = salary - w4_allowance_amt # 41700
###
# Single ANNUAL form Publication 15
expected_withholding = \
self.float_round(-((1940.00 + ((adjusted_salary - 31200) * 0.12)) + w4_additional_withholding),
self.payroll_digits)
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, 'married',
w4_additional_withholding=w4_additional_withholding)
self._log('2019 fed income married payslip additional withholding: adjusted_salary: ' + str(adjusted_salary))
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['EE_US_FED_INC_WITHHOLD'], expected_withholding)
def test_2019_taxes_with_w4_exempt(self):
salary = 6000.0
schedule_pay = 'bi-weekly'
w4_allowances = 0
employee = self._createEmployee()
self._createContract(employee, salary, schedule_pay, w4_allowances, '')
self._log('2019 tax w4 exempt payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
fed_inc_withhold = 0.0
if 'EE_US_FED_INC_WITHHOLD' in cats:
fed_inc_withhold = cats['EE_US_FED_INC_WITHHOLD']
self.assertPayrollEqual(fed_inc_withhold, 0.0)
def test_2019_taxes_with_fica_exempt(self):
salary = 6000.0
schedule_pay = 'bi-weekly'
w4_allowances = 2
employee = self._createEmployee()
contract = self._createContract(employee, salary, schedule_pay, w4_allowances)
contract.fica_exempt = True
self._log('2019 tax w4 exempt payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
ss_wages = cats.get('WAGE_US_FICA_SS', 0.0)
med_wages = cats.get('WAGE_US_FICA_M', 0.0)
ss = cats.get('EE_US_FICA_SS', 0.0)
med = cats.get('EE_US_FICA_M', 0.0)
self.assertPayrollEqual(ss_wages, 0.0)
self.assertPayrollEqual(med_wages, 0.0)
self.assertPayrollEqual(ss, 0.0)
self.assertPayrollEqual(med, 0.0)

View File

@@ -0,0 +1,92 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsKSPayslip(TestUsPayslip):
###
# 2018 Taxes and Rates
###
KS_UNEMP_MAX_WAGE = 14000.0
def test_2018_taxes(self):
self.debug = True
salary = 210
schedule_pay = 'weekly'
allowances = 2
additional_withholding = 0
# Amount of each withholding allowance for weekly from Withholding Allowance Amounts Table
# https://www.ksrevenue.org/pdf/kw1002017.pdf
withholding_allowance = 43.27 * allowances
taxable_pay = salary - withholding_allowance
# Tax Percentage Method for Single, taxable pay over $58, under $346
wh = -round(((taxable_pay - 58) * 0.031) - additional_withholding, 2)
employee = self._createEmployee()
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ks_hr_payroll.hr_payroll_salary_structure_us_ks_employee'),
schedule_pay=schedule_pay)
contract.ks_k4_allowances = allowances
contract.ks_additional_withholding = additional_withholding
contract.ks_k4_filing_status = 'single'
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
ks_unemp = contract.ks_unemp_rate(2018) / -100.0
self._log('2018 Kansas tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['KS_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['KS_UNEMP'], cats['KS_UNEMP_WAGES'] * ks_unemp)
self.assertPayrollEqual(cats['KS_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ks_unemp_wages = self.KS_UNEMP_MAX_WAGE - salary if (self.KS_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 Kansas tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['KS_UNEMP_WAGES'], remaining_ks_unemp_wages)
self.assertPayrollEqual(cats['KS_UNEMP'], remaining_ks_unemp_wages * ks_unemp)
def test_2018_taxes_with_state_exempt(self):
salary = 210
schedule_pay = 'weekly'
allowances = 2
# Tax Exempt
wh = 0
employee = self._createEmployee()
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ks_hr_payroll.hr_payroll_salary_structure_us_ks_employee'),
schedule_pay=schedule_pay)
contract.ks_k4_allowances = allowances
contract.ks_k4_filing_status = 'exempt'
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertEqual(cats['KS_WITHHOLD'], wh)

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
class TestUsMoPayslip(TestUsPayslip):

View File

@@ -0,0 +1,418 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsNCPayslip(TestUsPayslip):
###
# Taxes and Rates
###
NC_UNEMP_MAX_WAGE = 7000.0
def test_2018_taxes_weekly(self):
salary = 5000.0
schedule_pay = 'weekly'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 48.08
PST = 168.27
exemption = 1
# Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf
wh = -round((salary - (PST + (allowance_multiplier * exemption))) * 0.05599)
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = exemption
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (self.NC_UNEMP_MAX_WAGE - 2*salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip weekly:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_2018_taxes_with_external_weekly(self):
salary = 5000.0
external_wages = 7000.0
schedule_pay = 'weekly'
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, external_wages=external_wages,
struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 NorthCarolina_external tax first payslip weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], self.NC_UNEMP_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
def test_2018_taxes_with_state_exempt_weekly(self):
salary = 5000.0
external_wages = 6000.0
schedule_pay = 'weekly'
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, external_wages=external_wages, struct_id=self.ref(
'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), futa_type=USHrContract.FUTA_TYPE_BASIC, schedule_pay=schedule_pay)
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self.assertPayrollEqual(nc_unemp, 0.0)
self._log('2018 North Carolina exempt tax first payslip weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], self.NC_UNEMP_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
def test_2018_taxes_biweekly(self):
salary = 5000.0
schedule_pay = 'bi-weekly'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 96.15
PST = 336.54
allowances = 2
# Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf
wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599)
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = allowances
self.assertEqual(contract.schedule_pay, 'bi-weekly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip bi-weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (self.NC_UNEMP_MAX_WAGE - 2*salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip bi-weekly:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_2018_taxes_semimonthly(self):
salary = 4000.0
schedule_pay = 'semi-monthly'
nc_nc4_filing_status = 'head_household'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 104.17
PST = 583.33
allowances = 1
# Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf
wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599)
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref(
'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = allowances
contract.nc_nc4_filing_status = nc_nc4_filing_status
self.assertEqual(contract.schedule_pay, 'semi-monthly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (self.NC_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_2018_taxes_monthly(self):
salary = 4000.0
schedule_pay = 'monthly'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 208.33
PST = 729.17
allowances = 1
# Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf
wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599)
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref(
'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = allowances
self.assertEqual(contract.schedule_pay, 'monthly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (
self.NC_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_tax_exempt(self):
salary = 4000.0
wh = 0
schedule_pay = 'weekly'
excemptions = 1
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref(
'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = excemptions
contract.nc_nc4_filing_status = 'exempt'
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (
self.NC_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_additional_withholding(self):
salary = 4000.0
schedule_pay = 'weekly'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 48.08
PST = 168.27
additional_wh = 40.0
#4000 - (168.27 + (48.08 * 1)
allowances = 1
# Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf
wh = -round(((salary - (PST + (allowance_multiplier * allowances))) * 0.05599) + additional_wh)
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee,
salary,
struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'),
schedule_pay=schedule_pay)
contract.w4_is_nonresident_alien = True
contract.nc_nc4_additional_wh = additional_wh
contract.nc_nc4_allowances = allowances
self.assertEqual(contract.schedule_pay, 'weekly')
self.assertEqual(contract.w4_is_nonresident_alien, True)
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (self.NC_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 North Carolina tax second payslip weekly:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages)
self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)
def test_underflow(self):
salary = 150.0
schedule_pay = 'weekly'
# allowance_multiplier and Portion of Standard Deduction for weekly
allowance_multiplier = 48.08
PST = 168.27
exemption = 1
# Withholding should be 0, since pay is so low it's less than PST.
wh = 0.0
employee = self._createEmployee()
employee.company_id.nc_unemp_rate_2018 = 0.06
contract = self._createContract(employee, salary, struct_id=self.ref(
'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay)
contract.nc_nc4_allowances = exemption
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
nc_unemp = contract.nc_unemp_rate(2018) / -100.0
self._log('2018 North Carolina tax first payslip weekly:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp)
self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh)
process_payslip(payslip)

View File

@@ -0,0 +1,134 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
class TestUsNJPayslip(TestUsPayslip):
###
# 2018 Taxes and Rates
###
NJ_UNEMP_MAX_WAGE = 33700.0
# Examples found on page 24 of http://www.state.nj.us/treasury/taxation/pdf/current/njwt.pdf
def test_2018_taxes_example1(self):
salary = 300
schedule_pay = 'weekly'
allowances = 1
additional_withholding = 0
# Tax Percentage Method for Single, taxable pay over $58, under $346
wh = -4.21
employee = self._createEmployee()
employee.company_id.nj_unemp_employee = 0.3825
employee.company_id.nj_unemp_company = 3.4
employee.company_id.nj_sdi_employee = 0.19
employee.company_id.nj_sdi_company = 0.5
employee.company_id.nj_fli = 0.09
employee.company_id.nj_wf = 0.0
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_nj_hr_payroll.hr_payroll_salary_structure_us_nj_employee'),
schedule_pay=schedule_pay)
contract.nj_njw4_allowances = allowances
contract.nj_additional_withholding = additional_withholding
contract.nj_njw4_filing_status = 'single'
contract.nj_njw4_rate_table = 'A'
# tax rates
nj_unemp_employee = contract.nj_unemp_employee_rate(2018) / -100.0
nj_unemp_company = contract.nj_unemp_company_rate(2018) / -100.0
nj_sdi_employee = contract.nj_sdi_employee_rate(2018) / -100.0
nj_sdi_company = contract.nj_sdi_company_rate(2018) / -100.0
nj_fli = contract.nj_fli_rate(2018) / -100.0
nj_wf = contract.nj_wf_rate(2018) / -100.0
self.assertEqual(contract.schedule_pay, 'weekly')
self._log('2018 New Jersey tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NJ_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NJ_UNEMP_EMPLOYEE'], round(cats['NJ_UNEMP_WAGES'] * nj_unemp_employee, 2))
self.assertPayrollEqual(cats['NJ_UNEMP_COMPANY'], cats['NJ_UNEMP_WAGES'] * nj_unemp_company)
self.assertPayrollEqual(cats['NJ_SDI_EMPLOYEE'], cats['NJ_SDI_WAGES'] * nj_sdi_employee)
self.assertPayrollEqual(cats['NJ_SDI_COMPANY'], cats['NJ_SDI_WAGES'] * nj_sdi_company)
self.assertPayrollEqual(cats['NJ_FLI'], cats['NJ_FLI_WAGES'] * nj_fli)
self.assertPayrollEqual(cats['NJ_WF'], cats['NJ_WF_WAGES'] * nj_wf)
self.assertPayrollEqual(cats['NJ_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_nj_unemp_wages = self.NJ_UNEMP_MAX_WAGE - salary if (self.NJ_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 New Jersey tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NJ_UNEMP_WAGES'], remaining_nj_unemp_wages)
self.assertPayrollEqual(cats['NJ_UNEMP_COMPANY'], remaining_nj_unemp_wages * nj_unemp_company)
self.assertPayrollEqual(cats['NJ_UNEMP_EMPLOYEE'], remaining_nj_unemp_wages * nj_unemp_employee)
def test_2018_taxes_example2(self):
salary = 1400.00
schedule_pay = 'weekly'
allowances = 3
additional_withholding = 0
# Tax Percentage Method for Single, taxable pay over $58, under $346
wh = -27.60
employee = self._createEmployee()
employee.company_id.nj_unemp_employee = 0.3825
employee.company_id.nj_unemp_company = 3.4
employee.company_id.nj_sdi_employee = 0.19
employee.company_id.nj_sdi_company = 0.5
employee.company_id.nj_fli = 0.09
employee.company_id.nj_wf = 0.0
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_nj_hr_payroll.hr_payroll_salary_structure_us_nj_employee'),
schedule_pay=schedule_pay)
contract.nj_njw4_allowances = allowances
contract.nj_additional_withholding = additional_withholding
contract.nj_njw4_filing_status = 'married_joint'
# tax rates
nj_unemp_employee = contract.nj_unemp_employee_rate(2018) / -100.0
nj_unemp_company = contract.nj_unemp_company_rate(2018) / -100.0
nj_sdi_employee = contract.nj_sdi_employee_rate(2018) / -100.0
nj_sdi_company = contract.nj_sdi_company_rate(2018) / -100.0
nj_fli = contract.nj_fli_rate(2018) / -100.0
nj_wf = contract.nj_wf_rate(2018) / -100.0
self.assertEqual(contract.schedule_pay, 'weekly')
self._log('2018 New Jersey tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NJ_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NJ_UNEMP_EMPLOYEE'], round((cats['NJ_UNEMP_WAGES'] * nj_unemp_employee), 2))
self.assertPayrollEqual(cats['NJ_UNEMP_COMPANY'], cats['NJ_UNEMP_WAGES'] * nj_unemp_company)
self.assertPayrollEqual(cats['NJ_SDI_EMPLOYEE'], cats['NJ_SDI_WAGES'] * nj_sdi_employee)
self.assertPayrollEqual(cats['NJ_SDI_COMPANY'], cats['NJ_SDI_WAGES'] * nj_sdi_company)
self.assertPayrollEqual(cats['NJ_FLI'], cats['NJ_FLI_WAGES'] * nj_fli)
self.assertPayrollEqual(cats['NJ_WF'], cats['NJ_WF_WAGES'] * nj_wf)
self.assertPayrollEqual(cats['NJ_WITHHOLD'], wh)
process_payslip(payslip)

View File

@@ -0,0 +1,151 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
class TestUsNYPayslip(TestUsPayslip):
###
# Taxes and Rates
###
NY_UNEMP_MAX_WAGE = 11100
# Examples from http://www.edd.ca.gov/pdf_pub_ctr/18methb.pdf
def test_single_example1(self):
salary = 400
schedule_pay = 'weekly'
allowances = 3
additional_withholding = 0
wh = -8.20
employee = self._createEmployee()
employee.company_id.ny_unemp_rate_2018 = 0.825
employee.company_id.ny_rsf_rate_2018 = 0.075
employee.company_id.ny_mctmt_rate_2018 = 0.0
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ny_hr_payroll.hr_payroll_salary_structure_us_ny_employee'),
schedule_pay=schedule_pay)
contract.ny_it2104_allowances = allowances
contract.ny_additional_withholding = additional_withholding
contract.ny_it2104_filing_status = 'single'
self.assertEqual(contract.schedule_pay, 'weekly')
# tax rates
ny_unemp = contract.ny_unemp_rate(2018) / -100.0
ny_rsf = contract.ny_rsf_rate(2018) / -100.0
ny_mctmt = contract.ny_mctmt_rate(2018) / -100.0
self._log('2018 New York tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NY_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * ny_unemp)
self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * ny_rsf)
self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * ny_mctmt)
self.assertPayrollEqual(cats['NY_WITHHOLD'], wh)
process_payslip(payslip)
# Make a new payslip, this one will have maximums
remaining_ny_unemp_wages = self.NY_UNEMP_MAX_WAGE - salary if (self.NY_UNEMP_MAX_WAGE - 2 * salary < salary) \
else salary
self._log('2018 New York tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NY_UNEMP_WAGES'], remaining_ny_unemp_wages)
self.assertPayrollEqual(cats['NY_UNEMP'], remaining_ny_unemp_wages * ny_unemp)
def test_single_example2(self):
salary = 5000
schedule_pay = 'semi-monthly'
allowances = 3
additional_withholding = 0
wh = -284.19
employee = self._createEmployee()
employee.company_id.ny_unemp_rate_2018 = 0.825
employee.company_id.ny_rsf_rate_2018 = 0.075
employee.company_id.ny_mctmt_rate_2018 = 0.0
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ny_hr_payroll.hr_payroll_salary_structure_us_ny_employee'),
schedule_pay=schedule_pay)
contract.ny_it2104_allowances = allowances
contract.ny_additional_withholding = additional_withholding
contract.ny_it2104_filing_status = 'married'
self.assertEqual(contract.schedule_pay, 'semi-monthly')
# tax rates
ny_unemp = contract.ny_unemp_rate(2018) / -100.0
ny_rsf = contract.ny_rsf_rate(2018) / -100.0
ny_mctmt = contract.ny_mctmt_rate(2018) / -100.0
self._log('2018 New York tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NY_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * ny_unemp)
self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * ny_rsf)
self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * ny_mctmt)
self.assertPayrollEqual(cats['NY_WITHHOLD'], wh)
process_payslip(payslip)
def test_single_example3(self):
salary = 50000
schedule_pay = 'monthly'
allowances = 3
additional_withholding = 0
wh = -3575.63
employee = self._createEmployee()
employee.company_id.ny_unemp_rate_2018 = 0.825
employee.company_id.ny_rsf_rate_2018 = 0.075
employee.company_id.ny_mctmt_rate_2018 = 0.0
contract = self._createContract(employee,
salary,
struct_id=self.ref(
'l10n_us_ny_hr_payroll.hr_payroll_salary_structure_us_ny_employee'),
schedule_pay=schedule_pay)
contract.ny_it2104_allowances = allowances
contract.ny_additional_withholding = additional_withholding
contract.ny_it2104_filing_status = 'single'
self.assertEqual(contract.schedule_pay, 'monthly')
# tax rates
ny_unemp = contract.ny_unemp_rate(2018) / -100.0
ny_rsf = contract.ny_rsf_rate(2018) / -100.0
ny_mctmt = contract.ny_mctmt_rate(2018) / -100.0
self._log('2018 New York tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['NY_WITHHOLD'], wh)

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsOhPayslip(TestUsPayslip):

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsOhPayslip(TestUsPayslip):

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsOhPayslip(TestUsPayslip):

View File

@@ -0,0 +1,39 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsPAPayslip(TestUsPayslip):
###
# Taxes and Rates
###
PA_UNEMP_MAX_WAGE = 10000.0
def test_2018_taxes(self):
self.debug = True
salary = 4166.67
wh = -127.92
employee = self._createEmployee()
employee.company_id.pa_unemp_employee_rate_2018 = 0.06
employee.company_id.pa_unemp_company_rate_2018 = 3.6785
employee.company_id.pa_withhold_rate_2018 = 3.07
contract = self._createContract(employee, salary, struct_id=self.ref('l10n_us_pa_hr_payroll.hr_payroll_salary_structure_us_pa_employee'))
# tax rates
pa_unemp_employee = contract.pa_unemp_employee_rate(2018) / -100.0
pa_unemp_company = contract.pa_unemp_company_rate(2018) / -100.0
self._log('2018 Pennsylvania tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.onchange_contract()
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['PA_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['PA_UNEMP_EMPLOYEE'], cats['PA_UNEMP_WAGES'] * pa_unemp_employee)
self.assertPayrollEqual(cats['PA_UNEMP_COMPANY'], cats['PA_UNEMP_WAGES'] * pa_unemp_company)
self.assertPayrollEqual(cats['PA_WITHHOLD'], wh)

View File

@@ -0,0 +1,161 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsTXPayslip(TestUsPayslip):
###
# 2018 Taxes and Rates
###
TX_UNEMP_MAX_WAGE = 9000.0
def test_2018_taxes(self):
salary = 5000.0
employee = self._createEmployee()
employee.company_id.tx_unemp_rate_2018 = 2.7
employee.company_id.tx_oa_rate_2018 = 0.0
employee.company_id.tx_etia_rate_2018 = 0.1
contract = self._createContract(employee, salary, struct_id=self.ref('l10n_us_tx_hr_payroll.hr_payroll_salary_structure_us_tx_employee'))
# tax rates
tx_unemp = contract.tx_unemp_rate(2018) / -100.0
tx_oa = contract.tx_oa_rate(2018) / -100.00
tx_etia = contract.tx_etia_rate(2018) / -100.00
self._log('2018 Texas tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['TX_UNEMP'], cats['TX_UNEMP_WAGES'] * tx_unemp)
self.assertPayrollEqual(cats['TX_OA'], cats['TX_UNEMP_WAGES'] * tx_oa)
self.assertPayrollEqual(cats['TX_ETIA'], cats['TX_UNEMP_WAGES'] * 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('2018 Texas tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], remaining_tx_unemp_wages)
self.assertPayrollEqual(cats['TX_UNEMP'], remaining_tx_unemp_wages * tx_unemp)
def test_2018_taxes_with_external(self):
salary = 5000.0
external_wages = 6000.0
employee = self._createEmployee()
employee.company_id.tx_unemp_rate_2018 = 2.7
employee.company_id.tx_oa_rate_2018 = 0.0
employee.company_id.tx_etia_rate_2018 = 0.1
contract = self._createContract(employee, salary, external_wages=external_wages,
struct_id=self.ref('l10n_us_tx_hr_payroll.hr_payroll_salary_structure_us_tx_employee'))
# tax rates
tx_unemp = contract.tx_unemp_rate(2018) / -100.0
tx_oa = contract.tx_oa_rate(2018) / -100.00
tx_etia = contract.tx_etia_rate(2018) / -100.00
self._log('2018 Texas_external tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], self.TX_UNEMP_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['TX_UNEMP'], cats['TX_UNEMP_WAGES'] * tx_unemp)
self.assertPayrollEqual(cats['TX_OA'], cats['TX_UNEMP_WAGES'] * tx_oa)
self.assertPayrollEqual(cats['TX_ETIA'], cats['TX_UNEMP_WAGES'] * tx_etia)
def test_2018_taxes_with_state_exempt(self):
salary = 5000.0
external_wages = 6000.0
employee = self._createEmployee()
employee.company_id.tx_unemp_rate_2018 = 2.7
employee.company_id.tx_oa_rate_2018 = 0.0
employee.company_id.tx_etia_rate_2018 = 0.1
contract = self._createContract(employee, salary, external_wages=external_wages, struct_id=self.ref(
'l10n_us_tx_hr_payroll.hr_payroll_salary_structure_us_tx_employee'), futa_type=USHrContract.FUTA_TYPE_BASIC)
# tax rates
tx_unemp = contract.tx_unemp_rate(2018) / -100.0
tx_oa = contract.tx_oa_rate(2018) / -100.00
tx_etia = contract.tx_etia_rate(2018) / -100.00
self.assertPayrollEqual(tx_unemp, 0.0)
self._log('2018 Texas_external tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], self.TX_UNEMP_MAX_WAGE - external_wages)
self.assertPayrollEqual(cats['TX_UNEMP'], cats['TX_UNEMP_WAGES'] * tx_unemp)
self.assertPayrollEqual(cats['TX_OA'], cats['TX_UNEMP_WAGES'] * tx_oa)
self.assertPayrollEqual(cats['TX_ETIA'], cats['TX_UNEMP_WAGES'] * tx_etia)
def test_payslip_example(self):
salary = 2916.67
employee = self._createEmployee()
employee.company_id.tx_unemp_rate_2018 = 2.7
employee.company_id.tx_oa_rate_2018 = 0.0
employee.company_id.tx_etia_rate_2018 = 0.1
contract = self._createContract(employee, salary, struct_id=self.ref(
'l10n_us_tx_hr_payroll.hr_payroll_salary_structure_us_tx_employee'))
contract.w4_allowances = 2
contract.w4_filing_status = 'single'
# tax rates
tx_unemp = contract.tx_unemp_rate(2018) / -100.0
tx_oa = contract.tx_oa_rate(2018) / -100.00
tx_etia = contract.tx_etia_rate(2018) / -100.00
self._log('2018 Texas tax first payslip:')
payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], salary)
self.assertPayrollEqual(cats['TX_UNEMP'], cats['TX_UNEMP_WAGES'] * tx_unemp)
self.assertPayrollEqual(cats['TX_OA'], cats['TX_UNEMP_WAGES'] * tx_oa)
self.assertPayrollEqual(cats['TX_ETIA'], cats['TX_UNEMP_WAGES'] * 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('2018 Texas tax second payslip:')
payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['TX_UNEMP_WAGES'], remaining_tx_unemp_wages)
self.assertPayrollEqual(cats['TX_UNEMP'], remaining_tx_unemp_wages * tx_unemp)

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from openerp.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from openerp.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
from openerp.addons.l10n_us_hr_payroll.models.l10n_us_hr_payroll import USHrContract
class TestUsVaPayslip(TestUsPayslip):

View File

@@ -1,5 +1,4 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
from odoo.addons.l10n_us_hr_payroll.l10n_us_hr_payroll import USHrContract
class TestUsWAPayslip(TestUsPayslip):