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-12-29 12:03:22 +01:00
use FluidXml\FluidXml ;
use GuzzleHttp\Client ;
2018-09-17 17:51:55 +02:00
use Modules ;
2019-01-10 19:31:26 +01:00
use Modules\Anagrafiche\Anagrafica ;
use Modules\Fatture\Fattura ;
2018-09-17 17:51:55 +02:00
use Prints ;
2019-02-15 13:00:05 +01:00
use Translator ;
2019-01-10 19:31:26 +01:00
use UnexpectedValueException ;
2018-12-29 12:03:22 +01:00
use Uploads ;
2019-04-23 19:24:34 +02:00
use Validate ;
2018-07-05 17:56:38 +02:00
/**
* Classe per la gestione della fatturazione elettronica in XML .
*
* @ since 2.4 . 2
*/
class FatturaElettronica
{
2019-01-10 19:31:26 +01:00
/** @var Anagrafica Informazioni sull'anagrafica Azienda */
2018-07-06 18:06:23 +02:00
protected static $azienda = [];
2018-07-05 17:56:38 +02:00
2019-01-10 19:31:26 +01:00
/** @var Anagrafica Informazioni sull'anagrafica Cliente del documento */
2018-07-06 18:06:23 +02:00
protected $cliente = [];
2019-01-10 19:31:26 +01:00
/** @var Modules\Fatture\Fattura Informazioni sul documento */
protected $documento = null ;
/** @var Validator Oggetto dedicato alla validazione dell'XML */
protected $validator = null ;
2018-07-06 18:06:23 +02:00
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-12-29 12:03:22 +01:00
public function __construct ( $id_documento )
{
// Documento
2019-01-10 19:31:26 +01:00
$this -> documento = Fattura :: find ( $id_documento );
2018-12-29 12:03:22 +01:00
// Controllo sulla possibilità di creare la fattura elettronica
// Posso fatturare ai privati utilizzando il codice fiscale
2019-01-25 18:01:23 +01:00
if ( $this -> documento -> stato -> descrizione == 'Bozza' ) {
2019-01-10 19:31:26 +01:00
throw new UnexpectedValueException ();
2018-12-29 12:03:22 +01:00
}
}
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 .
*
2019-01-10 19:31:26 +01:00
* @ return bool
2018-12-29 12:03:22 +01:00
*/
public function isGenerated ()
{
$documento = $this -> getDocumento ();
return ! empty ( $documento [ 'progressivo_invio' ]) && file_exists ( DOCROOT . '/' . static :: getDirectory () . '/' . $this -> getFilename ());
}
/**
* Restituisce le informazioni sull ' anagrafica azienda .
*
2019-01-10 19:31:26 +01:00
* @ return Anagrafica
2018-12-29 12:03:22 +01:00
*/
public static function getAzienda ()
{
if ( empty ( static :: $azienda )) {
2019-01-10 19:31:26 +01:00
static :: $azienda = Anagrafica :: find ( setting ( 'Azienda predefinita' ));
2018-12-29 12:03:22 +01:00
}
return static :: $azienda ;
}
/**
* Restituisce le informazioni sull ' anagrafica cliente legata al documento .
*
2019-01-10 19:31:26 +01:00
* @ return Anagrafica
2018-12-29 12:03:22 +01:00
*/
public function getCliente ()
{
2019-01-10 19:31:26 +01:00
return $this -> getDocumento () -> anagrafica ;
2018-12-29 12:03:22 +01:00
}
2019-01-05 11:11:48 +01:00
2018-12-29 12:03:22 +01:00
/**
* Restituisce le righe del documento .
*
* @ return array
*/
public function getRighe ()
{
if ( empty ( $this -> righe )) {
2019-02-15 13:00:05 +01:00
$this -> righe = $this -> getDocumento () -> getRighe ();
2018-12-29 12:03:22 +01:00
}
return $this -> righe ;
}
/**
2019-01-22 17:16:17 +01:00
* Restituisce i contratti collegati al documento ( contratti e interventi e ordini ) .
2018-12-29 12:03:22 +01:00
*
* @ return array
*/
public function getContratti ()
{
if ( empty ( $this -> contratti )) {
$documento = $this -> getDocumento ();
$database = database ();
2019-07-22 16:13:38 +02:00
$contratti = $database -> fetchArray ( 'SELECT `id_documento_fe` AS id_documento, `num_item`, `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 AND `co_righe_documenti`.`idordine` = 0' );
2019-01-25 11:02:36 +01:00
2019-07-22 16:13:38 +02:00
$preventivi = $database -> fetchArray ( 'SELECT `id_documento_fe` AS id_documento, `num_item`, `codice_cig`, `codice_cup` FROM `co_preventivi` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idpreventivo` = `co_preventivi`.`id` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND `id_documento_fe` IS NOT NULL AND `co_righe_documenti`.`idordine` = 0' );
2018-12-29 12:03:22 +01:00
2019-07-22 16:13:38 +02:00
$interventi = $database -> fetchArray ( 'SELECT `id_documento_fe` AS id_documento, `num_item`, `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 AND `co_righe_documenti`.`idcontratto` = 0 AND `co_righe_documenti`.`idpreventivo` = 0' );
2019-01-25 11:02:36 +01:00
2019-07-16 09:50:43 +02:00
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
$dati = $dati_aggiuntivi [ 'dati_contratto' ] ? : [];
$this -> contratti = array_unique ( array_merge ( $contratti , $preventivi , $interventi , $dati ));
2018-12-29 12:03:22 +01:00
}
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 ();
2019-07-22 16:13:38 +02:00
$ordini = $database -> fetchArray ( 'SELECT `id_documento_fe` AS id_documento, `num_item`, `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 AND `co_righe_documenti`.`idddt` = 0' );
$ddt = $database -> fetchArray ( 'SELECT `id_documento_fe` AS id_documento, `num_item`, `codice_cig`, `codice_cup` FROM `dt_ddt` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idddt` = `dt_ddt`.`id` WHERE `co_righe_documenti`.`iddocumento` = ' . prepare ( $documento [ 'id' ]) . ' AND `id_documento_fe` IS NOT NULL' );
2018-12-29 12:03:22 +01:00
2019-07-16 09:50:43 +02:00
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
$dati = $dati_aggiuntivi [ 'dati_ordine' ] ? : [];
2019-07-22 16:13:38 +02:00
$this -> ordini = array_merge ( $ordini , $ddt , $dati );
2018-12-29 12:03:22 +01:00
}
return $this -> ordini ;
}
/**
* Restituisce le fatture collegate al documento .
*
* @ return array
*/
public function getFattureCollegate ()
{
if ( empty ( $this -> fatture_collegate )) {
$documento = $this -> getDocumento ();
$database = database ();
2019-07-16 09:50:43 +02:00
$note_accredito = $database -> fetchArray ( 'SELECT numero_esterno AS id_documento, data FROM co_documenti WHERE id=' . prepare ( $documento [ 'ref_documento' ]));
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
$dati = $dati_aggiuntivi [ 'dati_fatture' ] ? : [];
2018-12-29 12:03:22 +01:00
2019-07-16 09:50:43 +02:00
$this -> fatture_collegate = array_merge ( $note_accredito , $dati );
2018-12-29 12:03:22 +01:00
}
return $this -> fatture_collegate ;
}
/**
* Restituisce le informazioni relative al documento .
*
2019-02-15 13:00:05 +01:00
* @ return Fattura
2018-12-29 12:03:22 +01:00
*/
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 ()
{
2019-01-10 19:31:26 +01:00
if ( ! isset ( $this -> validator )) {
2018-12-29 12:03:22 +01:00
$this -> toXML ();
}
2019-01-10 19:31:26 +01:00
return $this -> validator -> getErrors ();
2018-12-29 12:03:22 +01:00
}
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' ,
2019-02-01 18:19:13 +01:00
'data_stato_fe' => date ( 'Y-m-d H:i:s' ),
2018-12-29 12:03:22 +01:00
], [ '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 )
{
2019-02-01 18:19:13 +01:00
if ( ! empty ( setting ( 'Terzo intermediario' ))) {
$anagrafica = Anagrafica :: find ( setting ( 'Terzo intermediario' ));
} else {
$anagrafica = static :: getAzienda ();
}
2019-03-29 12:46:17 +01:00
$prefix = 'IT' . ( ! empty ( $anagrafica [ 'codice_fiscale' ] and ( $anagrafica [ 'codice_fiscale' ] != $anagrafica [ 'piva' ])) ? $anagrafica [ 'codice_fiscale' ] : str_replace ( $anagrafica -> nazione -> iso2 , '' , $anagrafica [ '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
2019-01-10 19:31:26 +01:00
$this -> validator = new Validator ([
2018-12-29 12:03:22 +01:00
'FatturaElettronicaHeader' => static :: getHeader ( $this ),
'FatturaElettronicaBody' => static :: getBody ( $this ),
]);
2019-01-10 19:31:26 +01:00
$xml = $this -> validator -> validate ();
2018-12-29 12:03:22 +01:00
$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 )
2019-02-01 18:19:13 +01:00
{
// Se in impostazioni ho definito un terzo intermediario (es. Aruba, Teamsystem)
if ( ! empty ( setting ( 'Terzo intermediario' ))) {
$anagrafica = Anagrafica :: find ( setting ( 'Terzo intermediario' ));
} else {
$anagrafica = static :: getAzienda ();
}
$documento = $fattura -> getDocumento ();
2018-12-29 12:03:22 +01:00
$cliente = $fattura -> getCliente ();
2019-06-25 17:09:26 +02:00
$sede = database () -> fetchOne ( 'SELECT `codice_destinatario` FROM `an_sedi` WHERE `id` = ' . prepare ( $documento [ 'idsede_destinazione' ]));
2019-01-10 19:31:26 +01:00
if ( ! empty ( $sede )) {
$codice_destinatario = $sede [ 'codice_destinatario' ];
} else {
$codice_destinatario = $cliente -> codice_destinatario ;
}
2018-12-29 12:03:22 +01:00
// 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)
2019-01-10 19:31:26 +01:00
$default_code = ( $cliente -> nazione -> iso2 != 'IT' ) ? 'XXXXXXX' : $default_code ;
2018-12-29 12:03:22 +01:00
// Generazione dell'header
2019-02-13 17:49:01 +01:00
// Se all'Anagrafe Tributaria il trasmittente è censito con il codice fiscale, es. ditte individuali
$result = [
'IdTrasmittente' => [
'IdPaese' => $anagrafica -> nazione -> iso2 ,
2019-03-29 12:46:17 +01:00
'IdCodice' => ( ! empty ( $anagrafica [ 'codice_fiscale' ]) and ( $anagrafica [ 'codice_fiscale' ] != $anagrafica [ 'piva' ])) ? $anagrafica [ 'codice_fiscale' ] : str_replace ( $anagrafica -> nazione -> iso2 , '' , $anagrafica [ 'piva' ]),
2019-02-13 17:49:01 +01:00
],
];
$result [] = [
2018-12-29 12:03:22 +01:00
'ProgressivoInvio' => $documento [ 'progressivo_invio' ],
'FormatoTrasmissione' => ( $cliente [ 'tipo' ] == 'Ente pubblico' ) ? 'FPA12' : 'FPR12' ,
2019-05-04 00:32:28 +02:00
'CodiceDestinatario' => ! empty ( $codice_destinatario ) ? $codice_destinatario : $default_code ,
2018-12-29 12:03:22 +01:00
];
// Telefono di contatto
2019-02-01 17:55:28 +01:00
if ( ! empty ( $anagrafica [ 'telefono' ])) {
$result [ 'ContattiTrasmittente' ][ 'Telefono' ] = $anagrafica [ 'telefono' ];
2018-12-29 12:03:22 +01:00
}
// Email di contatto
2019-02-01 17:55:28 +01:00
if ( ! empty ( $anagrafica [ 'email' ])) {
$result [ 'ContattiTrasmittente' ][ 'Email' ] = $anagrafica [ 'email' ];
2018-12-29 12:03:22 +01:00
}
// Inizializzazione PEC solo se anagrafica azienda e codice destinatario non compilato, per privato e PA la PEC non serve
2019-01-22 09:01:43 +01:00
if ( empty ( $cliente [ 'codice_destinatario' ]) && $cliente [ 'tipo' ] == 'Azienda' && ! empty ( $cliente [ 'pec' ])) {
2018-12-29 12:03:22 +01:00
$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-02-13 17:49:01 +01:00
if ( ! empty ( $anagrafica -> nazione -> iso2 )) {
2019-01-10 19:31:26 +01:00
$result [ 'IdFiscaleIVA' ][ 'IdPaese' ] = $anagrafica -> nazione -> iso2 ;
2019-01-05 17:47:03 +01:00
}
2019-01-05 11:11:48 +01:00
2019-02-01 18:46:49 +01:00
$result [ 'IdFiscaleIVA' ][ 'IdCodice' ] = str_replace ( $anagrafica -> nazione -> iso2 , '' , $anagrafica [ 'piva' ]);
2018-12-29 12:03:22 +01:00
}
// Codice fiscale
if ( ! empty ( $anagrafica [ 'codice_fiscale' ])) {
2019-02-07 18:27:15 +01:00
$result [ 'CodiceFiscale' ] = preg_replace ( '/\s+/' , '' , $anagrafica [ 'codice_fiscale' ]);
2018-12-29 12:03:22 +01:00
}
2019-01-10 18:06:15 +01:00
2019-01-10 18:41:25 +01:00
if ( ! empty ( $anagrafica [ 'nome' ]) or ! empty ( $anagrafica [ 'cognome' ])) {
$result [ 'Anagrafica' ] = [
//'Denominazione' => $anagrafica['ragione_sociale'],
'Nome' => $anagrafica [ 'nome' ],
'Cognome' => $anagrafica [ 'cognome' ],
// TODO: 'Titolo' => $anagrafica['ragione_sociale'],
// TODO: CodEORI
];
} else {
$result [ 'Anagrafica' ] = [
'Denominazione' => $anagrafica [ 'ragione_sociale' ],
//'Nome' => $anagrafica['nome'],
//'Cognome' => $anagrafica['cognome'],
// TODO: 'Titolo' => $anagrafica['ragione_sociale'],
// TODO: CodEORI
];
}
2019-01-10 18:06:15 +01:00
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 .
*
2019-01-10 19:31:26 +01:00
* @ param array $anagrafica
*
2018-12-29 12:03:22 +01:00
* @ return array
*/
protected static function getSede ( $anagrafica )
{
$result = [
'Indirizzo' => $anagrafica [ 'indirizzo' ],
2019-02-28 16:04:19 +01:00
'CAP' => ( $anagrafica -> nazione -> iso2 == 'IT' ) ? $anagrafica [ 'cap' ] : '00000' ,
2018-12-29 12:03:22 +01:00
'Comune' => $anagrafica [ 'citta' ],
];
2019-01-03 15:24:21 +01:00
// Provincia impostata e SOLO SE nazione ITALIA
2019-01-10 19:31:26 +01:00
if ( ! empty ( $anagrafica [ 'provincia' ]) && $anagrafica -> nazione -> iso2 == 'IT' ) {
2019-01-03 15:24:21 +01:00
$result [ 'Provincia' ] = strtoupper ( $anagrafica [ 'provincia' ]);
2018-12-29 12:03:22 +01:00
}
2019-01-17 16:11:10 +01:00
if ( ! empty ( $anagrafica -> nazione -> iso2 )) {
$result [ 'Nazione' ] = $anagrafica -> nazione -> iso2 ;
}
2018-12-29 12:03:22 +01:00
return $result ;
}
/**
2019-01-30 13:04:59 +01:00
* Restituisce l ' array responsabile per la generazione del tag CedentePrestatore ( mia Azienda ovvero il fornitore ) ( 1.2 ) .
2018-12-29 12:03:22 +01:00
*
* @ return array
*/
protected static function getCedentePrestatore ( $fattura )
2019-01-30 12:21:10 +01:00
{
2019-02-01 18:19:13 +01:00
$documento = $fattura -> getDocumento ();
2019-01-30 12:21:10 +01:00
2019-02-01 18:19:13 +01:00
//Fattura per conto terzi, il cliente diventa il cedente al posto della mia Azienda (fornitore)
if ( $documento [ 'is_fattura_conto_terzi' ]) {
$azienda = $fattura -> getCliente ();
} else {
$azienda = static :: getAzienda ();
}
2019-01-30 12:21:10 +01:00
2018-12-29 12:03:22 +01:00
$result = [
'DatiAnagrafici' => static :: getDatiAnagrafici ( $azienda , true ),
'Sede' => static :: getSede ( $azienda ),
];
// IscrizioneREA
if ( ! empty ( $azienda [ 'codicerea' ])) {
2019-01-31 02:19:05 +01:00
$codice = explode ( '-' , clean ( $azienda [ 'codicerea' ], '\-' ));
2018-12-29 12:03:22 +01:00
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-30 13:04:59 +01:00
* Restituisce l ' array responsabile per la generazione del tag CessionarioCommittente ( Cliente ) ( 1.4 ) .
2018-12-29 12:03:22 +01:00
*
* @ return array
*/
protected static function getCessionarioCommittente ( $fattura )
2019-02-01 18:19:13 +01:00
{
$documento = $fattura -> getDocumento ();
//Fattura per conto terzi, la mia Azienda (fornitore) diventa il cessionario al posto del cliente
if ( $documento [ 'is_fattura_conto_terzi' ]) {
$cliente = static :: getAzienda ();
} else {
$cliente = $fattura -> getCliente ();
}
2018-12-29 12:03:22 +01:00
$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 )
{
2019-01-11 15:57:46 +01:00
$intermediario = Anagrafica :: find ( setting ( 'Terzo intermediario' ));
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
2019-02-24 10:24:39 +01:00
protected static function chunkSplit ( $str , $chunklen )
2019-02-21 16:16:43 +01:00
{
$res = [];
$k = ceil ( strlen ( $str ) / $chunklen );
for ( $i = 0 ; $i < $k ; ++ $i ) {
$res [] = substr ( $str , $i * $chunklen , $chunklen );
}
return $res ;
}
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 ();
$result = [
2019-01-10 19:31:26 +01:00
'TipoDocumento' => $documento -> tipo -> codice_tipo_documento_fe ,
2018-12-29 12:03:22 +01:00
'Divisa' => 'EUR' ,
'Data' => $documento [ 'data' ],
'Numero' => $documento [ 'numero_esterno' ],
];
$righe = $fattura -> getRighe ();
2019-02-01 18:19:13 +01:00
// Ritenuta d'Acconto
2018-12-29 12:03:22 +01:00
$id_ritenuta = null ;
2019-02-01 18:19:13 +01:00
$totale_ritenutaacconto = 0 ;
// Rivalsa
$id_rivalsainps = null ;
2019-01-05 11:11:48 +01:00
$totale_rivalsainps = 0 ;
2019-02-01 18:19:13 +01:00
2018-12-29 12:03:22 +01:00
foreach ( $righe as $riga ) {
2019-02-01 18:19:13 +01:00
if ( ! empty ( $riga [ 'idritenutaacconto' ]) and empty ( $riga [ 'is_descrizione' ])) {
2018-12-29 12:03:22 +01:00
$id_ritenuta = $riga [ 'idritenutaacconto' ];
2019-01-05 11:11:48 +01:00
$totale_ritenutaacconto += $riga [ 'ritenutaacconto' ];
}
2019-01-30 17:01:58 +01:00
if ( ! empty ( $riga [ 'idrivalsainps' ]) and empty ( $riga [ 'is_descrizione' ])) {
2019-01-05 11:11:48 +01:00
$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' ] = [
2019-04-23 19:24:34 +02:00
'TipoRitenuta' => Validate :: isValidTaxCode ( $azienda [ 'codice_fiscale' ]) ? '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)
2019-05-17 18:50:32 +02:00
$bollo = $documento -> getBollo ();
if ( ! empty ( $bollo )) {
2018-12-29 12:03:22 +01:00
$result [ 'DatiBollo' ] = [
'BolloVirtuale' => 'SI' ,
2019-05-17 18:50:32 +02:00
'ImportoBollo' => $bollo ,
2018-12-29 12:03:22 +01:00
];
}
2019-01-30 17:01:58 +01:00
// Cassa Previdenziale (Rivalsa) (2.1.1.7)
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 ));
2019-01-22 15:52:22 +01:00
$percentuale = database () -> fetchOne ( 'SELECT percentuale FROM co_rivalse WHERE id = ' . prepare ( $id_rivalsainps ))[ 'percentuale' ];
2019-01-05 11:11:48 +01:00
2018-12-29 12:03:22 +01:00
$dati_cassa = [
2019-04-14 00:19:01 +02:00
'TipoCassa' => setting ( 'Tipo Cassa Previdenziale' ),
2019-01-05 11:11:48 +01:00
'AlCassa' => $percentuale ,
'ImportoContributoCassa' => $totale_rivalsainps ,
2019-01-10 19:31:26 +01:00
'ImponibileCassa' => $documento -> imponibile ,
2018-12-29 12:03:22 +01:00
'AliquotaIVA' => $iva [ 'percentuale' ],
];
2019-04-23 19:28:05 +02:00
if ( $riga -> calcolo_ritenuta_acconto == 'IMP+RIV' ) {
2018-12-29 12:03:22 +01:00
$dati_cassa [ 'Ritenuta' ] = 'SI' ;
2019-01-25 11:02:36 +01:00
}
if ( ! empty ( $iva [ 'codice_natura_fe' ])) {
$dati_cassa [ 'Natura' ] = $iva [ 'codice_natura_fe' ];
}
2019-01-22 17:16:17 +01:00
//$dati_cassa['RiferimentoAmministrazione'] = '';
2018-12-29 12:03:22 +01:00
$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)
2019-03-29 12:46:17 +01:00
// Disabilitazione per aggiornamento sconti
2019-01-03 21:17:04 +01:00
// Importo Totale Documento (2.1.1.9)
2019-02-12 11:41:32 +01:00
// Valorizzare l’ importo complessivo lordo della fattura (onnicomprensivo di Iva, bollo, contributi previdenziali, ecc…)
2019-02-07 12:08:57 +01:00
$result [ 'ImportoTotaleDocumento' ] = abs ( $documento -> totale );
2018-12-29 12:03:22 +01:00
2019-02-26 21:38:26 +01:00
// Arrotondamento - Eventuale arrotondamento sul totale documento (ammette anche il segno negativo) (2.1.1.10)
// Causale - Descrizione della causale del documento (2.1.1.11)
$causali = self :: chunkSplit ( $documento [ 'note' ], 200 );
2019-02-26 11:01:35 +01:00
foreach ( $causali as $causale ) {
$result [] = [ 'Causale' => $causale ];
}
2019-02-26 21:38:26 +01:00
// Art73 - Ciò consente al cedente/prestatore l'emissione nello stesso anno di più documenti aventi stesso numero (2.1.1.12)
2019-07-15 18:34:59 +02:00
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
if ( ! empty ( $dati_aggiuntivi [ 'art73' ])) {
$result [ 'Art73' ] = 'SI' ;
}
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 = [];
2019-02-05 12:38:28 +01:00
//Se imposto il vettore deve essere indicata anche la p.iva nella sua anagrafica
2018-12-29 12:03:22 +01:00
if ( $documento [ 'idvettore' ]) {
2019-01-10 19:31:26 +01:00
$vettore = Anagrafica :: find ( $documento [ 'idvettore' ]);
2018-12-29 12:03:22 +01:00
$result [ 'DatiAnagraficiVettore' ] = static :: getDatiAnagrafici ( $vettore );
}
2019-02-13 17:49:01 +01:00
if ( ! empty ( $causale )) {
$result [ 'CausaleTrasporto' ] = $causale ;
}
if ( ! empty ( $documento [ 'n_colli' ])) {
$result [ 'NumeroColli' ] = $documento [ 'n_colli' ];
}
if ( ! empty ( $aspetto )) {
$result [ 'Descrizione' ] = $aspetto ;
}
if ( $documento [ 'tipo_resa' ]) {
2018-12-29 12:03:22 +01:00
$result [ 'TipoResa' ] = $documento [ 'tipo_resa' ];
2019-02-13 17:49:01 +01:00
}
2018-12-29 12:03:22 +01:00
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiOrdineAcquisto .
*
* @ return array
*/
2019-07-16 09:50:43 +02:00
protected static function getDatiOrdineAcquisto ( $fattura , $lista = null )
2018-12-29 12:03:22 +01:00
{
2019-07-16 09:50:43 +02:00
$lista = isset ( $lista ) ? $lista : $fattura -> getOrdiniAcquisto ();
2018-12-29 12:03:22 +01:00
$result = [];
2019-07-16 09:50:43 +02:00
foreach ( $lista as $element ) {
$dati = [];
2019-07-16 10:01:16 +02:00
foreach ( $element [ 'riferimento_linea' ] as $linea ) {
2019-07-16 09:50:43 +02:00
$dati [] = [
'RiferimentoNumeroLinea' => $linea ,
2018-12-29 12:03:22 +01:00
];
}
2019-07-16 09:50:43 +02:00
$dati [ 'IdDocumento' ] = $element [ 'id_documento' ];
if ( ! empty ( $element [ 'data' ])) {
$dati [ 'Data' ] = $element [ 'data' ];
}
2019-02-26 21:37:37 +01:00
if ( ! empty ( $element [ 'num_item' ])) {
$dati [ 'NumItem' ] = $element [ 'num_item' ];
}
2019-07-16 09:50:43 +02:00
if ( ! empty ( $element [ 'codice_commessa' ])) {
$dati [ 'CodiceCommessaConvenzione' ] = $element [ 'codice_commessa' ];
}
2018-12-29 12:03:22 +01:00
if ( ! empty ( $element [ 'codice_cup' ])) {
$dati [ 'CodiceCUP' ] = $element [ 'codice_cup' ];
}
2019-07-16 11:55:14 +02:00
if ( ! empty ( $element [ 'codice_cig' ])) {
$dati [ 'CodiceCIG' ] = $element [ 'codice_cig' ];
}
2018-12-29 12:03:22 +01:00
$result [] = $dati ;
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiContratto .
*
* @ return array
*/
protected static function getDatiContratto ( $fattura )
{
$contratti = $fattura -> getContratti ();
2019-07-16 09:50:43 +02:00
return self :: getDatiOrdineAcquisto ( $fattura , $contratti );
}
2018-12-29 12:03:22 +01:00
2019-07-16 09:50:43 +02:00
/**
* Restituisce l ' array responsabile per la generazione del tag DatiConvenzione .
*
* @ return array
*/
protected static function getDatiConvenzione ( $fattura )
{
$documento = $fattura -> getDocumento ();
2019-05-10 06:32:06 +02:00
2019-07-16 09:50:43 +02:00
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
$dati = $dati_aggiuntivi [ 'dati_convenzione' ] ? : [];
2019-05-10 06:32:06 +02:00
2019-07-16 09:50:43 +02:00
return self :: getDatiOrdineAcquisto ( $fattura , $dati );
}
2018-12-29 12:03:22 +01:00
2019-07-16 09:50:43 +02:00
/**
* Restituisce l ' array responsabile per la generazione del tag DatiRicezione .
*
* @ return array
*/
protected static function getDatiRicezione ( $fattura )
{
$documento = $fattura -> getDocumento ();
2018-12-29 12:03:22 +01:00
2019-07-16 09:50:43 +02:00
$dati_aggiuntivi = $documento -> dati_aggiuntivi_fe ;
$dati = $dati_aggiuntivi [ 'dati_ricezione' ] ? : [];
return self :: getDatiOrdineAcquisto ( $fattura , $dati );
2018-12-29 12:03:22 +01:00
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiFattureCollegate .
*
* @ return array
*/
protected static function getDatiFattureCollegate ( $fattura )
{
$fatture = $fattura -> getFattureCollegate ();
2019-07-16 09:50:43 +02:00
return self :: getDatiOrdineAcquisto ( $fattura , $fatture );
2018-12-29 12:03:22 +01:00
}
/**
* 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 ,
];
}
}
}
2019-07-16 09:50:43 +02:00
// Controllo le le righe per la fatturazione di contratti
$dati_convenzioni = static :: getDatiConvenzione ( $fattura );
if ( ! empty ( $dati_convenzioni )) {
foreach ( $dati_convenzioni as $dato ) {
if ( ! empty ( $dato )) {
$result [] = [
'DatiConvenzione' => $dato ,
];
}
}
}
// Controllo le le righe per la fatturazione di contratti
$dati_ricezioni = static :: getDatiRicezione ( $fattura );
if ( ! empty ( $dati_ricezioni )) {
foreach ( $dati_ricezioni as $dato ) {
if ( ! empty ( $dato )) {
$result [] = [
'DatiRicezione' => $dato ,
];
}
}
}
2018-12-29 12:03:22 +01:00
// 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 ,
];
}
}
}
2019-01-10 19:31:26 +01:00
if ( $documento -> tipo -> descrizione == 'Fattura accompagnatoria di vendita' ) {
2018-12-29 12:03:22 +01:00
$result [ 'DatiTrasporto' ] = static :: getDatiTrasporto ( $fattura );
}
return $result ;
}
/**
* Restituisce l ' array responsabile per la generazione del tag DatiBeniServizi .
*
2019-02-15 13:00:05 +01:00
* @ param $fattura
*
* @ throws \Exception
*
2018-12-29 12:03:22 +01:00
* @ return array
*/
protected static function getDatiBeniServizi ( $fattura )
{
$documento = $fattura -> getDocumento ();
2019-02-15 13:00:05 +01:00
$ritenuta_contributi = $documento -> ritenutaContributi ;
$righe = $documento -> getRighe ();
2018-12-29 12:03:22 +01:00
$database = database ();
$result = [];
// Righe del documento
2019-02-21 11:51:03 +01:00
$iva_descrizioni = $righe -> first ( function ( $item , $key ) {
return $item -> aliquota != null ;
}) -> aliquota ;
2019-08-02 13:01:16 +02:00
$numero = 1 ;
foreach ( $righe as $idx => $riga ) {
2019-07-15 16:53:18 +02:00
$dati_aggiuntivi = $riga -> dati_aggiuntivi_fe ;
2018-12-29 12:03:22 +01:00
$dettaglio = [
2019-08-02 13:01:16 +02:00
'NumeroLinea' => $numero ++ ,
2018-12-29 12:03:22 +01:00
];
2019-01-03 21:17:04 +01:00
// 2.2.1.2
2019-07-15 16:53:18 +02:00
if ( ! empty ( $dati_aggiuntivi [ 'tipo_cessione_prestazione' ])) {
$dettaglio [ 'TipoCessionePrestazione' ] = $dati_aggiuntivi [ 'tipo_cessione_prestazione' ];
2018-12-29 12:03:22 +01:00
}
2019-01-03 21:17:04 +01:00
2019-02-15 13:00:05 +01:00
// 2.2.1.3
if ( $riga -> isArticolo ()) {
2019-04-16 10:25:56 +02:00
//$tipo_codice = $database->fetchOne('SELECT `mg_categorie`.`nome` FROM `mg_categorie` INNER JOIN `mg_articoli` ON `mg_categorie`.`id` = `mg_articoli`.`id_categoria` WHERE `mg_articoli`.`id` = '.prepare($riga['idarticolo']))['nome'];
2019-01-25 11:02:36 +01:00
2019-01-03 21:17:04 +01:00
$codice_articolo = [
2019-04-16 10:25:56 +02:00
'CodiceTipo' => 'COD' ,
2019-02-15 13:00:05 +01:00
'CodiceValore' => $riga -> articolo -> codice ,
2019-01-03 18:54:09 +01:00
];
2019-01-03 21:17:04 +01:00
$dettaglio [ 'CodiceArticolo' ] = $codice_articolo ;
}
2019-01-25 11:02:36 +01:00
2019-02-01 18:19:13 +01:00
// Non ammesso ’
// $descrizione = html_entity_decode($riga['descrizione'], ENT_HTML5, 'UTF-8');
2019-01-25 11:02:36 +01:00
$descrizione = str_replace ( '>' , ' ' , $riga [ 'descrizione' ]);
$descrizione = str_replace ( '…' , '...' , $descrizione );
2019-02-15 13:00:05 +01:00
$descrizione = str_replace ( '’ ' , ' ' , $descrizione );
2019-01-25 11:02:36 +01:00
2019-04-19 01:39:58 +02:00
if ( setting ( 'Riferimento dei documenti in Fattura Elettronica' )) {
$ref = doc_references ( $riga -> toArray (), 'entrata' , [ 'iddocumento' ]);
if ( ! empty ( $ref )) {
$descrizione .= " \n " . $ref [ 'description' ];
}
2019-01-30 12:21:10 +01:00
}
2019-02-15 13:00:05 +01:00
$dettaglio [ 'Descrizione' ] = $descrizione ;
$qta = abs ( $riga -> qta ) ? : 1 ;
$dettaglio [ 'Quantita' ] = $qta ;
2018-12-29 12:03:22 +01:00
if ( ! empty ( $riga [ 'um' ])) {
$dettaglio [ 'UnitaMisura' ] = $riga [ 'um' ];
}
2019-07-15 16:53:18 +02:00
if ( ! empty ( $dati_aggiuntivi [ 'data_inizio_periodo' ])) {
$dettaglio [ 'DataInizioPeriodo' ] = $dati_aggiuntivi [ 'data_inizio_periodo' ];
2018-12-29 12:03:22 +01:00
}
2019-07-15 16:53:18 +02:00
if ( ! empty ( $dati_aggiuntivi [ 'data_fine_periodo' ])) {
$dettaglio [ 'DataFinePeriodo' ] = $dati_aggiuntivi [ 'data_fine_periodo' ];
2018-12-29 12:03:22 +01:00
}
2019-05-04 00:32:28 +02:00
$dettaglio [ 'PrezzoUnitario' ] = $riga -> prezzo_unitario_vendita ? : 0 ;
2018-12-29 12:03:22 +01:00
2019-01-03 18:54:09 +01:00
// Sconto (2.2.1.10)
2019-04-12 18:59:31 +02:00
$sconto = $riga -> sconto ;
$sconto_unitario = $riga -> sconto_unitario ;
2019-04-19 01:39:58 +02:00
2019-04-18 11:38:51 +02:00
if ( ! empty (( float ) $sconto_unitario )) {
2018-12-29 12:03:22 +01:00
$sconto = [
2019-02-15 13:00:05 +01:00
'Tipo' => $riga -> sconto_unitario > 0 ? 'SC' : 'MG' ,
2018-12-29 12:03:22 +01:00
];
if ( $riga [ 'tipo_sconto' ] == 'PRC' ) {
2019-02-15 13:00:05 +01:00
$sconto [ 'Percentuale' ] = $sconto_unitario ;
2018-12-29 12:03:22 +01:00
} else {
2019-02-15 13:00:05 +01:00
$sconto [ 'Importo' ] = $sconto_unitario ;
2018-12-29 12:03:22 +01:00
}
$dettaglio [ 'ScontoMaggiorazione' ] = $sconto ;
}
2019-02-15 13:00:05 +01:00
$aliquota = $riga -> aliquota ? : $iva_descrizioni ;
$percentuale = floatval ( $aliquota -> percentuale );
2019-07-16 11:34:40 +02:00
$prezzo_totale = $documento -> isNota () ? - $riga -> totale_imponibile : $riga -> totale_imponibile ;
2019-07-16 11:57:33 +02:00
$prezzo_totale = $prezzo_totale ? : 0 ;
2019-07-16 11:33:19 +02:00
$dettaglio [ 'PrezzoTotale' ] = $prezzo_totale ;
2018-12-29 12:03:22 +01:00
$dettaglio [ 'AliquotaIVA' ] = $percentuale ;
2019-02-15 13:00:05 +01:00
if ( ! empty ( $riga [ 'idritenutaacconto' ]) && empty ( $riga [ 'is_descrizione' ])) {
2019-03-29 12:46:17 +01:00
if ( $riga [ 'calcolo_ritenuta_acconto' ] == 'IMP+RIV' ) {
$dettaglio [ 'Ritenuta' ] = 'SI' ;
}
2018-12-29 12:03:22 +01:00
}
2019-02-15 13:00:05 +01:00
// Controllo aggiuntivo codice_natura_fe per evitare che venga riportato il tag vuoto
if ( empty ( $percentuale ) && ! empty ( $aliquota [ 'codice_natura_fe' ])) {
$dettaglio [ 'Natura' ] = $aliquota [ 'codice_natura_fe' ];
2018-12-29 12:03:22 +01:00
}
2019-07-15 16:53:18 +02:00
if ( ! empty ( $dati_aggiuntivi [ 'riferimento_amministrazione' ])) {
$dettaglio [ 'RiferimentoAmministrazione' ] = $dati_aggiuntivi [ 'riferimento_amministrazione' ];
2018-12-29 12:03:22 +01:00
}
2019-01-10 18:41:25 +01:00
// AltriDatiGestionali (2.2.1.16) - Ritenuta ENASARCO
2019-02-01 18:19:13 +01:00
// https://forum.italia.it/uploads/default/original/2X/d/d35d721c3a3a601d2300378724a270154e23af52.jpeg
2019-02-15 13:00:05 +01:00
if ( ! empty ( $riga [ 'ritenuta_contributi' ])) {
2019-07-15 16:53:18 +02:00
$dettaglio [][ 'AltriDatiGestionali' ] = [
2019-01-10 18:41:25 +01:00
'TipoDato' => 'CASSA-PREV' ,
2019-04-14 00:19:01 +02:00
'RiferimentoTesto' => setting ( 'Tipo Cassa Previdenziale' ) . ' - ' . $ritenuta_contributi -> descrizione . ' (' . Translator :: numberToLocale ( $ritenuta_contributi -> percentuale ) . '%)' ,
2019-02-15 13:00:05 +01:00
'RiferimentoNumero' => $riga -> ritenuta_contributi ,
2019-01-10 18:41:25 +01:00
];
}
2019-07-15 16:53:18 +02:00
if ( ! empty ( $dati_aggiuntivi [ 'altri_dati' ])) {
foreach ( $dati_aggiuntivi [ 'altri_dati' ] as $dato ) {
$altri_dati = [];
if ( ! empty ( $dato [ 'tipo_dato' ])) {
$altri_dati [ 'TipoDato' ] = $dato [ 'tipo_dato' ];
}
if ( ! empty ( $dato [ 'riferimento_testo' ])) {
$altri_dati [ 'RiferimentoTesto' ] = $dato [ 'riferimento_testo' ];
}
if ( ! empty ( $dato [ 'riferimento_numero' ])) {
$altri_dati [ 'RiferimentoNumero' ] = $dato [ 'riferimento_numero' ];
}
if ( ! empty ( $dato [ 'riferimento_data' ])) {
$altri_dati [ 'RiferimentoData' ] = $dato [ 'riferimento_data' ];
}
$dettaglio [][ 'AltriDatiGestionali' ] = $altri_dati ;
}
}
2018-12-29 12:03:22 +01:00
$result [] = [
'DettaglioLinee' => $dettaglio ,
];
}
// Riepiloghi per IVA per percentuale
2019-02-14 18:33:25 +01:00
$riepiloghi_percentuale = $righe -> filter ( function ( $item , $key ) {
2019-02-21 11:51:03 +01:00
return $item -> aliquota != null && $item -> aliquota -> codice_natura_fe == null ;
2019-02-14 18:33:25 +01:00
}) -> groupBy ( function ( $item , $key ) {
return $item -> aliquota -> percentuale ;
});
2018-12-29 12:03:22 +01:00
foreach ( $riepiloghi_percentuale as $riepilogo ) {
2019-07-16 11:34:40 +02:00
$totale = round ( $riepilogo -> sum ( 'totale_imponibile' ) + $riepilogo -> sum ( 'rivalsa_inps' ), 2 );
2019-02-14 18:33:25 +01:00
$imposta = round ( $riepilogo -> sum ( 'iva' ) + $riepilogo -> sum ( 'iva_rivalsa_inps' ), 2 );
2019-07-16 11:33:19 +02:00
$totale = $documento -> isNota () ? - $totale : $totale ;
$imposta = $documento -> isNota () ? - $imposta : $imposta ;
2019-02-14 18:33:25 +01:00
$dati = $riepilogo -> first () -> aliquota ;
2018-12-29 12:03:22 +01:00
$iva = [
2019-02-14 18:33:25 +01:00
'AliquotaIVA' => $dati [ 'percentuale' ],
2019-07-16 11:33:19 +02:00
'ImponibileImporto' => $totale ,
'Imposta' => $imposta ,
2019-02-14 18:33:25 +01:00
'EsigibilitaIVA' => $dati [ 'esigibilita' ],
2018-12-29 12:03:22 +01:00
];
2019-02-14 18:33:25 +01:00
// Con split payment EsigibilitaIVA sempre a S
2018-12-29 12:03:22 +01:00
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'];
}
2019-01-25 11:02:36 +01:00
2019-02-14 18:33:25 +01:00
// 2.2.2
2018-12-29 12:03:22 +01:00
$result [] = [
'DatiRiepilogo' => $iva ,
];
}
// Riepiloghi per IVA per natura
2019-02-14 18:33:25 +01:00
$riepiloghi_natura = $righe -> filter ( function ( $item , $key ) {
2019-02-21 11:51:03 +01:00
return $item -> aliquota != null && $item -> aliquota -> codice_natura_fe != null ;
2019-02-14 18:33:25 +01:00
}) -> groupBy ( function ( $item , $key ) {
return $item -> aliquota -> codice_natura_fe ;
});
2018-12-29 12:03:22 +01:00
foreach ( $riepiloghi_natura as $riepilogo ) {
2019-07-16 11:34:40 +02:00
$totale = round ( $riepilogo -> sum ( 'totale_imponibile' ) + $riepilogo -> sum ( 'rivalsa_inps' ), 2 );
2019-02-14 18:33:25 +01:00
$imposta = round ( $riepilogo -> sum ( 'iva' ) + $riepilogo -> sum ( 'iva_rivalsa_inps' ), 2 );
2019-07-16 11:33:19 +02:00
$totale = $documento -> isNota () ? - $totale : $totale ;
$imposta = $documento -> isNota () ? - $imposta : $imposta ;
2019-02-14 18:33:25 +01:00
$dati = $riepilogo -> first () -> aliquota ;
2018-12-29 12:03:22 +01:00
$iva = [
'AliquotaIVA' => 0 ,
2019-02-15 13:00:05 +01:00
'Natura' => $dati -> codice_natura_fe ,
2019-07-16 11:33:19 +02:00
'ImponibileImporto' => $totale ,
'Imposta' => $imposta ,
2019-02-15 13:00:05 +01:00
'EsigibilitaIVA' => $dati -> esigibilita ,
'RiferimentoNormativo' => $dati -> descrizione ,
2018-12-29 12:03:22 +01:00
];
2019-02-14 18:33:25 +01:00
// Con split payment EsigibilitaIVA sempre a S
2018-12-29 12:03:22 +01:00
if ( $documento [ 'split_payment' ]) {
$iva [ 'EsigibilitaIVA' ] = 'S' ;
}
2019-01-25 11:02:36 +01:00
2019-02-14 18:33:25 +01:00
// 2.2.2
2018-12-29 12:03:22 +01:00
$result [] = [
'DatiRiepilogo' => $iva ,
];
}
return $result ;
}
/**
2019-01-30 16:42:28 +01:00
* Restituisce l ' array responsabile per la generazione del tag DatiPagamento ( 2.4 ) .
2018-12-29 12:03:22 +01:00
*
* @ return array
*/
protected static function getDatiPagamento ( $fattura )
{
$documento = $fattura -> getDocumento ();
2019-05-02 14:27:30 +02:00
$fattura = Fattura :: find ( $documento [ 'id' ]);
$banca = $fattura -> getBanca ();
2018-12-29 12:03:22 +01:00
$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:41:25 +01:00
'ImportoPagamento' => abs ( $scadenza [ 'da_pagare' ]),
2018-12-29 12:03:22 +01:00
];
2019-05-02 14:27:30 +02:00
if ( ! empty ( $banca [ 'appoggiobancario' ])) {
$pagamento [ 'IstitutoFinanziario' ] = $banca [ 'appoggiobancario' ];
}
if ( ! empty ( $banca [ 'codiceiban' ])) {
$pagamento [ 'IBAN' ] = clean ( $banca [ 'codiceiban' ]);
2018-12-29 12:03:22 +01:00
}
2019-05-02 14:27:30 +02:00
if ( ! empty ( $banca [ 'bic' ])) {
$pagamento [ 'BIC' ] = $banca [ 'bic' ];
}
2019-01-10 18:41:25 +01:00
$result [][ 'DettaglioPagamento' ] = $pagamento ;
}
2019-01-10 18:06:15 +01:00
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 ) {
2019-07-12 16:08:15 +02:00
if ( $allegato [ 'category' ] == 'Allegati Fattura Elettronica' ) {
2018-12-29 12:03:22 +01:00
$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 ();
$print = Prints :: getModulePredefinedPrint ( $id_module );
2019-07-10 11:53:35 +02:00
$info = Prints :: render ( $print [ 'id' ], $documento [ 'id' ], DOCROOT . '/' . $dir );
$name = 'Stampa allegata' ;
$is_presente = database () -> fetchNum ( 'SELECT id FROM zz_files WHERE id_module = ' . prepare ( $id_module ) . ' AND id_record = ' . prepare ( $documento [ 'id' ]) . ' AND name = ' . prepare ( $name ));
2019-07-10 15:02:09 +02:00
if ( empty ( $is_presente )) {
2019-07-10 11:53:35 +02:00
Uploads :: register ( array_merge ([
'name' => $name ,
'original' => basename ( $info [ 'path' ]),
], $data ));
}
2018-12-29 12:03:22 +01:00
$attachments [] = [
'NomeAttachment' => 'Fattura' ,
'FormatoAttachment' => 'PDF' ,
2019-07-10 11:53:35 +02:00
'Attachment' => base64_encode ( file_get_contents ( $info [ 'path' ])),
2018-12-29 12:03:22 +01:00
];
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 ;
}
protected function getUploadData ()
{
return [
2019-01-11 15:57:46 +01:00
'category' => tr ( 'Fattura Elettronica' ),
2018-12-29 12:03:22 +01:00
'id_module' => Modules :: get ( 'Fatture di vendita' )[ 'id' ],
'id_record' => $this -> getDocumento ()[ 'id' ],
];
}
2018-07-05 17:56:38 +02:00
}