diff --git a/clevercloud/cron.json b/clevercloud/cron.json index bbe267a78..f377b9235 100644 --- a/clevercloud/cron.json +++ b/clevercloud/cron.json @@ -15,6 +15,7 @@ "0 7 * * 2 $ROOT/clevercloud/siaes_send_completion_reminder_emails.sh", "0 8 * * * $ROOT/clevercloud/siaes_send_user_request_reminder_emails.sh", "30 8 * * * $ROOT/clevercloud/tenders_send_author_transactioned_question_emails.sh", + "35 8 * * * $ROOT/clevercloud/tenders_send_siae_transactioned_question_emails.sh", "0 9 * * * $ROOT/clevercloud/tenders_send_siae_contacted_reminder_emails.sh", "10 9 * * * $ROOT/clevercloud/tenders_send_siae_interested_reminder_emails.sh", "*/5 8-15 * * 1-5 $ROOT/clevercloud/tenders_send_validated.sh" diff --git a/clevercloud/tenders_send_siae_transactioned_question_emails.sh b/clevercloud/tenders_send_siae_transactioned_question_emails.sh new file mode 100755 index 000000000..9996cf5e2 --- /dev/null +++ b/clevercloud/tenders_send_siae_transactioned_question_emails.sh @@ -0,0 +1,22 @@ +#!/bin/bash -l + +# Send email for tender transactioned question to siae (interested) + +# Do not run if this env var is not set: +if [[ -z "$CRON_TENDER_SEND_SIAE_TRANSACTIONED_QUESTION_ENABLED" ]]; then + echo "CRON_TENDER_SEND_SIAE_TRANSACTIONED_QUESTION_ENABLED not set. Exiting..." + exit 0 +fi + +# About clever cloud cronjobs: +# https://www.clever-cloud.com/doc/tools/crons/ + +if [[ "$INSTANCE_NUMBER" != "0" ]]; then + echo "Instance number is ${INSTANCE_NUMBER}. Stop here." + exit 0 +fi + +# $APP_HOME is set by default by clever cloud. +cd $APP_HOME + +django-admin send_siae_transactioned_question_emails diff --git a/config/settings/base.py b/config/settings/base.py index 6bd8d14a4..be10a60ab 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -383,6 +383,9 @@ MAILJET_TENDERS_AUTHOR_TRANSACTIONED_QUESTION_7D_TEMPLATE_ID = env.int( "MAILJET_TENDERS_AUTHOR_TRANSACTIONED_QUESTION_7D_TEMPLATE_ID", 5207181 ) # 4951625 +MAILJET_TENDERS_SIAE_TRANSACTIONED_QUESTION_7D_TEMPLATE_ID = env.int( + "MAILJET_TENDERS_SIAE_TRANSACTIONED_QUESTION_7D_TEMPLATE_ID", 5207266 +) # -- Sendinblue (BREVO) diff --git a/lemarche/tenders/management/commands/send_author_transactioned_question_emails.py b/lemarche/tenders/management/commands/send_author_transactioned_question_emails.py index 0bc99b682..34bcb971e 100644 --- a/lemarche/tenders/management/commands/send_author_transactioned_question_emails.py +++ b/lemarche/tenders/management/commands/send_author_transactioned_question_emails.py @@ -35,7 +35,7 @@ def add_arguments(self, parser): ) def handle(self, kind=None, reminder=False, dry_run=False, **options): - self.stdout.write("Script to send email transactioned_question for tenders...") + self.stdout.write("Script to send email tender transactioned_question to authors...") tender_qs = Tender.objects.sent().filter(survey_transactioned_answer=None) if kind: diff --git a/lemarche/tenders/management/commands/send_siae_transactioned_question_emails.py b/lemarche/tenders/management/commands/send_siae_transactioned_question_emails.py new file mode 100644 index 000000000..2a9feb681 --- /dev/null +++ b/lemarche/tenders/management/commands/send_siae_transactioned_question_emails.py @@ -0,0 +1,41 @@ +from datetime import datetime, timedelta + +from django.core.management.base import BaseCommand + +from lemarche.tenders.models import Tender +from lemarche.www.tenders.tasks import send_tenders_siaes_survey + + +seven_days_ago = datetime.today().date() - timedelta(days=7) + + +class Command(BaseCommand): + """ + Daily script to send an email to tender siaes + Rules + - Tender must be "sent" + no info on "transactioned" + When? + - J+7 after tender start_working_date + + Usage: + python manage.py send_siae_transactioned_question_emails --dry-run + python manage.py send_siae_transactioned_question_emails + """ + + def add_arguments(self, parser): + parser.add_argument("--kind", type=str, dest="kind") + parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Dry run, no sends") + + def handle(self, kind=None, reminder=False, dry_run=False, **options): + self.stdout.write("Script to send email tender transactioned_question to interested siaes...") + + # tender must be sent & no info on transaction & start_working_date J+7 + tender_qs = Tender.objects.sent().filter(siae_transactioned=None) + tender_qs = tender_qs.filter(start_working_date=seven_days_ago) + + self.stdout.write(f"Found {tender_qs.count()} tenders") + + if not dry_run: + email_kind = "transactioned_question_7d" + for tender in tender_qs: + send_tenders_siaes_survey(tender, kind=email_kind) diff --git a/lemarche/www/tenders/tasks.py b/lemarche/www/tenders/tasks.py index 94300de2b..c693c8bdd 100644 --- a/lemarche/www/tenders/tasks.py +++ b/lemarche/www/tenders/tasks.py @@ -556,6 +556,79 @@ def send_tenders_author_feedback_or_survey(tender: Tender, kind="feedback_30d"): tender.save() +def send_tenders_siaes_survey(tender: Tender, kind="transactioned_question_7d"): + tendersiae_qs = TenderSiae.objects.filter(tender=tender) + + if kind == "transactioned_question_7d": + # siae must be interested + tendersiae_qs = tendersiae_qs.filter(detail_contact_click_date__isnull=False) + # siae must not have received the survey yet + tendersiae_qs = tendersiae_qs.filter(survey_transactioned_answer=None, survey_transactioned_send_date=None) + + for tendersiae in tendersiae_qs: + send_tenders_siae_survey(tendersiae, kind=kind) + + # log email batch + log_item = { + "action": f"email_siaes_{kind}_sent", + "siae_count": tendersiae_qs.count(), + "email_timestamp": timezone.now().isoformat(), + } + tender.logs.append(log_item) + tender.save() + + +def send_tenders_siae_survey(tendersiae: TenderSiae, kind="transactioned_question_7d"): + email_subject = f"Suite à notre demande de {tendersiae.tender.title}" + template_id = settings.MAILJET_TENDERS_SIAE_TRANSACTIONED_QUESTION_7D_TEMPLATE_ID + + for user in tendersiae.siae.users.all(): + recipient_list = whitelist_recipient_list([user.email]) + if recipient_list: + recipient_email = recipient_list[0] if recipient_list else "" + recipient_name = user.full_name + + variables = { + "TENDER_AUTHOR_FULL_NAME": tendersiae.tender.contact_full_name, + "tender_author_company": tendersiae.tender.author.company_name, + "TENDER_TITLE": tendersiae.tender.title, + "TENDER_VALIDATE_AT": tendersiae.tender.first_sent_at.strftime("%d %B %Y"), # TODO: TENDER_SENT_AT? + "TENDER_KIND": tendersiae.tender.get_kind_display(), + } + + user_sesame_query_string = sesame_get_query_string(user) # TODO: sesame scope parameter + answer_url_with_sesame_token = ( + f"https://{get_domain_url()}" + + reverse( + "tenders:detail-siae-survey-transactioned", args=[tendersiae.tender.slug, tendersiae.siae.slug] + ) + + user_sesame_query_string + ) + variables["ANSWER_YES_URL"] = answer_url_with_sesame_token + "&answer=True" + variables["ANSWER_NO_URL"] = answer_url_with_sesame_token + "&answer=False" + # add timestamp + tendersiae.survey_transactioned_send_date = timezone.now() + + api_mailjet.send_transactional_email_with_template( + template_id=template_id, + subject=email_subject, + recipient_email=recipient_email, + recipient_name=recipient_name, + variables=variables, + ) + + # log email + log_item = { + "action": f"email_{kind}_sent", + "email_to": recipient_list, + "email_subject": email_subject, + # "email_body": email_body, + "email_timestamp": timezone.now().isoformat(), + } + tendersiae.logs.append(log_item) + tendersiae.save() + + def notify_admin_siae_wants_cocontracting(tender: Tender, siae: Siae): email_subject = f"Marché de l'inclusion : la structure {siae.name} souhaite répondre en co-traitance" tender_admin_url = get_object_admin_url(tender)