Skip to content

Commit e522d9b

Browse files
author
Clément Mombereau
committed
[ADD] new module project_customer_access
1 parent a1c0eb3 commit e522d9b

14 files changed

Lines changed: 676 additions & 0 deletions

project_customer_access/README.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
=======================
2+
Project Customer Access
3+
=======================
4+
5+
Project menu and views for customers in your own ERP
6+
7+
Purpose
8+
=======
9+
10+
This module does this and that...
11+
12+
Explain the use case.
13+
14+
Configuration
15+
=============
16+
17+
To configure this module, you need to:
18+
19+
#. Go to ...
20+
21+
Usage
22+
=====
23+
24+
To use this module, you need to:
25+
26+
#. Go to ...
27+
28+
29+
How to test
30+
===========
31+
32+
...
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2024 Akretion
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
{
5+
"name": "Project Customer Access",
6+
"summary": """Project menu and views for customers in your own ERP""",
7+
"version": "16.0.1.0.0",
8+
"license": "AGPL-3",
9+
"author": "Akretion",
10+
"website": "http://akretion.com",
11+
"depends": [
12+
"project",
13+
# https://github.com/OCA/server-backend
14+
"base_group_backend",
15+
# https://github.com/OCA/server-auth
16+
"cross_connect_server",
17+
],
18+
"data": [
19+
"data/res_groups.xml",
20+
"security/ir.model.access.csv",
21+
"security/project_customer_access_security.xml",
22+
"views/project_task_views.xml",
23+
],
24+
"demo": ["data/project_customer_access_demo.xml"],
25+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<data>
4+
5+
<record id="endpoint_1" model="fastapi.endpoint">
6+
<field name="name">Cross Connect Server Endpoint Demo</field>
7+
<field name="root_path">/api</field>
8+
<field name="app">cross_connect</field>
9+
</record>
10+
11+
<record id="cross_connect_client_1" model="cross.connect.client">
12+
<field name="name">Test Client</field>
13+
<field name="endpoint_id" ref="endpoint_1"/>
14+
<field name="api_key">server-api-key</field>
15+
</record>
16+
17+
</data>
18+
</odoo>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<odoo>
2+
3+
<record id="project_access_category" model="ir.module.category">
4+
<field name="name">Project Access</field>
5+
<field name="sequence">90</field>
6+
</record>
7+
<record id="group_customer" model="res.groups">
8+
<field name="name">Customer</field>
9+
<field name="category_id" ref="project_customer_access.project_access_category"/>
10+
<field name="implied_ids" eval="[(4, ref('base_group_backend.group_backend_ui_users'))]"/>
11+
</record>
12+
<record id="group_manager" model="res.groups">
13+
<field name="name">Manager</field>
14+
<field name="category_id" ref="project_customer_access.project_access_category"/>
15+
<field name="implied_ids" eval="[(4, ref('project_customer_access.group_customer'))]"/>
16+
</record>
17+
18+
</odoo>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import project
2+
from . import res_users
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Copyright 2024 Akretion
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
import json
5+
6+
from lxml import etree
7+
from odoo.exceptions import AccessError
8+
from odoo import _, api, fields, models
9+
10+
11+
class ProjectProject(models.Model):
12+
_inherit = "project.project"
13+
14+
cross_connect_client_id = fields.Many2one("cross.connect.client")
15+
16+
17+
class ProjectTask(models.Model):
18+
_inherit = "project.task"
19+
20+
# TODO: add explicit Error message on create if no project selected
21+
# by customer instead of ir.rule Error message
22+
23+
def _get_customer_access_view_ids(self):
24+
form_id = self.env.ref("project_customer_access.view_task_form")
25+
kanban_id = self.env.ref("project_customer_access.view_task_kanban")
26+
return form_id | kanban_id
27+
28+
def _get_editable_fields_customer(self):
29+
return ["name", "description"]
30+
31+
def _get_editable_fields_manager(self):
32+
return ["name", "description", "tag_ids", "stage_id", "project_id"]
33+
34+
def _get_readonly_value(self, field):
35+
field_name = field.attrib.get("name")
36+
37+
if self.env.user.has_group("project_customer_access.group_manager"):
38+
return field_name not in self._get_editable_fields_manager()
39+
40+
elif self.env.user.has_group("project_customer_access.group_customer"):
41+
if field_name == "project_id":
42+
# project_id must be readonly only after creation
43+
return [("create_date", "!=", False)]
44+
elif field_name in self._get_editable_fields_customer():
45+
# Allows the customers who are not manager to modify only their tasks
46+
return [("user_ids", "not in", self.env.user.id)]
47+
else:
48+
return True
49+
50+
else:
51+
return True
52+
53+
@api.model
54+
def get_view(self, view_id=None, view_type="form", **options):
55+
res = super().get_view(view_id=view_id, view_type=view_type, **options)
56+
customer_access_view_ids = self._get_customer_access_view_ids()
57+
58+
if view_id in customer_access_view_ids.ids:
59+
doc = etree.XML(res["arch"])
60+
61+
for field in doc.xpath("//field[@name][not(ancestor::field)]"):
62+
modifiers = json.loads(
63+
field.attrib.get("modifiers", '{"readonly": false}')
64+
)
65+
if modifiers.get("readonly") is not True:
66+
modifiers["readonly"] = self._get_readonly_value(field)
67+
68+
field.attrib["modifiers"] = json.dumps(modifiers)
69+
70+
res["arch"] = etree.tostring(doc, pretty_print=True)
71+
72+
return res
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2024 Akretion
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import _, api, fields, models
5+
6+
7+
class ResUsers(models.Model):
8+
_inherit = "res.users"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2+
access_customer_project,access_customer_project,project.model_project_project,project_customer_access.group_customer,1,0,0,0
3+
access_customer_task,access_customer_task,project.model_project_task,project_customer_access.group_customer,1,1,1,0
4+
access_customer_task_type,access_customer_task_type,project.model_project_task_type,project_customer_access.group_customer,1,0,0,0
5+
access_customer_internal_task_type,access_customer_internal_task_type,project.model_project_task_stage_personal,project_customer_access.group_customer,1,1,0,0
6+
access_customer_task_rating,access_customer_task_rating,rating.model_rating_rating,project_customer_access.group_customer,1,0,0,0
7+
access_project_customer_manager,access_project_customer_manager,project.model_project_task,project_customer_access.group_manager,1,1,1,1
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<data noupdate="1">
4+
5+
<record id="rule_project_customer_access_tasks" model="ir.rule">
6+
<field name="name">Project Customer Access: Tasks</field>
7+
<field name="model_id" ref="project.model_project_task"/>
8+
<field name="domain_force">
9+
[('project_id.cross_connect_client_id', '=', user.cross_connect_client_id.id)]
10+
</field>
11+
<field name="perm_create" eval="0" />
12+
<field name="perm_read" eval="1" />
13+
<field name="perm_write" eval="0" />
14+
<field name="perm_unlink" eval="0" />
15+
<field name="groups" eval="[(4,ref('project_customer_access.group_customer'))]"/>
16+
</record>
17+
18+
<!-- <record id="rule_project_customer_access_customer_read" model="ir.rule">
19+
<field name="name">Project Customer Access Tasks: Customer read</field>
20+
<field name="model_id" ref="project.model_project_task"/>
21+
<field name="domain_force">
22+
[('project_id.cross_connect_client_id', '=', user.cross_connect_client_id.id)]
23+
</field>
24+
<field name="perm_create" eval="0" />
25+
<field name="perm_read" eval="1" />
26+
<field name="perm_write" eval="0" />
27+
<field name="perm_unlink" eval="0" />
28+
<field name="groups" eval="[(4,ref('project_customer_access.group_customer'))]"/>
29+
</record> -->
30+
31+
32+
<!-- <record id="rule_project_customer_access_tasks_customer" model="ir.rule">
33+
<field name="name">Project Customer Access Tasks: Customer</field>
34+
<field name="model_id" ref="project.model_project_task"/>
35+
<field name="domain_force">
36+
[('user_ids', 'in', user.id)]
37+
</field>
38+
<field name="groups" eval="[(4,ref('project_customer_access.group_customer'))]"/>
39+
</record> -->
40+
41+
<!-- <record id="rule_project_customer_access_tasks_manager" model="ir.rule">
42+
<field name="name">Project Customer Access Tasks: Manager</field>
43+
<field name="model_id" ref="project.model_project_task"/>
44+
<field name="domain_force">
45+
[('project_id.cross_connect_client_id', '=', user.cross_connect_client_id.id)]
46+
</field>
47+
<field name="groups" eval="[(4,ref('project_customer_access.group_manager'))]"/>
48+
</record> -->
49+
50+
<record id="rule_project_customer_access_projects" model="ir.rule">
51+
<field name="name">Project Customer Access: Projects</field>
52+
<field name="model_id" ref="project.model_project_project"/>
53+
<field name="domain_force">
54+
[('cross_connect_client_id', '=', user.cross_connect_client_id.id)]
55+
</field>
56+
<field name="groups" eval="[(4,ref('project_customer_access.group_customer'))]"/>
57+
</record>
58+
59+
</data>
60+
</odoo>

0 commit comments

Comments
 (0)