Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dépôt de besoin] Champ supplémentaires dans le sondage transaction #964

Merged
merged 3 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions lemarche/templates/tenders/survey_transactioned_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{% extends "layouts/base.html" %}
{% load bootstrap4 %}

{% block title %}Avez-vous contractualisé ?{{ block.super }}{% endblock %}

{% block breadcrumbs %}
<section>
<div class="container">
<div class="row">
<div class="col-12">
<nav class="c-breadcrumb c-breadcrumb--marche" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'wagtail_serve' '' %}">Accueil</a></li>
<li class="breadcrumb-item"><a href="{% url 'dashboard:home' %}">Tableau de bord</a></li>
<li class="breadcrumb-item"><a href="{% url 'tenders:list' %}">Mes besoins</a></li>
<li class="breadcrumb-item"><a href="{% url 'tenders:detail' tender.slug %}" title="{{ tender.title }}">{{ tender.title|truncatechars:25 }}</a></li>
<li class="breadcrumb-item active" aria-current="page">Avez-vous contractualisé ?</li>
</ol>
</nav>
</div>
</div>
</div>
</section>
{% endblock %}

{% block content %}
<section class="s-section">
<div class="s-section__container container">
<h1 class="h1 mb-3 mb-lg-5">
<strong>Avez-vous contractualisé ?</strong>
</h1>
<div class="row">
<div class="col-12">
<form method="POST" action="" class="mb-3 mb-lg-5">
{% csrf_token %}

<div class="row mb-3 mb-lg-5">
<div class="col-12 col-lg-8">
<div class="bg-white d-block rounded-lg shadow-lg p-3 p-lg-5">
<fieldset>
<legend class="h5">{{ form.survey_transactioned_answer.label }}</legend>
{% bootstrap_field form.survey_transactioned_answer show_label=False %}
</fieldset>
</div>
</div>
</div>

{% if tender.survey_transactioned_answer == None or tender.survey_transactioned_answer == True %}
<div class="row mb-3 mb-lg-5">
<div class="col-12 col-lg-8">
<div class="bg-white d-block rounded-lg shadow-lg p-3 p-lg-5">
<fieldset>
<legend class="h5">{{ form.survey_transactioned_amount.label }}</legend>
{% bootstrap_field form.survey_transactioned_amount show_label=False %}
</fieldset>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="alert alert-info mt-3 mt-lg-0" role="alert">
<p class="mb-0">
<i class="ri-information-line ri-lg"></i>
Cette information restera strictement confidentielle et ne sera exploitée qu'à des fins statistiques.
</p>
</div>
</div>
</div>
{% endif %}

<div class="row mb-3 mb-lg-5">
<div class="col-12 col-lg-8">
<div class="bg-white d-block rounded-lg shadow-lg p-3 p-lg-5">
<fieldset>
<legend class="h5">{{ form.survey_transactioned_feedback.label }}</legend>
{% bootstrap_field form.survey_transactioned_feedback show_label=False %}
</fieldset>
</div>
</div>
</div>

<div class="row mt-3 mt-lg-5">
<div class="col-12 col-lg-8 text-right">
<button type="submit" class="btn btn-primary">
<span>Envoyer ma réponse</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
{% endblock %}
4 changes: 4 additions & 0 deletions lemarche/tenders/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
# status
"survey_transactioned_send_date",
"survey_transactioned_answer",
"survey_transactioned_amount",
"survey_transactioned_feedback",
"survey_transactioned_answer_date",
"validated_at",
"question_count_annotated_with_link",
Expand Down Expand Up @@ -293,6 +295,8 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
"fields": (
"survey_transactioned_send_date",
"survey_transactioned_answer",
"survey_transactioned_amount",
"survey_transactioned_feedback",
"survey_transactioned_answer_date",
"siae_transactioned",
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 4.2.2 on 2023-11-05 08:21

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("tenders", "0059_tender_siae_count_updated"),
]

operations = [
migrations.AddField(
model_name="tender",
name="survey_transactioned_amount",
field=models.PositiveIntegerField(
blank=True, null=True, verbose_name="Sondage transaction : montant du besoin"
),
),
migrations.AddField(
model_name="tender",
name="survey_transactioned_feedback",
field=models.TextField(blank=True, verbose_name="Sondage transaction : retour d'expérience"),
),
migrations.AlterField(
model_name="tender",
name="survey_transactioned_answer",
field=models.BooleanField(blank=True, null=True, verbose_name="Sondage transaction : réponse"),
),
migrations.AlterField(
model_name="tender",
name="survey_transactioned_answer_date",
field=models.DateTimeField(blank=True, null=True, verbose_name="Sondage transaction : date de réponse"),
),
migrations.AlterField(
model_name="tender",
name="survey_transactioned_send_date",
field=models.DateTimeField(
blank=True, null=True, verbose_name="Sondage transaction : date d'envoi de l'e-mail"
),
),
]
12 changes: 9 additions & 3 deletions lemarche/tenders/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,19 @@ class Tender(models.Model):
default=list,
)
survey_transactioned_send_date = models.DateTimeField(
verbose_name="Sondage transaction J+30 : date d'envoi de l'e-mail", blank=True, null=True
verbose_name="Sondage transaction : date d'envoi de l'e-mail", blank=True, null=True
)
survey_transactioned_answer = models.BooleanField(
verbose_name="Sondage transaction J+30 : réponse", blank=True, null=True
verbose_name="Sondage transaction : réponse", blank=True, null=True
)
survey_transactioned_amount = models.PositiveIntegerField(
verbose_name="Sondage transaction : montant du besoin", blank=True, null=True
)
survey_transactioned_feedback = models.TextField(
verbose_name="Sondage transaction : retour d'expérience", blank=True
)
survey_transactioned_answer_date = models.DateTimeField(
"Sondage transaction J+30 : date de réponse", blank=True, null=True
"Sondage transaction : date de réponse", blank=True, null=True
)

