Compare commits
109 Commits
ce96c95fa1
...
ff32c723e6
| Author | SHA1 | Date |
|---|---|---|
|
|
ff32c723e6 | |
|
|
05d145c5cd | |
|
|
9c6feae512 | |
|
|
71293ad8ef | |
|
|
fc053eca72 | |
|
|
40020cf23c | |
|
|
edc151bb1e | |
|
|
2908134931 | |
|
|
212900a1d3 | |
|
|
bd382f6d20 | |
|
|
5f23d59213 | |
|
|
db1906ce4c | |
|
|
1befd50b28 | |
|
|
9c1ebc720c | |
|
|
b88c388b75 | |
|
|
52641f4514 | |
|
|
9b751e29d5 | |
|
|
a588370258 | |
|
|
2498d1010b | |
|
|
ab560ad6d6 | |
|
|
daf31782fd | |
|
|
f88623168f | |
|
|
0537dc1979 | |
|
|
e5972f0f92 | |
|
|
902813c978 | |
|
|
eb4ccbfa22 | |
|
|
01f5d4c74e | |
|
|
f07ae8eb99 | |
|
|
2fd52bfb86 | |
|
|
19bdf92f67 | |
|
|
827e8c22a0 | |
|
|
27e51a80d2 | |
|
|
90f50950fd | |
|
|
d2f1caf810 | |
|
|
995688ad8e | |
|
|
efc7643304 | |
|
|
55178e4b15 | |
|
|
50daabba44 | |
|
|
6cb1d7526e | |
|
|
1424e147e8 | |
|
|
2aabe1e7c6 | |
|
|
426b3d71a4 | |
|
|
62df996ae4 | |
|
|
11066ba9c1 | |
|
|
09d68ec225 | |
|
|
a77bb66622 | |
|
|
b34dcf6d5b | |
|
|
af98a28428 | |
|
|
7b91e82363 | |
|
|
c225eeec5d | |
|
|
be0cbc33bb | |
|
|
2e53ada2f3 | |
|
|
baa6dec075 | |
|
|
c9555b962e | |
|
|
08f388019f | |
|
|
743fb36d90 | |
|
|
3d2c673050 | |
|
|
7a6352ee21 | |
|
|
27eed9ee63 | |
|
|
909bf116b6 | |
|
|
fdc9f88129 | |
|
|
448385fd45 | |
|
|
351180260a | |
|
|
e489072aae | |
|
|
4e44c708d9 | |
|
|
2188551da3 | |
|
|
953794adc2 | |
|
|
adb500009f | |
|
|
eee154da0c | |
|
|
a072f600e6 | |
|
|
87028c063a | |
|
|
e24e329b27 | |
|
|
c8902cd7f2 | |
|
|
044e01aa23 | |
|
|
a42d6449cf | |
|
|
a801a30488 | |
|
|
e32ad6cc9b | |
|
|
758c3dc10f | |
|
|
2342ded3ff | |
|
|
38080d56c0 | |
|
|
2288404bc2 | |
|
|
9f3d07d7be | |
|
|
a8bc538da4 | |
|
|
91b7f05c45 | |
|
|
b7f5f4ec3e | |
|
|
a79a1a7b0e | |
|
|
2033d5c227 | |
|
|
c5d35be79a | |
|
|
8638551d38 | |
|
|
185d33209a | |
|
|
124c1a62b5 | |
|
|
45895e0225 | |
|
|
65d86303c5 | |
|
|
0bc54d0d13 | |
|
|
8cd88a5d43 | |
|
|
ebaa1b3c66 | |
|
|
506d9e82aa | |
|
|
b326aba2f7 | |
|
|
74c8705962 | |
|
|
cd075e628e | |
|
|
aa9f2aa12d | |
|
|
0f071e6dda | |
|
|
dd9e87f3f5 | |
|
|
2e16a1d4fa | |
|
|
1ac7246284 | |
|
|
2d6f549b17 | |
|
|
e0a1c363a6 | |
|
|
d3262bc894 | |
|
|
56fd53e470 |
|
|
@ -18,8 +18,12 @@
|
||||||
'version': '0.1',
|
'version': '0.1',
|
||||||
|
|
||||||
# any module necessary for this one to work correctly
|
# any module necessary for this one to work correctly
|
||||||
|
|
||||||
'depends': ['base','hr','account','mail','hr_skills', 'hr_contract'],
|
'depends': ['base','hr','account','mail','hr_skills', 'hr_contract'],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# always loaded
|
# always loaded
|
||||||
'data': [
|
'data': [
|
||||||
'security/security.xml',
|
'security/security.xml',
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,8 @@ class HRJobRecruitment(models.Model):
|
||||||
rec.submission_status = 'zero'
|
rec.submission_status = 'zero'
|
||||||
|
|
||||||
|
|
||||||
|
experience = fields.Many2one('candidate.experience', string="Experience")
|
||||||
|
|
||||||
@api.depends('application_ids.submitted_to_client')
|
@api.depends('application_ids.submitted_to_client')
|
||||||
def _compute_no_of_submissions(self):
|
def _compute_no_of_submissions(self):
|
||||||
counts = dict(self.env['hr.applicant']._read_group(
|
counts = dict(self.env['hr.applicant']._read_group(
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from odoo import models, fields, api
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import json
|
import json
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import datetime
|
from pytz import timezone, UTC
|
||||||
|
|
||||||
|
|
||||||
class AttendanceWeeklyReport(models.Model):
|
class AttendanceWeeklyReport(models.Model):
|
||||||
|
|
@ -22,32 +22,39 @@ class AttendanceWeeklyReport(models.Model):
|
||||||
last_monday = today - timedelta(days=today.weekday() + 7)
|
last_monday = today - timedelta(days=today.weekday() + 7)
|
||||||
last_sunday = last_monday + timedelta(days=6)
|
last_sunday = last_monday + timedelta(days=6)
|
||||||
|
|
||||||
|
user_tz = self.env.user.tz or 'UTC'
|
||||||
|
tz = timezone(user_tz)
|
||||||
|
|
||||||
|
# Search for attendance in UTC (Odoo stores in UTC)
|
||||||
attendances = self.env['hr.attendance'].search([
|
attendances = self.env['hr.attendance'].search([
|
||||||
('check_in', '>=', str(last_monday)),
|
('check_in', '>=', str(last_monday)),
|
||||||
('check_out', '<=', str(last_sunday + timedelta(days=1)))
|
('check_out', '<=', str(last_sunday + timedelta(days=1)))
|
||||||
])
|
])
|
||||||
|
|
||||||
employee_data = {}
|
|
||||||
|
|
||||||
employee_data = defaultdict(list)
|
employee_data = defaultdict(list)
|
||||||
grouped_attendance = defaultdict(lambda: defaultdict(list)) # {emp: {date: [attendances]}}
|
grouped_attendance = defaultdict(lambda: defaultdict(list)) # {emp: {date: [attendances]}}
|
||||||
|
|
||||||
|
# Group attendances by employee and local date
|
||||||
for att in attendances:
|
for att in attendances:
|
||||||
emp = att.employee_id.name
|
emp = att.employee_id.name
|
||||||
date = att.check_in.date()
|
check_in_local = att.check_in.astimezone(tz)
|
||||||
grouped_attendance[emp][date].append(att)
|
date_local = check_in_local.date()
|
||||||
|
grouped_attendance[emp][date_local].append(att)
|
||||||
|
|
||||||
|
# Process each employee's attendance
|
||||||
for emp_name, dates in grouped_attendance.items():
|
for emp_name, dates in grouped_attendance.items():
|
||||||
for date, records in dates.items():
|
for date, records in dates.items():
|
||||||
records = sorted(records, key=lambda a: a.check_in)
|
records = sorted(records, key=lambda a: a.check_in)
|
||||||
total_seconds = 0
|
total_seconds = 0
|
||||||
first_in = records[0].check_in.time().strftime('%H:%M')
|
first_in = records[0].check_in.astimezone(tz).strftime('%H:%M')
|
||||||
last_out = 'N/A'
|
last_out = 'N/A'
|
||||||
|
|
||||||
for rec in records:
|
for rec in records:
|
||||||
if rec.check_in and rec.check_out:
|
if rec.check_in and rec.check_out:
|
||||||
total_seconds += (rec.check_out - rec.check_in).total_seconds()
|
check_in_local = rec.check_in.astimezone(tz)
|
||||||
last_out = rec.check_out.time().strftime('%H:%M')
|
check_out_local = rec.check_out.astimezone(tz)
|
||||||
|
total_seconds += (check_out_local - check_in_local).total_seconds()
|
||||||
|
last_out = check_out_local.strftime('%H:%M')
|
||||||
|
|
||||||
employee_data[emp_name].append({
|
employee_data[emp_name].append({
|
||||||
'date': date.strftime('%Y-%m-%d'),
|
'date': date.strftime('%Y-%m-%d'),
|
||||||
|
|
@ -55,7 +62,6 @@ class AttendanceWeeklyReport(models.Model):
|
||||||
'out': last_out,
|
'out': last_out,
|
||||||
'hours': f'{total_seconds / 3600:.2f}',
|
'hours': f'{total_seconds / 3600:.2f}',
|
||||||
})
|
})
|
||||||
|
|
||||||
# Inline QWeb-compatible HTML template (must be in a real view in production)
|
# Inline QWeb-compatible HTML template (must be in a real view in production)
|
||||||
html_template = """
|
html_template = """
|
||||||
<div style="max-width:800px;margin:auto;background-color:#fff;padding:20px;border:1px solid #ddd;border-radius:8px;">
|
<div style="max-width:800px;margin:auto;background-color:#fff;padding:20px;border:1px solid #ddd;border-radius:8px;">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue