[wip] l10n_ca_hr_payroll: Adding canada pension plan algorithm.

H5939
This commit is contained in:
Jared Self
2021-05-25 17:48:41 -06:00
parent 769693b261
commit 6d9c12f913
7 changed files with 130 additions and 18 deletions

View File

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

View File

@@ -36,9 +36,9 @@
<field name="name">EE: CA Canada Pension Plan</field>
<field name="code">EE_CA_CPP</field>
<field name="condition_select">python</field>
<field name="condition_python">result = ca_cpp_canada_pension_plan_withholding(payslip)</field>
<field name="condition_python">result, _ = ca_cpp_canada_pension_plan_withholding(payslip, categories)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = ca_cpp_canada_pension_plan_withholding(payslip)</field>
<field name="amount_python_compute">result, result_rate = ca_cpp_canada_pension_plan_withholding(payslip, categories)</field>
<field name="partner_id" ref="res_partner_ca_cpp"/>
<field name="appears_on_payslip" eval="True"/>
</record>

View File

@@ -1,3 +1,4 @@
from . import ca_payroll_config
from . import hr_ca_contract
from . import hr_payslip
from .federal import ca_fit

View File

@@ -1,9 +1,114 @@
from odoo import fields
from .common import TestCAPayslip
from datetime import datetime, timedelta
import logging
_logger = logging.getLogger("__name__")
def ca_cpp_canada_pension_plan_withholding(payslip):
_logger.warning('ca_cpp_canada_pension_plan_withholding************************')
pass
def ca_cpp_canada_pension_plan_withholding(payslip, categories):
#K2 = [(0.15 × ((0.0545 × ((S1 × PI) + B1 $3,500)*, maximum $3,166.45)))) + (0.15 × ((0.0158 × ((S1 × IE) + B1), maximum $889.54))]
payperiods_s1 = _compute_payperiod_ratio_s1(payslip)
pensionable_income_pi = _compute_pensionable_income_pi(payslip, categories)
#todo: remove
import pydevd_pycharm
pydevd_pycharm.settrace('192.168.1.27', port=6900, stdoutToServer=True, stderrToServer=True)
return 0.0, 0.0
def _compute_payperiod_ratio_s1(payslip):
wage_type = payslip.wage_type
pay_periods = payslip.dict.PAY_PERIODS_IN_YEAR[wage_type]
if wage_type == 'annually':
return 1
elif wage_type == 'semi_annually':
if payslip.date_to.month < 7:
return 1/pay_periods
else:
return 2/pay_periods
elif wage_type == 'quarterly':
quarters = {
1:1,
2:1,
3:1,
4:2,
5:2,
6:2,
7:3,
8:3,
9:3,
10:4,
11:4,
12:4,
}
quarter = quarters[payslip.date_to.month]
return quarter/pay_periods
elif wage_type == 'bi-monthly':
bi_monthly_int = {
1:1,
2:1,
3:2,
4:2,
5:3,
6:3,
7:4,
8:4,
9:5,
10:5,
11:6,
12:6,
}
bi_monthly = bi_monthly_int[payslip.date_to.month]
return bi_monthly/pay_periods
elif wage_type == 'monthly':
return payslip.date_to.month/pay_periods
elif wage_type == 'semi-monthly':
pay_period = payslip.date_to.month * 2
if payslip.date_to.day <= 15:
return pay_period/pay_periods
else:
pay_period += 1
return pay_period/pay_periods
elif wage_type == 'bi-weekly':
week_num = payslip.date_to.isocalendar()[1]
if week_num == 53:
return 1
else:
return week_num/pay_periods
elif wage_type == 'weekly':
return payslip.date_to.isocalendar()[1]/pay_periods
elif wage_type == 'daily':
day_of_year = payslip.date_to.timetuple().tm_yday
return day_of_year/pay_periods
else:
raise Exception(f'Payslip does not have a valid wage_type. The wagetype presented is "{wage_type}".')
def _compute_pensionable_income_of_slip(slip):
pensionable_income = 0.0
for line in slip.line_ids:
if line.category_id.code == 'BASIC':
pensionable_income += line.amount
return pensionable_income
def _compute_pensionable_income_year_to_date_piytd(payslip, categories):
employee_payslips = payslip.dict.env['hr.payslip'].search([
('employee_id', '=', payslip.dict.employee_id.id),
('id', '!=', payslip.dict.id),
])
piytd = 0.0
for slip in employee_payslips:
piytd += _compute_pensionable_income_of_slip(slip)
return piytd
def _compute_pensionable_income_pi(payslip, categories):
"""
PI = Pensionable income for the pay period, or the gross income plus any taxable benefits for the pay period, plus PIYTD
"""
pensionable_income_year_to_date_piytd = _compute_pensionable_income_year_to_date_piytd(payslip, categories)
pensionable_income_for_current_payslip = _compute_pensionable_income_of_slip(payslip)
return pensionable_income_year_to_date_piytd + pensionable_income_for_current_payslip

