Merge branch 'imp/15.0/l10n_pe_hr_payroll__gratif' into '15.0-test'

imp/15.0/l10n_pe_hr_payroll__gratif into 15.0-test

See merge request hibou-io/hibou-odoo/suite!1446
This commit is contained in:
Hibou Bot
2022-07-27 20:11:56 +00:00
13 changed files with 138 additions and 20 deletions

View File

@@ -119,13 +119,17 @@ class TestPayslip(common.TransactionCase):
contract.structure_type_id.default_struct_id.schedule_pay = schedule_pay
return contract
def _createPayslip(self, employee, date_from, date_to, skip_compute=False):
slip = self.env['hr.payslip'].create({
def _createPayslip(self, employee, date_from, date_to, skip_compute=False, other_values=False):
if not other_values:
other_values = {}
create_values = {
'name': 'Test %s From: %s To: %s' % (employee.name, date_from, date_to),
'employee_id': employee.id,
'date_from': date_from,
'date_to': date_to
})
}
create_values.update(other_values)
slip = self.env['hr.payslip'].create(create_values)
# Included in hr.payslip.action_refresh_from_work_entries() as ov 14.0 EE
# slip._onchange_employee()
# as is the 'compute' that is almost always called immediaately after

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
@@ -8,6 +10,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()
@@ -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">

View File

@@ -3,7 +3,7 @@
{
'name': 'Peru - Payroll with Accounting',
'author': 'Hibou Corp. <hello@hibou.io>',
'version': '15.0.2022.1.0',
'version': '15.0.2022.2.0',
'category': 'Human Resources',
'depends': [
'l10n_pe_hr_payroll',

View File

@@ -21,6 +21,7 @@
# exp_com='1222',
# exp_bono='1223',
# exp_essalud='1241',
# exp_gratif='1245',
env['account.chart.template']._pe_configure_payroll_account_data(companies, salary_rules=records, full_reset=False)
</field>
</record>
@@ -44,6 +45,7 @@
# exp_com='1222',
# exp_bono='1223',
# exp_essalud='1241',
# exp_gratif='1245',
env['account.chart.template']._pe_configure_payroll_account_data(companies, salary_rules=records, full_reset=True)
</field>
</record>

View File

@@ -7,6 +7,7 @@ EXP_EXTRA = '621100'
EXP_COM = '6212000'
EXP_BONO = '6213000'
EXP_ESSALUD = '6271000'
EXP_GRATIF = '6214000'
PAY_EE = '4111000'
PAY_AFP = '4170000'
@@ -39,6 +40,7 @@ class AccountChartTemplate(models.Model):
exp_com=EXP_COM,
exp_bono=EXP_BONO,
exp_essalud=EXP_ESSALUD,
exp_gratif=EXP_GRATIF,
salary_rules=None, full_reset=False):
account_codes = (
pay_ee,
@@ -52,6 +54,7 @@ class AccountChartTemplate(models.Model):
exp_com,
exp_bono,
exp_essalud,
exp_gratif,
)
pe_structures = self.env['hr.payroll.structure'].search([('country_id', '=', self.env.ref('base.pe').id)])
journal_field_id = self.env['ir.model.fields'].search([
@@ -131,6 +134,7 @@ class AccountChartTemplate(models.Model):
set_rule_accounts('ALW_BADGES%', accounts[exp_bono], accounts['none'])
set_rule_accounts('ALW_COM%', accounts[exp_com], accounts['none'])
set_rule_accounts('ALW_EXTRA%', accounts[exp_extra], accounts['none'])
set_rule_accounts('ALW_GRATIF%', accounts[exp_gratif], accounts['none'])
# EE_* -> AP debit
set_rule_accounts('EE_%', accounts[pay_ee], accounts['none']) # initialize
set_rule_accounts('EE_PE_AFP%', accounts[pay_afp], accounts['none'])