Backport CA payroll to 10.0

This commit is contained in:
Jared Kipe
2019-01-07 14:40:42 -08:00
committed by Jared Kipe
parent d7ba50f024
commit 2dd50081a1
11 changed files with 1678 additions and 95 deletions

View File

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

View File

@@ -0,0 +1,32 @@
{
'name': 'USA - California - Payroll',
'author': 'Hibou Corp. <hello@hibou.io>',
'license': 'AGPL-3',
'category': 'Localization',
'depends': ['l10n_us_hr_payroll'],
'version': '11.0.2019.0.0',
'description': """
USA::California Payroll Rules.
==============================
* Contribution register and partner for California Department of Taxation - Unemployment Insurance Tax
* Contribution register and partner for California Department of Taxation - Income Tax Withholding
* Contribution register and partner for Califronia Department of Taxation - Employee Training Tax
* Contribution register and partner for Califronia Department of Taxation - State Disability Insurance
* Contract level California Exemptions
* Contract level California State Disability Insurance
* Company level California Unemployment Insurance Tax
* Company level California Employee Training Tax
""",
'auto_install': False,
'website': 'https://hibou.io/',
'data': [
'views/hr_payroll_views.xml',
'data/base.xml',
'data/rates.xml',
'data/rules.xml',
'data/final.xml',
],
'installable': True
}

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- CONTRIBUTION REGISTERS -->
<record id="res_partner_cador_uit" model="res.partner">
<field name="name">California Department of Taxation (CA DE88)</field>
<field name="supplier">1</field>
<field eval="0" name="customer"/>
</record>
<record id="res_partner_cador_withhold" model="res.partner">
<field name="name">California Department of Taxation - Income Tax Withholding</field>
<field name="supplier">1</field>
<field eval="0" name="customer"/>
<field eval="False" name="active"/>
</record>
<record id="res_partner_cador_ett" model="res.partner">
<field name="name">California Department of Taxation - Employment Training Tax</field>
<field name="supplier">1</field>
<field eval="0" name="customer"/>
<field eval="False" name="active"/>
</record>
<record id="res_partner_cador_sdi" model="res.partner">
<field name="name">California Department of Taxation - State Disability Insurance</field>
<field name="supplier">1</field>
<field eval="0" name="customer"/>
<field eval="False" name="active"/>
</record>
<record id="contrib_register_cador_uit" model="hr.contribution.register">
<field name="name">California (CA DE88)</field>
<field name="note">California Department of Taxation (CA DE88)</field>
<field name="partner_id" ref="res_partner_cador_uit"/>
</record>
<!-- HR SALARY RULE CATEGORIES-->
<record id="hr_payroll_ca_uit_wages" model="hr.salary.rule.category">
<field name="name">Wage: US-CA Unemployment Insurance</field>
<field name="code">WAGE_US_CA_UNEMP</field>
</record>
<record id="hr_payroll_ca_uit" model="hr.salary.rule.category">
<field name="name">ER: US-CA Unemployment Insurance</field>
<field name="code">ER_US_CA_UNEMP</field>
<field name="parent_id" ref="hr_payroll.COMP"/>
</record>
<record id="hr_payroll_ca_ett_wages" model="hr.salary.rule.category">
<field name="name">Wage: US-CA Employee Training Tax</field>
<field name="code">WAGE_US_CA_ETT</field>
</record>
<record id="hr_payroll_ca_ett" model="hr.salary.rule.category">
<field name="name">ER: US-CA Employee Training Tax</field>
<field name="code">ER_US_CA_ETT</field>
<field name="parent_id" ref="hr_payroll.COMP"/>
</record>
<record id="hr_payroll_ca_sdi_wages" model="hr.salary.rule.category">
<field name="name">Wage: US-CA State Disability Insurance</field>
<field name="code">WAGE_US_CA_SDI</field>
</record>
<record id="hr_payroll_ca_sdi" model="hr.salary.rule.category">
<field name="name">EE: US-CA State Disability Insurance</field>
<field name="code">EE_US_CA_SDI</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_ca_income_withhold" model="hr.salary.rule.category">
<field name="name">EE: US-CA Income Withholding</field>
<field name="code">EE_US_CA_INC_WITHHOLD</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_payroll_rates_ca_unemp_2018" model="hr.payroll.rate">
<field name="name">US California Unemployment</field>
<field name="code">US_CA_UNEMP</field>
<field name="rate">2.6</field>
<field name="date_from">2018-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_ca_ett_2018" model="hr.payroll.rate">
<field name="name">US California Employment Training Tax</field>
<field name="code">US_CA_ETT</field>
<field name="rate">0.1</field>
<field name="date_from">2018-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_ca_sdi_2018" model="hr.payroll.rate">
<field name="name">US California State Disability Insurance</field>
<field name="code">US_CA_SDI</field>
<field name="rate">1.0</field>
<field name="date_from">2018-01-01</field>
<field name="wage_limit_year" eval="114967.0"/>
</record>
<record id="hr_payroll_rates_ca_unemp_2019" model="hr.payroll.rate">
<field name="name">US California Unemployment</field>
<field name="code">US_CA_UNEMP</field>
<field name="rate">3.4</field>
<field name="date_from">2019-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_ca_ett_2019" model="hr.payroll.rate">
<field name="name">US California Employment Training Tax</field>
<field name="code">US_CA_ETT</field>
<field name="rate">0.1</field>
<field name="date_from">2019-01-01</field>
<field name="wage_limit_year" eval="7000"/>
</record>
<record id="hr_payroll_rates_ca_sdi_2019" model="hr.payroll.rate">
<field name="name">US California State Disability Insurance</field>
<field name="code">US_CA_SDI</field>
<field name="rate">1.0</field>
<field name="date_from">2019-01-01</field>
<field name="wage_limit_year" eval="18371.0"/>
</record>
</odoo>

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,16 @@
from odoo import models, fields, api
class USCAHrContract(models.Model):
_inherit = 'hr.contract'
ca_de4_allowances = fields.Integer(string="California CA-4 Allowances",
default=0,
help="Estimated Deductions claimed on DE-4")
ca_additional_allowances = fields.Integer(string="Additional Allowances", default=0)
ca_de4_filing_status = fields.Selection([
('exempt', 'Exempt'),
('single', 'Single'),
('married', 'Married'),
('head_household', 'Head of Household')
], string='CA Filing Status', default='single')

