19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:31:00 +01:00
parent a1137a1456
commit e1d89e11e3
2789 changed files with 1093187 additions and 605897 deletions

View file

@ -4,16 +4,16 @@
from odoo import api, fields, models, tools
class TimesheetAttendance(models.Model):
class HrTimesheetAttendanceReport(models.Model):
_name = 'hr.timesheet.attendance.report'
_auto = False
_description = 'Timesheet Attendance Report'
user_id = fields.Many2one('res.users', readonly=True)
employee_id = fields.Many2one('hr.employee', readonly=True)
date = fields.Date(readonly=True)
total_timesheet = fields.Float("Timesheets Hours", readonly=True)
total_attendance = fields.Float("Attendance Hours", readonly=True)
total_difference = fields.Float("Hours Difference", readonly=True)
total_timesheet = fields.Float("Timesheets Time", readonly=True)
total_attendance = fields.Float("Attendance Time", readonly=True)
total_difference = fields.Float("Time Difference", readonly=True)
timesheets_cost = fields.Float("Timesheet Cost", readonly=True)
attendance_cost = fields.Float("Attendance Cost", readonly=True)
cost_difference = fields.Float("Cost Difference", readonly=True)
@ -21,10 +21,10 @@ class TimesheetAttendance(models.Model):
def init(self):
tools.drop_view_if_exists(self.env.cr, self._table)
self._cr.execute("""CREATE OR REPLACE VIEW %s AS (
self.env.cr.execute("""CREATE OR REPLACE VIEW %s AS (
SELECT
max(id) AS id,
t.user_id,
t.employee_id,
t.date,
t.company_id,
coalesce(sum(t.attendance), 0) AS total_attendance,
@ -37,25 +37,26 @@ class TimesheetAttendance(models.Model):
SELECT
-hr_attendance.id AS id,
hr_employee.hourly_cost AS emp_cost,
resource_resource.user_id AS user_id,
hr_attendance.employee_id AS employee_id,
hr_attendance.worked_hours AS attendance,
NULL AS timesheet,
CAST(hr_attendance.check_in
at time zone 'utc'
at time zone
(SELECT calendar.tz FROM resource_calendar as calendar
INNER JOIN hr_employee as employee ON employee.id = employee_id
WHERE calendar.id = employee.resource_calendar_id)
INNER JOIN hr_employee as employee ON employee.id = hr_attendance.employee_id
LEFT JOIN hr_version v ON v.id = employee.current_version_id
WHERE calendar.id = v.resource_calendar_id)
as DATE) as date,
resource_resource.company_id as company_id
hr_employee.company_id as company_id
FROM hr_attendance
LEFT JOIN hr_employee ON hr_employee.id = hr_attendance.employee_id
LEFT JOIN resource_resource on resource_resource.id = hr_employee.resource_id
WHERE check_in::date <= CURRENT_DATE
UNION ALL
SELECT
ts.id AS id,
hr_employee.hourly_cost AS emp_cost,
ts.user_id AS user_id,
ts.employee_id AS employee_id,
NULL AS attendance,
ts.unit_amount AS timesheet,
ts.date AS date,
@ -63,16 +64,15 @@ class TimesheetAttendance(models.Model):
FROM account_analytic_line AS ts
LEFT JOIN hr_employee ON hr_employee.id = ts.employee_id
WHERE ts.project_id IS NOT NULL
AND date <= CURRENT_DATE
) AS t
GROUP BY t.user_id, t.date, t.company_id, t.emp_cost
GROUP BY t.employee_id, t.date, t.company_id, t.emp_cost
ORDER BY t.date
)
""" % self._table)
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
if not orderby and groupby:
orderby_list = [groupby] if isinstance(groupby, str) else groupby
orderby_list = [field.split(':')[0] for field in orderby_list]
orderby = ','.join([f"{field} desc" if field == 'date' else field for field in orderby_list])
return super().read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
def formatted_read_group(self, domain, groupby=(), aggregates=(), having=(), offset=0, limit=None, order=None) -> list[dict]:
if not order and groupby:
order = ', '.join(f"{spec} DESC" if spec.startswith('date:') else spec for spec in groupby)
return super().formatted_read_group(domain, groupby, aggregates, having=having, offset=offset, limit=limit, order=order)

View file

@ -6,9 +6,22 @@
<field name="model">hr.timesheet.attendance.report</field>
<field name="arch" type="xml">
<search string="Timesheet Attendance">
<field name="user_id" string="Employee"/>
<filter name="month" string="Date" date="date"/>
<filter name="group_by_user" string="Employee" context="{'group_by': 'user_id'}"/>
<field name="employee_id" string="Employee"/>
<filter string="My Team" name="my_team" domain="[('employee_id.parent_id.user_id', '=', uid)]"/>
<filter string="My Department" name="my_department" domain="[('employee_id.member_of_department', '=', True)]"/>
<separator/>
<filter name="month" string="Date" date="date">
<filter name="date_this_week" string="This Week" domain="[
('date', '&gt;=', '=week_start'),
('date', '&lt;', '=week_start +1w'),
]"/>
<filter name="date_today" string="Today" domain="[('date', '&gt;=', 'today'), ('date', '&lt;', 'today +1d')]"/>
<filter name="date_last_week" string="Last Week" domain="[
('date', '&gt;=', '=week_start -1w'),
('date', '&lt;', '=week_start'),
]"/>
</filter>
<filter name="group_by_user" string="Employee" context="{'group_by': 'employee_id'}"/>
<filter name="group_by_month" string="Date" date="date" context="{'group_by': 'date'}"/>
</search>
</field>
@ -29,20 +42,6 @@
</field>
</record>
<record id="hr_timesheet_attendance_report_view_tree" model="ir.ui.view">
<field name="name">hr.timesheet.attendance.report.view.tree</field>
<field name="model">hr.timesheet.attendance.report</field>
<field name="arch" type="xml">
<tree string="Timesheet Attendance">
<field name="date"/>
<field name="user_id" optional="show" widget="many2one_avatar_user"/>
<field name="total_timesheet" optional="show" sum="Sum of Total Timesheet"/>
<field name="total_attendance" optional="show" sum="Sum of Total Attendance"/>
<field name="total_difference" optional="show" sum="Sum of Total Difference"/>
</tree>
</field>
</record>
<record id="hr_timesheet_attendance_report_view_graph" model="ir.ui.view">
<field name="name">hr.timesheet.attendance.report.view.graph</field>
<field name="model">hr.timesheet.attendance.report</field>
@ -55,8 +54,9 @@
</record>
<record id="action_hr_timesheet_attendance_report" model="ir.actions.act_window">
<field name="name">Timesheet / Attendance</field>
<field name="name">Timesheets / Attendance Analysis</field>
<field name="res_model">hr.timesheet.attendance.report</field>
<field name="path">timesheets-attendance-analysis</field>
<field name="view_mode">graph,pivot</field>
<field name="view_id" eval="False"/>
<field name="context">{}</field>
@ -85,6 +85,6 @@
<menuitem id="menu_hr_timesheet_attendance_report"
parent="hr_timesheet.menu_timesheets_reports"
action="action_hr_timesheet_attendance_report"
name="Timesheet / Attendance"/>
name="Timesheets / Attendance Analysis"/>
</data>
</odoo>