From 96493be79610fdd70f45e6bb46871d1e0fb89d97 Mon Sep 17 00:00:00 2001 From: pranaysaidurga Date: Mon, 25 May 2026 16:38:40 +0530 Subject: [PATCH] Leaves Timesheets Management --- .../leaves_timesheets_extended/__init__.py | 1 + .../__manifest__.py | 22 +++++ .../data/project_task_data.xml | 26 ++++++ .../models/__init__.py | 1 + .../models/hr_leave.py | 80 +++++++++++++++++++ .../security/ir.model.access.csv | 1 + .../views/hr_leave_views.xml | 31 +++++++ 7 files changed, 162 insertions(+) create mode 100644 addons_extensions/leaves_timesheets_extended/__init__.py create mode 100644 addons_extensions/leaves_timesheets_extended/__manifest__.py create mode 100644 addons_extensions/leaves_timesheets_extended/data/project_task_data.xml create mode 100644 addons_extensions/leaves_timesheets_extended/models/__init__.py create mode 100644 addons_extensions/leaves_timesheets_extended/models/hr_leave.py create mode 100644 addons_extensions/leaves_timesheets_extended/security/ir.model.access.csv create mode 100644 addons_extensions/leaves_timesheets_extended/views/hr_leave_views.xml diff --git a/addons_extensions/leaves_timesheets_extended/__init__.py b/addons_extensions/leaves_timesheets_extended/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/addons_extensions/leaves_timesheets_extended/__manifest__.py b/addons_extensions/leaves_timesheets_extended/__manifest__.py new file mode 100644 index 000000000..b63ce0866 --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/__manifest__.py @@ -0,0 +1,22 @@ +{ + 'name': 'Leaves Timesheets Extended', + 'version': '18.0.1.0.0', + 'category': 'Human Resources', + 'summary': 'Integrate Leaves with Timesheets', + 'author': 'Srivyn Platforms', + 'license': 'LGPL-3', + + 'depends': [ + 'hr_holidays', + 'hr_timesheet', + 'project', + ], + + 'data': [ + 'data/project_task_data.xml', + 'views/hr_leave_views.xml', + ], + + 'installable': True, + 'application': False, +} \ No newline at end of file diff --git a/addons_extensions/leaves_timesheets_extended/data/project_task_data.xml b/addons_extensions/leaves_timesheets_extended/data/project_task_data.xml new file mode 100644 index 000000000..2c8193cd5 --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/data/project_task_data.xml @@ -0,0 +1,26 @@ + + + + + + Internal Project + + + + + True + + + + + Leaves Management + + + + + + + + \ No newline at end of file diff --git a/addons_extensions/leaves_timesheets_extended/models/__init__.py b/addons_extensions/leaves_timesheets_extended/models/__init__.py new file mode 100644 index 000000000..91cd9ccad --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/models/__init__.py @@ -0,0 +1 @@ +from . import hr_leave \ No newline at end of file diff --git a/addons_extensions/leaves_timesheets_extended/models/hr_leave.py b/addons_extensions/leaves_timesheets_extended/models/hr_leave.py new file mode 100644 index 000000000..c13a8bd31 --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/models/hr_leave.py @@ -0,0 +1,80 @@ +from odoo import models, fields, api + + +class HrLeave(models.Model): + _inherit = 'hr.leave' + + project_id = fields.Many2one( + 'project.project', + string='Project' + ) + + task_id = fields.Many2one( + 'project.task', + string='Task' + ) + + timesheet_line_id = fields.Many2one( + 'account.analytic.line', + string='Timesheet Entry', + readonly=True, + copy=False + ) + + # CREATE TIMESHEET ON APPROVAL + + def action_validate(self, check_state=True): + res = super().action_validate(check_state=check_state) + + default_project = self.env.ref( + 'leaves_timesheets_extended.project_internal_leave' + ) + + default_task = self.env.ref( + 'leaves_timesheets_extended.task_leave_management' + ) + + for leave in self: + + # Prevent duplicate creation + if leave.timesheet_line_id: + continue + + project = leave.project_id or default_project + task = leave.task_id or default_task + + # Hours Calculation + if leave.request_unit_half: + hours = 4 + else: + hours = leave.number_of_days * 8 + + analytic_line = self.env[ + 'account.analytic.line' + ].create({ + 'name': f"Leave: {leave.holiday_status_id.name}", + 'employee_id': leave.employee_id.id, + 'user_id': leave.employee_id.user_id.id, + 'project_id': project.id, + 'task_id': task.id, + 'unit_amount': hours, + 'date': leave.request_date_from, + 'company_id': leave.company_id.id, + }) + + leave.timesheet_line_id = analytic_line.id + + return res + # DELETE TIMESHEET ON REFUSE + + def action_refuse(self): + res = super().action_refuse() + + for leave in self: + + if leave.timesheet_line_id: + leave.timesheet_line_id.unlink() + leave.timesheet_line_id = False + + return res + diff --git a/addons_extensions/leaves_timesheets_extended/security/ir.model.access.csv b/addons_extensions/leaves_timesheets_extended/security/ir.model.access.csv new file mode 100644 index 000000000..97dd8b917 --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/security/ir.model.access.csv @@ -0,0 +1 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink diff --git a/addons_extensions/leaves_timesheets_extended/views/hr_leave_views.xml b/addons_extensions/leaves_timesheets_extended/views/hr_leave_views.xml new file mode 100644 index 000000000..11555109d --- /dev/null +++ b/addons_extensions/leaves_timesheets_extended/views/hr_leave_views.xml @@ -0,0 +1,31 @@ + + + + + + + hr.leave.form.inherit.timesheet + + + hr.leave + + + + + + + + + + + + + + + + + + \ No newline at end of file