View File

@@ -0,0 +1,2 @@
from . import test_us_ca_payslip_2018
from . import test_us_ca_payslip_2019

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.models.l10n_us_hr_payroll import USHrContract
class TestUsCAPayslip(TestUsPayslip):
@@ -10,6 +9,10 @@ class TestUsCAPayslip(TestUsPayslip):
CA_UIT_MAX_WAGE = 7000
CA_SDI_MAX_WAGE = 114967
CA_UIT = -2.6 / 100.0
CA_ETT = -0.1 / 100.0
CA_SDI = -1.0 / 100.0
# Examples from http://www.edd.ca.gov/pdf_pub_ctr/18methb.pdf
def test_example_a(self):
salary = 210
@@ -32,11 +35,6 @@ class TestUsCAPayslip(TestUsPayslip):
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()
@@ -49,13 +47,13 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], cats['WAGE_US_CA_UNEMP'] * self.CA_UIT)
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], cats['WAGE_US_CA_ETT'] * self.CA_ETT)
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], cats['WAGE_US_CA_SDI'] * self.CA_SDI)
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)
@@ -71,8 +69,8 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], remaining_ca_uit_wages * self.CA_UIT)
def test_example_b(self):
salary = 1250
@@ -81,16 +79,8 @@ class TestUsCAPayslip(TestUsPayslip):
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(
@@ -117,13 +107,13 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)
@@ -139,8 +129,8 @@ class TestUsCAPayslip(TestUsPayslip):
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))
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_c(self):
salary = 3800
@@ -149,16 +139,8 @@ class TestUsCAPayslip(TestUsPayslip):
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(
@@ -185,13 +167,13 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)
@@ -207,8 +189,8 @@ class TestUsCAPayslip(TestUsPayslip):
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))
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_d(self):
salary = 800
@@ -217,16 +199,8 @@ class TestUsCAPayslip(TestUsPayslip):
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(
@@ -253,13 +227,13 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)
@@ -275,8 +249,8 @@ class TestUsCAPayslip(TestUsPayslip):
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))
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_e(self):
salary = 1800
@@ -285,16 +259,8 @@ class TestUsCAPayslip(TestUsPayslip):
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(
@@ -321,13 +287,13 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)
@@ -343,8 +309,8 @@ class TestUsCAPayslip(TestUsPayslip):
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))
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_f(self):
salary = 45000
@@ -353,16 +319,8 @@ class TestUsCAPayslip(TestUsPayslip):
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(
@@ -389,10 +347,10 @@ class TestUsCAPayslip(TestUsPayslip):
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)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
process_payslip(payslip)

