Source code for organisations.views.club_menu_tabs.finance

import datetime

from django.db.models import Sum, Min
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from accounts.models import User
from club_sessions.models import Session
from cobalt.settings import GLOBAL_CURRENCY_SYMBOL, BRIDGE_CREDITS
from events.models import Event, Congress
from notifications.views.core import send_cobalt_email_to_system_number
from organisations.decorators import check_club_menu_access
from organisations.models import ClubLog, MemberMembershipType, Organisation
from organisations.views.club_menu import tab_finance_htmx
from organisations.views.club_menu_tabs.members import club_admin_edit_member_htmx
from organisations.club_admin_core import (
    is_member_allowing_auto_pay,
    is_player_a_member,
)
from payments.models import (
    UserPendingPayment,
    OrganisationTransaction,
    TRANSACTION_TYPE,
)
from payments.views.core import (
    update_account,
    update_organisation,
    org_balance,
    org_balance_at_date,
)
from payments.views.org_report.csv import organisation_transactions_csv_download
from payments.views.org_report.data import (
    organisation_transactions_by_date_range,
    sessions_and_payments_by_date_range,
    event_payments_summary_by_date_range,
    combined_view_events_sessions_other,
    congress_payments_summary_by_date_range,
)
from payments.views.org_report.xls import organisation_transactions_xls_download
from payments.views.payments_api import payment_api_batch
from rbac.core import (
    rbac_get_users_in_group_by_name,
)
from utils.utils import cobalt_paginator


@check_club_menu_access(check_payments=True)
def cancel_user_pending_debt_htmx(request, club):
    """Cancel a debt for a user"""

    user_pending_payment = get_object_or_404(
        UserPendingPayment, pk=request.POST.get("user_pending_payment_id")
    )
    if user_pending_payment.organisation != club:
        message = "This debt is not for this club"
    else:
        user_pending_payment.delete()
        message = "Pending payment deleted"

        ClubLog(
            organisation=club,
            actor=request.user,
            action=f"Cancelled debt for {user_pending_payment.system_number} for {GLOBAL_CURRENCY_SYMBOL}{user_pending_payment.amount:.2f}",
        ).save()

    # We get called from the member page too, check if we should return the member view or default ot finance
    if request.POST.get("return_member_tab"):
        # JPG cleanup
        # return edit_member_htmx(request, message=message)
        request.POST = request.POST.copy()
        request.POST["system_number"] = user_pending_payment.system_number
        request.POST["message"] = message
        return club_admin_edit_member_htmx(request)

    return tab_finance_htmx(request, message=message)


@check_club_menu_access(check_payments=True)
def get_org_balance_htmx(request, club):
    """Show balance for this club"""

    last_tran = OrganisationTransaction.objects.filter(organisation=club).last()
    balance = last_tran.balance if last_tran else 0.0

    return HttpResponse(f"${balance:,.2f}")


@check_club_menu_access(check_payments_view=True)
def transactions_htmx(request, club):
    """handle the transaction listing part of the finance tab"""

    # Get view type - default to all
    view_type = request.POST.get("view_type", "all")

    if view_type == "session":
        things = _summary_by_sessions(request, club)

    elif view_type == "event":
        things = _summary_by_events(request, club)

    elif view_type == "other":
        transactions = (
            OrganisationTransaction.objects.filter(organisation=club)
            .filter(event_id__isnull=True)
            .filter(club_session_id__isnull=True)
            .order_by("-pk")
        )
        things = cobalt_paginator(request, transactions)

    elif view_type == "membership":
        transactions = OrganisationTransaction.objects.filter(
            organisation=club,
            type="Club Membership",
        ).order_by("-pk")
        things = cobalt_paginator(request, transactions)

    else:  # all
        transactions = OrganisationTransaction.objects.filter(
            organisation=club
        ).order_by("-pk")
        things = cobalt_paginator(request, transactions)

    hx_post = reverse("organisations:transactions_htmx")
    hx_target = "#id_finance_transactions"
    hx_vars = f"club_id: {club.id}, view_type: '{view_type}'"

    return render(
        request,
        "organisations/club_menu/finance/transactions_htmx.html",
        {
            "club": club,
            "things": things,
            "hx_post": hx_post,
            "hx_target": hx_target,
            "hx_vars": hx_vars,
            "view_type": view_type,
        },
    )


def _summary_by_sessions(request, club):
    """Summarise by session only"""

    # Get the session transactions on their own and paginate
    session_transactions = (
        OrganisationTransaction.objects.filter(organisation=club)
        .exclude(club_session_id=None)
        .order_by("-club_session_id")
        .values("description", "club_session_id")
        .annotate(amount=Sum("amount"))
        .annotate(created_date=Min("created_date"))
    )

    return cobalt_paginator(request, session_transactions)


def _summary_by_events(request, club):
    """Summarise by event only"""

    # TODO: This loads all events for an organisation since the start of time. Probably okay for many years, but
    # may need fixed later.

    # Get the event transactions on their own and paginate
    event_transactions = (
        OrganisationTransaction.objects.filter(organisation=club)
        .exclude(event_id=None)
        .order_by("-event_id")
        .values("event_id")
        .annotate(amount=Sum("amount"))
        .annotate(created_date=Min("created_date"))
    )

    # Get event names
    event_ids = event_transactions.values_list("event_id")
    event_names = Event.objects.filter(id__in=event_ids).values(
        "id", "congress__name", "event_name"
    )

    event_names_dict = {}
    for event_name in event_names:
        event_names_dict[
            event_name["id"]
        ] = f"{event_name['congress__name']} - {event_name['event_name']}"

    # Augment data
    for event_transaction in event_transactions:
        event_transaction["description"] = event_names_dict[
            event_transaction["event_id"]
        ]

    return cobalt_paginator(request, event_transactions)


