mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-04 23:11:26 +00:00
Split SubscriptionForm
into SubscriptionNewUserForm
and SubscriptionExistingUserForm
This commit is contained in:
parent
75406f7b58
commit
d2d639e5f6
@ -529,13 +529,15 @@ class User(AbstractBaseUser):
|
||||
return False
|
||||
|
||||
@cached_property
|
||||
def can_create_subscription(self):
|
||||
from club.models import Club
|
||||
def can_create_subscription(self) -> bool:
|
||||
from club.models import Membership
|
||||
|
||||
for club in Club.objects.filter(id__in=settings.SITH_CAN_CREATE_SUBSCRIPTIONS):
|
||||
if club in self.clubs_with_rights:
|
||||
return True
|
||||
return False
|
||||
return (
|
||||
Membership.objects.board()
|
||||
.ongoing()
|
||||
.filter(club_id__in=settings.SITH_CAN_CREATE_SUBSCRIPTIONS)
|
||||
.exists()
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def is_launderette_manager(self):
|
||||
|
@ -1,3 +1,5 @@
|
||||
import htmx from "htmx.org";
|
||||
|
||||
import "htmx-ext-response-targets/response-targets";
|
||||
|
||||
Object.assign(window, { htmx });
|
||||
|
@ -262,8 +262,10 @@ a:not(.button) {
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
padding: 9px 13px;
|
||||
margin: 3px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
|
||||
&.btn-blue {
|
||||
@ -367,6 +369,7 @@ a:not(.button) {
|
||||
.alert-aside {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -22,6 +22,7 @@
|
||||
"d3-force-3d": "^3.0.5",
|
||||
"easymde": "^2.18.0",
|
||||
"glob": "^11.0.0",
|
||||
"htmx-ext-response-targets": "^2.0.1",
|
||||
"htmx.org": "^2.0.3",
|
||||
"jquery": "^3.7.1",
|
||||
"jquery-ui": "^1.14.0",
|
||||
@ -4140,6 +4141,11 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/htmx-ext-response-targets": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/htmx-ext-response-targets/-/htmx-ext-response-targets-2.0.1.tgz",
|
||||
"integrity": "sha512-uCMw098+0xcrs7UW/s8l8hqj5wfOaVnVV7286cS+TNMNguo8fQpi/PEaZuT4VUysIiRcjj4pcTkuaP6Q9iJ3XA=="
|
||||
},
|
||||
"node_modules/htmx.org": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.3.tgz",
|
||||
|
@ -47,6 +47,7 @@
|
||||
"easymde": "^2.18.0",
|
||||
"glob": "^11.0.0",
|
||||
"htmx.org": "^2.0.3",
|
||||
"htmx-ext-response-targets": "^2.0.1",
|
||||
"jquery": "^3.7.1",
|
||||
"jquery-ui": "^1.14.0",
|
||||
"jquery.shorten": "^1.0.0",
|
||||
|
@ -1,9 +1,6 @@
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
from core.views.widgets.select import (
|
||||
AutoCompleteSelect,
|
||||
AutoCompleteSelectMultiple,
|
||||
)
|
||||
from core.views.widgets.select import AutoCompleteSelect, AutoCompleteSelectMultiple
|
||||
from sas.models import Album
|
||||
from sas.schemas import AlbumSchema
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import random
|
||||
import secrets
|
||||
from typing import Any
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
@ -22,67 +23,90 @@ class SelectionDateForm(forms.Form):
|
||||
|
||||
|
||||
class SubscriptionForm(forms.ModelForm):
|
||||
def save(self, *args, **kwargs):
|
||||
if self.errors:
|
||||
# let django deal with the error messages
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
duration, user = self.instance.semester_duration, self.instance.member
|
||||
self.instance.subscription_start = self.instance.compute_start(
|
||||
duration=duration, user=user
|
||||
)
|
||||
self.instance.subscription_end = self.instance.compute_end(
|
||||
duration=duration, start=self.instance.subscription_start, user=user
|
||||
)
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class SubscriptionNewUserForm(SubscriptionForm):
|
||||
"""Form to create subscriptions with the user they belong to.
|
||||
|
||||
Examples:
|
||||
```py
|
||||
assert not User.objects.filter(email=request.POST.get("email")).exists()
|
||||
form = SubscriptionNewUserForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
|
||||
# now the user exists and is subscribed
|
||||
user = User.objects.get(email=request.POST.get("email"))
|
||||
assert user.is_subscribed
|
||||
"""
|
||||
|
||||
__user_fields = forms.fields_for_model(
|
||||
User,
|
||||
["first_name", "last_name", "email", "date_of_birth"],
|
||||
widgets={"date_of_birth": SelectDate},
|
||||
)
|
||||
first_name = __user_fields["first_name"]
|
||||
last_name = __user_fields["last_name"]
|
||||
email = __user_fields["email"]
|
||||
date_of_birth = __user_fields["date_of_birth"]
|
||||
|
||||
class Meta:
|
||||
model = Subscription
|
||||
fields = ["subscription_type", "payment_method", "location"]
|
||||
|
||||
field_order = [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"email",
|
||||
"date_of_birth",
|
||||
"subscription_type",
|
||||
"payment_method",
|
||||
"location",
|
||||
]
|
||||
|
||||
def clean_email(self):
|
||||
email = self.cleaned_data["email"]
|
||||
if User.objects.filter(email=email).exists():
|
||||
raise ValidationError(_("A user with that email address already exists"))
|
||||
return email
|
||||
|
||||
def clean(self) -> dict[str, Any]:
|
||||
member = User(
|
||||
first_name=self.cleaned_data.get("first_name"),
|
||||
last_name=self.cleaned_data.get("last_name"),
|
||||
email=self.cleaned_data.get("email"),
|
||||
date_of_birth=self.cleaned_data.get("date_of_birth"),
|
||||
)
|
||||
member.generate_username()
|
||||
member.set_password(secrets.token_urlsafe(nbytes=10))
|
||||
self.instance.member = member
|
||||
return super().clean()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.errors:
|
||||
# let django deal with the error messages
|
||||
return super().save(*args, **kwargs)
|
||||
self.instance.member.save()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class SubscriptionExistingUserForm(SubscriptionForm):
|
||||
"""Form to add a subscription to an existing user."""
|
||||
|
||||
class Meta:
|
||||
model = Subscription
|
||||
fields = ["member", "subscription_type", "payment_method", "location"]
|
||||
widgets = {"member": AutoCompleteSelectUser}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["member"].required = False
|
||||
self.fields |= forms.fields_for_model(
|
||||
User,
|
||||
fields=["first_name", "last_name", "email", "date_of_birth"],
|
||||
widgets={"date_of_birth": SelectDate},
|
||||
)
|
||||
|
||||
def clean_member(self):
|
||||
subscriber = self.cleaned_data.get("member")
|
||||
if subscriber:
|
||||
subscriber = User.objects.filter(id=subscriber.id).first()
|
||||
return subscriber
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if (
|
||||
cleaned_data.get("member") is None
|
||||
and "last_name" not in self.errors.as_data()
|
||||
and "first_name" not in self.errors.as_data()
|
||||
and "email" not in self.errors.as_data()
|
||||
and "date_of_birth" not in self.errors.as_data()
|
||||
):
|
||||
self.errors.pop("member", None)
|
||||
if self.errors:
|
||||
return cleaned_data
|
||||
if User.objects.filter(email=cleaned_data.get("email")).first() is not None:
|
||||
self.add_error(
|
||||
"email",
|
||||
ValidationError(_("A user with that email address already exists")),
|
||||
)
|
||||
else:
|
||||
u = User(
|
||||
last_name=self.cleaned_data.get("last_name"),
|
||||
first_name=self.cleaned_data.get("first_name"),
|
||||
email=self.cleaned_data.get("email"),
|
||||
date_of_birth=self.cleaned_data.get("date_of_birth"),
|
||||
)
|
||||
u.generate_username()
|
||||
u.set_password(str(random.randrange(1000000, 10000000)))
|
||||
u.save()
|
||||
cleaned_data["member"] = u
|
||||
elif cleaned_data.get("member") is not None:
|
||||
self.errors.pop("last_name", None)
|
||||
self.errors.pop("first_name", None)
|
||||
self.errors.pop("email", None)
|
||||
self.errors.pop("date_of_birth", None)
|
||||
if cleaned_data.get("member") is None:
|
||||
# This should be handled here,
|
||||
# but it is done in the Subscription model's clean method
|
||||
# TODO investigate why!
|
||||
raise ValidationError(
|
||||
_(
|
||||
"You must either choose an existing "
|
||||
"user or create a new one properly"
|
||||
)
|
||||
)
|
||||
return cleaned_data
|
||||
|
@ -93,22 +93,23 @@ class Subscription(models.Model):
|
||||
|
||||
def clean(self):
|
||||
today = localdate()
|
||||
active_subscriptions = Subscription.objects.exclude(pk=self.pk).filter(
|
||||
subscription_start__gte=today, subscription_end__lte=today
|
||||
threshold = timedelta(weeks=settings.SITH_SUBSCRIPTION_END)
|
||||
# a user may subscribe if :
|
||||
# - he/she is not currently subscribed
|
||||
# - its current subscription ends in less than a few weeks
|
||||
overlapping_subscriptions = Subscription.objects.exclude(pk=self.pk).filter(
|
||||
member=self.member,
|
||||
subscription_start__lte=today,
|
||||
subscription_end__gte=today + threshold,
|
||||
)
|
||||
for s in active_subscriptions:
|
||||
if (
|
||||
s.is_valid_now()
|
||||
and s.subscription_end - timedelta(weeks=settings.SITH_SUBSCRIPTION_END)
|
||||
> date.today()
|
||||
):
|
||||
if overlapping_subscriptions.exists():
|
||||
raise ValidationError(
|
||||
_("You can not subscribe many time for the same period")
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def compute_start(
|
||||
d: date | None = None, duration: int = 1, user: User | None = None
|
||||
d: date | None = None, duration: int | float = 1, user: User | None = None
|
||||
) -> date:
|
||||
"""Computes the start date of the subscription.
|
||||
|
||||
@ -132,7 +133,7 @@ class Subscription(models.Model):
|
||||
|
||||
@staticmethod
|
||||
def compute_end(
|
||||
duration: int, start: date | None = None, user: User | None = None
|
||||
duration: int | float, start: date | None = None, user: User | None = None
|
||||
) -> date:
|
||||
"""Compute the end date of the subscription.
|
||||
|
||||
@ -163,3 +164,19 @@ class Subscription(models.Model):
|
||||
|
||||
def is_valid_now(self):
|
||||
return self.subscription_start <= date.today() <= self.subscription_end
|
||||
|
||||
@property
|
||||
def semester_duration(self) -> float:
|
||||
"""Duration of this subscription, in number of semester.
|
||||
|
||||
Notes:
|
||||
The `Subscription` object doesn't have to actually exist
|
||||
in the database to access this property
|
||||
|
||||
Examples:
|
||||
```py
|
||||
subscription = Subscription(subscription_type="deux-semestres")
|
||||
assert subscription.semester_duration == 2.0
|
||||
```
|
||||
"""
|
||||
return settings.SITH_SUBSCRIPTIONS[self.subscription_type]["duration"]
|
||||
|
@ -0,0 +1,10 @@
|
||||
<form
|
||||
hx-post="{{ post_url }}"
|
||||
hx-target="this"
|
||||
hx-disabled-elt="find input[type='submit']"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
{% csrf_token %}
|
||||
{{ form.as_p() }}
|
||||
<input type="submit" value="{% trans %}Save{% endtrans %}">
|
||||
</form>
|
@ -0,0 +1,27 @@
|
||||
<div class="alert alert-green">
|
||||
<div class="alert-main">
|
||||
<h3 class="alert-title">
|
||||
{% trans user=subscription.member %}Subscription created for {{ user }}{% endtrans %}
|
||||
</h3>
|
||||
<p>
|
||||
|
||||
{% trans trimmed user=subscription.member.get_short_name(), type=subscription.subscription_type, end=subscription.subscription_end %}
|
||||
{{ user }} received its new {{ type }} subscription.
|
||||
It will be active until {{ end }} included.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="alert-aside">
|
||||
<a class="btn btn-blue" href="{{ subscription.member.get_absolute_url() }}">
|
||||
{% trans %}Go to user profile{% endtrans %}
|
||||
</a>
|
||||
<a class="btn btn-grey" href="{{ url("subscription:subscription") }}">
|
||||
{# We don't know if this fragment is displayed after creating a subscription
|
||||
for a previously existing user or for a newly created one.
|
||||
Thus, we don't know which form should be used to create another subscription
|
||||
in this place.
|
||||
Therefore, we reload the entire page. It just works. #}
|
||||
{% trans %}Create another subscription{% endtrans %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
@ -1,62 +1,38 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
|
||||
{% from "core/macros.jinja" import tabs %}
|
||||
|
||||
{% block title %}
|
||||
{% trans %}New subscription{% endtrans %}
|
||||
{% endblock %}
|
||||
|
||||
{# The following statics are bundled with our autocomplete select.
|
||||
However, if one tries to swap a form by another, then the urls in script-once
|
||||
and link-once disappear.
|
||||
So we give them here.
|
||||
If the aforementioned bug is resolved, you can remove this. #}
|
||||
{% block additional_js %}
|
||||
<script type="module" defer src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script>
|
||||
{% endblock %}
|
||||
{% block additional_css %}
|
||||
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.css") }}">
|
||||
<link rel="stylesheet" href="{{ static("core/components/ajax-select.scss") }}">
|
||||
{% endblock %}
|
||||
|
||||
{% macro form_fragment(form_object, post_url) %}
|
||||
{# Include the form fragment inside a with block,
|
||||
in order to inject the right form in the right place #}
|
||||
{% with form=form_object, post_url=post_url %}
|
||||
{% include "subscription/fragments/creation_form.jinja" %}
|
||||
{% endwith %}
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans %}New subscription{% endtrans %}</h3>
|
||||
<div id="user_info"></div>
|
||||
<form action="" method="post" id="subscription_form">
|
||||
{% csrf_token %}
|
||||
{{ form.non_field_errors() }}
|
||||
<p>{{ form.member.errors }}<label for="{{ form.member.name }}">{{ form.member.label }}</label> {{ form.member }}</p>
|
||||
<div id="new_member">
|
||||
<p>{{ form.first_name.errors }}<label for="{{ form.first_name.name }}">{{ form.first_name.label }}</label> {{ form.first_name }}</p>
|
||||
<p>{{ form.last_name.errors }}<label for="{{ form.last_name.name }}">{{ form.last_name.label }}</label> {{ form.last_name }}</p>
|
||||
<p>{{ form.email.errors }}<label for="{{ form.email.name }}">{{ form.email.label }}</label> {{ form.email }}</p>
|
||||
<p>{{ form.date_of_birth.errors }}<label for="{{ form.date_of_birth.name }}">{{ form.date_of_birth.label}}</label> {{ form.date_of_birth }}</p>
|
||||
<div id="subscription-form" hx-ext="response-targets">
|
||||
{{ tabs([
|
||||
(_("Existing member"), form_fragment(existing_user_form, existing_user_post_url)),
|
||||
(_("New member"), form_fragment(new_user_form, new_user_post_url)),
|
||||
]) }}
|
||||
</div>
|
||||
<p>{{ form.subscription_type.errors }}<label for="{{ form.subscription_type.name }}">{{ form.subscription_type.label }}</label> {{ form.subscription_type }}</p>
|
||||
<p>{{ form.payment_method.errors }}<label for="{{ form.payment_method.name }}">{{ form.payment_method.label }}</label> {{
|
||||
form.payment_method }}</p>
|
||||
<p>{% trans %}Eboutic is reserved to specific users. In doubt, don't use it.{% endtrans %}</p>
|
||||
<p>{{ form.location.errors }}<label for="{{ form.location.name }}">{{ form.location.label }}</label> {{ form.location }}</p>
|
||||
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
{{ super() }}
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
$( function() {
|
||||
select = $("#id_member");
|
||||
member_block = $("#subscription_form #new_member");
|
||||
user_info = $("#user_info");
|
||||
function display_new_member() {
|
||||
if (select.val()) {
|
||||
member_block.hide();
|
||||
member_block.children().each(function() {
|
||||
$(this).children().each(function() {
|
||||
$(this).removeAttr('required');
|
||||
});
|
||||
});
|
||||
user_info.load("/user/"+select.val()+"/mini");
|
||||
user_info.show();
|
||||
} else {
|
||||
member_block.show();
|
||||
member_block.children().each(function() {
|
||||
$(this).children().each(function() {
|
||||
$(this).prop('required', true);
|
||||
});
|
||||
});
|
||||
|
||||
user_info.empty();
|
||||
user_info.hide();
|
||||
}
|
||||
}
|
||||
select.on("change", display_new_member);
|
||||
display_new_member();
|
||||
} );
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -15,10 +15,31 @@
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from subscription.views import NewSubscription, SubscriptionsStatsView
|
||||
from subscription.views import (
|
||||
CreateSubscriptionExistingUserFragment,
|
||||
CreateSubscriptionNewUserFragment,
|
||||
NewSubscription,
|
||||
SubscriptionCreatedFragment,
|
||||
SubscriptionsStatsView,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
# Subscription views
|
||||
path("", NewSubscription.as_view(), name="subscription"),
|
||||
path(
|
||||
"fragment/existing-user/",
|
||||
CreateSubscriptionExistingUserFragment.as_view(),
|
||||
name="fragment-existing-user",
|
||||
),
|
||||
path(
|
||||
"fragment/new-user/",
|
||||
CreateSubscriptionNewUserFragment.as_view(),
|
||||
name="fragment-new-user",
|
||||
),
|
||||
path(
|
||||
"fragment/<int:subscription_id>/creation-success",
|
||||
SubscriptionCreatedFragment.as_view(),
|
||||
name="creation-success",
|
||||
),
|
||||
path("stats/", SubscriptionsStatsView.as_view(), name="stats"),
|
||||
]
|
||||
|
@ -13,85 +13,94 @@
|
||||
#
|
||||
#
|
||||
|
||||
import secrets
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.edit import CreateView, FormView
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.timezone import localdate
|
||||
from django.views.generic import CreateView, DetailView, TemplateView
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
from subscription.forms import SelectionDateForm, SubscriptionForm
|
||||
from subscription.forms import (
|
||||
SelectionDateForm,
|
||||
SubscriptionExistingUserForm,
|
||||
SubscriptionNewUserForm,
|
||||
)
|
||||
from subscription.models import Subscription
|
||||
|
||||
|
||||
class NewSubscription(CreateView):
|
||||
class CanCreateSubscriptionMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
return self.request.user.can_create_subscription
|
||||
|
||||
|
||||
class NewSubscription(CanCreateSubscriptionMixin, TemplateView):
|
||||
template_name = "subscription/subscription.jinja"
|
||||
form_class = SubscriptionForm
|
||||
|
||||
def dispatch(self, request, *arg, **kwargs):
|
||||
if request.user.can_create_subscription:
|
||||
return super().dispatch(request, *arg, **kwargs)
|
||||
raise PermissionDenied
|
||||
|
||||
def get_initial(self):
|
||||
if "member" in self.request.GET:
|
||||
return {
|
||||
"member": self.request.GET["member"],
|
||||
"subscription_type": "deux-semestres",
|
||||
def get_context_data(self, **kwargs):
|
||||
return super().get_context_data(**kwargs) | {
|
||||
"existing_user_form": SubscriptionExistingUserForm(),
|
||||
"new_user_form": SubscriptionNewUserForm(),
|
||||
"existing_user_post_url": reverse("subscription:fragment-existing-user"),
|
||||
"new_user_post_url": reverse("subscription:fragment-new-user"),
|
||||
}
|
||||
return {"subscription_type": "deux-semestres"}
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.subscription_start = Subscription.compute_start(
|
||||
duration=settings.SITH_SUBSCRIPTIONS[form.instance.subscription_type][
|
||||
"duration"
|
||||
],
|
||||
user=form.instance.member,
|
||||
|
||||
class CreateSubscriptionFragment(CanCreateSubscriptionMixin, CreateView):
|
||||
template_name = "subscription/fragments/creation_form.jinja"
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse(
|
||||
"subscription:creation-success", kwargs={"subscription_id": self.object.id}
|
||||
)
|
||||
form.instance.subscription_end = Subscription.compute_end(
|
||||
duration=settings.SITH_SUBSCRIPTIONS[form.instance.subscription_type][
|
||||
"duration"
|
||||
],
|
||||
start=form.instance.subscription_start,
|
||||
user=form.instance.member,
|
||||
)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class CreateSubscriptionExistingUserFragment(CreateSubscriptionFragment):
|
||||
"""Create a subscription for a user who already exists."""
|
||||
|
||||
form_class = SubscriptionExistingUserForm
|
||||
extra_context = {"post_url": reverse_lazy("subscription:fragment-existing-user")}
|
||||
|
||||
|
||||
class CreateSubscriptionNewUserFragment(CreateSubscriptionFragment):
|
||||
"""Create a subscription for a user who already exists."""
|
||||
|
||||
form_class = SubscriptionNewUserForm
|
||||
extra_context = {"post_url": reverse_lazy("subscription:fragment-new-user")}
|
||||
|
||||
|
||||
class SubscriptionCreatedFragment(CanCreateSubscriptionMixin, DetailView):
|
||||
template_name = "subscription/fragments/creation_success.jinja"
|
||||
model = Subscription
|
||||
pk_url_kwarg = "subscription_id"
|
||||
context_object_name = "subscription"
|
||||
|
||||
|
||||
class SubscriptionsStatsView(FormView):
|
||||
template_name = "subscription/stats.jinja"
|
||||
form_class = SelectionDateForm
|
||||
success_url = reverse_lazy("subscriptions:stats")
|
||||
|
||||
def dispatch(self, request, *arg, **kwargs):
|
||||
import datetime
|
||||
|
||||
self.start_date = datetime.datetime.today()
|
||||
self.start_date = localdate()
|
||||
self.end_date = self.start_date
|
||||
res = super().dispatch(request, *arg, **kwargs)
|
||||
if request.user.is_root or request.user.is_board_member:
|
||||
return res
|
||||
return super().dispatch(request, *arg, **kwargs)
|
||||
raise PermissionDenied
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.form = self.get_form()
|
||||
self.start_date = self.form["start_date"]
|
||||
self.end_date = self.form["end_date"]
|
||||
res = super().post(request, *args, **kwargs)
|
||||
if request.user.is_root or request.user.is_board_member:
|
||||
return res
|
||||
raise PermissionDenied
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def get_initial(self):
|
||||
init = {
|
||||
return {
|
||||
"start_date": self.start_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"end_date": self.end_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
}
|
||||
return init
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
from subscription.models import Subscription
|
||||
|
||||
kwargs = super().get_context_data(**kwargs)
|
||||
kwargs["subscriptions_total"] = Subscription.objects.filter(
|
||||
subscription_end__gte=self.end_date, subscription_start__lte=self.start_date
|
||||
@ -100,6 +109,3 @@ class SubscriptionsStatsView(FormView):
|
||||
kwargs["payment_types"] = settings.SITH_COUNTER_PAYMENT_METHOD
|
||||
kwargs["locations"] = settings.SITH_SUBSCRIPTION_LOCATIONS
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse_lazy("subscriptions:stats")
|
||||
|
@ -85,6 +85,7 @@ export default defineConfig((config: UserConfig) => {
|
||||
inject({
|
||||
// biome-ignore lint/style/useNamingConvention: that's how it's called
|
||||
Alpine: "alpinejs",
|
||||
htmx: "htmx.org",
|
||||
}),
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
|
Loading…
Reference in New Issue
Block a user