diff --git a/lemarche/templates/tenders/_detail_card.html b/lemarche/templates/tenders/_detail_card.html index 8c2718d07..7ce52339d 100644 --- a/lemarche/templates/tenders/_detail_card.html +++ b/lemarche/templates/tenders/_detail_card.html @@ -69,7 +69,7 @@

{% endif %} - {% if source_form or not source_form and tender.constraints %} + {% if tender.constraints %}

Contraintes techniques spécifiques

{{ tender.constraints|default:"-"|safe|linebreaks }}

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..1f4faca20 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étails du besoin{% endblock %} +{% block step_title_again %}Détails 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..c0266d513 100644 --- a/lemarche/templates/tenders/create_step_general.html +++ b/lemarche/templates/tenders/create_step_general.html @@ -34,9 +34,21 @@ Optimiser vos titres,
Votre titre doit être le plus précis sans être très long ou court. - Les structures inclusives doivent directement pouvoir comprendre vos attente.
- Ne pas utiliser les mots devis, prestation de service et sourcing.
- Par exemple : nettoyage des locaux de mon entreprise à Nantes + Les structures inclusives doivent directement pouvoir comprendre vos attente. +

+ + + + +
+
{% bootstrap_field form.description %}
+
+
+
+

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

diff --git a/lemarche/www/tenders/forms.py b/lemarche/www/tenders/forms.py index 7fee4bc25..dd1bc6d84 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,6 +79,7 @@ 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()"}), } @@ -84,6 +87,12 @@ class Meta: def __init__(self, kind, questions_list=None, *args, **kwargs): super().__init__(*args, **kwargs) 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 +100,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,10 +122,29 @@ def clean_questions_list(self): questions.pop(index) return questions + def clean(self): + super().clean() + today = date.today() + max_deadline_date = self.cleaned_data.get("start_working_date") + deadline_date = self.cleaned_data.get("deadline_date") + # check that deadline_date < start_working_date + if max_deadline_date and deadline_date and (deadline_date > max_deadline_date): + self.add_error( + "deadline_date", + ( + "La date de clôture des réponses ne doit pas être supérieure à la date " + f"de début d'intervention ({max_deadline_date})." + ), + ) + # check that deadline_date > today + if deadline_date and (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 - max_deadline_date = None external_link = None user_is_anonymous = None user_does_not_have_company_name = None @@ -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..a499fe91b 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,12 @@ def get_form_kwargs(self, step): Initial data """ kwargs = super().get_form_kwargs(step) - if step == self.STEP_DESCRIPTION: + if step == self.STEP_DETAIL: kwargs["kind"] = self.get_cleaned_data_for_step(self.STEP_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") + kwargs["external_link"] = self.get_cleaned_data_for_step(self.STEP_DETAIL).get("external_link") kwargs["user"] = self.request.user return kwargs