diff --git a/resource_booking_portal/README.rst b/resource_booking_portal/README.rst new file mode 100644 index 00000000..99e9ffb4 --- /dev/null +++ b/resource_booking_portal/README.rst @@ -0,0 +1,107 @@ +======================= +resource_booking_portal +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:8ad914e817c82df68edfc22189124e669f753f35ebd77cb05e6e5d05465a4c02 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcalendar-lightgray.png?logo=github + :target: https://github.com/OCA/calendar/tree/14.0/resource_booking_portal + :alt: OCA/calendar +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/calendar-14-0/calendar-14-0-resource_booking_portal + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/calendar&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon allows portal users to create bookings from the portal if they have the necessary permissions. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +#. You need a portal user with the "Create booking from portal" option active. + +#. You can find this option on the "Access Rights" page, + but only if the user belongs to the portal user group. + +#. Log in with the user mentioned above. + +#. Go to **"My Account."** + +#. In **"My Account,"** you will find a new section called **"Actions."** + +#. In this section, there is a button to access the **create booking form.** + When you create a booking with this form, you must select the **subject** and **type**. + The **description** is optional. + +#. When you use the **"Continue"** button, you can assign a date with your commercial representative. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Binhex + +Contributors +~~~~~~~~~~~~ + + +* `Binhex `_: + + * Adasat Torres de León + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-adasatorres| image:: https://github.com/adasatorres.png?size=40px + :target: https://github.com/adasatorres + :alt: adasatorres + +Current `maintainer `__: + +|maintainer-adasatorres| + +This module is part of the `OCA/calendar `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/resource_booking_portal/__init__.py b/resource_booking_portal/__init__.py new file mode 100644 index 00000000..e4f4917a --- /dev/null +++ b/resource_booking_portal/__init__.py @@ -0,0 +1,3 @@ +from . import controllers +from . import models +from . import wizard diff --git a/resource_booking_portal/__manifest__.py b/resource_booking_portal/__manifest__.py new file mode 100644 index 00000000..341430bb --- /dev/null +++ b/resource_booking_portal/__manifest__.py @@ -0,0 +1,20 @@ +{ + "name": "resource_booking_portal", + "summary": """ + This addons allow create booking from portal. + """, + "author": "Odoo Community Association (OCA), Binhex", + "website": "https://github.com/OCA/calendar", + "maintainers": ["adasatorres"], + "category": "portal", + "version": "14.0.1.0.0", + "license": "AGPL-3", + "depends": [ + "resource_booking", + ], + "data": [ + "views/portal_templates.xml", + "views/res_users_views.xml", + "wizard/portal_wizard_views.xml", + ], +} diff --git a/resource_booking_portal/controllers/__init__.py b/resource_booking_portal/controllers/__init__.py new file mode 100644 index 00000000..8c3feb6f --- /dev/null +++ b/resource_booking_portal/controllers/__init__.py @@ -0,0 +1 @@ +from . import portal diff --git a/resource_booking_portal/controllers/portal.py b/resource_booking_portal/controllers/portal.py new file mode 100644 index 00000000..f5b3c1bc --- /dev/null +++ b/resource_booking_portal/controllers/portal.py @@ -0,0 +1,36 @@ +from odoo.http import request, route + +from odoo.addons.portal.controllers import portal + + +class CustomerPortal(portal.CustomerPortal): + @route(["/my/bookings/prepare/form"], auth="user", type="http", website=True) + def portal_bookings_prepare_form(self): + values = { + "page_name": "create_booking", + "types": request.env["resource.booking.type"] + .sudo() + .search_read([], ["id", "name"]), + } + return request.render("resource_booking_portal.booking_create_form", values) + + @route( + ["/my/bookings/create"], auth="user", type="http", method=["POST"], website=True + ) + def portal_bookings_create(self, **post): + + Booking = request.env["resource.booking"].sudo() + BookingType = request.env["resource.booking.type"].sudo() + partner_id = request.env.user.partner_id + res = Booking.create( + { + "name": post.get("name"), + "type_id": BookingType.browse(int(post.get("type"))).id, + "partner_id": partner_id.id, + "combination_auto_assign": True, + "description": post.get("description", False), + "user_id": partner_id.user_id.id, + } + ) + + return request.redirect("/my/bookings/%s/schedule" % res.id) diff --git a/resource_booking_portal/i18n/es.po b/resource_booking_portal/i18n/es.po new file mode 100644 index 00000000..d97ed514 --- /dev/null +++ b/resource_booking_portal/i18n/es.po @@ -0,0 +1,125 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * resource_booking_portal +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-09-03 10:36+0000\n" +"PO-Revision-Date: 2024-09-03 11:38+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.4.4\n" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.portal_my_home_menu +msgid "Create booking" +msgstr "Crear reserva" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.portal_my_home +msgid "Actions" +msgstr "Acciones" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.res_users_portal_form_view_inherit +msgid "Booking" +msgstr "Reserva" + +#. module: resource_booking_portal +#: code:addons/resource_booking_portal/wizard/portal_wizard.py:0 +#: model:ir.model.fields,field_description:resource_booking_portal.field_portal_wizard_user__booking_from_portal +#, python-format +msgid "Booking from portal" +msgstr "Reserva desde el portal" + +#. module: resource_booking_portal +#: model:res.groups,name:resource_booking_portal.group_portal_sellers_bookings +msgid "Can create booking from portal" +msgstr "Puede crear reservas desde el portal" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_form +msgid "Continue" +msgstr "Continuar" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.portal_my_home +msgid "Create a booking" +msgstr "Crear una reserva" + +#. module: resource_booking_portal +#: code:addons/resource_booking_portal/models/res_users.py:0 +#: model:ir.model.fields,field_description:resource_booking_portal.field_res_users__create_booking_from_portal +#, python-format +msgid "Create booking from portal" +msgstr "Crear reserva desde el portal" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_form +msgid "Description" +msgstr "Descripción" + +#. module: resource_booking_portal +#: model:ir.model.fields,field_description:resource_booking_portal.field_portal_wizard_user__display_name +#: model:ir.model.fields,field_description:resource_booking_portal.field_res_users__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: resource_booking_portal +#: model:ir.model.fields,field_description:resource_booking_portal.field_portal_wizard_user__id +#: model:ir.model.fields,field_description:resource_booking_portal.field_res_users__id +msgid "ID" +msgstr "ID" + +#. module: resource_booking_portal +#: model:ir.model.fields,field_description:resource_booking_portal.field_res_users__is_portal_user +msgid "Is Portal User" +msgstr "Es usuario de portal" + +#. module: resource_booking_portal +#: model:ir.model.fields,field_description:resource_booking_portal.field_portal_wizard_user____last_update +#: model:ir.model.fields,field_description:resource_booking_portal.field_res_users____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_form +msgid "Name" +msgstr "Asunto" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.res_users_portal_form_view_inherit +msgid "Portal" +msgstr "Portal" + +#. module: resource_booking_portal +#: model:ir.model,name:resource_booking_portal.model_portal_wizard_user +msgid "Portal User Config" +msgstr "Configuración de usuario de portal" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_form +msgid "Resource Name" +msgstr "Asunto" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_confirmation +msgid "TEST" +msgstr "" + +#. module: resource_booking_portal +#: model_terms:ir.ui.view,arch_db:resource_booking_portal.booking_create_form +msgid "Type" +msgstr "Tipo" + +#. module: resource_booking_portal +#: model:ir.model,name:resource_booking_portal.model_res_users +msgid "Users" +msgstr "Usuarios" diff --git a/resource_booking_portal/models/__init__.py b/resource_booking_portal/models/__init__.py new file mode 100644 index 00000000..88351653 --- /dev/null +++ b/resource_booking_portal/models/__init__.py @@ -0,0 +1 @@ +from . import res_users diff --git a/resource_booking_portal/models/res_users.py b/resource_booking_portal/models/res_users.py new file mode 100644 index 00000000..df18a96d --- /dev/null +++ b/resource_booking_portal/models/res_users.py @@ -0,0 +1,14 @@ +from odoo import fields, models + + +class ResUsers(models.Model): + _inherit = "res.users" + + create_booking_from_portal = fields.Boolean( + string="Create booking from portal", + ) + is_portal_user = fields.Boolean(compute="_compute_is_portal_user") + + def _compute_is_portal_user(self): + for record in self: + record.is_portal_user = record.has_group("base.group_portal") diff --git a/resource_booking_portal/readme/CONTRIBUTORS.rst b/resource_booking_portal/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..bcd95202 --- /dev/null +++ b/resource_booking_portal/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ + +* `Binhex `_: + + * Adasat Torres de León diff --git a/resource_booking_portal/readme/DESCRIPTION.rst b/resource_booking_portal/readme/DESCRIPTION.rst new file mode 100644 index 00000000..16093eb7 --- /dev/null +++ b/resource_booking_portal/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This addon allows portal users to create bookings from the portal if they have the necessary permissions. diff --git a/resource_booking_portal/readme/USAGE.rst b/resource_booking_portal/readme/USAGE.rst new file mode 100644 index 00000000..6336da9d --- /dev/null +++ b/resource_booking_portal/readme/USAGE.rst @@ -0,0 +1,16 @@ +#. You need a portal user with the "Create booking from portal" option active. + +#. You can find this option on the "Access Rights" page, + but only if the user belongs to the portal user group. + +#. Log in with the user mentioned above. + +#. Go to **"My Account."** + +#. In **"My Account,"** you will find a new section called **"Actions."** + +#. In this section, there is a button to access the **create booking form.** + When you create a booking with this form, you must select the **subject** and **type**. + The **description** is optional. + +#. When you use the **"Continue"** button, you can assign a date with your commercial representative. diff --git a/resource_booking_portal/static/description/icon.png b/resource_booking_portal/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/resource_booking_portal/static/description/icon.png differ diff --git a/resource_booking_portal/static/description/index.html b/resource_booking_portal/static/description/index.html new file mode 100644 index 00000000..c1eecffc --- /dev/null +++ b/resource_booking_portal/static/description/index.html @@ -0,0 +1,447 @@ + + + + + +resource_booking_portal + + + +
+

resource_booking_portal

+ + +

Beta License: AGPL-3 OCA/calendar Translate me on Weblate Try me on Runboat

+

This addon allows portal users to create bookings from the portal if they have the necessary permissions.

+

Table of contents

+ +
+

Usage

+
    +
  1. You need a portal user with the “Create booking from portal” option active.
  2. +
  3. You can find this option on the “Access Rights” page, +but only if the user belongs to the portal user group.
  4. +
  5. Log in with the user mentioned above.
  6. +
  7. Go to “My Account.”
  8. +
  9. In “My Account,” you will find a new section called “Actions.”
  10. +
  11. In this section, there is a button to access the create booking form. +When you create a booking with this form, you must select the subject and type. +The description is optional.
  12. +
  13. When you use the “Continue” button, you can assign a date with your commercial representative.
  14. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Binhex
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

adasatorres

+

This module is part of the OCA/calendar project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/resource_booking_portal/tests/__init__.py b/resource_booking_portal/tests/__init__.py new file mode 100644 index 00000000..57458a18 --- /dev/null +++ b/resource_booking_portal/tests/__init__.py @@ -0,0 +1,3 @@ +from . import test_portal_wizard_user +from . import test_res_users +from . import test_portal diff --git a/resource_booking_portal/tests/test_portal.py b/resource_booking_portal/tests/test_portal.py new file mode 100644 index 00000000..8431cca9 --- /dev/null +++ b/resource_booking_portal/tests/test_portal.py @@ -0,0 +1,55 @@ +from odoo.tests.common import HttpCase + + +class TestCustomerPortal(HttpCase): + def setUp(self): + super().setUp() + + self.test_user = self.env["res.users"].create( + { + "name": "test user", + "login": "test@example.com", + "password": "password", + "groups_id": [(4, self.env.ref("base.group_user").id)], + } + ) + + self.resource = self.env["resource.resource"].create( + {"name": "Test Resource", "user_id": self.test_user.id} + ) + + self.combination = self.env["resource.booking.combination"].create( + {"resource_ids": [(6, 0, self.resource.ids)]} + ) + + self.booking_type = self.env["resource.booking.type"].create( + { + "name": "Test Booking Type", + "combination_rel_ids": [(6, 0, self.combination.ids)], + } + ) + + self.portal_user = self.env["res.users"].create( + { + "name": "Portal user", + "login": "portal@example.com", + "password": "password", + "groups_id": [(4, self.env.ref("base.group_portal").id)], + } + ) + self.authenticate("portal@example.com", "password") + + def test_portal_bookings_prepare_form(self): + response = self.url_open("/my/bookings/prepare/form") + self.assertEqual(response.status_code, 200) + + def test_portal_bookings_create(self): + response = self.url_open( + "/my/bookings/create", + data={ + "name": "Test Booking", + "type": str(self.booking_type.id), + "description": "Test Description", + }, + ) + self.assertEqual(response.status_code, 302) diff --git a/resource_booking_portal/tests/test_portal_wizard_user.py b/resource_booking_portal/tests/test_portal_wizard_user.py new file mode 100644 index 00000000..83ce5c90 --- /dev/null +++ b/resource_booking_portal/tests/test_portal_wizard_user.py @@ -0,0 +1,42 @@ +from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user + + +class TestPortalWizardUser(MailCommon): + def setUp(self): + super().setUp() + self.partner = self.env["res.partner"].create( + { + "name": "Testing Partner", + "email": "testing_partner@example.com", + } + ) + + self.portal_user = mail_new_test_user( + self.env, + name="Portal user", + login="portal_user", + email="portal_user@example.com", + groups="base.group_portal", + ) + + def test_portal_wizard_create_user(self): + portal_wizard = ( + self.env["portal.wizard"] + .with_context(active_ids=[self.partner.id]) + .create({}) + ) + + self.assertEqual(len(portal_wizard.user_ids), 1) + + portal_user = portal_wizard.user_ids + + self.assertFalse(portal_user.user_id) + self.assertFalse(portal_user.in_portal) + self.assertFalse(portal_user.booking_from_portal) + + portal_user.email = "first_email@example.com" + portal_user.booking_from_portal = True + new_user = portal_user._create_user() + + self.assertTrue(new_user) + self.assertTrue(new_user.create_booking_from_portal) diff --git a/resource_booking_portal/tests/test_res_users.py b/resource_booking_portal/tests/test_res_users.py new file mode 100644 index 00000000..72b1f2fe --- /dev/null +++ b/resource_booking_portal/tests/test_res_users.py @@ -0,0 +1,24 @@ +from odoo.tests.common import TransactionCase + + +class TestResUsers(TransactionCase): + def setUp(self): + super().setUp() + self.test_user = self.env["res.users"].create( + { + "name": "test", + "login": "test", + "password": "test", + "groups_id": [(4, self.env.ref("base.group_portal").id, 0)], + "create_booking_from_portal": False, + } + ) + + def test_is_portal_user(self): + self.test_user._compute_is_portal_user() + self.assertTrue(self.test_user.is_portal_user) + + def test_create_booking_from_portal(self): + self.assertFalse(self.test_user.create_booking_from_portal) + self.test_user.create_booking_from_portal = True + self.assertTrue(self.test_user.create_booking_from_portal) diff --git a/resource_booking_portal/views/portal_templates.xml b/resource_booking_portal/views/portal_templates.xml new file mode 100644 index 00000000..3f8d141e --- /dev/null +++ b/resource_booking_portal/views/portal_templates.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + +