mirror of
https://github.com/devcode-it/openstamanager.git
synced 2024-12-26 07:44:02 +01:00
441 lines
14 KiB
PHP
Executable File
441 lines
14 KiB
PHP
Executable File
<?php
|
||
/*
|
||
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
|
||
* Copyright (C) DevCode s.r.l.
|
||
*
|
||
* 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/>.
|
||
*/
|
||
|
||
namespace Plugins\ImportFE;
|
||
|
||
use Modules;
|
||
use Modules\Anagrafiche\Anagrafica;
|
||
use Modules\Anagrafiche\Nazione;
|
||
use Modules\Anagrafiche\Tipo as TipoAnagrafica;
|
||
use Modules\Banche\Banca;
|
||
use Modules\Fatture\Fattura;
|
||
use Modules\Fatture\Stato as StatoFattura;
|
||
use Modules\Fatture\Tipo as TipoFattura;
|
||
use UnexpectedValueException;
|
||
use Uploads;
|
||
use Util\XML;
|
||
|
||
/**
|
||
* Classe per la gestione della fatturazione elettronica in XML.
|
||
*
|
||
* @since 2.4.9
|
||
*/
|
||
class FatturaElettronica
|
||
{
|
||
protected static $directory = null;
|
||
|
||
/** @var array Percorso del file XML */
|
||
protected $file = null;
|
||
|
||
/** @var array XML della fattura */
|
||
protected $xml = null;
|
||
|
||
/** @var Fattura Fattura collegata */
|
||
protected $fattura = null;
|
||
|
||
public function __construct($name)
|
||
{
|
||
$this->file = static::getImportDirectory().'/'.$name;
|
||
|
||
if (string_ends_with($name, '.p7m')) {
|
||
$file = XML::decodeP7M($this->file);
|
||
|
||
if (!empty($file)) {
|
||
delete($this->file);
|
||
|
||
$this->file = $file;
|
||
}
|
||
}
|
||
|
||
$this->xml = XML::readFile($this->file);
|
||
|
||
// Individuazione fattura pre-esistente
|
||
$dati_generali = $this->getBody()['DatiGenerali']['DatiGeneraliDocumento'];
|
||
$data = $dati_generali['Data'];
|
||
$numero = $dati_generali['Numero'];
|
||
$progressivo_invio = $this->getHeader()['DatiTrasmissione']['ProgressivoInvio'];
|
||
|
||
$fattura = Fattura::where([
|
||
'progressivo_invio' => $progressivo_invio,
|
||
'numero_esterno' => $numero,
|
||
'data' => $data,
|
||
])->first();
|
||
|
||
if (!empty($fattura) && $fattura->tipo->dir == 'uscita') {
|
||
throw new UnexpectedValueException();
|
||
}
|
||
}
|
||
|
||
public static function getImportDirectory()
|
||
{
|
||
if (!isset(self::$directory)) {
|
||
$module = Modules::get('Fatture di acquisto');
|
||
|
||
$plugins = $module->plugins;
|
||
if (!empty($plugins)) {
|
||
$plugin = $plugins->first(function ($value, $key) {
|
||
return $value->name == 'Fatturazione Elettronica';
|
||
});
|
||
|
||
self::$directory = base_dir().'/'.$plugin->upload_directory;
|
||
}
|
||
}
|
||
|
||
return self::$directory;
|
||
}
|
||
|
||
public static function store($filename, $content)
|
||
{
|
||
$directory = static::getImportDirectory();
|
||
$file = $directory.'/'.$filename;
|
||
|
||
directory($directory);
|
||
file_put_contents($file, $content);
|
||
|
||
return $filename;
|
||
}
|
||
|
||
public static function isValid($name)
|
||
{
|
||
try {
|
||
new static($name);
|
||
|
||
return true;
|
||
} catch (UnexpectedValueException $e) {
|
||
$file = static::getImportDirectory().'/'.$name;
|
||
delete($file);
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public static function manage($name)
|
||
{
|
||
try {
|
||
$manager = new FatturaOrdinaria($name);
|
||
|
||
$tipo = $manager->getBody()['DatiGenerali']['DatiGeneraliDocumento']['TipoDocumento'];
|
||
if ($tipo == 'TD06') {
|
||
$manager = new Parcella($name);
|
||
}
|
||
} catch (UnexpectedValueException $e) {
|
||
$manager = new FatturaSemplificata($name);
|
||
}
|
||
|
||
return $manager;
|
||
}
|
||
|
||
public function getHeader()
|
||
{
|
||
return $this->xml['FatturaElettronicaHeader'];
|
||
}
|
||
|
||
public function getBody()
|
||
{
|
||
return $this->xml['FatturaElettronicaBody'];
|
||
}
|
||
|
||
public function delete()
|
||
{
|
||
delete($this->file);
|
||
}
|
||
|
||
public function getAllegati()
|
||
{
|
||
$result = $this->getBody()['Allegati'];
|
||
|
||
$result = $this->forceArray($result);
|
||
|
||
return array_clean($result);
|
||
}
|
||
|
||
public function saveAllegati()
|
||
{
|
||
$allegati = $this->getAllegati();
|
||
|
||
$module = Modules::get('Fatture di acquisto');
|
||
|
||
$info = [
|
||
'category' => tr('Fattura Elettronica'),
|
||
'id_module' => $module->id,
|
||
'id_record' => $this->fattura->id,
|
||
];
|
||
|
||
foreach ($allegati as $allegato) {
|
||
$content = base64_decode($allegato['Attachment']);
|
||
|
||
$extension = '.pdf';
|
||
if (!empty($allegato['FormatoAttachment'])) {
|
||
$extension = '.'.strtolower($allegato['FormatoAttachment']);
|
||
}
|
||
|
||
$original = $allegato['NomeAttachment'].$extension;
|
||
try {
|
||
Uploads::upload($content, array_merge($info, [
|
||
'name' => $allegato['NomeAttachment'],
|
||
'original_name' => $original,
|
||
]));
|
||
} catch(UnexpectedValueException $e) {}
|
||
}
|
||
|
||
// Registrazione XML come allegato
|
||
Uploads::upload($this->file, array_merge($info, [
|
||
'name' => tr('Fattura Elettronica'),
|
||
'original_name' => basename($this->file),
|
||
]));
|
||
}
|
||
|
||
public function findAnagrafica($type = 'Fornitore')
|
||
{
|
||
$info = $this->getAnagrafe();
|
||
|
||
$tipologia = TipoAnagrafica::where('descrizione', $type)->first();
|
||
|
||
$anagrafica = Anagrafica::whereHas('tipi', function ($query) use ($tipologia) {
|
||
$query->where('an_tipianagrafiche.idtipoanagrafica', '=', $tipologia->id);
|
||
});
|
||
|
||
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']);
|
||
}
|
||
|
||
//Se non trovo l'anagrafica tra i fornitori, provo a ricercarla anche tra i clienti
|
||
if (empty($anagrafica->first())){
|
||
|
||
$type = 'Cliente';
|
||
|
||
$tipologia = TipoAnagrafica::where('descrizione', $type)->first();
|
||
|
||
$anagrafica = Anagrafica::whereHas('tipi', function ($query) use ($tipologia) {
|
||
$query->where('an_tipianagrafiche.idtipoanagrafica', '=', $tipologia->id);
|
||
});
|
||
|
||
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']);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
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')
|
||
{
|
||
$anagrafica = $this->findAnagrafica($type);
|
||
|
||
if (!empty($anagrafica)) {
|
||
return $anagrafica;
|
||
}
|
||
|
||
$info = $this->getAnagrafe();
|
||
|
||
$anagrafica = Anagrafica::build($info['ragione_sociale'], $info['nome'], $info['cognome'], [
|
||
TipoAnagrafica::where('descrizione', $type)->first()->id,
|
||
]);
|
||
|
||
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'];
|
||
$sede->citta = $info['sede']['citta'];
|
||
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;
|
||
}
|
||
|
||
/**
|
||
* Registra la fattura elettronica come fattura del gestionale.
|
||
*
|
||
* @param int $id_pagamento
|
||
* @param int $id_sezionale
|
||
* @param int $id_tipo
|
||
* @param string $data_registrazione
|
||
* @param int $ref_fattura
|
||
*
|
||
* @return Fattura
|
||
*/
|
||
public function saveFattura($id_pagamento, $id_sezionale, $id_tipo, $data_registrazione, $ref_fattura, $is_ritenuta_pagata = false)
|
||
{
|
||
$dati_generali = $this->getBody()['DatiGenerali']['DatiGeneraliDocumento'];
|
||
$data = self::parseDate($dati_generali['Data']);
|
||
|
||
$fattura = $this->prepareFattura($id_tipo, $data, $data_registrazione, $id_sezionale, $ref_fattura);
|
||
$this->fattura = $fattura;
|
||
|
||
$numero_esterno = $dati_generali['Numero'];
|
||
$progressivo_invio = $this->getHeader()['DatiTrasmissione']['ProgressivoInvio'];
|
||
|
||
$fattura->progressivo_invio = $progressivo_invio;
|
||
$fattura->numero_esterno = $numero_esterno;
|
||
$fattura->idpagamento = $id_pagamento;
|
||
$fattura->is_ritenuta_pagata = $is_ritenuta_pagata;
|
||
|
||
// 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;
|
||
|
||
// Riferimento per nota di credito e debito
|
||
$fattura->ref_documento = $ref_fattura ?: null;
|
||
|
||
// 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.
|
||
// La data di ricezione della fattura è contenuta all’interno della “ricevuta di consegna” visibile al trasmittente della stessa.
|
||
$fattura->data_registrazione = $data_registrazione;
|
||
$fattura->data_competenza = $fattura->data;
|
||
|
||
$stato_documento = StatoFattura::where('descrizione', 'Emessa')->first();
|
||
$fattura->stato()->associate($stato_documento);
|
||
|
||
$causali = $dati_generali['Causale'];
|
||
if (!empty($causali)) {
|
||
$note = '';
|
||
foreach ($causali as $causale) {
|
||
$note .= $causale;
|
||
}
|
||
|
||
$fattura->note = $note;
|
||
}
|
||
|
||
// Sconto finale da ScontoMaggiorazione: non importato
|
||
$fattura->save();
|
||
|
||
// Fix generazione idsede
|
||
$fattura->refresh();
|
||
|
||
return $fattura;
|
||
}
|
||
|
||
public function getFattura()
|
||
{
|
||
return $this->fattura;
|
||
}
|
||
|
||
public function save($info = [])
|
||
{
|
||
$this->saveFattura($info['id_pagamento'], $info['id_segment'], $info['id_tipo'], $info['data_registrazione'], $info['ref_fattura'], $info['is_ritenuta_pagata']);
|
||
|
||
$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']);
|
||
|
||
$this->saveAllegati();
|
||
|
||
$this->getFattura()->save(['forza_emissione']);
|
||
|
||
return $this->getFattura()->id;
|
||
}
|
||
|
||
public static function parseDate($data)
|
||
{
|
||
return date('Y-m-d', strtotime($data));
|
||
}
|
||
|
||
protected function prepareFattura($id_tipo, $data, $data_registrazione, $id_sezionale, $ref_fattura)
|
||
{
|
||
$anagrafica = $this->saveAnagrafica();
|
||
|
||
$tipo = TipoFattura::where('id', $id_tipo)->first();
|
||
|
||
$fattura = Fattura::build($anagrafica, $tipo, $data, $id_sezionale, null, $data_registrazione);
|
||
$this->fattura = $fattura;
|
||
|
||
// Riferimento per nota di credito e debito
|
||
$fattura->ref_documento = $ref_fattura ?: null;
|
||
|
||
return $fattura;
|
||
}
|
||
|
||
protected function forceArray($result)
|
||
{
|
||
$result = isset($result[0]) ? $result : [$result];
|
||
|
||
return $result;
|
||
}
|
||
}
|