Compare commits

..

No commits in common. "a85830d7ff1e9bddff269cbc6754c50166011ef9" and "37dafc4eaaef91d19d47d905f4b5adb30e7b4450" have entirely different histories.

13 changed files with 54 additions and 128 deletions

View File

@ -4,7 +4,6 @@ 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.5.3 (2024-07-18)](#253-2024-07-18)
- [2.5.2 (2024-05-31)](#252-2024-05-31)
- [2.5.1 (2024-04-24)](#251-2024-04-24)
- [2.5 (2024-03-28)](#25-2024-03-28)
@ -69,73 +68,6 @@ 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.5.3 (2024-07-18)
### Aggiunto (Added)
- Aggiunto il valore delle **Vendite al banco** sul grafico del Fatturato
- Aggiunta legenda in **Articoli**
- Aggiunta la possibilità di spostare il marcatore della mappa manualmente
- Aggiunta plugin LeafletJS per mappe a schermo intero
- Aggiunto riferimento articolo in Pianificazione fatturazione in **Contratti**
- Aggiunta la gestione dell'invio automatico dei promemoria delle scadenze
- Aggiunto avviso nel caso di scadenza durante il mese di chiusura aziendale
- Aggiunta gestione caratteri speciali in fattura elettronica
- Aggiunta impostazione per utilizzare codice come barcode
### Modificato (Changed)
- Rimozione agenti secondari in **Anagrafiche**
- Migliorati gli stili grafici
- Ripristinata l'impostazione per limitare la visualizzazione degli **Impianti** a quelli gestiti dal tecnico da **App**
- Migliorata la gestione dell'invio automatico di solleciti di pagamento
- Spostata la gestione dei **Tag** in Strumenti
- Replicato l'header anche sui plugin del modulo
- Migliorato l'header delle **Attività**
- Unificati i pulsanti su un'unica riga
- Corretta la colorazione degli **Hooks**
- Ottimizzata l'apertura del riquadro **Mappa**
- Rimossi i file header.php non completati
- Modificato l'avviso in plugin **Componenti**
- Migliorata la tabella **Scadenzario**
### Fixed
- Corretta la procedura di installazione dei moduli e plugins
- Corretta l'esportazione delle scadenze con più banche
- Corretta gestione dei plugin
- Corretti i requisiti di installazione
- Corretti i plugins **Statistiche di vendita**, **Listino fornitori**, **Pianificazione fatturazione contratti**, **Impianti del cliente**, **Statistiche anagrafiche**, **Allegati**,**Contratti del cliente**, **DDT del cliente**, **Listino clienti**, **Componenti**, **Dichiarazioni d'intento** e **Note**
- Corretti i widgets **Promemoria attività da pianificare**, **Stampa calendario** e **Anagrafiche**
- Corrette le informazioni per tipo di anagrafica
- Corretto il controllo documento duplicato in **Fatture di vendita**
- Corretti i link al modulo **Attività**
- Corretto il salvataggio dell'immagine **Impianto**
- Corretta la compressione dei JS
- Corretto il click su **Dashboard** da mobile
- Corretto il filtro nelle selezioni
- Corretti i moduli **Liste**, **Template email**
- Corretta la vista delle sottocategorie in **Articoli**
- Corretta la sincronizzazione dei campi personalizzati e degli impianti in App
- Corretta la creazione di **Attività** collegate ad Impianti
- Corretti i campi personalizzati
- Corretta l'importazione delle Note di credito
- Corretto il controllo dei valori delle **Fatture di acquisto**
- Corretta la gestione degli arrotondamenti in fase di importazione **Fattura di acquisto**
- Corretta la gestione dei periodi multipli in **Statistiche**
- Corretta la modifica delle **Fasce orarie**, **Scadenze** e **Causali movimento**
- Corretto temporaneamente l'avviso del componente di videoscrittura
- Corretta la verifica della connessione SMTP in **Account email**
- Corretta l'eliminazione delle **Regole di pagamento**
- Corretto il filtro per data e numero delle tabelle
- Corretta la creazione di **Attributi** e **Combinazioni**
- Corretta l'eliminazione **Articoli** da azioni di gruppo
- Corretta la query di rinnovo contratto
- Corretta l'eliminazione, esportazione, calcolo coordinate e aggiunta listino **Anagrafiche** da azioni di gruppo
- Corretto il cambio stato degli **Ordini** da azioni di gruppo
- Corretto il salvataggio e la visualizzazione delle note delle **Checklists**
- Corretta la creazione preventivo da azioni di gruppo in **Articoli**
- Corretta la pagina di login
- Corrette le **Stampe contabili**, **Automezzi** e **Inventario**
- Corretta la tipologia attività in modifica sessione
- Corretto l'avviso di occupazione dei tecnici
## 2.5.2 (2024-05-31)
### Aggiunto (Added)
- Migrazione a tema grafico AdminLTE 3

View File

@ -618,7 +618,7 @@ if (Auth::check()) {
if (!empty($messages['warning']) || !empty($messages['error'])) {
echo '
<div class="card card-warning card-center card-center-large">
<div class="card card-warning card-center">
<div class="card-header with-border text-center">
<h3 class="card-title">'.tr('Informazioni').'</h3>
</div>

View File

@ -266,12 +266,8 @@ switch (post('op')) {
$new->codice = $codice;
$new->qta = 0;
$nome_immagine = $articolo->immagine;
$new->immagine = $nome_immagine;
$new->save();
$id_record = $new->id;
// Copia degli allegati
$copia_allegati = post('copia_allegati');
if (!empty($copia_allegati)) {
@ -284,6 +280,13 @@ switch (post('op')) {
}
}
// Salvataggio immagine relativa
$nome_immagine = $articolo->immagine_upload->getTranslation('title');
$new->immagine = $new->uploads()->where('name', $nome_immagine)->first()->filename;
$new->save();
$id_record = $new->id;
flash()->info(tr('Articolo duplicato correttamente!'));
break;

View File

@ -148,7 +148,7 @@ percentuale = 0;
$(document).ready(function () {
var sub = $('#add-form').find('#subcategoria_add');
var original = sub.parent().find(".input-group-append button").attr("onclick");
var original = sub.parent().find(".input-group-addon button").attr("onclick");
$('#add-form').find('#categoria').change(function() {
updateSelectOption("id_categoria", $(this).val());
@ -157,11 +157,11 @@ $(document).ready(function () {
sub.selectReset();
if($(this).val()){
sub.parent().find(".input-group-append button").removeClass("hide");
sub.parent().find(".input-group-append button").attr("onclick", original.replace('&ajax=yes', "&ajax=yes&id_original=" + $(this).val()));
sub.parent().find(".input-group-addon button").removeClass("hide");
sub.parent().find(".input-group-addon button").attr("onclick", original.replace('&ajax=yes', "&ajax=yes&id_original=" + $(this).val()));
}
else {
sub.parent().find(".input-group-append button").addClass("hide");
sub.parent().find(".input-group-addon button").addClass("hide");
}
});

View File

@ -19,12 +19,12 @@
include_once __DIR__.'/../../core.php';
echo '
<button type="button" class="btn btn-primary" onclick="if( confirm(\'Confermando, tutte le checklist degli impianti di questa categoria verranno aggiornate. Continuare?\') ){ $(\'#check-impianto\').submit(); }"> <i class="fa fa-refresh"></i> '.tr('Sincronizza checklist impianti').'</button>';
// Sincronizza checklist impianti
echo '
<form action="" method="post" id="check-impianto">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="op" value="sync_checklist">
</form>
<button type="button" class="btn btn-primary" onclick="if( confirm(\'Confermando, tutte le checklist degli impianti di questa categoria verranno aggiornate. Continuare?\') ){ $(\'#check-impianto\').submit(); }"> <i class="fa fa-refresh"></i> '.tr('Sincronizza checklist impianti').'</button>';
</form>';

View File

@ -33,10 +33,10 @@ switch (post('op')) {
$fascia_oraria_new = FasciaOraria::where('id', '=', (new FasciaOraria())->getByField('title', $descrizione))->where('id', '!=', $id_record)->first();
if (empty($fascia_oraria_new)) {
if (!empty($is_predefined)) {
$dbo->query('UPDATE `in_fasceorarie` SET `is_predefined` = 0');
$dbo->query('UPDATE `in_fasceorarie` SET `predefined` = 0');
}
$fascia_oraria->setTranslation('title', $descrizione);
$fascia_oraria->giorni = implode(',', $giorni);
$fascia_oraria->giorni = $giorni;
$fascia_oraria->ora_inizio = $ora_inizio;
$fascia_oraria->ora_fine = $ora_fine;
$fascia_oraria->include_bank_holidays = $include_bank_holidays;

View File

@ -71,7 +71,7 @@ $id_modulo_categorie_impianti = Module::where('name', 'Categorie impianti')->fir
<script type="text/javascript">
$(document).ready(function () {
var sub = $('#add-form').find('#sottocategoria_add');
var original = sub.parent().find(".input-group-append button").attr("onclick");
var original = sub.parent().find(".input-group-addon button").attr("onclick");
$('#add-form').find('#id_categoria').change(function() {
updateSelectOption("id_categoria", $(this).val());
@ -80,11 +80,11 @@ $(document).ready(function () {
sub.selectReset();
if($(this).val()){
sub.parent().find(".input-group-append button").removeClass("hide");
sub.parent().find(".input-group-append button").attr("onclick", original.replace('&ajax=yes', "&ajax=yes&id_original=" + $(this).val()));
sub.parent().find(".input-group-addon button").removeClass("hide");
sub.parent().find(".input-group-addon button").attr("onclick", original.replace('&ajax=yes', "&ajax=yes&id_original=" + $(this).val()));
}
else {
sub.parent().find(".input-group-append button").addClass("hide");
sub.parent().find(".input-group-addon button").addClass("hide");
}
});

View File

@ -493,10 +493,6 @@ echo '
$("#dettagli_cliente").html(data);
});
}
let data = anagrafica.getData();
input("idcontratto").getElement()
.selectSetNew(data.id_contratto, data.descrizione_contratto);
// Quando modifico orario inizio, allineo anche l\'orario fine
let orario_inizio = input("orario_inizio").getElement();

View File

@ -239,8 +239,7 @@ switch (post('op')) {
// Calcolo del nuovo codice sulla base della data di richiesta
$new->codice = Intervento::getNextCodice($data_richiesta, $new->id_segment);
$new->firma_file = '';
$new->firma_data = '';
$new->save();
$id_record = $new->id;
@ -318,7 +317,6 @@ switch (post('op')) {
flash()->info(tr('Attività duplicate correttamente!'));
break;
case 'delete-bulk':

View File

@ -36,7 +36,7 @@ $button = '<i class="fa fa-edit"></i> '.tr('Modifica');
$intervento = Intervento::find($id_record);
if (!empty($intervento->id_contratto)) {
$query = 'SELECT `in_tipiintervento`.`id`, `title` as `descrizione`, `co_contratti_tipiintervento`.`costo_ore` AS prezzo_ore_unitario, `co_contratti_tipiintervento`.`costo_km` AS prezzo_km_unitario, `co_contratti_tipiintervento`.`costo_dirittochiamata` AS prezzo_dirittochiamata FROM `in_tipiintervento` LEFT JOIN `in_tipiintervento_lang` ON (`in_tipiintervento`.`id` = `in_tipiintervento_lang`.`id_record` AND `in_tipiintervento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') INNER JOIN `co_contratti_tipiintervento` ON `in_tipiintervento`.`id` = `co_contratti_tipiintervento`.`idtipointervento` WHERE `co_contratti_tipiintervento`.`idcontratto` = '.prepare($intervento->id_contratto).' AND `in_tipiintervento`.`deleted_at` IS NULL ORDER BY `title`';
$query = 'SELECT `in_tipiintervento`.`id`, `title`, `co_contratti_tipiintervento`.`costo_ore` AS prezzo_ore_unitario, `co_contratti_tipiintervento`.`costo_km` AS prezzo_km_unitario, `co_contratti_tipiintervento`.`costo_dirittochiamata` AS prezzo_dirittochiamata FROM `in_tipiintervento` LEFT JOIN `in_tipiintervento_lang` ON (`in_tipiintervento`.`id` = `in_tipiintervento_lang`.`id_record` AND `in_tipiintervento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') INNER JOIN `co_contratti_tipiintervento` ON `in_tipiintervento`.`id` = `co_contratti_tipiintervento`.`idtipointervento` WHERE `co_contratti_tipiintervento`.`idcontratto` = '.prepare($intervento->id_contratto).' AND `in_tipiintervento`.`deleted_at` IS NULL ORDER BY `title`';
} else {
$query = 'SELECT `in_tipiintervento`.`id`, `title` as `descrizione`, `in_tariffe`.`costo_ore` AS prezzo_ore_unitario, `in_tariffe`.`costo_km` AS prezzo_km_unitario, `in_tariffe`.`costo_dirittochiamata` AS prezzo_dirittochiamata FROM `in_tipiintervento` LEFT JOIN `in_tipiintervento_lang` ON (`in_tipiintervento`.`id` = `in_tipiintervento_lang`.`id_record` AND `in_tipiintervento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).') INNER JOIN `in_tariffe` ON `in_tipiintervento`.`id` = `in_tariffe`.`idtipointervento` WHERE `in_tariffe`.`idtecnico` = '.prepare($sessione['idtecnico']).' AND `in_tipiintervento`.`deleted_at` IS NULL ORDER BY `title`';
}

View File

@ -75,10 +75,10 @@ foreach ($tecnici as $id_tecnico => $ore) {
// Conflitti ristretti per orario
foreach ($ore as $orario) {
$query_conflitto = $query.' AND ((orario_inizio >= '.prepare($orario['inizio']).' AND orario_inizio <= '.prepare($orario['fine']).') OR
(orario_fine >= '.prepare($orario['inizio']).' AND orario_fine <= '.prepare($orario['fine']).') OR
(orario_inizio <= '.prepare($orario['inizio']).' AND orario_fine >= '.prepare($orario['inizio']).') OR
(orario_inizio <= '.prepare($orario['fine']).' AND orario_fine >= '.prepare($orario['fine']).'))';
$query_conflitto = $query.' AND ((orario_inizio > '.prepare($orario['inizio']).' AND orario_inizio < '.prepare($orario['fine']).') OR
(orario_fine > '.prepare($orario['inizio']).' AND orario_fine < '.prepare($orario['fine']).') OR
(orario_inizio < '.prepare($orario['inizio']).' AND orario_fine > '.prepare($orario['inizio']).') OR
(orario_inizio < '.prepare($orario['fine']).' AND orario_fine > '.prepare($orario['fine']).'))';
$conflitto = $database->fetchArray($query_conflitto);
if (!empty($conflitto)) {
@ -96,47 +96,44 @@ if (empty($elenco_conflitti)) {
}
echo '
<div class="card card-danger">
<div class="card-header">
<h3 class="card-title">'.tr('⚠️ Sono presenti dei conflitti con le sessioni di lavoro di alcuni tecnici').'</h3>
</div>
<div class="card-body">
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>'.tr('Tecnico').'</th>
<th>'.tr('Attività').'</th>
<th>'.tr('Orario di conflitto').'</th>
</tr>
</thead>
<div class="alert alert-warning">
<p>'.tr('Sono presenti dei conflitti con le sessioni di lavoro di alcuni tecnici').'.</p>
<tbody>';
<table class="table table-condensed">
<thead>
<tr>
<th>'.tr('Tecnico').'</th>
<th>'.tr('Attività').'</th>
<th>'.tr('Orario di conflitto').'</th>
</tr>
</thead>
<tbody>';
foreach ($elenco_conflitti as $id_tecnico => $elenco_conflitti_tecnico) {
$anagrafica_tecnico = $database->fetchOne('SELECT ragione_sociale, deleted_at FROM an_anagrafiche WHERE idanagrafica = '.prepare($id_tecnico));
foreach ($elenco_conflitti_tecnico as $conflitto) {
echo '
<tr>
<td>'.$anagrafica_tecnico['ragione_sociale'].' '.(!empty($anagrafica_tecnico['deleted_at']) ? '<small class="text-danger">('.tr('Eliminato').')' : '').'</td>
<td>Attività corrente</td>
<td>'.timestampFormat($conflitto['inizio']).' - '.timestampFormat($conflitto['fine']).'</td>
</tr>';
<tr>
<td>'.$anagrafica_tecnico['ragione_sociale'].' '.(!empty($anagrafica_tecnico['deleted_at']) ? '<small class="text-danger">('.tr('Eliminato').')' : '').'</td>
<td></td>
<td>'.timestampFormat($conflitto['inizio']).' - '.timestampFormat($conflitto['fine']).'</td>
</tr>';
foreach ($conflitto['conflitti'] as $conflitto_intervento) {
$intervento = Intervento::find($conflitto_intervento['idintervento']);
echo '
<tr>
<td>'.$anagrafica_tecnico['ragione_sociale'].' '.(!empty($anagrafica_tecnico['deleted_at']) ? '<small class="text-danger">('.tr('Eliminato').')' : '').'</td>
<td>'.Modules::link('Interventi', $intervento->id, $intervento->getReference()).'</td>
<td>'.timestampFormat($conflitto_intervento['orario_inizio']).' - '.timestampFormat($conflitto_intervento['orario_fine']).'</td>
</tr>';
<tr>
<td>'.$anagrafica_tecnico['ragione_sociale'].' '.(!empty($anagrafica_tecnico['deleted_at']) ? '<small class="text-danger">('.tr('Eliminato').')' : '').'</td>
<td>'.Modules::link('Interventi', $intervento->id, $intervento->getReference()).'</td>
<td>'.timestampFormat($conflitto_intervento['orario_inizio']).' - '.timestampFormat($conflitto_intervento['orario_fine']).'</td>
</tr>';
}
}
}
echo '
</tbody>
</table>
</div>
</tbody>
</table>
</div>';

View File

@ -60,7 +60,7 @@ foreach ($articoli as $elenco) {
LEFT JOIN `or_statiordine_lang` ON (`or_statiordine`.`id` = `or_statiordine_lang`.`id_record` AND `or_statiordine_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).")
INNER JOIN `or_tipiordine` ON `or_tipiordine`.`id` = `or_ordini`.`idtipoordine`
WHERE
`or_statiordine_lang`.`title` = 'Bozza'
`or_statiordine`.`title` = 'Bozza'
AND `dir` = 'entrata'
AND `confermato` = 1
AND `idarticolo`=".prepare($articolo->id).'

View File

@ -20,5 +20,5 @@
include_once __DIR__.'/../../core.php';
if (!empty($id_record)) {
$record = $dbo->fetchOne('SELECT *, `co_staticontratti`.`is_pianificabile` AS is_pianificabile FROM `co_contratti` INNER JOIN `co_staticontratti` ON `co_contratti`.`idstato` = `co_staticontratti`.`id` WHERE `co_contratti`.`id`='.prepare($id_record));
$record = $dbo->fetchOne('SELECT *, `co_staticontratti`.`is_pianificabile` AS is_pianificabile FROM `co_contratti` INNER JOIN `co_stationtratti` ON `co_contratti`.`idstato` = `co_staticontratti`.`id` WHERE `co_contratti`.`id`='.prepare($id_record));
}