2024-12-05 18:19:11 +01:00
|
|
|
"""Organization related plugins."""
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
import requests
|
2024-12-05 15:44:30 +01:00
|
|
|
from requests.adapters import HTTPAdapter, Retry
|
2024-12-05 18:19:11 +01:00
|
|
|
|
|
|
|
|
from core.plugins.base import BaseOrganizationPlugin
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NameFromSiretOrganizationPlugin(BaseOrganizationPlugin):
|
|
|
|
|
"""
|
|
|
|
|
This plugin is used to convert the organization registration ID
|
|
|
|
|
to the proper name. For French organization the registration ID
|
|
|
|
|
is the SIRET.
|
|
|
|
|
|
|
|
|
|
This is a very specific plugin for French organizations and this
|
|
|
|
|
first implementation is very basic. It surely needs to be improved
|
|
|
|
|
later.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
_api_url = "https://recherche-entreprises.api.gouv.fr/search?q={siret}"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2025-01-30 14:21:53 +01:00
|
|
|
def get_organization_name_from_results(data, siret):
|
2024-12-05 15:44:30 +01:00
|
|
|
"""Return the organization name from the results of a SIRET search."""
|
2024-12-05 18:19:11 +01:00
|
|
|
for result in data["results"]:
|
2025-01-30 14:21:53 +01:00
|
|
|
is_commune = (
|
|
|
|
|
result.get("nature_juridique") == "7210"
|
|
|
|
|
) # INSEE code for commune
|
2024-12-05 18:19:11 +01:00
|
|
|
for organization in result["matching_etablissements"]:
|
|
|
|
|
if organization.get("siret") == siret:
|
2025-01-30 14:21:53 +01:00
|
|
|
if is_commune:
|
2024-12-05 15:44:30 +01:00
|
|
|
return organization["libelle_commune"].title()
|
|
|
|
|
|
2025-01-30 14:21:53 +01:00
|
|
|
store_signs = organization.get("liste_enseignes") or []
|
|
|
|
|
if store_signs:
|
|
|
|
|
return store_signs[0].title()
|
|
|
|
|
if name := result.get("nom_raison_sociale"):
|
|
|
|
|
return name.title()
|
2024-12-05 18:19:11 +01:00
|
|
|
|
|
|
|
|
logger.warning("No organization name found for SIRET %s", siret)
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def run_after_create(self, organization):
|
|
|
|
|
"""After creating an organization, update the organization name."""
|
|
|
|
|
if not organization.registration_id_list:
|
|
|
|
|
# No registration ID to convert...
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if organization.name not in organization.registration_id_list:
|
|
|
|
|
# The name has probably already been customized
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# In the nominal case, there is only one registration ID because
|
|
|
|
|
# the organization as been created from it.
|
2024-12-05 15:44:30 +01:00
|
|
|
try:
|
|
|
|
|
# Retry logic as the API may be rate limited
|
|
|
|
|
s = requests.Session()
|
|
|
|
|
retries = Retry(total=5, backoff_factor=0.1, status_forcelist=[429])
|
|
|
|
|
s.mount("https://", HTTPAdapter(max_retries=retries))
|
|
|
|
|
|
|
|
|
|
siret = organization.registration_id_list[0]
|
|
|
|
|
response = s.get(self._api_url.format(siret=siret), timeout=10)
|
|
|
|
|
response.raise_for_status()
|
|
|
|
|
data = response.json()
|
|
|
|
|
name = self.get_organization_name_from_results(data, siret)
|
|
|
|
|
if not name:
|
|
|
|
|
return
|
|
|
|
|
except requests.RequestException as exc:
|
|
|
|
|
logger.exception("%s: Unable to fetch organization name from SIRET", exc)
|
2024-12-05 18:19:11 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
organization.name = name
|
|
|
|
|
organization.save(update_fields=["name", "updated_at"])
|
|
|
|
|
logger.info("Organization %s name updated to %s", organization, name)
|