mirror of https://gitlab.crans.org/bde/nk20
Credit/debit support
This commit is contained in:
parent
321927ba1e
commit
040bb27528
|
@ -6,7 +6,7 @@ from rest_polymorphic.serializers import PolymorphicSerializer
|
||||||
|
|
||||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
|
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
|
||||||
TemplateTransaction
|
TemplateTransaction, SpecialTransaction
|
||||||
|
|
||||||
|
|
||||||
class NoteSerializer(serializers.ModelSerializer):
|
class NoteSerializer(serializers.ModelSerializer):
|
||||||
|
@ -144,9 +144,21 @@ class MembershipTransactionSerializer(serializers.ModelSerializer):
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialTransactionSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
REST API Serializer for Special transactions.
|
||||||
|
The djangorestframework plugin will analyse the model `SpecialTransaction` and parse all fields in the API.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = SpecialTransaction
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class TransactionPolymorphicSerializer(PolymorphicSerializer):
|
class TransactionPolymorphicSerializer(PolymorphicSerializer):
|
||||||
model_serializer_mapping = {
|
model_serializer_mapping = {
|
||||||
Transaction: TransactionSerializer,
|
Transaction: TransactionSerializer,
|
||||||
TemplateTransaction: TemplateTransactionSerializer,
|
TemplateTransaction: TemplateTransactionSerializer,
|
||||||
MembershipTransaction: MembershipTransactionSerializer,
|
MembershipTransaction: MembershipTransactionSerializer,
|
||||||
|
SpecialTransaction: SpecialTransactionSerializer,
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,6 @@ class Transaction(PolymorphicModel):
|
||||||
class TemplateTransaction(Transaction):
|
class TemplateTransaction(Transaction):
|
||||||
"""
|
"""
|
||||||
Special type of :model:`note.Transaction` associated to a :model:`note.TransactionTemplate`.
|
Special type of :model:`note.Transaction` associated to a :model:`note.TransactionTemplate`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template = models.ForeignKey(
|
template = models.ForeignKey(
|
||||||
|
@ -183,6 +182,27 @@ class TemplateTransaction(Transaction):
|
||||||
return _('template')
|
return _('template')
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialTransaction(Transaction):
|
||||||
|
"""
|
||||||
|
Special type of :model:`note.Transaction` associated to transactions with special notes
|
||||||
|
"""
|
||||||
|
|
||||||
|
last_name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("name"),
|
||||||
|
)
|
||||||
|
|
||||||
|
first_name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("first_name"),
|
||||||
|
)
|
||||||
|
|
||||||
|
bank = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
verbose_name=_("bank")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MembershipTransaction(Transaction):
|
class MembershipTransaction(Transaction):
|
||||||
"""
|
"""
|
||||||
Special type of :model:`note.Transaction` associated to a :model:`member.Membership`.
|
Special type of :model:`note.Transaction` associated to a :model:`member.Membership`.
|
||||||
|
|
|
@ -37,20 +37,16 @@ class HistoryTable(tables.Table):
|
||||||
.order_by(('-' if is_descending else '') + 'total')
|
.order_by(('-' if is_descending else '') + 'total')
|
||||||
return queryset, True
|
return queryset, True
|
||||||
|
|
||||||
|
|
||||||
def render_amount(self, value):
|
def render_amount(self, value):
|
||||||
return pretty_money(value)
|
return pretty_money(value)
|
||||||
|
|
||||||
|
|
||||||
def render_total(self, value):
|
def render_total(self, value):
|
||||||
return pretty_money(value)
|
return pretty_money(value)
|
||||||
|
|
||||||
|
|
||||||
# Django-tables escape strings. That's a wrong thing.
|
# Django-tables escape strings. That's a wrong thing.
|
||||||
def render_reason(self, value):
|
def render_reason(self, value):
|
||||||
return html.unescape(value)
|
return html.unescape(value)
|
||||||
|
|
||||||
|
|
||||||
def render_valid(self, value):
|
def render_valid(self, value):
|
||||||
return "✔" if value else "✖"
|
return "✔" if value else "✖"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ from django.views.generic import CreateView, ListView, UpdateView, TemplateView
|
||||||
from django_tables2 import SingleTableView
|
from django_tables2 import SingleTableView
|
||||||
|
|
||||||
from .forms import TransactionTemplateForm
|
from .forms import TransactionTemplateForm
|
||||||
from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction
|
from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction, NoteSpecial
|
||||||
|
from .models.transactions import SpecialTransaction
|
||||||
from .tables import HistoryTable
|
from .tables import HistoryTable
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ class TransactionCreate(LoginRequiredMixin, TemplateView):
|
||||||
context['title'] = _('Transfer money from your account '
|
context['title'] = _('Transfer money from your account '
|
||||||
'to one or others')
|
'to one or others')
|
||||||
context['polymorphic_ctype'] = ContentType.objects.get_for_model(Transaction).pk
|
context['polymorphic_ctype'] = ContentType.objects.get_for_model(Transaction).pk
|
||||||
|
context['special_polymorphic_ctype'] = ContentType.objects.get_for_model(SpecialTransaction).pk
|
||||||
|
context['special_types'] = NoteSpecial.objects.order_by("special_type").all()
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,24 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-12">
|
<div class="col-xl-12">
|
||||||
<button id="switch_mode" class="form-control btn btn-secondary">Passer en mode transfert</button>
|
<div class="btn-group btn-group-toggle" style="width: 100%" data-toggle="buttons">
|
||||||
|
<label class="btn btn-sm btn-outline-primary active">
|
||||||
|
<input type="radio" name="transaction_type" id="type_gift" checked>
|
||||||
|
Virement
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-sm btn-outline-primary">
|
||||||
|
<input type="radio" name="transaction_type" id="type_transfer">
|
||||||
|
Transfert
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-sm btn-outline-primary">
|
||||||
|
<input type="radio" name="transaction_type" id="type_credit">
|
||||||
|
Crédit
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-sm btn-outline-primary">
|
||||||
|
<input type="radio" name="transaction_type" id="type_debit">
|
||||||
|
Retrait
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -31,6 +48,48 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6" id="external_div" style="display: none;">
|
||||||
|
<div class="card border-success shadow mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<p class="card-text font-weight-bold">
|
||||||
|
Paiement externe
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group list-group-flush" id="source_note_list">
|
||||||
|
</ul>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="credit_type">Type de transfert :</label>
|
||||||
|
<select id="credit_type" class="custom-select">
|
||||||
|
{% for special_type in special_types %}
|
||||||
|
<option value="{{ special_type.id }}">{{ special_type.special_type }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="last_name">Nom :</label>
|
||||||
|
<input type="text" id="last_name" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="first_name">Prénom :</label>
|
||||||
|
<input type="text" id="first_name" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label for="bank">Banque :</label>
|
||||||
|
<input type="text" id="bank" class="form-control" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-md-12" id="dests_div">
|
<div class="col-md-12" id="dests_div">
|
||||||
<div class="card border-info shadow mb-4">
|
<div class="card border-info shadow mb-4">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
@ -75,7 +134,23 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
sources_notes_display = [];
|
sources_notes_display = [];
|
||||||
dests = [];
|
dests = [];
|
||||||
dests_notes_display = [];
|
dests_notes_display = [];
|
||||||
transfer_mode = false;
|
|
||||||
|
function reset() {
|
||||||
|
sources_notes_display.length = 0;
|
||||||
|
sources.length = 0;
|
||||||
|
dests_notes_display.length = 0;
|
||||||
|
dests.length = 0;
|
||||||
|
$("#source_note_list").html("");
|
||||||
|
$("#dest_note_list").html("");
|
||||||
|
$("#source_alias_matched").html("");
|
||||||
|
$("#dest_alias_matched").html("");
|
||||||
|
$("#amount").val("");
|
||||||
|
$("#reason").val("");
|
||||||
|
$("#last_name").val("");
|
||||||
|
$("#first_name").val("");
|
||||||
|
$("#bank").val("");
|
||||||
|
refreshBalance();
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
autoCompleteNote("source_note", "source_alias_matched", "source_note_list", sources, sources_notes_display,
|
autoCompleteNote("source_note", "source_alias_matched", "source_note_list", sources, sources_notes_display,
|
||||||
|
@ -84,22 +159,32 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
"dest_alias", "dest_note");
|
"dest_alias", "dest_note");
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#switch_mode").click(function () {
|
$("#type_gift").click(function() {
|
||||||
transfer_mode ^= true;
|
|
||||||
if (transfer_mode) {
|
|
||||||
$("#switch_mode").text("Passer en mode virement");
|
|
||||||
$("#emitters_div").show();
|
|
||||||
$("#dests_div").attr('class', 'col-md-6');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#switch_mode").text("Passer en mode transfert");
|
|
||||||
$("#emitters_div").hide();
|
$("#emitters_div").hide();
|
||||||
|
$("#external_div").hide();
|
||||||
$("#dests_div").attr('class', 'col-md-12');
|
$("#dests_div").attr('class', 'col-md-12');
|
||||||
}
|
});
|
||||||
|
|
||||||
|
$("#type_transfer").click(function() {
|
||||||
|
$("#emitters_div").show();
|
||||||
|
$("#external_div").hide();
|
||||||
|
$("#dests_div").attr('class', 'col-md-6');
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#type_credit").click(function() {
|
||||||
|
$("#emitters_div").hide();
|
||||||
|
$("#external_div").show();
|
||||||
|
$("#dests_div").attr('class', 'col-md-6');
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#type_debit").click(function() {
|
||||||
|
$("#emitters_div").hide();
|
||||||
|
$("#external_div").show();
|
||||||
|
$("#dests_div").attr('class', 'col-md-6');
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#transfer").click(function() {
|
$("#transfer").click(function() {
|
||||||
if (sources_notes_display.length === 0) {
|
if ($("#type_gift").is(':checked')) {
|
||||||
dests_notes_display.forEach(function (dest) {
|
dests_notes_display.forEach(function (dest) {
|
||||||
$.post("/api/note/transaction/transaction/",
|
$.post("/api/note/transaction/transaction/",
|
||||||
{
|
{
|
||||||
|
@ -120,17 +205,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+ " vers la note " + dest[0] + " a été fait avec succès !</div>\n";
|
+ " vers la note " + dest[0] + " a été fait avec succès !</div>\n";
|
||||||
msgDiv.html(html);
|
msgDiv.html(html);
|
||||||
|
|
||||||
sources_notes_display.length = 0;
|
reset();
|
||||||
sources.length = 0;
|
|
||||||
dests_notes_display.length = 0;
|
|
||||||
dests.length = 0;
|
|
||||||
$("#source_note_list").html("");
|
|
||||||
$("#dest_note_list").html("");
|
|
||||||
$("#source_alias_matched").html("");
|
|
||||||
$("#dest_alias_matched").html("");
|
|
||||||
$("#amount").val("");
|
|
||||||
$("#reason").val("");
|
|
||||||
refreshBalance();
|
|
||||||
}).fail(function (err) {
|
}).fail(function (err) {
|
||||||
let msgDiv = $("#messages");
|
let msgDiv = $("#messages");
|
||||||
let html = msgDiv.html();
|
let html = msgDiv.html();
|
||||||
|
@ -139,21 +214,11 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+ " vers la note " + dest[0] + " a échoué : " + err.responseText + "</div>\n";
|
+ " vers la note " + dest[0] + " a échoué : " + err.responseText + "</div>\n";
|
||||||
msgDiv.html(html);
|
msgDiv.html(html);
|
||||||
|
|
||||||
sources_notes_display.length = 0;
|
reset();
|
||||||
sources.length = 0;
|
|
||||||
dests_notes_display.length = 0;
|
|
||||||
dests.length = 0;
|
|
||||||
$("#source_note_list").html("");
|
|
||||||
$("#dest_note_list").html("");
|
|
||||||
$("#source_alias_matched").html("");
|
|
||||||
$("#dest_alias_matched").html("");
|
|
||||||
$("#amount").val("");
|
|
||||||
$("#reason").val("");
|
|
||||||
refreshBalance();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else if ($("#type_transfer").is(':checked')) {
|
||||||
sources_notes_display.forEach(function (source) {
|
sources_notes_display.forEach(function (source) {
|
||||||
dests_notes_display.forEach(function (dest) {
|
dests_notes_display.forEach(function (dest) {
|
||||||
$.post("/api/note/transaction/transaction/",
|
$.post("/api/note/transaction/transaction/",
|
||||||
|
@ -175,17 +240,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+ " vers la note " + dest[0] + " a été fait avec succès !</div>\n";
|
+ " vers la note " + dest[0] + " a été fait avec succès !</div>\n";
|
||||||
msgDiv.html(html);
|
msgDiv.html(html);
|
||||||
|
|
||||||
sources_notes_display.length = 0;
|
reset();
|
||||||
sources.length = 0;
|
|
||||||
dests_notes_display.length = 0;
|
|
||||||
dests.length = 0;
|
|
||||||
$("#source_note_list").html("");
|
|
||||||
$("#dest_note_list").html("");
|
|
||||||
$("#source_alias_matched").html("");
|
|
||||||
$("#dest_alias_matched").html("");
|
|
||||||
$("#amount").val("");
|
|
||||||
$("#reason").val("");
|
|
||||||
refreshBalance();
|
|
||||||
}).fail(function (err) {
|
}).fail(function (err) {
|
||||||
let msgDiv = $("#messages");
|
let msgDiv = $("#messages");
|
||||||
let html = msgDiv.html();
|
let html = msgDiv.html();
|
||||||
|
@ -194,20 +249,53 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+ " vers la note " + dest[0] + " a échoué : " + err.responseText + "</div>\n";
|
+ " vers la note " + dest[0] + " a échoué : " + err.responseText + "</div>\n";
|
||||||
msgDiv.html(html);
|
msgDiv.html(html);
|
||||||
|
|
||||||
sources_notes_display.length = 0;
|
reset();
|
||||||
sources.length = 0;
|
|
||||||
dests_notes_display.length = 0;
|
|
||||||
dests.length = 0;
|
|
||||||
$("#source_note_list").html("");
|
|
||||||
$("#dest_note_list").html("");
|
|
||||||
$("#source_alias_matched").html("");
|
|
||||||
$("#dest_alias_matched").html("");
|
|
||||||
$("#amount").val("");
|
|
||||||
$("#reason").val("");
|
|
||||||
refreshBalance();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else if ($("#type_credit").is(':checked') || $("#type_debit").is(':checked')) {
|
||||||
|
let special_note = $("#credit_type").val();
|
||||||
|
let user_note = dests_notes_display[0][1];
|
||||||
|
let source, dest, reason;
|
||||||
|
if ($("#type_credit").is(':checked')) {
|
||||||
|
source = special_note;
|
||||||
|
dest = user_note;
|
||||||
|
reason = $("#reason").val() + " (Crédit " + $("#credit_type option:selected").text().toLowerCase() + ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
source = user_note;
|
||||||
|
dest = special_note;
|
||||||
|
reason = $("#reason").val() + " (Retrait " + $("#credit_type option:selected").text().toLowerCase() + ")";
|
||||||
|
}
|
||||||
|
$.post("/api/note/transaction/transaction/",
|
||||||
|
{
|
||||||
|
"csrfmiddlewaretoken": CSRF_TOKEN,
|
||||||
|
"quantity": dest[3],
|
||||||
|
"amount": $("#amount").val(),
|
||||||
|
"reason": reason,
|
||||||
|
"valid": true,
|
||||||
|
"polymorphic_ctype": {{ special_polymorphic_ctype }},
|
||||||
|
"resourcetype": "SpecialTransaction",
|
||||||
|
"source": source,
|
||||||
|
"destination": dest,
|
||||||
|
"last_name": $("#last_name").val(),
|
||||||
|
"first_name": $("#first_name").val(),
|
||||||
|
"bank": $("#bank").val()
|
||||||
|
}, function () {
|
||||||
|
let msgDiv = $("#messages");
|
||||||
|
let html = msgDiv.html();
|
||||||
|
html += "<div class=\"alert alert-success\">Le crédit/retrait a bien été effectué !</div>\n";
|
||||||
|
msgDiv.html(html);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}).fail(function (err) {
|
||||||
|
let msgDiv = $("#messages");
|
||||||
|
let html = msgDiv.html();
|
||||||
|
html += "<div class=\"alert alert-danger\">Le crédit/transfert a échoué : " + err.responseText + "</div>\n";
|
||||||
|
msgDiv.html(html);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue