odoo18/addons_extensions/flutter_odoo/models/hr_leave.py

172 lines
8.6 KiB
Python

from logging import exception
from odoo import api, models, _, fields
from odoo.exceptions import ValidationError
from odoo.tools.misc import format_date
from datetime import datetime
class HRLeave(models.Model):
_inherit = "hr.leave"
def flutter_check_overlap_constrain(self,employee_id, to_date, from_date, fetched_leave_id=None):
if self.env.context.get('leave_skip_date_check', False):
return
date_from = datetime.fromisoformat(from_date).replace(hour=0, minute=0, second=0)
date_to = datetime.fromisoformat(to_date).replace(hour=23, minute=59, second=59)
employee_id = int(employee_id)
all_leaves = self.search([
('date_from', '<', date_to),
('date_to', '>', date_from),
('employee_id', 'in', [employee_id]),
('state', 'not in', ['cancel', 'refuse']),
])
domain = [
('employee_id', '=', employee_id),
('date_from', '<', date_to),
('date_to', '>', date_from),
('state', 'not in', ['cancel', 'refuse']),
]
if fetched_leave_id and fetched_leave_id > 0:
all_leaves = self.search([
('date_from', '<', date_to),
('date_to', '>', date_from),
('employee_id', 'in', [employee_id]),
('id','!=', fetched_leave_id),
('state', 'not in', ['cancel', 'refuse']),
])
domain = [
('employee_id', '=', employee_id),
('date_from', '<', date_to),
('date_to', '>', date_from),
('id', '!=', fetched_leave_id),
('state', 'not in', ['cancel', 'refuse']),
]
conflicting_holidays = all_leaves.filtered_domain(domain)
if conflicting_holidays:
conflicting_holidays_list = []
# Do not display the name of the employee if the conflicting holidays have an employee_id.user_id equivalent to the user id
holidays_only_have_uid = bool(employee_id)
holiday_states = dict(conflicting_holidays.fields_get(allfields=['state'])['state']['selection'])
for conflicting_holiday in conflicting_holidays:
conflicting_holiday_data = {}
conflicting_holiday_data['employee_name'] = conflicting_holiday.employee_id.name
conflicting_holiday_data['date_from'] = format_date(self.env,
min(conflicting_holiday.mapped('date_from')))
conflicting_holiday_data['date_to'] = format_date(self.env,
min(conflicting_holiday.mapped('date_to')))
conflicting_holiday_data['state'] = holiday_states[conflicting_holiday.state]
if conflicting_holiday.employee_id.user_id.id != self.env.uid:
holidays_only_have_uid = False
if conflicting_holiday_data not in conflicting_holidays_list:
conflicting_holidays_list.append(conflicting_holiday_data)
if not conflicting_holidays_list:
return
conflicting_holidays_strings = []
if holidays_only_have_uid:
for conflicting_holiday_data in conflicting_holidays_list:
conflicting_holidays_string = _('from %(date_from)s to %(date_to)s - %(state)s',
date_from=conflicting_holiday_data['date_from'],
date_to=conflicting_holiday_data['date_to'],
state=conflicting_holiday_data['state'])
conflicting_holidays_strings.append(conflicting_holidays_string)
error = """\
You've already booked time off which overlaps with this period:
%s
Attempting to double-book your time off won't magically make your vacation 2x better!
""".join(conflicting_holidays_strings)
return error
for conflicting_holiday_data in conflicting_holidays_list:
conflicting_holidays_string = "\n" + _(
'%(employee_name)s - from %(date_from)s to %(date_to)s - %(state)s',
employee_name=conflicting_holiday_data['employee_name'],
date_from=conflicting_holiday_data['date_from'],
date_to=conflicting_holiday_data['date_to'],
state=conflicting_holiday_data['state'])
conflicting_holidays_strings.append(conflicting_holidays_string)
error = "An employee already booked time off which overlaps with this period:%s","".join(conflicting_holidays_strings)
return error
@api.model
def calculate_leave_duration(self, date_from, date_to, employee_id):
"""
Calculate the number of days and hours for the given date range and employee.
"""
employee = self.env['hr.employee'].browse(employee_id)
if not employee:
return {'error': 'Employee not found'}
from_date = datetime.fromisoformat(date_from).replace(hour=0, minute=0, second=0)
to_date = datetime.fromisoformat(date_to).replace(hour=23, minute=59, second=59)
# Define a fake leave record to use _get_durations
leave_values = {
'employee_id': employee.id,
'date_from': fields.Datetime.from_string(from_date),
'date_to': fields.Datetime.from_string(to_date),
'holiday_status_id': self.env['hr.leave.type'].search([], limit=1).id,
# Replace with appropriate leave type ID
'resource_calendar_id': employee.resource_calendar_id.id,
}
leave = self.new(leave_values)
durations = leave._get_durations()
leave_id = list(durations.keys())[0]
days, hours = durations[leave_id]
return {
'days': float(days),
'hours': float(hours),
}
@api.model
def submit_leave_flutter_odoo(self,leave_request_data, existing_leave_id = None):
try:
date_from = datetime.fromisoformat(leave_request_data['date_from']).replace(hour=0, minute=0, second=0)
date_to = datetime.fromisoformat(leave_request_data['date_to']).replace(hour=23, minute=59, second=59)
if existing_leave_id and existing_leave_id > 0:
leave_id = self.env['hr.leave'].sudo().browse(existing_leave_id)
else:
leave_id = False
if leave_id:
leave_id.sudo().write({
'employee_id': leave_request_data['employee_id'],
'holiday_status_id': leave_request_data['holiday_status_id'],
'request_date_from': date_from.date(),
'request_date_to':date_to.date(),
'name': leave_request_data['description'],
'request_unit_half': leave_request_data['is_half_day'],
'request_date_from_period': 'pm' if leave_request_data['half_day_option'] == 'afternoon' else 'am',
})
leave = leave_id
else:
leave = self.env['hr.leave'].sudo().create({
'employee_id': leave_request_data['employee_id'],
'holiday_status_id': leave_request_data['holiday_status_id'],
'request_date_from': date_from.date(),
'request_date_to':date_to.date(),
'name':leave_request_data['description'],
'request_unit_half': leave_request_data['is_half_day'],
'request_date_from_period': 'pm' if leave_request_data['half_day_option'] == 'afternoon' else 'am',
})
attachment_ids = []
for attachment in leave_request_data['attachments']:
attachment_record = self.env['ir.attachment'].create({
'name': attachment['name'], # Attachment name
'datas': attachment['datas'], # Base64 encoded data
'res_model': 'hr.leave', # Model to link
'res_id': leave.id, # ID of the leave record
})
attachment_ids.append(attachment_record.id)
# Link the attachments to the leave record
if attachment_ids:
leave.supported_attachment_ids = [(6, 0, attachment_ids)]
leave._check_validity()
leave.state = 'confirm'
return {'status': 'success', 'leave_id': leave.id, 'message': ''}
except Exception as e:
return {'status': 'error','leave_id': '', 'message': str(e)}