Remove soge, need to fix perm
This commit is contained in:
parent
94f5788922
commit
00edcabb8e
21 changed files with 57 additions and 606 deletions
|
|
@ -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
|
||||
|
|
|
|||
35
.gitpod.yml
Normal file
35
.gitpod.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# 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 update
|
||||
init: sudo apt update
|
||||
- name: Apt install
|
||||
init: sudo apt install --no-install-recommends -y \
|
||||
ipython3 python3-setuptools python3-venv python3-dev \
|
||||
texlive-xetex gettext libjs-bootstrap4 fonts-font-awesome git
|
||||
- name : Install requirements
|
||||
init: pip3 install -r requirements.txt
|
||||
- name : Setup env
|
||||
init: cp .env_example .env
|
||||
- name: Django collectstatic
|
||||
init: python3 manage.py collectstatic --noinput
|
||||
- name: Django compilemessages
|
||||
init: python3 manage.py compilemessages
|
||||
- name: Django makemigrations
|
||||
init: python3 manage.py makemigrations
|
||||
- name: Django migrate
|
||||
init: python3 manage.py migrate
|
||||
- name: Django loaddata
|
||||
init: python3 manage.py loaddata initial
|
||||
- name: Django create dev superuser
|
||||
init: python3 manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'adminpass')"
|
||||
- name: Django start server
|
||||
command: python3 manage.py runserver 0.0.0.0:8000
|
||||
ports:
|
||||
- port: 8000
|
||||
onOpen: open-preview
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -44,15 +44,6 @@ 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 WEISignupForm(forms.Form):
|
||||
wei_registration = forms.BooleanField(
|
||||
|
|
@ -67,11 +58,6 @@ 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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<h4> {% trans "Validate account" %}</h4>
|
||||
</div>
|
||||
|
||||
{% if declare_soge_account %}
|
||||
<div class="alert alert-info">
|
||||
{% trans "The user declared that he/she opened a bank account in the Société générale." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card-body" id="profile_infos">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
|
@ -78,16 +72,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
||||
{% block extrajavascript %}
|
||||
<script>
|
||||
soge_field = $("#id_soge");
|
||||
|
||||
function fillFields() {
|
||||
let checked = soge_field.is(':checked');
|
||||
if (!checked) {
|
||||
$("input").attr('disabled', false);
|
||||
$("select").attr('disabled', false);
|
||||
return;
|
||||
}
|
||||
|
||||
let credit_type = $("#id_credit_type");
|
||||
credit_type.attr('disabled', true);
|
||||
credit_type.val(4);
|
||||
|
|
@ -110,11 +96,5 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
join_kfet.attr('checked', 'checked');
|
||||
}
|
||||
|
||||
soge_field.change(fillFields);
|
||||
|
||||
{% if declare_soge_account %}
|
||||
soge_field.attr('checked', true);
|
||||
fillFields();
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__'
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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', ]
|
||||
|
|
|
|||
|
|
@ -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 ...',
|
||||
},
|
||||
),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,183 +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())
|
||||
if 'wei' in settings.INSTALLED_APPS:
|
||||
from wei.models import WEIMembership
|
||||
if not WEIMembership.objects.filter(club__weiclub__year=datetime.date.today().year, user=self.user)\
|
||||
.exists():
|
||||
# 80 € for people that don't go to WEI
|
||||
amount += 8000
|
||||
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)
|
||||
|
||||
if 'wei' in settings.INSTALLED_APPS:
|
||||
from wei.models import WEIClub
|
||||
wei = WEIClub.objects.order_by('-year').first()
|
||||
wei_qs = Membership.objects.filter(user=self.user, club=wei, date_start__gte=wei.membership_start)
|
||||
if wei_qs.exists():
|
||||
m = wei_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))
|
||||
|
|
|
|||
|
|
@ -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', )
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<a href="{% url "treasury:remittance_list" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Remittance" %}s
|
||||
</a>
|
||||
<a href="{% url "treasury:soge_credits" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Société générale credits" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<a href="#" class="btn btn-sm btn-outline-primary active">
|
||||
{% trans "Remittance" %}s
|
||||
</a>
|
||||
<a href="{% url "treasury:soge_credits" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Société générale credits" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ from django.urls import reverse
|
|||
from member.models import Membership, Club
|
||||
from note.models import SpecialTransaction, NoteSpecial, Transaction
|
||||
|
||||
from ..api.views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet, \
|
||||
SogeCreditViewSet
|
||||
from ..models import Invoice, Product, Remittance, RemittanceType, SogeCredit
|
||||
from ..api.views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet
|
||||
from ..models import Invoice, Product, Remittance, RemittanceType
|
||||
|
||||
|
||||
class TestInvoices(TestCase):
|
||||
|
|
@ -296,112 +295,6 @@ class TestRemittances(TestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
class TestSogeCredits(TestCase):
|
||||
"""
|
||||
Check that credits from the Société générale are working correctly.
|
||||
"""
|
||||
|
||||
fixtures = ('initial',)
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.user = User.objects.create_superuser(
|
||||
username="admintoto",
|
||||
password="totototo",
|
||||
email="admin@example.com",
|
||||
)
|
||||
self.client.force_login(self.user)
|
||||
sess = self.client.session
|
||||
sess["permission_mask"] = 42
|
||||
sess.save()
|
||||
|
||||
self.kfet = Club.objects.get(name="Kfet")
|
||||
self.bde = self.kfet.parent_club
|
||||
|
||||
self.kfet_membership = Membership(
|
||||
user=self.user,
|
||||
club=self.kfet,
|
||||
)
|
||||
self.kfet_membership._force_renew_parent = True
|
||||
self.kfet_membership._soge = True
|
||||
self.kfet_membership.save()
|
||||
|
||||
def test_admin_page(self):
|
||||
"""
|
||||
Render the admin page.
|
||||
"""
|
||||
response = self.client.get(reverse("admin:index") + "treasury/sogecredit/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_sogecredit_list(self):
|
||||
"""
|
||||
Display the list of all credits.
|
||||
"""
|
||||
response = self.client.get(reverse("treasury:soge_credits"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.get(reverse("treasury:soge_credits") + "?search=toto&valid=")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_validate_soge_credit(self):
|
||||
"""
|
||||
Try to validate a credit.
|
||||
"""
|
||||
soge_credit = SogeCredit.objects.get(user=self.user)
|
||||
|
||||
response = self.client.get(reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
response = self.client.post(reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)), data=dict(
|
||||
validate=True,
|
||||
))
|
||||
self.assertRedirects(response, reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)), 302, 200)
|
||||
soge_credit.refresh_from_db()
|
||||
self.assertTrue(soge_credit.valid)
|
||||
self.user.note.refresh_from_db()
|
||||
self.assertEqual(
|
||||
Transaction.objects.filter(Q(source=self.user.note) | Q(destination=self.user.note)).count(), 3)
|
||||
self.assertTrue(self.user.profile.soge)
|
||||
|
||||
def test_delete_soge_credit(self):
|
||||
"""
|
||||
Try to invalidate a credit.
|
||||
"""
|
||||
soge_credit = SogeCredit.objects.get(user=self.user)
|
||||
|
||||
response = self.client.get(reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertRaises(ValidationError, self.client.post,
|
||||
reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)), data=dict(delete=True))
|
||||
|
||||
SpecialTransaction.objects.create(
|
||||
source=NoteSpecial.objects.get(special_type="Carte bancaire"),
|
||||
destination=self.user.note,
|
||||
amount=self.bde.membership_fee_paid + self.kfet.membership_fee_paid,
|
||||
quantity=1,
|
||||
reason="Registration is not complete, pliz pay",
|
||||
last_name="TOTO",
|
||||
first_name="Toto",
|
||||
)
|
||||
|
||||
response = self.client.post(reverse("treasury:manage_soge_credit", args=(soge_credit.pk,)),
|
||||
data=dict(delete=True))
|
||||
# 403 because no SogeCredit exists anymore, then a PermissionDenied is raised
|
||||
self.assertRedirects(response, reverse("treasury:soge_credits"), 302, 403)
|
||||
self.assertFalse(SogeCredit.objects.filter(pk=soge_credit.pk))
|
||||
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(), 4)
|
||||
self.assertFalse(self.user.profile.soge)
|
||||
|
||||
def test_invoice_api(self):
|
||||
"""
|
||||
Load some API pages
|
||||
"""
|
||||
response = self.client.get("/api/treasury/soge_credit/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
class TestTreasuryAPI(TestAPI):
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
|
@ -447,7 +340,6 @@ class TestTreasuryAPI(TestAPI):
|
|||
club=self.kfet,
|
||||
)
|
||||
self.kfet_membership._force_renew_parent = True
|
||||
self.kfet_membership._soge = True
|
||||
self.kfet_membership.save()
|
||||
|
||||
def test_invoice_api(self):
|
||||
|
|
@ -474,8 +366,3 @@ class TestTreasuryAPI(TestAPI):
|
|||
"""
|
||||
self.check_viewset(RemittanceTypeViewSet, "/api/treasury/remittance_type/")
|
||||
|
||||
def test_sogecredit_api(self):
|
||||
"""
|
||||
Load SogeCredit API page and test all filters and permissions
|
||||
"""
|
||||
self.check_viewset(SogeCreditViewSet, "/api/treasury/soge_credit/")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from django.urls import path
|
|||
|
||||
from .views import InvoiceCreateView, InvoiceListView, InvoiceUpdateView, InvoiceDeleteView, InvoiceRenderView,\
|
||||
RemittanceListView, RemittanceCreateView, RemittanceUpdateView, LinkTransactionToRemittanceView,\
|
||||
UnlinkTransactionToRemittanceView, SogeCreditListView, SogeCreditManageView
|
||||
UnlinkTransactionToRemittanceView
|
||||
|
||||
app_name = 'treasury'
|
||||
urlpatterns = [
|
||||
|
|
@ -23,7 +23,4 @@ urlpatterns = [
|
|||
path('remittance/link_transaction/<int:pk>/', LinkTransactionToRemittanceView.as_view(), name='link_transaction'),
|
||||
path('remittance/unlink_transaction/<int:pk>/', UnlinkTransactionToRemittanceView.as_view(),
|
||||
name='unlink_transaction'),
|
||||
|
||||
path('soge-credits/list/', SogeCreditListView.as_view(), name='soge_credits'),
|
||||
path('soge-credits/manage/<int:pk>/', SogeCreditManageView.as_view(), name='manage_soge_credit'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ from permission.backends import PermissionBackend
|
|||
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
|
||||
|
||||
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, \
|
||||
LinkTransactionToRemittanceForm, SogeCreditForm
|
||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
|
||||
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
|
||||
LinkTransactionToRemittanceForm
|
||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
||||
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable
|
||||
|
||||
|
||||
class InvoiceCreateView(ProtectQuerysetMixin, ProtectedCreateView):
|
||||
|
|
@ -393,70 +393,3 @@ class UnlinkTransactionToRemittanceView(LoginRequiredMixin, View):
|
|||
transaction.save()
|
||||
|
||||
return redirect('treasury:remittance_list')
|
||||
|
||||
|
||||
class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableView):
|
||||
"""
|
||||
List all Société Générale credits
|
||||
"""
|
||||
model = SogeCredit
|
||||
table_class = SogeCreditTable
|
||||
extra_context = {"title": _("List of credits from the Société générale")}
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
# Check that the user is authenticated
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
|
||||
if not super().get_queryset().exists():
|
||||
raise PermissionDenied(_("You are not able to see the treasury interface."))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
"""
|
||||
Filter the table with the given parameter.
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
qs = super().get_queryset()
|
||||
if "search" in self.request.GET:
|
||||
pattern = self.request.GET["search"]
|
||||
if pattern:
|
||||
qs = qs.filter(
|
||||
Q(user__first_name__iregex=pattern)
|
||||
| Q(user__last_name__iregex=pattern)
|
||||
| Q(user__note__alias__name__iregex="^" + pattern)
|
||||
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||
)
|
||||
|
||||
if "valid" not in self.request.GET or not self.request.GET["valid"]:
|
||||
qs = qs.filter(credit_transaction__valid=False)
|
||||
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['form'] = SogeCreditForm(self.request.POST or None)
|
||||
return context
|
||||
|
||||
|
||||
class SogeCreditManageView(LoginRequiredMixin, ProtectQuerysetMixin, BaseFormView, DetailView):
|
||||
"""
|
||||
Manage credits from the Société générale.
|
||||
"""
|
||||
model = SogeCredit
|
||||
form_class = Form
|
||||
extra_context = {"title": _("Manage credits from the Société générale")}
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
if "validate" in form.data:
|
||||
self.get_object().validate(True)
|
||||
elif "delete" in form.data:
|
||||
self.get_object().delete()
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
if "validate" in self.request.POST:
|
||||
return reverse_lazy('treasury:manage_soge_credit', args=(self.get_object().pk,))
|
||||
return reverse_lazy('treasury:soge_credits')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue