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] Nouveau status "SENT" #997

Merged
merged 6 commits into from
Dec 6, 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
4 changes: 2 additions & 2 deletions lemarche/templates/tenders/_card_list_item.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
{% if tender.deadline_date_is_outdated_annotated %}
<span class="badge badge-xs badge-base badge-pill badge-pilotage float-right">Clôturé</span>
{% endif %}
{% if tender.status == tender.STATUS_DRAFT %}
{% if tender.is_draft %}
<span class="badge badge-xs badge-base badge-pill badge-outline-warning float-right">
<i class="ri-draft-fill"></i>Brouillon
</span>
{% elif tender.status == tender.STATUS_PUBLISHED %}
{% elif tender.is_pending_validation_or_validated %}
<span class="badge badge-xs badge-base badge-pill badge-outline-info float-right">
<i class="ri-loader-fill"></i>En cours de validation
</span>
Expand Down
4 changes: 2 additions & 2 deletions lemarche/templates/tenders/_detail_admin_extra_info.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ <h2 class="h3">Informations Admin</h2>
Publié le {{ tender.published_at|date }}
</li>
<li class="mb-2">
{% if tender.is_validated %}
Validé le {{ tender.validated_at|date }}
{% if tender.is_sent %}
Validé le {{ tender.sent_at|date }}
{% else %}
Statut : {{ tender.get_status_display }}
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion lemarche/templates/tenders/_detail_side_infos_author.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</div>
</div>
{% endif %}
{% if tender.is_validated %}
{% if tender.is_sent %}
<div class="alert alert-success fade show" role="status">
<div class="row">
<div class="col-auto pr-0">
Expand Down
12 changes: 6 additions & 6 deletions lemarche/templates/tenders/_list_item_buyer.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
{% if tender.deadline_date_is_outdated_annotated %}
<span class="badge badge-sm badge-base badge-pill badge-pilotage">Clôturé</span>
{% endif %}
{% if tender.status == tender.STATUS_DRAFT %}
{% if tender.is_draft %}
<span class="badge badge-sm badge-base badge-pill badge-outline-warning float-right">
<i class="ri-draft-fill"></i>Brouillon
</span>
{% elif tender.status == tender.STATUS_PUBLISHED %}
{% elif tender.is_pending_validation_or_validated %}
<span class="badge badge-sm badge-base badge-pill badge-outline-info float-right">
<i class="ri-loader-fill"></i>En cours de validation
</span>
{% elif tender.status == tender.STATUS_VALIDATED %}
{% elif tender.is_sent %}
<span class="badge badge-sm badge-base badge-pill badge-outline-success float-right">
<i class="ri-mail-send-line"></i>Envoyé
</span>
Expand All @@ -33,17 +33,17 @@ <h2 class="py-2">{{ tender.title }}</h2>
<i class="ri-time-line"></i>
Créé le {{ tender.created_at|date }}
</div>
{% if tender.status == tender.STATUS_VALIDATED %}
{% if tender.is_sent %}
<div class="col-md-4">
<i class="ri-time-line"></i>
Publié le {{ tender.validated_at|date }}
Publié le {{ tender.sent_at|date }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-4 text-center my-auto">
<hr class="d-md-none" />
{% if tender.status == tender.STATUS_VALIDATED %}
{% if tender.is_sent %}
{% if tender.siae_detail_contact_click_since_last_seen_date_count_annotated %}
<span class="badge badge-base badge-pill badge-pilotage">
<i class="ri-thumb-up-line ri-xl"></i>&nbsp;{{ 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 }}
Expand Down
7 changes: 5 additions & 2 deletions lemarche/templates/tenders/admin_change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@
{% if original %}
<div class="submit-row">
{% if original.validated_at %}
<i>Validé et envoyé le {{ original.validated_at }}</i><br>
<button type="submit" name="_restart_tender" value="1" class="button">Renvoyer aux structures</button>
<i>Validé le {{ original.validated_at }}.&nbsp;</i>
{% if original.sent_at %}
<i>Envoyé le {{ original.sent_at }}.</i><br>
<button type="submit" name="_restart_tender" value="1" class="button">Renvoyer aux structures</button>
{% endif %}
{% else %}
<button type="submit" name="_validate_tender" value="1" class="button">Valider (sauvegarder) et envoyer aux structures</button>
{% endif %}
Expand Down
8 changes: 4 additions & 4 deletions lemarche/templates/tenders/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ <h1>{{ page_title }}</h1>
{% 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 %}

<li class="nav-item">
<a role="button" hx-push-url="true" hx-get="{{ TENDERS_LIST_URL }}"
Expand All @@ -71,8 +71,8 @@ <h1>{{ page_title }}</h1>
</a>
</li>
<li class="nav-item">
<a role="button" hx-push-url="true" hx-get="{{ TENDERS_VALIDATED_LIST_URL }}"
class="nav-link{% if request.get_full_path == TENDERS_VALIDATED_LIST_URL %} active{% endif %}"
<a role="button" hx-push-url="true" hx-get="{{ TENDERS_SENT_LIST_URL }}"
class="nav-link{% if request.get_full_path == TENDERS_SENT_LIST_URL %} active{% endif %}"
hx-target="#tendersList" hx-swap="outerHTML">
Envoyé
</a>
Expand All @@ -93,7 +93,7 @@ <h1>{{ page_title }}</h1>
{% 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.
<br />
Contacter notre équipe en cas de problème avec un de vos dépôts de besoins en cours de validation.
Expand Down
26 changes: 15 additions & 11 deletions lemarche/tenders/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ class TenderQuestionInline(admin.TabularInline):
extra = 0


def update_and_send_tender_task(tender: Tender):
def validate_and_send_tender_task(tender: Tender):
# 1) validate the tender
tender.set_validated(with_save=True)
tender.set_validated_and_sent(with_save=True)
# 2) find the matching Siaes? done in Tender post_save signal
send_confirmation_published_email_to_author(tender, nb_matched_siaes=tender.siaes.count())
# 3) send the tender to all matching Siaes & Partners
Expand All @@ -123,7 +123,7 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
list_display = [
"id",
"status",
"is_validate",
"is_validated_or_sent",
"title",
"user_with_link",
"kind",
Expand All @@ -138,6 +138,7 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
"siae_transactioned",
"created_at",
"validated_at",
"sent_at",
]

list_filter = [
Expand Down Expand Up @@ -174,6 +175,7 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
"survey_transactioned_feedback",
"survey_transactioned_answer_date",
"validated_at",
"sent_at",
"question_count_with_link",
"siae_count_annotated_with_link",
"siae_email_send_count_annotated_with_link",
Expand Down Expand Up @@ -321,6 +323,7 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin):
"status",
"published_at",
"validated_at",
"sent_at",
)
},
),
Expand Down Expand Up @@ -386,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):
Expand All @@ -399,11 +402,11 @@ def save_formset(self, request, form, formset, change):
form.instance.author = request.user
super().save_formset(request, form, formset, change)

