Meilleure gestion des SIRET absents du SIRENE dans acheteur et titulaire

This commit is contained in:
Colin Maudry
2026-02-05 14:18:38 +01:00
parent cb885eeb90
commit 64fc40e5aa
3 changed files with 77 additions and 68 deletions
+21 -7
View File
@@ -218,12 +218,15 @@ layout = [
) )
def update_acheteur_infos(url): def update_acheteur_infos(url):
acheteur_siret = url.split("/")[-1] acheteur_siret = url.split("/")[-1]
if len(acheteur_siret) != 14: # if len(acheteur_siret) != 14:
acheteur_siret = ( # acheteur_siret = (
f"Le SIRET renseigné doit faire 14 caractères ({acheteur_siret})" # f"Le SIRET renseigné doit faire 14 caractères ({acheteur_siret})"
) # )
data = get_annuaire_data(acheteur_siret) data = get_annuaire_data(acheteur_siret)
data_etablissement = data["matching_etablissements"][0] data_etablissement = data.get("matching_etablissements") if data else None
if data_etablissement:
data_etablissement = data_etablissement[0]
acheteur_map = point_on_map( acheteur_map = point_on_map(
data_etablissement["latitude"], data_etablissement["longitude"] data_etablissement["latitude"], data_etablissement["longitude"]
) )
@@ -234,10 +237,21 @@ def update_acheteur_infos(url):
lien_annuaire = ( lien_annuaire = (
f"https://annuaire-entreprises.data.gouv.fr/etablissement/{acheteur_siret}" f"https://annuaire-entreprises.data.gouv.fr/etablissement/{acheteur_siret}"
) )
raison_sociale = data["nom_raison_sociale"]
libelle_commune = data_etablissement["libelle_commune"]
else:
acheteur_map = html.Div()
code_departement, nom_departement, nom_region = "", "", ""
departement = ""
lien_annuaire = ""
raison_sociale = ""
libelle_commune = ""
return ( return (
acheteur_siret, acheteur_siret,
data["nom_raison_sociale"], raison_sociale,
data_etablissement["libelle_commune"], libelle_commune,
acheteur_map, acheteur_map,
departement, departement,
nom_region, nom_region,
+28 -38
View File
@@ -56,6 +56,9 @@ datatable = html.Div(
className="marches_table", className="marches_table",
children=DataTable( children=DataTable(
dtid="titulaire_datatable", dtid="titulaire_datatable",
persistence=True,
persistence_type="local",
persisted_props=["filter_query", "sort_by"],
page_action="custom", page_action="custom",
filter_action="custom", filter_action="custom",
sort_action="custom", sort_action="custom",
@@ -68,8 +71,6 @@ datatable = html.Div(
layout = [ layout = [
dcc.Store(id="titulaire_data", storage_type="memory"), dcc.Store(id="titulaire_data", storage_type="memory"),
dcc.Store(id="titulaire-hidden-columns", storage_type="local"), dcc.Store(id="titulaire-hidden-columns", storage_type="local"),
dcc.Store(id="titulaire-filters", storage_type="local"),
dcc.Store(id="titulaire-sort", storage_type="local"),
dcc.Store(id="filter-cleanup-trigger-titulaire"), dcc.Store(id="filter-cleanup-trigger-titulaire"),
dcc.Location(id="titulaire_url", refresh="callback-nav"), dcc.Location(id="titulaire_url", refresh="callback-nav"),
html.Div( html.Div(
@@ -217,12 +218,11 @@ layout = [
) )
def update_titulaire_infos(url): def update_titulaire_infos(url):
titulaire_siret = url.split("/")[-1] titulaire_siret = url.split("/")[-1]
if len(titulaire_siret) != 14:
titulaire_siret = (
f"Le SIRET renseigné doit faire 14 caractères ({titulaire_siret})"
)
data = get_annuaire_data(titulaire_siret) data = get_annuaire_data(titulaire_siret)
data_etablissement = data["matching_etablissements"][0] data_etablissement = data.get("matching_etablissements") if data else None
if data_etablissement:
data_etablissement = data_etablissement[0]
titulaire_map = point_on_map( titulaire_map = point_on_map(
data_etablissement["latitude"], data_etablissement["longitude"] data_etablissement["latitude"], data_etablissement["longitude"]
) )
@@ -233,10 +233,23 @@ def update_titulaire_infos(url):
lien_annuaire = ( lien_annuaire = (
f"https://annuaire-entreprises.data.gouv.fr/etablissement/{titulaire_siret}" f"https://annuaire-entreprises.data.gouv.fr/etablissement/{titulaire_siret}"
) )
raison_sociale = data["nom_raison_sociale"]
libelle_commune = data_etablissement["libelle_commune"]
else:
titulaire_map = html.Div()
code_departement, nom_departement, nom_region = "", "", ""
departement = ""
lien_annuaire = ""
raison_sociale = html.Span(
f"N° SIREN inconnu de l'INSEE ({titulaire_siret[:9]})"
)
libelle_commune = ""
return ( return (
titulaire_siret, titulaire_siret,
data["nom_raison_sociale"], raison_sociale,
data_etablissement["libelle_commune"], libelle_commune,
titulaire_map, titulaire_map,
departement, departement,
nom_region, nom_region,
@@ -314,16 +327,17 @@ def get_titulaire_marches_data(url, titulaire_year: str) -> tuple:
Output("btn-download-filtered-data-titulaire", "children"), Output("btn-download-filtered-data-titulaire", "children"),
Output("btn-download-filtered-data-titulaire", "title"), Output("btn-download-filtered-data-titulaire", "title"),
Output("filter-cleanup-trigger-titulaire", "data", allow_duplicate=True), Output("filter-cleanup-trigger-titulaire", "data", allow_duplicate=True),
Input(component_id="titulaire_url", component_property="href"),
Input("titulaire_data", "data"), Input("titulaire_data", "data"),
Input("titulaire_datatable", "page_current"), Input("titulaire_datatable", "page_current"),
Input("titulaire_datatable", "page_size"), Input("titulaire_datatable", "page_size"),
Input("titulaire-filters", "data"), Input("titulaire_datatable", "filter_query"),
Input("titulaire-sort", "data"), Input("titulaire_datatable", "sort_by"),
State("titulaire_datatable", "data_timestamp"), State("titulaire_datatable", "data_timestamp"),
config_prevent_initial_callbacks=True, config_prevent_initial_callbacks=True,
) )
def get_last_marches_data( def get_last_marches_data(
data, page_current, page_size, filter_query, sort_by, data_timestamp href, data, page_current, page_size, filter_query, sort_by, data_timestamp
) -> list[dict]: ) -> list[dict]:
return prepare_table_data( return prepare_table_data(
data, data,
@@ -374,8 +388,8 @@ def download_titulaire_data(
State("titulaire_data", "data"), State("titulaire_data", "data"),
Input("btn-download-filtered-data-titulaire", "n_clicks"), Input("btn-download-filtered-data-titulaire", "n_clicks"),
State("titulaire_nom", "children"), State("titulaire_nom", "children"),
State("titulaire-filters", "data"), State("titulaire_datatable", "filter_query"),
State("titulaire-sort", "data"), State("titulaire_datatable", "sort_by"),
State("titulaire_datatable", "hidden_columns"), State("titulaire_datatable", "hidden_columns"),
prevent_initial_call=True, prevent_initial_call=True,
) )
@@ -469,30 +483,6 @@ def toggle_titulaire_columns(click_open, click_close, is_open):
return is_open return is_open
@callback(
Output("titulaire-filters", "data"), Input("titulaire_datatable", "filter_query")
)
def sync_filters_to_local_storage(filter_query):
return filter_query
@callback(Output("titulaire-sort", "data"), Input("titulaire_datatable", "sort_by"))
def sync_sort_to_local_storage(sort_by):
return sort_by
@callback(
Output("titulaire_datatable", "filter_query", allow_duplicate=True),
Output("titulaire_datatable", "sort_by", allow_duplicate=True),
Input("titulaire_url", "href"),
State("titulaire-filters", "data"),
State("titulaire-sort", "data"),
prevent_initial_call=True,
)
def sync_local_storage_to_datatable(href, filter_query, sort_by):
return filter_query, sort_by
@callback( @callback(
Output("titulaire_datatable", "filter_query", allow_duplicate=True), Output("titulaire_datatable", "filter_query", allow_duplicate=True),
Output("titulaire_datatable", "sort_by"), Output("titulaire_datatable", "sort_by"),
+8 -3
View File
@@ -9,7 +9,7 @@ import dash
import polars as pl import polars as pl
import polars.selectors as cs import polars.selectors as cs
from dash import no_update from dash import no_update
from httpx import get, post from httpx import HTTPError, get, post
from polars.exceptions import ComputeError from polars.exceptions import ComputeError
from unidecode import unidecode from unidecode import unidecode
@@ -208,8 +208,13 @@ def format_values(dff: pl.DataFrame) -> pl.DataFrame:
def get_annuaire_data(siret: str) -> dict: def get_annuaire_data(siret: str) -> dict:
url = f"https://recherche-entreprises.api.gouv.fr/search?q={siret}" url = f"https://recherche-entreprises.api.gouv.fr/search?q={siret}"
response = get(url) try:
return response.json()["results"][0] response = get(url).raise_for_status()
response = response.json()["results"][0]
except (HTTPError, IndexError):
response = None
logger.warning("Could not fetch data from recherche-entreprises.api.")
return response
def get_decp_data() -> pl.DataFrame: def get_decp_data() -> pl.DataFrame: