Compare commits

..

7 Commits

Author SHA1 Message Date
Yohann D'ANELLO b706efe463 2A+ can change their selected bus or team if the registration is not validated 2020-08-01 23:27:07 +02:00
Yohann D'ANELLO 37dc535d6d Display only one user 2020-08-01 23:05:14 +02:00
Yohann D'ANELLO 5ccbad8359 Fix transfer form reset 2020-08-01 23:03:10 +02:00
Yohann D'ANELLO c0cdb13130 Can't concatenate string and proxy 2020-08-01 22:30:34 +02:00
Yohann D'ANELLO 8434841ec5 Fix one permission 2020-08-01 22:28:28 +02:00
Yohann D'ANELLO cadf981013 passer en négatif -> être en négatif 2020-08-01 21:48:18 +02:00
Yohann D'ANELLO efc2b6b0b0 Send mail to users when the note balance is negative 2020-08-01 21:44:16 +02:00
16 changed files with 250 additions and 36 deletions

View File

@ -131,15 +131,22 @@ class Profile(models.Model):
return reverse('user_detail', args=(self.pk,)) return reverse('user_detail', args=(self.pk,))
def send_email_validation_link(self): def send_email_validation_link(self):
subject = _("Activate your Note Kfet account") subject = "[Note Kfet]" + str(_("Activate your Note Kfet account"))
message = loader.render_to_string('registration/mails/email_validation_email.html', message = loader.render_to_string('registration/mails/email_validation_email.txt',
{ {
'user': self.user, 'user': self.user,
'domain': os.getenv("NOTE_URL", "note.example.com"), 'domain': os.getenv("NOTE_URL", "note.example.com"),
'token': email_validation_token.make_token(self.user), 'token': email_validation_token.make_token(self.user),
'uid': urlsafe_base64_encode(force_bytes(self.user.pk)), 'uid': urlsafe_base64_encode(force_bytes(self.user.pk)),
}) })
self.user.email_user(subject, message) html = loader.render_to_string('registration/mails/email_validation_email.txt',
{
'user': self.user,
'domain': os.getenv("NOTE_URL", "note.example.com"),
'token': email_validation_token.make_token(self.user),
'uid': urlsafe_base64_encode(force_bytes(self.user.pk)),
})
self.user.email_user(subject, message, html_message=html)
class Club(models.Model): class Club(models.Model):

View File

@ -131,7 +131,7 @@ class UserDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
""" """
We can't display information of a not registered user. We can't display information of a not registered user.
""" """
return super().get_queryset().filter(profile__registration_valid=True) return super().get_queryset().filter(profile__registration_valid=True).distinct()
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)

View File

@ -7,6 +7,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models from django.db import models
from django.template.loader import render_to_string
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
@ -67,6 +68,13 @@ class Note(PolymorphicModel):
pretty.short_description = _('Note') pretty.short_description = _('Note')
@property
def last_negative_duration(self):
if self.balance >= 0 or self.last_negative is None:
return None
delta = timezone.now() - self.last_negative
return "{:d} jours".format(delta.days)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
""" """
Save note with it's alias (called in polymorphic children) Save note with it's alias (called in polymorphic children)
@ -128,6 +136,21 @@ class NoteUser(Note):
def pretty(self): def pretty(self):
return _("%(user)s's note") % {'user': str(self.user)} return _("%(user)s's note") % {'user': str(self.user)}
def save(self, *args, **kwargs):
if self.pk and self.balance < 0:
old_note = NoteUser.objects.get(pk=self.pk)
if old_note.balance >= 0:
# Passage en négatif
self.last_negative = timezone.now()
self.send_mail_negative_balance()
super().save(*args, **kwargs)
def send_mail_negative_balance(self):
plain_text = render_to_string("note/mails/negative_balance.txt", dict(note=self))
html = render_to_string("note/mails/negative_balance.html", dict(note=self))
self.user.email_user("[Note Kfet] Passage en négatif (compte n°{:d})"
.format(self.user.pk), plain_text, html_message=html)
class NoteClub(Note): class NoteClub(Note):
""" """

View File

@ -7,7 +7,7 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from polymorphic.models import PolymorphicModel from polymorphic.models import PolymorphicModel
from .notes import Note, NoteClub, NoteSpecial from .notes import Note, NoteClub, NoteSpecial, NoteUser
from ..templatetags.pretty_money import pretty_money from ..templatetags.pretty_money import pretty_money
""" """

View File

