From 30bc0ee07632196d2748e30ddbf97bd424e1ab8c Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 6 Jul 2016 00:14:44 +0200 Subject: [PATCH] [IMP] website_project_issue: Portal access to Issues Move portal features (mainly ir.rule) from project_issue to website_project_issue. Remove backend menu item, issues should be accessed from the website_portal My account page, the backend portal menuitem is removed. Add the dependency on website_portal to display the issue count on projects. Original authors: Vipul Bhatt, Florian Wintjens --- .../project_issue/models/project_project.py | 4 +- .../security/project_issue_security.xml | 32 +------ .../views/project_issue_view.xml | 22 ----- addons/website_project_issue/__openerp__.py | 9 +- .../website_project_issue/controllers/main.py | 73 ++++++++++----- .../security/portal_security.xml | 44 ++++----- .../tests/test_access_rights.py | 19 +--- .../views/project_issue_templates.xml | 91 +++++++++++++++---- 8 files changed, 153 insertions(+), 141 deletions(-) diff --git a/addons/project_issue/models/project_project.py b/addons/project_issue/models/project_project.py index acc0b37b1a4..583e9319e4b 100644 --- a/addons/project_issue/models/project_project.py +++ b/addons/project_issue/models/project_project.py @@ -19,8 +19,10 @@ class Project(models.Model): res.append(("project.issue", "Issues")) return res + @api.multi def _compute_issue_count(self): - self.issue_count = self.env['project.issue'].search_count([('project_id', '=', self.id), '|', ('stage_id.fold', '=', False), ('stage_id', '=', False)]) + for project in self: + project.issue_count = self.env['project.issue'].search_count([('project_id', '=', project.id), '|', ('stage_id.fold', '=', False), ('stage_id', '=', False)]) def _issue_needaction_count(self): issue_data = self.env['project.issue'].read_group([('project_id', 'in', self.ids), ('message_needaction', '=', True)], ['project_id'], ['project_id']) diff --git a/addons/project_issue/security/project_issue_security.xml b/addons/project_issue/security/project_issue_security.xml index f6608700ab9..8006d0f934f 100644 --- a/addons/project_issue/security/project_issue_security.xml +++ b/addons/project_issue/security/project_issue_security.xml @@ -10,40 +10,16 @@ - Project/Issue: employees: employee or (followers and following) + Project/Issue: employees: no need to follow or (following project or following issue ['|', - ('project_id.privacy_visibility', '=', 'employees'), - '&', - ('project_id.privacy_visibility', '=', 'followers'), + ('project_id.privacy_visibility', '!=', 'followers'), + '|', + ('project_id.message_partner_ids', 'in', [user.partner_id.id]), ('message_partner_ids', 'in', [user.partner_id.id]), ] - - Project/Issue: portal users: (portal and colleagues following) or (followers and following) - - ['|', - '&', - ('project_id.privacy_visibility', '=', 'portal'), - ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_partner_ids', 'in', [user.partner_id.id]), - ] - - - - - Project/Issue: employees: portal, employee or (followers and following) - ['|', - ('project_id.privacy_visibility', 'in', ['portal', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_partner_ids', 'in', [user.partner_id.id]), - ] - - diff --git a/addons/project_issue/views/project_issue_view.xml b/addons/project_issue/views/project_issue_view.xml index f897fd1f5db..ed29e2db2e8 100644 --- a/addons/project_issue/views/project_issue_view.xml +++ b/addons/project_issue/views/project_issue_view.xml @@ -267,26 +267,4 @@

- - - - Issues - project.issue - form - tree,form - - - {"search_default_user_id":'', "search_default_draft":'', "search_default_todo":'', "portal":'True'} - - current - -

- Click to create an issue. -

- You can track your issues from this menu and the action we will take. -

-
-
- diff --git a/addons/website_project_issue/__openerp__.py b/addons/website_project_issue/__openerp__.py index c17e64848f2..b7f02e20390 100644 --- a/addons/website_project_issue/__openerp__.py +++ b/addons/website_project_issue/__openerp__.py @@ -1,22 +1,19 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. - - { 'name': 'Website Project Issue', + 'category': 'Hidden', 'version': '0.1', 'complexity': 'easy', 'description': """ This module adds project issues inside your account's page on website if project_issue and website_portal are installed. ================================================================================================== """, - 'depends': ['project_issue', 'website_portal'], + 'depends': ['project_issue', 'website_project'], 'data': [ - 'security/portal_security.xml', + 'security/project_issue_security.xml', 'security/ir.model.access.csv', 'views/project_issue_templates.xml', ], - 'installable': True, 'auto_install': True, - 'category': 'Hidden', } diff --git a/addons/website_project_issue/controllers/main.py b/addons/website_project_issue/controllers/main.py index 4e8b4cd35ba..d81d9f69ff9 100644 --- a/addons/website_project_issue/controllers/main.py +++ b/addons/website_project_issue/controllers/main.py @@ -1,58 +1,83 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp import http + +from collections import OrderedDict + +from openerp import http, _ from openerp.addons.website_portal.controllers.main import website_account from openerp.http import request class WebsiteAccount(website_account): - @http.route() - def account(self): - response = super(WebsiteAccount, self).account() - # TDE FIXME: shouldn't that be mnaged by the access rule itself ? - # portal projects where you or someone from your company are a follower - user = request.env.user - issue_count = request.env['project.issue'].sudo().search_count([ - '&', - ('project_id.privacy_visibility', '=', 'portal'), - ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id, user.partner_id.id]) - ]) - response.qcontext.update({'issue_count': issue_count}) - return response + + def _prepare_portal_layout_values(self): + values = super(WebsiteAccount, self)._prepare_portal_layout_values() + # domain is needed to hide non portal project for employee + issue_count = request.env['project.issue'].search_count([('project_id.privacy_visibility','=','portal')]) + values.update({ + 'issue_count': issue_count, + }) + return values @http.route(['/my/issues', '/my/issues/page/'], type='http', auth="user", website=True) - def portal_my_issues(self, page=1, date_begin=None, date_end=None, **kw): + def my_issues(self, page=1, date_begin=None, date_end=None, project=None, sortby=None, **kw): values = self._prepare_portal_layout_values() - ProjectIssue = request.env['project.issue'] - domain = [] + + sortings = { + 'date': {'label': _('Newest'), 'order': 'create_date desc'}, + 'name': {'label': _('Name'), 'order': 'name'}, + 'stage': {'label': _('Stage'), 'order': 'stage_id'}, + 'update': {'label': _('Last Stage Update'), 'order': 'date_last_stage_update desc'}, + } + + projects = request.env['project.project'].search([('privacy_visibility','=','portal')]) + + project_filters = { + 'all': {'label': _('All'), 'domain': []}, + } + + for proj in projects: + project_filters.update({ + str(proj.id): {'label': proj.name, 'domain': [('project_id', '=', proj.id)]} + }) + + domain = [('project_id.privacy_visibility','=','portal')] + domain += project_filters.get(project, project_filters['all'])['domain'] + order = sortings.get(sortby, sortings['date'])['order'] + # archive groups - Default Group By 'create_date' archive_groups = self._get_archive_groups('project.issue', domain) if date_begin and date_end: - domain += [('create_date', '>=', date_begin), ('create_date', '<', date_end)] + domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)] # pager - issue_count = ProjectIssue.search_count(domain) pager = request.website.pager( url="/my/issues", url_args={'date_begin': date_begin, 'date_end': date_end}, - total=issue_count, + total=values['issue_count'], page=page, step=self._items_per_page ) # content according to pager and archive selected - project_issues = ProjectIssue.search(domain, order="stage_id", limit=self._items_per_page, offset=pager['offset']) + project_issues = request.env['project.issue'].search(domain, order=order, limit=self._items_per_page, offset=pager['offset']) values.update({ 'date': date_begin, + 'date_end': date_end, + 'project_filters': OrderedDict(sorted(project_filters.items())), + 'projects': projects, + 'project': project, + 'sortings': sortings, + 'sortby': sortby, 'issues': project_issues, 'page_name': 'issue', 'archive_groups': archive_groups, 'default_url': '/my/issues', 'pager': pager }) - return request.website.render("website_project_issue.portal_my_issues", values) + return request.website.render("website_project_issue.my_issues", values) @http.route(['/my/issues/'], type='http', auth="user", website=True) - def issues_followup(self, issue_id=None, **kw): + def my_issues_issue(self, issue_id=None, **kw): issue = request.env['project.issue'].browse(issue_id) - return request.website.render("website_project_issue.issues_followup", {'issue': issue}) + return request.website.render("website_project_issue.my_issues_issue", {'issue': issue}) diff --git a/addons/website_project_issue/security/portal_security.xml b/addons/website_project_issue/security/portal_security.xml index c30bd029f50..7699392344c 100644 --- a/addons/website_project_issue/security/portal_security.xml +++ b/addons/website_project_issue/security/portal_security.xml @@ -1,29 +1,21 @@ - - + + - - Project/Issue: portal users: (portal and colleagues following) or (followers and following) - - ['|', - '&', - ('project_id.privacy_visibility', '=', 'portal'), - ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_partner_ids', 'in', [user.partner_id.id]), - ] - - + + Project/Issue: portal users: (portal and (following project or following issue) + + [ + '|', + '&', + ('project_id.privacy_visibility', '=', 'portal'), + ('project_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + '&', + ('project_id.privacy_visibility', '=', 'portal'), + ('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + ] + + - - Project/Issue: employees: portal, employee or (followers and following) - ['|', - ('project_id.privacy_visibility', 'in', ['portal', 'employees']), - '&', - ('project_id.privacy_visibility', '=', 'followers'), - ('message_partner_ids', 'in', [user.partner_id.id]), - ] - - - + + diff --git a/addons/website_project_issue/tests/test_access_rights.py b/addons/website_project_issue/tests/test_access_rights.py index afa986aa08d..defdd6ff55c 100644 --- a/addons/website_project_issue/tests/test_access_rights.py +++ b/addons/website_project_issue/tests/test_access_rights.py @@ -84,18 +84,6 @@ class TestPortalIssue(TestPortalProjectBase): # ---------------------------------------- self.project_pigs.write({'privacy_visibility': 'followers'}) - # Do: Alfred reads project -> ko (employee ko followers) - # Test: no project issue visible - issues = Issue.sudo(self.user_projectuser.id).search([('project_id', '=', pigs_id)]) - self.assertEqual(set(issues.ids), set([self.issue_4.id]), - 'access rights: employee user should not see issues of a not-followed followers project, only assigned') - - # Do: Chell reads project -> ko (portal ko employee) - # Test: no project issue visible - issues = Issue.sudo(self.user_portal.id).search([('project_id', '=', pigs_id)]) - self.assertEqual(set(issues.ids), set([self.issue_5.id]), - 'access rights: portal user should not see issues of a not-followed followers project, only assigned') - # Data: subscribe Alfred, Chell and Donovan as follower self.project_pigs.message_subscribe_users(user_ids=[self.user_projectuser.id, self.user_portal.id, self.user_public.id]) self.issue_1.sudo(self.user_projectmanager.id).message_subscribe_users(user_ids=[self.user_portal.id, self.user_projectuser.id]) @@ -104,11 +92,12 @@ class TestPortalIssue(TestPortalProjectBase): # Do: Alfred reads project -> ok (follower ok followers) # Test: followed + assigned issues visible issues = Issue.sudo(self.user_projectuser.id).search([('project_id', '=', pigs_id)]) - self.assertEqual(set(issues.ids), set([self.issue_1.id, self.issue_3.id, self.issue_4.id]), + + self.assertEqual(set(issues.ids), test_issue_ids, 'access rights: employee user should not see followed + assigned issues of a follower project') # Do: Chell reads project -> ok (follower ok follower) # Test: followed + assigned issues visible issues = Issue.sudo(self.user_portal.id).search([('project_id', '=', pigs_id)]) - self.assertEqual(set(issues.ids), set([self.issue_1.id, self.issue_3.id, self.issue_5.id]), - 'access rights: employee user should not see followed + assigned issues of a follower project') + self.assertFalse(set(issues.ids), + 'access rights: portal user should not see issues of a follower project') diff --git a/addons/website_project_issue/views/project_issue_templates.xml b/addons/website_project_issue/views/project_issue_templates.xml index a0bdc8338a1..b1a0a93be43 100644 --- a/addons/website_project_issue/views/project_issue_templates.xml +++ b/addons/website_project_issue/views/project_issue_templates.xml @@ -1,7 +1,7 @@ -