This commit is contained in:
Simon C 2024-01-24 16:29:09 +01:00
parent 1d0f53fb10
commit 5a572c7f4a
18 changed files with 927 additions and 0 deletions

21
.env Normal file
View File

@ -0,0 +1,21 @@
# postgrest
POSTGREST_CONTAINER_NAME=postgrest
POSTGREST_IMAGE=postgrest/postgrest:v12.0.2
# postgres
POSTGRES_CONTAINER_NAME=postgres
POSTGRES_IMAGE=postgres:latest
POSTGRES_VOLUME_NAME=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres
DB_ANON_ROLE=anon
DB_SCHEMA=public
# swagger
SWAGGER_CONTAINER_NAME=swagger
SWAGGER_IMAGE=swaggerapi/swagger-ui:v5.11.0

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
tmp

View File

@ -7,3 +7,17 @@ Création d'une API unifié pour accéder à l'ensemble des données dont P4Pill
- Base de données : [PostgreSQL](https://www.postgresql.org/)
- API : [PostgREST](https://postgrest.org/) ([Documentation](https://postgrest.org/en/stable/explanations/install.html#docker))
- UI : [Swagger UI](https://swagger.io/tools/swagger-ui/)
## Données
### FINESS
### INPI
Il y a 2 posibilités pour récupérer les données :
- depuis l'API
- depuis [des fichiers](https://www.data.gouv.fr/fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/)

80
docker-compose.yml Normal file
View File

@ -0,0 +1,80 @@
---
version: "3.8"
volumes:
postgres:
name: ${POSTGRES_VOLUME_NAME:-postgres}
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:
container_name: ${POSTGRES_CONTAINER_NAME:-postgres}
image: ${POSTGRES_IMAGE:-postgres:16.1-alpine}
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: ${POSTGRES_USER:?err}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?err}
POSTGRES_DB: ${POSTGRES_DB:?err}
DB_ANON_ROLE: ${DB_ANON_ROLE:?err}
DB_SCHEMA: ${DB_SCHEMA:?err}
volumes:
- postgres:/var/lib/postgresql/data
- "./initdb:/docker-entrypoint-initdb.d"
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- back-end
swagger:
container_name: ${SWAGGER_CONTAINER_NAME:-swagger}
image: ${SWAGGER_IMAGE:-swaggerapi/swagger-ui:v5.10.3}
restart: always
ports:
- "8080:8080"
environment:
API_URL: http://localhost:3000/
networks:
- front-end
- back-end
networks:
front-end:
back-end:

3
html/css/app.css Normal file
View File

@ -0,0 +1,3 @@
body {
margin-bottom: 40px;
}

11
html/css/pure-min.css vendored Normal file

File diff suppressed because one or more lines are too long

43
html/index.html Normal file
View File

@ -0,0 +1,43 @@
<!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>

53
html/js/app.js Normal file
View File

@ -0,0 +1,53 @@
'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);
}

View File

@ -0,0 +1,9 @@
#!/bin/bash
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-END
CREATE USER ${DB_ANON_ROLE};
GRANT USAGE ON SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
ALTER DEFAULT PRIVILEGES IN SCHEMA ${DB_SCHEMA} GRANT SELECT ON TABLES TO ${DB_ANON_ROLE};
GRANT SELECT ON ALL SEQUENCES IN SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
GRANT SELECT ON ALL TABLES IN SCHEMA ${DB_SCHEMA} TO ${DB_ANON_ROLE};
END

View File

@ -0,0 +1,45 @@
--
-- 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;
SET client_encoding = 'LATIN1';
CREATE TABLE IF NOT EXISTS finess (
nofinesset VARCHAR(255),
nofinessej VARCHAR(255),
rs VARCHAR(255),
rslongue VARCHAR(255),
complrs VARCHAR(255),
compldistrib VARCHAR(255),
numvoie VARCHAR(255),
typvoie VARCHAR(255),
voie VARCHAR(255),
compvoie VARCHAR(255),
lieuditbp VARCHAR(255),
commune VARCHAR(255),
departement VARCHAR(255),
libdepartement VARCHAR(255),
ligneacheminement VARCHAR(255),
telephone VARCHAR(255),
telecopie VARCHAR(255),
categetab VARCHAR(255),
libcategetab VARCHAR(255),
categagretab VARCHAR(255),
libcategagretab VARCHAR(255),
siret VARCHAR(255),
codeape VARCHAR(255),
codemft VARCHAR(255),
libmft VARCHAR(255),
codesph VARCHAR(255),
libsph VARCHAR(255),
dateouv DATE DEFAULT '1900-01-01',
dateautor DATE DEFAULT '1900-01-01',
datemaj DATE DEFAULT '1900-01-01',
numuai VARCHAR(255),
coordxet FLOAT DEFAULT 0,
coordyet FLOAT DEFAULT 0
);

194
package-lock.json generated Normal file
View File

@ -0,0 +1,194 @@
{
"name": "data",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@etalab/decoupage-administratif": "^3.1.1",
"csv-parse": "^5.5.3",
"pg": "^8.11.3",
"proj4": "^2.10.0"
}
},
"node_modules/@etalab/decoupage-administratif": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@etalab/decoupage-administratif/-/decoupage-administratif-3.1.1.tgz",
"integrity": "sha512-/1yqSlo6Xerdz1MN+rh57hDWcAam18gwSK5u4wFjT1glRUiN/o1A4IQe6pvB9JqGvHv6WbF5X7WyE+yxeMqLig==",
"engines": {
"node": ">= 10"
}
},
"node_modules/buffer-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
"engines": {
"node": ">=4"
}
},
"node_modules/csv-parse": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.3.tgz",
"integrity": "sha512-v0KW6C0qlZzoGjk6u5tLmVfyZxNgPGXZsWTXshpAgKVGmGXzaVWGdlCFxNx5iuzcXT/oJN1HHM9DZKwtAtYa+A=="
},
"node_modules/mgrs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
"integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA=="
},
"node_modules/packet-reader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
},
"node_modules/pg": {
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz",
"integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==",
"dependencies": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "^2.6.2",
"pg-pool": "^3.6.1",
"pg-protocol": "^1.6.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
},
"engines": {
"node": ">= 8.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.1.1"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz",
"integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA=="
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz",
"integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
"integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/proj4": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/proj4/-/proj4-2.10.0.tgz",
"integrity": "sha512-0eyB8h1PDoWxucnq88/EZqt7UZlvjhcfbXCcINpE7hqRN0iRPWE/4mXINGulNa/FAvK+Ie7F+l2OxH/0uKV36A==",
"dependencies": {
"mgrs": "1.0.0",
"wkt-parser": "^1.3.3"
}
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/wkt-parser": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz",
"integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw=="
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
}
}
}

