forked from data.coop/membersystem
Compare commits
No commits in common. "5c5153adb6f381d9521afcd96805719f8f4808fa" and "3193cafe4b5d11e17f2cbe81582fe61e02f0654a" have entirely different histories.
5c5153adb6
...
3193cafe4b
|
@ -4,8 +4,6 @@ from django.conf import settings
|
|||
from django.core.mail import send_mail
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.utils import timezone
|
||||
from membership.models import Membership
|
||||
|
||||
from . import models
|
||||
|
||||
|
@ -21,19 +19,3 @@ def check_total_amount(sender: models.Payment, instance: models.Payment, **kwarg
|
|||
settings.DEFAULT_FROM_EMAIL,
|
||||
settings.ADMINS,
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.Payment)
|
||||
def mark_order_paid(sender: models.Payment, instance: models.Payment, **kwargs: dict) -> None: # noqa: ARG001
|
||||
"""Mark an order as paid when payment is received."""
|
||||
instance.order.is_paid = True
|
||||
instance.order.save()
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.Payment)
|
||||
def activate_membership(sender: models.Order, instance: models.Order, **kwargs: dict) -> None: # noqa: ARG001
|
||||
"""Mark a membership as activated when its order is marked as paid."""
|
||||
if instance.is_paid:
|
||||
Membership.objects.filter(order=instance, activated=False, activated_on=None).update(
|
||||
activated=True, activated_on=timezone.now()
|
||||
)
|
||||
|
|
|
@ -2,15 +2,10 @@
|
|||
|
||||
from collections.abc import Callable
|
||||
|
||||
from accounting.models import Account
|
||||
from accounting.models import Order
|
||||
from accounting.models import OrderProduct
|
||||
from django.contrib import admin
|
||||
from django.contrib import messages
|
||||
from django.contrib.admin import ModelAdmin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import transaction
|
||||
from django.db.models import QuerySet
|
||||
from django.http import HttpRequest
|
||||
from django.http import HttpResponse
|
||||
|
@ -52,34 +47,12 @@ def decorate_ensure_membership_type_exists(membership_type: models.MembershipTyp
|
|||
return admin_action
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def ensure_membership_type_exists(
|
||||
request: HttpRequest,
|
||||
queryset: QuerySet,
|
||||
membership_type: models.MembershipType,
|
||||
request: HttpRequest, # noqa: ARG001
|
||||
queryset: QuerySet, # noqa: ARG001
|
||||
membership_type: models.MembershipType, # noqa: ARG001
|
||||
) -> HttpResponse:
|
||||
"""Inner function that ensures that a membership exists for a given queryset of Member objects."""
|
||||
for member in queryset:
|
||||
if member.memberships.filter(membership_type=membership_type).current():
|
||||
messages.info(request, f"{member} already has a membership {membership_type}")
|
||||
else:
|
||||
# Get the default account of the member. We don't really know what to do if a person owns multiple accounts.
|
||||
account, __ = Account.objects.get_or_create(owner=member)
|
||||
# Create an Order for the products in the membership
|
||||
order = Order.objects.create(member=member, account=account)
|
||||
# Add stuff to the order
|
||||
for product in membership_type.products.all():
|
||||
OrderProduct.objects.create(order=order, product=product, price=product.price, vat=product.vat)
|
||||
# Create the Membership
|
||||
models.Membership.objects.create(
|
||||
membership_type=membership_type,
|
||||
user=member,
|
||||
period=models.SubscriptionPeriod.objects.current(),
|
||||
order=order,
|
||||
)
|
||||
|
||||
# Associate the order with that membership
|
||||
messages.success(request, f"{member} has ordered a '{membership_type}' (unpaid)")
|
||||
|
||||
|
||||
@admin.register(models.Member)
|
||||
|
@ -92,18 +65,11 @@ class MemberAdmin(UserAdmin):
|
|||
def get_actions(self, request: HttpRequest) -> dict:
|
||||
"""Populate actions with dynamic data (MembershipType)."""
|
||||
current_period = models.SubscriptionPeriod.objects.current()
|
||||
|
||||
super_dict = super().get_actions(request)
|
||||
|
||||
if current_period:
|
||||
for i, mtype in enumerate(models.MembershipType.objects.filter(active=True)):
|
||||
for mtype in models.MembershipType.objects.filter(active=True):
|
||||
action_label = f"Ensure membership {mtype.name}, {current_period.period}, {mtype.total_including_vat}"
|
||||
action_func = decorate_ensure_membership_type_exists(mtype, action_label)
|
||||
# Django ModelAdmin uses the non-unique __name__ property, so we need to suffix it to make it unique
|
||||
action_func.__name__ += f"_{i}"
|
||||
self.actions.append(action_func)
|
||||
|
||||
return super_dict
|
||||
self.actions.append(decorate_ensure_membership_type_exists(mtype, action_label))
|
||||
return super().get_actions(request)
|
||||
|
||||
|
||||
@admin.register(models.WaitingListEntry)
|
||||
|
|
|
@ -99,17 +99,16 @@ class Membership(CreatedModifiedAbstract):
|
|||
"""Filter memberships for a given member."""
|
||||
return self.filter(user=member)
|
||||
|
||||
def active(self) -> Self:
|
||||
"""Get only activated, non-revoked memberships (may have expired so use also current())."""
|
||||
return self.filter(activated=True, revoked=False)
|
||||
|
||||
def _current(self) -> Self:
|
||||
"""Filter memberships for the current period."""
|
||||
return self.filter(period__period__contains=timezone.now())
|
||||
return self.filter(activated=True, revoked=False, period__period__contains=timezone.now())
|
||||
|
||||
def current(self) -> "Membership | None":
|
||||
"""Get the current membership."""
|
||||
return self._current().first()
|
||||
try:
|
||||
return self._current().get()
|
||||
except self.model.DoesNotExist:
|
||||
return None
|
||||
|
||||
def previous(self) -> list["Membership"]:
|
||||
"""Get previous memberships."""
|
||||
|
@ -120,7 +119,7 @@ class Membership(CreatedModifiedAbstract):
|
|||
|
||||
objects = QuerySet.as_manager()
|
||||
|
||||
user = models.ForeignKey("auth.User", on_delete=models.PROTECT, related_name="memberships")
|
||||
user = models.ForeignKey("auth.User", on_delete=models.PROTECT)
|
||||
|
||||
membership_type = models.ForeignKey(
|
||||
"membership.MembershipType",
|
||||
|
|
Loading…
Reference in a new issue