@ -2207,7 +2207,7 @@
"auth", "auth",
"user" "user"
], ],
"query": "{\"memberships__club\": [\"club\"], \"memberships__date__start__lte\": [\"today\"], \"memberships__date__end__gte\": [\"today\"]}", "query": "{\"memberships__club\": [\"club\"], \"memberships__date_start__lte\": [\"today\"], \"memberships__date_end__gte\": [\"today\"]}",
"type": "view", "type": "view",
"mask": 3, "mask": 3,
"field": "", "field": "",
@ -2247,6 +2247,22 @@
"description": "Créer une note d'utilisateur" "description": "Créer une note d'utilisateur"
} }
}, },
{
"model": "permission.permission",
"pk": 144,
"fields": {
"model": [
"wei",
"weiregistration"
],
"query": "[\"AND\", {\"user\": [\"user\"], \"wei__membership_start__lte\": [\"today\"], \"wei__membership_end__gte\": [\"today\"], \"first_year\": false, \"membership\": null}]",
"type": "change",
"mask": 1,
"field": "information_json",
"permanent": false,
"description": "Modifier mes préférences en terme de bus et d'équipe si mon inscription n'est pas validée et que je suis en 2A+"
}
},
{ {
"model": "permission.role", "model": "permission.role",
"pk": 1, "pk": 1,
@ -2300,7 +2316,8 @@
99, 99,
101, 101,
108, 108,
109 109,
144
] ]
} }
}, },
@ -2569,7 +2586,8 @@
140, 140,
141, 141,
142, 142,
143 143,
144
] ]
} }
}, },

@ -1 +1 @@
Subproject commit dce51ad26134d396d7cbfca7c63bd2ed391dd969 Subproject commit 4b37f8286f493b1a28bd0faa0052ee3967fe543e

View File

@ -2128,33 +2128,33 @@ msgstr ""
msgid "Forgotten your password or username?" msgid "Forgotten your password or username?"
msgstr "" msgstr ""
#: templates/registration/mails/email_validation_email.html:3 #: templates/registration/mails/email_validation_email.txt:3
msgid "Hi" msgid "Hi"
msgstr "" msgstr ""
#: templates/registration/mails/email_validation_email.html:5 #: templates/registration/mails/email_validation_email.txt:5
msgid "" 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 ""
#: templates/registration/mails/email_validation_email.html:9 #: templates/registration/mails/email_validation_email.txt:9
msgid "" msgid ""
"This link is only valid for a couple of days, after that you will need to " "This link is only valid for a couple of days, after that you will need to "
"contact us to validate your email." "contact us to validate your email."
msgstr "" msgstr ""
#: templates/registration/mails/email_validation_email.html:11 #: templates/registration/mails/email_validation_email.txt:11
msgid "" msgid ""
"After that, you'll have to wait that someone validates your account before " "After that, you'll have to wait that someone validates your account before "
"you can log in. You will need to pay your membership in the Kfet." "you can log in. You will need to pay your membership in the Kfet."
msgstr "" msgstr ""
#: templates/registration/mails/email_validation_email.html:13 #: templates/registration/mails/email_validation_email.txt:13
msgid "Thanks" msgid "Thanks"
msgstr "" msgstr ""
#: templates/registration/mails/email_validation_email.html:15 #: templates/registration/mails/email_validation_email.txt:15
msgid "The Note Kfet team." msgid "The Note Kfet team."
msgstr "" msgstr ""

View File

@ -2197,11 +2197,11 @@ msgstr ""
msgid "Forgotten your password or username?" msgid "Forgotten your password or username?"
msgstr "Mot de passe ou pseudo oublié ?" msgstr "Mot de passe ou pseudo oublié ?"
#: templates/registration/mails/email_validation_email.html:3 #: templates/registration/mails/email_validation_email.txt:3
msgid "Hi" msgid "Hi"
msgstr "Bonjour" msgstr "Bonjour"
#: templates/registration/mails/email_validation_email.html:5 #: templates/registration/mails/email_validation_email.txt:5
msgid "" 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."
@ -2209,7 +2209,7 @@ msgstr ""
"Vous vous êtes inscrits récemment sur la Note Kfet. Merci de cliquer sur le " "Vous vous êtes inscrits 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:9 #: templates/registration/mails/email_validation_email.txt:9
msgid "" msgid ""
"This link is only valid for a couple of days, after that you will need to " "This link is only valid for a couple of days, after that you will need to "
"contact us to validate your email." "contact us to validate your email."
@ -2217,7 +2217,7 @@ msgstr ""
"Ce lien n'est valide que pendant quelques jours. Après cela, vous devrez " "Ce lien n'est valide que pendant quelques jours. Après cela, vous devrez "
"nous contacter pour valider votre email." "nous contacter pour valider votre email."
#: templates/registration/mails/email_validation_email.html:11 #: templates/registration/mails/email_validation_email.txt:11
msgid "" msgid ""
"After that, you'll have to wait that someone validates your account before " "After that, you'll have to wait that someone validates your account before "
"you can log in. You will need to pay your membership in the Kfet." "you can log in. You will need to pay your membership in the Kfet."
@ -2225,11 +2225,11 @@ msgstr ""
"Après cela, vous devrez attendre que quelqu'un valide votre compte avant de " "Après cela, vous devrez attendre que quelqu'un valide votre compte avant de "
"pouvoir vous connecter. Vous devrez payer votre adhésion à la Kfet." "pouvoir vous connecter. Vous devrez payer votre adhésion à la Kfet."
#: templates/registration/mails/email_validation_email.html:13 #: templates/registration/mails/email_validation_email.txt:13
msgid "Thanks" msgid "Thanks"
msgstr "Merci" msgstr "Merci"
#: templates/registration/mails/email_validation_email.html:15 #: templates/registration/mails/email_validation_email.txt:15
msgid "The Note Kfet team." msgid "The Note Kfet team."
msgstr "L'équipe de la Note Kfet." msgstr "L'équipe de la Note Kfet."

