Skip to content

Commit

Permalink
feat(rdvi): add webhooks handler
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-naeka committed Aug 15, 2024
1 parent f313cb1 commit f1be203
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 48 deletions.
1 change: 1 addition & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,3 +711,4 @@
RDV_SOLIDARITES_TOKEN_EXPIRY = os.getenv("RDV_SOLIDARITES_TOKEN_EXPIRY", 86000) # Token expires after 24h (86400s)
RDV_INSERTION_API_BASE_URL = os.getenv("RDV_INSERTION_API_BASE_URL")
RDV_INSERTION_INVITE_HOLD_DURATION = datetime.timedelta(days=int(os.getenv("RDV_INSERTION_INVITE_HOLD_DAYS", 10)))
RDV_INSERTION_WEBHOOK_SECRET = os.getenv("RDV_INSERTION_WEBHOOK_SECRET")
1 change: 1 addition & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
path("legal/terms/", TemplateView.as_view(template_name="static/legal/terms.html"), name="legal-terms"),
path("", include("itou.www.security.urls")),
path("gps/", include("itou.www.gps.urls")),
path("rdvi/", include("itou.www.rdv_insertion.urls")),
path("staff/", include("itou.www.itou_staff_views.urls")),
]

Expand Down
2 changes: 1 addition & 1 deletion itou/companies/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def export(self, request, queryset):
"block_job_applications",
"job_applications_blocked_at",
"approvals_list",
"rdv_insertion_id",
"rdv_solidarites_id",
)
},
),
Expand Down
4 changes: 2 additions & 2 deletions itou/companies/migrations/0005_company_rdv_insertion_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ class Migration(migrations.Migration):
name="rdv_insertion_id",
field=models.IntegerField(
blank=True,
error_messages={"unique": "Une entreprise avec cet ID d'organisation RDV-I existe déjà."},
error_messages={"unique": "Une entreprise avec cet ID d'organisation RDV-S existe déjà."},
help_text="Permet d'initier la prise de RDV via RDV-I lorsque renseigné.",
null=True,
unique=True,
verbose_name="identifiant d'organisation RDV-I",
verbose_name="identifiant d'organisation RDV-S",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0.8 on 2024-08-15 19:10

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("companies", "0006_alter_company_created_by_alter_company_insee_city_and_more"),
]

operations = [
migrations.RenameField(
model_name="company",
old_name="rdv_insertion_id",
new_name="rdv_solidarites_id",
),
]
6 changes: 3 additions & 3 deletions itou/companies/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,13 @@ class Company(AddressMixin, OrganizationAbstract):
verbose_name="score de recommandation (ratio de candidatures récentes vs nombre d'offres d'emploi)", null=True
)

