Skip to content
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
423070d
Service.is_orientable_ft_service(): optimise les appels multiples ave…
ggounot Mar 13, 2026
4f02ee1
settings/base: add EMPLOIS_EMAIL
ggounot Mar 13, 2026
1789c03
feat: Ajout d'une API pour les Emplois
ggounot Mar 13, 2026
7d19ff7
Orientation: ajout related_name="orientations", au champ service
ggounot Mar 13, 2026
99cad4b
ServiceSerializer: ajour champ average_orientation_response_delay_days
ggounot Mar 13, 2026
774db11
Ajout d'un endpoint pour les DisabledDoraFormDIStructure
ggounot Mar 13, 2026
1bd8f9b
tests: faire une assertion pour le nombre précis de queries
dmc1985 Mar 17, 2026
e788656
refactor: enlever des méthodes inutiles du serializer
dmc1985 Mar 17, 2026
93bfd34
Update back/dora/services/models.py
dmc1985 Mar 17, 2026
1ad03f8
refactor: faire qu'un seul query pour toutes les villes/EPCIs au lieu…
dmc1985 Mar 17, 2026
555b1ea
tests: ajouter des tests pour la route disabled-dora-form-di-structures
dmc1985 Mar 18, 2026
85383da
tests: renommer un fichier de test
dmc1985 Mar 18, 2026
428eb20
refactor: online_form n'est qu'un string (pas None si c'est un string…
dmc1985 Mar 18, 2026
eedea71
fix: ajouter 'full_desc' au serializer
dmc1985 Mar 18, 2026
3a6a871
refactor: changer le nom du champ à is_orientable_with_form
dmc1985 Mar 19, 2026
7104f8a
DO NOT MERGE & TO DISCUSS
rsebille Mar 26, 2026
7568209
restaure les modes de mobilisation
ggounot Apr 13, 2026
3a7fd81
ajout d'un champ custom_mobilization_form
ggounot Apr 13, 2026
c0bd4e9
restaure le champ is_contact_info_public
ggounot Apr 13, 2026
8e2327d
ajout des champs recurrence, access_conditions, contact_name, contact…
ggounot Apr 13, 2026
968053f
adaptation des tests
ggounot Apr 13, 2026
e57e233
autorise l'accès non authentifié à l'API emplois en local en excluant…
ggounot Apr 13, 2026
725c99c
ajout d'un endpoint pour récupérer toutes les données de référence
ggounot Apr 15, 2026
2f98440
funding_labels: retourne la liste des valeurs uniquement
ggounot Apr 15, 2026
f247cec
retourne les valeurs des modes d'orientation uniquement
ggounot Apr 15, 2026
6b55da4
ajout des champs complémentaires aux modes d'orientation
ggounot Apr 15, 2026
a4fc779
forms: retourne les clés S3 uniquement
ggounot Apr 15, 2026
bc5a260
access_conditions: utilisation de SlugRelatedField
ggounot Apr 15, 2026
09cc5f7
suppression du champ custom_mobilization_form
ggounot Apr 15, 2026
1320e2c
suppression des TODO
ggounot Apr 15, 2026
9388fe4
suppression de la fixture published_service
ggounot Apr 22, 2026
2b06065
refactoring de tests
ggounot Apr 22, 2026
9ebcba0
refactoring de tests
ggounot Apr 22, 2026
d89c465
refactoring de tests
ggounot Apr 22, 2026
1dd34c1
spécifie le nombre de requêtes
ggounot Apr 22, 2026
96c1086
déplace les imports en haut du fichier
ggounot Apr 22, 2026
2f57d3f
suppression du cache des données géographiques maintenant inutile
ggounot Apr 22, 2026
d697f0a
spécifie le nombre de requêtes
ggounot Apr 22, 2026
e76f335
calcule le temps de réponse moyen en Python seulement
ggounot Apr 22, 2026
875e1b9
suppression du flag EMPLOIS_API_ALLOW_UNAUTHENTICATED_LOCAL permettan…
ggounot Apr 22, 2026
2981283
création d'un queryset pour les orientations répondues
ggounot Apr 23, 2026
b08cac3
utilisation d'une fixture paramétrique
ggounot Apr 23, 2026
ab073c0
utilise assertSnapshotQueries
ggounot Apr 23, 2026
2b7d39e
teste le ServiceSerializer avec les données complètes
ggounot Apr 23, 2026
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
3 changes: 3 additions & 0 deletions back/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"dora.auth_links",
"dora.nexus",
"dora.decoupage_administratif",
"dora.emplois",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -373,6 +374,8 @@
os.getenv("DATA_INCLUSION_EXCLUDE_DUPLICATES") == "true"
)

EMPLOIS_EMAIL = os.getenv("EMPLOIS_EMAIL")

