From 2be841e8236e7171b13b26e3a299e7386639fc20 Mon Sep 17 00:00:00 2001 From: raman Date: Mon, 2 Jun 2025 14:52:30 +0530 Subject: [PATCH] weekly attendance auto mail --- .../weekly_attendance_report/__init__.py | 1 + .../weekly_attendance_report/__manifest__.py | 11 ++ .../models/__init__.py | 1 + .../models/attendance_report.py | 131 ++++++++++++++++++ .../security/ir.model.access.csv | 2 + 5 files changed, 146 insertions(+) create mode 100644 addons_extensions/weekly_attendance_report/__init__.py create mode 100644 addons_extensions/weekly_attendance_report/__manifest__.py create mode 100644 addons_extensions/weekly_attendance_report/models/__init__.py create mode 100644 addons_extensions/weekly_attendance_report/models/attendance_report.py create mode 100644 addons_extensions/weekly_attendance_report/security/ir.model.access.csv diff --git a/addons_extensions/weekly_attendance_report/__init__.py b/addons_extensions/weekly_attendance_report/__init__.py new file mode 100644 index 000000000..9a7e03ede --- /dev/null +++ b/addons_extensions/weekly_attendance_report/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/addons_extensions/weekly_attendance_report/__manifest__.py b/addons_extensions/weekly_attendance_report/__manifest__.py new file mode 100644 index 000000000..aaa9bcde8 --- /dev/null +++ b/addons_extensions/weekly_attendance_report/__manifest__.py @@ -0,0 +1,11 @@ +{ + 'name': 'Weekly Attendance Email Report', + 'version': '1.0', + 'category': 'Human Resources', + 'depends': ['hr_attendance', 'mail'], + 'data': [ + 'security/ir.model.access.csv', + ], + 'installable': True, + 'application': False, +} diff --git a/addons_extensions/weekly_attendance_report/models/__init__.py b/addons_extensions/weekly_attendance_report/models/__init__.py new file mode 100644 index 000000000..98cad3460 --- /dev/null +++ b/addons_extensions/weekly_attendance_report/models/__init__.py @@ -0,0 +1 @@ +from . import attendance_report \ No newline at end of file diff --git a/addons_extensions/weekly_attendance_report/models/attendance_report.py b/addons_extensions/weekly_attendance_report/models/attendance_report.py new file mode 100644 index 000000000..60026722d --- /dev/null +++ b/addons_extensions/weekly_attendance_report/models/attendance_report.py @@ -0,0 +1,131 @@ +from odoo import models, fields, api +from datetime import timedelta +import json +from collections import defaultdict +from datetime import datetime + + +class AttendanceWeeklyReport(models.Model): + _name = 'attendance.weekly.report' + _description = 'Weekly Attendance Report' + + def send_weekly_attendance_email(self): + management_emails = self.env['hr.employee'].search([ + ('department_id.name', '=', 'Administration'), + ('work_email', '!=', False) + ]).mapped('work_email') + + if not management_emails: + return + + today = fields.Date.context_today(self) + last_monday = today - timedelta(days=today.weekday() + 7) + last_sunday = last_monday + timedelta(days=6) + + attendances = self.env['hr.attendance'].search([ + ('check_in', '>=', str(last_monday)), + ('check_out', '<=', str(last_sunday + timedelta(days=1))) + ]) + + employee_data = {} + + employee_data = defaultdict(list) + grouped_attendance = defaultdict(lambda: defaultdict(list)) # {emp: {date: [attendances]}} + + for att in attendances: + emp = att.employee_id.name + date = att.check_in.date() + grouped_attendance[emp][date].append(att) + + for emp_name, dates in grouped_attendance.items(): + for date, records in dates.items(): + records = sorted(records, key=lambda a: a.check_in) + total_seconds = 0 + first_in = records[0].check_in.time().strftime('%H:%M') + last_out = 'N/A' + + for rec in records: + if rec.check_in and rec.check_out: + total_seconds += (rec.check_out - rec.check_in).total_seconds() + last_out = rec.check_out.time().strftime('%H:%M') + + employee_data[emp_name].append({ + 'date': date.strftime('%Y-%m-%d'), + 'in': first_in, + 'out': last_out, + 'hours': f'{total_seconds / 3600:.2f}', + }) + + # Inline QWeb-compatible HTML template (must be in a real view in production) + html_template = """ +
+

Dear Management,

+

+ Please find below the attendance summary for the period + %(from_date)s to %(to_date)s. +

+ + %(employee_tables)s + +

Regards,
Odoo HR System

+ For more details, visit ftprotech.in +
+ """ + + employee_tables_html = "" + if employee_data: + for emp_name, records in employee_data.items(): + rows = "" + total = 0 + for line in records: + total += float(line['hours']) if line['hours'] != False else 0 + rows += f""" + + {line['date']} + {line['in']} + {line['out']} + {line['hours']} + + """ + t =f""" + + + Total worked Hours {total:.2f} + + + """ + table = f""" +
+

{emp_name}

+ + + + + + + + + + {rows}{t} + +
DateCheck InCheck OutHours Worked
+
+ """ + employee_tables_html += table + else: + employee_tables_html = "

No attendance data available for this period.

" + + # Final HTML body + body_html = html_template % { + 'from_date': last_monday.strftime('%Y-%m-%d'), + 'to_date': last_sunday.strftime('%Y-%m-%d'), + 'employee_tables': employee_tables_html + } + + # Send email to all management emails + for email in management_emails: + self.env['mail.mail'].create({ + 'email_to': email, + 'subject': f"Weekly Attendance Report: {last_monday} to {last_sunday}", + 'body_html': body_html, + }).send() diff --git a/addons_extensions/weekly_attendance_report/security/ir.model.access.csv b/addons_extensions/weekly_attendance_report/security/ir.model.access.csv new file mode 100644 index 000000000..44a7ad01c --- /dev/null +++ b/addons_extensions/weekly_attendance_report/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id,perm_read,perm_write,perm_create,perm_unlink +access_attendance_weekly_report,access_attendance_weekly_report,model_attendance_weekly_report,,1,1,1,1