def is_validate(self, tender: Tender):
return tender.validated_at is not None
def is_validated_or_sent(self, tender: Tender):
return tender.is_validated_or_sent

is_validate.boolean = True
is_validate.short_description = "Validé"
is_validated_or_sent.boolean = True
is_validated_or_sent.short_description = "Validé / Envoyé"

def user_with_link(self, tender):
url = reverse("admin:users_user_change", args=[tender.author_id])
Expand Down Expand Up @@ -487,18 +490,19 @@ def logs_display(self, tender=None):
logs_display.short_description = Tender._meta.get_field("logs").verbose_name

def response_change(self, request, obj: Tender):
"""
Catch submit of custom admin button to Validate or Resend Tender
"""
if request.POST.get("_validate_tender"):
update_and_send_tender_task(tender=obj)
validate_and_send_tender_task(tender=obj)
self.message_user(request, "Ce dépôt de besoin a été validé et envoyé aux structures")
if settings.BITOUBI_ENV == "prod":
api_hubspot.create_deal_from_tender(tender=obj)

return HttpResponseRedirect(".")
elif request.POST.get("_restart_tender"):
restart_send_tender_task(tender=obj)
self.message_user(request, "Ce dépôt de besoin a été renvoyé aux structures")
return HttpResponseRedirect(".")