View File

@@ -0,0 +1,425 @@
from odoo.addons.l10n_us_hr_payroll.tests.test_us_payslip import TestUsPayslip, process_payslip
class TestUsCAPayslip(TestUsPayslip):
###
# Taxes and Rates
###
CA_UIT_MAX_WAGE = 7000
CA_UIT_MAX_WAGE = 7000
CA_SDI_MAX_WAGE = 18371
CA_UIT = -3.4 / 100.0
CA_ETT = -0.1 / 100.0
CA_SDI = -1.0 / 100.0
# 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')
self._log('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California 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_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], cats['WAGE_US_CA_UNEMP'] * self.CA_UIT)
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], cats['WAGE_US_CA_ETT'] * self.CA_ETT)
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], cats['WAGE_US_CA_SDI'] * self.CA_SDI)
self.assertPayrollEqual(cats['EE_US_CA_INC_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('2019 California 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_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], remaining_ca_uit_wages * self.CA_UIT)
def test_example_b(self):
salary = 1250
schedule_pay = 'bi-weekly'
allowances = 2
additional_allowances = 1
# for additional allowances
wh = salary - 38
wh = wh - 339
wh = (wh - 632) * 0.022 + 6.95
wh = wh - 9.65
# 2.651 - 9.65
wh = -wh
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_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('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California 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_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_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('2019 California 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_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_c(self):
salary = 3800
schedule_pay = 'monthly'
allowances = 5
additional_allowances = 0.72
wh = -0.11
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_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('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California 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_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_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('2019 California 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_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_d(self):
salary = 800
schedule_pay = 'weekly'
allowances = 3
additional_allowances = 0
wh = -3.18
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_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('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California 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_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_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('2019 California 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_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_e(self):
salary = 1800
schedule_pay = 'semi-monthly'
allowances = 4
additional_allowances = 0
wh = -3.08
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_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('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California 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_CA_UNEMP'], salary)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_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('2019 California 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_CA_UNEMP'], remaining_ca_uit_wages)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
def test_example_f(self):
salary = 45000
schedule_pay = 'annually'
allowances = 4
additional_allowances = 0
wh = -113.85
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_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('2018 California tax last payslip:')
payslip = self._createPayslip(employee, '2018-12-01', '2018-12-31')
payslip.compute_sheet()
process_payslip(payslip)
self._log('2019 California tax first payslip:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
self.assertPayrollEqual(cats['EE_US_CA_INC_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

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="hr_contract_form_l10n_us_ca_inherit" model="ir.ui.view">
<field name="name">hr.contract.form.inherit</field>
<field name="model">hr.contract</field>
<field name="priority">147</field>
<field name="inherit_id" ref="hr_contract.hr_contract_view_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//group[@name='state_filing']" position="inside">
<group string="California" name="ca">
<field name="ca_de4_filing_status"/>
<field name="ca_de4_allowances" string="DE-4 Allowances"/>
<field name="ca_additional_allowances" string="Additional Allowances"/>
</group>
</xpath>
</data>
</field>
</record>
</data>
</odoo>