Credit/debit support

This commit is contained in:
Yohann D'ANELLO 2020-03-14 15:13:58 +01:00 committed by Bombar Maxime
parent 321927ba1e
commit 040bb27528
5 changed files with 186 additions and 67 deletions

View File

@ -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,
} }

View File

@ -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`.

View File

@ -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 ""

View File

@ -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

View File

@ -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; $("#emitters_div").hide();
if (transfer_mode) { $("#external_div").hide();
$("#switch_mode").text("Passer en mode virement"); $("#dests_div").attr('class', 'col-md-12');
$("#emitters_div").show(); });
$("#dests_div").attr('class', 'col-md-6');
} $("#type_transfer").click(function() {
else { $("#emitters_div").show();
$("#switch_mode").text("Passer en mode transfert"); $("#external_div").hide();
$("#emitters_div").hide(); $("#dests_div").attr('class', 'col-md-6');
$("#dests_div").attr('class', 'col-md-12'); });
}
$("#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>