From 862ac93035706f000314fe29739ba168deea98b7 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 20 Jan 2025 12:52:40 +0100 Subject: [PATCH] [FIX] event_sale: failed payment on soldout events When there's a quotation for events registrations and the seats are limited, if the customer pays the quoutation the payment will fail when the quoutation gets confirmed. With this change we prevent the customer from paying that event that is soldout. Steps to reproduce: - Limit the seats for a given event. - Set autoconfirmation on. - Create a quotation for a ticket in that event. - Use the customer preview link to go to the portal view. - Pay the quotation (i.e. with demo payment method) - The confirmation crashes as there aren't seats available. This is an issue as well as the payment is already fulfilled at bank level, but as the system crashes the callback isn't confirmed at Odoo. --- addons/event_sale/__manifest__.py | 1 + addons/event_sale/models/sale_order.py | 16 ++++++++++++++++ addons/event_sale/views/templates.xml | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 addons/event_sale/views/templates.xml diff --git a/addons/event_sale/__manifest__.py b/addons/event_sale/__manifest__.py index 2b08fa36c0a23..7e879a7f54be5 100644 --- a/addons/event_sale/__manifest__.py +++ b/addons/event_sale/__manifest__.py @@ -24,6 +24,7 @@ 'views/event_registration_views.xml', 'views/event_views.xml', 'views/sale_order_views.xml', + 'views/templates.xml', 'data/event_sale_data.xml', 'data/mail_data.xml', 'report/event_event_templates.xml', diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index 5e64c979fd69f..707b0eff78410 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -7,6 +7,7 @@ class SaleOrder(models.Model): _inherit = "sale.order" attendee_count = fields.Integer('Attendee Count', compute='_compute_attendee_count') + has_soldout_event = fields.Boolean(compute="_compute_has_soldout_event") def write(self, vals): """ Synchronize partner from SO to registrations. This is done notably @@ -52,6 +53,21 @@ def _compute_attendee_count(self): for sale_order in self: sale_order.attendee_count = attendee_count_data.get(sale_order.id, 0) + def _compute_has_soldout_event(self): + """Meant to be used in the portal to prevent customers from paying for an event + that is sold out. Not only because we'd overbook the event, but also because it + will probably crash on the confirmation of the order when the registrations + are created.""" + self.has_soldout_event = False + for order in self.filtered(lambda x: x.state in ["draft", "sent"]): + order.has_soldout_event = bool(order.order_line.event_id.filtered( + lambda x: x.seats_limited and x.seats_max and x.seats_available <= 0 + )) + + def has_to_be_paid(self, include_draft=False): + has_to_be_paid = super().has_to_be_paid(include_draft=include_draft) + return has_to_be_paid and not self.has_soldout_event + def unlink(self): self.order_line._unlink_associated_registrations() return super(SaleOrder, self).unlink() diff --git a/addons/event_sale/views/templates.xml b/addons/event_sale/views/templates.xml new file mode 100644 index 0000000000000..7da78df7525e8 --- /dev/null +++ b/addons/event_sale/views/templates.xml @@ -0,0 +1,11 @@ + + + +