@openade/fe
Version:
Fatturazione Elettronica - Electronic Invoicing for Sistema di Interscambio (SDI)
309 lines • 11.8 kB
JavaScript
"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