diff --git a/la_chariotte/order/forms.py b/la_chariotte/order/forms.py index 2cf2817..0d53139 100644 --- a/la_chariotte/order/forms.py +++ b/la_chariotte/order/forms.py @@ -18,9 +18,26 @@ class GroupedOrderForm(forms.ModelForm): widget=forms.TimeInput(attrs={"type": "time"}), initial=datetime.time(hour=23, minute=59, second=59), ) - is_phone_mandatory = forms.BooleanField( - label="Numéro de téléphone obligatoire pour les participants", + + required_phone = forms.TypedChoiceField( + label="Numéro de téléphone", required=False, + choices=[ + (0, "Désactivé"), + (1, "Facultatif"), + (2, "Obligatoire"), + ], + coerce=int, + ) + required_email = forms.TypedChoiceField( + label="Adresse email", + required=False, + choices=[ + (0, "Désactivé"), + (1, "Facultatif"), + (2, "Obligatoire"), + ], + coerce=int, ) class Meta: @@ -33,7 +50,8 @@ class GroupedOrderForm(forms.ModelForm): "delivery_slot", "place", "description", - "is_phone_mandatory", + "required_phone", + "required_email", ] widgets = { "name": forms.TextInput( diff --git a/la_chariotte/order/migrations/0030_remove_groupedorder_is_phone_mandatory_and_more.py b/la_chariotte/order/migrations/0030_remove_groupedorder_is_phone_mandatory_and_more.py new file mode 100644 index 0000000..d082ac6 --- /dev/null +++ b/la_chariotte/order/migrations/0030_remove_groupedorder_is_phone_mandatory_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 4.2.19 on 2025-03-06 16:37 + +import django.core.validators +from django.db import migrations, models + + +def migrate_from_is_phone_mandatory(apps, schema_editor): + """For continuity, move is_phone_mandatory to the new required_phone field, and set + required_email=2 for the orders that were created so far.""" + + GroupedOrder = apps.get_model("order", "GroupedOrder") + for grouped_order in GroupedOrder.objects.all(): + grouped_order.required_email = 2 + grouped_order.required_phone = 2 if grouped_order.is_phone_mandatory else 1 + grouped_order.save() + +class Migration(migrations.Migration): + + dependencies = [ + ("order", "0029_set_phone_mandatory_for_existing_orders"), + ] + + operations = [ + migrations.AddField( + model_name="groupedorder", + name="required_email", + field=models.IntegerField( + verbose_name="Adresse email", + blank=True, + default=2, + validators=[ + django.core.validators.MaxValueValidator(2), + django.core.validators.MinValueValidator(0), + ], + ), + ), + migrations.AddField( + model_name="groupedorder", + name="required_phone", + field=models.IntegerField( + verbose_name="Numéro de téléphone", + blank=True, + default=2, + validators=[ + django.core.validators.MaxValueValidator(2), + django.core.validators.MinValueValidator(0), + ], + ), + ), + migrations.RunPython(migrate_from_is_phone_mandatory), + migrations.RemoveField( + model_name="groupedorder", + name="is_phone_mandatory", + ), + ] diff --git a/la_chariotte/order/models.py b/la_chariotte/order/models.py index 5450f72..e21c24e 100644 --- a/la_chariotte/order/models.py +++ b/la_chariotte/order/models.py @@ -2,6 +2,7 @@ import random import base36 from django.core.exceptions import ValidationError +from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.urls import reverse from django.utils import timezone @@ -26,8 +27,28 @@ class GroupedOrder(models.Model): ) description = models.TextField("Description", null=True, blank=True) code = models.CharField(auto_created=True) - is_phone_mandatory = models.BooleanField( - default=False, verbose_name="Numéro de téléphone obligatoire" + + # Whether phone/email registration is possible/necessary for this grouped order + # 0 = disabled + # 1 = optional + # 2 = required + required_phone = models.IntegerField( + verbose_name="Numéro de téléphone", + default=2, + blank=True, + validators=[ + MaxValueValidator(2), + MinValueValidator(0), + ], + ) + required_email = models.IntegerField( + verbose_name="Adresse email", + default=2, + blank=True, + validators=[ + MaxValueValidator(2), + MinValueValidator(0), + ], ) def create_code_from_pk(self): diff --git a/la_chariotte/order/templates/order/grouped_order_detail.html b/la_chariotte/order/templates/order/grouped_order_detail.html index b73d467..ef3ba38 100644 --- a/la_chariotte/order/templates/order/grouped_order_detail.html +++ b/la_chariotte/order/templates/order/grouped_order_detail.html @@ -157,16 +157,22 @@
+ {% if required_phone or required_email %}+ {% if required_phone != 0 %} +
-
+ {% if required_phone == 2 %}required{% endif %}>
+ {% endif %} + {% if required_email != 0 %} ++ value="{{ order_author.email }}" {% if required_email == 2 %}required{% endif %}> + {% endif %}
diff --git a/la_chariotte/order/views/grouped_order.py b/la_chariotte/order/views/grouped_order.py index 55d9cca..ea31135 100644 --- a/la_chariotte/order/views/grouped_order.py +++ b/la_chariotte/order/views/grouped_order.py @@ -134,8 +134,9 @@ class GroupedOrderDetailView(generic.DetailView): "prices_dict": json.dumps(prices_dict, cls=DjangoJSONEncoder), "remaining_qty": remaining_qty, "order_author": order_author, - # Used to set if the phone is required in the form - "is_phone_mandatory": grouped_order.is_phone_mandatory, + # Used to set if the phone/email is required/optional/disabled in the form + "required_phone": grouped_order.required_phone, + "required_email": grouped_order.required_email, } ) return context diff --git a/la_chariotte/order/views/order.py b/la_chariotte/order/views/order.py index 032b219..3a5f019 100644 --- a/la_chariotte/order/views/order.py +++ b/la_chariotte/order/views/order.py @@ -40,15 +40,67 @@ def place_order(request, code): ) orders_dict[i] = value - # create an order + error_message = None + first_name = request.POST["first_name"] last_name = request.POST["last_name"] - phone = request.POST["phone"] - email = request.POST["email"] note = request.POST["note"] + + # check if required/optional phone is supplied + # When not supplied, use "" because the order_author table phone has a NOT NULL statement + error_message = None + if grouped_order.required_phone == 0: + phone = "" + else: + if "phone" in request.POST and request.POST["phone"] != "": + # Phone is supplied, whether required or not + phone = request.POST["phone"] + elif grouped_order.required_phone == 2: + # Phone is not supplied, but was required + error_message = ( + "Le numéro de téléphone est obligatoire pour cette commande groupée" + ) + phone = "" + else: + # Phone is not supplied, but was not mandatory + phone = "" + + # check if required/optional email is supplied + # When not supplied, use "" because the order_author table email has a NOT NULL statement + if grouped_order.required_email == 0: + email = "" + else: + if "email" in request.POST and request.POST["email"] != "": + # email is supplied, whether required or not + email = request.POST["email"] + elif grouped_order.required_email == 2: + # email is not supplied, but was required + error_message = ( + "L'adresse email est obligatoire pour cette commande groupée" + ) + email = "" + else: + # email is not supplied, but was not mandatory + email = "" + + # create an author author = OrderAuthor.objects.create( first_name=first_name, last_name=last_name, email=email, phone=phone ) + if error_message: + author.delete() + return render( + request, + "order/grouped_order_detail.html", + { + "grouped_order": grouped_order, + "error_message": error_message, + "note": note, + "author": author, + }, + ) + + # create an order order = Order.objects.create( author=author, grouped_order=grouped_order, @@ -57,7 +109,6 @@ def place_order(request, code): ) # add items to the order - error_message = None for key, quantity in orders_dict.items(): quantity = int(quantity) item = grouped_order.item_set.get(pk=key.split("_")[1]) diff --git a/la_chariotte/tests/test_order_views_grouped_order.py b/la_chariotte/tests/test_order_views_grouped_order.py index ce6fa36..418f944 100644 --- a/la_chariotte/tests/test_order_views_grouped_order.py +++ b/la_chariotte/tests/test_order_views_grouped_order.py @@ -362,7 +362,7 @@ class TestGroupedOrderDetailView: "first_name": {authenticated_user_with_name.first_name}, "last_name": {authenticated_user_with_name.last_name}, "phone": "0645632569", - "email": {authenticated_user_with_name.email}, + "email": {authenticated_user_with_name.username}, "note": "test note", }, ) @@ -670,7 +670,7 @@ class TestGroupedOrderDetailView: name="gr order test", orga_user=other_user, ) - assert grouped_order.is_phone_mandatory == True + assert grouped_order.required_phone == 2 item = models.Item.objects.create( name="test item 1", grouped_order=grouped_order, price=1, max_limit=2 ) @@ -686,12 +686,53 @@ class TestGroupedOrderDetailView: assert ( "Numéro de téléphone (facultatif)" not in response.content.decode() ) - grouped_order.is_phone_mandatory = False + + grouped_order.required_phone = 1 grouped_order.save() response = client.get(detail_url) assert "gr order test" in response.content.decode() assert "Numéro de téléphone (facultatif)" in response.content.decode() + grouped_order.required_phone = 0 + grouped_order.save() + response = client.get(detail_url) + assert "gr order test" in response.content.decode() + assert '