Compare commits

..

No commits in common. "66defee3ea84145039d202ec6aeeede54884cca8" and "58fe8914cfd5a0dfca76e92bde4e638b1ff827c2" have entirely different histories.

9 changed files with 43 additions and 66 deletions

View File

@ -68,8 +68,12 @@ class HistoryTable(tables.Table):
"note.change_transaction_invalidity_reason", record) else None,
"onmouseover": lambda record: '$("#invalidity_reason_'
+ str(record.id) + '").show();$("#invalidity_reason_'
+ str(record.id) + '").focus();',
"onmouseout": lambda record: '$("#invalidity_reason_' + str(record.id) + '").hide()',
+ str(record.id) + '").focus();'
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
"onmouseout": lambda record: '$("#invalidity_reason_' + str(record.id) + '").hide()'
if PermissionBackend.check_perm(get_current_authenticated_user(),
"note.change_transaction_invalidity_reason", record) else None,
}
}
)
@ -97,18 +101,15 @@ class HistoryTable(tables.Table):
"""
When the validation status is hovered, an input field is displayed to let the user specify an invalidity reason
"""
has_perm = PermissionBackend\
.check_perm(get_current_authenticated_user(), "note.change_transaction_invalidity_reason", record)
val = "" if value else ""
if value and not has_perm:
if not PermissionBackend\
.check_perm(get_current_authenticated_user(), "note.change_transaction_invalidity_reason", record):
return val
val += "<input type='text' class='form-control' id='invalidity_reason_" + str(record.id) \
+ "' value='" + (html.escape(record.invalidity_reason)
if record.invalidity_reason else ("" if value else str(_("No reason specified")))) \
+ "'" + ("" if value and has_perm else " disabled") \
+ "'" + ("" if value else " disabled") \
+ " placeholder='" + html.escape(_("invalidity reason").capitalize()) + "'" \
+ " style='position: absolute; width: 15em; margin-left: -15.5em; margin-top: -2em; display: none;'>"
return format_html(val)

View File

@ -4,15 +4,12 @@
import functools
import json
import operator
from copy import copy
from time import sleep
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.core.mail import mail_admins
from django.db import models
from django.db.models import F, Q, Model
from django.forms import model_to_dict
from django.utils.translation import gettext_lazy as _
@ -41,40 +38,35 @@ class InstancedPermission:
if permission_type == self.type:
self.update_query()
obj = copy(obj)
obj.pk = 0
# Don't increase indexes, if the primary key is an AutoField
if not hasattr(obj, "pk") or not obj.pk:
obj.pk = 0
oldpk = None
else:
oldpk = obj.pk
# Ensure previous models are deleted
for ignored in range(1000):
if self.model.model_class().objects.filter(pk=0).exists():
if self.model.model_class().objects.filter(pk=obj.pk).exists():
# If the object exists, that means that one permission is currently checked.
# We wait before the other permission, at most 1 second.
sleep(0.001)
continue
break
for o in self.model.model_class().objects.filter(pk=0).all():
for o in self.model.model_class().objects.filter(pk=obj.pk).all():
o._force_delete = True
Model.delete(o)
# An object with pk 0 wouldn't deleted. That's not normal, we alert admins.
msg = "Lors de la vérification d'une permission d'ajout, un objet de clé primaire nulle était "\
"encore présent.\n"\
"Type de permission : " + self.type + "\n"\
"Modèle : " + str(self.model) + "\n"\
"Objet trouvé : " + str(model_to_dict(o)) + "\n\n"\
"--\nLe BDE"
mail_admins("[Note Kfet] Un objet a été supprimé de force", msg)
# Force insertion, no data verification, no trigger
obj._force_save = True
Model.save(obj, force_insert=True)
# We don't want log anything
obj._no_log = True
ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
ret = self.model.model_class().objects.filter(self.query & Q(pk=obj.pk)).exists()
# Delete testing object
obj._force_delete = True
Model.delete(obj)
with open("/tmp/log", "w") as f:
f.write(str(obj) + ", " + str(obj.pk) + ", " + str(self.model.model_class().objects.filter(pk=0).exists()))
# If the primary key was specified, we restore it
obj.pk = oldpk
return ret
if permission_type == self.type:

View File

@ -179,6 +179,8 @@ class FutureUserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableVi
| Q(profile__section__iregex=pattern)
| Q(username__iregex="^" + pattern)
)
else:
qs = qs.none()
return qs[:20]

@ -1 +1 @@
Subproject commit f41a5a32f7417a874b497640373ea3911eb1e133
Subproject commit 1f300c3b7bac0b7a31c1a252a83ba68a8268d33d

View File

@ -236,12 +236,14 @@ class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTable
pattern = self.request.GET.get("search", "")
if not pattern:
qs = qs.filter(
Q(user__first_name__iregex=pattern)
| Q(user__last_name__iregex=pattern)
| Q(user__note__alias__name__iregex="^" + pattern)
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
)
return qs.none()
qs = qs.filter(
Q(user__first_name__iregex=pattern)
| Q(user__last_name__iregex=pattern)
| Q(user__note__alias__name__iregex="^" + pattern)
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
)
return qs[:20]

View File

@ -217,7 +217,6 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
// Clear search on click
field.click(function () {
field.tooltip('hide');
field.removeClass('is-invalid');
field.val("");
});
@ -234,8 +233,6 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
// When the user type something, the matched aliases are refreshed
field.keyup(function (e) {
field.removeClass('is-invalid');
if (e.originalEvent.charCode === 13)
return;

View File

@ -154,22 +154,6 @@ function reset() {
* Apply all transactions: all notes in `notes` buy each item in `buttons`
*/
function consumeAll() {
let error = false;
if (notes_display.length === 0) {
$("#note").addClass('is-invalid');
$("#note_list").html(li("", "<strong>Ajoutez des émetteurs.</strong>", "text-danger"));
error = true;
}
if (buttons.length === 0) {
$("#consos_list").html(li("", "<strong>Ajoutez des consommations.</strong>", "text-danger"));
error = true;
}
if (error)
return;
notes_display.forEach(function(note_display) {
buttons.forEach(function(button) {
consume(note_display.note, note_display.name, button.dest, button.quantity * note_display.quantity, button.amount,

View File

@ -219,16 +219,6 @@ $("#btn_transfer").click(function() {
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)
return;
@ -296,7 +286,6 @@ $("#btn_transfer").click(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) {
addMsg("Le transfert de "
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name
@ -311,6 +300,11 @@ $("#btn_transfer").click(function() {
let given_reason = reason;
let source_id, dest_id;
if ($("#type_credit").is(':checked')) {
if (!dests_notes_display.length) {
$("#dest_note").addClass('is-invalid');
return;
}
user_note = dests_notes_display[0].note.id;
source_id = special_note;
dest_id = user_note;
@ -319,6 +313,11 @@ $("#btn_transfer").click(function() {
reason += " (" + given_reason + ")";
}
else {
if (!sources_notes_display.length) {
$("#source_note").addClass('is-invalid');
return;
}
user_note = sources_notes_display[0].note.id;
source_id = user_note;
dest_id = special_note;

View File

@ -53,9 +53,9 @@
</ul>
</div>
<div class="card-footer text-center">
<span id="consume_all" class="btn btn-primary">
<a id="consume_all" href="#" class="btn btn-primary">
{% trans "Consume!" %}
</span>
</a>
</div>
</div>
</div>