Skip to content

Commit

Permalink
feat(rdvi): add RDV-I webhooks handler
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-naeka committed Sep 13, 2024
1 parent 6f0de12 commit 6bb1ddb
Show file tree
Hide file tree
Showing 13 changed files with 648 additions and 27 deletions.
1 change: 1 addition & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,3 +691,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 @@ -88,6 +88,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
38 changes: 22 additions & 16 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 @@ -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 @@ -262,7 +249,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 @@ -300,6 +288,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 @@ -150,7 +150,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 @@ -179,7 +180,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 @@ -190,7 +191,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"
149 changes: 149 additions & 0 deletions itou/utils/mocks/rdv_insertion.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,152 @@
"Erreur inconnue",
],
}


RDV_INSERTION_WEBHOOK_INVITATION_HEADERS = {
"Host": "localhost",
"Accept": "application/json",
"Content-Type": "application/json",
"X-Rdvi-Signature": "9ccf14d92f839a383ad27177e9ff4fd346b4d2295a36e842378fca3486cd5152",
}


RDV_INSERTION_WEBHOOK_INVITATION_BODY = {
"data": {
"id": 4806,
"user": {
"id": 3432,
"uid": None,
"role": "demandeur",
"email": "tech@inclusion.beta.gouv.fr",
"title": "madame",
"address": "102 Quai de Jemmapes, 75010 Paris 10ème",
"last_name": "Test",
"birth_date": "1969-05-01",
"birth_name": None,
"created_at": "2024-08-07T17:01:30.719+02:00",
"first_name": "Jeanne",
"phone_number": None,
"france_travail_id": None,
"affiliation_number": None,
"rights_opening_date": None,
"rdv_solidarites_user_id": 5527,
"carnet_de_bord_carnet_id": None,
},
"format": "email",
"clicked": True,
"created_at": "2024-08-15T19:23:08.107+02:00",
"delivered_at": "2024-08-16T08:17:08+02:00",
"motif_category": {"id": 16, "name": "Entretien SIAE", "short_name": "siae_interview"},
"delivery_status": None,
"rdv_with_referents": False,
},
"meta": {"event": "updated", "model": "Invitation", "timestamp": "2024-08-15 19:23:12 +0200"},
}


RDV_INSERTION_WEBHOOK_APPOINTMENT_HEADERS = {
"Host": "localhost",
"Accept": "application/json",
"Content-Type": "application/json",
"X-Rdvi-Signature": "1504bcba3bd89bd6ff409b9b80463c5ebf120665e3978be7d11a39cb18a4d189",
}


RDV_INSERTION_WEBHOOK_APPOINTMENT_BODY = {
"data": {
"id": 1261,
"lieu": {
"name": "PDI",
"address": "6 Boulevard Saint-Denis, Paris, 75010",
"phone_number": "",
"rdv_solidarites_lieu_id": 1026,
},
"uuid": "37141381-ac77-41a6-8a7e-748d1c9439d5",
"motif": {
"name": "Entretien d'embauche",
"collectif": False,
"follow_up": False,
"location_type": "public_office",
"motif_category": {"id": 16, "name": "Entretien SIAE", "short_name": "siae_interview"},
"rdv_solidarites_motif_id": 1443,
},
"users": [
{
"id": 3432,
"uid": None,
"role": "demandeur",
"email": "tech@inclusion.beta.gouv.fr",
"title": "madame",
"address": "102 Quai de Jemmapes, 75010 Paris 10ème",
"last_name": "Test",
"birth_date": "1969-05-01",
"birth_name": None,
"created_at": "2024-08-07T17:01:30.719+02:00",
"first_name": "Jeanne",
"phone_number": None,
"france_travail_id": None,
"affiliation_number": None,
"rights_opening_date": None,
"rdv_solidarites_user_id": 5527,
"carnet_de_bord_carnet_id": None,
}
],
"agents": [
{
"id": 370,
"email": "tech@inclusion.beta.gouv.fr",
"last_name": "Itou",
"first_name": "Tech",
"rdv_solidarites_agent_id": 1791,
}
],
"status": "unknown",
"address": "6 Boulevard Saint-Denis, Paris, 75010",
"starts_at": "2024-08-26T09:00:00.000+02:00",
"created_by": "user",
"users_count": 1,
"cancelled_at": "2024-08-20T09:00:00.000+02:00",
"organisation": {
"id": 91,
"name": "Les Emplois de l'Inclusion",
"email": None,
"phone_number": "0102030405",
"motif_categories": [{"id": 16, "name": "Entretien SIAE", "short_name": "siae_interview"}],
"department_number": "60",
"rdv_solidarites_organisation_id": 654,
},
"participations": [
{
"id": 1174,
"user": {
"id": 3432,
"uid": None,
"role": "demandeur",
"email": "tech@inclusion.beta.gouv.fr",
"title": "madame",
"address": "102 Quai de Jemmapes, 75010 Paris 10ème",
"last_name": "Test",
"birth_date": "1969-05-01",
"birth_name": None,
"created_at": "2024-08-07T17:01:30.719+02:00",
"first_name": "Jeanne",
"phone_number": None,
"france_travail_id": None,
"affiliation_number": None,
"rights_opening_date": None,
"rdv_solidarites_user_id": 5527,
"carnet_de_bord_carnet_id": None,
},
"status": "unknown",
"starts_at": "2024-08-26T09:00:00.000+02:00",
"created_at": "2024-08-15T19:30:08.719+02:00",
"created_by": "user",
}
],
"duration_in_min": 30,
"max_participants_count": None,
"rdv_solidarites_rdv_id": 8725,
},
"meta": {"event": "created", "model": "Rdv", "timestamp": "2024-08-15 19:30:08 +0200"},
}
Empty file.
10 changes: 10 additions & 0 deletions itou/www/rdv_insertion/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.urls import path

from itou.www.rdv_insertion import views


app_name = "rdv_insertion"

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

0 comments on commit 6bb1ddb

Please sign in to comment.