add portal_event_registration
This commit is contained in:
parent
18fd73ed1b
commit
de0520d5a8
9 changed files with 393 additions and 0 deletions
3
portal_event_registration/__init__.py
Normal file
3
portal_event_registration/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import controllers, models
|
||||
18
portal_event_registration/__manifest__.py
Normal file
18
portal_event_registration/__manifest__.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Portal Event Registration",
|
||||
"summary": "Allows portal users to view their event registrations "
|
||||
"and upload attachments to the chatter.",
|
||||
"version": "18.0.1.0.0",
|
||||
"license": "AGPL-3",
|
||||
"author": "Custom",
|
||||
"depends": ["event", "portal"],
|
||||
"data": [
|
||||
"security/security.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"security/ir.model.access.csv",
|
||||
"views/portal_templates.xml",
|
||||
],
|
||||
"installable": True,
|
||||
}
|
||||
3
portal_event_registration/controllers/__init__.py
Normal file
3
portal_event_registration/controllers/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import portal
|
||||
117
portal_event_registration/controllers/portal.py
Normal file
117
portal_event_registration/controllers/portal.py
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, http
|
||||
from odoo.exceptions import AccessError, MissingError
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.portal.controllers.portal import CustomerPortal
|
||||
from odoo.addons.portal.controllers.portal import pager as portal_pager
|
||||
|
||||
|
||||
class EventRegistrationPortal(CustomerPortal):
|
||||
|
||||
def _prepare_home_portal_values(self, counters):
|
||||
values = super()._prepare_home_portal_values(counters)
|
||||
if "event_count" in counters:
|
||||
Registration = request.env["event.registration"]
|
||||
partner = request.env.user.partner_id
|
||||
domain = self._get_event_registration_domain(partner)
|
||||
values["event_count"] = (
|
||||
Registration.search_count(domain)
|
||||
if Registration.has_access("read")
|
||||
else 0
|
||||
)
|
||||
return values
|
||||
|
||||
def _get_event_registration_domain(self, partner):
|
||||
return [
|
||||
("partner_id", "child_of", [partner.commercial_partner_id.id]),
|
||||
("state", "!=", "cancel"),
|
||||
]
|
||||
|
||||
def _get_event_searchbar_sortings(self):
|
||||
return {
|
||||
"date": {"label": _("Event Date"), "order": "event_begin_date desc"},
|
||||
"name": {"label": _("Event Name"), "order": "event_id asc"},
|
||||
"state": {"label": _("Status"), "order": "state asc"},
|
||||
}
|
||||
|
||||
@http.route(
|
||||
["/my/events", "/my/events/page/<int:page>"],
|
||||
type="http",
|
||||
auth="user",
|
||||
website=True,
|
||||
)
|
||||
def portal_my_events(self, page=1, sortby=None, **kw):
|
||||
partner = request.env.user.partner_id
|
||||
Registration = request.env["event.registration"]
|
||||
domain = self._get_event_registration_domain(partner)
|
||||
|
||||
searchbar_sortings = self._get_event_searchbar_sortings()
|
||||
if not sortby:
|
||||
sortby = "date"
|
||||
order = searchbar_sortings[sortby]["order"]
|
||||
|
||||
total = (
|
||||
Registration.search_count(domain) if Registration.has_access("read") else 0
|
||||
)
|
||||
pager = portal_pager(
|
||||
url="/my/events",
|
||||
url_args={"sortby": sortby},
|
||||
total=total,
|
||||
page=page,
|
||||
step=self._items_per_page,
|
||||
)
|
||||
registrations = (
|
||||
Registration.search(
|
||||
domain,
|
||||
order=order,
|
||||
limit=self._items_per_page,
|
||||
offset=pager["offset"],
|
||||
)
|
||||
if Registration.has_access("read")
|
||||
else Registration
|
||||
)
|
||||
|
||||
request.session["my_events_history"] = registrations.ids[:100]
|
||||
|
||||
values = self._prepare_portal_layout_values()
|
||||
values.update(
|
||||
{
|
||||
"registrations": registrations,
|
||||
"page_name": "event",
|
||||
"pager": pager,
|
||||
"sortby": sortby,
|
||||
"searchbar_sortings": searchbar_sortings,
|
||||
"default_url": "/my/events",
|
||||
}
|
||||
)
|
||||
return request.render("portal_event_registration.portal_my_events", values)
|
||||
|
||||
@http.route(
|
||||
["/my/events/<int:registration_id>"],
|
||||
type="http",
|
||||
auth="user",
|
||||
website=True,
|
||||
)
|
||||
def portal_my_event_detail(self, registration_id, access_token=None, **kw):
|
||||
try:
|
||||
registration_sudo = self._document_check_access(
|
||||
"event.registration", registration_id, access_token=access_token
|
||||
)
|
||||
except (AccessError, MissingError):
|
||||
return request.redirect("/my")
|
||||
|
||||
values = self._prepare_portal_layout_values()
|
||||
values["registration"] = registration_sudo
|
||||
values = self._get_page_view_values(
|
||||
registration_sudo,
|
||||
access_token,
|
||||
values,
|
||||
"my_events_history",
|
||||
False,
|
||||
**kw,
|
||||
)
|
||||
return request.render(
|
||||
"portal_event_registration.portal_my_event_detail", values
|
||||
)
|
||||
3
portal_event_registration/models/__init__.py
Normal file
3
portal_event_registration/models/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import event_registration
|
||||
11
portal_event_registration/models/event_registration.py
Normal file
11
portal_event_registration/models/event_registration.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class EventRegistration(models.Model):
|
||||
_inherit = "event.registration"
|
||||
|
||||
# Allow portal users (who only have read access) to post messages
|
||||
# and upload attachments via the portal chatter.
|
||||
_mail_post_access = "read"
|
||||
3
portal_event_registration/security/ir.model.access.csv
Normal file
3
portal_event_registration/security/ir.model.access.csv
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_event_event_portal,event.event.portal,event.model_event_event,base.group_portal,1,0,0,0
|
||||
access_event_registration_portal,event.registration.portal,event.model_event_registration,base.group_portal,1,0,0,0
|
||||
|
30
portal_event_registration/security/security.xml
Normal file
30
portal_event_registration/security/security.xml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Allow portal users to read events where they have a registration -->
|
||||
<record id="event_registration_portal_rule" model="ir.rule">
|
||||
<field name="name">Event Registration: portal users see own registrations</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="domain_force">
|
||||
[('partner_id', 'child_of', [user.commercial_partner_id.id])]
|
||||
</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Allow portal users to read events where they are registered -->
|
||||
<record id="event_event_portal_rule" model="ir.rule">
|
||||
<field name="name">Event Event: portal users see events with own registrations</field>
|
||||
<field name="model_id" ref="event.model_event_event"/>
|
||||
<field name="domain_force">
|
||||
[('registration_ids.partner_id', 'child_of', [user.commercial_partner_id.id])]
|
||||
</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
</odoo>
|
||||
205
portal_event_registration/views/portal_templates.xml
Normal file
205
portal_event_registration/views/portal_templates.xml
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ===== Breadcrumbs ===== -->
|
||||
<template
|
||||
id="portal_my_home_menu_event"
|
||||
name="Portal layout: event menu entries"
|
||||
inherit_id="portal.portal_breadcrumbs"
|
||||
priority="25"
|
||||
>
|
||||
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
|
||||
<li
|
||||
t-if="page_name == 'event' or registration"
|
||||
t-attf-class="breadcrumb-item #{'active' if not registration else ''}"
|
||||
>
|
||||
<a t-if="registration" t-attf-href="/my/events?{{ keep_query() }}">My Events</a>
|
||||
<t t-else="">My Events</t>
|
||||
</li>
|
||||
<li t-if="registration" class="breadcrumb-item active">
|
||||
<t t-out="registration.event_id.name"/>
|
||||
</li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- ===== Portal Home entry ===== -->
|
||||
<template
|
||||
id="portal_my_home_event"
|
||||
name="My Events"
|
||||
customize_show="True"
|
||||
inherit_id="portal.portal_my_home"
|
||||
priority="25"
|
||||
>
|
||||
<xpath expr="//div[hasclass('o_portal_docs')]" position="before">
|
||||
<t t-set="portal_client_category_enable" t-value="True"/>
|
||||
</xpath>
|
||||
<div id="portal_client_category" position="inside">
|
||||
<t t-call="portal.portal_docs_entry">
|
||||
<t t-set="title">My Events</t>
|
||||
<t t-set="url" t-value="'/my/events'"/>
|
||||
<t t-set="text">View the events you are registered for</t>
|
||||
<t t-set="placeholder_count" t-value="'event_count'"/>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ===== List: /my/events ===== -->
|
||||
<template id="portal_my_events" name="My Event Registrations">
|
||||
<t t-call="portal.portal_layout">
|
||||
<t t-set="breadcrumbs_searchbar" t-value="True"/>
|
||||
|
||||
<t t-call="portal.portal_searchbar">
|
||||
<t t-set="title">My Events</t>
|
||||
</t>
|
||||
|
||||
<div t-if="not registrations" class="alert alert-warning" role="alert">
|
||||
You have no active registrations for any event.
|
||||
</div>
|
||||
|
||||
<t t-if="registrations" t-call="portal.portal_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Event</th>
|
||||
<th class="text-end">Start Date</th>
|
||||
<th class="text-end">End Date</th>
|
||||
<th class="text-center">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="registrations" t-as="reg">
|
||||
<tr>
|
||||
<td>
|
||||
<a t-attf-href="/my/events/#{reg.id}">
|
||||
<t t-out="reg.event_id.name"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="reg.event_begin_date" t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="reg.event_end_date" t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span
|
||||
t-if="reg.state == 'open'"
|
||||
class="badge rounded-pill text-bg-success"
|
||||
><i class="fa fa-fw fa-check"/> Registered</span>
|
||||
<span
|
||||
t-elif="reg.state == 'done'"
|
||||
class="badge rounded-pill text-bg-primary"
|
||||
><i class="fa fa-fw fa-star"/> Attended</span>
|
||||
<span
|
||||
t-elif="reg.state == 'draft'"
|
||||
class="badge rounded-pill text-bg-warning"
|
||||
><i class="fa fa-fw fa-clock-o"/> Pending</span>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ===== Detail: /my/events/<id> ===== -->
|
||||
<template id="portal_my_event_detail" name="Event Registration Detail">
|
||||
<t t-call="portal.portal_layout">
|
||||
<div class="row mt16 o_portal_sidebar">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<t t-call="portal.portal_record_sidebar">
|
||||
<t t-set="classes" t-value="'col-12 col-lg-3 d-print-none'"/>
|
||||
<t t-set="entries">
|
||||
<ul class="list-group list-group-flush flex-wrap flex-row flex-lg-column">
|
||||
<li class="list-group-item flex-grow-1">
|
||||
<div class="small mb-1 fw-bold text-uppercase">Status</div>
|
||||
<span
|
||||
t-if="registration.state == 'open'"
|
||||
class="badge rounded-pill text-bg-success"
|
||||
><i class="fa fa-check"/> Registered</span>
|
||||
<span
|
||||
t-elif="registration.state == 'done'"
|
||||
class="badge rounded-pill text-bg-primary"
|
||||
><i class="fa fa-star"/> Attended</span>
|
||||
<span
|
||||
t-elif="registration.state == 'draft'"
|
||||
class="badge rounded-pill text-bg-warning"
|
||||
><i class="fa fa-clock-o"/> Pending</span>
|
||||
<span
|
||||
t-elif="registration.state == 'cancel'"
|
||||
class="badge rounded-pill text-bg-danger"
|
||||
><i class="fa fa-times"/> Cancelled</span>
|
||||
</li>
|
||||
<li t-if="registration.event_id.organizer_id" class="list-group-item flex-grow-1">
|
||||
<div class="small mb-1 fw-bold text-uppercase">Organizer</div>
|
||||
<t t-out="registration.event_id.organizer_id.name"/>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Main content -->
|
||||
<div id="portal_event_content" class="col-12 col-lg-9">
|
||||
<div class="o_portal_html_view shadow p-3">
|
||||
<div class="o_portal_html_loader text-center">
|
||||
<i class="fa fa-circle-o-notch fa-spin fa-2x fa-fw text-black-50"/>
|
||||
</div>
|
||||
|
||||
<!-- Event header -->
|
||||
<div class="pb-3 border-bottom">
|
||||
<h2>
|
||||
<t t-out="registration.event_id.name"/>
|
||||
</h2>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<strong>Start:</strong>
|
||||
<span t-field="registration.event_begin_date"/>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<strong>End:</strong>
|
||||
<span t-field="registration.event_end_date"/>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="registration.event_id.address_id">
|
||||
<div class="mt-2">
|
||||
<strong>Location:</strong>
|
||||
<span t-field="registration.event_id.address_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address']}"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- Attendee details -->
|
||||
<div class="mt-3">
|
||||
<h4>Registration Details</h4>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<td><t t-out="registration.name"/></td>
|
||||
</tr>
|
||||
<tr t-if="registration.email">
|
||||
<th>Email</th>
|
||||
<td><t t-out="registration.email"/></td>
|
||||
</tr>
|
||||
<tr t-if="registration.phone">
|
||||
<th>Phone</th>
|
||||
<td><t t-out="registration.phone"/></td>
|
||||
</tr>
|
||||
<tr t-if="registration.event_ticket_id">
|
||||
<th>Ticket Type</th>
|
||||
<td><t t-out="registration.event_ticket_id.name"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Chatter with attachments -->
|
||||
<div class="mt-4">
|
||||
<h4>Messages & Documents</h4>
|
||||
<t t-call="portal.message_thread"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue