[IMP] l10n_ca_hr_payroll: paramatarize more Federal

This commit is contained in:
Jared Kipe
2021-12-27 15:14:25 -08:00
parent 33a9b41b9d
commit e2052404af
22 changed files with 330 additions and 128 deletions

View File

@@ -17,6 +17,7 @@ Canada - Payroll Rules.
'data': [
'security/ir.model.access.csv',
'data/base.xml',
'data/ded.xml',
'data/federal.xml',
'data/ca_cpp.xml',
# 'views/hr_contract_views.xml',

View File

@@ -21,10 +21,33 @@
</record>
<!-- Categories -->
<record id="hr_payroll_category_ee_fed_cpp" model="hr.salary.rule.category">
<field name="name">EE: Canada Pension Plan</field>
<field name="code">EE_CA_CPP</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_category_ee_fed_ei" model="hr.salary.rule.category">
<field name="name">EE: CA Employment Insurance</field>
<field name="code">EE_CA_EI</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_category_ee_fed_fit" model="hr.salary.rule.category">
<field name="name">EE: Federal Income Tax Withholding</field>
<field name="code">EE_CA_FIT</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_category_alw_fed_fit_exempt" model="hr.salary.rule.category">
<field name="name">ALW: FIT Exempt</field>
<field name="code">ALW_FIT_EXEMPT</field>
<field name="parent_id" ref="hr_payroll.ALW"/>
</record>
<record id="hr_payroll_category_ded_fed_fit_exempt" model="hr.salary.rule.category">
<field name="name">DED: FIT Exempt</field>
<field name="code">DED_FIT_EXEMPT</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<!-- Included in Gross Remuneration -->

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="rule_parameter_ca_fed_tax_rate" model="hr.rule.parameter">
<field name="name">CA Federal Tax Rate</field>
<field name="code">ca_fed_tax_rate</field>
<field name="country_id" ref="base.ca"/>
</record>
<data noupdate="1">
<record id="rule_parameter_ca_fed_tax_rate_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">{
'annually': (
( 0, 0.1500, 0.00),
( 49029, 0.2050, 2696.00),
( 98040, 0.2600, 8088.00),
( 151978, 0.2900, 12648.00),
( 216511, 0.3300, 21308.00),
( 'inf', 0.3300, 21308.00),
),
}</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_tax_rate"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
</data>
<record id="res_partner_ca_fed" model="res.partner">
<field name="name">CA Federal - Canada Revenue Agency - Federal Income Tax</field>
</record>
<!-- Rules -->
<record id="hr_payroll_rule_ee_ca_fit" model="hr.salary.rule">
<field name="sequence" eval="195"/>
<field name="struct_id" ref="hr_ca_payroll_structure"/>
<field name="category_id" ref="hr_payroll_category_basic_ca_salary"/>
<field name="name">EE: CA Federal Income Tax</field>
<field name="code">EE_CA_FIT</field>
<field name="condition_select">python</field>
<field name="condition_python">result, _ = ca_fit_federal_income_tax_withholding(payslip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result, result_rate = ca_fit_federal_income_tax_withholding(payslip)</field>
<field name="partner_id" ref="res_partner_ca_fed"/>
<field name="appears_on_payslip" eval="True"/>
</record>
</odoo>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- FIT Exempt -->
<!-- F (RPP, RRSP, PRPP, RCA) Retirement plans-->
<!-- F2 (Annual alimony or maintenance payments)-->
<!-- U1 (Union Dues) -->
</odoo>

View File

@@ -6,45 +6,191 @@
<field name="code">ca_fed_tax_rate</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_tax_rate_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">[
( 0, 0.1500, 0.00),
( 49020, 0.2050, 2696.00),
( 98040, 0.2600, 8088.00),
( 151978, 0.2900, 12648.00),
( 216511, 0.3300, 21308.00),
( 'inf', 0.3300, 21308.00),
]</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_tax_rate"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<data noupdate="1">
<record id="rule_parameter_ca_fed_tax_rate_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">[
( 0, 0.1500, 0.00),
( 49020, 0.2050, 2696.00),
( 98040, 0.2600, 8088.00),
( 151978, 0.2900, 12648.00),
( 216511, 0.3300, 21308.00),
( 'inf', 0.3300, 21308.00),
]</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_tax_rate"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
</data>
<record id="rule_parameter_ca_fed_k1" model="hr.rule.parameter">
<field name="name">CA Federal Personal Tax Credit Rate (K1)</field>
<field name="code">ca_fed_k1</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k1_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.15</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k1"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2" model="hr.rule.parameter">
<field name="name">CA Federal Pension &amp; EI Credit Rate (K1)</field>
<field name="code">ca_fed_k2</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.15</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2_pc_max" model="hr.rule.parameter">
<field name="name">CA Federal Pension Credit Maximum (K2)</field>
<field name="code">ca_fed_k2_pc_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2_pc_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">3166.45</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2_pc_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2_pei_max" model="hr.rule.parameter">
<field name="name">CA Federal Pension Credit Maximum (K2)</field>
<field name="code">ca_fed_k2_pei_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2_pei_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">889.54</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2_pei_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pc_max" model="hr.rule.parameter">
<field name="name">CA Quebec Federal Pension Credit Maximum (K2Q)</field>
<field name="code">ca_fed_k2q_pc_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pc_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">3427.90</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2q_pc_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pei_max" model="hr.rule.parameter">
<field name="name">CA Quebec Federal Pension Credit Maximum (K2Q)</field>
<field name="code">ca_fed_k2q_pei_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pei_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">664.34</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2q_pei_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pie" model="hr.rule.parameter">
<field name="name">CA Quebec Insurable Earnings Credit Rate (K2Q)</field>
<field name="code">ca_fed_k2q_pie</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pie_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.00494</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2q_pie"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pie_max" model="hr.rule.parameter">
<field name="name">CA Quebec Insurable Earnings Credit Maximum (K2Q)</field>
<field name="code">ca_fed_k2q_pie_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k2q_pie_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">412.49</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k2q_pie_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k4" model="hr.rule.parameter">
<field name="name">CA Nonrefundable Tax Credit Rate (K4)</field>
<field name="code">ca_fed_k4</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k4_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.15</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k4"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_k4" model="hr.rule.parameter">
<field name="name">CA Employment Amount Rate (K4)</field>
<field name="code">ca_fed_k4</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_k4_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.15</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_k4"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_cea" model="hr.rule.parameter">
<field name="name">CA Employment Amount (CEA)</field>
<field name="code">ca_fed_cea</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_cea_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">1257.0</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_cea"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_lcf_max" model="hr.rule.parameter">
<field name="name">CA LCF Max</field>
<field name="code">ca_fed_lcf_max</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_lcf_max_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">750.0</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_lcf_max"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_lcf_rate" model="hr.rule.parameter">
<field name="name">CA LCF Rate</field>
<field name="code">ca_fed_lcf_rate</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_lcf_rate_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">15.0</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_lcf_rate"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_t1q" model="hr.rule.parameter">
<field name="name">CA T1 Quebec Rate</field>
<field name="code">ca_fed_t1q</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_t1q_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.165</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_t1q"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<record id="rule_parameter_ca_fed_t1_outside" model="hr.rule.parameter">
<field name="name">CA T1 Outside Rate</field>
<field name="code">ca_fed_t1_outside</field>
<field name="country_id" ref="base.ca"/>
</record>
<record id="rule_parameter_ca_fed_t1_outside_2021_01" model="hr.rule.parameter.value">
<field name="parameter_value">0.48</field>
<field name="rule_parameter_id" ref="rule_parameter_ca_fed_t1_outside"/>
<field name="date_from" eval="datetime(2021, 1, 1).date()"/>
</record>
<!-- Partner -->
<record id="res_partner_ca_fed" model="res.partner">
<field name="name">CA Federal - Canada Revenue Agency - Federal Income Tax</field>
</record>
<!-- Categories -->
<record id="hr_payroll_category_ee_fed_cpp" model="hr.salary.rule.category">
<field name="name">EE: Canada Pension Plan</field>
<field name="code">EE_CA_CPP</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_category_ee_fed_ei" model="hr.salary.rule.category">
<field name="name">EE: CA Employment Insurance</field>
<field name="code">EE_CA_EI</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_payroll_category_ee_fed_fit" model="hr.salary.rule.category">
<field name="name">EE: Federal Income Tax Withholding</field>
<field name="code">EE_CA_FIT</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<!-- Rules -->
<record id="hr_payroll_rule_ee_fed_cpp" model="hr.salary.rule">
<field name="sequence" eval="181"/>

View File

@@ -74,8 +74,12 @@ class HRContractCanadaPayrollConfig(models.Model):
# fed_td1_6_disability_amount = fields.Float()
# fed_td1_7_spouse_amount = fields.Float()
# fed_td1_8_dependant_amount = fields.Float()
fed_td1_total_claim_amount = fields.Float()
fed_td1_deduction_prescribed_zone = fields.Float()
fed_td1_additional = fields.Float()
is_cpp_exempt = fields.Boolean()
is_ei_exempt = fields.Boolean()
is_outside_ca = fields.Boolean(string='Outside Canada or beyond limits of province/territory')

View File

@@ -1,5 +1,7 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from ..state.general import _state_applies
def _compute_annual_taxable_income(payslip, categories):
"""
@@ -8,16 +10,107 @@ def _compute_annual_taxable_income(payslip, categories):
"""
P = payslip.dict.get_pay_periods_in_year()
I = categories.GROSS \
- categories.ALW_FIT_EXEMPT \
+ categories.DED_FIT_EXEMPT
F = 0.0 # Payroll deductions for RPP or RRSP ...
F2 = 0.0
U1 = 0.0 # Union Dues
- categories.ALW_FIT_EXEMPT
# F = 0.0 # Payroll deductions for RPP or RRSP ...
# F2 = 0.0 # Annual Alimony or maintenance payments
# U1 = 0.0 # Union Dues
I += categories.DED_FIT_EXEMPT
HD = 0.0 # Annual deduction for living in a prescribed zone Form TD1
F1 = 0.0 # Annual deductions such as child care and authorized
A = (P * (I - F - F2 - U1)) - HD - F1
# A = (P * (I - F - F2 - U1)) - HD - F1
A = (P * I) - HD - F1
return A
def ca_fit_k1_personal_tax_credit(payslip, categories, worked_days, inputs):
TC = payslip.contract_id.ca_payroll_config_value('fed_td1_total_claim_amount')
k1 = payslip.rule_parameter('ca_fed_k1')
return k1 * TC
def ca_fit_k2_cpp_ei_tax_credit(payslip, categories, worked_days, inputs):
P = payslip.dict.get_pay_periods_in_year()
C = -categories.EE_CA_CPP
EI = -categories.EE_CA_EI
k2 = payslip.rule_parameter('ca_fed_k2')
result = 0.0
if _state_applies(payslip, 'QC'):
pc_max = payslip.rule_parameter('ca_fed_k2q_pc_max')
pei_max = payslip.rule_parameter('ca_fed_k2q_pei_max')
pie = payslip.rule_parameter('ca_fed_k2q_pie')
pie_max = payslip.rule_parameter('ca_fed_k2q_pie_max')
IE = 0.0 # TODO get IE
result = k2 * min(P * IE * pie, pie_max)
else:
pc_max = payslip.rule_parameter('ca_fed_k2_pc_max')
pei_max = payslip.rule_parameter('ca_fed_k2_pei_max')
if not payslip.contract_id.ca_payroll_config_value('is_cpp_exempt'):
result += k2 * min(P * C, pc_max)
if not payslip.contract_id.ca_payroll_config_value('is_ei_exempt'):
result += k2 * min(P * EI, pei_max)
return result
def ca_fit_k3_other_tax_credits(payslip, categories, worked_days, inputs):
# this could be a category (if it were a dummy category)
# this could be a contract field, but what would it truely mean?
# How would we know if we implemented this after the first pay period?
# adjust (P * K3) / PR
return 0.0
def ca_fit_k4_non_refunable_tax_credit(payslip, categories, worked_days, inputs):
k4 = payslip.rule_parameter('ca_fed_k4')
A = _compute_annual_taxable_income(payslip, categories)
cea = payslip.rule_parameter('ca_fed_cea')
return min(k4 * A, k4 * cea)
def ca_fit_t3_annual_basic_federal_tax(payslip, categories, worked_days, inputs):
"""
T3 = Annual basic federal tax
= (R × A) K K1 K2 K3 K4
If the result is negative, T3 = $0.
"""
A = _compute_annual_taxable_income(payslip, categories)
rates = payslip.rule_parameter('ca_fed_tax_rate')
for annual_taxable_income, rate, federal_constant in rates:
annual_taxable_income = float(annual_taxable_income)
if A < annual_taxable_income:
break
R, K = rate, federal_constant
T3 = (R * A) - K
T3 -= ca_fit_k1_personal_tax_credit(payslip, categories, worked_days, inputs)
T3 -= ca_fit_k2_cpp_ei_tax_credit(payslip, categories, worked_days, inputs)
T3 -= ca_fit_k3_other_tax_credits(payslip, categories, worked_days, inputs)
T3 -= ca_fit_k4_non_refunable_tax_credit(payslip, categories, worked_days, inputs)
if T3 < 0.0:
return 0.0
return T3
def ca_fit_t1_federal_income_tax_payable(payslip, categories, worked_days, inputs):
T3 = ca_fit_t3_annual_basic_federal_tax(payslip, categories, worked_days, inputs)
# Short out as it can only go down..
if T3 <= 0.0:
return 0.0
amount_deducted_stock = 0.0
# amount deducted or withheld during the year for the acquisition by the employee of approved shares of the capital stock of a prescribed labour-sponsored venture capital corporation
# this amount could be a category, but it would need to be year to date.
LCF = min(750.0, 0.15 * amount_deducted_stock) # 0.0 => amount deducted or withheld during the year for the acquisition by the employee of approved shares of the capital stock of a prescribed labour-sponsored venture capital corporation
if _state_applies(payslip, 'QC'):
t1q = payslip.rule_parameter('ca_fed_t1q')
T1 = (T3 - LCF) - (t1q * T3)
elif payslip.contract_id.ca_payroll_config_value('is_outside_ca'):
t1_outside = payslip.rule_parameter('ca_fed_t1_outside')
T1 = T3 + (t1_outside * T3) - LCF
else:
T1 = T3 - LCF
if T1 < 0.0:
return 0.0
return T1
def ca_fit_federal_income_tax_withholding(payslip, categories, worked_days, inputs):
L = payslip.contract_id.ca_payroll_config_value('fed_td1_additional')
@@ -27,42 +120,14 @@ def ca_fit_federal_income_tax_withholding(payslip, categories, worked_days, inpu
return -L, 100.0
elif A <= 0.0:
return 0.0, 0.0
TC = payslip.contract_id.ca_payroll_config_value('fed_td1_total_claim_amount')
T1 = ca_fit_t1_federal_income_tax_payable(payslip, categories, worked_days, inputs)
if T1 <= 0.0 and L:
return -L, 100.0
elif T1 <= 0.0:
return 0.0, 0.0
P = payslip.dict.get_pay_periods_in_year()
"""
T3 = Annual basic federal tax
= (R × A) K K1 K2 K3 K4
If the result is negative, T3 = $0.
"""
rates = payslip.rule_parameter('ca_fed_tax_rate')
for annual_taxable_income, rate, federal_constant in rates:
annual_taxable_income = float(annual_taxable_income)
if A < annual_taxable_income:
break
R, K = rate, federal_constant
K1 = 0.15 * TC
K2 = 0.0
if not payslip.contract_id.ca_payroll_config_value('is_cpp_exempt'):
C = -categories.EE_CA_CPP
K2 += 0.15 * min(P * C, 3166.45) # min because we can only have up to
if not payslip.contract_id.ca_payroll_config_value('is_ei_exempt'):
EI = -categories.EE_CA_EI
K2 += 0.15 * min(P * EI, 889.54)
K3 = 0.0 # medical
CEA = 1257.0 # TODO this is an indexed parameter
K4 = min(0.15 * A, 0.15 * CEA)
T3 = (R * A) - K - K1 - K2 - K3 - K4
LCF = min(750.0, 0.15 * 0.0) # 0.0 => amount deducted or withheld during the year for the acquisition by the employee of approved shares of the capital stock of a prescribed labour-sponsored venture capital corporation
T1 = T3 - LCF
if T1 < 0.0:
T1 = 0.0
T = (T1 / P) + L
if T > 0.0:
T = round(T, 2)

View File

@@ -0,0 +1,6 @@
def _state_applies(payslip, state_code):
return state_code == payslip.contract_id.ca_payroll_config_value('state_code')
# Export for eval context
is_ca_state = _state_applies

View File

@@ -4,6 +4,3 @@ from . import common
# Tests moved to `l10n_ca_hr_payroll_params`
# common remains for site specific tests
from . import test_ca_fed_2021_1
# from . import test_ca_province_payslip