mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	✨ Adhere to parent clubs automatically, adhere to Kfet automatically when registering to the WEI
This commit is contained in:
		| @@ -10,6 +10,7 @@ from django.core.exceptions import ValidationError | ||||
| from django.db import models | ||||
| from django.template import loader | ||||
| from django.urls import reverse, reverse_lazy | ||||
| from django.utils import timezone | ||||
| from django.utils.encoding import force_bytes | ||||
| from django.utils.http import urlsafe_base64_encode | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| @@ -301,13 +302,34 @@ class Membership(models.Model): | ||||
|         else: | ||||
|             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): | ||||
|         """ | ||||
|         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: | ||||
|             for role in self.roles.all(): | ||||
| @@ -327,17 +349,54 @@ class Membership(models.Model): | ||||
|             ).exists(): | ||||
|                 raise ValidationError(_('User is already a member of the club')) | ||||
|  | ||||
|             if self.user.profile.paid: | ||||
|                 self.fee = self.club.membership_fee_paid | ||||
|             else: | ||||
|                 self.fee = self.club.membership_fee_unpaid | ||||
|         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.club.membership_duration is not None: | ||||
|                 self.date_end = self.date_start + datetime.timedelta(days=self.club.membership_duration) | ||||
|             else: | ||||
|                 self.date_end = self.date_start + datetime.timedelta(days=424242) | ||||
|             if self.club.membership_end is not None and self.date_end > self.club.membership_end: | ||||
|                 self.date_end = self.club.membership_end | ||||
|         if self.user.profile.paid: | ||||
|             self.fee = self.club.membership_fee_paid | ||||
|         else: | ||||
|             self.fee = self.club.membership_fee_unpaid | ||||
|  | ||||
|         if self.club.membership_duration is not None: | ||||
|             self.date_end = self.date_start + datetime.timedelta(days=self.club.membership_duration) | ||||
|         else: | ||||
|             self.date_end = self.date_start + datetime.timedelta(days=424242) | ||||
|         if self.club.membership_end is not None and self.date_end > self.club.membership_end: | ||||
|             self.date_end = self.club.membership_end | ||||
|  | ||||
|         super().save(*args, **kwargs) | ||||
|  | ||||
| @@ -360,8 +419,9 @@ class Membership(models.Model): | ||||
|                 reason="Adhésion " + self.club.name, | ||||
|             ) | ||||
|             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 | ||||
|                 # to treasurers. | ||||
|                 transaction.valid = False | ||||
|   | ||||
| @@ -442,6 +442,16 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|                 .get(pk=self.kwargs["club_pk"], weiclub=None) | ||||
|             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 club.name != "BDE": | ||||
|                 del form.fields['soge'] | ||||
| @@ -454,26 +464,54 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|                 context["total_fee"] = "{:.02f}".format(fee / 100, ) | ||||
|         else: | ||||
|             # This is a renewal. Fields can be pre-completed. | ||||
|             context["renewal"] = True | ||||
|  | ||||
|             old_membership = self.get_queryset().get(pk=self.kwargs["pk"]) | ||||
|             club = old_membership.club | ||||
|             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'].disabled = True | ||||
|             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 \ | ||||
|                 else club.membership_fee_unpaid | ||||
|             form.fields['credit_amount'].initial = (club.membership_fee_paid if user.profile.paid | ||||
|                 else club.membership_fee_unpaid) + additional_fee_renewal | ||||
|             form.fields['last_name'].initial = user.last_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 club.name != "BDE" or user.profile.soge: | ||||
|             if (club.name != "BDE" and club.name != "Kfet") or user.profile.soge: | ||||
|                 del form.fields['soge'] | ||||
|             else: | ||||
|                 fee = 0 | ||||
|                 bde = Club.objects.get(name="BDE") | ||||
|                 fee += bde.membership_fee_paid if user.profile.paid else bde.membership_fee_unpaid | ||||
|                 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 | ||||
|                 kfet = Club.objects.get(name="Kfet") | ||||
|                 fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid | ||||
|                 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 | ||||
|                 context["total_fee"] = "{:.02f}".format(fee / 100, ) | ||||
|  | ||||
|         context['club'] = club | ||||
| @@ -502,7 +540,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|         last_name = form.cleaned_data["last_name"] | ||||
|         first_name = form.cleaned_data["first_name"] | ||||
|         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 | ||||
|         # later. The membership transaction will be invalidated. | ||||
| @@ -513,10 +551,17 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|         if credit_type is None: | ||||
|             credit_amount = 0 | ||||
|  | ||||
|         if user.profile.paid: | ||||
|             fee = club.membership_fee_paid | ||||
|         else: | ||||
|             fee = club.membership_fee_unpaid | ||||
|         fee = 0 | ||||
|         c = club | ||||
|         while c is not None: | ||||
|             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( | ||||
|                 club__name="Kfet", | ||||
|                 user=user, | ||||
| @@ -524,22 +569,11 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|                 date_end__gte=datetime.now().date(), | ||||
|         ).exists(): | ||||
|             # 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 | ||||
|             form.add_error('user', | ||||
|                            _("This user don't have enough money to join this club, and can't have a negative balance.")) | ||||
|             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( | ||||
|                 user=form.instance.user, | ||||
|                 club=club, | ||||
| @@ -561,7 +595,7 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|  | ||||
|         # 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. | ||||
|             # 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. | ||||
| @@ -593,6 +627,8 @@ class ClubAddMemberView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): | ||||
|             transaction._force_save = True | ||||
|             transaction.save() | ||||
|  | ||||
|         form.instance._force_renew_parent = True | ||||
|  | ||||
|         ret = super().form_valid(form) | ||||
|  | ||||
|         member_role = Role.objects.filter(name="Membre de club").all() | ||||
| @@ -603,33 +639,40 @@ 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 | ||||
|         # Kfet membership. | ||||
|         if soge: | ||||
|             # If not already done, create BDE and Kfet memberships | ||||
|             bde = Club.objects.get(name="BDE") | ||||
|             kfet = Club.objects.get(name="Kfet") | ||||
|             kfet_fee = kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid | ||||
|  | ||||
|             # Get current membership, to get the end date | ||||
|             old_membership = Membership.objects.filter( | ||||
|                 club__name="Kfet", | ||||
|                 user=user, | ||||
|                 date_start__lte=datetime.today(), | ||||
|                 date_end__gte=datetime.today(), | ||||
|             ) | ||||
|             soge_clubs = [bde, kfet] | ||||
|             for club in soge_clubs: | ||||
|                 fee = club.membership_fee_paid if user.profile.paid else club.membership_fee_unpaid | ||||
|  | ||||
|             membership = Membership( | ||||
|                 club=kfet, | ||||
|                 user=user, | ||||
|                 fee=kfet_fee, | ||||
|                 date_start=old_membership.get().date_end + timedelta(days=1) | ||||
|                 if old_membership.exists() else form.instance.date_start, | ||||
|             ) | ||||
|             membership._force_save = True | ||||
|             membership._soge = True | ||||
|             membership.save() | ||||
|             membership.refresh_from_db() | ||||
|             if old_membership.exists(): | ||||
|                 membership.roles.set(old_membership.get().roles.all()) | ||||
|             else: | ||||
|                 membership.roles.add(Role.objects.get(name="Adhérent Kfet")) | ||||
|             membership.save() | ||||
|                 # Get current membership, to get the end date | ||||
|                 old_membership = Membership.objects.filter( | ||||
|                     club=club, | ||||
|                     user=user, | ||||
|                 ).order_by("-date_start") | ||||
|  | ||||
|                 if old_membership.filter(date_start__gte=club.membership_start).exists(): | ||||
|                     # Membership is already renewed | ||||
|                     continue | ||||
|  | ||||
|                 membership = Membership( | ||||
|                     club=club, | ||||
|                     user=user, | ||||
|                     fee=fee, | ||||
|                     date_start=max(old_membership.first().date_end + timedelta(days=1), club.membership_start) | ||||
|                     if old_membership.exists() else form.instance.date_start, | ||||
|                 ) | ||||
|                 membership._force_save = True | ||||
|                 membership._soge = True | ||||
|                 membership.save() | ||||
|                 membership.refresh_from_db() | ||||
|                 if old_membership.exists(): | ||||
|                     membership.roles.set(old_membership.get().roles.all()) | ||||
|                 else: | ||||
|                     membership.roles.add(Role.objects.get(name="Adhérent Kfet")) | ||||
|                 membership.save() | ||||
|  | ||||
|         return ret | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user