[docs] def pay_member_from_organisation( request, club, amount, description, member, event_id=-1, session_id=-1, is_membership_fee=False, ): """Pay a member from an organisation's account. Calling module is responsible for security. This works off the request object. Request should have member_id, description and amount. Although description can be overridden as a parameter Return: status, message Status is True/False for success Message contains tet narrative """ if amount <= 0: return False, "Amount was less than zero" if amount > org_balance(club): return False, "Club has insufficient funds for this transfer" event = Event.objects.get(pk=event_id) if event_id > 0 else None session = Session.objects.get(pk=session_id) if session_id > 0 else None # Pay user update_account( member=member, amount=amount, description=description, organisation=club, payment_type="Org Transfer" if not is_membership_fee else "Club Membership", ) # debit club update_organisation( organisation=club, amount=-amount, description=description, payment_type="Org Transfer" if not is_membership_fee else "Club Membership", member=member, event=event, session=session, ) # log it ClubLog( organisation=club, actor=request.user, action=f"Paid {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to {member}", ).save() # notify user # COB-768 JPG 15-12-23: Change in message text msg = f"""{club} (administrator {request.user}) has paid {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to your {BRIDGE_CREDITS} account for {description}. <br><br>If you have any queries please contact {club} in the first instance. """ send_cobalt_email_to_system_number( system_number=member.system_number, subject=f"Payment from {club}", message=msg, club=club, ) return ( True, f"Payment of {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} made to {member.full_name}", )
[docs] def top_up_member_from_organisation(request, club, amount, description, member): """Pay a member from an organisation's account when a top up is made. Calling module is responsible for security. This works off the request object. Request should have member_id, description and amount. Although description can be overridden as a parameter Return: status, message Status is True/False for success Message contains tet narrative """ if amount <= 0: return False, "Amount was less than zero" if amount > org_balance(club): return False, "Club has insufficient funds for this transfer" # Pay user update_account( member=member, amount=amount, description=description, organisation=club, payment_type="Club Top Up", ) # debit club update_organisation( organisation=club, amount=-amount, description=description, payment_type="Club Top Up", member=member, ) # log it ClubLog( organisation=club, actor=request.user, action=f"Made top up payment of {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to {member}", ).save() return ( True, f"Top Up of {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} made to {member.full_name}", )
@check_club_menu_access(check_payments=True) def pay_member_htmx(request, club): """make a payment to a member""" if "save" not in request.POST: hx_post = reverse("organisations:pay_member_htmx") events = ( Event.objects.filter(congress__congress_master__org=club) .select_related("congress") .order_by("-denormalised_start_date")[:20] ) sessions = Session.objects.filter(session_type__organisation=club).order_by( "-session_date" )[:20] return render( request, "organisations/club_menu/finance/pay_member_htmx.html", {"club": club, "hx_post": hx_post, "events": events, "sessions": sessions}, ) member = get_object_or_404(User, pk=request.POST.get("member_id")) amount = float(request.POST.get("amount")) description = request.POST.get("description") event_id = int(request.POST.get("event_id", -1)) session_id = int(request.POST.get("session_id", -1)) is_membership_fee = request.POST.get("membership_fee", False) _, message = pay_member_from_organisation( request, club, amount, description, member, event_id, session_id, is_membership_fee, ) return tab_finance_htmx(request, message=message) @check_club_menu_access(check_payments=True) def charge_member_htmx(request, club): """make a charge to a member""" if "save" not in request.POST: hx_post = reverse("organisations:charge_member_htmx") return render( request, "organisations/club_menu/finance/charge_member_htmx.html", {"club": club, "hx_post": hx_post}, ) member = get_object_or_404(User, pk=request.POST.get("member_id")) description = request.POST.get("description") amount = float(request.POST.get("amount")) is_membership_fee = request.POST.get("membership_fee", False) # Validate if amount <= 0: return tab_finance_htmx(request, message="Amount was less than zero") # Check membership # JPG Query - this will just check for current active members. if not is_player_a_member(club, member.system_number): return tab_finance_htmx( request, message=f"{member} is not a member of the club. Cannot charge user.", ) if is_membership_fee: if not is_member_allowing_auto_pay(club=club, user=member): return tab_finance_htmx( request, message=( f"{member} is not allowing the club to charge their membership fees " + f"to {BRIDGE_CREDITS}." ), ) # Try to charge user if payment_api_batch( member=member, amount=amount, description=description, organisation=club, payment_type="Org Transfer" if not is_membership_fee else "Club Membership", ): # log it ClubLog( organisation=club, actor=request.user, action=f"Charged {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to {member}", ).save() # notify user # COB-768 JPG 15-12-23: Change in message text msg = f"""{club} (administrator {request.user}) has charged {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to your {BRIDGE_CREDITS} account for {description}. <br><br>If you have any queries please contact {club} in the first instance. """ send_cobalt_email_to_system_number( system_number=member.system_number, subject=f"Charge from {club}", message=msg, club=club, ) return tab_finance_htmx( request, message=f"Charge of {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} made to {member.full_name} via {BRIDGE_CREDITS}", ) else: return tab_finance_htmx( request, message=f"Payment FAILED for {member.full_name}. Insufficient funds.", ) @check_club_menu_access(check_payments=True) def pay_org_htmx(request, club): """make a payment to another club""" if "save" not in request.POST: return render( request, "organisations/club_menu/finance/pay_org_htmx.html", {"club": club}, ) org = get_object_or_404(Organisation, pk=request.POST.get("org_id")) description = request.POST.get("description") amount = float(request.POST.get("amount")) # Validate if amount <= 0: return tab_finance_htmx(request, message="Amount was less than zero") if amount > org_balance(club): return tab_finance_htmx( request, message="Club has insufficient funds for this transfer" ) if org == club: return tab_finance_htmx( request, message="Ignoring attempt to transfer to yourself" ) # debit this club update_organisation( organisation=club, amount=-amount, description=description, payment_type="Org Transfer", other_organisation=org, ) # credit other club update_organisation( organisation=org, amount=amount, description=description, payment_type="Org Transfer", other_organisation=club, ) # log it ClubLog( organisation=club, actor=request.user, action=f"Transferred {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} to {org}", ).save() # notify payments users at other club, not general admins though # There is no really clean way to do this. We use the rbac tree to find either the basic group (basic RBAC) or # the payments_edit group (advanced RBAC). # try basic other_club_admins = rbac_get_users_in_group_by_name( f"{club.rbac_name_qualifier}.basic" ) if not other_club_admins: # try advanced other_club_admins = rbac_get_users_in_group_by_name( f"{club.rbac_name_qualifier}.payments_edit" ) for other_club_admin in other_club_admins: msg = f"""{request.user} from {club} has paid {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} into the {BRIDGE_CREDITS} account for {org}. The description was: {description}. <br><br>If you have any queries please contact {club} in the first instance. """ send_cobalt_email_to_system_number( system_number=other_club_admin.system_number, subject=f"Transfer from {club}", message=msg, club=club, ) return tab_finance_htmx( request, message=f"Transfer of {GLOBAL_CURRENCY_SYMBOL}{amount:,.2f} made to {org} via {BRIDGE_CREDITS}", ) @check_club_menu_access(check_payments=True) def transaction_details_htmx(request, club): """return details of a transaction""" trans = get_object_or_404(OrganisationTransaction, pk=request.POST.get("trans_id")) if trans.organisation != club: return HttpResponse("Transaction does not belong to this club") return render( request, "organisations/club_menu/finance/transaction_detail_htmx.html", {"club": club, "trans": trans}, ) @check_club_menu_access(check_payments=True) def transaction_event_details_htmx(request, club): """return a breakdown of the transactions that make up payments for an event. Appears on the finance view when a user drills into the event""" use_filtered_view = request.POST.get("use_filtered_view") # Get transactions and paginate event = get_object_or_404(Event, pk=request.POST.get("event_id")) event_transactions = OrganisationTransaction.objects.filter( organisation=club, event_id=event.id ).order_by("-created_date") things = cobalt_paginator(request, event_transactions) # Set up HTMX data hx_post = reverse("organisations:transaction_event_details_htmx") hx_vars = f"club_id: {club.id}, event_id:{event.id}" if use_filtered_view: hx_target = "#id_filtered_transactions" hx_vars = f"{hx_vars}, use_filtered_view:1" else: hx_target = "#id_finance_transactions" return render( request, "organisations/club_menu/finance/transaction_event_detail_htmx.html", { "things": things, "club": club, "event": event, "use_filtered_view": use_filtered_view, "hx_post": hx_post, "hx_target": hx_target, "hx_vars": hx_vars, }, ) @check_club_menu_access(check_payments=True) def transaction_congress_details_htmx(request, club): """return a list of events for a congress so the user can drill into the details""" use_filtered_view = request.POST.get("use_filtered_view") # Get congress from POST congress_id = request.POST.get("congress_id") congress = get_object_or_404(Congress, pk=congress_id) # Get events for this congress event_ids = Event.objects.filter(congress_id=congress_id) # Get payments for these events event_payments = ( OrganisationTransaction.objects.filter(organisation=club) .filter(event_id__in=event_ids) .values("event_id") .annotate(amount=Sum("amount")) ) # Turn into dictionary event_payments_dict = {} for event_payment in event_payments: event_payments_dict[event_payment["event_id"]] = event_payment["amount"] # Get events so we have name, dates etc events = Event.objects.filter(pk__in=event_ids).order_by("-denormalised_start_date") # Augment with payment amounts for event in events: event.total_payments = event_payments_dict.get(event.id, 0) things = cobalt_paginator(request, events) # Set up HTMX data hx_post = reverse("organisations:transaction_congress_details_htmx") hx_vars = f"club_id: {club.id}, congress_id:{congress.id}" if use_filtered_view: hx_target = "#id_filtered_transactions" hx_vars = f"{hx_vars}, use_filtered_view:1" else: hx_target = "#id_finance_transactions" return render( request, "organisations/club_menu/finance/transaction_congress_detail_htmx.html", { "things": things, "club": club, "congress": congress, "use_filtered_view": use_filtered_view, "hx_post": hx_post, "hx_target": hx_target, "hx_vars": hx_vars, }, ) @check_club_menu_access(check_payments=True) def transaction_session_details_htmx(request, club): """return details of a session""" club_session = get_object_or_404(Session, pk=request.POST.get("club_session_id")) session_transactions = OrganisationTransaction.objects.filter( organisation=club, club_session_id=club_session.id ) # trans = get_object_or_404(OrganisationTransaction, pk=request.POST.get("trans_id")) # if trans.organisation != club: # return HttpResponse("Transaction does not belong to this club") return render( request, "organisations/club_menu/finance/transaction_session_detail_htmx.html", { "club": club, "club_session": club_session, "session_transactions": session_transactions, }, ) @check_club_menu_access(check_payments=True) def transaction_filter_htmx(request, club): """tab for CSV downloads and filtered view""" start_date = request.POST.get("start_date") end_date = request.POST.get("end_date") description_search = request.POST.get("description_search") view_type_selector = request.POST.get("view_type_selector") transaction_type = request.POST.get("transaction_type_selector") if not view_type_selector: # first call - show blank form today = datetime.date.today() today_str = today.strftime("%Y-%m-%d") last_month = today.replace(day=1) - datetime.timedelta(days=1) first_of_last_month_str = f"{last_month.strftime('%Y-%m')}-01" last_of_last_month_str = last_month.strftime("%Y-%m-%d") first_of_last_year_str = datetime.date( int(today.strftime("%Y")) - 1, 1, 1 ).strftime("%Y-%m-%d") last_of_last_year_str = datetime.date( int(today.strftime("%Y")) - 1, 12, 31 ).strftime("%Y-%m-%d") reference_dates = { "Month to date": ( f"{datetime.date.today().strftime('%Y-%m')}-01", today_str, ), "Year to date": ( f"{datetime.date.today().strftime('%Y')}-01-01", today_str, ), "Last Month": (first_of_last_month_str, last_of_last_month_str), "Last Year": (first_of_last_year_str, last_of_last_year_str), "All": ("1901-01-01", today_str), } return render( request, "organisations/club_menu/finance/transaction_filter_htmx.html", { "club": club, "reference_dates": reference_dates, "transaction_type": "all", "transaction_types": TRANSACTION_TYPE, }, ) if not start_date or not end_date: return HttpResponse("Enter dates to perform search") if "download-csv" in request.POST: return organisation_transactions_csv_download( request, club, start_date, end_date, description_search, transaction_type, ) if "download-xls" in request.POST: return organisation_transactions_xls_download( request, club, start_date, end_date, description_search ) if "show_filtered_data" in request.POST: return organisation_transactions_filtered_data( request, club, start_date, end_date, description_search, view_type_selector, transaction_type, ) return HttpResponse("an error occurred")
[docs] def organisation_transactions_filtered_data( request, club, start_date, end_date, description_search, view_type_selector, transaction_type, ): """show filtered data (date and search) on screen, not as CSV/XLS download""" # set up data for pagination footer hx_data = { "hx_post": reverse("organisations:transaction_filter_htmx"), "hx_target": "#id_filtered_transactions", "hx_vars": f"club_id: {club.id}, show_filtered_data: 1, start_date: '{start_date}', end_date: '{end_date}', view_type_selector: '{view_type_selector}'", } if description_search: hx_data[ "hx_vars" ] = f"{hx_data['hx_vars']}, description_search: '{description_search}'" if view_type_selector == "all" or ( view_type_selector == "txntype" and transaction_type == "all" ): return organisation_transactions_filtered_data_all( request, club, start_date, end_date, description_search, hx_data ) elif view_type_selector == "session": return organisation_transactions_filtered_data_sessions( request, club, start_date, end_date, hx_data ) elif view_type_selector == "event": return organisation_transactions_filtered_data_events( request, club, start_date, end_date, hx_data ) elif view_type_selector == "congress": return organisation_transactions_filtered_data_congresses( request, club, start_date, end_date, hx_data ) elif view_type_selector == "combined": return organisation_transactions_filtered_data_combined( request, club, start_date, end_date, hx_data ) elif view_type_selector == "txntype": return organisation_transactions_filtered_data_txntype( request, club, start_date, end_date, description_search, hx_data, transaction_type, ) else: return HttpResponse("No view provided")
[docs] def organisation_transactions_filtered_data_txntype( request, club, start_date, end_date, description_search, hx_data, transaction_type, ): """handle the filter by transaction type option""" organisation_transactions = organisation_transactions_by_date_range( club, start_date, end_date, description_search, augment_data=False, transaction_type=transaction_type, ) total_for_type = 0 for org_transaction in organisation_transactions: total_for_type += org_transaction.amount things = cobalt_paginator(request, organisation_transactions, 50) return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_txntype_htmx.html", { "club": club, "things": things, "organisation_transactions": organisation_transactions, "total_for_type": total_for_type, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )
[docs] def organisation_transactions_filtered_data_all( request, club, start_date, end_date, description_search, hx_data ): """handle the all option""" organisation_transactions = organisation_transactions_by_date_range( club, start_date, end_date, description_search, augment_data=False ) things = cobalt_paginator(request, organisation_transactions, 50) # COB-772 balance_at_end_date = org_balance_at_date(club, end_date) end_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d") return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_all_htmx.html", { "club": club, "things": things, "balance_at_end_date": balance_at_end_date, "end_datetime": end_datetime, "organisation_transactions": organisation_transactions, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )
[docs] def organisation_transactions_filtered_data_sessions( request, club, start_date, end_date, hx_data ): """handle the sessions option""" # Get data sessions_in_range, payments_dict = sessions_and_payments_by_date_range( club, start_date, end_date ) # Add session total amount to data sessions_total = 0 for session_in_range_id in sessions_in_range: sessions_in_range[session_in_range_id].amount = payments_dict.get( session_in_range_id, "No Payments" ) # COB-772 sessions_total += payments_dict.get(session_in_range_id, 0) # Paginate list_of_sessions = list(sessions_in_range.values()) list_of_sessions.reverse() things = cobalt_paginator(request, list_of_sessions) # COB-772 balance_at_end_date = org_balance_at_date(club, end_date) end_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d") return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_sessions_htmx.html", { "club": club, "things": things, "balance_at_end_date": balance_at_end_date, "end_datetime": end_datetime, "sessions_total": sessions_total, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )
[docs] def organisation_transactions_filtered_data_events( request, club, start_date, end_date, hx_data ): """handle the events option""" event_data = event_payments_summary_by_date_range(club, start_date, end_date) list_of_events = list(event_data.values()) list_of_events.reverse() things = cobalt_paginator(request, list_of_events) # COB-772 balance_at_end_date = org_balance_at_date(club, end_date) end_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d") events_total = 0 for event_id in event_data: events_total += event_data[event_id]["amount"] return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_events_htmx.html", { "club": club, "things": things, "balance_at_end_date": balance_at_end_date, "end_datetime": end_datetime, "events_total": events_total, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )
[docs] def organisation_transactions_filtered_data_combined( request, club, start_date, end_date, hx_data ): """handle the all option""" organisation_transactions = combined_view_events_sessions_other( club, start_date, end_date ) # this is a tuple, convert to a list data = [ organisation_transaction[1] for organisation_transaction in organisation_transactions ] data.reverse() things = cobalt_paginator(request, data) # COB-772 balance_at_end_date = org_balance_at_date(club, end_date) end_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d") return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_combined_htmx.html", { "club": club, "things": things, "balance_at_end_date": balance_at_end_date, "end_datetime": end_datetime, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )
[docs] def organisation_transactions_filtered_data_congresses( request, club, start_date, end_date, hx_data ): """handle the congress option""" congress_data = congress_payments_summary_by_date_range(club, start_date, end_date) print(congress_data) list_of_congresses = list(congress_data.values()) list_of_congresses.reverse() things = cobalt_paginator(request, list_of_congresses) # COB-772 balance_at_end_date = org_balance_at_date(club, end_date) end_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d") congresses_total = 0 for congress_id in congress_data: congresses_total += congress_data[congress_id]["amount"] return render( request, "organisations/club_menu/finance/organisation_transactions_filtered_data_congresses_htmx.html", { "club": club, "things": things, "balance_at_end_date": balance_at_end_date, "end_datetime": end_datetime, "congresses_total": congresses_total, "hx_target": hx_data["hx_target"], "hx_post": hx_data["hx_post"], "hx_vars": hx_data["hx_vars"], }, )