Merge pull request #3260 from expsa/attendance_certification

Attendance certification
This commit is contained in:
mohammed-alkhazrji 2025-05-20 17:21:22 +03:00 committed by GitHub
commit 53f6838db0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 72 additions and 91 deletions

View File

@ -258,7 +258,7 @@ msgstr "أيقونة نوع النشاط"
#: model_terms:ir.ui.view,arch_db:attendances.employee_lateness_absense_overtime_form_view
#, python-format
msgid "Actual Absent Hours"
msgstr ""
msgstr " ساعات الغياب"
#. module: attendances
#: model:ir.model.fields,field_description:attendances.field_hr_attendance_report_line__additional_hours
@ -766,7 +766,7 @@ msgstr ""
#. module: attendances
#: model_terms:ir.ui.view,arch_db:attendances.employee_lateness_absense_overtime_form_view
msgid "Early Exist"
msgstr "دخول مبكر"
msgstr "خروج مبكر"
#. module: attendances
#: code:addons/attendances/wizard/attendances_report_wiz.py:0
@ -1749,6 +1749,11 @@ msgstr ""
msgid "Send Email"
msgstr "إرسال إيميل"
#. module: attendances
#: model:ir.model.fields,field_description:attendances.field_hr_attendance_report__send_email
msgid " Is Send Email"
msgstr "تم إرسال إيميل"
#. module: attendances
#: model:ir.model.fields,field_description:attendances.field_hr_attendance_transaction__sequence
msgid "Sequence"

View File

