diff --git a/website/orders/api/v1/serializers.py b/website/orders/api/v1/serializers.py index e00b5354..c9e3f7fc 100644 --- a/website/orders/api/v1/serializers.py +++ b/website/orders/api/v1/serializers.py @@ -108,10 +108,22 @@ class Meta: "ready_at", "paid", "paid_at", + "picked_up", + "picked_up_at", "type", "priority", ] - read_only_fields = ["id", "created", "user", "product", "order_price", "ready_at", "paid_at"] + read_only_fields = [ + "id", + "created", + "user", + "product", + "order_price", + "ready_at", + "paid_at", + "picked_up_at", + "prioritize", + ] class ShiftSerializer(WritableModelSerializer): diff --git a/website/orders/api/v1/views.py b/website/orders/api/v1/views.py index 863220f2..2cd16e3f 100644 --- a/website/orders/api/v1/views.py +++ b/website/orders/api/v1/views.py @@ -72,7 +72,7 @@ def perform_create(self, serializer): # Save the order while ignoring the order_type, user, paid and ready argument as the user does not have # permissions to save orders for all users in the shift. order = serializer.save( - shift=shift, type=Order.TYPE_ORDERED, user=self.request.user, paid=False, ready=False + shift=shift, type=Order.TYPE_ORDERED, user=self.request.user, paid=False, ready=False, picked_up=False ) log_action(self.request.user, order, CHANGE, "Created order via API.") @@ -108,6 +108,8 @@ class OrderRetrieveUpdateDestroyAPIView(LoggedRetrieveUpdateDestroyAPIView): "ready": {"type": "boolean"}, "paid": {"type": "boolean"}, "priority": {"type": "number"}, + "picked_up": {"type": "boolean"}, + "deprioritize": {"type": "boolean"}, }, } ) diff --git a/website/orders/migrations/0008_order_picked_up_order_picked_up_at.py b/website/orders/migrations/0008_order_picked_up_order_picked_up_at.py new file mode 100644 index 00000000..554576a0 --- /dev/null +++ b/website/orders/migrations/0008_order_picked_up_order_picked_up_at.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.4 on 2023-11-12 09:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("orders", "0007_order_deprioritize"), + ] + + operations = [ + migrations.AddField( + model_name="order", + name="picked_up", + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name="order", + name="picked_up_at", + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name="order", + name="picked_up", + field=models.BooleanField(default=False), + ), + ] diff --git a/website/orders/models.py b/website/orders/models.py index 8bb84dd5..e3705ff7 100644 --- a/website/orders/models.py +++ b/website/orders/models.py @@ -438,7 +438,9 @@ def _clean(self): elif old_instance is not None and not old_instance.finalized and self.finalized: # Shift was not finalized yet but will be made finalized now if not self.shift_done: - raise ValidationError({"finalized": "Shift can't be finalized if not all Orders are paid and ready"}) + raise ValidationError( + {"finalized": "Shift can't be finalized if not all Orders are paid, ready and picked up."} + ) if self.end <= self.start: raise ValidationError({"end": "End date cannot be before start date."}) @@ -545,7 +547,10 @@ class Order(models.Model): paid = models.BooleanField(default=False) paid_at = models.DateTimeField(null=True, blank=True) - type = models.PositiveIntegerField(choices=TYPES, default=TYPE_ORDERED) + picked_up = models.BooleanField(default=False) + picked_up_at = models.DateTimeField(null=True, blank=True) + + type = models.PositiveIntegerField(choices=TYPES, default=0) priority = models.PositiveIntegerField(choices=PRIORITIES, default=PRIORITY_NORMAL) @@ -587,12 +592,22 @@ def venue(self): """ return self.shift.venue + @property + def completed(self) -> bool: + """ + Check if an Order is completed. + + :return: True if this Order is paid, ready and picked up, False otherwise. + :rtype: boolean + """ + return self.paid and self.ready and self.picked_up + @property def done(self): """ Check if an Order is done. - :return: True if this Order is paid and ready, False otherwise + :return: True if this Order is paid, ready and picked up, False otherwise :rtype: boolean """ return self.paid and self.ready diff --git a/website/orders/services.py b/website/orders/services.py index 37fdf0b5..9ec03709 100644 --- a/website/orders/services.py +++ b/website/orders/services.py @@ -56,7 +56,7 @@ def execute_data_minimisation(dry_run=False): return users -def add_scanned_order(product: Product, shift: Shift, ready=True, paid=True) -> Order: +def add_scanned_order(product: Product, shift: Shift, ready=True, paid=True, picked_up=True) -> Order: """ Add a single Scanned Order (of type TYPE_SCANNED). @@ -64,6 +64,7 @@ def add_scanned_order(product: Product, shift: Shift, ready=True, paid=True) -> :param shift: The shift for which the Orders have to be created :param ready: Whether the Order should be directly made ready :param paid: Whether the Order should be directly made paid + :param picked_up: Whether the Order should be directly made picked up :return: The created Order """ # Check if Shift is not finalized @@ -79,7 +80,14 @@ def add_scanned_order(product: Product, shift: Shift, ready=True, paid=True) -> raise OrderException("This Product is not available in this Shift") return Order.objects.create( - product=product, shift=shift, type=Order.TYPE_SCANNED, user=None, user_association=None, ready=ready, paid=paid + product=product, + shift=shift, + type=Order.TYPE_SCANNED, + user=None, + user_association=None, + ready=ready, + paid=paid, + picked_up=picked_up, ) @@ -90,6 +98,7 @@ def add_user_order( priority: int = Order.PRIORITY_NORMAL, paid: bool = False, ready: bool = False, + picked_up: bool = False, **kwargs, ) -> Order: """ @@ -101,6 +110,7 @@ def add_user_order( :param priority: Which priority the Order should have :param paid: Whether the order should be set as paid :param ready: Whether the order should be set as ready + :param picked_up: Whether the order should be set as picked up :return: The created Order """ # Check order permissions @@ -147,6 +157,8 @@ def add_user_order( paid=paid, ready=ready, priority=priority, + picked_up=picked_up, + priority=priority, ) diff --git a/website/orders/templates/orders/order_admin_list.html b/website/orders/templates/orders/order_admin_list.html index d70fb6d7..e007fda6 100644 --- a/website/orders/templates/orders/order_admin_list.html +++ b/website/orders/templates/orders/order_admin_list.html @@ -220,6 +220,20 @@
${ index + 1 }$.
${ order.product.name }$ (€${ (Math.round(order.order_price * 100) / 100).toFixed(2) }$)