Adhere to parent clubs automatically, adhere to Kfet automatically when registering to the WEI

This commit is contained in:
Yohann D'ANELLO 2020-08-04 20:04:41 +02:00
parent 358691aaa9
commit a096dc4427
16 changed files with 588 additions and 266 deletions

View File

@ -10,6 +10,7 @@ from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.template import loader from django.template import loader
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -301,13 +302,34 @@ class Membership(models.Model):
else: else:
return self.date_start.toordinal() <= datetime.datetime.now().toordinal() return self.date_start.toordinal() <= datetime.datetime.now().toordinal()
def renew(self):
if Membership.objects.filter(
user=self.user,
club=self.club,
date_start__gte=self.club.membership_start,
).exists():
# Membership is already renewed
return
new_membership = Membership(
user=self.user,
club=self.club,
date_start=max(self.date_end + datetime.timedelta(days=1), self.club.membership_start),
)
from django.forms import model_to_dict
if hasattr(self, '_force_renew_parent') and self._force_renew_parent:
new_membership._force_renew_parent = True
if hasattr(self, '_soge') and self._soge:
new_membership._soge = True
if hasattr(self, '_force_save') and self._force_save:
new_membership._force_save = True
new_membership.save()
new_membership.roles.set(self.roles.all())
new_membership.save()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
""" """
Calculate fee and end date before saving the membership and creating the transaction if needed. Calculate fee and end date before saving the membership and creating the transaction if needed.
""" """
if self.club.parent_club is not None:
if not Membership.objects.filter(user=self.user, club=self.club.parent_club).exists():
raise ValidationError(_('User is not a member of the parent club') + ' ' + self.club.parent_club.name)
if self.pk: if self.pk:
for role in self.roles.all(): for role in self.roles.all():
@ -327,6 +349,43 @@ class Membership(models.Model):
).exists(): ).exists():
raise ValidationError(_('User is already a member of the club')) raise ValidationError(_('User is already a member of the club'))
if self.club.parent_club is not None:
if not Membership.objects.filter(
user=self.user,
club=self.club.parent_club,
date_start__gte=self.club.parent_club.membership_start,
).exists():
if hasattr(self, '_force_renew_parent') and self._force_renew_parent:
parent_membership = Membership.objects.filter(
user=self.user,
club=self.club.parent_club,
).order_by("-date_start")
if parent_membership.exists():
# Renew the previous membership of the parent club
parent_membership = parent_membership.first()
parent_membership._force_renew_parent = True
if hasattr(self, '_soge'):
parent_membership._soge = True
if hasattr(self, '_force_save'):
parent_membership._force_save = True
parent_membership.renew()
else:
# Create a new membership in the parent club
parent_membership = Membership(
user=self.user,
club=self.club.parent_club,
date_start=self.date_start,
)
parent_membership._force_renew_parent = True
if hasattr(self, '_soge'):
parent_membership._soge = True
if hasattr(self, '_force_save'):
parent_membership._force_save = True
parent_membership.save()
else:
raise ValidationError(_('User is not a member of the parent club')
+ ' ' + self.club.parent_club.name)
if self.user.profile.paid: if self.user.profile.paid:
self.fee = self.club.membership_fee_paid self.fee = self.club.membership_fee_paid
else: else:
@ -360,8 +419,9 @@ class Membership(models.Model):
reason="Adhésion " + self.club.name, reason="Adhésion " + self.club.name,
) )
transaction._force_save = True transaction._force_save = True
print(hasattr(self, '_soge')) if hasattr(self, '_soge') and "treasury" in settings.INSTALLED_APPS\
if hasattr(self, '_soge') and "treasury" in settings.INSTALLED_APPS: and (self.club.name == "BDE" or self.club.name == "Kfet" or
("wei" in settings.INSTALLED_APPS and hasattr(self.club, "weiclub") and self.club.weiclub)):
# If the soge pays, then the transaction is unvalidated in a first time, then submitted for control # If the soge pays, then the transaction is unvalidated in a first time, then submitted for control
# to treasurers. # to treasurers.
transaction.valid = False transaction.valid = False

View File

@ -442,6 +442,16 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
.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
c = club
clubs_renewal = []
additional_fee_renewal = 0
while c.parent_club is not None:
c = c.parent_club
clubs_renewal.append(c)
additional_fee_renewal += c.membership_fee_paid if user.profile.paid else c.membership_fee_unpaid
context["clubs_renewal"] = clubs_renewal
context["additional_fee_renewal"] = additional_fee_renewal
# If the concerned club is the BDE, then we add the option that Société générale pays the membership. # If the concerned club is the BDE, then we add the option that Société générale pays the membership.
if club.name != "BDE": if club.name != "BDE":
del form.fields['soge'] del form.fields['soge']
@ -454,25 +464,53 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
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
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
c = club
clubs_renewal = []
additional_fee_renewal = 0
while c.parent_club is not None:
c = c.parent_club
if not Membership.objects.filter(
club=c,
user=user,
date_start__gte=c.membership_start,
).exists():
clubs_renewal.append(c)
additional_fee_renewal += c.membership_fee_paid if user.profile.paid else c.membership_fee_unpaid
context["clubs_renewal"] = clubs_renewal
context["additional_fee_renewal"] = additional_fee_renewal
form.fields['user'].initial = user form.fields['user'].initial = user
form.fields['user'].disabled = True form.fields['user'].disabled = True
form.fields['date_start'].initial = old_membership.date_end + timedelta(days=1) form.fields['date_start'].initial = old_membership.date_end + timedelta(days=1)
form.fields['credit_amount'].initial = club.membership_fee_paid if user.profile.paid \ form.fields['credit_amount'].initial = (club.membership_fee_paid if user.profile.paid
else club.membership_fee_unpaid else club.membership_fee_unpaid) + additional_fee_renewal
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 is not yet done
if club.name != "BDE" 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:
fee = 0 fee = 0
bde = Club.objects.get(name="BDE") bde = Club.objects.get(name="BDE")
if not Membership.objects.filter(
club=bde,
user=user,
date_start__gte=bde.membership_start,
).exists():
fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid
kfet = Club.objects.get(name="Kfet") kfet = Club.objects.get(name="Kfet")
if not Membership.objects.filter(
club=kfet,
user=user,
date_start__gte=bde.membership_start,
).exists():
fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
context["total_fee"] = "{:.02f}".format(fee / 100, ) context["total_fee"] = "{:.02f}".format(fee / 100, )
@ -502,7 +540,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
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"]
bank = form.cleaned_data["bank"] bank = form.cleaned_data["bank"]
soge = form.cleaned_data["soge"] and not user.profile.soge and club.name == "BDE" soge = form.cleaned_data["soge"] and not user.profile.soge and (club.name == "BDE" or club.name == "Kfet")
# If Société générale pays, then we store that information but the payment must be controlled by treasurers # If Société générale pays, then we store that information but the payment must be controlled by treasurers
# later. The membership transaction will be invalidated. # later. The membership transaction will be invalidated.
@ -513,10 +551,17 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
if credit_type is None: if credit_type is None:
credit_amount = 0 credit_amount = 0
if user.profile.paid: fee = 0
fee = club.membership_fee_paid c = club
else: while c is not None:
fee = club.membership_fee_unpaid if not Membership.objects.filter(
club=c,
user=user,
date_start__gte=c.membership_start,
).exists():
fee += c.membership_fee_paid if user.profile.paid else c.membership_fee_unpaid
c = c.parent_club
if user.note.balance + credit_amount < fee and not Membership.objects.filter( if user.note.balance + credit_amount < fee and not Membership.objects.filter(
club__name="Kfet", club__name="Kfet",
user=user, user=user,
@ -524,22 +569,11 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
date_end__gte=datetime.now().date(), date_end__gte=datetime.now().date(),
).exists(): ).exists():
# Users without a valid Kfet membership can't have a negative balance. # Users without a valid Kfet membership can't have a negative balance.
# Club 2 = Kfet (hard-code :'( )
# TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note # TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note
form.add_error('user', form.add_error('user',
_("This user don't have enough money to join this club, and can't have a negative balance.")) _("This user don't have enough money to join this club, and can't have a negative balance."))
return super().form_invalid(form) return super().form_invalid(form)
if club.parent_club is not None:
if not Membership.objects.filter(
user=form.instance.user,
club=club.parent_club,
date_start__lte=form.instance.date_start,
date_end__gte=form.instance.date_start,
).exists():
form.add_error('user', _('User is not a member of the parent club') + ' ' + club.parent_club.name)
return super().form_invalid(form)
if Membership.objects.filter( if Membership.objects.filter(
user=form.instance.user, user=form.instance.user,
club=club, club=club,
@ -561,7 +595,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
# Now, all is fine, the membership can be created. # Now, all is fine, the membership can be created.
if club.name == "BDE": 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, # We could automate that and remove the section field from the Profile model,
# but with this way users can customize their section as they want. # but with this way users can customize their section as they want.
@ -593,6 +627,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
transaction._force_save = True transaction._force_save = True
transaction.save() transaction.save()
form.instance._force_renew_parent = True
ret = super().form_valid(form) ret = super().form_valid(form)
member_role = Role.objects.filter(name="Membre de club").all() member_role = Role.objects.filter(name="Membre de club").all()
@ -603,22 +639,29 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
# If Société générale pays, then we assume that this is the BDE membership, and we auto-renew the # If Société générale pays, then we assume that this is the BDE membership, and we auto-renew the
# Kfet membership. # Kfet membership.
if soge: if soge:
# If not already done, create BDE and Kfet memberships
bde = Club.objects.get(name="BDE")
kfet = Club.objects.get(name="Kfet") kfet = Club.objects.get(name="Kfet")
kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
soge_clubs = [bde, kfet]
for club in soge_clubs:
fee = club.membership_fee_paid if user.profile.paid else club.membership_fee_unpaid
# Get current membership, to get the end date # Get current membership, to get the end date
old_membership = Membership.objects.filter( old_membership = Membership.objects.filter(
club__name="Kfet", club=club,
user=user, user=user,
date_start__lte=datetime.today(), ).order_by("-date_start")
date_end__gte=datetime.today(),
) if old_membership.filter(date_start__gte=club.membership_start).exists():
# Membership is already renewed
continue
membership = Membership( membership = Membership(
club=kfet, club=club,
user=user, user=user,
fee=kfet_fee, fee=fee,
date_start=old_membership.get().date_end + timedelta(days=1) date_start=max(old_membership.first().date_end + timedelta(days=1), club.membership_start)
if old_membership.exists() else form.instance.date_start, if old_membership.exists() else form.instance.date_start,
) )
membership._force_save = True membership._force_save = True

View File

@ -353,18 +353,13 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
qs = super().get_queryset() qs = super().get_queryset()
if "search" in self.request.GET: if "search" in self.request.GET:
pattern = self.request.GET["search"] pattern = self.request.GET["search"]
if pattern:
if not pattern:
return qs.none()
qs = qs.filter( qs = qs.filter(
Q(user__first_name__iregex=pattern) Q(user__first_name__iregex=pattern)
| Q(user__last_name__iregex=pattern) | Q(user__last_name__iregex=pattern)
| Q(user__note__alias__name__iregex="^" + pattern) | Q(user__note__alias__name__iregex="^" + pattern)
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern)) | Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
) )
else:
qs = qs.none()
if "valid" in self.request.GET: if "valid" in self.request.GET:
q = Q(credit_transaction=None) q = Q(credit_transaction=None)