@ -45,18 +45,26 @@ class HrAttendanceReport(models.Model):
compute='_compute_selected_lines',
string="Selected Employees Lines"
)
send_email = fields.Boolean(string=" Is Send Email", default=False,store=True)
@api.depends('selected_employee_ids', 'line_ids')
@api.depends('selected_employee_ids', 'line_ids','department_ids')
def _compute_selected_lines(self):
for report in self:
lines = report.line_ids.filtered(lambda line: line.employee_name.id in report.selected_employee_ids.ids)
report.selected_lines = lines
@api.depends('line_ids.employee_name')
@api.onchange('department_ids')
def _compute_available_employees(self):
for report in self:
report.available_employee_ids = report.line_ids.mapped('employee_name')
if report.department_ids:
employees = self.env['hr.employee'].search([
('department_id', 'in', report.department_ids.ids),
('finger_print', '=', True)
])
report.available_employee_ids = employees
else:
report.available_employee_ids = self.env['hr.employee'].browse([])
def unlink(self):
for rec in self:
@ -139,11 +147,13 @@ class HrAttendanceReport(models.Model):
holidays_module = module.search([('state', '=', 'installed'), ('name', '=', 'hr_holidays_public')])
transaction_pool = self.env['hr.attendance.transaction']
reason_pool = self.env['hr.reasons.lateness']
domain = self._context.get('emp_id', False) and [('id', '=', self._context.get('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)
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')]
if self.calendar_ids: trans_domain += [('calendar_id', 'in', self.calendar_ids.ids)]
for employee in emps:
@ -388,19 +398,22 @@ class HrAttendanceReport(models.Model):
recs.unlink()
def _get_email_template(self):
return self.env.ref('attendances.emapproval')
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:
continue
template.with_context(
email_to=line.employee_name.work_email,
employee_name=line.employee_name.name,
default_model=self._name,
default_res_id=self.id,
).send_mail(self.id, force_send=True)
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

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api,_
from odoo import models, fields, api
class HrAttendanceReportLine(models.Model):
@ -7,20 +7,20 @@ class HrAttendanceReportLine(models.Model):
employee_name = fields.Many2one(comodel_name='hr.employee')
delay = fields.Float()
leave = fields.Float(string=_('Holiday Hours'))
leave = fields.Float(string='Holiday Hours')
exists = fields.Float()
extra_break_duration = fields.Float()
absent = fields.Float(string=_(' Hours of Absent'))
absent = fields.Float(string='Absent Hours')
mission_by_days = fields.Float(string='Mission Hours')
line_id = fields.Many2one(comodel_name='hr.attendance.report')
absent_days_by_hr = fields.Float(string=_('Absent Hours By HR'))
absent_days_by_hr = fields.Float(string='Absent Hours By HR')
dummy_field = fields.Float()
total_hours = fields.Float(string=_('Total Absence Hours')) # get total hours in month from attendance configuration
total_amount = fields.Float(string=_('Total Salary')) # get from total allowance in contract
total_hours = fields.Float(string='Total Absence Hours') # get total hours in month from attendance configuration
total_amount = fields.Float(string='Total Salary') # get from total allowance in contract
amount_per_hour = fields.Float() # get from total_amount / total_hours
total_deduction = fields.Float() # get from delay+leave+absent * amount_per_hour
actual_absent_hours = fields.Float(string=_('Actual Absent Hours'))
total_permission_hours = fields.Float(string=_('Total Permission Hours'))
actual_absent_hours = fields.Float(string='Actual Absent Hours')
total_permission_hours = fields.Float(string='Total Permission Hours')
additional_hours = fields.Float(string='Additional Hours', default=0)

View File

@ -1,18 +1,15 @@
<odoo>
<data>
<record id="emapproval" model="mail.template">
<field name="name">Attendance departure verification</field>
<field name="model_id" ref="attendances.model_hr_attendance_report"/>
<field name="subject">تصديق الحضور والانصراف - ${object.name}</field>
<field name="email_to">${ctx.get('email_to')}</field> <!-- مهم -->
<field name="body_html">
<![CDATA[
<p>Dear ${ ctx.get('employee_name')},</p>
<p>تم تصديق الحضور والانصراف من ${object.date_from} إلى ${object.date_to}.</p>
<p>وشكرًا.</p>
]]>
</field>
<data noupdate="1">
<record id="emapproval_line" model="mail.template">
<field name="name">Attendance departure verification Line</field>
<field name="model_id" ref="attendances.model_hr_attendance_report_line"/>
<field name="subject">تصديق الحضور والانصراف - ${object.line_id.name}</field>
<field name="email_to">${ctx.get('email_to')}</field>
<field name="body_html"><![CDATA[
<p>Dear ${ctx.get('employee_name')},</p>
<p>تم تصديق الحضور والانصراف من ${object.line_id.date_from} إلى ${object.line_id.date_to}.</p>
<p>وشكرًا.</p>
]]></field>
</record>
</data>
</odoo>

View File

@ -14,7 +14,7 @@
<field name="arch" type="xml">
<form>
<header>
<button name="action_send_email" string="Send Email" type="object" class="oe_highlight" states="approved,generated,confirmed" groups="hr.group_hr_user"/>
<button name="action_send_email" string="Send Email" type="object" class="oe_highlight" groups="hr.group_hr_user" attrs="{'invisible': ['|', ('state', 'not in', ['approved', 'generated', 'confirmed']), ('send_email', '=', True)]}"/>
<button name="generate_report" string="Generate Report" class="oe_highlight" type="object"
states="draft" groups="hr.group_hr_user"/>
@ -56,6 +56,8 @@
</group>
<group>
<field name="calendar_ids" widget="many2many_tags" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="send_email" attrs="{'invisible': [('send_email', '=', False)]}"/>
</group>
<notebook>
@ -107,70 +109,34 @@
</field>
</page>
<page string="Departments">
<field name="department_ids" widget="many2many_tags" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="department_ids" widget="many2many" attrs="{'readonly':[('state','!=','draft')]}"/>
</page>
<page string="Employees">
<group>
<field name="selected_employee_ids"
widget="many2many_tags"
domain="[('id', 'in', available_employee_ids)]"
string="اختر الموظفين"
context="{'search_default_available_employees': True}"/>
</group>
<field name="selected_lines" nolabel="1" attrs="{'readonly':[('state','!=','generated')]}">
<tree editable="bottom" decoration-danger="total_deduction &gt; 0">
<field name="employee_name" string="Employee Name" readonly="1"/>
<field name="delay" string="Delay" widget="float_time" readonly="1" sum="Total:"/>
<field name="exists" string="Early Exist" widget="float_time" readonly="1" sum="Total:"/>
<field name="total_permission_hours" string="Permission Hours" widget="float_time" readonly="1" sum="Total:" optional="show"/>
<field name="actual_absent_hours" string="Actual Absent Hours" widget="float_time" readonly="1" sum="Total:" />
<field name="extra_break_duration" string="Extra Break Duration" widget="float_time" readonly="1" sum="Total:"/>
<field name="mission_by_days" string="Mission Hours" widget="float_time" readonly="1" sum="Total:" optional="show"/>
<field name="leave" string="Holiday Hours" widget="float_time" readonly="1" sum="Total:" optional="show"/>
<field name="absent" string="Absent Hours" widget="float_time" readonly="1" sum="Total:"/>
<field name="additional_hours" string="Additional Hours" widget="float_time" readonly="1" sum="Total:"/>
<field name="absent_days_by_hr" string="Absent Hours By HR" widget="float_time" sum="Total:"/>
<field name="dummy_field" invisible="1" widget="float_time" sum="Total:"/>
<field name="total_hours" string="Total Absence Hours" widget="float_time" readonly="1" force_save="1" sum="Total:"/>
<field name="total_amount" string="Total Salary" readonly="1" sum="Total:" optional="show"/>
<field name="amount_per_hour" string="Amount Per Hour" readonly="1" sum="Total:" optional="show"/>
<field name="total_deduction" string="Total Deduction" readonly="1" force_save="1" sum="Total:"/>
<field name="selected_employee_ids"
widget="many2many"
domain="[('id', 'in', available_employee_ids)]"
string="اختر الموظفين"
context="{'search_default_available_employees': True}"
options="{'no_create': True}"
>
<tree editable="top">
<field name="name"/>
<field name="company_id" invisible="1"/>
<field name="department_id"/>
</tree>
<form>
<sheet>
<group>
<field name="employee_name" string="Employee Name"/>
<field name="delay" string="Delay" widget="float_time"/>
<field name="leave" string="Leave" widget="float_time"/>
<field name="exists" string="Early Exist" widget="float_time"/>
<field name="total_permission_hours" string="Permission Hours" widget="float_time"/>
<field name="actual_absent_hours" string="Actual Absent Hours" widget="float_time"/>
<field name="extra_break_duration" string="Extra Break Duration" widget="float_time"/>
<field name="mission_by_days" string="Missions By Days" widget="float_time"/>
<field name="absent" string="Absent" widget="float_time"/>
<field name="absent_days_by_hr" string="Absent Days By HR" widget="float_time"/>
<field name="total_hours" string="Total Working Hours" widget="float_time" force_save="1"/>
<field name="additional_hours" string="Additional Hours" widget="float_time" force_save="1"/>
<field name="total_amount" string="Total Salary"/>
<field name="amount_per_hour" string="Amount Per Hour"/>
<field name="total_deduction" string="Total Deduction" force_save="1"/>
<field name="dummy_field" invisible="1"/>
<field name="advantage_id" readonly="1" string="Deduction Employee"/>
</group>
</sheet>
</form>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="activity_ids" widget="mail_activity"/>