2018-07-05 17:56:38 +02:00
< ? php
2018-11-30 15:33:25 +01:00
namespace Plugins\ExportFE ;
2018-07-05 17:56:38 +02:00
2018-09-06 17:10:23 +02:00
use DateTime ;
2018-12-29 12:03:22 +01:00
use FluidXml\FluidXml ;
use GuzzleHttp\Client ;
2018-09-17 17:51:55 +02:00
use Modules ;
use Prints ;
2018-12-29 12:03:22 +01:00
use Respect\Validation\Validator as v ;
use Stringy\Stringy as S ;
use Uploads ;
2018-07-05 17:56:38 +02:00
/**
* Classe per la gestione della fatturazione elettronica in XML .
*
* @ since 2.4 . 2
*/
class FatturaElettronica
{
2018-07-06 18:06:23 +02:00
/** @var array Informazioni sull'anagrafica Azienda */
protected static $azienda = [];
2018-07-05 17:56:38 +02:00
2018-07-06 18:06:23 +02:00
/** @var array Informazioni sull'anagrafica Cliente del documento */
protected $cliente = [];
/** @var array Informazioni sul documento */
protected $documento = [];
2018-11-09 12:45:22 +01:00
/** @var array Contratti collegati al documento */
protected $contratti = [];
2018-11-23 12:43:45 +01:00
/** @var array Ordini di acquisto collegati al documento */
protected $ordini = [];
2018-11-09 12:45:22 +01:00
/** @var array Righe del documento */
protected $righe = [];
2018-07-06 18:06:23 +02:00
/** @var array XML della fattura */
protected $xml = null ;
2018-07-05 17:56:38 +02:00
2018-11-16 10:41:21 +01:00
/** @var array Irregolarità nella fattura XML */
protected $errors = null ;
2018-07-06 18:06:23 +02:00
/** @var array Elenco di campi dello standard per la formattazione e la validazione */
2018-07-05 17:56:38 +02:00
protected static $validators = [
'IdPaese' => [
'type' => 'string' ,
'size' => 2 ,
],
'IdCodice' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 28 ],
2018-07-05 17:56:38 +02:00
],
'ProgressivoInvio' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'FormatoTrasmissione' => [
'type' => 'string' ,
'size' => 5 ,
],
'CodiceDestinatario' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 6 , 7 ],
2018-07-05 17:56:38 +02:00
],
'Telefono' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 5 , 12 ],
2018-07-05 17:56:38 +02:00
],
'Email' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 7 , 256 ],
2018-07-05 17:56:38 +02:00
],
'PECDestinatario' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 7 , 256 ],
2018-07-05 17:56:38 +02:00
],
'CodiceFiscale' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 11 , 16 ],
2018-07-05 17:56:38 +02:00
],
'Denominazione' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 80 ],
2018-07-05 17:56:38 +02:00
],
'Nome' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'Cognome' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'Titolo' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 2 , 10 ],
2018-07-05 17:56:38 +02:00
],
'CodEORI' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 13 , 17 ],
2018-07-05 17:56:38 +02:00
],
'AlboProfessionale' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'ProvinciaAlbo' => [
'type' => 'string' ,
'size' => 2 ,
],
'NumeroIscrizioneAlbo' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'DataIscrizioneAlbo' => [
'type' => 'date' ,
'size' => 10 ,
],
'RegimeFiscale' => [
'type' => 'string' ,
'size' => 4 ,
],
'Indirizzo' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'NumeroCivico' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 8 ],
2018-07-05 17:56:38 +02:00
],
'CAP' => [
'type' => 'string' ,
'size' => 5 ,
],
'Comune' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'Provincia' => [
'type' => 'string' ,
'size' => 2 ,
],
'Nazione' => [
'type' => 'string' ,
'size' => 2 ,
],
'Ufficio' => [
'type' => 'string' ,
'size' => 2 ,
],
'NumeroREA' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'CapitaleSociale' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'SocioUnico' => [
'type' => 'string' ,
'size' => 2 ,
],
'StatoLiquidazione' => [
'type' => 'string' ,
'size' => 2 ,
],
'Fax' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 5 , 12 ],
2018-07-05 17:56:38 +02:00
],
'RiferimentoAmministrazione' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'SoggettoEmittente' => [
'type' => 'string' ,
'size' => 2 ,
],
'TipoDocumento' => [
'type' => 'string' ,
'size' => 4 ,
],
'Divisa' => [
'type' => 'string' ,
'size' => 3 ,
],
'Data' => [
'type' => 'date' ,
'size' => 10 ,
],
'Numero' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'TipoRitenuta' => [
'type' => 'string' ,
'size' => 4 ,
],
'ImportoRitenuta' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'AliquotaRitenuta' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 6 ],
2018-07-05 17:56:38 +02:00
],
'CausalePagamento' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 2 ],
2018-07-05 17:56:38 +02:00
],
'BolloVirtuale' => [
'type' => 'string' ,
'size' => 2 ,
],
'ImportoBollo' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'TipoCassa' => [
'type' => 'string' ,
'size' => 4 ,
],
'AlCassa' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 6 ],
2018-07-05 17:56:38 +02:00
],
'ImportoContributoCassa' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'ImponibileCassa' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'AliquotaIVA' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 6 ],
2018-07-05 17:56:38 +02:00
],
'Ritenuta' => [
'type' => 'string' ,
'size' => 2 ,
],
'Natura' => [
'type' => 'string' ,
'size' => 2 ,
],
'Tipo' => [
'type' => 'string' ,
'size' => 2 ,
],
'Percentuale' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 6 ],
2018-07-05 17:56:38 +02:00
],
'Importo' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'ImportoTotaleDocumento' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'Arrotondamento' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 21 ],
2018-07-05 17:56:38 +02:00
],
'Causale' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 200 ],
2018-07-05 17:56:38 +02:00
],
'Art73' => [
'type' => 'string' ,
'size' => 2 ,
],
'RiferimentoNumeroLinea' => [
'type' => 'integer' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 4 ],
2018-07-05 17:56:38 +02:00
],
'IdDocumento' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'NumItem' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'CodiceCommessaConvenzione' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 100 ],
2018-07-05 17:56:38 +02:00
],
'CodiceCUP' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 15 ],
2018-07-05 17:56:38 +02:00
],
'CodiceCIG' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 15 ],
2018-07-05 17:56:38 +02:00
],
'RiferimentoFase' => [
'type' => 'integer' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 3 ],
2018-07-05 17:56:38 +02:00
],
'NumeroDDT' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'DataDDT' => [
'type' => 'date' ,
'size' => 10 ,
],
'NumeroLicenzaGuida' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'MezzoTrasporto' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 80 ],
2018-07-05 17:56:38 +02:00
],
'CausaleTrasporto' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 100 ],
2018-07-05 17:56:38 +02:00
],
'NumeroColli' => [
'type' => 'integer' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 4 ],
2018-07-05 17:56:38 +02:00
],
'Descrizione' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 1000 ],
2018-07-05 17:56:38 +02:00
],
'UnitaMisuraPeso' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'PesoLordo' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 7 ],
2018-07-05 17:56:38 +02:00
],
'PesoNetto' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 7 ],
2018-07-05 17:56:38 +02:00
],
'DataOraRitiro' => [
'type' => 'date' ,
'size' => 19 ,
],
'DataInizioTrasporto' => [
'type' => 'date' ,
'size' => 10 ,
],
'TipoResa' => [
'type' => 'string' ,
'size' => 3 ,
],
'DataOraConsegna' => [
'type' => 'date' ,
'size' => 19 ,
],
'NumeroFatturaPrincipale' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'DataFatturaPrincipale' => [
'type' => 'date' ,
'size' => 10 ,
],
'NumeroLinea' => [
'type' => 'integer' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 4 ],
2018-07-05 17:56:38 +02:00
],
'TipoCessionePrestazione' => [
'type' => 'string' ,
'size' => 2 ,
],
'CodiceArticolo' => [
'type' => 'normalizedString' ,
],
'CodiceTipo' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 35 ],
2018-07-05 17:56:38 +02:00
],
'CodiceValore' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 35 ],
2018-07-05 17:56:38 +02:00
],
'Quantita' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 21 ],
2018-07-05 17:56:38 +02:00
],
'UnitaMisura' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'DataInizioPeriodo' => [
'type' => 'date' ,
'size' => 10 ,
],
'DataFinePeriodo' => [
'type' => 'date' ,
'size' => 10 ,
],
'PrezzoUnitario' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 21 ],
2018-07-05 17:56:38 +02:00
],
'PrezzoTotale' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 21 ],
2018-07-05 17:56:38 +02:00
],
'TipoDato' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'RiferimentoTesto' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'RiferimentoNumero' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 21 ],
2018-07-05 17:56:38 +02:00
],
'RiferimentoData' => [
'type' => 'normalizedString' ,
'size' => 10 ,
],
'SpeseAccessorie' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'ImponibileImporto' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'Imposta' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'EsigibilitaIVA' => [
'type' => 'string' ,
'size' => 1 ,
],
'RiferimentoNormativo' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 100 ],
2018-07-05 17:56:38 +02:00
],
'TotalePercorso' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 15 ],
2018-07-05 17:56:38 +02:00
],
'CondizioniPagamento' => [
'type' => 'string' ,
'size' => 4 ,
],
'Beneficiario' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 200 ],
2018-07-05 17:56:38 +02:00
],
'ModalitaPagamento' => [
'type' => 'string' ,
'size' => 4 ,
],
'DataRiferimentoTerminiPagamento' => [
'type' => 'date' ,
'size' => 10 ,
],
'GiorniTerminiPagamento' => [
'type' => 'integer' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 3 ],
2018-07-05 17:56:38 +02:00
],
'DataScadenzaPagamento' => [
'type' => 'date' ,
'size' => 10 ,
],
'ImportoPagamento' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'CodUfficioPostale' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 20 ],
2018-07-05 17:56:38 +02:00
],
'CognomeQuietanzante' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'NomeQuietanzante' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'CFQuietanzante' => [
'type' => 'string' ,
'size' => 16 ,
],
'TitoloQuietanzante' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 2 , 10 ],
2018-07-05 17:56:38 +02:00
],
'IstitutoFinanziario' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 80 ],
2018-07-05 17:56:38 +02:00
],
'IBAN' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 15 , 34 ],
2018-07-05 17:56:38 +02:00
],
'ABI' => [
'type' => 'string' ,
'size' => 5 ,
],
'CAB' => [
'type' => 'string' ,
'size' => 5 ,
],
'BIC' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 8 , 11 ],
2018-07-05 17:56:38 +02:00
],
'ScontoPagamentoAnticipato' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'DataLimitePagamentoAnticipato' => [
'type' => 'date' ,
'size' => 10 ,
],
'PenalitaPagamentiRitardati' => [
'type' => 'decimal' ,
2018-07-06 18:06:23 +02:00
'size' => [ 4 , 15 ],
2018-07-05 17:56:38 +02:00
],
'DataDecorrenzaPenale' => [
'type' => 'date' ,
'size' => 10 ,
],
'CodicePagamento' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'NomeAttachment' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 60 ],
2018-07-05 17:56:38 +02:00
],
'AlgoritmoCompressione' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'FormatoAttachment' => [
'type' => 'string' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 10 ],
2018-07-05 17:56:38 +02:00
],
'DescrizioneAttachment' => [
'type' => 'normalizedString' ,
2018-07-06 18:06:23 +02:00
'size' => [ 1 , 100 ],
2018-07-05 17:56:38 +02:00
],
'Attachment' => [
'type' => 'base64Binary' ,
],
];
2018-12-29 12:03:22 +01:00
public function __construct ( $id_documento )
{
$database = database ();
// Documento
$this -> documento = $database -> fetchOne ( ' SELECT `co_documenti` .* , `co_tipidocumento` . `descrizione` AS `tipo` , `co_tipidocumento` . `codice_tipo_documento_fe` AS `tipo_documento` , `co_statidocumento` . `descrizione` AS `stato` FROM `co_documenti`
INNER JOIN `co_tipidocumento` ON `co_tipidocumento` . `id` = `co_documenti` . `idtipodocumento`
INNER JOIN `co_statidocumento` ON `co_statidocumento` . `id` = `co_documenti` . `idstatodocumento`
WHERE `co_documenti` . `id` = ' . prepare ( $id_documento ));
// Controllo sulla possibilità di creare la fattura elettronica
// Posso fatturare ai privati utilizzando il codice fiscale
if ( $this -> documento [ 'stato' ] != 'Emessa' ) {
throw new \UnexpectedValueException ();
}
}
public function __toString ()
{
2019-01-03 21:17:04 +01:00
return $this -> toXML ();
2018-12-29 12:03:22 +01:00
}
/**
* Restituisce le informazioni sull ' anagrafica azienda .
*
* @ return array
*/
public function isGenerated ()
{
$documento = $this -> getDocumento ();
return ! empty ( $documento [ 'progressivo_invio' ]) && file_exists ( DOCROOT . '/' . static :: getDirectory () . '/' . $this -> getFilename ());
}
/**
* Restituisce le informazioni sull ' anagrafica azienda .
*
* @ return array
*/
public static function getAzienda ()
{
if ( empty ( static :: $azienda )) {
static :: $azienda = static :: getAnagrafica ( setting ( 'Azienda predefinita' ));
}
return static :: $azienda ;
}
/**
* Restituisce le informazioni sull ' anagrafica cliente legata al documento .
*
* @ return array
*/
public function getCliente ()
{
if ( empty ( $this -> cliente )) {
$cliente = static :: getAnagrafica ( $this -> getDocumento ()[ 'idanagrafica' ]);
$sede = database () -> fetchOne ( 'SELECT `codice_destinatario` FROM `an_sedi` WHERE `id` = ' . prepare ( $this -> getDocumento ()[ 'idsede' ]));
if ( ! empty ( $sede )) {
$cliente [ 'codice_destinatario' ] = $sede [ 'codice_destinatario' ];
}
$this -> cliente = $cliente ;
}
return $this -> cliente ;
}
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
/**
2019-01-04 19:23:28 +01:00
* Restituisce le informazioni sull 'anagrafica dell' intermediario .
*
* @ return array
*/
public function getIntermediario ()
{
2019-01-05 17:47:03 +01:00
if ( empty ( $this -> intermediario )) {
$intermediario = static :: getAnagrafica ( setting ( 'Terzo intermediario' ));
$this -> intermediario = $intermediario ;
}
2019-01-05 11:11:48 +01:00
2019-01-04 19:23:28 +01:00
return $this -> intermediario ;
}
2019-01-05 11:11:48 +01:00
2018-12-29 12:03:22 +01:00
/**
* Restituisce le informazioni riguardanti un anagrafica sulla base dell ' identificativo fornito .
*
* @ param int $id
*
* @ return array
*/
public static function getAnagrafica ( $id )
{
return database () -> fetchOne ( 'SELECT *, (SELECT `iso2` FROM `an_nazioni` WHERE `an_nazioni`.`id` = `an_anagrafiche`.`id_nazione`) AS nazione FROM `an_anagrafiche` WHERE `idanagrafica` = ' . prepare ( $id ));
}
/**
* Restituisce le righe del documento .
*
* @ return array
*/
public function getRighe ()
{
if ( empty ( $this -> righe )) {
2019-01-10 18:06:15 +01:00
$this -> righe = database () -> fetchArray ( 'SELECT * FROM `co_righe_documenti` WHERE `sconto_globale` = 0 AND is_descrizione = 0 AND `iddocumento` = ' . prepare ( $this -> getDocumento ()[ 'id' ]));
2018-12-29 12:03:22 +01:00
}
return $this -> righe ;
}
/**
* Restituisce i contratti collegati al documento ( contratti e interventi ) .
*
* @ return array
*/
public function getContratti ()
{
if ( empty ( $this -> contratti )) {
$documento = $this -> getDocumento ();
$database = database ();
$contratti = $database -> fetchArray ( 'SELECT `id_documento_fe`, `codice_cig`, `codice_cup` FROM `co_contratti` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idcontratto` = `co_contratti`.`id` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND `id_documento_fe` IS NOT NULL' );
$interventi = $database -> fetchArray ( 'SELECT `id_documento_fe`, `codice_cig`, `codice_cup` FROM `in_interventi` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idintervento` = `in_interventi`.`id` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND `id_documento_fe` IS NOT NULL' );
$this -> contratti = array_merge ( $contratti , $interventi );
}
return $this -> contratti ;
}
/**
* Restituisce gli ordini di acquisto collegati al documento .
*
* @ return array
*/
public function getOrdiniAcquisto ()
{
if ( empty ( $this -> ordini )) {
$documento = $this -> getDocumento ();
$database = database ();
$ordini = $database -> fetchArray ( 'SELECT `id_documento_fe`, `codice_cig`, `codice_cup` FROM `or_ordini` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idordine` = `or_ordini`.`id` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND `id_documento_fe` IS NOT NULL' );
$this -> ordini = $ordini ;
}
return $this -> ordini ;
}
/**
* Restituisce le fatture collegate al documento .
*
* @ return array
*/
public function getFattureCollegate ()
{
if ( empty ( $this -> fatture_collegate )) {
$documento = $this -> getDocumento ();
$database = database ();
$note_accredito = $database -> fetchArray ( 'SELECT numero_esterno, data FROM co_documenti WHERE id=' . prepare ( $documento [ 'ref_documento' ]));
$this -> fatture_collegate = $note_accredito ;
}
return $this -> fatture_collegate ;
}
/**
* Restituisce le informazioni relative al documento .
*
* @ return array
*/
public function getDocumento ()
{
return $this -> documento ;
}
/**
* Restituisce lo stato di validazione interna dell ' XML della fattura .
*
* @ return bool
*/
public function isValid ()
{
return empty ( $this -> getErrors ());
}
/**
* Restituisce l 'elenco delle irregolarità interne all' XML della fattura .
*
* @ return bool
*/
public function getErrors ()
{
if ( ! isset ( $this -> errors )) {
$this -> toXML ();
}
return $this -> errors ;
}
2019-01-03 21:17:04 +01:00
/**
* Ottiene il codice destinatario a partire dal database ufficiale indicepa www . indicepa . gov . it .
*
* @ param $codice_fiscale
*
* @ throws \GuzzleHttp\Exception\GuzzleException
*
* @ return string | null
*/
2018-12-29 12:03:22 +01:00
public static function PA ( $codice_fiscale )
{
$id = setting ( 'Authorization ID Indice PA' );
if ( empty ( $id )) {
return null ;
}
2019-01-03 21:17:04 +01:00
// Configurazione per localhost: CURLOPT_SSL_VERIFYPEER
2018-12-29 12:03:22 +01:00
$client = new Client ([ 'curl' => [ CURLOPT_SSL_VERIFYPEER => false ]]);
$response = $client -> request ( 'POST' , 'https://www.indicepa.gov.it/public-ws/WS01_SFE_CF.php' , [
'form_params' => [
'AUTH_ID' => $id ,
'CF' => $codice_fiscale ,
],
]);
$json = json_decode ( $response -> getBody (), true );
return isset ( $json [ 'data' ][ 0 ][ 'OU' ][ 0 ][ 'cod_uni_ou' ]) ? $json [ 'data' ][ 0 ][ 'OU' ][ 0 ][ 'cod_uni_ou' ] : null ;
}
public static function getDirectory ()
{
return Uploads :: getDirectory ( Modules :: get ( 'Fatture di vendita' )[ 'id' ]);
}
/**
* Salva il file XML .
*
* @ param string $directory
*
* @ return string Nome del file
*/
public function save ( $directory )
{
2019-01-03 18:54:09 +01:00
$name = 'Fattura Elettronica' ;
2018-12-29 12:03:22 +01:00
$previous = $this -> getFilename ();
$data = $this -> getUploadData ();
Uploads :: delete ( $previous , $data );
// Generazione nome XML
$filename = $this -> getFilename ( true );
// Salvataggio del file
$file = rtrim ( $directory , '/' ) . '/' . $filename ;
$result = directory ( $directory ) && file_put_contents ( $file , $this -> toXML ());
// Registrazione come allegato
Uploads :: register ( array_merge ([
'name' => $name ,
'original' => $filename ,
], $data ));
// Aggiornamento effettivo
database () -> update ( 'co_documenti' , [
'progressivo_invio' => $this -> getDocumento ()[ 'progressivo_invio' ],
'codice_stato_fe' => 'GEN' ,
], [ 'id' => $this -> getDocumento ()[ 'id' ]]);
return ( $result === false ) ? null : $filename ;
}
/**
* Restituisce il nome del file XML per la fattura elettronica .
*
* @ return string
*/
public function getFilename ( $new = false )
{
$azienda = static :: getAzienda ();
2019-01-04 19:23:28 +01:00
$prefix = 'IT' . ( ! empty ( $azienda [ 'codice_fiscale' ]) ? $azienda [ 'codice_fiscale' ] : $azienda [ 'piva' ]);
2018-12-29 12:03:22 +01:00
if ( empty ( $this -> documento [ 'progressivo_invio' ]) || ! empty ( $new )) {
$database = database ();
do {
$code = date ( 'y' ) . secure_random_string ( 3 );
} while ( $database -> fetchNum ( 'SELECT `id` FROM `co_documenti` WHERE `progressivo_invio` = ' . prepare ( $code )) != 0 );
// Registrazione
$this -> documento [ 'progressivo_invio' ] = $code ;
}
return $prefix . '_' . $this -> documento [ 'progressivo_invio' ] . '.xml' ;
}
/**
* Restituisce il codice XML della fattura elettronica .
*
* @ return string
*/
public function toXML ()
{
if ( empty ( $this -> xml )) {
$this -> errors = [];
$cliente = $this -> getCliente ();
// Inizializzazione libreria per la generazione della fattura in XML
$fattura = new FluidXml ( null , [ 'stylesheet' => 'http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2.1/fatturaPA_v1.2.1.xsl' ]);
// Generazione dell'elemento root
$fattura -> namespace ( 'p' , 'http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2' );
$root = $fattura -> addChild ( 'p:FatturaElettronica' , true );
$rootNode = $root [ 0 ];
// Completamento dei tag
$attributes = [
'versione' => ( $cliente [ 'tipo' ] == 'Ente pubblico' ) ? 'FPA12' : 'FPR12' ,
'xmlns:ds' => 'http://www.w3.org/2000/09/xmldsig#' ,
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' ,
'xsi:schemaLocation' => 'http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd' ,
];
foreach ( $attributes as $key => $value ) {
$rootNode -> setAttribute ( $key , $value );
}
// Generazione della fattura elettronica
$xml = static :: prepareForXML ([
'FatturaElettronicaHeader' => static :: getHeader ( $this ),
'FatturaElettronicaBody' => static :: getBody ( $this ),
]);
$fattura -> add ( $xml );
$this -> xml = $fattura -> __toString ();
}
return $this -> xml ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiTrasmission .
*
* @ return array
*/
protected static function getDatiTrasmissione ( $fattura )
{
$azienda = static :: getAzienda ();
$documento = $fattura -> getDocumento ();
$cliente = $fattura -> getCliente ();
// Se sto fatturando ad un ente pubblico il codice destinatario di default è 99999 (sei nove), in alternativa uso 0000000 (sette zeri)
$default_code = ( $cliente [ 'tipo' ] == 'Ente pubblico' ) ? '999999' : '0000000' ;
// Se il mio cliente non ha sede in Italia il codice destinatario di default diventa (XXXXXXX) (sette X)
$default_code = ( $cliente [ 'nazione' ] != 'IT' ) ? 'XXXXXXX' : $default_code ;
// Generazione dell'header
// Se all'Anagrafe Tributaria il trasmittente è censito con il codice fiscale
$result = [
'IdTrasmittente' => [
'IdPaese' => $azienda [ 'nazione' ],
2019-01-04 19:23:28 +01:00
'IdCodice' => ( ! empty ( $azienda [ 'codice_fiscale' ])) ? $azienda [ 'codice_fiscale' ] : $azienda [ 'piva' ],
2018-12-29 12:03:22 +01:00
],
'ProgressivoInvio' => $documento [ 'progressivo_invio' ],
'FormatoTrasmissione' => ( $cliente [ 'tipo' ] == 'Ente pubblico' ) ? 'FPA12' : 'FPR12' ,
'CodiceDestinatario' => ! empty ( $cliente [ 'codice_destinatario' ]) ? $cliente [ 'codice_destinatario' ] : $default_code ,
];
// Telefono di contatto
if ( ! empty ( $azienda [ 'telefono' ])) {
$result [ 'ContattiTrasmittente' ][ 'Telefono' ] = $azienda [ 'telefono' ];
}
// Email di contatto
if ( ! empty ( $azienda [ 'email' ])) {
$result [ 'ContattiTrasmittente' ][ 'Email' ] = $azienda [ 'email' ];
}
// Inizializzazione PEC solo se anagrafica azienda e codice destinatario non compilato, per privato e PA la PEC non serve
if ( empty ( $cliente [ 'codice_destinatario' ]) && $cliente [ 'tipo' ] == 'Azienda' ) {
$result [ 'PECDestinatario' ] = $cliente [ 'pec' ];
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione dei tag DatiAnagrafici per Azienda e Cliente .
*
* @ return array
*/
protected static function getDatiAnagrafici ( $anagrafica , $azienda = false )
{
$result = [];
// Partita IVA (obbligatoria se presente)
if ( ! empty ( $anagrafica [ 'piva' ])) {
2019-01-05 17:47:03 +01:00
if ( ! empty ( $anagrafica [ 'nazione' ])) {
$result [ 'IdFiscaleIVA' ][ 'IdPaese' ] = $anagrafica [ 'nazione' ];
}
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
$result [ 'IdFiscaleIVA' ][ 'IdCodice' ] = $anagrafica [ 'piva' ];
2018-12-29 12:03:22 +01:00
}
// Codice fiscale
if ( ! empty ( $anagrafica [ 'codice_fiscale' ])) {
$result [ 'CodiceFiscale' ] = $anagrafica [ 'codice_fiscale' ];
}
2019-01-10 18:06:15 +01:00
$result [ 'Anagrafica' ] = [
'Denominazione' => $anagrafica [ 'ragione_sociale' ],
// TODO: 'Nome' => $azienda['ragione_sociale'],
// TODO: 'Cognome' => $azienda['ragione_sociale'],
// TODO: 'Titolo' => $azienda['ragione_sociale'],
// TODO: CodEORI
];
2018-12-29 12:03:22 +01:00
// Informazioni specifiche azienda
if ( $azienda ) {
$result [ 'RegimeFiscale' ] = setting ( 'Regime Fiscale' );
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione dei tag Sede per Azienda e Cliente .
*
* @ return array
*/
protected static function getSede ( $anagrafica )
{
$result = [
'Indirizzo' => $anagrafica [ 'indirizzo' ],
'CAP' => $anagrafica [ 'cap' ],
'Comune' => $anagrafica [ 'citta' ],
];
2019-01-03 15:24:21 +01:00
// Provincia impostata e SOLO SE nazione ITALIA
2018-12-29 12:03:22 +01:00
if ( ! empty ( $anagrafica [ 'provincia' ]) && $anagrafica [ 'nazione' ] == 'IT' ) {
2019-01-03 15:24:21 +01:00
$result [ 'Provincia' ] = strtoupper ( $anagrafica [ 'provincia' ]);
2018-12-29 12:03:22 +01:00
}
$result [ 'Nazione' ] = $anagrafica [ 'nazione' ];
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag CedentePrestatore .
*
* @ return array
*/
protected static function getCedentePrestatore ( $fattura )
{
$azienda = static :: getAzienda ();
$result = [
'DatiAnagrafici' => static :: getDatiAnagrafici ( $azienda , true ),
'Sede' => static :: getSede ( $azienda ),
];
// IscrizioneREA
if ( ! empty ( $azienda [ 'codicerea' ])) {
$codice = explode ( '-' , $azienda [ 'codicerea' ]);
if ( ! empty ( $codice [ 0 ]) && ! empty ( $codice [ 1 ])) {
$result [ 'IscrizioneREA' ] = [
'Ufficio' => strtoupper ( $codice [ 0 ]),
'NumeroREA' => $codice [ 1 ],
];
}
if ( ! empty ( $azienda [ 'capitale_sociale' ])) {
$result [ 'IscrizioneREA' ][ 'CapitaleSociale' ] = $azienda [ 'capitale_sociale' ];
}
$result [ 'IscrizioneREA' ][ 'StatoLiquidazione' ] = 'LN' ; // Non in liquidazione
}
// Contatti
// Telefono
if ( ! empty ( $azienda [ 'telefono' ])) {
$result [ 'Contatti' ][ 'Telefono' ] = $azienda [ 'telefono' ];
}
// Fax
if ( ! empty ( $azienda [ 'fax' ])) {
$result [ 'Contatti' ][ 'Fax' ] = $azienda [ 'fax' ];
}
// Email
if ( ! empty ( $azienda [ 'email' ])) {
$result [ 'Contatti' ][ 'Email' ] = $azienda [ 'email' ];
}
return $result ;
}
/**
2019-01-04 19:23:28 +01:00
* Restituisce l ' array responsabile per la generazione del tag CessionarioCommittente ( 1.4 ) .
2018-12-29 12:03:22 +01:00
*
* @ return array
*/
protected static function getCessionarioCommittente ( $fattura )
{
$cliente = $fattura -> getCliente ();
$result = [
'DatiAnagrafici' => static :: getDatiAnagrafici ( $cliente ),
'Sede' => static :: getSede ( $cliente ),
];
return $result ;
}
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
/**
2019-01-06 14:18:48 +01:00
* Restituisce l ' array responsabile per la generazione del tag TerzoIntermediarioOSoggettoEmittente ( 1.5 ) .
*
* @ return array
*/
2019-01-05 17:47:03 +01:00
protected static function getTerzoIntermediarioOSoggettoEmittente ( $fattura )
{
$intermediario = $fattura -> getIntermediario ();
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
$result = [
2019-01-04 19:23:28 +01:00
'DatiAnagrafici' => static :: getDatiAnagrafici ( $intermediario ),
];
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
return $result ;
}
2019-01-05 11:11:48 +01:00
2018-12-29 12:03:22 +01:00
/**
* Restituisce l ' array responsabile per la generazione del tag DatiGeneraliDocumento .
*
* @ return array
*/
protected static function getDatiGeneraliDocumento ( $fattura )
{
$documento = $fattura -> getDocumento ();
$azienda = static :: getAzienda ();
2019-01-06 14:18:48 +01:00
$fattura = Modules\Fatture\Fattura :: find ( $documento [ 'id' ]);
2018-12-29 12:03:22 +01:00
$result = [
'TipoDocumento' => $documento [ 'tipo_documento' ],
'Divisa' => 'EUR' ,
'Data' => $documento [ 'data' ],
'Numero' => $documento [ 'numero_esterno' ],
// TODO: 'Causale' => $documento['causale'],
];
// Ritenuta d'Acconto
$righe = $fattura -> getRighe ();
$id_ritenuta = null ;
2019-01-05 11:11:48 +01:00
$id_rivalsainps = null ;
$totale_rivalsainps = 0 ;
$totale_ritenutaacconto = 0 ;
2018-12-29 12:03:22 +01:00
foreach ( $righe as $riga ) {
if ( ! empty ( $riga [ 'idritenutaacconto' ])) {
$id_ritenuta = $riga [ 'idritenutaacconto' ];
2019-01-05 11:11:48 +01:00
$totale_ritenutaacconto += $riga [ 'ritenutaacconto' ];
}
if ( ! empty ( $riga [ 'idrivalsainps' ])) {
$id_rivalsainps = $riga [ 'idrivalsainps' ];
$totale_rivalsainps += $riga [ 'rivalsainps' ];
$aliquota_iva_rivalsainps = $riga [ 'idiva' ];
2018-12-29 12:03:22 +01:00
}
}
if ( ! empty ( $id_ritenuta )) {
$percentuale = database () -> fetchOne ( 'SELECT percentuale FROM co_ritenutaacconto WHERE id = ' . prepare ( $id_ritenuta ))[ 'percentuale' ];
$result [ 'DatiRitenuta' ] = [
'TipoRitenuta' => ( $azienda [ 'tipo' ] == 'Privato' ) ? 'RT01' : 'RT02' ,
2019-01-05 11:11:48 +01:00
'ImportoRitenuta' => $totale_ritenutaacconto ,
2018-12-29 12:03:22 +01:00
'AliquotaRitenuta' => $percentuale ,
'CausalePagamento' => setting ( " Causale ritenuta d'acconto " ),
];
}
2019-01-03 18:54:09 +01:00
// Bollo (2.1.1.6)
2018-12-29 12:03:22 +01:00
$documento [ 'bollo' ] = floatval ( $documento [ 'bollo' ]);
if ( ! empty ( $documento [ 'bollo' ])) {
$result [ 'DatiBollo' ] = [
'BolloVirtuale' => 'SI' ,
'ImportoBollo' => $documento [ 'bollo' ],
];
}
// Cassa Previdenziale
2019-01-05 11:11:48 +01:00
if ( ! empty ( $id_rivalsainps )) {
$iva = database () -> fetchOne ( 'SELECT `percentuale`, `codice_natura_fe` FROM `co_iva` WHERE `id` = ' . prepare ( $aliquota_iva_rivalsainps ));
$percentuale = database () -> fetchOne ( 'SELECT percentuale FROM co_rivalsainps WHERE id = ' . prepare ( $id_rivalsainps ))[ 'percentuale' ];
2018-12-29 12:03:22 +01:00
$dati_cassa = [
'TipoCassa' => setting ( 'Tipo Cassa' ),
2019-01-05 11:11:48 +01:00
'AlCassa' => $percentuale ,
'ImportoContributoCassa' => $totale_rivalsainps ,
2019-01-05 17:47:03 +01:00
'ImponibileCassa' => $fattura -> imponibile ,
2018-12-29 12:03:22 +01:00
'AliquotaIVA' => $iva [ 'percentuale' ],
];
$ritenuta_predefinita = setting ( " Percentuale ritenuta d'acconto " );
if ( ! empty ( $ritenuta_predefinita )) {
$dati_cassa [ 'Ritenuta' ] = 'SI' ;
}
$dati_cassa [ 'Natura' ] = $iva [ 'codice_natura_fe' ];
$dati_cassa [ 'RiferimentoAmministrazione' ] = '' ;
$result [ 'DatiCassaPrevidenziale' ] = $dati_cassa ;
2019-01-05 11:11:48 +01:00
}
2018-12-29 12:03:22 +01:00
2019-01-03 18:54:09 +01:00
// Sconto globale (2.1.1.8)
2018-12-29 12:03:22 +01:00
$documento [ 'sconto_globale' ] = floatval ( $documento [ 'sconto_globale' ]);
if ( ! empty ( $documento [ 'sconto_globale' ])) {
$sconto = [
'Tipo' => $documento [ 'sconto_globale' ] > 0 ? 'SC' : 'MG' ,
];
if ( $documento [ 'tipo_sconto_globale' ] == 'PRC' ) {
$sconto [ 'Percentuale' ] = $documento [ 'sconto_globale' ];
} else {
$sconto [ 'Importo' ] = $documento [ 'sconto_globale' ];
}
$result [ 'ScontoMaggiorazione' ] = $sconto ;
}
2019-01-03 21:17:04 +01:00
// Importo Totale Documento (2.1.1.9)
// Importo totale del documento al netto dell'eventuale sconto e comprensivo di imposta a debito del cessionario / committente
2019-01-09 17:12:00 +01:00
$result [ 'ImportoTotaleDocumento' ] = abs ( $fattura -> netto );
2018-12-29 12:03:22 +01:00
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiTrasporto .
*
* @ return array
*/
protected static function getDatiTrasporto ( $fattura )
{
$documento = $fattura -> getDocumento ();
$database = database ();
$causale = $database -> fetchOne ( 'SELECT descrizione FROM dt_causalet WHERE id = ' . prepare ( $documento [ 'idcausalet' ]))[ 'descrizione' ];
$aspetto = $database -> fetchOne ( 'SELECT descrizione FROM dt_aspettobeni WHERE id = ' . prepare ( $documento [ 'idaspettobeni' ]))[ 'descrizione' ];
$result = [];
if ( $documento [ 'idvettore' ]) {
$vettore = static :: getAnagrafica ( $documento [ 'idvettore' ]);
$result [ 'DatiAnagraficiVettore' ] = static :: getDatiAnagrafici ( $vettore );
}
$result [ 'CausaleTrasporto' ] = $causale ;
$result [ 'NumeroColli' ] = $documento [ 'n_colli' ];
$result [ 'Descrizione' ] = $aspetto ;
if ( $documento [ 'tipo_resa' ]) {
$result [ 'TipoResa' ] = $documento [ 'tipo_resa' ];
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiOrdineAcquisto .
*
* @ return array
*/
protected static function getDatiOrdineAcquisto ( $fattura )
{
$ordini = $fattura -> getOrdiniAcquisto ();
$result = [];
foreach ( $ordini as $element ) {
if ( ! empty ( $element [ 'id_documento_fe' ])) {
$dati = [
'IdDocumento' => $element [ 'id_documento_fe' ],
];
}
if ( ! empty ( $element [ 'codice_cig' ])) {
$dati [ 'CodiceCIG' ] = $element [ 'codice_cig' ];
}
if ( ! empty ( $element [ 'codice_cup' ])) {
$dati [ 'CodiceCUP' ] = $element [ 'codice_cup' ];
}
$result [] = $dati ;
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiContratto .
*
* @ return array
*/
protected static function getDatiContratto ( $fattura )
{
$contratti = $fattura -> getContratti ();
$result = [];
foreach ( $contratti as $element ) {
if ( ! empty ( $element [ 'id_documento_fe' ])) {
$dati = [
'IdDocumento' => $element [ 'id_documento_fe' ],
];
}
if ( ! empty ( $element [ 'codice_cig' ])) {
$dati [ 'CodiceCIG' ] = $element [ 'codice_cig' ];
}
if ( ! empty ( $element [ 'codice_cup' ])) {
$dati [ 'CodiceCUP' ] = $element [ 'codice_cup' ];
}
$result [] = $dati ;
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiFattureCollegate .
*
* @ return array
*/
protected static function getDatiFattureCollegate ( $fattura )
{
$fatture = $fattura -> getFattureCollegate ();
$result = [];
foreach ( $fatture as $element ) {
$result [] = [
'IdDocumento' => $element [ 'numero_esterno' ],
'Data' => $element [ 'data' ],
];
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiDocumento .
*
* @ return array
*/
protected static function getDatiGenerali ( $fattura )
{
$documento = $fattura -> getDocumento ();
$cliente = $fattura -> getCliente ();
$result = [
'DatiGeneraliDocumento' => static :: getDatiGeneraliDocumento ( $fattura ),
];
// Controllo le le righe per la fatturazione di ordini
$dati_ordini = static :: getDatiOrdineAcquisto ( $fattura );
if ( ! empty ( $dati_ordini )) {
foreach ( $dati_ordini as $dato ) {
if ( ! empty ( $dato )) {
$result [] = [
'DatiOrdineAcquisto' => $dato ,
];
}
}
}
// Controllo le le righe per la fatturazione di contratti
$dati_contratti = static :: getDatiContratto ( $fattura );
if ( ! empty ( $dati_contratti )) {
foreach ( $dati_contratti as $dato ) {
if ( ! empty ( $dato )) {
$result [] = [
'DatiContratto' => $dato ,
];
}
}
}
// Controllo le le righe per la fatturazione di contratti
$dati_fatture_collegate = static :: getDatiFattureCollegate ( $fattura );
if ( ! empty ( $dati_fatture_collegate )) {
foreach ( $dati_fatture_collegate as $dato ) {
if ( ! empty ( $dato )) {
$result [] = [
'DatiFattureCollegate' => $dato ,
];
}
}
}
if ( $documento [ 'tipo' ] == 'Fattura accompagnatoria di vendita' ) {
$result [ 'DatiTrasporto' ] = static :: getDatiTrasporto ( $fattura );
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiBeniServizi .
*
* @ return array
*/
protected static function getDatiBeniServizi ( $fattura )
{
$documento = $fattura -> getDocumento ();
$database = database ();
$result = [];
// Righe del documento
$righe_documento = $fattura -> getRighe ();
foreach ( $righe_documento as $numero => $riga ) {
$riga [ 'subtotale' ] = abs ( $riga [ 'subtotale' ]);
$riga [ 'qta' ] = abs ( $riga [ 'qta' ]);
$riga [ 'sconto' ] = abs ( $riga [ 'sconto' ]);
$prezzo_unitario = $riga [ 'subtotale' ] / $riga [ 'qta' ];
$prezzo_totale = $riga [ 'subtotale' ] - $riga [ 'sconto' ];
$iva = $database -> fetchOne ( 'SELECT `percentuale`, `codice_natura_fe` FROM `co_iva` WHERE `id` = ' . prepare ( $riga [ 'idiva' ]));
$percentuale = floatval ( $iva [ 'percentuale' ]);
$dettaglio = [
'NumeroLinea' => $numero + 1 ,
];
2019-01-03 21:17:04 +01:00
// 2.2.1.2
2018-12-29 12:03:22 +01:00
if ( ! empty ( $riga [ 'tipo_cessione_prestazione' ])) {
$dettaglio [ 'TipoCessionePrestazione' ] = $riga [ 'tipo_cessione_prestazione' ];
}
2019-01-03 21:17:04 +01:00
//2.2.1.3
if ( ! empty ( $riga [ 'idarticolo' ])) {
$codice_articolo = [
2019-01-03 18:54:09 +01:00
'CodiceTipo' => 'OSM' ,
2019-01-03 21:17:04 +01:00
'CodiceValore' => $database -> fetchOne ( 'SELECT `codice` FROM `mg_articoli` WHERE `id` = ' . prepare ( $riga [ 'idarticolo' ]))[ 'codice' ],
2019-01-03 18:54:09 +01:00
];
2019-01-03 21:17:04 +01:00
$dettaglio [ 'CodiceArticolo' ] = $codice_articolo ;
}
2018-12-29 12:03:22 +01:00
$dettaglio [ 'Descrizione' ] = $riga [ 'descrizione' ];
$dettaglio [ 'Quantita' ] = $riga [ 'qta' ];
if ( ! empty ( $riga [ 'um' ])) {
$dettaglio [ 'UnitaMisura' ] = $riga [ 'um' ];
}
if ( ! empty ( $riga [ 'data_inizio_periodo' ])) {
$dettaglio [ 'DataInizioPeriodo' ] = $riga [ 'data_inizio_periodo' ];
}
if ( ! empty ( $riga [ 'data_fine_periodo' ])) {
$dettaglio [ 'DataFinePeriodo' ] = $riga [ 'data_fine_periodo' ];
}
$dettaglio [ 'PrezzoUnitario' ] = $prezzo_unitario ;
2019-01-03 18:54:09 +01:00
// Sconto (2.2.1.10)
2018-12-29 12:03:22 +01:00
$riga [ 'sconto_unitario' ] = floatval ( $riga [ 'sconto_unitario' ]);
if ( ! empty ( $riga [ 'sconto_unitario' ])) {
$sconto = [
'Tipo' => $riga [ 'sconto_unitario' ] > 0 ? 'SC' : 'MG' ,
];
if ( $riga [ 'tipo_sconto' ] == 'PRC' ) {
$sconto [ 'Percentuale' ] = $riga [ 'sconto_unitario' ];
} else {
$sconto [ 'Importo' ] = $riga [ 'sconto_unitario' ];
}
$dettaglio [ 'ScontoMaggiorazione' ] = $sconto ;
}
$dettaglio [ 'PrezzoTotale' ] = $prezzo_totale ;
$dettaglio [ 'AliquotaIVA' ] = $percentuale ;
if ( ! empty ( $riga [ 'idritenutaacconto' ])) {
$dettaglio [ 'Ritenuta' ] = 'SI' ;
}
if ( empty ( $percentuale )) {
2019-01-05 17:47:03 +01:00
//Controllo aggiuntivo codice_natura_fe per evitare che venga riportato il tag vuoto
if ( ! empty ( $iva [ 'codice_natura_fe' ])) {
$dettaglio [ 'Natura' ] = $iva [ 'codice_natura_fe' ];
}
2018-12-29 12:03:22 +01:00
}
if ( ! empty ( $riga [ 'riferimento_amministrazione' ])) {
$dettaglio [ 'RiferimentoAmministrazione' ] = $riga [ 'riferimento_amministrazione' ];
}
$result [] = [
'DettaglioLinee' => $dettaglio ,
];
}
// Riepiloghi per IVA per percentuale
$riepiloghi_percentuale = $database -> fetchArray ( 'SELECT SUM(`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`) as totale, SUM(`co_righe_documenti`.`iva`) as iva, `co_iva`.`esigibilita`, `co_iva`.`percentuale`, `co_iva`.`dicitura` FROM `co_righe_documenti` INNER JOIN `co_iva` ON `co_iva`.`id` = `co_righe_documenti`.`idiva` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND
`co_iva` . `codice_natura_fe` IS NULL AND sconto_globale = 0 GROUP BY `co_iva` . `percentuale` ' );
foreach ( $riepiloghi_percentuale as $riepilogo ) {
$iva = [
'AliquotaIVA' => $riepilogo [ 'percentuale' ],
2019-01-10 18:06:15 +01:00
'ImponibileImporto' => $riepilogo [ 'totale' ],
'Imposta' => $riepilogo [ 'iva' ],
2018-12-29 12:03:22 +01:00
'EsigibilitaIVA' => $riepilogo [ 'esigibilita' ],
];
//Con split payment EsigibilitaIVA sempre a S
if ( $documento [ 'split_payment' ]) {
$iva [ 'EsigibilitaIVA' ] = 'S' ;
}
// TODO: la dicitura può essere diversa tra diverse IVA con stessa percentuale/natura
// nei riepiloghi viene fatto un accorpamento percentuale/natura
if ( ! empty ( $riepilogo [ 'dicitura' ])) {
// $iva['RiferimentoNormativo'] = $riepilogo['dicitura'];
}
$result [] = [
'DatiRiepilogo' => $iva ,
];
}
// Riepiloghi per IVA per natura
$riepiloghi_natura = $database -> fetchArray ( 'SELECT SUM(`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`) as totale, SUM(`co_righe_documenti`.`iva`) as iva, `co_iva`.`esigibilita`, `co_iva`.`codice_natura_fe` FROM `co_righe_documenti` INNER JOIN `co_iva` ON `co_iva`.`id` = `co_righe_documenti`.`idiva` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND
`co_iva` . `codice_natura_fe` IS NOT NULL GROUP BY `co_iva` . `codice_natura_fe` ' );
foreach ( $riepiloghi_natura as $riepilogo ) {
$iva = [
'AliquotaIVA' => 0 ,
'Natura' => $riepilogo [ 'codice_natura_fe' ],
2019-01-10 18:06:15 +01:00
'ImponibileImporto' => $riepilogo [ 'totale' ],
'Imposta' => $riepilogo [ 'iva' ],
2018-12-29 12:03:22 +01:00
'EsigibilitaIVA' => $riepilogo [ 'esigibilita' ],
];
//Con split payment EsigibilitaIVA sempre a S
if ( $documento [ 'split_payment' ]) {
$iva [ 'EsigibilitaIVA' ] = 'S' ;
}
$result [] = [
'DatiRiepilogo' => $iva ,
];
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiPagamento .
*
* @ return array
*/
protected static function getDatiPagamento ( $fattura )
{
$documento = $fattura -> getDocumento ();
$database = database ();
$co_pagamenti = $database -> fetchOne ( 'SELECT * FROM `co_pagamenti` WHERE `id` = ' . prepare ( $documento [ 'idpagamento' ]));
$result = [
'CondizioniPagamento' => ( $co_pagamenti [ 'prc' ] == 100 ) ? 'TP02' : 'TP01' ,
];
$co_scadenziario = $database -> fetchArray ( 'SELECT * FROM `co_scadenziario` WHERE `iddocumento` = ' . prepare ( $documento [ 'id' ]));
foreach ( $co_scadenziario as $scadenza ) {
$pagamento = [
'ModalitaPagamento' => $co_pagamenti [ 'codice_modalita_pagamento_fe' ],
'DataScadenzaPagamento' => $scadenza [ 'scadenza' ],
2019-01-10 18:06:15 +01:00
'ImportoPagamento' => $scadenza [ 'da_pagare' ],
2018-12-29 12:03:22 +01:00
];
if ( ! empty ( $documento [ 'idbanca' ])) {
$co_banche = $database -> fetchOne ( 'SELECT * FROM co_banche WHERE id = ' . prepare ( $documento [ 'idbanca' ]));
if ( ! empty ( $co_banche [ 'nome' ])) {
$pagamento [ 'IstitutoFinanziario' ] = $co_banche [ 'nome' ];
}
if ( ! empty ( $co_banche [ 'iban' ])) {
$pagamento [ 'IBAN' ] = $co_banche [ 'iban' ];
}
if ( ! empty ( $co_banche [ 'bic' ])) {
$pagamento [ 'BIC' ] = $co_banche [ 'bic' ];
}
}
}
2019-01-10 18:06:15 +01:00
$result [] = [
'DettaglioPagamento' => $pagamento ,
];
2018-12-29 12:03:22 +01:00
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag Allegati .
*
* @ return array
*/
protected static function getAllegati ( $fattura )
{
$documento = $fattura -> getDocumento ();
$cliente = $fattura -> getCliente ();
$attachments = [];
// Informazioni sul modulo
$id_module = Modules :: get ( 'Fatture di vendita' )[ 'id' ];
$directory = Uploads :: getDirectory ( $id_module );
// Allegati
$allegati = Uploads :: get ([
'id_module' => $id_module ,
'id_record' => $documento [ 'id' ],
]);
// Inclusione
foreach ( $allegati as $allegato ) {
if ( $allegato [ 'category' ] == 'Fattura Elettronica' ) {
$file = DOCROOT . '/' . $directory . '/' . $allegato [ 'filename' ];
$attachments [] = [
'NomeAttachment' => $allegato [ 'name' ],
'FormatoAttachment' => Uploads :: fileInfo ( $file )[ 'extension' ],
'Attachment' => base64_encode ( file_get_contents ( $file )),
];
}
}
// Aggiunta della stampa
$print = false ;
if ( $cliente [ 'tipo' ] == 'Privato' ) {
$print = setting ( 'Allega stampa per fattura verso Privati' );
} elseif ( $cliente [ 'tipo' ] == 'Azienda' ) {
$print = setting ( 'Allega stampa per fattura verso Aziende' );
} else {
$print = setting ( 'Allega stampa per fattura verso PA' );
}
if ( ! $print ) {
return $attachments ;
}
$data = $fattura -> getUploadData ();
$dir = static :: getDirectory ();
$rapportino_nome = sanitizeFilename ( $documento [ 'numero_esterno' ] . '.pdf' );
$filename = slashes ( DOCROOT . '/' . $dir . '/' . $rapportino_nome );
Uploads :: delete ( $rapportino_nome , $data );
$print = Prints :: getModulePredefinedPrint ( $id_module );
Prints :: render ( $print [ 'id' ], $documento [ 'id' ], $filename );
Uploads :: register ( array_merge ([
'name' => 'Stampa allegata' ,
'original' => $rapportino_nome ,
], $data ));
$attachments [] = [
'NomeAttachment' => 'Fattura' ,
'FormatoAttachment' => 'PDF' ,
'Attachment' => base64_encode ( file_get_contents ( $filename )),
];
return $attachments ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag FatturaElettronicaHeader .
*
* @ return array
*/
protected static function getHeader ( $fattura )
{
$result = [
'DatiTrasmissione' => static :: getDatiTrasmissione ( $fattura ),
'CedentePrestatore' => static :: getCedentePrestatore ( $fattura ),
'CessionarioCommittente' => static :: getCessionarioCommittente ( $fattura ),
];
2019-01-05 11:11:48 +01:00
2019-01-05 17:47:03 +01:00
//Terzo Intermediario o Soggetto Emittente
if ( ! empty ( setting ( 'Terzo intermediario' ))) {
$result [ 'TerzoIntermediarioOSoggettoEmittente' ] = static :: getTerzoIntermediarioOSoggettoEmittente ( $fattura );
$result [ 'SoggettoEmittente' ] = 'TZ' ;
}
2018-12-29 12:03:22 +01:00
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag FatturaElettronicaBody .
*
* @ return array
*/
protected static function getBody ( $fattura )
{
$result = [
'DatiGenerali' => static :: getDatiGenerali ( $fattura ),
'DatiBeniServizi' => static :: getDatiBeniServizi ( $fattura ),
'DatiPagamento' => static :: getDatiPagamento ( $fattura ),
];
// Allegati
$allegati = static :: getAllegati ( $fattura );
if ( ! empty ( $allegati )) {
foreach ( $allegati as $allegato ) {
$result [] = [
'Allegati' => $allegato ,
];
}
}
return $result ;
}
/**
* Prepara i contenuti per la generazione dell ' XML della fattura .
* Effettua inoltre dei controlli interni di validità sui campi previsti dallo standard .
*
* @ param mixed $input
* @ param string $key
*
* @ return mixed
*/
protected function prepareForXML ( $input , $key = null )
{
$output = null ;
if ( is_array ( $input )) {
foreach ( $input as $key => $value ) {
$output [ $key ] = $this -> prepareForXML ( $value , $key );
}
} elseif ( ! is_null ( $input )) {
$info = static :: $validators [ $key ];
$size = isset ( $info [ 'size' ]) ? $info [ 'size' ] : null ;
$output = $input ;
2019-01-03 21:17:04 +01:00
2018-12-29 12:03:22 +01:00
// Operazioni di normalizzazione
// Formattazione decimali
if ( $info [ 'type' ] == 'decimal' ) {
$output = number_format ( $output , 2 , '.' , '' );
}
2019-01-03 21:17:04 +01:00
2018-12-29 12:03:22 +01:00
// Formattazione date
elseif ( $info [ 'type' ] == 'date' ) {
$object = DateTime :: createFromFormat ( 'Y-m-d H:i:s' , $output );
if ( is_object ( $object )) {
$output = $object -> format ( 'Y-m-d' );
}
}
2019-01-03 21:17:04 +01:00
2018-12-29 12:03:22 +01:00
// Formattazione testo
elseif ( $info [ 'type' ] == 'string' ) {
}
// Riduzione delle dimensioni
if ( $info [ 'type' ] != 'integer' && isset ( $size [ 1 ])) {
$output = trim ( $output );
$output = S :: create ( $output ) -> substr ( 0 , $size [ 1 ]) -> __toString ();
}
// Validazione
if ( $info [ 'type' ] == 'string' || $info [ 'type' ] == 'normalizedString' ) {
$validator = v :: stringType ();
if ( isset ( $size [ 1 ])) {
$validator = $validator -> length ( $size [ 0 ], $size [ 1 ]);
}
} elseif ( $info [ 'type' ] == 'decimal' ) {
$validator = v :: floatVal ();
} elseif ( $info [ 'type' ] == 'integer' ) {
$validator = v :: intVal ();
} elseif ( $info [ 'type' ] == 'date' ) {
$validator = v :: date ();
}
if ( ! empty ( $validator )) {
$validation = $validator -> validate ( $output );
// Segnalazione dell'irregolarità
if ( ! intval ( $validation )) {
$this -> errors [] = $key ;
}
}
}
return $output ;
}
protected function getUploadData ()
{
return [
'category' => tr ( 'Fattura elettronica' ),
'id_module' => Modules :: get ( 'Fatture di vendita' )[ 'id' ],
'id_record' => $this -> getDocumento ()[ 'id' ],
];
}
2018-07-05 17:56:38 +02:00
}