mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	Credit/debit support
This commit is contained in:
		
				
					committed by
					
						 Bombar Maxime
						Bombar Maxime
					
				
			
			
				
	
			
			
			
						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.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \ | ||||
|     TemplateTransaction | ||||
|     TemplateTransaction, SpecialTransaction | ||||
|  | ||||
|  | ||||
| class NoteSerializer(serializers.ModelSerializer): | ||||
| @@ -144,9 +144,21 @@ class MembershipTransactionSerializer(serializers.ModelSerializer): | ||||
|         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): | ||||
|     model_serializer_mapping = { | ||||
|         Transaction: TransactionSerializer, | ||||
|         TemplateTransaction: TemplateTransactionSerializer, | ||||
|         MembershipTransaction: MembershipTransactionSerializer, | ||||
|         SpecialTransaction: SpecialTransactionSerializer, | ||||
|     } | ||||
|   | ||||
| @@ -165,7 +165,6 @@ class Transaction(PolymorphicModel): | ||||
| class TemplateTransaction(Transaction): | ||||
|     """ | ||||
|     Special type of :model:`note.Transaction` associated to a :model:`note.TransactionTemplate`. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     template = models.ForeignKey( | ||||
| @@ -183,6 +182,27 @@ class TemplateTransaction(Transaction): | ||||
|         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): | ||||
|     """ | ||||
|     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') | ||||
|         return queryset, True | ||||
|  | ||||
|  | ||||
|     def render_amount(self, value): | ||||
|         return pretty_money(value) | ||||
|  | ||||
|  | ||||
|     def render_total(self, value): | ||||
|         return pretty_money(value) | ||||
|  | ||||
|  | ||||
|     # Django-tables escape strings. That's a wrong thing. | ||||
|     def render_reason(self, value): | ||||
|         return html.unescape(value) | ||||
|  | ||||
|  | ||||
|     def render_valid(self, value): | ||||
|         return "✔" if value else "✖" | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,8 @@ from django.views.generic import CreateView, ListView, UpdateView, TemplateView | ||||
| from django_tables2 import SingleTableView | ||||
|  | ||||
| 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 | ||||
|  | ||||
|  | ||||
| @@ -30,6 +31,8 @@ class TransactionCreate(LoginRequiredMixin, TemplateView): | ||||
|         context['title'] = _('Transfer money from your account ' | ||||
|                              'to one or others') | ||||
|         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 | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,24 @@ SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
|     <div class="row"> | ||||
|         <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> | ||||
|  | ||||
| @@ -31,6 +48,48 @@ SPDX-License-Identifier: GPL-2.0-or-later | ||||
|             </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="card border-info shadow mb-4"> | ||||
|                 <div class="card-header"> | ||||
| @@ -75,7 +134,23 @@ SPDX-License-Identifier: GPL-2.0-or-later | ||||
|         sources_notes_display = []; | ||||
|         dests = []; | ||||
|         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() { | ||||
|            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"); | ||||
|         }); | ||||
|  | ||||
|         $("#switch_mode").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(); | ||||
|                 $("#dests_div").attr('class', 'col-md-12'); | ||||
|             } | ||||
|         $("#type_gift").click(function() { | ||||
|             $("#emitters_div").hide(); | ||||
|             $("#external_div").hide(); | ||||
|             $("#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() { | ||||
|             if (sources_notes_display.length === 0) { | ||||
|             if ($("#type_gift").is(':checked')) { | ||||
|                 dests_notes_display.forEach(function (dest) { | ||||
|                     $.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"; | ||||
|                             msgDiv.html(html); | ||||
|  | ||||
|                             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(""); | ||||
|                             refreshBalance(); | ||||
|                             reset(); | ||||
|                         }).fail(function (err) { | ||||
|                         let msgDiv = $("#messages"); | ||||
|                         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"; | ||||
|                         msgDiv.html(html); | ||||
|  | ||||
|                         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(""); | ||||
|                         refreshBalance(); | ||||
|                         reset(); | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|             else { | ||||
|             else if ($("#type_transfer").is(':checked')) { | ||||
|                 sources_notes_display.forEach(function (source) { | ||||
|                     dests_notes_display.forEach(function (dest) { | ||||
|                         $.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"; | ||||
|                                 msgDiv.html(html); | ||||
|  | ||||
|                                 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(""); | ||||
|                                 refreshBalance(); | ||||
|                                 reset(); | ||||
|                             }).fail(function (err) { | ||||
|                                 let msgDiv = $("#messages"); | ||||
|                                 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"; | ||||
|                                 msgDiv.html(html); | ||||
|  | ||||
|                                 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(""); | ||||
|                                 refreshBalance(); | ||||
|                                 reset(); | ||||
|                         }); | ||||
|                     }); | ||||
|                 }); | ||||
|             } 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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user