9
package.json Normal file
View File

@ -0,0 +1,9 @@
{
"type": "module",
"dependencies": {
"@etalab/decoupage-administratif": "^3.1.1",
"csv-parse": "^5.5.3",
"pg": "^8.11.3",
"proj4": "^2.10.0"
}
}

7
scripts/download.js Normal file
View File

@ -0,0 +1,7 @@
import { downloadFiness } from './helpers/finess.js'
async function main() {
downloadFiness()
}
main()

262
scripts/helpers/finess.js Normal file
View File

@ -0,0 +1,262 @@
import fs from 'fs';
import readline from 'readline';
import pg from 'pg';
import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile } from './functions.js'
import { transformToGPS } from './gps.js'
const { Pool } = pg
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',
'nofinessej',
'rs',
'rslongue',
'complrs',
'compldistrib',
'numvoie',
'typvoie',
'voie',
'compvoie',
'lieuditbp',
'commune',
'departement',
'libdepartement',
'ligneacheminement',
'telephone',
'telecopie',
'categetab',
'libcategetab',
'categagretab',
'libcategagretab',
'siret',
'codeape',
'codemft',
'libmft',
'codesph',
'libsph',
'dateouv',
'dateautor',
'datemaj',
'numuai',
'coordxet',
'coordyet'
];
// Fonction pour insérer une ligne dans la base de données
async function insertRow(data) {
const query = {
text: `INSERT INTO finess (${columns.join(', ')}) VALUES (${columns.map((col, index) => `$${index + 1}`).join(', ')})`,
values: data,
};
const client = await pool.connect();
try {
await client.query(query);
} catch (error) {
console.log(data.join(', '))
console.error('Erreur lors de l\'insertion de la ligne:', error.message || error);
} 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) {
// Supposons que les données dans le fichier soient séparées par des virgules (à ajuster selon votre format)
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
await insertRow(data);
console.log(index)
}
// Fermer le pool de connexions à la base de données à la fin du traitement
await pool.end();
}
// await creerTableFINESS(client);
await processFile(nomFichierCSV)
}
// Fonction pour créer la table FINESS dans PostgreSQL
export async function creerTableFINESS(client) {
try {
// Requête SQL de création de table
const requeteCreationTable = `
CREATE TABLE IF NOT EXISTS finess (
nofinesset VARCHAR(255),
nofinessej VARCHAR(255),
rs VARCHAR(255),
rslongue VARCHAR(255),
complrs VARCHAR(255),
compldistrib VARCHAR(255),
numvoie VARCHAR(255),
typvoie VARCHAR(255),
voie VARCHAR(255),
compvoie VARCHAR(255),
lieuditbp VARCHAR(255),
commune VARCHAR(255),
departement VARCHAR(255),
libdepartement VARCHAR(255),
ligneacheminement VARCHAR(255),
telephone VARCHAR(255),
telecopie VARCHAR(255),
categetab VARCHAR(255),
libcategetab VARCHAR(255),
categagretab VARCHAR(255),
libcategagretab VARCHAR(255),
siret VARCHAR(255),
codeape VARCHAR(255),
codemft VARCHAR(255),
libmft VARCHAR(255),
codesph VARCHAR(255),
libsph VARCHAR(255),
dateouv DATE DEFAULT '1900-01-01',
dateautor DATE DEFAULT '1900-01-01',
datemaj DATE DEFAULT '1900-01-01',
numuai VARCHAR(255),
coordxet FLOAT DEFAULT 0,
coordyet FLOAT DEFAULT 0,
PRIMARY KEY (nofinesset)
);
`;
// Exécution de la requête de création de table
await client.query(requeteCreationTable);
console.log('Table FINESS créée avec succès.');
} catch (erreur) {
console.error(`Erreur lors de la création de la table : ${erreur.message}`);
}
}

