Riferimento API

XML Builder

Package @fatturazione-elettronica-aruba/xml-builder

XML Builder

Costruzione, validazione e serializzazione fatture elettroniche FatturaPA.

FatturaBuilder

Builder fluent per la costruzione di fatture.

import { FatturaBuilder } from '@fatturazione-elettronica-aruba/xml-builder';

const builder = FatturaBuilder.create();

Metodi

create()

Crea una nuova istanza del builder.

const builder = FatturaBuilder.create();

setVersione(versione)

Imposta la versione dello schema (default: '1.2.2').

builder.setVersione('1.2.2');

setDatiTrasmissione(dati)

Imposta i dati di trasmissione completi.

builder.setDatiTrasmissione({
  idTrasmittente: { idPaese: 'IT', idCodice: '01234567890' },
  progressivoInvio: '00001',
  formatoTrasmissione: 'FPR12',
  codiceDestinatario: 'ABC1234',
  pecDestinatario?: string,
  contattiTrasmittente?: { telefono?: string, email?: string },
});

setTrasmissioneB2B(params)

Helper per trasmissione B2B (formato FPR12).

builder.setTrasmissioneB2B({
  idPaese: string;
  idCodice: string;
  progressivoInvio: string;
  codiceDestinatario?: string;  // Default: '0000000'
  pecDestinatario?: string;
});

setTrasmissionePA(params)

Helper per trasmissione PA (formato FPA12).

builder.setTrasmissionePA({
  idPaese: string;
  idCodice: string;
  progressivoInvio: string;
  codiceDestinatario: string;   // Codice IPA 6 caratteri
});

setCedentePrestatore(cedente)

Imposta il cedente/prestatore (venditore).

builder.setCedentePrestatore({
  datiAnagrafici: {
    idFiscaleIVA?: { idPaese: string, idCodice: string },
    codiceFiscale?: string,
    anagrafica: { denominazione?: string, nome?: string, cognome?: string },
    regimeFiscale: RegimeFiscale,
  },
  sede: Indirizzo,
  stabileOrganizzazione?: Indirizzo,
  iscrizioneREA?: IscrizioneREA,
  contatti?: Contatti,
  riferimentoAmministrazione?: string,
});

setCessionarioCommittente(cessionario)

Imposta il cessionario/committente (acquirente).

builder.setCessionarioCommittente({
  datiAnagrafici: {
    idFiscaleIVA?: { idPaese: string, idCodice: string },
    codiceFiscale?: string,
    anagrafica: { denominazione?: string, nome?: string, cognome?: string },
  },
  sede: Indirizzo,
  stabileOrganizzazione?: Indirizzo,
  rappresentanteFiscale?: RappresentanteFiscale,
});

setDatiGenerali(dati)

Imposta i dati generali del documento.

builder.setDatiGenerali({
  datiGeneraliDocumento: {
    tipoDocumento: TipoDocumento,
    divisa: string,           // Es: 'EUR'
    data: string,             // YYYY-MM-DD
    numero: string,
    importoTotaleDocumento?: number,
    causale?: string[],
    datiRitenuta?: DatiRitenuta,
    datiBollo?: DatiBollo,
  },
  datiOrdineAcquisto?: DatiDocumentoCorrelato[],
  datiContratto?: DatiDocumentoCorrelato[],
  datiDDT?: DatiDDT[],
});

setDatiBeniServizi(dati)

Imposta le linee di dettaglio e riepilogo IVA.

builder.setDatiBeniServizi({
  dettaglioLinee: [
    {
      numeroLinea: number,
      descrizione: string,
      quantita?: number,
      unitaMisura?: string,
      prezzoUnitario: number,
      prezzoTotale: number,
      aliquotaIVA: number,
      natura?: Natura,
      scontoMaggiorazione?: ScontoMaggiorazione[],
    },
  ],
  datiRiepilogo: [
    {
      aliquotaIVA: number,
      imponibileImporto: number,
      imposta: number,
      natura?: Natura,
      esigibilitaIVA?: 'I' | 'D' | 'S',
      riferimentoNormativo?: string,
    },
  ],
});

addLinea(linea)

Aggiunge una singola linea di dettaglio. numeroLinea (progressivo) e prezzoTotale (prezzoUnitario × quantita, con sconti applicati) sono calcolati se omessi. DatiRiepilogo e ImportoTotaleDocumento vengono calcolati in build().

