mirror of
https://framagit.org/la-chariotte/la-chariotte.git
synced 2025-05-08 14:51:52 +02:00
Compare commits
2 commits
8bef3e533a
...
8f2a6c2d6b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8f2a6c2d6b | ||
![]() |
3f17095959 |
8 changed files with 1258 additions and 57 deletions
1213
chariotte-v0-data.sql
Normal file
1213
chariotte-v0-data.sql
Normal file
File diff suppressed because it is too large
Load diff
|
@ -22,21 +22,22 @@ 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
|
||||||
price
|
total_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
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
# 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,6 +25,7 @@ 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):
|
||||||
|
@ -51,12 +52,16 @@ class GroupedOrder(models.Model):
|
||||||
)
|
)
|
||||||
self.code = f"{base_36_pk}{random_string}"[:code_length]
|
self.code = f"{base_36_pk}{random_string}"[:code_length]
|
||||||
|
|
||||||
@property
|
def compute_total_price(self):
|
||||||
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
|
||||||
return price
|
self.total_price = 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
|
||||||
|
@ -118,24 +123,26 @@ 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)
|
||||||
|
|
||||||
@property
|
def compute_order_articles_nb(self):
|
||||||
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
|
||||||
return articles_nb
|
self.articles_nb = articles_nb
|
||||||
|
self.save()
|
||||||
|
|
||||||
@property
|
def compute_order_price(self):
|
||||||
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()
|
||||||
return price
|
self.price = price
|
||||||
|
self.save()
|
||||||
|
|
||||||
def __str__(self): # pragma: no cover
|
def __str__(self): # pragma: no cover
|
||||||
return (
|
return (
|
||||||
|
@ -150,13 +157,15 @@ 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)
|
||||||
|
|
||||||
@property
|
ordered_nb = models.IntegerField(default=0)
|
||||||
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
|
||||||
return ordered_nb
|
self.ordered_nb = 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,6 +150,12 @@ 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
|
||||||
|
@ -222,6 +228,7 @@ 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)
|
||||||
|
|
||||||
|
@ -293,11 +300,7 @@ 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 = [
|
items = grouped_order.item_set.filter(ordered_nb__gt=0).order_by("name")
|
||||||
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,6 +72,7 @@ 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",
|
||||||
|
@ -102,6 +103,8 @@ 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
|
||||||
|
@ -120,6 +123,7 @@ 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 len(response.context["items"]) == 0
|
assert response.context["items"].count() == 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 len(response.context["items"]) == 2
|
assert response.context["items"].count() == 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,4 +44,11 @@ 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