mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[wip] l10n_ca_hr_payroll: Adding canada pension plan algorithm.
H5939
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from . import ca_payroll_config
|
||||
from . import hr_ca_contract
|
||||
from . import hr_payslip
|
||||
from .federal import ca_fit
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user