View File

@ -0,0 +1,72 @@
import path from 'path';
import fs from 'fs'
import { writeFile, mkdir } from 'fs/promises'
import readline from 'readline';
export const loadEnvFile = () => {
// Charger les variables d'environnement à partir du fichier .env
const envPath = './.env'; // Spécifiez le chemin correct si différent
const envFile = fs.readFileSync(envPath, 'utf-8');
const envVariables = envFile.split('\n').reduce((acc, line) => {
const [key, value] = line.split('=');
if (key && value) {
acc[key.trim()] = value.trim();
}
return acc;
}, {});
return envVariables
}
export const downloadAndSaveFile = async (url, filename) => {
const folder = path.dirname(filename)
if (!fs.existsSync(folder)) await mkdir(folder)
const response = await fetch(url)
const buffer = Buffer.from(await response.arrayBuffer())
await writeFile(filename, buffer)
}
export const downloadJSON = async (url) => (await fetch(url)).json()
// Fonction pour lire un fichier ligne par ligne et filtrer les lignes en fonction de la condition
export async function filtrerEtEnregistrerLignes(fichierEntree, fichierSortie1, fichierSortie2, condition) {
try {
// Créer un flux de lecture pour le fichier d'entrée
const lecteur = readline.createInterface({
input: fs.createReadStream(fichierEntree),
crlfDelay: Infinity
});
// Créer un flux d'écriture pour le fichier de sortie 1
const fichierSortieStream1 = fs.createWriteStream(fichierSortie1);
// Créer un flux d'écriture pour le fichier de sortie 2
const fichierSortieStream2 = fs.createWriteStream(fichierSortie2);
// Fonction pour traiter chaque ligne du fichier
const traiterLigne = (ligne) => {
// Appliquer la condition à la ligne
if (condition(ligne)) {
// Écrire la ligne dans le fichier de sortie 1
fichierSortieStream1.write(`${ligne}\n`);
} else {
// Écrire la ligne dans le fichier de sortie 2
fichierSortieStream2.write(`${ligne}\n`);
}
};
// Lire chaque ligne du fichier
for await (const ligne of lecteur) {
traiterLigne(ligne);
}
console.log('Filtrage et enregistrement des lignes terminés.');
// Fermer les flux d'écriture
fichierSortieStream1.end();
fichierSortieStream2.end();
} catch (erreur) {
console.error(`Erreur lors du filtrage et de l'enregistrement des lignes : ${erreur.message}`);
}
}

