From 8cd6ce98a26e0520b6b25ca97cd9ce7b63e6b60d Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Tue, 25 Sep 2018 11:55:52 +0200 Subject: [PATCH] Miglioramenti importazione FE --- lib/common.php | 15 ++- modules/fatture/src/Articolo.php | 38 ++++++ modules/fatture/src/Fattura.php | 12 ++ modules/fatture/src/Riga.php | 16 ++- modules/interventi/actions.php | 2 + modules/interventi/src/Articolo.php | 2 +- plugins/exportPA/src/FatturaElettronica.php | 18 +-- plugins/importPA/actions.php | 30 +++-- plugins/importPA/edit.php | 10 +- plugins/importPA/rows.php | 18 ++- plugins/importPA/src/FatturaElettronica.php | 131 +++++++++++++++----- src/App.php | 4 +- src/Traits/ArticleTrait.php | 23 ++++ src/Traits/RowTrait.php | 65 ++++++++++ templates/fatture/body.php | 2 +- 15 files changed, 319 insertions(+), 67 deletions(-) create mode 100644 modules/fatture/src/Articolo.php create mode 100644 src/Traits/ArticleTrait.php create mode 100644 src/Traits/RowTrait.php diff --git a/lib/common.php b/lib/common.php index 57a568eb6..c118411ba 100644 --- a/lib/common.php +++ b/lib/common.php @@ -43,7 +43,16 @@ function sum($first, $second = null, $decimals = 4) return floatval($result); } -function aggiorna_sconto($tables, $fields, $id_record, $options = []) +/** + * Calcola lo sconto globale per i documenti e lo aggiorna di conseguenza. + * Attenzione: eseguire la funzione dopo l'inserimento e la modifica di tutte le righe del documento. + * + * @param array $tables + * @param array $fields + * @param int $id_record + * @param array $options + */ +function aggiorna_sconto(array $tables, array $fields, $id_record, array $options = []) { $dbo = database(); @@ -60,6 +69,8 @@ function aggiorna_sconto($tables, $fields, $id_record, $options = []) $iva = 0; if (!empty($sconto[0]['sconto_globale'])) { + // Commit: 2c7f69867accb4f12a0c7cfd320714bb98e31a67 + // L'aliquota IVA viene calcolata in percentuale sull'imponibile e l'iva effettiva delle righe del documento. if ($sconto[0]['tipo_sconto_globale'] == 'PRC') { $rs = $dbo->fetchArray('SELECT SUM(subtotale - sconto) AS imponibile, SUM(iva) AS iva FROM (SELECT '.$tables['row'].'.subtotale, '.$tables['row'].'.sconto, '.$tables['row'].'.iva FROM '.$tables['row'].' WHERE '.$fields['row'].'='.prepare($id_record).') AS t'); $subtotale = $rs[0]['imponibile']; @@ -85,7 +96,7 @@ function aggiorna_sconto($tables, $fields, $id_record, $options = []) 'subtotale' => $subtotale, 'qta' => 1, 'idiva' => $idiva, - 'desc_iva' => $rsi[0]['descrizione'], + //'desc_iva' => $rsi[0]['descrizione'], 'iva' => -$iva, 'sconto_globale' => 1, 'order' => orderValue($tables['row'], $fields['row'], $id_record), diff --git a/modules/fatture/src/Articolo.php b/modules/fatture/src/Articolo.php new file mode 100644 index 000000000..228d5b0f8 --- /dev/null +++ b/modules/fatture/src/Articolo.php @@ -0,0 +1,38 @@ +fattura()->associate($fattura); + $this->articolo()->associate($articolo); + + // Salvataggio delle informazioni + $this->descrizione = isset($attributes['descrizione']) ? $attributes['descrizione'] : $articolo->descrizione; + $this->abilita_serial = $articolo->abilita_serial; + + $this->save(); + } + + public function articolo() + { + return $this->belongsTo(Original::class, 'idarticolo'); + } + + public function fattura() + { + return $this->belongsTo(Fattura::class, 'iddocumento'); + } +} diff --git a/modules/fatture/src/Fattura.php b/modules/fatture/src/Fattura.php index fab4ef42d..b8abddee3 100644 --- a/modules/fatture/src/Fattura.php +++ b/modules/fatture/src/Fattura.php @@ -329,4 +329,16 @@ class Fattura extends Model { return $this->hasMany(Riga::class, 'iddocumento'); } + + public function updateSconto() + { + // Aggiornamento sconto + aggiorna_sconto([ + 'parent' => 'co_documenti', + 'row' => 'co_righe_documenti', + ], [ + 'parent' => 'id', + 'row' => 'iddocumento', + ], $this->id); + } } diff --git a/modules/fatture/src/Riga.php b/modules/fatture/src/Riga.php index 79e2d403f..e2034bbd5 100644 --- a/modules/fatture/src/Riga.php +++ b/modules/fatture/src/Riga.php @@ -3,18 +3,24 @@ namespace Modules\Fatture; use Illuminate\Database\Eloquent\Model; +use Traits\RowTrait; class Riga extends Model { + use RowTrait; + protected $table = 'co_righe_documenti'; + public function __construct(Fattura $fattura, array $attributes = array()) + { + parent::__construct($attributes); + + $this->fattura()->associate($fattura); + $this->save(); + } + public function fattura() { return $this->belongsTo(Fattura::class, 'iddocumento'); } - - public function getImponibile() - { - return $this->subtotale - $this->sconto; - } } diff --git a/modules/interventi/actions.php b/modules/interventi/actions.php index 08e71c1e9..2527c8f26 100644 --- a/modules/interventi/actions.php +++ b/modules/interventi/actions.php @@ -531,6 +531,8 @@ switch (post('op')) { $articolo->setSconto(post('sconto'), post('tipo_sconto')); $articolo->setIVA(post('idiva')); + $articolo->save(); + // Aggiorno l'automezzo dell'intervento $dbo->query('UPDATE in_interventi SET idautomezzo='.prepare(post('idautomezzo')).' WHERE id='.prepare($id_record).' '.Modules::getAdditionalsQuery($id_module)); diff --git a/modules/interventi/src/Articolo.php b/modules/interventi/src/Articolo.php index b4c7a866a..dd20b2e22 100644 --- a/modules/interventi/src/Articolo.php +++ b/modules/interventi/src/Articolo.php @@ -118,7 +118,7 @@ class Articolo extends Model database()->sync('mg_prodotti', [ 'id_riga_intervento' => $this->id, 'dir' => 'entrata', - 'id_articolo' => $this->idintervento, + 'id_articolo' => $this->idarticolo, ], [ 'serial' => $serials, ]); diff --git a/plugins/exportPA/src/FatturaElettronica.php b/plugins/exportPA/src/FatturaElettronica.php index 00df1aa97..550522682 100644 --- a/plugins/exportPA/src/FatturaElettronica.php +++ b/plugins/exportPA/src/FatturaElettronica.php @@ -308,15 +308,16 @@ class FatturaElettronica ]; // Sconto globale + $documento['sconto_globale'] = floatval($documento['sconto_globale']); if (!empty($documento['sconto_globale'])) { $sconto = [ 'Tipo' => $documento['sconto_globale'] > 0 ? 'SC' : 'MG', ]; - if ($riga['tipo_sconto_globale'] == 'PRC') { - $sconto['Percentuale'] = $riga['sconto_globale']; + if ($documento['tipo_sconto_globale'] == 'PRC') { + $sconto['Percentuale'] = $documento['sconto_globale']; } else { - $sconto['Importo'] = $riga['sconto_globale']; + $sconto['Importo'] = $documento['sconto_globale']; } $result['ScontoMaggiorazione'] = $sconto; @@ -386,7 +387,7 @@ class FatturaElettronica $result = []; // Righe del documento - $righe_documento = $database->fetchArray('SELECT * FROM `co_righe_documenti` WHERE `iddocumento` = '.prepare($documento['id'])); + $righe_documento = $database->fetchArray('SELECT * FROM `co_righe_documenti` WHERE `sconto_globale` = 0 AND `iddocumento` = '.prepare($documento['id'])); foreach ($righe_documento as $numero => $riga) { $prezzo_unitario = $riga['subtotale'] / $riga['qta']; $prezzo_totale = $riga['subtotale'] - $riga['sconto']; @@ -402,15 +403,16 @@ class FatturaElettronica ]; // Sconto - if (!empty($riga['sconto'])) { + $riga['sconto_unitario'] = floatval($riga['sconto_unitario']); + if (!empty($riga['sconto_unitario'])) { $sconto = [ - 'Tipo' => $riga['sconto'] > 0 ? 'SC' : 'MG', + 'Tipo' => $riga['sconto_unitario'] > 0 ? 'SC' : 'MG', ]; if ($riga['tipo_sconto'] == 'PRC') { - $sconto['Percentuale'] = $riga['sconto']; + $sconto['Percentuale'] = $riga['sconto_unitario']; } else { - $sconto['Importo'] = $riga['sconto']; + $sconto['Importo'] = $riga['sconto_unitario']; } $dettaglio['ScontoMaggiorazione'] = $sconto; diff --git a/plugins/importPA/actions.php b/plugins/importPA/actions.php index 277dc9297..331e8feb1 100644 --- a/plugins/importPA/actions.php +++ b/plugins/importPA/actions.php @@ -2,6 +2,8 @@ include_once __DIR__.'/../../core.php'; +$directory = Uploads::getDirectory($id_module); + switch (filter('op')) { case 'save': $id = Uploads::getFakeID(); @@ -12,11 +14,20 @@ switch (filter('op')) { 'id_record' => $id, ]); - echo json_encode([ - 'id' => $id, - 'filename' => $filename, - 'id_segment' => post('id_segment'), - ]); + try { + $xml = file_get_contents(DOCROOT.'/'.$directory.'/'.$filename); + $fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment')); + + echo json_encode([ + 'id' => $id, + 'filename' => $filename, + 'id_segment' => post('id_segment'), + ]); + } catch (UnexpectedValueException $e) { + echo json_encode([ + 'already' => 1 + ]); + } break; @@ -24,14 +35,13 @@ switch (filter('op')) { $id = post('id'); $filename = post('filename'); - $directory = Uploads::getDirectory($id_module); - $xml = file_get_contents(DOCROOT.'/'.$directory.'/'.$filename); - $fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml); + $fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment')); - $id_record = $fattura_pa->saveFattura(post('id_segment'), post('articoli')); + $id_record = $fattura_pa->saveFattura(); - $fattura_pa->saveRighe(post('articoli')); + $fattura_pa->saveRighe(post('articoli'), post('iva')); + $fattura_pa->getFattura()->updateSconto(); $fattura_pa->saveAllegati($directory); diff --git a/plugins/importPA/edit.php b/plugins/importPA/edit.php index 9db30377a..ed3fc1387 100644 --- a/plugins/importPA/edit.php +++ b/plugins/importPA/edit.php @@ -23,7 +23,15 @@ echo ' success: function(data){ data = JSON.parse(data); - launch_modal("'.tr('Righe fattura').'", globals.rootdir + "/plugins/importPA/rows.php?id_module=" + globals.id_module + "&id_plugin=" + '.$id_plugin.' + "&id=" + data.id + "&filename=" + data.filename + "&id_segment" + data.id_segment) + if (!data.already) { + launch_modal("'.tr('Righe fattura').'", globals.rootdir + "/plugins/importPA/rows.php?id_module=" + globals.id_module + "&id_plugin=" + '.$id_plugin.' + "&id=" + data.id + "&filename=" + data.filename + "&id_segment=" + data.id_segment) + } else { + swal({ + title: "'.tr('Fattura già importata!').'", + type: "info", + }) + } + }, error: function(data) { alert("'.tr('Errore').': " + data); diff --git a/plugins/importPA/rows.php b/plugins/importPA/rows.php index b2ab786bc..e9b6a4ffb 100644 --- a/plugins/importPA/rows.php +++ b/plugins/importPA/rows.php @@ -5,7 +5,7 @@ include_once __DIR__.'/../../core.php'; $directory = Uploads::getDirectory($id_module); $xml = file_get_contents(DOCROOT.'/'.$directory.'/'.get('filename')); -$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml); +$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment')); $righe = $fattura_pa->getRighe(); @@ -25,18 +25,30 @@ if (!empty($righe)) { '.tr('Riga').' '.tr('Descrizione').' - '.tr('Quantità').' - '.tr('Prezzo unitario').' + '.tr('Quantità').' + '.tr('Prezzo unitario').' + '.tr('Iva associata').'* '.tr('Articolo associato').' '; foreach ($righe as $key => $riga) { + $query = 'SELECT id, IF(codice IS NULL, descrizione, CONCAT(codice, " - ", descrizione)) AS descrizione FROM co_iva WHERE percentuale = '.prepare($riga['AliquotaIVA']); + + if (!empty($riga['Natura'])) { + $query .= ' AND codice_natura_fe = '.prepare($riga['Natura']); + } + + $query .= ' ORDER BY descrizione ASC'; + echo ' '.$key.' '.$riga['Descrizione'].' '.$riga['Quantita'].' '.$riga['UnitaMisura'].' '.$riga['PrezzoUnitario'].' + + {[ "type": "select", "name": "iva['.$key.']", "values": "query='.str_replace('"', '\"', $query).'", "required": 1 ]} + {[ "type": "select", "name": "articoli['.$key.']", "ajax-source": "articoli" ]} diff --git a/plugins/importPA/src/FatturaElettronica.php b/plugins/importPA/src/FatturaElettronica.php index e8f1eeb8f..48a5dbc6a 100644 --- a/plugins/importPA/src/FatturaElettronica.php +++ b/plugins/importPA/src/FatturaElettronica.php @@ -3,6 +3,9 @@ namespace Plugins\ImportPA; use Modules\Fatture\Fattura; +use Modules\Fatture\Riga; +use Modules\Fatture\Articolo; +use Modules\Articoli\Articolo as ArticoloOriginale; use Modules\Fatture\Stato as StatoFattura; use Modules\Fatture\Tipo as TipoFattura; use Modules\Anagrafiche\Anagrafica; @@ -23,19 +26,31 @@ class FatturaElettronica /** @var Fattura Fattura collegata */ protected $fattura = null; + protected $id_sezionale = null; - public function __construct($content) + public function __construct($content, $id_sezionale) { $xml = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); $json = json_encode($xml); $array = json_decode($json, true); $this->xml = $array; - } + $this->id_sezionale = $id_sezionale; - public function getFattura() - { - return $this->fattura; + // Individuazione fattura pre-esistente + $dati_generali = $this->getBody()['DatiGenerali']['DatiGeneraliDocumento']; + $data = $dati_generali['Data']; + $numero = $dati_generali['Numero']; + + $fattura = Fattura::where([ + 'id_segment' => $id_sezionale, + 'data' => $data, + 'numero' => $numero, + ])->first(); + + if (!empty($fattura)) { + throw new \UnexpectedValueException(); + } } public function getHeader() @@ -132,28 +147,70 @@ class FatturaElettronica return $anagrafica->id; } - public function saveRighe($articoli) - { - $righe = $this->getRighe(); - } - public function getRighe() { - return $this->getBody()['DatiBeniServizi']['DettaglioLinee']; + $result = $this->getBody()['DatiBeniServizi']['DettaglioLinee']; + + if (!isset($result[0])) { + $result = [$result]; + } + + return $result; } - public static function existsFattura($id_anagrafica, $data, $numero, $id_tipo) + public function saveRighe($articoli, $iva) { - return database()->fetchOne('SELECT `id` FROM `co_documenti` WHERE idanagrafica = '.prepare($id_anagrafica) .' AND idtipodocumento = '.prepare($id_tipo).' AND data = '.prepare($data).' AND numero = '.prepare($numero)); + $righe = $this->getRighe(); + + foreach ($righe as $key => $riga) { + $articolo = ArticoloOriginale::find($articoli[$key]); + + if (!empty($articolo)) { + $obj = new Articolo($this->getFattura(), $articolo); + } else { + $obj = new Riga($this->getFattura()); + } + + $obj->descrizione = $riga['Descrizione']; + $obj->setSubtotale($riga['PrezzoUnitario'], $riga['Quantita']); + /* + $obj->qta = $riga['Quantita']; + $obj->prezzo = $riga['PrezzoUnitario']; + */ + $obj->um = $riga['UnitaMisura']; + + $sconto =$riga['ScontoMaggiorazione']; + if (!empty($sconto)) { + $tipo = !empty($sconto['Percentuale']) ? 'PRC' : 'EUR'; + $unitario = $sconto['Percentuale'] ?: $sconto['Importo']; + + $unitario = ($sconto['Tipo'] == 'SC') ? $unitario : -$unitario; + + $obj->sconto_unitario = $unitario; + $obj->tipo_sconto = $tipo; + $obj->sconto = $obj->sconto; + } + + $obj->setIVA($iva[$key]); + + $obj->save(); + } + } + + public function getAllegati() + { + $result = $this->getBody()['Allegati']; + + if (!isset($result[0])) { + $result = [$result]; + } + + return $result; } public function saveAllegati($directory) { - $allegati = $this->getBody()['Allegati']; - - if (!isset($allegati[0])) { - $allegati = [$allegati]; - } + $allegati = $this->getAllegati(); foreach ($allegati as $allegato) { $content = base64_decode($allegato['Attachment']); @@ -170,13 +227,17 @@ class FatturaElettronica } } + public function getFattura() + { + return $this->fattura; + } + /** * Registra la fattura elettronica come fattura del gestionale. * - * @param int $id_segment * @return int */ - public function saveFattura($id_segment) + public function saveFattura() { $id_anagrafica = static::createAnagrafica($this->getHeader()['CedentePrestatore']); @@ -184,31 +245,35 @@ class FatturaElettronica $data = $dati_generali['Data']; $numero = $dati_generali['Numero']; - $tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? TipoFattura::where('descrizione', 'Fattura immediata di acquisto') : TipoFattura::where('descrizione', 'Fattura accompagnatoria di acquisto'); - $id_tipo = $tipo->first()->id; - - $result = self::existsFattura($id_anagrafica, $data, $numero, $id_tipo); - // Fattura già inserita - if (!empty($result)) { - $this->fattura = Fattura::find($result['id']); - - return $result['id']; - } + $tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? 'Fattura immediata di acquisto' : 'Fattura accompagnatoria di acquisto'; + $id_tipo = TipoFattura::where('descrizione', $tipo)->first()->id; $fattura = Fattura::create([ 'idanagrafica' => $id_anagrafica, 'data' => $data, - 'id_segment' => $id_segment, + 'id_segment' => $this->id_sezionale, 'tipo' => $id_tipo, ]); + $this->fattura = $fattura; $fattura->numero = $numero; $stato_documento = StatoFattura::where('descrizione', 'Emessa')->first(); $fattura->stato()->associate($stato_documento); - $fattura->save(); - $this->fattura = $fattura; + // Sconto globale + $sconto = $dati_generali['ScontoMaggiorazione']; + if (!empty($sconto)) { + $tipo = !empty($sconto['Percentuale']) ? 'PRC' : 'EUR'; + $unitario = $sconto['Percentuale'] ?: $sconto['Importo']; + + $unitario = ($sconto['Tipo'] == 'SC') ? $unitario : -$unitario; + + $fattura->sconto_globale = $unitario; + $fattura->tipo_sconto_globale = $tipo; + } + + $fattura->save(); return $fattura->id; } diff --git a/src/App.php b/src/App.php index efb9a23f4..54f550046 100644 --- a/src/App.php +++ b/src/App.php @@ -377,12 +377,10 @@ class App $id_parent = filter('id_parent'); $id_module = Modules::getCurrent()['id']; - $id_plugin = Plugins::getCurrent()['id']; + $segment = $_SESSION['module_'.$id_module]['id_segment']; $user = Auth::user(); - $segment = !empty($_SESSION['module_'.$id_module]['id_segment']); - // Elenco delle sostituzioni $replace = [ // Identificatori diff --git a/src/Traits/ArticleTrait.php b/src/Traits/ArticleTrait.php new file mode 100644 index 000000000..f5dd8a27c --- /dev/null +++ b/src/Traits/ArticleTrait.php @@ -0,0 +1,23 @@ +sync('mg_prodotti', [ + 'id_riga_'.$this->serialID => $this->id, + 'dir' => 'entrata', + 'id_articolo' => $this->idarticolo, + ], [ + 'serial' => $serials, + ]); + } +} diff --git a/src/Traits/RowTrait.php b/src/Traits/RowTrait.php new file mode 100644 index 000000000..a9dd31fba --- /dev/null +++ b/src/Traits/RowTrait.php @@ -0,0 +1,65 @@ +fetchOne('SELECT * FROM co_iva WHERE id = :id_iva', [ + ':id_iva' => $id_iva, + ]); + $descrizione = $iva['descrizione']; + + $valore = ($this->subtotale - $this->sconto) * $iva['percentuale'] / 100; + + $this->idiva = $iva['id']; + $this->desc_iva = $descrizione; + + $this->iva = $valore; + $this->iva_indetraibile = $valore / 100 * $iva['indetraibile']; + } + + public function getPrezzoAttribute() + { + return $this->subtotale / $this->qta; + } + + public function setSubtotale($prezzo, $qta) + { + $this->qta = $qta; + + $this->subtotale = $prezzo * $qta; + } + + /* + public function getPrezzoAttribute() + { + return $this->{$this->variabilePrezzo}; + } + + public function getSubtotaleAttribute() + { + return $this->prezzo * $this->qta; + } + */ + + public function getTotaleAttribute() + { + return $this->subtotale + $this->iva; + } + + public function getScontoAttribute() + { + return calcola_sconto([ + 'sconto' => $this->sconto_unitario, + 'prezzo' => $this->prezzo, + 'tipo' => $this->tipo_sconto, + 'qta' => $this->qta, + ]); + } +} diff --git a/templates/fatture/body.php b/templates/fatture/body.php index ce46f5242..db1664700 100644 --- a/templates/fatture/body.php +++ b/templates/fatture/body.php @@ -187,7 +187,7 @@ foreach ($righe as $r) { // Iva echo ' '; - if (empty($r['is_descrizione'])) { + if (empty($r['is_descrizione']) && empty($r['sconto_globale'])) { echo ' '.Translator::numberToLocale($r['perc_iva']); }