1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-06-21 01:48:21 +02:00

Add option to add a posteriori a Sogé credit

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
2021-09-06 00:47:11 +02:00
parent b646f549d6
commit 4e1ba1447a
6 changed files with 213 additions and 126 deletions

View File

@ -1,6 +1,6 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.db import transaction
from rest_framework import serializers
from note.api.serializers import SpecialTransactionSerializer
@ -68,6 +68,14 @@ class SogeCreditSerializer(serializers.ModelSerializer):
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__'

View File

@ -4,11 +4,12 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django import forms
from django.contrib.auth.models import User
from django.db import transaction
from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import AmountInput
from note_kfet.inputs import AmountInput, Autocomplete
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
class InvoiceForm(forms.ModelForm):
@ -161,3 +162,19 @@ class LinkTransactionToRemittanceForm(forms.ModelForm):
class Meta:
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 ...',
},
),
}

View File

@ -289,6 +289,7 @@ class SogeCredit(models.Model):
transactions = models.ManyToManyField(
MembershipTransaction,
related_name="+",
blank=True,
verbose_name=_("membership transactions"),
)
@ -313,7 +314,7 @@ class SogeCredit(models.Model):
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:
if self.valid or not self.pk:
return
bde = Club.objects.get(name="BDE")
@ -402,7 +403,8 @@ class SogeCredit(models.Model):
self.credit_transaction.amount = self.amount
self.credit_transaction._force_save = True
self.credit_transaction.save()
super().save(*args, **kwargs)
return super().save(*args, **kwargs)
def delete(self, **kwargs):
"""

View File

@ -3,6 +3,7 @@
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load render_table from django_tables2 %}
{% load crispy_forms_filters %}
{% load i18n %}
{% block content %}
@ -27,7 +28,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
{{ title }}
</h3>
<div class="card-body">
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
<div class="input-group">
<input id="searchbar" type="text" class="form-control" placeholder="Nom/prénom/note ...">
<div class="input-group-append">
<button id="add_sogecredit" class="btn btn-success" data-toggle="modal" data-target="#add-sogecredit-modal">{% trans "Add" %}</button>
</div>
</div>
<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" checked>
@ -47,28 +53,65 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endif %}
</div>
</div>
{# Popup to add new Soge credits manually if needed #}
<div class="modal fade" id="add-sogecredit-modal" tabindex="-1" role="dialog" aria-labelledby="addSogeCredit"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="lockNote">{% trans "Add credit from the Société générale" %}</h5>
<button type="button" class="close btn-modal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{{ form|crispy }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-modal" data-dismiss="modal">{% trans "Close" %}</button>
<button type="button" class="btn btn-success btn-modal" data-dismiss="modal" onclick="addSogeCredit()">{% trans "Add" %}</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extrajavascript %}
<script type="text/javascript">
$(document).ready(function () {
let old_pattern = null;
let searchbar_obj = $("#searchbar");
let invalid_only_obj = $("#invalid_only");
let old_pattern = null;
let searchbar_obj = $("#searchbar");
let invalid_only_obj = $("#invalid_only");
function reloadTable() {
let pattern = searchbar_obj.val();
function reloadTable() {
let pattern = searchbar_obj.val();
$("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + (
invalid_only_obj.is(':checked') ? "" : "&valid=1") + " #credits_table");
$("#credits_table").load(location.pathname + "?search=" + pattern.replace(" ", "%20") + (
invalid_only_obj.is(':checked') ? "" : "&valid=1") + " #credits_table");
$(".table-row").click(function () {
window.document.location = $(this).data("href");
});
}
$(".table-row").click(function () {
window.document.location = $(this).data("href");
});
}
searchbar_obj.keyup(reloadTable);
invalid_only_obj.change(reloadTable);
});
searchbar_obj.keyup(reloadTable);
invalid_only_obj.change(reloadTable);
function addSogeCredit() {
let user_pk = $('#id_user_pk').val()
if (!user_pk)
return
$.post('/api/treasury/soge_credit/?format=json', {
csrfmiddlewaretoken: CSRF_TOKEN,
user: user_pk,
}).done(function() {
addMsg("{% trans "Credit successfully registered" %}", 'success', 10000)
reloadTable()
}).fail(function (xhr) {
errMsg(xhr.responseJSON, 30000)
reloadTable()
})
}
</script>
{% endblock %}

View File

@ -25,7 +25,8 @@ from note_kfet.settings.base import BASE_DIR
from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin, ProtectedCreateView
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, \
LinkTransactionToRemittanceForm, SogeCreditForm
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, SogeCredit
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable, SogeCreditTable
@ -433,6 +434,11 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
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):
"""