From e03e9e790d8b540f29d79bd2f3067227c18f9560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Reuiller?= Date: Tue, 26 Sep 2023 17:13:08 +0200 Subject: [PATCH] tender form : move description and deadline fields --- .../tenders/create_step_contact.html | 1 - ...scription.html => create_step_detail.html} | 29 +++------ .../tenders/create_step_general.html | 14 ++++ lemarche/www/tenders/forms.py | 64 +++++++++---------- lemarche/www/tenders/tests.py | 14 ++-- lemarche/www/tenders/utils.py | 2 +- lemarche/www/tenders/views.py | 19 +++--- 7 files changed, 73 insertions(+), 70 deletions(-) rename lemarche/templates/tenders/{create_step_description.html => create_step_detail.html} (86%) diff --git a/lemarche/templates/tenders/create_step_contact.html b/lemarche/templates/tenders/create_step_contact.html index ec83009f6..b3f631a46 100644 --- a/lemarche/templates/tenders/create_step_contact.html +++ b/lemarche/templates/tenders/create_step_contact.html @@ -23,7 +23,6 @@ {% endif %} {% bootstrap_field form.response_kind %} - {% bootstrap_field form.deadline_date %} {% endblock %} diff --git a/lemarche/templates/tenders/create_step_description.html b/lemarche/templates/tenders/create_step_detail.html similarity index 86% rename from lemarche/templates/tenders/create_step_description.html rename to lemarche/templates/tenders/create_step_detail.html index 298811c6e..534f0b0a4 100644 --- a/lemarche/templates/tenders/create_step_description.html +++ b/lemarche/templates/tenders/create_step_detail.html @@ -1,28 +1,17 @@ {% extends "tenders/create_base.html" %} {% load bootstrap4 static %} -{% block step_title %}Description du besoin{% endblock %} -{% block step_title_again %}Description du besoin{% endblock %} +{% block step_title %}Détail du besoin{% endblock %} +{% block step_title_again %}Détail du besoin{% endblock %} {% block step_subtitle %} Veuillez détailler au maximum votre besoin pour que les prestataires inclusifs puissent se positionner. {% endblock %} {% block content_form %} {% csrf_token %}
-
{% bootstrap_field form.description %}
-
-
-
-

- Conseil -
- Décrivez en détail votre besoin pour permettre aux prestataires inclusifs de vous faire des réponses personnalisées. -

-
-
-
+
{% bootstrap_field form.start_working_date %}
-
{% bootstrap_field form.start_working_date %}
+
{% bootstrap_field form.deadline_date %}
{% bootstrap_field form.external_link %}
@@ -48,7 +37,7 @@

Questions à poser aux prestataires ciblés

@@ -174,10 +163,10 @@

Questions à poser aux prestataires ciblés

Alpine.data('TenderQuestionForm', TenderQuestionForm); }); document.addEventListener('DOMContentLoaded', function () { - const selectDesciptionAmount = document.getElementById('id_description-amount'); - const divWhyIsBlank = document.getElementById('id_description-why_amount_is_blank'); - toggleRadioSelectElement(divWhyIsBlank, selectDesciptionAmount.value); - selectDesciptionAmount.addEventListener("change", function () { + const selectDetailAmount = document.getElementById('id_detail-amount'); + const divWhyIsBlank = document.getElementById('id_detail-why_amount_is_blank'); + toggleRadioSelectElement(divWhyIsBlank, selectDetailAmount.value); + selectDetailAmount.addEventListener("change", function () { toggleRadioSelectElement(divWhyIsBlank, this.value); }); }); diff --git a/lemarche/templates/tenders/create_step_general.html b/lemarche/templates/tenders/create_step_general.html index 05689dfb4..694fd0f1e 100644 --- a/lemarche/templates/tenders/create_step_general.html +++ b/lemarche/templates/tenders/create_step_general.html @@ -42,6 +42,20 @@ +
+
{% bootstrap_field form.description %}
+
+
+
+

+ Conseil +
+ Décrivez en détail votre besoin pour permettre aux prestataires inclusifs de vous faire des réponses personnalisées. +

+
+
+
+
{% bootstrap_field form.sectors form_group_class="form-group form-group-required use-multiselect" %} diff --git a/lemarche/www/tenders/forms.py b/lemarche/www/tenders/forms.py index 7fee4bc25..7092ad8b5 100644 --- a/lemarche/www/tenders/forms.py +++ b/lemarche/www/tenders/forms.py @@ -29,6 +29,7 @@ class Meta: fields = [ "kind", "title", + "description", "sectors", "location", # generated by js "is_country_area", @@ -42,6 +43,7 @@ def __init__(self, *args, **kwargs): self.fields["kind"].choices = self.FORM_KIND_CHOICES self.fields["location"].to_field_name = "slug" # required fields + self.fields["description"].required = True # self.fields["perimeters"].required = True # JS # label, placeholder & help_text self.fields["title"].widget.attrs["placeholder"] = "Ex : Devis rénovation façade" @@ -59,7 +61,7 @@ def clean(self): self.add_error("sectors", msg_field_missing.format(Sector._meta.verbose_name_plural)) -class TenderCreateStepDescriptionForm(forms.ModelForm): +class TenderCreateStepDetailForm(forms.ModelForm): # fields from previous step kind = None @@ -68,8 +70,8 @@ class TenderCreateStepDescriptionForm(forms.ModelForm): class Meta: model = Tender fields = [ - "description", "start_working_date", + "deadline_date", "external_link", "amount", "why_amount_is_blank", @@ -77,13 +79,21 @@ class Meta: ] widgets = { "start_working_date": forms.widgets.DateInput(attrs={"class": "form-control", "type": "date"}), + "deadline_date": forms.widgets.DateInput(attrs={"class": "form-control", "type": "date"}), "why_amount_is_blank": forms.widgets.RadioSelect, "amount": forms.Select(attrs={"x-model": "formData.amount", "x-on:change": "getImpactMessage()"}), } - def __init__(self, kind, questions_list=None, *args, **kwargs): + def __init__(self, max_deadline_date, kind, questions_list=None, *args, **kwargs): super().__init__(*args, **kwargs) + self.max_deadline_date = max_deadline_date self.kind = kind + + # required fields + self.fields["deadline_date"].required = True + + if self.instance.deadline_date: + self.initial["deadline_date"] = self.instance.deadline_date.isoformat() if questions_list: self.initial["questions_list"] = questions_list # to remove blank option @@ -91,8 +101,6 @@ def __init__(self, kind, questions_list=None, *args, **kwargs): if self.instance.start_working_date: self.initial["start_working_date"] = self.instance.start_working_date.isoformat() - # required fields - self.fields["description"].required = True # label, placeholder & help_text if self.kind != tender_constants.KIND_TENDER: self.fields["external_link"].label = "Lien à partager" @@ -115,6 +123,24 @@ def clean_questions_list(self): questions.pop(index) return questions + def clean_deadline_date(self): + today = date.today() + # check that deadline_date < start_working_date + if ( + self.max_deadline_date + and self.cleaned_data.get("deadline_date") + and (self.cleaned_data.get("deadline_date") > self.max_deadline_date) + ): + self.add_error( + "deadline_date", + f"La date de clôture des réponses ne doit pas être supérieure à la date de début d'intervention ({self.max_deadline_date}).", # noqa + ) + # check that deadline_date > today + if self.cleaned_data.get("deadline_date") and (self.cleaned_data.get("deadline_date") < today): + self.add_error( + "deadline_date", "La date de clôture des réponses ne doit pas être antérieure à aujourd'hui." + ) + class TenderCreateStepContactForm(forms.ModelForm): # fields from previous step @@ -140,11 +166,7 @@ class Meta: "contact_email", "contact_phone", "response_kind", - "deadline_date", ] - widgets = { - "deadline_date": forms.widgets.DateInput(attrs={"class": "form-control", "type": "date"}), - } labels = { "contact_first_name": "Prénom", "contact_last_name": "Nom", @@ -152,19 +174,14 @@ class Meta: "contact_phone": "Téléphone", } - def __init__(self, max_deadline_date, external_link, user: User, *args, **kwargs): + def __init__(self, external_link, user: User, *args, **kwargs): super().__init__(*args, **kwargs) - self.max_deadline_date = max_deadline_date self.external_link = external_link self.user = user user_is_anonymous = not user.is_authenticated - if self.instance.deadline_date: - self.initial["deadline_date"] = self.instance.deadline_date.isoformat() - # required fields self.fields["response_kind"].required = True - self.fields["deadline_date"].required = True if user_is_anonymous: self.fields["contact_first_name"].required = True self.fields["contact_last_name"].required = True @@ -185,23 +202,6 @@ def __init__(self, max_deadline_date, external_link, user: User, *args, **kwargs def clean(self): super().clean() - today = date.today() - # check that deadline_date < start_working_date - if ( - self.max_deadline_date - and self.cleaned_data.get("deadline_date") - and (self.cleaned_data.get("deadline_date") > self.max_deadline_date) - ): - self.add_error( - "deadline_date", - f"La date de clôture des réponses ne doit pas être supérieure à la date de début d'intervention ({self.max_deadline_date}).", # noqa - ) - # check that deadline_date > today - if self.cleaned_data.get("deadline_date") and (self.cleaned_data.get("deadline_date") < today): - self.add_error( - "deadline_date", "La date de clôture des réponses ne doit pas être antérieure à aujourd'hui." - ) - if not self.user.is_authenticated: # contact_email must be filled if RESPONSE_KIND_EMAIL if self.cleaned_data.get("response_kind") and ( diff --git a/lemarche/www/tenders/tests.py b/lemarche/www/tenders/tests.py index 922c2dded..9ecd91089 100644 --- a/lemarche/www/tenders/tests.py +++ b/lemarche/www/tenders/tests.py @@ -43,16 +43,17 @@ def _generate_fake_data_form( "tender_create_multi_step_view-current_step": "general", "general-kind": tender_not_saved.kind, "general-title": tender_not_saved.title, + "general-description": tender_not_saved.description, "general-sectors": cls.sectors, "general-location": cls.location_slug, "general-is_country_area": tender_not_saved.is_country_area, } | _step_1 step_2 = { - "tender_create_multi_step_view-current_step": "description", - "description-description": tender_not_saved.description, - "description-start_working_date": tender_not_saved.start_working_date, - "description-external_link": tender_not_saved.external_link, - "description-amount": tender_constants.AMOUNT_RANGE_1000_MORE, + "tender_create_multi_step_view-current_step": "detail", + "detail-start_working_date": tender_not_saved.start_working_date, + "detail-deadline_date": tender_not_saved.deadline_date, + "detail-external_link": tender_not_saved.external_link, + "detail-amount": tender_constants.AMOUNT_RANGE_1000_MORE, } | _step_2 step_3 = { "tender_create_multi_step_view-current_step": "contact", @@ -62,7 +63,6 @@ def _generate_fake_data_form( "contact-contact_phone": "0123456789", "contact-contact_company_name": "TEST", "contact-response_kind": [Tender.RESPONSE_KIND_EMAIL], - "contact-deadline_date": tender_not_saved.deadline_date, } | _step_3 step_4 = { "tender_create_multi_step_view-current_step": "survey", @@ -189,7 +189,7 @@ def test_tender_wizard_form_questions_list(self): {"text": "Êtes-vous disponible tout l'été ? "}, ] tenders_step_data = self._generate_fake_data_form( - _step_2={"description-questions_list": json.dumps(initial_data_questions_list)} # json field + _step_2={"detail-questions_list": json.dumps(initial_data_questions_list)} # json field ) self._check_every_step(tenders_step_data, final_redirect_page=reverse("siae:search_results")) diff --git a/lemarche/www/tenders/utils.py b/lemarche/www/tenders/utils.py index 4f0bc0dfe..8f3aace67 100644 --- a/lemarche/www/tenders/utils.py +++ b/lemarche/www/tenders/utils.py @@ -80,7 +80,7 @@ def get_or_create_user(request_user, tender_dict: dict, source=User.SOURCE_TENDE user = request_user need_to_be_saved = False if not user.phone: - user.phone = tender_dict.get("contact_phone") + user.phone = tender_dict.get("contact_phone", "") need_to_be_saved = True if not user.company_name: user.company_name = tender_dict.get("contact_company_name") diff --git a/lemarche/www/tenders/views.py b/lemarche/www/tenders/views.py index f3daa8edc..31b907aad 100644 --- a/lemarche/www/tenders/views.py +++ b/lemarche/www/tenders/views.py @@ -27,7 +27,7 @@ from lemarche.www.tenders.forms import ( TenderCreateStepConfirmationForm, TenderCreateStepContactForm, - TenderCreateStepDescriptionForm, + TenderCreateStepDetailForm, TenderCreateStepGeneralForm, TenderCreateStepSurveyForm, ) @@ -64,14 +64,14 @@ class TenderCreateMultiStepView(SessionWizardView): Vous pourrez revenir plus tard pour le publier. Vous le retrouverez dans votre tableau de bord. """ STEP_GENERAL = "general" - STEP_DESCRIPTION = "description" + STEP_DETAIL = "detail" STEP_CONTACT = "contact" STEP_SURVEY = "survey" STEP_CONFIRMATION = "confirmation" TEMPLATES = { STEP_GENERAL: "tenders/create_step_general.html", - STEP_DESCRIPTION: "tenders/create_step_description.html", + STEP_DETAIL: "tenders/create_step_detail.html", STEP_CONTACT: "tenders/create_step_contact.html", STEP_SURVEY: "tenders/create_step_survey.html", STEP_CONFIRMATION: "tenders/create_step_confirmation.html", @@ -79,7 +79,7 @@ class TenderCreateMultiStepView(SessionWizardView): form_list = [ (STEP_GENERAL, TenderCreateStepGeneralForm), - (STEP_DESCRIPTION, TenderCreateStepDescriptionForm), + (STEP_DETAIL, TenderCreateStepDetailForm), (STEP_CONTACT, TenderCreateStepContactForm), (STEP_SURVEY, TenderCreateStepSurveyForm), (STEP_CONFIRMATION, TenderCreateStepConfirmationForm), @@ -103,14 +103,15 @@ def get_form_kwargs(self, step): Initial data """ kwargs = super().get_form_kwargs(step) - if step == self.STEP_DESCRIPTION: - kwargs["kind"] = self.get_cleaned_data_for_step(self.STEP_GENERAL).get("kind") + if step == self.STEP_DETAIL: + cleaned_data_general = self.get_cleaned_data_for_step(self.STEP_GENERAL) + kwargs["max_deadline_date"] = cleaned_data_general.get("start_working_date") + kwargs["kind"] = cleaned_data_general.get("kind") if self.instance.id: kwargs["questions_list"] = list(self.instance.questions_list()) if step == self.STEP_CONTACT: - cleaned_data_description = self.get_cleaned_data_for_step(self.STEP_DESCRIPTION) - kwargs["max_deadline_date"] = cleaned_data_description.get("start_working_date") - kwargs["external_link"] = cleaned_data_description.get("external_link") + cleaned_data_detail = self.get_cleaned_data_for_step(self.STEP_DETAIL) + kwargs["external_link"] = cleaned_data_detail.get("external_link") kwargs["user"] = self.request.user return kwargs