mirror of
https://github.com/devcode-it/openstamanager.git
synced 2025-02-16 19:40:44 +01:00
Introduzione controllo su XML delle Fatture elettroniche di vendita
Refactoring della precedente azione bulk in favore della classe DatiFattureElettroniche.
This commit is contained in:
parent
7ab35c7edf
commit
beefb22078
@ -21,6 +21,7 @@ include_once __DIR__.'/../../core.php';
|
||||
|
||||
use Models\Cache;
|
||||
use Modules\Aggiornamenti\Controlli\Controllo;
|
||||
use Modules\Aggiornamenti\Controlli\DatiFattureElettroniche;
|
||||
use Modules\Aggiornamenti\Controlli\PianoConti;
|
||||
use Modules\Aggiornamenti\UpdateHook;
|
||||
|
||||
@ -49,6 +50,7 @@ switch (filter('op')) {
|
||||
case 'controlli-disponibili':
|
||||
$controlli = [
|
||||
PianoConti::class,
|
||||
DatiFattureElettroniche::class,
|
||||
];
|
||||
|
||||
$results = [];
|
||||
|
@ -191,7 +191,7 @@ function addRiga(controllo, panel, record) {
|
||||
let body = panel.find("tbody");
|
||||
|
||||
// Generazione riga
|
||||
let riga = `<tr class="text-` + record.type + `" id="controllo-` + controllo["id"] + `-` + record.id + `">
|
||||
let riga = `<tr class="` + record.type + `" id="controllo-` + controllo["id"] + `-` + record.id + `">
|
||||
<td>` + record.nome + `</td>
|
||||
<td>` + record.descrizione + `</td>
|
||||
<td></td>
|
||||
|
181
modules/aggiornamenti/src/Controlli/DatiFattureElettroniche.php
Normal file
181
modules/aggiornamenti/src/Controlli/DatiFattureElettroniche.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?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 Modules\Aggiornamenti\Controlli;
|
||||
|
||||
use Modules\Fatture\Fattura;
|
||||
use Util\XML;
|
||||
|
||||
class DatiFattureElettroniche extends Controllo
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return tr('Corrispondeze Fatture Elettroniche XMl e Fatture di vendita');
|
||||
}
|
||||
|
||||
public function getType($record)
|
||||
{
|
||||
return 'info';
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
$fatture_vendita = Fattura::vendita()
|
||||
->whereNotIn('codice_stato_fe', ['ERR', 'NS', 'EC02', 'ERVAL'])
|
||||
->where('data', '>=', $_SESSION['period_start'])
|
||||
->where('data', '<=', $_SESSION['period_end'])
|
||||
->orderBy('data')
|
||||
->get();
|
||||
|
||||
foreach ($fatture_vendita as $fattura_vendita) {
|
||||
$this->checkFattura($fattura_vendita);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkFattura(Fattura $fattura_vendita)
|
||||
{
|
||||
try {
|
||||
$xml = XML::read($fattura_vendita->getXML());
|
||||
$totale_documento_xml = null;
|
||||
|
||||
// Totale basato sul campo ImportoTotaleDocumento
|
||||
$dati_generali = $xml['FatturaElettronicaBody']['DatiGenerali']['DatiGeneraliDocumento'];
|
||||
$dati_anagrafici = $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici'];
|
||||
if (isset($dati_generali['ImportoTotaleDocumento'])) {
|
||||
$totale_documento_indicato = abs(floatval($dati_generali['ImportoTotaleDocumento']));
|
||||
|
||||
// Calcolo del totale basato sui DatiRiepilogo
|
||||
if (empty($totale_documento_xml) && empty($dati_generali['ScontoMaggiorazione'])) {
|
||||
$totale_documento_xml = 0;
|
||||
|
||||
$riepiloghi = $xml['FatturaElettronicaBody']['DatiBeniServizi']['DatiRiepilogo'];
|
||||
if (!empty($riepiloghi) && !isset($riepiloghi[0])) {
|
||||
$riepiloghi = [$riepiloghi];
|
||||
}
|
||||
|
||||
foreach ($riepiloghi as $riepilogo) {
|
||||
$totale_documento_xml = sum([$totale_documento_xml, $riepilogo['ImponibileImporto'], $riepilogo['Imposta']]);
|
||||
}
|
||||
|
||||
$totale_documento_xml = abs($totale_documento_xml);
|
||||
} else {
|
||||
$totale_documento_xml = $totale_documento_indicato;
|
||||
}
|
||||
|
||||
$totale_documento_xml = $fattura_vendita->isNota() ? -$totale_documento_xml : $totale_documento_xml;
|
||||
}
|
||||
|
||||
// Se riscontro un'anomalia
|
||||
if ($fattura_vendita->anagrafica->piva != $dati_anagrafici['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $dati_anagrafici['CodiceFiscale'] || $fattura_vendita->totale != $totale_documento_xml) {
|
||||
$anomalia = [
|
||||
'fattura_vendita' => $fattura_vendita,
|
||||
'codice_fiscale_xml' => !empty($dati_anagrafici['CodiceFiscale']) ? $dati_anagrafici['CodiceFiscale'] : null,
|
||||
'codice_fiscale' => $fattura_vendita->anagrafica->codice_fiscale,
|
||||
'piva_xml' => !empty($dati_anagrafici['IdFiscaleIVA']['IdCodice']) ? $dati_anagrafici['IdFiscaleIVA']['IdCodice'] : null,
|
||||
'piva' => $fattura_vendita->anagrafica->piva,
|
||||
'totale_documento_xml' => moneyFormat($totale_documento_xml, 2),
|
||||
'totale_documento' => moneyFormat($fattura_vendita->totale, 2),
|
||||
];
|
||||
|
||||
$riepilogo_anomalie = '
|
||||
<table class="table table-bordered table-condensed">
|
||||
<tr>
|
||||
<th>Sorgente</th>
|
||||
<th>P. Iva</th>
|
||||
<th>Cod. fiscale</th>
|
||||
<th>Totale</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>XML</td>
|
||||
<td>'.$anomalia['piva_xml'].'</td>
|
||||
<td>'.$anomalia['codice_fiscale_xml'].'</td>
|
||||
<td>'.$anomalia['totale_documento_xml'].'</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Gestionale</td>
|
||||
<td>'.$this->htmlDiff($anomalia['piva_xml'], $anomalia['piva']).'</td>
|
||||
<td>'.$this->htmlDiff($anomalia['codice_fiscale_xml'], $anomalia['codice_fiscale']).'</td>
|
||||
<td>'.$this->htmlDiff($anomalia['totale_documento_xml'], $anomalia['totale_documento']).'</td>
|
||||
</tr>
|
||||
</table>';
|
||||
|
||||
$this->addResult([
|
||||
'id' => $fattura_vendita->id,
|
||||
'nome' => $fattura_vendita->getReference(),
|
||||
'descrizione' => $riepilogo_anomalie,
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->addResult([
|
||||
'id' => $fattura_vendita->id,
|
||||
'nome' => $fattura_vendita->getReference(),
|
||||
'descrizione' => tr("Impossibile verificare l'XML di questa fattura"),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function execute($record, $params = [])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function diff($old, $new)
|
||||
{
|
||||
$matrix = [];
|
||||
$maxlen = 0;
|
||||
foreach ($old as $oindex => $ovalue) {
|
||||
$nkeys = array_keys($new, $ovalue);
|
||||
foreach ($nkeys as $nindex) {
|
||||
$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
|
||||
$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
|
||||
if ($matrix[$oindex][$nindex] > $maxlen) {
|
||||
$maxlen = $matrix[$oindex][$nindex];
|
||||
$omax = $oindex + 1 - $maxlen;
|
||||
$nmax = $nindex + 1 - $maxlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($maxlen == 0) {
|
||||
return [['d' => $old, 'i' => $new]];
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$this->diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
|
||||
array_slice($new, $nmax, $maxlen),
|
||||
$this->diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
|
||||
}
|
||||
|
||||
protected function htmlDiff($old, $new)
|
||||
{
|
||||
$ret = '';
|
||||
$diff = $this->diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new));
|
||||
foreach ($diff as $k) {
|
||||
if (is_array($k)) {
|
||||
$ret .= (!empty($k['d']) ? '<del>'.implode(' ', $k['d']).'</del> ' : '').
|
||||
(!empty($k['i']) ? '<span>'.implode(' ', $k['i']).'</span> ' : '');
|
||||
} else {
|
||||
$ret .= $k.' ';
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
use Modules\Aggiornamenti\Controlli\DatiFattureElettroniche;
|
||||
use Modules\Fatture\Export\CSV;
|
||||
use Modules\Fatture\Fattura;
|
||||
use Modules\Fatture\Stato;
|
||||
@ -321,155 +322,49 @@ switch (post('op')) {
|
||||
break;
|
||||
|
||||
case 'check-bulk':
|
||||
$list = [];
|
||||
$anomalie = collect();
|
||||
|
||||
$controllo = new DatiFattureElettroniche();
|
||||
$fatture = [];
|
||||
foreach ($id_records as $id) {
|
||||
$fattura_vendita = Fattura::vendita()
|
||||
->whereNotIn('codice_stato_fe', ['ERR', 'NS', 'EC02', 'ERVAL'])
|
||||
->where('data', '>=', $_SESSION['period_start'])
|
||||
->where('data', '<=', $_SESSION['period_end'])
|
||||
->where('id', '=', $id)
|
||||
->orderBy('data')
|
||||
->get();
|
||||
|
||||
$fattura_vendita = $fattura_vendita[0];
|
||||
->whereNotIn('codice_stato_fe', ['ERR', 'NS', 'EC02', 'ERVAL'])
|
||||
->where('data', '>=', $_SESSION['period_start'])
|
||||
->where('data', '<=', $_SESSION['period_end'])
|
||||
->where('id', '=', $id)
|
||||
->orderBy('data')
|
||||
->first();
|
||||
|
||||
if (!empty($fattura_vendita)) {
|
||||
try {
|
||||
$xml = XML::read($fattura_vendita->getXML());
|
||||
$fatture[$id] = $fattura_vendita;
|
||||
|
||||
$totale_documento_xml = null;
|
||||
|
||||
// Totale basato sul campo ImportoTotaleDocumento
|
||||
$dati_generali = $xml['FatturaElettronicaBody']['DatiGenerali']['DatiGeneraliDocumento'];
|
||||
if (isset($dati_generali['ImportoTotaleDocumento'])) {
|
||||
$totale_documento_indicato = abs(floatval($dati_generali['ImportoTotaleDocumento']));
|
||||
|
||||
// Calcolo del totale basato sui DatiRiepilogo
|
||||
if (empty($totale_documento_xml) && empty($dati_generali['ScontoMaggiorazione'])) {
|
||||
$totale_documento_xml = 0;
|
||||
|
||||
$riepiloghi = $xml['FatturaElettronicaBody']['DatiBeniServizi']['DatiRiepilogo'];
|
||||
if (!empty($riepiloghi) && !isset($riepiloghi[0])) {
|
||||
$riepiloghi = [$riepiloghi];
|
||||
}
|
||||
|
||||
foreach ($riepiloghi as $riepilogo) {
|
||||
$totale_documento_xml = sum([$totale_documento_xml, $riepilogo['ImponibileImporto'], $riepilogo['Imposta']]);
|
||||
}
|
||||
|
||||
$totale_documento_xml = abs($totale_documento_xml);
|
||||
} else {
|
||||
$totale_documento_xml = $totale_documento_indicato;
|
||||
}
|
||||
$totale_documento_xml = $fattura_vendita->isNota() ? -$totale_documento_xml : $totale_documento_xml;
|
||||
}
|
||||
|
||||
// Se riscontro un'anomalia
|
||||
if ($fattura_vendita->anagrafica->piva != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale'] || $fattura_vendita->totale != $totale_documento_xml) {
|
||||
/*echo json_encode([
|
||||
'totale_documento_xml' => $totale_documento_xml,
|
||||
'totale_documento' => $totale_documento,
|
||||
]);*/
|
||||
|
||||
$anomalie->push([
|
||||
'fattura_vendita' => $fattura_vendita,
|
||||
'codice_fiscale_xml' => !empty($xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale']) ? $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale'] : null,
|
||||
'codice_fiscale' => $fattura_vendita->anagrafica->codice_fiscale,
|
||||
'piva_xml' => !empty($xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice']) ? $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice'] : null,
|
||||
'piva' => $fattura_vendita->anagrafica->piva,
|
||||
'totale_documento_xml' => moneyFormat($totale_documento_xml, 2),
|
||||
'totale_documento' => moneyFormat($fattura_vendita->totale, 2),
|
||||
'have_xml' => 1,
|
||||
]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$anomalie->push([
|
||||
'fattura_vendita' => $fattura_vendita,
|
||||
'have_xml' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
array_push($list, $fattura_vendita->numero_esterno);
|
||||
$controllo->checkFattura($fattura_vendita);
|
||||
}
|
||||
}
|
||||
|
||||
$results = $controllo->getResults();
|
||||
$num = count($results);
|
||||
|
||||
// Messaggi di risposta
|
||||
if (empty($list)) {
|
||||
if (empty($fatture)) {
|
||||
flash()->warning(tr('Nessuna fattura utile per il controllo!'));
|
||||
} elseif (empty($results)) {
|
||||
flash()->info(tr('Nessuna anomalia!'));
|
||||
} else {
|
||||
flash()->info(tr('Fatture _LIST_ controllate.', [
|
||||
'_LIST_' => implode(',', $list),
|
||||
'_LIST_' => implode(',', array_column($results, 'numero')),
|
||||
]));
|
||||
|
||||
// Se ci sono anomalie
|
||||
if ($anomalie->count() > 0) {
|
||||
function diff($old, $new)
|
||||
{
|
||||
$matrix = [];
|
||||
$maxlen = 0;
|
||||
foreach ($old as $oindex => $ovalue) {
|
||||
$nkeys = array_keys($new, $ovalue);
|
||||
foreach ($nkeys as $nindex) {
|
||||
$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
|
||||
$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
|
||||
if ($matrix[$oindex][$nindex] > $maxlen) {
|
||||
$maxlen = $matrix[$oindex][$nindex];
|
||||
$omax = $oindex + 1 - $maxlen;
|
||||
$nmax = $nindex + 1 - $maxlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($maxlen == 0) {
|
||||
return [['d' => $old, 'i' => $new]];
|
||||
}
|
||||
$riepilogo_anomalie = tr('Attenzione: Trovate _NUM_ anomalie! Le seguenti fatture non trovano corrispondenza tra XML e dati nel documento', ['_NUM_' => $num]).':</br></br>';
|
||||
|
||||
return array_merge(
|
||||
diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
|
||||
array_slice($new, $nmax, $maxlen),
|
||||
diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
|
||||
}
|
||||
foreach ($results as $anomalia) {
|
||||
$fattura = $fatture[$anomalia['id']];
|
||||
|
||||
function htmlDiff($old, $new)
|
||||
{
|
||||
$ret = '';
|
||||
$diff = diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new));
|
||||
foreach ($diff as $k) {
|
||||
if (is_array($k)) {
|
||||
$ret .= (!empty($k['d']) ? '<del>'.implode(' ', $k['d']).'</del> ' : '').
|
||||
(!empty($k['i']) ? '<span>'.implode(' ', $k['i']).'</span> ' : '');
|
||||
} else {
|
||||
$ret .= $k.' ';
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$riepilogo_anomalie .= tr('Attenzione: Trovate _NUM_ anomalie! Le seguenti fatture non trovano corrispondenza tra XML e dati nel documento:', ['_NUM_' => $anomalie->count()]).' </br></br>';
|
||||
|
||||
foreach ($anomalie as $anomalia) {
|
||||
$riepilogo_anomalie .= '<ul><li>'.reference($anomalia['fattura_vendita'], $anomalia['fattura_vendita']->getReference()).'</li>';
|
||||
|
||||
if (!empty($anomalia['have_xml'])) {
|
||||
$riepilogo_anomalie .= '<li><table class="table table-bordered table-condensed">
|
||||
<tr><th>Sorgente</th><th>P. Iva</th><th>Cod. fiscale</th><th>Totale</th></tr>';
|
||||
|
||||
$riepilogo_anomalie .= '<tr><td>XML</td> <td>'.$anomalia['piva_xml'].'</td> <td>'.$anomalia['codice_fiscale_xml'].'</td> <td>'.$anomalia['totale_documento_xml'].'</td></tr>';
|
||||
|
||||
$riepilogo_anomalie .= '<tr><td>Gestionale</td> <td>'.htmlDiff($anomalia['piva_xml'], $anomalia['piva']).'</td> <td>'.htmlDiff($anomalia['codice_fiscale_xml'], $anomalia['codice_fiscale']).'</td> <td>'.htmlDiff($anomalia['totale_documento_xml'], $anomalia['totale_documento']).'</td></tr></table></li>';
|
||||
} else {
|
||||
$riepilogo_anomalie .= ' <li>'.tr('Impossibile verificare l\'XML di questa fattura.').'</li>';
|
||||
}
|
||||
|
||||
$riepilogo_anomalie .= '</ul><br>';
|
||||
}
|
||||
|
||||
flash()->warning($riepilogo_anomalie);
|
||||
} else {
|
||||
flash()->info(tr('Nessuna anomalia!'));
|
||||
$riepilogo_anomalie .= '<ul>
|
||||
<li>'.reference($fattura, $fattura->getReference()).'</li>
|
||||
<li>'.$anomalia['descrizione'].'</li>
|
||||
</ul><br>';
|
||||
}
|
||||
|
||||
flash()->warning($riepilogo_anomalie);
|
||||
}
|
||||
break;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user