Пример #1
0
def handle_free_tickets(flow: str, view: ProductView, basket: Basket):
    """The user is trying to "buy" only free tickets.

    This is effectively a payment stage, handled differently
    from the rest of the flow.
    """
    # They must be authenticated for this.
    if not current_user.is_authenticated:
        app.logger.warn("User is not authenticated, sending to login")
        flash("You must be logged in to buy additional free tickets")
        return redirect(
            url_for("users.login", next=url_for("tickets.main", flow=flow)))

    # We sell under-12 tickets to non-CfP users, to enforce capacity.
    # We don't let people order an under-12 ticket on its own.
    # However, CfP users need to be able to buy day and parking tickets.
    admissions_tickets = current_user.get_owned_tickets(
        type="admission_ticket")
    if not any(admissions_tickets) and not view.cfp_accepted_only:
        app.logger.warn(
            "User trying to buy free add-ons without an admission ticket")
        flash(
            "You must have an admissions ticket to buy additional free tickets"
        )
        return redirect(url_for("tickets.main", flow=flow))

    basket.user = current_user
    basket.check_out_free()
    db.session.commit()

    Basket.clear_from_session()

    msg = EmailMessage(
        "Your EMF ticket order",
        from_email=from_email("TICKETS_EMAIL"),
        to=[current_user.email],
    )

    already_emailed = set_tickets_emailed(current_user)
    msg.body = render_template(
        "emails/tickets-ordered-email-free.txt",
        user=current_user,
        basket=basket,
        already_emailed=already_emailed,
    )
    if feature_enabled("ISSUE_TICKETS"):
        attach_tickets(msg, current_user)

    msg.send()

    if len(basket.purchases) == 1:
        flash("Your ticket has been confirmed")
    else:
        flash("Your tickets have been confirmed")

    return redirect(url_for("users.purchases"))
Пример #2
0
def start_payment(form: TicketPaymentForm, basket: Basket, flow: str):
    if Decimal(form.basket_total.data) != Decimal(basket.total):
        # Check that the user's basket approximately matches what we told them they were paying.
        price_changed.inc()
        app.logger.warn(
            "User's basket has changed value %s -> %s",
            form.basket_total.data,
            basket.total,
        )
        flash(
            """The items you selected have changed, possibly because you had two windows open.
              Please verify that you've selected the correct items."""
        )
        return redirect(url_for("tickets.pay", flow=flow))

    user = current_user

    if user.is_anonymous:
        try:
            new_user = create_current_user(form.email.data, form.name.data)
        except IntegrityError as e:
            app.logger.warn("Adding user raised %r, possible double-click", e)
            return redirect(url_for("tickets.pay", flow=flow))

        user = new_user
    elif user.name == user.email:
        user.name = form.name.data

    if form.allow_promo.data:
        user.promo_opt_in = True

    if basket.requires_shipping:
        if not user.shipping:
            user.shipping = UserShipping()

        user.shipping.address_1 = form.address_1.data
        user.shipping.address_2 = form.address_2.data
        user.shipping.town = form.town.data
        user.shipping.postcode = form.postcode.data
        user.shipping.country = form.country.data

    payment_type = form.get_payment_class()

    basket.user = user
    try:
        payment = basket.create_payment(payment_type)
    except VoucherUsedError as e:
        # Voucher has been used since we last checked it at the "choose" stage.
        app.logger.exception("Voucher used at payment stage")
        flash(
            "The voucher you've used does not allow you to buy this many adult tickets. "
            "Please choose fewer tickets."
        )
        db.session.rollback()
        return redirect(url_for("tickets.main", flow=flow))

    basket.cancel_surplus_purchases()
    db.session.commit()

    # Remove voucher ID from session, if it exists.
    try:
        del session["ticket_voucher"]
    except KeyError:
        pass

    Basket.clear_from_session()

    if not payment:
        empty_baskets.inc()
        app.logger.warn("User tried to pay for empty basket")
        flash(
            "We're sorry, your session information has been lost. Please try ordering again."
        )
        return redirect(url_for("tickets.main", flow=flow))

    if payment_type == BankPayment:
        return transfer_start(payment)
    if payment_type == StripePayment:
        return stripe_start(payment)

    app.logger.exception(f"Unexpected payment_type: {repr(payment_type)}")
    flash("We're sorry, an unexpected error occurred. Please try ordering again.")
    return redirect(url_for("tickets.main", flow=flow))