Skip to content

Commit

Permalink
fixup! ✨(backend) add start and end date on order groups model
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanreveille committed Feb 4, 2025
1 parent d7f3b0d commit a3c4153
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 387 deletions.
4 changes: 4 additions & 0 deletions src/backend/joanie/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ def nb_available_seats(self, obj): # pylint: disable=no-self-use
"""Return the number of available seats for this order group."""
return obj.nb_seats - obj.get_nb_binding_orders()

def get_is_active(self, obj):
"""Return the computed value of is_active"""
return obj.is_enabled


class CourseProductRelationInline(admin.StackedInline):
"""Admin class for the CourseProductRelation model"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class Migration(migrations.Migration):

dependencies = [
('core', '0052_alter_unique_constraint_order_when_canceled_or_refund'),
('core', '0053_alter_certificate_options_and_more'),
]

operations = [
Expand Down
36 changes: 36 additions & 0 deletions src/backend/joanie/core/models/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,42 @@ def can_edit(self):
"""Return True if the order group can be edited."""
return not self.orders.exists()

@property
def is_enabled(self):
"""
Returns boolean whether the order group is active based on its status, availability,
and time constraints.
When a start or end date is setted, we need to verify if we are in the period
of early bird, or last minute depending on the course run enrollment start or
enrollment end datetimes. When both dates are setted, we need to make sure that the
current day is between those.
"""
now = timezone.now()
is_active = False

if self.course_product_relation.product.type == enums.PRODUCT_TYPE_CERTIFICATE: # pylint: disable=no-member
instance = self.course_product_relation.course
else:
instance = self.course_product_relation.product
course_run_dates = instance.get_equivalent_course_run_dates( # pylint: disable=no-member
ignore_archived=True
)

available_seats = self.nb_seats - self.get_nb_binding_orders()

if not self.is_active or not available_seats:
is_active = False
elif not self.start and not self.end and available_seats:
is_active = self.is_active
elif self.start and self.end and available_seats:
is_active = self.start <= now <= self.end
elif self.end and available_seats: # Early birds
is_active = self.end >= now >= course_run_dates["enrollment_start"]
elif self.start and available_seats: # Last minutes
is_active = self.start <= now <= course_run_dates["enrollment_end"]

return is_active


class OrderManager(models.Manager):
"""Custom manager for the Order model."""
Expand Down
22 changes: 8 additions & 14 deletions src/backend/joanie/core/serializers/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
ThumbnailDetailField,
)
from joanie.core.utils import Echo
from joanie.core.utils.ordergroup import is_active
from joanie.payment import models as payment_models


Expand Down Expand Up @@ -473,23 +472,20 @@ def get_nb_available_seats(self, order_group) -> int:
"""Return the number of available seats for this order group."""
return order_group.nb_seats - order_group.get_nb_binding_orders()

def get_is_active(self, order_group):
"""
Return if the order group is active if start or end dates are setted. Else, it returns
the value in the database.
"""
return is_active(order_group)
def get_is_active(self, instance):
"""Return the computed value of is_active of the order group."""
return instance.is_enabled

def update(self, instance, validated_data):
"""
Update instance and ensure `is_active` is only updated if explicitly
passed in the request. Else, don't update the field.
"""
is_active_explicit = "is_active" in self.initial_data

if is_active_explicit:
instance.is_active = self.initial_data["is_active"]

instance.is_active = (
self.initial_data["is_active"]
if "is_active" in self.initial_data
else instance.is_active
)
return super().update(instance, validated_data)


Expand All @@ -502,8 +498,6 @@ class AdminOrderGroupCreateSerializer(AdminOrderGroupSerializer):
the order group.
"""

is_active = serializers.BooleanField(required=False)

class Meta(AdminOrderGroupSerializer.Meta):
fields = [*AdminOrderGroupSerializer.Meta.fields, "course_product_relation"]

Expand Down
5 changes: 5 additions & 0 deletions src/backend/joanie/core/serializers/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ class OrderGroupSerializer(serializers.ModelSerializer):
"""Serializer for order groups in a product."""

nb_available_seats = serializers.SerializerMethodField(read_only=True)
is_active = serializers.SerializerMethodField(read_only=True)

class Meta:
model = models.OrderGroup
Expand All @@ -770,6 +771,10 @@ def get_nb_available_seats(self, order_group) -> int:
"""Return the number of available seats for this order group."""
return order_group.nb_seats - order_group.get_nb_binding_orders()

def get_is_active(self, instance):
"""Return the computed value of is_active of the order group."""
return instance.is_enabled


class DefinitionResourcesProductSerializer(serializers.ModelSerializer):
"""
Expand Down
27 changes: 0 additions & 27 deletions src/backend/joanie/core/utils/ordergroup.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_api_admin_orders_course_retrieve(self):
total=D("1.00"),
)

with self.assertNumQueries(39):
with self.assertNumQueries(42):
response = self.client.get(f"/api/v1.0/admin/orders/{order.id}/")

self.assertEqual(response.status_code, HTTPStatus.OK)
Expand Down
Loading

0 comments on commit a3c4153

Please sign in to comment.