View File

@ -6,6 +6,8 @@ from django.contrib.auth.models import User
from django.db.models import Q from django.db.models import Q
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial
from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget
from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole
@ -75,6 +77,35 @@ class WEIMembershipForm(forms.ModelForm):
widget=CheckboxSelectMultiple(), widget=CheckboxSelectMultiple(),
) )
credit_type = forms.ModelChoiceField(
queryset=NoteSpecial.objects.all(),
label=_("Credit type"),
empty_label=_("No credit"),
required=False,
)
credit_amount = forms.IntegerField(
label=_("Credit amount"),
widget=AmountInput(),
initial=0,
required=False,
)
last_name = forms.CharField(
label=_("Last name"),
required=False,
)
first_name = forms.CharField(
label=_("First name"),
required=False,
)
bank = forms.CharField(
label=_("Bank"),
required=False,
)
def clean(self): def clean(self):
cleaned_data = super().clean() cleaned_data = super().clean()
if cleaned_data["team"] is not None and cleaned_data["team"].bus != cleaned_data["bus"]: if cleaned_data["team"] is not None and cleaned_data["team"].bus != cleaned_data["bus"]:

View File

@ -3,9 +3,13 @@
import django_tables2 as tables import django_tables2 as tables
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_tables2 import A from django_tables2 import A
from note_kfet.middlewares import get_current_authenticated_user
from permission.backends import PermissionBackend
from .models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership from .models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership
@ -53,8 +57,12 @@ class WEIRegistrationTable(tables.Table):
verbose_name=_("Validate"), verbose_name=_("Validate"),
text=_("Validate"), text=_("Validate"),
attrs={ attrs={
'th': {
'id': 'validate-membership-header'
},
'a': { 'a': {
'class': 'btn btn-success' 'class': 'btn btn-success',
'data-type': 'validate-membership'
} }
} }
) )
@ -65,12 +73,33 @@ class WEIRegistrationTable(tables.Table):
verbose_name=_("delete"), verbose_name=_("delete"),
text=_("Delete"), text=_("Delete"),
attrs={ attrs={
'th': {
'id': 'delete-membership-header'
},
'a': { 'a': {
'class': 'btn btn-danger' 'class': 'btn btn-danger',
'data-type': 'delete-membership'
} }
}, },
) )
def render_validate(self, record):
if PermissionBackend.check_perm(get_current_authenticated_user(), "wei.add_weimembership", WEIMembership(
club=record.wei,
user=record.user,
date_start=timezone.now().date(),
date_end=timezone.now().date(),
fee=0,
registration=record,
)):
return _("Validate")
return format_html("<span class='no-perm'></span>")
def render_delete(self, record):
if PermissionBackend.check_perm(get_current_authenticated_user(), "wei.delete_weimembership", record):
return _("Delete")
return format_html("<span class='no-perm'></span>")
class Meta: class Meta:
attrs = { attrs = {
'class': 'table table-condensed table-striped table-hover' 'class': 'table table-condensed table-striped table-hover'

View File

@ -24,10 +24,11 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import BaseFormView, DeleteView from django.views.generic.edit import BaseFormView, DeleteView
from django_tables2 import SingleTableView from django_tables2 import SingleTableView
from member.models import Membership, Club from member.models import Membership, Club
from note.models import Transaction, NoteClub, Alias from note.models import Transaction, NoteClub, Alias, SpecialTransaction, NoteSpecial
from note.tables import HistoryTable from note.tables import HistoryTable
from note_kfet.settings import BASE_DIR from note_kfet.settings import BASE_DIR
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.models import Role
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
from .forms.registration import WEIChooseBusForm from .forms.registration import WEIChooseBusForm
@ -666,6 +667,15 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
survey = CurrentSurvey(self.object) survey = CurrentSurvey(self.object)
if not survey.is_complete(): if not survey.is_complete():
return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk}) return reverse_lazy("wei:wei_survey", kwargs={"pk": self.object.pk})
if PermissionBackend.check_perm(self.request.user, "wei.add_weimembership", WEIMembership(
club=self.object.wei,
user=self.object.user,
date_start=timezone.now().date(),
date_end=timezone.now().date(),
fee=0,
registration=self.object,
)):
return reverse_lazy("wei:validate_registration", kwargs={"pk": self.object.pk})
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk}) return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})
@ -723,19 +733,55 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
if survey.information.valid: if survey.information.valid:
context["suggested_bus"] = survey.information.get_selected_bus() context["suggested_bus"] = survey.information.get_selected_bus()
context["club"] = registration.wei context["club"] = registration.wei
context["fee"] = registration.wei.membership_fee_paid if registration.user.profile.paid \
else registration.wei.membership_fee_unpaid kfet = registration.wei.parent_club
bde = kfet.parent_club
context["kfet_member"] = Membership.objects.filter( context["kfet_member"] = Membership.objects.filter(
club__name="Kfet", club__name=kfet.name,
user=registration.user, user=registration.user,
date_start__gte=registration.wei.parent_club.membership_start, date_start__gte=kfet.membership_start,
).exists() ).exists()
context["bde_member"] = Membership.objects.filter(
club__name=bde.name,
user=registration.user,
date_start__gte=bde.membership_start,
).exists()
fee = registration.wei.membership_fee_paid if registration.user.profile.paid \
else registration.wei.membership_fee_unpaid
if not context["kfet_member"]:
fee += kfet.membership_fee_paid if registration.user.profile.paid \
else kfet.membership_fee_unpaid
if not context["bde_member"]:
fee += bde.membership_fee_paid if registration.user.profile.paid \
else bde.membership_fee_unpaid
context["fee"] = fee
form = context["form"]
if registration.soge_credit:
form.fields["credit_amount"].initial = fee
else:
form.fields["credit_amount"].initial = max(0, fee - registration.user.note.balance)
return context return context
def get_form(self, form_class=None): def get_form(self, form_class=None):
form = super().get_form(form_class) form = super().get_form(form_class)
registration = WEIRegistration.objects.get(pk=self.kwargs["pk"]) registration = WEIRegistration.objects.get(pk=self.kwargs["pk"])
form.fields["last_name"].initial = registration.user.last_name
form.fields["first_name"].initial = registration.user.first_name
if registration.soge_credit:
form.fields["credit_type"].disabled = True
form.fields["credit_type"].initial = NoteSpecial.objects.get(special_type="Virement bancaire")
form.fields["credit_amount"].disabled = True
form.fields["last_name"].disabled = True
form.fields["first_name"].disabled = True
form.fields["bank"].disabled = True
form.fields["bank"].initial = "Société générale"
form.fields["bus"].widget.attrs["api_url"] = "/api/wei/bus/?wei=" + str(registration.wei.pk) form.fields["bus"].widget.attrs["api_url"] = "/api/wei/bus/?wei=" + str(registration.wei.pk)
if registration.first_year: if registration.first_year:
# Use the results of the survey to fill initial data # Use the results of the survey to fill initial data
@ -750,7 +796,7 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
if "preferred_bus_pk" in information and len(information["preferred_bus_pk"]) == 1: if "preferred_bus_pk" in information and len(information["preferred_bus_pk"]) == 1:
form["bus"].initial = Bus.objects.get(pk=information["preferred_bus_pk"][0]) form["bus"].initial = Bus.objects.get(pk=information["preferred_bus_pk"][0])
if "preferred_team_pk" in information and len(information["preferred_team_pk"]) == 1: if "preferred_team_pk" in information and len(information["preferred_team_pk"]) == 1:
form["team"].initial = Bus.objects.get(pk=information["preferred_team_pk"][0]) form["team"].initial = BusTeam.objects.get(pk=information["preferred_team_pk"][0])
if "preferred_roles_pk" in information: if "preferred_roles_pk" in information:
form["roles"].initial = WEIRole.objects.filter( form["roles"].initial = WEIRole.objects.filter(
Q(pk__in=information["preferred_roles_pk"]) | Q(name="Adhérent WEI") Q(pk__in=information["preferred_roles_pk"]) | Q(name="Adhérent WEI")
@ -770,38 +816,80 @@ class WEIValidateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Crea
membership.club = club membership.club = club
membership.date_start = min(date.today(), club.date_start) membership.date_start = min(date.today(), club.date_start)
membership.registration = registration membership.registration = registration
# Force the membership of the clubs BDE and Kfet
membership._force_renew_parent = True
if user.profile.paid: if user.profile.paid:
fee = club.membership_fee_paid fee = club.membership_fee_paid
else: else:
fee = club.membership_fee_unpaid fee = club.membership_fee_unpaid
if not registration.soge_credit and user.note.balance < fee: kfet = club.parent_club
# Users must have money before registering to the WEI. bde = kfet.parent_club
# TODO Send a notification to the user (with a mail?) to tell her/him to credit her/his note
form.add_error('bus', kfet_member = Membership.objects.filter(
_("This user don't have enough money to join this club, and can't have a negative balance.")) club__name=kfet.name,
return super().form_invalid(form) user=registration.user,
date_start__gte=kfet.membership_start,
).exists()
bde_member = Membership.objects.filter(
club__name=bde.name,
user=registration.user,
date_start__gte=bde.membership_start,
).exists()
if not kfet_member:
fee += kfet.membership_fee_paid if registration.user.profile.paid else kfet.membership_fee_unpaid
if not bde_member:
fee += bde.membership_fee_paid if registration.user.profile.paid else bde.membership_fee_unpaid
credit_type = form.cleaned_data["credit_type"]
credit_amount = form.cleaned_data["credit_amount"]
last_name = form.cleaned_data["last_name"]
first_name = form.cleaned_data["first_name"]
bank = form.cleaned_data["bank"]
if credit_type is None or registration.soge_credit:
credit_amount = 0
if not registration.caution_check and not registration.first_year: if not registration.caution_check and not registration.first_year:
form.add_error('bus', _("This user didn't give her/his caution check.")) form.add_error('bus', _("This user didn't give her/his caution check."))
return super().form_invalid(form) return super().form_invalid(form)
if club.parent_club is not None: # parent_club is never None: this is Kfet. if not registration.soge_credit and user.note.balance < fee + credit_amount:
# We want that the user is member of the Kfet club *of this year*: the Kfet membership is included # Users must have money before registering to the WEI.
# in the WEI registration. form.add_error('bus',
if not Membership.objects.filter( _("This user don't have enough money to join this club, and can't have a negative balance."))
user=form.instance.user,
club=club.parent_club, # Kfet
date_start__gte=club.parent_club.membership_start,
).exists():
form.add_error('bus', _('User is not a member of the parent club') + ' ' + club.parent_club.name)
return super().form_invalid(form) return super().form_invalid(form)
if credit_amount:
if not last_name:
form.add_error('last_name', _("This field is required."))
return super().form_invalid(form)
if not first_name:
form.add_error('first_name', _("This field is required."))
return super().form_invalid(form)
# Credit note before adding the membership
SpecialTransaction.objects.create(
source=credit_type,
destination=registration.user.note,
amount=credit_amount,
reason="Crédit " + str(credit_type) + " (WEI)",
last_name=last_name,
first_name=first_name,
bank=bank,
)
# Now, all is fine, the membership can be created. # Now, all is fine, the membership can be created.
if registration.soge_credit:
form.instance._soge = True
if registration.first_year: if registration.first_year:
membership = form.instance membership = form.instance
# If the user is not a member of the club Kfet, then the membership is created.
membership.save() membership.save()
membership.refresh_from_db() membership.refresh_from_db()
membership.roles.set(WEIRole.objects.filter(name="1A").all()) membership.roles.set(WEIRole.objects.filter(name="1A").all())

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-03 23:53+0200\n" "POT-Creation-Date: 2020-08-04 20:03+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -45,7 +45,7 @@ msgid "You can't invite more than 3 people to this activity."
msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité." msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
#: apps/activity/models.py:24 apps/activity/models.py:49 #: apps/activity/models.py:24 apps/activity/models.py:49
#: apps/member/models.py:158 apps/note/models/notes.py:212 #: apps/member/models.py:159 apps/note/models/notes.py:212
#: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45 #: apps/note/models/transactions.py:25 apps/note/models/transactions.py:45
#: apps/note/models/transactions.py:268 apps/permission/models.py:339 #: apps/note/models/transactions.py:268 apps/permission/models.py:339
#: apps/wei/models.py:65 apps/wei/models.py:117 #: apps/wei/models.py:65 apps/wei/models.py:117
@ -84,7 +84,7 @@ msgstr "description"
msgid "type" msgid "type"
msgstr "type" msgstr "type"
#: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:266 #: apps/activity/models.py:67 apps/logs/models.py:22 apps/member/models.py:267
#: apps/note/models/notes.py:126 apps/treasury/models.py:222 #: apps/note/models/notes.py:126 apps/treasury/models.py:222
#: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14 #: apps/wei/models.py:159 templates/treasury/sogecredit_detail.html:14
#: templates/wei/survey.html:16 #: templates/wei/survey.html:16
@ -189,12 +189,13 @@ msgstr "Type"
#: apps/activity/tables.py:77 apps/member/forms.py:103 #: apps/activity/tables.py:77 apps/member/forms.py:103
#: apps/registration/forms.py:70 apps/treasury/forms.py:120 #: apps/registration/forms.py:70 apps/treasury/forms.py:120
#: apps/wei/forms/registration.py:95
msgid "Last name" msgid "Last name"
msgstr "Nom de famille" msgstr "Nom de famille"
#: apps/activity/tables.py:79 apps/member/forms.py:108 #: apps/activity/tables.py:79 apps/member/forms.py:108
#: apps/registration/forms.py:75 apps/treasury/forms.py:122 #: apps/registration/forms.py:75 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:129 #: apps/wei/forms/registration.py:100 templates/note/transaction_form.html:129
msgid "First name" msgid "First name"
msgstr "Prénom" msgstr "Prénom"
@ -268,7 +269,7 @@ msgid "edit"
msgstr "Modifier" msgstr "Modifier"
#: apps/logs/models.py:63 apps/note/tables.py:137 apps/note/tables.py:165 #: apps/logs/models.py:63 apps/note/tables.py:137 apps/note/tables.py:165
#: apps/permission/models.py:137 apps/wei/tables.py:65 #: apps/permission/models.py:137 apps/wei/tables.py:73
msgid "delete" msgid "delete"
msgstr "Supprimer" msgstr "Supprimer"
@ -292,25 +293,25 @@ msgstr "journal de modification"
msgid "changelogs" msgid "changelogs"
msgstr "journaux de modifications" msgstr "journaux de modifications"
#: apps/member/admin.py:52 apps/member/models.py:185 #: apps/member/admin.py:52 apps/member/models.py:186
#: templates/member/club_info.html:41 #: templates/member/club_info.html:41
msgid "membership fee (paid students)" msgid "membership fee (paid students)"
msgstr "cotisation pour adhérer (normalien élève)" msgstr "cotisation pour adhérer (normalien élève)"
#: apps/member/admin.py:53 apps/member/models.py:190 #: apps/member/admin.py:53 apps/member/models.py:191
#: templates/member/club_info.html:44 #: templates/member/club_info.html:44
msgid "membership fee (unpaid students)" msgid "membership fee (unpaid students)"
msgstr "cotisation pour adhérer (normalien étudiant)" msgstr "cotisation pour adhérer (normalien étudiant)"
#: apps/member/admin.py:67 apps/member/models.py:277 #: apps/member/admin.py:67 apps/member/models.py:278
msgid "roles" msgid "roles"
msgstr "rôles" msgstr "rôles"
#: apps/member/admin.py:68 apps/member/models.py:291 #: apps/member/admin.py:68 apps/member/models.py:292
msgid "fee" msgid "fee"
msgstr "cotisation" msgstr "cotisation"
#: apps/member/apps.py:14 apps/wei/tables.py:150 apps/wei/tables.py:181 #: apps/member/apps.py:14 apps/wei/tables.py:179 apps/wei/tables.py:210
msgid "member" msgid "member"
msgstr "adhérent" msgstr "adhérent"
@ -328,10 +329,12 @@ msgid "Check this case is the Société Générale paid the inscription."
msgstr "Cochez cette case si la Société Générale a payé l'inscription." msgstr "Cochez cette case si la Société Générale a payé l'inscription."
#: apps/member/forms.py:89 apps/registration/forms.py:57 #: apps/member/forms.py:89 apps/registration/forms.py:57
#: apps/wei/forms/registration.py:82
msgid "Credit type" msgid "Credit type"
msgstr "Type de rechargement" msgstr "Type de rechargement"
#: apps/member/forms.py:90 apps/registration/forms.py:58 #: apps/member/forms.py:90 apps/registration/forms.py:58
#: apps/wei/forms/registration.py:83
msgid "No credit" msgid "No credit"
msgstr "Pas de rechargement" msgstr "Pas de rechargement"
@ -340,11 +343,13 @@ msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion." msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion."
#: apps/member/forms.py:96 apps/registration/forms.py:63 #: apps/member/forms.py:96 apps/registration/forms.py:63
#: apps/wei/forms/registration.py:88
msgid "Credit amount" msgid "Credit amount"
msgstr "Montant à créditer" msgstr "Montant à créditer"
#: apps/member/forms.py:113 apps/registration/forms.py:80 #: apps/member/forms.py:113 apps/registration/forms.py:80
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:135 #: apps/treasury/forms.py:124 apps/wei/forms/registration.py:105
#: templates/note/transaction_form.html:135
msgid "Bank" msgid "Bank"
msgstr "Banque" msgstr "Banque"
@ -356,171 +361,171 @@ msgstr "Utilisateur"
msgid "Roles" msgid "Roles"
msgstr "Rôles" msgstr "Rôles"
#: apps/member/models.py:34 #: apps/member/models.py:35
#: templates/registration/future_profile_detail.html:40 #: templates/registration/future_profile_detail.html:40
#: templates/wei/weimembership_form.html:48 #: templates/wei/weimembership_form.html:48
msgid "phone number" msgid "phone number"
msgstr "numéro de téléphone" msgstr "numéro de téléphone"
#: apps/member/models.py:41 templates/member/profile_info.html:29 #: apps/member/models.py:42 templates/member/profile_info.html:29
#: templates/registration/future_profile_detail.html:34 #: templates/registration/future_profile_detail.html:34
#: templates/wei/weimembership_form.html:42 #: templates/wei/weimembership_form.html:42
msgid "section" msgid "section"
msgstr "section" msgstr "section"
#: apps/member/models.py:42 #: apps/member/models.py:43
msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgid "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\"" msgstr "e.g. \"1A0\", \"9A♥\", \"SAPHIRE\""
#: apps/member/models.py:50 templates/wei/weimembership_form.html:36 #: apps/member/models.py:51 templates/wei/weimembership_form.html:36
msgid "department" msgid "department"
msgstr "département" msgstr "département"
#: apps/member/models.py:52 #: apps/member/models.py:53
msgid "Informatics (A0)" msgid "Informatics (A0)"
msgstr "Informatique (A0)" msgstr "Informatique (A0)"
#: apps/member/models.py:53 #: apps/member/models.py:54
msgid "Mathematics (A1)" msgid "Mathematics (A1)"
msgstr "Mathématiques (A1)" msgstr "Mathématiques (A1)"
#: apps/member/models.py:54 #: apps/member/models.py:55
msgid "Physics (A2)" msgid "Physics (A2)"
msgstr "Physique (A2)" msgstr "Physique (A2)"
#: apps/member/models.py:55 #: apps/member/models.py:56
msgid "Applied physics (A'2)" msgid "Applied physics (A'2)"
msgstr "Physique appliquée (A'2)" msgstr "Physique appliquée (A'2)"
#: apps/member/models.py:56 #: apps/member/models.py:57
msgid "Chemistry (A''2)" msgid "Chemistry (A''2)"
msgstr "Chimie (A''2)" msgstr "Chimie (A''2)"
#: apps/member/models.py:57 #: apps/member/models.py:58
msgid "Biology (A3)" msgid "Biology (A3)"
msgstr "Biologie (A3)" msgstr "Biologie (A3)"
#: apps/member/models.py:58 #: apps/member/models.py:59
msgid "SAPHIRE (B1234)" msgid "SAPHIRE (B1234)"
msgstr "SAPHIRE (B1234)" msgstr "SAPHIRE (B1234)"
#: apps/member/models.py:59 #: apps/member/models.py:60
msgid "Mechanics (B1)" msgid "Mechanics (B1)"
msgstr "Mécanique (B1)" msgstr "Mécanique (B1)"
#: apps/member/models.py:60 #: apps/member/models.py:61
msgid "Civil engineering (B2)" msgid "Civil engineering (B2)"
msgstr "Génie civil (B2)" msgstr "Génie civil (B2)"
#: apps/member/models.py:61 #: apps/member/models.py:62
msgid "Mechanical engineering (B3)" msgid "Mechanical engineering (B3)"
msgstr "Génie mécanique (B3)" msgstr "Génie mécanique (B3)"
#: apps/member/models.py:62 #: apps/member/models.py:63
msgid "EEA (B4)" msgid "EEA (B4)"
msgstr "EEA (B4)" msgstr "EEA (B4)"
#: apps/member/models.py:63 #: apps/member/models.py:64
msgid "Design (C)" msgid "Design (C)"
msgstr "Design (C)" msgstr "Design (C)"
#: apps/member/models.py:64 #: apps/member/models.py:65
msgid "Economy-management (D2)" msgid "Economy-management (D2)"
msgstr "Économie-gestion (D2)" msgstr "Économie-gestion (D2)"
#: apps/member/models.py:65 #: apps/member/models.py:66
msgid "Social sciences (D3)" msgid "Social sciences (D3)"
msgstr "Sciences sociales (D3)" msgstr "Sciences sociales (D3)"
#: apps/member/models.py:66 #: apps/member/models.py:67
msgid "English (E)" msgid "English (E)"
msgstr "Anglais (E)" msgstr "Anglais (E)"
#: apps/member/models.py:67 #: apps/member/models.py:68
msgid "External (EXT)" msgid "External (EXT)"
msgstr "Externe (EXT)" msgstr "Externe (EXT)"
#: apps/member/models.py:74 #: apps/member/models.py:75
msgid "promotion" msgid "promotion"
msgstr "promotion" msgstr "promotion"
#: apps/member/models.py:75 #: apps/member/models.py:76
msgid "Year of entry to the school (None if not ENS student)" msgid "Year of entry to the school (None if not ENS student)"
msgstr "Année d'entrée dans l'école (None si non-étudiant·e de l'ENS)" msgstr "Année d'entrée dans l'école (None si non-étudiant·e de l'ENS)"
#: apps/member/models.py:79 templates/member/profile_info.html:32 #: apps/member/models.py:80 templates/member/profile_info.html:32
#: templates/registration/future_profile_detail.html:37 #: templates/registration/future_profile_detail.html:37
#: templates/wei/weimembership_form.html:45 #: templates/wei/weimembership_form.html:45
msgid "address" msgid "address"
msgstr "adresse" msgstr "adresse"
#: apps/member/models.py:86 #: apps/member/models.py:87
#: templates/registration/future_profile_detail.html:43 #: templates/registration/future_profile_detail.html:43
#: templates/wei/weimembership_form.html:51 #: templates/wei/weimembership_form.html:51
msgid "paid" msgid "paid"
msgstr "payé" msgstr "payé"
#: apps/member/models.py:87 #: apps/member/models.py:88
msgid "Tells if the user receive a salary." msgid "Tells if the user receive a salary."
msgstr "Indique si l'utilisateur perçoit un salaire." msgstr "Indique si l'utilisateur perçoit un salaire."
#: apps/member/models.py:92 #: apps/member/models.py:93
msgid "email confirmed" msgid "email confirmed"
msgstr "adresse email confirmée" msgstr "adresse email confirmée"
#: apps/member/models.py:97 #: apps/member/models.py:98
msgid "registration valid" msgid "registration valid"
msgstr "inscription valid" msgstr "inscription valid"
#: apps/member/models.py:126 apps/member/models.py:127 #: apps/member/models.py:127 apps/member/models.py:128
msgid "user profile" msgid "user profile"
msgstr "profil utilisateur" msgstr "profil utilisateur"
#: apps/member/models.py:134 #: apps/member/models.py:135
msgid "Activate your Note Kfet account" msgid "Activate your Note Kfet account"
msgstr "Activez votre compte Note Kfet" msgstr "Activez votre compte Note Kfet"
#: apps/member/models.py:163 templates/member/club_info.html:57 #: apps/member/models.py:164 templates/member/club_info.html:57
#: templates/registration/future_profile_detail.html:22 #: templates/registration/future_profile_detail.html:22
#: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24 #: templates/wei/weiclub_info.html:52 templates/wei/weimembership_form.html:24
msgid "email" msgid "email"
msgstr "courriel" msgstr "courriel"
#: apps/member/models.py:170 #: apps/member/models.py:171
msgid "parent club" msgid "parent club"
msgstr "club parent" msgstr "club parent"
#: apps/member/models.py:179 #: apps/member/models.py:180
msgid "require memberships" msgid "require memberships"
msgstr "nécessite des adhésions" msgstr "nécessite des adhésions"
#: apps/member/models.py:180 #: apps/member/models.py:181
msgid "Uncheck if this club don't require memberships." msgid "Uncheck if this club don't require memberships."
msgstr "Décochez si ce club n'utilise pas d'adhésions." msgstr "Décochez si ce club n'utilise pas d'adhésions."
#: apps/member/models.py:196 templates/member/club_info.html:33 #: apps/member/models.py:197 templates/member/club_info.html:33
msgid "membership duration" msgid "membership duration"
msgstr "durée de l'adhésion" msgstr "durée de l'adhésion"
#: apps/member/models.py:197 #: apps/member/models.py:198
msgid "The longest time (in days) a membership can last (NULL = infinite)." msgid "The longest time (in days) a membership can last (NULL = infinite)."
msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)." msgstr "La durée maximale (en jours) d'une adhésion (NULL = infinie)."
#: apps/member/models.py:204 templates/member/club_info.html:23 #: apps/member/models.py:205 templates/member/club_info.html:23
msgid "membership start" msgid "membership start"
msgstr "début de l'adhésion" msgstr "début de l'adhésion"
#: apps/member/models.py:205 #: apps/member/models.py:206
msgid "How long after January 1st the members can renew their membership." msgid "How long after January 1st the members can renew their membership."
msgstr "" msgstr ""
"Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur " "Combien de temps après le 1er Janvier les adhérents peuvent renouveler leur "
"adhésion." "adhésion."
#: apps/member/models.py:212 templates/member/club_info.html:28 #: apps/member/models.py:213 templates/member/club_info.html:28
msgid "membership end" msgid "membership end"
msgstr "fin de l'adhésion" msgstr "fin de l'adhésion"
#: apps/member/models.py:213 #: apps/member/models.py:214
msgid "" msgid ""
"How long the membership can last after January 1st of the next year after " "How long the membership can last after January 1st of the next year after "
"members can renew their membership." "members can renew their membership."
@ -528,46 +533,46 @@ msgstr ""
"Combien de temps l'adhésion peut durer après le 1er Janvier de l'année " "Combien de temps l'adhésion peut durer après le 1er Janvier de l'année "
"suivante avant que les adhérents peuvent renouveler leur adhésion." "suivante avant que les adhérents peuvent renouveler leur adhésion."
#: apps/member/models.py:247 apps/member/models.py:272 #: apps/member/models.py:248 apps/member/models.py:273
#: apps/note/models/notes.py:163 #: apps/note/models/notes.py:163
msgid "club" msgid "club"
msgstr "club" msgstr "club"
#: apps/member/models.py:248 #: apps/member/models.py:249
msgid "clubs" msgid "clubs"
msgstr "clubs" msgstr "clubs"
#: apps/member/models.py:282 #: apps/member/models.py:283
msgid "membership starts on" msgid "membership starts on"
msgstr "l'adhésion commence le" msgstr "l'adhésion commence le"
#: apps/member/models.py:286 #: apps/member/models.py:287
msgid "membership ends on" msgid "membership ends on"
msgstr "l'adhésion finit le" msgstr "l'adhésion finit le"
#: apps/member/models.py:310 apps/member/views.py:540 apps/wei/views.py:798 #: apps/member/models.py:339
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
#: apps/member/models.py:317
#, python-brace-format #, python-brace-format
msgid "The role {role} does not apply to the club {club}." msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}." msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:328 apps/member/views.py:549 #: apps/member/models.py:350 apps/member/views.py:583
msgid "User is already a member of the club" msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club" msgstr "L'utilisateur est déjà membre du club"
#: apps/member/models.py:379 #: apps/member/models.py:386
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
#: apps/member/models.py:439
#, python-brace-format #, python-brace-format
msgid "Membership of {user} for the club {club}" msgid "Membership of {user} for the club {club}"
msgstr "Adhésion de {user} pour le club {club}" msgstr "Adhésion de {user} pour le club {club}"
#: apps/member/models.py:382 #: apps/member/models.py:442
msgid "membership" msgid "membership"
msgstr "adhésion" msgstr "adhésion"
#: apps/member/models.py:383 #: apps/member/models.py:443
msgid "memberships" msgid "memberships"
msgstr "adhésions" msgstr "adhésions"
@ -625,7 +630,7 @@ msgstr "Modifier le club"
msgid "Add new member to the club" msgid "Add new member to the club"
msgstr "Ajouter un nouveau membre au club" msgstr "Ajouter un nouveau membre au club"
#: apps/member/views.py:530 apps/wei/views.py:783 #: apps/member/views.py:574 apps/wei/views.py:862
msgid "" msgid ""
"This user don't have enough money to join this club, and can't have a " "This user don't have enough money to join this club, and can't have a "
"negative balance." "negative balance."
@ -633,25 +638,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas " "Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif." "avoir un solde négatif."
#: apps/member/views.py:553 #: apps/member/views.py:587
msgid "The membership must start after {:%m-%d-%Y}." msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
#: apps/member/views.py:558 #: apps/member/views.py:592
msgid "The membership must begin before {:%m-%d-%Y}." msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}." msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:575 apps/member/views.py:577 apps/member/views.py:579 #: apps/member/views.py:609 apps/member/views.py:611 apps/member/views.py:613
#: apps/registration/views.py:290 apps/registration/views.py:292 #: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:294 #: apps/registration/views.py:294 apps/wei/views.py:867 apps/wei/views.py:871
msgid "This field is required." msgid "This field is required."
msgstr "Ce champ est requis." msgstr "Ce champ est requis."
#: apps/member/views.py:647 #: apps/member/views.py:690
msgid "Manage roles of an user in the club" msgid "Manage roles of an user in the club"
msgstr "Gérer les rôles d'un utilisateur dans le club" msgstr "Gérer les rôles d'un utilisateur dans le club"
#: apps/member/views.py:672 #: apps/member/views.py:715
msgid "Members of the club" msgid "Members of the club"
msgstr "Membres du club" msgstr "Membres du club"
@ -950,13 +955,13 @@ msgstr "Cliquez pour valider"
msgid "No reason specified" msgid "No reason specified"
msgstr "Pas de motif spécifié" msgstr "Pas de motif spécifié"
#: apps/note/tables.py:139 apps/note/tables.py:167 apps/wei/tables.py:66 #: apps/note/tables.py:139 apps/note/tables.py:167 apps/wei/tables.py:74
#: templates/treasury/sogecredit_detail.html:59 #: apps/wei/tables.py:100 templates/treasury/sogecredit_detail.html:59
#: templates/wei/weiregistration_confirm_delete.html:32 #: templates/wei/weiregistration_confirm_delete.html:32
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: apps/note/tables.py:162 apps/wei/tables.py:42 apps/wei/tables.py:43 #: apps/note/tables.py:162 apps/wei/tables.py:46 apps/wei/tables.py:47
#: templates/member/club_info.html:67 templates/note/conso_form.html:128 #: templates/member/club_info.html:67 templates/note/conso_form.html:128
#: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15 #: templates/wei/bus_tables.html:15 templates/wei/busteam_tables.html:15
#: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68 #: templates/wei/busteam_tables.html:33 templates/wei/weiclub_info.html:68
@ -1190,7 +1195,7 @@ msgstr "Trésorerie"
#: templates/activity/activity_form.html:9 #: templates/activity/activity_form.html:9
#: templates/activity/activity_invite.html:8 #: templates/activity/activity_invite.html:8
#: templates/django_filters/rest_framework/form.html:5 #: templates/django_filters/rest_framework/form.html:5
#: templates/member/add_members.html:14 templates/member/club_form.html:9 #: templates/member/add_members.html:31 templates/member/club_form.html:9
#: templates/note/transactiontemplate_form.html:15 #: templates/note/transactiontemplate_form.html:15
#: templates/treasury/invoice_form.html:46 templates/wei/bus_form.html:13 #: templates/treasury/invoice_form.html:46 templates/wei/bus_form.html:13
#: templates/wei/busteam_form.html:13 templates/wei/weiclub_form.html:15 #: templates/wei/busteam_form.html:13 templates/wei/weiclub_form.html:15
@ -1410,7 +1415,7 @@ msgstr "Joindre une transaction à une remise"
msgid "List of credits from the Société générale" msgid "List of credits from the Société générale"
msgstr "Liste des crédits de la Société générale" msgstr "Liste des crédits de la Société générale"
#: apps/treasury/views.py:384 #: apps/treasury/views.py:379
msgid "Manage credits from the Société générale" msgid "Manage credits from the Société générale"
msgstr "Gérer les crédits de la Société générale" msgstr "Gérer les crédits de la Société générale"
@ -1419,12 +1424,12 @@ msgstr "Gérer les crédits de la Société générale"
msgid "WEI" msgid "WEI"
msgstr "WEI" msgstr "WEI"
#: apps/wei/forms/registration.py:48 apps/wei/models.py:112 #: apps/wei/forms/registration.py:50 apps/wei/models.py:112
#: apps/wei/models.py:297 #: apps/wei/models.py:297
msgid "bus" msgid "bus"
msgstr "Bus" msgstr "Bus"
#: apps/wei/forms/registration.py:49 #: apps/wei/forms/registration.py:51
msgid "" msgid ""
"This choice is not definitive. The WEI organizers are free to attribute for " "This choice is not definitive. The WEI organizers are free to attribute for "
"you a bus and a team, in particular if you are a free eletron." "you a bus and a team, in particular if you are a free eletron."
@ -1433,11 +1438,11 @@ msgstr ""
"attribuer un bus et une équipe, en particulier si vous êtes un électron " "attribuer un bus et une équipe, en particulier si vous êtes un électron "
"libre." "libre."
#: apps/wei/forms/registration.py:56 #: apps/wei/forms/registration.py:58
msgid "Team" msgid "Team"
msgstr "Équipe" msgstr "Équipe"
#: apps/wei/forms/registration.py:58 #: apps/wei/forms/registration.py:60
msgid "" msgid ""
"Leave this field empty if you won't be in a team (staff, bus chief, free " "Leave this field empty if you won't be in a team (staff, bus chief, free "
"electron)" "electron)"
@ -1445,16 +1450,16 @@ msgstr ""
"Laissez ce champ vide si vous ne serez pas dans une équipe (staff, chef de " "Laissez ce champ vide si vous ne serez pas dans une équipe (staff, chef de "
"bus ou électron libre)" "bus ou électron libre)"
#: apps/wei/forms/registration.py:64 apps/wei/forms/registration.py:74 #: apps/wei/forms/registration.py:66 apps/wei/forms/registration.py:76
#: apps/wei/models.py:147 #: apps/wei/models.py:147
msgid "WEI Roles" msgid "WEI Roles"
msgstr "Rôles au WEI" msgstr "Rôles au WEI"
#: apps/wei/forms/registration.py:65 #: apps/wei/forms/registration.py:67
msgid "Select the roles that you are interested in." msgid "Select the roles that you are interested in."
msgstr "Sélectionnez les rôles qui vous intéressent." msgstr "Sélectionnez les rôles qui vous intéressent."
#: apps/wei/forms/registration.py:81 #: apps/wei/forms/registration.py:112
msgid "This team doesn't belong to the given bus." msgid "This team doesn't belong to the given bus."
msgstr "Cette équipe n'appartient pas à ce bus." msgstr "Cette équipe n'appartient pas à ce bus."
@ -1624,97 +1629,97 @@ msgstr "adhésion au WEI"
msgid "WEI memberships" msgid "WEI memberships"
msgstr "adhésions au WEI" msgstr "adhésions au WEI"
#: apps/wei/tables.py:53 apps/wei/tables.py:54 #: apps/wei/tables.py:57 apps/wei/tables.py:58 apps/wei/tables.py:95
#: templates/treasury/sogecredit_detail.html:57 #: templates/treasury/sogecredit_detail.html:57
msgid "Validate" msgid "Validate"
msgstr "Valider" msgstr "Valider"
#: apps/wei/tables.py:96 #: apps/wei/tables.py:125
msgid "Year" msgid "Year"
msgstr "Année" msgstr "Année"
#: apps/wei/tables.py:134 templates/wei/bus_tables.html:26 #: apps/wei/tables.py:163 templates/wei/bus_tables.html:26
#: templates/wei/busteam_tables.html:43 #: templates/wei/busteam_tables.html:43
msgid "Teams" msgid "Teams"
msgstr "Équipes" msgstr "Équipes"
#: apps/wei/tables.py:143 apps/wei/tables.py:184 #: apps/wei/tables.py:172 apps/wei/tables.py:213
msgid "Members count" msgid "Members count"
msgstr "Nombre de membres" msgstr "Nombre de membres"
#: apps/wei/tables.py:150 apps/wei/tables.py:181 #: apps/wei/tables.py:179 apps/wei/tables.py:210
msgid "members" msgid "members"
msgstr "adhérents" msgstr "adhérents"
#: apps/wei/views.py:56 #: apps/wei/views.py:57
msgid "Search WEI" msgid "Search WEI"
msgstr "Chercher un WEI" msgstr "Chercher un WEI"
#: apps/wei/views.py:74 templates/wei/weiclub_list.html:10 #: apps/wei/views.py:75 templates/wei/weiclub_list.html:10
msgid "Create WEI" msgid "Create WEI"
msgstr "Créer un WEI" msgstr "Créer un WEI"
#: apps/wei/views.py:94 #: apps/wei/views.py:95
msgid "WEI Detail" msgid "WEI Detail"
msgstr "Détails du WEI" msgstr "Détails du WEI"
#: apps/wei/views.py:189 #: apps/wei/views.py:190
msgid "View members of the WEI" msgid "View members of the WEI"
msgstr "Voir les membres du WEI" msgstr "Voir les membres du WEI"
#: apps/wei/views.py:217 #: apps/wei/views.py:218
msgid "Find WEI Membership" msgid "Find WEI Membership"
msgstr "Trouver une adhésion au WEI" msgstr "Trouver une adhésion au WEI"
#: apps/wei/views.py:227 #: apps/wei/views.py:228
msgid "View registrations to the WEI" msgid "View registrations to the WEI"
msgstr "Voir les inscriptions au WEI" msgstr "Voir les inscriptions au WEI"
#: apps/wei/views.py:251 #: apps/wei/views.py:252
msgid "Find WEI Registration" msgid "Find WEI Registration"
msgstr "Trouver une inscription au WEI" msgstr "Trouver une inscription au WEI"
#: apps/wei/views.py:262 #: apps/wei/views.py:263
msgid "Update the WEI" msgid "Update the WEI"
msgstr "Modifier le WEI" msgstr "Modifier le WEI"
#: apps/wei/views.py:283 #: apps/wei/views.py:284
msgid "Create new bus" msgid "Create new bus"
msgstr "Ajouter un nouveau bus" msgstr "Ajouter un nouveau bus"
#: apps/wei/views.py:314 #: apps/wei/views.py:315
msgid "Update bus" msgid "Update bus"
msgstr "Modifier le bus" msgstr "Modifier le bus"
#: apps/wei/views.py:344 #: apps/wei/views.py:345
msgid "Manage bus" msgid "Manage bus"
msgstr "Gérer le bus" msgstr "Gérer le bus"
#: apps/wei/views.py:371 #: apps/wei/views.py:372
msgid "Create new team" msgid "Create new team"
msgstr "Créer une nouvelle équipe" msgstr "Créer une nouvelle équipe"
#: apps/wei/views.py:403 #: apps/wei/views.py:404
msgid "Update team" msgid "Update team"
msgstr "Modifier l'équipe" msgstr "Modifier l'équipe"
#: apps/wei/views.py:434 #: apps/wei/views.py:435
msgid "Manage WEI team" msgid "Manage WEI team"
msgstr "Gérer l'équipe WEI" msgstr "Gérer l'équipe WEI"
#: apps/wei/views.py:456 #: apps/wei/views.py:457
msgid "Register first year student to the WEI" msgid "Register first year student to the WEI"
msgstr "Inscrire un 1A au WEI" msgstr "Inscrire un 1A au WEI"
#: apps/wei/views.py:468 templates/wei/weiclub_info.html:62 #: apps/wei/views.py:469 templates/wei/weiclub_info.html:62
msgid "Register 1A" msgid "Register 1A"
msgstr "Inscrire un 1A" msgstr "Inscrire un 1A"
#: apps/wei/views.py:489 apps/wei/views.py:560 #: apps/wei/views.py:490 apps/wei/views.py:561
msgid "This user is already registered to this WEI." msgid "This user is already registered to this WEI."
msgstr "Cette personne est déjà inscrite au WEI." msgstr "Cette personne est déjà inscrite au WEI."
#: apps/wei/views.py:494 #: apps/wei/views.py:495
msgid "" msgid ""
"This user can't be in her/his first year since he/she has already participed " "This user can't be in her/his first year since he/she has already participed "
"to a WEI." "to a WEI."
@ -1722,39 +1727,39 @@ msgstr ""
"Cet utilisateur ne peut pas être en première année puisqu'iel a déjà " "Cet utilisateur ne peut pas être en première année puisqu'iel a déjà "
"participé à un WEI." "participé à un WEI."
#: apps/wei/views.py:511 #: apps/wei/views.py:512
msgid "Register old student to the WEI" msgid "Register old student to the WEI"
msgstr "Inscrire un 2A+ au WEI" msgstr "Inscrire un 2A+ au WEI"
#: apps/wei/views.py:523 templates/wei/weiclub_info.html:65 #: apps/wei/views.py:524 templates/wei/weiclub_info.html:65
msgid "Register 2A+" msgid "Register 2A+"
msgstr "Inscrire un 2A+" msgstr "Inscrire un 2A+"
#: apps/wei/views.py:542 apps/wei/views.py:627 #: apps/wei/views.py:543 apps/wei/views.py:628
msgid "You already opened an account in the Société générale." msgid "You already opened an account in the Société générale."
msgstr "Vous avez déjà ouvert un compte auprès de la société générale." msgstr "Vous avez déjà ouvert un compte auprès de la société générale."
#: apps/wei/views.py:590 #: apps/wei/views.py:591
msgid "Update WEI Registration" msgid "Update WEI Registration"
msgstr "Modifier l'inscription WEI" msgstr "Modifier l'inscription WEI"
#: apps/wei/views.py:677 #: apps/wei/views.py:687
msgid "Delete WEI registration" msgid "Delete WEI registration"
msgstr "Supprimer l'inscription WEI" msgstr "Supprimer l'inscription WEI"
#: apps/wei/views.py:688 #: apps/wei/views.py:698
msgid "You don't have the right to delete this WEI registration." msgid "You don't have the right to delete this WEI registration."
msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI." msgstr "Vous n'avez pas la permission de supprimer cette inscription au WEI."
#: apps/wei/views.py:707 #: apps/wei/views.py:717
msgid "Validate WEI registration" msgid "Validate WEI registration"
msgstr "Valider l'inscription WEI" msgstr "Valider l'inscription WEI"
#: apps/wei/views.py:787 #: apps/wei/views.py:856
msgid "This user didn't give her/his caution check." msgid "This user didn't give her/his caution check."
msgstr "Cet utilisateur n'a pas donné son chèque de caution." msgstr "Cet utilisateur n'a pas donné son chèque de caution."
#: apps/wei/views.py:830 apps/wei/views.py:883 apps/wei/views.py:893 #: apps/wei/views.py:918 apps/wei/views.py:971 apps/wei/views.py:981
#: templates/wei/survey.html:12 templates/wei/survey_closed.html:12 #: templates/wei/survey.html:12 templates/wei/survey_closed.html:12
#: templates/wei/survey_end.html:12 #: templates/wei/survey_end.html:12
msgid "Survey WEI" msgid "Survey WEI"
@ -1807,7 +1812,7 @@ msgstr "Page inexistante"
msgid "" msgid ""
"The requested path <code>%(request_path)s</code> was not found on the server." "The requested path <code>%(request_path)s</code> was not found on the server."
msgstr "" msgstr ""
"The chemin demandé <code>%(request_path)s</code> n'a pas été trouvé sur le " "Le chemin demandé <code>%(request_path)s</code> n'a pas été trouvé sur le "
"serveur." "serveur."
#: templates/500.html:6 #: templates/500.html:6
@ -1926,13 +1931,33 @@ msgstr ""
msgid "Field filters" msgid "Field filters"
msgstr "" msgstr ""
#: templates/member/add_members.html:15
#, python-format
msgid ""
"The user is not a member of the club·s %(clubs)s. An additional fee of "
"%(pretty_fee)s will be charged to renew automatically the membership in this/"
"these club·s."
msgstr ""
"Cet utilisateur n'est pas membre du/des club·s parent·s %(clubs)s. Un "
"montant supplémentaire de%(pretty_fee)s sera débitée afin de renouveler "
"automatiquement l'adhésion dans ce·s club·s."
#: templates/member/add_members.html:20
#, python-format
msgid ""
"This club has parents %(clubs)s. An additional fee of %(pretty_fee)s will be "
"charged to adhere automatically to this/these club·s."
msgstr ""
"Ce club a pour parent·s %(clubs)s. Un coût supplémentaire de %(pretty_fee)s "
"peut être ajouté pour adhérer automatiquement à ce·s club·s."
#: templates/member/alias_update.html:5 #: templates/member/alias_update.html:5
msgid "Add alias" msgid "Add alias"
msgstr "Ajouter un alias" msgstr "Ajouter un alias"
#: templates/member/autocomplete_model.html:11 #: templates/member/autocomplete_model.html:11
msgid "Reset" msgid "Reset"
msgstr "" msgstr "Réinitialiser"
#: templates/member/club_info.html:17 #: templates/member/club_info.html:17
msgid "Club Parent" msgid "Club Parent"
@ -2478,7 +2503,7 @@ msgid ""
"validated, but no credit will be operated." "validated, but no credit will be operated."
msgstr "" msgstr ""
"Si vous supprimez cette demande de crédit, alors toutes les transactions " "Si vous supprimez cette demande de crédit, alors toutes les transactions "
"d'adhésion seront aussi validées, but il n'y aura pas de transaction de " "d'adhésion seront aussi validées, mais il n'y aura pas de transaction de "
"crédit créée." "crédit créée."
#: templates/treasury/sogecredit_detail.html:37 #: templates/treasury/sogecredit_detail.html:37
@ -2678,6 +2703,7 @@ msgstr ""
"aura validé la création du compte, ou bien changer de moyen de paiement." "aura validé la création du compte, ou bien changer de moyen de paiement."
#: templates/wei/weimembership_form.html:162 #: templates/wei/weimembership_form.html:162
#, python-format
msgid "" msgid ""
"The note don't have enough money (%(balance)s, %(pretty_fee)s required). The " "The note don't have enough money (%(balance)s, %(pretty_fee)s required). The "
"registration may fail." "registration may fail."
@ -2686,25 +2712,29 @@ msgstr ""
"L'inscription va échouer." "L'inscription va échouer."
#: templates/wei/weimembership_form.html:169 #: templates/wei/weimembership_form.html:169
msgid "The note has enough money, the registration is possible." #, fuzzy, python-format
#| msgid "The note has enough money, the registration is possible."
msgid ""
"The note has enough money (%(pretty_fee)s required), the registration is "
"possible."
msgstr "La note a assez d'argent, l'inscription est possible." msgstr "La note a assez d'argent, l'inscription est possible."
#: templates/wei/weimembership_form.html:176 #: templates/wei/weimembership_form.html:178
msgid "The user didn't give her/his caution check." msgid "The user didn't give her/his caution check."
msgstr "L'utilisateur n'a pas donné son chèque de caution." msgstr "L'utilisateur n'a pas donné son chèque de caution."
#: templates/wei/weimembership_form.html:184 #: templates/wei/weimembership_form.html:186
#, fuzzy
#| msgid ""
#| "You must also go to the Kfet to pay your membership. The WEI registration "
#| "includes the BDE membership."
msgid "" msgid ""
"This user is not a member of the Kfet club for the comming year. Please " "This user is not a member of the Kfet club for the coming year. The "
"adhere <a href=\"%(future_user_detail)s\">here if he/she is in her/his first " "membership will be processed automatically, the WEI registration includes "
"year</a> or <a href=\"%(club_detail)s\">here if he/she was an old member</a> " "the membership fee."
"before you validate the registration of the WEI."
msgstr "" msgstr ""
"Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. Merci de le faire adhérer\n" "Vous devrez également vous rendre à la Kfet pour payer votre adhésion. "
"<a href=\"%(future_user_detail)s\">ici s'iel est en première année</a>\n" "L'inscription au WEI inclut l'adhésion au BDE."
"ou <a href=\"%(club_detail)s\">ici s'iel est un ancien membre</a> avant de "
"valider\n"
"l'inscription au WEI."
#: templates/wei/weimembership_list.html:24 #: templates/wei/weimembership_list.html:24
msgid "View unvalidated registrations..." msgid "View unvalidated registrations..."
@ -2730,3 +2760,16 @@ msgstr "Il n'y a pas de pré-inscription en attente avec cette entrée."
#: templates/wei/weiregistration_list.html:24 #: templates/wei/weiregistration_list.html:24
msgid "View validated memberships..." msgid "View validated memberships..."
msgstr "Voir les adhésions validées ..." msgstr "Voir les adhésions validées ..."
#~ msgid ""
#~ "This user is not a member of the Kfet club for the comming year. Please "
#~ "adhere <a href=\"%(future_user_detail)s\">here if he/she is in her/his "
#~ "first year</a> or <a href=\"%(club_detail)s\">here if he/she was an old "
#~ "member</a> before you validate the registration of the WEI."
#~ msgstr ""
#~ "Cet utilisateur n'est pas membre du club Kfet pour l'année à venir. Merci "
#~ "de le faire adhérer\n"
#~ "<a href=\"%(future_user_detail)s\">ici s'iel est en première année</a>\n"
#~ "ou <a href=\"%(club_detail)s\">ici s'iel est un ancien membre</a> avant "
#~ "de valider\n"
#~ "l'inscription au WEI."

View File

@ -124,27 +124,27 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="nav-link" href="{% url 'wei:current_wei_detail' %}"><i class="fas fa-bus"></i> {% trans 'WEI' %}</a> <a class="nav-link" href="{% url 'wei:current_wei_detail' %}"><i class="fas fa-bus"></i> {% trans 'WEI' %}</a>
</li> </li>
{% endif %} {% endif %}
{% if user.is_authenticated %} {% if request.user.is_authenticated %}
<li class="nav-item active"> <li class="nav-item active">
<a class="nav-link" href="{% url 'permission:rights' %}"><i class="fas fa-balance-scale"></i> {% trans 'Rights' %}</a> <a class="nav-link" href="{% url 'permission:rights' %}"><i class="fas fa-balance-scale"></i> {% trans 'Rights' %}</a>
</li> </li>
{% endif %} {% endif %}
{% if user.is_staff and ""|has_perm:user %} {% if request.user.is_staff and ""|has_perm:user %}
<li class="nav-item active"> <li class="nav-item active">
<a data-turbolinks="false" class="nav-link" href="{% url 'admin:index' %}"><i class="fas fa-user-cog"></i> {% trans 'Admin' %}</a> <a data-turbolinks="false" class="nav-link" href="{% url 'admin:index' %}"><i class="fas fa-user-cog"></i> {% trans 'Admin' %}</a>
</li> </li>
{% endif %} {% endif %}
</ul> </ul>
<ul class="navbar-nav ml-auto"> <ul class="navbar-nav ml-auto">
{% if user.is_authenticated %} {% if request.user.is_authenticated %}
<li class="dropdown"> <li class="dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
<span id="user_balance">{{ user.username }} ({{ user.note.balance | pretty_money }})</span> <span id="user_balance">{{ request.user.username }} ({{ request.user.note.balance | pretty_money }})</span>
</a> </a>
<div class="dropdown-menu dropdown-menu-right" <div class="dropdown-menu dropdown-menu-right"
aria-labelledby="navbarDropdownMenuLink"> aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="{% url 'member:user_detail' pk=user.pk %}"> <a class="dropdown-item" href="{% url 'member:user_detail' pk=request.user.pk %}">
<i class="fas fa-user"></i> Mon compte <i class="fas fa-user"></i> Mon compte
</a> </a>
<a class="dropdown-item" href="{% url 'logout' %}"> <a class="dropdown-item" href="{% url 'logout' %}">
@ -168,7 +168,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div> </div>
</nav> </nav>
<div class="container-fluid my-3" style="max-width: 1600px;"> <div class="container-fluid my-3" style="max-width: 1600px;">
{% if user.is_authenticated and not user.profile.email_confirmed %} {% if request.user.is_authenticated and not request.user.profile.email_confirmed %}
<div class="alert alert-warning"> <div class="alert alert-warning">
{% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %} {% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %}
</div> </div>

