netgescon-day0/docs/00-IMPORT/03-SCRIPTS/import-runner.js

355 lines
13 KiB
JavaScript

#!/usr/bin/env node
/**
* NetGescon Import Runner
* Script automatico per import dati da Gescon a NetGescon via API
*
* Uso: node import-runner.js [--validate-only] [--step=admin|stabili|all]
*/
const fs = require('fs');
const path = require('path');
const axios = require('axios');
class NetGesconImporter {
constructor() {
this.config = {
apiUrl: process.env.NETGESCON_API_URL || 'http://localhost:8000/api/v1',
email: process.env.NETGESCON_EMAIL || 'admin@netgescon.local',
password: process.env.NETGESCON_PASSWORD || 'password',
timeout: 30000
};
this.token = null;
this.dataPath = path.join(__dirname, '..', '01-GESCON');
this.mappingPath = path.join(__dirname, '..', '02-MAPPING');
this.stats = {
startTime: new Date(),
amministratori: { importati: 0, errori: 0, duplicati: 0 },
stabili: { importati: 0, errori: 0, duplicati: 0 },
totaleOperazioni: 0,
erroriGlobali: []
};
}
log(message, level = 'INFO') {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [${level}] ${message}`);
// Salva log su file
const logMessage = `${timestamp} [${level}] ${message}\n`;
fs.appendFileSync(path.join(__dirname, 'import.log'), logMessage);
}
async login() {
try {
this.log('Tentativo login API NetGescon...');
const response = await axios.post(`${this.config.apiUrl}/auth/login`, {
email: this.config.email,
password: this.config.password
}, {
timeout: this.config.timeout,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (response.data.success) {
this.token = response.data.data.token;
this.log('Login API completato con successo');
return true;
} else {
throw new Error(response.data.message || 'Login fallito');
}
} catch (error) {
this.log(`Errore login API: ${error.message}`, 'ERROR');
return false;
}
}
loadData(filename) {
try {
const filePath = path.join(this.dataPath, filename);
const rawData = fs.readFileSync(filePath, 'utf8');
return JSON.parse(rawData);
} catch (error) {
this.log(`Errore caricamento file ${filename}: ${error.message}`, 'ERROR');
return null;
}
}
loadMapping() {
try {
const mappingFile = path.join(this.mappingPath, 'campo-mapping.json');
const rawData = fs.readFileSync(mappingFile, 'utf8');
return JSON.parse(rawData);
} catch (error) {
this.log(`Errore caricamento mapping: ${error.message}`, 'ERROR');
return null;
}
}
async importAmministratori(validateOnly = false) {
this.log('=== INIZIO IMPORT AMMINISTRATORI ===');
const data = this.loadData('amministratori.json');
if (!data) return false;
const mapping = this.loadMapping();
if (!mapping) return false;
try {
// Prepara dati per API
const apiData = {
bulk_import: true,
validate_only: validateOnly,
amministratori: data.amministratori.map(admin => this.transformAmministratore(admin, mapping))
};
this.log(`Preparati ${apiData.amministratori.length} amministratori per import`);
const response = await axios.post(`${this.config.apiUrl}/import/amministratori`, apiData, {
timeout: this.config.timeout * 2,
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (response.data.success) {
const result = response.data.data;
this.stats.amministratori.importati = result.importati || 0;
this.stats.amministratori.errori = result.errori || 0;
this.stats.amministratori.duplicati = result.duplicati || 0;
this.log(`Import amministratori completato: ${result.importati} importati, ${result.errori} errori, ${result.duplicati} duplicati`);
if (result.dettagli) {
result.dettagli.forEach(dettaglio => {
this.log(` - ${dettaglio.codice}: ${dettaglio.status} - ${dettaglio.message || ''}`);
});
}
return true;
} else {
throw new Error(response.data.message || 'Import amministratori fallito');
}
} catch (error) {
this.log(`Errore import amministratori: ${error.message}`, 'ERROR');
if (error.response?.data?.errors) {
this.log(`Dettagli errore: ${JSON.stringify(error.response.data.errors)}`, 'ERROR');
}
return false;
}
}
transformAmministratore(admin, mapping) {
const adminMapping = mapping.amministratori;
return {
codice_amministratore: admin.codice_amministratore_new,
denominazione: admin.dati_anagrafici.denominazione,
ragione_sociale: admin.dati_anagrafici.ragione_sociale,
codice_fiscale: admin.dati_anagrafici.codice_fiscale,
partita_iva: admin.dati_anagrafici.partita_iva,
indirizzo: admin.indirizzo.via,
cap: admin.indirizzo.cap,
citta: admin.indirizzo.citta,
provincia: admin.indirizzo.provincia,
telefono: admin.contatti.telefono,
email: admin.contatti.email,
pec: admin.contatti.pec,
responsabile_nome: admin.responsabile.nome,
responsabile_cognome: admin.responsabile.cognome,
responsabile_cf: admin.responsabile.codice_fiscale,
data_nascita: admin.responsabile.data_nascita,
comune_nascita: admin.responsabile.luogo_nascita,
provincia_nascita: admin.responsabile.provincia_nascita,
sesso: admin.responsabile.sesso,
data_iscrizione_albo: admin.professionale.data_iscrizione_albo,
numero_albo: admin.professionale.numero_albo,
note: admin.sistema.note,
attivo: admin.sistema.attivo
};
}
async importStabili(validateOnly = false) {
this.log('=== INIZIO IMPORT STABILI ===');
const data = this.loadData('stabili.json');
if (!data) return false;
const mapping = this.loadMapping();
if (!mapping) return false;
try {
// Prepara dati per API
const apiData = {
bulk_import: true,
validate_only: validateOnly,
stabili: data.stabili.map(stabile => this.transformStabile(stabile, mapping))
};
this.log(`Preparati ${apiData.stabili.length} stabili per import`);
const response = await axios.post(`${this.config.apiUrl}/import/stabili`, apiData, {
timeout: this.config.timeout * 3,
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (response.data.success) {
const result = response.data.data;
this.stats.stabili.importati = result.importati || 0;
this.stats.stabili.errori = result.errori || 0;
this.stats.stabili.duplicati = result.duplicati || 0;
this.log(`Import stabili completato: ${result.importati} importati, ${result.errori} errori, ${result.duplicati} duplicati`);
if (result.dettagli) {
result.dettagli.forEach(dettaglio => {
this.log(` - ${dettaglio.codice}: ${dettaglio.status} - ${dettaglio.message || ''}`);
});
}
return true;
} else {
throw new Error(response.data.message || 'Import stabili fallito');
}
} catch (error) {
this.log(`Errore import stabili: ${error.message}`, 'ERROR');
if (error.response?.data?.errors) {
this.log(`Dettagli errore: ${JSON.stringify(error.response.data.errors)}`, 'ERROR');
}
return false;
}
}
transformStabile(stabile, mapping) {
return {
cod_stabile_old: stabile.cod_stabile_old,
denominazione: stabile.dati_anagrafici.denominazione,
indirizzo: stabile.dati_anagrafici.indirizzo_completo,
cap: stabile.dati_anagrafici.cap,
citta: stabile.dati_anagrafici.citta,
provincia: stabile.dati_anagrafici.provincia,
codice_fiscale: stabile.dati_anagrafici.codice_fiscale,
num_condomini: stabile.struttura.num_condomini,
num_scale: stabile.struttura.num_scale,
cf_amministratore: stabile.amministrazione.cf_amministratore,
iban_bancario: stabile.dati_bancari.iban_principale,
iban_postale: stabile.dati_bancari.iban_postale,
banca: stabile.dati_bancari.banca,
abi: stabile.dati_bancari.abi,
cab: stabile.dati_bancari.cab,
intestazione: stabile.dati_bancari.intestazione,
autorizzazione: stabile.autorizzazioni?.numero,
data_nomina: stabile.amministrazione.data_nomina,
note: stabile.sistema.note,
email_amministratore: stabile.contatti?.email_amministratore,
pec_amministratore: stabile.contatti?.pec_amministratore,
pec_condominio: stabile.contatti?.pec_condominio,
migrazione_data: stabile.sistema.migrazione_data,
attivo: stabile.sistema.attivo
};
}
async generateReport() {
const endTime = new Date();
const duration = Math.round((endTime - this.stats.startTime) / 1000);
const report = {
timestamp: endTime.toISOString(),
durata_secondi: duration,
statistiche: this.stats,
successo: this.stats.erroriGlobali.length === 0
};
// Salva report su file
const reportPath = path.join(__dirname, `import-report-${endTime.getTime()}.json`);
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
this.log('=== REPORT FINALE ===');
this.log(`Durata import: ${duration} secondi`);
this.log(`Amministratori - Importati: ${this.stats.amministratori.importati}, Errori: ${this.stats.amministratori.errori}`);
this.log(`Stabili - Importati: ${this.stats.stabili.importati}, Errori: ${this.stats.stabili.errori}`);
this.log(`Report salvato in: ${reportPath}`);
return report;
}
async run(options = {}) {
const { validateOnly = false, step = 'all' } = options;
this.log('=== AVVIO NETGESCON IMPORT RUNNER ===');
this.log(`Modalità: ${validateOnly ? 'VALIDAZIONE' : 'IMPORT COMPLETO'}`);
this.log(`Step: ${step}`);
// Login API
if (!await this.login()) {
this.log('Impossibile procedere senza login API', 'ERROR');
return false;
}
let success = true;
// Import amministratori
if (step === 'all' || step === 'admin') {
success = await this.importAmministratori(validateOnly) && success;
}
// Import stabili (solo se amministratori ok)
if ((step === 'all' || step === 'stabili') && success) {
success = await this.importStabili(validateOnly) && success;
}
// Genera report finale
await this.generateReport();
this.log(`=== IMPORT ${success ? 'COMPLETATO' : 'FALLITO'} ===`);
return success;
}
}
// Gestione parametri command line
function parseArgs() {
const args = process.argv.slice(2);
const options = {};
args.forEach(arg => {
if (arg === '--validate-only') {
options.validateOnly = true;
} else if (arg.startsWith('--step=')) {
options.step = arg.split('=')[1];
}
});
return options;
}
// Esecuzione principale
if (require.main === module) {
const options = parseArgs();
const importer = new NetGesconImporter();
importer.run(options)
.then(success => {
process.exit(success ? 0 : 1);
})
.catch(error => {
console.error('Errore fatale:', error);
process.exit(1);
});
}
module.exports = NetGesconImporter;