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