diff --git a/src/pretix/base/services/cart.py b/src/pretix/base/services/cart.py index 66eaa0b1fc..03e5ad36f2 100644 --- a/src/pretix/base/services/cart.py +++ b/src/pretix/base/services/cart.py @@ -61,7 +61,7 @@ from pretix.base.models import ( Seat, SeatCategoryMapping, Voucher, ) from pretix.base.models.event import SubEvent -from pretix.base.models.orders import OrderFee +from pretix.base.models.orders import CheckoutSession, OrderFee from pretix.base.models.tax import TaxRule from pretix.base.reldate import RelativeDateWrapper from pretix.base.services.checkin import _save_answers @@ -472,6 +472,16 @@ class CartManager: if term_last < time_machine_now(self.real_now_dt): raise CartError(error_messages['payment_ended']) + def _ensure_checkout_session(self): + CheckoutSession.objects.get_or_create( + event=self.event, + cart_id=self.cart_id, + defaults={ + "sales_channel": self._sales_channel, + "testmode": self.event.testmode, + }, + ) + def _extend_expiry_of_valid_existing_positions(self): # real_now_dt is initialized at CartManager instantiation, so it's slightly in the past. Add a small # delta to reduce risk of extending already expired CartPositions. @@ -1559,6 +1569,7 @@ class CartManager: def commit(self): self._check_presale_dates() + self._ensure_checkout_session() self._check_max_cart_size() err = self._delete_out_of_timeframe() diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 23b21c9be1..e021f72ec8 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -73,7 +73,7 @@ from pretix.base.models import ( ) from pretix.base.models.event import SubEvent from pretix.base.models.orders import ( - BlockedTicketSecret, InvoiceAddress, OrderFee, OrderRefund, + BlockedTicketSecret, CheckoutSession, InvoiceAddress, OrderFee, OrderRefund, generate_secret, ) from pretix.base.models.organizer import SalesChannel, TeamAPIToken @@ -1030,7 +1030,8 @@ def _apply_rounding_and_fees(positions: List[CartPosition], payment_requests: Li def _create_order(event: Event, *, email: str, positions: List[CartPosition], now_dt: datetime, payment_requests: List[dict], sales_channel: SalesChannel, locale: str=None, address: InvoiceAddress=None, meta_info: dict=None, shown_total=None, - customer=None, valid_if_pending=False, api_meta: dict=None, tax_rounding_mode=None): + customer=None, valid_if_pending=False, api_meta: dict=None, tax_rounding_mode=None, + cart_id: str=None): payments = [] try: @@ -1113,6 +1114,8 @@ def _create_order(event: Event, *, email: str, positions: List[CartPosition], no if meta_info: for msg in meta_info.get('confirm_messages', []): order.log_action('pretix.event.order.consent', data={'msg': msg}) + if cart_id: + CheckoutSession.objects.filter(event=event, cart_id=cart_id).delete() order_placed.send(event, order=order, bulk=False) return order, payments @@ -1160,7 +1163,7 @@ def _order_placed_email_attendee(event: Event, order: Order, position: OrderPosi def _perform_order(event: Event, payment_requests: List[dict], position_ids: List[str], email: str, locale: str, address: int, meta_info: dict=None, sales_channel: str='web', - shown_total=None, customer=None, api_meta: dict=None, tax_rounding_mode=None): + shown_total=None, customer=None, api_meta: dict=None, tax_rounding_mode=None, cart_id: str=None): for p in payment_requests: p['pprov'] = event.get_payment_providers(cached=True)[p['provider']] if not p['pprov']: @@ -1267,6 +1270,7 @@ def _perform_order(event: Event, payment_requests: List[dict], position_ids: Lis valid_if_pending=valid_if_pending, api_meta=api_meta, tax_rounding_mode=tax_rounding_mode, + cart_id=cart_id, ) try: @@ -3169,12 +3173,12 @@ class OrderChangeManager: def perform_order(self, event: Event, payments: List[dict], positions: List[str], email: str=None, locale: str=None, address: int=None, meta_info: dict=None, sales_channel: str='web', shown_total=None, customer=None, override_now_dt: datetime=None, - api_meta: dict=None): + api_meta: dict=None, cart_id: str=None): with language(locale), time_machine_now_assigned(override_now_dt): try: try: return _perform_order(event, payments, positions, email, locale, address, meta_info, - sales_channel, shown_total, customer, api_meta) + sales_channel, shown_total, customer, api_meta, cart_id=cart_id) except LockTimeoutException: self.retry() except (MaxRetriesExceededError, LockTimeoutException): diff --git a/src/pretix/presale/checkoutflow.py b/src/pretix/presale/checkoutflow.py index b6db5dcd97..41a77a7686 100644 --- a/src/pretix/presale/checkoutflow.py +++ b/src/pretix/presale/checkoutflow.py @@ -1660,6 +1660,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep): customer=self.cart_session.get('customer'), override_now_dt=time_machine_now(default=None), api_meta=api_meta, + cart_id=get_or_create_cart_id(request), ) def get_success_message(self, value):