membersystem/src/accounting/admin.py
Benjamin Bach b3795977ed Membership invitations and order emails (#47)
* [x] Create invite emails from admin
* [x] Sign up on special invite form (create password and username)
* [x] Create email with unpaid orders and payment links
* [x] Lodge unpaid orders somewhere in UI for visibility

Reviewed-on: https://git.data.coop/data.coop/membersystem/pulls/47
Reviewed-by: valberg <valberg@orn.li>
Co-authored-by: Benjamin Bach <benjamin@overtag.dk>
Co-committed-by: Benjamin Bach <benjamin@overtag.dk>
2024-08-14 09:17:29 +00:00

94 lines
3 KiB
Python

"""Admin for the accounting app."""
from django import forms
from django.contrib import admin
from django.contrib import messages
from django.db.models import QuerySet
from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _
from membership.emails import OrderEmail
from . import models
class OrderProductInline(admin.TabularInline):
"""Administer contents of an order inline."""
model = models.OrderProduct
class OrderAdminForm(forms.ModelForm):
"""Special Form for the OrderAdmin so we don't need to require the account field."""
account = forms.ModelChoiceField(
required=False,
queryset=models.Account.objects.all(),
help_text=_("Leave empty to auto-choose the member's own account or to create one."),
)
class Meta:
model = models.Order
exclude = () # noqa: DJ006
def clean(self): # noqa: ANN201
cd = super().clean()
if not cd["account"] and cd["member"]:
try:
cd["account"] = models.Account.objects.get_or_create(owner=cd["member"])[0]
except models.Account.MultipleObjectsReturned:
cd["account"] = models.Account.objects.filter(owner=cd["member"]).first()
return cd
@admin.register(models.Order)
class OrderAdmin(admin.ModelAdmin):
"""Admin for the Order model."""
inlines = (OrderProductInline,)
form = OrderAdminForm
actions = ("send_order",)
list_display = ("member", "description", "created", "is_paid", "total_with_vat")
search_fields = ("member__email", "membership__membership_type__name", "description")
list_filter = ("is_paid", "membership__membership_type")
@admin.action(description="Send order link to selected unpaid orders")
def send_order(self, request: HttpRequest, queryset: QuerySet[models.Order]) -> None:
for order in queryset:
if order.is_paid:
messages.error(
request,
f"Order pk={order.id} is already marked paid, not sending email to: {order.member.email}",
)
continue
email = OrderEmail(order, request)
email.send()
messages.success(request, f"Sent an order for order pk={order.id} link to: {order.member.email}")
@admin.register(models.Payment)
class PaymentAdmin(admin.ModelAdmin):
"""Admin for the Payment model."""
list_display = ("order__member", "description", "order_id", "created")
@admin.display(description=_("Order ID"))
def order_id(self, instance: models.Payment) -> int:
"""Return the ID of the order."""
return instance.order.id
@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ("name", "price", "vat")
class TransactionInline(admin.TabularInline):
model = models.Transaction
@admin.register(models.Account)
class AccountAdmin(admin.ModelAdmin):
list_display = ("owner", "balance")
inlines = (TransactionInline,)