Merge pull request 'Application des changement statuts et RI' (#846) from status-change-2024-nov-13 into master
Reviewed-on: #846
This commit is contained in:
commit
5c4b752363
31 changed files with 748 additions and 165 deletions
|
@ -130,15 +130,33 @@ class UserProfileAdmin(UserAdmin):
|
||||||
is_buro.short_description = "Membre du Buro"
|
is_buro.short_description = "Membre du Buro"
|
||||||
is_buro.boolean = True
|
is_buro.boolean = True
|
||||||
|
|
||||||
|
def is_chef(self, obj):
|
||||||
|
try:
|
||||||
|
return obj.profile.is_chef
|
||||||
|
except CofProfile.DoesNotExist:
|
||||||
|
return False
|
||||||
|
|
||||||
|
is_chef.short_description = "Chef K-Fêt"
|
||||||
|
is_chef.boolean = True
|
||||||
|
|
||||||
def is_cof(self, obj):
|
def is_cof(self, obj):
|
||||||
try:
|
try:
|
||||||
return obj.profile.is_cof
|
return obj.profile.is_cof
|
||||||
except CofProfile.DoesNotExist:
|
except CofProfile.DoesNotExist:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
is_cof.short_description = "Membre du COF"
|
is_cof.short_description = "Membre COF"
|
||||||
is_cof.boolean = True
|
is_cof.boolean = True
|
||||||
|
|
||||||
|
def is_kfet(self, obj):
|
||||||
|
try:
|
||||||
|
return obj.profile.is_kfet
|
||||||
|
except CofProfile.DoesNotExist:
|
||||||
|
return False
|
||||||
|
|
||||||
|
is_kfet.short_description = "Membre K-Fêt"
|
||||||
|
is_kfet.boolean = True
|
||||||
|
|
||||||
list_display = UserAdmin.list_display + (
|
list_display = UserAdmin.list_display + (
|
||||||
"profile_phone",
|
"profile_phone",
|
||||||
"profile_occupation",
|
"profile_occupation",
|
||||||
|
@ -146,7 +164,9 @@ class UserProfileAdmin(UserAdmin):
|
||||||
"profile_mailing_bda",
|
"profile_mailing_bda",
|
||||||
"profile_mailing_bda_revente",
|
"profile_mailing_bda_revente",
|
||||||
"is_cof",
|
"is_cof",
|
||||||
|
"is_kfet",
|
||||||
"is_buro",
|
"is_buro",
|
||||||
|
"is_chef",
|
||||||
)
|
)
|
||||||
list_display_links = ("username", "email", "first_name", "last_name")
|
list_display_links = ("username", "email", "first_name", "last_name")
|
||||||
list_filter = UserAdmin.list_filter + (
|
list_filter = UserAdmin.list_filter + (
|
||||||
|
|
|
@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def cof_required(view_func):
|
def cof_required(view_func):
|
||||||
"""Décorateur qui vérifie que l'utilisateur est connecté et membre du COF.
|
"""Décorateur qui vérifie que l'utilisateur est connecté et membre COF.
|
||||||
|
|
||||||
- Si l'utilisteur n'est pas connecté, il est redirigé vers la page de
|
- Si l'utilisteur n'est pas connecté, il est redirigé vers la page de
|
||||||
connexion
|
connexion
|
||||||
|
@ -33,6 +33,31 @@ def cof_required(view_func):
|
||||||
return login_required(_wrapped_view)
|
return login_required(_wrapped_view)
|
||||||
|
|
||||||
|
|
||||||
|
def kfet_required(view_func):
|
||||||
|
"""Décorateur qui vérifie que l'utilisateur est connecté et membre K-Fêt.
|
||||||
|
|
||||||
|
- Si l'utilisteur n'est pas connecté, il est redirigé vers la page de
|
||||||
|
connexion
|
||||||
|
- Si l'utilisateur est connecté mais pas membre K-Fêt, il obtient une
|
||||||
|
page d'erreur lui demandant de s'inscrire à la K-Fêt
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_kfet(user):
|
||||||
|
try:
|
||||||
|
return user.profile.is_cof or user.profile.is_kfet
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@wraps(view_func)
|
||||||
|
def _wrapped_view(request, *args, **kwargs):
|
||||||
|
if is_kfet(request.user):
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
|
return render(request, "kfet-denied.html", status=403)
|
||||||
|
|
||||||
|
return login_required(_wrapped_view)
|
||||||
|
|
||||||
|
|
||||||
def buro_required(view_func):
|
def buro_required(view_func):
|
||||||
"""Décorateur qui vérifie que l'utilisateur est connecté et membre du burô.
|
"""Décorateur qui vérifie que l'utilisateur est connecté et membre du burô.
|
||||||
|
|
||||||
|
@ -58,6 +83,33 @@ def buro_required(view_func):
|
||||||
return login_required(_wrapped_view)
|
return login_required(_wrapped_view)
|
||||||
|
|
||||||
|
|
||||||
|
def chef_required(view_func):
|
||||||
|
"""Décorateur qui vérifie que l'utilisateur est connecté et membre du burô ou chef K-fêt.
|
||||||
|
|
||||||
|
- Si l'utilisateur n'est pas connecté, il est redirigé vers la page de
|
||||||
|
connexion
|
||||||
|
- Si l'utilisateur est connecté mais pas membre du burô ou chef, il obtient une
|
||||||
|
page d'erreur 403 Forbidden
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_chef(user):
|
||||||
|
try:
|
||||||
|
return user.profile.is_chef or user.profile.is_buro
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@wraps(view_func)
|
||||||
|
def _wrapped_view(request, *args, **kwargs):
|
||||||
|
if is_chef(request.user):
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request, "buro-denied.html", status=403
|
||||||
|
) # TODO: reservé au burô ou au chef
|
||||||
|
|
||||||
|
return login_required(_wrapped_view)
|
||||||
|
|
||||||
|
|
||||||
class CofRequiredMixin(PermissionRequiredMixin):
|
class CofRequiredMixin(PermissionRequiredMixin):
|
||||||
def has_permission(self):
|
def has_permission(self):
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
|
@ -79,3 +131,18 @@ class BuroRequiredMixin(PermissionRequiredMixin):
|
||||||
"L'utilisateur %s n'a pas de profil !", self.request.user.username
|
"L'utilisateur %s n'a pas de profil !", self.request.user.username
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class ChefRequiredMixin(PermissionRequiredMixin):
|
||||||
|
def has_permission(self):
|
||||||
|
if not self.request.user.is_authenticated:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
return (
|
||||||
|
self.request.user.profile.is_chef or self.request.user.profile.is_buro
|
||||||
|
)
|
||||||
|
except AttributeError:
|
||||||
|
logger.error(
|
||||||
|
"L'utilisateur %s n'a pas de profil !", self.request.user.username
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
|
@ -284,6 +284,7 @@ class RegistrationProfileForm(forms.ModelForm):
|
||||||
"occupation",
|
"occupation",
|
||||||
"departement",
|
"departement",
|
||||||
"is_cof",
|
"is_cof",
|
||||||
|
"is_kfet",
|
||||||
"type_cotiz",
|
"type_cotiz",
|
||||||
"mailing_cof",
|
"mailing_cof",
|
||||||
"mailing_bda",
|
"mailing_bda",
|
||||||
|
@ -293,6 +294,19 @@ class RegistrationProfileForm(forms.ModelForm):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class RegistrationKFProfileForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = CofProfile
|
||||||
|
fields = [
|
||||||
|
"login_clipper",
|
||||||
|
"phone",
|
||||||
|
"occupation",
|
||||||
|
"departement",
|
||||||
|
"is_kfet",
|
||||||
|
"comments",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
STATUS_CHOICES = (
|
STATUS_CHOICES = (
|
||||||
("no", "Non"),
|
("no", "Non"),
|
||||||
("wait", "Oui mais attente paiement"),
|
("wait", "Oui mais attente paiement"),
|
||||||
|
@ -444,3 +458,20 @@ class GestioncofConfigForm(ConfigForm):
|
||||||
max_length=2048,
|
max_length=2048,
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ----
|
||||||
|
# Formulaire pour les adhésions self-service
|
||||||
|
# ----
|
||||||
|
|
||||||
|
|
||||||
|
class SubscribForm(forms.Form):
|
||||||
|
accept_ri = forms.BooleanField(
|
||||||
|
label="Lu et accepte le réglement intérieur de l'AEENS (COF).", required=True
|
||||||
|
)
|
||||||
|
accept_status = forms.BooleanField(
|
||||||
|
label="Lu et accepte les status de l'AEENS (COF).", required=True
|
||||||
|
)
|
||||||
|
accept_charte_kf = forms.BooleanField(
|
||||||
|
label="Lu et accepte la charte de la K-Fêt.", required=True
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 4.2.16 on 2024-12-24 10:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("gestioncof", "0020_merge_20241218_2240"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="is_kfet",
|
||||||
|
field=models.BooleanField(default=False, verbose_name="Membre K-Fêt"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="is_cof",
|
||||||
|
field=models.BooleanField(default=False, verbose_name="Membre COF"),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Generated by Django 4.2.16 on 2024-12-30 14:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("gestioncof", "0021_cofprofile_is_kfet_alter_cofprofile_is_cof"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="date_adhesion",
|
||||||
|
field=models.DateField(
|
||||||
|
blank=True, null=True, verbose_name="Date d'adhésion COF"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
old_name="date_adhesion",
|
||||||
|
new_name="date_adhesion_cof",
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="date_adhesion_kfet",
|
||||||
|
field=models.DateField(
|
||||||
|
blank=True, null=True, verbose_name="Date d'adhésion K-Fêt"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
18
gestioncof/migrations/0023_cofprofile_is_chef.py
Normal file
18
gestioncof/migrations/0023_cofprofile_is_chef.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.16 on 2025-01-21 10:06
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("gestioncof", "0022_rename_cofprofile_date_adhesion_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="cofprofile",
|
||||||
|
name="is_chef",
|
||||||
|
field=models.BooleanField(default=False, verbose_name="Chef K-Fêt"),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,7 +1,13 @@
|
||||||
|
from datetime import date
|
||||||
|
from smtplib import SMTPRecipientsRefused
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.mail import send_mail
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_delete, post_save
|
from django.db.models.signals import post_delete, post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
from django.template import loader
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from bda.models import Spectacle
|
from bda.models import Spectacle
|
||||||
|
@ -49,8 +55,12 @@ class CofProfile(models.Model):
|
||||||
login_clipper = models.CharField(
|
login_clipper = models.CharField(
|
||||||
"Login clipper", max_length=32, blank=True, unique=True, null=True
|
"Login clipper", max_length=32, blank=True, unique=True, null=True
|
||||||
)
|
)
|
||||||
is_cof = models.BooleanField("Membre du COF", default=False)
|
is_cof = models.BooleanField("Membre COF", default=False)
|
||||||
date_adhesion = models.DateField("Date d'adhésion", blank=True, null=True)
|
is_kfet = models.BooleanField("Membre K-Fêt", default=False)
|
||||||
|
date_adhesion_cof = models.DateField("Date d'adhésion COF", blank=True, null=True)
|
||||||
|
date_adhesion_kfet = models.DateField(
|
||||||
|
"Date d'adhésion K-Fêt", blank=True, null=True
|
||||||
|
)
|
||||||
phone = models.CharField("Téléphone", max_length=20, blank=True)
|
phone = models.CharField("Téléphone", max_length=20, blank=True)
|
||||||
occupation = models.CharField(
|
occupation = models.CharField(
|
||||||
_("Occupation"),
|
_("Occupation"),
|
||||||
|
@ -75,6 +85,7 @@ class CofProfile(models.Model):
|
||||||
)
|
)
|
||||||
comments = models.TextField("Commentaires visibles par l'utilisateur", blank=True)
|
comments = models.TextField("Commentaires visibles par l'utilisateur", blank=True)
|
||||||
is_buro = models.BooleanField("Membre du Burô", default=False)
|
is_buro = models.BooleanField("Membre du Burô", default=False)
|
||||||
|
is_chef = models.BooleanField("Chef K-Fêt", default=False)
|
||||||
petits_cours_accept = models.BooleanField(
|
petits_cours_accept = models.BooleanField(
|
||||||
"Recevoir des petits cours", default=False
|
"Recevoir des petits cours", default=False
|
||||||
)
|
)
|
||||||
|
@ -89,6 +100,46 @@ class CofProfile(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.user.username
|
return self.user.username
|
||||||
|
|
||||||
|
def make_adh_cof(self, request, was_cof):
|
||||||
|
if self.is_cof and not was_cof:
|
||||||
|
notify_new_member(request, self.user)
|
||||||
|
self.date_adhesion_cof = date.today()
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def make_adh_kfet(self, request, was_kfet):
|
||||||
|
if self.is_kfet and not was_kfet:
|
||||||
|
notify_new_member(request, self.user)
|
||||||
|
self.date_adhesion_kfet = date.today()
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
|
def notify_new_member(request, member: User):
|
||||||
|
if not member.email:
|
||||||
|
messages.warning(
|
||||||
|
request,
|
||||||
|
"GestioCOF n'a pas d'adresse mail pour {}, ".format(member)
|
||||||
|
+ "aucun email de bienvenue n'a été envoyé",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Try to send a welcome email and report SMTP errors
|
||||||
|
try:
|
||||||
|
send_mail(
|
||||||
|
"Bienvenue au COF",
|
||||||
|
loader.render_to_string(
|
||||||
|
"gestioncof/mails/welcome.txt", context={"member": member}
|
||||||
|
),
|
||||||
|
"cof@ens.fr",
|
||||||
|
[member.email],
|
||||||
|
)
|
||||||
|
except SMTPRecipientsRefused:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
"Error lors de l'envoi de l'email de bienvenue à {} ({})".format(
|
||||||
|
member, member.email
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=User)
|
@receiver(post_save, sender=User)
|
||||||
def create_user_profile(sender, instance, created, **kwargs):
|
def create_user_profile(sender, instance, created, **kwargs):
|
||||||
|
|
|
@ -701,6 +701,9 @@ header a:active {
|
||||||
.user-is-cof {
|
.user-is-cof {
|
||||||
color : #ADE297;
|
color : #ADE297;
|
||||||
}
|
}
|
||||||
|
.user-is-kfet {
|
||||||
|
color : #FF8C00;
|
||||||
|
}
|
||||||
.user-is-not-cof {
|
.user-is-not-cof {
|
||||||
color: #EE8585;
|
color: #EE8585;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "base_title.html" %}
|
{% extends "base_title.html" %}
|
||||||
|
|
||||||
{% block realcontent %}
|
{% block realcontent %}
|
||||||
<h2>Section réservée aux membres du COF -- merci de vous inscrire au COF ou de passer au COF/nous envoyer un mail si vous êtes déjà membre :)</h2>
|
<h2>Section réservée aux membres COF -- merci de vous inscrire au COF ou de passer au COF/nous envoyer un mail si vous êtes déjà membre :)</h2>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</a>
|
</a>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
|
{% if user.is_authenticated %}
|
||||||
<span class="hidden-xxs"> | </span>
|
<span class="hidden-xxs"> | </span>
|
||||||
<span><a href="{% url "cof-logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
<span><a href="{% url "cof-logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<h2 class="member-status">{% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}, {% if user.profile.is_cof %}<tt class="user-is-cof">au COF{% else %}<tt class="user-is-not-cof">non-COF{% endif %}</tt></h2>
|
<h2 class="member-status">{%if user.is_authenticated %}{% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}, {% endif %}{% if user.profile.is_cof %}<tt class="user-is-cof">au COF{% elif user.profile.is_kfet %}<tt class="user-is-kfet">membre K-Fêt{% else %}<tt class="user-is-not-cof">non-COF{% endif %}</tt></h2>
|
||||||
</div><!-- /.container -->
|
</div><!-- /.container -->
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
19
gestioncof/templates/gestioncof/carte_kf.html
Normal file
19
gestioncof/templates/gestioncof/carte_kf.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% extends "base_title.html" %}
|
||||||
|
{% load bootstrap %}
|
||||||
|
|
||||||
|
{% block page_size %}col-sm-8{%endblock%}
|
||||||
|
|
||||||
|
{% block realcontent %}
|
||||||
|
<h2>Pass K-Fêt</h2>
|
||||||
|
|
||||||
|
<center style="font-size: 20pt;">
|
||||||
|
<p>Profil de {{ user.first_name }} {{ user.last_name }}</p>
|
||||||
|
|
||||||
|
{% if user.profile.is_cof %}
|
||||||
|
<p>Membre COF depuis le {{ user.profile.date_adhesion_cof }}</p>
|
||||||
|
{% else %}
|
||||||
|
<p>Membre K-Fêt depuis le {{ user.profile.date_adhesion_kfet }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="container hidden-xs espace"></div>
|
<div class="container hidden-xs espace"></div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="home-menu row">
|
<div class="home-menu row">
|
||||||
<div class="{% if user.profile.is_buro %}col-sm-6 {% else %}col-sm-8 col-sm-offset-2 col-xs-12 {%endif%}normal-user-hm">
|
<div class="{% if user.profile.is_buro or user.profile.is_chef %}col-sm-6 {% else %}col-sm-8 col-sm-offset-2 col-xs-12 {%endif%}normal-user-hm">
|
||||||
{% if open_surveys %}
|
{% if open_surveys %}
|
||||||
<h3 class="block-title">Sondages en cours<span class="pull-right glyphicon glyphicon-stats"></span></h3>
|
<h3 class="block-title">Sondages en cours<span class="pull-right glyphicon glyphicon-stats"></span></h3>
|
||||||
<div class="hm-block">
|
<div class="hm-block">
|
||||||
|
@ -50,6 +50,9 @@
|
||||||
<ul>
|
<ul>
|
||||||
{# TODO: Since Django 1.9, we can store result with "as", allowing proper value management (if None) #}
|
{# TODO: Since Django 1.9, we can store result with "as", allowing proper value management (if None) #}
|
||||||
<li><a href="{% slugurl "k-fet" %}">Page d'accueil</a></li>
|
<li><a href="{% slugurl "k-fet" %}">Page d'accueil</a></li>
|
||||||
|
{% if user.profile.is_cof or user.profile.is_kfet %}
|
||||||
|
<li><a href="{% url "profile.carte" %}">Carte K-Fêt</a></li>
|
||||||
|
{% endif %}
|
||||||
<li><a href="https://cof.ens.fr/k-fet/le-calendrier/">Calendrier</a></li>
|
<li><a href="https://cof.ens.fr/k-fet/le-calendrier/">Calendrier</a></li>
|
||||||
{% if perms.kfet.is_team %}
|
{% if perms.kfet.is_team %}
|
||||||
<li><a href="{% url 'kfet.kpsul' %}">K-Psul</a></li>
|
<li><a href="{% url 'kfet.kpsul' %}">K-Psul</a></li>
|
||||||
|
@ -68,9 +71,23 @@
|
||||||
{% if not user.profile.login_clipper %}
|
{% if not user.profile.login_clipper %}
|
||||||
<li><a href="{% url "password_change" %}">Changer mon mot de passe</a></li>
|
<li><a href="{% url "password_change" %}">Changer mon mot de passe</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if not user.profile.is_cof and not user.profile.is_kfet %}
|
||||||
|
<li><a href="{% url "self.kf_registration" %}">Adhérer à la K-Fêt</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if user.profile.is_chef and not user.profile.is_buro %}
|
||||||
|
<div class="col-sm-6 buro-user-hm">
|
||||||
|
<h3 class="block-title">Administration<span class="pull-right glyphicon glyphicon-cog"></span></h3>
|
||||||
|
<div class="hm-block">
|
||||||
|
<ul>
|
||||||
|
<h4>Général</h4>
|
||||||
|
<li><a href="{% url "registration" %}">Inscription d'un nouveau membre</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if user.profile.is_buro %}
|
{% if user.profile.is_buro %}
|
||||||
<div class="col-sm-6 buro-user-hm">
|
<div class="col-sm-6 buro-user-hm">
|
||||||
<h3 class="block-title">Administration<span class="pull-right glyphicon glyphicon-cog"></span></h3>
|
<h3 class="block-title">Administration<span class="pull-right glyphicon glyphicon-cog"></span></h3>
|
||||||
|
|
21
gestioncof/templates/gestioncof/registration_kf_form.html
Normal file
21
gestioncof/templates/gestioncof/registration_kf_form.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{% load bootstrap %}
|
||||||
|
|
||||||
|
{% if login_clipper %}
|
||||||
|
<h3>Inscription associée au compte clipper <tt>{{ login_clipper }}</tt></h3>
|
||||||
|
{% elif member %}
|
||||||
|
<h3>Inscription du compte GestioCOF existant <tt>{{ member.username }}</tt></h3>
|
||||||
|
{% else %}
|
||||||
|
<h3>Inscription d'un nouveau compte (extérieur ?)</h3>
|
||||||
|
{% endif %}
|
||||||
|
<form role="form" id="profile" method="post" action="{% url 'registration' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{{ user_form | bootstrap }}
|
||||||
|
{{ profile_form | bootstrap }}
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
{% if login_clipper or member %}
|
||||||
|
<input type="hidden" name="user_exists" value="1" />
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" class="btn btn-primary pull-right" value="Enregistrer l'inscription" />
|
||||||
|
</form>
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "base_title.html" %}
|
||||||
|
|
||||||
|
{% block realcontent %}
|
||||||
|
<h2>Inscription d'un nouveau membre</h2>
|
||||||
|
<div id="form-placeholder">
|
||||||
|
{% include "gestioncof/registration_kf_form.html" %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
28
gestioncof/templates/gestioncof/self_registration.html
Normal file
28
gestioncof/templates/gestioncof/self_registration.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{% extends "base_title.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block page_size %}col-sm-8{% endblock %}
|
||||||
|
|
||||||
|
{% load bootstrap %}
|
||||||
|
|
||||||
|
{% block realcontent %}
|
||||||
|
|
||||||
|
{% if member %}
|
||||||
|
<h3>Inscription K-Fêt du compte GestioCOF existant <tt>{{ member.username }}</tt></h3>
|
||||||
|
{% else %}
|
||||||
|
<h3>Inscription K-Fêt d'un nouveau compte (extérieur ?)</h3>
|
||||||
|
{% endif %}
|
||||||
|
<form role="form" id="profile" method="post" action="{% url 'self.kf_registration' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{{ user_form | bootstrap }}
|
||||||
|
{{ profile_form | bootstrap }}
|
||||||
|
{{ agreement_form | bootstrap }}
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
{% if login_clipper or member %}
|
||||||
|
<input type="hidden" name="user_exists" value="1" />
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" class="btn btn-primary pull-right" value="Adhérer" />
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
5
gestioncof/templates/kfet-denied.html
Normal file
5
gestioncof/templates/kfet-denied.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends "base_title.html" %}
|
||||||
|
|
||||||
|
{% block realcontent %}
|
||||||
|
<h2>Section réservée aux membres K-Fêt -- merci de vous inscrire au COF ou de passer au COF/nous envoyer un mail si vous êtes déjà membre :)</h2>
|
||||||
|
{% endblock %}
|
|
@ -486,7 +486,7 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
|
||||||
u1.last_name = "last"
|
u1.last_name = "last"
|
||||||
u1.email = "user@mail.net"
|
u1.email = "user@mail.net"
|
||||||
u1.save()
|
u1.save()
|
||||||
u1.profile.date_adhesion = date(2023, 5, 22)
|
u1.profile.date_adhesion_cof = date(2023, 5, 22)
|
||||||
u1.profile.phone = "0123456789"
|
u1.profile.phone = "0123456789"
|
||||||
u1.profile.departement = "Dept"
|
u1.profile.departement = "Dept"
|
||||||
u1.profile.save()
|
u1.profile.save()
|
||||||
|
|
|
@ -80,6 +80,7 @@ registration_patterns = [
|
||||||
views.RegistrationAutocompleteView.as_view(),
|
views.RegistrationAutocompleteView.as_view(),
|
||||||
name="cof.registration.autocomplete",
|
name="cof.registration.autocomplete",
|
||||||
),
|
),
|
||||||
|
path("self_kf", views.self_kf_registration, name="self.kf_registration"),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -99,6 +100,7 @@ urlpatterns = [
|
||||||
name="cof-user-autocomplete",
|
name="cof-user-autocomplete",
|
||||||
),
|
),
|
||||||
path("config", views.ConfigUpdate.as_view(), name="config.edit"),
|
path("config", views.ConfigUpdate.as_view(), name="config.edit"),
|
||||||
|
path("carte", views.carte_kf, name="profile.carte"),
|
||||||
# -----
|
# -----
|
||||||
# Authentification
|
# Authentification
|
||||||
# -----
|
# -----
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import csv
|
import csv
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import date, timedelta
|
from datetime import timedelta
|
||||||
from smtplib import SMTPRecipientsRefused
|
|
||||||
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
@ -14,11 +13,10 @@ from django.contrib.auth.views import (
|
||||||
redirect_to_login,
|
redirect_to_login,
|
||||||
)
|
)
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core.mail import send_mail
|
from django.db.models import Q
|
||||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template import loader
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.urls import reverse_lazy
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import FormView, TemplateView
|
from django.views.generic import FormView, TemplateView
|
||||||
|
@ -27,7 +25,14 @@ from icalendar import Calendar, Event as Vevent
|
||||||
|
|
||||||
from bda.models import Spectacle, Tirage
|
from bda.models import Spectacle, Tirage
|
||||||
from gestioncof.autocomplete import cof_autocomplete
|
from gestioncof.autocomplete import cof_autocomplete
|
||||||
from gestioncof.decorators import BuroRequiredMixin, buro_required, cof_required
|
from gestioncof.decorators import (
|
||||||
|
BuroRequiredMixin,
|
||||||
|
ChefRequiredMixin,
|
||||||
|
buro_required,
|
||||||
|
chef_required,
|
||||||
|
cof_required,
|
||||||
|
kfet_required,
|
||||||
|
)
|
||||||
from gestioncof.forms import (
|
from gestioncof.forms import (
|
||||||
CalendarForm,
|
CalendarForm,
|
||||||
ClubsForm,
|
ClubsForm,
|
||||||
|
@ -38,9 +43,11 @@ from gestioncof.forms import (
|
||||||
GestioncofConfigForm,
|
GestioncofConfigForm,
|
||||||
PhoneForm,
|
PhoneForm,
|
||||||
ProfileForm,
|
ProfileForm,
|
||||||
|
RegistrationKFProfileForm,
|
||||||
RegistrationPassUserForm,
|
RegistrationPassUserForm,
|
||||||
RegistrationProfileForm,
|
RegistrationProfileForm,
|
||||||
RegistrationUserForm,
|
RegistrationUserForm,
|
||||||
|
SubscribForm,
|
||||||
SurveyForm,
|
SurveyForm,
|
||||||
SurveyStatusFilterForm,
|
SurveyStatusFilterForm,
|
||||||
UserForm,
|
UserForm,
|
||||||
|
@ -86,7 +93,9 @@ class ResetComptes(BuroRequiredMixin, TemplateView):
|
||||||
nb_adherents = CofProfile.objects.filter(is_cof=True).count()
|
nb_adherents = CofProfile.objects.filter(is_cof=True).count()
|
||||||
CofProfile.objects.update(
|
CofProfile.objects.update(
|
||||||
is_cof=False,
|
is_cof=False,
|
||||||
date_adhesion=None,
|
is_kfet=False,
|
||||||
|
date_adhesion_cof=None,
|
||||||
|
date_adhesion_kfet=None,
|
||||||
mailing_cof=False,
|
mailing_cof=False,
|
||||||
mailing_bda=False,
|
mailing_bda=False,
|
||||||
mailing_bda_revente=False,
|
mailing_bda_revente=False,
|
||||||
|
@ -421,13 +430,20 @@ def profile(request):
|
||||||
return render(request, "gestioncof/profile.html", context)
|
return render(request, "gestioncof/profile.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@kfet_required
|
||||||
|
def carte_kf(request):
|
||||||
|
user = request.user
|
||||||
|
return render(request, "gestioncof/carte_kf.html", {"user": user})
|
||||||
|
|
||||||
|
|
||||||
def registration_set_ro_fields(user_form, profile_form):
|
def registration_set_ro_fields(user_form, profile_form):
|
||||||
user_form.fields["username"].widget.attrs["readonly"] = True
|
user_form.fields["username"].widget.attrs["readonly"] = True
|
||||||
profile_form.fields["login_clipper"].widget.attrs["readonly"] = True
|
profile_form.fields["login_clipper"].widget.attrs["readonly"] = True
|
||||||
|
|
||||||
|
|
||||||
@buro_required
|
@chef_required
|
||||||
def registration_form2(request, login_clipper=None, username=None, fullname=None):
|
def registration_form2(request, login_clipper=None, username=None, fullname=None):
|
||||||
|
is_buro = request.user.profile.is_buro
|
||||||
events = Event.objects.filter(old=False).all()
|
events = Event.objects.filter(old=False).all()
|
||||||
member = None
|
member = None
|
||||||
if login_clipper:
|
if login_clipper:
|
||||||
|
@ -449,85 +465,84 @@ def registration_form2(request, login_clipper=None, username=None, fullname=None
|
||||||
user_form.fields["first_name"].initial = bits[0]
|
user_form.fields["first_name"].initial = bits[0]
|
||||||
if len(bits) > 1:
|
if len(bits) > 1:
|
||||||
user_form.fields["last_name"].initial = " ".join(bits[1:])
|
user_form.fields["last_name"].initial = " ".join(bits[1:])
|
||||||
# profile
|
if is_buro:
|
||||||
profile_form = RegistrationProfileForm(
|
# profile
|
||||||
initial={"login_clipper": login_clipper}
|
profile_form = RegistrationProfileForm(
|
||||||
)
|
initial={"login_clipper": login_clipper}
|
||||||
|
)
|
||||||
|
# events & clubs
|
||||||
|
event_formset = EventFormset(events=events, prefix="events")
|
||||||
|
clubs_form = ClubsForm()
|
||||||
|
else:
|
||||||
|
profile_form = RegistrationKFProfileForm(
|
||||||
|
initial={"login_clipper": login_clipper}
|
||||||
|
)
|
||||||
|
|
||||||
registration_set_ro_fields(user_form, profile_form)
|
registration_set_ro_fields(user_form, profile_form)
|
||||||
# events & clubs
|
|
||||||
event_formset = EventFormset(events=events, prefix="events")
|
|
||||||
clubs_form = ClubsForm()
|
|
||||||
if username:
|
if username:
|
||||||
member = get_object_or_404(User, username=username)
|
member = get_object_or_404(User, username=username)
|
||||||
(profile, _) = CofProfile.objects.get_or_create(user=member)
|
(profile, _) = CofProfile.objects.get_or_create(user=member)
|
||||||
# already existing, prefill
|
# already existing, prefill
|
||||||
user_form = RegistrationUserForm(instance=member)
|
user_form = RegistrationUserForm(instance=member)
|
||||||
profile_form = RegistrationProfileForm(instance=profile)
|
if is_buro:
|
||||||
|
profile_form = RegistrationProfileForm(instance=profile)
|
||||||
|
# events
|
||||||
|
current_registrations = []
|
||||||
|
for event in events:
|
||||||
|
try:
|
||||||
|
current_registrations.append(
|
||||||
|
EventRegistration.objects.get(user=member, event=event)
|
||||||
|
)
|
||||||
|
except EventRegistration.DoesNotExist:
|
||||||
|
current_registrations.append(None)
|
||||||
|
event_formset = EventFormset(
|
||||||
|
events=events,
|
||||||
|
prefix="events",
|
||||||
|
current_registrations=current_registrations,
|
||||||
|
)
|
||||||
|
# Clubs
|
||||||
|
clubs_form = ClubsForm(initial={"clubs": member.clubs.all()})
|
||||||
|
else:
|
||||||
|
profile_form = RegistrationKFProfileForm(instance=profile)
|
||||||
registration_set_ro_fields(user_form, profile_form)
|
registration_set_ro_fields(user_form, profile_form)
|
||||||
# events
|
|
||||||
current_registrations = []
|
|
||||||
for event in events:
|
|
||||||
try:
|
|
||||||
current_registrations.append(
|
|
||||||
EventRegistration.objects.get(user=member, event=event)
|
|
||||||
)
|
|
||||||
except EventRegistration.DoesNotExist:
|
|
||||||
current_registrations.append(None)
|
|
||||||
event_formset = EventFormset(
|
|
||||||
events=events, prefix="events", current_registrations=current_registrations
|
|
||||||
)
|
|
||||||
# Clubs
|
|
||||||
clubs_form = ClubsForm(initial={"clubs": member.clubs.all()})
|
|
||||||
elif not login_clipper:
|
elif not login_clipper:
|
||||||
# new user
|
# new user
|
||||||
user_form = RegistrationPassUserForm()
|
user_form = RegistrationPassUserForm()
|
||||||
profile_form = RegistrationProfileForm()
|
if is_buro:
|
||||||
event_formset = EventFormset(events=events, prefix="events")
|
profile_form = RegistrationProfileForm()
|
||||||
clubs_form = ClubsForm()
|
event_formset = EventFormset(events=events, prefix="events")
|
||||||
return render(
|
clubs_form = ClubsForm()
|
||||||
request,
|
else:
|
||||||
"gestioncof/registration_form.html",
|
profile_form = RegistrationKFProfileForm()
|
||||||
{
|
if is_buro:
|
||||||
"member": member,
|
return render(
|
||||||
"login_clipper": login_clipper,
|
|
||||||
"user_form": user_form,
|
|
||||||
"profile_form": profile_form,
|
|
||||||
"event_formset": event_formset,
|
|
||||||
"clubs_form": clubs_form,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def notify_new_member(request, member: User):
|
|
||||||
if not member.email:
|
|
||||||
messages.warning(
|
|
||||||
request,
|
request,
|
||||||
"GestioCOF n'a pas d'adresse mail pour {}, ".format(member)
|
"gestioncof/registration_form.html",
|
||||||
+ "aucun email de bienvenue n'a été envoyé",
|
{
|
||||||
|
"member": member,
|
||||||
|
"login_clipper": login_clipper,
|
||||||
|
"user_form": user_form,
|
||||||
|
"profile_form": profile_form,
|
||||||
|
"event_formset": event_formset,
|
||||||
|
"clubs_form": clubs_form,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return
|
else:
|
||||||
|
return render(
|
||||||
# Try to send a welcome email and report SMTP errors
|
|
||||||
try:
|
|
||||||
send_mail(
|
|
||||||
"Bienvenue au COF",
|
|
||||||
loader.render_to_string(
|
|
||||||
"gestioncof/mails/welcome.txt", context={"member": member}
|
|
||||||
),
|
|
||||||
"cof@ens.fr",
|
|
||||||
[member.email],
|
|
||||||
)
|
|
||||||
except SMTPRecipientsRefused:
|
|
||||||
messages.error(
|
|
||||||
request,
|
request,
|
||||||
"Error lors de l'envoi de l'email de bienvenue à {} ({})".format(
|
"gestioncof/registration_kf_form.html",
|
||||||
member, member.email
|
{
|
||||||
),
|
"member": member,
|
||||||
|
"login_clipper": login_clipper,
|
||||||
|
"user_form": user_form,
|
||||||
|
"profile_form": profile_form,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@buro_required
|
@chef_required
|
||||||
def registration(request):
|
def registration(request):
|
||||||
|
is_buro = request.user.profile.is_buro
|
||||||
if request.POST:
|
if request.POST:
|
||||||
request_dict = request.POST.copy()
|
request_dict = request.POST.copy()
|
||||||
member = None
|
member = None
|
||||||
|
@ -541,10 +556,15 @@ def registration(request):
|
||||||
user_form = RegistrationPassUserForm(request_dict)
|
user_form = RegistrationPassUserForm(request_dict)
|
||||||
else:
|
else:
|
||||||
user_form = RegistrationUserForm(request_dict)
|
user_form = RegistrationUserForm(request_dict)
|
||||||
profile_form = RegistrationProfileForm(request_dict)
|
if is_buro:
|
||||||
clubs_form = ClubsForm(request_dict)
|
profile_form = RegistrationProfileForm(request_dict)
|
||||||
events = Event.objects.filter(old=False).all()
|
clubs_form = ClubsForm(request_dict)
|
||||||
event_formset = EventFormset(events=events, data=request_dict, prefix="events")
|
events = Event.objects.filter(old=False).all()
|
||||||
|
event_formset = EventFormset(
|
||||||
|
events=events, data=request_dict, prefix="events"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
profile_form = RegistrationKFProfileForm(request_dict)
|
||||||
if "user_exists" in request_dict and request_dict["user_exists"]:
|
if "user_exists" in request_dict and request_dict["user_exists"]:
|
||||||
username = request_dict["username"]
|
username = request_dict["username"]
|
||||||
try:
|
try:
|
||||||
|
@ -565,63 +585,72 @@ def registration(request):
|
||||||
member = user_form.save()
|
member = user_form.save()
|
||||||
profile, _ = CofProfile.objects.get_or_create(user=member)
|
profile, _ = CofProfile.objects.get_or_create(user=member)
|
||||||
was_cof = profile.is_cof
|
was_cof = profile.is_cof
|
||||||
|
was_kfet = profile.is_kfet
|
||||||
# Maintenant on remplit le formulaire de profil
|
# Maintenant on remplit le formulaire de profil
|
||||||
profile_form = RegistrationProfileForm(request_dict, instance=profile)
|
if is_buro:
|
||||||
if (
|
profile_form = RegistrationProfileForm(request_dict, instance=profile)
|
||||||
profile_form.is_valid()
|
else:
|
||||||
and event_formset.is_valid()
|
profile_form = RegistrationKFProfileForm(request_dict, instance=profile)
|
||||||
and clubs_form.is_valid()
|
if profile_form.is_valid() and (
|
||||||
|
not is_buro or (event_formset.is_valid() and clubs_form.is_valid())
|
||||||
):
|
):
|
||||||
# Enregistrement du profil
|
# Enregistrement du profil
|
||||||
profile = profile_form.save()
|
profile = profile_form.save()
|
||||||
if profile.is_cof and not was_cof:
|
if is_buro:
|
||||||
notify_new_member(request, member)
|
if profile.is_cof:
|
||||||
profile.date_adhesion = date.today()
|
profile.make_adh_cof(request, was_cof)
|
||||||
profile.save()
|
|
||||||
|
|
||||||
# Enregistrement des inscriptions aux événements
|
if profile.is_kfet:
|
||||||
for form in event_formset:
|
profile.make_adh_kfet(request, was_kfet)
|
||||||
if "status" not in form.cleaned_data:
|
|
||||||
form.cleaned_data["status"] = "no"
|
if is_buro:
|
||||||
if form.cleaned_data["status"] == "no":
|
# Enregistrement des inscriptions aux événements
|
||||||
try:
|
for form in event_formset:
|
||||||
current_registration = EventRegistration.objects.get(
|
if "status" not in form.cleaned_data:
|
||||||
user=member, event=form.event
|
form.cleaned_data["status"] = "no"
|
||||||
)
|
if form.cleaned_data["status"] == "no":
|
||||||
current_registration.delete()
|
try:
|
||||||
except EventRegistration.DoesNotExist:
|
current_registration = EventRegistration.objects.get(
|
||||||
pass
|
user=member, event=form.event
|
||||||
continue
|
)
|
||||||
all_choices = get_event_form_choices(form.event, form)
|
current_registration.delete()
|
||||||
(
|
except EventRegistration.DoesNotExist:
|
||||||
current_registration,
|
pass
|
||||||
created_reg,
|
continue
|
||||||
) = EventRegistration.objects.get_or_create(
|
all_choices = get_event_form_choices(form.event, form)
|
||||||
user=member, event=form.event
|
(
|
||||||
)
|
current_registration,
|
||||||
update_event_form_comments(form.event, form, current_registration)
|
created_reg,
|
||||||
current_registration.options.set(all_choices)
|
) = EventRegistration.objects.get_or_create(
|
||||||
current_registration.paid = form.cleaned_data["status"] == "paid"
|
user=member, event=form.event
|
||||||
current_registration.save()
|
)
|
||||||
# if form.event.title == "Mega 15" and created_reg:
|
update_event_form_comments(
|
||||||
# field = EventCommentField.objects.get(
|
form.event, form, current_registration
|
||||||
# event=form.event, name="Commentaires")
|
)
|
||||||
# try:
|
current_registration.options.set(all_choices)
|
||||||
# comments = EventCommentValue.objects.get(
|
current_registration.paid = (
|
||||||
# commentfield=field,
|
form.cleaned_data["status"] == "paid"
|
||||||
# registration=current_registration).content
|
)
|
||||||
# except EventCommentValue.DoesNotExist:
|
current_registration.save()
|
||||||
# comments = field.default
|
# if form.event.title == "Mega 15" and created_reg:
|
||||||
# FIXME : il faut faire quelque chose de propre ici,
|
# field = EventCommentField.objects.get(
|
||||||
# par exemple écrire un mail générique pour
|
# event=form.event, name="Commentaires")
|
||||||
# l'inscription aux événements et/ou donner la
|
# try:
|
||||||
# possibilité d'associer un mail aux événements
|
# comments = EventCommentValue.objects.get(
|
||||||
# send_custom_mail(...)
|
# commentfield=field,
|
||||||
# Enregistrement des inscriptions aux clubs
|
# registration=current_registration).content
|
||||||
member.clubs.clear()
|
# except EventCommentValue.DoesNotExist:
|
||||||
for club in clubs_form.cleaned_data["clubs"]:
|
# comments = field.default
|
||||||
club.membres.add(member)
|
# FIXME : il faut faire quelque chose de propre ici,
|
||||||
club.save()
|
# par exemple écrire un mail générique pour
|
||||||
|
# l'inscription aux événements et/ou donner la
|
||||||
|
# possibilité d'associer un mail aux événements
|
||||||
|
# send_custom_mail(...)
|
||||||
|
# Enregistrement des inscriptions aux clubs
|
||||||
|
member.clubs.clear()
|
||||||
|
for club in clubs_form.cleaned_data["clubs"]:
|
||||||
|
club.membres.add(member)
|
||||||
|
club.save()
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# Success
|
# Success
|
||||||
|
@ -633,27 +662,91 @@ def registration(request):
|
||||||
member.get_full_name(), member.email
|
member.get_full_name(), member.email
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if profile.is_cof:
|
if is_buro and profile.is_cof:
|
||||||
msg += "\nIl est désormais membre du COF n°{:d} !".format(
|
msg += "\nIl est désormais membre du COF n°{:d} !".format(
|
||||||
member.profile.id
|
member.profile.id
|
||||||
)
|
)
|
||||||
messages.success(request, msg, extra_tags="safe")
|
messages.success(request, msg, extra_tags="safe")
|
||||||
return render(
|
if is_buro:
|
||||||
request,
|
return render(
|
||||||
"gestioncof/registration_post.html",
|
request,
|
||||||
{
|
"gestioncof/registration_post.html",
|
||||||
"user_form": user_form,
|
{
|
||||||
"profile_form": profile_form,
|
"user_form": user_form,
|
||||||
"member": member,
|
"profile_form": profile_form,
|
||||||
"login_clipper": login_clipper,
|
"member": member,
|
||||||
"event_formset": event_formset,
|
"login_clipper": login_clipper,
|
||||||
"clubs_form": clubs_form,
|
"event_formset": event_formset,
|
||||||
},
|
"clubs_form": clubs_form,
|
||||||
)
|
},
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"gestioncof/registration_kf_post.html",
|
||||||
|
{
|
||||||
|
"user_form": user_form,
|
||||||
|
"profile_form": profile_form,
|
||||||
|
"member": member,
|
||||||
|
"login_clipper": login_clipper,
|
||||||
|
},
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return render(request, "registration.html")
|
return render(request, "registration.html")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: without login
|
||||||
|
@login_required
|
||||||
|
def self_kf_registration(request):
|
||||||
|
member = request.user
|
||||||
|
(profile, _) = CofProfile.objects.get_or_create(user=member)
|
||||||
|
|
||||||
|
if profile.is_kfet or profile.is_cof:
|
||||||
|
msg = "Vous êtes déjà adhérent du COF !"
|
||||||
|
messages.success(request, msg)
|
||||||
|
response = HttpResponse(content="", status=303)
|
||||||
|
response["Location"] = reverse("profile")
|
||||||
|
return response
|
||||||
|
|
||||||
|
was_kfet = profile.is_kfet
|
||||||
|
if request.POST:
|
||||||
|
user_form = RegistrationUserForm(request.POST, instance=member)
|
||||||
|
profile_form = PhoneForm(request.POST, instance=profile)
|
||||||
|
agreement_form = SubscribForm(request.POST)
|
||||||
|
if (
|
||||||
|
user_form.is_valid()
|
||||||
|
and profile_form.is_valid()
|
||||||
|
and agreement_form.is_valid()
|
||||||
|
):
|
||||||
|
member = user_form.save()
|
||||||
|
profile = profile_form.save()
|
||||||
|
profile.is_kfet = True
|
||||||
|
profile.save()
|
||||||
|
profile.make_adh_kfet(request, was_kfet)
|
||||||
|
|
||||||
|
msg = "Votre adhésion a été enregistrée avec succès."
|
||||||
|
messages.success(request, msg, extra_tags="safe")
|
||||||
|
response = HttpResponse(content="", status=303)
|
||||||
|
response["Location"] = reverse("profile")
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
user_form = RegistrationUserForm(instance=member)
|
||||||
|
profile_form = PhoneForm(instance=profile)
|
||||||
|
agreement_form = SubscribForm()
|
||||||
|
|
||||||
|
user_form.fields["username"].widget.attrs["readonly"] = True
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"gestioncof/self_registration.html",
|
||||||
|
{
|
||||||
|
"user_form": user_form,
|
||||||
|
"profile_form": profile_form,
|
||||||
|
"agreement_form": agreement_form,
|
||||||
|
"member": member,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# -----
|
# -----
|
||||||
# Clubs
|
# Clubs
|
||||||
# -----
|
# -----
|
||||||
|
@ -707,7 +800,7 @@ def export_members(request):
|
||||||
response["Content-Disposition"] = "attachment; filename=membres_cof.csv"
|
response["Content-Disposition"] = "attachment; filename=membres_cof.csv"
|
||||||
|
|
||||||
writer = csv.writer(response)
|
writer = csv.writer(response)
|
||||||
for profile in CofProfile.objects.filter(is_cof=True).all():
|
for profile in CofProfile.objects.filter(Q(is_cof=True) | Q(is_kfet=True)).all():
|
||||||
user = profile.user
|
user = profile.user
|
||||||
bits = [
|
bits = [
|
||||||
user.id,
|
user.id,
|
||||||
|
@ -718,8 +811,10 @@ def export_members(request):
|
||||||
profile.phone,
|
profile.phone,
|
||||||
profile.occupation,
|
profile.occupation,
|
||||||
profile.departement,
|
profile.departement,
|
||||||
|
"COF" if profile.is_cof else "K-Fêt",
|
||||||
profile.type_cotiz,
|
profile.type_cotiz,
|
||||||
profile.date_adhesion,
|
profile.date_adhesion_cof,
|
||||||
|
profile.date_adhesion_kfet,
|
||||||
]
|
]
|
||||||
writer.writerow([str(bit) for bit in bits])
|
writer.writerow([str(bit) for bit in bits])
|
||||||
|
|
||||||
|
@ -975,6 +1070,6 @@ class UserAutocompleteView(BuroRequiredMixin, Select2QuerySetView):
|
||||||
search_fields = ("username", "first_name", "last_name")
|
search_fields = ("username", "first_name", "last_name")
|
||||||
|
|
||||||
|
|
||||||
class RegistrationAutocompleteView(BuroRequiredMixin, AutocompleteView):
|
class RegistrationAutocompleteView(ChefRequiredMixin, AutocompleteView):
|
||||||
template_name = "gestioncof/search_results.html"
|
template_name = "gestioncof/search_results.html"
|
||||||
search_composer = cof_autocomplete
|
search_composer = cof_autocomplete
|
||||||
|
|
|
@ -195,7 +195,13 @@ class CofForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CofProfile
|
model = CofProfile
|
||||||
fields = ["login_clipper", "is_cof", "departement"]
|
fields = ["login_clipper", "is_cof", "is_kfet", "departement"]
|
||||||
|
|
||||||
|
|
||||||
|
class CofKFForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = CofProfile
|
||||||
|
fields = ["is_kfet"]
|
||||||
|
|
||||||
|
|
||||||
class UserForm(forms.ModelForm):
|
class UserForm(forms.ModelForm):
|
||||||
|
@ -350,6 +356,7 @@ class ArticleForm(forms.ModelForm):
|
||||||
fields = [
|
fields = [
|
||||||
"name",
|
"name",
|
||||||
"is_sold",
|
"is_sold",
|
||||||
|
"no_exte",
|
||||||
"hidden",
|
"hidden",
|
||||||
"price",
|
"price",
|
||||||
"stock",
|
"stock",
|
||||||
|
@ -364,6 +371,7 @@ class ArticleRestrictForm(ArticleForm):
|
||||||
fields = [
|
fields = [
|
||||||
"name",
|
"name",
|
||||||
"is_sold",
|
"is_sold",
|
||||||
|
"no_exte",
|
||||||
"hidden",
|
"hidden",
|
||||||
"price",
|
"price",
|
||||||
"category",
|
"category",
|
||||||
|
|
20
kfet/migrations/0081_article_no_exte.py
Normal file
20
kfet/migrations/0081_article_no_exte.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 4.2.16 on 2025-01-06 16:35
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("kfet", "0080_accountnegative_last_rappel"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="article",
|
||||||
|
name="no_exte",
|
||||||
|
field=models.BooleanField(
|
||||||
|
default=False, verbose_name="Réservé au adhérents"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
34
kfet/migrations/0082_alter_operation_options.py
Normal file
34
kfet/migrations/0082_alter_operation_options.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Generated by Django 4.2.16 on 2025-01-18 10:01
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("kfet", "0081_article_no_exte"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="operation",
|
||||||
|
options={
|
||||||
|
"permissions": (
|
||||||
|
("perform_deposit", "Effectuer une charge"),
|
||||||
|
(
|
||||||
|
"perform_negative_operations",
|
||||||
|
"Enregistrer des commandes en négatif",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"perform_liq_reserved",
|
||||||
|
"Effectuer une opération réservé aux adhérents sur LIQ",
|
||||||
|
),
|
||||||
|
("cancel_old_operations", "Annuler des commandes non récentes"),
|
||||||
|
(
|
||||||
|
"perform_commented_operations",
|
||||||
|
"Enregistrer des commandes avec commentaires",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
18
kfet/migrations/0083_operationgroup_is_kfet.py
Normal file
18
kfet/migrations/0083_operationgroup_is_kfet.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.16 on 2025-03-18 10:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("kfet", "0082_alter_operation_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="operationgroup",
|
||||||
|
name="is_kfet",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
|
@ -119,6 +119,10 @@ class Account(models.Model):
|
||||||
def is_cof(self):
|
def is_cof(self):
|
||||||
return self.cofprofile.is_cof
|
return self.cofprofile.is_cof
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_kfet(self):
|
||||||
|
return self.cofprofile.is_kfet
|
||||||
|
|
||||||
# Propriétés supplémentaires
|
# Propriétés supplémentaires
|
||||||
@property
|
@property
|
||||||
def balance_ukf(self):
|
def balance_ukf(self):
|
||||||
|
@ -494,6 +498,7 @@ class ArticleCategory(models.Model):
|
||||||
class Article(models.Model):
|
class Article(models.Model):
|
||||||
name = models.CharField("nom", max_length=45)
|
name = models.CharField("nom", max_length=45)
|
||||||
is_sold = models.BooleanField("en vente", default=True)
|
is_sold = models.BooleanField("en vente", default=True)
|
||||||
|
no_exte = models.BooleanField("Réservé au adhérents", default=False)
|
||||||
hidden = models.BooleanField(
|
hidden = models.BooleanField(
|
||||||
"caché",
|
"caché",
|
||||||
default=False,
|
default=False,
|
||||||
|
@ -682,6 +687,7 @@ class OperationGroup(models.Model):
|
||||||
at = models.DateTimeField(default=timezone.now)
|
at = models.DateTimeField(default=timezone.now)
|
||||||
amount = models.DecimalField(max_digits=6, decimal_places=2, default=0)
|
amount = models.DecimalField(max_digits=6, decimal_places=2, default=0)
|
||||||
is_cof = models.BooleanField(default=False)
|
is_cof = models.BooleanField(default=False)
|
||||||
|
is_kfet = models.BooleanField(default=False)
|
||||||
# Optional
|
# Optional
|
||||||
comment = models.CharField(max_length=255, blank=True, default="")
|
comment = models.CharField(max_length=255, blank=True, default="")
|
||||||
valid_by = models.ForeignKey(
|
valid_by = models.ForeignKey(
|
||||||
|
@ -754,6 +760,10 @@ class Operation(models.Model):
|
||||||
permissions = (
|
permissions = (
|
||||||
("perform_deposit", "Effectuer une charge"),
|
("perform_deposit", "Effectuer une charge"),
|
||||||
("perform_negative_operations", "Enregistrer des commandes en négatif"),
|
("perform_negative_operations", "Enregistrer des commandes en négatif"),
|
||||||
|
(
|
||||||
|
"perform_liq_reserved",
|
||||||
|
"Effectuer une opération réservé aux adhérents sur LIQ",
|
||||||
|
),
|
||||||
("cancel_old_operations", "Annuler des commandes non récentes"),
|
("cancel_old_operations", "Annuler des commandes non récentes"),
|
||||||
(
|
(
|
||||||
"perform_commented_operations",
|
"perform_commented_operations",
|
||||||
|
|
|
@ -5,6 +5,7 @@ var Account = Backbone.Model.extend({
|
||||||
'name': '',
|
'name': '',
|
||||||
'email': '',
|
'email': '',
|
||||||
'is_cof': '',
|
'is_cof': '',
|
||||||
|
'is_kfet': '',
|
||||||
'promo': '',
|
'promo': '',
|
||||||
'balance': '',
|
'balance': '',
|
||||||
'is_frozen': false,
|
'is_frozen': false,
|
||||||
|
@ -69,7 +70,7 @@ var AccountView = Backbone.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
get_is_cof: function () {
|
get_is_cof: function () {
|
||||||
return this.model.get("is_cof") ? 'COF' : 'Non-COF';
|
return this.model.get("is_cof") ? 'Membre COF' : (this.model.get("is_kfet") ? 'Membre K-Fêt' : 'Non-COF');
|
||||||
},
|
},
|
||||||
|
|
||||||
get_balance: function () {
|
get_balance: function () {
|
||||||
|
|
|
@ -34,10 +34,11 @@ Modification de mes informations
|
||||||
{% include 'kfet/form_snippet.html' with form=account_form %}
|
{% include 'kfet/form_snippet.html' with form=account_form %}
|
||||||
{% include 'kfet/form_snippet.html' with form=frozen_form %}
|
{% include 'kfet/form_snippet.html' with form=frozen_form %}
|
||||||
{% include 'kfet/form_snippet.html' with form=group_form %}
|
{% include 'kfet/form_snippet.html' with form=group_form %}
|
||||||
|
{% include 'kfet/form_snippet.html' with form=cof_form %}
|
||||||
{% include 'kfet/form_snippet.html' with form=pwd_form %}
|
{% include 'kfet/form_snippet.html' with form=pwd_form %}
|
||||||
|
|
||||||
{% include 'kfet/form_authentication_snippet.html' %}
|
{% include 'kfet/form_authentication_snippet.html' %}
|
||||||
{% include 'kfet/form_submit_snippet.html' with value="Mettre à jour" %}
|
{% include 'kfet/form_submit_snippet.html' with value="Mettre à jour" %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
<td class="text-right">Prix</td>
|
<td class="text-right">Prix</td>
|
||||||
<td class="text-right">Stock</td>
|
<td class="text-right">Stock</td>
|
||||||
<td class="text-right" data-sorter="article__is_sold">En vente</td>
|
<td class="text-right" data-sorter="article__is_sold">En vente</td>
|
||||||
|
<td class="text-right" data-sorter="article__is_no_exte">Reservé aux adhérents</td>
|
||||||
<td class="text-right" data-sorter="article__hidden">Affiché</td>
|
<td class="text-right" data-sorter="article__hidden">Affiché</td>
|
||||||
<td class="text-right" data-sorter="shortDate">Dernier inventaire</td>
|
<td class="text-right" data-sorter="shortDate">Dernier inventaire</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -63,6 +64,7 @@
|
||||||
<td class="text-right">{{ article.price }}€</td>
|
<td class="text-right">{{ article.price }}€</td>
|
||||||
<td class="text-right">{{ article.stock }}</td>
|
<td class="text-right">{{ article.stock }}</td>
|
||||||
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
|
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
|
||||||
|
<td class="text-right">{{ article.no_exte | yesno:"Réservé,Non réservé"}}</td>
|
||||||
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
|
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
|
||||||
{% with last_inventory=article.inventory.0 %}
|
{% with last_inventory=article.inventory.0 %}
|
||||||
<td class="text-right" title="{{ last_inventory.at }}">
|
<td class="text-right" title="{{ last_inventory.at }}">
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
<td class="text-right">Prix</td>
|
<td class="text-right">Prix</td>
|
||||||
<td class="text-right">Stock</td>
|
<td class="text-right">Stock</td>
|
||||||
<td class="text-right" data-sorter="article__is_sold">En vente</td>
|
<td class="text-right" data-sorter="article__is_sold">En vente</td>
|
||||||
|
<td class="text-right" data-sorter="article__is_no_exte">Reservé aux adhérents</td>
|
||||||
<td class="text-right" data-sorter="article__hidden">Affiché</td>
|
<td class="text-right" data-sorter="article__hidden">Affiché</td>
|
||||||
<td class="text-right" data-sorter="shortDate">Dernier inventaire</td>
|
<td class="text-right" data-sorter="shortDate">Dernier inventaire</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -111,6 +114,7 @@
|
||||||
<td class="text-right">{{ article.price }}€</td>
|
<td class="text-right">{{ article.price }}€</td>
|
||||||
<td class="text-right">{{ article.stock }}</td>
|
<td class="text-right">{{ article.stock }}</td>
|
||||||
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
|
<td class="text-right">{{ article.is_sold | yesno:"En vente,Non vendu"}}</td>
|
||||||
|
<td class="text-right">{{ article.no_exte | yesno:"Réservé,Non réservé"}}</td>
|
||||||
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
|
<td class="text-right">{{ article.hidden | yesno:"Caché,Affiché" }}</td>
|
||||||
{% with last_inventory=article.inventory.0 %}
|
{% with last_inventory=article.inventory.0 %}
|
||||||
<td class="text-right" title="{{ last_inventory.at }}">
|
<td class="text-right" title="{{ last_inventory.at }}">
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<li><b>Stock:</b> {{ article.stock }}</li>
|
<li><b>Stock:</b> {{ article.stock }}</li>
|
||||||
<li><b>En vente:</b> {{ article.is_sold|yesno|title }}</li>
|
<li><b>En vente:</b> {{ article.is_sold|yesno|title }}</li>
|
||||||
<li><b>Affiché:</b> {{ article.hidden|yesno|title }}</li>
|
<li><b>Affiché:</b> {{ article.hidden|yesno|title }}</li>
|
||||||
|
<li><b>Réservé aux adhérents:</b> {{ article.no_exte|yesno|title }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
@ -160,4 +161,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -397,8 +397,8 @@ $(document).ready(function() {
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
var articles_container = $('#articles_data tbody');
|
var articles_container = $('#articles_data tbody');
|
||||||
var article_category_default_html = '<tr class="category"><td colspan="3"></td></tr>';
|
var article_category_default_html = '<tr class="category"><td colspan="4"></td></tr>';
|
||||||
var article_default_html = '<tr class="article"><td class="name"></td><td class="price"></td><td class="stock"></td></tr>';
|
var article_default_html = '<tr class="article"><td class="name"></td><td class="price"></td><td class="no_exte"></td><td class="stock" style="width: 0;white-space: nowrap;"></td></tr>';
|
||||||
|
|
||||||
function addArticle(article) {
|
function addArticle(article) {
|
||||||
var article_html = $(article_default_html);
|
var article_html = $(article_default_html);
|
||||||
|
@ -411,6 +411,7 @@ $(document).ready(function() {
|
||||||
article_html.addClass('low-stock');
|
article_html.addClass('low-stock');
|
||||||
}
|
}
|
||||||
article_html.find('.price').text(amountToUKF(article['price'], false, false)+' UKF');
|
article_html.find('.price').text(amountToUKF(article['price'], false, false)+' UKF');
|
||||||
|
article_html.find('.no_exte').text(article['no_exte'] ? "Réservé aux adhérents" : "");
|
||||||
var category_html = articles_container
|
var category_html = articles_container
|
||||||
.find('#data-category-'+article['category_id']);
|
.find('#data-category-'+article['category_id']);
|
||||||
if (category_html.length == 0) {
|
if (category_html.length == 0) {
|
||||||
|
|
|
@ -43,7 +43,9 @@
|
||||||
<li>
|
<li>
|
||||||
{% if account.is_cof %}
|
{% if account.is_cof %}
|
||||||
<span title="Réduction de {{ kfet_config.reduction_cof }} % sur tes commandes" data-toggle="tooltip"
|
<span title="Réduction de {{ kfet_config.reduction_cof }} % sur tes commandes" data-toggle="tooltip"
|
||||||
data-placement="right">Adhérent COF</span>
|
data-placement="right">Membre COF</span>
|
||||||
|
{% elif account.is_kfet %}
|
||||||
|
Membre K-Fêt
|
||||||
{% else %}
|
{% else %}
|
||||||
Non-COF
|
Non-COF
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -66,6 +66,7 @@ from kfet.forms import (
|
||||||
CheckoutStatementCreateForm,
|
CheckoutStatementCreateForm,
|
||||||
CheckoutStatementUpdateForm,
|
CheckoutStatementUpdateForm,
|
||||||
CofForm,
|
CofForm,
|
||||||
|
CofKFForm,
|
||||||
ContactForm,
|
ContactForm,
|
||||||
DemandeSoireeForm,
|
DemandeSoireeForm,
|
||||||
FilterHistoryForm,
|
FilterHistoryForm,
|
||||||
|
@ -187,13 +188,17 @@ def account(request):
|
||||||
positive_accounts = Account.objects.filter(balance__gte=0).exclude(trigramme="#13")
|
positive_accounts = Account.objects.filter(balance__gte=0).exclude(trigramme="#13")
|
||||||
negative_accounts = Account.objects.filter(balance__lt=0).exclude(trigramme="#13")
|
negative_accounts = Account.objects.filter(balance__lt=0).exclude(trigramme="#13")
|
||||||
|
|
||||||
return render(request, "kfet/account.html", {
|
return render(
|
||||||
"accounts": accounts,
|
request,
|
||||||
"positive_count": positive_accounts.count(),
|
"kfet/account.html",
|
||||||
"positives_sum": sum(acc.balance for acc in positive_accounts),
|
{
|
||||||
"negative_count": negative_accounts.count(),
|
"accounts": accounts,
|
||||||
"negatives_sum": sum(acc.balance for acc in negative_accounts),
|
"positive_count": positive_accounts.count(),
|
||||||
})
|
"positives_sum": sum(acc.balance for acc in positive_accounts),
|
||||||
|
"negative_count": negative_accounts.count(),
|
||||||
|
"negatives_sum": sum(acc.balance for acc in negative_accounts),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -252,6 +257,11 @@ def account_create(request):
|
||||||
account = trigramme_form.save(data=data)
|
account = trigramme_form.save(data=data)
|
||||||
account_form = AccountNoTriForm(request.POST, instance=account)
|
account_form = AccountNoTriForm(request.POST, instance=account)
|
||||||
account_form.save()
|
account_form.save()
|
||||||
|
was_kfet = account.is_kfet
|
||||||
|
account.cofprofile.is_kfet = cof_form.cleaned_data["is_kfet"]
|
||||||
|
account.cofprofile.save()
|
||||||
|
if account.cofprofile.is_kfet:
|
||||||
|
account.cofprofile.make_adh_kfet(request, was_kfet)
|
||||||
messages.success(request, "Compte créé : %s" % account.trigramme)
|
messages.success(request, "Compte créé : %s" % account.trigramme)
|
||||||
account.send_creation_email()
|
account.send_creation_email()
|
||||||
return redirect("kfet.account.create")
|
return redirect("kfet.account.create")
|
||||||
|
@ -432,6 +442,7 @@ def account_update(request, trigramme):
|
||||||
account_form = AccountForm(instance=account)
|
account_form = AccountForm(instance=account)
|
||||||
group_form = UserGroupForm(instance=account.user)
|
group_form = UserGroupForm(instance=account.user)
|
||||||
frozen_form = AccountFrozenForm(instance=account)
|
frozen_form = AccountFrozenForm(instance=account)
|
||||||
|
cof_form = CofKFForm(instance=account.cofprofile)
|
||||||
pwd_form = AccountPwdForm()
|
pwd_form = AccountPwdForm()
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
@ -439,6 +450,7 @@ def account_update(request, trigramme):
|
||||||
account_form = AccountForm(request.POST, instance=account)
|
account_form = AccountForm(request.POST, instance=account)
|
||||||
group_form = UserGroupForm(request.POST, instance=account.user)
|
group_form = UserGroupForm(request.POST, instance=account.user)
|
||||||
frozen_form = AccountFrozenForm(request.POST, instance=account)
|
frozen_form = AccountFrozenForm(request.POST, instance=account)
|
||||||
|
cof_form = CofKFForm(request.POST, instance=account.cofprofile)
|
||||||
pwd_form = AccountPwdForm(request.POST, account=account)
|
pwd_form = AccountPwdForm(request.POST, account=account)
|
||||||
|
|
||||||
forms = []
|
forms = []
|
||||||
|
@ -455,6 +467,11 @@ def account_update(request, trigramme):
|
||||||
elif group_form.has_changed():
|
elif group_form.has_changed():
|
||||||
warnings.append("statut d'équipe")
|
warnings.append("statut d'équipe")
|
||||||
|
|
||||||
|
if request.user.has_perm("kfet.change_account"):
|
||||||
|
forms.append(cof_form)
|
||||||
|
elif cof_form.has_changed():
|
||||||
|
warnings.append("adhésion kfet")
|
||||||
|
|
||||||
# Il ne faut pas valider `pwd_form` si elle est inchangée
|
# Il ne faut pas valider `pwd_form` si elle est inchangée
|
||||||
if pwd_form.has_changed():
|
if pwd_form.has_changed():
|
||||||
if self_update or request.user.has_perm("kfet.change_account_password"):
|
if self_update or request.user.has_perm("kfet.change_account_password"):
|
||||||
|
@ -471,8 +488,11 @@ def account_update(request, trigramme):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if all(form.is_valid() for form in forms):
|
if all(form.is_valid() for form in forms):
|
||||||
|
was_kfet = account.is_kfet
|
||||||
for form in forms:
|
for form in forms:
|
||||||
form.save()
|
form.save()
|
||||||
|
if account.is_kfet:
|
||||||
|
account.cofprofile.make_adh_kfet(request, was_kfet)
|
||||||
|
|
||||||
if len(warnings):
|
if len(warnings):
|
||||||
messages.warning(
|
messages.warning(
|
||||||
|
@ -504,6 +524,7 @@ def account_update(request, trigramme):
|
||||||
"frozen_form": frozen_form,
|
"frozen_form": frozen_form,
|
||||||
"group_form": group_form,
|
"group_form": group_form,
|
||||||
"pwd_form": pwd_form,
|
"pwd_form": pwd_form,
|
||||||
|
"cof_form": cof_form,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -988,6 +1009,7 @@ def account_read_json(request, trigramme):
|
||||||
"name": account.name,
|
"name": account.name,
|
||||||
"email": account.email,
|
"email": account.email,
|
||||||
"is_cof": account.is_cof,
|
"is_cof": account.is_cof,
|
||||||
|
"is_kfet": account.is_kfet,
|
||||||
"promo": account.promo,
|
"promo": account.promo,
|
||||||
"balance": account.balance,
|
"balance": account.balance,
|
||||||
"is_frozen": account.is_frozen,
|
"is_frozen": account.is_frozen,
|
||||||
|
@ -1164,6 +1186,22 @@ def kpsul_perform_operations(request):
|
||||||
if is_addcost and operation.article.category.has_addcost:
|
if is_addcost and operation.article.category.has_addcost:
|
||||||
operation.addcost_amount /= cof_grant_divisor
|
operation.addcost_amount /= cof_grant_divisor
|
||||||
operation.amount = operation.amount / cof_grant_divisor
|
operation.amount = operation.amount / cof_grant_divisor
|
||||||
|
if not on_acc.is_cof and not on_acc.is_kfet and operation.article.no_exte:
|
||||||
|
if on_acc.is_cash:
|
||||||
|
required_perms.add("kfet.perform_liq_reserved")
|
||||||
|
else:
|
||||||
|
data["errors"].append(
|
||||||
|
{
|
||||||
|
"code": "reserved",
|
||||||
|
"message": (
|
||||||
|
"L'article "
|
||||||
|
+ operation.article.name
|
||||||
|
+ " est réservé aux adhérents du COF, or "
|
||||||
|
+ on_acc.trigramme
|
||||||
|
+ " ne l'est pas"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
to_articles_stocks[operation.article] -= operation.article_nb
|
to_articles_stocks[operation.article] -= operation.article_nb
|
||||||
else:
|
else:
|
||||||
if on_acc.is_cash:
|
if on_acc.is_cash:
|
||||||
|
@ -1221,6 +1259,7 @@ def kpsul_perform_operations(request):
|
||||||
operationgroup.valid_by = request.user.profile.account_kfet
|
operationgroup.valid_by = request.user.profile.account_kfet
|
||||||
# Filling cof status for statistics
|
# Filling cof status for statistics
|
||||||
operationgroup.is_cof = on_acc.is_cof
|
operationgroup.is_cof = on_acc.is_cof
|
||||||
|
operationgroup.is_kfet = on_acc.is_kfet
|
||||||
|
|
||||||
# Starting transaction to ensure data consistency
|
# Starting transaction to ensure data consistency
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
@ -1271,6 +1310,7 @@ def kpsul_perform_operations(request):
|
||||||
"checkout__name": operationgroup.checkout.name,
|
"checkout__name": operationgroup.checkout.name,
|
||||||
"at": operationgroup.at,
|
"at": operationgroup.at,
|
||||||
"is_cof": operationgroup.is_cof,
|
"is_cof": operationgroup.is_cof,
|
||||||
|
"is_kfet": operationgroup.is_kfet,
|
||||||
"comment": operationgroup.comment,
|
"comment": operationgroup.comment,
|
||||||
"valid_by__trigramme": (
|
"valid_by__trigramme": (
|
||||||
operationgroup.valid_by and operationgroup.valid_by.trigramme or None
|
operationgroup.valid_by and operationgroup.valid_by.trigramme or None
|
||||||
|
@ -1486,7 +1526,7 @@ def cancel_operations(request):
|
||||||
# Sort objects by pk to get deterministic responses.
|
# Sort objects by pk to get deterministic responses.
|
||||||
opegroups_pk = [opegroup.pk for opegroup in to_groups_amounts]
|
opegroups_pk = [opegroup.pk for opegroup in to_groups_amounts]
|
||||||
opegroups = (
|
opegroups = (
|
||||||
OperationGroup.objects.values("id", "amount", "is_cof")
|
OperationGroup.objects.values("id", "amount", "is_cof", "is_kfet")
|
||||||
.filter(pk__in=opegroups_pk)
|
.filter(pk__in=opegroups_pk)
|
||||||
.order_by("pk")
|
.order_by("pk")
|
||||||
)
|
)
|
||||||
|
@ -1715,6 +1755,7 @@ def kpsul_articles_data(request):
|
||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"price",
|
"price",
|
||||||
|
"no_exte",
|
||||||
"stock",
|
"stock",
|
||||||
"category_id",
|
"category_id",
|
||||||
"category__name",
|
"category__name",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue