netgescon-day0/docs/91-database/02-tabelle-collegate/fatture_elettroniche.md

53 KiB

📄 FATTURE ELETTRONICHE - Sistema Import XML Completo

🎯 OVERVIEW

Sistema completo per gestione fatture elettroniche XML secondo normativa italiana. Struttura modulare espandibile con tabelle di configurazione separate per massima flessibilità futura. Include dati specifici consumi per statistiche e ripartizione condominiale.


🗄️ STRUTTURA MYSQL MODULARE

1. TABELLA PRINCIPALE - FATTURE ELETTRONICHE

CREATE TABLE fatture_elettroniche (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    uuid                        VARCHAR(36) NOT NULL UNIQUE,            -- UUID per identificazione esterna
    
    -- Gestione Multi-Tenant
    gestione_id                 BIGINT NOT NULL,                        -- FK gestioni.id
    
    -- Dati XML Originali
    nome_file_xml               VARCHAR(500) NOT NULL,                  -- Nome file XML originale
    hash_file_xml               VARCHAR(64) NOT NULL UNIQUE,            -- Hash per prevenire duplicati
    contenuto_xml_originale     LONGTEXT NULL,                          -- XML completo originale
    versione_xml                VARCHAR(10) DEFAULT 'FPR12',            -- Versione formato (FPR12, etc.)
    
    -- Dati Trasmissione
    id_trasmittente_paese       VARCHAR(2) DEFAULT 'IT',                -- Paese trasmittente
    id_trasmittente_codice      VARCHAR(11) NOT NULL,                   -- Codice trasmittente
    progressivo_invio           VARCHAR(10) NOT NULL,                   -- Progressivo invio SDI
    formato_trasmissione        VARCHAR(10) DEFAULT 'FPR12',            -- Formato trasmissione
    codice_destinatario         VARCHAR(7) NULL,                        -- Codice destinatario (se presente)
    pec_destinatario            VARCHAR(255) NULL,                      -- Email PEC destinatario
    
    -- Dati Sistema SDI
    identificativo_sdi          BIGINT NULL,                            -- ID univoco assegnato da SDI
    hash_sdi                    VARCHAR(64) NULL,                       -- Hash calcolato da SDI
    data_ora_ricezione_sdi      TIMESTAMP NULL,                         -- Timestamp ricezione SDI
    message_id_sdi              VARCHAR(20) NULL,                       -- Message ID interno SDI
    stato_sdi                   ENUM('RICEVUTA','ACCETTATA','RIFIUTATA','CONSEGNATA','MANCATA_CONSEGNA') NULL, -- Stato SDI
    
    -- Dati Documento
    tipo_documento              VARCHAR(4) NOT NULL DEFAULT 'TD01',     -- TD01=Fattura, TD04=Nota credito, etc.
    numero_fattura              VARCHAR(50) NOT NULL,                   -- Numero fattura
    data_fattura                DATE NOT NULL,                          -- Data emissione
    divisa                      VARCHAR(3) DEFAULT 'EUR',               -- Valuta
    
    -- Importi Principali
    importo_totale_documento    DECIMAL(12,2) NOT NULL,                 -- Importo totale fattura
    arrotondamento              DECIMAL(8,2) DEFAULT 0,                 -- Arrotondamento applicato
    
    -- Cedente/Prestatore (Fornitore)
    cedente_partita_iva         VARCHAR(11) NULL,                       -- P.IVA cedente
    cedente_codice_fiscale      VARCHAR(16) NULL,                       -- CF cedente
    cedente_denominazione       VARCHAR(255) NOT NULL,                  -- Ragione sociale
    cedente_nome                VARCHAR(100) NULL,                      -- Nome (se persona fisica)
    cedente_cognome             VARCHAR(100) NULL,                      -- Cognome (se persona fisica)
    cedente_regime_fiscale      VARCHAR(4) NULL,                        -- Regime fiscale (RF01, etc.)
    cedente_indirizzo           VARCHAR(255) NULL,                      -- Indirizzo completo
    cedente_numero_civico       VARCHAR(10) NULL,                       -- Numero civico
    cedente_cap                 VARCHAR(5) NULL,                        -- CAP
    cedente_comune              VARCHAR(100) NULL,                      -- Comune
    cedente_provincia           VARCHAR(2) NULL,                        -- Provincia
    cedente_nazione             VARCHAR(2) DEFAULT 'IT',                -- Nazione
    cedente_telefono            VARCHAR(20) NULL,                       -- Telefono
    cedente_email               VARCHAR(255) NULL,                      -- Email
    
    -- Cessionario/Committente (Cliente - Condominio)
    cessionario_codice_fiscale  VARCHAR(16) NULL,                       -- CF condominio
    cessionario_denominazione   VARCHAR(255) NOT NULL,                  -- Nome condominio
    cessionario_nome            VARCHAR(100) NULL,                      -- Nome (se persona fisica)
    cessionario_cognome         VARCHAR(100) NULL,                      -- Cognome (se persona fisica)
    cessionario_indirizzo       VARCHAR(255) NULL,                      -- Indirizzo condominio
    cessionario_numero_civico   VARCHAR(10) NULL,                       -- Numero civico
    cessionario_cap             VARCHAR(5) NULL,                        -- CAP
    cessionario_comune          VARCHAR(100) NULL,                      -- Comune
    cessionario_provincia       VARCHAR(2) NULL,                        -- Provincia
    cessionario_nazione         VARCHAR(2) DEFAULT 'IT',                -- Nazione
    
    -- Ritenute d'Acconto
    ha_ritenuta                 BOOLEAN DEFAULT FALSE,                  -- Se presente ritenuta
    tipo_ritenuta               VARCHAR(4) NULL,                        -- RT01, RT02, etc.
    importo_ritenuta            DECIMAL(10,2) DEFAULT 0,                -- Importo ritenuta
    aliquota_ritenuta           DECIMAL(5,2) DEFAULT 0,                 -- Aliquota % ritenuta
    causale_pagamento_id        BIGINT NULL,                            -- FK causali_pagamento_ritenuta.id
    
    -- Bollo
    bollo_virtuale              BOOLEAN DEFAULT FALSE,                  -- Se bollo virtuale
    importo_bollo               DECIMAL(8,2) DEFAULT 0,                 -- Importo bollo
    
    -- Causale e Note
    causale                     TEXT NULL,                              -- Causale fattura
    note                        TEXT NULL,                              -- Note aggiuntive
    
    -- Stato Import e Processamento
    stato_import                ENUM('IMPORTATA','ELABORATA','CONTABILIZZATA','PAGATA','ERRORE') DEFAULT 'IMPORTATA',
    errori_import               TEXT NULL,                              -- Errori durante import
    data_import                 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,    -- Data import XML
    
    -- Collegamenti Contabili
    contabilita_id              BIGINT NULL,                            -- FK contabilita.id (se contabilizzata)
    movimento_bancario_id       BIGINT NULL,                            -- FK movimenti_bancari.id (se pagata)
    
    -- Dati per Matching e Riconciliazione
    fornitore_normalizzato      VARCHAR(255) NULL,                      -- Nome fornitore normalizzato per matching
    categoria_fornitore         VARCHAR(100) NULL,                      -- Categoria automatica (ENERGIA, ACQUA, MANUTENZIONE, etc.)
    keywords_riconoscimento     JSON NULL,                              -- Keywords per riconoscimento automatico
    
    -- Sistema
    attiva                      BOOLEAN DEFAULT TRUE,
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by                  BIGINT NULL,                            -- FK users.id
    updated_by                  BIGINT NULL,                            -- FK users.id
    
    -- Indici
    INDEX idx_gestione (gestione_id),
    INDEX idx_data_fattura (data_fattura),
    INDEX idx_numero_fattura (numero_fattura),
    INDEX idx_cedente_piva (cedente_partita_iva),
    INDEX idx_importo_totale (importo_totale_documento),
    INDEX idx_tipo_documento (tipo_documento),
    INDEX idx_stato_import (stato_import),
    INDEX idx_categoria_fornitore (categoria_fornitore),
    INDEX idx_contabilita (contabilita_id),
    INDEX idx_movimento_bancario (movimento_bancario_id),
    INDEX idx_identificativo_sdi (identificativo_sdi),
    INDEX idx_stato_sdi (stato_sdi),
    UNIQUE KEY unique_hash_file (hash_file_xml),
    UNIQUE KEY unique_identificativo_sdi (identificativo_sdi),
    
    -- Foreign Keys
    FOREIGN KEY (gestione_id) REFERENCES gestioni(id) ON DELETE CASCADE,
    FOREIGN KEY (causale_pagamento_id) REFERENCES causali_pagamento_ritenuta(id) ON DELETE SET NULL,
    FOREIGN KEY (contabilita_id) REFERENCES contabilita(id) ON DELETE SET NULL,
    FOREIGN KEY (movimento_bancario_id) REFERENCES movimenti_bancari(id) ON DELETE SET NULL,
    FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL,
    FOREIGN KEY (updated_by) REFERENCES users(id) ON DELETE SET NULL,
    
    -- Constraints
    CONSTRAINT chk_importo_positivo CHECK (importo_totale_documento > 0),
    CONSTRAINT chk_aliquota_ritenuta CHECK (aliquota_ritenuta >= 0 AND aliquota_ritenuta <= 100),
    CONSTRAINT chk_importo_ritenuta CHECK (importo_ritenuta >= 0)
);

-- Trigger per UUID automatico
DELIMITER $$
CREATE TRIGGER trg_fatture_elettroniche_uuid 
BEFORE INSERT ON fatture_elettroniche 
FOR EACH ROW 
BEGIN 
    IF NEW.uuid IS NULL OR NEW.uuid = '' THEN 
        SET NEW.uuid = UUID(); 
    END IF; 
END$$
DELIMITER ;

2. TABELLE COLLEGATE 1:N

A. RIGHE FATTURA

CREATE TABLE fatture_righe (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    numero_linea                INT NOT NULL,                           -- Numero progressivo riga
    
    -- Descrizione Articolo/Servizio
    descrizione                 TEXT NOT NULL,                          -- Descrizione completa
    descrizione_normalizzata    VARCHAR(500) NULL,                      -- Descrizione normalizzata per matching
    
    -- Quantità e Misure
    quantita                    DECIMAL(12,6) DEFAULT 1,                -- Quantità
    unita_misura_id             BIGINT NULL,                            -- FK unita_misura.id
    unita_misura_custom         VARCHAR(10) NULL,                       -- Se unità non in tabella
    
    -- Prezzi
    prezzo_unitario             DECIMAL(12,6) NOT NULL,                 -- Prezzo unitario
    prezzo_totale               DECIMAL(12,2) NOT NULL,                 -- Prezzo totale riga
    sconto_percentuale          DECIMAL(5,2) DEFAULT 0,                 -- Sconto %
    sconto_importo              DECIMAL(10,2) DEFAULT 0,                -- Sconto in euro
    
    -- IVA
    aliquota_iva_id             BIGINT NULL,                            -- FK iva_tipologie.id
    aliquota_iva_custom         DECIMAL(5,2) NULL,                      -- Se aliquota non in tabella
    natura_iva_id               BIGINT NULL,                            -- FK nature_iva.id (per esenti)
    
    -- Ritenute
    soggetta_ritenuta           BOOLEAN DEFAULT FALSE,                  -- Se riga soggetta a ritenuta
    
    -- Dati Specifici Consumi (per utility)
    consumo_tipo                ENUM('ENERGIA_ELETTRICA','ACQUA','GAS','RISCALDAMENTO','ALTRO') NULL,
    consumo_quantita            DECIMAL(12,3) NULL,                     -- kWh, m³, mc, etc.
    consumo_unita               VARCHAR(10) NULL,                       -- kWh, m³, mc
    consumo_periodo_dal         DATE NULL,                              -- Periodo consumo inizio
    consumo_periodo_al          DATE NULL,                              -- Periodo consumo fine
    consumo_lettura_precedente  DECIMAL(12,3) NULL,                     -- Lettura precedente
    consumo_lettura_attuale     DECIMAL(12,3) NULL,                     -- Lettura attuale
    consumo_coefficiente        DECIMAL(8,4) DEFAULT 1,                 -- Coefficiente moltiplicativo
    consumo_note                TEXT NULL,                              -- Note sui consumi
    
    -- Collegamento a Unità Immobiliari (per ripartizione)
    unita_immobiliare_id        BIGINT NULL,                            -- FK unita_immobiliari.id (se specifico)
    ripartizione_tipo           ENUM('MILLESIMI_GENERALI','MILLESIMI_SCALE','MILLESIMI_ASCENSORE','MILLESIMI_RISCALDAMENTO','PARTI_UGUALI','PERSONALIZZATA','SPECIFICO') NULL,
    
    -- Categorie per Statistica
    categoria_servizio          VARCHAR(100) NULL,                      -- Categoria servizio (PULIZIE, MANUTENZIONE, etc.)
    sottocategoria              VARCHAR(100) NULL,                      -- Sottocategoria
    
    -- Altri Dati Gestionali (campi aggiuntivi dal XML)
    altri_dati_gestionali       JSON NULL,                              -- Dati aggiuntivi dal XML
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_numero_linea (numero_linea),
    INDEX idx_aliquota_iva (aliquota_iva_id),
    INDEX idx_natura_iva (natura_iva_id),
    INDEX idx_consumo_tipo (consumo_tipo),
    INDEX idx_unita_immobiliare (unita_immobiliare_id),
    INDEX idx_categoria_servizio (categoria_servizio),
    UNIQUE KEY unique_fattura_linea (fattura_elettronica_id, numero_linea),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE,
    FOREIGN KEY (unita_misura_id) REFERENCES unita_misura(id) ON DELETE SET NULL,
    FOREIGN KEY (aliquota_iva_id) REFERENCES iva_tipologie(id) ON DELETE SET NULL,
    FOREIGN KEY (natura_iva_id) REFERENCES nature_iva(id) ON DELETE SET NULL,
    FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id) ON DELETE SET NULL,
    
    -- Constraints
    CONSTRAINT chk_quantita_positiva CHECK (quantita > 0),
    CONSTRAINT chk_prezzo_unitario CHECK (prezzo_unitario >= 0),
    CONSTRAINT chk_prezzo_totale CHECK (prezzo_totale >= 0),
    CONSTRAINT chk_sconto_percentuale CHECK (sconto_percentuale >= 0 AND sconto_percentuale <= 100),
    CONSTRAINT chk_consumo_quantita CHECK (consumo_quantita >= 0),
    CONSTRAINT chk_consumo_periodo CHECK (consumo_periodo_al >= consumo_periodo_dal OR (consumo_periodo_al IS NULL AND consumo_periodo_dal IS NULL))
);

B. RIEPILOGHI IVA

CREATE TABLE fatture_riepiloghi_iva (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    
    -- Dati IVA
    aliquota_iva_id             BIGINT NULL,                            -- FK iva_tipologie.id
    aliquota_iva_custom         DECIMAL(5,2) NULL,                      -- Se aliquota non in tabella
    natura_iva_id               BIGINT NULL,                            -- FK nature_iva.id (per esenti)
    
    -- Importi
    imponibile_importo          DECIMAL(12,2) NOT NULL,                 -- Imponibile
    imposta                     DECIMAL(12,2) NOT NULL,                 -- IVA
    spese_accessorie            DECIMAL(10,2) DEFAULT 0,                -- Spese accessorie
    arrotondamento              DECIMAL(8,2) DEFAULT 0,                 -- Arrotondamento
    
    -- Esigibilità
    esigibilita_iva             VARCHAR(1) DEFAULT 'I',                 -- I=Immediata, D=Differita, S=Split payment
    
    -- Riferimenti Normativi
    riferimento_normativo       TEXT NULL,                              -- Riferimento normativo per esenzioni
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_aliquota_iva (aliquota_iva_id),
    INDEX idx_natura_iva (natura_iva_id),
    INDEX idx_esigibilita (esigibilita_iva),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE,
    FOREIGN KEY (aliquota_iva_id) REFERENCES iva_tipologie(id) ON DELETE SET NULL,
    FOREIGN KEY (natura_iva_id) REFERENCES nature_iva(id) ON DELETE SET NULL,
    
    -- Constraints
    CONSTRAINT chk_imponibile_positivo CHECK (imponibile_importo >= 0),
    CONSTRAINT chk_imposta_positiva CHECK (imposta >= 0)
);

C. PAGAMENTI

CREATE TABLE fatture_pagamenti (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    numero_pagamento            INT DEFAULT 1,                          -- Numero progressivo (per rate multiple)
    
    -- Condizioni Pagamento
    condizioni_pagamento        VARCHAR(4) NOT NULL,                    -- TP01, TP02, TP03, etc.
    modalita_pagamento          VARCHAR(4) NOT NULL,                    -- MP01, MP05, etc.
    
    -- Date
    data_riferimento_termini    DATE NULL,                              -- Data riferimento per termini
    giorni_termini_pagamento    INT NULL,                               -- Giorni per pagamento
    data_scadenza_pagamento     DATE NOT NULL,                          -- Data scadenza
    
    -- Importo
    importo_pagamento           DECIMAL(12,2) NOT NULL,                 -- Importo da pagare
    
    -- Dati Bancari
    istituto_finanziario        VARCHAR(255) NULL,                      -- Nome banca
    iban                        VARCHAR(34) NULL,                       -- IBAN
    abi                         VARCHAR(5) NULL,                        -- Codice ABI
    cab                         VARCHAR(5) NULL,                        -- Codice CAB
    bic                         VARCHAR(11) NULL,                       -- BIC/SWIFT
    
    -- Codici Pagamento
    codice_pagamento            VARCHAR(100) NULL,                      -- Codice/descrizione pagamento
    cro                         VARCHAR(30) NULL,                       -- CRO
    cuc                         VARCHAR(30) NULL,                       -- CUC
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_data_scadenza (data_scadenza_pagamento),
    INDEX idx_modalita (modalita_pagamento),
    INDEX idx_iban (iban),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE,
    
    -- Constraints
    CONSTRAINT chk_importo_pagamento_positivo CHECK (importo_pagamento > 0),
    CONSTRAINT chk_giorni_termini CHECK (giorni_termini_pagamento >= 0)
);

D. RICEVUTE SDI E NOTIFICHE

CREATE TABLE fatture_ricevute_sdi (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    
    -- Dati Ricevuta SDI
    tipo_ricevuta               ENUM('RICEVUTA_CONSEGNA','NOTIFICA_ESITO','RICEVUTA_SCARTO','ALTRO') NOT NULL,
    identificativo_sdi          BIGINT NULL,                            -- ID univoco SDI
    nome_file_ricevuta          VARCHAR(500) NOT NULL,                  -- Nome file ricevuta
    hash_ricevuta               VARCHAR(64) NULL,                       -- Hash ricevuta
    data_ora_ricezione          TIMESTAMP NULL,                         -- Timestamp ricezione
    message_id                  VARCHAR(20) NULL,                       -- Message ID SDI
    
    -- Esito
    esito                       ENUM('ACCETTATA','RIFIUTATA','CONSEGNATA','MANCATA_CONSEGNA') NULL,
    motivo_rifiuto              TEXT NULL,                              -- Motivo se rifiutata
    
    -- Contenuto XML
    contenuto_xml_ricevuta      LONGTEXT NULL,                          -- XML completo ricevuta
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_tipo_ricevuta (tipo_ricevuta),
    INDEX idx_identificativo_sdi (identificativo_sdi),
    INDEX idx_esito (esito),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE
);

