[FW][FIX] event : Changing seats_max could desync seates_reserved
Issue: Sometimes, when changing the Maximum (seats_max) on one of the tickets of an event, it triggered a recompute for the other tickets Steps to reproduce : Install Events Settings > Event > Enable "Tickets" Create an event template (or use Sell Online default one) with Check "Ticketing" and set the line price to 0 Create an event : with that template and Autoconfirm checked Add a line for the Tickets: name: VIP price: 10 Save the event Create two attendees for the event, one for each Event Ticket (event_ticket_id) and confirm them (on the form, not Confirm Attendee) Change the Maximum (seats_max) of one ticket and save -> the Confirmed (seats_reserved) will be recomputed but the confirmed for the other ticket will increase as well Side-Note: I haven't been able to find a deterministic way to reproduce the bug but it seems that the bug appear the most when doing all the steps at once, and trying to not log out or refresh the page. Also it works best on a runbot or at least with runbot data. Without my modification, the new test passes on my local odoo server, but fails on a dump of a runbot on my computer, adding my modification makes it work on either case Why is that a bug: The recomputation seems to fail for some reason, we are setting all the event/ticket in self to 0, but only update the value of those by fetching a SQL query so there might be a desync there opw-2642555 closes odoo/odoo#78023 Forward-port-of: #76492 X-original-commit: f4c936c9dc141de27a77006fb87dd2b63d88ec97 Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com> Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com> Signed-off-by: Nathan Marotte <nmarotte@users.noreply.github.com>
This commit is contained in:
@@ -232,7 +232,7 @@ class EventEvent(models.Model):
|
||||
self._cr.execute(query, (tuple(self.ids),))
|
||||
res = self._cr.fetchall()
|
||||
for event_id, state, num in res:
|
||||
results[event_id][state_field[state]] += num
|
||||
results[event_id][state_field[state]] = num
|
||||
|
||||
# compute seats_available
|
||||
for event in self:
|
||||
|
||||
@@ -98,6 +98,7 @@ class EventTicket(models.Model):
|
||||
for ticket in self:
|
||||
ticket.seats_unconfirmed = ticket.seats_reserved = ticket.seats_used = ticket.seats_available = 0
|
||||
# aggregate registrations by ticket and by state
|
||||
results = {}
|
||||
if self.ids:
|
||||
state_field = {
|
||||
'draft': 'seats_unconfirmed',
|
||||
@@ -112,10 +113,11 @@ class EventTicket(models.Model):
|
||||
self.env['event.registration'].flush(['event_id', 'event_ticket_id', 'state'])
|
||||
self.env.cr.execute(query, (tuple(self.ids),))
|
||||
for event_ticket_id, state, num in self.env.cr.fetchall():
|
||||
ticket = self.browse(event_ticket_id)
|
||||
ticket[state_field[state]] += num
|
||||
results.setdefault(event_ticket_id, {})[state_field[state]] = num
|
||||
|
||||
# compute seats_available
|
||||
for ticket in self:
|
||||
ticket.update(results.get(ticket._origin.id or ticket.id, {}))
|
||||
if ticket.seats_max > 0:
|
||||
ticket.seats_available = ticket.seats_max - (ticket.seats_reserved + ticket.seats_used)
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
from . import test_event_internals
|
||||
from . import test_event_sale
|
||||
from . import test_event_sale_ui
|
||||
from . import test_event_specific
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import datetime
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo.addons.event_sale.tests.common import TestEventSaleCommon
|
||||
from odoo.tests.common import Form
|
||||
|
||||
|
||||
class TestEventSpecific(TestEventSaleCommon):
|
||||
|
||||
def test_event_change_max_seat_no_side_effect(self):
|
||||
"""
|
||||
Test that changing the Maximum (seats_max), the seats_reserved of all the ticket do not change
|
||||
"""
|
||||
# Enable "sell tickets with sales orders" so that we have a price column on the tickets
|
||||
# Event template
|
||||
with Form(self.env['event.type']) as event_type_form:
|
||||
event_type_form.name = "Pastafarian Event Template"
|
||||
# Edit the default line
|
||||
with event_type_form.event_type_ticket_ids.new() as ticket_line:
|
||||
ticket_line.name = 'Pastafarian Registration'
|
||||
ticket_line.price = 0
|
||||
event_type = event_type_form.save()
|
||||
|
||||
with Form(self.env['event.event']) as event_event_form:
|
||||
event_event_form.name = 'Annual Pastafarian Reunion (APR)'
|
||||
event_event_form.date_begin = datetime.datetime.now() + relativedelta(days=2)
|
||||
event_event_form.date_end = datetime.datetime.now() + relativedelta(days=3)
|
||||
event_event_form.event_type_id = event_type # Set the template
|
||||
event_event_form.auto_confirm = True
|
||||
# Create second ticket (VIP)
|
||||
with event_event_form.event_ticket_ids.new() as ticket_line:
|
||||
ticket_line.name = 'VIP (Very Important Pastafarian)'
|
||||
ticket_line.price = 10
|
||||
event_event = event_event_form.save()
|
||||
|
||||
# Add two registrations for the event, one registration for each ticket type
|
||||
for ticket in event_event.event_ticket_ids:
|
||||
self.env['event.registration'].create({
|
||||
'event_id': event_event.id,
|
||||
'event_ticket_id': ticket.id
|
||||
})
|
||||
|
||||
# Edit the maximum
|
||||
before_confirmed = [t.seats_reserved for t in event_event.event_ticket_ids]
|
||||
with Form(event_event) as event_event_form:
|
||||
with event_event_form.event_ticket_ids.edit(0) as ticket_line:
|
||||
ticket_line.seats_max = ticket_line.seats_max + 1
|
||||
after_confirmed = [t.seats_reserved for t in event_event.event_ticket_ids]
|
||||
self.assertEqual(before_confirmed, after_confirmed)
|
||||
Reference in New Issue
Block a user