openstamanager/plugins/importFE/src/FatturaElettronica.php

406 lines
12 KiB
PHP
Raw Normal View History

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;
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-11-30 15:33:25 +01:00
use UnexpectedValueException;
2018-12-29 12:03:22 +01:00
use Uploads;
use Util\XML;
2018-09-24 18:10:16 +02:00
/**
* Classe per la gestione della fatturazione elettronica in XML.
*
2019-04-19 03:18:05 +02:00
* @since 2.4.9
2018-09-24 18:10:16 +02:00
*/
class FatturaElettronica
{
2018-11-30 15:33:25 +01:00
protected static $directory = null;
/** @var array Percorso del file XML */
protected $file = null;
2018-09-24 18:10:16 +02:00
/** @var array XML della fattura */
protected $xml = null;
2019-05-04 00:37:49 +02:00
/** @var Fattura Fattura collegata */
2018-09-24 18:10:16 +02:00
protected $fattura = null;
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
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();
if (!empty($fattura)) {
2018-11-30 15:33:25 +01:00
throw new UnexpectedValueException();
}
}
public static function getImportDirectory()
{
if (!isset(self::$directory)) {
$module = Modules::get('Fatture di acquisto');
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
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;
} catch (UnexpectedValueException $e) {
2019-04-19 03:18:05 +02: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-19 03:18:05 +02:00
public static function manage($name)
2018-09-24 18:10:16 +02:00
{
2019-04-19 03:18:05 +02: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);
}
2019-04-19 03:18:05 +02: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-19 03:18:05 +02:00
public function getHeader()
2018-09-24 18:10:16 +02:00
{
2019-04-19 03:18:05 +02:00
return $this->xml['FatturaElettronicaHeader'];
2018-09-24 18:10:16 +02:00
}
2019-04-19 03:18:05 +02:00
public function getBody()
2018-09-24 18:10:16 +02:00
{
2019-04-19 03:18:05 +02:00
return $this->xml['FatturaElettronicaBody'];
}
2019-02-18 10:34:31 +01:00
2019-04-19 03:18:05 +02: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-19 03:18:05 +02: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
2018-09-25 16:47:44 +02:00
$module = Modules::get('Fatture di acquisto');
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']);
$extension = '.pdf';
if (!empty($allegato['FormatoAttachment'])) {
$extension = '.'.strtolower($allegato['FormatoAttachment']);
}
$original = $allegato['NomeAttachment'].$extension;
Uploads::upload($content, array_merge($info, [
'name' => $allegato['NomeAttachment'],
'original_name' => $original,
2018-11-30 15:33:25 +01:00
]));
2018-09-24 18:10:16 +02:00
}
2018-11-30 15:33:25 +01:00
// Registrazione XML come allegato
2019-07-22 11:35:44 +02:00
Uploads::upload($this->file, array_merge($info, [
2018-11-30 15:33:25 +01:00
'name' => tr('Fattura Elettronica'),
'original_name' => basename($this->file),
2018-11-30 15:33:25 +01:00
]));
2018-09-24 18:10:16 +02:00
}
public function findAnagrafica($type = 'Fornitore')
2018-09-25 11:55:52 +02:00
{
2019-04-19 03:18:05 +02:00
$info = $this->getAnagrafe();
$tipologia = TipoAnagrafica::where('descrizione', $type)->first();
$anagrafica = Anagrafica::whereHas('tipi', function ($query) use ($tipologia) {
$query->where('an_tipianagrafiche.idtipoanagrafica', '=', $tipologia->id);
});
2019-07-24 15:41:04 +02:00
if (!empty($info['partita_iva']) && !empty($info['codice_fiscale'])) {
$anagrafica->where('piva', $info['partita_iva'])
->orWhere('codice_fiscale', $info['codice_fiscale']);
} elseif (!empty($info['codice_fiscale'])) {
2019-04-19 03:18:05 +02:00
$anagrafica->where('codice_fiscale', $info['codice_fiscale']);
2019-07-24 15:41:04 +02:00
} elseif (!empty($info['partita_iva'])) {
$anagrafica->where('piva', $info['partita_iva']);
2019-04-19 03:18:05 +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')
{
$anagrafica = $this->findAnagrafica($type);
2019-04-19 03:18:05 +02:00
if (!empty($anagrafica)) {
return $anagrafica;
}
$info = $this->getAnagrafe();
2019-04-19 03:18:05 +02:00
$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'];
2020-06-30 13:33:42 +02:00
$sede->citta = $info['sede']['citta'];
2019-04-19 03:18:05 +02: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-19 03:18:05 +02:00
* @return Fattura
2018-09-24 18:10:16 +02: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
2019-07-22 12:52:48 +02:00
$fattura = $this->prepareFattura($id_tipo, $data, $id_sezionale, $ref_fattura);
$this->fattura = $fattura;
$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;
$fattura->numero_esterno = $numero_esterno;
2018-09-25 16:47:44 +02:00
$fattura->idpagamento = $id_pagamento;
$fattura->is_ritenuta_pagata = $is_ritenuta_pagata;
2019-04-04 17:30:58 +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;
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-19 03:18:05 +02:00
// La data di ricezione della fattura è contenuta allinterno della “ricevuta di consegna” visibile al trasmittente della stessa.
2019-07-22 15:45:36 +02:00
$fattura->data_registrazione = $data_registrazione;
$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-19 03:18:05 +02: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;
}
// 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-19 03:18:05 +02:00
return $fattura;
2018-09-24 18:10:16 +02:00
}
2018-11-30 15:33:25 +01:00
2019-04-19 03:18:05 +02:00
public function getFattura()
2018-11-30 15:33:25 +01:00
{
2019-04-19 03:18:05 +02:00
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']);
2019-04-19 03:18:05 +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']);
2019-04-19 03:18:05 +02:00
$this->saveAllegati();
return $this->getFattura()->id;
}
2020-10-09 16:43:07 +02:00
public static function parseDate($data)
{
return date('Y-m-d', strtotime($data));
}
2019-07-22 12:52:48 +02:00
protected function prepareFattura($id_tipo, $data, $id_sezionale, $ref_fattura)
{
$anagrafica = $this->saveAnagrafica();
$tipo = TipoFattura::where('id', $id_tipo)->first();
$fattura = Fattura::build($anagrafica, $tipo, $data, $id_sezionale);
$this->fattura = $fattura;
// Riferimento per nota di credito e debito
$fattura->ref_documento = $ref_fattura ?: null;
return $fattura;
}
2019-04-19 03:18:05 +02: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
}