E. ERRORI SDI

CREATE TABLE fatture_errori_sdi (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    ricevuta_sdi_id             BIGINT NULL,                            -- FK fatture_ricevute_sdi.id
    
    -- Dati Errore
    codice_errore               VARCHAR(10) NOT NULL,                   -- Codice errore SDI (es: 00002)
    descrizione_errore          TEXT NOT NULL,                          -- Descrizione errore
    posizione_errore            VARCHAR(255) NULL,                      -- Posizione nel XML se disponibile
    
    -- Classificazione
    gravita                     ENUM('FATALE','WARNING','INFO') DEFAULT 'FATALE',
    categoria                   VARCHAR(100) NULL,                      -- Categoria errore (FORMATO, DATI, etc.)
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_ricevuta (ricevuta_sdi_id),
    INDEX idx_codice_errore (codice_errore),
    INDEX idx_gravita (gravita),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE,
    FOREIGN KEY (ricevuta_sdi_id) REFERENCES fatture_ricevute_sdi(id) ON DELETE CASCADE
);

F. FIRME DIGITALI

CREATE TABLE fatture_firme_digitali (
    -- Identificativi
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    fattura_elettronica_id      BIGINT NOT NULL,                        -- FK fatture_elettroniche.id
    
    -- Dati Firma
    tipo_firma                  ENUM('XADES','CADES','PADES') DEFAULT 'XADES',
    algoritmo_firma             VARCHAR(100) NULL,                      -- rsa-sha256, etc.
    timestamp_firma             TIMESTAMP NULL,                         -- Momento della firma
    
    -- Certificato
    certificato_x509            LONGTEXT NULL,                          -- Certificato X509 completo
    issuer_certificato          VARCHAR(500) NULL,                      -- Emittente certificato
    subject_certificato         VARCHAR(500) NULL,                      -- Soggetto certificato
    serial_number               VARCHAR(100) NULL,                      -- Numero seriale
    data_scadenza_certificato   DATE NULL,                              -- Scadenza certificato
    
    -- Validazione
    firma_valida                BOOLEAN NULL,                           -- Se firma valida
    certificato_valido          BOOLEAN NULL,                           -- Se certificato valido
    data_validazione            TIMESTAMP NULL,                         -- Quando validata
    errori_validazione          TEXT NULL,                              -- Errori di validazione
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_fattura (fattura_elettronica_id),
    INDEX idx_tipo_firma (tipo_firma),
    INDEX idx_timestamp_firma (timestamp_firma),
    INDEX idx_firma_valida (firma_valida),
    INDEX idx_scadenza_certificato (data_scadenza_certificato),
    
    -- Foreign Keys
    FOREIGN KEY (fattura_elettronica_id) REFERENCES fatture_elettroniche(id) ON DELETE CASCADE
);

3. TABELLE DI CONFIGURAZIONE ESPANDIBILI

A. TIPOLOGIE IVA

CREATE TABLE iva_tipologie (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(10) NOT NULL UNIQUE,            -- Codice aliquota (22, 10, 4, etc.)
    aliquota                    DECIMAL(5,2) NOT NULL,                  -- Percentuale
    descrizione                 VARCHAR(255) NOT NULL,                  -- Descrizione
    attiva                      BOOLEAN DEFAULT TRUE,                   -- Se attiva
    data_inizio_validita        DATE NOT NULL,                          -- Da quando valida
    data_fine_validita          DATE NULL,                              -- Fino a quando valida
    note                        TEXT NULL,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_aliquota (aliquota),
    INDEX idx_attiva (attiva),
    INDEX idx_validita (data_inizio_validita, data_fine_validita),
    
    -- Constraints
    CONSTRAINT chk_aliquota_range CHECK (aliquota >= 0 AND aliquota <= 100)
);

-- Inserimento dati iniziali IVA Italia
INSERT INTO iva_tipologie (codice, aliquota, descrizione, data_inizio_validita) VALUES
('22', 22.00, 'Aliquota ordinaria 22%', '2013-10-01'),
('10', 10.00, 'Aliquota ridotta 10%', '1973-01-01'),
('4', 4.00, 'Aliquota super ridotta 4%', '1973-01-01'),
('0', 0.00, 'Aliquota zero', '1973-01-01'),
('5', 5.00, 'Aliquota ridotta 5%', '1995-01-01');

B. NATURE IVA (per esenzioni)

CREATE TABLE nature_iva (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(4) NOT NULL UNIQUE,             -- N1, N2, N3, etc.
    descrizione                 VARCHAR(255) NOT NULL,                  -- Descrizione natura
    riferimento_normativo       TEXT NULL,                              -- Riferimento normativo
    attiva                      BOOLEAN DEFAULT TRUE,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_attiva (attiva)
);

-- Inserimento nature IVA standard
INSERT INTO nature_iva (codice, descrizione, riferimento_normativo) VALUES
('N1', 'Escluse ex art. 15', 'DPR 633/72, art. 15'),
('N2', 'Non soggette', 'Art. 7-bis DPR 633/72'),
('N3', 'Non imponibili', 'DPR 633/72'),
('N4', 'Esenti', 'DPR 633/72'),
('N5', 'Regime del margine', 'DPR 633/72'),
('N6', 'Inversione contabile', 'Art. 17 DPR 633/72'),
('N7', 'IVA assolta in altro stato UE', 'Art. 7-ter DPR 633/72');

C. CAUSALI PAGAMENTO RITENUTA

CREATE TABLE causali_pagamento_ritenuta (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(4) NOT NULL UNIQUE,             -- A, B, C, D, etc.
    descrizione                 VARCHAR(255) NOT NULL,                  -- Descrizione causale
    aliquota_standard           DECIMAL(5,2) NULL,                      -- Aliquota standard per questa causale
    attiva                      BOOLEAN DEFAULT TRUE,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_attiva (attiva)
);

