ajout des résumés et checks

This commit is contained in:
François Poulain 2024-05-04 18:24:39 +02:00
parent 9e18978be4
commit aa25a77257
3 changed files with 142 additions and 9 deletions

View File

@ -1,5 +1,5 @@
from datetime import date, timedelta from datetime import date, timedelta
from django.contrib import admin from django.contrib import admin, messages
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse from django.urls import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -25,6 +25,7 @@ admin_site.register(models.Pain, PainAdmin)
class IngrédientInline(admin.TabularInline): class IngrédientInline(admin.TabularInline):
model = models.Ingrédient model = models.Ingrédient
sortable_field_name = 'ordre'
extra = 1 extra = 1
class RecetteAdmin(admin.ModelAdmin): class RecetteAdmin(admin.ModelAdmin):
@ -118,16 +119,16 @@ class FournéeAdmin(nested_admin.NestedModelAdmin):
"""Pour chaque pâte on regarde si les coulées sont complètes. """Pour chaque pâte on regarde si les coulées sont complètes.
Si elles ne le sont pas, on ajoute ce qui manque.""" Si elles ne le sont pas, on ajoute ce qui manque."""
for pâte_id, pâte_nom in obj.commande_set.values_list('réservation__pain__pâte', 'réservation__pain__pâte__nom').distinct(): for pâte_id, pâte_nom in obj.commande_set.values_list('réservation__pain__pâte', 'réservation__pain__pâte__nom').order_by('réservation__pain__pâte').distinct():
commandes = models.Réservation.objects.filter(commande__fournée=obj, pain__pâte_id=pâte_id).values('pain__poids', 'quantité') somme_commandée = obj.masse_commandée(pâte_id)
somme_commandée = sum([c['quantité'] * c['pain__poids'] for c in commandes])
somme_coulée = sum(obj.coulée_set.filter(pâte_id=pâte_id).values_list('quantité', flat=True)) somme_coulée = sum(obj.coulée_set.filter(pâte_id=pâte_id).values_list('quantité', flat=True))
if somme_commandée > somme_coulée:
pâte_manquante = somme_commandée - somme_coulée pâte_manquante = somme_commandée - somme_coulée
if pâte_manquante > 0:
obj.coulée_set.create(pâte_id=pâte_id, quantité=pâte_manquante) obj.coulée_set.create(pâte_id=pâte_id, quantité=pâte_manquante)
self.message_user(request, f"Création d'une coulée de {pâte_manquante} kg pour la pâte {pâte_nom}.") self.message_user(request, f"Création d'une coulée de {pâte_manquante.normalize()} kg pour la pâte {pâte_nom}.")
elif pâte_manquante < 0:
self.message_user(request, f"Attention la pâte {pâte_nom} est prévue en excès ({-pâte_manquante.normalize()} kg en trop)", messages.WARNING)
# for pâte_id in f.coulée_set.values_list('pâte', flat=True)
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
"""Décale d'une semaine en cas de save_as si c'est utile""" """Décale d'une semaine en cas de save_as si c'est utile"""
@ -148,6 +149,58 @@ class FournéeAdmin(nested_admin.NestedModelAdmin):
else: else:
return super().response_change(request, obj) return super().response_change(request, obj)
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
obj = self.model.objects.get(pk=object_id)
extra_context["commandes"] = obj.commande_set.all()
coulées = obj.coulée_set.all()
ingrédients = sorted(set(coulées.values_list('pâte__ingrédient__nom', 'pâte__ingrédient__ordre')), key=lambda x:x[1])
extra_context["ingrédients"] = ingrédients
""" on créé un tableau coulée / ingrédient """
extra_context["coulées"] = []
for c in obj.coulée_set.all():
tmp = [c]
for i, _ in ingrédients:
if c.pâte.ingrédient_set.filter(nom=i).exists():
tmp.append(sum(c.pâte.ingrédient_set.filter(nom=i).values_list('quantité', flat=True)))
else:
tmp.append("")
masse_coulée = sum(obj.coulée_set.filter(pâte = c.pâte).values_list('quantité', flat=True))
masse_commandée = obj.masse_commandée(c.pâte_id)
if masse_coulée == masse_commandée:
problems = ""
elif masse_coulée > masse_commandée:
problems = f"{(masse_coulée - masse_commandée).normalize()} kg coulés en trop !!"
elif masse_coulée < masse_commandée:
problems = f"{(masse_commandée - masse_coulée).normalize()} kg coulés en moins !!"
extra_context["coulées"].append([problems, tmp])
pains = set(obj.commande_set.values_list('pains__nom', flat=True))
""" liste des pains, vérifiant s'ils sont coulés """
extra_context["pains"] = [(not obj.coulée_set.filter(pâte__pain__nom=p).exists(), p) for p in pains]
""" on créé un tableau pains / commande """
extra_context["divisions"] = []
for c in obj.commande_set.all():
tmp = [c]
for p in pains:
if c.réservation_set.filter(pain__nom=p).exists():
tmp.append(sum(c.réservation_set.filter(pain__nom=p).values_list('quantité', flat=True)).normalize())
else:
tmp.append("")
extra_context["divisions"].append(tmp)
totaux = []
for p in pains:
total = sum(obj.commande_set.filter(pains__nom=p).values_list('réservation__quantité', flat=True)).normalize()
totaux.append(total)
extra_context["totaux"] = totaux
return super().change_view(
request,
object_id,
form_url,
extra_context=extra_context,
)
admin_site.register(models.Fournée, FournéeAdmin) admin_site.register(models.Fournée, FournéeAdmin)

View File

@ -11,14 +11,19 @@ class Fournée(models.Model):
def __str__(self): def __str__(self):
return f"Fournée du {self.date: %d-%m-%Y} pour {self.pour}" return f"Fournée du {self.date: %d-%m-%Y} pour {self.pour}"
def masse_commandée(self, pâte_id):
"Renvoie la masse commandée d'une pâte donnée"
poids_qté = self.commande_set.filter(réservation__pain__pâte_id=pâte_id).values('réservation__pain__poids', 'réservation__quantité')
return sum([c['réservation__quantité'] * c['réservation__pain__poids'] for c in poids_qté])
class Ingrédient(models.Model): class Ingrédient(models.Model):
class Meta: class Meta:
ordering = ["-quantité"] ordering = ["ordre", "-quantité"]
recette = models.ForeignKey("Recette", on_delete=models.CASCADE) recette = models.ForeignKey("Recette", on_delete=models.CASCADE)
nom = models.CharField(max_length=64) nom = models.CharField(max_length=64)
quantité = models.DecimalField(max_digits=6, decimal_places=3) quantité = models.DecimalField(max_digits=6, decimal_places=3)
ordre = models.SmallIntegerField(default=0)
def __str__(self): def __str__(self):
return f"{self.nom} ({self.quantité} kg)" return f"{self.nom} ({self.quantité} kg)"

View File

@ -4,3 +4,78 @@
{% if save_on_top %}{% block submit_buttons_top %}{% fournée_submit_row %}{% endblock %}{% endif %} {% if save_on_top %}{% block submit_buttons_top %}{% fournée_submit_row %}{% endblock %}{% endif %}
{% block submit_buttons_bottom %}{% fournée_submit_row %}{% endblock %} {% block submit_buttons_bottom %}{% fournée_submit_row %}{% endblock %}
{% block after_field_sets %}
{% if commandes %}
<h2>Résumé des commandes</h2>
<ul>
{% for commande in commandes %}
<li>{{ commande }}</li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}
{% block after_related_objects %}
{% if coulées %}
<h2>Résumé des coulées</h2>
<table>
<thead>
<tr>
<th></th>
{% for i, _ in ingrédients %}
<th scope="col">{{ i }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for problems, coulée in coulées %}
<tr{% if problems %} style="color: var(--delete-button-hover-bg);"{% endif %}>
{% for i in coulée %}
{% if forloop.first %}<th scope="row">{% else %}<td>{% endif %}
{{ i }}
{% if forloop.first %}{% if problems %} ({{ problems }}){% endif %}</th>{% else %}</td>{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<p></p>
{% endif %}
{% if divisions %}
<hr>
<h2>Résumé des divisions</h2>
<table>
<thead>
<tr>
<th></th>
{% for problems, p in pains %}
<th scope="col"{% if problems %} style="color: var(--delete-button-hover-bg);"{% endif %}>{{ p }}{% if problems %}<br>sans coulée{% endif %}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for commande in divisions %}
<tr>
{% for p in commande %}
{% if forloop.first %}<th scope="row">{% else %}<td style="text-align:center">{% endif %}
{{ p }}
{% if forloop.first %}</th>{% else %}</td>{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr><td colspan={{totaux | length | add:"1" }}></td></tr>
<tr><td colspan={{totaux | length | add:"1" }}></td></tr>
<tr>
<th>Totaux</th>
{% for p in totaux %}
<th scope="col" style="text-align:center">{{ p }}</th>
{% endfor %}
</tr>
</tfoot>
</table>
<p></p>
{% endif %}
{% endblock %}