mirror of
https://framagit.org/la-chariotte/la-chariotte.git
synced 2025-05-03 04:11:52 +02:00
Make aggregated values computed when called instead of stored in DB
- GroupedOrder.total_price - Order.articles_nb - Order.price - Item.ordered_nb
This commit is contained in:
parent
3d38bb56c0
commit
686a31b96a
7 changed files with 57 additions and 45 deletions
|
@ -22,22 +22,21 @@ classDiagram
|
||||||
name
|
name
|
||||||
deadline : DateTime
|
deadline : DateTime
|
||||||
delivery_date : Date
|
delivery_date : Date
|
||||||
|
delivery_slot
|
||||||
place
|
place
|
||||||
description
|
description
|
||||||
orga : CustomUser
|
orga : CustomUser
|
||||||
total_price
|
|
||||||
}
|
}
|
||||||
class Item{
|
class Item{
|
||||||
name
|
name
|
||||||
grouped_order : GroupedOrder
|
grouped_order : GroupedOrder
|
||||||
ordered_nb
|
ordered_nb
|
||||||
total_price
|
price
|
||||||
max_limit
|
max_limit
|
||||||
}
|
}
|
||||||
class Order{
|
class Order{
|
||||||
grouped_order : GroupedOrder
|
grouped_order : GroupedOrder
|
||||||
author : OrderAuthor
|
author : OrderAuthor
|
||||||
price
|
|
||||||
created_date
|
created_date
|
||||||
note
|
note
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Generated by Django 4.2.16 on 2024-10-31 21:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("order", "0026_groupedorder_delivery_slot"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="groupedorder",
|
||||||
|
name="total_price",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="item",
|
||||||
|
name="ordered_nb",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="order",
|
||||||
|
name="articles_nb",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="order",
|
||||||
|
name="price",
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="order",
|
||||||
|
name="created_date",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
auto_now_add=True, verbose_name="Date et heure de commande"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -25,7 +25,6 @@ class GroupedOrder(models.Model):
|
||||||
max_length=100, null=True, blank=True, verbose_name="Lieu de livraison"
|
max_length=100, null=True, blank=True, verbose_name="Lieu de livraison"
|
||||||
)
|
)
|
||||||
description = models.TextField("Description", null=True, blank=True)
|
description = models.TextField("Description", null=True, blank=True)
|
||||||
total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
|
||||||
code = models.CharField(auto_created=True)
|
code = models.CharField(auto_created=True)
|
||||||
|
|
||||||
def create_code_from_pk(self):
|
def create_code_from_pk(self):
|
||||||
|
@ -52,16 +51,12 @@ class GroupedOrder(models.Model):
|
||||||
)
|
)
|
||||||
self.code = f"{base_36_pk}{random_string}"[:code_length]
|
self.code = f"{base_36_pk}{random_string}"[:code_length]
|
||||||
|
|
||||||
def compute_total_price(self):
|
@property
|
||||||
|
def total_price(self):
|
||||||
price = 0
|
price = 0
|
||||||
for order in self.order_set.all():
|
for order in self.order_set.all():
|
||||||
price += order.price
|
price += order.price
|
||||||
self.total_price = price
|
return price
|
||||||
self.save()
|
|
||||||
|
|
||||||
def compute_items_ordered_nb(self):
|
|
||||||
for item in self.item_set.all():
|
|
||||||
item.compute_ordered_nb()
|
|
||||||
|
|
||||||
def get_total_ordered_items(self):
|
def get_total_ordered_items(self):
|
||||||
total_nb = 0
|
total_nb = 0
|
||||||
|
@ -123,26 +118,24 @@ class Order(models.Model):
|
||||||
GroupedOrder, on_delete=models.CASCADE, related_name="order_set"
|
GroupedOrder, on_delete=models.CASCADE, related_name="order_set"
|
||||||
)
|
)
|
||||||
author = models.ForeignKey(OrderAuthor, on_delete=models.CASCADE)
|
author = models.ForeignKey(OrderAuthor, on_delete=models.CASCADE)
|
||||||
articles_nb = models.PositiveIntegerField(default=0)
|
|
||||||
price = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
|
||||||
created_date = models.DateTimeField("Date et heure de commande", auto_now_add=True)
|
created_date = models.DateTimeField("Date et heure de commande", auto_now_add=True)
|
||||||
note = models.TextField(max_length=200, null=True, blank=True)
|
note = models.TextField(max_length=200, null=True, blank=True)
|
||||||
|
|
||||||
def compute_order_articles_nb(self):
|
@property
|
||||||
|
def articles_nb(self):
|
||||||
"""Computes the number of articles in this order"""
|
"""Computes the number of articles in this order"""
|
||||||
articles_nb = 0
|
articles_nb = 0
|
||||||
for ord_item in self.ordered_items.all():
|
for ord_item in self.ordered_items.all():
|
||||||
articles_nb += ord_item.nb
|
articles_nb += ord_item.nb
|
||||||
self.articles_nb = articles_nb
|
return articles_nb
|
||||||
self.save()
|
|
||||||
|
|
||||||
def compute_order_price(self):
|
@property
|
||||||
|
def price(self):
|
||||||
"""Computes the total price of the order"""
|
"""Computes the total price of the order"""
|
||||||
price = 0
|
price = 0
|
||||||
for ord_item in self.ordered_items.all():
|
for ord_item in self.ordered_items.all():
|
||||||
price += ord_item.get_price()
|
price += ord_item.get_price()
|
||||||
self.price = price
|
return price
|
||||||
self.save()
|
|
||||||
|
|
||||||
def __str__(self): # pragma: no cover
|
def __str__(self): # pragma: no cover
|
||||||
return (
|
return (
|
||||||
|
@ -157,15 +150,13 @@ class Item(models.Model):
|
||||||
price = models.DecimalField(max_digits=10, decimal_places=2)
|
price = models.DecimalField(max_digits=10, decimal_places=2)
|
||||||
max_limit = models.PositiveSmallIntegerField(null=True, blank=True)
|
max_limit = models.PositiveSmallIntegerField(null=True, blank=True)
|
||||||
|
|
||||||
ordered_nb = models.IntegerField(default=0)
|
@property
|
||||||
|
def ordered_nb(self):
|
||||||
def compute_ordered_nb(self):
|
|
||||||
"""Computes the number of times this item has been ordered"""
|
"""Computes the number of times this item has been ordered"""
|
||||||
ordered_nb = 0
|
ordered_nb = 0
|
||||||
for order in self.orders.all():
|
for order in self.orders.all():
|
||||||
ordered_nb += order.nb
|
ordered_nb += order.nb
|
||||||
self.ordered_nb = ordered_nb
|
return ordered_nb
|
||||||
self.save()
|
|
||||||
|
|
||||||
def get_total_price(self):
|
def get_total_price(self):
|
||||||
"""Returns the total price of all orders on this item"""
|
"""Returns the total price of all orders on this item"""
|
||||||
|
|
|
@ -150,12 +150,6 @@ class GroupedOrderOverview(UserIsOrgaMixin, generic.DetailView):
|
||||||
# Staff can see but not edit grouped orders
|
# Staff can see but not edit grouped orders
|
||||||
return super().test_func() or self.request.user.is_staff
|
return super().test_func() or self.request.user.is_staff
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
# Compute grouped order total price before display
|
|
||||||
self.get_object().compute_total_price()
|
|
||||||
self.get_object().compute_items_ordered_nb()
|
|
||||||
return super().get(self, request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(GroupedOrderOverview, self).get_context_data(**kwargs)
|
context = super(GroupedOrderOverview, self).get_context_data(**kwargs)
|
||||||
# Add share link to context
|
# Add share link to context
|
||||||
|
@ -228,7 +222,6 @@ class GroupedOrderDuplicateView(UserIsOrgaMixin, generic.RedirectView):
|
||||||
# duplicate each item and add it to new_grouped_order
|
# duplicate each item and add it to new_grouped_order
|
||||||
for item in initial_grouped_order.item_set.all():
|
for item in initial_grouped_order.item_set.all():
|
||||||
item.pk = None
|
item.pk = None
|
||||||
item.ordered_nb = 0
|
|
||||||
item.save()
|
item.save()
|
||||||
new_grouped_order.item_set.add(item)
|
new_grouped_order.item_set.add(item)
|
||||||
|
|
||||||
|
@ -300,7 +293,11 @@ class GroupedOrderExportView(UserIsOrgaMixin, generic.DetailView):
|
||||||
context = super(GroupedOrderExportView, self).get_context_data(**kwargs)
|
context = super(GroupedOrderExportView, self).get_context_data(**kwargs)
|
||||||
grouped_order = self.get_object()
|
grouped_order = self.get_object()
|
||||||
|
|
||||||
items = grouped_order.item_set.filter(ordered_nb__gt=0).order_by("name")
|
items = [
|
||||||
|
item
|
||||||
|
for item in grouped_order.item_set.all().order_by("name")
|
||||||
|
if item.ordered_nb > 0
|
||||||
|
]
|
||||||
orders = grouped_order.order_set.all().order_by(
|
orders = grouped_order.order_set.all().order_by(
|
||||||
"author__last_name", "author__first_name"
|
"author__last_name", "author__first_name"
|
||||||
)
|
)
|
||||||
|
|
|
@ -72,7 +72,6 @@ def place_order(request, code):
|
||||||
if error_message:
|
if error_message:
|
||||||
order.delete()
|
order.delete()
|
||||||
author.delete()
|
author.delete()
|
||||||
grouped_order.compute_items_ordered_nb()
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"order/grouped_order_detail.html",
|
"order/grouped_order_detail.html",
|
||||||
|
@ -103,8 +102,6 @@ def place_order(request, code):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Send confirmation mail and redirect to confirmation page
|
# Send confirmation mail and redirect to confirmation page
|
||||||
order.compute_order_price()
|
|
||||||
grouped_order.compute_items_ordered_nb()
|
|
||||||
send_order_confirmation_mail(order)
|
send_order_confirmation_mail(order)
|
||||||
|
|
||||||
# Redirect to prevent data from being posted twice when the user hits the Back
|
# Redirect to prevent data from being posted twice when the user hits the Back
|
||||||
|
@ -123,7 +120,6 @@ def validate_item_ordered_nb(item, ordered_nb):
|
||||||
|
|
||||||
def validate_articles_ordered_nb(order):
|
def validate_articles_ordered_nb(order):
|
||||||
"""Return an error if no items are ordered"""
|
"""Return an error if no items are ordered"""
|
||||||
order.compute_order_articles_nb()
|
|
||||||
if order.articles_nb == 0:
|
if order.articles_nb == 0:
|
||||||
return "Veuillez commander au moins un produit"
|
return "Veuillez commander au moins un produit"
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1396,7 +1396,7 @@ class TestGroupedOrderSheetView:
|
||||||
response = client_log.get(generate_sheet_url)
|
response = client_log.get(generate_sheet_url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.context["grouped_order"] == grouped_order
|
assert response.context["grouped_order"] == grouped_order
|
||||||
assert response.context["items"].count() == 0
|
assert len(response.context["items"]) == 0
|
||||||
assert len(response.context["orders_dict"]) == 0
|
assert len(response.context["orders_dict"]) == 0
|
||||||
|
|
||||||
# we order some items in the grouped order
|
# we order some items in the grouped order
|
||||||
|
@ -1404,7 +1404,7 @@ class TestGroupedOrderSheetView:
|
||||||
response = client_log.get(generate_sheet_url)
|
response = client_log.get(generate_sheet_url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.context["grouped_order"] == grouped_order
|
assert response.context["grouped_order"] == grouped_order
|
||||||
assert response.context["items"].count() == 2
|
assert len(response.context["items"]) == 2
|
||||||
assert response.context["orders_dict"][order] == [3, 2]
|
assert response.context["orders_dict"][order] == [3, 2]
|
||||||
assert response.context["grouped_order"].total_price == 35
|
assert response.context["grouped_order"].total_price == 35
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,4 @@ def order_items_in_grouped_order(grouped_order):
|
||||||
models.OrderedItem.objects.create(order=order, item=item_2, nb=2)
|
models.OrderedItem.objects.create(order=order, item=item_2, nb=2)
|
||||||
models.OrderedItem.objects.create(order=order_2, item=item_1, nb=1)
|
models.OrderedItem.objects.create(order=order_2, item=item_1, nb=1)
|
||||||
models.OrderedItem.objects.create(order=order_3, item=item_2, nb=1)
|
models.OrderedItem.objects.create(order=order_3, item=item_2, nb=1)
|
||||||
item_1.compute_ordered_nb()
|
|
||||||
item_2.compute_ordered_nb()
|
|
||||||
order.compute_order_price()
|
|
||||||
order_2.compute_order_price()
|
|
||||||
order_3.compute_order_price()
|
|
||||||
grouped_order.compute_total_price()
|
|
||||||
grouped_order.save()
|
|
||||||
return order
|
return order
|
||||||
|
|
Loading…
Reference in a new issue