# validation
Expand Down
27 changes: 25 additions & 2 deletions lemarche/www/tenders/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ def clean_questions_list(self):
questions = self.cleaned_data["questions_list"]
if questions is None:
return questions
elif type(questions) != list:
elif type(questions) is not list:
raise ValueError("It's not a list")
for index, question in enumerate(questions):
if type(question) != dict:
if type(question) is not dict:
raise ValueError("Bad format")
if not question.get("text"):
questions.pop(index)
Expand Down Expand Up @@ -277,3 +277,26 @@ def clean(self) -> dict[str, any]:

class TenderCreateStepConfirmationForm(forms.Form):
pass


class TenderSurveyTransactionedForm(forms.ModelForm):
class Meta:
model = Tender
fields = [
"survey_transactioned_answer",
"survey_transactioned_amount",
"survey_transactioned_feedback",
]

def __init__(self, tender_survey_transactioned_answer=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields[
"survey_transactioned_answer"
].label = "Avez-vous contractualisé avec un prestataire trouvé via le Marché de l'inclusion ?"
self.fields["survey_transactioned_amount"].label = "Quel est le montant de la transaction ?"
self.fields["survey_transactioned_feedback"].label = "Partagez-nous votre retour d'expérience"
self.fields["survey_transactioned_feedback"].widget.attrs.update({"placeholder": "Champ libre"})
if tender_survey_transactioned_answer is not None:
self.fields["survey_transactioned_answer"].disabled = True
if tender_survey_transactioned_answer is False:
self.fields["survey_transactioned_amount"].widget = forms.HiddenInput()
72 changes: 27 additions & 45 deletions lemarche/www/tenders/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@ def setUpTestData(cls):
cls.user_partner = UserFactory(kind=User.KIND_PARTNER)
cls.user_admin = UserFactory(kind=User.KIND_ADMIN)
cls.tender = TenderFactory(kind=tender_constants.KIND_TENDER, author=cls.user_buyer_1, siaes=[cls.siae])
cls.user_buyer_1_sesame_query_string = sesame_get_query_string(cls.user_buyer_1)

def test_anonymous_user_cannot_call_tender_survey_transactioned(self):
url = reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
Expand Down Expand Up @@ -1300,45 +1301,34 @@ def test_only_tender_author_with_sesame_token_can_call_tender_survey_transaction
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
)
response = self.client.get(url)
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse("tenders:detail", kwargs={"slug": self.tender.slug}))
# but the user is not logged in !
url = reverse("dashboard:home")
response = self.client.get(url)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/accounts/login/?next=/profil/")
response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200)
# full form displayed (but should never happen)

def test_update_tender_stats_on_tender_survey_transactioned_answer_true(self):
user_sesame_query_string = sesame_get_query_string(self.user_buyer_1)
self.assertEqual(self.tender.survey_transactioned_answer, None)
self.assertEqual(self.tender.siae_transactioned, None)
# load without answer
# load with answer 'True': partial form
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
)
response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200) # redirect
self.assertRedirects(response, reverse("tenders:detail", kwargs={"slug": self.tender.slug}))
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, None)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, None)
# load with answer
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
+ self.user_buyer_1_sesame_query_string
+ "&answer=True"
)
response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, True)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, True)
# fill in form
response = self.client.post(
url, data={"survey_transactioned_amount": 1000, "survey_transactioned_feedback": "Feedback"}, follow=True
)
self.assertEqual(response.status_code, 200) # redirect
self.assertRedirects(response, reverse("tenders:detail", kwargs={"slug": self.tender.slug}))
self.assertContains(response, "Merci pour vote réponse")
self.assertContains(response, "Merci pour votre réponse")
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, True)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, True)
# reload with answer, ignore changes
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_amount, 1000)
# reload with answer, ignore changes and redirect
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
+ self.user_buyer_1_sesame_query_string
+ "&answer=False"
)
response = self.client.get(url, follow=True)
Expand All @@ -1349,35 +1339,27 @@ def test_update_tender_stats_on_tender_survey_transactioned_answer_true(self):
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, True)

def test_update_tender_stats_on_tender_survey_transactioned_answer_false(self):
user_sesame_query_string = sesame_get_query_string(self.user_buyer_1)
self.assertEqual(self.tender.survey_transactioned_answer, None)
self.assertEqual(self.tender.siae_transactioned, None)
# load without answer
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
)
response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200) # redirect
self.assertRedirects(response, reverse("tenders:detail", kwargs={"slug": self.tender.slug}))
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, None)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, None)
# load with answer
# load with answer 'False': partial form
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
+ self.user_buyer_1_sesame_query_string
+ "&answer=False"
)
response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, False)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, False)
# fill in form
response = self.client.post(url, data={"survey_transactioned_feedback": "Feedback"}, follow=True)
self.assertEqual(response.status_code, 200) # redirect
self.assertRedirects(response, reverse("tenders:detail", kwargs={"slug": self.tender.slug}))
self.assertContains(response, "Merci pour vote réponse")
self.assertContains(response, "Merci pour votre réponse")
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_answer, False)
self.assertEqual(Tender.objects.get(id=self.tender.id).siae_transactioned, False)
self.assertEqual(Tender.objects.get(id=self.tender.id).survey_transactioned_amount, None)
# reload with answer, ignore changes
url = (
reverse("tenders:detail-survey-transactioned", kwargs={"slug": self.tender.slug})
+ user_sesame_query_string
+ self.user_buyer_1_sesame_query_string
+ "&answer=True"
)
response = self.client.get(url, follow=True)
Expand Down
Loading