rdv_insertion_id = models.IntegerField(
verbose_name="identifiant d'organisation RDV-I",
rdv_solidarites_id = models.IntegerField(
verbose_name="identifiant d'organisation RDV-S",
blank=True,
null=True,
unique=True,
help_text="Permet d'initier la prise de RDV via RDV-I lorsque renseigné.",
error_messages={"unique": "Une entreprise avec cet ID d'organisation RDV-I existe déjà."},
error_messages={"unique": "Une entreprise avec cet ID d'organisation RDV-S existe déjà."},
)

# Use the generic relation to let NotificationSettings being collected on deletion
Expand Down
40 changes: 23 additions & 17 deletions itou/rdv_insertion/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.7 on 2024-08-07 10:33
# Generated by Django 5.0.8 on 2024-08-15 19:20

import uuid

Expand All @@ -11,7 +11,7 @@ class Migration(migrations.Migration):
initial = True

dependencies = [
("companies", "0005_company_rdv_insertion_id"),
("companies", "0007_rename_rdv_insertion_id_company_rdv_solidarites_id"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

Expand All @@ -23,26 +23,13 @@ class Migration(migrations.Migration):
("name", models.CharField(editable=False, verbose_name="nom")),
("address", models.CharField(editable=False, verbose_name="adresse")),
("phone_number", models.CharField(editable=False, null=True, verbose_name="téléphone")),
("rdv_insertion_id", models.IntegerField(editable=False, unique=True)),
("rdv_solidarites_id", models.IntegerField(editable=False, unique=True)),
],
options={
"verbose_name": "lieu d'un événement RDV-I",
"verbose_name_plural": "lieux d'événements RDV-I",
},
),
migrations.CreateModel(
name="WebhookEvent",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="créée le")),
("body", models.JSONField(editable=False)),
("headers", models.JSONField(editable=False)),
],
options={
"verbose_name": "événement du webhook RDV-I",
"verbose_name_plural": "événements du webhook RDV-I",
},
),
migrations.CreateModel(
name="InvitationRequest",
fields=[
Expand Down Expand Up @@ -261,7 +248,8 @@ class Migration(migrations.Migration):
verbose_name="état",
),
),
("rdv_insertion_id", models.IntegerField(editable=False, unique=True)),
("rdv_insertion_user_id", models.IntegerField(db_index=True, editable=False)),
("rdv_insertion_id", models.IntegerField(editable=False, null=True, unique=True)),
(
"appointment",
models.ForeignKey(
Expand Down Expand Up @@ -299,6 +287,24 @@ class Migration(migrations.Migration):
verbose_name="participants",
),
),
migrations.CreateModel(
name="WebhookEvent",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("created_at", models.DateTimeField(auto_now_add=True, verbose_name="créée le")),
("body", models.JSONField(editable=False)),
("headers", models.JSONField(editable=False)),
("is_processed", models.BooleanField(default=False, editable=False)),
],
options={
"verbose_name": "événement du webhook RDV-I",
"verbose_name_plural": "événements du webhook RDV-I",
"indexes": [
models.Index(models.F("body__data__id"), name="webhookevent_rdvi_id_idx"),
models.Index(models.F("body__meta__model"), name="webhookevent_rdvi_type_idx"),
],
},
),
migrations.AddConstraint(
model_name="invitation",
constraint=models.UniqueConstraint(
Expand Down
18 changes: 16 additions & 2 deletions itou/rdv_insertion/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ class Participation(models.Model):
editable=False,
)
status = models.CharField("état", default=Status.UNKNOWN, choices=Status.choices, editable=False)
rdv_insertion_id = models.IntegerField(unique=True, editable=False)
rdv_insertion_user_id = models.IntegerField(db_index=True, editable=False)
rdv_insertion_id = models.IntegerField(unique=True, null=True, editable=False)

class Meta:
verbose_name = "participation à un événement RDV-I"
Expand Down Expand Up @@ -178,7 +179,7 @@ class Location(models.Model):
name = models.CharField("nom", editable=False)
address = models.CharField("adresse", editable=False)
phone_number = models.CharField("téléphone", null=True, editable=False)
rdv_insertion_id = models.IntegerField(unique=True, editable=False)
rdv_solidarites_id = models.IntegerField(unique=True, editable=False)

class Meta:
verbose_name = "lieu d'un événement RDV-I"
Expand All @@ -189,7 +190,20 @@ class WebhookEvent(models.Model):
created_at = models.DateTimeField("créée le", auto_now_add=True)
body = models.JSONField(editable=False)
headers = models.JSONField(editable=False)
is_processed = models.BooleanField(default=False, editable=False)

class Meta:
verbose_name = "événement du webhook RDV-I"
verbose_name_plural = "événements du webhook RDV-I"
indexes = [
models.Index(models.F("body__data__id"), name="webhookevent_rdvi_id_idx"),
models.Index(models.F("body__meta__model"), name="webhookevent_rdvi_type_idx"),
]

@property
def for_appointment(self):
return self.body["meta"]["model"].lower() == "rdv"

@property
def for_invitation(self):
return self.body["meta"]["model"].lower() == "invitation"
2 changes: 1 addition & 1 deletion itou/templates/apply/includes/list_job_applications.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
</a>
{% elif job_applications_list_kind is JobApplicationsListKind.RECEIVED %}
<span>
{% if request.current_organization.rdv_insertion_id %}
{% if request.current_organization.rdv_solidarites_id %}
{% include "apply/includes/buttons/rdv_insertion_invite.html" with job_application=job_application for_detail=False %}
{% endif %}
<a class="btn btn-outline-primary{% if job_application.pending_for_weeks >= job_application.WEEKS_BEFORE_CONSIDERED_OLD %} btn-block w-100 w-md-auto{% endif %}"
Expand Down
4 changes: 2 additions & 2 deletions itou/templates/apply/process_details_company.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
aria-selected="true"
{% matomo_event "candidature" "clic-onglet" "informations-generales" %}>Informations générales</a>
</li>
{% if job_application.upcoming_appointments or request.current_organization.rdv_insertion_id %}
{% if job_application.upcoming_appointments or request.current_organization.rdv_solidarites_id %}
<li class="nav-item" role="presentation">
<a class="nav-link"
id="appointments-tab"
Expand Down Expand Up @@ -95,7 +95,7 @@ <h3>Action préalable à l'embauche</h3>
{% include "apply/includes/job_application_answers.html" with job_application=job_application %}
</div>

{% if job_application.upcoming_participations_count or request.current_organization.rdv_insertion_id %}
{% if job_application.upcoming_participations_count or request.current_organization.rdv_solidarites_id %}
<div class="tab-pane fade" id="appointments" role="tabpanel" aria-labelledby="appointments-tab">
{# Appointments ------------------------------------------------- #}
{% include "apply/includes/appointments.html" with job_application=job_application %}
Expand Down
4 changes: 2 additions & 2 deletions itou/www/apply/views/process_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ def rdv_insertion_invite(request, job_application_id, for_detail=False):
)

# Ensure company has RDV-I configured
if not job_application.to_company.rdv_insertion_id:
if not job_application.to_company.rdv_solidarites_id:
return render(
request,
template_name,
Expand All @@ -1122,7 +1122,7 @@ def rdv_insertion_invite(request, job_application_id, for_detail=False):
with transaction.atomic():
url = (
f"{settings.RDV_INSERTION_API_BASE_URL}organisations/"
f"{job_application.to_company.rdv_insertion_id}/users/create_and_invite"
f"{job_application.to_company.rdv_solidarites_id}/users/create_and_invite"
)
headers = {"Content-Type": "application/json; charset=utf-8", **get_api_credentials()}

Expand Down
Empty file.
11 changes: 11 additions & 0 deletions itou/www/rdv_insertion/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.urls import path

from itou.www.rdv_insertion import views


# https://docs.djangoproject.com/en/dev/topics/http/urls/#url-namespaces-and-included-urlconfs
app_name = "rdv_insertion"

urlpatterns = [
path("webhook", views.webhook, name="webhook"),
]
Loading

0 comments on commit f1be203

Please sign in to comment.