mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-27 03:12:05 +02:00
19.0 vanilla
This commit is contained in:
parent
a1137a1456
commit
e1d89e11e3
2789 changed files with 1093187 additions and 605897 deletions
|
|
@ -1,11 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="timesheets_analysis_report_list" model="ir.ui.view">
|
||||
<field name="name">timesheets.analysis.report.list</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="project_id"/>
|
||||
<field name="task_id"/>
|
||||
<field name="currency_id" column_invisible="1"/>
|
||||
<field name="amount" string="Timesheet Costs" optional="hide" sum="Total"/>
|
||||
<field name="unit_amount" optional="show" widget="timesheet_uom" sum="Total"
|
||||
decoration-danger="unit_amount > 24 or unit_amount < 0"
|
||||
decoration-muted="unit_amount == 0"
|
||||
/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="timesheets_analysis_report_form" model="ir.ui.view">
|
||||
<field name="name">timesheets.analysis.report.form</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Timesheets Analysis">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="project_id"/>
|
||||
<field name="task_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="employee_id"/>
|
||||
<field name="date"/>
|
||||
<field name="amount" invisible="1"/>
|
||||
<field name="unit_amount" string="Time Spent" widget="timesheet_uom" decoration-danger="unit_amount > 24"
|
||||
decoration-muted="unit_amount == 0"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="name" widget="text" nolabel="1"/>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="timesheets_analysis_report_pivot_employee" model="ir.ui.view">
|
||||
<field name="name">timesheets.analysis.report.pivot</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Timesheets Analysis" sample="1" disable_linking="True">
|
||||
<pivot string="Timesheets Analysis" sample="1">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="date" interval="month" type="col"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
|
|
@ -18,7 +62,7 @@
|
|||
<field name="name">timesheets.analysis.report.graph</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview" disable_linking="True">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
<field name="unit_amount" type="measure" widget="timesheet_uom"/>
|
||||
|
|
@ -30,7 +74,7 @@
|
|||
<field name="name">timesheets.analysis.report.pivot</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Timesheets Analysis" sample="1" disable_linking="True">
|
||||
<pivot string="Timesheets Analysis" sample="1">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="date" interval="month" type="col"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
|
|
@ -43,7 +87,7 @@
|
|||
<field name="name">timesheets.analysis.report.graph</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview" disable_linking="True">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
<field name="unit_amount" type="measure" widget="timesheet_uom"/>
|
||||
|
|
@ -55,7 +99,7 @@
|
|||
<field name="name">timesheets.analysis.report.pivot</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Timesheets Analysis" sample="1" disable_linking="True">
|
||||
<pivot string="Timesheets Analysis" sample="1">
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="task_id" type="row"/>
|
||||
|
|
@ -69,7 +113,7 @@
|
|||
<field name="name">timesheets.analysis.report.graph</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview" disable_linking="True">
|
||||
<graph string="Timesheets" sample="1" js_class="hr_timesheet_graphview">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="task_id" type="row"/>
|
||||
<field name="amount" string="Timesheet Costs"/>
|
||||
|
|
@ -81,28 +125,11 @@
|
|||
<record id="hr_timesheet_report_search" model="ir.ui.view">
|
||||
<field name="name">timesheets.analysis.report.search</field>
|
||||
<field name="model">timesheets.analysis.report</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_search"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Timesheet">
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="project_id"/>
|
||||
<field name="ancestor_task_id" groups="project.group_subtask_project"/>
|
||||
<field name="task_id"/>
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
<field name="manager_id"/>
|
||||
<filter name="mine" string="My Timesheets" domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter name="month" string="Date" date="date"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Project" name="groupby_project" domain="[]" context="{'group_by': 'project_id'}"/>
|
||||
<filter string="Ancestor Task" name="groupby_parent_task" domain="[]" context="{'group_by': 'ancestor_task_id'}" groups="project.group_subtask_project"/>
|
||||
<filter string="Task" name="groupby_task" domain="[]" context="{'group_by': 'task_id'}"/>
|
||||
<filter string="Date" name="groupby_date" domain="[]" context="{'group_by': 'date'}" help="Timesheet by Date"/>
|
||||
<filter string="Department" name="groupby_department" domain="[]" context="{'group_by': 'department_id'}"/>
|
||||
<filter string="Manager" name="groupby_manager" domain="[]" context="{'group_by': 'manager_id'}"/>
|
||||
<filter string="Employee" name="groupby_employee" domain="[]" context="{'group_by': 'employee_id'}"/>
|
||||
</group>
|
||||
<search position="attributes">
|
||||
<attribute name="string">Timesheet Report</attribute>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -111,6 +138,7 @@
|
|||
<record id="act_hr_timesheet_report" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets by Employee</field>
|
||||
<field name="res_model">timesheets.analysis.report</field>
|
||||
<field name="path">timesheets-by-employee</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="hr_timesheet_report_search"/>
|
||||
|
|
@ -139,10 +167,18 @@
|
|||
<field name="act_window_id" ref="act_hr_timesheet_report"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_view_report_by_employee_list" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheets_analysis_report_list"/>
|
||||
<field name="act_window_id" ref="act_hr_timesheet_report"/>
|
||||
</record>
|
||||
|
||||
<!-- Group by project-->
|
||||
<record id="timesheet_action_report_by_project" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets by Project</field>
|
||||
<field name="res_model">timesheets.analysis.report</field>
|
||||
<field name="path">timesheets-by-project</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="hr_timesheet_report_search"/>
|
||||
|
|
@ -171,10 +207,18 @@
|
|||
<field name="act_window_id" ref="timesheet_action_report_by_project"/>
|
||||
</record>
|
||||
|
||||
<record id="timesheet_action_view_report_by_project_list" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheets_analysis_report_list"/>
|
||||
<field name="act_window_id" ref="timesheet_action_report_by_project"/>
|
||||
</record>
|
||||
|
||||
<!-- Group by task -->
|
||||
<record id="timesheet_action_report_by_task" model="ir.actions.act_window">
|
||||
<field name="name">Timesheets by Task</field>
|
||||
<field name="res_model">timesheets.analysis.report</field>
|
||||
<field name="path">timesheets-by-task</field>
|
||||
<field name="domain">[('project_id', '!=', False)]</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="hr_timesheet_report_search"/>
|
||||
|
|
@ -203,34 +247,11 @@
|
|||
<field name="act_window_id" ref="timesheet_action_report_by_task"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_timesheets_reports"
|
||||
name="Reporting"
|
||||
parent="timesheet_menu_root"
|
||||
sequence="99"/>
|
||||
|
||||
<menuitem id="menu_timesheets_reports_timesheet"
|
||||
name="Timesheets"
|
||||
parent="menu_timesheets_reports"
|
||||
sequence="10"/>
|
||||
|
||||
<menuitem id="menu_hr_activity_analysis"
|
||||
parent="menu_timesheets_reports_timesheet"
|
||||
action="act_hr_timesheet_report"
|
||||
groups="hr_timesheet.group_hr_timesheet_approver"
|
||||
name="By Employee"
|
||||
sequence="10"/>
|
||||
|
||||
<menuitem id="timesheet_menu_report_timesheet_by_project"
|
||||
parent="menu_timesheets_reports_timesheet"
|
||||
action="timesheet_action_report_by_project"
|
||||
name="By Project"
|
||||
sequence="15"/>
|
||||
|
||||
<menuitem id="timesheet_menu_report_timesheet_by_task"
|
||||
parent="menu_timesheets_reports_timesheet"
|
||||
action="timesheet_action_report_by_task"
|
||||
name="By Task"
|
||||
sequence="20"/>
|
||||
|
||||
<record id="timesheet_action_view_report_by_task_list" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view_mode">list</field>
|
||||
<field name="view_id" ref="hr_timesheet.timesheets_analysis_report_list"/>
|
||||
<field name="act_window_id" ref="timesheet_action_report_by_task"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, api
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ReportProjectTaskUser(models.Model):
|
||||
_inherit = "report.project.task.user"
|
||||
|
||||
hours_planned = fields.Float('Planned Hours', readonly=True)
|
||||
hours_effective = fields.Float('Effective Hours', readonly=True)
|
||||
remaining_hours = fields.Float('Remaining Hours', readonly=True)
|
||||
progress = fields.Float('Progress', group_operator='avg', readonly=True)
|
||||
overtime = fields.Float(readonly=True)
|
||||
allocated_hours = fields.Float('Allocated Time', readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
effective_hours = fields.Float('Time Spent', readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
remaining_hours = fields.Float('Time Remaining', readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
remaining_hours_percentage = fields.Float('Time Remaining Percentage', readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
progress = fields.Float('Progress', aggregator='avg', readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
overtime = fields.Float(readonly=True, groups="hr_timesheet.group_hr_timesheet_user")
|
||||
|
||||
def _select(self):
|
||||
select_to_append = """,
|
||||
(t.effective_hours * 100) / NULLIF(t.planned_hours, 0) as progress,
|
||||
t.effective_hours as hours_effective,
|
||||
t.planned_hours - t.effective_hours - t.subtask_effective_hours as remaining_hours,
|
||||
NULLIF(t.planned_hours, 0) as hours_planned,
|
||||
t.overtime as overtime
|
||||
return super()._select() + """,
|
||||
CASE WHEN COALESCE(t.allocated_hours, 0) = 0 THEN NULL ELSE t.effective_hours * 100 / t.allocated_hours END as progress,
|
||||
NULLIF(t.effective_hours, 0) as effective_hours,
|
||||
CASE WHEN COALESCE(t.allocated_hours, 0) = 0 THEN NULL ELSE t.allocated_hours - t.effective_hours END as remaining_hours,
|
||||
CASE WHEN t.allocated_hours > 0 THEN t.remaining_hours / t.allocated_hours ELSE 0 END as remaining_hours_percentage,
|
||||
NULLIF(t.allocated_hours, 0) as allocated_hours,
|
||||
NULLIF(t.overtime, 0) as overtime
|
||||
"""
|
||||
return super(ReportProjectTaskUser, self)._select() + select_to_append
|
||||
|
||||
def _group_by(self):
|
||||
group_by_append = """,
|
||||
return super()._group_by() + """,
|
||||
t.effective_hours,
|
||||
t.subtask_effective_hours,
|
||||
t.planned_hours,
|
||||
t.allocated_hours,
|
||||
t.overtime
|
||||
"""
|
||||
return super(ReportProjectTaskUser, self)._group_by() + group_by_append
|
||||
|
||||
@api.model
|
||||
def _get_view_cache_key(self, view_id=None, view_type='form', **options):
|
||||
"""The override of _get_view changing the time field labels according to the company timesheet encoding UOM
|
||||
makes the view cache dependent on the company timesheet encoding uom"""
|
||||
key = super()._get_view_cache_key(view_id, view_type, **options)
|
||||
return key + (self.env.company.timesheet_encode_uom_id,)
|
||||
|
||||
@api.model
|
||||
def _get_view(self, view_id=None, view_type='form', **options):
|
||||
arch, view = super()._get_view(view_id, view_type, **options)
|
||||
if view_type in ['pivot', 'graph'] and self.env.company.timesheet_encode_uom_id == self.env.ref('uom.product_uom_day'):
|
||||
arch = self.env['account.analytic.line']._apply_time_label(arch, related_model=self._name)
|
||||
return arch, view
|
||||
|
|
|
|||
|
|
@ -6,13 +6,12 @@
|
|||
<field name="model">report.project.task.user</field>
|
||||
<field name="inherit_id" ref="project.view_task_project_user_graph" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//graph" position="attributes">
|
||||
<attribute name="js_class">hr_timesheet_graphview</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='project_id']" position='after'>
|
||||
<field name="hours_planned" widget="timesheet_uom" type="measure"/>
|
||||
<field name="hours_effective" widget="timesheet_uom" type="measure"/>
|
||||
<field name="allocated_hours" widget="timesheet_uom" type="measure"/>
|
||||
<field name="effective_hours" widget="timesheet_uom" type="measure"/>
|
||||
<field name="overtime" widget="timesheet_uom"/>
|
||||
<field name="remaining_hours" widget="timesheet_uom" type="measure"/>
|
||||
<field name="remaining_hours_percentage" invisible="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
@ -22,43 +21,14 @@
|
|||
<field name="model">report.project.task.user</field>
|
||||
<field name="inherit_id" ref="project.view_task_project_user_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='project_id']" position='after'>
|
||||
<field name="hours_planned" widget="timesheet_uom" type="measure"/>
|
||||
<field name="hours_effective" widget="timesheet_uom" type="measure"/>
|
||||
<pivot position="inside">
|
||||
<field name="allocated_hours" widget="timesheet_uom" type="measure"/>
|
||||
<field name="effective_hours" widget="timesheet_uom" type="measure"/>
|
||||
<field name="remaining_hours" widget="timesheet_uom" type="measure"/>
|
||||
</xpath>
|
||||
<field name="overtime" widget="timesheet_uom" type="measure"/>
|
||||
<field name="remaining_hours_percentage" invisible="1"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="report_project_task_user_view_search" model="ir.ui.view">
|
||||
<field name="name">report.project.task.user.view.search.inherit.hr.timesheet</field>
|
||||
<field name="model">report.project.task.user</field>
|
||||
<field name="inherit_id" ref="project.view_task_project_user_search" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='late']" position="after">
|
||||
<filter string="Tasks in Overtime" name="overtime" domain="[('overtime', '>', 0)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='my_favorite_projects']" position="after">
|
||||
<filter string="My Team's Projects" name="my_team_projects" domain="[('project_id.user_id.employee_id.parent_id.user_id', '=', uid), ('project_id.user_id', '!=', uid), ('user_ids', '!=', uid), ('user_ids', '!=', False)]"/>
|
||||
<filter string="My Department's Projects" name="my_department" domain="[('project_id.user_id.employee_id.member_of_department', '=', True)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='followed_by_me']" position="after">
|
||||
<filter string="My Team's Tasks" name="my_team_tasks" domain="[('user_ids.employee_id.parent_id.user_id', '=', uid)]" />
|
||||
<filter string="My Department's Tasks" name="my_department" domain="[('user_ids.employee_id.member_of_department', '=', True)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="report_project_task_user_view_tree" model="ir.ui.view">
|
||||
<field name="name">report.project.task.user.view.tree.inherit.hr.timesheet</field>
|
||||
<field name="model">report.project.task.user</field>
|
||||
<field name="inherit_id" ref="project.report_project_task_user_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="user_ids" position="after">
|
||||
<field name="hours_effective" optional="hide" widget="float_time"/>
|
||||
<field name="progress" optional="hide" widget="progressbar"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -7,52 +7,57 @@
|
|||
<table class="table table-sm">
|
||||
<thead style="display: table-row-group">
|
||||
<tr>
|
||||
<t t-set="timesheet_record_label" t-value="False"/>
|
||||
<t t-if="show_task">
|
||||
<t t-set="timesheet_record_label">Task</t>
|
||||
</t>
|
||||
<t t-elif="show_project">
|
||||
<t t-set="timesheet_record_label">Project</t>
|
||||
</t>
|
||||
<th class="text-start align-middle"><span>Date</span></th>
|
||||
<th class="text-start align-middle"><span>Employee</span></th>
|
||||
<th class="text-start align-middle" t-if="show_project"><span>Project</span></th>
|
||||
<th class="text-start align-middle" t-if="show_task"><span>Task</span></th>
|
||||
<th class="text-start align-middle" t-if="timesheet_record_label"><span t-out="timesheet_record_label"/></th>
|
||||
<th class="text-start align-middle"><span>Description</span></th>
|
||||
<th class="text-end">
|
||||
<span t-if="is_uom_day">Days Spent</span>
|
||||
<span t-else="">Hours Spent</span>
|
||||
<span>Time Spent</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr t-foreach="lines" t-as="line" t-att-style="'background-color: #F1F1F1;' if line_index % 2 == 0 else ''">
|
||||
<td class="align-middle">
|
||||
<span t-field="line.date"/>
|
||||
<span t-field="line.date">2021-09-01</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<span t-field="line.user_id.partner_id.name"/>
|
||||
<span t-if="not line.user_id.partner_id.name" t-field="line.employee_id"/>
|
||||
<span t-if="line.user_id.partner_id.name" t-field="line.user_id.partner_id.name">Audrey Peterson</span>
|
||||
<span t-else="" t-field="line.employee_id">Audrey Peterson</span>
|
||||
</td>
|
||||
<td t-if="show_project" class="align-middle">
|
||||
<span t-field="line.project_id.sudo().name"/>
|
||||
</td>
|
||||
<td t-if="show_task" class="align-middle">
|
||||
<span t-if="line.task_id" t-field="line.task_id.sudo().name"/>
|
||||
<t t-set="timesheet_record_info" t-value="False"/>
|
||||
<t t-if="show_project">
|
||||
<t t-set="timesheet_record_info" t-value="line.project_id.sudo().name"/>
|
||||
<t t-if="show_task and line.task_id" t-set="timesheet_record_info" t-value="'%s / %s' % (timesheet_record_info, line.task_id.sudo().name)"/>
|
||||
</t>
|
||||
<t t-elif="show_task" t-set="timesheet_record_info" t-value="line.task_id.sudo().name"/>
|
||||
<td t-if="show_task or show_project" class="align-middle">
|
||||
<span t-if="timesheet_record_info" t-out="timesheet_record_info">Research and Development/New Portal System</span>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<span t-field="line.name" t-options="{'widget': 'text'}"/>
|
||||
<span t-field="line.name" t-options="{'widget': 'text'}">Call client and discuss project</span>
|
||||
</td>
|
||||
<td class="text-end align-middle">
|
||||
<span t-if="is_uom_day" t-esc="line._get_timesheet_time_day()" t-options="{'widget': 'timesheet_uom'}"/>
|
||||
<span t-else="" t-field="line.unit_amount" t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}"/>
|
||||
<span t-if="not is_uom_day" t-field="line.unit_amount" t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}">2 hours</span>
|
||||
<span t-else="" t-esc="line._get_timesheet_time_day()" t-options="{'widget': 'timesheet_uom'}">1 day</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<t t-set="nbCols" t-value="4"/>
|
||||
<t t-if="show_project" t-set="nbCols" t-value="nbCols + 1"/>
|
||||
<t t-if="show_task" t-set="nbCols" t-value="nbCols + 1"/>
|
||||
<td class="text-end" t-attf-colspan="{{nbCols}}">
|
||||
<strong t-if="is_uom_day">
|
||||
<span style="margin-right: 15px;">Total (Days)</span>
|
||||
<t t-esc="lines._convert_hours_to_days(sum(lines.mapped('unit_amount')))" t-options="{'widget': 'timesheet_uom'}"/>
|
||||
<td class="text-end" colspan="100">
|
||||
<strong t-if="not is_uom_day">
|
||||
<span style="margin-right: 15px;">Total (Hours)</span>
|
||||
<t t-esc="sum(lines.mapped('unit_amount'))" t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}">2 hours</t>
|
||||
</strong>
|
||||
<strong t-else="">
|
||||
<span style="margin-right: 15px;">Total (Hours)</span>
|
||||
<t t-esc="sum(lines.mapped('unit_amount'))" t-options="{'widget': 'duration', 'digital': True, 'unit': 'hour', 'round': 'minute'}"/>
|
||||
<span style="margin-right: 15px;">Total (Days)</span>
|
||||
<t t-esc="lines._convert_hours_to_days(sum(lines.mapped('unit_amount')))" t-options="{'widget': 'timesheet_uom'}">1 day</t>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -66,32 +71,28 @@
|
|||
<t t-set="show_record" t-value="len(docs.ids) == 1"/>
|
||||
<t t-set="title" t-value="docs._description"/>
|
||||
<t t-set="company" t-value="docs.company_id if len(docs) == 1 else docs.env.company"/>
|
||||
<t t-set="show_task" t-value="True"/>
|
||||
<t t-if="not from_project">
|
||||
<t t-set="show_task" t-value="False"/>
|
||||
<t t-set="timesheet_report_data" t-value="docs._get_timesheet_report_data()"/>
|
||||
<t t-set="timesheets_per_task" t-value="timesheet_report_data['timesheets_per_task']"/>
|
||||
<t t-set="subtask_ids_per_task_id" t-value="timesheet_report_data['subtask_ids_per_task_id']"/>
|
||||
</t>
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="web.internal_layout">
|
||||
<div class="page">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-if="from_project" t-set="show_task"
|
||||
t-value="bool(doc.timesheet_ids.task_id)"/>
|
||||
<div class="oe_structure"/>
|
||||
<div class="row mt8">
|
||||
<div class="col-12">
|
||||
<t t-if="doc.allow_timesheets and doc.timesheet_ids">
|
||||
<h1 class="my-4">
|
||||
<t t-if="not show_record">
|
||||
<t t-out="title"/>: <span t-field="doc.name"/>
|
||||
</t>
|
||||
</h1>
|
||||
<h2>
|
||||
<span>Timesheets
|
||||
<t t-if="show_record">
|
||||
for the <t t-out="doc.name"/> <t t-out="title"/>
|
||||
</t>
|
||||
</span>
|
||||
</h2>
|
||||
<t t-set='lines' t-value='doc.timesheet_ids'/>
|
||||
<t t-call="hr_timesheet.timesheet_table"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt8">
|
||||
<t t-set="lines" t-value="doc.timesheet_ids if from_project else timesheets_per_task.get(doc, doc.env['account.analytic.line'])"/>
|
||||
<h1 t-if="lines">
|
||||
<t t-out="title"/>: <t t-out="doc.name"/>
|
||||
</h1>
|
||||
<t t-if="lines" t-call="hr_timesheet.timesheet_table"/>
|
||||
<t t-if="not from_project">
|
||||
<t t-set="task_id" t-value="doc.id"/>
|
||||
<t t-call="hr_timesheet.timesheet_report_subtask"/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
|
@ -99,10 +100,25 @@
|
|||
</t>
|
||||
</template>
|
||||
|
||||
<template id="timesheet_report_subtask">
|
||||
<t t-set="subtasks" t-value="doc.browse(subtask_ids_per_task_id.get(task_id, []))"/>
|
||||
<t t-foreach="subtasks.sorted('sequence')" t-as="subtask">
|
||||
<t t-if="subtask in timesheets_per_task">
|
||||
<h2 class="my-4">
|
||||
Sub-Task of '<t t-out="doc.name"/>': <t t-out="subtask.name"/>
|
||||
</h2>
|
||||
<t t-set="lines" t-value="timesheets_per_task[subtask]"/>
|
||||
<t t-call="hr_timesheet.timesheet_table"/>
|
||||
</t>
|
||||
<t t-set="task_id" t-value="subtask.id"/>
|
||||
<t t-call="hr_timesheet.timesheet_report_subtask"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="report_timesheet">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="company" t-value="docs.project_id.company_id if len(docs.project_id) == 1 else docs.env.company"/>
|
||||
<t t-call="web.internal_layout">
|
||||
<t t-set="company" t-value="docs.project_id.sudo().company_id if len(docs.project_id) == 1 else docs.env.company"/>
|
||||
<t t-set="show_task" t-value="bool(docs.task_id)"/>
|
||||
<t t-set="show_project" t-value="len(docs.project_id) > 1"/>
|
||||
<div class="page">
|
||||
|
|
@ -112,7 +128,7 @@
|
|||
<h2>
|
||||
<span>Timesheets
|
||||
<t t-if="len(docs.project_id) == 1">
|
||||
for the <t t-out="docs.project_id.name"/> Project
|
||||
for the <t t-out="docs.project_id.sudo().name">Research and Development</t> Project
|
||||
</t>
|
||||
</span>
|
||||
</h2>
|
||||
|
|
@ -129,7 +145,7 @@
|
|||
<!-- Project Task Timesheet Report for given timesheets -->
|
||||
<template id="report_timesheet_task">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="web.internal_layout">
|
||||
<t t-set="company" t-value="docs.project_id.company_id if len(docs.project_id) == 1 else docs.env.company"/>
|
||||
<t t-set="show_task" t-value="len(docs.task_id) > 1"/>
|
||||
<t t-set="show_project" t-value="False"/>
|
||||
|
|
@ -172,6 +188,7 @@
|
|||
<record id="timesheet_report_task" model="ir.actions.report">
|
||||
<field name="name">Timesheets</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="group_ids" eval="[(4,ref('hr_timesheet.group_hr_timesheet_user'))]"/>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">hr_timesheet.report_project_task_timesheet</field>
|
||||
<field name="report_file">report_timesheet_task</field>
|
||||
|
|
@ -188,6 +205,7 @@
|
|||
<record id="timesheet_report_project" model="ir.actions.report">
|
||||
<field name="name">Timesheets</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="group_ids" eval="[(4,ref('hr_timesheet.group_hr_timesheet_user'))]"/>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">hr_timesheet.report_timesheet_project</field>
|
||||
<field name="report_file">report_timesheet_project</field>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from psycopg2 import sql
|
||||
|
||||
from odoo import api, tools, fields, models
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.sql import drop_view_if_exists, SQL
|
||||
|
||||
|
||||
class TimesheetsAnalysisReport(models.Model):
|
||||
_name = "timesheets.analysis.report"
|
||||
_name = 'timesheets.analysis.report'
|
||||
_inherit = ["hr.manager.department.report"]
|
||||
_description = "Timesheets Analysis Report"
|
||||
_auto = False
|
||||
|
||||
|
|
@ -14,15 +15,26 @@ class TimesheetsAnalysisReport(models.Model):
|
|||
user_id = fields.Many2one("res.users", string="User", readonly=True)
|
||||
project_id = fields.Many2one("project.project", string="Project", readonly=True)
|
||||
task_id = fields.Many2one("project.task", string="Task", readonly=True)
|
||||
ancestor_task_id = fields.Many2one("project.task", string="Ancestor Task", readonly=True)
|
||||
employee_id = fields.Many2one("hr.employee", string="Employee", readonly=True)
|
||||
parent_task_id = fields.Many2one("project.task", string="Parent Task", readonly=True)
|
||||
manager_id = fields.Many2one("hr.employee", "Manager", readonly=True)
|
||||
company_id = fields.Many2one("res.company", string="Company", readonly=True)
|
||||
department_id = fields.Many2one("hr.department", string="Department", readonly=True)
|
||||
currency_id = fields.Many2one('res.currency', string="Currency", readonly=True)
|
||||
date = fields.Date("Date", readonly=True)
|
||||
amount = fields.Monetary("Amount", readonly=True)
|
||||
unit_amount = fields.Float("Hours Spent", readonly=True)
|
||||
amount = fields.Monetary("Amount", currency_field="currency_id", readonly=True)
|
||||
unit_amount = fields.Float("Time Spent", readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string="Partner", readonly=True)
|
||||
milestone_id = fields.Many2one('project.milestone', related='task_id.milestone_id')
|
||||
message_partner_ids = fields.Many2many('res.partner', compute='_compute_message_partner_ids',
|
||||
search='_search_message_partner_ids', readonly=True)
|
||||
|
||||
@api.depends('project_id.message_partner_ids', 'task_id.message_partner_ids')
|
||||
def _compute_message_partner_ids(self):
|
||||
for line in self:
|
||||
line.message_partner_ids = line.task_id.message_partner_ids | line.project_id.message_partner_ids
|
||||
|
||||
def _search_message_partner_ids(self, operator, value):
|
||||
return self.env['account.analytic.line']._search_message_partner_ids(operator, value)
|
||||
|
||||
@property
|
||||
def _table_query(self):
|
||||
|
|
@ -37,7 +49,7 @@ class TimesheetsAnalysisReport(models.Model):
|
|||
A.user_id AS user_id,
|
||||
A.project_id AS project_id,
|
||||
A.task_id AS task_id,
|
||||
A.ancestor_task_id AS ancestor_task_id,
|
||||
A.parent_task_id AS parent_task_id,
|
||||
A.employee_id AS employee_id,
|
||||
A.manager_id AS manager_id,
|
||||
A.company_id AS company_id,
|
||||
|
|
@ -45,7 +57,8 @@ class TimesheetsAnalysisReport(models.Model):
|
|||
A.currency_id AS currency_id,
|
||||
A.date AS date,
|
||||
A.amount AS amount,
|
||||
A.unit_amount AS unit_amount
|
||||
A.unit_amount AS unit_amount,
|
||||
A.partner_id AS partner_id
|
||||
"""
|
||||
|
||||
@api.model
|
||||
|
|
@ -56,25 +69,6 @@ class TimesheetsAnalysisReport(models.Model):
|
|||
def _where(self):
|
||||
return "WHERE A.project_id IS NOT NULL"
|
||||
|
||||
@api.model
|
||||
def _get_view_cache_key(self, view_id=None, view_type='form', **options):
|
||||
"""The override of _get_view changing the time field labels according to the company timesheet encoding UOM
|
||||
makes the view cache dependent on the company timesheet encoding uom"""
|
||||
key = super()._get_view_cache_key(view_id, view_type, **options)
|
||||
return key + (self.env.company.timesheet_encode_uom_id,)
|
||||
|
||||
@api.model
|
||||
def _get_view(self, view_id=None, view_type='form', **options):
|
||||
arch, view = super()._get_view(view_id, view_type, **options)
|
||||
if view_type in ["pivot", "graph"] and self.env.company.timesheet_encode_uom_id == self.env.ref("uom.product_uom_day"):
|
||||
arch = self.env["account.analytic.line"]._apply_time_label(arch, related_model=self._name)
|
||||
return arch, view
|
||||
|
||||
def init(self):
|
||||
tools.drop_view_if_exists(self.env.cr, self._table)
|
||||
self.env.cr.execute(
|
||||
sql.SQL("CREATE or REPLACE VIEW {} as ({})").format(
|
||||
sql.Identifier(self._table),
|
||||
sql.SQL(self._table_query)
|
||||
)
|
||||
)
|
||||
drop_view_if_exists(self.env.cr, self._table)
|
||||
self.env.cr.execute(SQL("""CREATE or REPLACE VIEW %s as (%s)""", SQL.identifier(self._table), SQL(self._table_query)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue