[IMP] {website_}event{_sale,_exhibitor}: ease ticket access
The tickets are reworked, made easier to print and have their structure reworked for qr code addition (in ENT branch). Also they are easier to download as buttons are added to do so. 1. Design Tickets have their background removed in order to ease their printing. More room is given to details, the design is simplified. New RESPONSIVE HTML TICKET The confirmation email will now contain a link "See tickets" leading to a new version of the full page ticket, called "responsive_html". It does not generate / download PDF but rather leads to a rendered qweb html page, with design working properly on different screen sizes. The design is a tweaked version of the full_page ticket template, simplified. It allows users to see their ticket directly without needing a pdf viewer. 2. Download Tickets Buttons "Download / See Tickets" Buttons are added in - Email Templates (Ticket and Badge) - The SO confirmation (if payment). All tickets, per event. - The registration confirmation (if no payment). All tickets in the same PDF. They are for the same event. In order to access tickets, a route event/my_tickets is added in the controller. It takes an event_id, registration_ids and a hash based on those plus the database secret using tools.hmac. The groundtruth hash is obtained for given registration ids in the method _get_tickets_access_hash on event.event. The route is used in all places listed above. The hash must be valid and attendees must exist. No condition on payment is set in my_tickets as we want the download tickets link to work for non-free tickets as well at the end of the sale process, and as the sale order could not be linked to any invoice at that stage (if automatic invoices is not set in the settings), registrations being 'not paid' at that point. This could be cleaned in further work as different states are to be clarified. The route must be public as it must work even for public users. (from email or as public user registering on front-end) Also, we give sudo access to the course in the case of invitation to a course that is not yet published, as long as the hash and registration are valid. 3. Email Templates In order to have similar mail templates for badge and tickets, Registration Badge content is duplicated from Registration Confirmation and slightly tweaked, replacing existing body. Also, the info of the payment / order moved from full page ticket to the body of the confirmation email. PR ENT - odoo/enterprise#41164 PR UPG - odoo/upgrade#5007 Task-3061851 closes odoo/odoo#120933 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -59,6 +59,7 @@ Key Features
|
||||
'web.report_assets_common': [
|
||||
'/event/static/src/scss/event_foldable_badge_report.scss',
|
||||
'/event/static/src/scss/event_full_page_ticket_report.scss',
|
||||
'/event/static/src/scss/event_full_page_ticket_responsive_html_report.scss',
|
||||
],
|
||||
'web.report_assets_pdf': [
|
||||
'/event/static/src/scss/event_full_page_ticket_report_pdf.scss',
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from odoo import _
|
||||
from odoo.http import Controller, request, route, content_disposition
|
||||
from odoo.tools import consteq
|
||||
|
||||
|
||||
class EventController(Controller):
|
||||
@@ -23,3 +26,52 @@ class EventController(Controller):
|
||||
('Content-Length', len(content)),
|
||||
('Content-Disposition', content_disposition('%s.ics' % event.name))
|
||||
])
|
||||
|
||||
@route(['/event/<int:event_id>/my_tickets'], type='http', auth='public')
|
||||
def event_my_tickets(self, event_id, registration_ids, tickets_hash, badge_mode=False, responsive_html=False):
|
||||
""" Returns a pdf response, containing all tickets for attendees in registration_ids for event_id.
|
||||
|
||||
Throw Forbidden if no registration is valid / hash is invalid / parameters are missing.
|
||||
This route is used in links in emails to attendees, as well as in registration confirmation screens.
|
||||
|
||||
:param event: the id of prompted event. Only its attendees will be considered.
|
||||
:param registration_ids: ids of event.registrations of which tickets are generated
|
||||
:param tickets_hash: string hash used to access the tickets.
|
||||
:param badge_mode: boolean, True to use template of foldable badge instead of full page ticket.
|
||||
:param responsive_html: boolean, True if we want to see the a responsive html ticket.
|
||||
"""
|
||||
registration_ids = json.loads(registration_ids or '[]')
|
||||
if not event_id or not tickets_hash or not registration_ids:
|
||||
raise NotFound()
|
||||
|
||||
# We sudo the event in case of invitations sent before publishing it.
|
||||
event_sudo = request.env['event.event'].browse(event_id).exists().sudo()
|
||||
hash_truth = event_sudo and event_sudo._get_tickets_access_hash(registration_ids)
|
||||
if not consteq(tickets_hash, hash_truth):
|
||||
raise NotFound()
|
||||
|
||||
event_registrations_sudo = event_sudo.registration_ids.filtered(lambda reg: reg.id in registration_ids)
|
||||
report_name_prefix = _("Ticket") if responsive_html else _("Badges") if badge_mode else _("Tickets")
|
||||
report_name = f"{report_name_prefix} - {event_sudo.name} ({event_sudo.date_begin_located})"
|
||||
if len(event_registrations_sudo) == 1:
|
||||
report_name += f" - {event_registrations_sudo[0].name}"
|
||||
|
||||
# sudo is necessary for accesses in templates.
|
||||
if responsive_html:
|
||||
html = request.env['ir.actions.report'].sudo()._render_qweb_html(
|
||||
'event.action_report_event_registration_responsive_html_ticket',
|
||||
event_registrations_sudo.ids,
|
||||
)[0]
|
||||
return request.make_response(html)
|
||||
|
||||
pdf = request.env['ir.actions.report'].sudo()._render_qweb_pdf(
|
||||
'event.action_report_event_registration_foldable_badge' if badge_mode else
|
||||
'event.action_report_event_registration_full_page_ticket',
|
||||
event_registrations_sudo.ids,
|
||||
)[0]
|
||||
pdfhttpheaders = [
|
||||
('Content-Type', 'application/pdf'),
|
||||
('Content-Length', len(pdf)),
|
||||
('Content-Disposition', content_disposition(f'{report_name}.pdf')),
|
||||
]
|
||||
return request.make_response(pdf, headers=pdfhttpheaders)
|
||||
|
||||
@@ -10,31 +10,6 @@
|
||||
<field name="email_to">{{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }}</field>
|
||||
<field name="description">Sent automatically to someone after they registered to an event</field>
|
||||
<field name="body_html" type="html">
|
||||
<div>
|
||||
Dear <t t-out="object.name or 'Guest'"/>,<br/>
|
||||
Thank you for your inquiry.<br/>
|
||||
Here is your badge for the event <t t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</t>.<br/>
|
||||
If you have any questions, please let us know.
|
||||
<br/><br/>
|
||||
Thank you,
|
||||
<t t-if="object.event_id.user_id.signature">
|
||||
<br />
|
||||
<t t-out="object.event_id.user_id.signature or ''">--<br/>Mitchell Admin</t>
|
||||
</t>
|
||||
</div></field>
|
||||
<field name="report_template_ids" eval="[(4, ref('event.action_report_event_registration_foldable_badge'))]"/>
|
||||
<field name="lang">{{ object.event_id.lang or object.partner_id.lang }}</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="event_subscription" model="mail.template">
|
||||
<field name="name">Event: Registration Confirmation</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="subject">Your registration at {{ object.event_id.name }}</field>
|
||||
<field name="email_from">{{ (object.event_id.organizer_id.email_formatted or object.event_id.user_id.email_formatted or '') }}</field>
|
||||
<field name="email_to">{{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }}</field>
|
||||
<field name="description">Sent to attendees after registering to an event</field>
|
||||
<field name="body_html" type="html">
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"><tr><td align="center">
|
||||
<t t-set="date_begin" t-value="format_datetime(object.event_id.date_begin, tz='UTC', dt_format="yyyyMMdd'T'HHmmss'Z'")"/>
|
||||
<t t-set="date_end" t-value="format_datetime(object.event_id.date_end, tz='UTC', dt_format="yyyyMMdd'T'HHmmss'Z'")"/>
|
||||
@@ -53,13 +28,11 @@
|
||||
<t t-out="object.name or 'Guest'"/>
|
||||
</span>
|
||||
</td><td valign="middle" align="right">
|
||||
<t t-if="is_online">
|
||||
<a t-att-href="object.event_id.website_url"
|
||||
style="padding: 8px 12px; font-size: 12px; color: #FFFFFF; text-decoration: none !important; font-weight: 400; background-color: #875A7B; border: 0px solid #875A7B; border-radius:3px">
|
||||
View Event
|
||||
</a>
|
||||
</t>
|
||||
<t t-elif="not object.company_id.uses_default_logo">
|
||||
<a t-attf-href="/event/{{ object.event_id.id }}/my_tickets?badge_mode=1&registration_ids={{ object.ids }}&tickets_hash={{ object.event_id._get_tickets_access_hash(object.ids) }}"
|
||||
target="_blank" style="padding: 8px 12px; font-size: 12px; color: #FFFFFF; text-decoration: none !important; font-weight: 400; background-color: #875A7B; border: 0px solid #875A7B; border-radius:3px">
|
||||
Download Badge
|
||||
</a>
|
||||
<t t-if="not object.company_id.uses_default_logo">
|
||||
<img t-att-src="'/logo.png?company=%s' % object.company_id.id" style="padding: 0px; margin: 0px; height: auto; width: 80px;" t-att-alt="'%s' % object.company_id.name"/>
|
||||
</t>
|
||||
</td></tr>
|
||||
@@ -76,14 +49,13 @@
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<div>
|
||||
Hello <t t-out="object.name or 'Guest'"/>,<br/>
|
||||
We are happy to confirm your registration to the event
|
||||
Please find attached your badge for
|
||||
<t t-if="is_online">
|
||||
<a t-att-href="object.event_id.website_url" style="color:#875A7B;text-decoration:none;" t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</a>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</strong>
|
||||
<strong t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</strong>.
|
||||
</t>
|
||||
for attendee <t t-out="object.name or 'Guest'"/>.
|
||||
</div>
|
||||
<div>
|
||||
<br />
|
||||
@@ -138,33 +110,276 @@
|
||||
<t t-if="event_address">
|
||||
<t t-set="location" t-value="''"/>
|
||||
<t t-if="object.event_id.address_id.name">
|
||||
<div t-out="object.event_id.address_id.name or ''">Teksa SpA</div>
|
||||
<div t-out="object.event_id.address_id.name">Teksa SpA</div>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.street">
|
||||
<div t-out="object.event_id.address_id.street or ''">Puerto Madero 9710</div>
|
||||
<div t-out="object.event_id.address_id.street">Puerto Madero 9710</div>
|
||||
<t t-set="location" t-value="object.event_id.address_id.street"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.street2">
|
||||
<div t-out="object.event_id.address_id.street2 or ''">Of A15, Santiago (RM)</div>
|
||||
<t t-set="location" t-value="'%s, %s' % (location, object.event_id.address_id.street2)"/>
|
||||
<div t-out="object.event_id.address_id.street2">Of A15, Santiago (RM)</div>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.street2}}"/>
|
||||
</t>
|
||||
<div>
|
||||
<t t-if="object.event_id.address_id.city">
|
||||
<t t-out="object.event_id.address_id.city or ''">Pudahuel</t>,
|
||||
<t t-set="location" t-value="'%s, %s' % (location, object.event_id.address_id.city)"/>
|
||||
<t t-out="object.event_id.address_id.city">Pudahuel</t>,
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.city}}"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.state_id.name">
|
||||
<t t-out="object.event_id.address_id.state_id.name or ''">C1</t>,
|
||||
<t t-set="location" t-value="'%s, %s' % (location, object.event_id.address_id.state_id.name)"/>
|
||||
<t t-out="object.event_id.address_id.state_id.name">C1</t>,
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.state_id.name}}"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.zip">
|
||||
<t t-out="object.event_id.address_id.zip or ''">98450</t>
|
||||
<t t-set="location" t-value="'%s, %s' % (location, object.event_id.address_id.zip)"/>
|
||||
<t t-out="object.event_id.address_id.zip">98450</t>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.zip}}"/>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="object.event_id.address_id.country_id.name">
|
||||
<div t-out="object.event_id.address_id.country_id.name or ''">Argentina</div>
|
||||
<t t-set="location" t-value="'%s, %s' % (location, object.event_id.address_id.country_id.name)"/>
|
||||
<div t-out="object.event_id.address_id.country_id.name">Argentina</div>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.country_id.name}}"/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
<tr><td style="text-align:center;">
|
||||
<t t-if="event_organizer">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"/>
|
||||
</t>
|
||||
</td></tr>
|
||||
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<!-- CONTACT ORGANIZER -->
|
||||
<t t-if="event_organizer">
|
||||
<div>
|
||||
<span style="font-weight:300;margin:10px 0px">Questions about this event?</span>
|
||||
<div>Please contact the organizer:</div>
|
||||
<ul>
|
||||
<li><t t-out="event_organizer.name or ''">YourCompany</t></li>
|
||||
<t t-if="event_organizer.email">
|
||||
<li>Mail: <a t-attf-href="mailto:{{ event_organizer.email }}" style="text-decoration:none;color:#875A7B;" t-out="event_organizer.email">info@yourcompany.com</a></li>
|
||||
</t>
|
||||
<t t-if="event_organizer.phone">
|
||||
<li>Phone: <t t-out="event_organizer.phone">+1 650-123-4567</t></li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</td></tr>
|
||||
<tr><td style="text-align:center;">
|
||||
<!-- CONTACT ORGANIZER SEPARATION -->
|
||||
<t t-if="is_online or event_address">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"/>
|
||||
</t>
|
||||
</td></tr>
|
||||
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<!-- PWA MARKGETING -->
|
||||
<t t-if="is_online">
|
||||
<div>
|
||||
<strong>Get the best mobile experience.</strong>
|
||||
<a href="/event">Install our mobile app</a>
|
||||
</div>
|
||||
</t>
|
||||
</td></tr>
|
||||
<tr><td style="text-align:center;">
|
||||
<!-- PWA MARKGETING SEPARATION-->
|
||||
<t t-if="is_online and event_address">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"/>
|
||||
</t>
|
||||
</td></tr>
|
||||
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<!-- GOOGLE MAPS LINK -->
|
||||
<t t-if="event_address and location">
|
||||
<table style="width:100%;"><tr><td>
|
||||
<div>
|
||||
<i class="fa fa-map-marker"/>
|
||||
<a t-attf-href="https://maps.google.com/maps?q={{ location }}" target="new">
|
||||
<img t-if="event_address.static_map_url and event_address.static_map_url_is_valid"
|
||||
t-att-src="event_address.static_map_url"
|
||||
style="vertical-align:bottom; width: 100%;" alt="Google Maps"/>
|
||||
<t t-else="">See location on Google Maps</t>
|
||||
</a>
|
||||
</div>
|
||||
</td></tr></table>
|
||||
</t>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td></tr>
|
||||
<!-- FOOTER BY -->
|
||||
<tr><td align="center" style="min-width: 590px;">
|
||||
<t t-if="object.company_id">
|
||||
<table width="590" border="0" cellpadding="0" cellspacing="0" style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;">
|
||||
<tr><td style="text-align: center; font-size: 14px;">
|
||||
Sent by <a target="_blank" t-attf-href="{{ object.company_id.website }}" style="color: #875A7B;" t-out="object.company_id.name or ''">YourCompany</a>
|
||||
<t t-if="is_online">
|
||||
<br />
|
||||
Discover <a href="/event" style="color:#875A7B;">all our events</a>.
|
||||
</t>
|
||||
</td></tr>
|
||||
</table>
|
||||
</t>
|
||||
</td></tr>
|
||||
</table>
|
||||
</field>
|
||||
<field name="report_template_ids" eval="[(4, ref('event.action_report_event_registration_foldable_badge'))]"/>
|
||||
<field name="lang">{{ object.event_id.lang or object.partner_id.lang }}</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="event_subscription" model="mail.template">
|
||||
<field name="name">Event: Registration Confirmation</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="subject">Your registration at {{ object.event_id.name }}</field>
|
||||
<field name="email_from">{{ (object.event_id.organizer_id.email_formatted or object.event_id.user_id.email_formatted or '') }}</field>
|
||||
<field name="email_to">{{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }}</field>
|
||||
<field name="description">Sent to attendees after registering to an event</field>
|
||||
<field name="body_html" type="html">
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"><tr><td align="center">
|
||||
<t t-set="date_begin" t-value="format_datetime(object.event_id.date_begin, tz='UTC', dt_format="yyyyMMdd'T'HHmmss'Z'")"/>
|
||||
<t t-set="date_end" t-value="format_datetime(object.event_id.date_end, tz='UTC', dt_format="yyyyMMdd'T'HHmmss'Z'")"/>
|
||||
<t t-set="is_online" t-value="'is_published' in object.event_id and object.event_id.is_published"/>
|
||||
<t t-set="is_sale" t-value="'sale_order_id' in object and object.sale_order_id"/>
|
||||
<t t-set="event_organizer" t-value="object.event_id.organizer_id"/>
|
||||
<t t-set="event_address" t-value="object.event_id.address_id"/>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="590" style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;">
|
||||
<tbody>
|
||||
<!-- HEADER -->
|
||||
<tr>
|
||||
<td align="center" style="min-width: 590px;">
|
||||
<table width="590" border="0" cellpadding="0" cellspacing="0" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
|
||||
<tr><td valign="middle">
|
||||
<span style="font-size: 10px;">Your registration</span><br/>
|
||||
<span style="font-size: 20px; font-weight: bold;">
|
||||
<t t-out="object.name or 'Guest'"/>
|
||||
</span>
|
||||
</td><td valign="middle" align="right">
|
||||
<a t-attf-href="/event/{{ object.event_id.id }}/my_tickets?registration_ids={{ object.ids }}&tickets_hash={{ object.event_id._get_tickets_access_hash(object.ids) }}&responsive_html=1"
|
||||
target="_blank" style="padding: 8px 12px; font-size: 12px; color: #FFFFFF; text-decoration: none !important; font-weight: 400; background-color: #875A7B; border: 0px solid #875A7B; border-radius:3px">
|
||||
View Ticket
|
||||
</a>
|
||||
<t t-if="not object.company_id.uses_default_logo">
|
||||
<img t-att-src="'/logo.png?company=%s' % object.company_id.id" style="padding: 0px; margin: 0px; height: auto; width: 80px;" t-att-alt="'%s' % object.company_id.name"/>
|
||||
</t>
|
||||
</td></tr>
|
||||
<tr><td colspan="2" style="text-align:center;">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin:16px 0px 16px 0px;"/>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- EVENT DESCRIPTION -->
|
||||
<tr>
|
||||
<td align="center" style="min-width: 590px;">
|
||||
<table width="590" border="0" cellpadding="0" cellspacing="0" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<div>
|
||||
Hello <t t-out="object.name or 'Guest'"/>,<br/>
|
||||
We are happy to confirm your registration to the event
|
||||
<t t-if="is_online">
|
||||
<a t-att-href="object.event_id.website_url" style="color:#875A7B;text-decoration:none;" t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</a>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</strong>
|
||||
</t>.
|
||||
<t t-if="object.partner_id and object.partner_id.name and object.partner_id.name != object.name">
|
||||
This ticket was registered by <t t-out="object.partner_id.name"/>.
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="is_sale">
|
||||
<br/>
|
||||
The order for this ticket has reference <t t-out="object.sale_order_id.name"/>
|
||||
and was placed on <t t-out="object.sale_order_id.date_order.date()"/>
|
||||
<t t-if="object.sale_order_line_id.price_unit"> for an amount of
|
||||
<t t-out="object.sale_order_line_id.price_unit" t-options="{'widget': 'monetary', 'display_currency': object.sale_order_line_id.currency_id}"/>
|
||||
</t>.
|
||||
</div>
|
||||
<div>
|
||||
<br />
|
||||
<strong>Add this event to your calendar</strong>
|
||||
<a t-attf-href="https://www.google.com/calendar/render?action=TEMPLATE&text={{ object.event_id.name }}&dates={{ date_begin }}/{{ date_end }}&location={{ location }}" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;" target="new"><img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16" alt=""/> Google</a>
|
||||
<a t-attf-href="/event/{{ slug(object.event_id) }}/ics" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;"><img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16" alt=""/> iCal/Outlook</a>
|
||||
<a t-attf-href="https://calendar.yahoo.com/?v=60&view=d&type=20&title={{ object.event_id.name }}&in_loc={{ location }}&st={{ format_datetime(object.event_id.date_begin, tz='UTC', dt_format='yyyyMMdd\'T\'HHmmss') }}&et={{ format_datetime(object.event_id.date_end, tz='UTC', dt_format='yyyyMMdd\'T\'HHmmss') }}" style="padding:3px 5px;border:1px solid #875A7B;color:#875A7B;text-decoration:none;border-radius:3px;" target="new">
|
||||
<img src="/web_editor/font_to_img/61525/rgb(135,90,123)/16" style="vertical-align:middle;" height="16" alt=""/> Yahoo
|
||||
</a>
|
||||
<br /><br />
|
||||
</div>
|
||||
<div>
|
||||
See you soon,<br/>
|
||||
<span style="color: #454748;">
|
||||
-- <br/>
|
||||
<t t-if="event_organizer">
|
||||
<t t-out="event_organizer.name">YourCompany</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
The <t t-out="object.event_id.name or ''">OpenWood Collection Online Reveal</t> Team
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr><td style="text-align:center;">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"/>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- DETAILS -->
|
||||
<tr>
|
||||
<td align="center" style="min-width: 590px;">
|
||||
<table width="590" border="0" cellpadding="0" cellspacing="0" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
|
||||
<tr><td valign="top" style="font-size: 14px;">
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td style="vertical-align:top;">
|
||||
<img src="/web_editor/font_to_img/61555/rgb(81,81,102)/34" style="padding:4px;max-width:inherit;" height="34" alt=""/>
|
||||
</td>
|
||||
<td style="padding: 0px 10px 0px 10px;width:50%;line-height:20px;vertical-align:top;">
|
||||
<div><strong>From</strong> <t t-out="object.event_id.date_begin_located or ''">May 4, 2021, 7:00:00 AM</t></div>
|
||||
<div><strong>To</strong> <t t-out="object.event_id.date_end_located or ''">May 6, 2021, 5:00:00 PM</t></div>
|
||||
<div style="font-size:12px;color:#9e9e9e"><i>(<t t-out="object.event_id.date_tz or ''">Europe/Brussels</t>)</i></div>
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<t t-if="event_address">
|
||||
<img src="/web_editor/font_to_img/61505/rgb(81,81,102)/34" style="padding:4px;max-width:inherit;" height="34" alt=""/>
|
||||
</t>
|
||||
</td>
|
||||
<td style="padding: 0px 10px 0px 10px;width:50%;vertical-align:top;">
|
||||
<t t-if="event_address">
|
||||
<t t-set="location" t-value="''"/>
|
||||
<t t-if="object.event_id.address_id.name">
|
||||
<div t-out="object.event_id.address_id.name">Teksa SpA</div>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.street">
|
||||
<div t-out="object.event_id.address_id.street">Puerto Madero 9710</div>
|
||||
<t t-set="location" t-value="object.event_id.address_id.street"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.street2">
|
||||
<div t-out="object.event_id.address_id.street2">Of A15, Santiago (RM)</div>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.street2}}"/>
|
||||
</t>
|
||||
<div>
|
||||
<t t-if="object.event_id.address_id.city">
|
||||
<t t-out="object.event_id.address_id.city">Pudahuel</t>,
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.city}}"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.state_id.name">
|
||||
<t t-out="object.event_id.address_id.state_id.name">C1</t>,
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.state_id.name}}"/>
|
||||
</t>
|
||||
<t t-if="object.event_id.address_id.zip">
|
||||
<t t-out="object.event_id.address_id.zip">98450</t>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.zip}}"/>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="object.event_id.address_id.country_id.name">
|
||||
<div t-out="object.event_id.address_id.country_id.name">Argentina</div>
|
||||
<t t-set="location" t-valuef="{{location}}, {{object.event_id.address_id.country_id.name}}"/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
@@ -189,7 +404,7 @@
|
||||
<li>Mail: <a t-attf-href="mailto:{{ event_organizer.email }}" style="text-decoration:none;color:#875A7B;" t-out="event_organizer.email or ''">info@yourcompany.com</a></li>
|
||||
</t>
|
||||
<t t-if="event_organizer.phone">
|
||||
<li>Phone: <t t-out="event_organizer.phone or ''">+1 650-123-4567</t></li>
|
||||
<li>Phone: <t t-out="event_organizer.phone">+1 650-123-4567</t></li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytz
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import _, api, Command, fields, models
|
||||
from odoo import _, api, Command, fields, models, tools
|
||||
from odoo.addons.base.models.res_partner import _tz_get
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.osv import expression
|
||||
@@ -677,6 +677,13 @@ class EventEvent(models.Model):
|
||||
result[event.id] = cal.serialize().encode('utf-8')
|
||||
return result
|
||||
|
||||
def _get_tickets_access_hash(self, registration_ids):
|
||||
""" Returns the ground truth hash for accessing the tickets in route /event/<int:event_id>/my_tickets.
|
||||
The dl links are always made event-dependant, hence the method linked to the record in self.
|
||||
"""
|
||||
self.ensure_one()
|
||||
return tools.hmac(self.env(su=True), 'event-registration-ticket-report-access', (self.id, sorted(registration_ids)))
|
||||
|
||||
@api.autovacuum
|
||||
def _gc_mark_events_done(self):
|
||||
""" move every ended events in the next 'ended stage' """
|
||||
|
||||
@@ -86,4 +86,12 @@
|
||||
<field name="paperformat_id" ref="paperformat_event_foldable_badge"/>
|
||||
</record>
|
||||
|
||||
<record id="action_report_event_registration_responsive_html_ticket" model="ir.actions.report">
|
||||
<field name="name">Responsive Html Full Page Ticket</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">event.event_registration_report_template_responsive_html_ticket</field>
|
||||
<field name="report_file">event.event_registration_report_template_responsive_html_ticket</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
(<span itemprop="timezone" t-out="event.date_tz"/>)
|
||||
</div>
|
||||
<div t-if="event.address_id" class="o_event_foldable_badge_font_faded o_event_foldable_badge_font_small text-center">
|
||||
<t t-set="use_map_marker" t-value="True"/>
|
||||
<t t-call="event.event_report_template_formatted_event_address"/>
|
||||
</div>
|
||||
<div class="text-center mt-5 pt-2">
|
||||
@@ -110,61 +111,39 @@
|
||||
|
||||
<template id="event_report_template_full_page_ticket">
|
||||
<div class="row page">
|
||||
<div class="o_event_full_page_ticket_container page w-100">
|
||||
<div t-attf-class="o_event_full_page_ticket_container page w-100 #{'o_event_full_page_ticket_responsive_html' if responsive_html else 'o_event_full_page_ticket'}">
|
||||
<div class="o_event_full_page_ticket_wrapper">
|
||||
<div class="o_event_full_page_ticket_details row">
|
||||
<div class="col-10">
|
||||
<div class="row">
|
||||
<div class="col-8 page">
|
||||
<div class="o_event_full_page_ticket_font_faded">
|
||||
Event Ticket For
|
||||
</div>
|
||||
<h5 class="o_event_full_page_ticket_event_name text-odoo fw-bold py-0 my-0" t-field="event.name"/>
|
||||
<span itemprop="startDate" t-field="event.date_begin"
|
||||
t-options='{"widget": "datetime", "date_only": True}'
|
||||
class="fw-bold"/>
|
||||
<span itemprop="startDateTime" t-field="event.date_begin"
|
||||
class="fw-bold"
|
||||
t-options='{"widget": "datetime", "time_only": True, "hide_seconds": True, "tz_name": event.date_tz}'/>
|
||||
<span class="oi oi-arrow-right o_event_full_page_ticket_font_faded"/>
|
||||
<span t-if="not event.is_one_day"
|
||||
itemprop="endDate" t-field="event.date_end"
|
||||
t-options='{"widget": "datetime", "date_only": True}'
|
||||
class="fw-bold"/>
|
||||
<span itemprop="endDateTime" t-field="event.date_end"
|
||||
class="fw-bold"
|
||||
t-options='{"widget": "datetime", "time_only": True, "hide_seconds": True, "tz_name": event.date_tz}'/>
|
||||
<span itemprop="timeZone" class="o_event_full_page_ticket_font_faded small">(<t t-out="event.date_tz"/>)</span>
|
||||
<div t-if="event.address_id" class="o_event_full_page_ticket_font_faded">
|
||||
<t t-call="event.event_report_template_formatted_event_address"/>
|
||||
</div>
|
||||
<br/>
|
||||
<h5 t-if="attendee" t-field="attendee.name"></h5>
|
||||
<h5 t-elif="not attendee"><span>John Doe</span></h5>
|
||||
<t t-set="first_ticket" t-value="event.event_ticket_ids[0] if event.event_ticket_ids else None"/>
|
||||
<div t-if="attendee" class="o_event_full_page_ticket_font_faded" t-field="attendee.event_ticket_id"/>
|
||||
<div t-elif="first_ticket" t-out="first_ticket.name"
|
||||
class="o_event_full_page_ticket_font_faded"/>
|
||||
</div>
|
||||
<div class="col-4 o_event_full_page_ticket_side_info page">
|
||||
<span t-if="event.organizer_id.image_128">
|
||||
<img t-att-src="image_data_uri(event.organizer_id.image_128)" class="o_event_full_page_ticket_event_logo mb-2"/>
|
||||
</span>
|
||||
<div t-if="attendee and attendee.partner_id" class="mb-2 o_event_full_page_ticket_side_info_booked_by">
|
||||
<div class="o_event_full_page_ticket_font_faded o_event_full_page_ticket_small_caps fw-bold">Booked By</div>
|
||||
<div class="o_event_full_page_ticket_small" t-field="attendee.partner_id"/>
|
||||
</div>
|
||||
<div class="o_event_full_page_ticket_details d-flex">
|
||||
<div class="o_event_full_page_left_details ps-3 pt-4 pb-3 pe-2">
|
||||
<span itemprop="startDate" t-field="event.date_begin"
|
||||
t-options='{"widget": "datetime", "date_only": True}'
|
||||
class="fw-bold"/>
|
||||
<span itemprop="startDateTime" t-field="event.date_begin"
|
||||
class="fw-bold"
|
||||
t-options='{"widget": "datetime", "time_only": True, "hide_seconds": True, "tz_name": event.date_tz}'/>
|
||||
<h2 class="o_event_full_page_ticket_event_name fw-bold pt-3 pb-2" t-field="event.name"/>
|
||||
<div t-if="event.address_id">
|
||||
<t t-set="use_map_marker" t-value="False"/>
|
||||
<t t-call="event.event_report_template_formatted_event_address"/>
|
||||
</div>
|
||||
<div t-if="not responsive_html" t-field="event.ticket_instructions" class="o_event_full_page_extra_instructions pt-3"></div>
|
||||
<div class="row pt-3 g-0">
|
||||
<h5 class="col-6" t-if="attendee" t-field="attendee.name"></h5>
|
||||
<h5 class="col-6" t-elif="not attendee"><span>John Doe</span></h5>
|
||||
<t t-set="first_ticket" t-value="event.event_ticket_ids[0] if event.event_ticket_ids else None"/>
|
||||
<div class="col-6 text-end">
|
||||
<div t-if="attendee" class="o_event_full_page_ticket_font_faded o_event_full_page_ticket_type pe-4" t-field="attendee.event_ticket_id"/>
|
||||
<div t-elif="first_ticket" t-out="first_ticket.name" class="o_event_full_page_ticket_font_faded pe-4"/>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="not responsive_html" class="o_event_full_page_ticket_sponsors_container"></div>
|
||||
</div>
|
||||
<div class="o_event_full_page_ticket_barcode col-2">
|
||||
<div class="o_event_full_page_ticket_barcode_container">
|
||||
</div>
|
||||
<div class="o_event_full_page_ticket_barcode">
|
||||
<div class="o_event_full_page_ticket_barcode_container px-2"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page oe_structure"/>
|
||||
<div t-field="event.ticket_instructions" class="o_event_full_page_extra_instructions px-2 pt-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -203,6 +182,7 @@
|
||||
<t t-call="web.html_container">
|
||||
<t t-set="event" t-value="attendee.event_id._set_tz_context()"/>
|
||||
<t t-set="main_object" t-value="attendee"/>
|
||||
<t t-set="responsive_html" t-value="False"/>
|
||||
<t t-call="event.event_report_full_page_ticket_layout">
|
||||
<t t-call="event.event_report_template_full_page_ticket"/>
|
||||
</t>
|
||||
@@ -215,6 +195,22 @@
|
||||
<t t-call="web.html_container">
|
||||
<t t-set="event" t-value="event._set_tz_context()"/>
|
||||
<t t-set="main_object" t-value="event"/>
|
||||
<t t-set="responsive_html" t-value="False"/>
|
||||
<t t-call="event.event_report_full_page_ticket_layout">
|
||||
<t t-call="event.event_report_template_full_page_ticket"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- EVENT RESPONSIVE HTML TICKET : Responsive web page -->
|
||||
|
||||
<template id="event_registration_report_template_responsive_html_ticket">
|
||||
<t t-foreach="docs" t-as="attendee">
|
||||
<t t-call="web.html_container">
|
||||
<t t-set="event" t-value="attendee.event_id._set_tz_context()"/>
|
||||
<t t-set="main_object" t-value="attendee"/>
|
||||
<t t-set="responsive_html" t-value="True"/>
|
||||
<t t-call="event.event_report_full_page_ticket_layout">
|
||||
<t t-call="event.event_report_template_full_page_ticket"/>
|
||||
</t>
|
||||
@@ -228,7 +224,7 @@
|
||||
<!-- Small utility template to display "Venue" as:
|
||||
fa-map-marker PartnerName
|
||||
RestOfAddress -->
|
||||
<span class="fa fa-map-marker"/>
|
||||
<span t-if="use_map_marker" class="fa fa-map-marker"/>
|
||||
<t t-if="event.address_id.contact_address.strip()">
|
||||
<t t-set="address_bits" t-value="event.address_id.contact_address.split('\n')"/>
|
||||
<t t-if="address_bits">
|
||||
@@ -241,7 +237,7 @@
|
||||
<t t-set="remaining_bits" t-value="address_bits[1:]"/>
|
||||
<t t-foreach="remaining_bits" t-as="address_bit">
|
||||
<t t-if="address_bit and address_bit.strip()">
|
||||
<span t-out="address_bit"/>
|
||||
<span class="text-muted" t-out="address_bit"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -28,13 +28,9 @@
|
||||
}
|
||||
|
||||
.o_event_foldable_badge_ticket {
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(/event/static/src/img/report_foldable_badge_background.png);
|
||||
|
||||
.o_event_foldable_badge_ticket_wrapper {
|
||||
background-color: white;
|
||||
border: solid 1px #939393;
|
||||
border-radius: .7rem;
|
||||
margin: 0px 8px;
|
||||
padding: 10px 3px;
|
||||
font-size: 1.2rem;
|
||||
|
||||
@@ -5,54 +5,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* COMMON FOR FULL PAGE TICKET AND RESPONSIVE HTML VERSION */
|
||||
|
||||
.o_event_full_page_ticket_container {
|
||||
z-index: 1;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(/event/static/src/img/report_full_page_ticket_background.png);
|
||||
padding: 40px 40px 0px 40px;
|
||||
padding-top: 40px;
|
||||
|
||||
.o_event_full_page_ticket_font_faded {
|
||||
color: #939393;
|
||||
}
|
||||
|
||||
.o_event_full_page_ticket_small {
|
||||
font-size: .8rem;
|
||||
.o_event_full_page_ticket_details {
|
||||
background-color: white;
|
||||
border: solid 1px #939393;
|
||||
margin: 0px 8px;
|
||||
padding: 10px 3px;
|
||||
box-shadow: -3px 3px 9px 0px rgba(0,0,0,0.51);
|
||||
}
|
||||
|
||||
.o_event_full_page_ticket_small_caps {
|
||||
text-transform: uppercase;
|
||||
font-size: .8rem;
|
||||
.o_event_full_page_ticket_barcode {
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_event_full_page_ticket_wrapper {
|
||||
z-index: 2;
|
||||
.o_event_full_page_ticket_details {
|
||||
background-color: white;
|
||||
border: solid 1px #939393;
|
||||
border-radius: .7rem;
|
||||
margin: 0px 8px;
|
||||
padding: 10px 3px;
|
||||
box-shadow: -3px 3px 9px 0px rgba(0,0,0,0.51);
|
||||
/* FULL PAGE TICKET - PDF REPORT */
|
||||
|
||||
.o_event_full_page_ticket_event_logo {
|
||||
max-height: 50px;
|
||||
}
|
||||
.o_event_full_page_ticket {
|
||||
|
||||
.o_event_full_page_ticket_barcode {
|
||||
padding-left: 30px;
|
||||
|
||||
.o_event_full_page_ticket_barcode_container {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
width: 67px;
|
||||
|
||||
img {
|
||||
padding: 0px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_event_full_page_left_details {
|
||||
width: 82%;
|
||||
}
|
||||
.o_event_full_page_ticket_barcode {
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.o_event_full_page_extra_instructions {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* FULL PAGE TICKET - RESONSIVE HTML WEB VERSION */
|
||||
|
||||
.o_event_full_page_ticket_responsive_html {
|
||||
.o_event_full_page_ticket_details {
|
||||
max-width: 1000px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.o_event_full_page_left_details {
|
||||
width: calc(100% - 132px);
|
||||
}
|
||||
.o_event_full_page_ticket_barcode {
|
||||
width: 132px;
|
||||
}
|
||||
// Give details more space for small screens
|
||||
@media (max-width: map-get($grid-breakpoints, "md")) {
|
||||
.o_event_full_page_left_details {
|
||||
width: calc(100% - 116px);
|
||||
padding-left: 0.5rem !important;
|
||||
}
|
||||
.o_event_full_page_ticket_barcode {
|
||||
width: 116px;
|
||||
.o_event_full_page_ticket_barcode_container {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
}
|
||||
.o_event_full_page_ticket_type {
|
||||
padding-right: 0rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ this event.
|
||||
'views/sale_order_views.xml',
|
||||
'data/event_sale_data.xml',
|
||||
'data/mail_templates.xml',
|
||||
'report/event_event_templates.xml',
|
||||
'report/event_sale_report_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/ir_rule.xml',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="event_report_template_full_page_ticket_inherit_sale" inherit_id="event.event_report_template_full_page_ticket">
|
||||
<xpath expr="//div[hasclass('o_event_full_page_ticket_side_info_booked_by')]" position="before">
|
||||
<div t-if="attendee and attendee.sale_order_id" class="mb-2">
|
||||
<div class="o_event_full_page_ticket_font_faded o_event_full_page_ticket_small_caps fw-bold">Order Ref</div>
|
||||
<div class="o_event_full_page_ticket_small" t-field="attendee.sale_order_id"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('o_event_full_page_ticket_side_info')]" position="inside">
|
||||
<div t-if="attendee and attendee.sale_order_id" class="mb-2">
|
||||
<div class="o_event_full_page_ticket_font_faded o_event_full_page_ticket_small_caps fw-bold">Order Date</div>
|
||||
<div class="o_event_full_page_ticket_small" t-out="attendee.sale_order_id.date_order.date()"/>
|
||||
</div>
|
||||
<div t-if="attendee and attendee.sale_order_line_id.price_unit">
|
||||
<div class="o_event_full_page_ticket_font_faded o_event_full_page_ticket_small_caps fw-bold">Price</div>
|
||||
<div class="o_event_full_page_ticket_small" t-field="attendee.sale_order_line_id.price_unit"
|
||||
t-options="{'widget': 'monetary', 'display_currency': attendee.sale_order_line_id.currency_id}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -8,6 +8,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<field name="event_id" position="after">
|
||||
<field name="sale_order_id" optional="hide"/>
|
||||
<field name="payment_status" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -361,6 +361,14 @@
|
||||
<u><a class="h4 text-primary" t-out="event.name" t-att-href="event.website_url" /></u>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="attendees" class="row mb-3">
|
||||
<div class="col-12 mb-2">
|
||||
<a class="btn btn-primary" title="Download All Tickets" target="_blank"
|
||||
t-attf-href="/event/{{ event.id }}/my_tickets?registration_ids={{ attendees.ids }}&tickets_hash={{ event._get_tickets_access_hash(attendees.ids) }}">
|
||||
Download Tickets <i class="ms-1 fa fa-download"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3 o_wereg_confirmed_attendees">
|
||||
<div class="col-md-4 col-xs-12 mt-3" t-foreach="attendees" t-as="attendee">
|
||||
<div class="d-flex flex-column">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<template id="event_report_full_page_ticket_layout_inherit_exhibitor" inherit_id="event.event_report_full_page_ticket_layout">
|
||||
<xpath expr="//div[hasclass('o_event_full_page_ticket_powered_by')]" position="before">
|
||||
<div class="o_event_full_page_ticket_sponsors_container text-center mb-2">
|
||||
<div t-if="not responsive_html" class="o_event_full_page_ticket_sponsors_container text-center mb-2">
|
||||
<t t-foreach="event.sponsor_ids.filtered(lambda sponsor: sponsor.image_128 and sponsor.website_published)[:10]"
|
||||
t-as="sponsor">
|
||||
<div class="o_event_full_page_ticket_sponsor_card d-inline-block">
|
||||
@@ -16,4 +16,21 @@
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="event_report_template_full_page_ticket_inherit_exhibitor" inherit_id="event.event_report_template_full_page_ticket">
|
||||
<xpath expr="//div[hasclass('o_event_full_page_ticket_sponsors_container')]" position="inside">
|
||||
<t t-set="sponsors" t-value="event.sponsor_ids.filtered(lambda sponsor: sponsor.image_128 and sponsor.website_published)[:3]"/>
|
||||
<div t-if="sponsors" class="o_event_full_page_ticket_sponsors_container row g-0 pt-2">
|
||||
<t t-foreach="sponsors" t-as="sponsor">
|
||||
<div class="col-4 text-center">
|
||||
<div class="h-100 p-2 pb-0 o_event_full_page_ticket_sponsor_card d-inline-block">
|
||||
<!-- Has to be base64-ified otherwise the reporting engine will sometimes load images
|
||||
and sometimes not before printing, resulting in random results. -->
|
||||
<img class="img img-fluid" t-attf-src="data:images/png;base64,#{sponsor.image_128}"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.o_event_full_page_ticket_footer {
|
||||
.o_event_full_page_ticket_footer, .o_event_full_page_ticket {
|
||||
.o_event_full_page_ticket_sponsors_container {
|
||||
min-height: 70px;
|
||||
.o_event_full_page_ticket_sponsor_card {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class WebsiteEventSale(WebsiteSale):
|
||||
@@ -10,4 +11,10 @@ class WebsiteEventSale(WebsiteSale):
|
||||
values = super(WebsiteEventSale,
|
||||
self)._prepare_shop_payment_confirmation_values(order)
|
||||
values['events'] = order.order_line.event_id
|
||||
attendee_per_event_read_group = request.env['event.registration'].sudo()._read_group(
|
||||
[('sale_order_id', '=', order.id)],
|
||||
groupby=['event_id'],
|
||||
aggregates=['id:array_agg'],
|
||||
)
|
||||
values['attendee_ids_per_event'] = dict(attendee_per_event_read_group)
|
||||
return values
|
||||
|
||||
@@ -80,7 +80,12 @@
|
||||
</div>
|
||||
<div class="col-lg-8 p-4">
|
||||
<h3 t-esc="event.name" />
|
||||
<a class="btn btn-primary mb-2" t-attf-href="/event/#{ slug(event) }">Go to Event</a>
|
||||
<t t-set="attendee_ids" t-value="attendee_ids_per_event.get(event, [])"/>
|
||||
<a t-if="order.state == 'sale' and attendee_ids" class="btn btn-primary text-white mb-2 me-2" target="_blank"
|
||||
t-attf-href="/event/{{ event.id }}/my_tickets?registration_ids={{ attendee_ids }}&tickets_hash={{ event._get_tickets_access_hash(attendee_ids) }}">
|
||||
Download Tickets <i class="ms-1 fa fa-download"/>
|
||||
</a>
|
||||
<a class="mb-2" t-attf-href="/event/#{ slug(event) }">Go to Event</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user