View File

@ -2,12 +2,29 @@
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% load pretty_money %}
{% block profile_info %} {% block profile_info %}
{% include "member/club_info.html" %} {% include "member/club_info.html" %}
{% endblock %} {% endblock %}
{% block profile_content %} {% block profile_content %}
{% if additional_fee_renewal %}
<div class="alert alert-warning">
{% if renewal %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
The user is not a member of the club·s {{ clubs }}. An additional fee of {{ pretty_fee }}
will be charged to renew automatically the membership in this/these club·s.
{% endblocktrans %}
{% else %}
{% blocktrans trimmed with clubs=clubs_renewal|join:", " pretty_fee=additional_fee_renewal|pretty_money %}
This club has parents {{ clubs }}. An additional fee of {{ pretty_fee }}
will be charged to adhere automatically to this/these club·s.
{% endblocktrans %}
{% endif %}
</div>
{% endif %}
<form method="post" action=""> <form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}

View File

@ -14,7 +14,5 @@
$("#history_list").load("{% url 'member:club_detail' pk=object.pk %} #history_list"); $("#history_list").load("{% url 'member:club_detail' pk=object.pk %} #history_list");
$("#profile_infos").load("{% url 'member:club_detail' pk=object.pk %} #profile_infos"); $("#profile_infos").load("{% url 'member:club_detail' pk=object.pk %} #profile_infos");
} }
window.history.replaceState({}, document.title, location.pathname);
</script> </script>
{% endblock %} {% endblock %}

