From 72b0d77cb5296fddd76a012ced93c2f316f6a97c Mon Sep 17 00:00:00 2001 From: Noe Antoine Date: Tue, 9 May 2023 16:02:56 +0200 Subject: [PATCH] [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) --- addons/event/__manifest__.py | 1 + addons/event/controllers/main.py | 52 +++ addons/event/data/mail_template_data.xml | 311 +++++++++++++++--- addons/event/models/event_event.py | 9 +- addons/event/report/event_event_reports.xml | 8 + addons/event/report/event_event_templates.xml | 94 +++--- .../img/report_foldable_badge_background.png | Bin 6587 -> 0 bytes .../report_full_page_ticket_background.png | Bin 4249 -> 0 bytes .../src/scss/event_foldable_badge_report.scss | 4 - .../scss/event_full_page_ticket_report.scss | 53 +-- ...ll_page_ticket_responsive_html_report.scss | 32 ++ addons/event_sale/__manifest__.py | 1 - addons/event_sale/models/account_move.py | 2 +- .../report/event_event_templates.xml | 22 -- .../views/event_registration_views.xml | 1 + .../event_templates_page_registration.xml | 8 + .../website_event_exhibitor_templates.xml | 19 +- .../scss/event_full_page_ticket_report.scss | 2 +- addons/website_event_sale/controllers/sale.py | 7 + .../views/website_sale_templates.xml | 7 +- 20 files changed, 469 insertions(+), 164 deletions(-) delete mode 100644 addons/event/static/src/img/report_foldable_badge_background.png delete mode 100644 addons/event/static/src/img/report_full_page_ticket_background.png create mode 100644 addons/event/static/src/scss/event_full_page_ticket_responsive_html_report.scss delete mode 100644 addons/event_sale/report/event_event_templates.xml diff --git a/addons/event/__manifest__.py b/addons/event/__manifest__.py index 286b684cdfa..4d9a1002d94 100644 --- a/addons/event/__manifest__.py +++ b/addons/event/__manifest__.py @@ -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', diff --git a/addons/event/controllers/main.py b/addons/event/controllers/main.py index 3d11a3eee39..33c52960d59 100644 --- a/addons/event/controllers/main.py +++ b/addons/event/controllers/main.py @@ -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//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) diff --git a/addons/event/data/mail_template_data.xml b/addons/event/data/mail_template_data.xml index 84c490aec06..4fd4458ea59 100644 --- a/addons/event/data/mail_template_data.xml +++ b/addons/event/data/mail_template_data.xml @@ -10,31 +10,6 @@ {{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }} Sent automatically to someone after they registered to an event -
- Dear ,
- Thank you for your inquiry.
- Here is your badge for the event OpenWood Collection Online Reveal.
- If you have any questions, please let us know. -

- Thank you, - -
- --
Mitchell Admin
-
-
- - {{ object.event_id.lang or object.partner_id.lang }} - - - - - Event: Registration Confirmation - - Your registration at {{ object.event_id.name }} - {{ (object.event_id.organizer_id.email_formatted or object.event_id.user_id.email_formatted or '') }} - {{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }} - Sent to attendees after registering to an event - @@ -76,14 +49,13 @@ + +
@@ -53,13 +28,11 @@ - - - View Event - - - + + Download Badge + +
Hello ,
- We are happy to confirm your registration to the event + Please find attached your badge for OpenWood Collection Online Reveal - OpenWood Collection Online Reveal + OpenWood Collection Online Reveal. - for attendee .

@@ -138,33 +110,276 @@ -
Teksa SpA
+
Teksa SpA
-
Puerto Madero 9710
+
Puerto Madero 9710
-
Of A15, Santiago (RM)
- +
Of A15, Santiago (RM)
+
- Pudahuel, - + Pudahuel, + - C1, - + C1, + - 98450 - + 98450 +
-
Argentina
- +
Argentina
+ + +
+
+ + + +
+
+ + + + + +
+ Questions about this event? +
Please contact the organizer:
+ +
+
+ + + + +
+
+ + + + + +
+ Get the best mobile experience. + Install our mobile app +
+
+ + + + +
+
+ + + + + +
+ +
+
+ + + + + + + + + + + + +
+ Sent by YourCompany + +
+ Discover all our events. +
+
+
+ + +
+ + {{ object.event_id.lang or object.partner_id.lang }} + +
+ + + Event: Registration Confirmation + + Your registration at {{ object.event_id.name }} + {{ (object.event_id.organizer_id.email_formatted or object.event_id.user_id.email_formatted or '') }} + {{ (object.email and '"%s" <%s>' % (object.name, object.email) or object.partner_id.email_formatted or '') }} + Sent to attendees after registering to an event + +
+ + + + + + + + + + + + + + + + + + +
+ + + +
+ Your registration
+ + + +
+ + View Ticket + + + + +
+
+
+
+ + + +
+
+ Hello ,
+ We are happy to confirm your registration to the event + + OpenWood Collection Online Reveal + + + OpenWood Collection Online Reveal + . + + This ticket was registered by . + +
+
+
+ The order for this ticket has reference + and was placed on + for an amount of + + . +
+
+
+ Add this event to your calendar + Google + iCal/Outlook + + Yahoo + +

+
+
+ See you soon,
+ + --
+ + YourCompany + + + The OpenWood Collection Online Reveal Team + +
+
+
+
+
+
+ +
+ + + + + + @@ -189,7 +404,7 @@
  • Mail: info@yourcompany.com
  • -
  • Phone: +1 650-123-4567
  • +
  • Phone: +1 650-123-4567
  • diff --git a/addons/event/models/event_event.py b/addons/event/models/event_event.py index a2b15e24100..7ac8da308b6 100644 --- a/addons/event/models/event_event.py +++ b/addons/event/models/event_event.py @@ -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//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' """ diff --git a/addons/event/report/event_event_reports.xml b/addons/event/report/event_event_reports.xml index a09483ed43f..3970b91f394 100644 --- a/addons/event/report/event_event_reports.xml +++ b/addons/event/report/event_event_reports.xml @@ -86,4 +86,12 @@ + + Responsive Html Full Page Ticket + event.registration + qweb-pdf + event.event_registration_report_template_responsive_html_ticket + event.event_registration_report_template_responsive_html_ticket + + diff --git a/addons/event/report/event_event_templates.xml b/addons/event/report/event_event_templates.xml index 64af5054b30..0bc0f01120b 100644 --- a/addons/event/report/event_event_templates.xml +++ b/addons/event/report/event_event_templates.xml @@ -36,6 +36,7 @@ ()
    +
    @@ -110,61 +111,39 @@ @@ -203,6 +182,7 @@ + @@ -215,6 +195,22 @@ + + + + + + + + + + +
    + + +
    From May 4, 2021, 7:00:00 AM
    +
    To May 6, 2021, 5:00:00 PM
    +
    (Europe/Brussels)
    +
    + + + + + + + +
    Teksa SpA
    +
    + +
    Puerto Madero 9710
    + + + +
    Of A15, Santiago (RM)
    + + +
    + + Pudahuel, + + + + C1, + + + + 98450 + + +
    + +
    Argentina
    +