示例#1
0
def tickets_reserved(flow=None, currency=None):
    if current_user.is_anonymous:
        return redirect(url_for('users.login', next=url_for('.tickets_reserved', flow=flow)))

    basket = Basket(current_user, get_user_currency())
    basket.load_purchases_from_db()
    basket.save_to_session()

    if currency in CURRENCY_SYMBOLS:
        set_user_currency(currency)

    return redirect(url_for('tickets.pay', flow=flow))
示例#2
0
def tickets_reserved(flow=None, currency=None):
    if current_user.is_anonymous:
        return redirect(
            url_for("users.login", next=url_for(".tickets_reserved", flow=flow))
        )

    basket = Basket(current_user, get_user_currency())
    basket.load_purchases_from_db()
    basket.save_to_session()

    if currency in CURRENCY_SYMBOLS:
        set_user_currency(currency)

    return redirect(url_for("tickets.pay", flow=flow))
示例#3
0
def handle_ticket_selection(form, view: ProductView, flow: str,
                            basket: Basket):
    """
    For consistency and to avoid surprises, we try to ensure a few things here:
    - if the user successfully submits a form with no errors, their basket is updated
    - if they don't, the basket is left untouched
    - the basket is updated to match what was submitted, even if they added tickets in another tab
    - if they already have tickets in their basket, only reserve the extra tickets as necessary
    - don't unreserve surplus tickets until the payment is created
    - if the user hasn't submitted anything, we use their current reserved ticket counts
    - if the user has reserved tickets from exhausted tiers on this view, we still show them
    - if the user has reserved tickets from other views, don't show and don't mess with them
    - this means the user can combine tickets from multiple views into a single basket
    - show the sold-out/unavailable states only when the user doesn't have reserved tickets

    We currently don't deal with multiple price tiers being available around the same time.
    Reserved tickets from a previous tier should be cancelled before activating a new one.
    """
    if form.currency_code.data != get_user_currency():
        set_user_currency(form.currency_code.data)
        # Commit so we don't lose the currency change if an error occurs
        db.session.commit()
        # Reload the basket because set_user_currency has changed it under us
        basket = Basket.from_session(current_user, get_user_currency())

    form.add_to_basket(basket)

    if not any(basket.values()):
        empty_baskets.inc()
        if view.type == "tickets":
            flash("Please select at least one ticket to buy.")
        elif view.type == "hire":
            flash("Please select at least one item to hire.")
        else:
            flash("Please select at least one item to buy.")

        basket.save_to_session()
        return redirect(url_for("tickets.main", flow=flow))

    # Ensure this purchase is valid for this voucher.
    voucher = Voucher.get_by_code(basket.voucher)
    if voucher and not voucher.check_capacity(basket):
        basket.save_to_session()
        if voucher.is_used:
            flash("Your voucher has been used by someone else.")
        else:
            flash(f"You can only purchase {voucher.tickets_remaining} adult "
                  "tickets with this voucher. Please select fewer tickets.")
        return redirect(url_for("tickets.main", flow=flow))

    app.logger.info("Saving basket %s", basket)

    try:
        # Convert the user's basket into a purchase.
        basket.create_purchases()
        basket.ensure_purchase_capacity()
        db.session.commit()
    except CapacityException as e:
        # Damn, capacity's gone since we created the purchases
        # Redirect back to show what's currently in the basket
        db.session.rollback()
        no_capacity.inc()
        app.logger.warn("Limit exceeded creating tickets: %s", e)
        flash(
            "We're very sorry, but there is not enough capacity available to "
            "allocate these tickets. You may be able to try again with a smaller amount."
        )
        return redirect(url_for("tickets.main", flow=flow))

    basket.save_to_session()

    if basket.total != 0:
        # Send the user off to pay
        return redirect(url_for("tickets.pay", flow=flow))
    else:
        return handle_free_tickets(flow, view, basket)