builder.addLinea({
  descrizione: string,
  quantita?: number,
  unitaMisura?: string,
  prezzoUnitario: number,
  aliquotaIVA: number,
  natura?: Natura,
  scontoMaggiorazione?: ScontoMaggiorazione[],
  numeroLinea?: number,   // opzionale, auto-assegnato
  prezzoTotale?: number,  // opzionale, auto-calcolato
});

setDettaglioLinee(linee)

Imposta tutte le linee in un colpo solo (sostituisce quelle già aggiunte). Stesso auto-calcolo di addLinea.

builder.setDettaglioLinee([
  { descrizione: 'Articolo A', quantita: 2, prezzoUnitario: 50, aliquotaIVA: 22 },
  { descrizione: 'Articolo B', quantita: 1, prezzoUnitario: 100, aliquotaIVA: 10 },
]);

setEsigibilitaIVA(esigibilitaIVA)

Imposta l'EsigibilitaIVA di default ('I' | 'D' | 'S', default 'I') applicata ai DatiRiepilogo calcolati automaticamente. Non applicata ai gruppi con Natura.

builder.setEsigibilitaIVA('S'); // split payment

addDatiPagamento(pagamento)

Aggiunge dati di pagamento.

builder.addDatiPagamento({
  condizioniPagamento: 'TP01' | 'TP02' | 'TP03',
  dettaglioPagamento: [
    {
      modalitaPagamento: ModalitaPagamento,
      importoPagamento: number,
      dataScadenzaPagamento?: string,
      iban?: string,
      istitutoFinanziario?: string,
    },
  ],
});

newBody()

Finalizza il body corrente e inizia uno nuovo (per fatture lotto).

builder
  .setDatiGenerali({ ... })
  .setDatiBeniServizi({ ... })
  .newBody()
  .setDatiGenerali({ ... })  // Nuova fattura
  .setDatiBeniServizi({ ... });

build()

Costruisce la fattura elettronica. Ripetibile: non muta lo stato del builder.

const fattura: FatturaElettronica = builder.build();

validate(options?)

Costruisce e valida in un'unica chiamata, restituendo un ValidationResult.

const result = builder.validate({ strict: true });

toXml(options?)

Costruisce e serializza in XML FatturaPA in un'unica chiamata.

const xml = builder.toXml({ includeSchemaLocation: true });

toResult(options?)

Costruisce, valida e serializza in un'unica chiamata, restituendo anche il nome file SDI.

const { fattura, xml, validazione, filename } = builder.toResult({
  validation?: ValidationOptions,
  serializer?: FatturaSerializerOptions,
});
// filename: '<IdPaese><IdCodice>_<Progressivo>.xml'

reset()

Resetta il builder allo stato iniziale.

builder.reset();

FatturaValidator

Validatore per fatture elettroniche.

import { FatturaValidator, validateFattura } from '@fatturazione-elettronica-aruba/xml-builder';

// Istanza
const validator = new FatturaValidator(options);
const result = validator.validate(fattura);

// Helper
const result = validateFattura(fattura, options);

Opzioni

interface ValidationOptions {
  validateTotals?: boolean;        // Default: true
  validateCodiceFiscale?: boolean; // Default: true
  validatePartitaIVA?: boolean;    // Default: true
  validateDates?: boolean;         // Default: true
  strict?: boolean;                // Default: false
}

Risultato

interface ValidationResult {
  valid: boolean;
  errors: ValidationError[];
  warnings: ValidationError[];
}

interface ValidationError {
  path: string;
  message: string;
  code: string;
}

FatturaSerializer

Serializza fatture in XML.

import { FatturaSerializer } from '@fatturazione-elettronica-aruba/xml-builder';

const serializer = new FatturaSerializer({
  includeSchemaLocation?: boolean,  // Default: true
});

const xml = serializer.serialize(fattura);
Il serializer effettua coercizione difensiva: i number passati dove sono attese stringhe (es. P.IVA dal database) vengono serializzati senza errori. Quantita mantiene 2–8 decimali (es. 0.001), prezzi/aliquote usano 2 decimali.

Utilities

Helper puri esportati dal package. Utili per mappare i dati di dominio senza re-implementare la logica IVA/totali o gli oggetti anagrafici annidati.

calcolaRiepilogo(linee, options?)

Calcola i DatiRiepilogo (raggruppati per aliquotaIVA + natura) e l'importoTotaleDocumento dalle linee, con arrotondamenti corretti (regole SDI).

const { datiRiepilogo, importoTotaleDocumento } = calcolaRiepilogo(linee, {
  esigibilitaIVA: 'I', // default; non applicata ai gruppi con Natura
});

calcolaPrezzoTotale(prezzoUnitario, quantita?, scontoMaggiorazione?)

Calcola il PrezzoTotale di una linea (= prezzoUnitario × quantita, con sconti/maggiorazioni applicati), arrotondato a 2 decimali.

calcolaPrezzoTotale(75, 40);                              // 3000
calcolaPrezzoTotale(100, 1, [{ tipo: 'SC', percentuale: 10 }]); // 90

toNumber(value) / round2(value)

toNumber converte number | string | null | undefined in number (i numerici dei DB arrivano spesso come stringa). round2 arrotonda a 2 decimali evitando errori di floating point.

toNumber('12.50'); // 12.5
round2(1.005);     // 1.01

cedentePrestatore(input) / cessionario(input)

Costruiscono CedentePrestatore / CessionarioCommittente da campi piatti, con coercizione a stringa e IdFiscaleIVA/CodiceFiscale/contatti opzionali.

const cedente = cedentePrestatore({
  piva: '01234567890', codiceFiscale, denominazione: 'Azienda SRL',
  regimeFiscale: 'RF01',           // default 'RF01'
  indirizzo, cap, comune, provincia, nazione, // nazione default 'IT'
  telefono, email,
});

const cliente = cessionario({
  piva, codiceFiscale,            // entrambi opzionali
  denominazione, indirizzo, cap, comune, provincia,
});

sede(input) / contatti(input)

sede costruisce un Indirizzo (default nazione: 'IT'); contatti costruisce un blocco Contatti oppure ritorna undefined se tutti i campi sono vuoti.

nomeFileSdi(idPaese, idCodice, progressivo)

Costruisce il nome file SDI <IdPaese><IdCodice>_<Progressivo>.xml (progressivo completato a 5 caratteri con zeri a sinistra).

nomeFileSdi('IT', '01234567890', '1'); // 'IT01234567890_00001.xml'

Tipi

TipoDocumento

type TipoDocumento =
  | 'TD01' | 'TD02' | 'TD03' | 'TD04' | 'TD05' | 'TD06'
  | 'TD07' | 'TD08' | 'TD09' | 'TD10' | 'TD11' | 'TD12'
  | 'TD16' | 'TD17' | 'TD18' | 'TD19' | 'TD20' | 'TD21'
  | 'TD22' | 'TD23' | 'TD24' | 'TD25' | 'TD26' | 'TD27' | 'TD28';

RegimeFiscale

type RegimeFiscale =
  | 'RF01' | 'RF02' | 'RF04' | 'RF05' | 'RF06' | 'RF07'
  | 'RF08' | 'RF09' | 'RF10' | 'RF11' | 'RF12' | 'RF13'
  | 'RF14' | 'RF15' | 'RF16' | 'RF17' | 'RF18' | 'RF19';

Natura

type Natura =
  | 'N1' | 'N2' | 'N2.1' | 'N2.2'
  | 'N3' | 'N3.1' | 'N3.2' | 'N3.3' | 'N3.4' | 'N3.5' | 'N3.6'
  | 'N4' | 'N5' | 'N6' | 'N6.1' | 'N6.2' | 'N6.3' | 'N6.4'
  | 'N6.5' | 'N6.6' | 'N6.7' | 'N6.8' | 'N6.9' | 'N7';

ModalitaPagamento

type ModalitaPagamento =
  | 'MP01' | 'MP02' | 'MP03' | 'MP04' | 'MP05'
  | 'MP06' | 'MP07' | 'MP08' | 'MP09' | 'MP10'
  | 'MP11' | 'MP12' | 'MP13' | 'MP14' | 'MP15'
  | 'MP16' | 'MP17' | 'MP18' | 'MP19' | 'MP20'
  | 'MP21' | 'MP22' | 'MP23';

Indirizzo

interface Indirizzo {
  indirizzo: string;
  numeroCivico?: string;
  cap: string;
  comune: string;
  provincia?: string;
  nazione: string;
}