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: move tests and improve
This commit is contained in:
@@ -53,4 +53,34 @@
|
|||||||
<field name="parent_id" ref="hr_payroll.COMP"/>
|
<field name="parent_id" ref="hr_payroll.COMP"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- ESSALUD-->
|
||||||
|
<record id="hr_payroll_category_ee_essalud" model="hr.salary.rule.category">
|
||||||
|
<field name="name">EE: Essalud (rem)</field>
|
||||||
|
<field name="code">EE_PE_ESSALUD</field>
|
||||||
|
<field name="parent_id" ref="hr_payroll.DED"/>
|
||||||
|
</record>
|
||||||
|
<record id="hr_payroll_category_er_essalud" model="hr.salary.rule.category">
|
||||||
|
<field name="name">EE: Essalud</field>
|
||||||
|
<field name="code">ER_PE_ESSALUD</field>
|
||||||
|
<field name="parent_id" ref="hr_payroll.COMP"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Bonus input & rule -->
|
||||||
|
<record id="input_type_bono" model="hr.payslip.input.type">
|
||||||
|
<field name="name">Bono</field>
|
||||||
|
<field name="code">BONO</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="hr_salary_rule_bonus" model="hr.salary.rule">
|
||||||
|
<field name="condition_select">python</field>
|
||||||
|
<field name="condition_python">result = inputs.BONO.amount > 0.0 if inputs.BONO else False</field>
|
||||||
|
<field name="amount_select">code</field>
|
||||||
|
<field name="amount_python_compute">result = inputs.BONO.amount if inputs.BONO else 0</field>
|
||||||
|
<field name="code">BASIC_BONO</field>
|
||||||
|
<field name="category_id" ref="hr_payroll.BASIC"/>
|
||||||
|
<field name="name">Bono</field>
|
||||||
|
<field name="sequence" eval="25"/>
|
||||||
|
<field name="struct_id" ref="l10n_pe_hr_payroll.hr_payroll_structure"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<record id="hr_payroll_rule_er_essalud" model="hr.salary.rule">
|
<record id="hr_payroll_rule_er_essalud" model="hr.salary.rule">
|
||||||
<field name="sequence" eval="220"/>
|
<field name="sequence" eval="220"/>
|
||||||
<field name="struct_id" ref="hr_payroll_structure"/>
|
<field name="struct_id" ref="hr_payroll_structure"/>
|
||||||
<field name="category_id" ref="hr_payroll_category_ee_pe_afp"/>
|
<field name="category_id" ref="hr_payroll_category_er_essalud"/>
|
||||||
<field name="name">ER: PE Essalud</field>
|
<field name="name">ER: PE Essalud</field>
|
||||||
<field name="code">ER_PE_ESSALUD</field>
|
<field name="code">ER_PE_ESSALUD</field>
|
||||||
<field name="condition_select">python</field>
|
<field name="condition_select">python</field>
|
||||||
|
|||||||
@@ -47,12 +47,17 @@
|
|||||||
<field name="condition_python">result = categories.GROSS</field>
|
<field name="condition_python">result = categories.GROSS</field>
|
||||||
<field name="amount_select">code</field>
|
<field name="amount_select">code</field>
|
||||||
<field name="amount_python_compute">
|
<field name="amount_python_compute">
|
||||||
# TODO normalize anual wage based on pay period
|
pay_periods_in_year = payslip.pay_periods_in_year
|
||||||
uit = payslip.rule_parameter('pe_uit')
|
uit = payslip.rule_parameter('pe_uit')
|
||||||
wage = categories.GROSS
|
|
||||||
wage_year = wage * 12.0
|
basic_wage = BASIC
|
||||||
# additional 2 months
|
wage_period = categories.GROSS
|
||||||
wage_year += wage * 2.0
|
period_additional_wage = max(wage_period - basic_wage, 0.0)
|
||||||
|
wage_year = basic_wage * pay_periods_in_year
|
||||||
|
# additional 2 months (July and December)
|
||||||
|
wage_year += wage_year * (1/6) # 2 months 2/12
|
||||||
|
wage_year += period_additional_wage
|
||||||
|
|
||||||
over_7uit = wage_year - (7.0 * uit)
|
over_7uit = wage_year - (7.0 * uit)
|
||||||
if over_7uit <= 0.0:
|
if over_7uit <= 0.0:
|
||||||
result = 0.0
|
result = 0.0
|
||||||
@@ -72,7 +77,7 @@ else:
|
|||||||
break
|
break
|
||||||
last_uit = _uit
|
last_uit = _uit
|
||||||
tax = -total_tax / 12.0
|
tax = -total_tax / 12.0
|
||||||
result, result_rate = wage, (tax / wage * 100.0)</field>
|
result, result_rate = wage_period, (tax / wage_period * 100.0)</field>
|
||||||
<field name="partner_id" ref="res_partner_ir_5ta_cat"/>
|
<field name="partner_id" ref="res_partner_ir_5ta_cat"/>
|
||||||
<field name="appears_on_payslip" eval="True"/>
|
<field name="appears_on_payslip" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# 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 . import browsable_object
|
|
||||||
from . import hr_contract
|
from . import hr_contract
|
||||||
from . import hr_payslip
|
from . import hr_payslip
|
||||||
from . import pe_payroll_config
|
from . import pe_payroll_config
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
|
||||||
|
|
||||||
from odoo import fields
|
|
||||||
from odoo.addons.hr_payroll.models import browsable_object
|
|
||||||
|
|
||||||
|
|
||||||
class BrowsableObject(object):
|
|
||||||
def __init__(self, employee_id, dict, env):
|
|
||||||
self.employee_id = employee_id
|
|
||||||
self.dict = dict
|
|
||||||
self.env = env
|
|
||||||
# Customization to allow changing the behavior of the discrete browsable objects.
|
|
||||||
# you can think of this as 'compiling' the query based on the configuration.
|
|
||||||
sum_field = env['ir.config_parameter'].sudo().get_param('hr_payroll.payslip.sum_behavior', 'date_from')
|
|
||||||
if sum_field == 'date' and 'date' not in env['hr.payslip']:
|
|
||||||
# missing attribute, closest by definition
|
|
||||||
sum_field = 'date_to'
|
|
||||||
if not sum_field:
|
|
||||||
sum_field = 'date_from'
|
|
||||||
self._compile_browsable_query(sum_field)
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
return attr in self.dict and self.dict.__getitem__(attr) or 0.0
|
|
||||||
|
|
||||||
def _compile_browsable_query(self, sum_field):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class InputLine(BrowsableObject):
|
|
||||||
"""a class that will be used into the python code, mainly for usability purposes"""
|
|
||||||
def _compile_browsable_query(self, sum_field):
|
|
||||||
self.__browsable_query = """
|
|
||||||
SELECT sum(amount) as sum
|
|
||||||
FROM hr_payslip as hp, hr_payslip_input as pi
|
|
||||||
WHERE hp.employee_id = %s AND hp.state = 'done'
|
|
||||||
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pi.payslip_id AND pi.code = %s""".format(sum_field=sum_field)
|
|
||||||
|
|
||||||
def sum(self, code, from_date, to_date=None):
|
|
||||||
if to_date is None:
|
|
||||||
to_date = fields.Date.today()
|
|
||||||
self.env.cr.execute(self.__browsable_query, (self.employee_id, from_date, to_date, code))
|
|
||||||
return self.env.cr.fetchone()[0] or 0.0
|
|
||||||
|
|
||||||
|
|
||||||
class WorkedDays(BrowsableObject):
|
|
||||||
"""a class that will be used into the python code, mainly for usability purposes"""
|
|
||||||
def _compile_browsable_query(self, sum_field):
|
|
||||||
self.__browsable_query = """
|
|
||||||
SELECT sum(number_of_days) as number_of_days, sum(number_of_hours) as number_of_hours
|
|
||||||
FROM hr_payslip as hp, hr_payslip_worked_days as pi
|
|
||||||
WHERE hp.employee_id = %s AND hp.state = 'done'
|
|
||||||
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pi.payslip_id AND pi.code = %s""".format(sum_field=sum_field)
|
|
||||||
|
|
||||||
def _sum(self, code, from_date, to_date=None):
|
|
||||||
if to_date is None:
|
|
||||||
to_date = fields.Date.today()
|
|
||||||
self.env.cr.execute(self.__browsable_query, (self.employee_id, from_date, to_date, code))
|
|
||||||
return self.env.cr.fetchone()
|
|
||||||
|
|
||||||
def sum(self, code, from_date, to_date=None):
|
|
||||||
res = self._sum(code, from_date, to_date)
|
|
||||||
return res and res[0] or 0.0
|
|
||||||
|
|
||||||
def sum_hours(self, code, from_date, to_date=None):
|
|
||||||
res = self._sum(code, from_date, to_date)
|
|
||||||
return res and res[1] or 0.0
|
|
||||||
|
|
||||||
|
|
||||||
class Payslips(BrowsableObject):
|
|
||||||
"""a class that will be used into the python code, mainly for usability purposes"""
|
|
||||||
def _compile_browsable_query(self, sum_field):
|
|
||||||
# Note that the core odoo has this as `hp.credit_note = False` but what if it is NULL?
|
|
||||||
# reverse of the desired behavior.
|
|
||||||
self.__browsable_query_rule = """
|
|
||||||
SELECT sum(case when hp.credit_note is not True then (pl.total) else (-pl.total) end)
|
|
||||||
FROM hr_payslip as hp, hr_payslip_line as pl
|
|
||||||
WHERE hp.employee_id = %s AND hp.state = 'done'
|
|
||||||
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id AND pl.code = %s""".format(sum_field=sum_field)
|
|
||||||
# Original (non-recursive)
|
|
||||||
# self.__browsable_query_category = """
|
|
||||||
# SELECT sum(case when hp.credit_note is not True then (pl.total) else (-pl.total) end)
|
|
||||||
# FROM hr_payslip as hp, hr_payslip_line as pl, hr_salary_rule_category as rc
|
|
||||||
# WHERE hp.employee_id = %s AND hp.state = 'done'
|
|
||||||
# AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id
|
|
||||||
# AND rc.id = pl.category_id AND rc.code = %s""".format(sum_field=sum_field)
|
|
||||||
|
|
||||||
# Hibou Recursive version
|
|
||||||
self.__browsable_query_category = """
|
|
||||||
WITH RECURSIVE
|
|
||||||
category_by_code as (
|
|
||||||
SELECT id
|
|
||||||
FROM hr_salary_rule_category
|
|
||||||
WHERE code = %s
|
|
||||||
),
|
|
||||||
category_ids as (
|
|
||||||
SELECT COALESCE((SELECT id FROM category_by_code), -1) AS id
|
|
||||||
UNION ALL
|
|
||||||
SELECT rc.id
|
|
||||||
FROM hr_salary_rule_category AS rc
|
|
||||||
JOIN category_ids AS rcs ON rcs.id = rc.parent_id
|
|
||||||
)
|
|
||||||
|
|
||||||
SELECT sum(case when hp.credit_note is not True then (pl.total) else (-pl.total) end)
|
|
||||||
FROM hr_payslip as hp, hr_payslip_line as pl
|
|
||||||
WHERE hp.employee_id = %s AND hp.state = 'done'
|
|
||||||
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id
|
|
||||||
AND pl.category_id in (SELECT id from category_ids)""".format(sum_field=sum_field)
|
|
||||||
|
|
||||||
def sum(self, code, from_date, to_date=None):
|
|
||||||
if to_date is None:
|
|
||||||
to_date = fields.Date.today()
|
|
||||||
self.env.cr.execute(self.__browsable_query_rule, (self.employee_id, from_date, to_date, code))
|
|
||||||
res = self.env.cr.fetchone()
|
|
||||||
return res and res[0] or 0.0
|
|
||||||
|
|
||||||
def rule_parameter(self, code):
|
|
||||||
return self.env['hr.rule.parameter']._get_parameter_from_code(code, self.dict.date_to)
|
|
||||||
|
|
||||||
def sum_category(self, code, from_date, to_date=None):
|
|
||||||
if to_date is None:
|
|
||||||
to_date = fields.Date.today()
|
|
||||||
|
|
||||||
self.env['hr.payslip'].flush(['credit_note', 'employee_id', 'state', 'date_from', 'date_to'])
|
|
||||||
self.env['hr.payslip.line'].flush(['total', 'slip_id', 'category_id'])
|
|
||||||
self.env['hr.salary.rule.category'].flush(['code'])
|
|
||||||
|
|
||||||
# standard version
|
|
||||||
# self.env.cr.execute(self.__browsable_query_category, (self.employee_id, from_date, to_date, code))
|
|
||||||
# recursive category version
|
|
||||||
self.env.cr.execute(self.__browsable_query_category, (code, self.employee_id, from_date, to_date))
|
|
||||||
res = self.env.cr.fetchone()
|
|
||||||
return res and res[0] or 0.0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def paid_amount(self):
|
|
||||||
return self.dict._get_paid_amount()
|
|
||||||
|
|
||||||
|
|
||||||
# Patch over Core
|
|
||||||
browsable_object.BrowsableObject.__init__ = BrowsableObject.__init__
|
|
||||||
browsable_object.BrowsableObject._compile_browsable_query = BrowsableObject._compile_browsable_query
|
|
||||||
browsable_object.InputLine._compile_browsable_query = InputLine._compile_browsable_query
|
|
||||||
browsable_object.InputLine.sum = InputLine.sum
|
|
||||||
browsable_object.WorkedDays._compile_browsable_query = WorkedDays._compile_browsable_query
|
|
||||||
browsable_object.WorkedDays.sum = WorkedDays.sum
|
|
||||||
browsable_object.Payslips._compile_browsable_query = Payslips._compile_browsable_query
|
|
||||||
browsable_object.Payslips.sum = Payslips.sum
|
|
||||||
browsable_object.Payslips.sum_category = Payslips.sum_category
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
# TODO make/move to l10n_pe_hr_payroll_params
|
# Tests moved to `l10n_pe_hr_payroll_params`
|
||||||
# Tests moved to `l10n_us_hr_payroll_params`
|
|
||||||
# common remains for site specific tests
|
# common remains for site specific tests
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
from . import test_2020
|
|
||||||
# from . import test_2022
|
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
|
||||||
|
|
||||||
from .common import TestPePayslip, process_payslip
|
|
||||||
|
|
||||||
|
|
||||||
class Test2020(TestPePayslip):
|
|
||||||
|
|
||||||
###
|
|
||||||
# 2020 Taxes and Rates
|
|
||||||
###
|
|
||||||
|
|
||||||
def test_2020_taxes(self):
|
|
||||||
# High salary to hit the maximum for AFP_SEGURO
|
|
||||||
salary = 8000.00
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
|
||||||
|
|
||||||
contract = self._createContract(employee,
|
|
||||||
wage=salary,
|
|
||||||
retirement_type='afp',
|
|
||||||
afp_type='profuturo',
|
|
||||||
afp_comision_type='mixta',
|
|
||||||
comp_ss_type='essalud',
|
|
||||||
)
|
|
||||||
self._log(contract.read())
|
|
||||||
|
|
||||||
self._log('2020 tax first payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
# Employee
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_PENSIONES'], -cats['GROSS'] * (10.0 / 100.0))
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_SEGURO'], -cats['GROSS'] * (1.35 / 100.0))
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_COMISION_MIXTA'], -cats['GROSS'] * (0.67 / 100.0))
|
|
||||||
# Employer
|
|
||||||
self.assertPayrollEqual(rules['ER_PE_ESSALUD'], -cats['GROSS'] * (6.75 / 100.0))
|
|
||||||
|
|
||||||
process_payslip(payslip)
|
|
||||||
|
|
||||||
self._log('2020 tax second payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2020-02-01', '2020-02-28')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
# Employee
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_PENSIONES'], -cats['GROSS'] * (10.0 / 100.0))
|
|
||||||
|
|
||||||
self.assertTrue(cats['GROSS'] < 9707.03)
|
|
||||||
# Seguro has a wage base.
|
|
||||||
second_seguro = -(9707.03 - cats['GROSS']) * (1.35 / 100.0)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_SEGURO'], second_seguro)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_COMISION_MIXTA'], -cats['GROSS'] * (0.67 / 100.0))
|
|
||||||
# Employer
|
|
||||||
self.assertPayrollEqual(rules['ER_PE_ESSALUD'], -cats['GROSS'] * (6.75 / 100.0))
|
|
||||||
|
|
||||||
process_payslip(payslip)
|
|
||||||
|
|
||||||
self._log('2020 tax third payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2020-03-01', '2020-03-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
# Employee
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_PENSIONES'], -cats['GROSS'] * (10.0 / 100.0))
|
|
||||||
|
|
||||||
self.assertTrue(cats['GROSS'] < 9707.03)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_SEGURO'], 0.0)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_COMISION_MIXTA'], -cats['GROSS'] * (0.67 / 100.0))
|
|
||||||
# Employer
|
|
||||||
self.assertPayrollEqual(rules['ER_PE_ESSALUD'], -cats['GROSS'] * (6.75 / 100.0))
|
|
||||||
|
|
||||||
process_payslip(payslip)
|
|
||||||
|
|
||||||
def test_2020_onp(self):
|
|
||||||
salary = 3500.00
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
|
||||||
|
|
||||||
contract = self._createContract(employee,
|
|
||||||
wage=salary,
|
|
||||||
retirement_type='onp',
|
|
||||||
onp_rule_id=self.env.ref('l10n_pe_hr_payroll.hr_payroll_rule_ee_onp').id,
|
|
||||||
comp_ss_type='essalud',
|
|
||||||
)
|
|
||||||
self._log(contract.read())
|
|
||||||
|
|
||||||
self._log('2020 tax first payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
# Employee
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_PENSIONES'], 0.0)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_SEGURO'], 0.0)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_COMISION_MIXTA'], 0.0)
|
|
||||||
self.assertPayrollEqual(cats['EE_PE_ONP'], -cats['GROSS'] * (13.0 / 100.0))
|
|
||||||
# Employer
|
|
||||||
self.assertPayrollEqual(rules['ER_PE_ESSALUD'], -cats['GROSS'] * (6.75 / 100.0))
|
|
||||||
|
|
||||||
process_payslip(payslip)
|
|
||||||
|
|
||||||
def test_2020_ir_5ta_cat(self):
|
|
||||||
salary = 1500.00
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
|
||||||
|
|
||||||
contract = self._createContract(employee,
|
|
||||||
wage=salary,
|
|
||||||
retirement_type='onp',
|
|
||||||
onp_rule_id=self.env.ref('l10n_pe_hr_payroll.hr_payroll_rule_ee_onp').id,
|
|
||||||
comp_ss_type='essalud',
|
|
||||||
)
|
|
||||||
|
|
||||||
self._log('2020 tax first payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_IR_5TA_CAT'], 0.0)
|
|
||||||
payslip.state = 'cancel'
|
|
||||||
payslip.unlink()
|
|
||||||
|
|
||||||
# larger salary to trigger calculation
|
|
||||||
salary = 3000.0
|
|
||||||
contract.wage = salary
|
|
||||||
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
self.assertPayrollEqual(cats['GROSS'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_IR_5TA_CAT'], -74.67)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
|
||||||
|
|
||||||
from .common import TestPePayslip, process_payslip
|
|
||||||
|
|
||||||
|
|
||||||
class Test2022(TestPePayslip):
|
|
||||||
|
|
||||||
# AFP Constants
|
|
||||||
AFP_PENSIONES = 0.1 # 10%
|
|
||||||
AFP_SEGURO = 0.0174 # 1.74%
|
|
||||||
AFP_COMISION = 0.0018 # 0.18%
|
|
||||||
|
|
||||||
# ER ESSALUD
|
|
||||||
ER_ESSALUD = 0.0675 # 6.75%
|
|
||||||
|
|
||||||
###
|
|
||||||
# 2022 Taxes and Rates
|
|
||||||
###
|
|
||||||
|
|
||||||
def test_2022_taxes(self):
|
|
||||||
salary = 3290.0
|
|
||||||
|
|
||||||
employee = self._createEmployee()
|
|
||||||
|
|
||||||
contract = self._createContract(employee, wage=salary)
|
|
||||||
self._log(contract.read())
|
|
||||||
|
|
||||||
self._log('2022 tax first payslip:')
|
|
||||||
payslip = self._createPayslip(employee, '2022-01-01', '2022-01-31')
|
|
||||||
payslip.compute_sheet()
|
|
||||||
|
|
||||||
cats = self._getCategories(payslip)
|
|
||||||
rules = self._getRules(payslip)
|
|
||||||
# Employee
|
|
||||||
self.assertPayrollEqual(cats['BASIC'], salary)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_PENSIONES'], -cats['BASIC'] * self.AFP_PENSIONES)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_SEGURO'], -cats['BASIC'] * self.AFP_SEGURO)
|
|
||||||
self.assertPayrollEqual(rules['EE_PE_AFP_COMISION'], -cats['BASIC'] * self.AFP_COMISION)
|
|
||||||
# Employer
|
|
||||||
self.assertPayrollEqual(rules['ER_PE_ESSALUD'], -cats['BASIC'] * self.ER_ESSALUD)
|
|
||||||
|
|
||||||
process_payslip(payslip)
|
|
||||||
Reference in New Issue
Block a user