summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorPriyanka Kakadiya <pka@odoo.com>2019-05-10 11:09:54 +0000
committerPriyanka Kakadiya <pka@odoo.com>2019-06-14 04:49:21 +0000
commitd74ee9a0cf6d72d5433bd213050c9b2846de0ea7 (patch)
tree266d79c27eeff46c4500715e1dd9a524aef2a9e6 /addons
parent562997b2bc0b55f92177952fff3160c762b3e6bb (diff)
[IMP] hr_timesheet: added a timesheet for portal user
Purpose of the commit is to add a timesheet section on portal where you can see all the timesheets and user can see and use the filter options on them (available when only hr_timesheet is installed) task-1932488
Diffstat (limited to 'addons')
-rw-r--r--addons/hr_timesheet/__init__.py1
-rw-r--r--addons/hr_timesheet/__manifest__.py1
-rw-r--r--addons/hr_timesheet/controllers/__init__.py5
-rw-r--r--addons/hr_timesheet/controllers/portal.py106
-rw-r--r--addons/hr_timesheet/controllers/project.py18
-rw-r--r--addons/hr_timesheet/models/hr_timesheet.py8
-rw-r--r--addons/hr_timesheet/views/hr_timesheet_portal_templates.xml64
-rw-r--r--addons/hr_timesheet/views/project_portal_templates.xml38
8 files changed, 224 insertions, 17 deletions
diff --git a/addons/hr_timesheet/__init__.py b/addons/hr_timesheet/__init__.py
index 2609681a938..5905766d867 100644
--- a/addons/hr_timesheet/__init__.py
+++ b/addons/hr_timesheet/__init__.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from . import controllers
from . import models
from . import report
diff --git a/addons/hr_timesheet/__manifest__.py b/addons/hr_timesheet/__manifest__.py
index 22af4117533..d80c3769250 100644
--- a/addons/hr_timesheet/__manifest__.py
+++ b/addons/hr_timesheet/__manifest__.py
@@ -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/hr_timesheet_portal_templates.xml',
'report/hr_timesheet_report_view.xml',
'report/report_timesheet_templates.xml',
'views/hr_views.xml',
diff --git a/addons/hr_timesheet/controllers/__init__.py b/addons/hr_timesheet/controllers/__init__.py
new file mode 100644
index 00000000000..86c009b5649
--- /dev/null
+++ b/addons/hr_timesheet/controllers/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import portal
+from . import project
diff --git a/addons/hr_timesheet/controllers/portal.py b/addons/hr_timesheet/controllers/portal.py
new file mode 100644
index 00000000000..9fd6ac942fc
--- /dev/null
+++ b/addons/hr_timesheet/controllers/portal.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from collections import OrderedDict
+from dateutil.relativedelta import relativedelta
+from operator import itemgetter
+
+from odoo import fields, http, _
+from odoo.http import request
+from odoo.tools import date_utils, groupby as groupbyelem
+from odoo.osv.expression import AND
+
+from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
+
+
+class TimesheetCustomerPortal(CustomerPortal):
+
+ def _prepare_portal_layout_values(self):
+ values = super(TimesheetCustomerPortal, self)._prepare_portal_layout_values()
+ domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
+ values['timesheet_count'] = request.env['account.analytic.line'].sudo().search_count(domain)
+ return values
+
+ @http.route(['/my/timesheets', '/my/timesheets/page/<int:page>'], type='http', auth="user", website=True)
+ def portal_my_timesheets(self, page=1, sortby=None, filterby=None, search=None, search_in='all', groupby='project', **kw):
+ Timesheet_sudo = request.env['account.analytic.line'].sudo()
+ values = self._prepare_portal_layout_values()
+ domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
+
+ searchbar_sortings = {
+ 'date': {'label': _('Newest'), 'order': 'date desc'},
+ 'name': {'label': _('Name'), 'order': 'name'},
+ }
+
+ searchbar_inputs = {
+ 'all': {'input': 'all', 'label': _('Search in All')},
+ }
+
+ searchbar_groupby = {
+ 'none': {'input': 'none', 'label': _('None')},
+ 'project': {'input': 'project', 'label': _('Project')},
+ }
+
+ today = fields.Date.today()
+ quarter_start, quarter_end = date_utils.get_quarter(today)
+ last_week = today + relativedelta(weeks=-1)
+ last_month = today + relativedelta(months=-1)
+ last_year = today + relativedelta(years=-1)
+
+ searchbar_filters = {
+ 'all': {'label': _('All'), 'domain': []},
+ 'today': {'label': _('Today'), 'domain': [("date", "=", today)]},
+ 'week': {'label': _('This week'), 'domain': [('date', '>=', date_utils.start_of(today, "week")), ('date', '<=', date_utils.end_of(today, 'week'))]},
+ 'month': {'label': _('This month'), 'domain': [('date', '>=', date_utils.start_of(today, 'month')), ('date', '<=', date_utils.end_of(today, 'month'))]},
+ 'year': {'label': _('This year'), 'domain': [('date', '>=', date_utils.start_of(today, 'year')), ('date', '<=', date_utils.end_of(today, 'year'))]},
+ 'quarter': {'label': _('This Quarter'), 'domain': [('date', '>=', quarter_start), ('date', '<=', quarter_end)]},
+ 'last_week': {'label': _('Last week'), 'domain': [('date', '>=', date_utils.start_of(last_week, "week")), ('date', '<=', date_utils.end_of(last_week, 'week'))]},
+ 'last_month': {'label': _('Last month'), 'domain': [('date', '>=', date_utils.start_of(last_month, 'month')), ('date', '<=', date_utils.end_of(last_month, 'month'))]},
+ 'last_year': {'label': _('Last year'), 'domain': [('date', '>=', date_utils.start_of(last_year, 'year')), ('date', '<=', date_utils.end_of(last_year, 'year'))]},
+ }
+ # default sort by value
+ if not sortby:
+ sortby = 'date'
+ order = searchbar_sortings[sortby]['order']
+ # default filter by value
+ if not filterby:
+ filterby = 'all'
+ domain = AND([domain, searchbar_filters[filterby]['domain']])
+
+ if search and search_in:
+ domain = AND([domain, [('name', 'ilike', search)]])
+
+ timesheet_count = Timesheet_sudo.search_count(domain)
+ # pager
+ pager = portal_pager(
+ url="/my/timesheets",
+ url_args={'sortby': sortby, 'search_in': search_in, 'search': search, 'filterby': filterby},
+ total=timesheet_count,
+ page=page,
+ step=self._items_per_page
+ )
+
+ if groupby == 'project':
+ order = "project_id, %s" % order
+ timesheets = Timesheet_sudo.search(domain, order=order, limit=self._items_per_page, offset=pager['offset'])
+ if groupby == 'project':
+ grouped_timesheets = [Timesheet_sudo.concat(*g) for k, g in groupbyelem(timesheets, itemgetter('project_id'))]
+ else:
+ grouped_timesheets = [timesheets]
+
+ values.update({
+ 'timesheets': timesheets,
+ 'grouped_timesheets': grouped_timesheets,
+ 'page_name': 'timesheet',
+ 'default_url': '/my/timesheets',
+ 'pager': pager,
+ 'searchbar_sortings': searchbar_sortings,
+ 'search_in': search_in,
+ 'sortby': sortby,
+ 'groupby': groupby,
+ 'searchbar_inputs': searchbar_inputs,
+ 'searchbar_groupby': searchbar_groupby,
+ 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
+ 'filterby': filterby,
+ })
+ return request.render("hr_timesheet.portal_my_timesheets", values)
diff --git a/addons/hr_timesheet/controllers/project.py b/addons/hr_timesheet/controllers/project.py
new file mode 100644
index 00000000000..bc321ab98fa
--- /dev/null
+++ b/addons/hr_timesheet/controllers/project.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.http import request
+from odoo.osv import expression
+
+from odoo.addons.project.controllers.portal import CustomerPortal
+
+
+class ProjectCustomerPortal(CustomerPortal):
+
+ def _task_get_page_view_values(self, task, access_token, **kwargs):
+ values = super(ProjectCustomerPortal, self)._task_get_page_view_values(task, access_token, **kwargs)
+ domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
+ domain = expression.AND([domain, [('task_id', '=', task.id)]])
+ timesheets = request.env['account.analytic.line'].sudo().search(domain)
+ values['timesheets'] = timesheets
+ return values
diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py
index ce2abd5f871..200b4a0a84e 100644
--- a/addons/hr_timesheet/models/hr_timesheet.py
+++ b/addons/hr_timesheet/models/hr_timesheet.py
@@ -102,6 +102,14 @@ class AccountAnalyticLine(models.Model):
# Business Methods
# ----------------------------------------------------
+ def _timesheet_get_portal_domain(self):
+ return ['|', '&',
+ ('task_id.project_id.privacy_visibility', '=', 'portal'),
+ ('task_id.project_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id]),
+ '&',
+ ('task_id.project_id.privacy_visibility', '=', 'portal'),
+ ('task_id.message_partner_ids', 'child_of', [self.env.user.partner_id.commercial_partner_id.id])]
+
def _timesheet_preprocess(self, vals):
""" Deduce other field values from the one given.
Overrride this to compute on the fly some field that can not be computed fields.
diff --git a/addons/hr_timesheet/views/hr_timesheet_portal_templates.xml b/addons/hr_timesheet/views/hr_timesheet_portal_templates.xml
new file mode 100644
index 00000000000..939c306767f
--- /dev/null
+++ b/addons/hr_timesheet/views/hr_timesheet_portal_templates.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <template id="portal_layout" name="Portal layout: timesheet menu entry" inherit_id="portal.portal_breadcrumbs" priority="35">
+ <xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
+ <li t-if="page_name == 'timesheet' or timesheet" t-attf-class="breadcrumb-item #{'active' if not timesheet else ''}">
+ <t>Timesheets</t>
+ </li>
+ </xpath>
+ </template>
+
+ <template id="portal_my_home_timesheet" name="Portal My Home : timesheets entries" inherit_id="portal.portal_my_home" priority="45">
+ <xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
+ <t t-if="timesheet_count" t-call="portal.portal_docs_entry">
+ <t t-set="title">Timesheets</t>
+ <t t-set="url" t-value="'/my/timesheets'"/>
+ <t t-set="count" t-value="timesheet_count"/>
+ </t>
+ </xpath>
+ </template>
+
+ <template id="portal_my_timesheets" name="My Timesheets">
+ <t t-call="portal.portal_layout">
+ <t t-set="breadcrumbs_searchbar" t-value="True"/>
+
+ <t t-call="portal.portal_searchbar">
+ <t t-set="title">Timesheets</t>
+ </t>
+ <t t-if="not grouped_timesheets">
+ <div class="alert alert-warning mt8" role="alert">
+ There are no timesheets.
+ </div>
+ </t>
+ <t t-if="grouped_timesheets">
+ <t t-call="portal.portal_table">
+ <t t-foreach="grouped_timesheets" t-as="timesheets">
+ <thead>
+ <tr t-attf-class="{{'thead-light' if not groupby == 'none' else ''}}">
+ <th t-if="groupby == 'none'">Description</th>
+ <th t-else="">
+ <em class="font-weight-normal text-muted">Timesheets for project:</em>
+ <span t-field="timesheets[0].project_id.name"/></th>
+ <th>Date</th>
+ <th>Employee</th>
+ <th class="text-right">Duration</th>
+ </tr>
+ </thead>
+ <tbody>
+ <t t-foreach="timesheets" t-as="timesheet">
+ <tr>
+ <td><span t-esc="timesheet.name"/></td>
+ <td><span t-field="timesheet.date" t-options='{"widget": "date"}'/></td>
+ <td><span t-field="timesheet.employee_id"/></td>
+ <td class="text-right"><span t-field="timesheet.unit_amount" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/></td>
+ </tr>
+ </t>
+ </tbody>
+ </t>
+ </t>
+ </t>
+ </t>
+ </template>
+
+</odoo>
diff --git a/addons/hr_timesheet/views/project_portal_templates.xml b/addons/hr_timesheet/views/project_portal_templates.xml
index 27f68907def..8a3e6ff2ad0 100644
--- a/addons/hr_timesheet/views/project_portal_templates.xml
+++ b/addons/hr_timesheet/views/project_portal_templates.xml
@@ -3,27 +3,31 @@
<template id="portal_my_task" inherit_id="project.portal_my_task" name="Portal: My Task with Timesheets">
<xpath expr="//t[@t-set='card_body']" position="inside">
- <div class="container" t-if="task.timesheet_ids">
+ <div class="container" t-if="timesheets">
<hr class="mt-4 mb-1"/>
<h5 class="mt-2 mb-2">Timesheets</h5>
- <table class="table table-sm">
- <thead>
- <tr>
- <th>Date</th>
- <th>Description</th>
- <th>Responsible</th>
- <th class="text-right">Duration</th>
- </tr>
- </thead>
- <tr t-foreach="task.timesheet_ids" t-as="timesheet">
- <td><t t-esc="timesheet.date"/></td>
- <td><t t-esc="timesheet.name"/></td>
- <td><t t-esc="timesheet.sudo().user_id.name"/></td>
- <td class="text-right"><span t-field="timesheet.unit_amount" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/></td>
- </tr>
- </table>
+ <t t-call="hr_timesheet.portal_timesheet_table"/>
</div>
</xpath>
</template>
+ <template id="portal_timesheet_table" name="Portal Timesheet Table">
+ <table class="table table-sm">
+ <thead>
+ <tr>
+ <th>Date</th>
+ <th>Description</th>
+ <th>Employee</th>
+ <th class="text-right">Duration</th>
+ </tr>
+ </thead>
+ <tr t-foreach="timesheets" t-as="timesheet">
+ <td><t t-esc="timesheet.date" t-options='{"widget": "date"}'/></td>
+ <td><t t-esc="timesheet.name"/></td>
+ <td><t t-esc="timesheet.employee_id.name"/></td>
+ <td class="text-right"><span t-field="timesheet.unit_amount" t-options='{"widget": "duration", "unit": "hour", "round": "minute"}'/></td>
+ </tr>
+ </table>
+ </template>
+
</odoo>