@@ -586,73 +586,6 @@ def _check_slots_dates(self):
586
586
# raise ValidationError(_('There are not enough seats available for:')
587
587
# + '\n%s\n' % '\n'.join(sold_out_events))
588
588
589
- def _verify_seats_availability (self , slot_id = False , ticket_id = False , minimal_availability = 0 ):
590
- """ Check the number of seats available for the event.
591
- :slot_id: for the specified slot if specified.
592
- :ticket_id: for the specified ticket if specified.
593
- :minimal_availability: A minimal availability can be specified to ensure there is
594
- at least this number of seats left. Useful in the sale flow.
595
- Raises:
596
- ValidationError: If the event / slot / ticket / slot ticket do not have enough seats available.
597
- """
598
- sold_out_records = []
599
- slot_tickets_nb_registrations = {
600
- (slot .id , ticket .id ): count
601
- for (slot , ticket , count ) in self .env ['event.registration' ]._read_group (
602
- domain = [('event_id' , 'in' , self .ids ), ('state' , 'in' , ['open' , 'done' ]), ('active' , '=' , True )],
603
- groupby = ['event_slot_id' , 'event_ticket_id' ],
604
- aggregates = ['__count' ]
605
- )
606
- }
607
- for event in self :
608
- slot = False
609
- ticket = False
610
- if slot_id :
611
- slot = self .env ['event.slot' ].browse (slot_id )
612
- if ticket_id :
613
- ticket = self .env ['event.event.ticket' ].browse (ticket_id )
614
- # Event / slot seats_max
615
- if event .seats_limited and event .seats_max :
616
- # TODO: ne fonctionne pas parce que ça verifie les valeurs avant le write et on ne sait pas
617
- # cb de registrations sont impactée, on pourrait vouloir write sur 6 registrations
618
- if slot and slot .seats_available < minimal_availability :
619
- sold_out_records .append (_ (
620
- '- the slot "%(slot_name)s" (%(event_name)s): Missing %(nb_too_many)i seats.' ,
621
- slot_name = slot .name ,
622
- event_name = event .name ,
623
- nb_too_many = minimal_availability - slot .seats_available ,
624
- ))
625
- # TODO: same
626
- elif event .seats_available < minimal_availability :
627
- sold_out_records .append (_ (
628
- '- the event "%(event_name)s": Missing %(nb_too_many)i seats.' ,
629
- event_name = event .name ,
630
- nb_too_many = minimal_availability - event .seats_available ,
631
- ))
632
- # Ticket seats_max
633
- if ticket and ticket .seats_max :
634
- if slot :
635
- # TODO: same
636
- slot_ticket_seats_available = ticket .seats_max - slot_tickets_nb_registrations .get ((slot .id , ticket .id ), 0 )
637
- if slot_ticket_seats_available <= minimal_availability :
638
- sold_out_records .append (_ (
639
- '- the slot ticket "%(slot_ticket_name)s" (%(event_name)s): Missing %(nb_too_many)i seats.' ,
640
- slot_ticket_name = f'{ ticket .name } - { slot .name } ' ,
641
- event_name = event .name ,
642
- nb_too_many = minimal_availability - slot_ticket_seats_available ,
643
- ))
644
- # TODO: same
645
- elif ticket .seats_available <= minimal_availability :
646
- sold_out_records .append (_ (
647
- '- the ticket "%(ticket_name)s" (%(event_name)s): Missing %(nb_too_many)i seats.' ,
648
- ticket_name = ticket .name ,
649
- event_name = event .name ,
650
- nb_too_many = minimal_availability - ticket .seats_available ,
651
- ))
652
- if sold_out_records :
653
- raise ValidationError (_ ('There are not enough seats available for:\n %(sold_out_records)s\n ' ,
654
- sold_out_records = '\n ' .join (sold_out_records )))
655
-
656
589
@api .constrains ('date_begin' , 'date_end' )
657
590
def _check_closing_date (self ):
658
591
for event in self :
@@ -721,6 +654,82 @@ def _set_tz_context(self):
721
654
self .ensure_one ()
722
655
return self .with_context (tz = self .date_tz or 'UTC' )
723
656
657
+ def _get_seats_availability (self , slot_tickets ):
658
+ self .ensure_one ()
659
+ if not (all (len (item ) == 2 for item in slot_tickets )):
660
+ raise ValueError ('Input should be a list of tuples containing slot, ticket' )
661
+
662
+ slot_tickets_nb_registrations = {
663
+ (slot .id , ticket .id ): count
664
+ for (slot , ticket , count ) in self .env ['event.registration' ]._read_group (
665
+ domain = [('event_id' , 'in' , self .ids ), ('state' , 'in' , ['open' , 'done' ]), ('active' , '=' , True )],
666
+ groupby = ['event_slot_id' , 'event_ticket_id' ],
667
+ aggregates = ['__count' ]
668
+ )
669
+ }
670
+
671
+ availabilities = []
672
+ for slot , ticket in slot_tickets :
673
+ available = None
674
+ # event is constrained: max stands for either each slot, either global (no slots)
675
+ if self .seats_max :
676
+ if slot :
677
+ available = slot .seats_available
678
+ else :
679
+ available = self .seats_available
680
+ # ticket is constrained: max standard for either each slot / ticket, either global (no slots)
681
+ if available != 0 and ticket and ticket .seats_max :
682
+ if slot :
683
+ ticket_available = ticket .seats_max - slot_tickets_nb_registrations .get ((slot .id , ticket .id ), 0 )
684
+ else :
685
+ ticket_available = ticket .seats_available
686
+ available = ticket_available if available == None else min (available , ticket_available )
687
+ availabilities .append (available )
688
+ return availabilities
689
+
690
+ def _verify_seats_availability (self , slot_tickets ):
691
+ """ Check event seats availability, for combinations of slot / ticket.
692
+
693
+ :slot_tickets: a list of tuples(slot, ticket, count). SLot and ticket
694
+ are optional, depending on event configuration. If count is 0
695
+ it is a simple check current values do not overflow limit. If count
696
+ is given, it serves as a check there are enough remaining seats.
697
+
698
+ Raises:
699
+ ValidationError: if the event / slot / ticket do not have enough
700
+ available seats
701
+ """
702
+ self .ensure_one ()
703
+ if not (all (len (item ) == 3 for item in slot_tickets )):
704
+ raise ValueError ('Input should be a list of tuples containing slot, ticket, count' )
705
+
706
+ sold_out = []
707
+ availabilities = self ._get_seats_availability ([(item [0 ], item [1 ]) for item in slot_tickets ])
708
+ for (slot , ticket , count ), available in zip (slot_tickets , availabilities , strict = True ):
709
+ if available is None : # unconstrained
710
+ continue
711
+ if available < count :
712
+ if slot and ticket :
713
+ name = f'{ ticket .name } - { slot .name } '
714
+ elif slot :
715
+ name = slot .name
716
+ elif ticket :
717
+ name = ticket .name
718
+ else :
719
+ name = self .name
720
+ sold_out .append ((name , count - available ))
721
+
722
+ if sold_out :
723
+ info = [] # note: somehow using list comprehension make translate.py crash in default lang
724
+ for item in sold_out :
725
+ info .append (_ ('tde %(slot_name)s: missing %(count)s seats' , slot_name = item [0 ], count = item [1 ]))
726
+ raise ValidationError (
727
+ _ ('There are not enough seats available for %(event_name)s:\n %(sold_out_info)s' ,
728
+ event_name = self .name ,
729
+ sold_out_info = '\n ' .join (info ),
730
+ )
731
+ )
732
+
724
733
# ------------------------------------------------------------
725
734
# ACTIONS
726
735
# ------------------------------------------------------------
0 commit comments