diff --git a/.env_example b/.env_example
index 7e1dbd3..1793552 100644
--- a/.env_example
+++ b/.env_example
@@ -1,4 +1,4 @@
-DJANGO_APP_STAGE=prod
+DJANGO_APP_STAGE=dev
# Only used in dev mode, change to "postgresql" if you want to use PostgreSQL in dev
DJANGO_DEV_STORE_METHOD=sqlite
DJANGO_DB_HOST=localhost
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 0000000..0eb3a46
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,39 @@
+# This configuration file was automatically generated by Gitpod.
+# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
+# and commit this file to your remote git repository to share the goodness with others.
+
+tasks:
+ - name: Apt install
+ command: |
+ sudo apt update
+ sudo apt install --no-install-recommends -y \
+ ipython3 python3-setuptools python3-venv python3-dev \
+ texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome git
+ gp sync-done apt
+ - name : Install requirements
+ init : gp sync-await apt
+ command: |
+ pip3 install -r requirements.txt
+ gp sync-done pip
+ - name : Setup env
+ command: cp .env_example .env
+ - name: Django Init
+ init : gp sync-await pip
+ command: |
+ python3 manage.py collectstatic --noinput
+ python3 manage.py compilemessages
+ python3 manage.py makemigrations
+ python3 manage.py migrate
+ python3 manage.py loaddata initial
+ python3 manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'adminpass')"
+ gp sync-done django
+
+ - name: Django start server
+ init : gp sync-await django
+ command: python3 manage.py runserver 0.0.0.0:8000
+ports:
+ - port: 8000
+ onOpen: open-preview
+
+
+
diff --git a/apps/member/templates/member/add_members.html b/apps/member/templates/member/add_members.html
index 4fd1a83..07b4931 100644
--- a/apps/member/templates/member/add_members.html
+++ b/apps/member/templates/member/add_members.html
@@ -60,17 +60,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
});
}
- soge_field = $("#id_soge");
function fillFields() {
- let checked = soge_field.is(':checked');
- if (!checked) {
- $("input").attr('disabled', false);
- $("#id_user").attr('disabled', true);
- $("select").attr('disabled', false);
- return;
- }
-
let credit_type = $("#id_credit_type");
credit_type.attr('disabled', true);
credit_type.val(4);
@@ -83,7 +74,5 @@ SPDX-License-Identifier: GPL-3.0-or-later
bank.attr('disabled', true);
bank.val('Société générale');
}
-
- soge_field.change(fillFields);
{% endblock %}
\ No newline at end of file
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
index 149779a..07d7bfa 100644
--- a/apps/permission/fixtures/initial.json
+++ b/apps/permission/fixtures/initial.json
@@ -1095,70 +1095,6 @@
"description": "Supprimer un produit"
}
},
- {
- "model": "permission.permission",
- "pk": 70,
- "fields": {
- "model": [
- "treasury",
- "sogecredit"
- ],
- "query": "{}",
- "type": "add",
- "mask": 1,
- "field": "",
- "permanent": false,
- "description": "Ajouter un crédit de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale"
- }
- },
- {
- "model": "permission.permission",
- "pk": 71,
- "fields": {
- "model": [
- "treasury",
- "sogecredit"
- ],
- "query": "{}",
- "type": "view",
- "mask": 3,
- "field": "",
- "permanent": false,
- "description": "Voir tous les crédits de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale"
- }
- },
- {
- "model": "permission.permission",
- "pk": 72,
- "fields": {
- "model": [
- "treasury",
- "sogecredit"
- ],
- "query": "{}",
- "type": "change",
- "mask": 1,
- "field": "",
- "permanent": false,
- "description": "Modifier un crédit de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale"
- }
- },
- {
- "model": "permission.permission",
- "pk": 73,
- "fields": {
- "model": [
- "treasury",
- "sogecredit"
- ],
- "query": "{}",
- "type": "delete",
- "mask": 3,
- "field": "",
- "permanent": false,
- "description": "Supprimer un crédit de la Soci\u00e9t\u00e9 g\u00e9n\u00e9rale"
- }
- },
{
"model": "permission.permission",
"pk": 145,
@@ -2044,7 +1980,6 @@
36,
39,
40,
- 70,
152,
153,
154,
@@ -2171,9 +2106,6 @@
67,
68,
69,
- 71,
- 72,
- 73,
146,
147,
150,
@@ -2270,10 +2202,6 @@
67,
68,
69,
- 70,
- 71,
- 72,
- 73,
145,
146,
147,
@@ -2351,8 +2279,6 @@
29,
30,
31,
- 70,
- 72,
166,
167,
168,
@@ -2439,8 +2365,6 @@
56,
57,
58,
- 70,
- 72,
147,
150,
166,
diff --git a/apps/permission/tests/test_permission_denied.py b/apps/permission/tests/test_permission_denied.py
index 1aa3e9e..4a86375 100644
--- a/apps/permission/tests/test_permission_denied.py
+++ b/apps/permission/tests/test_permission_denied.py
@@ -146,9 +146,6 @@ class TestPermissionDenied(TestCase):
response = self.client.get(reverse("treasury:remittance_list"))
self.assertEqual(response.status_code, 403)
- def test_list_soge_credits(self):
- response = self.client.get(reverse("treasury:soge_credits"))
- self.assertEqual(response.status_code, 403)
class TestLoginRedirect(TestCase):
diff --git a/apps/registration/forms.py b/apps/registration/forms.py
index b3d8ec0..e867c81 100644
--- a/apps/registration/forms.py
+++ b/apps/registration/forms.py
@@ -44,25 +44,11 @@ class SignUpForm(UserCreationForm):
fields = ('first_name', 'last_name', 'username', 'email', )
-class DeclareSogeAccountOpenedForm(forms.Form):
- soge_account = forms.BooleanField(
- label=_("I declare that I opened or I will open soon a bank account in the Société générale with the BDE "
- "partnership."),
- help_text=_("Warning: this engages you to open your bank account. If you finally decides to don't open your "
- "account, you will have to pay the BDE membership."),
- required=False,
- )
-
class ValidationForm(forms.Form):
"""
Validate the inscription of the new users and pay memberships.
"""
- soge = forms.BooleanField(
- label=_("Inscription paid by Société Générale"),
- required=False,
- help_text=_("Check this case if the Société Générale paid the inscription."),
- )
credit_type = forms.ModelChoiceField(
queryset=NoteSpecial.objects,
diff --git a/apps/registration/tables.py b/apps/registration/tables.py
index 960866a..10b439d 100644
--- a/apps/registration/tables.py
+++ b/apps/registration/tables.py
@@ -3,7 +3,6 @@
import django_tables2 as tables
from django.contrib.auth.models import User
-from treasury.models import SogeCredit
class FutureUserTable(tables.Table):
@@ -22,7 +21,6 @@ class FutureUserTable(tables.Table):
fields = ('last_name', 'first_name', 'username', 'email', )
model = User
row_attrs = {
- 'class': lambda record: 'table-row'
- + (' bg-warning' if SogeCredit.objects.filter(user=record).exists() else ''),
+ 'class': lambda record: 'table-row',
'data-href': lambda record: record.pk
}
diff --git a/apps/registration/templates/registration/future_profile_detail.html b/apps/registration/templates/registration/future_profile_detail.html
index 577ad21..bb42475 100644
--- a/apps/registration/templates/registration/future_profile_detail.html
+++ b/apps/registration/templates/registration/future_profile_detail.html
@@ -57,12 +57,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
- {% trans "The user declared that he/she opened a bank account in the Société générale." %}
-
- {% endif %}
-
{% csrf_token %}
{{ form|crispy }}
@@ -78,16 +72,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% block extrajavascript %}
{% endblock %}
diff --git a/apps/registration/tests/test_registration.py b/apps/registration/tests/test_registration.py
index 18cf16d..4bf27fa 100644
--- a/apps/registration/tests/test_registration.py
+++ b/apps/registration/tests/test_registration.py
@@ -10,7 +10,6 @@ from django.utils.http import urlsafe_base64_encode
from member.models import Club, Membership
from note.models import NoteUser, NoteSpecial, Transaction
from registration.tokens import email_validation_token
-from treasury.models import SogeCredit
"""
Check that pre-registrations and validations are working as well.
@@ -190,7 +189,6 @@ class TestValidateRegistration(TestCase):
# BDE Membership is mandatory
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Chèque").id,
credit_amount=4200,
last_name="TOTO",
@@ -204,7 +202,6 @@ class TestValidateRegistration(TestCase):
# Same
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type="",
credit_amount=0,
last_name="TOTO",
@@ -218,7 +215,6 @@ class TestValidateRegistration(TestCase):
# The BDE membership is not free
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Espèces").id,
credit_amount=0,
last_name="TOTO",
@@ -232,7 +228,6 @@ class TestValidateRegistration(TestCase):
# Last and first names are required for a credit
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Chèque").id,
credit_amount=4000,
last_name="",
@@ -249,7 +244,6 @@ class TestValidateRegistration(TestCase):
self.user.username = "admïntoto"
self.user.save()
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Chèque").id,
credit_amount=500,
last_name="TOTO",
@@ -275,7 +269,6 @@ class TestValidateRegistration(TestCase):
self.user.profile.save()
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Chèque").id,
credit_amount=500,
last_name="TOTO",
@@ -290,7 +283,6 @@ class TestValidateRegistration(TestCase):
self.assertTrue(NoteUser.objects.filter(user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="BDE", user=self.user).exists())
self.assertFalse(Membership.objects.filter(club__name="Kfet", user=self.user).exists())
- self.assertFalse(SogeCredit.objects.filter(user=self.user).exists())
self.assertEqual(Transaction.objects.filter(
Q(source=self.user.note) | Q(destination=self.user.note)).count(), 2)
@@ -311,7 +303,6 @@ class TestValidateRegistration(TestCase):
self.user.profile.save()
response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=False,
credit_type=NoteSpecial.objects.get(special_type="Espèces").id,
credit_amount=4000,
last_name="TOTO",
@@ -326,49 +317,12 @@ class TestValidateRegistration(TestCase):
self.assertTrue(NoteUser.objects.filter(user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="BDE", user=self.user).exists())
self.assertTrue(Membership.objects.filter(club__name="Kfet", user=self.user).exists())
- self.assertFalse(SogeCredit.objects.filter(user=self.user).exists())
self.assertEqual(Transaction.objects.filter(
Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
response = self.client.get(self.user.profile.get_absolute_url())
self.assertEqual(response.status_code, 200)
- def test_validate_kfet_registration_with_soge(self):
- """
- The user joins the BDE and the Kfet, but the membership is paid by the Société générale.
- """
- response = self.client.get(reverse("registration:future_user_detail", args=(self.user.pk,)))
- self.assertEqual(response.status_code, 200)
-
- response = self.client.get(self.user.profile.get_absolute_url())
- self.assertEqual(response.status_code, 404)
-
- self.user.profile.email_confirmed = True
- self.user.profile.save()
-
- response = self.client.post(reverse("registration:future_user_detail", args=(self.user.pk,)), data=dict(
- soge=True,
- credit_type=NoteSpecial.objects.get(special_type="Espèces").id,
- credit_amount=4000,
- last_name="TOTO",
- first_name="Toto",
- bank="Société générale",
- join_bde=True,
- join_kfet=True,
- ))
- self.assertRedirects(response, self.user.profile.get_absolute_url(), 302, 200)
- self.user.profile.refresh_from_db()
- self.assertTrue(self.user.profile.registration_valid)
- self.assertTrue(NoteUser.objects.filter(user=self.user).exists())
- self.assertTrue(Membership.objects.filter(club__name="BDE", user=self.user).exists())
- 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(), 3)
- self.assertFalse(Transaction.objects.filter(valid=True).exists())
-
- response = self.client.get(self.user.profile.get_absolute_url())
- self.assertEqual(response.status_code, 200)
def test_invalidate_registration(self):
"""
diff --git a/apps/registration/views.py b/apps/registration/views.py
index b256f59..684d9fc 100644
--- a/apps/registration/views.py
+++ b/apps/registration/views.py
@@ -22,9 +22,8 @@ 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, DeclareSogeAccountOpenedForm
+from .forms import SignUpForm, ValidationForm
from .tables import FutureUserTable
from .tokens import email_validation_token
@@ -42,7 +41,6 @@ class UserCreateView(CreateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["profile_form"] = self.second_form(self.request.POST if self.request.POST else None)
- context["soge_form"] = DeclareSogeAccountOpenedForm(self.request.POST if self.request.POST else None)
del context["profile_form"].fields["section"]
del context["profile_form"].fields["report_frequency"]
del context["profile_form"].fields["last_report"]
@@ -75,13 +73,6 @@ class UserCreateView(CreateView):
user.profile.send_email_validation_link()
- soge_form = DeclareSogeAccountOpenedForm(self.request.POST)
- if "soge_account" in soge_form.data and soge_form.data["soge_account"]:
- # If the user declares that a bank account got opened, prepare the soge credit to warn treasurers
- soge_credit = SogeCredit(user=user)
- soge_credit._force_save = True
- soge_credit.save()
-
return super().form_valid(form)
def get_success_url(self):
@@ -239,8 +230,6 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
fee += kfet.membership_fee_paid if user.profile.paid else kfet.membership_fee_unpaid
ctx["total_fee"] = "{:.02f}".format(fee / 100, )
- ctx["declare_soge_account"] = SogeCredit.objects.filter(user=user).exists()
-
return ctx
def get_form(self, form_class=None):
@@ -263,7 +252,6 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
return self.form_invalid(form)
# Get form data
- soge = form.cleaned_data["soge"]
credit_type = form.cleaned_data["credit_type"]
credit_amount = form.cleaned_data["credit_amount"]
last_name = form.cleaned_data["last_name"]
@@ -272,10 +260,6 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
join_bde = form.cleaned_data["join_bde"]
join_kfet = form.cleaned_data["join_kfet"]
- if soge:
- # If Société Générale pays the inscription, the user automatically joins the two clubs.
- join_bde = True
- join_kfet = True
if not join_bde:
# This software belongs to the BDE.
@@ -295,12 +279,12 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
# If the bank pays, then we don't credit now. Treasurers will validate the transaction
# and credit the note later.
- credit_type = None if soge else credit_type
+ credit_type = credit_type
# If the user does not select any payment method, then no credit will be performed.
credit_amount = 0 if credit_type is None else credit_amount
- if fee > credit_amount and not soge:
+ if fee > credit_amount:
# Check if the user credits enough money
form.add_error('credit_type',
_("The entered amount is not enough for the memberships, should be at least {}")
@@ -320,13 +304,6 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user.profile.save()
user.refresh_from_db()
- if not soge and SogeCredit.objects.filter(user=user).exists():
- # If the user declared that a bank account was opened but in the validation form the SoGé case was
- # unchecked, delete the associated credit
- soge_credit = SogeCredit.objects.get(user=user)
- soge_credit._force_delete = True
- soge_credit.delete()
-
if credit_type is not None and credit_amount > 0:
# Credit the note
SpecialTransaction.objects.create(
@@ -334,7 +311,7 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
destination=user.note,
quantity=1,
amount=credit_amount,
- reason="Crédit " + ("Société générale" if soge else credit_type.special_type) + " (Inscription)",
+ reason="Crédit " + credit_type.special_type + " (Inscription)",
last_name=last_name,
first_name=first_name,
bank=bank,
@@ -348,8 +325,6 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user=user,
fee=bde_fee,
)
- if soge:
- membership._soge = True
membership.save()
membership.refresh_from_db()
membership.roles.add(Role.objects.get(name="Adhérent BDE"))
@@ -362,18 +337,13 @@ class FutureUserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin,
user=user,
fee=kfet_fee,
)
- if soge:
- membership._soge = True
+
membership.save()
membership.refresh_from_db()
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):
@@ -393,8 +363,7 @@ class FutureUserInvalidateView(ProtectQuerysetMixin, LoginRequiredMixin, View):
user = User.objects.filter(profile__registration_valid=False)\
.filter(PermissionBackend.filter_queryset(request, User, "change", "is_valid"))\
.get(pk=self.kwargs["pk"])
- # Delete associated soge credits before
- SogeCredit.objects.filter(user=user).delete()
+
user.delete()
diff --git a/apps/treasury/admin.py b/apps/treasury/admin.py
index 5069e53..b71ca0a 100644
--- a/apps/treasury/admin.py
+++ b/apps/treasury/admin.py
@@ -5,7 +5,7 @@ from django.contrib import admin
from note_kfet.admin import admin_site
from .forms import ProductForm
-from .models import RemittanceType, Remittance, SogeCredit, Invoice, Product
+from .models import RemittanceType, Remittance, Invoice, Product
@admin.register(RemittanceType, site=admin_site)
@@ -27,19 +27,6 @@ class RemittanceAdmin(admin.ModelAdmin):
return not obj or (not obj.closed and super().has_change_permission(request, obj))
-@admin.register(SogeCredit, site=admin_site)
-class SogeCreditAdmin(admin.ModelAdmin):
- """
- Admin customisation for Remittance
- """
- list_display = ('user', 'valid',)
- readonly_fields = ('transactions', 'credit_transaction',)
-
- def has_add_permission(self, request):
- # Don't create a credit manually
- return False
-
-
class ProductInline(admin.StackedInline):
"""
Inline product in invoice admin
diff --git a/apps/treasury/api/serializers.py b/apps/treasury/api/serializers.py
index 5442fd0..7601618 100644
--- a/apps/treasury/api/serializers.py
+++ b/apps/treasury/api/serializers.py
@@ -4,7 +4,7 @@ from django.db import transaction
from rest_framework import serializers
from note.api.serializers import SpecialTransactionSerializer
-from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit
+from ..models import Invoice, Product, RemittanceType, Remittance
class ProductSerializer(serializers.ModelSerializer):
@@ -61,21 +61,3 @@ class RemittanceSerializer(serializers.ModelSerializer):
def get_transactions(self, obj):
return serializers.ListSerializer(child=SpecialTransactionSerializer()).to_representation(obj.transactions)
-
-class SogeCreditSerializer(serializers.ModelSerializer):
- """
- REST API Serializer for SogeCredit types.
- The djangorestframework plugin will analyse the model `SogeCredit` and parse all fields in the API.
- """
-
- @transaction.atomic
- def save(self, **kwargs):
- # Update soge transactions after creating a credit
- instance = super().save(**kwargs)
- instance.update_transactions()
- instance.save()
- return instance
-
- class Meta:
- model = SogeCredit
- fields = '__all__'
diff --git a/apps/treasury/api/urls.py b/apps/treasury/api/urls.py
index 90c9d33..17be8bf 100644
--- a/apps/treasury/api/urls.py
+++ b/apps/treasury/api/urls.py
@@ -1,7 +1,7 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
-from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet, SogeCreditViewSet
+from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet
def register_treasury_urls(router, path):
@@ -12,4 +12,3 @@ def register_treasury_urls(router, path):
router.register(path + '/product', ProductViewSet)
router.register(path + '/remittance_type', RemittanceTypeViewSet)
router.register(path + '/remittance', RemittanceViewSet)
- router.register(path + '/soge_credit', SogeCreditViewSet)
diff --git a/apps/treasury/api/views.py b/apps/treasury/api/views.py
index e6ba9ce..bd05cb2 100644
--- a/apps/treasury/api/views.py
+++ b/apps/treasury/api/views.py
@@ -5,9 +5,8 @@ from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from api.viewsets import ReadProtectedModelViewSet
-from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer,\
- SogeCreditSerializer
-from ..models import Invoice, Product, RemittanceType, Remittance, SogeCredit
+from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer
+from ..models import Invoice, Product, RemittanceType, Remittance
class InvoiceViewSet(ReadProtectedModelViewSet):
@@ -60,18 +59,3 @@ class RemittanceViewSet(ReadProtectedModelViewSet):
filter_backends = [DjangoFilterBackend, SearchFilter]
filterset_fields = ['date', 'remittance_type', 'comment', 'closed', 'transaction_proxies__transaction', ]
search_fields = ['$remittance_type__note__special_type', '$comment', ]
-
-
-class SogeCreditViewSet(ReadProtectedModelViewSet):
- """
- REST API View set.
- The djangorestframework plugin will get all `SogeCredit` objects, serialize it to JSON with the given serializer,
- then render it on /api/treasury/soge_credit/
- """
- queryset = SogeCredit.objects.order_by('id')
- serializer_class = SogeCreditSerializer
- filter_backends = [DjangoFilterBackend, SearchFilter]
- filterset_fields = ['user', 'user__last_name', 'user__first_name', 'user__email', 'user__note__alias__name',
- 'user__note__alias__normalized_name', 'transactions', 'credit_transaction', ]
- search_fields = ['$user__last_name', '$user__first_name', '$user__email', '$user__note__alias__name',
- '$user__note__alias__normalized_name', ]
diff --git a/apps/treasury/forms.py b/apps/treasury/forms.py
index 0244118..8a07eab 100644
--- a/apps/treasury/forms.py
+++ b/apps/treasury/forms.py
@@ -9,7 +9,7 @@ from django.db import transaction
from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import AmountInput, Autocomplete
-from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
+from .models import Invoice, Product, Remittance, SpecialTransactionProxy
class InvoiceForm(forms.ModelForm):
@@ -163,18 +163,3 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
model = SpecialTransactionProxy
fields = ('remittance', )
-
-class SogeCreditForm(forms.ModelForm):
- class Meta:
- model = SogeCredit
- fields = ('user', )
- widgets = {
- "user": Autocomplete(
- User,
- attrs={
- 'api_url': '/api/user/',
- 'name_field': 'username',
- 'placeholder': 'Nom ...',
- },
- ),
- }
diff --git a/apps/treasury/migrations/0005_delete_sogecredit.py b/apps/treasury/migrations/0005_delete_sogecredit.py
new file mode 100644
index 0000000..3989e41
--- /dev/null
+++ b/apps/treasury/migrations/0005_delete_sogecredit.py
@@ -0,0 +1,16 @@
+# Generated by Django 2.2.28 on 2022-07-31 11:45
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('treasury', '0004_auto_20211005_1544'),
+ ]
+
+ operations = [
+ migrations.DeleteModel(
+ name='SogeCredit',
+ ),
+ ]
diff --git a/apps/treasury/models.py b/apps/treasury/models.py
index 912c2bd..4f8c9d5 100644
--- a/apps/treasury/models.py
+++ b/apps/treasury/models.py
@@ -273,167 +273,3 @@ class SpecialTransactionProxy(models.Model):
def __str__(self):
return str(self.transaction)
-
-
-class SogeCredit(models.Model):
- """
- Manage the credits from the Société générale.
- """
- user = models.OneToOneField(
- User,
- on_delete=models.PROTECT,
- verbose_name=_("user"),
- )
-
- transactions = models.ManyToManyField(
- MembershipTransaction,
- related_name="+",
- blank=True,
- verbose_name=_("membership transactions"),
- )
-
- credit_transaction = models.OneToOneField(
- SpecialTransaction,
- on_delete=models.SET_NULL,
- verbose_name=_("credit transaction"),
- null=True,
- )
-
- @property
- def valid(self):
- return self.credit_transaction and self.credit_transaction.valid
-
- @property
- def amount(self):
- if self.valid:
- return self.credit_transaction.total
- amount = sum(transaction.total for transaction in self.transactions.all())
- return amount
-
- def update_transactions(self):
- """
- The Sogé credit may be created after the user already paid its memberships.
- We query transactions and update the credit, if it is unvalid.
- """
- if self.valid or not self.pk:
- return
-
- bde = Club.objects.get(name="BDE")
- kfet = Club.objects.get(name="Kfet")
- bde_qs = Membership.objects.filter(user=self.user, club=bde, date_start__gte=bde.membership_start)
- kfet_qs = Membership.objects.filter(user=self.user, club=kfet, date_start__gte=kfet.membership_start)
-
- if bde_qs.exists():
- m = bde_qs.get()
- if MembershipTransaction.objects.filter(membership=m).exists(): # non-free membership
- if m.transaction not in self.transactions.all():
- self.transactions.add(m.transaction)
-
- if kfet_qs.exists():
- m = kfet_qs.get()
- if MembershipTransaction.objects.filter(membership=m).exists(): # non-free membership
- if m.transaction not in self.transactions.all():
- self.transactions.add(m.transaction)
-
- for tr in self.transactions.all():
- tr.valid = False
- tr.save()
-
- def invalidate(self):
- """
- Invalidating a Société générale delete the transaction of the bank if it was already created.
- Treasurers must know what they do, With Great Power Comes Great Responsibility...
- """
- if self.valid:
- self.credit_transaction.valid = False
- self.credit_transaction.save()
- for tr in self.transactions.all():
- tr.valid = False
- tr._force_save = True
- tr.save()
-
- def validate(self, force=False):
- if self.valid and not force:
- # The credit is already done
- return
-
- # First invalidate all transaction and delete the credit if already did (and force mode)
- self.invalidate()
- # Refresh credit amount
- self.save()
- self.credit_transaction.valid = True
- self.credit_transaction._force_save = True
- self.credit_transaction.save()
- self.save()
-
- for tr in self.transactions.all():
- tr.valid = True
- tr._force_save = True
- tr.created_at = timezone.now()
- tr.save()
-
- @transaction.atomic
- def save(self, *args, **kwargs):
- # This is a pre-registered user that declared that a SoGé account was opened.
- # No note exists yet.
- if not NoteUser.objects.filter(user=self.user).exists():
- return super().save(*args, **kwargs)
-
- if not self.credit_transaction:
- credit_transaction = SpecialTransaction(
- 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,
- )
- credit_transaction._force_save = True
- credit_transaction.save()
- credit_transaction.refresh_from_db()
- self.credit_transaction = credit_transaction
- elif not self.valid:
- self.credit_transaction.amount = self.amount
- self.credit_transaction._force_save = True
- self.credit_transaction.save()
-
- return 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.
- Treasurers must know what they do, this is difficult to undo this operation.
- With Great Power Comes Great Responsibility...
- """
-
- total_fee = sum(transaction.total for transaction in self.transactions.all() if not transaction.valid)
- if self.user.note.balance < total_fee:
- raise ValidationError(_("This user doesn't have enough money to pay the memberships with its note. "
- "Please ask her/him to credit the note before invalidating this credit."))
-
- self.invalidate()
- for tr in self.transactions.all():
- tr._force_save = True
- tr.valid = True
- tr.created_at = timezone.now()
- tr.save()
- if self.credit_transaction:
- # If the soge credit is deleted while the user is not validated yet,
- # there is not credit transaction.
- # There is a credit transaction iff the user declares that no bank account
- # was opened after the validation of the account.
- self.credit_transaction.valid = False
- self.credit_transaction.reason += " (invalide)"
- self.credit_transaction._force_save = True
- self.credit_transaction.save()
- super().delete(**kwargs)
-
- class Meta:
- verbose_name = _("Credit from the Société générale")
- verbose_name_plural = _("Credits from the Société générale")
-
- def __str__(self):
- return _("Soge credit for {user}").format(user=str(self.user))
diff --git a/apps/treasury/tables.py b/apps/treasury/tables.py
index f309c20..0041c25 100644
--- a/apps/treasury/tables.py
+++ b/apps/treasury/tables.py
@@ -7,7 +7,7 @@ from django_tables2 import A
from note.models import SpecialTransaction
from note.templatetags.pretty_money import pretty_money
-from .models import Invoice, Remittance, SogeCredit
+from .models import Invoice, Remittance
class InvoiceTable(tables.Table):
@@ -120,28 +120,3 @@ class SpecialTransactionTable(tables.Table):
template_name = 'django_tables2/bootstrap4.html'
fields = ('created_at', 'source', 'destination', 'last_name', 'first_name', 'bank', 'amount', 'reason',)
order_by = ('-created_at',)
-
-
-class SogeCreditTable(tables.Table):
- user = tables.LinkColumn(
- 'treasury:manage_soge_credit',
- args=[A('pk')],
- )
-
- amount = tables.Column(
- verbose_name=_("Amount"),
- )
-
- valid = tables.Column(
- verbose_name=_("Valid"),
- )
-
- def render_amount(self, value):
- return pretty_money(value)
-
- def render_valid(self, value):
- return _("Yes") if value else _("No")
-
- class Meta:
- model = SogeCredit
- fields = ('user', 'user__last_name', 'user__first_name', 'amount', 'valid', )
diff --git a/apps/treasury/templates/treasury/invoice_list.html b/apps/treasury/templates/treasury/invoice_list.html
index d9cd8a3..e42fbf2 100644
--- a/apps/treasury/templates/treasury/invoice_list.html
+++ b/apps/treasury/templates/treasury/invoice_list.html
@@ -15,9 +15,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% trans "Remittance" %}s
-
- {% trans "Société générale credits" %}
-
diff --git a/apps/treasury/templates/treasury/remittance_list.html b/apps/treasury/templates/treasury/remittance_list.html
index 8ced1ad..7d9e915 100644
--- a/apps/treasury/templates/treasury/remittance_list.html
+++ b/apps/treasury/templates/treasury/remittance_list.html
@@ -15,9 +15,6 @@ SPDX-License-Identifier: GPL-3.0-or-later