diff --git a/l10n_pe_hr_payroll/__manifest__.py b/l10n_pe_hr_payroll/__manifest__.py
index ee6cb479..bd7cf558 100644
--- a/l10n_pe_hr_payroll/__manifest__.py
+++ b/l10n_pe_hr_payroll/__manifest__.py
@@ -22,6 +22,7 @@ Peru - Payroll Rules.
'data/integration_rules.xml',
'data/afp_rules.xml',
'data/onp_rules.xml',
+ 'data/ir_4ta_cat_rules.xml',
'data/ir_5ta_cat_rules.xml',
'data/er_rules.xml',
'views/hr_contract_views.xml',
diff --git a/l10n_pe_hr_payroll/data/afp_rules.xml b/l10n_pe_hr_payroll/data/afp_rules.xml
index 2f08b5e7..ffeed643 100644
--- a/l10n_pe_hr_payroll/data/afp_rules.xml
+++ b/l10n_pe_hr_payroll/data/afp_rules.xml
@@ -24,7 +24,7 @@
- EE: PE AFP Pensiones
+ EE: PE AFP Pensions
EE_PE_AFP_PENSIONES
python
result = categories.GROSS and contract.pe_payroll_config_value('retirement_type') == 'afp'
@@ -37,7 +37,7 @@
- EE: PE AFP Seguro
+ EE: PE AFP Insurance
EE_PE_AFP_SEGURO
python
result = categories.GROSS and contract.pe_payroll_config_value('retirement_type') == 'afp'
@@ -60,7 +60,7 @@ result, result_rate = eligible_wage, rate
- EE: PE AFP Comisión Mixta
+ EE: PE AFP Mixed Commission
EE_PE_AFP_COMISION_MIXTA
python
result = categories.GROSS and contract.pe_payroll_config_value('retirement_type') == 'afp' and contract.pe_payroll_config_value('afp_comision_type') == 'mixta'
@@ -73,7 +73,7 @@ result, result_rate = eligible_wage, rate
- EE: PE AFP Comisión (Non-Mixta)
+ EE: PE AFP Comission (Non-Mixed)
EE_PE_AFP_COMISION_NON_MIXTA
python
result = categories.GROSS and contract.pe_payroll_config_value('retirement_type') == 'afp' and contract.pe_payroll_config_value('afp_comision_type') == 'non_mixta'
diff --git a/l10n_pe_hr_payroll/data/base.xml b/l10n_pe_hr_payroll/data/base.xml
index ced1315b..5e3a2efa 100644
--- a/l10n_pe_hr_payroll/data/base.xml
+++ b/l10n_pe_hr_payroll/data/base.xml
@@ -2,13 +2,13 @@
- Peru Employee
+ Peru Employee (5ta Cat.)
- Peru Employee Standard
+ Peru Employee (5ta Cat.)
@@ -17,6 +17,19 @@
]"/>
+
+ Peru Employee (4ta Cat.)
+
+
+
+
+
+ Peru Employee (4ta Cat.)
+
+
+
+
+
EE: AFP
@@ -43,16 +56,23 @@
- EE: IR 5ta Cat.
+ EE: IR 5th Cat.
EE_PE_IR_5TA_CAT
- ER: IR 5ta Cat.
+ ER: IR 5th Cat.
ER_PE_IR_5TA_CAT
+
+
+ EE: IR 4th Cat.
+ EE_PE_IR_4TA_CAT
+
+
+
EE: Essalud (rem)
@@ -67,7 +87,7 @@
- Bono
+ Bonus
BONO
result = inputs.BONO.amount if inputs.BONO else 0
BASIC_BONO
- Bono
+ Bonus
diff --git a/l10n_pe_hr_payroll/data/ir_4ta_cat_rules.xml b/l10n_pe_hr_payroll/data/ir_4ta_cat_rules.xml
new file mode 100644
index 00000000..d18d87f3
--- /dev/null
+++ b/l10n_pe_hr_payroll/data/ir_4ta_cat_rules.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ EE: IR 4ta Cat.
+ ee_ir_4ta_cat
+
+
+
+ 8.0
+
+
+
+
+
+
+
+
+
+ EE: PE IR 4th Cat.
+ EE_PE_IR_4TA_CAT
+ python
+ result, _ = ir_4ta_cat(payslip, categories, worked_days, inputs)
+ code
+ result, result_rate = ir_4ta_cat(payslip, categories, worked_days, inputs)
+
+
+
+
diff --git a/l10n_pe_hr_payroll/data/ir_5ta_cat_rules.xml b/l10n_pe_hr_payroll/data/ir_5ta_cat_rules.xml
index b2ad02c1..bafd7b5b 100644
--- a/l10n_pe_hr_payroll/data/ir_5ta_cat_rules.xml
+++ b/l10n_pe_hr_payroll/data/ir_5ta_cat_rules.xml
@@ -48,7 +48,7 @@
- EE: PE IR 5TA Cat.
+ EE: PE IR 5th Cat.
EE_PE_IR_5TA_CAT
python
result, _ = ir_5ta_cat(payslip, categories, worked_days, inputs, BASIC)
diff --git a/l10n_pe_hr_payroll/i18n/es.po b/l10n_pe_hr_payroll/i18n/es.po
new file mode 100644
index 00000000..da3d014e
--- /dev/null
+++ b/l10n_pe_hr_payroll/i18n/es.po
@@ -0,0 +1,323 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * l10n_pe_hr_payroll
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 13.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-05-06 01:45+0000\n"
+"PO-Revision-Date: 2022-05-06 01:45+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__retirement_type__afp
+msgid "AFP"
+msgstr "AFP"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__afp_comision_type
+msgid "AFP Commission Type"
+msgstr "Tipo de Comisión de AFP"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__afp_type
+msgid "AFP Type"
+msgstr "Tipo de AFP"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_salary_rule_gamification
+msgid "Badges"
+msgstr "Insignias"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_salary_rule_bonus
+msgid "Bonus"
+msgstr "Bono"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_salary_rule_commission
+msgid "Commissions"
+msgstr "Comisiones"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__comp_ss_eps_rule_id
+msgid "Company Social Security EPS Rule"
+msgstr "Regla EPS de la Seguridad Social de la Empresa"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__comp_ss_type
+msgid "Company Social Services"
+msgstr "Servicios Social de la Empresa"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model,name:l10n_pe_hr_payroll.model_hr_contract_pe_payroll_config
+msgid "Contract PE Payroll Forms"
+msgstr "Formularios de Nómina del Contrato PE"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__create_uid
+msgid "Created by"
+msgstr "Creado Por"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__create_date
+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"
+msgstr "Descripción"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__display_name
+msgid "Display Name"
+msgstr "Nombre para Mostrar"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_ee_pe_afp
+msgid "EE: AFP"
+msgstr "EE: AFP"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_er_essalud
+msgid "EE: Essalud"
+msgstr "EE: Essalud"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_ee_essalud
+msgid "EE: Essalud (rem)"
+msgstr "EE: Essalud (rem)"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_ee_ir_4ta_cat
+msgid "EE: IR 4th Cat."
+msgstr "EE: IR 4ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_ee_ir_5ta_cat
+msgid "EE: IR 5th Cat."
+msgstr "EE: IR 5ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_ee_pe_onp
+msgid "EE: ONP"
+msgstr "EE: ONP"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_afp_comision_non_mixta
+msgid "EE: PE AFP Comission (Non-Mixed)"
+msgstr "EE: PE AFP Comisión (No-Mixta)"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_afp_seguro
+msgid "EE: PE AFP Insurance"
+msgstr "EE: PE AFP Seguro"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_afp_comision_mixta
+msgid "EE: PE AFP Mixed Commission"
+msgstr "EE: PE AFP Comisión Mixta"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_afp_pensiones
+msgid "EE: PE AFP Pensions"
+msgstr "EE: PE AFP Pensiones"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_ir_4ta_cat
+msgid "EE: PE IR 4th Cat."
+msgstr "EE: PE IR 4ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_ir_5ta_cat
+msgid "EE: PE IR 5th Cat."
+msgstr "EE: PE IR 5ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_ee_onp
+msgid "EE: PE ONP/SNP"
+msgstr "EE: PE ONP/SNP"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__comp_ss_type__eps
+msgid "EPS"
+msgstr "EPS"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_er_pe_afp
+msgid "ER: AFP"
+msgstr "ER: AFP"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_er_ir_5ta_cat
+msgid "ER: IR 5th Cat."
+msgstr "ER: IR 5ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule.category,name:l10n_pe_hr_payroll.hr_payroll_category_er_pe_onp
+msgid "ER: ONP"
+msgstr "ER: ONP"
+
+#. module: l10n_pe_hr_payroll
+#: model:hr.salary.rule,name:l10n_pe_hr_payroll.hr_payroll_rule_er_essalud
+msgid "ER: PE Essalud"
+msgstr "ER: PE Essalud"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__employee_id
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_form
+msgid "Employee"
+msgstr "Empleado"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model,name:l10n_pe_hr_payroll.model_hr_contract
+msgid "Employee Contract"
+msgstr "Contrato de Empleado"
+
+#. module: l10n_pe_hr_payroll
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_form
+msgid "Employee Payroll Forms"
+msgstr "Formularios de Nómina del Empleado"
+
+#. module: l10n_pe_hr_payroll
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_form
+msgid "Employer"
+msgstr "Empleador"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__comp_ss_type__essalud
+msgid "Essalud"
+msgstr "Essalud"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract__pe_payroll_ee_4ta_cat_exempt
+msgid "Exempt from 4th Cat. withholding."
+msgstr "Exento de Retención de la 4ta Cat."
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,help:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__date_hired
+msgid "For calculations like IR 5TH CAT."
+msgstr "Para Cálculos como IR 5TA CAT."
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_type__habitat
+msgid "Habitat"
+msgstr "Habitat"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__id
+msgid "ID"
+msgstr "ID"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_type__integra
+msgid "Integra"
+msgstr "Integra"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config____last_update
+msgid "Last Modified on"
+msgstr "Última Modificación En"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__write_uid
+msgid "Last Updated by"
+msgstr "Última Actualización Por"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__write_date
+msgid "Last Updated on"
+msgstr "Ultima Actualización En"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_comision_type__mixta
+msgid "Mixed"
+msgstr "Mixta"
+
+#. module: l10n_pe_hr_payroll
+#: model_terms:ir.actions.act_window,help:l10n_pe_hr_payroll.pe_payroll_config_action_main
+msgid "No Forms"
+msgstr "Sin Formularios"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_comision_type__non_mixta
+msgid "Non-Mixed"
+msgstr "No-Mixta"
+
+#. module: l10n_pe_hr_payroll
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_form
+msgid "Not supported. Specify rule."
+msgstr "No Soportado. Indique una Regla"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__retirement_type__onp
+msgid "ONP"
+msgstr "ONP"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model,name:l10n_pe_hr_payroll.model_hr_payslip
+msgid "Pay Slip"
+msgstr "Recibo de Nómina"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract__pe_payroll_config_id
+msgid "Payroll Forms"
+msgstr "Formularios de Nómina"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.actions.act_window,name:l10n_pe_hr_payroll.pe_payroll_config_action_main
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_tree
+msgid "Peru Employee Payroll Forms"
+msgstr "Formularios de Nómina del Empleado de Perú"
+
+#. module: l10n_pe_hr_payroll
+#: model_terms:ir.ui.view,arch_db:l10n_pe_hr_payroll.pe_payroll_config_search
+msgid "Peru Employee Payroll Forms Search"
+msgstr "Búsqueda de Formularios de Nómina del Empleado de Perú"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.ui.menu,name:l10n_pe_hr_payroll.pe_payroll_config_menu_main
+msgid "Peru Payroll Forms"
+msgstr "Formularios de Nómina de Perú"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_type__prima
+msgid "Prima"
+msgstr "Prima"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__afp_type__profuturo
+msgid "Profuturo"
+msgstr "Profuturo"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model,name:l10n_pe_hr_payroll.model_publisher_warranty_contract
+msgid "Publisher Warranty Contract"
+msgstr "Contrato de Garantía del Editorial"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields.selection,name:l10n_pe_hr_payroll.selection__hr_contract_pe_payroll_config__retirement_type__retired
+msgid "Retired"
+msgstr "Jubilado"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,field_description:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__retirement_type
+msgid "Retirement Type"
+msgstr "Tipo de Jubilación"
+
+#. module: l10n_pe_hr_payroll
+#: model:ir.model.fields,help:l10n_pe_hr_payroll.field_hr_contract_pe_payroll_config__comp_ss_eps_rule_id
+msgid "Rule code prefix 'ER_PE_EPS' to select here."
+msgstr "Prefijo del Código de la Regla 'ER_PE_EPS' a Seleccionar Aquí."
diff --git a/l10n_pe_hr_payroll/models/hr_contract.py b/l10n_pe_hr_payroll/models/hr_contract.py
index b7980e38..f6bfbacf 100644
--- a/l10n_pe_hr_payroll/models/hr_contract.py
+++ b/l10n_pe_hr_payroll/models/hr_contract.py
@@ -7,6 +7,7 @@ class PEHRContract(models.Model):
_inherit = 'hr.contract'
pe_payroll_config_id = fields.Many2one('hr.contract.pe_payroll_config', 'Payroll Forms')
+ pe_payroll_ee_4ta_cat_exempt = fields.Boolean(string='Exempt from 4th Cat. withholding.')
def pe_payroll_config_value(self, name):
return self.pe_payroll_config_id[name]
diff --git a/l10n_pe_hr_payroll/models/hr_payslip.py b/l10n_pe_hr_payroll/models/hr_payslip.py
index 2788cb61..df66de83 100644
--- a/l10n_pe_hr_payroll/models/hr_payslip.py
+++ b/l10n_pe_hr_payroll/models/hr_payslip.py
@@ -2,6 +2,7 @@
from odoo import api, fields, models
from .rules.general import _general_rate
+from .rules.ir_4ta_cat import ir_4ta_cat
from .rules.ir_5ta_cat import ir_5ta_cat
@@ -12,6 +13,7 @@ class HRPayslip(models.Model):
res = super()._get_base_local_dict()
res.update({
'general_rate': _general_rate,
+ 'ir_4ta_cat': ir_4ta_cat,
'ir_5ta_cat': ir_5ta_cat,
})
return res
diff --git a/l10n_pe_hr_payroll/models/pe_payroll_config.py b/l10n_pe_hr_payroll/models/pe_payroll_config.py
index 1f87801d..ebac2dc1 100644
--- a/l10n_pe_hr_payroll/models/pe_payroll_config.py
+++ b/l10n_pe_hr_payroll/models/pe_payroll_config.py
@@ -1,6 +1,6 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
-from odoo import api, fields, models
+from odoo import api, fields, models, _
class HRContractPEPayrollConfig(models.Model):
@@ -10,7 +10,7 @@ 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 5TA CAT.')
+ help='For calculations like IR 5TH CAT.')
retirement_type = fields.Selection([
('afp', 'AFP'),
@@ -26,8 +26,8 @@ class HRContractPEPayrollConfig(models.Model):
('profuturo', 'Profuturo'),
], string='AFP Type', default='profuturo')
afp_comision_type = fields.Selection([
- ('mixta', 'Mixta'),
- ('non_mixta', 'Non-Mixta'),
+ ('mixta', 'Mixed'),
+ ('non_mixta', 'Non-Mixed'),
], string='AFP Commission Type', default='mixta')
comp_ss_type = fields.Selection([
diff --git a/l10n_pe_hr_payroll/models/rules/__init__.py b/l10n_pe_hr_payroll/models/rules/__init__.py
index 12ea88cf..9b5a0ca1 100644
--- a/l10n_pe_hr_payroll/models/rules/__init__.py
+++ b/l10n_pe_hr_payroll/models/rules/__init__.py
@@ -1,4 +1,5 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from . import general
+from . import ir_4ta_cat
from . import ir_5ta_cat
diff --git a/l10n_pe_hr_payroll/models/rules/ir_4ta_cat.py b/l10n_pe_hr_payroll/models/rules/ir_4ta_cat.py
new file mode 100644
index 00000000..54bcfcf4
--- /dev/null
+++ b/l10n_pe_hr_payroll/models/rules/ir_4ta_cat.py
@@ -0,0 +1,10 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+def ir_4ta_cat(payslip, categories, worked_days, inputs):
+ if payslip.contract_id.pe_payroll_ee_4ta_cat_exempt:
+ return 0.0, 0.0
+ wage = categories.GROSS
+ assert wage == 11000.00
+ rate = payslip.rule_parameter('ee_ir_4ta_cat')
+ assert rate == 8.0
+ return wage, -rate
diff --git a/l10n_pe_hr_payroll/models/rules/ir_5ta_cat.py b/l10n_pe_hr_payroll/models/rules/ir_5ta_cat.py
index 9e726f55..da802e61 100644
--- a/l10n_pe_hr_payroll/models/rules/ir_5ta_cat.py
+++ b/l10n_pe_hr_payroll/models/rules/ir_5ta_cat.py
@@ -1,44 +1,60 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+from datetime import date
+
def ir_5ta_cat(payslip, categories, worked_days, inputs, basic_wage):
pay_periods_in_year = payslip.pay_periods_in_year
uit = payslip.rule_parameter('pe_uit')
-
- # there are two special scenarios
- # 1. IF employee's `date_hired` is in current year
+ payslip_date_end = payslip.dict.date_to
+
+ # IF this is the last payroll in June or December
+ # THEN we need to 'true up' the last two quarters of withholding (e.g. give a refund)
+ last_payslip_june = payslip_date_end.month == 6 and payslip_date_end.day == 30
+ # NOTE we do NOT currently support 'catch up' in June. Our formula genearlly already catches up.
+ last_payslip_june = False
+ last_payslip_december = payslip_date_end.month == 12 and payslip_date_end.day == 31
+
+ wage_period = categories.GROSS
+ if not any((basic_wage, wage_period, last_payslip_june, last_payslip_december)):
+ return 0.0, 0.0
+
+ period_additional_wage = max(wage_period - basic_wage, 0.0) # 0.0 or positive
+
+ year = payslip_date_end.year
+ next_year = date(year+1, 1, 1)
+ prior_wage_year = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01')
+ pay_periods_at_current = round(((next_year - payslip_date_end).days / 365) * pay_periods_in_year) + 1.0
+
+ wage_year = (basic_wage * pay_periods_at_current) + prior_wage_year
+
+ # IF employee's `date_hired` 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')
payslip_date_end = payslip.dict.date_to
hired_in_year = date_hired.year == payslip_date_end.year
-
- # 2. IF this is the last payroll in June or December
- # THEN we need to 'true up' the last two quarters of withholding (e.g. give a refund)
- last_payslip_june = payslip_date_end.month == 6 and payslip_date_end.day == 30
- last_payslip_december = payslip_date_end.month == 12 and payslip_date_end.day == 31
-
- # basic_wage = BASIC # must be paramatarized as we will not have locals
- wage_period = categories.GROSS
- if not all((basic_wage, wage_period)) and not any((last_payslip_june, last_payslip_december)):
- return 0.0, 0.0
-
- period_additional_wage = max(wage_period - basic_wage, 0.0) # 0.0 or positive
- wage_year = basic_wage * pay_periods_in_year
- # this can be reduced
- remaining_months = 12
+ periods_in_year_eligible = pay_periods_in_year
if hired_in_year:
- # e.g. hired in March (3) gives us 12 - 3 + 1 = 10 (Jan, Feb are the 2 missing from 12)
- remaining_months = 12 - date_hired.month + 1
+ periods_in_year_eligible = round(((next_year - date_hired).days / 365) * pay_periods_in_year)
- # additional 2 months (July and December) (note 2/12 == 1/6)
- wage_2 = wage_year * (1/6)
- if remaining_months < 6:
- wage_2 = wage_year * (1/12)
- wage_3 = wage_2 * (payslip.rule_parameter('ee_ir_5ta_cat_ley_29351') / 100.0)
- wage_year += wage_2 + wage_3
- # now that we have wage_year, we may need to adjust it by remaining months
- wage_year = wage_year * remaining_months / 12 # could be 12/12
+ # normalize 1era Gratification
+ if hired_in_year and date_hired.month > 6:
+ wage_gratif_1 = 0.0
+ elif hired_in_year:
+ wage_gratif_1 = basic_wage / 6 * (6 - date_hired.month + 1)
+ else:
+ wage_gratif_1 = basic_wage
+
+ # normalize 2da Gratification
+ if hired_in_year and date_hired.month > 6:
+ wage_gratif_2 = basic_wage / 6 * (12 - date_hired.month + 1)
+ else:
+ wage_gratif_2 = basic_wage
+
+ wage_year += wage_gratif_1 + wage_gratif_2
+ cat_ley = (wage_gratif_1 + wage_gratif_2) * (payslip.rule_parameter('ee_ir_5ta_cat_ley_29351') / 100.0)
+ wage_year += cat_ley
wage_year += period_additional_wage
-
+
over_7uit = wage_year - (7.0 * uit)
total_tax = 0.0
if over_7uit > 0.0:
@@ -57,15 +73,19 @@ def ir_5ta_cat(payslip, categories, worked_days, inputs, basic_wage):
break
last_uit = _uit
- if total_tax:
- if last_payslip_june or last_payslip_december:
- year = payslip_date_end.year
- ytd_tax = -payslip.sum_category('EE_PE_IR_5TA_CAT', str(year) + '-01-01', str(year+1) + '-01-01')
- if last_payslip_june:
- total_tax /= 2
- # remaining_tax may flip signs
- remaining_tax = -(total_tax - ytd_tax)
- return wage_period, (remaining_tax / wage_period * 100.0)
- tax = -total_tax / remaining_months # TODO needs to be normalized to periods in year if not monthly...
- return wage_period, (tax / wage_period * 100.0)
- return 0.0, 0.0
+ # if total_tax:
+ ytd_tax = -payslip.sum_category('EE_PE_IR_5TA_CAT', str(year) + '-01-01', str(year+1) + '-01-01')
+
+ if last_payslip_june or last_payslip_december:
+ if last_payslip_june:
+ # does not work right because the gratif_2 is already there
+ total_tax /= 2
+ # remaining_tax may flip signs
+ remaining_tax = -(total_tax - ytd_tax)
+ if not wage_period:
+ # to give refund, cannot normalize to wage
+ return remaining_tax, 100.0
+ return wage_period, (remaining_tax / wage_period * 100.0)
+
+ tax = -(total_tax - ytd_tax) / pay_periods_at_current
+ return wage_period, (tax / wage_period * 100.0)
diff --git a/l10n_pe_hr_payroll/views/hr_contract_views.xml b/l10n_pe_hr_payroll/views/hr_contract_views.xml
index ece8dc38..a3aa7a7f 100644
--- a/l10n_pe_hr_payroll/views/hr_contract_views.xml
+++ b/l10n_pe_hr_payroll/views/hr_contract_views.xml
@@ -12,6 +12,8 @@
attrs="{'invisible': [('structure_type_id', '!=', %(l10n_pe_hr_payroll.structure_type_employee)s)],
'required': [('structure_type_id', '=', %(l10n_pe_hr_payroll.structure_type_employee)s)]}"
context="{'default_employee_id': employee_id}"/>
+
diff --git a/l10n_pe_hr_payroll_account/data/l10n_pe_hr_payroll_account_data.xml b/l10n_pe_hr_payroll_account/data/l10n_pe_hr_payroll_account_data.xml
index da9f915f..b178e84c 100644
--- a/l10n_pe_hr_payroll_account/data/l10n_pe_hr_payroll_account_data.xml
+++ b/l10n_pe_hr_payroll_account/data/l10n_pe_hr_payroll_account_data.xml
@@ -14,6 +14,7 @@
# pay_ee='1234',
# pay_afp='1235',
# pay_onp='1236',
+ # pay_ir_4ta_cat='2222',
# pay_ir_5ta_cat='1238',
# pay_essalud='1239',
# exp_salary='1240',
@@ -36,6 +37,7 @@
# pay_ee='1234',
# pay_afp='1235',
# pay_onp='1236',
+ # pay_ir_4ta_cat='2222',
# pay_ir_5ta_cat='1238',
# pay_essalud='1239',
# exp_salary='1240',
diff --git a/l10n_pe_hr_payroll_account/i18n/es.po b/l10n_pe_hr_payroll_account/i18n/es.po
new file mode 100644
index 00000000..1ec384e8
--- /dev/null
+++ b/l10n_pe_hr_payroll_account/i18n/es.po
@@ -0,0 +1,31 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * l10n_pe_hr_payroll_account
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 13.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-04-29 22:13+0000\n"
+"PO-Revision-Date: 2022-04-29 22:13+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: l10n_pe_hr_payroll_account
+#: model:ir.model,name:l10n_pe_hr_payroll_account.model_account_chart_template
+msgid "Account Chart Template"
+msgstr "Plantila de Plan Contable"
+
+#. module: l10n_pe_hr_payroll_account
+#: model:ir.actions.server,name:l10n_pe_hr_payroll_account.action_pe_salary_rule_account_set
+msgid "Peru Default Accounting"
+msgstr "Contabilidad para Perú por Defecto"
+
+#. module: l10n_pe_hr_payroll_account
+#: model:ir.actions.server,name:l10n_pe_hr_payroll_account.action_pe_salary_rule_account_reset
+msgid "Peru Default Accounting (Reset)"
+msgstr "Contabilidad de Perú por Defecto (Resetear)"
\ No newline at end of file
diff --git a/l10n_pe_hr_payroll_account/models/account_chart_template.py b/l10n_pe_hr_payroll_account/models/account_chart_template.py
index cf9bd10b..d920ba7a 100644
--- a/l10n_pe_hr_payroll_account/models/account_chart_template.py
+++ b/l10n_pe_hr_payroll_account/models/account_chart_template.py
@@ -10,6 +10,7 @@ EXP_ESSALUD = '6271000'
PAY_EE = '4111000'
PAY_AFP = '4170000'
PAY_ONP = '4032000'
+PAY_IR_4TA_CAT = '4017200'
PAY_IR_5TA_CAT = '4017300'
PAY_ESSALUD = '4031000'
@@ -29,6 +30,7 @@ class AccountChartTemplate(models.Model):
pay_ee=PAY_EE,
pay_afp=PAY_AFP,
pay_onp=PAY_ONP,
+ pay_ir_4ta_cat=PAY_IR_4TA_CAT,
pay_ir_5ta_cat=PAY_IR_5TA_CAT,
pay_essalud=PAY_ESSALUD,
exp_salary=EXP_SALARY,
@@ -40,6 +42,7 @@ class AccountChartTemplate(models.Model):
pay_ee,
pay_afp,
pay_onp,
+ pay_ir_4ta_cat,
pay_ir_5ta_cat,
pay_essalud,
exp_salary,
@@ -133,6 +136,7 @@ class AccountChartTemplate(models.Model):
set_rule_accounts('EE_%', accounts[pay_ee], accounts['none']) # initialize
set_rule_accounts('EE_PE_AFP%', accounts[pay_afp], accounts['none'])
set_rule_accounts('EE_PE_ONP%', accounts[pay_onp], accounts['none'])
+ set_rule_accounts('EE_PE_IR_4TA_CAT%', accounts[pay_ir_4ta_cat], accounts['none'])
set_rule_accounts('EE_PE_IR_5TA_CAT%', accounts[pay_ir_5ta_cat], accounts['none'])
# ER_* -> AP debit, SE credit
set_rule_accounts('ER_%', accounts[pay_ee], accounts[exp_salary]) # initialize