Merge branch 'master' into 'Production'

Update prod

See merge request klub-dev-ens/gestioCOF!517
This commit is contained in:
Tom Hubrecht 2023-02-21 21:50:26 +01:00
commit 3178657e33
8 changed files with 85 additions and 21 deletions

View file

@ -27,6 +27,15 @@ adhérents ni des cotisations.
## Version ??? - ??/??/????
## Version 0.13 - 19/02/2023
### K-Fêt
- Rajoute la valeur des inventaires
- Résout les problèmes de négatif ne disparaissant pas
- Affiche son surnom s'il y en a un
- Bugfixes
## Version 0.12.1 - 03/10/2022
### K-Fêt

View file

@ -19,23 +19,31 @@ class Command(BaseCommand):
def handle(self, *args, **options):
now = timezone.now()
# Le premier mail est envoyé après 24h de négatif, puis toutes les semaines
first_delay = timedelta(days=1)
periodic_delay = timedelta(weeks=1)
accounts_first_mail = (
AccountNegative.objects.filter(start__lt=now - first_delay)
.filter(last_rappel__isnull=True)
.all()
# On n'envoie des mails qu'aux comptes qui ont un négatif vraiment actif
# et dont la balance est négative
account_negatives = AccountNegative.objects.filter(
account__balance__lt=0
).exclude(end__lte=now)
accounts_first_mail = account_negatives.filter(
start__lt=now - first_delay, last_rappel__isnull=True
)
accounts_periodic_mail = (
AccountNegative.objects.filter(last_rappel__isnull=False)
.filter(last_rappel__lt=now - periodic_delay)
.all()
accounts_periodic_mail = account_negatives.filter(
last_rappel__lt=now - periodic_delay
)
for neg in accounts_first_mail:
neg.send_rappel()
self.stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
for neg in accounts_periodic_mail:
neg.send_rappel()
self.stdout.write("Mail de rappel pour {neg.account} envoyé avec succès.")
if (not accounts_first_mail) and (not accounts_periodic_mail):
if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
self.stdout.write("Aucun mail à envoyer.")

View file

@ -260,8 +260,10 @@ class Account(models.Model):
elif hasattr(self, "negative"):
if self.negative.end is None:
self.negative.end = timezone.now()
self.negative.save()
elif timezone.now() > self.negative.end + kfet_config.cancel_duration:
# Idem: on supprime le négatif après une légère période
# Nécessaire pour se souvenir du négatif après une charge annulée
self.negative.delete()
class UserHasAccount(Exception):

View file

@ -61,7 +61,7 @@ ul {
}
.table td.no-padding {
padding:0;
padding:0 !important;
}
.table thead {

View file

@ -248,7 +248,7 @@ function KHistory(options = {}) {
that.cancel_entry(entry);
}
if (type == "operation") {
for (let opegroup of data["opegroups_to_update"]) {
for (let opegroup of (data["opegroups_to_update"] || [])) {
that.update_opegroup(opegroup)
}
}

View file

@ -37,6 +37,12 @@
{% block main %}
<div class="messages">
<div class="alert alert-info">
Les valeurs de stock sont calculées sur la base du prix actuel des articles.
</div>
</div>
<div class="table-responsive">
<table
class="table table-condensed table-hover table-striped sortable"
@ -50,28 +56,36 @@
<td>Erreur</td>
</tr>
</thead>
{% regroup inventoryarts by article.category as category_list %}
{% regroup inventoryarts by article.category.name as category_list %}
{% for category in category_list %}
<tbody class="tablesorter-no-sort">
<tr class="section">
<td colspan="4">{{ category.grouper.name }}</td>
<td colspan="4">{{ category.grouper }}</td>
</tr>
</tbody>
<tbody>
{% for inventoryart in category.list %}
<tr>
<td>
<a href="{% url "kfet.article.read" inventoryart.article.id %}">
<a href="{% url "kfet.article.read" inventoryart.article_id %}">
{{ inventoryart.article.name }}
</a>
</td>
<td>{{ inventoryart.stock_old }}</td>
<td>{{ inventoryart.stock_new }}</td>
<td>{{ inventoryart.stock_error }}</td>
<td>{{ inventoryart.stock_error }} / {{ inventoryart.amount_error|floatformat:"-2" }} €</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
<tbody>
<tr class="section">
<td>Valeurs totales</td>
<td>{{ total_amount_old|floatformat:"-2" }} €</td>
<td>{{ total_amount_new|floatformat:"-2" }} €</td>
<td>{{ total_amount_error|floatformat:"-2" }} €</td>
</tr>
</tbody>
</table>
</div>

View file

@ -31,9 +31,7 @@
<div class="text">
<h4>{{ account.name|title }}</h4>
<ul class="list-unstyled">
{% if perms.kfet.is_team %}
<li>{{ account.nickname }}</li>
{% endif %}
<li>{{ account.email|default:"Pas d'email!" }}</li>
<li>
{% if account.promo %}
@ -53,7 +51,7 @@
</ul>
</div>
{% if account.negative %}
{% if account.negative and account.balance_ukf < 0 %}
<div class="text">
<h4>Négatif</h4>
<ul class="list-unstyled">

View file

@ -14,7 +14,18 @@ from django.contrib.auth.models import Permission, User
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import SuspiciousOperation
from django.db import transaction
from django.db.models import Count, F, Max, OuterRef, Prefetch, Q, Subquery, Sum
from django.db.models import (
Count,
DecimalField,
ExpressionWrapper,
F,
Max,
OuterRef,
Prefetch,
Q,
Subquery,
Sum,
)
from django.forms import ValidationError, formset_factory
from django.http import (
Http404,
@ -2013,12 +2024,34 @@ class InventoryRead(DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
inventoryarticles = (
output_field = DecimalField(max_digits=10, decimal_places=2, default=0)
inventory_articles = (
InventoryArticle.objects.select_related("article", "article__category")
.filter(inventory=self.object)
.annotate(
amount_error=ExpressionWrapper(
F("stock_error") * F("article__price"), output_field=output_field
)
)
.order_by("article__category__name", "article__name")
)
context["inventoryarts"] = inventoryarticles
context["inventoryarts"] = inventory_articles
stats = inventory_articles.aggregate(
new=ExpressionWrapper(
Sum(F("stock_new") * F("article__price")), output_field=output_field
),
error=Sum("amount_error"),
old=ExpressionWrapper(
Sum(F("stock_old") * F("article__price")), output_field=output_field
),
)
context.update(
{
"total_amount_old": stats["old"],
"total_amount_new": stats["new"],
"total_amount_error": stats["error"],
}
)
return context