mirror of https://gitlab.crans.org/bde/nk20
The BDE offers 80 € to each new member that registers to the Société générale
This commit is contained in:
parent
dc6a5f56f6
commit
fa3c723140
|
@ -27,8 +27,8 @@ def create_bde_and_kfet(apps, schema_editor):
|
|||
parent_club_id=1,
|
||||
email="tresorerie.bde@example.com",
|
||||
require_memberships=True,
|
||||
membership_fee_paid=500,
|
||||
membership_fee_unpaid=500,
|
||||
membership_fee_paid=3500,
|
||||
membership_fee_unpaid=3500,
|
||||
membership_duration=396,
|
||||
membership_start="2020-08-01",
|
||||
membership_end="2021-09-30",
|
||||
|
|
|
@ -138,7 +138,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
|||
"""
|
||||
We can't display information of a not registered user.
|
||||
"""
|
||||
return super().get_queryset().filter(profile__registration_valid=True)
|
||||
return super().get_queryset(**kwargs).filter(profile__registration_valid=True)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""
|
||||
|
|
|
@ -175,7 +175,7 @@ class Transaction(PolymorphicModel):
|
|||
|
||||
created = self.pk is None
|
||||
to_transfer = self.amount * self.quantity
|
||||
if not created:
|
||||
if not created and not self.valid and not hasattr(self, "_force_save"):
|
||||
# Revert old transaction
|
||||
old_transaction = Transaction.objects.get(pk=self.pk)
|
||||
# Check that nothing important changed
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.contrib.auth.models import User
|
|||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.forms import HiddenInput
|
||||
from django.http import Http404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import UpdateView, TemplateView, CreateView
|
||||
from member.models import Membership
|
||||
|
@ -24,9 +25,20 @@ class ProtectQuerysetMixin:
|
|||
Display 404 error if the user can't see an object, remove the fields the user can't
|
||||
update on an update form (useful if the user can't change only specified fields).
|
||||
"""
|
||||
def get_queryset(self, **kwargs):
|
||||
def get_queryset(self, filter_permissions=True, **kwargs):
|
||||
qs = super().get_queryset(**kwargs)
|
||||
return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view")).distinct()
|
||||
return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view")).distinct()\
|
||||
if filter_permissions else qs
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
try:
|
||||
return super().get_object(queryset)
|
||||
except Http404 as e:
|
||||
try:
|
||||
super().get_object(self.get_queryset(filter_permissions=False))
|
||||
raise PermissionDenied()
|
||||
except Http404:
|
||||
raise e
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
|
|
|
@ -364,7 +364,7 @@ class TestValidateRegistration(TestCase):
|
|||
self.assertTrue(Membership.objects.filter(club__name="Kfet", user=self.user).exists())
|
||||
self.assertTrue(SogeCredit.objects.filter(user=self.user).exists())
|
||||
self.assertEqual(Transaction.objects.filter(
|
||||
Q(source=self.user.note) | Q(destination=self.user.note)).count(), 2)
|
||||
Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
|
||||
self.assertFalse(Transaction.objects.filter(valid=True).exists())
|
||||
|
||||
response = self.client.get(self.user.profile.get_absolute_url())
|
||||
|
|
|
@ -21,6 +21,7 @@ from note.templatetags.pretty_money import pretty_money
|
|||
from permission.backends import PermissionBackend
|
||||
from permission.models import Role
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from treasury.models import SogeCredit
|
||||
|
||||
from .forms import SignUpForm, ValidationForm
|
||||
from .tables import FutureUserTable
|
||||
|
@ -219,6 +220,9 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
|
|||
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
|
||||
# In 2020, for COVID-19 reasons, the BDE offered 80 € to each new member that opens a Sogé account,
|
||||
# since there is no WEI.
|
||||
fee += 8000
|
||||
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
|
||||
|
||||
return ctx
|
||||
|
@ -342,6 +346,11 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
|
|||
membership.roles.add(Role.objects.get(name="Adhérent Kfet"))
|
||||
membership.save()
|
||||
|
||||
if soge:
|
||||
soge_credit = SogeCredit.objects.get(user=user)
|
||||
# Update the credit transaction amount
|
||||
soge_credit.save()
|
||||
|
||||
return ret
|
||||
|
||||
def get_success_url(self):
|
||||
|
|
|
@ -291,11 +291,11 @@ class SogeCredit(models.Model):
|
|||
|
||||
@property
|
||||
def valid(self):
|
||||
return self.credit_transaction is not None
|
||||
return self.credit_transaction.valid
|
||||
|
||||
@property
|
||||
def amount(self):
|
||||
return sum(transaction.total for transaction in self.transactions.all())
|
||||
return sum(transaction.total for transaction in self.transactions.all()) + 8000
|
||||
|
||||
def invalidate(self):
|
||||
"""
|
||||
|
@ -304,11 +304,7 @@ class SogeCredit(models.Model):
|
|||
"""
|
||||
if self.valid:
|
||||
self.credit_transaction.valid = False
|
||||
self.credit_transaction._force_save = True
|
||||
self.credit_transaction.save()
|
||||
self.credit_transaction._force_delete = True
|
||||
self.credit_transaction.delete()
|
||||
self.credit_transaction = None
|
||||
for transaction in self.transactions.all():
|
||||
transaction.valid = False
|
||||
transaction._force_save = True
|
||||
|
@ -321,17 +317,10 @@ class SogeCredit(models.Model):
|
|||
|
||||
# First invalidate all transaction and delete the credit if already did (and force mode)
|
||||
self.invalidate()
|
||||
self.credit_transaction = SpecialTransaction.objects.create(
|
||||
source=NoteSpecial.objects.get(special_type="Virement bancaire"),
|
||||
destination=self.user.note,
|
||||
quantity=1,
|
||||
amount=self.amount,
|
||||
reason="Crédit société générale",
|
||||
last_name=self.user.last_name,
|
||||
first_name=self.user.first_name,
|
||||
bank="Société générale",
|
||||
created_at=self.transactions.order_by("-created_at").first().created_at,
|
||||
)
|
||||
# Refresh credit amount
|
||||
self.save()
|
||||
self.credit_transaction.valid = True
|
||||
self.credit_transaction.save()
|
||||
self.save()
|
||||
|
||||
for transaction in self.transactions.all():
|
||||
|
@ -340,6 +329,25 @@ class SogeCredit(models.Model):
|
|||
transaction.created_at = timezone.now()
|
||||
transaction.save()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.credit_transaction:
|
||||
self.credit_transaction = SpecialTransaction.objects.create(
|
||||
source=NoteSpecial.objects.get(special_type="Virement bancaire"),
|
||||
destination=self.user.note,
|
||||
quantity=1,
|
||||
amount=0,
|
||||
reason="Crédit société générale",
|
||||
last_name=self.user.last_name,
|
||||
first_name=self.user.first_name,
|
||||
bank="Société générale",
|
||||
valid=False,
|
||||
)
|
||||
elif not self.valid:
|
||||
self.credit_transaction.amount = self.amount
|
||||
self.credit_transaction._force_save = True
|
||||
self.credit_transaction.save()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def delete(self, **kwargs):
|
||||
"""
|
||||
Deleting a SogeCredit is equivalent to say that the Société générale didn't pay.
|
||||
|
@ -358,6 +366,9 @@ class SogeCredit(models.Model):
|
|||
transaction.valid = True
|
||||
transaction.created_at = timezone.now()
|
||||
transaction.save()
|
||||
self.credit_transaction.valid = False
|
||||
self.credit_transaction.reason += " (invalide)"
|
||||
self.credit_transaction.save()
|
||||
super().delete(**kwargs)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -30,7 +30,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
|
||||
<div class="form-check">
|
||||
<label for="invalid_only" class="form-check-label">
|
||||
<input id="invalid_only" name="invalid_only" type="checkbox" class="checkboxinput form-check-input">
|
||||
<input id="invalid_only" name="invalid_only" type="checkbox" class="checkboxinput form-check-input" checked>
|
||||
{% trans "Filter with unvalidated credits only" %}
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -353,7 +353,6 @@ class TestSogeCredits(TestCase):
|
|||
soge_credit.refresh_from_db()
|
||||
self.assertTrue(soge_credit.valid)
|
||||
self.user.note.refresh_from_db()
|
||||
self.assertEqual(self.user.note.balance, 0)
|
||||
self.assertEqual(
|
||||
Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
|
||||
self.assertTrue(self.user.profile.soge)
|
||||
|
@ -391,7 +390,7 @@ class TestSogeCredits(TestCase):
|
|||
self.user.note.refresh_from_db()
|
||||
self.assertEqual(self.user.note.balance, 0)
|
||||
self.assertEqual(
|
||||
Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
|
||||
Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 4)
|
||||
self.assertFalse(self.user.profile.soge)
|
||||
|
||||
def test_invoice_api(self):
|
||||
|
|
|
@ -425,11 +425,8 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
|
|||
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||
)
|
||||
|
||||
if "valid" in self.request.GET:
|
||||
q = Q(credit_transaction=None)
|
||||
if not self.request.GET["valid"]:
|
||||
q = ~q
|
||||
qs = qs.filter(q)
|
||||
if "valid" not in self.request.GET or not self.request.GET["valid"]:
|
||||
qs = qs.filter(credit_transaction__valid=False)
|
||||
|
||||
return qs[:20]
|
||||
|
||||
|
|
Loading…
Reference in New Issue