[IMP] hr_timesheet: extend project update description
This commit adds content in the default project update description. The informations added are related to the timesheeted time on project or project tasks. PR : #68899 task-2393768
This commit is contained in:
@@ -29,6 +29,7 @@ up a management by affair.
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/project_views.xml',
|
||||
'views/project_portal_templates.xml',
|
||||
'views/project_update_templates.xml',
|
||||
'views/hr_timesheet_portal_templates.xml',
|
||||
'report/hr_timesheet_report_view.xml',
|
||||
'report/report_timesheet_templates.xml',
|
||||
|
||||
@@ -3671,4 +3671,22 @@
|
||||
<field name="amount">-90.0</field>
|
||||
</record>
|
||||
|
||||
<!-- Projects -->
|
||||
<record id="project.project_milestone_2" model="project.milestone">
|
||||
<field name="deadline" eval="(DateTime.now() + relativedelta(years=1, months=3)).strftime('%Y-%m-15')"/>
|
||||
</record>
|
||||
|
||||
<record id="project_update_1" model="project.update" context="{'default_project_id': ref('project.project_project_1')}">
|
||||
<field name="name">Weekly review</field>
|
||||
<field name="user_id" eval="ref('base.user_demo')"/>
|
||||
<field name="progress" eval="30"/>
|
||||
<field name="status">on_hold</field>
|
||||
</record>
|
||||
<record id="project_update_2" model="project.update" context="{'default_project_id': ref('project.project_project_2')}">
|
||||
<field name="name">Weekly review</field>
|
||||
<field name="user_id" eval="ref('base.user_admin')"/>
|
||||
<field name="progress" eval="30"/>
|
||||
<field name="status">off_track</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -7,4 +7,5 @@ from . import ir_http
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
from . import project
|
||||
from . import project_update
|
||||
from . import uom
|
||||
|
||||
@@ -98,6 +98,10 @@ class Project(models.Model):
|
||||
warning_msg, self.env.ref('hr_timesheet.timesheet_action_project').id,
|
||||
_('See timesheet entries'), {'active_ids': projects_with_timesheets.ids})
|
||||
|
||||
def _convert_project_uom_to_timesheet_encode_uom(self, time):
|
||||
uom_from = self.company_id.project_time_mode_id
|
||||
uom_to = self.env.company.timesheet_encode_uom_id
|
||||
return round(uom_from._compute_quantity(time, uom_to, raise_if_failure=False), 2)
|
||||
|
||||
class Task(models.Model):
|
||||
_name = "project.task"
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.misc import formatLang
|
||||
|
||||
class ProjectUpdate(models.Model):
|
||||
_inherit = 'project.update'
|
||||
|
||||
@api.model
|
||||
def _get_template_values(self, project):
|
||||
return {
|
||||
**super(ProjectUpdate, self)._get_template_values(project),
|
||||
'people': self._get_people_values(project),
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_people_values(self, project):
|
||||
return {
|
||||
'uom': self.env.company._timesheet_uom_text(),
|
||||
'is_uom_hour': self.env.company._is_timesheet_hour_uom(),
|
||||
'activities': self._get_activities(project)
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_activities(self, project):
|
||||
if not self.user_has_groups('hr_timesheet.group_hr_timesheet_user'):
|
||||
return []
|
||||
today = fields.Datetime.today()
|
||||
query = """
|
||||
SELECT timesheet.employee_id as employee_id,
|
||||
gs as period,
|
||||
sum(timesheet.unit_amount) as unit_amount,
|
||||
employee.name as name
|
||||
FROM project_project p
|
||||
INNER JOIN account_analytic_line timesheet
|
||||
ON timesheet.project_id = p.id
|
||||
INNER JOIN hr_employee employee
|
||||
ON timesheet.employee_id = employee.id
|
||||
CROSS JOIN generate_series(
|
||||
%(today)s::date - '180 days'::interval,
|
||||
%(today)s::date,
|
||||
'30 days'::interval
|
||||
) gs
|
||||
WHERE p.id = %(project_id)s
|
||||
AND gs >= timesheet.date
|
||||
AND gs - '30 days'::interval < timesheet.date
|
||||
GROUP BY timesheet.employee_id,
|
||||
gs, employee.name
|
||||
ORDER BY gs DESC, employee.name ASC
|
||||
"""
|
||||
self.env.cr.execute(query, {'project_id': project.id, 'today': today})
|
||||
results = self.env.cr.dictfetchall()
|
||||
activities = defaultdict(lambda: {
|
||||
'unit_amount': 0,
|
||||
'worked': False,
|
||||
})
|
||||
digits = not self.env.company._is_timesheet_hour_uom() and 2 or 0
|
||||
for result in results:
|
||||
if result['period'] == today:
|
||||
activities[result['employee_id']] = {
|
||||
'name': result['name'],
|
||||
'unit_amount': formatLang(self.env, project._convert_project_uom_to_timesheet_encode_uom(result['unit_amount']), digits=digits),
|
||||
'worked': True,
|
||||
'new': True,
|
||||
}
|
||||
else:
|
||||
name = activities[result['employee_id']].get('name', result['name'])
|
||||
activities[result['employee_id']].update(name=name, new=False)
|
||||
return list(activities.values())
|
||||
@@ -63,3 +63,9 @@ class ResCompany(models.Model):
|
||||
}]
|
||||
project_ids = self.env['project.project'].create(results)
|
||||
return project_ids
|
||||
|
||||
def _is_timesheet_hour_uom(self):
|
||||
return self.timesheet_encode_uom_id and self.timesheet_encode_uom_id == self.env.ref('uom.product_uom_hour')
|
||||
|
||||
def _timesheet_uom_text(self):
|
||||
return self._is_timesheet_hour_uom() and _("hours") or _("days")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<template id="project_update_default_description" inherit_id="project.project_update_default_description">
|
||||
<xpath expr="//div[@name='milestone']" position="after">
|
||||
<t t-if="project.allow_timesheets and people['activities'] and user.has_group('hr_timesheet.group_hr_timesheet_approver')">
|
||||
<hr/>
|
||||
<div name="people">
|
||||
<h1>People</h1>
|
||||
|
||||
Activities of the past 30 days:
|
||||
<ul>
|
||||
<t t-foreach="people['activities']" t-as="activity">
|
||||
<li><span class="fa-li"><i class="fa" t-att-class="{'fa-check-square': activity['worked'], 'fa-square-o': not activity['worked']}"></i></span>
|
||||
<t t-if="activity['worked']">
|
||||
<t t-esc="activity['name']"/>:
|
||||
<t t-esc="activity['unit_amount']" />
|
||||
<t t-esc="people['uom']"/>
|
||||
<span t-if="activity['new']" class="text-success">
|
||||
<font style="color: rgb(0, 128, 0);">
|
||||
<b>(new this month)</b>
|
||||
</font>
|
||||
</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<s><t t-esc="activity['name']"/></s> <span class="text-muted"><font style="color: rgb(128, 128, 128);"><b>(no activity in past 30 days)</b></font></span>
|
||||
</t>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user