[IMP] l10n_pe_hr_payroll: implement salary struct for gratif

This commit is contained in:
Jared Kipe
2022-07-27 20:09:41 +00:00
parent b87fd7c3db
commit 5862d51683
9 changed files with 124 additions and 16 deletions

View File

@@ -3,7 +3,7 @@
{
'name': 'Peru - Payroll',
'author': 'Hibou Corp. <hello@hibou.io>',
'version': '15.0.2022.1.0',
'version': '15.0.2022.2.0',
'category': 'Payroll Localization',
'depends': [
'hr_payroll_hibou',

View File

@@ -17,6 +17,7 @@
<record id="hr_payroll_structure" model="hr.payroll.structure">
<field name="name">Peru Employee (5ta Cat.)</field>
<field name="code">PE5</field>
<field name="country_id" ref="base.pe"/>
<field name="type_id" ref="l10n_pe_hr_payroll.structure_type_employee"/>
<field name="unpaid_work_entry_type_ids" eval="[
@@ -28,6 +29,15 @@
<field name="default_struct_id" ref="hr_payroll_structure"/>
</record>
<record id="hr_payroll_structure_gratif" model="hr.payroll.structure">
<field name="name">July/December Gratuity (5ta Cat.)</field>
<field name="code">PE5GRATIF</field>
<field name="type_id" ref="l10n_pe_hr_payroll.structure_type_employee"/>
<field name="country_id" ref="base.pe"/>
<field name="rule_ids" eval="[]"/>
<field name="use_worked_day_lines" eval="False"/>
</record>
<record id="structure_type_employee_4ta_cat" model="hr.payroll.structure.type">
<field name="name">Peru Employee (4ta Cat.)</field>
<field name="default_resource_calendar_id" ref="resource.resource_calendar_std"/>

View File

@@ -58,4 +58,51 @@
<field name="partner_id" ref="partner_sunat"/>
</record>
<!-- July/December Gratuity -->
<record id="input_type_gratif_months" model="hr.payslip.input.type">
<field name="name">Gratif Full Months</field>
<field name="code">MONTHS</field>
<field name="country_id" ref="base.pe" />
<field name="struct_ids" eval="[
(4, ref('l10n_pe_hr_payroll.hr_payroll_structure_gratif')),
]" />
</record>
<record id="hr_payroll_rule_ir_5ta_cat_gratif" model="hr.salary.rule">
<field name="sequence" eval="80"/>
<field name="struct_id" ref="hr_payroll_structure_gratif"/>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Gratif</field>
<field name="code">ALW_GRATIF</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = payslip.paid_amount</field>
<field name="appears_on_payslip" eval="True"/>
</record>
<record id="hr_payroll_rule_ir_5ta_cat_gratif_bono" model="hr.salary.rule">
<field name="sequence" eval="90"/>
<field name="struct_id" ref="hr_payroll_structure_gratif"/>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Gratif Bonifextra</field>
<field name="code">ALW_GRATIF_BONIFEXTRA</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.ALW</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result, result_rate = categories.ALW, payslip.rule_parameter('er_essalud')</field>
<field name="appears_on_payslip" eval="True"/>
</record>
<record id="hr_payroll_rule_ir_5ta_cat_gratif_net" model="hr.salary.rule">
<field name="sequence" eval="200"/>
<field name="struct_id" ref="hr_payroll_structure_gratif"/>
<field name="category_id" ref="hr_payroll.NET"/>
<field name="name">Net Gratif</field>
<field name="code">NET</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW + categories.DED</field>
<field name="appears_on_payslip" eval="True"/>
</record>
</odoo>

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-30 16:24+0000\n"
"PO-Revision-Date: 2022-06-30 16:24+0000\n"
"POT-Creation-Date: 2022-07-27 20:00+0000\n"
"PO-Revision-Date: 2022-07-27 20:00+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -70,11 +70,6 @@ msgstr "Creado Por"
msgid "Created on"
msgstr "Creado En"
#. module: l10n_pe_hr_payroll
#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__date_hired
msgid "Date Hired"
msgstr "Fecha de Contratación"
#. module: l10n_pe_hr_payroll
#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__name
msgid "Description"

View File

@@ -1,5 +1,7 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from datetime import date
from odoo import api, fields, models
from .rules.general import _general_rate
from .rules.ir_4ta_cat import ir_4ta_cat
@@ -9,6 +11,48 @@ from .rules.ir_5ta_cat import ir_5ta_cat
class HRPayslip(models.Model):
_inherit = 'hr.payslip'
@api.model_create_multi
def create(self, vals_list):
payslips = super().create(vals_list)
draft_slips = payslips.filtered(lambda p: p.employee_id and p.state == 'draft')
if not draft_slips:
return payslips
for slip in draft_slips.filtered(lambda s: s.struct_id.code == 'PE5GRATIF'):
slip._pe_5thcat_gratif_update_input_line()
return payslips
def _pe_5thcat_gratif_update_input_line(self):
full_months_type = self.env.ref('l10n_pe_hr_payroll.input_type_gratif_months', raise_if_not_found=False)
if not full_months_type:
return
for payslip in self:
# compute full months, for now I'll hard code to 6
amount = payslip._pe_5thcat_gratif_months()
lines_to_remove = payslip.input_line_ids.filtered(lambda x: x.input_type_id == full_months_type)
input_lines_vals = [(2, line.id, False) for line in lines_to_remove]
input_lines_vals.append((0, 0, {
'amount': amount,
'input_type_id': full_months_type.id
}))
payslip.update({'input_line_ids': input_lines_vals})
def _pe_5thcat_gratif_months(self):
full_months = 0
# are we in July or December?
# brute force, but this algorithm should be very very fast
date_hire = self.contract_id.first_contract_date
if self.date_to.month == 7:
for i in range(1, 7):
if date_hire < date(self.date_to.year, i, 15):
full_months += 1
else:
for i in range(7, 13):
if date_hire < date(self.date_to.year-1, i, 15):
full_months += 1
return full_months
def _get_base_local_dict(self):
res = super()._get_base_local_dict()
res.update({
@@ -17,3 +61,20 @@ class HRPayslip(models.Model):
'ir_5ta_cat': ir_5ta_cat,
})
return res
def _get_paid_amount(self):
if self.struct_id.code == 'PE5GRATIF':
return self._pe_5thcat_gratif()
return super()._get_paid_amount()
def _pe_5thcat_gratif(self):
if self.contract_id.structure_type_id != self.struct_id.type_id:
return 0.0
# TODO hourly averages daily hours to compute from wage
basic = self.contract_id._get_contract_wage()
month_line = self.input_line_ids.filtered(lambda l: l.code == 'MONTHS')
if not basic or not month_line:
return 0.0
# normalize to 6 months
return basic * (1.0 / 6.0) * month_line.amount

View File

@@ -9,8 +9,6 @@ class HRContractPEPayrollConfig(models.Model):
name = fields.Char(string="Description")
employee_id = fields.Many2one('hr.employee', string="Employee", required=True)
date_hired = fields.Date(string='Date Hired', required=True, default=fields.Date.today,
help='For calculations like IR 5TH CAT.')
ee_5ta_cat_exempt = fields.Boolean(string='Exempt from 5th Cat. withholding.')

View File

@@ -31,9 +31,9 @@ def ir_5ta_cat(payslip, categories, worked_days, inputs):
wage_year = (basic_wage * pay_periods_at_current) + prior_wage_year
# IF employee's `date_hired` is in current year
# IF employee's `first_contract_date` is in current year
# THEN we can pro-rate the period (reduce withholding)
date_hired = payslip.dict.contract_id.pe_payroll_config_value('date_hired')
date_hired = payslip.dict.contract_id.first_contract_date
payslip_date_end = payslip.dict.date_to
hired_in_year = date_hired.year == payslip_date_end.year
periods_in_year_eligible = pay_periods_in_year

View File

@@ -12,6 +12,7 @@ class TestPePayslip(common.TestPayslip):
super().setUp()
self.structure_type = self.env.ref('l10n_pe_hr_payroll.structure_type_employee')
self.structure = self.env.ref('l10n_pe_hr_payroll.hr_payroll_structure')
self.structure_gratif = self.env.ref('l10n_pe_hr_payroll.hr_payroll_structure_gratif')
self.structure_type.default_struct_id = self.structure
# self.debug = True
self._log('PE structue_type %s %s and structure %s %s' % (self.structure_type, self.structure_type.name, self.structure, self.structure.name))
@@ -52,8 +53,6 @@ class TestPePayslip(common.TestPayslip):
self._logger.warning('cannot locate attribute names "%s" on hr.contract().' % (key, ))
# PE Payroll Config Defaults Should be set on the Model
if 'date_hired' not in config_values:
config_values['date_hired'] = '2016-01-01'
config = config_model.create(config_values)
contract_values['pe_payroll_config_id'] = config.id

View File

@@ -8,7 +8,6 @@
<field name="employee_id"/>
<field name="name"/>
<field name="retirement_type"/>
<field name="date_hired"/>
<field name="create_date"/>
<field name="write_date"/>
</tree>
@@ -24,7 +23,6 @@
<group name="General">
<field name="employee_id"/>
<field name="name"/>
<field name="date_hired"/>
</group>
<group>
<group name="employee" string="Employee">