From 3cd5ab08c7d027ebe7a08e0c86a46d3f50dec7f2 Mon Sep 17 00:00:00 2001 From: Daniel Reis Date: Thu, 2 Jan 2025 08:13:31 +0000 Subject: [PATCH] [ADD] payroll_salary_table --- payroll_salary_table/README.rst | 1 + payroll_salary_table/__init__.py | 1 + payroll_salary_table/__manifest__.py | 15 ++ payroll_salary_table/models/__init__.py | 4 + payroll_salary_table/models/hr_contract.py | 27 +++ payroll_salary_table/models/hr_payslip.py | 17 ++ payroll_salary_table/models/hr_salary_rule.py | 32 ++++ .../models/hr_salary_table.py | 77 ++++++++ payroll_salary_table/pyproject.toml | 3 + .../security/hr_payroll_security.xml | 19 ++ .../security/ir.model.access.csv | 4 + .../views/hr_salary_table.xml | 172 ++++++++++++++++++ 12 files changed, 372 insertions(+) create mode 100644 payroll_salary_table/README.rst create mode 100644 payroll_salary_table/__init__.py create mode 100644 payroll_salary_table/__manifest__.py create mode 100644 payroll_salary_table/models/__init__.py create mode 100644 payroll_salary_table/models/hr_contract.py create mode 100644 payroll_salary_table/models/hr_payslip.py create mode 100644 payroll_salary_table/models/hr_salary_rule.py create mode 100644 payroll_salary_table/models/hr_salary_table.py create mode 100644 payroll_salary_table/pyproject.toml create mode 100644 payroll_salary_table/security/hr_payroll_security.xml create mode 100644 payroll_salary_table/security/ir.model.access.csv create mode 100644 payroll_salary_table/views/hr_salary_table.xml diff --git a/payroll_salary_table/README.rst b/payroll_salary_table/README.rst new file mode 100644 index 00000000..1e90f747 --- /dev/null +++ b/payroll_salary_table/README.rst @@ -0,0 +1 @@ +TODO! diff --git a/payroll_salary_table/__init__.py b/payroll_salary_table/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/payroll_salary_table/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/payroll_salary_table/__manifest__.py b/payroll_salary_table/__manifest__.py new file mode 100644 index 00000000..749f5e55 --- /dev/null +++ b/payroll_salary_table/__manifest__.py @@ -0,0 +1,15 @@ +{ + "name": "Payroll Value Table", + "version": "18.0.1.0.0", + "category": "Payroll", + "website": "https://github.com/OCA/payroll", + "license": "LGPL-3", + "author": "Daniel Reis, Odoo Community Association (OCA)", + "depends": ["payroll", "hr_master_data"], + "data": [ + "security/hr_payroll_security.xml", + "security/ir.model.access.csv", + "views/hr_salary_table.xml", + ], + "maintainers": ["dreispt"], +} diff --git a/payroll_salary_table/models/__init__.py b/payroll_salary_table/models/__init__.py new file mode 100644 index 00000000..eb3f0913 --- /dev/null +++ b/payroll_salary_table/models/__init__.py @@ -0,0 +1,4 @@ +from . import hr_contract +from . import hr_payslip +from . import hr_salary_rule +from . import hr_salary_table diff --git a/payroll_salary_table/models/hr_contract.py b/payroll_salary_table/models/hr_contract.py new file mode 100644 index 00000000..531f57a7 --- /dev/null +++ b/payroll_salary_table/models/hr_contract.py @@ -0,0 +1,27 @@ +from odoo import api, fields, models + + +class HrContract(models.Model): + _inherit = "hr.contract" + + @api.depends_context("active_date") + @api.depends("contract_values_ids") + def _compute_active_values_ids(self): + active_date = self.env.context.get("active_date") + for contract in self: + contract.active_values_ids = contract.contract_values_ids.filtered( + lambda x: not active_date + or ( + (not x.date_start or x.date_start <= active_date) + and (not x.date_end or x.date_end >= active_date) + ) + ) + + contract_values_ids = fields.One2many( + comodel_name="hr.employee.data.value", + inverse_name="contract_id", + ) + active_values_ids = fields.One2many( + comodel_name="hr.employee.data.value", + compute="_compute_active_values_ids", + ) diff --git a/payroll_salary_table/models/hr_payslip.py b/payroll_salary_table/models/hr_payslip.py new file mode 100644 index 00000000..58653791 --- /dev/null +++ b/payroll_salary_table/models/hr_payslip.py @@ -0,0 +1,17 @@ +from odoo import models + + +class HrPayslip(models.Model): + _inherit = "hr.payslip" + + def _get_employee_contracts(self): + # Set active_date in the context + # To be used to filter active values + self = self.with_context(active_date=self.date_to) + return super()._get_employee_contracts() + + def localdict_hook(self, localdict): + contract = localdict["contract"] + # TODO: Make values a dotnotaion accessible object + localdict["values"] = contract.active_values_ids + return localdict diff --git a/payroll_salary_table/models/hr_salary_rule.py b/payroll_salary_table/models/hr_salary_rule.py new file mode 100644 index 00000000..1a2bcc1c --- /dev/null +++ b/payroll_salary_table/models/hr_salary_rule.py @@ -0,0 +1,32 @@ +from odoo import api, fields, models + + +class HrSalaryRule(models.Model): + _inherit = "hr.salary.rule" + + salary_table_lines_ids = fields.One2many( + comodel_name="hr.salary.table.line", + inverse_name="salary_rule_id", + ) + active_salary_table_lines_ids = fields.One2many( + comodel_name="hr.salary.table.line", + compute="_compute_active_salary_table_lines_ids", + ) + + @api.depends_context("active_date") + @api.depends("salary_table_lines_ids") + def _compute_active_salary_table_lines_ids(self): + """ + Lists only active salary table lines at a provided date. + Used by the Payslip computation to query the salary table. + """ + active_date = self.env.context.get("active_date") + for rule in self: + lines = rule.salary_table_lines_ids.filtered( + lambda x: not active_date + or ( + (not x.date_start or x.date_start <= active_date) + and (not x.date_end or x.date_end >= active_date) + ) + ) + rule.active_salary_table_lines_ids = lines diff --git a/payroll_salary_table/models/hr_salary_table.py b/payroll_salary_table/models/hr_salary_table.py new file mode 100644 index 00000000..84cc082d --- /dev/null +++ b/payroll_salary_table/models/hr_salary_table.py @@ -0,0 +1,77 @@ +from odoo import fields, models + + +class HrSalaryTableTemplate(models.Model): + _name = "hr.salary.table.template" + _description = "Salary Table Template" + + name = fields.Char(required=True) + code = fields.Char() + type_1_id = fields.Many2one("hr.data.type") + type_2_id = fields.Many2one("hr.data.type") + type_3_id = fields.Many2one("hr.data.type") + line_ids = fields.One2many( + comodel_name="hr.salary.table", + inverse_name="template_id", + ) + note = fields.Text() + active = fields.Boolean(default=True) + + +class HrSalaryTable(models.Model): + _name = "hr.salary.table" + _description = "Salary Table" + + template_id = fields.Many2one("hr.salary.table.template", required=True) + company_id = fields.Many2one("res.company") + salary_rule_id = fields.Many2one("hr.salary.rule", required=True) + date_start = fields.Date() + date_end = fields.Date() + line_ids = fields.One2many( + comodel_name="hr.salary.table.line", + inverse_name="table_id", + ) + note = fields.Text() + + +class HrSalaryTableLine(models.Model): + _name = "hr.salary.table.line" + _description = "Salary Table Line" + + table_id = fields.Many2one("hr.salary.table") + template_id = fields.Many2one( + "hr.salary.table.template", related="table_id.template_id", store=True + ) + salary_rule_id = fields.Many2one( + "hr.salary.rule", related="table_id.salary_rule_id", store=True + ) + type_1_id = fields.Many2one( + "hr.data.type", related="table_id.template_id.type_1_id" + ) + type_2_id = fields.Many2one( + "hr.data.type", related="table_id.template_id.type_2_id" + ) + type_3_id = fields.Many2one( + "hr.data.type", related="table_id.template_id.type_3_id" + ) + company_id = fields.Many2one( + comodel_name="res.company", related="table_id.company_id", store=True + ) + date_start = fields.Date(related="table_id.date_start", store=True) + date_end = fields.Date(related="table_id.date_end", store=True) + value_1_id = fields.Many2one( + "hr.data.type.value", + domain="[('type_id', '=', type_1_id)]", + ) + value_2_id = fields.Many2one( + "hr.data.type.value", + domain="[('type_id', '=', type_2_id)]", + ) + value_3_id = fields.Many2one( + "hr.data.type.value", + domain="[('type_id', '=', type_3_id)]", + ) + number_from = fields.Float() + number_to = fields.Float() + result = fields.Float() + note = fields.Text() diff --git a/payroll_salary_table/pyproject.toml b/payroll_salary_table/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/payroll_salary_table/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/payroll_salary_table/security/hr_payroll_security.xml b/payroll_salary_table/security/hr_payroll_security.xml new file mode 100644 index 00000000..fcf6e699 --- /dev/null +++ b/payroll_salary_table/security/hr_payroll_security.xml @@ -0,0 +1,19 @@ + + + + Salary Table: multi-company + + + + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] + + + + Salary Table Line: multi-company + + + + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] + + + diff --git a/payroll_salary_table/security/ir.model.access.csv b/payroll_salary_table/security/ir.model.access.csv new file mode 100644 index 00000000..d6ad31a3 --- /dev/null +++ b/payroll_salary_table/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_hr_salary_table_template_user,hr.salary.table.template user,model_hr_salary_table_template,payroll.group_payroll_user,1,1,1,1 +access_hr_salary_table_user,hr.salary.table user,model_hr_salary_table,payroll.group_payroll_user,1,1,1,1 +access_hr_salary_table_line_user,hr.salary.table.line user,model_hr_salary_table_line,payroll.group_payroll_user,1,1,1,1 diff --git a/payroll_salary_table/views/hr_salary_table.xml b/payroll_salary_table/views/hr_salary_table.xml new file mode 100644 index 00000000..787199d4 --- /dev/null +++ b/payroll_salary_table/views/hr_salary_table.xml @@ -0,0 +1,172 @@ + + + + hr.salary.table.template.list + hr.salary.table.template + + + + + + + + + + + + + + hr.salary.table.form.template + hr.salary.table.template + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + hr.salary.table.list + hr.salary.table + + + + + + + + + + + + + hr.salary.table.form + hr.salary.table + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + hr.salary.table.line.list + hr.salary.table.line + + + + + + + + + + + + + + + + + + + + Salary Table Templates + hr.salary.table.template + list,form + + + + Salary Tables + hr.salary.table + list,form + + + + Salary Table Lines + hr.salary.table.line + list,form + + + + + + + + +