mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[IMP] l10n_pe_hr_payroll: implement salary struct for gratif
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
'name': 'Peru - Payroll',
|
'name': 'Peru - Payroll',
|
||||||
'author': 'Hibou Corp. <hello@hibou.io>',
|
'author': 'Hibou Corp. <hello@hibou.io>',
|
||||||
'version': '15.0.2022.1.0',
|
'version': '15.0.2022.2.0',
|
||||||
'category': 'Payroll Localization',
|
'category': 'Payroll Localization',
|
||||||
'depends': [
|
'depends': [
|
||||||
'hr_payroll_hibou',
|
'hr_payroll_hibou',
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<record id="hr_payroll_structure" model="hr.payroll.structure">
|
<record id="hr_payroll_structure" model="hr.payroll.structure">
|
||||||
<field name="name">Peru Employee (5ta Cat.)</field>
|
<field name="name">Peru Employee (5ta Cat.)</field>
|
||||||
|
<field name="code">PE5</field>
|
||||||
<field name="country_id" ref="base.pe"/>
|
<field name="country_id" ref="base.pe"/>
|
||||||
<field name="type_id" ref="l10n_pe_hr_payroll.structure_type_employee"/>
|
<field name="type_id" ref="l10n_pe_hr_payroll.structure_type_employee"/>
|
||||||
<field name="unpaid_work_entry_type_ids" eval="[
|
<field name="unpaid_work_entry_type_ids" eval="[
|
||||||
@@ -28,6 +29,15 @@
|
|||||||
<field name="default_struct_id" ref="hr_payroll_structure"/>
|
<field name="default_struct_id" ref="hr_payroll_structure"/>
|
||||||
</record>
|
</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">
|
<record id="structure_type_employee_4ta_cat" model="hr.payroll.structure.type">
|
||||||
<field name="name">Peru Employee (4ta Cat.)</field>
|
<field name="name">Peru Employee (4ta Cat.)</field>
|
||||||
<field name="default_resource_calendar_id" ref="resource.resource_calendar_std"/>
|
<field name="default_resource_calendar_id" ref="resource.resource_calendar_std"/>
|
||||||
|
|||||||
@@ -58,4 +58,51 @@
|
|||||||
<field name="partner_id" ref="partner_sunat"/>
|
<field name="partner_id" ref="partner_sunat"/>
|
||||||
</record>
|
</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>
|
</odoo>
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Odoo Server 15.0+e\n"
|
"Project-Id-Version: Odoo Server 15.0+e\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-06-30 16:24+0000\n"
|
"POT-Creation-Date: 2022-07-27 20:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-06-30 16:24+0000\n"
|
"PO-Revision-Date: 2022-07-27 20:00+0000\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -70,11 +70,6 @@ msgstr "Creado Por"
|
|||||||
msgid "Created on"
|
msgid "Created on"
|
||||||
msgstr "Creado En"
|
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
|
#. module: l10n_pe_hr_payroll
|
||||||
#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__name
|
#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__name
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
# 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 odoo import api, fields, models
|
||||||
from .rules.general import _general_rate
|
from .rules.general import _general_rate
|
||||||
from .rules.ir_4ta_cat import ir_4ta_cat
|
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):
|
class HRPayslip(models.Model):
|
||||||
_inherit = 'hr.payslip'
|
_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):
|
def _get_base_local_dict(self):
|
||||||
res = super()._get_base_local_dict()
|
res = super()._get_base_local_dict()
|
||||||
res.update({
|
res.update({
|
||||||
@@ -17,3 +61,20 @@ class HRPayslip(models.Model):
|
|||||||
'ir_5ta_cat': ir_5ta_cat,
|
'ir_5ta_cat': ir_5ta_cat,
|
||||||
})
|
})
|
||||||
return res
|
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
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ class HRContractPEPayrollConfig(models.Model):
|
|||||||
|
|
||||||
name = fields.Char(string="Description")
|
name = fields.Char(string="Description")
|
||||||
employee_id = fields.Many2one('hr.employee', string="Employee", required=True)
|
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.')
|
ee_5ta_cat_exempt = fields.Boolean(string='Exempt from 5th Cat. withholding.')
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ def ir_5ta_cat(payslip, categories, worked_days, inputs):
|
|||||||
|
|
||||||
wage_year = (basic_wage * pay_periods_at_current) + prior_wage_year
|
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)
|
# 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
|
payslip_date_end = payslip.dict.date_to
|
||||||
hired_in_year = date_hired.year == payslip_date_end.year
|
hired_in_year = date_hired.year == payslip_date_end.year
|
||||||
periods_in_year_eligible = pay_periods_in_year
|
periods_in_year_eligible = pay_periods_in_year
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class TestPePayslip(common.TestPayslip):
|
|||||||
super().setUp()
|
super().setUp()
|
||||||
self.structure_type = self.env.ref('l10n_pe_hr_payroll.structure_type_employee')
|
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 = 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.structure_type.default_struct_id = self.structure
|
||||||
# self.debug = True
|
# 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))
|
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, ))
|
self._logger.warning('cannot locate attribute names "%s" on hr.contract().' % (key, ))
|
||||||
|
|
||||||
# PE Payroll Config Defaults Should be set on the Model
|
# 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)
|
config = config_model.create(config_values)
|
||||||
contract_values['pe_payroll_config_id'] = config.id
|
contract_values['pe_payroll_config_id'] = config.id
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
<field name="employee_id"/>
|
<field name="employee_id"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="retirement_type"/>
|
<field name="retirement_type"/>
|
||||||
<field name="date_hired"/>
|
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="write_date"/>
|
<field name="write_date"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
<group name="General">
|
<group name="General">
|
||||||
<field name="employee_id"/>
|
<field name="employee_id"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="date_hired"/>
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<group name="employee" string="Employee">
|
<group name="employee" string="Employee">
|
||||||
|
|||||||
Reference in New Issue
Block a user