View File

@ -11,10 +11,8 @@
{% block extrajavascript %} {% block extrajavascript %}
<script> <script>
function refreshHistory() { function refreshHistory() {
$("#history_list").load("{% url 'member:user_detail' pk=object.pk %} #history_list"); $("#history_list").load("{% url 'member:user_detail' pk=user_object.pk %} #history_list");
$("#profile_infos").load("{% url 'member:user_detail' pk=object.pk %} #profile_infos"); $("#profile_infos").load("{% url 'member:user_detail' pk=user_object.pk %} #profile_infos");
} }
window.history.replaceState({}, document.title, location.pathname);
</script> </script>
{% endblock %} {% endblock %}

View File

@ -2,22 +2,22 @@
<div class="card bg-light shadow"> <div class="card bg-light shadow">
<div class="card-header text-center" > <div class="card-header text-center" >
<h4> {% trans "Account #" %} {{ user.pk }}</h4> <h4> {% trans "Account #" %} {{ user_object.pk }}</h4>
</div> </div>
<div class="card-top text-center"> <div class="card-top text-center">
<a href="{% url 'member:user_update_pic' user.pk %}"> <a href="{% url 'member:user_update_pic' user_object.pk %}">
<img src="{{ user.note.display_image.url }}" class="img-thumbnail mt-2" > <img src="{{ user_object.note.display_image.url }}" class="img-thumbnail mt-2" >
</a> </a>
</div> </div>
<div class="card-body" id="profile_infos"> <div class="card-body" id="profile_infos">
<dl class="row"> <dl class="row">
<dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt> <dt class="col-xl-6">{% trans 'name'|capfirst %}, {% trans 'first name' %}</dt>
<dd class="col-xl-6">{{ user.last_name }} {{ user.first_name }}</dd> <dd class="col-xl-6">{{ user_object.last_name }} {{ user_object.first_name }}</dd>
<dt class="col-xl-6">{% trans 'username'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'username'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.username }}</dd> <dd class="col-xl-6">{{ user_object.username }}</dd>
{% if user.pk == user.pk %} {% if user_object.pk == user_object.pk %}
<dt class="col-xl-6">{% trans 'password'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'password'|capfirst %}</dt>
<dd class="col-xl-6"> <dd class="col-xl-6">
<a class="small" href="{% url 'password_change' %}"> <a class="small" href="{% url 'password_change' %}">
@ -27,25 +27,25 @@
{% endif %} {% endif %}
<dt class="col-xl-6">{% trans 'section'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'section'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.profile.section }}</dd> <dd class="col-xl-6">{{ user_object.profile.section }}</dd>
<dt class="col-xl-6">{% trans 'address'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'address'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.profile.address }}</dd> <dd class="col-xl-6">{{ user_object.profile.address }}</dd>
<dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.note.balance | pretty_money }}</dd> <dd class="col-xl-6">{{ user_object.note.balance | pretty_money }}</dd>
<dt class="col-xl-6"> <a href="{% url 'member:user_alias' user.pk %}">{% trans 'aliases'|capfirst %}</a></dt> <dt class="col-xl-6"> <a href="{% url 'member:user_alias' user_object.pk %}">{% trans 'aliases'|capfirst %}</a></dt>
<dd class="col-xl-6 text-truncate">{{ user.note.alias_set.all|join:", " }}</dd> <dd class="col-xl-6 text-truncate">{{ user_object.note.alias_set.all|join:", " }}</dd>
</dl> </dl>
{% if user.pk == user.pk %} {% if user_object.pk == user_object.pk %}
<a class="small" href="{% url 'member:auth_token' %}">{% trans 'Manage auth token' %}</a> <a class="small" href="{% url 'member:auth_token' %}">{% trans 'Manage auth token' %}</a>
{% endif %} {% endif %}
</div> </div>
<div class="card-footer text-center"> <div class="card-footer text-center">
<a class="btn btn-primary btn-sm" href="{% url 'member:user_update_profile' user.pk %}">{% trans 'Update Profile' %}</a> <a class="btn btn-primary btn-sm" href="{% url 'member:user_update_profile' user_object.pk %}">{% trans 'Update Profile' %}</a>
{% url 'member:user_detail' user.pk as user_profile_url %} {% url 'member:user_detail' user_object.pk as user_profile_url %}
{%if request.path_info != user_profile_url %} {%if request.path_info != user_profile_url %}
<a class="btn btn-primary btn-sm" href="{{ user_profile_url }}">{% trans 'View Profile' %}</a> <a class="btn btn-primary btn-sm" href="{{ user_profile_url }}">{% trans 'View Profile' %}</a>
{% endif %} {% endif %}

View File

@ -2,10 +2,10 @@
{% load i18n %} {% load i18n %}
{% load perms %} {% load perms %}
{% if not object.profile.email_confirmed and "member.change_profile_email_confirmed"|has_perm:user.profile %} {% if not object.profile.email_confirmed and "member.change_profile_email_confirmed"|has_perm:user_object.profile %}
<div class="alert alert-warning"> <div class="alert alert-warning">
{% trans "This user doesn't have confirmed his/her e-mail address." %} {% trans "This user doesn't have confirmed his/her e-mail address." %}
<a href="{% url "registration:email_validation_resend" pk=user.pk %}">{% trans "Click here to resend a validation link." %}</a> <a href="{% url "registration:email_validation_resend" pk=user_object.pk %}">{% trans "Click here to resend a validation link." %}</a>
</div> </div>
{% endif %} {% endif %}
@ -22,7 +22,7 @@
<div class="card"> <div class="card">
<div class="card-header position-relative" id="historyListHeading"> <div class="card-header position-relative" id="historyListHeading">
<a class="stretched-link font-weight-bold" {% if "note.view_note"|has_perm:user.note %} href="{% url 'note:transactions' pk=user.note.pk %}" {% endif %}> <a class="stretched-link font-weight-bold" {% if "note.view_note"|has_perm:user_object.note %} href="{% url 'note:transactions' pk=user_object.note.pk %}" {% endif %}>
<i class="fa fa-euro"></i> {% trans "Transaction history" %} <i class="fa fa-euro"></i> {% trans "Transaction history" %}
</a> </a>
</div> </div>

