diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f143a90..f15b53fb4 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Tutti i maggiori cambiamenti di questo progetto saranno documentati in questo fi Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://keepachangelog.com/), e il progetto segue il [Semantic Versioning](http://semver.org/) per definire le versioni delle release. +- [2.4.50 (2023-10-06)](#2450-2023-10-06) - [2.4.49 (2023-09-22)](#2449-2023-09-25) - [2.4.48 (2023-08-01)](#2448-2023-08-01) - [2.4.47 (2023-06-30)](#2447-2023-06-30) @@ -60,6 +61,35 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k - [2.2 (2016-11-10)](#22-2016-11-10) - [2.1 (2015-04-02)](#21-2015-04-02) + +## 2.4.50 (2023-10-06) +### Aggiunto (Added) +- Aggiunta funzionalità Aggiorna prezzi in row-list dei documenti +- Aggiunta mappa nei moduli DDT +- Aggiunta colore nei record in base allo stato del documento +- Aggiunta colonna Sezionale in Tipi documento +- Aggiunta gestione fatture con più ritenute +- Aggiunti i preventivi in attesa di conferma in Informazioni Aggiuntive +- Aggiunta l'importazione dei seriali da fatture di acquisto +- Aggiunta creazione del tipo di anagrafica se mancante in import anagrafiche +- Aggiunta gestione inline dei campi Costo e Prezzo unitario nei documenti +- Aggiunto il login amministratore da app +- Aggiunta l'esportazione xml delle scadenze di bonifici per la banca +### Modificato (Changed) +- Aggiornato il modello Asso Invoice +- Eliminata la cartella tests +- Disabilitato il tasto Elimina documento nel caso siano selezionate delle righe +### Fixed +- Corretto il campo RiferimentoAmministrazione in generazione XML +- Corretta la visualizzazione della dicitura fissa in fattura +- Corretta la visualizzazione della tabella del modulo Listini cliente +- Corretta l'importazione delle anagrafiche con chiave primaria rientrante in campi_sede +- Corretto il template sollecito di pagamento raggruppato per anagrafica +- Corretta la visualizzazione del tasto sms +- Corretta la generazione dell'autofattura in presenza di articoli +- Corretto il campo RiferimentoNumeroLinea in fase di generazione XML +- Corretta la duplicazione delle fatture +- Corretta la query dei documenti collegati ## 2.4.49 (2023-09-25) ### Aggiunto (Added) - Aggiunto avviso in caso di impossibilità di caricare la mappa diff --git a/modules/anagrafiche/src/Import/CSV.php b/modules/anagrafiche/src/Import/CSV.php index 780f44f7e..135242ac0 100644 --- a/modules/anagrafiche/src/Import/CSV.php +++ b/modules/anagrafiche/src/Import/CSV.php @@ -262,13 +262,13 @@ class CSV extends CSVImporter $tipo_anagrafica = $database->fetchOne('SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE lower(descrizione) = LOWER('.prepare($tipo).') OR idtipoanagrafica = '.prepare($tipo))['idtipoanagrafica']; } - + $tipologie[] = $tipo_anagrafica; } } unset($record['idtipoanagrafica']); - $tipi_selezionati = []; + $tipi_selezionati = []; if (!empty($record['tipo'])) { $tipi_selezionati = explode(',', $record['tipo']); } diff --git a/modules/articoli/edit.php b/modules/articoli/edit.php index c30f3b14f..7988051cc 100755 --- a/modules/articoli/edit.php +++ b/modules/articoli/edit.php @@ -392,11 +392,11 @@ $("#scorporaIva").click( function() { // Collegamenti diretti // Fatture, ddt, preventivi collegati a questo articolo -$elementi = $dbo->fetchArray('SELECT `co_documenti`.`id`, `co_documenti`.`data`, `co_documenti`.`numero`, `co_documenti`.`numero_esterno`, `co_tipidocumento`.`descrizione` AS tipo_documento, `co_tipidocumento`.`dir`, SUM(co_righe_documenti.qta) AS qta_totale, ((SUM(co_righe_documenti.prezzo_unitario)-SUM(co_righe_documenti.sconto_unitario))/SUM(co_righe_documenti.qta)) AS prezzo_unitario, SUM(co_righe_documenti.prezzo_unitario)-SUM(co_righe_documenti.sconto_unitario) AS prezzo_totale FROM `co_documenti` JOIN `co_tipidocumento` ON `co_tipidocumento`.`id` = `co_documenti`.`idtipodocumento` INNER JOIN `co_righe_documenti` ON `co_documenti`.`id`=`co_righe_documenti`.`iddocumento` WHERE `co_righe_documenti`.`idarticolo` = '.prepare($id_record).' GROUP BY co_documenti.id +$elementi = $dbo->fetchArray('SELECT `co_documenti`.`id`, `co_documenti`.`data`, `co_documenti`.`numero`, `co_documenti`.`numero_esterno`, `co_tipidocumento`.`descrizione` AS tipo_documento, `co_tipidocumento`.`dir`, SUM(co_righe_documenti.qta) AS qta_totale, ((SUM(co_righe_documenti.prezzo_unitario)-SUM(co_righe_documenti.sconto_unitario))*SUM(co_righe_documenti.qta)) AS prezzo_totale, SUM(co_righe_documenti.prezzo_unitario)-SUM(co_righe_documenti.sconto_unitario) AS prezzo_unitario FROM `co_documenti` JOIN `co_tipidocumento` ON `co_tipidocumento`.`id` = `co_documenti`.`idtipodocumento` INNER JOIN `co_righe_documenti` ON `co_documenti`.`id`=`co_righe_documenti`.`iddocumento` WHERE `co_righe_documenti`.`idarticolo` = '.prepare($id_record).' GROUP BY co_documenti.id -UNION SELECT `dt_ddt`.`id`, `dt_ddt`.`data`, `dt_ddt`.`numero`, `dt_ddt`.`numero_esterno`, `dt_tipiddt`.`descrizione` AS tipo_documento, `dt_tipiddt`.`dir`, SUM(dt_righe_ddt.qta) AS qta_totale, ((SUM(dt_righe_ddt.prezzo_unitario)-SUM(dt_righe_ddt.sconto_unitario))/SUM(dt_righe_ddt.qta)) AS prezzo_unitario, SUM(dt_righe_ddt.prezzo_unitario)-SUM(dt_righe_ddt.sconto_unitario) AS prezzo_totale FROM `dt_ddt` JOIN `dt_tipiddt` ON `dt_tipiddt`.`id` = `dt_ddt`.`idtipoddt` INNER JOIN `dt_righe_ddt` ON `dt_ddt`.`id`=`dt_righe_ddt`.`idddt` WHERE `dt_righe_ddt`.`idarticolo` = '.prepare($id_record).' GROUP BY dt_ddt.id +UNION SELECT `dt_ddt`.`id`, `dt_ddt`.`data`, `dt_ddt`.`numero`, `dt_ddt`.`numero_esterno`, `dt_tipiddt`.`descrizione` AS tipo_documento, `dt_tipiddt`.`dir`, SUM(dt_righe_ddt.qta) AS qta_totale, ((SUM(dt_righe_ddt.prezzo_unitario)-SUM(dt_righe_ddt.sconto_unitario))*SUM(dt_righe_ddt.qta)) AS prezzo_totale, SUM(dt_righe_ddt.prezzo_unitario)-SUM(dt_righe_ddt.sconto_unitario) AS prezzo_unitario FROM `dt_ddt` JOIN `dt_tipiddt` ON `dt_tipiddt`.`id` = `dt_ddt`.`idtipoddt` INNER JOIN `dt_righe_ddt` ON `dt_ddt`.`id`=`dt_righe_ddt`.`idddt` WHERE `dt_righe_ddt`.`idarticolo` = '.prepare($id_record).' GROUP BY dt_ddt.id -UNION SELECT `co_preventivi`.`id`, `co_preventivi`.`data_bozza`, `co_preventivi`.`numero`, 0 AS numero_esterno , "Preventivo" AS tipo_documento, 0 AS dir, SUM(co_righe_preventivi.qta) AS qta_totale, ((SUM(co_righe_preventivi.prezzo_unitario)-SUM(co_righe_preventivi.sconto_unitario))/SUM(co_righe_preventivi.qta)) AS prezzo_unitario, SUM(co_righe_preventivi.prezzo_unitario)-SUM(co_righe_preventivi.sconto_unitario) AS prezzo_totale FROM `co_preventivi` INNER JOIN `co_righe_preventivi` ON `co_preventivi`.`id`=`co_righe_preventivi`.`idpreventivo` WHERE `co_righe_preventivi`.`idarticolo` = '.prepare($id_record).' GROUP BY co_preventivi.id ORDER BY `data`'); +UNION SELECT `co_preventivi`.`id`, `co_preventivi`.`data_bozza`, `co_preventivi`.`numero`, 0 AS numero_esterno , "Preventivo" AS tipo_documento, 0 AS dir, SUM(co_righe_preventivi.qta) AS qta_totale, ((SUM(co_righe_preventivi.prezzo_unitario)-SUM(co_righe_preventivi.sconto_unitario))*SUM(co_righe_preventivi.qta)) AS prezzo_totale, SUM(co_righe_preventivi.prezzo_unitario)-SUM(co_righe_preventivi.sconto_unitario) AS prezzo_unitario FROM `co_preventivi` INNER JOIN `co_righe_preventivi` ON `co_preventivi`.`id`=`co_righe_preventivi`.`idpreventivo` WHERE `co_righe_preventivi`.`idarticolo` = '.prepare($id_record).' GROUP BY co_preventivi.id ORDER BY `data`'); if (!empty($elementi)) { echo ' diff --git a/modules/dashboard/ajax.php b/modules/dashboard/ajax.php index 187e5b297..4c89f0e8a 100644 --- a/modules/dashboard/ajax.php +++ b/modules/dashboard/ajax.php @@ -142,11 +142,11 @@ switch (filter('op')) { )'; $preventivi = $dbo->fetchArray($query); - + foreach ($preventivi as $preventivo) { if ($preventivo['is_pianificabile'] == 1 || $preventivo['stato'] = 'In attesa di conferma') { if (!empty($preventivo['data_accettazione']) && $preventivo['data_accettazione'] != '0000-00-00') { - $query."AND co_statipreventivi.is_pianificabile=1"; + $query.'AND co_statipreventivi.is_pianificabile=1'; $results[] = [ 'id' => 'A_'.$modulo_preventivi->id.'_'.$preventivo['id'], 'idintervento' => $preventivo['id'], diff --git a/modules/ddt/row-list.php b/modules/ddt/row-list.php index 725ad3c91..483f39fd9 100755 --- a/modules/ddt/row-list.php +++ b/modules/ddt/row-list.php @@ -139,10 +139,10 @@ foreach ($righe as $riga) { if ($riga->isDescrizione()) { echo ' '; - if ($dir == 'entrata') { - echo ''; - } - echo ' + if ($dir == 'entrata') { + echo ''; + } + echo ' '; diff --git a/modules/fatture/actions.php b/modules/fatture/actions.php index 700817726..c38bc29ea 100755 --- a/modules/fatture/actions.php +++ b/modules/fatture/actions.php @@ -856,12 +856,19 @@ switch ($op) { $tipo = Tipo::find(post('idtipodocumento')); $iva = Aliquota::find(setting('Iva predefinita')); - $imponibile += Riga::join('co_iva', 'co_iva.id', '=', 'co_righe_documenti.idiva') + $imponibile = $database->table('co_righe_documenti') + ->join('co_iva', 'co_iva.id', '=', 'co_righe_documenti.idiva') ->where('co_iva.codice_natura_fe', 'LIKE', 'N3%') ->where('co_righe_documenti.iddocumento', $fattura->id) ->sum('subtotale'); - $totale_imponibile = setting('Utilizza prezzi di vendita comprensivi di IVA') ? $imponibile + ($imponibile * $iva->percentuale / 100) : $imponibile; + $sconto = $database->table('co_righe_documenti') + ->join('co_iva', 'co_iva.id', '=', 'co_righe_documenti.idiva') + ->where('co_iva.codice_natura_fe', 'LIKE', 'N3%') + ->where('co_righe_documenti.iddocumento', $fattura->id) + ->sum('sconto'); + + $totale_imponibile = setting('Utilizza prezzi di vendita comprensivi di IVA') ? ($imponibile - $sconto) + (($imponibile - $sconto) * $iva->percentuale / 100) : ($imponibile - $sconto); $totale_imponibile = $fattura->tipo->reversed == 1 ? -$totale_imponibile : $totale_imponibile; $autofattura = Fattura::build($anagrafica, $tipo, $data, $id_segment); @@ -1185,7 +1192,7 @@ switch ($op) { flash()->info(tr('Riga aggiornata!')); } - break; + break; } // Nota di debito diff --git a/modules/fatture/row-list.php b/modules/fatture/row-list.php index d3a78b8b5..84a20a7ef 100755 --- a/modules/fatture/row-list.php +++ b/modules/fatture/row-list.php @@ -188,7 +188,7 @@ foreach ($righe as $riga) { if ($dir == 'entrata') { echo ''; } - echo ' + echo ' diff --git a/modules/ordini/row-list.php b/modules/ordini/row-list.php index 535856110..c11f6d96a 100755 --- a/modules/ordini/row-list.php +++ b/modules/ordini/row-list.php @@ -193,10 +193,10 @@ foreach ($righe as $riga) { if ($riga->isDescrizione()) { echo ' '; - if ($dir == 'entrata') { - echo ''; - } - echo ' + if ($dir == 'entrata') { + echo ''; + } + echo ' '; diff --git a/plugins/exportFE/src/FatturaElettronica.php b/plugins/exportFE/src/FatturaElettronica.php index 2687a598c..fdd4bd8d6 100755 --- a/plugins/exportFE/src/FatturaElettronica.php +++ b/plugins/exportFE/src/FatturaElettronica.php @@ -849,7 +849,6 @@ class FatturaElettronica 'Sede' => static::getSede($cliente), ]; - return $result; } @@ -1132,7 +1131,7 @@ class FatturaElettronica $dati = []; if (!empty($element['riferimento_linea'])) { - $dati['RiferimentoNumeroLinea'] = $element['riferimento_linea']; + $dati['RiferimentoNumeroLinea'] = $element['riferimento_linea']['id']; } $dati['IdDocumento'] = $element['id_documento']; diff --git a/plugins/importFE/actions.php b/plugins/importFE/actions.php index 8379b9c61..ae016bce0 100755 --- a/plugins/importFE/actions.php +++ b/plugins/importFE/actions.php @@ -139,7 +139,7 @@ switch (filter('op')) { 'crea_articoli' => post('crea_articoli'), 'is_ritenuta_pagata' => post('is_ritenuta_pagata'), 'update_info' => post('update_info'), - 'serial' => post('flag_crea_seriali') ? post('serial') : [], + 'serial' => post('flag_crea_seriali') ? post('serial') : [], ]; $fattura_pa = FatturaElettronica::manage($filename); diff --git a/plugins/importFE/generate.php b/plugins/importFE/generate.php index 6fed05a94..0429c7eba 100755 --- a/plugins/importFE/generate.php +++ b/plugins/importFE/generate.php @@ -326,7 +326,7 @@ echo '
- {[ "type": "checkbox", "label": "'.tr('Creazione seriali').'", "name": "flag_crea_seriali", "value": 0, "help": "'.tr("Nel caso di righe contenenti serial, il gestionale procede alla registrazione del serial").'" ]} + {[ "type": "checkbox", "label": "'.tr('Creazione seriali').'", "name": "flag_crea_seriali", "value": 0, "help": "'.tr('Nel caso di righe contenenti serial, il gestionale procede alla registrazione del serial').'" ]}
'; $ritenuta = $dati_generali['DatiRitenuta']; @@ -421,7 +421,7 @@ if (!empty($righe)) { $serial = []; foreach ($codici as $codice) { $codici_articoli[] = $codice['CodiceValore'].' ('.$codice['CodiceTipo'].')'; - if (str_contains($codice['CodiceTipo'], 'serial') || str_contains($codice['CodiceTipo'], 'Serial')) { + if (str_contains($codice['CodiceTipo'], 'serial') || str_contains($codice['CodiceTipo'], 'Serial')) { $serial[] = $codice['CodiceValore']; } } @@ -605,13 +605,13 @@ if (!empty($righe)) {
'; - for ($i = 0; $i < $qta; $i++) { - echo ' + for ($i = 0; $i < $qta; ++$i) { + echo '
{[ "type": "text", "label": "'.tr('Serial').'", "name": "serial['.$key.'][]", "value": "'.$serial[$i].'" ]}
'; - } - echo ' + } + echo '
diff --git a/plugins/importFE/src/FatturaOrdinaria.php b/plugins/importFE/src/FatturaOrdinaria.php index aa890db0b..f7e9d6bac 100755 --- a/plugins/importFE/src/FatturaOrdinaria.php +++ b/plugins/importFE/src/FatturaOrdinaria.php @@ -385,7 +385,7 @@ class FatturaOrdinaria extends FatturaElettronica // Arrotondamenti differenti nella fattura XML $diff = round(abs($totale_righe) + $totale_arrotondamento - abs($fattura->totale_imponibile), 2); // Aggiunta della riga di arrotondamento nel caso in cui ci sia una differenza tra i totali, o tra l'imponibile dell'XML e quello ricavato dalla somma delle righe - + if (($diff != 0 && $diff != $totale_arrotondamento) || (($fattura->totale_imponibile + $fattura->rivalsa_inps) != $totale_imp)) { // Rimozione dell'IVA calcolata automaticamente dal gestionale $iva_arrotondamento = database()->fetchOne('SELECT * FROM co_iva WHERE percentuale=0 AND deleted_at IS NULL'); diff --git a/plugins/presentazioni_bancarie/src/Gestore.php b/plugins/presentazioni_bancarie/src/Gestore.php index 51b2a3c0b..f99c99555 100644 --- a/plugins/presentazioni_bancarie/src/Gestore.php +++ b/plugins/presentazioni_bancarie/src/Gestore.php @@ -128,6 +128,7 @@ class Gestore $intestazione->ragione_sociale_creditore = strtoupper($this->azienda->ragione_sociale); $intestazione->indirizzo_creditore = strtoupper($this->azienda['indirizzo']); $intestazione->partita_iva_o_codice_fiscale_creditore = !empty($this->azienda->partita_iva) ? $this->azienda->partita_iva : $this->azienda->codice_fiscale; + $intestazione->identificativo_creditore = !empty($this->azienda->partita_iva) ? $this->azienda->partita_iva : $this->azienda->codice_fiscale; $intestazione->descrizione_banca = $descrizione_banca; $this->bonifico = new CbiSepa($intestazione); diff --git a/src/API/App/v1/Checklists.php b/src/API/App/v1/Checklists.php old mode 100644 new mode 100755 index c480fe788..c2e5b875a --- a/src/API/App/v1/Checklists.php +++ b/src/API/App/v1/Checklists.php @@ -22,8 +22,8 @@ namespace API\App\v1; use API\App\AppResource; use Auth; use Carbon\Carbon; -use Models\User; use Modules\Checklists\Check; +use Models\User; class Checklists extends AppResource { @@ -37,7 +37,6 @@ class Checklists extends AppResource // Informazioni sull'utente $user = Auth::user(); - $id_tecnico = $user->id_anagrafica; // Elenco di interventi di interesse $risorsa_interventi = $this->getRisorsaInterventi(); @@ -46,24 +45,46 @@ class Checklists extends AppResource // Elenco sessioni degli interventi da rimuovere $da_interventi = []; if (!empty($interventi)) { - $query = 'SELECT zz_checks.id - FROM zz_checks - INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id - INNER JOIN in_interventi_tecnici ON in_interventi_tecnici.idintervento = in_interventi.id - INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id - INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check - WHERE - zz_modules.name="Interventi" - AND - zz_check_user.id_utente = :id_tecnico - AND - in_interventi.id IN ('.implode(',', $interventi).') - OR (orario_fine NOT BETWEEN :period_start AND :period_end)'; - $records = database()->fetchArray($query, [ - ':period_end' => $end, - ':period_start' => $start, - ':id_tecnico' => $user->id, - ]); + if($user->is_admin){ + $query = ' + SELECT zz_checks.id + FROM zz_checks + INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id + INNER JOIN in_interventi_tecnici ON in_interventi_tecnici.idintervento = in_interventi.id + INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id + INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check + WHERE + zz_modules.name="Interventi" + AND + in_interventi.id IN ('.implode(',', $interventi).') + OR (orario_fine NOT BETWEEN :period_start AND :period_end)'; + + $records = database()->fetchArray($query, [ + ':period_end' => $end, + ':period_start' => $start, + ]); + }else{ + $query = ' + SELECT zz_checks.id + FROM zz_checks + INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id + INNER JOIN in_interventi_tecnici ON in_interventi_tecnici.idintervento = in_interventi.id + INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id + INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check + WHERE + zz_modules.name="Interventi" + AND + zz_check_user.id_utente = :id_tecnico + AND + in_interventi.id IN ('.implode(',', $interventi).') + OR (orario_fine NOT BETWEEN :period_start AND :period_end)'; + + $records = database()->fetchArray($query, [ + ':period_end' => $end, + ':period_start' => $start, + ':id_tecnico' => $user->id + ]); + } $da_interventi = array_column($records, 'id'); } @@ -90,30 +111,47 @@ class Checklists extends AppResource } $user = Auth::user(); - $id_tecnico = $user->id_anagrafica; $id_interventi = array_keys($interventi); - $query = 'SELECT zz_checks.id - FROM zz_checks - INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id - INNER JOIN in_interventi_tecnici ON in_interventi_tecnici.idintervento = in_interventi.id - INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id - INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check - WHERE - zz_modules.name="Interventi" - AND zz_check_user.id_utente = :id_tecnico - AND in_interventi.id IN ('.implode(',', $id_interventi).') - AND (orario_fine BETWEEN :period_start AND :period_end)'; + if($user->is_admin){ + $query = 'SELECT zz_checks.id + FROM zz_checks + INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id + INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id + INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check + WHERE + zz_modules.name="Interventi" + AND in_interventi.id IN ('.implode(',', $id_interventi).')'; - // Filtro per data - if ($last_sync_at) { - $query .= ' AND zz_checks.updated_at > '.prepare($last_sync_at); + // Filtro per data + if ($last_sync_at) { + $query .= ' AND zz_checks.updated_at > '.prepare($last_sync_at); + } + + $records = database()->fetchArray($query); + }else{ + $query = 'SELECT zz_checks.id + FROM zz_checks + INNER JOIN in_interventi ON zz_checks.id_record = in_interventi.id + INNER JOIN in_interventi_tecnici ON in_interventi_tecnici.idintervento = in_interventi.id + INNER JOIN zz_modules ON zz_checks.id_module = zz_modules.id + INNER JOIN zz_check_user ON zz_checks.id = zz_check_user.id_check + WHERE + zz_modules.name="Interventi" + AND zz_check_user.id_utente = :id_tecnico + AND in_interventi.id IN ('.implode(',', $id_interventi).') + AND (orario_fine BETWEEN :period_start AND :period_end)'; + + // Filtro per data + if ($last_sync_at) { + $query .= ' AND zz_checks.updated_at > '.prepare($last_sync_at); + } + $records = database()->fetchArray($query, [ + ':period_start' => $start, + ':period_end' => $end, + ':id_tecnico' => $user->id + ]); } - $records = database()->fetchArray($query, [ - ':period_start' => $start, - ':period_end' => $end, - ':id_tecnico' => $user->id, - ]); return $this->mapModifiedRecords($records); } @@ -121,17 +159,16 @@ class Checklists extends AppResource public function retrieveRecord($id) { // Gestione della visualizzazione dei dettagli del record - $query = 'SELECT zz_checks.id, + $query = "SELECT zz_checks.id, zz_checks.id_record AS id_intervento, zz_checks.checked_at, zz_checks.content, zz_checks.note, IF(zz_checks.id_parent IS NULL, 0, zz_checks.id_parent) AS id_parent, zz_checks.checked_by, - zz_checks.order AS ordine, - zz_checks.is_titolo + zz_checks.order AS ordine FROM zz_checks - WHERE zz_checks.id = '.prepare($id); + WHERE zz_checks.id = ".prepare($id); $record = database()->fetchOne($query); @@ -142,11 +179,11 @@ class Checklists extends AppResource { $check = Check::find($data['id']); - $check->checked_at = (!empty($data['checked_at']) ? $data['checked_at'] : null); + $check->checked_at = (!empty($data['checked_at']) ? $data['checked_at'] : NULL); $check->content = $data['content']; $check->note = $data['note']; $user = User::where('idanagrafica', $data['checked_by'])->first(); - if (!empty($user)) { + if(!empty($user)){ $check->checked_by = $user->id; } @@ -159,4 +196,4 @@ class Checklists extends AppResource { return new Interventi(); } -} +} \ No newline at end of file diff --git a/src/API/App/v1/Impianti.php b/src/API/App/v1/Impianti.php old mode 100644 new mode 100755 index ab491d282..1861ac7aa --- a/src/API/App/v1/Impianti.php +++ b/src/API/App/v1/Impianti.php @@ -22,6 +22,7 @@ namespace API\App\v1; use API\App\AppResource; use Illuminate\Database\Eloquent\Builder; use Modules\Impianti\Impianto; +use Auth; class Impianti extends AppResource { @@ -32,11 +33,26 @@ class Impianti extends AppResource public function getModifiedRecords($last_sync_at) { - $statement = Impianto::select('id', 'updated_at') + $statement = Impianto::select('id', 'updated_at', 'idtecnico') ->whereHas('anagrafica.tipi', function (Builder $query) { $query->where('descrizione', '=', 'Cliente'); }); + //Limite impianti visualizzabili dal tecnico + $limite_impianti = setting("Limita la visualizzazione degli impianti a quelli gestiti dal tecnico"); + + if($limite_impianti == 1 && !Auth::user()->is_admin){ + $id_tecnico = Auth::user()->id_anagrafica; + + // Elenco di interventi di interesse + $risorsa_interventi = $this->getRisorsaInterventi(); + // Da applicazione, i Clienti sono sincronizzati prima degli Interventi: last_sync_at permette di identificare le stesse modifiche + $interventi = $risorsa_interventi->getModifiedRecords(null); + $id_interventi = array_keys($interventi); + + $statement->where('idtecnico', $id_tecnico)->orWhere('id', 'IN', ('SELECT idimpianto FROM my_impianti_interventi WHERE idintervento IN ('.implode(',', $id_interventi).')')); + } + // Filtro per data if ($last_sync_at) { $statement = $statement->where('updated_at', '>', $last_sync_at); @@ -73,4 +89,8 @@ class Impianti extends AppResource return $record; } + protected function getRisorsaInterventi() + { + return new Interventi(); + } } diff --git a/src/API/App/v1/Interventi.php b/src/API/App/v1/Interventi.php old mode 100644 new mode 100755 index 2480f96e2..bcede684b --- a/src/API/App/v1/Interventi.php +++ b/src/API/App/v1/Interventi.php @@ -58,7 +58,31 @@ class Interventi extends AppResource // Informazioni sull'utente $id_tecnico = Auth::user()->id_anagrafica; - $query = 'SELECT in_interventi.id FROM in_interventi WHERE + if(Auth::user()->is_admin){ + $query = 'SELECT in_interventi.id FROM in_interventi WHERE + deleted_at IS NOT NULL + OR ( + in_interventi.id NOT IN ( + SELECT idintervento FROM in_interventi_tecnici + WHERE in_interventi_tecnici.idintervento = in_interventi.id + AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end + ) + AND in_interventi.id IN ( + SELECT idintervento FROM in_interventi_tecnici + WHERE in_interventi_tecnici.idintervento = in_interventi.id + AND in_interventi_tecnici.orario_fine BETWEEN :remove_period_start AND :remove_period_end + ) + )'; + + $records = database()->fetchArray($query, [ + ':period_end' => $end, + ':period_start' => $start, + ':remove_period_end' => $remove_end, + ':remove_period_start' => $remove_start, + ]); + + }else{ + $query = 'SELECT in_interventi.id FROM in_interventi WHERE deleted_at IS NOT NULL OR ( in_interventi.id NOT IN ( @@ -74,15 +98,17 @@ class Interventi extends AppResource AND in_interventi_tecnici.idtecnico = :id_tecnico_q2 ) )'; - $records = database()->fetchArray($query, [ + + $records = database()->fetchArray($query, [ ':period_end' => $end, ':period_start' => $start, ':remove_period_end' => $remove_end, ':remove_period_start' => $remove_start, ':id_tecnico_q1' => $id_tecnico, ':id_tecnico_q2' => $id_tecnico, - ]); - + ]); + } + $interventi = array_column($records, 'id'); $mancanti = $this->getMissingIDs('in_interventi', 'id', $last_sync_at); @@ -100,52 +126,96 @@ class Interventi extends AppResource $id_tecnico = Auth::user()->id_anagrafica; if (setting('Visualizza solo promemoria assegnati') == 1) { - $query = ' - SELECT - in_interventi.id, - in_interventi.updated_at - FROM - in_interventi - WHERE - deleted_at IS NULL AND ( - in_interventi.id IN ( - SELECT idintervento FROM in_interventi_tecnici - WHERE in_interventi_tecnici.idintervento = in_interventi.id - AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end - AND in_interventi_tecnici.idtecnico = :id_tecnico_q1 - ) - OR ( - in_interventi.id NOT IN ( - SELECT idintervento FROM in_interventi_tecnici - ) - AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0 AND in_interventi.id IN ( - SELECT id_intervento FROM in_interventi_tecnici_assegnati WHERE in_interventi_tecnici_assegnati.id_tecnico = :id_tecnico_q2) - ) - ) - )'; - } else { - $query = ' - SELECT - in_interventi.id, - in_interventi.updated_at - FROM - in_interventi - WHERE - deleted_at IS NULL AND ( - in_interventi.id IN ( - SELECT idintervento FROM in_interventi_tecnici - WHERE in_interventi_tecnici.idintervento = in_interventi.id - AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end - AND in_interventi_tecnici.idtecnico = :id_tecnico_q1 - ) - OR ( - in_interventi.id NOT IN ( - SELECT idintervento FROM in_interventi_tecnici + if(Auth::user()->is_admin){ + $query = ' + SELECT + in_interventi.id, + in_interventi.updated_at + FROM + in_interventi + WHERE + deleted_at IS NULL AND (in_interventi.id IN ( + SELECT idintervento FROM in_interventi_tecnici WHERE in_interventi_tecnici.idintervento = in_interventi.id AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end ) - AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0) - ) - )'; - } + OR ( + in_interventi.id NOT IN ( SELECT idintervento FROM in_interventi_tecnici + ) + AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0) + ) + )'; + }else{ + $query = ' + SELECT + in_interventi.id, + in_interventi.updated_at + FROM + in_interventi + WHERE + deleted_at IS NULL AND ( + in_interventi.id IN ( + SELECT idintervento FROM in_interventi_tecnici + WHERE in_interventi_tecnici.idintervento = in_interventi.id + AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end + AND in_interventi_tecnici.idtecnico = :id_tecnico_q1 + ) + OR ( + in_interventi.id NOT IN ( + SELECT idintervento FROM in_interventi_tecnici + ) + AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0) AND in_interventi.id IN ( + SELECT id_intervento FROM in_interventi_tecnici_assegnati WHERE in_interventi_tecnici_assegnati.id_tecnico = :id_tecnico_q2 + ) + ) + )'; + } + + } else { + if(Auth::user()->is_admin){ + $query = ' + SELECT + in_interventi.id, + in_interventi.updated_at + FROM + in_interventi + WHERE + deleted_at IS NULL AND ( + in_interventi.id IN ( + SELECT idintervento FROM in_interventi_tecnici + WHERE in_interventi_tecnici.idintervento = in_interventi.id + AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end + ) + OR ( + in_interventi.id NOT IN ( + SELECT idintervento FROM in_interventi_tecnici + ) + AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0) + ) + )'; + }else{ + $query = ' + SELECT + in_interventi.id, + in_interventi.updated_at + FROM + in_interventi + WHERE + deleted_at IS NULL AND ( + in_interventi.id IN ( + SELECT idintervento FROM in_interventi_tecnici + WHERE in_interventi_tecnici.idintervento = in_interventi.id + AND in_interventi_tecnici.orario_fine BETWEEN :period_start AND :period_end + AND in_interventi_tecnici.idtecnico = :id_tecnico_q1 + ) + OR ( + in_interventi.id NOT IN ( + SELECT idintervento FROM in_interventi_tecnici + ) + AND in_interventi.idstatointervento IN (SELECT idstatointervento FROM in_statiintervento WHERE is_completato = 0) + ) + )'; + } + + } // Filtro per data // Gestione di tecnici assegnati o impianti modificati @@ -161,18 +231,32 @@ class Interventi extends AppResource } if (setting('Visualizza solo promemoria assegnati') == 1) { - $records = database()->fetchArray($query, [ - ':period_start' => $start, - ':period_end' => $end, - ':id_tecnico_q1' => $id_tecnico, - ':id_tecnico_q2' => $id_tecnico, - ]); + if(Auth::user()->is_admin){ + $records = database()->fetchArray($query, [ + ':period_start' => $start, + ':period_end' => $end, + ]); + } else { + $records = database()->fetchArray($query, [ + ':period_start' => $start, + ':period_end' => $end, + ':id_tecnico_q1' => $id_tecnico, + ':id_tecnico_q2' => $id_tecnico, + ]); + } } else { - $records = database()->fetchArray($query, [ - ':period_start' => $start, - ':period_end' => $end, - ':id_tecnico_q1' => $id_tecnico, - ]); + if(Auth::user()->is_admin){ + $records = database()->fetchArray($query, [ + ':period_start' => $start, + ':period_end' => $end, + ]); + } else { + $records = database()->fetchArray($query, [ + ':period_start' => $start, + ':period_end' => $end, + ':id_tecnico_q1' => $id_tecnico, + ]); + } } return $this->mapModifiedRecords($records); @@ -269,10 +353,12 @@ class Interventi extends AppResource // Aggiornamento degli impianti collegati $database->query('DELETE FROM my_impianti_interventi WHERE idintervento = '.prepare($record->id)); foreach ($data['impianti'] as $id_impianto) { - $database->insert('my_impianti_interventi', [ - 'idimpianto' => $id_impianto, - 'idintervento' => $record->id, - ]); + if(!empty($id_impianto)){ + $database->insert('my_impianti_interventi', [ + 'idimpianto' => $id_impianto, + 'idintervento' => $record->id, + ]); + } } // Aggiornamento dei tecnici assegnati @@ -283,6 +369,10 @@ class Interventi extends AppResource ], [ 'id_tecnico' => $tecnici_assegnati, ]); + + if(!empty($data['idrichiesta'])){ + database()->query('UPDATE in_richieste SET idintervento = '.prepare($record->id).', updated_at=NOW() WHERE id = '.prepare($data['idrichiesta'])); + } } protected function salvaFirma($firma_base64) diff --git a/src/API/App/v1/Login.php b/src/API/App/v1/Login.php old mode 100644 new mode 100755 index d9a7ea8ed..a91b2e44b --- a/src/API/App/v1/Login.php +++ b/src/API/App/v1/Login.php @@ -35,18 +35,32 @@ class Login extends Resource implements CreateInterface if (auth()->attempt($request['username'], $request['password'])) { $user = $this->getUser(); $token = auth()->getToken(); - - // Informazioni sull'utente, strettamente collegato ad una anagrafica di tipo Tecnico - $utente = $database->fetchOne("SELECT - `an_anagrafiche`.`idanagrafica` AS id_anagrafica, - `an_anagrafiche`.`ragione_sociale` - FROM `zz_users` - INNER JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica` - INNER JOIN an_tipianagrafiche_anagrafiche ON an_tipianagrafiche_anagrafiche.idanagrafica = an_anagrafiche.idanagrafica - INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica = an_tipianagrafiche.idtipoanagrafica - WHERE an_tipianagrafiche.descrizione = 'Tecnico' AND `an_anagrafiche`.`deleted_at` IS NULL AND `id` = :id", [ - ':id' => $user['id'], - ]); + + if(setting("Permetti l'accesso agli amministratori")){ + $utente = $database->fetchOne("SELECT + `an_anagrafiche`.`idanagrafica` AS id_anagrafica, + `an_anagrafiche`.`ragione_sociale`, + zz_groups.nome AS gruppo + FROM `zz_users` + INNER JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica` + INNER JOIN zz_groups ON zz_users.idgruppo=zz_groups.id + WHERE `an_anagrafiche`.`deleted_at` IS NULL AND `zz_users`.`id` = :id", [ + ':id' => $user['id'], + ]); + }else{ + $utente = $database->fetchOne("SELECT + `an_anagrafiche`.`idanagrafica` AS id_anagrafica, + `an_anagrafiche`.`ragione_sociale`, + zz_groups.nome AS gruppo + FROM `zz_users` + INNER JOIN `an_anagrafiche` ON `an_anagrafiche`.`idanagrafica` = `zz_users`.`idanagrafica` + INNER JOIN an_tipianagrafiche_anagrafiche ON an_tipianagrafiche_anagrafiche.idanagrafica = an_anagrafiche.idanagrafica + INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica = an_tipianagrafiche.idtipoanagrafica + INNER JOIN zz_groups ON zz_users.idgruppo=zz_groups.id + WHERE an_tipianagrafiche.descrizione = 'Tecnico' AND `an_anagrafiche`.`deleted_at` IS NULL AND `id` = :id", [ + ':id' => $user['id'], + ]); + } if (!empty($utente)) { // Informazioni da restituire tramite l'API @@ -54,6 +68,7 @@ class Login extends Resource implements CreateInterface 'id_anagrafica' => (string) $utente['id_anagrafica'], 'ragione_sociale' => $utente['ragione_sociale'], 'token' => $token, + 'gruppo' => $utente['gruppo'], 'version' => Update::getVersion(), ]; } else { diff --git a/src/API/Manager.php b/src/API/Manager.php index 7f5fa48bc..0b0804c02 100755 --- a/src/API/Manager.php +++ b/src/API/Manager.php @@ -289,7 +289,10 @@ class Manager // Operazioni della risorsa $response = $object->{$method}($request); - $database->commitTransaction(); + try{ + $database->commitTransaction(); + } catch (PDOException $e) { + } // Operazioni di completamento $object->close($request, $response); diff --git a/templates/preventivi/body.php b/templates/preventivi/body.php index 9e47e6dea..605d2d6af 100755 --- a/templates/preventivi/body.php +++ b/templates/preventivi/body.php @@ -305,7 +305,7 @@ foreach ($righe as $key => $riga) { $autofill->next(); $next = $righe->flatten()[$num]; - if ($has_gruppo && ($next->is_titolo || $next == null)) { + if ($has_gruppo && ($next->is_titolo || $next == null) && ($options['pricing'] || ($options['show-only-total']))) { echo ' diff --git a/update/2_4_50.sql b/update/2_4_50.sql index 929cec649..2c5d7179a 100644 --- a/update/2_4_50.sql +++ b/update/2_4_50.sql @@ -89,3 +89,9 @@ INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`, UPDATE `zz_prints` SET `predefined` = '0' WHERE `zz_prints`.`name` IN ('Stampa calendario settimanale', "Intervento & checklist", "Intervento & checklist (senza costi)", "Barcode bulk"); +UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `co_tipidocumento` LEFT JOIN zz_segments ON co_tipidocumento.id_segment = zz_segments.id WHERE 1=1 AND deleted_at IS NULL HAVING 2=2' WHERE `zz_modules`.`name` = 'Tipi documento'; + +-- Impostazione per login amministratore da app +INSERT INTO `zz_settings` (`nome`, `valore`, `tipo`, `editable`, `sezione`, `order`, `help`) VALUES ("Permetti l\'accesso agli amministratori", '1', 'boolean', 1, 'Applicazione', 4, ''); + +UPDATE `co_pianodeiconti2` SET `dir` = 'entrata/uscita' WHERE `co_pianodeiconti2`.`descrizione` = 'Immobilizzazioni'; \ No newline at end of file