mirror of https://gitlab.crans.org/bde/nk20
Compare commits
7 Commits
963ba05d01
...
11fbbca2a8
Author | SHA1 | Date |
---|---|---|
Yohann D'ANELLO | 11fbbca2a8 | |
Yohann D'ANELLO | 901af1a86a | |
Yohann D'ANELLO | 5f87e76be8 | |
Yohann D'ANELLO | 8c885d372b | |
Yohann D'ANELLO | 255e4dd0aa | |
Yohann D'ANELLO | 4afb849aec | |
Yohann D'ANELLO | 872456df20 |
|
@ -142,7 +142,10 @@ class Profile(models.Model):
|
||||||
indexes = [models.Index(fields=['user'])]
|
indexes = [models.Index(fields=['user'])]
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('user_detail', args=(self.pk,))
|
return reverse('member:user_detail', args=(self.user_id,))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.user)
|
||||||
|
|
||||||
def send_email_validation_link(self):
|
def send_email_validation_link(self):
|
||||||
subject = "[Note Kfet]" + str(_("Activate your Note Kfet account"))
|
subject = "[Note Kfet]" + str(_("Activate your Note Kfet account"))
|
||||||
|
|
|
@ -237,9 +237,9 @@ class TransactionPolymorphicSerializer(PolymorphicSerializer):
|
||||||
field.set(value)
|
field.set(value)
|
||||||
else:
|
else:
|
||||||
setattr(instance, attr, value)
|
setattr(instance, attr, value)
|
||||||
instance.validate(True)
|
instance.validate()
|
||||||
else:
|
else:
|
||||||
serializer.Meta.model(**attrs).validate(True)
|
serializer.Meta.model(**attrs).validate()
|
||||||
attrs[self.resource_type_field_name] = resource_type
|
attrs[self.resource_type_field_name] = resource_type
|
||||||
return super().validate(attrs)
|
return super().validate(attrs)
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ class TransactionTemplate(models.Model):
|
||||||
|
|
||||||
amount = models.PositiveIntegerField(
|
amount = models.PositiveIntegerField(
|
||||||
verbose_name=_('amount'),
|
verbose_name=_('amount'),
|
||||||
help_text=_('in centimes'),
|
|
||||||
)
|
)
|
||||||
category = models.ForeignKey(
|
category = models.ForeignKey(
|
||||||
TemplateCategory,
|
TemplateCategory,
|
||||||
|
@ -164,7 +163,7 @@ class Transaction(PolymorphicModel):
|
||||||
models.Index(fields=['destination']),
|
models.Index(fields=['destination']),
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate(self, reset=False):
|
def validate(self):
|
||||||
previous_source_balance = self.source.balance
|
previous_source_balance = self.source.balance
|
||||||
previous_dest_balance = self.destination.balance
|
previous_dest_balance = self.destination.balance
|
||||||
|
|
||||||
|
@ -188,23 +187,19 @@ class Transaction(PolymorphicModel):
|
||||||
source_balance = self.source.balance
|
source_balance = self.source.balance
|
||||||
dest_balance = self.destination.balance
|
dest_balance = self.destination.balance
|
||||||
|
|
||||||
if reset:
|
|
||||||
self.source.balance = previous_source_balance
|
|
||||||
self.destination.balance = previous_dest_balance
|
|
||||||
|
|
||||||
if source_balance > 2147483647 or source_balance < -2147483648\
|
if source_balance > 2147483647 or source_balance < -2147483648\
|
||||||
or dest_balance > 2147483647 or dest_balance < -2147483648:
|
or dest_balance > 2147483647 or dest_balance < -2147483648:
|
||||||
raise ValidationError(_("The note balances must be between - 21 474 836.47 € and 21 474 836.47 €."))
|
raise ValidationError(_("The note balances must be between - 21 474 836.47 € and 21 474 836.47 €."))
|
||||||
|
|
||||||
|
return source_balance - previous_source_balance, dest_balance - previous_dest_balance
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
When saving, also transfer money between two notes
|
When saving, also transfer money between two notes
|
||||||
"""
|
"""
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
self.source.refresh_from_db()
|
diff_source, diff_dest = self.validate()
|
||||||
self.destination.refresh_from_db()
|
|
||||||
self.validate(False)
|
|
||||||
|
|
||||||
if not self.source.is_active or not self.destination.is_active:
|
if not self.source.is_active or not self.destination.is_active:
|
||||||
if 'force_insert' not in kwargs or not kwargs['force_insert']:
|
if 'force_insert' not in kwargs or not kwargs['force_insert']:
|
||||||
|
@ -229,9 +224,13 @@ class Transaction(PolymorphicModel):
|
||||||
self.log("Saved")
|
self.log("Saved")
|
||||||
|
|
||||||
# Save notes
|
# Save notes
|
||||||
|
self.source.refresh_from_db()
|
||||||
|
self.source.balance += diff_source
|
||||||
self.source._force_save = True
|
self.source._force_save = True
|
||||||
self.source.save()
|
self.source.save()
|
||||||
self.log("Source saved")
|
self.log("Source saved")
|
||||||
|
self.destination.refresh_from_db()
|
||||||
|
self.destination.balance += diff_dest
|
||||||
self.destination._force_save = True
|
self.destination._force_save = True
|
||||||
self.destination.save()
|
self.destination.save()
|
||||||
self.log("Destination saved")
|
self.log("Destination saved")
|
||||||
|
|
|
@ -847,10 +847,6 @@ msgstr ""
|
||||||
msgid "A template with this name already exist"
|
msgid "A template with this name already exist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:60
|
|
||||||
msgid "in centimes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:72
|
#: apps/note/models/transactions.py:72
|
||||||
msgid "display"
|
msgid "display"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -504,7 +504,7 @@ msgstr "adresse email confirmée"
|
||||||
|
|
||||||
#: apps/member/models.py:111
|
#: apps/member/models.py:111
|
||||||
msgid "registration valid"
|
msgid "registration valid"
|
||||||
msgstr "inscription valid"
|
msgstr "inscription valide"
|
||||||
|
|
||||||
#: apps/member/models.py:140 apps/member/models.py:141
|
#: apps/member/models.py:140 apps/member/models.py:141
|
||||||
msgid "user profile"
|
msgid "user profile"
|
||||||
|
@ -854,10 +854,6 @@ msgstr "catégories de transaction"
|
||||||
msgid "A template with this name already exist"
|
msgid "A template with this name already exist"
|
||||||
msgstr "Un modèle de transaction avec un nom similaire existe déjà."
|
msgstr "Un modèle de transaction avec un nom similaire existe déjà."
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:60
|
|
||||||
msgid "in centimes"
|
|
||||||
msgstr "en centimes"
|
|
||||||
|
|
||||||
#: apps/note/models/transactions.py:72
|
#: apps/note/models/transactions.py:72
|
||||||
msgid "display"
|
msgid "display"
|
||||||
msgstr "afficher"
|
msgstr "afficher"
|
||||||
|
@ -2373,7 +2369,7 @@ msgid ""
|
||||||
"You recently registered on the Note Kfet. Please click on the link below to "
|
"You recently registered on the Note Kfet. Please click on the link below to "
|
||||||
"confirm your registration."
|
"confirm your registration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous vous êtes inscrits récemment sur la Note Kfet. Merci de cliquer sur le "
|
"Vous vous êtes inscrit·e récemment sur la Note Kfet. Merci de cliquer sur le "
|
||||||
"lien ci-dessous pour confirmer votre adresse email."
|
"lien ci-dessous pour confirmer votre adresse email."
|
||||||
|
|
||||||
#: templates/registration/mails/email_validation_email.html:26
|
#: templates/registration/mails/email_validation_email.html:26
|
||||||
|
|
|
@ -265,7 +265,10 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
|
||||||
consumers.results.forEach(function (consumer) {
|
consumers.results.forEach(function (consumer) {
|
||||||
let note = consumer.note;
|
let note = consumer.note;
|
||||||
note.email_confirmed = consumer.email_confirmed;
|
note.email_confirmed = consumer.email_confirmed;
|
||||||
note.membership = consumer.membership;
|
if (consumer.hasOwnProperty("membership") && consumer.membership)
|
||||||
|
note.membership = consumer.membership;
|
||||||
|
else
|
||||||
|
note.membership = undefined;
|
||||||
let extra_css = displayStyle(note);
|
let extra_css = displayStyle(note);
|
||||||
aliases_matched_html += li(alias_prefix + '_' + consumer.id,
|
aliases_matched_html += li(alias_prefix + '_' + consumer.id,
|
||||||
consumer.name,
|
consumer.name,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
// Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
// When a transaction is performed, lock the interface to prevent spam clicks.
|
||||||
|
var LOCK = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the history table on the consumptions page.
|
* Refresh the history table on the consumptions page.
|
||||||
*/
|
*/
|
||||||
|
@ -35,8 +38,11 @@ $(document).ready(function() {
|
||||||
note_list_obj.html("");
|
note_list_obj.html("");
|
||||||
|
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function(button) {
|
||||||
$("#conso_button_" + button.id).click(removeNote(button, "conso_button", buttons,
|
$("#conso_button_" + button.id).click(function() {
|
||||||
"consos_list"));
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
removeNote(button, "conso_button", buttons,"consos_list");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -52,8 +58,11 @@ $(document).ready(function() {
|
||||||
$("#note_list").html(consos_list_obj.html());
|
$("#note_list").html(consos_list_obj.html());
|
||||||
consos_list_obj.html("");
|
consos_list_obj.html("");
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function(button) {
|
||||||
$("#conso_button_" + button.id).click(removeNote(button, "conso_button", buttons,
|
$("#conso_button_" + button.id).click(function() {
|
||||||
"note_list"));
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
removeNote(button, "conso_button", buttons,"note_list");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -127,7 +136,11 @@ function addConso(dest, amount, type, category_id, category_name, template_id, t
|
||||||
$("#" + list).html(html);
|
$("#" + list).html(html);
|
||||||
|
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function(button) {
|
||||||
$("#conso_button_" + button.id).click(removeNote(button, "conso_button", buttons, list));
|
$("#conso_button_" + button.id).click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
removeNote(button, "conso_button", buttons, list);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -148,6 +161,7 @@ function reset() {
|
||||||
$("#profile_pic_link").attr("href", "#");
|
$("#profile_pic_link").attr("href", "#");
|
||||||
refreshHistory();
|
refreshHistory();
|
||||||
refreshBalance();
|
refreshBalance();
|
||||||
|
LOCK = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,6 +169,11 @@ function reset() {
|
||||||
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
||||||
*/
|
*/
|
||||||
function consumeAll() {
|
function consumeAll() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOCK = true;
|
||||||
|
|
||||||
let error = false;
|
let error = false;
|
||||||
|
|
||||||
if (notes_display.length === 0) {
|
if (notes_display.length === 0) {
|
||||||
|
@ -168,8 +187,10 @@ function consumeAll() {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error) {
|
||||||
|
LOCK = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
notes_display.forEach(function(note_display) {
|
notes_display.forEach(function(note_display) {
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function(button) {
|
||||||
|
@ -218,7 +239,7 @@ function consume(source, source_alias, dest, quantity, amount, reason, type, cat
|
||||||
addMsg("Attention, La transaction depuis la note " + source_alias + " a été réalisée avec " +
|
addMsg("Attention, La transaction depuis la note " + source_alias + " a été réalisée avec " +
|
||||||
"succès, mais la note émettrice " + source_alias + " est en négatif.",
|
"succès, mais la note émettrice " + source_alias + " est en négatif.",
|
||||||
"warning", 30000);
|
"warning", 30000);
|
||||||
if (source.note.membership && source.note.membership.date_end < new Date().toISOString())
|
if (source.membership && source.membership.date_end < new Date().toISOString())
|
||||||
addMsg("Attention : la note émettrice " + source.name + " n'est plus adhérente.",
|
addMsg("Attention : la note émettrice " + source.name + " n'est plus adhérente.",
|
||||||
"danger", 30000);
|
"danger", 30000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
var LOCK = false;
|
||||||
|
|
||||||
sources = [];
|
sources = [];
|
||||||
sources_notes_display = [];
|
sources_notes_display = [];
|
||||||
dests = [];
|
dests = [];
|
||||||
|
@ -42,6 +44,8 @@ function reset(refresh=true) {
|
||||||
refreshBalance();
|
refreshBalance();
|
||||||
refreshHistory();
|
refreshHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCK = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
@ -91,6 +95,9 @@ $(document).ready(function() {
|
||||||
let dest = $("#dest_note");
|
let dest = $("#dest_note");
|
||||||
|
|
||||||
$("#type_transfer").click(function() {
|
$("#type_transfer").click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
$("#source_me_div").removeClass('d-none');
|
$("#source_me_div").removeClass('d-none');
|
||||||
$("#source_note").removeClass('is-invalid');
|
$("#source_note").removeClass('is-invalid');
|
||||||
$("#dest_note").removeClass('is-invalid');
|
$("#dest_note").removeClass('is-invalid');
|
||||||
|
@ -102,6 +109,9 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#type_credit").click(function() {
|
$("#type_credit").click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
$("#source_me_div").addClass('d-none');
|
$("#source_me_div").addClass('d-none');
|
||||||
$("#source_note").removeClass('is-invalid');
|
$("#source_note").removeClass('is-invalid');
|
||||||
$("#dest_note").removeClass('is-invalid');
|
$("#dest_note").removeClass('is-invalid');
|
||||||
|
@ -122,6 +132,9 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#type_debit").click(function() {
|
$("#type_debit").click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
$("#source_me_div").addClass('d-none');
|
$("#source_me_div").addClass('d-none');
|
||||||
$("#source_note").removeClass('is-invalid');
|
$("#source_note").removeClass('is-invalid');
|
||||||
$("#dest_note").removeClass('is-invalid');
|
$("#dest_note").removeClass('is-invalid');
|
||||||
|
@ -165,6 +178,9 @@ $(document).ready(function() {
|
||||||
location.hash = "";
|
location.hash = "";
|
||||||
|
|
||||||
$("#source_me").click(function() {
|
$("#source_me").click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
// Shortcut to set the current user as the only emitter
|
// Shortcut to set the current user as the only emitter
|
||||||
sources_notes_display.length = 0;
|
sources_notes_display.length = 0;
|
||||||
sources.length = 0;
|
sources.length = 0;
|
||||||
|
@ -198,6 +214,11 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#btn_transfer").click(function() {
|
$("#btn_transfer").click(function() {
|
||||||
|
if (LOCK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOCK = true;
|
||||||
|
|
||||||
let error = false;
|
let error = false;
|
||||||
|
|
||||||
let amount_field = $("#amount");
|
let amount_field = $("#amount");
|
||||||
|
@ -237,8 +258,10 @@ $("#btn_transfer").click(function() {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error) {
|
||||||
|
LOCK = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let reason = reason_field.val();
|
let reason = reason_field.val();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue