timetracker/games/views/purchase.py

239 lines
8.7 KiB
Python
Raw Normal View History

2024-08-08 18:17:43 +00:00
from typing import Any
from django.contrib.auth.decorators import login_required
2024-08-08 20:54:15 +00:00
from django.core.paginator import Paginator
2024-08-12 19:42:34 +00:00
from django.http import (
HttpRequest,
HttpResponse,
HttpResponseBadRequest,
HttpResponseRedirect,
)
from django.shortcuts import get_object_or_404, redirect, render
2024-08-08 18:17:43 +00:00
from django.template.loader import render_to_string
from django.urls import reverse
2024-08-12 19:42:34 +00:00
from django.utils import timezone
2024-08-08 18:17:43 +00:00
from common.components import A, Button, Icon, LinkedNameWithPlatformIcon
2024-09-08 19:03:37 +00:00
from common.time import dateformat
2024-10-04 09:36:46 +00:00
from common.utils import format_float_or_int
2024-08-12 19:42:34 +00:00
from games.forms import PurchaseForm
from games.models import Edition, Purchase
from games.views.general import use_custom_redirect
2024-08-08 18:17:43 +00:00
@login_required
def list_purchases(request: HttpRequest) -> HttpResponse:
context: dict[Any, Any] = {}
2024-08-08 20:54:15 +00:00
page_number = request.GET.get("page", 1)
limit = request.GET.get("limit", 10)
purchases = Purchase.objects.order_by("-date_purchased")
page_obj = None
if int(limit) != 0:
2024-08-09 11:59:14 +00:00
paginator = Paginator(purchases, limit)
page_obj = paginator.get_page(page_number)
purchases = page_obj.object_list
2024-08-08 18:17:43 +00:00
context = {
"title": "Manage purchases",
"page_obj": page_obj or None,
"elided_page_range": (
page_obj.paginator.get_elided_page_range(
page_number, on_each_side=1, on_ends=1
)
if page_obj
else None
2024-08-08 20:54:15 +00:00
),
2024-08-08 18:17:43 +00:00
"data": {
"header_action": A([], Button([], "Add purchase"), url="add_purchase"),
2024-08-08 18:17:43 +00:00
"columns": [
"Name",
2024-09-02 21:52:28 +00:00
"Type",
2024-08-08 18:17:43 +00:00
"Price",
"Currency",
"Infinite",
"Purchased",
"Refunded",
"Finished",
"Dropped",
"Created",
"Actions",
],
"rows": [
[
LinkedNameWithPlatformIcon(
name=purchase.edition.name,
game_id=purchase.edition.game.pk,
platform=purchase.platform,
),
2024-09-02 21:52:28 +00:00
purchase.get_type_display(),
2024-10-04 09:36:46 +00:00
format_float_or_int(purchase.price),
2024-08-08 18:17:43 +00:00
purchase.price_currency,
purchase.infinite,
2024-09-08 19:03:37 +00:00
purchase.date_purchased.strftime(dateformat),
2024-08-08 18:17:43 +00:00
(
2024-09-08 19:03:37 +00:00
purchase.date_refunded.strftime(dateformat)
2024-08-08 18:17:43 +00:00
if purchase.date_refunded
else "-"
),
(
2024-09-08 19:03:37 +00:00
purchase.date_finished.strftime(dateformat)
2024-08-08 18:17:43 +00:00
if purchase.date_finished
else "-"
),
(
2024-09-08 19:03:37 +00:00
purchase.date_dropped.strftime(dateformat)
2024-08-08 18:17:43 +00:00
if purchase.date_dropped
else "-"
),
2024-09-08 19:03:37 +00:00
purchase.created_at.strftime(dateformat),
2024-08-08 18:17:43 +00:00
render_to_string(
2024-09-08 19:03:37 +00:00
"cotton/button_group.html",
2024-08-08 18:17:43 +00:00
{
"buttons": [
2024-09-10 13:04:18 +00:00
{
"href": reverse(
"finish_purchase", args=[purchase.pk]
),
"slot": Icon("checkmark"),
"title": "Mark as finished",
}
if not purchase.date_finished
else {},
2024-09-10 12:46:50 +00:00
{
"href": reverse(
"drop_purchase", args=[purchase.pk]
),
"slot": Icon("eject"),
"title": "Mark as dropped",
}
if not purchase.date_dropped
else {},
2024-09-10 12:50:02 +00:00
{
"href": reverse(
"refund_purchase", args=[purchase.pk]
),
"slot": Icon("refund"),
"title": "Mark as refunded",
}
if not purchase.date_refunded
else {},
2024-08-08 18:17:43 +00:00
{
"href": reverse(
"edit_purchase", args=[purchase.pk]
),
2024-09-08 19:03:37 +00:00
"slot": Icon("edit"),
2024-09-10 12:46:10 +00:00
"title": "Edit",
"color": "gray",
2024-08-08 18:17:43 +00:00
},
{
"href": reverse(
"delete_purchase", args=[purchase.pk]
),
2024-09-08 19:03:37 +00:00
"slot": Icon("delete"),
2024-09-10 12:46:10 +00:00
"title": "Delete",
2024-08-08 18:17:43 +00:00
"color": "red",
},
]
},
),
]
for purchase in purchases
],
},
}
return render(request, "list_purchases.html", context)
2024-08-12 19:42:34 +00:00
@login_required
def add_purchase(request: HttpRequest, edition_id: int = 0) -> HttpResponse:
context: dict[str, Any] = {}
initial = {"date_purchased": timezone.now()}
if request.method == "POST":
form = PurchaseForm(request.POST or None, initial=initial)
if form.is_valid():
purchase = form.save()
if "submit_and_redirect" in request.POST:
return HttpResponseRedirect(
reverse(
"add_session_for_purchase", kwargs={"purchase_id": purchase.id}
)
)
else:
return redirect("list_purchases")
else:
if edition_id:
edition = Edition.objects.get(id=edition_id)
form = PurchaseForm(
initial={
**initial,
"edition": edition,
"platform": edition.platform,
}
)
else:
form = PurchaseForm(initial=initial)
context["form"] = form
context["title"] = "Add New Purchase"
context["script_name"] = "add_purchase.js"
return render(request, "add_purchase.html", context)
@login_required
@use_custom_redirect
def edit_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
context = {}
purchase = get_object_or_404(Purchase, id=purchase_id)
form = PurchaseForm(request.POST or None, instance=purchase)
if form.is_valid():
form.save()
return redirect("list_sessions")
context["title"] = "Edit Purchase"
context["form"] = form
context["purchase_id"] = str(purchase_id)
context["script_name"] = "add_purchase.js"
return render(request, "add_purchase.html", context)
@login_required
def delete_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
purchase = get_object_or_404(Purchase, id=purchase_id)
purchase.delete()
return redirect("list_purchases")
2024-08-12 19:42:34 +00:00
2024-09-10 12:46:50 +00:00
@login_required
def drop_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
purchase = get_object_or_404(Purchase, id=purchase_id)
purchase.date_dropped = timezone.now()
purchase.save()
return redirect("list_purchases")
2024-09-10 12:46:50 +00:00
2024-09-10 12:50:02 +00:00
@login_required
def refund_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
purchase = get_object_or_404(Purchase, id=purchase_id)
purchase.date_refunded = timezone.now()
purchase.save()
return redirect("list_purchases")
2024-09-10 12:50:02 +00:00
2024-09-10 13:04:18 +00:00
@login_required
def finish_purchase(request: HttpRequest, purchase_id: int) -> HttpResponse:
purchase = get_object_or_404(Purchase, id=purchase_id)
purchase.date_finished = timezone.now()
purchase.save()
return redirect("list_purchases")
2024-08-12 19:42:34 +00:00
def related_purchase_by_edition(request: HttpRequest) -> HttpResponse:
edition_id = request.GET.get("edition")
if not edition_id:
return HttpResponseBadRequest("Invalid edition_id")
form = PurchaseForm()
form.fields["related_purchase"].queryset = Purchase.objects.filter(
edition_id=edition_id, type=Purchase.GAME
).order_by("edition__sort_name")
return render(request, "partials/related_purchase_field.html", {"form": form})