UNPKG

@openade/fe

Version:

Fatturazione Elettronica - Electronic Invoicing for Sistema di Interscambio (SDI)

309 lines 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ArchiveManager = void 0; exports.createArchiveManager = createArchiveManager; exports.archiveInvoices = archiveInvoices; const crypto_1 = require("crypto"); const compression_service_1 = require("./compression.service"); const encryption_service_1 = require("./encryption.service"); class ArchiveManager { constructor(config) { this.config = { retentionDays: 3650, compression: true, encryption: false, format: 'zip', metadataFile: 'metadata.json', indexFile: 'index.json', ...config, }; this.compressionService = new compression_service_1.CompressionService(); this.encryptionService = new encryption_service_1.EncryptionService(); } async initialize() { await this.ensureArchiveDirectory(); } async createArchive(invoices, archiveName, periodStart, periodEnd) { try { const archiveId = this.generateArchiveId(); const archivePath = `${this.config.archiveDir}/${archiveId}_${archiveName}`; if (this.config.fileStorage.createDirectory) { await this.config.fileStorage.createDirectory(archivePath); } const entries = []; let totalSize = 0; for (const { invoice, filename, xmlContent } of invoices) { const entry = await this.archiveInvoice(invoice, filename, xmlContent, archivePath); entries.push(entry); totalSize += entry.size; } const metadata = { id: archiveId, name: archiveName, createdAt: new Date().toISOString(), periodStart, periodEnd, invoiceCount: invoices.length, totalSize, checksum: this.calculateArchiveChecksum(entries), compressed: this.config.compression, encrypted: this.config.encryption, format: this.config.format, retentionDate: this.calculateRetentionDate(), }; await this.saveArchiveMetadata(archivePath, metadata); await this.saveArchiveIndex(archivePath, entries); if (this.config.compression) { await this.compressArchive(archivePath); } if (this.config.encryption) { await this.encryptArchive(archivePath); } return { archiveId, success: true, invoiceCount: invoices.length, archiveSize: totalSize, metadata, }; } catch (error) { return { archiveId: '', success: false, invoiceCount: 0, archiveSize: 0, error: error instanceof Error ? error.message : 'Unknown error', }; } } async archiveInvoice(invoice, filename, xmlContent, archivePath) { const filePath = `${archivePath}/${filename}`; const content = Buffer.from(xmlContent, 'utf8'); const checksum = this.calculateFileChecksum(content); await this.config.fileStorage.store(filePath, new Uint8Array(content)); const invoiceId = this.extractInvoiceId(invoice); const invoiceDate = this.extractInvoiceDate(invoice); const customerVatNumber = this.extractCustomerVatNumber(invoice); const amount = this.extractInvoiceAmount(invoice); return { filename, invoiceId, invoiceDate, customerVatNumber, amount, size: content.length, checksum, archiveDate: new Date().toISOString(), }; } async listArchives() { try { const archives = []; const items = await this.config.fileStorage.list(this.config.archiveDir); for (const item of items) { const metadata = await this.loadArchiveMetadata(item); if (metadata) { archives.push(metadata); } } return archives.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()); } catch { return []; } } async getArchive(archiveId) { try { const archivePath = await this.findArchivePath(archiveId); if (!archivePath) { return null; } return await this.loadArchiveMetadata(archivePath); } catch { return null; } } async extractArchive(archiveId, extractPath) { try { const archivePath = await this.findArchivePath(archiveId); if (!archivePath) { return false; } if (this.config.fileStorage.createDirectory) { await this.config.fileStorage.createDirectory(extractPath); } await this.copyArchiveContents(archivePath, extractPath); return true; } catch { return false; } } async deleteArchive(archiveId) { try { const archivePath = await this.findArchivePath(archiveId); if (!archivePath) { return false; } await this.removeDirectory(archivePath); return true; } catch { return false; } } async cleanupExpiredArchives() { try { const archives = await this.listArchives(); const now = new Date(); let deletedCount = 0; for (const archive of archives) { const retentionDate = new Date(archive.retentionDate); if (now > retentionDate) { const deleted = await this.deleteArchive(archive.id); if (deleted) { deletedCount++; } } } return deletedCount; } catch { return 0; } } generateArchiveId() { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 8); return `ARCH_${timestamp}_${random}`; } async ensureArchiveDirectory() { if (this.config.fileStorage.createDirectory) { await this.config.fileStorage.createDirectory(this.config.archiveDir); } } calculateFileChecksum(content) { return (0, crypto_1.createHash)('sha256').update(content).digest('hex'); } calculateArchiveChecksum(entries) { const combined = entries.map((e) => `${e.filename}:${e.checksum}`).join('|'); return (0, crypto_1.createHash)('sha256').update(combined).digest('hex'); } calculateRetentionDate() { const date = new Date(); date.setDate(date.getDate() + this.config.retentionDays); return date.toISOString(); } async saveArchiveMetadata(archivePath, metadata) { const metadataPath = `${archivePath}/${this.config.metadataFile}`; await this.config.fileStorage.store(metadataPath, JSON.stringify(metadata, null, 2)); } async saveArchiveIndex(archivePath, entries) { const indexPath = `${archivePath}/${this.config.indexFile}`; await this.config.fileStorage.store(indexPath, JSON.stringify(entries, null, 2)); } async loadArchiveMetadata(archivePath) { try { const metadataPath = `${archivePath}/${this.config.metadataFile}`; const content = await this.config.fileStorage.retrieve(metadataPath); if (!content) { return null; } return JSON.parse(Buffer.from(content).toString('utf8')); } catch { return null; } } async findArchivePath(archiveId) { try { const items = await this.config.fileStorage.list(this.config.archiveDir); for (const item of items) { if (item.startsWith(archiveId)) { return `${this.config.archiveDir}/${item}`; } } return null; } catch { return null; } } async copyArchiveContents(sourcePath, destPath) { const items = await this.config.fileStorage.list(sourcePath); for (const item of items) { const sourceItemPath = `${sourcePath}/${item}`; const destItemPath = `${destPath}/${item}`; const content = await this.config.fileStorage.retrieve(sourceItemPath); if (content) { await this.config.fileStorage.store(destItemPath, content); } } } async removeDirectory(dirPath) { const items = await this.config.fileStorage.list(dirPath); for (const item of items) { const itemPath = `${dirPath}/${item}`; await this.config.fileStorage.delete(itemPath); } } async compressArchive(archivePath) { if (!this.config.compression) return; const items = await this.config.fileStorage.list(archivePath); for (const item of items) { const filePath = `${archivePath}/${item}`; const content = await this.config.fileStorage.retrieve(filePath); if (content) { const compressed = await this.compressionService.compress(Buffer.from(content)); await this.config.fileStorage.store(filePath, compressed); } } } async encryptArchive(archivePath) { if (!this.config.encryption) return; const encryptionKey = await this.encryptionService.generateKey(); const items = await this.config.fileStorage.list(archivePath); for (const item of items) { const filePath = `${archivePath}/${item}`; const content = await this.config.fileStorage.retrieve(filePath); if (content) { const encrypted = await this.encryptionService.encrypt(Buffer.from(content), encryptionKey); await this.config.fileStorage.store(filePath, encrypted); } } } extractInvoiceId(invoice) { return invoice.fatturaElettronicaHeader.datiTrasmissione.progressivoInvio; } extractInvoiceDate(invoice) { const body = Array.isArray(invoice.fatturaElettronicaBody) ? invoice.fatturaElettronicaBody[0] : invoice.fatturaElettronicaBody; return body.datiGenerali.datiGeneraliDocumento.data; } extractCustomerVatNumber(invoice) { const customer = invoice.fatturaElettronicaHeader.cessionarioCommittente; return customer.datiAnagrafici.idFiscaleIVA?.idCodice; } extractInvoiceAmount(invoice) { const body = Array.isArray(invoice.fatturaElettronicaBody) ? invoice.fatturaElettronicaBody[0] : invoice.fatturaElettronicaBody; return body.datiBeniServizi.datiRiepilogo.reduce((total, riepilogo) => { return total + riepilogo.imponibileImporto + riepilogo.imposta; }, 0); } } exports.ArchiveManager = ArchiveManager; function createArchiveManager(config) { return new ArchiveManager(config); } async function archiveInvoices(invoices, archiveName, periodStart, periodEnd, config) { const manager = createArchiveManager(config); return await manager.createArchive(invoices, archiveName, periodStart, periodEnd); } //# sourceMappingURL=archive.manager.js.map