netgescon-day0/docs/00-IMPORT/03-SCRIPTS/validation-checker.js

355 lines
13 KiB
JavaScript

#!/usr/bin/env node
/**
* NetGescon Validation Checker
* Script per validazione preliminare dati prima dell'import
*/
const fs = require('fs');
const path = require('path');
class ValidationChecker {
constructor() {
this.dataPath = path.join(__dirname, '..', '01-GESCON');
this.mappingPath = path.join(__dirname, '..', '02-MAPPING');
this.errors = [];
this.warnings = [];
}
log(message, level = 'INFO') {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [${level}] ${message}`);
}
loadData(filename) {
try {
const filePath = path.join(this.dataPath, filename);
const rawData = fs.readFileSync(filePath, 'utf8');
return JSON.parse(rawData);
} catch (error) {
this.errors.push(`Errore caricamento ${filename}: ${error.message}`);
return null;
}
}
validateCodiceFiscale(cf) {
if (!cf || cf.length !== 16) return false;
// Controllo caratteri
const cfRegex = /^[A-Z]{6}[0-9]{2}[A-Z][0-9]{2}[A-Z][0-9]{3}[A-Z]$/;
if (!cfRegex.test(cf)) return false;
// Controllo carattere di controllo (algoritmo semplificato)
const controlChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const oddValues = { 'A': 1, 'B': 0, 'C': 5, 'D': 7, 'E': 9, 'F': 13, 'G': 15, 'H': 17, 'I': 19, 'J': 21, 'K': 2, 'L': 4, 'M': 18, 'N': 20, 'O': 11, 'P': 3, 'Q': 6, 'R': 8, 'S': 12, 'T': 14, 'U': 16, 'V': 10, 'W': 22, 'X': 25, 'Y': 24, 'Z': 23, '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, '5': 13, '6': 15, '7': 17, '8': 19, '9': 21 };
const evenValues = { 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25, '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9 };
let sum = 0;
for (let i = 0; i < 15; i++) {
const char = cf[i];
sum += (i % 2 === 0) ? oddValues[char] : evenValues[char];
}
const expectedControl = controlChars[sum % 26];
return cf[15] === expectedControl;
}
validateEmail(email) {
if (!email) return false;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
validateCAP(cap) {
if (!cap) return false;
const capRegex = /^[0-9]{5}$/;
return capRegex.test(cap);
}
validateIBAN(iban) {
if (!iban) return false;
// Rimuovi spazi
iban = iban.replace(/\s/g, '');
// Controllo lunghezza (IT = 27 caratteri)
if (iban.length !== 27 || !iban.startsWith('IT')) return false;
const ibanRegex = /^IT[0-9]{2}[A-Z][0-9]{22}$/;
return ibanRegex.test(iban);
}
validateProvince() {
const validProvinces = [
'AG', 'AL', 'AN', 'AO', 'AR', 'AP', 'AT', 'AV', 'BA', 'BT', 'BL', 'BN', 'BG', 'BI', 'BO', 'BZ', 'BS', 'BR',
'CA', 'CL', 'CB', 'CI', 'CE', 'CT', 'CZ', 'CH', 'CO', 'CS', 'CR', 'KR', 'CN', 'EN', 'FM', 'FE', 'FI', 'FG',
'FC', 'FR', 'GE', 'GO', 'GR', 'IM', 'IS', 'SP', 'AQ', 'LT', 'LE', 'LC', 'LI', 'LO', 'LU', 'MC', 'MN', 'MS',
'MT', 'VS', 'ME', 'MI', 'MO', 'MB', 'NA', 'NO', 'NU', 'OG', 'OT', 'OR', 'PD', 'PA', 'PR', 'PV', 'PG', 'PU',
'PE', 'PC', 'PI', 'PT', 'PN', 'PZ', 'PO', 'RG', 'RA', 'RC', 'RE', 'RI', 'RN', 'RM', 'RO', 'SA', 'SS', 'SV',
'SI', 'SR', 'SO', 'TA', 'TE', 'TR', 'TO', 'TP', 'TN', 'TV', 'TS', 'UD', 'VA', 'VE', 'VB', 'VC', 'VR', 'VV',
'VI', 'VT'
];
return (provincia) => validProvinces.includes(provincia);
}
validateAmministratori() {
this.log('Validazione amministratori...');
const data = this.loadData('amministratori.json');
if (!data) return false;
const isValidProvincia = this.validateProvince();
let validCount = 0;
data.amministratori.forEach((admin, index) => {
const prefix = `Amministratore ${index + 1} (${admin.codice_amministratore_new})`;
let hasErrors = false;
// Validazione codice fiscale
if (!this.validateCodiceFiscale(admin.dati_anagrafici.codice_fiscale)) {
this.errors.push(`${prefix}: Codice fiscale non valido - ${admin.dati_anagrafici.codice_fiscale}`);
hasErrors = true;
}
// Validazione email
if (!this.validateEmail(admin.contatti.email)) {
this.errors.push(`${prefix}: Email non valida - ${admin.contatti.email}`);
hasErrors = true;
}
// Validazione PEC (se presente)
if (admin.contatti.pec && !this.validateEmail(admin.contatti.pec)) {
this.errors.push(`${prefix}: PEC non valida - ${admin.contatti.pec}`);
hasErrors = true;
}
// Validazione CAP
if (!this.validateCAP(admin.indirizzo.cap)) {
this.errors.push(`${prefix}: CAP non valido - ${admin.indirizzo.cap}`);
hasErrors = true;
}
// Validazione provincia
if (!isValidProvincia(admin.indirizzo.provincia)) {
this.errors.push(`${prefix}: Provincia non valida - ${admin.indirizzo.provincia}`);
hasErrors = true;
}
// Validazione campi obbligatori
const requiredFields = [
{ field: 'denominazione', value: admin.dati_anagrafici.denominazione },
{ field: 'indirizzo', value: admin.indirizzo.via },
{ field: 'citta', value: admin.indirizzo.citta },
{ field: 'responsabile_nome', value: admin.responsabile.nome },
{ field: 'responsabile_cognome', value: admin.responsabile.cognome }
];
requiredFields.forEach(({ field, value }) => {
if (!value || value.trim() === '') {
this.errors.push(`${prefix}: Campo obbligatorio mancante - ${field}`);
hasErrors = true;
}
});
// Warning per campi facoltativi
if (!admin.contatti.telefono) {
this.warnings.push(`${prefix}: Telefono non specificato`);
}
if (!admin.contatti.pec) {
this.warnings.push(`${prefix}: PEC non specificata`);
}
if (!hasErrors) validCount++;
});
this.log(`Amministratori validati: ${validCount}/${data.amministratori.length}`);
return validCount > 0;
}
validateStabili() {
this.log('Validazione stabili...');
const data = this.loadData('stabili.json');
if (!data) return false;
const isValidProvincia = this.validateProvince();
let validCount = 0;
data.stabili.forEach((stabile, index) => {
const prefix = `Stabile ${index + 1} (${stabile.cod_stabile_old})`;
let hasErrors = false;
// Validazione codice fiscale
if (!this.validateCodiceFiscale(stabile.dati_anagrafici.codice_fiscale)) {
this.errors.push(`${prefix}: Codice fiscale non valido - ${stabile.dati_anagrafici.codice_fiscale}`);
hasErrors = true;
}
// Validazione IBAN (se presente)
if (stabile.dati_bancari.iban_principale && !this.validateIBAN(stabile.dati_bancari.iban_principale)) {
this.errors.push(`${prefix}: IBAN principale non valido - ${stabile.dati_bancari.iban_principale}`);
hasErrors = true;
}
if (stabile.dati_bancari.iban_postale && !this.validateIBAN(stabile.dati_bancari.iban_postale)) {
this.errors.push(`${prefix}: IBAN postale non valido - ${stabile.dati_bancari.iban_postale}`);
hasErrors = true;
}
// Validazione CAP
if (!this.validateCAP(stabile.dati_anagrafici.cap)) {
this.errors.push(`${prefix}: CAP non valido - ${stabile.dati_anagrafici.cap}`);
hasErrors = true;
}
// Validazione provincia
if (!isValidProvincia(stabile.dati_anagrafici.provincia)) {
this.errors.push(`${prefix}: Provincia non valida - ${stabile.dati_anagrafici.provincia}`);
hasErrors = true;
}
// Validazione amministratore
if (!this.validateCodiceFiscale(stabile.amministrazione.cf_amministratore)) {
this.errors.push(`${prefix}: CF amministratore non valido - ${stabile.amministrazione.cf_amministratore}`);
hasErrors = true;
}
// Validazione campi obbligatori
const requiredFields = [
{ field: 'denominazione', value: stabile.dati_anagrafici.denominazione },
{ field: 'indirizzo', value: stabile.dati_anagrafici.indirizzo_completo },
{ field: 'citta', value: stabile.dati_anagrafici.citta }
];
requiredFields.forEach(({ field, value }) => {
if (!value || value.trim() === '') {
this.errors.push(`${prefix}: Campo obbligatorio mancante - ${field}`);
hasErrors = true;
}
});
// Warning per dati struttura
if (!stabile.struttura.num_condomini || stabile.struttura.num_condomini <= 0) {
this.warnings.push(`${prefix}: Numero condomini non specificato o zero`);
}
if (stabile.struttura.num_scale === null || stabile.struttura.num_scale === undefined) {
this.warnings.push(`${prefix}: Numero scale non specificato`);
}
if (!stabile.dati_bancari.iban_principale) {
this.warnings.push(`${prefix}: IBAN bancario non specificato`);
}
if (!hasErrors) validCount++;
});
this.log(`Stabili validati: ${validCount}/${data.stabili.length}`);
return validCount > 0;
}
validateCrossReferences() {
this.log('Validazione riferimenti incrociati...');
const amministratoriData = this.loadData('amministratori.json');
const stabiliData = this.loadData('stabili.json');
if (!amministratoriData || !stabiliData) return false;
// Crea mappa amministratori per CF
const adminMap = new Map();
amministratoriData.amministratori.forEach(admin => {
adminMap.set(admin.dati_anagrafici.codice_fiscale, admin);
});
// Controlla che ogni stabile abbia un amministratore valido
stabiliData.stabili.forEach(stabile => {
const cfAmministratore = stabile.amministrazione.cf_amministratore;
if (!adminMap.has(cfAmministratore)) {
this.errors.push(`Stabile ${stabile.cod_stabile_old}: Amministratore non trovato - ${cfAmministratore}`);
}
});
// Controlla duplicati CF stabili
const cfStabili = new Set();
stabiliData.stabili.forEach(stabile => {
const cf = stabile.dati_anagrafici.codice_fiscale;
if (cfStabili.has(cf)) {
this.errors.push(`CF duplicato tra stabili: ${cf}`);
}
cfStabili.add(cf);
});
return true;
}
generateReport() {
const report = {
timestamp: new Date().toISOString(),
summary: {
total_errors: this.errors.length,
total_warnings: this.warnings.length,
validation_passed: this.errors.length === 0
},
errors: this.errors,
warnings: this.warnings
};
// Salva report
const reportPath = path.join(__dirname, `validation-report-${Date.now()}.json`);
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
this.log('=== REPORT VALIDAZIONE ===');
this.log(`Errori: ${this.errors.length}`);
this.log(`Warning: ${this.warnings.length}`);
this.log(`Validazione: ${this.errors.length === 0 ? 'SUPERATA' : 'FALLITA'}`);
this.log(`Report salvato: ${reportPath}`);
// Mostra errori
if (this.errors.length > 0) {
this.log('ERRORI TROVATI:', 'ERROR');
this.errors.forEach(error => this.log(` - ${error}`, 'ERROR'));
}
// Mostra warning
if (this.warnings.length > 0) {
this.log('WARNING TROVATI:', 'WARN');
this.warnings.forEach(warning => this.log(` - ${warning}`, 'WARN'));
}
return report;
}
async run() {
this.log('=== AVVIO VALIDATION CHECKER ===');
// Validazioni
this.validateAmministratori();
this.validateStabili();
this.validateCrossReferences();
// Genera report
const report = this.generateReport();
return report.summary.validation_passed;
}
}
// Esecuzione principale
if (require.main === module) {
const checker = new ValidationChecker();
checker.run()
.then(success => {
process.exit(success ? 0 : 1);
})
.catch(error => {
console.error('Errore fatale:', error);
process.exit(1);
});
}
module.exports = ValidationChecker;