mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
Update l10n_us_ca_hr_payroll for 2019 Rates and Limits.
This commit is contained in:
@@ -1 +1 @@
|
|||||||
from . import hr_payroll
|
from . import models
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'category': 'Localization',
|
'category': 'Localization',
|
||||||
'depends': ['l10n_us_hr_payroll'],
|
'depends': ['l10n_us_hr_payroll'],
|
||||||
'version': '11.0.2018.1.0',
|
'version': '11.0.2019.0.0',
|
||||||
'description': """
|
'description': """
|
||||||
USA::California Payroll Rules.
|
USA::California Payroll Rules.
|
||||||
==============================
|
==============================
|
||||||
@@ -22,9 +22,10 @@ USA::California Payroll Rules.
|
|||||||
'auto_install': False,
|
'auto_install': False,
|
||||||
'website': 'https://hibou.io/',
|
'website': 'https://hibou.io/',
|
||||||
'data': [
|
'data': [
|
||||||
'hr_payroll_view.xml',
|
'views/hr_payroll_views.xml',
|
||||||
'data/base.xml',
|
'data/base.xml',
|
||||||
'data/rules_2018.xml',
|
'data/rates.xml',
|
||||||
|
'data/rules.xml',
|
||||||
'data/final.xml',
|
'data/final.xml',
|
||||||
],
|
],
|
||||||
'installable': True
|
'installable': True
|
||||||
|
|||||||
@@ -32,62 +32,43 @@
|
|||||||
<field name="partner_id" ref="res_partner_cador_uit"/>
|
<field name="partner_id" ref="res_partner_cador_uit"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- These are deprecated in favor of a single grouped register for CA DE88 -->
|
|
||||||
<!-- They are left here in case their details or structure is needed later. -->
|
|
||||||
<!--<record id="contrib_register_cador_withhold" model="hr.contribution.register">-->
|
|
||||||
<!--<field name="name">California Income Tax Withholding</field>-->
|
|
||||||
<!--<field name="note">California Department of Taxation - Income Tax Withholding</field>-->
|
|
||||||
<!--<field name="partner_id" ref="res_partner_cador_withhold"/>-->
|
|
||||||
<!--</record>-->
|
|
||||||
<!--<record id="contrib_register_cador_ett" model="hr.contribution.register">-->
|
|
||||||
<!--<field name="name">Employment Training Tax</field>-->
|
|
||||||
<!--<field name="note">California Department of Taxation - Employment Training Tax</field>-->
|
|
||||||
<!--<field name="partner_id" ref="res_partner_cador_ett"/>-->
|
|
||||||
<!--</record>-->
|
|
||||||
<!--<record id="contrib_register_cador_sdi" model="hr.contribution.register">-->
|
|
||||||
<!--<field name="name">State Disability Insurance</field>-->
|
|
||||||
<!--<field name="note">California Department of Taxation - State Disability Insurance</field>-->
|
|
||||||
<!--<field name="partner_id" ref="res_partner_cador_sdi"/>-->
|
|
||||||
<!--</record>-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- HR SALARY RULE CATEGORIES-->
|
<!-- HR SALARY RULE CATEGORIES-->
|
||||||
<record id="hr_payroll_ca_uit_wages" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_uit_wages" model="hr.salary.rule.category">
|
||||||
<field name="name">California Unemployment Insurance Tax - Wages</field>
|
<field name="name">Wage: US-CA Unemployment Insurance</field>
|
||||||
<field name="code">CA_UIT_WAGES</field>
|
<field name="code">WAGE_US_CA_UNEMP</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_uit" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_uit" model="hr.salary.rule.category">
|
||||||
<field name="name">California Unemployment Insurance Tax</field>
|
<field name="name">ER: US-CA Unemployment Insurance</field>
|
||||||
<field name="code">CA_UIT</field>
|
<field name="code">ER_US_CA_UNEMP</field>
|
||||||
<field name="parent_id" ref="hr_payroll.COMP"/>
|
<field name="parent_id" ref="hr_payroll.COMP"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_ett_wages" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_ett_wages" model="hr.salary.rule.category">
|
||||||
<field name="name">California Employee Training Tax - Wages</field>
|
<field name="name">Wage: US-CA Employee Training Tax</field>
|
||||||
<field name="code">CA_ETT_WAGES</field>
|
<field name="code">WAGE_US_CA_ETT</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_ett" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_ett" model="hr.salary.rule.category">
|
||||||
<field name="name">California Employee Training Tax</field>
|
<field name="name">ER: US-CA Employee Training Tax</field>
|
||||||
<field name="code">CA_ETT</field>
|
<field name="code">ER_US_CA_ETT</field>
|
||||||
<field name="parent_id" ref="hr_payroll.COMP"/>
|
<field name="parent_id" ref="hr_payroll.COMP"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_sdi_wages" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_sdi_wages" model="hr.salary.rule.category">
|
||||||
<field name="name">California State Disability Insurance - Wages</field>
|
<field name="name">Wage: US-CA State Disability Insurance</field>
|
||||||
<field name="code">CA_SDI_WAGES</field>
|
<field name="code">WAGE_US_CA_SDI</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_sdi" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_sdi" model="hr.salary.rule.category">
|
||||||
<field name="name">California State Disability Insurance</field>
|
<field name="name">EE: US-CA State Disability Insurance</field>
|
||||||
<field name="code">CA_SDI</field>
|
<field name="code">EE_US_CA_SDI</field>
|
||||||
<field name="parent_id" ref="hr_payroll.DED"/>
|
<field name="parent_id" ref="hr_payroll.DED"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="hr_payroll_ca_income_withhold" model="hr.salary.rule.category">
|
<record id="hr_payroll_ca_income_withhold" model="hr.salary.rule.category">
|
||||||
<field name="name">California Income Withholding</field>
|
<field name="name">EE: US-CA Income Withholding</field>
|
||||||
<field name="code">CA_WITHHOLD</field>
|
<field name="code">EE_US_CA_INC_WITHHOLD</field>
|
||||||
<field name="parent_id" ref="hr_payroll.DED"/>
|
<field name="parent_id" ref="hr_payroll.DED"/>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
46
l10n_us_ca_hr_payroll/data/rates.xml
Executable file
46
l10n_us_ca_hr_payroll/data/rates.xml
Executable 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>
|
||||||
1005
l10n_us_ca_hr_payroll/data/rules.xml
Executable file
1005
l10n_us_ca_hr_payroll/data/rules.xml
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,576 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
|
|
||||||
<!-- HR SALARY RULES-->
|
|
||||||
<!-- UIT -->
|
|
||||||
<record id="hr_payroll_rules_ca_uit_wages_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="423"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_uit_wages"/>
|
|
||||||
<field name="name">California Unemployment Insurance Tax - Wages (2018)</field>
|
|
||||||
<field name="code">CA_UIT_WAGES_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
###
|
|
||||||
ytd = payslip.sum('CA_UIT_WAGES_2018', '2018-01-01', '2019-01-01')
|
|
||||||
ytd += contract.external_wages
|
|
||||||
remaining = 7000.0 - ytd
|
|
||||||
if remaining <= 0.0:
|
|
||||||
result = 0
|
|
||||||
elif remaining < categories.BASIC:
|
|
||||||
result = remaining
|
|
||||||
else:
|
|
||||||
result = categories.BASIC
|
|
||||||
</field>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="hr_payroll_rules_ca_uit_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="443"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_uit"/>
|
|
||||||
<field name="name">California Unemployment Insurance Tax(2018)</field>
|
|
||||||
<field name="code">CA_UIT_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
result_rate = -contract.ca_uit_rate(2018)
|
|
||||||
result = categories.CA_UIT_WAGES
|
|
||||||
|
|
||||||
# result_rate of 0 implies 100% due to bug
|
|
||||||
if result_rate == 0.0:
|
|
||||||
result = 0.0
|
|
||||||
</field>
|
|
||||||
<field name="register_id" ref="contrib_register_cador_uit"/>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ETT -->
|
|
||||||
<record id="hr_payroll_rules_ca_ett_wages_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="423"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_ett_wages"/>
|
|
||||||
<field name="name">California Employment Training Tax - Wages (2018)</field>
|
|
||||||
<field name="code">CA_ETT_WAGES_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
###
|
|
||||||
ytd = payslip.sum('CA_ETT_WAGES_2018', '2018-01-01', '2019-01-01')
|
|
||||||
ytd += contract.external_wages
|
|
||||||
remaining = 7000.0 - ytd
|
|
||||||
if remaining <= 0.0:
|
|
||||||
result = 0
|
|
||||||
elif remaining < categories.BASIC:
|
|
||||||
result = remaining
|
|
||||||
else:
|
|
||||||
result = categories.BASIC
|
|
||||||
</field>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="hr_payroll_rules_ca_ett_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="443"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_ett"/>
|
|
||||||
<field name="name">California Employee Training Tax(2018)</field>
|
|
||||||
<field name="code">CA_ETT_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
result_rate = -contract.ca_ett_rate(2018)
|
|
||||||
result = categories.CA_ETT_WAGES
|
|
||||||
|
|
||||||
# result_rate of 0 implies 100% due to bug
|
|
||||||
if result_rate == 0.0:
|
|
||||||
result = 0.0
|
|
||||||
</field>
|
|
||||||
<field name="register_id" ref="contrib_register_cador_uit"/>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- SDI -->
|
|
||||||
<record id="hr_payroll_rules_ca_sdi_wages_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="190"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_sdi_wages"/>
|
|
||||||
<field name="name">California State Disability Insurance Tax - Wages (2018)</field>
|
|
||||||
<field name="code">CA_SDI_WAGES_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
###
|
|
||||||
ytd = payslip.sum('CA_SDI_WAGES_2018', '2018-01-01', '2019-01-01')
|
|
||||||
ytd += contract.external_wages
|
|
||||||
remaining = 114967.0 - ytd
|
|
||||||
if remaining <= 0.0:
|
|
||||||
result = 0
|
|
||||||
elif remaining < categories.BASIC:
|
|
||||||
result = remaining
|
|
||||||
else:
|
|
||||||
result = categories.BASIC
|
|
||||||
</field>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="hr_payroll_rules_ca_sdi_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="195"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_sdi"/>
|
|
||||||
<field name="name">California State Disability Insurance(2018)</field>
|
|
||||||
<field name="code">CA_SDI_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
result_rate = -contract.ca_sdi_rate(2018)
|
|
||||||
result = categories.CA_SDI_WAGES
|
|
||||||
|
|
||||||
# result_rate of 0 implies 100% due to bug
|
|
||||||
if result_rate == 0.0:
|
|
||||||
result = 0.0
|
|
||||||
</field>
|
|
||||||
<field name="register_id" ref="contrib_register_cador_uit"/>
|
|
||||||
<field name="appears_on_payslip" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- STATE INCOME WITHHOLDING -->
|
|
||||||
<record id="hr_payroll_rules_ca_inc_withhold_2018" model="hr.salary.rule">
|
|
||||||
<field name="sequence" eval="145"/>
|
|
||||||
<field name="category_id" ref="hr_payroll_ca_income_withhold"/>
|
|
||||||
<field name="name">California Income Withholding</field>
|
|
||||||
<field name="code">CA_INC_WITHHOLD_2018</field>
|
|
||||||
<field name="condition_select">python</field>
|
|
||||||
<field name="condition_python">result = (payslip.date_to[:4] == '2018')</field>
|
|
||||||
<field name="amount_select">code</field>
|
|
||||||
<field name="amount_python_compute">
|
|
||||||
wages = categories.GROSS
|
|
||||||
allowances = contract.ca_de4_allowances
|
|
||||||
additional_allowances = contract.ca_additional_allowances
|
|
||||||
schedule_pay = contract.schedule_pay
|
|
||||||
filing_status = contract.ca_de4_filing_status
|
|
||||||
low_income = False
|
|
||||||
|
|
||||||
# Tables are found in http://www.edd.ca.gov/pdf_pub_ctr/18methb.pdf
|
|
||||||
# First check low income exemption table (Step 1)
|
|
||||||
low_income_exemption_table = {
|
|
||||||
'weekly': (270, 270, 540, 540),
|
|
||||||
'bi-weekly': (540, 540, 1081, 1081),
|
|
||||||
'semi-monthly': (585, 585, 1171, 1171),
|
|
||||||
'monthly': (1171, 1171, 2341, 2341),
|
|
||||||
'quarterly': (3512, 3512, 7024, 7024),
|
|
||||||
'semi-annual': (7024, 7024, 14048, 14048),
|
|
||||||
'annually': (14048, 14048, 28095, 28095),
|
|
||||||
}
|
|
||||||
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
_, _, _, income = low_income_exemption_table[schedule_pay]
|
|
||||||
if wages <= income:
|
|
||||||
result = 0
|
|
||||||
low_income = True
|
|
||||||
elif filing_status == 'married':
|
|
||||||
if allowances >= 2:
|
|
||||||
_, _, income, _ = low_income_exemption_table[schedule_pay]
|
|
||||||
if wages <= income:
|
|
||||||
result = 0
|
|
||||||
low_income = True
|
|
||||||
else:
|
|
||||||
_, income, _, _ = low_income_exemption_table[schedule_pay]
|
|
||||||
if wages <= income:
|
|
||||||
result = 0
|
|
||||||
low_income = True
|
|
||||||
else:
|
|
||||||
income, _, _, _ = low_income_exemption_table[schedule_pay]
|
|
||||||
if wages <= income:
|
|
||||||
result = 0
|
|
||||||
low_income = True
|
|
||||||
|
|
||||||
if not low_income:
|
|
||||||
# Estimated deduction table (Step 2)
|
|
||||||
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),
|
|
||||||
'annually': (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000),
|
|
||||||
}
|
|
||||||
|
|
||||||
allowance_index = additional_allowances - 1
|
|
||||||
if additional_allowances > 10:
|
|
||||||
deduction = (estimated_deduction_table[schedule_pay][0]) * additional_allowances
|
|
||||||
wages -= deduction
|
|
||||||
elif additional_allowances > 0:
|
|
||||||
deduction = estimated_deduction_table[schedule_pay][allowance_index]
|
|
||||||
wages -= deduction
|
|
||||||
|
|
||||||
# Standard deduction table (Step 3)
|
|
||||||
standard_deduction_table = {
|
|
||||||
'weekly': (81, 81, 163, 163),
|
|
||||||
'bi-weekly': (163, 163, 326, 326),
|
|
||||||
'semi-monthly': (177, 177, 353, 353),
|
|
||||||
'monthly': (353, 353, 706, 706),
|
|
||||||
'quarterly': (1059, 1059, 2118, 2118),
|
|
||||||
'semi-annual': (2118, 2118, 4236, 4236),
|
|
||||||
'annually': (4236, 4236, 8472, 8472),
|
|
||||||
}
|
|
||||||
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
_, _, _, deduction = standard_deduction_table[schedule_pay]
|
|
||||||
wages -= deduction
|
|
||||||
elif filing_status == 'married':
|
|
||||||
if allowances >= 2:
|
|
||||||
_, _, deduction, _ = standard_deduction_table[schedule_pay]
|
|
||||||
wages -= deduction
|
|
||||||
else:
|
|
||||||
_, deduction, _, _ = standard_deduction_table[schedule_pay]
|
|
||||||
wages -= deduction
|
|
||||||
else:
|
|
||||||
deduction, _, _, _ = standard_deduction_table[schedule_pay]
|
|
||||||
wages -= deduction
|
|
||||||
|
|
||||||
# Tax Rate Tables (Step 4)
|
|
||||||
#### WEEKLY ####
|
|
||||||
if schedule_pay == 'weekly':
|
|
||||||
if filing_status == 'head_household' and wages > 0:
|
|
||||||
tax_rate_table = [
|
|
||||||
(316, 0.011, 0.0),
|
|
||||||
(750, 0.022, 3.48),
|
|
||||||
(967, 0.044, 13.03),
|
|
||||||
(1196, 0.066, 22.58),
|
|
||||||
(1413, 0.088, 37.69),
|
|
||||||
(7212, 0.1023, 56.79),
|
|
||||||
(8654, 0.1133, 650.03),
|
|
||||||
(14423, 0.1243, 813.41),
|
|
||||||
(19231, 0.1353, 1530.50),
|
|
||||||
(float('inf'), 0.1463, 2181.02),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(316, 0.011, 0.0),
|
|
||||||
(750, 0.022, 3.48),
|
|
||||||
(1184, 0.044, 13.03),
|
|
||||||
(1642, 0.066, 32.13),
|
|
||||||
(2076, 0.088, 62.36),
|
|
||||||
(10606, 0.1023, 100.55),
|
|
||||||
(12726, 0.1133, 973.17),
|
|
||||||
(19231, 0.1243, 1213.37),
|
|
||||||
(21210, 0.1353, 2021.94),
|
|
||||||
(float('inf'), 0.1463, 2289.70),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(158, 0.011, 0.0),
|
|
||||||
(375, 0.022, 1.74),
|
|
||||||
(592, 0.044, 6.51),
|
|
||||||
(821, 0.066, 16.06),
|
|
||||||
(1038, 0.088, 31.17),
|
|
||||||
(5303, 0.1023, 50.27),
|
|
||||||
(6363, 0.1133, 486.58),
|
|
||||||
(10605, 0.1243, 606.68),
|
|
||||||
(19231, 0.1353, 1133.96),
|
|
||||||
(float('inf'), 0.1463, 2301.06),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### BI-WEEKLY ####
|
|
||||||
elif schedule_pay == 'bi-weekly':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(632, 0.011, 0.0),
|
|
||||||
(1500, 0.022, 6.95),
|
|
||||||
(1934, 0.044, 26.05),
|
|
||||||
(2392, 0.066, 45.15),
|
|
||||||
(2826, 0.088, 75.38),
|
|
||||||
(14424, 0.1023, 113.57),
|
|
||||||
(17308, 0.1133, 1300.05),
|
|
||||||
(28846, 0.1243, 1626.81),
|
|
||||||
(38462, 0.1353, 3060.98),
|
|
||||||
(float('inf'), 0.1463, 4362.02),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(632, 0.011, 0.0),
|
|
||||||
(1500, 0.022, 6.95),
|
|
||||||
(2368, 0.044, 26.05),
|
|
||||||
(3284, 0.066, 64.24),
|
|
||||||
(4152, 0.088, 124.70),
|
|
||||||
(21212, 0.1023, 201.08),
|
|
||||||
(25452, 0.1133, 1946.32),
|
|
||||||
(38462, 0.1243, 2426.71),
|
|
||||||
(42420, 0.1353, 4043.85),
|
|
||||||
(float('inf'), 0.1463, 4579.37),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(316, 0.011, 0.0),
|
|
||||||
(750, 0.022, 3.48),
|
|
||||||
(1184, 0.044, 13.03),
|
|
||||||
(1642, 0.066, 32.13),
|
|
||||||
(2076, 0.088, 62.36),
|
|
||||||
(10606, 0.1023, 100.55),
|
|
||||||
(12726, 0.1133, 973.17),
|
|
||||||
(21210, 0.1243, 1213.37),
|
|
||||||
(38462, 0.1353, 2267.93),
|
|
||||||
(float('inf'), 0.1463, 4602.13),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### SEMI-MONTHLY ####
|
|
||||||
elif schedule_pay == 'semi-monthly':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(686, 0.011, 0.0),
|
|
||||||
(1625, 0.022, 7.55),
|
|
||||||
(2094, 0.044, 28.21),
|
|
||||||
(2592, 0.066, 48.85),
|
|
||||||
(3062, 0.088, 81.72),
|
|
||||||
(15625, 0.1023, 123.08),
|
|
||||||
(18750, 0.1133, 1408.27),
|
|
||||||
(31250, 0.1243, 1762.33),
|
|
||||||
(41667, 0.1353, 3316.08),
|
|
||||||
(float('inf'), 0.1463, 4725.50),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(686, 0.011, 0.0),
|
|
||||||
(1624, 0.022, 7.55),
|
|
||||||
(2564, 0.044, 28.19),
|
|
||||||
(3560, 0.066, 69.55),
|
|
||||||
(4498, 0.088, 135.29),
|
|
||||||
(22978, 0.1023, 217.83),
|
|
||||||
(27574, 0.1133, 2108.33),
|
|
||||||
(41667, 0.1243, 2629.06),
|
|
||||||
(45956, 0.1353, 4380.82),
|
|
||||||
(float('inf'), 0.1463, 4961.12),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(343, 0.011, 0.0),
|
|
||||||
(812, 0.022, 3.77),
|
|
||||||
(1282, 0.044, 14.09),
|
|
||||||
(1780, 0.066, 34.77),
|
|
||||||
(2249, 0.088, 67.64),
|
|
||||||
(11489, 0.1023, 108.91),
|
|
||||||
(13787, 0.1133, 1054.16),
|
|
||||||
(22978, 0.1243, 1314.52),
|
|
||||||
(41667, 0.1353, 2456.96),
|
|
||||||
(float('inf'), 0.1463, 4985.58),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### MONTHLY ####
|
|
||||||
elif schedule_pay == 'monthly':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(1372, 0.011, 0.0),
|
|
||||||
(3250, 0.022, 15.09),
|
|
||||||
(4188, 0.044, 56.41),
|
|
||||||
(5184, 0.066, 97.68),
|
|
||||||
(6124, 0.088, 163.42),
|
|
||||||
(31250, 0.1023, 246.148),
|
|
||||||
(37500, 0.1133, 2816.53),
|
|
||||||
(62500, 0.1243, 3524.66),
|
|
||||||
(83334, 0.1353, 6632.16),
|
|
||||||
(float('inf'), 0.1463, 9451.00),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(1372, 0.011, 0.0),
|
|
||||||
(3248, 0.022, 15.09),
|
|
||||||
(5128, 0.044, 56.36),
|
|
||||||
(7120, 0.066, 139.08),
|
|
||||||
(8996, 0.088, 270.55),
|
|
||||||
(45956, 0.1023, 435.64),
|
|
||||||
(55148, 0.1133, 4216.65),
|
|
||||||
(83334, 0.1243, 5258.10),
|
|
||||||
(91912, 0.1353, 8761.62),
|
|
||||||
(float('inf'), 0.1463, 9922.22),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(686, 0.011, 0.0),
|
|
||||||
(1624, 0.022, 7.55),
|
|
||||||
(2564, 0.044, 28.19),
|
|
||||||
(3560, 0.066, 69.55),
|
|
||||||
(4498, 0.088, 135.29),
|
|
||||||
(22978, 0.1023, 217.83),
|
|
||||||
(27574, 0.1133, 2108.33),
|
|
||||||
(45956, 0.1243, 2629.06),
|
|
||||||
(83334, 0.1353, 4913.94),
|
|
||||||
(float('inf'), 0.1463, 9971.18),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### QUARTERLY ####
|
|
||||||
elif schedule_pay == 'quarterly':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(4114, 0.011, 0.0),
|
|
||||||
(9748, 0.022, 45.25),
|
|
||||||
(12566, 0.044, 169.20),
|
|
||||||
(15552, 0.066, 293.19),
|
|
||||||
(18369, 0.088, 490.27),
|
|
||||||
(93751, 0.1023, 738.17),
|
|
||||||
(112501, 0.1133, 8449.75),
|
|
||||||
(187501, 0.1243, 10574.13),
|
|
||||||
(250000, 0.1353, 19896.63),
|
|
||||||
(float('inf'), 0.1463, 28352.74),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(4112, 0.011, 0.0),
|
|
||||||
(9748, 0.022, 45.23),
|
|
||||||
(15384, 0.044, 169.22),
|
|
||||||
(21356, 0.066, 417.20),
|
|
||||||
(26990, 0.088, 811.35),
|
|
||||||
(137870, 0.1023, 1307.14),
|
|
||||||
(165442, 0.1133, 12650.16),
|
|
||||||
(250000, 0.1243, 15774.07),
|
|
||||||
(275736, 0.1353, 26284.63),
|
|
||||||
(float('inf'), 0.1463, 29766.71),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(2056, 0.011, 0.0),
|
|
||||||
(4874, 0.022, 22.62),
|
|
||||||
(7692, 0.044, 84.62),
|
|
||||||
(10678, 0.066, 208.61),
|
|
||||||
(13495, 0.088, 405.69),
|
|
||||||
(68935, 0.1023, 653.59),
|
|
||||||
(82721, 0.1133, 6325.10),
|
|
||||||
(137868, 0.1243, 7887.05),
|
|
||||||
(250000, 0.1353, 14741.82),
|
|
||||||
(float('inf'), 0.1463, 29913.28),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### SEMI-ANNUAL ####
|
|
||||||
elif schedule_pay == 'semi-annual':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(8228, 0.011, 0.0),
|
|
||||||
(19496, 0.022, 90.51),
|
|
||||||
(25132, 0.044, 338.41),
|
|
||||||
(31104, 0.066, 586.39),
|
|
||||||
(36738, 0.088, 980.54),
|
|
||||||
(187502, 0.1023, 1476.33),
|
|
||||||
(225002, 0.1133, 16899.49),
|
|
||||||
(375002, 0.1243, 21148.24),
|
|
||||||
(500000, 0.1353, 39793.24),
|
|
||||||
(float('inf'), 0.1463, 56705.47),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(8224, 0.011, 0.0),
|
|
||||||
(19496, 0.022, 90.46),
|
|
||||||
(30768, 0.044, 338.44),
|
|
||||||
(42712, 0.066, 834.41),
|
|
||||||
(53980, 0.088, 1622.71),
|
|
||||||
(275740, 0.1023, 2614.29),
|
|
||||||
(330884, 0.1133, 25300.34),
|
|
||||||
(500000, 0.1243, 31548.16),
|
|
||||||
(551472, 0.1353, 52569.28),
|
|
||||||
(float('inf'), 0.1463, 59533.44),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(4112, 0.011, 0.0),
|
|
||||||
(9748, 0.022, 45.23),
|
|
||||||
(15384, 0.044, 169.22),
|
|
||||||
(21356, 0.066, 417.20),
|
|
||||||
(26990, 0.088, 811.35),
|
|
||||||
(137870, 0.1023, 1307.14),
|
|
||||||
(165442, 0.1133, 12650.16),
|
|
||||||
(275736, 0.1243, 15774.07),
|
|
||||||
(500000, 0.1353, 29483.61),
|
|
||||||
(float('inf'), 0.1463, 59826.53),
|
|
||||||
]
|
|
||||||
|
|
||||||
#### ANNUAL ####
|
|
||||||
elif schedule_pay == 'annually':
|
|
||||||
if filing_status == 'head_household':
|
|
||||||
tax_rate_table = [
|
|
||||||
(16457, 0.011, 0.0),
|
|
||||||
(38991, 0.022, 181.03),
|
|
||||||
(50264, 0.044, 676.78),
|
|
||||||
(62206, 0.066, 1172.79),
|
|
||||||
(73477, 0.088, 1960.96),
|
|
||||||
(375002, 0.1023, 2952.81),
|
|
||||||
(450003, 0.1133, 33798.82),
|
|
||||||
(750003, 0.1243, 42296.43),
|
|
||||||
(1000000, 0.1353, 79586.43),
|
|
||||||
(float('inf'), 0.1463, 113411.02),
|
|
||||||
]
|
|
||||||
|
|
||||||
elif filing_status == 'married':
|
|
||||||
tax_rate_table = [
|
|
||||||
(16446, 0.011, 0.0),
|
|
||||||
(38990, 0.022, 180.91),
|
|
||||||
(61538, 0.044, 676.88),
|
|
||||||
(85422, 0.066, 1668.99),
|
|
||||||
(107960, 0.088, 3245.33),
|
|
||||||
(551476, 0.1023, 5228.67),
|
|
||||||
(661768, 0.1133, 50600.36),
|
|
||||||
(1000000, 0.1243, 63096.44),
|
|
||||||
(1102946, 0.1353, 105138.68),
|
|
||||||
(float('inf'), 0.1463, 119067.26),
|
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
tax_rate_table = [
|
|
||||||
(8223, 0.011, 0.0),
|
|
||||||
(19495, 0.022, 90.45),
|
|
||||||
(30769, 0.044, 338.43),
|
|
||||||
(42711, 0.066, 834.49),
|
|
||||||
(53980, 0.088, 1622.66),
|
|
||||||
(275738, 0.1023, 2614.33),
|
|
||||||
(330884, 0.1133, 25300.17),
|
|
||||||
(551473, 0.1243, 31548.21),
|
|
||||||
(1000000, 0.1353, 58967.42),
|
|
||||||
(float('inf'), 0.1463, 119653.12),
|
|
||||||
]
|
|
||||||
|
|
||||||
over = 0.0
|
|
||||||
tax = 0.0
|
|
||||||
for row in tax_rate_table:
|
|
||||||
if wages <= row[0]:
|
|
||||||
tax = ((wages - over) * row[1]) + row[2]
|
|
||||||
break
|
|
||||||
over = row[0]
|
|
||||||
|
|
||||||
# Exemption allowance table (Step 5)
|
|
||||||
exemption_allowance_table = {
|
|
||||||
'weekly': (2.41, 4.82, 7.23, 9.65, 12.06, 14.47, 16.88, 19.29, 21.70, 24.12),
|
|
||||||
'bi-weekly': (4.82, 9.65, 14.47, 19.29, 24.12, 28.94, 33.76, 38.58, 43.41, 48.23),
|
|
||||||
'semi-monthly': (5.23, 10.45, 15.68, 20.90, 26.13, 31.35, 36.58, 41.80, 47.03, 52.25),
|
|
||||||
'monthly': (10.45, 20.90, 31.35, 41.80, 52.25, 62.70, 73.15, 83.60, 94.05, 104.50),
|
|
||||||
'quarterly': (31.35, 62.70, 94.05, 125.40, 156.75, 188.10, 219.45, 250.80, 282.15, 313.50),
|
|
||||||
'semi-annual': (62.70, 125.40, 188.10, 250.80, 313.50, 376.20, 438.90, 501.60, 564.30, 627.00),
|
|
||||||
'annually': (125.40, 250.80, 376.20, 501.60, 627.00, 752.40, 877.80, 1003.20, 1128.60, 1254.00),
|
|
||||||
}
|
|
||||||
|
|
||||||
allowance_index = allowances - 1
|
|
||||||
if allowances > 10:
|
|
||||||
deduction = (exemption_allowance_table[schedule_pay][0]) * allowances
|
|
||||||
tax -= deduction
|
|
||||||
elif allowances > 0:
|
|
||||||
deduction = exemption_allowance_table[schedule_pay][allowance_index]
|
|
||||||
tax -= deduction
|
|
||||||
|
|
||||||
result = -tax
|
|
||||||
</field>
|
|
||||||
<field name="register_id" ref="contrib_register_cador_uit"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
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')
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def ca_uit_rate(self, year):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.futa_type == self.FUTA_TYPE_BASIC:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
if hasattr(self.employee_id.company_id, 'ca_uit_rate_' + str(year)):
|
|
||||||
return self.employee_id.company_id['ca_uit_rate_' + str(year)]
|
|
||||||
|
|
||||||
raise NotImplemented('Year (' + str(year) + ') Not implemented for US California.')
|
|
||||||
|
|
||||||
def ca_ett_rate(self, year):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.futa_type == self.FUTA_TYPE_BASIC:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
if hasattr(self.employee_id.company_id, 'ca_ett_rate_' + str(year)):
|
|
||||||
return self.employee_id.company_id['ca_ett_rate_' + str(year)]
|
|
||||||
|
|
||||||
raise NotImplemented('Year (' + str(year) + ') Not implemented for US California.')
|
|
||||||
|
|
||||||
def ca_sdi_rate(self, year):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.futa_type == self.FUTA_TYPE_BASIC:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
if hasattr(self.employee_id.company_id, 'ca_sdi_rate_' + str(year)):
|
|
||||||
return self.employee_id.company_id['ca_sdi_rate_' + str(year)]
|
|
||||||
|
|
||||||
raise NotImplemented('Year (' + str(year) + ') Not implemented for US California.')
|
|
||||||
|
|
||||||
|
|
||||||
class CACompany(models.Model):
|
|
||||||
_inherit = 'res.company'
|
|
||||||
|
|
||||||
# UIT can be calculated using http://www.edd.ca.gov/pdf_pub_ctr/de44.pdf ETT is default.
|
|
||||||
ca_uit_rate_2018 = fields.Float(string="California Unemployment Insurance Tax Rate 2018", default=2.6)
|
|
||||||
ca_ett_rate_2018 = fields.Float(string="California Employment Training Tax Rate 2018", default=0.1)
|
|
||||||
ca_sdi_rate_2018 = fields.Float(string="California State Disability Insurance Rate 2018", default=1.0)
|
|
||||||
1
l10n_us_ca_hr_payroll/models/__init__.py
Normal file
1
l10n_us_ca_hr_payroll/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import hr_payroll
|
||||||
16
l10n_us_ca_hr_payroll/models/hr_payroll.py
Executable file
16
l10n_us_ca_hr_payroll/models/hr_payroll.py
Executable 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')
|
||||||
@@ -1 +1,2 @@
|
|||||||
from . import test_us_ca_payslip_2018
|
from . import test_us_ca_payslip_2018
|
||||||
|
from . import test_us_ca_payslip_2019
|
||||||
|
|||||||
@@ -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.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):
|
class TestUsCAPayslip(TestUsPayslip):
|
||||||
@@ -10,6 +9,10 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
CA_UIT_MAX_WAGE = 7000
|
CA_UIT_MAX_WAGE = 7000
|
||||||
CA_SDI_MAX_WAGE = 114967
|
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
|
# Examples from http://www.edd.ca.gov/pdf_pub_ctr/18methb.pdf
|
||||||
def test_example_a(self):
|
def test_example_a(self):
|
||||||
salary = 210
|
salary = 210
|
||||||
@@ -32,11 +35,6 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
self.assertEqual(contract.schedule_pay, 'weekly')
|
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:')
|
self._log('2017 California tax last payslip:')
|
||||||
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
|
payslip = self._createPayslip(employee, '2017-12-01', '2017-12-31')
|
||||||
payslip.compute_sheet()
|
payslip.compute_sheet()
|
||||||
@@ -49,13 +47,13 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], cats['CA_UIT_WAGES'] * ca_uit)
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], cats['WAGE_US_CA_UNEMP'] * self.CA_UIT)
|
||||||
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], cats['CA_ETT_WAGES'] * ca_ett)
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], cats['WAGE_US_CA_ETT'] * self.CA_ETT)
|
||||||
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], cats['CA_SDI_WAGES'] * ca_sdi)
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], cats['WAGE_US_CA_SDI'] * self.CA_SDI)
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
@@ -71,8 +69,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], remaining_ca_uit_wages * ca_uit)
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], remaining_ca_uit_wages * self.CA_UIT)
|
||||||
|
|
||||||
def test_example_b(self):
|
def test_example_b(self):
|
||||||
salary = 1250
|
salary = 1250
|
||||||
@@ -81,16 +79,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
additional_allowances = 1
|
additional_allowances = 1
|
||||||
|
|
||||||
wh = -2.89
|
wh = -2.89
|
||||||
# tax rates
|
|
||||||
ca_uit = 2.6
|
|
||||||
ca_ett = 0.1
|
|
||||||
ca_sdi = 1.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
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,
|
contract = self._createContract(employee,
|
||||||
salary,
|
salary,
|
||||||
struct_id=self.ref(
|
struct_id=self.ref(
|
||||||
@@ -117,13 +107,13 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
@@ -139,8 +129,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
|
||||||
|
|
||||||
def test_example_c(self):
|
def test_example_c(self):
|
||||||
salary = 3800
|
salary = 3800
|
||||||
@@ -149,16 +139,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
additional_allowances = 0.72
|
additional_allowances = 0.72
|
||||||
|
|
||||||
wh = -0.72
|
wh = -0.72
|
||||||
# tax rates
|
|
||||||
ca_uit = 2.6
|
|
||||||
ca_ett = 0.1
|
|
||||||
ca_sdi = 1.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
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,
|
contract = self._createContract(employee,
|
||||||
salary,
|
salary,
|
||||||
struct_id=self.ref(
|
struct_id=self.ref(
|
||||||
@@ -185,13 +167,13 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
@@ -207,8 +189,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
|
||||||
|
|
||||||
def test_example_d(self):
|
def test_example_d(self):
|
||||||
salary = 800
|
salary = 800
|
||||||
@@ -217,16 +199,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
additional_allowances = 0
|
additional_allowances = 0
|
||||||
|
|
||||||
wh = -3.31
|
wh = -3.31
|
||||||
# tax rates
|
|
||||||
ca_uit = 2.6
|
|
||||||
ca_ett = 0.1
|
|
||||||
ca_sdi = 1.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
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,
|
contract = self._createContract(employee,
|
||||||
salary,
|
salary,
|
||||||
struct_id=self.ref(
|
struct_id=self.ref(
|
||||||
@@ -253,13 +227,13 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
@@ -275,8 +249,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
|
||||||
|
|
||||||
def test_example_e(self):
|
def test_example_e(self):
|
||||||
salary = 1800
|
salary = 1800
|
||||||
@@ -285,16 +259,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
additional_allowances = 0
|
additional_allowances = 0
|
||||||
|
|
||||||
wh = -3.39
|
wh = -3.39
|
||||||
# tax rates
|
|
||||||
ca_uit = 2.6
|
|
||||||
ca_ett = 0.1
|
|
||||||
ca_sdi = 1.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
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,
|
contract = self._createContract(employee,
|
||||||
salary,
|
salary,
|
||||||
struct_id=self.ref(
|
struct_id=self.ref(
|
||||||
@@ -321,13 +287,13 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_ETT_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_ETT'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_SDI_WAGES'], salary)
|
self.assertPayrollEqual(cats['WAGE_US_CA_SDI'], salary)
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
@@ -343,8 +309,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT_WAGES'], remaining_ca_uit_wages)
|
self.assertPayrollEqual(cats['WAGE_US_CA_UNEMP'], remaining_ca_uit_wages)
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((remaining_ca_uit_wages * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((remaining_ca_uit_wages * self.CA_UIT), 2))
|
||||||
|
|
||||||
def test_example_f(self):
|
def test_example_f(self):
|
||||||
salary = 45000
|
salary = 45000
|
||||||
@@ -353,16 +319,8 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
additional_allowances = 0
|
additional_allowances = 0
|
||||||
|
|
||||||
wh = -121.11
|
wh = -121.11
|
||||||
# tax rates
|
|
||||||
ca_uit = 2.6
|
|
||||||
ca_ett = 0.1
|
|
||||||
ca_sdi = 1.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
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,
|
contract = self._createContract(employee,
|
||||||
salary,
|
salary,
|
||||||
struct_id=self.ref(
|
struct_id=self.ref(
|
||||||
@@ -389,10 +347,10 @@ class TestUsCAPayslip(TestUsPayslip):
|
|||||||
|
|
||||||
cats = self._getCategories(payslip)
|
cats = self._getCategories(payslip)
|
||||||
|
|
||||||
self.assertPayrollEqual(cats['CA_UIT'], round((cats['CA_UIT_WAGES'] * ca_uit)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_UNEMP'], round((cats['WAGE_US_CA_UNEMP'] * self.CA_UIT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_ETT'], round((cats['CA_ETT_WAGES'] * ca_ett)/-100, 2))
|
self.assertPayrollEqual(cats['ER_US_CA_ETT'], round((cats['WAGE_US_CA_ETT'] * self.CA_ETT), 2))
|
||||||
self.assertPayrollEqual(cats['CA_SDI'], round((cats['CA_SDI_WAGES'] * ca_sdi)/-100, 2))
|
self.assertPayrollEqual(cats['EE_US_CA_SDI'], round((cats['WAGE_US_CA_SDI'] * self.CA_SDI), 2))
|
||||||
self.assertPayrollEqual(cats['CA_WITHHOLD'], wh)
|
self.assertPayrollEqual(cats['EE_US_CA_INC_WITHHOLD'], wh)
|
||||||
|
|
||||||
process_payslip(payslip)
|
process_payslip(payslip)
|
||||||
|
|
||||||
|
|||||||
425
l10n_us_ca_hr_payroll/tests/test_us_ca_payslip_2019.py
Executable file
425
l10n_us_ca_hr_payroll/tests/test_us_ca_payslip_2019.py
Executable 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)
|
||||||
@@ -1,19 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<record id="us_ca_view_company_form" model="ir.ui.view">
|
|
||||||
<field name="name">res.company.form</field>
|
|
||||||
<field name="model">res.company</field>
|
|
||||||
<field name="priority">64</field>
|
|
||||||
<field name="inherit_id" ref="base.view_company_form"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<data>
|
|
||||||
<xpath expr="//field[@name='currency_id']" position="after">
|
|
||||||
<field name="ca_uit_rate_2018"/>
|
|
||||||
</xpath>
|
|
||||||
</data>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
<record id="hr_contract_form_l10n_us_ca_inherit" model="ir.ui.view">
|
<record id="hr_contract_form_l10n_us_ca_inherit" model="ir.ui.view">
|
||||||
<field name="name">hr.contract.form.inherit</field>
|
<field name="name">hr.contract.form.inherit</field>
|
||||||
<field name="model">hr.contract</field>
|
<field name="model">hr.contract</field>
|
||||||
Reference in New Issue
Block a user