View File

@ -15,6 +15,16 @@
$("#profile_infos").load("{% url 'wei:wei_detail' pk=object.pk %} #profile_infos"); $("#profile_infos").load("{% url 'wei:wei_detail' pk=object.pk %} #profile_infos");
} }
window.history.replaceState({}, document.title, location.pathname); $(document).ready(function() {
$(".no-perm").parent().addClass("d-none");
if ($("a[data-type='validate-membership']:not(.d-none)").length === 0) {
$("a[data-type='validate-membership']").parent().addClass("d-none");
$("#validate-membership-header").addClass("d-none");
}
if ($("a[data-type='delete-membership']:not(.d-none)").length === 0) {
$("a[data-type='delete-membership']").parent().addClass("d-none");
$("#delete-membership-header").addClass("d-none");
}
});
</script> </script>
{% endblock %} {% endblock %}

View File

@ -166,7 +166,9 @@
</div> </div>
{% else %} {% else %}
<div class="alert alert-success"> <div class="alert alert-success">
{% trans "The note has enough money, the registration is possible." %} {% blocktrans trimmed with pretty_fee=fee|pretty_money %}
The note has enough money ({{ pretty_fee }} required), the registration is possible.
{% endblocktrans %}
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -178,14 +180,12 @@
{% endif %} {% endif %}
{% if not kfet_member %} {% if not kfet_member %}
<div class="alert alert-danger"> <div class="alert alert-warning">
{% url 'registration:future_user_detail' pk=registration.user.pk as future_user_detail %} {% url 'registration:future_user_detail' pk=registration.user.pk as future_user_detail %}
{% url 'member:club_detail' pk=club.parent_club.parent_club.pk as club_detail %} {% url 'member:club_detail' pk=club.parent_club.parent_club.pk as club_detail %}
{% blocktrans trimmed %} {% blocktrans trimmed %}
This user is not a member of the Kfet club for the comming year. Please adhere This user is not a member of the Kfet club for the coming year. The membership will be
<a href="{{ future_user_detail }}">here if he/she is in her/his first year</a> processed automatically, the WEI registration includes the membership fee.
or <a href="{{ club_detail }}">here if he/she was an old member</a> before you validate
the registration of the WEI.
{% endblocktrans %} {% endblocktrans %}
</div> </div>
{% endif %} {% endif %}

View File

@ -41,6 +41,16 @@
} }
searchbar_obj.keyup(reloadTable); searchbar_obj.keyup(reloadTable);
$(".no-perm").parent().addClass("d-none");
if ($("a[data-type='validate-membership']:not(.d-none)").length === 0) {
$("a[data-type='validate-membership']").parent().addClass("d-none");
$("#validate-membership-header").addClass("d-none");
}
if ($("a[data-type='delete-membership']:not(.d-none)").length === 0) {
$("a[data-type='delete-membership']").parent().addClass("d-none");
$("#delete-membership-header").addClass("d-none");
}
}); });
</script> </script>
{% endblock %} {% endblock %}