return super().response_change(request, obj)

def extra_data_display(self, instance: Tender = None):
Expand Down
2 changes: 2 additions & 0 deletions lemarche/tenders/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@
STATUS_DRAFT = "DRAFT"
STATUS_PUBLISHED = "PUBLISHED"
STATUS_VALIDATED = "VALIDATED"
STATUS_SENT = "SENT"

STATUS_CHOICES = (
(STATUS_DRAFT, "Brouillon"),
(STATUS_PUBLISHED, "Publié"),
(STATUS_VALIDATED, "Validé"),
(STATUS_SENT, "Envoyé"),
)


Expand Down
5 changes: 3 additions & 2 deletions lemarche/tenders/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class Command(BaseCommand):
"""
Daily script to check recently validated Tenders. If incremental, then contact author
Daily script to check recently sent Tenders. If incremental, then contact author
When? J+2

Usage:
Expand All @@ -25,21 +25,21 @@ def handle(self, dry_run=False, **options):
self.stdout.write("Script to send Tender incremental emails...")

self.stdout.write("-" * 80)
self.stdout.write("Step 1: Find Tender validated J+2")
self.stdout.write("Step 1: Find Tender sent J+2")
two_days_ago = timezone.now() - timedelta(days=2)
three_days_ago = timezone.now() - timedelta(days=3)
tender_validated_incremental = Tender.objects.validated().is_incremental()
tender_validated_incremental_2_days = tender_validated_incremental.filter(
created_at__gte=three_days_ago
).filter(created_at__lt=two_days_ago)
self.stdout.write(f"Found {tender_validated_incremental_2_days.count()} Tenders")
tender_sent_incremental = Tender.objects.sent().is_incremental()
tender_sent_incremental_2_days = tender_sent_incremental.filter(sent_at__gte=three_days_ago).filter(
sent_at__lt=two_days_ago
)
self.stdout.write(f"Found {tender_sent_incremental_2_days.count()} Tenders")

if not dry_run:
self.stdout.write("-" * 80)
self.stdout.write("Step 2: Send emails")
for tender in tender_validated_incremental_2_days:
for tender in tender_sent_incremental_2_days:
send_author_incremental_2_days_email(tender)
self.stdout.write(f"Sent {tender_validated_incremental_2_days.count()} J+2 emails")
self.stdout.write(f"Sent {tender_sent_incremental_2_days.count()} J+2 emails")

self.stdout.write("-" * 80)
self.stdout.write("Done!")
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ def handle(self, kind=None, dry_run=False, is_all_tenders=False, **options):
self.stdout.write("-" * 80)
start_date_feature = datetime(2022, 6, 23).date()
# we first filter on validated tenders
tender_qs = Tender.objects.transaction_survey_email(kind=kind, all=is_all_tenders).filter(
deadline_date__gte=start_date_feature
tender_qs = (
Tender.objects.sent()
.transaction_survey_email(kind=kind, all=is_all_tenders)
.filter(deadline_date__gte=start_date_feature)
)

self.stdout.write(f"Found {tender_qs.count()} tenders")
Expand Down
37 changes: 37 additions & 0 deletions lemarche/tenders/migrations/0064_tender_status_sent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.2.2 on 2023-11-30 22:12

from django.db import migrations, models


def populate_tenders_sent_status(apps, schema_editor):
Tender = apps.get_model("tenders", "Tender")

for tender in Tender.objects.filter(validated_at__isnull=False):
tender.sent_at = tender.validated_at
tender.status = "SENT"
tender.save()


class Migration(migrations.Migration):
dependencies = [
("tenders", "0063_tender_distance_location"),
]

operations = [
migrations.AddField(
model_name="tender",
name="sent_at",
field=models.DateTimeField(blank=True, null=True, verbose_name="Date d'envoi"),
),
migrations.AlterField(
model_name="tender",
name="status",
field=models.CharField(
choices=[("DRAFT", "Brouillon"), ("PUBLISHED", "Publié"), ("VALIDATED", "Validé"), ("SENT", "Envoyé")],
default="DRAFT",
max_length=10,
verbose_name="Statut",
),
),
migrations.RunPython(populate_tenders_sent_status),
]
Loading