var LOCK = false; sources = []; sources_notes_display = []; dests = []; dests_notes_display = []; function refreshHistory() { $("#history").load("/note/transfer/ #history"); } function reset(refresh=true) { sources_notes_display.length = 0; sources.length = 0; dests_notes_display.length = 0; dests.length = 0; $("#source_note_list").html(""); $("#dest_note_list").html(""); let source_field = $("#source_note"); source_field.val(""); let event = jQuery.Event("keyup"); event.originalEvent = {charCode: 97}; source_field.trigger(event); source_field.removeClass('is-invalid'); source_field.attr("data-original-title", "").tooltip("hide"); let dest_field = $("#dest_note"); dest_field.val(""); dest_field.trigger(event); dest_field.removeClass('is-invalid'); dest_field.attr("data-original-title", "").tooltip("hide"); let amount_field = $("#amount"); amount_field.val(""); amount_field.removeClass('is-invalid'); $("#amount-required").html(""); let reason_field = $("#reason"); reason_field.val(""); reason_field.removeClass('is-invalid'); $("#reason-required").html(""); $("#last_name").val(""); $("#first_name").val(""); $("#bank").val(""); $("#user_note").val(""); $("#profile_pic").attr("src", "/static/member/img/default_picture.png"); $("#profile_pic_link").attr("href", "#"); if (refresh) { refreshBalance(); refreshHistory(); } LOCK = false; } $(document).ready(function() { /** * If we are in credit/debit mode, check that only one note is entered. * More over, get first name and last name to autocomplete fields. */ function checkUniqueNote() { if ($("#type_credit").is(":checked") || $("#type_debit").is(":checked")) { let arr = $("#type_credit").is(":checked") ? dests_notes_display : sources_notes_display; if (arr.length === 0) return; let last = arr[arr.length - 1]; arr.length = 0; arr.push(last); last.quantity = 1; if (!last.note.user) { $.getJSON("/api/note/note/" + last.note.id + "/?format=json", function(note) { last.note.user = note.user; $.getJSON("/api/user/" + last.note.user + "/", function(user) { $("#last_name").val(user.last_name); $("#first_name").val(user.first_name); }); }); } else { $.getJSON("/api/user/" + last.note.user + "/", function(user) { $("#last_name").val(user.last_name); $("#first_name").val(user.first_name); }); } } return true; } autoCompleteNote("source_note", "source_note_list", sources, sources_notes_display, "source_alias", "source_note", "user_note", "profile_pic", checkUniqueNote); autoCompleteNote("dest_note", "dest_note_list", dests, dests_notes_display, "dest_alias", "dest_note", "user_note", "profile_pic", checkUniqueNote); let source = $("#source_note"); let dest = $("#dest_note"); $("#type_transfer").change(function() { if (LOCK) return; $("#source_me_div").removeClass('d-none'); $("#source_note").removeClass('is-invalid'); $("#dest_note").removeClass('is-invalid'); $("#special_transaction_div").addClass('d-none'); source.removeClass('d-none'); $("#source_note_list").removeClass('d-none'); $("#credit_type").addClass('d-none'); dest.removeClass('d-none'); $("#dest_note_list").removeClass('d-none'); $("#debit_type").addClass('d-none'); $("#source_note_label").text(select_emitters_label); $("#dest_note_label").text(select_receveirs_label); location.hash = "transfer"; }); $("#type_credit").change(function() { if (LOCK) return; $("#source_me_div").addClass('d-none'); $("#source_note").removeClass('is-invalid'); $("#dest_note").removeClass('is-invalid'); $("#special_transaction_div").removeClass('d-none'); $("#source_note_list").addClass('d-none'); $("#dest_note_list").removeClass('d-none'); source.addClass('d-none'); source.tooltip('hide'); $("#credit_type").removeClass('d-none'); dest.removeClass('d-none'); dest.val(''); dest.tooltip('hide'); $("#debit_type").addClass('d-none'); $("#source_note_label").text(transfer_type_label); $("#dest_note_label").text(select_receveir_label); if (dests_notes_display.length > 1) { $("#dest_note_list").html(''); dests_notes_display.length = 0; } location.hash = "credit"; }); $("#type_debit").change(function() { if (LOCK) return; $("#source_me_div").addClass('d-none'); $("#source_note").removeClass('is-invalid'); $("#dest_note").removeClass('is-invalid'); $("#special_transaction_div").removeClass('d-none'); $("#source_note_list").removeClass('d-none'); $("#dest_note_list").addClass('d-none'); source.removeClass('d-none'); source.val(''); source.tooltip('hide'); $("#credit_type").addClass('d-none'); dest.addClass('d-none'); dest.tooltip('hide'); $("#debit_type").removeClass('d-none'); $("#source_note_label").text(select_emitter_label); $("#dest_note_label").text(transfer_type_label); if (sources_notes_display.length > 1) { $("#source_note_list").html(''); sources_notes_display.length = 0; } location.hash = "debit"; }); $("#credit_type").change(function() { let type = $("#credit_type option:selected").text(); if ($("#type_credit").is(":checked")) source.val(type); else dest.val(type); }); // Ensure we begin in transfer mode. Removing these lines may cause problems when reloading. let type_transfer = $("#type_transfer"); // Default mode type_transfer.removeAttr('checked'); $("#type_credit").removeAttr('checked'); $("#type_debit").removeAttr('checked'); if (location.hash) $("#type_" + location.hash.substr(1)).click(); else type_transfer.click(); $("#source_me").click(function() { if (LOCK) return; // Shortcut to set the current user as the only emitter sources_notes_display.length = 0; sources.length = 0; $("#source_note_list").html(""); let source_note = $("#source_note"); source_note.focus(); source_note.val(""); let event = jQuery.Event("keyup"); event.originalEvent = {charCode: 97}; source_note.trigger(event); source_note.val(username); event = jQuery.Event("keyup"); event.originalEvent = {charCode: 97}; source_note.trigger(event); let fill_note = function() { if (sources.length === 0) { setTimeout(fill_note, 100); return; } event = jQuery.Event("keypress"); event.originalEvent = {charCode: 13}; source_note.trigger(event); source_note.tooltip('hide'); source_note.val(''); $("#dest_note").focus(); }; fill_note(); }); }); $("#btn_transfer").click(function() { if (LOCK) return; LOCK = true; let error = false; let amount_field = $("#amount"); amount_field.removeClass('is-invalid'); $("#amount-required").html(""); let reason_field = $("#reason"); reason_field.removeClass('is-invalid'); $("#reason-required").html(""); if (!amount_field.val() || isNaN(amount_field.val()) || amount_field.val() <= 0) { amount_field.addClass('is-invalid'); $("#amount-required").html("Ce champ est requis et doit comporter un nombre décimal strictement positif."); error = true; } let amount = Math.floor(100 * amount_field.val()); if (amount > 2147483647) { amount_field.addClass('is-invalid'); $("#amount-required").html("Le montant ne doit pas excéder 21474836.47 €."); error = true; } if (!reason_field.val()) { reason_field.addClass('is-invalid'); $("#reason-required").html("Ce champ est requis."); error = true; } if (!sources_notes_display.length && !$("#type_credit").is(':checked')) { $("#source_note").addClass('is-invalid'); error = true; } if (!dests_notes_display.length && !$("#type_debit").is(':checked')) { $("#dest_note").addClass('is-invalid'); error = true; } if (error) { LOCK = false; return; } let reason = reason_field.val(); if ($("#type_transfer").is(':checked')) { // We copy the arrays to ensure that transactions are well-processed even if the form is reset [...sources_notes_display].forEach(function (source) { [...dests_notes_display].forEach(function (dest) { if (source.note.id === dest.note.id) { addMsg("Attention : la transaction de " + pretty_money(amount) + " de la note " + source.name + " vers la note " + dest.name + " n'a pas été faite car il s'agit de la même note au départ" + " et à l'arrivée.","warning", 10000); LOCK = false; return; } $.post("/api/note/transaction/transaction/", { "csrfmiddlewaretoken": CSRF_TOKEN, "quantity": source.quantity * dest.quantity, "amount": amount, "reason": reason, "valid": true, "polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE, "resourcetype": "Transaction", "source": source.note.id, "source_alias": source.name, "destination": dest.note.id, "destination_alias": dest.name }).done(function () { if (source.note.membership && source.note.membership.date_end < new Date().toISOString()) addMsg("Attention : la note émettrice " + source.name + " n'est plus adhérente.", "danger", 30000); if (dest.note.membership && dest.note.membership.date_end < new Date().toISOString()) addMsg("Attention : la note destination " + dest.name + " n'est plus adhérente.", "danger", 30000); if (!isNaN(source.note.balance)) { let newBalance = source.note.balance - source.quantity * dest.quantity * amount; if (newBalance <= -5000) { addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a été fait avec succès, " + "mais la note émettrice est en négatif sévère.", "danger", 10000); reset(); return; } else if (newBalance < 0) { addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a été fait avec succès, " + "mais la note émettrice est en négatif.", "warning", 10000); reset(); return; } } addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a été fait avec succès !", "success", 10000); reset(); }).fail(function (err) { // do it again but valid = false let errObj = JSON.parse(err.responseText); if (errObj["non_field_errors"]) { addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a échoué : " + errObj["non_field_errors"], "danger"); LOCK = false; return; } $.post("/api/note/transaction/transaction/", { "csrfmiddlewaretoken": CSRF_TOKEN, "quantity": source.quantity * dest.quantity, "amount": amount, "reason": reason, "valid": false, "invalidity_reason": "Solde insuffisant", "polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE, "resourcetype": "Transaction", "source": source.note.id, "source_alias": source.name, "destination": dest.note.id, "destination_alias": dest.name }).done(function () { addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a échoué : Solde insuffisant", "danger", 10000); reset(); }).fail(function (err) { let errObj = JSON.parse(err.responseText); let error = errObj["detail"] ? errObj["detail"] : errObj["non_field_errors"] if (!error) error = err.responseText; addMsg("Le transfert de " + pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name + " vers la note " + dest.name + " a échoué : " + error, "danger"); LOCK = false; }); }); }); }); } else if ($("#type_credit").is(':checked') || $("#type_debit").is(':checked')) { let special_note; let user_note; let alias; let given_reason = reason; let source_id, dest_id; if ($("#type_credit").is(':checked')) { special_note = $("#credit_type").val(); user_note = dests_notes_display[0].note; alias = dests_notes_display[0].name; source_id = special_note; dest_id = user_note.id; reason = "Crédit " + $("#credit_type option:selected").text().toLowerCase(); if (given_reason.length > 0) reason += " (" + given_reason + ")"; } else { special_note = $("#debit_type").val(); user_note = sources_notes_display[0].note; alias = sources_notes_display[0].name; source_id = user_note.id; dest_id = special_note; reason = "Retrait " + $("#credit_type option:selected").text().toLowerCase(); if (given_reason.length > 0) reason += " (" + given_reason + ")"; } $.post("/api/note/transaction/transaction/", { "csrfmiddlewaretoken": CSRF_TOKEN, "quantity": 1, "amount": amount, "reason": reason, "valid": true, "polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE, "resourcetype": "SpecialTransaction", "source": source_id, "source_alias": sources_notes_display.length ? alias : null, "destination": dest_id, "destination_alias": dests_notes_display.length ? alias : null, "last_name": $("#last_name").val(), "first_name": $("#first_name").val(), "bank": $("#bank").val() }).done(function () { addMsg("Le crédit/retrait a bien été effectué !", "success", 10000); if (user_note.membership && user_note.membership.date_end < new Date().toISOString()) addMsg("Attention : la note " + alias + " n'est plus adhérente.", "danger", 10000); reset(); }).fail(function (err) { let errObj = JSON.parse(err.responseText); let error = errObj["detail"] ? errObj["detail"] : errObj["non_field_errors"] if (!error) error = err.responseText; addMsg("Le crédit/retrait a échoué : " + error, "danger", 10000); LOCK = false; }); } });