diff --git a/lemarche/templates/tenders/_list_item_buyer.html b/lemarche/templates/tenders/_list_item_buyer.html
index f00044066..2ea06d275 100644
--- a/lemarche/templates/tenders/_list_item_buyer.html
+++ b/lemarche/templates/tenders/_list_item_buyer.html
@@ -9,15 +9,15 @@
{% if tender.deadline_date_is_outdated_annotated %}
Clôturé
{% endif %}
- {% if tender.status == tender.STATUS_DRAFT %}
+ {% if tender.is_draft %}
Brouillon
- {% elif tender.status == tender.STATUS_PUBLISHED %}
+ {% elif tender.is_pending_validation_or_validated %}
En cours de validation
- {% elif tender.status == tender.STATUS_VALIDATED %}
+ {% elif tender.is_sent %}
Envoyé
@@ -33,7 +33,7 @@
{{ tender.title }}
Créé le {{ tender.created_at|date }}
- {% if tender.status == tender.STATUS_VALIDATED %}
+ {% if tender.is_sent %}
- {% if tender.status == tender.STATUS_VALIDATED %}
+ {% if tender.is_sent %}
{% if tender.siae_detail_contact_click_since_last_seen_date_count_annotated %}
{{ tender.siae_detail_contact_click_since_last_seen_date_count_annotated }} nouveau{{ tender.siae_detail_contact_click_since_last_seen_date_count_annotated|pluralize:"x" }} prestataire{{ tender.siae_detail_contact_click_since_last_seen_date_count_annotated|pluralize }} intéressé{{ tender.siae_detail_contact_click_since_last_seen_date_count_annotated|pluralize }}
diff --git a/lemarche/templates/tenders/list.html b/lemarche/templates/tenders/list.html
index 540f7774f..0df3388e5 100644
--- a/lemarche/templates/tenders/list.html
+++ b/lemarche/templates/tenders/list.html
@@ -47,7 +47,7 @@ {{ page_title }}
{% url 'tenders:list' as TENDERS_LIST_URL %}
{% url 'tenders:list' status=tender_constants.STATUS_DRAFT as TENDERS_DRAFT_LIST_URL %}
{% url 'tenders:list' status=tender_constants.STATUS_PUBLISHED as TENDERS_PUBLISHED_LIST_URL %}
- {% url 'tenders:list' status=tender_constants.STATUS_VALIDATED as TENDERS_VALIDATED_LIST_URL %}
+ {% url 'tenders:list' status=tender_constants.STATUS_SENT as TENDERS_SENT_LIST_URL %}
{{ page_title }}
-
Envoyé
@@ -93,7 +93,7 @@ {{ page_title }}
{% if request.get_full_path == TENDERS_PUBLISHED_LIST_URL %}
Vous n'avez aucun besoin en cours de validation pour le moment.
{% endif %}
- {% if request.get_full_path == TENDERS_VALIDATED_LIST_URL %}
+ {% if request.get_full_path == TENDERS_SENT_LIST_URL %}
Vous n'avez aucun besoin d'envoyé pour le moment.
Contacter notre équipe en cas de problème avec un de vos dépôts de besoins en cours de validation.
diff --git a/lemarche/tenders/admin.py b/lemarche/tenders/admin.py
index 4374fde16..039431158 100644
--- a/lemarche/tenders/admin.py
+++ b/lemarche/tenders/admin.py
@@ -389,7 +389,7 @@ def save_related(self, request, form, formsets, change):
super().save_related(request=request, form=form, formsets=formsets, change=change)
tender: Tender = form.instance
# we can add `and obj.status != obj.STATUS_DRAFT` to disable matching when is draft
- if not tender.is_validated:
+ if not tender.is_validated_or_sent:
tender.set_siae_found_list()
def save_formset(self, request, form, formset, change):
diff --git a/lemarche/tenders/factories.py b/lemarche/tenders/factories.py
index 067da52b9..2ffa66732 100644
--- a/lemarche/tenders/factories.py
+++ b/lemarche/tenders/factories.py
@@ -34,7 +34,6 @@ class Meta:
deadline_date = date.today() + timedelta(days=10)
start_working_date = date.today() + timedelta(days=random.randint(12, 90))
author = factory.SubFactory(UserFactory)
- validated_at = timezone.now()
external_link = factory.Sequence("https://{0}example.com".format)
# Contact fields
contact_first_name = factory.Sequence("first_name{0}".format)
@@ -43,7 +42,9 @@ class Meta:
contact_phone = factory.fuzzy.FuzzyText(length=10, chars=string.digits)
# amount = tender_constants.AMOUNT_RANGE_100_150
# marche_benefits = factory.fuzzy.FuzzyChoice([key for (key, _) in constants.MARCHE_BENEFIT_CHOICES])
- status = tender_constants.STATUS_VALIDATED
+ status = tender_constants.STATUS_SENT
+ validated_at = timezone.now()
+ sent_at = timezone.now()
@factory.post_generation
def perimeters(self, create, extracted, **kwargs):
diff --git a/lemarche/tenders/models.py b/lemarche/tenders/models.py
index e8344622e..b546dcbcb 100644
--- a/lemarche/tenders/models.py
+++ b/lemarche/tenders/models.py
@@ -646,13 +646,17 @@ def is_pending_validation(self) -> bool:
def is_validated(self) -> bool:
return self.validated_at and self.status == tender_constants.STATUS_VALIDATED
+ @property
+ def is_pending_validation_or_validated(self) -> bool:
+ return self.is_pending_validation or self.is_validated
+
@property
def is_sent(self) -> bool:
return self.sent_at and self.status == tender_constants.STATUS_SENT
@property
def is_validated_or_sent(self) -> bool:
- return self.validated_at and self.status in [tender_constants.STATUS_VALIDATED, tender_constants.STATUS_SENT]
+ return self.is_validated or self.is_sent
def set_validated_and_sent(self, with_save=True):
self.validated_at = timezone.now()
diff --git a/lemarche/tenders/tests.py b/lemarche/tenders/tests.py
index ded7c2506..cb1fbfbe5 100644
--- a/lemarche/tenders/tests.py
+++ b/lemarche/tenders/tests.py
@@ -109,10 +109,12 @@ def test_status(self):
tender_pending_validation = TenderFactory(status=tender_constants.STATUS_PUBLISHED)
tender_validated_half = TenderFactory(status=tender_constants.STATUS_VALIDATED)
tender_validated_full = TenderFactory(status=tender_constants.STATUS_VALIDATED, validated_at=timezone.now())
+ tender_sent = TenderFactory(status=tender_constants.STATUS_SENT, sent_at=timezone.now())
self.assertTrue(tender_draft.is_draft, True)
self.assertTrue(tender_pending_validation.is_pending_validation, True)
self.assertTrue(tender_validated_half.is_validated, False)
self.assertTrue(tender_validated_full.is_validated, True)
+ self.assertTrue(tender_sent.is_sent, True)
def test_amount_display(self):
tender_with_amount = TenderFactory(amount=tender_constants.AMOUNT_RANGE_0_1, accept_share_amount=True)
@@ -329,9 +331,9 @@ def setUpTestData(cls):
TenderQuestionFactory(tender=cls.tender_with_siae_1)
def test_filter_with_siaes(self):
- self.tender_with_siae_2.validated_at = None
+ self.tender_with_siae_2.sent_at = None
self.tender_with_siae_2.save()
- # tender_with_siae_2 is not validated
+ # tender_with_siae_2 is not sent
self.assertEqual(Tender.objects.filter_with_siaes(self.user_siae.siaes.all()).count(), 1)
def test_with_siae_stats(self):
diff --git a/lemarche/utils/mixins.py b/lemarche/utils/mixins.py
index b4a103304..a211673dd 100644
--- a/lemarche/utils/mixins.py
+++ b/lemarche/utils/mixins.py
@@ -154,16 +154,16 @@ def handle_no_permission(self):
return HttpResponseRedirect(reverse_lazy("tenders:list"))
-class TenderAuthorOrAdminRequiredIfNotValidatedMixin(UserPassesTestMixin):
+class TenderAuthorOrAdminRequiredIfNotSentMixin(UserPassesTestMixin):
"""
- If the Tender's status is not "validated", restrict access to the Tender's author (or Admin)
+ If the Tender's status is not "sent", restrict access to the Tender's author (or Admin)
"""
def test_func(self):
# user = self.request.user
tender_slug = self.kwargs.get("slug")
tender = get_object_or_404(Tender.objects.all(), slug=tender_slug)
- if tender.status != tender_constants.STATUS_VALIDATED:
+ if tender.status != tender_constants.STATUS_SENT:
return TenderAuthorOrAdminRequiredMixin.test_func(self)
return True
diff --git a/lemarche/www/dashboard_networks/tests.py b/lemarche/www/dashboard_networks/tests.py
index 7ce800fa1..5cea5074e 100644
--- a/lemarche/www/dashboard_networks/tests.py
+++ b/lemarche/www/dashboard_networks/tests.py
@@ -35,7 +35,7 @@ def setUpTestData(cls):
author=cls.user_buyer,
amount=tender_constants.AMOUNT_RANGE_100_150,
accept_share_amount=False,
- status=tender_constants.STATUS_VALIDATED,
+ status=tender_constants.STATUS_SENT,
validated_at=timezone.now(),
deadline_date=timezone.now() - timedelta(days=5),
)
diff --git a/lemarche/www/pages/views.py b/lemarche/www/pages/views.py
index 7892b60f2..bd38fe443 100644
--- a/lemarche/www/pages/views.py
+++ b/lemarche/www/pages/views.py
@@ -370,7 +370,7 @@ def csrf_failure(request, reason=""): # noqa C901
if settings.BITOUBI_ENV == "prod":
notify_admin_tender_created(tender)
- if tender.status == tender_constants.STATUS_DRAFT:
+ if tender.is_draft:
messages.add_message(
request=request,
level=messages.INFO,
diff --git a/lemarche/www/tenders/tests.py b/lemarche/www/tenders/tests.py
index 16419cdde..fcf1125ba 100644
--- a/lemarche/www/tenders/tests.py
+++ b/lemarche/www/tenders/tests.py
@@ -471,7 +471,7 @@ def setUpTestData(cls):
cls.user_buyer_1 = UserFactory(kind=User.KIND_BUYER, company_name="Entreprise Buyer")
cls.user_buyer_2 = UserFactory(kind=User.KIND_BUYER)
cls.user_partner = UserFactory(kind=User.KIND_PARTNER)
- cls.tender = TenderFactory(author=cls.user_buyer_1, validated_at=timezone.now(), perimeters=[perimeter])
+ cls.tender = TenderFactory(author=cls.user_buyer_1, perimeters=[perimeter])
cls.tender_2 = TenderFactory(
author=cls.user_buyer_1, deadline_date=timezone.now() - timedelta(days=5), perimeters=[perimeter]
)
@@ -479,7 +479,6 @@ def setUpTestData(cls):
author=cls.user_buyer_1,
amount=tender_constants.AMOUNT_RANGE_100_150,
accept_share_amount=False,
- validated_at=timezone.now(),
deadline_date=timezone.now() - timedelta(days=5),
perimeters=[perimeter],
)
@@ -599,6 +598,8 @@ def setUpTestData(cls):
response_kind=[tender_constants.RESPONSE_KIND_EMAIL],
sectors=[sector_1],
location=grenoble_perimeter,
+ status=tender_constants.STATUS_SENT,
+ sent_at=timezone.now(),
)
cls.tendersiae_1_1 = TenderSiae.objects.create(
tender=cls.tender_1,
@@ -610,9 +611,14 @@ def setUpTestData(cls):
detail_contact_click_date=timezone.now(),
)
TenderQuestionFactory(tender=cls.tender_1)
- cls.tender_2 = TenderFactory(author=cls.user_buyer_1, contact_company_name="Another company")
+ cls.tender_2 = TenderFactory(
+ author=cls.user_buyer_1,
+ contact_company_name="Another company",
+ status=tender_constants.STATUS_SENT,
+ sent_at=timezone.now(),
+ )
- def test_anyone_can_view_validated_tenders(self):
+ def test_anyone_can_view_sent_tenders(self):
# anonymous
url = reverse("tenders:detail", kwargs={"slug": self.tender_1.slug})
response = self.client.get(url)
@@ -625,12 +631,18 @@ def test_anyone_can_view_validated_tenders(self):
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- def test_only_author_or_admin_can_view_non_validated_tender(self):
+ def test_only_author_or_admin_can_view_non_sent_tender(self):
tender_draft = TenderFactory(author=self.user_buyer_1, status=tender_constants.STATUS_DRAFT)
tender_published = TenderFactory(
author=self.user_buyer_1, status=tender_constants.STATUS_PUBLISHED, published_at=timezone.now()
)
- for tender in [tender_draft, tender_published]:
+ tender_validated_but_not_sent = TenderFactory(
+ author=self.user_buyer_1,
+ status=tender_constants.STATUS_VALIDATED,
+ published_at=timezone.now(),
+ validated_at=timezone.now(),
+ )
+ for tender in [tender_draft, tender_published, tender_validated_but_not_sent]:
# anonymous
url = reverse("tenders:detail", kwargs={"slug": tender.slug})
response = self.client.get(url)
diff --git a/lemarche/www/tenders/views.py b/lemarche/www/tenders/views.py
index e226ed650..a078b72da 100644
--- a/lemarche/www/tenders/views.py
+++ b/lemarche/www/tenders/views.py
@@ -21,7 +21,7 @@
from lemarche.utils.mixins import (
SesameTenderAuthorRequiredMixin,
SiaeUserRequiredOrSiaeIdParamMixin,
- TenderAuthorOrAdminRequiredIfNotValidatedMixin,
+ TenderAuthorOrAdminRequiredIfNotSentMixin,
TenderAuthorOrAdminRequiredMixin,
)
from lemarche.www.siaes.forms import SiaeFilterForm
@@ -324,7 +324,7 @@ def get_context_data(self, **kwargs):
return context
-class TenderDetailView(TenderAuthorOrAdminRequiredIfNotValidatedMixin, DetailView):
+class TenderDetailView(TenderAuthorOrAdminRequiredIfNotSentMixin, DetailView):
model = Tender
template_name = "tenders/detail.html"
context_object_name = "tender"