-- Inserimento causali standard
INSERT INTO causali_pagamento_ritenuta (codice, descrizione, aliquota_standard) VALUES
('A', 'Prestazioni di lavoro autonomo rientranti nell''esercizio di arte o professione abituale', 20.00),
('B', 'Utilizzazione economica di opere dell''ingegno', 20.00),
('C', 'Utili da partecipazione', 26.00),
('D', 'Prestazioni di lavoro autonomo non rientranti nell''esercizio di arte o professione abituale', 20.00),
('E', 'Prestazioni di lavoro autonomo non rientranti nell''esercizio di arte o professione abituale per le quali non è richiesta l''iscrizione a specifici albi professionali', 20.00),
('T', 'Prestazioni effettuate da soggetti non residenti', 30.00);

D. UNITÀ DI MISURA

CREATE TABLE unita_misura (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(10) NOT NULL UNIQUE,            -- NR, KG, M, M2, M3, KWH, etc.
    descrizione                 VARCHAR(100) NOT NULL,                  -- Descrizione
    categoria                   VARCHAR(50) NULL,                       -- Categoria (DIMENSIONE, PESO, ENERGIA, etc.)
    attiva                      BOOLEAN DEFAULT TRUE,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_categoria (categoria),
    INDEX idx_attiva (attiva)
);

-- Inserimento unità di misura standard
INSERT INTO unita_misura (codice, descrizione, categoria) VALUES
('NR', 'Numero', 'QUANTITA'),
('PZ', 'Pezzo', 'QUANTITA'),
('KG', 'Chilogrammo', 'PESO'),
('M', 'Metro', 'DIMENSIONE'),
('M2', 'Metro quadrato', 'SUPERFICIE'),
('M3', 'Metro cubo', 'VOLUME'),
('LT', 'Litro', 'VOLUME'),
('KWH', 'Chilowattora', 'ENERGIA'),
('MC', 'Metro cubo (gas)', 'ENERGIA'),
('GG', 'Giorni', 'TEMPO'),
('MM', 'Mesi', 'TEMPO'),
('AA', 'Anni', 'TEMPO'),
('HR', 'Ore', 'TEMPO');

E. COMUNI ITALIANI

CREATE TABLE comuni_italiani (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice_istat                VARCHAR(6) NOT NULL UNIQUE,             -- Codice ISTAT
    denominazione               VARCHAR(255) NOT NULL,                  -- Nome comune
    provincia                   VARCHAR(2) NOT NULL,                    -- Sigla provincia
    regione                     VARCHAR(50) NOT NULL,                   -- Nome regione
    cap                         VARCHAR(5) NULL,                        -- CAP principale
    attivo                      BOOLEAN DEFAULT TRUE,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_provincia (provincia),
    INDEX idx_regione (regione),
    INDEX idx_denominazione (denominazione),
    INDEX idx_attivo (attivo)
);

-- Inserimento comuni principali (esempio per Roma)
INSERT INTO comuni_italiani (codice_istat, denominazione, provincia, regione, cap) VALUES
('058091', 'Roma', 'RM', 'Lazio', '00100'),
('015146', 'Milano', 'MI', 'Lombardia', '20100'),
('072006', 'Napoli', 'NA', 'Campania', '80100'),
('010025', 'Torino', 'TO', 'Piemonte', '10100');

F. TIPOLOGIE CONTRIBUENTE

CREATE TABLE tipologie_contribuente (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(10) NOT NULL UNIQUE,            -- RF01, RF02, etc.
    descrizione                 VARCHAR(255) NOT NULL,                  -- Descrizione regime
    categoria                   VARCHAR(50) NULL,                       -- Categoria (ORDINARIO, AGEVOLATO, etc.)
    attiva                      BOOLEAN DEFAULT TRUE,
    
    -- Sistema
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_categoria (categoria),
    INDEX idx_attiva (attiva)
);

-- Inserimento regimi fiscali standard
INSERT INTO tipologie_contribuente (codice, descrizione, categoria) VALUES
('RF01', 'Ordinario', 'ORDINARIO'),
('RF02', 'Contribuenti minimi', 'AGEVOLATO'),
('RF04', 'Agricoltura e attività connesse e pesca', 'SETTORIALE'),
('RF05', 'Vendita sali e tabacchi', 'SETTORIALE'),
('RF06', 'Commercio fiammiferi', 'SETTORIALE'),
('RF07', 'Editoria', 'SETTORIALE'),
('RF08', 'Gestione servizi telefonia pubblica', 'SETTORIALE'),
('RF09', 'Rivendita documenti di trasporto pubblico e di sosta', 'SETTORIALE'),
('RF10', 'Intrattenimenti, giochi e altre attività', 'SETTORIALE'),
('RF11', 'Agenzie di viaggi e turismo', 'SETTORIALE'),
('RF12', 'Agriturismo', 'SETTORIALE'),
('RF13', 'Vendite a domicilio', 'SETTORIALE'),
('RF14', 'Rivendita beni usati, oggetti d''arte, d''antiquariato o da collezione', 'SETTORIALE'),
('RF15', 'Agenzie di vendite all''asta di oggetti d''arte, antiquariato o da collezione', 'SETTORIALE'),
('RF16', 'IVA per cassa P.A.', 'PUBBLICO'),
('RF17', 'IVA per cassa', 'ORDINARIO'),
('RF19', 'Forfettario', 'AGEVOLATO'),
('RF18', 'Altro', 'ALTRO');

G. CODICI ERRORE SDI UFFICIALI

CREATE TABLE codici_errore_sdi (
    id                          BIGINT PRIMARY KEY AUTO_INCREMENT,
    codice                      VARCHAR(10) NOT NULL UNIQUE,           -- Codice errore (es: 00002)
    descrizione                 TEXT NOT NULL,                          -- Descrizione ufficiale
    categoria                   VARCHAR(100) NULL,                      -- Categoria (FORMATO, DATI, etc.)
    gravita                     ENUM('FATALE','WARNING','INFO') DEFAULT 'FATALE',
    risoluzione_suggerita       TEXT NULL,                              -- Come risolvere
    
    -- Sistema
    attivo                      BOOLEAN DEFAULT TRUE,
    created_at                  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- Indici
    INDEX idx_codice (codice),
    INDEX idx_categoria (categoria),
    INDEX idx_gravita (gravita)
);

