diff --git a/plugins/importFE/actions.php b/plugins/importFE/actions.php index d2c5c9022..7a2064459 100755 --- a/plugins/importFE/actions.php +++ b/plugins/importFE/actions.php @@ -19,6 +19,7 @@ include_once __DIR__.'/../../core.php'; +use Carbon\Carbon; use Modules\DDT\DDT; use Modules\Ordini\Ordine; use Modules\Fatture\Fattura; @@ -280,10 +281,40 @@ switch (filter('op')) { $results = []; + // Dati ordini + $DatiOrdini = $fattura_pa->getBody()['DatiGenerali']['DatiOrdineAcquisto']; + $DatiDDT = $fattura_pa->getBody()['DatiGenerali']['DatiDDT']; + + + // Riorganizzazione dati ordini per numero di riga + $dati_ordini = []; + foreach ($DatiOrdini as $dato) { + foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) { + $dati_ordini[(int)$linea] = [ + 'numero' => $dato['IdDocumento'], + 'anno' => ( new Carbon($dato['Data']) )->format('Y'), + ]; + } + } + + // Riorganizzazione dati ordini per numero di riga + $dati_ddt = []; + foreach ($DatiDDT as $dato) { + foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) { + $dati_ddt[(int)$linea] = [ + 'numero' => $dato['NumeroDDT'], + 'anno' => ( new Carbon($dato['DataDDT']) )->format('Y'), + ]; + } + } + // Iterazione sulle singole righe $righe = $fattura_pa->getRighe(); foreach ($righe as $key => $riga) { $collegamento = null; + $match_documento_da_fe = true; + + $numero_linea = (int)$riga['NumeroLinea']; // Visualizzazione codici articoli $codici = $riga['CodiceArticolo'] ?: []; @@ -294,10 +325,18 @@ switch (filter('op')) { foreach ($codici as $codice) { if (!empty($anagrafica) && empty($id_articolo)) { $id_articolo = $database->fetchOne('SELECT id_articolo AS id FROM mg_fornitore_articolo WHERE codice_fornitore = '.prepare($codice['CodiceValore']).' AND id_fornitore = '.prepare($anagrafica->id))['id']; + + if (empty($id_articolo)) { + $id_articolo = $database->fetchOne('SELECT id_articolo AS id FROM mg_fornitore_articolo WHERE REPLACE(codice_fornitore, " ", "") = '.prepare($codice['CodiceValore']).' AND id_fornitore = '.prepare($anagrafica->id))['id']; + } } if (empty($id_articolo)) { - $id_articolo = $database->fetchOne('SELECT id FROM mg_articoli WHERE codice = '.prepare($codice['CodiceValore']))['id']; + $id_articolo = $database->fetchOne('SELECT id FROM mg_articoli WHERE codice = '.prepare($codice['CodiceValore']).' AND deleted_at IS NULL')['id']; + + if (empty($id_articolo)) { + $id_articolo = $database->fetchOne('SELECT id FROM mg_articoli WHERE REPLACE(codice, " ", "") = '.prepare($codice['CodiceValore']).' AND deleted_at IS NULL')['id']; + } } if (!empty($id_articolo)) { @@ -305,46 +344,126 @@ switch (filter('op')) { } } + // Se nella fattura elettronica è indicato un DDT cerco quel documento specifico + $ddt = $dati_ddt[$numero_linea]; $query = "SELECT dt_righe_ddt.id, dt_righe_ddt.idddt AS id_documento, dt_righe_ddt.is_descrizione, dt_righe_ddt.idarticolo, dt_righe_ddt.is_sconto, 'ddt' AS ref, - CONCAT('DDT num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM dt_statiddt WHERE id = idstatoddt) , ']') AS opzione - FROM dt_righe_ddt - INNER JOIN dt_ddt ON dt_ddt.id = dt_righe_ddt.idddt - WHERE dt_ddt.idanagrafica = ".prepare($anagrafica->id)." AND |where_ddt| + CONCAT('DDT num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM dt_statiddt WHERE id = idstatoddt) , ']') AS opzione + FROM dt_righe_ddt + INNER JOIN dt_ddt ON dt_ddt.id = dt_righe_ddt.idddt + WHERE + dt_ddt.numero_esterno = ".prepare($ddt['numero'])." + AND + YEAR(dt_ddt.data) = ".prepare($ddt['anno'])." + AND + dt_ddt.idanagrafica = ".prepare($anagrafica->id)." + AND + |where|"; - UNION SELECT or_righe_ordini.id, or_righe_ordini.idordine AS id_documento, or_righe_ordini.is_descrizione, or_righe_ordini.idarticolo, or_righe_ordini.is_sconto, 'ordine' AS ref, - CONCAT('Ordine num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM or_statiordine WHERE id = idstatoordine) , ']') AS opzione - FROM or_righe_ordini - INNER JOIN or_ordini ON or_ordini.id = or_righe_ordini.idordine - WHERE or_ordini.idanagrafica = ".prepare($anagrafica->id).' AND |where_ordini|'; - - // Ricerca di righe DDT/Ordine con stesso Articolo + // Ricerca di righe DDT con stesso Articolo if (!empty($id_articolo)) { $query_articolo = replace($query, [ - '|where_ddt|' => 'dt_righe_ddt.idarticolo = '.prepare($id_articolo), - '|where_ordini|' => 'or_righe_ordini.idarticolo = '.prepare($id_articolo), + '|where|' => 'dt_righe_ddt.idarticolo = '.prepare($id_articolo), ]); $collegamento = $database->fetchOne($query_articolo); } - // Ricerca di righe DDT/Ordine per stessa descrizione + // Ricerca di righe DDT per stessa descrizione if (empty($collegamento)) { + $match_documento_da_fe = false; $query_descrizione = replace($query, [ - '|where_ddt|' => 'dt_righe_ddt.descrizione = '.prepare($riga['Descrizione']), - '|where_ordini|' => 'or_righe_ordini.descrizione = '.prepare($riga['Descrizione']), + '|where|' => 'dt_righe_ddt.descrizione = '.prepare($riga['Descrizione']), ]); $collegamento = $database->fetchOne($query_descrizione); } - // Ricerca di righe DDT/Ordine per stesso importo - if (empty($collegamento)) { - $query_descrizione = replace($query, [ - '|where_ddt|' => 'dt_righe_ddt.prezzo_unitario = '.prepare($riga['PrezzoUnitario']), - '|where_ordini|' => 'or_righe_ordini.prezzo_unitario = '.prepare($riga['PrezzoUnitario']), - ]); - $collegamento = $database->fetchOne($query_descrizione); + // Se nella fattura elettronica NON è indicato un DDT ed è indicato anche un ordine + // cerco per quell'ordine + if (empty($collegamento)) { + $ordine = $dati_ordini[$numero_linea]; + $query = "SELECT or_righe_ordini.id, or_righe_ordini.idordine AS id_documento, or_righe_ordini.is_descrizione, or_righe_ordini.idarticolo, or_righe_ordini.is_sconto, 'ordine' AS ref, + CONCAT('Ordine num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM or_statiordine WHERE id = idstatoordine) , ']') AS opzione + FROM or_righe_ordini + INNER JOIN or_ordini ON or_ordini.id = or_righe_ordini.idordine + WHERE + or_ordini.numero_esterno = ".prepare($ddt['numero'])." + AND + YEAR(or_ordini.data) = ".prepare($ddt['anno'])." + AND + or_ordini.idanagrafica = ".prepare($anagrafica->id)." + AND + |where|"; + + // Ricerca di righe Ordine con stesso Articolo + if (!empty($id_articolo)) { + $query_articolo = replace($query, [ + '|where|' => 'or_righe_ordini.idarticolo = '.prepare($id_articolo), + ]); + + $collegamento = $database->fetchOne($query_articolo); + } + + // Ricerca di righe Ordine per stessa descrizione + if (empty($collegamento)) { + $query_descrizione = replace($query, [ + '|where|' => 'or_righe_ordini.descrizione = '.prepare($riga['Descrizione']), + ]); + + $collegamento = $database->fetchOne($query_descrizione); + } + } + + + /** + * TENTATIVO 2: ricerca solo per articolo o descrizione su documenti + * non referenziati nella fattura elettronica + */ + // Se non ci sono Ordini o DDT cerco per contenuto + if (empty($collegamento)) { + $match_documento_da_fe = false; + $query = "SELECT dt_righe_ddt.id, dt_righe_ddt.idddt AS id_documento, dt_righe_ddt.is_descrizione, dt_righe_ddt.idarticolo, dt_righe_ddt.is_sconto, 'ddt' AS ref, + CONCAT('DDT num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM dt_statiddt WHERE id = idstatoddt) , ']') AS opzione + FROM dt_righe_ddt + INNER JOIN dt_ddt ON dt_ddt.id = dt_righe_ddt.idddt + WHERE dt_ddt.idanagrafica = ".prepare($anagrafica->id)." AND |where_ddt| + + UNION SELECT or_righe_ordini.id, or_righe_ordini.idordine AS id_documento, or_righe_ordini.is_descrizione, or_righe_ordini.idarticolo, or_righe_ordini.is_sconto, 'ordine' AS ref, + CONCAT('Ordine num. ', IF(numero_esterno != '', numero_esterno, numero), ' del ', DATE_FORMAT(data, '%d/%m/%Y'), ' [', (SELECT descrizione FROM or_statiordine WHERE id = idstatoordine) , ']') AS opzione + FROM or_righe_ordini + INNER JOIN or_ordini ON or_ordini.id = or_righe_ordini.idordine + WHERE or_ordini.idanagrafica = ".prepare($anagrafica->id).' AND |where_ordini|'; + + // Ricerca di righe DDT/Ordine con stesso Articolo + if (!empty($id_articolo)) { + $query_articolo = replace($query, [ + '|where_ddt|' => 'dt_righe_ddt.idarticolo = '.prepare($id_articolo), + '|where_ordini|' => 'or_righe_ordini.idarticolo = '.prepare($id_articolo), + ]); + + $collegamento = $database->fetchOne($query_articolo); + } + + // Ricerca di righe DDT/Ordine per stessa descrizione + if (empty($collegamento)) { + $query_descrizione = replace($query, [ + '|where_ddt|' => 'dt_righe_ddt.descrizione = '.prepare($riga['Descrizione']), + '|where_ordini|' => 'or_righe_ordini.descrizione = '.prepare($riga['Descrizione']), + ]); + + $collegamento = $database->fetchOne($query_descrizione); + } + + // Ricerca di righe DDT/Ordine per stesso importo + if (empty($collegamento)) { + $query_descrizione = replace($query, [ + '|where_ddt|' => 'dt_righe_ddt.prezzo_unitario = '.prepare($riga['PrezzoUnitario']), + '|where_ordini|' => 'or_righe_ordini.prezzo_unitario = '.prepare($riga['PrezzoUnitario']), + ]); + + $collegamento = $database->fetchOne($query_descrizione); + } } if (!empty($collegamento)) { @@ -374,6 +493,7 @@ switch (filter('op')) { 'id' => $collegamento['id_documento'], 'descrizione' => reference($documento, tr('Origine')), 'opzione' => $collegamento['opzione'], + 'match_documento_da_fe' => $match_documento_da_fe, ], 'riga' => [ 'tipo' => get_class($riga), diff --git a/plugins/importFE/buttons.php b/plugins/importFE/buttons.php index 1075a2896..67910eef7 100755 --- a/plugins/importFE/buttons.php +++ b/plugins/importFE/buttons.php @@ -106,11 +106,13 @@ function compilaRiferimenti(btn) { return; } - for (const [id_riga, data] of response.entries()) { - // Selezione dinamica - $("#selezione_riferimento" + id_riga).selectSetNew(data.documento.id, data.documento.opzione); + for (id_riga in response) { + data = response[id_riga]; - // Impostazione del riferiment + // Selezione dinamica + $("#selezione_riferimento" + id_riga).addClass("already-loaded").selectSetNew(data.documento.id, data.documento.opzione).removeClass("already-loaded"); + + // Impostazione del riferimento impostaRiferimento(id_riga, data.documento, data.riga); } }, diff --git a/plugins/importFE/generate.php b/plugins/importFE/generate.php index 0f3a48a2b..52af2f8fe 100755 --- a/plugins/importFE/generate.php +++ b/plugins/importFE/generate.php @@ -325,6 +325,34 @@ if (!empty($righe)) { '; + + // Dati ordini + $DatiOrdini = $fattura_pa->getBody()['DatiGenerali']['DatiOrdineAcquisto']; + $DatiDDT = $fattura_pa->getBody()['DatiGenerali']['DatiDDT']; + + + // Riorganizzazione dati ordini per numero di riga + $dati_ordini = []; + foreach ($DatiOrdini as $dato) { + foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) { + $dati_ordini[(int)$linea] = [ + 'numero' => $dato['IdDocumento'], + 'data' => ( new Carbon($dato['Data']) )->format('d/m/Y'), + ]; + } + } + + // Riorganizzazione dati ordini per numero di riga + $dati_ddt = []; + foreach ($DatiDDT as $dato) { + foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) { + $dati_ddt[(int)$linea] = [ + 'numero' => $dato['NumeroDDT'], + 'data' => ( new Carbon($dato['DataDDT']) )->format('d/m/Y'), + ]; + } + } + foreach ($righe as $key => $riga) { $query = "SELECT id, IF(codice IS NULL, descrizione, CONCAT(codice, ' - ', descrizione)) AS descrizione FROM co_iva WHERE deleted_at IS NULL AND percentuale = ".prepare($riga['AliquotaIVA']); @@ -376,11 +404,23 @@ if (!empty($righe)) { $prezzo_unitario = $riga['PrezzoUnitario'] ?: $riga['Importo']; $is_descrizione = empty((float)$riga['Quantita']) && empty((float)$prezzo_unitario); + $riferimento_fe = ''; + + if ($dati_ddt[(int)$riga['NumeroLinea']]) { + $riferimento_fe = tr('DDT _NUMERO_ del _DATA_', + [ + '_NUMERO_' => $dati_ddt[(int)$riga['NumeroLinea']]['numero'], + '_DATA_' => $dati_ddt[(int)$riga['NumeroLinea']]['data'], + ]); + } + + echo ' '.(empty($codice_principale) ? '' : '').' - +
+ '.$riferimento_fe.' '.$riga['Descrizione'].'
@@ -562,13 +602,15 @@ input("crea_articoli").on("change", function (){ } }); - $("select[name^=selezione_riferimento").change(function() { - let $this = $(this); - let data = $this.selectData(); +$("select[name^=selezione_riferimento").change(function() { + if (!$(this).hasClass("already-loaded")) { + let $this = $(this); + let data = $this.selectData(); - if (data) { - let riga = $this.closest("tr").prev(); - selezionaRiferimento(riga, data.tipo, data.id, data.dir); + if (data) { + let riga = $this.closest("tr").prev(); + selezionaRiferimento(riga, data.tipo, data.id, data.dir); + } } }); @@ -651,23 +693,29 @@ function impostaRiferimento(id_riga, documento, riga) { let riga_fe = $("#id_riga_riferimento_" + id_riga).closest("tr").prev(); // Informazioni visibili sulla quantità - impostaContenuto(riga_fe.data("qta"), riga.qta, (riga.um ? " " + riga.um : ""), "#riferimento_" + id_riga + "_qta"); + impostaContenuto(riga_fe.data("qta"), riga.qta, (riga.um ? " " + riga.um : ""), "#riferimento_" + id_riga + "_qta", true); // Informazioni visibili sul prezzo unitario - impostaContenuto(riga_fe.data("prezzo_unitario"), riga.prezzo_unitario, " " + globals.currency, "#riferimento_" + id_riga + "_prezzo"); + impostaContenuto(riga_fe.data("prezzo_unitario"), riga.prezzo_unitario, " " + globals.currency, "#riferimento_" + id_riga + "_prezzo", true); // Informazioni visibili sull\'aliquota IVA - impostaContenuto(riga_fe.data("iva_percentuale"), riga.iva_percentuale, "%", "#riferimento_" + id_riga + "_iva"); + impostaContenuto(riga_fe.data("iva_percentuale"), parseInt(riga.iva_percentuale), "%", "#riferimento_" + id_riga + "_iva", false); $("#riferimento_" + id_riga).html(documento.descrizione ? documento.descrizione : ""); var descrizione = riga.descrizione; - console.log(descrizione); if(typeof descrizione !== "undefined"){ - descrizione = descrizione.replace(/_/g, " "); + descrizione = descrizione.replace(/_/g, " ").replace(/\n/g, "
"); } - $("#riferimento_" + id_riga + "_descrizione").html(descrizione ? descrizione : ""); + // Dettagli del documento trovato + icona_documento = documento.match_documento_da_fe ? "fa-check-circle text-success" : "fa-question-circle text-orange"; + tooltip_icona = documento.match_documento_da_fe ? "La corrispondenza trovata è avvenuta in base a quanto ha specificato il fornitore nella fattura elettronica" : "Nessuna corrispondenza con quanto ha specificato il fornitore nella fattura elettronica, il riferimento potrebbe non essere corretto"; + + $("#riferimento_" + id_riga + "_descrizione").html("
" + documento.opzione + "
"); + + // Dettagli della riga trovata + $("#riferimento_" + id_riga + "_descrizione").append(descrizione ? descrizione : ""); // Colorazione dell\'intera riga let warnings = riga_fe.find(".text-warning"); @@ -679,7 +727,7 @@ function impostaRiferimento(id_riga, documento, riga) { } // Informazioni visibili sull\'aliquota IVA -function impostaContenuto(valore_riga, valore_riferimento, contenuto_successivo, id_elemento) { +function impostaContenuto(valore_riga, valore_riferimento, contenuto_successivo, id_elemento, parse_riferimento) { let elemento = $(id_elemento); if (valore_riferimento === undefined) { elemento.html(""); @@ -689,7 +737,7 @@ function impostaContenuto(valore_riga, valore_riferimento, contenuto_successivo, valore_riga = parseFloat(valore_riga); valore_riferimento = parseFloat(valore_riferimento); - let contenuto = valore_riferimento.toLocale() + contenuto_successivo; + let contenuto = (parse_riferimento ? valore_riferimento.toLocale() + contenuto_successivo : valore_riferimento + contenuto_successivo); if (valore_riferimento === valore_riga) { contenuto = ` ` + contenuto; elemento.addClass("text-success").removeClass("text-warning"); diff --git a/plugins/importFE/src/FatturaOrdinaria.php b/plugins/importFE/src/FatturaOrdinaria.php index a7002fc10..56ffe491f 100755 --- a/plugins/importFE/src/FatturaOrdinaria.php +++ b/plugins/importFE/src/FatturaOrdinaria.php @@ -126,6 +126,11 @@ class FatturaOrdinaria extends FatturaElettronica $ritenuta_contributi = !empty($fattura->id_ritenuta_contributi); $conto_arrotondamenti = null; + // Disattivo temporaneamente l'impostazione per evadere solo le quantità previste + $original_setting_evasione = setting('Permetti il superamento della soglia quantità dei documenti di origine'); + + \Settings::setValue('Permetti il superamento della soglia quantità dei documenti di origine', 1); + foreach ($righe as $key => $riga) { $articolo = ArticoloOriginale::find($articoli[$key]); @@ -178,9 +183,9 @@ class FatturaOrdinaria extends FatturaElettronica $obj->descrizione = $riga['Descrizione']; // Collegamento al documento di riferimento - if (!empty($tipi_riferimenti[$key]) && is_subclass_of($tipi_riferimenti[$key], Component::class)) { + if (!empty($tipi_riferimenti[$key]) && is_subclass_of($tipi_riferimenti[$key], Component::class) && !empty($id_riferimenti[$key])) { $riga_origine = ($tipi_riferimenti[$key])::find($id_riferimenti[$key]); - list($riferimento_precedente, $nuovo_riferimento) = $obj->impostaOrigine($riga_origine); + list($riferimento_precedente, $nuovo_riferimento) = $obj->impostaOrigine($tipi_riferimenti[$key], $id_riferimenti[$key]); // Correzione della descrizione $obj->descrizione = str_replace($riferimento_precedente, '', $obj->descrizione); @@ -316,6 +321,9 @@ class FatturaOrdinaria extends FatturaElettronica $obj->save(); } + // Ripristino l'impostazione iniziale di evasione quantità + \Settings::setValue('Permetti il superamento della soglia quantità dei documenti di origine', $original_setting_evasione); + // Ricaricamento della fattura $fattura->refresh();