2018-09-24 18:10:16 +02:00
< ? php
2020-09-07 15:04:06 +02:00
/*
* OpenSTAManager : il software gestionale open source per l ' assistenza tecnica e la fatturazione
2021-01-20 15:08:51 +01:00
* Copyright ( C ) DevCode s . r . l .
2020-09-07 15:04:06 +02:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2018-09-24 18:10:16 +02:00
2018-11-30 15:33:25 +01:00
namespace Plugins\ImportFE ;
2018-09-24 18:10:16 +02:00
2018-12-29 12:03:22 +01:00
use Modules\Anagrafiche\Anagrafica ;
use Modules\Anagrafiche\Nazione ;
use Modules\Anagrafiche\Tipo as TipoAnagrafica ;
2021-10-18 10:23:39 +02:00
use Modules\Banche\Banca ;
2018-12-29 12:03:22 +01:00
use Modules\Fatture\Fattura ;
2018-09-24 18:10:16 +02:00
use Modules\Fatture\Stato as StatoFattura ;
use Modules\Fatture\Tipo as TipoFattura ;
2018-12-29 12:03:22 +01:00
use Util\XML ;
2018-09-24 18:10:16 +02:00
/**
* Classe per la gestione della fatturazione elettronica in XML .
*
2019-04-18 18:18:05 -07:00
* @ since 2.4 . 9
2018-09-24 18:10:16 +02:00
*/
class FatturaElettronica
{
2024-01-15 15:30:45 +01:00
protected static $directory ;
2018-11-30 15:33:25 +01:00
/** @var array Percorso del file XML */
2024-01-15 15:30:45 +01:00
protected $file ;
2018-11-30 15:33:25 +01:00
2018-09-24 18:10:16 +02:00
/** @var array XML della fattura */
2024-01-15 15:30:45 +01:00
protected $xml ;
2018-09-24 18:10:16 +02:00
2019-05-03 15:37:49 -07:00
/** @var Fattura Fattura collegata */
2024-01-15 15:30:45 +01:00
protected $fattura ;
2018-09-24 18:10:16 +02:00
2019-02-20 16:07:42 +01:00
public function __construct ( $name )
2018-09-24 18:10:16 +02:00
{
2019-02-20 16:07:42 +01:00
$this -> file = static :: getImportDirectory () . '/' . $name ;
2019-02-13 11:26:56 +01:00
2020-10-29 16:48:37 +01:00
if ( string_ends_with ( $name , '.p7m' )) {
2019-02-13 11:26:56 +01:00
$file = XML :: decodeP7M ( $this -> file );
2019-02-13 12:04:36 +01:00
if ( ! empty ( $file )) {
2019-02-13 11:26:56 +01:00
delete ( $this -> file );
$this -> file = $file ;
}
}
2018-12-07 10:56:49 +01:00
$this -> xml = XML :: readFile ( $this -> file );
2018-09-24 18:10:16 +02:00
2018-09-25 11:55:52 +02:00
// Individuazione fattura pre-esistente
$dati_generali = $this -> getBody ()[ 'DatiGenerali' ][ 'DatiGeneraliDocumento' ];
$data = $dati_generali [ 'Data' ];
$numero = $dati_generali [ 'Numero' ];
2018-11-30 15:33:25 +01:00
$progressivo_invio = $this -> getHeader ()[ 'DatiTrasmissione' ][ 'ProgressivoInvio' ];
2018-09-25 11:55:52 +02:00
$fattura = Fattura :: where ([
2018-11-30 15:33:25 +01:00
'progressivo_invio' => $progressivo_invio ,
2018-12-07 10:56:49 +01:00
'numero_esterno' => $numero ,
2018-09-25 11:55:52 +02:00
'data' => $data ,
]) -> first ();
2022-05-12 15:44:30 +02:00
if ( ! empty ( $fattura ) && $fattura -> tipo -> dir == 'uscita' ) {
2024-01-15 15:30:45 +01:00
throw new \UnexpectedValueException ();
2018-11-30 15:33:25 +01:00
}
}
public static function getImportDirectory ()
{
if ( ! isset ( self :: $directory )) {
2024-01-15 15:30:45 +01:00
$module = \Modules :: get ( 'Fatture di acquisto' );
2018-11-30 15:33:25 +01:00
2019-07-05 09:53:53 +02:00
$plugins = $module -> plugins ;
if ( ! empty ( $plugins )) {
$plugin = $plugins -> first ( function ( $value , $key ) {
return $value -> name == 'Fatturazione Elettronica' ;
});
2018-11-30 15:33:25 +01:00
2020-09-23 13:36:37 +02:00
self :: $directory = base_dir () . '/' . $plugin -> upload_directory ;
2019-07-05 09:53:53 +02:00
}
2018-11-30 15:33:25 +01:00
}
return self :: $directory ;
}
public static function store ( $filename , $content )
{
2018-12-12 17:26:25 +01:00
$directory = static :: getImportDirectory ();
$file = $directory . '/' . $filename ;
2018-11-30 15:33:25 +01:00
2018-12-12 17:26:25 +01:00
directory ( $directory );
2018-11-30 15:33:25 +01:00
file_put_contents ( $file , $content );
return $filename ;
}
2019-02-20 16:07:42 +01:00
public static function isValid ( $name )
2018-11-30 15:33:25 +01:00
{
try {
2019-02-20 16:07:42 +01:00
new static ( $name );
2018-11-30 15:33:25 +01:00
return true ;
2024-01-15 15:30:45 +01:00
} catch ( \UnexpectedValueException $e ) {
2019-04-18 18:18:05 -07:00
$file = static :: getImportDirectory () . '/' . $name ;
delete ( $file );
2018-11-30 15:33:25 +01:00
return false ;
2018-09-25 11:55:52 +02:00
}
2018-09-24 18:10:16 +02:00
}
2019-04-18 18:18:05 -07:00
public static function manage ( $name )
2018-09-24 18:10:16 +02:00
{
2019-04-18 18:18:05 -07:00
try {
2019-07-22 12:52:48 +02:00
$manager = new FatturaOrdinaria ( $name );
2018-09-24 18:10:16 +02:00
2019-07-22 12:52:48 +02:00
$tipo = $manager -> getBody ()[ 'DatiGenerali' ][ 'DatiGeneraliDocumento' ][ 'TipoDocumento' ];
if ( $tipo == 'TD06' ) {
$manager = new Parcella ( $name );
}
2024-01-15 15:30:45 +01:00
} catch ( \UnexpectedValueException $e ) {
2019-07-22 12:52:48 +02:00
$manager = new FatturaSemplificata ( $name );
2018-09-24 18:10:16 +02:00
}
2019-07-22 12:52:48 +02:00
return $manager ;
2018-09-24 18:10:16 +02:00
}
2019-04-18 18:18:05 -07:00
public function getHeader ()
2018-09-24 18:10:16 +02:00
{
2019-04-18 18:18:05 -07:00
return $this -> xml [ 'FatturaElettronicaHeader' ];
2018-09-24 18:10:16 +02:00
}
2019-04-18 18:18:05 -07:00
public function getBody ()
2018-09-24 18:10:16 +02:00
{
2019-04-18 18:18:05 -07:00
return $this -> xml [ 'FatturaElettronicaBody' ];
}
2019-02-18 10:34:31 +01:00
2019-04-18 18:18:05 -07:00
public function delete ()
{
delete ( $this -> file );
2018-09-24 18:10:16 +02:00
}
2018-09-25 11:55:52 +02:00
public function getAllegati ()
2018-09-24 18:10:16 +02:00
{
2018-09-25 11:55:52 +02:00
$result = $this -> getBody ()[ 'Allegati' ];
2019-04-18 18:18:05 -07:00
$result = $this -> forceArray ( $result );
2018-09-25 11:55:52 +02:00
2018-12-07 10:56:49 +01:00
return array_clean ( $result );
2018-09-24 18:10:16 +02:00
}
2018-11-30 15:33:25 +01:00
public function saveAllegati ()
2018-09-24 18:10:16 +02:00
{
2018-09-25 11:55:52 +02:00
$allegati = $this -> getAllegati ();
2018-09-24 18:10:16 +02:00
2024-01-15 15:30:45 +01:00
$module = \Modules :: get ( 'Fatture di acquisto' );
2018-09-25 16:47:44 +02:00
2018-11-30 15:33:25 +01:00
$info = [
'category' => tr ( 'Fattura Elettronica' ),
'id_module' => $module -> id ,
'id_record' => $this -> fattura -> id ,
];
2018-09-24 18:10:16 +02:00
foreach ( $allegati as $allegato ) {
$content = base64_decode ( $allegato [ 'Attachment' ]);
2018-12-12 17:54:31 +01:00
2021-04-02 14:58:34 +02:00
$extension = '.pdf' ;
2018-12-12 17:54:31 +01:00
if ( ! empty ( $allegato [ 'FormatoAttachment' ])) {
$extension = '.' . strtolower ( $allegato [ 'FormatoAttachment' ]);
}
$original = $allegato [ 'NomeAttachment' ] . $extension ;
2022-05-10 15:46:23 +02:00
try {
2024-01-15 15:30:45 +01:00
\Uploads :: upload ( $content , array_merge ( $info , [
2022-05-10 15:46:23 +02:00
'name' => $allegato [ 'NomeAttachment' ],
'original_name' => $original ,
]));
2024-01-15 15:30:45 +01:00
} catch ( \UnexpectedValueException $e ) {
2023-08-04 14:54:28 +02:00
}
2018-09-24 18:10:16 +02:00
}
2018-11-30 15:33:25 +01:00
// Registrazione XML come allegato
2024-01-15 15:30:45 +01:00
\Uploads :: upload ( $this -> file , array_merge ( $info , [
2018-11-30 15:33:25 +01:00
'name' => tr ( 'Fattura Elettronica' ),
2021-03-08 11:20:04 +01:00
'original_name' => basename ( $this -> file ),
2018-11-30 15:33:25 +01:00
]));
2018-09-24 18:10:16 +02:00
}
2019-07-24 15:29:03 +02:00
public function findAnagrafica ( $type = 'Fornitore' )
2018-09-25 11:55:52 +02:00
{
2019-04-18 18:18:05 -07:00
$info = $this -> getAnagrafe ();
2024-02-06 12:07:51 +01:00
$anagrafica = Anagrafica :: where ( 'tipo' , $type );
2019-04-18 18:18:05 -07:00
2019-07-24 15:41:04 +02:00
if ( ! empty ( $info [ 'partita_iva' ]) && ! empty ( $info [ 'codice_fiscale' ])) {
$anagrafica -> where ( 'piva' , $info [ 'partita_iva' ])
2022-11-24 21:34:14 +01:00
-> orWhere ( 'codice_fiscale' , $info [ 'codice_fiscale' ])
-> orWhere ( 'piva' , 'like' , '__' . $info [ 'partita_iva' ])
-> orwhere ( 'codice_fiscale' , 'like' , '__' . $info [ 'codice_fiscale' ]);
2019-07-24 15:41:04 +02:00
} elseif ( ! empty ( $info [ 'codice_fiscale' ])) {
2022-11-24 21:34:14 +01:00
$anagrafica -> where ( 'codice_fiscale' , $info [ 'codice_fiscale' ])
-> orWhere ( 'codice_fiscale' , 'like' , '__' . $info [ 'codice_fiscale' ]);
2019-07-24 15:41:04 +02:00
} elseif ( ! empty ( $info [ 'partita_iva' ])) {
2022-11-24 21:34:14 +01:00
$anagrafica -> where ( 'piva' , $info [ 'partita_iva' ])
-> orWhere ( 'piva' , 'like' , '__' . $info [ 'partita_iva' ]);
}
2024-02-06 12:07:51 +01:00
$anagrafica = $anagrafica -> get ();
2024-01-15 15:30:45 +01:00
// Se non trovo l'anagrafica tra i fornitori, provo a ricercarla anche tra i clienti
2024-02-06 12:07:51 +01:00
if ( empty ( $anagrafica )) {
2022-11-24 21:34:14 +01:00
$type = 'Cliente' ;
2024-02-06 17:25:50 +01:00
2024-02-06 12:07:51 +01:00
$anagrafica = Anagrafica :: where ( 'tipo' , $type );
2023-08-04 14:54:28 +02:00
2022-11-24 21:34:14 +01:00
if ( ! empty ( $info [ 'partita_iva' ]) && ! empty ( $info [ 'codice_fiscale' ])) {
$anagrafica -> where ( 'piva' , $info [ 'partita_iva' ])
-> orWhere ( 'codice_fiscale' , $info [ 'codice_fiscale' ])
-> orWhere ( 'piva' , 'like' , '__' . $info [ 'partita_iva' ])
-> orwhere ( 'codice_fiscale' , 'like' , '__' . $info [ 'codice_fiscale' ]);
} elseif ( ! empty ( $info [ 'codice_fiscale' ])) {
$anagrafica -> where ( 'codice_fiscale' , $info [ 'codice_fiscale' ])
-> orWhere ( 'codice_fiscale' , 'like' , '__' . $info [ 'codice_fiscale' ]);
} elseif ( ! empty ( $info [ 'partita_iva' ])) {
$anagrafica -> where ( 'piva' , $info [ 'partita_iva' ])
-> orWhere ( 'piva' , 'like' , '__' . $info [ 'partita_iva' ]);
}
2019-04-18 18:18:05 -07:00
}
2019-07-22 18:35:13 +02:00
return $anagrafica -> first ();
}
/**
* Restituisce l ' anagrafica collegata alla fattura , eventualmente generandola con i dati forniti .
*
* @ param string $type
*
* @ return Anagrafica
*/
public function saveAnagrafica ( $type = 'Fornitore' )
{
2019-07-24 15:29:03 +02:00
$anagrafica = $this -> findAnagrafica ( $type );
2019-04-18 18:18:05 -07:00
if ( ! empty ( $anagrafica )) {
return $anagrafica ;
}
2019-07-22 18:35:13 +02:00
$info = $this -> getAnagrafe ();
2019-04-18 18:18:05 -07:00
$anagrafica = Anagrafica :: build ( $info [ 'ragione_sociale' ], $info [ 'nome' ], $info [ 'cognome' ], [
2024-02-06 17:25:50 +01:00
( new TipoAnagrafica ()) -> getByName ( $type ) -> id_record ,
2019-04-18 18:18:05 -07:00
]);
if ( ! empty ( $info [ 'partita_iva' ])) {
$anagrafica -> partita_iva = $info [ 'partita_iva' ];
}
if ( ! empty ( $info [ 'codice_fiscale' ])) {
$anagrafica -> codice_fiscale = $info [ 'codice_fiscale' ];
}
// Informazioni sull'anagrafica
if ( ! empty ( $info [ 'rea' ])) {
if ( ! empty ( $info [ 'rea' ][ 'codice' ])) {
$anagrafica -> codicerea = $info [ 'rea' ][ 'codice' ];
}
if ( ! empty ( $info [ 'rea' ][ 'capitale_sociale' ])) {
$anagrafica -> capitale_sociale = $info [ 'rea' ][ 'capitale_sociale' ];
}
}
$anagrafica -> save ();
// Informazioni sulla sede
$sede = $anagrafica -> sedeLegale ;
$sede -> indirizzo = $info [ 'sede' ][ 'indirizzo' ];
$sede -> cap = $info [ 'sede' ][ 'cap' ];
2020-06-30 13:33:42 +02:00
$sede -> citta = $info [ 'sede' ][ 'citta' ];
2019-04-18 18:18:05 -07:00
if ( ! empty ( $info [ 'sede' ][ 'provincia' ])) {
$sede -> provincia = $info [ 'sede' ][ 'provincia' ];
}
$sede -> nazione () -> associate ( Nazione :: where ( 'iso2' , $info [ 'sede' ][ 'nazione' ]) -> first ());
$contatti = $info [ 'contatti' ];
if ( ! empty ( $contatti )) {
if ( ! empty ( $contatti [ 'telefono' ])) {
$sede -> telefono = $contatti [ 'telefono' ];
}
if ( ! empty ( $contatti [ 'fax' ])) {
$sede -> fax = $contatti [ 'fax' ];
}
if ( ! empty ( $contatti [ 'email' ])) {
$sede -> email = $contatti [ 'email' ];
}
}
$sede -> save ();
return $anagrafica ;
2018-09-25 11:55:52 +02:00
}
2018-09-24 18:10:16 +02:00
/**
* Registra la fattura elettronica come fattura del gestionale .
*
2019-07-22 12:52:48 +02:00
* @ param int $id_pagamento
* @ param int $id_sezionale
* @ param int $id_tipo
2019-07-22 11:35:44 +02:00
* @ param string $data_registrazione
2019-07-22 12:52:48 +02:00
* @ param int $ref_fattura
2019-07-22 11:35:44 +02:00
*
2019-04-18 18:18:05 -07:00
* @ return Fattura
2018-09-24 18:10:16 +02:00
*/
2021-02-04 13:19:14 +01:00
public function saveFattura ( $id_pagamento , $id_sezionale , $id_tipo , $data_registrazione , $ref_fattura , $is_ritenuta_pagata = false )
2018-09-24 18:10:16 +02:00
{
$dati_generali = $this -> getBody ()[ 'DatiGenerali' ][ 'DatiGeneraliDocumento' ];
2020-10-09 16:43:07 +02:00
$data = self :: parseDate ( $dati_generali [ 'Data' ]);
2019-01-10 18:41:25 +01:00
2022-01-11 11:54:50 +01:00
$fattura = $this -> prepareFattura ( $id_tipo , $data , $data_registrazione , $id_sezionale , $ref_fattura );
2019-07-22 12:52:48 +02:00
$this -> fattura = $fattura ;
2018-10-29 22:23:29 +01:00
$numero_esterno = $dati_generali [ 'Numero' ];
2018-11-30 15:33:25 +01:00
$progressivo_invio = $this -> getHeader ()[ 'DatiTrasmissione' ][ 'ProgressivoInvio' ];
2018-09-24 18:10:16 +02:00
2018-11-30 15:33:25 +01:00
$fattura -> progressivo_invio = $progressivo_invio ;
2018-10-29 22:23:29 +01:00
$fattura -> numero_esterno = $numero_esterno ;
2018-09-25 16:47:44 +02:00
$fattura -> idpagamento = $id_pagamento ;
2021-02-04 13:19:14 +01:00
$fattura -> is_ritenuta_pagata = $is_ritenuta_pagata ;
2019-04-04 08:30:58 -07:00
2023-06-27 17:16:56 +02:00
// Salvataggio banca fornitore se specificata nel file XML
$info_pagamento = $this -> getBody ()[ 'DatiPagamento' ][ 'DettaglioPagamento' ];
if ( $info_pagamento [ 'IBAN' ]) {
$banca_fornitore = Banca :: where ( 'iban' , $info_pagamento [ 'IBAN' ]) -> first ();
if ( empty ( $banca_fornitore )) {
$anagrafica = $fattura -> anagrafica ;
$nome = $info_pagamento [ 'IstitutoFinanziario' ] ? : 'Banca di ' . $anagrafica -> ragione_sociale ;
$banca_fornitore = Banca :: build ( $anagrafica , $nome , $info_pagamento [ 'IBAN' ], $info_pagamento [ 'BIC' ] ? : '' );
}
}
2021-09-30 14:48:15 +02:00
// Banca addebito del cliente o banca collegata al pagamento
if ( ! empty ( $fattura -> anagrafica -> idbanca_acquisti )) {
$banca = $fattura -> anagrafica -> idbanca_acquisti ;
} else {
$banca = Banca :: where ( 'id_pianodeiconti3' , $fattura -> pagamento -> idconto_acquisti ) -> where ( 'id_anagrafica' , setting ( 'Azienda predefinita' )) -> first () -> id ;
}
$fattura -> id_banca_azienda = $banca ;
2021-09-28 10:32:24 +02:00
2019-07-22 11:35:44 +02:00
// Riferimento per nota di credito e debito
$fattura -> ref_documento = $ref_fattura ? : null ;
2019-07-22 15:45:36 +02:00
// Per il destinatario, la data di registrazione della fattura assume grande rilievo ai fini IVA, poiché determina la decorrenza dei termini per poter esercitare il diritto alla detrazione.
2019-04-18 18:18:05 -07:00
// La data di ricezione della fattura è contenuta all’ interno della “ricevuta di consegna” visibile al trasmittente della stessa.
2019-07-22 15:45:36 +02:00
$fattura -> data_registrazione = $data_registrazione ;
2021-07-30 17:20:28 +02:00
$fattura -> data_competenza = $fattura -> data ;
2018-09-24 18:10:16 +02:00
$stato_documento = StatoFattura :: where ( 'descrizione' , 'Emessa' ) -> first ();
$fattura -> stato () -> associate ( $stato_documento );
2019-01-10 18:41:25 +01:00
$causali = $dati_generali [ 'Causale' ];
2019-04-18 18:18:05 -07:00
if ( ! empty ( $causali )) {
$note = '' ;
2019-01-10 18:41:25 +01:00
foreach ( $causali as $causale ) {
$note .= $causale ;
}
2019-07-23 18:04:01 +02:00
2019-01-10 18:41:25 +01:00
$fattura -> note = $note ;
}
2021-02-26 18:45:52 +01:00
// Sconto finale da ScontoMaggiorazione: non importato
2018-09-25 11:55:52 +02:00
$fattura -> save ();
2018-09-24 18:10:16 +02:00
2020-04-27 10:24:03 +02:00
// Fix generazione idsede
$fattura -> refresh ();
2019-04-18 18:18:05 -07:00
return $fattura ;
2018-09-24 18:10:16 +02:00
}
2018-11-30 15:33:25 +01:00
2019-04-18 18:18:05 -07:00
public function getFattura ()
2018-11-30 15:33:25 +01:00
{
2019-04-18 18:18:05 -07:00
return $this -> fattura ;
}
public function save ( $info = [])
{
2021-02-04 13:19:14 +01:00
$this -> saveFattura ( $info [ 'id_pagamento' ], $info [ 'id_segment' ], $info [ 'id_tipo' ], $info [ 'data_registrazione' ], $info [ 'ref_fattura' ], $info [ 'is_ritenuta_pagata' ]);
2019-04-18 18:18:05 -07:00
2023-09-28 12:31:03 +02:00
$this -> saveRighe ( $info [ 'articoli' ], $info [ 'iva' ], $info [ 'conto' ], $info [ 'movimentazione' ], $info [ 'crea_articoli' ], $info [ 'tipo_riga_riferimento' ], $info [ 'id_riga_riferimento' ], $info [ 'tipo_riga_riferimento_vendita' ], $info [ 'id_riga_riferimento_vendita' ], $info [ 'update_info' ], $info [ 'serial' ]);
2019-04-18 18:18:05 -07:00
$this -> saveAllegati ();
2021-10-21 09:45:51 +02:00
$this -> getFattura () -> save ([ 'forza_emissione' ]);
2019-04-18 18:18:05 -07:00
return $this -> getFattura () -> id ;
}
2020-10-09 16:43:07 +02:00
public static function parseDate ( $data )
{
return date ( 'Y-m-d' , strtotime ( $data ));
}
2022-01-11 11:54:50 +01:00
protected function prepareFattura ( $id_tipo , $data , $data_registrazione , $id_sezionale , $ref_fattura )
2019-07-22 12:52:48 +02:00
{
$anagrafica = $this -> saveAnagrafica ();
$tipo = TipoFattura :: where ( 'id' , $id_tipo ) -> first ();
2022-01-11 11:54:50 +01:00
$fattura = Fattura :: build ( $anagrafica , $tipo , $data , $id_sezionale , null , $data_registrazione );
2019-07-22 12:52:48 +02:00
$this -> fattura = $fattura ;
// Riferimento per nota di credito e debito
$fattura -> ref_documento = $ref_fattura ? : null ;
return $fattura ;
}
2019-04-18 18:18:05 -07:00
protected function forceArray ( $result )
{
$result = isset ( $result [ 0 ]) ? $result : [ $result ];
return $result ;
2018-11-30 15:33:25 +01:00
}
2018-09-24 18:10:16 +02:00
}