View File

@@ -3,6 +3,7 @@
from odoo import api, fields, models
from .federal.ca_fit import ca_fit_federal_income_tax_withholding
from .federal.ca_cpp import ca_cpp_canada_pension_plan_withholding
class HRPayslip(models.Model):
@@ -25,6 +26,7 @@ class HRPayslip(models.Model):
res = super()._get_base_local_dict()
res.update({
'ca_fit_federal_income_tax_withholding': ca_fit_federal_income_tax_withholding,
'ca_cpp_canada_pension_plan_withholding': ca_cpp_canada_pension_plan_withholding,
})
return res

View File

@@ -45,12 +45,7 @@ class TestCAPayslip(common.TestPayslip):
def get_providence(self):
pass
def get_ca_cpp_canada_pension_plan_withholding(self):
_logger.warning(f'self.rpp_withdrawal_per_check = {str(self.rpp_withdrawal_per_check)} --------------------------------')
if self.rpp_withdrawal_per_check > 0:
return self.rpp_withdrawal_per_check
else:
return 0.0
# def get_ca_state(self, code, cache={}):
# country_key = 'CA_COUNTRY'

View File

@@ -21,7 +21,7 @@ class TestPayslip(TestCAPayslip):
self._log('2021 tax first payslip:')
payslip = self._createPayslip(employee, date_from, date_to)
# self.assertEqual(payslip.struct_type_id, )
self.assertEqual(payslip.contract_id, contract, f'Payslip contract {str(payslip.contract_id)} is not correct')
self.assertEqual(payslip.contract_id, contract, f'Payslip contract {str(payslip.contract_id)} does not equal {str(contract)}')
self.assertEqual(payslip.struct_id.name, 'Canada Employee Standard',
f'payroll structure {payslip.struct_id.name} is not correct')
self.assertEqual(payslip.date_from, fields.Date.from_string(date_from),
@@ -31,10 +31,10 @@ class TestPayslip(TestCAPayslip):
self.assertEqual(payslip.employee_id.name, 'Jared',
f'payslip employee {payslip.employee_id.name} is not correct')
_logger.warning(str(payslip.read()))
for line in payslip.line_ids:
_logger.warning(f'payslip line read {str(line)}************************************')
_logger.warning(line.read())
# _logger.warning(str(payslip.read()))
# for line in payslip.line_ids:
# _logger.warning(f'payslip line read {str(line)}************************************')
# _logger.warning(line.read())
# if line.name == 'EE: CA Federal Income Tax':
# _logger.warning(f'payslip line read {str(line)}************************************')
@@ -49,7 +49,15 @@ class TestPayslip(TestCAPayslip):
# _logger.warning(str(payslip.contract_id.structure_type_id.struct_ids[0].rule_ids[0].read()))
# _logger.warning('payslip.rule_parameter(rule_parameter_ca_fed_tax_rate)************************************')
self.assertPayrollAlmostEqual(payslip.net_wage, 5565)
# import pydevd_pycharm
# pydevd_pycharm.settrace('192.168.1.27', port=6900, stdoutToServer=True, stderrToServer=True)
# self.assertPayrollAlmostEqual(payslip.net_wage, 5565)
# self.assertEqual(payslip.net_wage, 5565, 'total tax is off')
# schedule_pay = payslip.contract_id.schedule_pay