View File

@ -194,10 +194,12 @@ function consume(source, source_alias, dest, quantity, amount, reason, type, cat
if (!isNaN(source.balance)) { if (!isNaN(source.balance)) {
let newBalance = source.balance - quantity * amount; let newBalance = source.balance - quantity * amount;
if (newBalance <= -5000) if (newBalance <= -5000)
addMsg("Attention, la note émettrice " + source_alias + " passe en négatif sévère.", 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 sévère.",
"danger", 10000); "danger", 10000);
else if (newBalance < 0) else if (newBalance < 0)
addMsg("Attention, la note émettrice " + source_alias + " passe en négatif.", 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.",
"warning", 10000); "warning", 10000);
} }
reset(); reset();

View File

@ -16,11 +16,13 @@ function reset(refresh=true) {
$("#dest_note_list").html(""); $("#dest_note_list").html("");
let source_field = $("#source_note"); let source_field = $("#source_note");
source_field.val(""); source_field.val("");
source_field.trigger("keyup"); let event = jQuery.Event("keyup");
event.originalEvent = {charCode: 97};
source_field.trigger(event);
source_field.removeClass('is-invalid'); source_field.removeClass('is-invalid');
let dest_field = $("#dest_note"); let dest_field = $("#dest_note");
dest_field.val(""); dest_field.val("");
dest_field.trigger("keyup"); dest_field.trigger(event);
dest_field.removeClass('is-invalid'); dest_field.removeClass('is-invalid');
let amount_field = $("#amount"); let amount_field = $("#amount");
amount_field.val(""); amount_field.val("");
@ -247,7 +249,7 @@ $("#btn_transfer").click(function() {
addMsg("Le transfert de " addMsg("Le transfert de "
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + pretty_money(source.quantity * dest.quantity * amount) + " de la note "
+ source.name + " vers la note " + dest.name + " a été fait avec succès, " + + source.name + " vers la note " + dest.name + " a été fait avec succès, " +
"mais la note émettrice passe en négatif sévère.", "danger", 10000); "mais la note émettrice est en négatif sévère.", "danger", 10000);
reset(); reset();
return; return;
} }
@ -255,7 +257,7 @@ $("#btn_transfer").click(function() {
addMsg("Le transfert de " addMsg("Le transfert de "
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + pretty_money(source.quantity * dest.quantity * amount) + " de la note "
+ source.name + " vers la note " + dest.name + " a été fait avec succès, " + + source.name + " vers la note " + dest.name + " a été fait avec succès, " +
"mais la note émettrice passe en négatif.", "warning", 10000); "mais la note émettrice est en négatif.", "warning", 10000);
reset(); reset();
return; return;
} }
@ -333,9 +335,9 @@ $("#btn_transfer").click(function() {
"polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE, "polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE,
"resourcetype": "SpecialTransaction", "resourcetype": "SpecialTransaction",
"source": source_id, "source": source_id,
"source_alias": sources_notes_display[0].name, "source_alias": sources_notes_display.length ? sources_notes_display[0].name : null,
"destination": dest_id, "destination": dest_id,
"destination_alias": dests_notes_display[0].name, "destination_alias": dests_notes_display.length ? dests_notes_display[0].name : null,
"last_name": $("#last_name").val(), "last_name": $("#last_name").val(),
"first_name": $("#first_name").val(), "first_name": $("#first_name").val(),
"bank": $("#bank").val() "bank": $("#bank").val()

View File

@ -0,0 +1,44 @@
{% load pretty_money %}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Passage en négatif (compte n°{{ note.user.pk }})</title>
</head>
<body>
<p>
Bonjour {{ note.user.first_name }} {{ note.user.last_name }},
</p>
<p>
Ce mail t'a été envoyé parce que le solde de ta Note Kfet {{ note }} est négatif !
</p>
<p>
Ton solde actuel est de {{ note.balance|pretty_money }}.
</p>
<p>
Par ailleurs, le BDE ne sert pas d'alcool aux adhérents dont le solde
est inférieur à 0 € depuis plus de 24h.
</p>
<p>
Si tu ne comprends pas ton solde, tu peux consulter ton historique
sur <a href="{% url "member:user_detail" pk=note.user.pk %}">ton compte</a>.
</p>
<p>
Tu peux venir recharger ta note rapidement à la Kfet, ou envoyer un mail à
la trésorerie du BdE (<a href="mailto:tresorerie.bde@lists.crans.org">tresorerie.bde@lists.crans.org</a>)
pour payer par virement bancaire.
</p>
--
<p>
Le BDE<br>
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}
</p>
</body>
</html>

View File

@ -0,0 +1,23 @@
{% load pretty_money %}
Bonjour {{ note.user.first_name }} {{ note.user.last_name }},
Ce mail t'a été envoyé parce que le solde de ta Note Kfet
{{ note }} est négatif !
Ton solde actuel est de {{ note.balance|pretty_money }}.
Par ailleurs, le BDE ne sert pas d'alcool aux adhérents dont le solde
est inférieur à 0 € depuis plus de 24h.
Si tu ne comprends pas ton solde, tu peux consulter ton historique
sur ton compte {% url "member:user_detail" pk=note.user.pk %}
Tu peux venir recharger ta note rapidement à la Kfet, ou envoyer un mail à
la trésorerie du BdE (tresorerie.bde@lists.crans.org) pour payer par
virement bancaire.
--
Le BDE
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}

View File

@ -0,0 +1,41 @@
{% load pretty_money %}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>[Note Kfet] Liste des négatifs</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Pseudo</th>
<th>Email</th>
<th>Solde</th>
<th>Durée</th>
</tr>
</thead>
<tbody>
{% for note in notes %}
<tr>
<td>{{ note.user.last_name }}</td>
<td>{{ note.user.first_name }}</td>
<td>{{ note.user.username }}</td>
<td>{{ note.user.email }}</td>
<td>{{ note.balance|pretty_money }}</td>
<td>{{ note.last_negative_duration }}</td>
</tr>
{% endfor %}
</tbody>
</table>
--
<p>
Le BDE<br>
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}
</p>
</body>
</html>

