new report for employee attendance
This commit is contained in:
parent
44f17a8f52
commit
0b0de1f3d9
File diff suppressed because it is too large
Load Diff
|
|
@ -323,6 +323,67 @@
|
|||
|
||||
|
||||
</template>
|
||||
<template id="totals_only_attendance_report_template">
|
||||
<div class="page" style="font-size:12pt" dir="rtl">
|
||||
<center>
|
||||
<h2 style="font-weight:bold">تقرير الحضور والانصراف للموظفين</h2>
|
||||
</center>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h4 style="font-weight:bold">من تاريخ</h4>
|
||||
<t t-esc="date_start"/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h4 style="font-weight:bold">إلى</h4>
|
||||
<t t-esc="date_end"/>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-condensed" style="width:100%">
|
||||
<thead style="width:100%;">
|
||||
<tr style="width:100%;text-align:center;">
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الرقم الوظيفي</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:10%;text-align:center;">اسم الموظف</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:10%;text-align:center;">رقم الهوية</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:10%;text-align:center;">اﻹدارة</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:10%;text-align:center;">المسمي الوظيفي</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">ايام الحضور</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الاجازات</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الاجازات الرسمية</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الغياب</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">ساعات العمل الفعلية</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">ساعات العمل الاضافية</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الاستئذان</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">مهام عمل/انتداب/تدريب</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">التأخيرات</th>
|
||||
<th tyle="border: 1px solid gray; padding: 1px; font-size:0.8em;background-color: #b9d7d4;color: black;width:6%;text-align:center;">الخروج المبكر</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="summary" t-as="row">
|
||||
<tr style="text-align:center;font-weight:bold;background-color: #b9d7d4">
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['employee_number']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:10%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['name']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:10%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['iqama']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:10%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['department']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:10%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['job']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['days_present']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['leave_days']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['holiday_days']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['absent_days']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['office_hours']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['extra_hours']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['permission_hours']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['mission_hours']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['lateness_approved']"/>
|
||||
<td style="border: 1px solid gray;padding: 1px; width:6%;font-size:0.8em;background-color: white;color: black; text-align:center" t-esc="row['early_exit_approved']"/>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="general_attendances_report_temp">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
|
|
@ -336,6 +397,10 @@
|
|||
font-family: ae_AlMohanad;
|
||||
}
|
||||
</style>
|
||||
<t t-if="totals_only">
|
||||
<t t-call="attendances.totals_only_attendance_report_template"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-if="type == 'late'">
|
||||
<t t-call="attendances.late_attendance_report_template"/>
|
||||
</t>
|
||||
|
|
@ -347,6 +412,7 @@
|
|||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<record id="general_attendance_action_report" model="ir.actions.report">
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
</group>
|
||||
<group>
|
||||
<field name="to_date"/>
|
||||
<!-- <field name="employee_ids" widget="many2many_tags"/>-->
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="print_totals_only"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Employees" >
|
||||
<field name="employee_ids" nolabel="1" required="1">
|
||||
|
|
|
|||
|
|
@ -1,62 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import collections
|
||||
import datetime
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
import pytz
|
||||
from pytz import timezone
|
||||
import collections
|
||||
import datetime
|
||||
from odoo import fields, models, _,api
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
WEEK_DAYS_AR = {
|
||||
0: "الاثنين",
|
||||
1: "الثلاثاء",
|
||||
2: "الاربعاء",
|
||||
3: "الخميس",
|
||||
4: "الجمعة",
|
||||
5: "السبت",
|
||||
6: "الاحد",
|
||||
}
|
||||
|
||||
def hhmm(val):
|
||||
if not val:
|
||||
return "00:00"
|
||||
mins = float(val) * 60
|
||||
return "{0:02.0f}:{1:02.0f}".format(*divmod(mins, 60))
|
||||
|
||||
week_dayS_arabic={0:"الاثنين", 1: 'الثلاثاء', 4:'الجمعة' , 2:'الاربعاء',3: 'الخميس', 6:'الاحد',5: 'السبت'}
|
||||
class AttendancesReport(models.TransientModel):
|
||||
_name = "employee.attendance.report"
|
||||
_description = "Employee Attendance Report"
|
||||
|
||||
from_date = fields.Date(string='From Date', required=True)
|
||||
to_date = fields.Date(string='To Date', required=True)
|
||||
employee_ids = fields.Many2many(comodel_name='hr.employee', string='Employees' ,required=True)
|
||||
resource_calender_id = fields.Many2one(comodel_name='resource.calendar', string='Employee work record')
|
||||
type = fields.Selection(selection=[('late', 'Late and Early exit'), ('absent', 'Absent'), ('employee', 'Employee')],
|
||||
required=True,
|
||||
default='late', string='Type')
|
||||
from_date = fields.Date(required=True)
|
||||
to_date = fields.Date(required=True)
|
||||
employee_ids = fields.Many2many("hr.employee", string="Employees", required=True)
|
||||
resource_calender_id = fields.Many2one("resource.calendar", string="Employee work record")
|
||||
type = fields.Selection([
|
||||
("late", "Late and Early exit"),
|
||||
("absent", "Absent"),
|
||||
("employee", "Employee"),
|
||||
], default="late", required=True)
|
||||
print_totals_only = fields.Boolean(string="Totals only (one line per employee)", default=False)
|
||||
|
||||
def _payload(self):
|
||||
return {
|
||||
"ids": self.ids,
|
||||
"model": self._name,
|
||||
"form": {
|
||||
"resource_calender_id": self.resource_calender_id.id,
|
||||
"from_date": self.from_date,
|
||||
"to_date": self.to_date,
|
||||
"employee_ids": self.employee_ids.ids,
|
||||
"type": self.type,
|
||||
"print_totals_only": self.print_totals_only,
|
||||
},
|
||||
}
|
||||
|
||||
def print_report(self):
|
||||
if not self.employee_ids:
|
||||
raise ValidationError(_("Please select Employees Name"))
|
||||
data = {
|
||||
'ids': self.ids,
|
||||
'model': self._name,
|
||||
'form': {
|
||||
'resource_calender_id': self.resource_calender_id.id,
|
||||
'from_date': self.from_date,
|
||||
'to_date': self.to_date,
|
||||
'employee_ids': self.employee_ids.ids,
|
||||
'type': self.type,
|
||||
},
|
||||
}
|
||||
return self.env.ref('attendances.general_attendance_action_report').report_action(self, data=data)
|
||||
return self.env.ref("attendances.general_attendance_action_report").report_action(self, data=self._payload())
|
||||
|
||||
def print_excel_report(self):
|
||||
data = {
|
||||
'ids': self.ids,
|
||||
'model': self._name,
|
||||
'form': {
|
||||
'resource_calender_id': self.resource_calender_id.id,
|
||||
'from_date': self.from_date,
|
||||
'to_date': self.to_date,
|
||||
'employee_ids': self.employee_ids.ids,
|
||||
'type': self.type,
|
||||
},
|
||||
}
|
||||
return self.env.ref('attendances.general_attendance_action_xls').report_action(self, data=data, config=False)
|
||||
|
||||
return self.env.ref("attendances.general_attendance_action_xls").report_action(self, data=self._payload(), config=False)
|
||||
|
||||
class ReportAttendancePublic(models.AbstractModel):
|
||||
_name = 'report.attendances.general_attendances_report_temp'
|
||||
_name = "report.attendances.general_attendances_report_temp"
|
||||
_description = "General Attendances Report"
|
||||
|
||||
def get_value(self, data):
|
||||
type = data['form']['type']
|
||||
totals_only = data["form"].get("print_totals_only", False)
|
||||
employee_ids = data['form']['employee_ids']
|
||||
resource_calender_id = data['form']['resource_calender_id']
|
||||
from_date = data['form']['from_date']
|
||||
|
|
@ -109,7 +118,7 @@ class ReportAttendancePublic(models.AbstractModel):
|
|||
|
||||
data.append({
|
||||
'date': resource.date,
|
||||
'day': week_dayS_arabic[resource.date.weekday()],
|
||||
'day': WEEK_DAYS_AR[resource.date.weekday()],
|
||||
'sig_in': resource.sign_in,
|
||||
'sig_out': resource.sign_out,
|
||||
'lateness': resource.lateness,
|
||||
|
|
@ -145,7 +154,9 @@ class ReportAttendancePublic(models.AbstractModel):
|
|||
total_not_sig_out = len(list_not_log_out)
|
||||
total_leave = len(list_leave)
|
||||
total_dic[emp] = {'total_lateness': total_lateness, 'total_early_exit': total_early_exit,
|
||||
"total_extra_hours":total_extra_hours, "total_late_early":total_late_early,"total_leave":total_leave,'total_absent': total_absent, 'total_not_sig_in': total_not_sig_in,
|
||||
"total_extra_hours": total_extra_hours, "total_late_early": total_late_early,
|
||||
"total_leave": total_leave, 'total_absent': total_absent,
|
||||
'total_not_sig_in': total_not_sig_in,
|
||||
'total_not_sig_out': total_not_sig_out}
|
||||
grouped = collections.defaultdict(list)
|
||||
for item in data:
|
||||
|
|
@ -196,6 +207,41 @@ class ReportAttendancePublic(models.AbstractModel):
|
|||
self.env.user.tz or 'GMT')
|
||||
print_date = datetime.datetime.now(timezone('UTC'))
|
||||
print_date = print_date.astimezone(local_tz)
|
||||
totals_only = data['form'].get('print_totals_only', False)
|
||||
|
||||
summary_rows = []
|
||||
if totals_only:
|
||||
domain = [('date', '>=', start_date), ('date', '<=', end_date)]
|
||||
emp_ids = data['form']['employee_ids']
|
||||
cal_id = data['form']['resource_calender_id']
|
||||
if emp_ids:
|
||||
domain.append(('employee_id', 'in', list(set(emp_ids))))
|
||||
elif cal_id:
|
||||
rc = self.env['resource.calendar'].browse(cal_id)
|
||||
domain.append(('employee_id', 'in', rc.employee_ids.ids))
|
||||
att = self.env['hr.attendance.transaction'].search(domain)
|
||||
for emp in att.mapped('employee_id'):
|
||||
lines = att.filtered(lambda l, e=emp: l.employee_id == e)
|
||||
iq = getattr(emp, 'iqama_number', False) or getattr(emp, 'saudi_number', '')
|
||||
summary_rows.append({
|
||||
'employee_number': emp.emp_no or '',
|
||||
'name': emp.name,
|
||||
'iqama':iq.display_name or '',
|
||||
'department': emp.department_id.name,
|
||||
'job': emp.sudo().job_id.name,
|
||||
'days_present': len({l.date for l in lines if not l.is_absent}),
|
||||
'leave_days': len(lines.filtered(lambda l: l.normal_leave)),
|
||||
'holiday_days': len(lines.filtered(lambda l: l.public_holiday)),
|
||||
'absent_days': len(lines.filtered(lambda l: l.is_absent)),
|
||||
'office_hours': hhmm(sum(lines.mapped('office_hours'))),
|
||||
'extra_hours': hhmm(sum(lines.mapped('additional_hours'))),
|
||||
'permission_hours': hhmm(sum(lines.mapped('total_permission_hours'))),
|
||||
'mission_hours': hhmm(sum(lines.mapped('total_mission_hours'))),
|
||||
'lateness_approved': hhmm(sum(lines.filtered(lambda l: l.approve_lateness).mapped('lateness'))),
|
||||
'early_exit_approved': hhmm(sum(lines.filtered(lambda l: l.approve_exit_out).mapped('early_exit'))),
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
'doc_ids': data['ids'],
|
||||
'doc_model': data['model'],
|
||||
|
|
@ -206,12 +252,13 @@ class ReportAttendancePublic(models.AbstractModel):
|
|||
'mykey': mykey,
|
||||
'emp_data': emp_data,
|
||||
'total': total,
|
||||
'summary': summary_rows,
|
||||
'totals_only': totals_only,
|
||||
'print_date': print_date.strftime("%H:%m %m/%d/%Y"),
|
||||
'print_user': self.env.user.name
|
||||
|
||||
}
|
||||
|
||||
|
||||
class AttendancesReportXls(models.AbstractModel):
|
||||
_name = 'report.attendances.general_attendance_xls'
|
||||
_inherit = 'report.report_xlsx.abstract'
|
||||
|
|
@ -223,15 +270,81 @@ class AttendancesReportXls(models.AbstractModel):
|
|||
start_date = data['form']['from_date']
|
||||
end_date = data['form']['to_date']
|
||||
type = data['form']['type']
|
||||
totals_only = data['form'].get('print_totals_only', False)
|
||||
sheet = workbook.add_worksheet(U'Holiday Report')
|
||||
calendar_id = data['form']['resource_calender_id']
|
||||
sheet.right_to_left()
|
||||
sheet.set_column(1, 10, 15)
|
||||
# sheet.set_column(6, 100, 25)
|
||||
employee_ids = data['form']['employee_ids']
|
||||
format2 = workbook.add_format(
|
||||
{'font_size': 10, 'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center',
|
||||
'bold': True})
|
||||
format2.set_align('center')
|
||||
format2.set_align('vcenter')
|
||||
fmt = workbook.add_format({'font_size': 10, 'border': 1, 'align': 'center', 'valign': 'vcenter', 'bold': True})
|
||||
|
||||
if totals_only:
|
||||
sheet.merge_range('F2:P2', _('تقرير الحضور والانصراف للموظفين'), fmt)
|
||||
sheet.write('G3', _('من تاريخ'), fmt)
|
||||
sheet.write('J3', _('إلى تاريخ'), fmt)
|
||||
sheet.write(2, 7, str(start_date)[0:10], fmt)
|
||||
sheet.write(2, 10, str(end_date)[0:10], fmt)
|
||||
|
||||
headers = [
|
||||
'الرقم الوظيفي', 'اسم الموظف', 'رقم الهوية', 'اﻹدارة', 'المسمي الوظيفي',
|
||||
'ايام الحضور', 'الاجازات', 'الاجازات الرسمية', 'الغياب', 'ساعات العمل الفعلية',
|
||||
'ساعات العمل الاضافية', 'الاستئذان', 'مهام عمل/انتداب/تدريب', 'التأخيرات', 'الخروج المبكر',
|
||||
]
|
||||
header_row = 5
|
||||
for col, title in enumerate(headers, start=1):
|
||||
sheet.write(header_row, col, title, fmt)
|
||||
|
||||
domain = [('date', '>=', start_date), ('date', '<=', end_date)]
|
||||
if employee_ids:
|
||||
domain.append(('employee_id', 'in', list(set(employee_ids))))
|
||||
elif calendar_id:
|
||||
rc = self.env['resource.calendar'].browse(calendar_id)
|
||||
domain.append(('employee_id', 'in', rc.employee_ids.ids))
|
||||
att = self.env['hr.attendance.transaction'].search(domain)
|
||||
|
||||
row = header_row + 1
|
||||
for emp in att.mapped('employee_id'):
|
||||
lines = att.filtered(lambda l, e=emp: l.employee_id == e)
|
||||
sheet.write(row, 1, emp.emp_no or '', fmt)
|
||||
sheet.write(row, 2, emp.name, fmt)
|
||||
iq = getattr(emp, 'iqama_number', False) or getattr(emp, 'saudi_number', '')
|
||||
sheet.write(row, 3, iq.display_name, fmt)
|
||||
sheet.write(row, 4, emp.department_id.name, fmt)
|
||||
sheet.write(row, 5, emp.sudo().job_id.name, fmt)
|
||||
sheet.write(row, 6, len({l.date for l in lines if not l.is_absent}), fmt)
|
||||
sheet.write(row, 7, len(lines.filtered(lambda l: l.normal_leave)), fmt)
|
||||
sheet.write(row, 8, len(lines.filtered(lambda l: l.public_holiday)), fmt)
|
||||
sheet.write(row, 9, len(lines.filtered(lambda l: l.is_absent)), fmt)
|
||||
sheet.write(row, 10, hhmm(sum(lines.mapped('office_hours'))), fmt)
|
||||
sheet.write(row, 11, hhmm(sum(lines.mapped('additional_hours'))), fmt)
|
||||
sheet.write(row, 12, hhmm(sum(lines.mapped('total_permission_hours'))), fmt)
|
||||
sheet.write(row, 13, hhmm(sum(lines.mapped('total_mission_hours'))), fmt)
|
||||
sheet.write(row, 14, hhmm(sum(lines.filtered(lambda l: l.approve_lateness).mapped('lateness'))), fmt)
|
||||
sheet.write(row, 15, hhmm(sum(lines.filtered(lambda l: l.approve_exit_out).mapped('early_exit'))), fmt)
|
||||
row += 1
|
||||
sheet.write(row, 1, _('الاجمالي'), fmt)
|
||||
sheet.write(row, 2, '', fmt)
|
||||
sheet.write(row, 3, '', fmt)
|
||||
sheet.write(row, 4, '', fmt)
|
||||
sheet.write(row, 5, '', fmt)
|
||||
sheet.write(row, 6, len({l.date for l in att if not l.is_absent}), fmt)
|
||||
sheet.write(row, 7, len(att.filtered(lambda l: l.normal_leave)), fmt)
|
||||
sheet.write(row, 8, len(att.filtered(lambda l: l.public_holiday)), fmt)
|
||||
sheet.write(row, 9, len(att.filtered(lambda l: l.is_absent)), fmt)
|
||||
sheet.write(row, 10, hhmm(sum(att.mapped('office_hours'))), fmt)
|
||||
sheet.write(row, 11, hhmm(sum(att.mapped('additional_hours'))), fmt)
|
||||
sheet.write(row, 12, hhmm(sum(att.mapped('total_permission_hours'))), fmt)
|
||||
sheet.write(row, 13, hhmm(sum(att.mapped('total_mission_hours'))), fmt)
|
||||
sheet.write(row, 14, hhmm(sum(att.filtered(lambda l: l.approve_lateness).mapped('lateness'))), fmt)
|
||||
sheet.write(row, 15, hhmm(sum(att.filtered(lambda l: l.approve_exit_out).mapped('early_exit'))), fmt)
|
||||
return
|
||||
|
||||
|
||||
if type == 'late':
|
||||
sheet.merge_range('D3:I3', _("Attendance Reports"), format2)
|
||||
sheet.write('E4:E4', _("From date"), format2)
|
||||
|
|
@ -262,7 +375,6 @@ class AttendancesReportXls(models.AbstractModel):
|
|||
total_lateness = total_early_exit = total_extra_hours = total_office_hours = 0.0
|
||||
|
||||
for line in final_dic[key]:
|
||||
|
||||
sheet.merge_range(row - 3, h_col + 1, row - 3, h_col + 2, emp_data[key][0]['emp_no'], format2)
|
||||
sheet.write(row - 3, h_col + 4, emp_data[key][0]['job'], format2)
|
||||
sheet.merge_range(row - 2, h_col + 1, row - 2, h_col + 2, emp_data[key][0]['emp_namw'], format2)
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue