comments member views

This commit is contained in:
Pierre-antoine Comby 2020-08-18 18:19:39 +02:00
parent f324965f1a
commit 60b1cdbcf8
2 changed files with 61 additions and 34 deletions

View File

@ -65,6 +65,18 @@ class ProfileForm(forms.ModelForm):
exclude = ('user', 'email_confirmed', 'registration_valid', ) exclude = ('user', 'email_confirmed', 'registration_valid', )
class ImageForm(forms.Form):
"""
Form used for the js interface for profile picture
"""
image = forms.ImageField(required=False,
label=_('select an image'),
help_text=_('Maximal size: 2MB'))
x = forms.FloatField(widget=forms.HiddenInput())
y = forms.FloatField(widget=forms.HiddenInput())
width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput())
class ClubForm(forms.ModelForm): class ClubForm(forms.ModelForm):
def clean(self): def clean(self):
cleaned_data = super().clean() cleaned_data = super().clean()

View File

@ -3,8 +3,8 @@
import io import io
from datetime import timedelta, date from datetime import timedelta, date
from PIL import Image from PIL import Image
from django.conf import settings from django.conf import settings
from django.contrib.auth import logout from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
@ -18,8 +18,8 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, UpdateView, TemplateView from django.views.generic import DetailView, UpdateView, TemplateView
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from django_tables2.views import SingleTableView from django_tables2.views import SingleTableView
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from note.forms import ImageForm
from note.models import Alias, NoteUser from note.models import Alias, NoteUser
from note.models.transactions import Transaction, SpecialTransaction from note.models.transactions import Transaction, SpecialTransaction
from note.tables import HistoryTable, AliasTable from note.tables import HistoryTable, AliasTable
@ -28,7 +28,8 @@ from permission.backends import PermissionBackend
from permission.models import Role from permission.models import Role
from permission.views import ProtectQuerysetMixin, ProtectedCreateView from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm, MembershipRolesForm from .forms import UserForm, ProfileForm, ImageForm, ClubForm, MembershipForm,\
CustomAuthenticationForm, MembershipRolesForm,
from .models import Club, Membership from .models import Club, Membership
from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable from .tables import ClubTable, UserTable, MembershipTable, ClubManagerTable
@ -49,6 +50,7 @@ class CustomLoginView(LoginView):
class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
""" """
Update the user information. Update the user information.
On this view both `:models:member.User` and `:models:member.Profile` are updated through forms
""" """
model = User model = User
form_class = UserForm form_class = UserForm
@ -77,14 +79,11 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
return context return context
def form_valid(self, form): def form_valid(self, form):
new_username = form.data['username'] """
# Si l'utilisateur cherche à modifier son pseudo, le nouveau pseudo ne doit pas être proche d'un alias existant Check if ProfileForm is correct
note = NoteUser.objects.filter( then check if username is not already taken by someone else or by the user,
alias__normalized_name=Alias.normalize(new_username)) then check if email has changed, and if so ask for new validation.
if note.exists() and note.get().user != self.object: """
form.add_error('username',
_("An alias with a similar name already exists."))
return super().form_invalid(form)
profile_form = ProfileForm( profile_form = ProfileForm(
data=self.request.POST, data=self.request.POST,
@ -93,31 +92,35 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
profile_form.full_clean() profile_form.full_clean()
if not profile_form.is_valid(): if not profile_form.is_valid():
return super().form_invalid(form) return super().form_invalid(form)
new_username = form.data['username'] new_username = form.data['username']
# Check if the new username is not already taken as an alias of someone else.
note = NoteUser.objects.filter(
alias__normalized_name=Alias.normalize(new_username))
if note.exists() and note.get().user != self.object:
form.add_error('username',
_("An alias with a similar name already exists."))
return super().form_invalid(form)
# Check if the username is one of user's aliases.
alias = Alias.objects.filter(name=new_username) alias = Alias.objects.filter(name=new_username)
# Si le nouveau pseudo n'est pas un de nos alias,
# on supprime éventuellement un alias similaire pour le remplacer
if not alias.exists(): if not alias.exists():
similar = Alias.objects.filter( similar = Alias.objects.filter(
normalized_name=Alias.normalize(new_username)) normalized_name=Alias.normalize(new_username))
if similar.exists(): if similar.exists():
similar.delete() similar.delete()
olduser = User.objects.get(pk=form.instance.pk) olduser = User.objects.get(pk=form.instance.pk)
user = form.save(commit=False) user = form.save(commit=False)
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
user.save()
if olduser.email != user.email: if olduser.email != user.email:
# If the user changed her/his email, then it is unvalidated and a confirmation link is sent. # If the user changed her/his email, then it is unvalidated and a confirmation link is sent.
user.profile.email_confirmed = False user.profile.email_confirmed = False
user.profile.save()
user.profile.send_email_validation_link() user.profile.send_email_validation_link()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
user.save()
return super().form_valid(form) return super().form_valid(form)
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
@ -127,7 +130,7 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView): class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
""" """
Affiche les informations sur un utilisateur, sa note, ses clubs... Display all information about a user.
""" """
model = User model = User
context_object_name = "user_object" context_object_name = "user_object"
@ -141,6 +144,9 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
return super().get_queryset().filter(profile__registration_valid=True) return super().get_queryset().filter(profile__registration_valid=True)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""
Add history of transaction and list of membership of user.
"""
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
user = context['user_object'] user = context['user_object']
history_list = \ history_list = \
@ -356,22 +362,26 @@ class ClubDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
extra_context = {"title": _("Club detail")} extra_context = {"title": _("Club detail")}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""
Add list of managers (peoples with Permission/Roles in this club), history of transactions and members list
"""
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
club = context["club"] club = context["club"]
if PermissionBackend.check_perm(self.request.user, "member.change_club_membership_start", club): if PermissionBackend.check_perm(self.request.user, "member.change_club_membership_start", club):
club.update_membership_dates() club.update_membership_dates()
# managers list
managers = Membership.objects.filter(club=self.object, roles__name="Bureau de club")\ managers = Membership.objects.filter(club=self.object, roles__name="Bureau de club")\
.order_by('user__last_name').all() .order_by('user__last_name').all()
context["managers"] = ClubManagerTable(data=managers, prefix="managers-") context["managers"] = ClubManagerTable(data=managers, prefix="managers-")
# transaction history
club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\ club_transactions = Transaction.objects.all().filter(Q(source=club.note) | Q(destination=club.note))\
.filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\ .filter(PermissionBackend.filter_queryset(self.request.user, Transaction, "view"))\
.order_by('-created_at') .order_by('-created_at')
history_table = HistoryTable(club_transactions, prefix="history-") history_table = HistoryTable(club_transactions, prefix="history-")
history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1)) history_table.paginate(per_page=20, page=self.request.GET.get('history-page', 1))
context['history_list'] = history_table context['history_list'] = history_table
# member list
club_member = Membership.objects.filter( club_member = Membership.objects.filter(
club=club, club=club,
date_end__gte=date.today(), date_end__gte=date.today(),
@ -469,15 +479,19 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
) )
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""
Membership can be created, or renewed
In case of creation the url is /club/<club_pk>/add_member
For a renewal it will be `club/renew_membership/<pk>`
"""
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
form = context['form'] form = context['form']
if "club_pk" in self.kwargs: if "club_pk" in self.kwargs: # We create a new membership.
# We create a new membership.
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\ club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view"))\
.get(pk=self.kwargs["club_pk"], weiclub=None) .get(pk=self.kwargs["club_pk"], weiclub=None)
form.fields['credit_amount'].initial = club.membership_fee_paid form.fields['credit_amount'].initial = club.membership_fee_paid
# Ensure that the user is member of the parent club and all its the family tree.
c = club c = club
clubs_renewal = [] clubs_renewal = []
additional_fee_renewal = 0 additional_fee_renewal = 0
@ -498,8 +512,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
kfet = Club.objects.get(name="Kfet") kfet = Club.objects.get(name="Kfet")
fee += kfet.membership_fee_paid fee += kfet.membership_fee_paid
context["total_fee"] = "{:.02f}".format(fee / 100, ) context["total_fee"] = "{:.02f}".format(fee / 100, )
else: else: # This is a renewal. Fields can be pre-completed.
# This is a renewal. Fields can be pre-completed.
context["renewal"] = True context["renewal"] = True
old_membership = self.get_queryset().get(pk=self.kwargs["pk"]) old_membership = self.get_queryset().get(pk=self.kwargs["pk"])
@ -511,6 +524,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
additional_fee_renewal = 0 additional_fee_renewal = 0
while c.parent_club is not None: while c.parent_club is not None:
c = c.parent_club c = c.parent_club
# check if a valid membership exists for the parent club
if c.membership_start and not Membership.objects.filter( if c.membership_start and not Membership.objects.filter(
club=c, club=c,
user=user, user=user,
@ -529,7 +543,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
form.fields['last_name'].initial = user.last_name form.fields['last_name'].initial = user.last_name
form.fields['first_name'].initial = user.first_name form.fields['first_name'].initial = user.first_name
# If this is a renewal of a BDE membership, Société générale can pays, if it is not yet done # If this is a renewal of a BDE membership, Société générale can pays, if it has not been already done.
if (club.name != "BDE" and club.name != "Kfet") or user.profile.soge: if (club.name != "BDE" and club.name != "Kfet") or user.profile.soge:
del form.fields['soge'] del form.fields['soge']
else: else:
@ -559,11 +573,11 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
Create membership, check that all is good, make transactions Create membership, check that all is good, make transactions
""" """
# Get the club that is concerned by the membership # Get the club that is concerned by the membership
if "club_pk" in self.kwargs: if "club_pk" in self.kwargs: # get from url of new membership
club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view")) \ club = Club.objects.filter(PermissionBackend.filter_queryset(self.request.user, Club, "view")) \
.get(pk=self.kwargs["club_pk"]) .get(pk=self.kwargs["club_pk"])
user = form.instance.user user = form.instance.user
else: else: # get from url for renewal
old_membership = self.get_queryset().get(pk=self.kwargs["pk"]) old_membership = self.get_queryset().get(pk=self.kwargs["pk"])
club = old_membership.club club = old_membership.club
user = old_membership.user user = old_membership.user
@ -572,6 +586,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
# Get form data # Get form data
credit_type = form.cleaned_data["credit_type"] credit_type = form.cleaned_data["credit_type"]
# but with this way users can customize their section as they want.
credit_amount = form.cleaned_data["credit_amount"] credit_amount = form.cleaned_data["credit_amount"]
last_name = form.cleaned_data["last_name"] last_name = form.cleaned_data["last_name"]
first_name = form.cleaned_data["first_name"] first_name = form.cleaned_data["first_name"]
@ -589,6 +604,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
fee = 0 fee = 0
c = club c = club
# collect the fees required to be paid
while c is not None and c.membership_start: while c is not None and c.membership_start:
if not Membership.objects.filter( if not Membership.objects.filter(
club=c, club=c,
@ -632,9 +648,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, ProtectedCreateView):
# Now, all is fine, the membership can be created. # Now, all is fine, the membership can be created.
if club.name == "BDE" or club.name == "Kfet": if club.name == "BDE" or club.name == "Kfet":
# When we renew the BDE membership, we update the profile section. # When we renew the BDE membership, we update the profile section
# We could automate that and remove the section field from the Profile model, # that should happens at least once a year.
# but with this way users can customize their section as they want.
user.profile.section = user.profile.section_generated user.profile.section = user.profile.section_generated
user.profile.save() user.profile.save()