88
scripts/helpers/gps.js Normal file
View File

@ -0,0 +1,88 @@
import proj4 from 'proj4'
// Définir les paramètres de la projection WGS84 (EPSG:4326) (GPS)
proj4.defs('EPSG:4326', '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs');
// Définir les paramètres de la projection Lambert 93 (EPSG:2154)
proj4.defs('EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
// Définir les paramètres de la projection UTM Zone 20N (EPSG:32620)
proj4.defs('EPSG:32620', '+proj=utm +zone=20 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
// Définir les paramètres de la projection UTM_N21 (exemple)
proj4.defs('EPSG:32621', '+proj=utm +zone=21 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
// Définir les paramètres de la projection UTM_N22 (exemple)
proj4.defs('EPSG:32622', '+proj=utm +zone=22 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
// Définir les paramètres de la projection UTM_S38 (exemple)
proj4.defs('EPSG:32638', '+proj=utm +zone=38 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
// Définir les paramètres de la projection UTM_S40 (exemple)
proj4.defs('EPSG:32740', '+proj=utm +zone=40 +ellps=WGS84 +datum=WGS84 +units=m +no_defs');
export const transformToGPS = (system, coordX, coordY, ) => {
if (system.includes('LAMBERT_93')) {
return lambert93toGPS(coordX, coordY)
}
if (system.includes('UTM_N20')) {
return utmN20toGPS(coordX, coordY)
}
if (system.includes('UTM_N21')) {
return utmN21toGPS(coordX, coordY)
}
if (system.includes('UTM_N22')) {
return utmN22toGPS(coordX, coordY)
}
if (system.includes('UTM_S38')) {
return utmS38toGPS(coordX, coordY)
}
if (system.includes('UTM_S40')) {
return utmS40toGPS(coordX, coordY)
}
console.error(system);
}
function lambert93toGPS(easting, northing) {
// Convertir les coordonnées Lambert 93 en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:2154', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}
function utmN20toGPS(easting, northing) {
// Convertir les coordonnées UTM en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:32620', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}
function utmN21toGPS(easting, northing) {
// Convertir les coordonnées UTM_N21 en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:32621', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}
function utmN22toGPS(easting, northing) {
// Convertir les coordonnées UTM_N22 en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:32622', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}
function utmS38toGPS(easting, northing) {
// Convertir les coordonnées UTM_S38 en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:32638', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}
function utmS40toGPS(easting, northing) {
// Convertir les coordonnées UTM_S40 en WGS84 (GPS)
const [longitude, latitude] = proj4('EPSG:32740', 'EPSG:4326', [easting, northing]);
return { latitude, longitude };
}

7
scripts/import.js Normal file
View File

@ -0,0 +1,7 @@
import { importFiness } from './helpers/finess.js'
async function main() {
importFiness()
}
main()

7
scripts/transform.js Normal file
View File

@ -0,0 +1,7 @@
import { transformFiness } from './helpers/finess.js'
async function main() {
await transformFiness()
}
main()