View File

@ -0,0 +1,12 @@
{% load pretty_money %}
Nom | Prénom | Pseudo | Email | Solde | Durée
---------------------+------------+-----------------+-----------------------------------+----------+-----------
{% for note in notes %}
{{ note.user.last_name }} | {{ note.user.first_name }} | {{ note.user.username }} | {{ note.user.email }} | {{ note.balance|pretty_money }} | {{ note.last_negative_duration }}
{% endfor %}
--
Le BDE
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}

View File

@ -1,15 +1,41 @@
{% load i18n %} {% load i18n %}
{% trans "Hi" %} {{ user.username }}, <!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Passage en négatif (compte n°{{ note.user.pk }})</title>
</head>
<body>
{% trans "You recently registered on the Note Kfet. Please click on the link below to confirm your registration." %} <p>
{% trans "Hi" %} {{ user.username }},
</p>
https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %} <p>
{% trans "You recently registered on the Note Kfet. Please click on the link below to confirm your registration." %}
</p>
{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %} <p>
<a href="https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %}">
https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %}
</a>
</p>
{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %} <p>
{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %}
</p>
{% trans "Thanks" %}, <p>
{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %}
</p>
{% trans "The Note Kfet team." %} <p>
{% trans "Thanks" %},
</p>
--
<p>
{% trans "The Note Kfet team." %}
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}
</p>

View File

@ -0,0 +1,16 @@
{% load i18n %}
{% trans "Hi" %} {{ user.username }},
{% trans "You recently registered on the Note Kfet. Please click on the link below to confirm your registration." %}
https://{{ domain }}{% url 'registration:email_validation' uidb64=uid token=token %}
{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %}
{% trans "After that, you'll have to wait that someone validates your account before you can log in. You will need to pay your membership in the Kfet." %}
{% trans "Thanks" %},
{% trans "The Note Kfet team." %}
Mail généré par la Note Kfet le {% now "j F Y à H:i:s" %}