This commit is contained in:
MatteoPistorello 2023-10-06 12:47:50 +02:00
commit baf184de84
20 changed files with 363 additions and 155 deletions

View File

@ -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

View File

@ -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']);
}

View File

@ -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 '

View File

@ -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'],

View File

@ -139,10 +139,10 @@ foreach ($righe as $riga) {
if ($riga->isDescrizione()) {
echo '
<td></td>';
if ($dir == 'entrata') {
echo '<td></td>';
}
echo '
if ($dir == 'entrata') {
echo '<td></td>';
}
echo '
<td></td>
<td></td>
<td></td>';

View File

@ -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

View File

@ -188,7 +188,7 @@ foreach ($righe as $riga) {
if ($dir == 'entrata') {
echo '<td></td>';
}
echo '
echo '
<td></td>
<td></td>
<td></td>

View File

@ -193,10 +193,10 @@ foreach ($righe as $riga) {
if ($riga->isDescrizione()) {
echo '
<td></td>';
if ($dir == 'entrata') {
echo '<td></td>';
}
echo '
if ($dir == 'entrata') {
echo '<td></td>';
}
echo '
<td></td>
<td></td>
<td></td>';

View File

@ -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'];

View File

@ -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);

View File

@ -326,7 +326,7 @@ echo '
</div>
<div class="col-md-3">
{[ "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').'" ]}
</div>';
$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)) {
</div>
<div class="row">';
for ($i = 0; $i < $qta; $i++) {
echo '
for ($i = 0; $i < $qta; ++$i) {
echo '
<div class="col-md-3">
{[ "type": "text", "label": "'.tr('Serial').'", "name": "serial['.$key.'][]", "value": "'.$serial[$i].'" ]}
</div>';
}
echo '
}
echo '
</div>
</div>
</div>

View File

@ -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');

View File

@ -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);

131
src/API/App/v1/Checklists.php Normal file → Executable file
View File

@ -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();
}
}
}

22
src/API/App/v1/Impianti.php Normal file → Executable file
View File

@ -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();
}
}

218
src/API/App/v1/Interventi.php Normal file → Executable file
View File

@ -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)

39
src/API/App/v1/Login.php Normal file → Executable file
View File

@ -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 {

View File

@ -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);

View File

@ -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 '
<tr>
<td colspan="'.($options['show-only-total'] ? 2 : 5).'" class="text-right">

View File

@ -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';