496 lines
28 KiB
Python
496 lines
28 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import division
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from odoo import models, fields, _, exceptions,api
|
|
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
|
|
|
|
|
|
class HrAttendanceReport(models.Model):
|
|
_name = 'hr.attendance.report'
|
|
_rec_name = 'date_from'
|
|
_order = 'write_date desc'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
|
|
date_from = fields.Date()
|
|
date_to = fields.Date()
|
|
line_ids = fields.One2many('hr.attendance.report.line', 'line_id')
|
|
state = fields.Selection(
|
|
[('draft', _('Draft')), ('generated', _('Generated')),
|
|
# ('reviewed', _('Reviewed')),
|
|
('confirmed', _('HR Manager Approval')),
|
|
('approved', _('Approved')), ('refused', _('Refused'))], default="draft")
|
|
calendar_ids = fields.Many2many('resource.calendar', string='Calendars')
|
|
name = fields.Char(string=_("Name"), required=True)
|
|
|
|
deduct_date_from = fields.Date()
|
|
deduct_date_to = fields.Date()
|
|
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.user.company_id)
|
|
department_ids = fields.Many2many('hr.department', string='Departments')
|
|
|
|
selected_employee_ids = fields.Many2many(
|
|
'hr.employee',
|
|
string=_("Employees in Report"),
|
|
domain="[('id', 'in', available_employee_ids)]" # تحديد النطاق
|
|
)
|
|
|
|
available_employee_ids = fields.Many2many(
|
|
'hr.employee',
|
|
compute='_compute_available_employees',
|
|
store=False
|
|
)
|
|
|
|
send_email = fields.Boolean(string=" Is Send Email", default=False,store=True)
|
|
|
|
|
|
|
|
@api.onchange('department_ids')
|
|
def _compute_available_employees(self):
|
|
for report in self:
|
|
if report.department_ids:
|
|
employees = self.env['hr.employee'].search([
|
|
('department_id', 'in', report.department_ids.ids),
|
|
('finger_print', '=', True),
|
|
('state', '=', 'open')
|
|
])
|
|
report.available_employee_ids = employees
|
|
else:
|
|
report.available_employee_ids = self.env['hr.employee'].browse([])
|
|
|
|
def unlink(self):
|
|
for rec in self:
|
|
if rec.state != 'draft':
|
|
raise exceptions.UserError(_('You can not delete record in state not in draft'))
|
|
return super(HrAttendanceReport, self).unlink()
|
|
|
|
def draft_state(self):
|
|
self.state = "draft"
|
|
|
|
def reviewed(self):
|
|
self.state = "reviewed"
|
|
|
|
def confirmed(self):
|
|
self.state = "confirmed"
|
|
|
|
def set_to_draft(self):
|
|
for line in self.line_ids:
|
|
if line.advantage_id:
|
|
line.advantage_id.draft()
|
|
line.advantage_id.unlink()
|
|
self.line_ids.unlink()
|
|
# self.write({'line_ids': [fields.Command.clear()]})
|
|
self.state = "draft"
|
|
|
|
def approved(self):
|
|
for line in self.line_ids:
|
|
employee_contract = line.env['hr.contract'].search([('employee_id', '=', line.employee_name.id),
|
|
('state', '=', 'program_directory')])
|
|
if employee_contract and line.employee_name.finger_print:
|
|
advantage_arc = line.env['contract.advantage'].create({
|
|
'benefits_discounts': line.employee_name.resource_calendar_id.deduction_rule.id,
|
|
'type': 'customize',
|
|
'date_from': self.deduct_date_from,
|
|
'date_to': self.deduct_date_to,
|
|
'amount': line.total_deduction,
|
|
'employee_id': line.employee_name.id,
|
|
'contract_advantage_id': line.employee_name.contract_id.id,
|
|
'out_rule': True,
|
|
'state': 'confirm',
|
|
'comments': 'Absence Deduction'})
|
|
line.advantage_id = advantage_arc.id
|
|
|
|
self.state = "approved"
|
|
|
|
def refused(self):
|
|
for line in self.line_ids:
|
|
line.advantage_id.draft()
|
|
line.advantage_id.unlink()
|
|
self.state = "refused"
|
|
|
|
def calcualte_flexible_transaction(self, transactions):
|
|
planed_hours = sum(transactions.filtered(lambda t: t.public_holiday == False).mapped('plan_hours'))
|
|
office_hours = sum(transactions.mapped('office_hours'))
|
|
permission_hours = sum(transactions.filtered(
|
|
lambda t: t.personal_permission_id != False).mapped('total_permission_hours'))
|
|
mission_hours = sum(transactions.filtered(
|
|
lambda t: t.official_id != False
|
|
and t.official_id.mission_type.duration_type == 'hours').mapped('total_mission_hours'))
|
|
mission_by_days_hours = sum(transactions.filtered(
|
|
lambda t: t.official_id != False
|
|
and t.official_id.mission_type.duration_type == 'days').mapped('total_mission_hours'))
|
|
absent_hours = sum(transactions.filtered(lambda t: t.is_absent).mapped('plan_hours'))
|
|
actual_absent_days = len(transactions.filtered(lambda t: t.is_absent))
|
|
total_permission = sum(transactions.filtered(lambda t: t.approve_personal_permission).mapped('total_permission_hours'))
|
|
|
|
leave_hours = sum(transactions.filtered(lambda t: t.normal_leave == True).mapped('total_leave_hours'))
|
|
working_hours = office_hours + permission_hours + mission_hours + mission_by_days_hours + leave_hours
|
|
missed_hours = planed_hours - working_hours
|
|
|
|
|
|
missing_punch_transactions = transactions.filtered(
|
|
lambda t: (
|
|
not t.public_holiday and
|
|
not t.normal_leave and
|
|
(
|
|
(t.sign_in and not t.sign_out) or
|
|
(not t.sign_in and t.sign_out)
|
|
)
|
|
)
|
|
)
|
|
|
|
missing_punch_hours = sum([
|
|
t.plan_hours - t.office_hours if t.plan_hours > t.office_hours else 0.0
|
|
for t in missing_punch_transactions
|
|
])
|
|
|
|
if missed_hours < 0:
|
|
missed_hours = 0
|
|
|
|
early_exit_hours = sum(transactions.filtered(
|
|
lambda t: t.approve_exit_out).mapped('early_exit'))
|
|
|
|
lateness_hours = sum(transactions.filtered(
|
|
lambda t: t.approve_lateness).mapped('lateness'))
|
|
|
|
break_hours = sum(transactions.filtered(
|
|
lambda t: t.break_duration and t.break_duration > 0).mapped('break_duration'))
|
|
|
|
return {'leaves': leave_hours, 'missed_hours': missed_hours, 'mission_by_days': mission_by_days_hours, 'additional_hours': 0.0,'actual_absent_hours': absent_hours,'actual_absent_days':actual_absent_days,'total_permission_hours':total_permission,'missing_punch_hours':missing_punch_hours,'total_lateness':lateness_hours,'total_early_exit':early_exit_hours,'total_break_duration':break_hours}
|
|
|
|
def generate_report(self):
|
|
transaction_values = {}
|
|
item_list, mixed_calendar_emps = [], []
|
|
module = self.env['ir.module.module'].sudo()
|
|
official_mission_module = module.search([('state', '=', 'installed'), ('name', '=', 'exp_official_mission')])
|
|
personal_permission_module = module.search([('state', '=', 'installed'), ('name', '=', 'employee_requests')])
|
|
holidays_module = module.search([('state', '=', 'installed'), ('name', '=', 'hr_holidays_public')])
|
|
transaction_pool = self.env['hr.attendance.transaction']
|
|
reason_pool = self.env['hr.reasons.lateness']
|
|
emps = self.selected_employee_ids
|
|
if not emps:
|
|
domain = self._context.get('emp_id') and [('id', '=', self._context['emp_id'])] or []
|
|
domain += [('finger_print', '=', True)]
|
|
if self.department_ids:
|
|
domain += [('department_id', 'in', self.department_ids.ids), ('state', '=', 'open')]
|
|
emps = self.env['hr.employee'].search(domain)
|
|
trans_domain = [('date', '>=', self.date_from), ('date', '<=', self.date_to), ('attending_type', '=', 'in_cal'),('sequence','=',1)]
|
|
if self.calendar_ids: trans_domain += [('calendar_id', 'in', self.calendar_ids.ids)]
|
|
for employee in emps:
|
|
missed_hours, wasted_hours, absent, total_mission, leaves, hours_per_day, count, \
|
|
additional_hours,actual_absent_days,actual_absent_hours,total_permission_hours,missing_punch_hours,lateness_hours,early_exit_hours,break_hours = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0,0,0
|
|
emp_trans_dom = trans_domain.copy() + [('employee_id', '=', employee.id)]
|
|
attendance_transaction = transaction_pool.search(emp_trans_dom)
|
|
if len(attendance_transaction.mapped('calendar_id')) > 1:
|
|
mixed_calendar_emps.append(employee.id)
|
|
continue
|
|
else:
|
|
emp_calendar = attendance_transaction and attendance_transaction[0].calendar_id\
|
|
or employee.resource_calendar_id
|
|
if emp_calendar.is_flexible:
|
|
flexible_trans = attendance_transaction.filtered(lambda t: t.public_holiday == False)
|
|
no_of_days = len(set(flexible_trans.mapped('date')))
|
|
flexible_days = emp_calendar.number_of_flexi_days
|
|
if no_of_days >= flexible_days:
|
|
ord_trans_dates = sorted(set(flexible_trans.mapped('date')))
|
|
index = len(ord_trans_dates) > flexible_days and flexible_days - 1 or len(ord_trans_dates) - 1
|
|
df = fields.Date.from_string(self.date_from)
|
|
while no_of_days >= flexible_days:
|
|
dt = ord_trans_dates[index]
|
|
current_trans = attendance_transaction.filtered(lambda t: df <= t.date <= dt)
|
|
hours_dict = self.calcualte_flexible_transaction(current_trans)
|
|
actual_absent_hours = hours_dict.get('actual_absent_hours', 0.0)
|
|
actual_absent_days = hours_dict.get('actual_absent_days', 0.0)
|
|
total_permission_hours =hours_dict.get('total_permission_hours', 0.0)
|
|
missing_punch_hours = hours_dict.get('missing_punch_hours', 0.0)
|
|
break_hours = hours_dict.get('break_hours', 0.0)
|
|
early_exit_hours = hours_dict.get('early_exit_hours', 0.0)
|
|
lateness_hours = hours_dict.get('lateness_hours', 0.0)
|
|
|
|
total_mission += hours_dict['mission_by_days']
|
|
missed_hours += hours_dict['missed_hours']
|
|
leaves += hours_dict['leaves']
|
|
additional_hours += hours_dict['additional_hours']
|
|
df = fields.Date.from_string(dt) + timedelta(1)
|
|
index = index + flexible_days > len(ord_trans_dates) and len(ord_trans_dates) or index + flexible_days
|
|
no_of_days -= flexible_days
|
|
else:
|
|
if no_of_days and no_of_days < flexible_days:
|
|
current_trans = attendance_transaction.filtered(lambda t: df <= t.date <= self.date_to)
|
|
hours_dict = self.calcualte_flexible_transaction(current_trans)
|
|
actual_absent_hours = hours_dict.get('actual_absent_hours', 0.0)
|
|
actual_absent_days = hours_dict.get('actual_absent_days', 0.0)
|
|
break_hours = hours_dict.get('break_hours', 0.0)
|
|
early_exit_hours = hours_dict.get('early_exit_hours', 0.0)
|
|
lateness_hours = hours_dict.get('lateness_hours', 0.0)
|
|
total_permission_hours = hours_dict.get('total_permission_hours', 0.0)
|
|
missing_punch_hours = hours_dict.get('missing_punch_hours', 0.0)
|
|
total_mission += hours_dict['mission_by_days']
|
|
missed_hours += hours_dict['missed_hours']
|
|
leaves += hours_dict['leaves']
|
|
additional_hours += hours_dict['additional_hours']
|
|
else:
|
|
hours_dict = self.calcualte_flexible_transaction(attendance_transaction)
|
|
missed_hours = hours_dict['missed_hours']
|
|
actual_absent_hours = hours_dict.get('actual_absent_hours', 0.0)
|
|
actual_absent_days = hours_dict.get('actual_absent_days', 0.0)
|
|
break_hours = hours_dict.get('break_hours', 0.0)
|
|
early_exit_hours = hours_dict.get('early_exit_hours', 0.0)
|
|
lateness_hours = hours_dict.get('lateness_hours', 0.0)
|
|
total_permission_hours = hours_dict.get('total_permission_hours', 0.0)
|
|
leaves, total_mission = hours_dict['leaves'], hours_dict['mission_by_days']
|
|
working_hours_flexible_days = emp_calendar.total_flexible_hours
|
|
values = {
|
|
'employee_name': employee.id,
|
|
'delay': 0.0,
|
|
'leave': leaves,
|
|
'additional_hours': 0.0,
|
|
'exist_hours': 0.0,
|
|
'extra_break_duration': 0.0,
|
|
'absent': actual_absent_hours + missing_punch_hours + break_hours + early_exit_hours + lateness_hours ,
|
|
'mission_by_days': total_mission,
|
|
'absent_days_by_hr': 0.0,
|
|
'total_hours': missed_hours,
|
|
'dummy_field': missed_hours,
|
|
'actual_absent_hours': actual_absent_hours,
|
|
'actual_absent_days': actual_absent_days,
|
|
'total_permission_hours':total_permission_hours,
|
|
'missing_punch_hours':missing_punch_hours ,
|
|
'total_amount': employee.contract_id.total_allowance,
|
|
'amount_per_hour': employee.contract_id.total_allowance / working_hours_flexible_days,
|
|
'total_deduction': ((missed_hours+ missing_punch_hours) * (
|
|
employee.contract_id.total_allowance / working_hours_flexible_days))
|
|
}
|
|
item_list.append(values)
|
|
elif not emp_calendar.is_flexible:
|
|
emp_trans = attendance_transaction.filtered(lambda t: t.public_holiday == False)
|
|
for attendance in emp_trans:
|
|
lateness, early_exist, extra_break_duration, hours, additional_hours,missing_punch_hours = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
|
|
total_permission, total_mission_by_hour, total_mission_by_day, total_leaves,total_permission_hours = 0.0, 0.0, 0.0, 0.0,0.0
|
|
total_absent, lateness_hours_by_hr, get_total_amount,actual_absent_hours,actual_absent_days = 0.0, 0.0, 0.0,0.0,0.0
|
|
transaction_values['id'], transaction_values['name'] = attendance.employee_id.id, attendance.employee_id.name
|
|
total_hours_for_two_shifts = emp_calendar.shift_one_working_hours + \
|
|
emp_calendar.shift_two_working_hours
|
|
lateness_reasons = reason_pool.search([('latest_date', '=', attendance.date),
|
|
('employee_id', '=', employee.id),
|
|
('state', '=', 'hr_manager')])
|
|
# if lateness_reasons:
|
|
# if attendance.lateness > 0.0 or attendance.early_exit > 0.0:
|
|
# for late in lateness_reasons:
|
|
# if attendance.date == late.latest_date:
|
|
# lateness_hours_by_hr += (attendance.lateness + attendance.early_exit)
|
|
if attendance.approve_lateness:
|
|
lateness += attendance.lateness
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += attendance.lateness
|
|
if attendance.approve_exit_out:
|
|
early_exist += attendance.early_exit
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += attendance.early_exit
|
|
if personal_permission_module and attendance.approve_personal_permission:
|
|
total_permission += attendance.total_permission_hours
|
|
total_permission_hours+=attendance.total_permission_hours
|
|
if official_mission_module and attendance.is_official:
|
|
if attendance.official_id.mission_type.duration_type == 'days':
|
|
total_mission_by_day += attendance.total_mission_hours
|
|
else:
|
|
total_mission_by_hour += attendance.total_mission_hours
|
|
if holidays_module and attendance.normal_leave:
|
|
total_leaves += attendance.total_leave_hours
|
|
hours += attendance.official_hours
|
|
extra_break_duration += attendance.break_duration
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += attendance.break_duration
|
|
additional_hours += attendance.additional_hours
|
|
|
|
if (
|
|
not attendance.public_holiday and
|
|
not attendance.normal_leave and
|
|
(
|
|
(attendance.sign_in and not attendance.sign_out) or
|
|
(not attendance.sign_in and attendance.sign_out)
|
|
)
|
|
):
|
|
missing_punch_hours = (
|
|
attendance.plan_hours - attendance.official_hours
|
|
if attendance.plan_hours > attendance.official_hours
|
|
else 0.0
|
|
)
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += missing_punch_hours
|
|
|
|
if attendance.is_absent:
|
|
actual_absent_hours +=attendance.plan_hours
|
|
actual_absent_days +=1
|
|
total_absent += attendance.plan_hours
|
|
if attendance.calendar_id.is_full_day:
|
|
total_absent += attendance.calendar_id.break_duration
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += attendance.plan_hours + attendance.calendar_id.break_duration
|
|
elif attendance.sequence == 1:
|
|
total_absent += attendance.calendar_id.shift_one_break_duration
|
|
if lateness_reasons:
|
|
lateness_hours_by_hr += attendance.plan_hours + attendance.calendar_id.shift_one_break_duration
|
|
elif attendance.sequence == 2:
|
|
total_absent += attendance.calendar_id.shift_two_break_duration
|
|
else:
|
|
working_hours = total_permission + total_mission_by_hour + hours + attendance.carried_hours
|
|
absence_hours = attendance.plan_hours - working_hours
|
|
total_absent += absence_hours > 0 and absence_hours or 0
|
|
if total_absent == 0:
|
|
get_total_hours = (
|
|
lateness + early_exist + extra_break_duration + total_absent) - lateness_hours_by_hr
|
|
else:
|
|
get_total_hours = (total_absent - lateness_hours_by_hr)
|
|
if get_total_hours < 0:
|
|
get_total_hours = 0
|
|
if attendance.employee_id.contract_id.state == 'program_directory':
|
|
get_total_amount = attendance.employee_id.contract_id.total_allowance
|
|
if emp_calendar.is_full_day:
|
|
working_hours_per_week = emp_calendar.working_hours * emp_calendar.working_days
|
|
if working_hours_per_week != 0:
|
|
get_amount_per_hour = get_total_amount / working_hours_per_week
|
|
else:
|
|
get_amount_per_hour = 0
|
|
else:
|
|
get_amount_per_hour = get_total_amount / (
|
|
total_hours_for_two_shifts * emp_calendar.working_days)
|
|
values = {
|
|
'employee_name': attendance.employee_id.id,
|
|
'delay': lateness,
|
|
'leave': total_leaves,
|
|
'exist_hours': early_exist,
|
|
'extra_break_duration': extra_break_duration,
|
|
'absent': actual_absent_hours + missing_punch_hours + lateness + early_exist + extra_break_duration,
|
|
'mission_by_days': total_mission_by_day,
|
|
'absent_days_by_hr': lateness_hours_by_hr,
|
|
'total_hours': get_total_hours,
|
|
'dummy_field': get_total_hours,
|
|
'total_amount': get_total_amount,
|
|
'amount_per_hour': get_amount_per_hour,
|
|
'total_deduction': (get_total_hours)* get_amount_per_hour,
|
|
'additional_hours': additional_hours,
|
|
'actual_absent_hours':actual_absent_hours,
|
|
'total_permission_hours':total_permission_hours,
|
|
'missing_punch_hours':missing_punch_hours,
|
|
'actual_absent_days': actual_absent_days,
|
|
}
|
|
item_list.append(values)
|
|
from itertools import groupby, tee
|
|
from operator import itemgetter
|
|
grouper = itemgetter("employee_name")
|
|
result = []
|
|
for key, grp in groupby(sorted(item_list, key=grouper), grouper):
|
|
if not isinstance(key, tuple):
|
|
key = [key]
|
|
temp_dict = dict(zip(["employee_name"], key))
|
|
grp1, grp2, grp3, grp4, grp5, grp6, grp7, grp8, grp9, grp10, grp11, grp12, grp13, grp14, grp15,grp16,grp17,grp18,grp19 = tee(grp, 19)
|
|
temp_dict["actual_absent_hours"] = sum(item.get("actual_absent_hours", 0.0) for item in grp16)
|
|
temp_dict["actual_absent_days"] = sum(item.get("actual_absent_days", 0.0) for item in grp19)
|
|
temp_dict["total_permission_hours"] = sum(item.get("total_permission_hours", 0.0) for item in grp17)
|
|
temp_dict["missing_punch_hours"] = sum(item.get("missing_punch_hours", 0.0) for item in grp18)
|
|
|
|
temp_dict["delay"] = sum(item["delay"] for item in grp1)
|
|
temp_dict["leave"] = sum(item1["leave"] for item1 in grp2)
|
|
temp_dict["mission_by_days"] = sum(item1["mission_by_days"] for item1 in grp14)
|
|
temp_dict["absent"] = sum(item1["absent"] for item1 in grp3)
|
|
temp_dict["exist_hours"] = sum(item1["exist_hours"] for item1 in grp4)
|
|
temp_dict["extra_break_duration"] = sum(item1["extra_break_duration"] for item1 in grp5)
|
|
temp_dict["absent_days_by_hr"] = sum(item1["absent_days_by_hr"] for item1 in grp6)
|
|
temp_dict["total_hours"] = sum(item["total_hours"] for item in grp7) - (
|
|
temp_dict["leave"] + temp_dict["mission_by_days"])
|
|
temp_dict["dummy_field"] = sum(item["dummy_field"] for item in grp13)
|
|
temp_dict["total_amount"] = sum(item["total_amount"] for item in grp8) / len(list(grp9))
|
|
temp_dict["amount_per_hour"] = sum(item["amount_per_hour"] for item in grp10) / len(list(grp11))
|
|
|
|
############# re chick total_deduction
|
|
|
|
temp_dict["total_deduction"] = temp_dict["total_hours"]*temp_dict["amount_per_hour"]
|
|
#temp_dict["total_deduction"] = sum(item["total_deduction"] for item in grp12)
|
|
temp_dict["additional_hours"] = sum(item["additional_hours"] for item in grp15)
|
|
result.append(temp_dict)
|
|
self.write({'line_ids': [(0, 0, val) for val in result]})
|
|
self.state = "generated"
|
|
if mixed_calendar_emps:
|
|
self.manage_mixed_calendar(mixed_calendar_emps)
|
|
|
|
def manage_mixed_calendar(self, emp_calendars):
|
|
for emp in emp_calendars:
|
|
trans = self.env['hr.attendance.transaction'].search([('date', '>=', self.date_from),
|
|
('date', '<=', self.date_to),
|
|
('employee_id', '=', emp)])
|
|
calendar_ids = trans.mapped('calendar_id').ids
|
|
recs = self.env['hr.attendance.report']
|
|
for cal in calendar_ids:
|
|
tdates = list(set(trans.filtered(lambda l: l.calendar_id.id == cal).mapped('date')))
|
|
tdates.sort()
|
|
ldate = fields.Date.from_string(tdates[0]) + timedelta(len(tdates) - 1)
|
|
if ldate == fields.Date.from_string(tdates[-1]):
|
|
rec = self.create({'date_from': tdates[0], 'date_to': tdates[-1]})
|
|
rec.with_context(emp_id=emp).generate_report()
|
|
recs += rec
|
|
else:
|
|
ranges, date_range, base = [], [], tdates.pop(0)
|
|
date_range.append(base)
|
|
bdate = fields.Date.from_string(base) + timedelta(1)
|
|
for dt in tdates:
|
|
if bdate == fields.Date.from_string(dt):
|
|
date_range.append(dt)
|
|
bdate += timedelta(1)
|
|
if dt == tdates[-1]:
|
|
ranges.append(date_range)
|
|
else:
|
|
ranges.append(date_range)
|
|
date_range, bdate = [dt], fields.Date.from_string(dt) + timedelta(1)
|
|
for range in ranges:
|
|
rec = self.create({'date_from': range[0], 'date_to': range[-1]})
|
|
rec.with_context(emp_id=emp).generate_report()
|
|
recs += rec
|
|
main_rec = recs[0]
|
|
sum_recs = recs.filtered(lambda r: r.id != main_rec.id)
|
|
sum_line = main_rec.line_ids[0]
|
|
sum_line.write({
|
|
'line_id': self.id,
|
|
'delay': sum_line.delay + sum(sum_recs.mapped('line_ids.delay')),
|
|
'leave': sum_line.leave + sum(sum_recs.mapped('line_ids.leave')),
|
|
'absent': sum_line.absent + sum(sum_recs.mapped('line_ids.absent')),
|
|
'exist_hours': sum_line.exists + sum(sum_recs.mapped('line_ids.exist_hours')),
|
|
'total_hours': sum_line.total_hours + sum(sum_recs.mapped('line_ids.total_hours')),
|
|
'dummy_field': sum_line.dummy_field + sum(sum_recs.mapped('line_ids.dummy_field')),
|
|
'total_deduction': sum_line.total_deduction + sum(sum_recs.mapped('line_ids.total_deduction')),
|
|
'absent_days_by_hr': sum_line.absent_days_by_hr + sum(sum_recs.mapped('line_ids.absent_days_by_hr')),
|
|
'mission_by_days': sum_line.mission_by_days + sum(sum_recs.mapped('line_ids.mission_by_days')),
|
|
'extra_break_duration': sum_line.extra_break_duration + sum(
|
|
sum_recs.mapped('line_ids.extra_break_duration')),
|
|
'additional_hours': sum_line.additional_hours + sum(sum_recs.mapped('line_ids.additional_hours')),
|
|
})
|
|
|
|
recs.unlink()
|
|
def _get_email_template(self):
|
|
return self.env.ref('attendances.emapproval_line')
|
|
|
|
def action_send_email(self):
|
|
template = self._get_email_template()
|
|
sent_count = 0
|
|
for line in self.line_ids:
|
|
if (
|
|
not line.employee_name or
|
|
not line.employee_name.work_email or
|
|
line.total_deduction <= 0
|
|
):
|
|
continue
|
|
|
|
template.with_context(
|
|
email_to=line.employee_name.work_email,
|
|
employee_name=line.employee_name.name,
|
|
default_model='hr.attendance.report.line',
|
|
default_res_id=line.id,
|
|
).send_mail(line.id, force_send=True)
|
|
|
|
sent_count += 1
|
|
|
|
self.send_email = True
|
|
return sent_count
|
|
|
|
|