portal.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from collections import OrderedDict
  4. from dateutil.relativedelta import relativedelta
  5. from operator import itemgetter
  6. from odoo import fields, http, _
  7. from odoo.http import request
  8. from odoo.tools import date_utils, groupby as groupbyelem
  9. from odoo.osv.expression import AND, OR
  10. from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
  11. from odoo.addons.project.controllers.portal import ProjectCustomerPortal
  12. class TimesheetCustomerPortal(CustomerPortal):
  13. def _prepare_home_portal_values(self, counters):
  14. values = super()._prepare_home_portal_values(counters)
  15. if 'timesheet_count' in counters:
  16. Timesheet = request.env['account.analytic.line']
  17. domain = Timesheet._timesheet_get_portal_domain()
  18. values['timesheet_count'] = Timesheet.sudo().search_count(domain)
  19. return values
  20. def _get_searchbar_inputs(self):
  21. return {
  22. 'all': {'input': 'all', 'label': _('Search in All')},
  23. 'employee': {'input': 'employee', 'label': _('Search in Employee')},
  24. 'project': {'input': 'project', 'label': _('Search in Project')},
  25. 'task': {'input': 'task', 'label': _('Search in Task')},
  26. 'name': {'input': 'name', 'label': _('Search in Description')},
  27. }
  28. def _task_get_searchbar_sortings(self, milestones_allowed):
  29. values = super()._task_get_searchbar_sortings(milestones_allowed)
  30. values['progress'] = {'label': _('Progress'), 'order': 'progress asc', 'sequence': 10}
  31. return values
  32. def _get_searchbar_groupby(self):
  33. return {
  34. 'none': {'input': 'none', 'label': _('None')},
  35. 'project': {'input': 'project', 'label': _('Project')},
  36. 'task': {'input': 'task', 'label': _('Task')},
  37. 'date': {'input': 'date', 'label': _('Date')},
  38. 'employee': {'input': 'employee', 'label': _('Employee')}
  39. }
  40. def _get_search_domain(self, search_in, search):
  41. search_domain = []
  42. if search_in in ('project', 'all'):
  43. search_domain = OR([search_domain, [('project_id', 'ilike', search)]])
  44. if search_in in ('name', 'all'):
  45. search_domain = OR([search_domain, [('name', 'ilike', search)]])
  46. if search_in in ('employee', 'all'):
  47. search_domain = OR([search_domain, [('employee_id', 'ilike', search)]])
  48. if search_in in ('task', 'all'):
  49. search_domain = OR([search_domain, [('task_id', 'ilike', search)]])
  50. return search_domain
  51. def _get_groupby_mapping(self):
  52. return {
  53. 'project': 'project_id',
  54. 'task': 'task_id',
  55. 'employee': 'employee_id',
  56. 'date': 'date'
  57. }
  58. def _get_searchbar_sortings(self):
  59. return {
  60. 'date': {'label': _('Newest'), 'order': 'date desc'},
  61. 'employee': {'label': _('Employee'), 'order': 'employee_id'},
  62. 'project': {'label': _('Project'), 'order': 'project_id'},
  63. 'task': {'label': _('Task'), 'order': 'task_id'},
  64. 'name': {'label': _('Description'), 'order': 'name'},
  65. }
  66. @http.route(['/my/timesheets', '/my/timesheets/page/<int:page>'], type='http', auth="user", website=True)
  67. def portal_my_timesheets(self, page=1, sortby=None, filterby=None, search=None, search_in='all', groupby='none', **kw):
  68. Timesheet = request.env['account.analytic.line']
  69. domain = Timesheet._timesheet_get_portal_domain()
  70. Timesheet_sudo = Timesheet.sudo()
  71. values = self._prepare_portal_layout_values()
  72. _items_per_page = 100
  73. searchbar_sortings = self._get_searchbar_sortings()
  74. searchbar_inputs = self._get_searchbar_inputs()
  75. searchbar_groupby = self._get_searchbar_groupby()
  76. today = fields.Date.today()
  77. quarter_start, quarter_end = date_utils.get_quarter(today)
  78. last_week = today + relativedelta(weeks=-1)
  79. last_month = today + relativedelta(months=-1)
  80. last_year = today + relativedelta(years=-1)
  81. searchbar_filters = {
  82. 'all': {'label': _('All'), 'domain': []},
  83. 'today': {'label': _('Today'), 'domain': [("date", "=", today)]},
  84. 'week': {'label': _('This week'), 'domain': [('date', '>=', date_utils.start_of(today, "week")), ('date', '<=', date_utils.end_of(today, 'week'))]},
  85. 'month': {'label': _('This month'), 'domain': [('date', '>=', date_utils.start_of(today, 'month')), ('date', '<=', date_utils.end_of(today, 'month'))]},
  86. 'year': {'label': _('This year'), 'domain': [('date', '>=', date_utils.start_of(today, 'year')), ('date', '<=', date_utils.end_of(today, 'year'))]},
  87. 'quarter': {'label': _('This Quarter'), 'domain': [('date', '>=', quarter_start), ('date', '<=', quarter_end)]},
  88. 'last_week': {'label': _('Last week'), 'domain': [('date', '>=', date_utils.start_of(last_week, "week")), ('date', '<=', date_utils.end_of(last_week, 'week'))]},
  89. 'last_month': {'label': _('Last month'), 'domain': [('date', '>=', date_utils.start_of(last_month, 'month')), ('date', '<=', date_utils.end_of(last_month, 'month'))]},
  90. 'last_year': {'label': _('Last year'), 'domain': [('date', '>=', date_utils.start_of(last_year, 'year')), ('date', '<=', date_utils.end_of(last_year, 'year'))]},
  91. }
  92. # default sort by value
  93. if not sortby:
  94. sortby = 'date'
  95. order = searchbar_sortings[sortby]['order']
  96. # default filter by value
  97. if not filterby:
  98. filterby = 'all'
  99. domain = AND([domain, searchbar_filters[filterby]['domain']])
  100. if search and search_in:
  101. domain += self._get_search_domain(search_in, search)
  102. timesheet_count = Timesheet_sudo.search_count(domain)
  103. # pager
  104. pager = portal_pager(
  105. url="/my/timesheets",
  106. url_args={'sortby': sortby, 'search_in': search_in, 'search': search, 'filterby': filterby, 'groupby': groupby},
  107. total=timesheet_count,
  108. page=page,
  109. step=_items_per_page
  110. )
  111. def get_timesheets():
  112. groupby_mapping = self._get_groupby_mapping()
  113. field = groupby_mapping.get(groupby, None)
  114. orderby = '%s, %s' % (field, order) if field else order
  115. timesheets = Timesheet_sudo.search(domain, order=orderby, limit=_items_per_page, offset=pager['offset'])
  116. if field:
  117. if groupby == 'date':
  118. raw_timesheets_group = Timesheet_sudo.read_group(
  119. domain, ["unit_amount:sum", "ids:array_agg(id)"], ["date:day"]
  120. )
  121. grouped_timesheets = [(Timesheet_sudo.browse(group["ids"]), group["unit_amount"]) for group in raw_timesheets_group]
  122. else:
  123. time_data = Timesheet_sudo.read_group(domain, [field, 'unit_amount:sum'], [field])
  124. mapped_time = dict([(m[field][0] if m[field] else False, m['unit_amount']) for m in time_data])
  125. grouped_timesheets = [(Timesheet_sudo.concat(*g), mapped_time[k.id]) for k, g in groupbyelem(timesheets, itemgetter(field))]
  126. return timesheets, grouped_timesheets
  127. grouped_timesheets = [(
  128. timesheets,
  129. sum(Timesheet_sudo.search(domain).mapped('unit_amount'))
  130. )] if timesheets else []
  131. return timesheets, grouped_timesheets
  132. timesheets, grouped_timesheets = get_timesheets()
  133. values.update({
  134. 'timesheets': timesheets,
  135. 'grouped_timesheets': grouped_timesheets,
  136. 'page_name': 'timesheet',
  137. 'default_url': '/my/timesheets',
  138. 'pager': pager,
  139. 'searchbar_sortings': searchbar_sortings,
  140. 'search_in': search_in,
  141. 'search': search,
  142. 'sortby': sortby,
  143. 'groupby': groupby,
  144. 'searchbar_inputs': searchbar_inputs,
  145. 'searchbar_groupby': searchbar_groupby,
  146. 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
  147. 'filterby': filterby,
  148. 'is_uom_day': request.env['account.analytic.line']._is_timesheet_encode_uom_day(),
  149. })
  150. return request.render("hr_timesheet.portal_my_timesheets", values)
  151. class TimesheetProjectCustomerPortal(ProjectCustomerPortal):
  152. def _show_task_report(self, task_sudo, report_type, download):
  153. domain = request.env['account.analytic.line']._timesheet_get_portal_domain()
  154. task_domain = AND([domain, [('task_id', '=', task_sudo.id)]])
  155. timesheets = request.env['account.analytic.line'].sudo().search(task_domain)
  156. return self._show_report(model=timesheets,
  157. report_type=report_type, report_ref='hr_timesheet.timesheet_report_task_timesheets', download=download)