feat: Mise en place du projet

This commit is contained in:
Simon C
2024-02-08 12:28:51 +01:00
parent 10bc230e2e
commit 9b13a144e0
19 changed files with 368 additions and 369 deletions

View File

@ -1,10 +1,43 @@
import fs from 'fs';
import readline from 'readline';
import pg from 'pg';
import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile } from './functions.js'
import { downloadJSON, downloadAndSaveFile, filtrerEtEnregistrerLignes, loadEnvFile, customSplit } from './functions.js'
import { transformToGPS } from './gps.js'
const { Pool } = pg
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'
];
export const downloadFiness = async () => {
const MAIN_URL = 'https://www.data.gouv.fr/api/1/datasets/finess-extraction-du-fichier-des-etablissements/'
@ -20,31 +53,26 @@ 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, fichierEntree);
}
export const importFiness = async () => {
// Exemple d'utilisation avec le nom du fichier CSV
const fichierEntree = './tmp/finess.csv';
insererDonneesPostgres(fichierEntree);
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 {
// Créer un flux de lecture pour le fichier de coordonnées Lambert 93
// Créer un flux de lecture pour le fichier de coordonnées
const lecteurCoordonnees = readline.createInterface({
input: fs.createReadStream(fichierCoordonnees),
crlfDelay: Infinity
});
// Créer un dictionnaire pour stocker les coordonnées Lambert 93 par structureid
// Créer un dictionnaire pour stocker les coordonnées par structureid
const coordonnees = {};
// Fonction pour traiter chaque ligne du fichier de coordonnées Lambert 93
// Fonction pour traiter chaque ligne du fichier de coordonnées
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
@ -56,7 +84,7 @@ export async function fusionnerCoordonneesGPSStructures(fichierStructures, fichi
coordonnees[structureid] = { system, coordX, coordY };
};
// Lire chaque ligne du fichier de coordonnées Lambert 93
// Lire chaque ligne du fichier de coordonnées
for await (const ligne of lecteurCoordonnees) {
traiterLigneCoordonnees(ligne);
}
@ -70,193 +98,100 @@ export async function fusionnerCoordonneesGPSStructures(fichierStructures, fichi
// 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');
// Création de l'entête d'insertion
// fichierSortieStream.write('INSERT INTO finess (' + columns.join(', ') + ') VALUES\n');
fichierSortieStream.write(columns.join(";") + '\n');
// Fonction pour traiter chaque ligne du fichier de structures
const traiterLigneStructures = (ligne) => {
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"))
}
dataArray.shift(); // Suppression du premier champs inutil
// const defaultValue = (value) => (value === null || value === '' ? 'NULL' : `'${value.replaceAll("'", "''")}'`)
// const typedData = {
// nofinesset: defaultValue(dataArray[0]),
// nofinessej: defaultValue(dataArray[1]),
// rs: defaultValue(dataArray[2]),
// rslongue: defaultValue(dataArray[3]),
// complrs: defaultValue(dataArray[4]),
// compldistrib: defaultValue(dataArray[5]),
// numvoie: defaultValue(dataArray[6]),
// typvoie: defaultValue(dataArray[7]),
// voie: defaultValue(dataArray[8]),
// compvoie: defaultValue(dataArray[9]),
// lieuditbp: defaultValue(dataArray[10]),
// commune: defaultValue(dataArray[11]),
// departement: defaultValue(dataArray[12]),
// libdepartement: defaultValue(dataArray[13]),
// ligneacheminement: defaultValue(dataArray[14]),
// telephone: defaultValue(dataArray[15]),
// telecopie: defaultValue(dataArray[16]),
// categetab: defaultValue(dataArray[17]),
// libcategetab: defaultValue(dataArray[18]),
// categagretab: defaultValue(dataArray[19]),
// libcategagretab: defaultValue(dataArray[20]),
// siret: defaultValue(dataArray[21]),
// codeape: defaultValue(dataArray[22]),
// codemft: defaultValue(dataArray[23]),
// libmft: defaultValue(dataArray[24]),
// codesph: defaultValue(dataArray[25]),
// libsph: defaultValue(dataArray[26]),
// dateouv: defaultValue((new Date(dataArray[27] || '1900-01-01')).toISOString().split('T')[0]), // Utilise la date par défaut si la date est vide
// dateautor: defaultValue((new Date(dataArray[28] || '1900-01-01')).toISOString().split('T')[0]),
// datemaj: defaultValue((new Date(dataArray[29] || '1900-01-01')).toISOString().split('T')[0]),
// numuai: defaultValue(dataArray[30]),
// coordxet: dataArray[31] ? parseFloat(dataArray[31]) : 'NULL',
// coordyet: dataArray[32] ? parseFloat(dataArray[32]) : 'NULL',
// };
// if (typedData.nofinesset === '690051545') {
// console.log(dataArray[20])
// }
// 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`);
}
let isFirst = true
// Lire chaque ligne du fichier de structures
for await (const ligne of lecteurStructures) {
const valeurs = ligne.split(';');
const structureid = valeurs[1];
// Vérifier si des coordonnées Lambert 93 existent pour cette structureid
// 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
fichierSortieStream.write(`${ligne};${coordonneesGPS.latitude};${coordonneesGPS.longitude}\n`);
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
fichierSortieStream.write(`${ligne};;\n`);
ecrireLigneStructure(`${ligne};;`, isFirst);
}
} else {
// Si aucune coordonnée n'est disponible, écrire la ligne telle quelle dans le fichier de sortie
fichierSortieStream.write(`${ligne};;\n`);
ecrireLigneStructure(`${ligne};;`, isFirst);
}
};
// Lire chaque ligne du fichier de structures
for await (const ligne of lecteurStructures) {
traiterLigneStructures(ligne);
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) {
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

@ -3,6 +3,29 @@ import fs from 'fs'
import { writeFile, mkdir } from 'fs/promises'
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 = () => {
// Charger les variables d'environnement à partir du fichier .env
const envPath = './.env'; // Spécifiez le chemin correct si différent