-- Inserimento codici errore principali
INSERT INTO codici_errore_sdi (codice, descrizione, categoria, gravita, risoluzione_suggerita) VALUES
('00001', 'File non trovato', 'SISTEMA', 'FATALE', 'Verificare che il file sia presente'),
('00002', 'Nome file duplicato', 'DUPLICATO', 'FATALE', 'Modificare il progressivo invio'),
('00003', 'File non leggibile', 'FORMATO', 'FATALE', 'Verificare formato XML'),
('00100', 'Errore generico', 'GENERICO', 'FATALE', 'Verificare contenuto fattura'),
('00101', 'Partita IVA non valida', 'DATI', 'FATALE', 'Verificare P.IVA cedente'),
('00102', 'Codice fiscale non valido', 'DATI', 'FATALE', 'Verificare CF cessionario'),
('00200', 'Formato trasmissione non supportato', 'FORMATO', 'FATALE', 'Usare formato FPR12'),
('00300', 'Errore nella firma digitale', 'FIRMA', 'FATALE', 'Verificare certificato e firma'),
('00301', 'Certificato scaduto', 'FIRMA', 'FATALE', 'Rinnovare certificato di firma'),
('00400', 'Destinatario non trovato', 'DESTINATARIO', 'FATALE', 'Verificare codice destinatario o PEC');

📋 MIGRATION LARAVEL COMPLETA

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;

return new class extends Migration
{
    public function up()
    {
        // 1. Tabelle di configurazione (devono essere create prima)
        $this->createConfigurationTables();
        
        // 2. Tabella principale fatture elettroniche
        $this->createFattureElettronicheTable();
        
        // 3. Tabelle collegate
        $this->createRelatedTables();
        
        // 4. Trigger e procedure
        $this->createTriggersAndProcedures();
        
        // 5. Inserimento dati iniziali
        $this->insertInitialData();
    }
    
    private function createConfigurationTables()
    {
        // Tipologie IVA
        Schema::create('iva_tipologie', function (Blueprint $table) {
            $table->id();
            $table->string('codice', 10)->unique();
            $table->decimal('aliquota', 5, 2);
            $table->string('descrizione');
            $table->boolean('attiva')->default(true);
            $table->date('data_inizio_validita');
            $table->date('data_fine_validita')->nullable();
            $table->text('note')->nullable();
            $table->timestamps();
            
            $table->index(['aliquota']);
            $table->index(['attiva']);
            $table->index(['data_inizio_validita', 'data_fine_validita']);
        });
        
        // Nature IVA
        Schema::create('nature_iva', function (Blueprint $table) {
            $table->id();
            $table->string('codice', 4)->unique();
            $table->string('descrizione');
            $table->text('riferimento_normativo')->nullable();
            $table->boolean('attiva')->default(true);
            $table->timestamps();
            
            $table->index(['attiva']);
        });
        
        // Causali pagamento ritenuta
        Schema::create('causali_pagamento_ritenuta', function (Blueprint $table) {
            $table->id();
            $table->string('codice', 4)->unique();
            $table->string('descrizione');
            $table->decimal('aliquota_standard', 5, 2)->nullable();
            $table->boolean('attiva')->default(true);
            $table->timestamps();
            
            $table->index(['attiva']);
        });
        
        // Unità di misura
        Schema::create('unita_misura', function (Blueprint $table) {
            $table->id();
            $table->string('codice', 10)->unique();
            $table->string('descrizione', 100);
            $table->string('categoria', 50)->nullable();
            $table->boolean('attiva')->default(true);
            $table->timestamps();
            
            $table->index(['categoria']);
            $table->index(['attiva']);
        });
        
        // Comuni italiani
        Schema::create('comuni_italiani', function (Blueprint $table) {
            $table->id();
            $table->string('codice_istat', 6)->unique();
            $table->string('denominazione');
            $table->string('provincia', 2);
            $table->string('regione', 50);
            $table->string('cap', 5)->nullable();
            $table->boolean('attivo')->default(true);
            $table->timestamps();
            
            $table->index(['provincia']);
            $table->index(['regione']);
            $table->index(['denominazione']);
            $table->index(['attivo']);
        });
        
        // Tipologie contribuente
        Schema::create('tipologie_contribuente', function (Blueprint $table) {
            $table->id();
            $table->string('codice', 10)->unique();
            $table->string('descrizione');
            $table->string('categoria', 50)->nullable();
            $table->boolean('attiva')->default(true);
            $table->timestamps();
            
            $table->index(['categoria']);
            $table->index(['attiva']);
        });
    }
    
    private function createFattureElettronicheTable()
    {
        Schema::create('fatture_elettroniche', function (Blueprint $table) {
            // Identificativi
            $table->id();
            $table->uuid('uuid')->unique();
            
            // Multi-tenant
            $table->foreignId('gestione_id')->constrained('gestioni')->onDelete('cascade');
            
            // Dati XML
            $table->string('nome_file_xml', 500);
            $table->string('hash_file_xml', 64)->unique();
            $table->longText('contenuto_xml_originale')->nullable();
            $table->string('versione_xml', 10)->default('FPR12');
            
            // Trasmissione
            $table->string('id_trasmittente_paese', 2)->default('IT');
            $table->string('id_trasmittente_codice', 11);
            $table->string('progressivo_invio', 10);
            $table->string('formato_trasmissione', 10)->default('FPR12');
            $table->string('codice_destinatario', 7)->nullable();
            
            // Documento
            $table->string('tipo_documento', 4)->default('TD01');
            $table->string('numero_fattura', 50);
            $table->date('data_fattura');
            $table->string('divisa', 3)->default('EUR');
            
            // Importi
            $table->decimal('importo_totale_documento', 12, 2);
            $table->decimal('arrotondamento', 8, 2)->default(0);
            
            // Cedente/Prestatore
            $table->string('cedente_partita_iva', 11)->nullable();
            $table->string('cedente_codice_fiscale', 16)->nullable();
            $table->string('cedente_denominazione');
            $table->string('cedente_regime_fiscale', 4)->nullable();
            $table->string('cedente_indirizzo')->nullable();
            $table->string('cedente_cap', 5)->nullable();
            $table->string('cedente_comune', 100)->nullable();
            $table->string('cedente_provincia', 2)->nullable();
            $table->string('cedente_nazione', 2)->default('IT');
            $table->string('cedente_telefono', 20)->nullable();
            $table->string('cedente_email')->nullable();
            
            // Cessionario/Committente
            $table->string('cessionario_codice_fiscale', 16)->nullable();
            $table->string('cessionario_denominazione');
            $table->string('cessionario_indirizzo')->nullable();
            $table->string('cessionario_cap', 5)->nullable();
            $table->string('cessionario_comune', 100)->nullable();
            $table->string('cessionario_provincia', 2)->nullable();
            $table->string('cessionario_nazione', 2)->default('IT');
            
            // Ritenute
            $table->boolean('ha_ritenuta')->default(false);
            $table->string('tipo_ritenuta', 4)->nullable();
            $table->decimal('importo_ritenuta', 10, 2)->default(0);
            $table->decimal('aliquota_ritenuta', 5, 2)->default(0);
            $table->foreignId('causale_pagamento_id')->nullable()->constrained('causali_pagamento_ritenuta')->onDelete('set null');
            
            // Bollo
            $table->boolean('bollo_virtuale')->default(false);
            $table->decimal('importo_bollo', 8, 2)->default(0);
            
            // Causale
            $table->text('causale')->nullable();
            $table->text('note')->nullable();
            
            // Stato
            $table->enum('stato_import', ['IMPORTATA','ELABORATA','CONTABILIZZATA','PAGATA','ERRORE'])->default('IMPORTATA');
            $table->text('errori_import')->nullable();
            $table->timestamp('data_import')->useCurrent();
            
            // Collegamenti
            $table->foreignId('contabilita_id')->nullable()->constrained('contabilita')->onDelete('set null');
            $table->foreignId('movimento_bancario_id')->nullable()->constrained('movimenti_bancari')->onDelete('set null');
            
            // Matching
            $table->string('fornitore_normalizzato')->nullable();
            $table->string('categoria_fornitore', 100)->nullable();
            $table->json('keywords_riconoscimento')->nullable();
            
            // Sistema
            $table->boolean('attiva')->default(true);
            $table->timestamps();
            $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
            $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
            
            // Indici
            $table->index(['gestione_id']);
            $table->index(['data_fattura']);
            $table->index(['numero_fattura']);
            $table->index(['cedente_partita_iva']);
            $table->index(['importo_totale_documento']);
            $table->index(['tipo_documento']);
            $table->index(['stato_import']);
            $table->index(['categoria_fornitore']);
        });
    }
    
    private function createRelatedTables()
    {
        // Righe fattura
        Schema::create('fatture_righe', function (Blueprint $table) {
            $table->id();
            $table->foreignId('fattura_elettronica_id')->constrained('fatture_elettroniche')->onDelete('cascade');
            $table->integer('numero_linea');
            
            // Descrizione
            $table->text('descrizione');
            $table->string('descrizione_normalizzata', 500)->nullable();
            
            // Quantità
            $table->decimal('quantita', 12, 6)->default(1);
            $table->foreignId('unita_misura_id')->nullable()->constrained('unita_misura')->onDelete('set null');
            $table->string('unita_misura_custom', 10)->nullable();
            
            // Prezzi
            $table->decimal('prezzo_unitario', 12, 6);
            $table->decimal('prezzo_totale', 12, 2);
            $table->decimal('sconto_percentuale', 5, 2)->default(0);
            $table->decimal('sconto_importo', 10, 2)->default(0);
            
            // IVA
            $table->foreignId('aliquota_iva_id')->nullable()->constrained('iva_tipologie')->onDelete('set null');
            $table->decimal('aliquota_iva_custom', 5, 2)->nullable();
            $table->foreignId('natura_iva_id')->nullable()->constrained('nature_iva')->onDelete('set null');
            
            // Ritenute
            $table->boolean('soggetta_ritenuta')->default(false);
            
            // Consumi
            $table->enum('consumo_tipo', ['ENERGIA_ELETTRICA','ACQUA','GAS','RISCALDAMENTO','ALTRO'])->nullable();
            $table->decimal('consumo_quantita', 12, 3)->nullable();
            $table->string('consumo_unita', 10)->nullable();
            $table->date('consumo_periodo_dal')->nullable();
            $table->date('consumo_periodo_al')->nullable();
            $table->decimal('consumo_lettura_precedente', 12, 3)->nullable();
            $table->decimal('consumo_lettura_attuale', 12, 3)->nullable();
            $table->decimal('consumo_coefficiente', 8, 4)->default(1);
            $table->text('consumo_note')->nullable();
            
            // Ripartizione
            $table->foreignId('unita_immobiliare_id')->nullable()->constrained('unita_immobiliari')->onDelete('set null');
            $table->enum('ripartizione_tipo', ['MILLESIMI_GENERALI','MILLESIMI_SCALE','MILLESIMI_ASCENSORE','MILLESIMI_RISCALDAMENTO','PARTI_UGUALI','PERSONALIZZATA','SPECIFICO'])->nullable();
            
            // Categorie
            $table->string('categoria_servizio', 100)->nullable();
            $table->string('sottocategoria', 100)->nullable();
            
            // Altri dati
            $table->json('altri_dati_gestionali')->nullable();
            
            $table->timestamps();
            
            // Indici e vincoli
            $table->unique(['fattura_elettronica_id', 'numero_linea'], 'unique_fattura_linea');
            $table->index(['consumo_tipo']);
            $table->index(['categoria_servizio']);
        });
        
        // Riepiloghi IVA
        Schema::create('fatture_riepiloghi_iva', function (Blueprint $table) {
            $table->id();
            $table->foreignId('fattura_elettronica_id')->constrained('fatture_elettroniche')->onDelete('cascade');
            
            $table->foreignId('aliquota_iva_id')->nullable()->constrained('iva_tipologie')->onDelete('set null');
            $table->decimal('aliquota_iva_custom', 5, 2)->nullable();
            $table->foreignId('natura_iva_id')->nullable()->constrained('nature_iva')->onDelete('set null');
            
            $table->decimal('imponibile_importo', 12, 2);
            $table->decimal('imposta', 12, 2);
            $table->decimal('spese_accessorie', 10, 2)->default(0);
            $table->decimal('arrotondamento', 8, 2)->default(0);
            
            $table->string('esigibilita_iva', 1)->default('I');
            $table->text('riferimento_normativo')->nullable();
            
            $table->timestamps();
            
            $table->index(['fattura_elettronica_id']);
            $table->index(['esigibilita_iva']);
        });
        
        // Pagamenti
        Schema::create('fatture_pagamenti', function (Blueprint $table) {
            $table->id();
            $table->foreignId('fattura_elettronica_id')->constrained('fatture_elettroniche')->onDelete('cascade');
            $table->integer('numero_pagamento')->default(1);
            
            $table->string('condizioni_pagamento', 4);
            $table->string('modalita_pagamento', 4);
            
            $table->date('data_riferimento_termini')->nullable();
            $table->integer('giorni_termini_pagamento')->nullable();
            $table->date('data_scadenza_pagamento');
            
            $table->decimal('importo_pagamento', 12, 2);
            
            $table->string('istituto_finanziario')->nullable();
            $table->string('iban', 34)->nullable();
            $table->string('abi', 5)->nullable();
            $table->string('cab', 5)->nullable();
            $table->string('bic', 11)->nullable();
            
            $table->string('codice_pagamento', 100)->nullable();
            $table->string('cro', 30)->nullable();
            $table->string('cuc', 30)->nullable();
            
            $table->timestamps();
            
            $table->index(['fattura_elettronica_id']);
            $table->index(['data_scadenza_pagamento']);
            $table->index(['modalita_pagamento']);
            $table->index(['iban']);
        });
    }
    
    private function createTriggersAndProcedures()
    {
        // Trigger UUID automatico
        DB::unprepared('
            CREATE TRIGGER trg_fatture_elettroniche_uuid 
            BEFORE INSERT ON fatture_elettroniche 
            FOR EACH ROW 
            BEGIN 
                IF NEW.uuid IS NULL OR NEW.uuid = "" THEN 
                    SET NEW.uuid = UUID(); 
                END IF; 
            END
        ');
        
        // Trigger normalizzazione fornitore
        DB::unprepared('
            CREATE TRIGGER trg_fatture_normalizza_fornitore 
            BEFORE INSERT ON fatture_elettroniche 
            FOR EACH ROW 
            BEGIN 
                SET NEW.fornitore_normalizzato = UPPER(TRIM(NEW.cedente_denominazione));
                SET NEW.fornitore_normalizzato = REPLACE(NEW.fornitore_normalizzato, "S.R.L.", "SRL");
                SET NEW.fornitore_normalizzato = REPLACE(NEW.fornitore_normalizzato, "S.P.A.", "SPA");
                SET NEW.fornitore_normalizzato = REPLACE(NEW.fornitore_normalizzato, "S.N.C.", "SNC");
            END
        ');
    }
    
    private function insertInitialData()
    {
        // IVA
        DB::table('iva_tipologie')->insert([
            ['codice' => '22', 'aliquota' => 22.00, 'descrizione' => 'Aliquota ordinaria 22%', 'data_inizio_validita' => '2013-10-01'],
            ['codice' => '10', 'aliquota' => 10.00, 'descrizione' => 'Aliquota ridotta 10%', 'data_inizio_validita' => '1973-01-01'],
            ['codice' => '4', 'aliquota' => 4.00, 'descrizione' => 'Aliquota super ridotta 4%', 'data_inizio_validita' => '1973-01-01'],
            ['codice' => '0', 'aliquota' => 0.00, 'descrizione' => 'Aliquota zero', 'data_inizio_validita' => '1973-01-01'],
        ]);
        
        // Nature IVA
        DB::table('nature_iva')->insert([
            ['codice' => 'N1', 'descrizione' => 'Escluse ex art. 15', 'riferimento_normativo' => 'DPR 633/72, art. 15'],
            ['codice' => 'N2', 'descrizione' => 'Non soggette', 'riferimento_normativo' => 'Art. 7-bis DPR 633/72'],
            ['codice' => 'N3', 'descrizione' => 'Non imponibili', 'riferimento_normativo' => 'DPR 633/72'],
            ['codice' => 'N4', 'descrizione' => 'Esenti', 'riferimento_normativo' => 'DPR 633/72'],
        ]);
        
        // Causali ritenuta
        DB::table('causali_pagamento_ritenuta')->insert([
            ['codice' => 'A', 'descrizione' => 'Prestazioni di lavoro autonomo', 'aliquota_standard' => 20.00],
            ['codice' => 'D', 'descrizione' => 'Prestazioni lavoro autonomo non abituali', 'aliquota_standard' => 20.00],
            ['codice' => 'T', 'descrizione' => 'Prestazioni soggetti non residenti', 'aliquota_standard' => 30.00],
        ]);
        
        // Unità misura
        DB::table('unita_misura')->insert([
            ['codice' => 'NR', 'descrizione' => 'Numero', 'categoria' => 'QUANTITA'],
            ['codice' => 'KWH', 'descrizione' => 'Chilowattora', 'categoria' => 'ENERGIA'],
            ['codice' => 'M3', 'descrizione' => 'Metro cubo', 'categoria' => 'VOLUME'],
            ['codice' => 'LT', 'descrizione' => 'Litro', 'categoria' => 'VOLUME'],
        ]);
    }

    public function down()
    {
        DB::unprepared('DROP TRIGGER IF EXISTS trg_fatture_elettroniche_uuid');
        DB::unprepared('DROP TRIGGER IF EXISTS trg_fatture_normalizza_fornitore');
        
        Schema::dropIfExists('fatture_pagamenti');
        Schema::dropIfExists('fatture_riepiloghi_iva');
        Schema::dropIfExists('fatture_righe');
        Schema::dropIfExists('fatture_elettroniche');
        Schema::dropIfExists('tipologie_contribuente');
        Schema::dropIfExists('comuni_italiani');
        Schema::dropIfExists('unita_misura');
        Schema::dropIfExists('causali_pagamento_ritenuta');
        Schema::dropIfExists('nature_iva');
        Schema::dropIfExists('iva_tipologie');
    }
};

🔄 PROSSIMI STEP

Completato: Sistema Fatture Elettroniche modulare e espandibile con SDI
🔄 Prossimo: Eloquent Models e Business Logic
Seguente: XML Parser Service per import automatico con gestione ricevute SDI

Il sistema Fatture Elettroniche è ora completo con:

  • 📄 Struttura modulare espandibile
  • 🗄️ Tabelle configurazione separate
  • Dati consumi per statistiche
  • 🔗 Collegamenti contabili e bancari
  • 📊 Ripartizione automatica per unità
  • 🏛️ Integrazione SDI completa con ricevute, errori e firme digitali
  • 📋 Tracciamento stati e notifiche del Sistema di Interscambio
  • 🔐 Gestione firme e certificati X509
  • ⚠️ Codici errore ufficiali per diagnostica avanzata

🆕 NUOVE FUNZIONALITÀ SDI

  1. 📨 Ricevute Sistema: Tracciamento completo ricevute di consegna, notifiche esito e scarti
  2. ⚠️ Gestione Errori: Catalogazione errori SDI con codici ufficiali e soluzioni
  3. 🔐 Firme Digitali: Validazione certificati X509 e verifica integrità
  4. 📊 Stati Avanzati: Monitoraggio completo del ciclo di vita delle fatture nel SDI
  5. 🔍 Diagnostica: Sistema di troubleshooting con risoluzione guidata errori

Vuoi che proceda con i Models Laravel e la Business Logic per l'import XML con gestione SDI? 🚀