Membership invitations and order emails #47

Merged
valberg merged 10 commits from benjaoming/membersystem:membership-invite into main 2024-08-14 09:17:30 +00:00
6 changed files with 56 additions and 6 deletions
Showing only changes of commit 9962f2622b - Show all commits

View file

@ -2,7 +2,11 @@
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
@ -26,7 +30,7 @@ class OrderAdminForm(forms.ModelForm):
model = models.Order
exclude = () # noqa: DJ006
def clean(self): # noqa: D102, ANN201
def clean(self): # noqa: ANN201
cd = super().clean()
if not cd["account"] and cd["member"]:
try:
@ -43,10 +47,25 @@ class OrderAdmin(admin.ModelAdmin):
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):
@ -61,15 +80,15 @@ class PaymentAdmin(admin.ModelAdmin):
@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin): # noqa: D101
class ProductAdmin(admin.ModelAdmin):
list_display = ("name", "price", "vat")
class TransactionInline(admin.TabularInline): # noqa: D101
class TransactionInline(admin.TabularInline):
model = models.Transaction
@admin.register(models.Account)
class AccountAdmin(admin.ModelAdmin): # noqa: D101
class AccountAdmin(admin.ModelAdmin):
list_display = ("owner", "balance")
inlines = (TransactionInline,)

View file

@ -5,6 +5,7 @@
* Generally, an email consists of templates (for body and subject) and a get_context() method.
"""
from accounting.models import Order
from django.contrib import messages
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
@ -108,3 +109,18 @@ class InviteEmail(BaseEmail):
c["token"] = default_token_generator.make_token(self.membership.user)
c["referral_code"] = self.membership.referral_code
return c
class OrderEmail(BaseEmail):
template = "membership/emails/order.txt"
default_subject = _("Your data.coop order and payment")
def __init__(self, order: Order, request: HttpRequest, *args, **kwargs) -> None:
self.order = order
kwargs["user"] = order.member
super().__init__(request, *args, **kwargs)
def get_context_data(self) -> dict:
c = super().get_context_data()
c["order"] = self.order
return c

View file

@ -3,7 +3,7 @@
{% block content %}{% endblock %}
Regards,
{% trans "Cooperatively yours," %}
{{ site_name }}
{{ protocol }}://{{ domain }}

View file

@ -0,0 +1,6 @@
{% extends "membership/emails/base.txt" %}{% load i18n %}
{% block content %}{% url 'order:detail' order_id=order.id as order_url %}{% blocktrans %}You have an order in our system, you can pay it here:
{{ protocol }}://{{ domain }}{{ order_url }}
{% endblocktrans %}{% endblock %}

View file

@ -14,6 +14,10 @@
It is very much under construction.
</p>
{% for order in unpaid_orders %}
<p>You have an unpaid order: <a href="{% url "order:detail" order_id=order.id %}">View Order ID {{ order.id }}</a></p>
{% endfor %}
{% comment %}
<hr>
<br>

View file

@ -4,6 +4,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from accounting.models import Order
from django_view_decorator import view
from utils.view_utils import render
@ -19,7 +20,11 @@ if TYPE_CHECKING:
)
def index(request: HttpRequest) -> HttpResponse:
"""View to show the index page."""
return render(request, "index.html")
unpaid_orders = Order.objects.filter(member=request.user, is_paid=False)
context = {"unpaid_orders": list(unpaid_orders)}
return render(request, "index.html", context=context)
@view(