SKIP_DI_INTEGRATION_TESTS = True

# BREVO :
Expand Down
4 changes: 4 additions & 0 deletions back/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,14 @@
path("api/v2/", include("dora.api.urls", namespace="v2")),
]

emplois_api_patterns = [
path("api/emplois/", include("dora.emplois.urls", namespace="emplois")),
]

urlpatterns = [
*private_api_patterns,
*di_api_patterns,
*emplois_api_patterns,
# anciennes routes Inclusion-Connect (en attente de suppression)
*oidc_patterns,
# nouvelles routes OIDC pour ProConnect
Expand Down
8 changes: 8 additions & 0 deletions back/dora/decoupage_administratif/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ def get_from_code(self, code):
self._cache[code] = value
return value

def warm_cache(self, codes):
codes_to_fetch = {c.upper() for c in codes if c} - self._cache.keys()
if not codes_to_fetch:
return
found = {obj.code.upper(): obj for obj in self.filter(code__in=codes_to_fetch)}
for code in codes_to_fetch:
self._cache[code] = found.get(code)


# Cache instantané pour les tables comportant peu d'entités
# on fait la requête une fois pour toute
Expand Down
Empty file added back/dora/emplois/__init__.py
Empty file.
90 changes: 90 additions & 0 deletions back/dora/emplois/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from rest_framework import serializers

from dora.orientations.models import Orientation, OrientationStatus
from dora.services.models import Service
from dora.structures.models import DisabledDoraFormDIStructure


class ReferenceDataSerializer(serializers.Serializer):
kind = serializers.CharField()
label = serializers.CharField()
value = serializers.CharField()


class ServiceSerializer(serializers.ModelSerializer):
funding_labels = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="value"
)
coach_orientation_modes = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="value"
)
beneficiaries_access_modes = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="value"
)
forms = serializers.ListField(child=serializers.CharField())
access_conditions = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="name"
)
credentials = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="name"
)
is_orientable_with_form = serializers.SerializerMethodField()
average_orientation_response_delay_days = serializers.SerializerMethodField()

class Meta:
model = Service

fields = [
"id",
"short_desc",
"recurrence",
"funding_labels",
"coach_orientation_modes",
"coach_orientation_modes_other",
"coach_orientation_modes_external_form_link",
"coach_orientation_modes_external_form_link_text",
"beneficiaries_access_modes",
"beneficiaries_access_modes_other",
"beneficiaries_access_modes_external_form_link",
"beneficiaries_access_modes_external_form_link_text",
"forms",
"online_form",
"access_conditions",
"credentials",
"is_orientable_with_form",
"contact_name",
"contact_phone",
"contact_email",
"is_contact_info_public",
"average_orientation_response_delay_days",
]

def get_is_orientable_with_form(self, obj):
return obj.is_orientable() and any(
mode.value == "formulaire-dora"
for mode in obj.coach_orientation_modes.all()
)

def get_average_orientation_response_delay_days(self, obj):
"""Délai moyen de réponse aux demandes d'orientation, en jours."""
orientations = getattr(obj, "answered_orientations", None)
if orientations is None:
orientations = Orientation.objects.filter(
service=obj,
status__in=[
OrientationStatus.ACCEPTED,
OrientationStatus.REJECTED,
],
processing_date__isnull=False,
).only("creation_date", "processing_date")
Comment thread
rsebille marked this conversation as resolved.
Outdated

delays = [(o.processing_date - o.creation_date).days for o in orientations]
if not delays:
return None
return round(sum(delays) / len(delays))


class DisabledDoraFormDIStructureSerializer(serializers.ModelSerializer):
class Meta:
model = DisabledDoraFormDIStructure
fields = ["source", "structure_id"]
41 changes: 41 additions & 0 deletions back/dora/emplois/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import pytest
from data_inclusion.schema.v0 import TypologieStructure
from model_bakery import baker

from dora.core.test_utils import make_published_service
from dora.services.models import FranceTravailOrientableService


@pytest.fixture(autouse=True)
def _set_emplois_email(settings):
settings.EMPLOIS_EMAIL = "emplois@example.com"


@pytest.fixture
def emplois_user(api_client, settings):
user = baker.make("users.User", is_valid=True, email=settings.EMPLOIS_EMAIL)
api_client.force_authenticate(user=user)
return user


@pytest.fixture
def orientable_service_via_dora_form():
service = make_published_service(contact_email="contact@example.org")
service.structure.disable_orientation_form = False
service.structure.save()
service.save()
return service


@pytest.fixture
def ft_orientable_service():
service = make_published_service()
service.structure.typology = TypologieStructure.FT
service.structure.save()

FranceTravailOrientableService.objects.create(
structure=service.structure,
service=service,
)

return service
Loading
Loading