diff --git a/membership_status_in_portal/.gitignore b/membership_status_in_portal/.gitignore new file mode 100644 index 0000000..6da5887 --- /dev/null +++ b/membership_status_in_portal/.gitignore @@ -0,0 +1,2 @@ +*.*~ +*pyc diff --git a/membership_status_in_portal/README.rst b/membership_status_in_portal/README.rst new file mode 100644 index 0000000..0d8ffe8 --- /dev/null +++ b/membership_status_in_portal/README.rst @@ -0,0 +1,54 @@ +========================== +membership_status_in_portal +========================== + +Display the membership status of the connected user in the portal. + +Description +=========== + +In the portal account sidebar (all ``/my`` pages, including ``/my/home``), +this module shows the native Odoo membership status of the connected user +(``res.partner.membership_state`` provided by the ``membership`` module). + +No registration or renewal button is displayed: non-members only see their +status. + +Installation +============ + +Use Odoo normal module installation procedure to install +``membership_status_in_portal``. + +Known issues / Roadmap +====================== + +None yet. + +Bug Tracker +=========== + +Bugs are tracked on `our issues website `_. In case of +trouble, please check there if your issue has already been +reported. If you spotted it first, help us smashing it by providing a +detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Stéphan Sainléger + +Funders +------- + +The development of this module has been financially supported by: + +* Elabore (https://elabore.coop) + +Maintainer +---------- + +This module is maintained by Elabore. diff --git a/membership_status_in_portal/__init__.py b/membership_status_in_portal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/membership_status_in_portal/__manifest__.py b/membership_status_in_portal/__manifest__.py new file mode 100644 index 0000000..ad3328a --- /dev/null +++ b/membership_status_in_portal/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2026 Stéphan Sainléger (Elabore) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "membership_status_in_portal", + "version": "18.0.1.0.0", + "author": "Elabore", + "maintainer": "Elabore", + "website": "https://git.elabore.coop/elabore/member-tools", + "license": "AGPL-3", + "category": "Website", + "summary": "Display the membership status of portal users", + "depends": [ + "portal", + "membership", + ], + "data": [ + "views/portal_sidebar.xml", + ], + "installable": True, + "auto_install": False, + "application": False, +} diff --git a/membership_status_in_portal/tests/__init__.py b/membership_status_in_portal/tests/__init__.py new file mode 100644 index 0000000..0ce7ea6 --- /dev/null +++ b/membership_status_in_portal/tests/__init__.py @@ -0,0 +1 @@ +from . import test_portal_sidebar diff --git a/membership_status_in_portal/tests/test_portal_sidebar.py b/membership_status_in_portal/tests/test_portal_sidebar.py new file mode 100644 index 0000000..b2151be --- /dev/null +++ b/membership_status_in_portal/tests/test_portal_sidebar.py @@ -0,0 +1,66 @@ +import re + +from odoo.tests import HttpCase, tagged + + +@tagged("post_install", "-at_install") +class MembershipStatusPortalCase(HttpCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.portal_group = cls.env.ref("base.group_portal") + + def _create_portal_user(self, login, **partner_vals): + partner = self.env["res.partner"].create( + { + "name": login, + "lang": self.env.lang or "en_US", + **partner_vals, + } + ) + return self.env["res.users"].create( + { + "name": login, + "login": login, + "password": login, + "partner_id": partner.id, + "groups_id": [(6, 0, [self.portal_group.id])], + } + ) + + def _membership_label(self, partner): + selection = self.env["res.partner"].fields_get(["membership_state"])[ + "membership_state" + ]["selection"] + return dict(selection)[partner.membership_state] + + def _open_my_home(self, user): + self.authenticate(user.login, user.password) + response = self.url_open("/my/home") + self.assertEqual(response.status_code, 200) + return response.text + + def _extract_membership_block(self, html): + match = re.search(r'
+ + +