feat: Mise en place du projet
This commit is contained in:
parent
10bc230e2e
commit
9b13a144e0
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
tmp
|
tmp
|
||||||
.env
|
.env
|
||||||
|
initdb/*.csv
|
||||||
|
30
README.md
30
README.md
@ -1,4 +1,4 @@
|
|||||||
# Data Project
|
# Project Open Data
|
||||||
|
|
||||||
Création d'une API unifié pour accéder à l'ensemble des données dont P4Pillon a besoin.
|
Création d'une API unifié pour accéder à l'ensemble des données dont P4Pillon a besoin.
|
||||||
|
|
||||||
@ -26,23 +26,25 @@ Il y a 2 posibilités pour récupérer les données de l'ensemble des entreprise
|
|||||||
- depuis [des fichiers](https://www.data.gouv.fr/fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/)
|
- depuis [des fichiers](https://www.data.gouv.fr/fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/)
|
||||||
|
|
||||||
|
|
||||||
## Script
|
|
||||||
|
|
||||||
Nous mettons à disposition des scripts d'import des données de l'Open Data.
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run install # Install les dépendances du projet
|
|
||||||
npm run download # Télécharge toutes les données
|
|
||||||
npm run transform # Transforme les données téléchargés dans un format que postgres pourra intégrer
|
|
||||||
```
|
|
||||||
|
|
||||||
## Composants logiciels du projet
|
## Composants logiciels du projet
|
||||||
|
|
||||||
- Base de données : [PostgreSQL](https://www.postgresql.org/)
|
- Base de données : [PostgreSQL](https://www.postgresql.org/)
|
||||||
- API : [PostgREST](https://postgrest.org/) ([Documentation](https://postgrest.org/en/stable/explanations/install.html#docker))
|
- API : [PostgREST](https://postgrest.org/) ([Documentation](https://postgrest.org/en/stable/explanations/install.html#docker))
|
||||||
- UI : [Swagger UI](https://swagger.io/tools/swagger-ui/)
|
- UI : [Swagger UI](https://swagger.io/tools/swagger-ui/)
|
||||||
|
- Virtualisation : [Docker](https://docs.docker.com/)
|
||||||
- Orchestrateur : [Docker Compose](https://docs.docker.com/compose/)
|
- Orchestrateur : [Docker Compose](https://docs.docker.com/compose/)
|
||||||
|
|
||||||
|
|
||||||
|
## Script
|
||||||
|
|
||||||
|
Un script permet d'initialiser le projet en téléchargeant les dépendences, les données de l'Open Data ainsi que de transformer ses données en fichiers CSV.
|
||||||
|
|
||||||
|
Il faut avoir Docker d'installé et executer cette commande :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash build.sh
|
||||||
|
```
|
||||||
|
|
||||||
### Docker Compose
|
### Docker Compose
|
||||||
|
|
||||||
Nous utilisons Docker Compose pour la mise en place des différents services.
|
Nous utilisons Docker Compose pour la mise en place des différents services.
|
||||||
@ -53,16 +55,16 @@ La configuration se fait à l'aide d'un fichier `.env`, vous devez modifier les
|
|||||||
|
|
||||||
Voici quelques commandes possibles :
|
Voici quelques commandes possibles :
|
||||||
|
|
||||||
```
|
```bash
|
||||||
docker compose up -d # Création des conteneurs
|
docker compose up -d # Création des conteneurs
|
||||||
docker compose down -v # Suppresion des conteneurs ainsi que des données
|
docker compose down -v # Suppresion des conteneurs ainsi que des données
|
||||||
```
|
```
|
||||||
|
|
||||||
### PostgreSQL
|
### PostgreSQL
|
||||||
|
|
||||||
Nous utilisons la fonction
|
La fonction `COPY` est utilisé dans les fichiers SQL du dossier `./initdb` permettant d'importer les données d'un fichier CSV dans une base de données.
|
||||||
|
|
||||||
### PostgREST
|
### PostgREST
|
||||||
|
|
||||||
Pour la configuration : https://postgrest.org/en/latest/configuration.html#environment-variables
|
Pour la configuration : https://postgrest.org/en/latest/configuration.html#environment-variables
|
||||||
https://postgrest.org/en/stable/references/api/tables_views.html#horizontal-filtering-rows
|
Pour requêter des données : https://postgrest.org/en/stable/references/api/tables_views.html#horizontal-filtering-rows
|
||||||
|
25
build.sh
Normal file
25
build.sh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Commande de base avec Docker
|
||||||
|
npm="docker run -it --rm --user $(id -u):$(id -g) -v $PWD:/home/node/app -w /home/node/app node:lts-alpine npm config set update-notifier false && npm"
|
||||||
|
ash="docker run -it --rm --user $(id -u):$(id -g) -v $PWD:/home/node/app -w /home/node/app apteno/alpine-jq ash"
|
||||||
|
|
||||||
|
Suppression des fichiers
|
||||||
|
echo $'\n\n#\n# Suppression des fichiers 🧹\n#\n'
|
||||||
|
eval $npm run clean
|
||||||
|
|
||||||
|
# Installation des dépendances
|
||||||
|
echo $'\n\n#\n# Installation des dépendances ⬇️\n#\n'
|
||||||
|
eval $npm install
|
||||||
|
|
||||||
|
# Téléchargement des données
|
||||||
|
echo $'\n\n#\n# Téléchargement des données 💡\n#\n'
|
||||||
|
eval $npm run download
|
||||||
|
eval $ash ./scripts/download.sh
|
||||||
|
|
||||||
|
# Transformation des données
|
||||||
|
echo $'\n\n#\n# Transformation des données 🏗️\n#\n'
|
||||||
|
eval $npm run transform
|
||||||
|
eval $ash ./scripts/transform.sh
|
||||||
|
|
||||||
|
echo $'\n\n#\n# Le projet est prêt à être lancé avec Docker 🚀\n#\n'
|
29
docker-compose.local.yml
Normal file
29
docker-compose.local.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
front-end:
|
||||||
|
back-end:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
networks:
|
||||||
|
- back-end
|
||||||
|
|
||||||
|
postgrest:
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
networks:
|
||||||
|
- back-end
|
||||||
|
|
||||||
|
swagger:
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
networks:
|
||||||
|
- front-end
|
||||||
|
- back-end
|
19
docker-compose.traefik.yml
Normal file
19
docker-compose.traefik.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: ${TRAEFIK_NETWORK_NAME:-traefik}
|
||||||
|
external: true
|
||||||
|
opendata:
|
||||||
|
name: ${OPENDATA_NETWORK_NAME:-opendata}
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgrest:
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
swagger:
|
||||||
|
networks:
|
||||||
|
- traefik
|
@ -8,47 +8,10 @@ volumes:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
postgrest:
|
|
||||||
container_name: ${POSTGREST_CONTAINER_NAME:-postgrest}
|
|
||||||
image: ${POSTGREST_IMAGE:-postgrest/postgrest:v12.0.0}
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
# Available environment variables documented here:
|
|
||||||
# https://postgrest.org/en/latest/configuration.html#environment-variables
|
|
||||||
environment:
|
|
||||||
# The standard connection URI format, documented at
|
|
||||||
# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
|
||||||
PGRST_DB_URI: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:?err}
|
|
||||||
# The name of which database schema to expose to REST clients
|
|
||||||
PGRST_DB_SCHEMA: ${DB_SCHEMA}
|
|
||||||
# The database role to use when no client authentication is provided
|
|
||||||
PGRST_DB_ANON_ROLE: ${DB_ANON_ROLE}
|
|
||||||
# Overrides the base URL used within the OpenAPI self-documentation hosted at the API root path
|
|
||||||
PGRST_OPENAPI_SERVER_PROXY_URI: http://localhost:3000
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
networks:
|
|
||||||
- back-end
|
|
||||||
|
|
||||||
postgrest-demo:
|
|
||||||
container_name: postgrest-demo
|
|
||||||
image: nginx:mainline-alpine
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
volumes:
|
|
||||||
# anything in html directory is hosted via nginx
|
|
||||||
- "./html:/usr/share/nginx/html"
|
|
||||||
restart: always
|
|
||||||
networks:
|
|
||||||
- back-end
|
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
container_name: ${POSTGRES_CONTAINER_NAME:-postgres}
|
container_name: ${POSTGRES_CONTAINER_NAME:-postgres}
|
||||||
image: ${POSTGRES_IMAGE:-postgres:16.1-alpine}
|
image: ${POSTGRES_IMAGE:-postgres:16.1-alpine}
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: ${POSTGRES_USER:?err}
|
POSTGRES_USER: ${POSTGRES_USER:?err}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?err}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?err}
|
||||||
@ -60,21 +23,25 @@ services:
|
|||||||
- "./initdb:/docker-entrypoint-initdb.d"
|
- "./initdb:/docker-entrypoint-initdb.d"
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
networks:
|
|
||||||
- back-end
|
postgrest:
|
||||||
|
container_name: ${POSTGREST_CONTAINER_NAME:-postgrest}
|
||||||
|
image: ${POSTGREST_IMAGE:-postgrest/postgrest:v12.0.0}
|
||||||
|
restart: always
|
||||||
|
# https://postgrest.org/en/latest/configuration.html#environment-variables
|
||||||
|
environment:
|
||||||
|
PGRST_DB_URI: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:?err}
|
||||||
|
PGRST_DB_SCHEMA: ${DB_SCHEMA}
|
||||||
|
PGRST_DB_ANON_ROLE: ${DB_ANON_ROLE}
|
||||||
|
PGRST_OPENAPI_SERVER_PROXY_URI: ${POSTGREST_URL:-http://localhost:3000}
|
||||||
|
# https://postgrest.org/en/stable/references/configuration.html#db-max-rows
|
||||||
|
PGRST_DB_MAX_ROWS: ${PGRST_DB_MAX_ROWS:-100}
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
|
||||||
swagger:
|
swagger:
|
||||||
container_name: ${SWAGGER_CONTAINER_NAME:-swagger}
|
container_name: ${SWAGGER_CONTAINER_NAME:-swagger}
|
||||||
image: ${SWAGGER_IMAGE:-swaggerapi/swagger-ui:v5.10.3}
|
image: ${SWAGGER_IMAGE:-swaggerapi/swagger-ui:v5.11.0}
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
environment:
|
environment:
|
||||||
API_URL: http://localhost:3000/
|
API_URL: ${POSTGREST_URL:-http://localhost:3000/}
|
||||||
networks:
|
|
||||||
- front-end
|
|
||||||
- back-end
|
|
||||||
|
|
||||||
networks:
|
|
||||||
front-end:
|
|
||||||
back-end:
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
body {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
11
html/css/pure-min.css
vendored
11
html/css/pure-min.css
vendored
File diff suppressed because one or more lines are too long
@ -1,43 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
|
|
||||||
<!-- css -->
|
|
||||||
<link rel="stylesheet" href="css/pure-min.css">
|
|
||||||
<link rel="stylesheet" href="css/app.css">
|
|
||||||
|
|
||||||
<!-- javascript -->
|
|
||||||
<script src="js/app.js"></script>
|
|
||||||
|
|
||||||
<title>World Database</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="pure-g">
|
|
||||||
<div class="pure-u-1-8"></div>
|
|
||||||
<div class="pure-u-3-4">
|
|
||||||
<h1>World Database</h1>
|
|
||||||
<form class="pure-form" onsubmit="event.preventDefault(); app.searchClick()">
|
|
||||||
<fieldset>
|
|
||||||
<input id="city-input" type="text" placeholder="City" required>
|
|
||||||
<input type="submit" class="pure-button pure-button-primary" value="Search">
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<table class="pure-table pure-table-bordered pure-table-striped hidden" id="results-table">
|
|
||||||
<thead>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>District</th>
|
|
||||||
<th>Country</th>
|
|
||||||
<th>Population</th>
|
|
||||||
</thead>
|
|
||||||
<tbody id="results-table-body">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="pure-u-1-8"></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,53 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var CITY_QUERY_URL_PREFIX = 'http://localhost:3000/city?name=ilike.'
|
|
||||||
|
|
||||||
var app = {};
|
|
||||||
|
|
||||||
app.addResultRows = function (rows) {
|
|
||||||
var rowsString = '';
|
|
||||||
var rowsLength = rows.length;
|
|
||||||
|
|
||||||
if (rowsLength > 0) {
|
|
||||||
for (var i = 0; i < rowsLength; i++) {
|
|
||||||
rowsString += app.buildResultRowString(rows[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rowsString = '<tr><td colspan="4">Results not found</td></tr>';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('results-table-body').innerHTML = rowsString;
|
|
||||||
app.showElement('results-table');
|
|
||||||
}
|
|
||||||
|
|
||||||
app.buildResultRowString = function (row) {
|
|
||||||
return '<tr>' +
|
|
||||||
'<td>' + row.name + '</td>' +
|
|
||||||
'<td>' + row.district + '</td>' +
|
|
||||||
'<td>' + row.countrycode + '</td>' +
|
|
||||||
'<td>' + row.population + '</td>' +
|
|
||||||
'</tr>';
|
|
||||||
}
|
|
||||||
|
|
||||||
app.showElement = function (id) {
|
|
||||||
document.getElementById(id).classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
app.queryCity = function (cityName) {
|
|
||||||
var queryURL = CITY_QUERY_URL_PREFIX + '*' + cityName + '*';
|
|
||||||
|
|
||||||
fetch(queryURL)
|
|
||||||
.then(function(response) {
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(function (j) {
|
|
||||||
console.log(j);
|
|
||||||
app.addResultRows(j);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
app.searchClick = function () {
|
|
||||||
var city = document.getElementById('city-input').value;
|
|
||||||
|
|
||||||
app.queryCity(city);
|
|
||||||
}
|
|
@ -1,13 +1,5 @@
|
|||||||
--
|
|
||||||
-- PostgreSQL port of the MySQL "World" database.
|
|
||||||
--
|
|
||||||
-- The sample data used in the world database is Copyrighted.
|
|
||||||
-- Statistics Finland, http://www.stat.fi/worldinfigures
|
|
||||||
--
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
SET client_encoding = 'LATIN1';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS finess (
|
CREATE TABLE IF NOT EXISTS finess (
|
||||||
nofinesset VARCHAR(255),
|
nofinesset VARCHAR(255),
|
||||||
nofinessej VARCHAR(255),
|
nofinessej VARCHAR(255),
|
||||||
@ -43,3 +35,12 @@ CREATE TABLE IF NOT EXISTS finess (
|
|||||||
coordxet FLOAT DEFAULT 0,
|
coordxet FLOAT DEFAULT 0,
|
||||||
coordyet FLOAT DEFAULT 0
|
coordyet FLOAT DEFAULT 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
COPY finess FROM '/docker-entrypoint-initdb.d/finess.csv' DELIMITER ';' CSV HEADER;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY finess
|
||||||
|
ADD CONSTRAINT finess_pkey PRIMARY KEY (nofinesset);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
ANALYZE finess;
|
18
initdb/3_decoupage_administratif.sql
Normal file
18
initdb/3_decoupage_administratif.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS regions (
|
||||||
|
code VARCHAR(3),
|
||||||
|
chefLieu VARCHAR(5),
|
||||||
|
nom VARCHAR(255),
|
||||||
|
typeLiaison VARCHAR(255),
|
||||||
|
region_zone VARCHAR(255)
|
||||||
|
);
|
||||||
|
|
||||||
|
COPY regions FROM '/docker-entrypoint-initdb.d/regions.csv' DELIMITER ',' CSV;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY regions
|
||||||
|
ADD CONSTRAINT regions_pkey PRIMARY KEY (code);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
ANALYZE regions;
|
77
initdb/4_sirene.sql
Normal file
77
initdb/4_sirene.sql
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS sirene_stock_etablissement (
|
||||||
|
siren VARCHAR(9),
|
||||||
|
nic VARCHAR(5),
|
||||||
|
siret VARCHAR(14),
|
||||||
|
statutDiffusionEtablissement VARCHAR(1),
|
||||||
|
dateCreationEtablissement VARCHAR(19),
|
||||||
|
trancheEffectifsEtablissement VARCHAR(2),
|
||||||
|
anneeEffectifsEtablissement VARCHAR(19),
|
||||||
|
activitePrincipaleRegistreMetiersEtablissement VARCHAR(6),
|
||||||
|
dateDernierTraitementEtablissement VARCHAR(19),
|
||||||
|
etablissementSiege VARCHAR(5),
|
||||||
|
nombrePeriodesEtablissement NUMERIC(2),
|
||||||
|
complementAdresseEtablissement VARCHAR(38),
|
||||||
|
numeroVoieEtablissement VARCHAR(4),
|
||||||
|
indiceRepetitionEtablissement VARCHAR(4),
|
||||||
|
typeVoieEtablissement VARCHAR(4),
|
||||||
|
libelleVoieEtablissement VARCHAR(100),
|
||||||
|
codePostalEtablissement VARCHAR(5),
|
||||||
|
libelleCommuneEtablissement VARCHAR(100),
|
||||||
|
libelleCommuneEtrangerEtablissement VARCHAR(100),
|
||||||
|
distributionSpecialeEtablissement VARCHAR(26),
|
||||||
|
codeCommuneEtablissement VARCHAR(5),
|
||||||
|
codeCedexEtablissement VARCHAR(9),
|
||||||
|
libelleCedexEtablissement VARCHAR(100),
|
||||||
|
codePaysEtrangerEtablissement VARCHAR(5),
|
||||||
|
libellePaysEtrangerEtablissement VARCHAR(100),
|
||||||
|
complementAdresse2Etablissement VARCHAR(38),
|
||||||
|
numeroVoie2Etablissement VARCHAR(4),
|
||||||
|
indiceRepetition2Etablissement VARCHAR(4),
|
||||||
|
typeVoie2Etablissement VARCHAR(4),
|
||||||
|
libelleVoie2Etablissement VARCHAR(100),
|
||||||
|
codePostal2Etablissement VARCHAR(5),
|
||||||
|
libelleCommune2Etablissement VARCHAR(100),
|
||||||
|
libelleCommuneEtranger2Etablissement VARCHAR(100),
|
||||||
|
distributionSpeciale2Etablissement VARCHAR(26),
|
||||||
|
codeCommune2Etablissement VARCHAR(5),
|
||||||
|
codeCedex2Etablissement VARCHAR(9),
|
||||||
|
libelleCedex2Etablissement VARCHAR(100),
|
||||||
|
codePaysEtranger2Etablissement VARCHAR(5),
|
||||||
|
libellePaysEtranger2Etablissement VARCHAR(100),
|
||||||
|
dateDebut VARCHAR(19),
|
||||||
|
etatAdministratifEtablissement VARCHAR(1),
|
||||||
|
enseigne1Etablissement VARCHAR(50),
|
||||||
|
enseigne2Etablissement VARCHAR(50),
|
||||||
|
enseigne3Etablissement VARCHAR(50),
|
||||||
|
denominationUsuelleEtablissement VARCHAR(100),
|
||||||
|
activitePrincipaleEtablissement VARCHAR(6),
|
||||||
|
nomenclatureActivitePrincipaleEtablissement VARCHAR(8),
|
||||||
|
caractereEmployeurEtablissement VARCHAR(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
COPY sirene_stock_etablissement FROM '/docker-entrypoint-initdb.d/StockEtablissement_utf8.csv' DELIMITER ',' CSV HEADER;
|
||||||
|
|
||||||
|
-- Index sur la colonne siren
|
||||||
|
CREATE INDEX idx_siren ON sirene_stock_etablissement (siren);
|
||||||
|
|
||||||
|
-- Index sur la colonne siret
|
||||||
|
CREATE INDEX idx_siret ON sirene_stock_etablissement (siret);
|
||||||
|
|
||||||
|
-- Index sur la colonne codePostalEtablissement
|
||||||
|
CREATE INDEX idx_codePostalEtablissement ON sirene_stock_etablissement (codePostalEtablissement);
|
||||||
|
|
||||||
|
-- Index sur la colonne libelleCommuneEtablissement
|
||||||
|
CREATE INDEX idx_libelleCommuneEtablissement ON sirene_stock_etablissement (libelleCommuneEtablissement);
|
||||||
|
|
||||||
|
-- Index sur la colonne activitePrincipaleEtablissement
|
||||||
|
CREATE INDEX idx_activitePrincipaleEtablissement ON sirene_stock_etablissement (activitePrincipaleEtablissement);
|
||||||
|
|
||||||
|
-- ALTER TABLE ONLY sirene_stock_etablissement
|
||||||
|
-- ADD CONSTRAINT sirene_stock_etablissement_pkey PRIMARY KEY (siren);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
ANALYZE sirene_stock_etablissement;
|
@ -1,5 +1,10 @@
|
|||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm ./node_modules -rf && rm ./tmp -rf && rm ./initdb/*.csv -rf",
|
||||||
|
"download": "node scripts/download.js",
|
||||||
|
"transform": "node scripts/transform.js"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@etalab/decoupage-administratif": "^3.1.1",
|
"@etalab/decoupage-administratif": "^3.1.1",
|
||||||
"csv-parse": "^5.5.3",
|
"csv-parse": "^5.5.3",
|
||||||
|
4
scripts/download.sh
Executable file
4
scripts/download.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/ash
|
||||||
|
|
||||||
|
echo $'- Téléchargement des données INPI'
|
||||||
|
wget https://www.data.gouv.fr/fr/datasets/r/0651fb76-bcf3-4f6a-a38d-bc04fa708576 -O ./tmp/StockEtablissement_utf8.zip
|
@ -1,129 +1,9 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import readline from 'readline';
|
import readline from 'readline';
|
||||||
import pg from 'pg';
|
import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile, customSplit } from './functions.js'
|
||||||
import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile } from './functions.js'
|
|
||||||
import { transformToGPS } from './gps.js'
|
import { transformToGPS } from './gps.js'
|
||||||
|
|
||||||
const { Pool } = pg
|
const columns = [
|
||||||
|
|
||||||
export const downloadFiness = async () => {
|
|
||||||
const MAIN_URL = 'https://www.data.gouv.fr/api/1/datasets/finess-extraction-du-fichier-des-etablissements/'
|
|
||||||
const FILENAME = './tmp/finess.csv'
|
|
||||||
|
|
||||||
const data = await downloadJSON(MAIN_URL);
|
|
||||||
const finessUrl = data.resources.find(r => r.type === "main" && r.title.includes('géolocalisés'))?.url
|
|
||||||
|
|
||||||
downloadAndSaveFile(finessUrl, FILENAME)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const transformFiness = async () => {
|
|
||||||
const fichierEntree = './tmp/finess.csv';
|
|
||||||
const fichierStructures = './tmp/finess_structureet.csv';
|
|
||||||
const fichierGeolocalisation = './tmp/finess_geolocalisation.csv';
|
|
||||||
const conditionFiltre = (ligne) => ligne.includes('structureet');
|
|
||||||
|
|
||||||
await filtrerEtEnregistrerLignes(fichierEntree, fichierStructures, fichierGeolocalisation, conditionFiltre);
|
|
||||||
await fusionnerCoordonneesGPSStructures(fichierStructures, fichierGeolocalisation, fichierEntree);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const importFiness = async () => {
|
|
||||||
// Exemple d'utilisation avec le nom du fichier CSV
|
|
||||||
const fichierEntree = './tmp/finess.csv';
|
|
||||||
insererDonneesPostgres(fichierEntree);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour fusionner les coordonnées GPS dans le fichier CSV de structures
|
|
||||||
export async function fusionnerCoordonneesGPSStructures(fichierStructures, fichierCoordonnees, fichierSortie) {
|
|
||||||
try {
|
|
||||||
// Créer un flux de lecture pour le fichier de coordonnées Lambert 93
|
|
||||||
const lecteurCoordonnees = readline.createInterface({
|
|
||||||
input: fs.createReadStream(fichierCoordonnees),
|
|
||||||
crlfDelay: Infinity
|
|
||||||
});
|
|
||||||
|
|
||||||
// Créer un dictionnaire pour stocker les coordonnées Lambert 93 par structureid
|
|
||||||
const coordonnees = {};
|
|
||||||
|
|
||||||
// Fonction pour traiter chaque ligne du fichier de coordonnées Lambert 93
|
|
||||||
const traiterLigneCoordonnees = (ligne) => {
|
|
||||||
// exemple de ligne
|
|
||||||
// geolocalisation;970300802;317351.6;571220.2;2,ATLASANTE,100,IGN,BD_ADRESSE,V2.2,UTM_N22;2024-01-08
|
|
||||||
const valeurs = ligne.split(';');
|
|
||||||
const structureid = valeurs[1];
|
|
||||||
const coordX = parseFloat(valeurs[2]);
|
|
||||||
const coordY = parseFloat(valeurs[3]);
|
|
||||||
const system = valeurs[4]
|
|
||||||
coordonnees[structureid] = { system, coordX, coordY };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lire chaque ligne du fichier de coordonnées Lambert 93
|
|
||||||
for await (const ligne of lecteurCoordonnees) {
|
|
||||||
traiterLigneCoordonnees(ligne);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Créer un flux de lecture pour le fichier de structures
|
|
||||||
const lecteurStructures = readline.createInterface({
|
|
||||||
input: fs.createReadStream(fichierStructures),
|
|
||||||
crlfDelay: Infinity
|
|
||||||
});
|
|
||||||
|
|
||||||
// Créer un flux d'écriture vers le fichier de sortie
|
|
||||||
const fichierSortieStream = fs.createWriteStream(fichierSortie);
|
|
||||||
|
|
||||||
// Écrire l'entête dans le fichier de sortie
|
|
||||||
// fichierSortieStream.write('structureid,nofinesset,coordxet,coordyet,latitude,longitude\n');
|
|
||||||
|
|
||||||
// Fonction pour traiter chaque ligne du fichier de structures
|
|
||||||
const traiterLigneStructures = (ligne) => {
|
|
||||||
const valeurs = ligne.split(';');
|
|
||||||
const structureid = valeurs[1];
|
|
||||||
|
|
||||||
// Vérifier si des coordonnées Lambert 93 existent pour cette structureid
|
|
||||||
if (coordonnees.hasOwnProperty(structureid)) {
|
|
||||||
const { system, coordX, coordY } = coordonnees[structureid];
|
|
||||||
const coordonneesGPS = transformToGPS(system, coordX, coordY);
|
|
||||||
|
|
||||||
if (coordonneesGPS) {
|
|
||||||
// Écrire les valeurs dans le fichier de sortie
|
|
||||||
fichierSortieStream.write(`${ligne};${coordonneesGPS.latitude};${coordonneesGPS.longitude}\n`);
|
|
||||||
} else {
|
|
||||||
// Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
|
|
||||||
fichierSortieStream.write(`${ligne};;\n`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
|
|
||||||
fichierSortieStream.write(`${ligne};;\n`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lire chaque ligne du fichier de structures
|
|
||||||
for await (const ligne of lecteurStructures) {
|
|
||||||
traiterLigneStructures(ligne);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Fusion des coordonnées GPS dans le fichier de structures terminée.');
|
|
||||||
|
|
||||||
} catch (erreur) {
|
|
||||||
console.error(`Erreur lors de la fusion des coordonnées GPS : ${erreur.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour lire le fichier CSV et insérer les données dans PostgreSQL
|
|
||||||
export async function insererDonneesPostgres(nomFichierCSV) {
|
|
||||||
const envVariables = loadEnvFile()
|
|
||||||
|
|
||||||
const pool = new Pool({
|
|
||||||
user: envVariables.POSTGRES_USER,
|
|
||||||
host: 'localhost',
|
|
||||||
database: envVariables.POSTGRES_DB,
|
|
||||||
password: envVariables.POSTGRES_PASSWORD,
|
|
||||||
port: 5432,
|
|
||||||
max: 10, // Nombre maximum de connexions dans le pool
|
|
||||||
idleTimeoutMillis: 30000, // Délai d'attente maximum pour une connexion avant d'être libérée
|
|
||||||
});
|
|
||||||
const client = await pool.connect();
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
'nofinesset',
|
'nofinesset',
|
||||||
'nofinessej',
|
'nofinessej',
|
||||||
'rs',
|
'rs',
|
||||||
@ -157,106 +37,161 @@ export async function insererDonneesPostgres(nomFichierCSV) {
|
|||||||
'numuai',
|
'numuai',
|
||||||
'coordxet',
|
'coordxet',
|
||||||
'coordyet'
|
'coordyet'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Fonction pour insérer une ligne dans la base de données
|
export const downloadFiness = async () => {
|
||||||
async function insertRow(data) {
|
const MAIN_URL = 'https://www.data.gouv.fr/api/1/datasets/finess-extraction-du-fichier-des-etablissements/'
|
||||||
const query = {
|
const FILENAME = './tmp/finess.csv'
|
||||||
text: `INSERT INTO finess (${columns.join(', ')}) VALUES (${columns.map((col, index) => `$${index + 1}`).join(', ')})`,
|
|
||||||
values: data,
|
|
||||||
};
|
|
||||||
|
|
||||||
const client = await pool.connect();
|
const data = await downloadJSON(MAIN_URL);
|
||||||
|
const finessUrl = data.resources.find(r => r.type === "main" && r.title.includes('géolocalisés'))?.url
|
||||||
|
|
||||||
|
downloadAndSaveFile(finessUrl, FILENAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const transformFiness = async () => {
|
||||||
|
const fichierEntree = './tmp/finess.csv';
|
||||||
|
const fichierStructures = './tmp/finess_structureet.csv';
|
||||||
|
const fichierGeolocalisation = './tmp/finess_geolocalisation.csv';
|
||||||
|
const fichierSortie = './initdb/finess.csv'
|
||||||
|
const conditionFiltre = (ligne) => ligne.includes('structureet');
|
||||||
|
|
||||||
|
await filtrerEtEnregistrerLignes(fichierEntree, fichierStructures, fichierGeolocalisation, conditionFiltre);
|
||||||
|
await fusionnerCoordonneesGPSStructures(fichierStructures, fichierGeolocalisation, fichierSortie);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour fusionner les coordonnées GPS dans le fichier CSV de structures
|
||||||
|
export async function fusionnerCoordonneesGPSStructures(fichierStructures, fichierCoordonnees, fichierSortie) {
|
||||||
try {
|
try {
|
||||||
await client.query(query);
|
// Créer un flux de lecture pour le fichier de coordonnées
|
||||||
} catch (error) {
|
const lecteurCoordonnees = readline.createInterface({
|
||||||
console.log(data.join(', '))
|
input: fs.createReadStream(fichierCoordonnees),
|
||||||
console.error('Erreur lors de l\'insertion de la ligne:', error.message || error);
|
crlfDelay: Infinity
|
||||||
} finally {
|
|
||||||
client.release(); // Libérer la connexion du pool
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour lire le fichier ligne par ligne et appeler la fonction d'insertion
|
|
||||||
async function processFile(filePath) {
|
|
||||||
const fileStream = fs.createReadStream(filePath);
|
|
||||||
const rl = readline.createInterface({
|
|
||||||
input: fileStream,
|
|
||||||
crlfDelay: Infinity,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for await (const [index, line] of rl) {
|
// Créer un dictionnaire pour stocker les coordonnées par structureid
|
||||||
// Supposons que les données dans le fichier soient séparées par des virgules (à ajuster selon votre format)
|
const coordonnees = {};
|
||||||
let data = line.split(';');
|
|
||||||
data.shift();
|
|
||||||
if (data[27] === '') data[27] = null
|
|
||||||
if (data[28] === '') data[28] = null
|
|
||||||
if (data[29] === '') data[29] = null
|
|
||||||
|
|
||||||
// Appeler la fonction d'insertion avec la ligne de données
|
// Fonction pour traiter chaque ligne du fichier de coordonnées
|
||||||
await insertRow(data);
|
const traiterLigneCoordonnees = (ligne) => {
|
||||||
console.log(index)
|
// exemple de ligne
|
||||||
|
// geolocalisation;970300802;317351.6;571220.2;2,ATLASANTE,100,IGN,BD_ADRESSE,V2.2,UTM_N22;2024-01-08
|
||||||
|
const valeurs = ligne.split(';');
|
||||||
|
const structureid = valeurs[1];
|
||||||
|
const coordX = parseFloat(valeurs[2]);
|
||||||
|
const coordY = parseFloat(valeurs[3]);
|
||||||
|
const system = valeurs[4]
|
||||||
|
coordonnees[structureid] = { system, coordX, coordY };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lire chaque ligne du fichier de coordonnées
|
||||||
|
for await (const ligne of lecteurCoordonnees) {
|
||||||
|
traiterLigneCoordonnees(ligne);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fermer le pool de connexions à la base de données à la fin du traitement
|
// Créer un flux de lecture pour le fichier de structures
|
||||||
await pool.end();
|
const lecteurStructures = readline.createInterface({
|
||||||
|
input: fs.createReadStream(fichierStructures),
|
||||||
|
crlfDelay: Infinity
|
||||||
|
});
|
||||||
|
|
||||||
|
// Créer un flux d'écriture vers le fichier de sortie
|
||||||
|
const fichierSortieStream = fs.createWriteStream(fichierSortie);
|
||||||
|
|
||||||
|
// Création de l'entête d'insertion
|
||||||
|
// fichierSortieStream.write('INSERT INTO finess (' + columns.join(', ') + ') VALUES\n');
|
||||||
|
fichierSortieStream.write(columns.join(";") + '\n');
|
||||||
|
|
||||||
|
const ecrireLigneStructure = (ligne, isFirst) => {
|
||||||
|
let dataArray = ligne.split(';');
|
||||||
|
|
||||||
|
// Fix le nom d'une association contenant un ; ... "ASSO; LA RELÈVE"
|
||||||
|
if (dataArray.length > 34) {
|
||||||
|
dataArray = customSplit(ligne, ';')
|
||||||
|
dataArray = dataArray.map(value => value.replaceAll(";", "%3B"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// await creerTableFINESS(client);
|
dataArray.shift(); // Suppression du premier champs inutil
|
||||||
await processFile(nomFichierCSV)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour créer la table FINESS dans PostgreSQL
|
// const defaultValue = (value) => (value === null || value === '' ? 'NULL' : `'${value.replaceAll("'", "''")}'`)
|
||||||
export async function creerTableFINESS(client) {
|
// const typedData = {
|
||||||
try {
|
// nofinesset: defaultValue(dataArray[0]),
|
||||||
// Requête SQL de création de table
|
// nofinessej: defaultValue(dataArray[1]),
|
||||||
const requeteCreationTable = `
|
// rs: defaultValue(dataArray[2]),
|
||||||
CREATE TABLE IF NOT EXISTS finess (
|
// rslongue: defaultValue(dataArray[3]),
|
||||||
nofinesset VARCHAR(255),
|
// complrs: defaultValue(dataArray[4]),
|
||||||
nofinessej VARCHAR(255),
|
// compldistrib: defaultValue(dataArray[5]),
|
||||||
rs VARCHAR(255),
|
// numvoie: defaultValue(dataArray[6]),
|
||||||
rslongue VARCHAR(255),
|
// typvoie: defaultValue(dataArray[7]),
|
||||||
complrs VARCHAR(255),
|
// voie: defaultValue(dataArray[8]),
|
||||||
compldistrib VARCHAR(255),
|
// compvoie: defaultValue(dataArray[9]),
|
||||||
numvoie VARCHAR(255),
|
// lieuditbp: defaultValue(dataArray[10]),
|
||||||
typvoie VARCHAR(255),
|
// commune: defaultValue(dataArray[11]),
|
||||||
voie VARCHAR(255),
|
// departement: defaultValue(dataArray[12]),
|
||||||
compvoie VARCHAR(255),
|
// libdepartement: defaultValue(dataArray[13]),
|
||||||
lieuditbp VARCHAR(255),
|
// ligneacheminement: defaultValue(dataArray[14]),
|
||||||
commune VARCHAR(255),
|
// telephone: defaultValue(dataArray[15]),
|
||||||
departement VARCHAR(255),
|
// telecopie: defaultValue(dataArray[16]),
|
||||||
libdepartement VARCHAR(255),
|
// categetab: defaultValue(dataArray[17]),
|
||||||
ligneacheminement VARCHAR(255),
|
// libcategetab: defaultValue(dataArray[18]),
|
||||||
telephone VARCHAR(255),
|
// categagretab: defaultValue(dataArray[19]),
|
||||||
telecopie VARCHAR(255),
|
// libcategagretab: defaultValue(dataArray[20]),
|
||||||
categetab VARCHAR(255),
|
// siret: defaultValue(dataArray[21]),
|
||||||
libcategetab VARCHAR(255),
|
// codeape: defaultValue(dataArray[22]),
|
||||||
categagretab VARCHAR(255),
|
// codemft: defaultValue(dataArray[23]),
|
||||||
libcategagretab VARCHAR(255),
|
// libmft: defaultValue(dataArray[24]),
|
||||||
siret VARCHAR(255),
|
// codesph: defaultValue(dataArray[25]),
|
||||||
codeape VARCHAR(255),
|
// libsph: defaultValue(dataArray[26]),
|
||||||
codemft VARCHAR(255),
|
// dateouv: defaultValue((new Date(dataArray[27] || '1900-01-01')).toISOString().split('T')[0]), // Utilise la date par défaut si la date est vide
|
||||||
libmft VARCHAR(255),
|
// dateautor: defaultValue((new Date(dataArray[28] || '1900-01-01')).toISOString().split('T')[0]),
|
||||||
codesph VARCHAR(255),
|
// datemaj: defaultValue((new Date(dataArray[29] || '1900-01-01')).toISOString().split('T')[0]),
|
||||||
libsph VARCHAR(255),
|
// numuai: defaultValue(dataArray[30]),
|
||||||
dateouv DATE DEFAULT '1900-01-01',
|
// coordxet: dataArray[31] ? parseFloat(dataArray[31]) : 'NULL',
|
||||||
dateautor DATE DEFAULT '1900-01-01',
|
// coordyet: dataArray[32] ? parseFloat(dataArray[32]) : 'NULL',
|
||||||
datemaj DATE DEFAULT '1900-01-01',
|
// };
|
||||||
numuai VARCHAR(255),
|
// if (typedData.nofinesset === '690051545') {
|
||||||
coordxet FLOAT DEFAULT 0,
|
// console.log(dataArray[20])
|
||||||
coordyet FLOAT DEFAULT 0,
|
// }
|
||||||
PRIMARY KEY (nofinesset)
|
// const formattedData = Object.values(typedData).map((value) => (isNaN(value) ? `'${value.replaceAll("'", "''")}'` : (value === null || value === '' ? 'NULL' : value))); // Assurez-vous que les chaînes sont entourées de guillemets simples
|
||||||
);
|
// fichierSortieStream.write(`${isFirst ? '' : ',\n'} (${Object.values(typedData).join(', ')})`);
|
||||||
`;
|
// fichierSortieStream.write('INSERT INTO finess (' + columns.join(', ') + ') VALUES ' + `(${Object.values(typedData).join(', ')});\n`);
|
||||||
|
fichierSortieStream.write(`${dataArray.join(';')}\n`);
|
||||||
|
}
|
||||||
|
|
||||||
// Exécution de la requête de création de table
|
let isFirst = true
|
||||||
await client.query(requeteCreationTable);
|
// Lire chaque ligne du fichier de structures
|
||||||
|
for await (const ligne of lecteurStructures) {
|
||||||
|
const valeurs = ligne.split(';');
|
||||||
|
const structureid = valeurs[1];
|
||||||
|
|
||||||
console.log('Table FINESS créée avec succès.');
|
// Vérifier si des coordonnées existent pour cette structureid
|
||||||
|
if (coordonnees.hasOwnProperty(structureid)) {
|
||||||
|
const { system, coordX, coordY } = coordonnees[structureid];
|
||||||
|
const coordonneesGPS = transformToGPS(system, coordX, coordY);
|
||||||
|
|
||||||
|
if (coordonneesGPS) {
|
||||||
|
// Écrire les valeurs dans le fichier de sortie
|
||||||
|
ecrireLigneStructure(`${ligne};${coordonneesGPS.latitude};${coordonneesGPS.longitude}`, isFirst);
|
||||||
|
} else {
|
||||||
|
// Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
|
||||||
|
ecrireLigneStructure(`${ligne};;`, isFirst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
|
||||||
|
ecrireLigneStructure(`${ligne};;`, isFirst);
|
||||||
|
}
|
||||||
|
isFirst = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fermer la parenthèse finale et le point-virgule
|
||||||
|
// fichierSortieStream.write(';');
|
||||||
|
fichierSortieStream.end();
|
||||||
|
|
||||||
|
console.log(`Le fichier SQL a été généré : ${fichierSortie}`);
|
||||||
|
|
||||||
|
console.log('Fusion des coordonnées GPS dans le fichier de structures terminée.');
|
||||||
|
|
||||||
} catch (erreur) {
|
} catch (erreur) {
|
||||||
console.error(`Erreur lors de la création de la table : ${erreur.message}`);
|
console.error(`Erreur lors de la fusion des coordonnées GPS : ${erreur.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,29 @@ import fs from 'fs'
|
|||||||
import { writeFile, mkdir } from 'fs/promises'
|
import { writeFile, mkdir } from 'fs/promises'
|
||||||
import readline from 'readline';
|
import readline from 'readline';
|
||||||
|
|
||||||
|
export function customSplit(line, separator) {
|
||||||
|
const parts = [];
|
||||||
|
let currentPart = '';
|
||||||
|
let insideQuotes = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < line.length; i++) {
|
||||||
|
const char = line[i];
|
||||||
|
|
||||||
|
if (char === '"') {
|
||||||
|
insideQuotes = !insideQuotes;
|
||||||
|
} else if (char === separator && !insideQuotes) {
|
||||||
|
parts.push(currentPart.trim());
|
||||||
|
currentPart = '';
|
||||||
|
} else {
|
||||||
|
currentPart += char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(currentPart.trim());
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
export const loadEnvFile = () => {
|
export const loadEnvFile = () => {
|
||||||
// Charger les variables d'environnement à partir du fichier .env
|
// Charger les variables d'environnement à partir du fichier .env
|
||||||
const envPath = './.env'; // Spécifiez le chemin correct si différent
|
const envPath = './.env'; // Spécifiez le chemin correct si différent
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import { importFiness } from './helpers/finess.js'
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
importFiness()
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
10
scripts/transform.sh
Executable file
10
scripts/transform.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/ash
|
||||||
|
|
||||||
|
echo $'- Transformation des données de régions'
|
||||||
|
cat node_modules/@etalab/decoupage-administratif/data/regions.json | jq -r '.[] | [.code, .chefLieu, .nom, .typeLiaison, .zone] | @csv' > initdb/regions.csv
|
||||||
|
|
||||||
|
echo $'- Transformation des données de départements'
|
||||||
|
cat node_modules/@etalab/decoupage-administratif/data/departements.json | jq -r '.[] | [.code, .region, .chefLieu, .nom, .typeLiaison, .zone] | @csv' > initdb/departements.csv
|
||||||
|
|
||||||
|
echo $'- Extraction des données INPI'
|
||||||
|
unzip -o ./tmp/StockEtablissement_utf8.zip -d ./initdb/
|
Loading…
Reference in New Issue
Block a user