コード例 #1
0
def list_payments(event_id=None):
    """Api endpoint for listing all payments associated to an event.

    :param event_id: The primary key of the event we're listing the payments of
    :type event_id: int
    """
    if event_id is not None:
        event = Event.query.get(event_id)
        if event is None:
            return abort(404)
        if not event.has_edit_rights(current_user) and not current_user.is_accountant():
            return abort(403)
    else:
        if not current_user.is_accountant():
            return abort(403)

    page = int(request.args.get("page"))
    size = int(request.args.get("size"))
    filters = {k: v for (k, v) in request.args.items() if k.startswith("filters")}

    result = extract_payments(event_id, page, size, filters)

    data = EventPaymentSchema(many=True).dump(result.items)
    response = {"data": data, "last_page": result.pages}

    return json.dumps(response), 200, {"content-type": "application/json"}
コード例 #2
0
def list_payments(event_id):
    """Route for listing all payments associated to an event

    :param event_id: The primary key of the event we're listing the prices of
    :type event_id: int
    """
    event = Event.query.get(event_id)
    if event is None:
        flash("Événement inexistant", "error")
        return redirect(url_for("event.index"))

    if not current_user.is_accountant() and not event.has_edit_rights(
            current_user):
        flash("Accès refusé", "error")
        return redirect(url_for("event.view_event", event_id=event_id))

    return render_template("payment/payment_list.html", event=event)
コード例 #3
0
def payment_details(payment_id):
    """Route for displaying details about a given payment

    :param payment_id: Payment primary key
    :type payment_id: int
    """
    payment = Payment.query.get(payment_id)
    if payment is None:
        flash("Accès refusé", "error")
        return redirect(url_for("event.index"))

    event = payment.item.event
    if not current_user.is_accountant():
        if event is None or not event.has_edit_rights(current_user):
            flash("Accès refusé", "error")
            return redirect(url_for("event.view_event", event_id=event.id))

    return render_template(
        "payment/payment_details.html",
        payment=payment,
        event=event,
    )
コード例 #4
0
def report_offline(registration_id, payment_id=None):
    """Route for entering/editing an offline payment

    :param registration_id: The registration associated to the payment
    :type registration_id: int
    :param payment_id: If editing an existing payment, its primary key. Defaults to None
    :type payment_id: int, optional
    """
    registration = Registration.query.get(registration_id)
    if registration is None:
        flash("Inscription invalide", "error")
        return redirect(url_for("event.index"))

    event = registration.event
    if not current_user.is_accountant():
        if event is None or not event.has_edit_rights(current_user):
            flash("Accès refusé", "error")
            return redirect(url_for("event.view_event", event_id=event.id))

    payment = None
    if payment_id is not None:
        payment = Payment.query.get(payment_id)
        if (payment is None or payment.registration_id != int(registration_id)
                or not payment.is_offline()):
            flash("Paiement invalide", "error")
            return redirect(url_for("event.view_event", event_id=event.id))

    form = OfflinePaymentForm(registration, obj=payment)

    all_valid = False
    if form.validate_on_submit():

        item_price = ItemPrice.query.get(form.item_price.data)
        if (item_price is None or item_price.item.event_id != event.id
                or not item_price.is_available_to_user(registration.user)):
            flash("Tarif invalide.", "error")
        else:
            all_valid = True

    if all_valid:

        if payment is None:
            payment = Payment(registration=registration, item_price=item_price)
        else:
            payment.item_price_id = item_price.id
            payment.payment_item_id = item_price.item.id
            payment.amount_charged = item_price.amount
        form.populate_obj(payment)

        payment.reporter_id = current_user.id
        if payment.status == PaymentStatus.Refunded:
            payment.refund_time = current_time()
        else:
            payment.finalization_time = current_time()

        db.session.add(payment)

        if hasattr(
                form,
                "make_active") and form.make_active and form.make_active.data:
            registration.status = RegistrationStatus.Active
        db.session.add(registration)

        db.session.commit()
        return redirect(url_for(".list_payments", event_id=event.id))

    return render_template(
        "basicform.html",
        form=form,
        title="Paiement hors-ligne",
        subtitle=
        f"Inscription de {registration.user.full_name()} à {event.title}",
    )
コード例 #5
0
def export_payments(event_id=None):
    """Create an Excel document listing all approved payments associated to an event

    :param event_id: The primary key of the event we're listing the prices of
    :type event_id: int
    :return: The Excel file with the payments.
    """

    # Check that the user is allowed to retrieve the payments
    if event_id is not None:
        event = Event.query.get(event_id)
        if event is None:
            return abort(404)
        if not current_user.is_accountant() and not event.has_edit_rights(
                current_user):
            return abort(403)
    else:
        if not current_user.is_accountant():
            return abort(403)

    # Fetch all associated payments
    filters = {
        k: v
        for (k, v) in request.args.items() if k.startswith("filters")
    }
    payments = extract_payments(event_id, None, None, filters)

    # Create the excel document
    wb = Workbook()
    ws = wb.active
    FIELDS = {
        "item.event.activity_type_names": "Activités",
        "item.event.main_leader.first_name": "Prénom encadrant",
        "item.event.main_leader.last_name": "Nom encadrant",
        "item.event.title": "Collective",
        "item.event.start": "Date de la collective",
        "buyer.license": "Licence",
        "buyer.first_name": "Prénom",
        "buyer.last_name": "Nom",
        "buyer.mail": "Email",
        "buyer.phone": "Téléphone",
        "item.title": "Objet",
        "price.title": "Tarif",
        "amount_paid": "Prix payé",
        "finalization_time": "Date du paiement",
        "payment_status_str": "État",
        "refund_time": "Date de remboursement",
        "payment_type_str": "Type",
        "processor_order_ref": "Référence",
    }
    ws.append(list(FIELDS.values()))

    for payment in payments:
        payment.payment_type_str = payment.payment_type.display_name()
        payment.payment_status_str = payment.status.display_name()
        ws.append([str(deepgetattr(payment, field, "-")) for field in FIELDS])

    # set column width
    for c in "BCDEFGIK":
        ws.column_dimensions[c].width = 25
    for c in "AHJLM":
        ws.column_dimensions[c].width = 16

    out = BytesIO()
    wb.save(out)
    out.seek(0)

    time_str = current_time().strftime("%d_%m_%Y %H_%M")

    if event_id is not None:
        title = slugify(event.title)
        filename = f"CAF Annecy - Export paiements {title} au {time_str}.xlsx"
    else:
        filename = f"CAF Annecy - Export paiements au {time_str}.xlsx"

    return send_file(
        out,
        mimetype=
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        attachment_filename=filename,
        as_attachment=True,
    )