diff --git a/src/blueprints/formations.py b/src/blueprints/formations.py index 517043f..8fcaad8 100644 --- a/src/blueprints/formations.py +++ b/src/blueprints/formations.py @@ -2,13 +2,19 @@ from typing import Any, Tuple from flask import Blueprint, Response, request -from flask_jwt_extended import jwt_required +from flask_jwt_extended import get_jwt_identity, jwt_required from werkzeug.exceptions import HTTPException from src.blueprints.route_handler import HttpMethod, route_handler -from src.business_logic.formation.scrap.get_formation import ( - get_libelle_type_formation, +from src.business_logic.formation.scrap.get_main_formation import ( + auth_get_main_formations, get_main_formations, +) +from src.business_logic.formation.scrap.get_repartition_formations import ( + get_libelle_type_formation, +) +from src.business_logic.formation.scrap.search_formation import ( + auth_search_formations, search_formations, ) from src.constants.http_status_codes import ( @@ -24,11 +30,14 @@ def _filter_by_link(formations: list[dict[str, Any]], for_id: str) -> dict[str, @route_handler(formations, "/", HttpMethod.POST) +@jwt_required(optional=True) def resolve_get_main_formations() -> Tuple[Response, int] | HTTPException: data = request.get_json() offset = data.get("offset") limit = data.get("limit") - + user_id = get_jwt_identity() + if user_id: + return auth_get_main_formations(user_id, limit, offset) return get_main_formations(limit, offset) @@ -57,6 +66,9 @@ def resolve_get_search_formation() -> Tuple[Response, int] | HTTPException: limit = post.get("limit") offset = post.get("offset") + user_id = get_jwt_identity() + if user_id: + return auth_search_formations(user_id, query, limit, offset) return search_formations(query, limit, offset) diff --git a/src/business_logic/favoris/is_favorite.py b/src/business_logic/favoris/is_favorite.py index f5cb3d8..6337e00 100644 --- a/src/business_logic/favoris/is_favorite.py +++ b/src/business_logic/favoris/is_favorite.py @@ -1,11 +1,11 @@ from sqlalchemy import and_, exists -from src.business_logic.formation import get_formation_by_url +from src.business_logic.formation.get_formation_by_url import get_formation_by_url from src.models.user_favori import UserFavori from src import db -def is_favorite(user_id: str, url: str) -> bool: +def check_if_is_favorite(user_id: str, url: str) -> bool: formation = get_formation_by_url(url) if formation is None: diff --git a/src/business_logic/formation/__init__.py b/src/business_logic/formation/__init__.py index e3f8573..b7187e7 100644 --- a/src/business_logic/formation/__init__.py +++ b/src/business_logic/formation/__init__.py @@ -1,5 +1,6 @@ import os -from src.business_logic.formation.scrap.get_onisep_token import get_token + +from src.business_logic.formation.scrap.utils.get_onisep_token import get_token ONISEP_URL = "https://api.opendata.onisep.fr/api/1.0/dataset/" diff --git a/src/business_logic/formation/scrap/get_formation.py b/src/business_logic/formation/scrap/get_formation.py deleted file mode 100644 index 1829888..0000000 --- a/src/business_logic/formation/scrap/get_formation.py +++ /dev/null @@ -1,65 +0,0 @@ -import requests - -from src.business_logic.formation import HEADERS, ONISEP_URL -from src.business_logic.formation.scrap.types import ( - Facet, - SearchedFormations, -) -from src.models.formation import Formation - -# Idéo-Formations initiales en France -# https://opendata.onisep.fr/data/5fa591127f501/2-ideo-formations-initiales-en-france.htm -DATASET = "5fa591127f501" - - -def _get_data(params: str) -> dict: - url = ONISEP_URL + DATASET + params - response = requests.get(url, headers=HEADERS) - if response.status_code == 200: - return response.json() - raise Exception("Onisep API is down.", response.status_code) - - -def _format_formations(data: list[dict]) -> list[Formation]: - return [ - Formation( - code_nsf=int(formation.get("code_nsf") or 0), - type=formation.get("sigle_type_formation") - or formation.get("libelle_type_formation"), - libelle=formation.get("libelle_formation_principal"), - tutelle=formation.get("tutelle"), - url=formation.get("url_et_id_onisep"), - domain=formation.get("domainesous-domaine"), - niveau_de_sortie=formation.get("niveau_de_sortie_indicatif"), - duree=formation.get("duree"), - ).to_dict() - for formation in data - ] - - -def search_formations(query: str, limit: int, offset: int = None) -> SearchedFormations: - params = f"/search?q={query}&size={limit}" - if offset: - params += f"&from={offset}" - data = _get_data(params) - - formated_formations = _format_formations(data["results"]) - - return SearchedFormations(data["total"], formated_formations) - - -def get_libelle_type_formation(query: str) -> list[Facet]: - params = f"/search?q={query}" - data = _get_data(params) - return data["facets"]["libelle_type_formation"] - - -def get_main_formations(limit: int = 10, offset: int = None) -> SearchedFormations: - params = f"/search?&size={limit}" - if offset: - params += f"&from={offset}" - data = _get_data(params) - - formated_formations = _format_formations(data["results"]) - - return SearchedFormations(data["total"], formated_formations) diff --git a/src/business_logic/formation/scrap/get_main_formation.py b/src/business_logic/formation/scrap/get_main_formation.py new file mode 100644 index 0000000..bbc5dc9 --- /dev/null +++ b/src/business_logic/formation/scrap/get_main_formation.py @@ -0,0 +1,31 @@ +from src.business_logic.formation.scrap.utils.format_formations import ( + format_formation_with_is_favorite, + format_formations, +) +from src.business_logic.formation.scrap.types import FormationsWithTotal +from src.business_logic.formation.scrap.utils.get_onisep_data import get_onisep_data + + +def _get_raw_main_formations(limit: int = 10, offset: int = None) -> dict: + params = f"/search?&size={limit}" + if offset: + params += f"&from={offset}" + return get_onisep_data(params) + + +def get_main_formations(limit: int = 10, offset: int = None) -> FormationsWithTotal: + data = _get_raw_main_formations(limit, offset) + + formated_formations = format_formations(data["results"]) + + return FormationsWithTotal(data["total"], formated_formations) + + +def auth_get_main_formations( + user_id: int, limit: int = 10, offset: int = None +) -> FormationsWithTotal: + data = _get_raw_main_formations(limit, offset) + + formated_formations = format_formation_with_is_favorite(user_id, data["results"]) + + return FormationsWithTotal(data["total"], formated_formations) diff --git a/src/business_logic/formation/scrap/get_repartition_formations.py b/src/business_logic/formation/scrap/get_repartition_formations.py new file mode 100644 index 0000000..6c53b29 --- /dev/null +++ b/src/business_logic/formation/scrap/get_repartition_formations.py @@ -0,0 +1,8 @@ +from src.business_logic.formation.scrap.types import Facet +from src.business_logic.formation.scrap.utils.get_onisep_data import get_onisep_data + + +def get_libelle_type_formation(query: str) -> list[Facet]: + params = f"/search?q={query}" + data = get_onisep_data(params) + return data["facets"]["libelle_type_formation"] diff --git a/src/business_logic/formation/scrap/search_formation.py b/src/business_logic/formation/scrap/search_formation.py new file mode 100644 index 0000000..67254e6 --- /dev/null +++ b/src/business_logic/formation/scrap/search_formation.py @@ -0,0 +1,32 @@ +from src.business_logic.formation.scrap.utils.format_formations import ( + format_formation_with_is_favorite, + format_formations, +) +from src.business_logic.formation.scrap.types import FormationsWithTotal +from src.business_logic.formation.scrap.utils.get_onisep_data import get_onisep_data + + +def _get_raw_search_data(query: str, limit: int, offset: int = None) -> dict: + params = f"/search?q={query}&size={limit}" + if offset: + params += f"&from={offset}" + return get_onisep_data(params) + + +def search_formations( + query: str, limit: int, offset: int = None +) -> FormationsWithTotal: + data = _get_raw_search_data(query, limit, offset) + + formated_formations = format_formations(data["results"]) + + return FormationsWithTotal(data["total"], formated_formations) + + +def auth_search_formations( + user_id: int, query: str, limit: int, offset: int = None +) -> FormationsWithTotal: + data = _get_raw_search_data(query, limit, offset) + formated_formations = format_formation_with_is_favorite(user_id, data["results"]) + + return FormationsWithTotal(data["total"], formated_formations) diff --git a/src/business_logic/formation/scrap/types.py b/src/business_logic/formation/scrap/types.py index 3f86f5a..f741c7e 100644 --- a/src/business_logic/formation/scrap/types.py +++ b/src/business_logic/formation/scrap/types.py @@ -10,6 +10,12 @@ class Facet: @dataclass -class SearchedFormations: +class FormationIsFavortite: + formation: Formation + is_favorite: bool + + +@dataclass +class FormationsWithTotal: total: int - formations: list[Formation] + formations: list[Formation | FormationIsFavortite] diff --git a/src/business_logic/formation/scrap/utils/format_formations.py b/src/business_logic/formation/scrap/utils/format_formations.py new file mode 100644 index 0000000..fca3ded --- /dev/null +++ b/src/business_logic/formation/scrap/utils/format_formations.py @@ -0,0 +1,35 @@ +from src.business_logic.favoris.is_favorite import check_if_is_favorite +from src.business_logic.formation.scrap.types import ( + FormationIsFavortite, +) +from src.models.formation import Formation + + +def _create_formation_from_dict(formation: dict) -> Formation: + return Formation( + code_nsf=int(formation.get("code_nsf") or 0), + type=formation.get("sigle_type_formation") + or formation.get("libelle_type_formation"), + libelle=formation.get("libelle_formation_principal"), + tutelle=formation.get("tutelle"), + url=formation.get("url_et_id_onisep"), + domain=formation.get("domainesous-domaine"), + niveau_de_sortie=formation.get("niveau_de_sortie_indicatif"), + duree=formation.get("duree"), + ) + + +def format_formations(data: list[dict]) -> list[Formation]: + return [_create_formation_from_dict(formation).to_dict() for formation in data] + + +def format_formation_with_is_favorite( + user_id: int, data: list[dict] +) -> list[FormationIsFavortite]: + return [ + FormationIsFavortite( + formation=_create_formation_from_dict(formation).to_dict(), + is_favorite=check_if_is_favorite(user_id, formation["url_et_id_onisep"]), + ) + for formation in data + ] diff --git a/src/business_logic/formation/scrap/utils/get_onisep_data.py b/src/business_logic/formation/scrap/utils/get_onisep_data.py new file mode 100644 index 0000000..12b391d --- /dev/null +++ b/src/business_logic/formation/scrap/utils/get_onisep_data.py @@ -0,0 +1,15 @@ +# Idéo-Formations initiales en France +# https://opendata.onisep.fr/data/5fa591127f501/2-ideo-formations-initiales-en-france.htm +import requests +from src.business_logic.formation import HEADERS, ONISEP_URL + + +DATASET = "5fa591127f501" + + +def get_onisep_data(params: str) -> dict: + url = ONISEP_URL + DATASET + params + response = requests.get(url, headers=HEADERS) + if response.status_code == 200: + return response.json() + raise Exception("Onisep API is down.", response.status_code) diff --git a/src/business_logic/formation/scrap/get_onisep_token.py b/src/business_logic/formation/scrap/utils/get_onisep_token.py similarity index 100% rename from src/business_logic/formation/scrap/get_onisep_token.py rename to src/business_logic/formation/scrap/utils/get_onisep_token.py