Ajoute un mécanisme de réinitialisation des adhésions
This commit is contained in:
parent
713d686047
commit
1b8dd971b0
6 changed files with 139 additions and 75 deletions
|
@ -3,6 +3,7 @@ from os.path import splitext
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from shared.utils import choices_length
|
from shared.utils import choices_length
|
||||||
|
@ -93,6 +94,16 @@ class BDSProfile(models.Model):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def expired_members(cls):
|
||||||
|
now = timezone.now()
|
||||||
|
qs = cls.objects.filter(is_member=True)
|
||||||
|
if now.month > 1 and now.month < 7:
|
||||||
|
return qs.filter(cotisation_period="SE1")
|
||||||
|
elif now.month < 2 or now.month > 8:
|
||||||
|
return qs.none()
|
||||||
|
return qs
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Profil BDS")
|
verbose_name = _("Profil BDS")
|
||||||
verbose_name_plural = _("Profils BDS")
|
verbose_name_plural = _("Profils BDS")
|
||||||
|
|
22
bds/templates/bds/expired_members.html
Normal file
22
bds/templates/bds/expired_members.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{% extends "bds/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1 class="title">Liste des adhésions expirées</h1>
|
||||||
|
|
||||||
|
{% if object_list %}
|
||||||
|
<div class="content">
|
||||||
|
<ul>
|
||||||
|
{% for p in object_list %}
|
||||||
|
<li>{{ p.user.first_name }} {{ p.user.last_name }} ({{ p.user.username }}), {{ p.get_cotisation_period_display }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="buttons is-centered">
|
||||||
|
<a class="button is-danger" href="{% url 'bds:members.reset' %}">Réinitialiser les adhésions expirées</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -36,6 +36,8 @@
|
||||||
|
|
||||||
<a class=button href="{% url 'bds:export.members' %}">Télécharger la liste des membres (CSV)</a>
|
<a class=button href="{% url 'bds:export.members' %}">Télécharger la liste des membres (CSV)</a>
|
||||||
|
|
||||||
|
<a class=button href="{% url 'bds:members.expired' %}">Liste des adhésions expirées ({{ nb_expired }})</a>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
|
@ -5,100 +5,100 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% for form in forms.values %}
|
{% for form in forms.values %}
|
||||||
{% for error in form.non_field_errors %}
|
{% for error in form.non_field_errors %}
|
||||||
<div class="notification is-danger">
|
<div class="notification is-danger">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<h1 class="title">{% trans "Modification du profil " %}{{ view.user.username }}</h1>
|
<h1 class="title">{% trans "Modification du profil " %}{{ view.user.username }}</h1>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form method="post" action="" id="user-update-form">
|
<form method="post" action="" id="user-update-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
{% for form in forms.values %}
|
{% for form in forms.values %}
|
||||||
{% include "bds/forms/form.html" with form=form errors=False %}
|
{% include "bds/forms/form.html" with form=form errors=False %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form">
|
<form method="post" action="{% url 'bds:user.delete' view.user.pk %}" id="user-delete-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="columns is-gapless mt-5">
|
<div class="columns is-gapless mt-5">
|
||||||
<div class="column is-5">
|
<div class="column is-5">
|
||||||
<button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button>
|
<button id="user-update-button" class="button is-fullwidth is-primary">Enregistrer</button>
|
||||||
|
</div>
|
||||||
|
<div class="column is-2">
|
||||||
|
</div>
|
||||||
|
<div class="column is-5">
|
||||||
|
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-2">
|
|
||||||
</div>
|
|
||||||
<div class="column is-5">
|
|
||||||
<button id="user-delete-button" class="button is-fullwidth is-danger">Supprimer</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hidden by default -->
|
<!-- Hidden by default -->
|
||||||
<div id="confirm-delete-modal" class="modal">
|
<div id="confirm-delete-modal" class="modal">
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Confirmer la suppression</p>
|
<p class="modal-card-title">Confirmer la suppression</p>
|
||||||
<button id= "modal-close" class="delete" aria-label="close"></button>
|
<button id="modal-close" class="delete" aria-label="close"></button>
|
||||||
</header>
|
</header>
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible !
|
Voulez-vous réellement supprimer ce compte ? Attention, cette opération est irréversible !
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<button id="confirm-delete-button" class="button is-primary">Supprimer</button>
|
<button id="confirm-delete-button" class="button is-primary">Supprimer</button>
|
||||||
<button id="cancel-delete-button" class="button">Annuler</button>
|
<button id="cancel-delete-button" class="button">Annuler</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Adapted from https://bulma.io/lib/main.js
|
// Adapted from https://bulma.io/lib/main.js
|
||||||
function openModal(target) {
|
function openModal(target) {
|
||||||
$(document).addClass('is-clipped');
|
$(document).addClass('is-clipped');
|
||||||
$(`#${target}`).addClass('is-active');
|
$(`#${target}`).addClass('is-active');
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeModals() {
|
function closeModals() {
|
||||||
$(document).removeClass('is-clipped');
|
$(document).removeClass('is-clipped');
|
||||||
$(".modal").removeClass('is-active');
|
$(".modal").removeClass('is-active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si on clique sur enregistrer, ça marche
|
// Si on clique sur enregistrer, ça marche
|
||||||
$("#user-update-button").on("click", function() {
|
$("#user-update-button").on("click", function() {
|
||||||
$("#user-update-form").submit();
|
$("#user-update-form").submit();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Si on clique sur supprimer, confirmation demandée
|
||||||
|
$("#user-delete-button").on("click", function() {
|
||||||
|
openModal("confirm-delete-modal");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
|
||||||
|
|
||||||
|
$("#confirm-delete-button").on("click", function() {
|
||||||
|
$("#user-delete-form").submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("keydown", function(e) {
|
||||||
|
if (e.key == "Escape") {
|
||||||
|
closeModals();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key == "Enter") {
|
||||||
|
$("#user-update-form").submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Si on clique sur supprimer, confirmation demandée
|
|
||||||
$("#user-delete-button").on("click", function () {
|
|
||||||
openModal("confirm-delete-modal");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".modal-background, #modal-close, #cancel-delete-button").on("click", closeModals);
|
|
||||||
|
|
||||||
$("#confirm-delete-button").on("click", function() {
|
|
||||||
$("#user-delete-form").submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("keydown", function (e) {
|
|
||||||
if (e.key == "Escape") {
|
|
||||||
closeModals();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key == "Enter") {
|
|
||||||
$("#user-update-form").submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -15,4 +15,10 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
path("user/delete/<int:pk>", views.UserDeleteView.as_view(), name="user.delete"),
|
path("user/delete/<int:pk>", views.UserDeleteView.as_view(), name="user.delete"),
|
||||||
path("members", views.export_members, name="export.members"),
|
path("members", views.export_members, name="export.members"),
|
||||||
|
path(
|
||||||
|
"members/expired",
|
||||||
|
views.ResetMembershipListView.as_view(),
|
||||||
|
name="members.expired",
|
||||||
|
),
|
||||||
|
path("members/reset", views.ResetMembershipView.as_view(), name="members.reset"),
|
||||||
]
|
]
|
||||||
|
|
25
bds/views.py
25
bds/views.py
|
@ -8,7 +8,7 @@ from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import DeleteView, TemplateView
|
from django.views.generic import DeleteView, ListView, RedirectView, TemplateView
|
||||||
|
|
||||||
from bds.autocomplete import bds_search
|
from bds.autocomplete import bds_search
|
||||||
from bds.forms import ProfileForm, UserForm, UserFromClipperForm, UserFromScratchForm
|
from bds.forms import ProfileForm, UserForm, UserFromClipperForm, UserFromScratchForm
|
||||||
|
@ -30,6 +30,7 @@ class Home(StaffRequiredMixin, TemplateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context["member_count"] = BDSProfile.objects.filter(is_member=True).count()
|
context["member_count"] = BDSProfile.objects.filter(is_member=True).count()
|
||||||
|
context["nb_expired"] = BDSProfile.expired_members().count()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,6 +144,28 @@ class UserDeleteView(StaffRequiredMixin, DeleteView):
|
||||||
return super().delete(request, *args, **kwargs)
|
return super().delete(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ResetMembershipListView(StaffRequiredMixin, ListView):
|
||||||
|
model = BDSProfile
|
||||||
|
template_name = "bds/expired_members.html"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return BDSProfile.expired_members()
|
||||||
|
|
||||||
|
|
||||||
|
class ResetMembershipView(StaffRequiredMixin, RedirectView):
|
||||||
|
url = reverse_lazy("bds:members.expired")
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
qs = BDSProfile.expired_members()
|
||||||
|
nb = qs.count()
|
||||||
|
|
||||||
|
qs.update(cotisation_period="NO", is_member=False, mails_bds=False)
|
||||||
|
|
||||||
|
messages.success(request, f"{nb} adhésions réinitialisées")
|
||||||
|
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@permission_required("bds.is_team")
|
@permission_required("bds.is_team")
|
||||||
def export_members(request):
|
def export_members(request):
|
||||||
response = HttpResponse(content_type="text/csv")
|
response = HttpResponse(content_type="text/csv")
|
||||||
|
|
Loading…
Reference in a new issue