Skip to content

Commit 65da43b

Browse files
committed
feat: aggiunta sessioni tecnici multiple
1 parent 3a8c339 commit 65da43b

2 files changed

Lines changed: 238 additions & 27 deletions

File tree

modules/interventi/actions.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,24 +323,66 @@
323323

324324
// Collegamenti tecnici/interventi
325325
if (!empty(post('orario_inizio')) && !empty(post('orario_fine'))) {
326-
$idtecnici = post('idtecnico') ?: null;
327-
foreach ($idtecnici as $idtecnico) {
326+
$idtecnico = post('idtecnico');
327+
if (!empty($idtecnico)) {
328328
add_tecnico($id_record, $idtecnico, post('orario_inizio'), post('orario_fine'), $idcontratto);
329+
330+
OperationLog::setInfo('id_module', $id_module);
331+
OperationLog::setInfo('id_plugin', $id_plugin);
332+
OperationLog::setInfo('id_record', $id_record);
333+
OperationLog::setInfo('level', 'info');
334+
OperationLog::build('add_sessione');
329335
}
336+
}
330337

331-
OperationLog::setInfo('id_module', $id_module);
332-
OperationLog::setInfo('id_plugin', $id_plugin);
333-
OperationLog::setInfo('id_record', $id_record);
334-
OperationLog::setInfo('level', 'info');
335-
OperationLog::build('add_sessione');
338+
// Gestione sessioni aggiuntive
339+
$sessioni_aggiuntive = post('sessioni');
340+
if (!empty($sessioni_aggiuntive) && is_array($sessioni_aggiuntive)) {
341+
foreach ($sessioni_aggiuntive as $sessione) {
342+
if (!empty($sessione['orario_inizio']) && !empty($sessione['orario_fine']) && !empty($sessione['idtecnico'])) {
343+
// Crea la sessione manualmente per poter specificare un tipo attività diverso
344+
$intervento = Modules\Interventi\Intervento::find($id_record);
345+
$anagrafica = Modules\Anagrafiche\Anagrafica::find($sessione['idtecnico']);
346+
347+
$sessione_obj = new Modules\Interventi\Components\Sessione();
348+
$sessione_obj->document()->associate($intervento);
349+
$sessione_obj->anagrafica()->associate($anagrafica);
350+
351+
// Usa il tipo attività specificato per questa sessione, o quello dell'intervento come fallback
352+
$tipo_sessione_id = !empty($sessione['idtipointervento']) ? $sessione['idtipointervento'] : $idtipointervento;
353+
$tipo_sessione = Modules\TipiIntervento\Tipo::find($tipo_sessione_id);
354+
$sessione_obj->tipo()->associate($tipo_sessione);
355+
356+
$sessione_obj->orario_inizio = $sessione['orario_inizio'];
357+
$sessione_obj->orario_fine = $sessione['orario_fine'];
358+
359+
// Calcola i km se necessario
360+
if ($tipo_sessione->calcola_km) {
361+
if (!empty($intervento['idsede_destinazione'])) {
362+
$sede = $dbo->fetchOne('SELECT km FROM an_sedi WHERE id = '.prepare($intervento['idsede_destinazione']));
363+
$km = $sede['km'];
364+
} else {
365+
$km = $intervento->anagrafica->sedeLegale->km;
366+
}
367+
$sessione_obj->km = empty($km) ? 0 : $km;
368+
}
369+
370+
$sessione_obj->tipo_sconto = (setting('Tipo di sconto predefinito') == '%' ? 'PRC' : 'UNT');
371+
$sessione_obj->tipo_scontokm = (setting('Tipo di sconto predefinito') == '%' ? 'PRC' : 'UNT');
372+
373+
$sessione_obj->save();
374+
$sessione_obj->setTipo($tipo_sessione_id, true);
375+
$sessione_obj->save();
376+
}
377+
}
336378
}
337379

338380
// Assegnazione dei tecnici all'intervento
339381
$tecnici_assegnati = post('tecnici_assegnati');
340382
if (!empty($tecnici_assegnati)) {
341383
// Converte in array se necessario e filtra i valori vuoti
342384
$tecnici_assegnati = is_array($tecnici_assegnati) ? $tecnici_assegnati : [$tecnici_assegnati];
343-
$tecnici_assegnati = array_filter($tecnici_assegnati, fn ($value) => !empty($value) && is_numeric($value));
385+
$tecnici_assegnati = array_filter($tecnici_assegnati, function($value) { return !empty($value) && is_numeric($value); });
344386
$tecnici_assegnati = array_unique($tecnici_assegnati);
345387

346388
if (!empty($tecnici_assegnati)) {
@@ -538,7 +580,7 @@
538580
// Assegnazione dei tecnici all'intervento
539581
$tecnici_assegnati = (array) post('tecnici_assegnati');
540582
// Filtra i valori vuoti per evitare errori di foreign key
541-
$tecnici_assegnati = array_filter($tecnici_assegnati, fn ($value) => !empty($value) && is_numeric($value));
583+
$tecnici_assegnati = array_filter($tecnici_assegnati, function($value) { return !empty($value) && is_numeric($value); });
542584

543585
if (!empty($tecnici_assegnati)) {
544586
$dbo->sync('in_interventi_tecnici_assegnati', [

modules/interventi/add.php

Lines changed: 187 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@
146146
<input type="hidden" name="backto" value="record-edit">
147147
148148
<!-- Fix creazione da Anagrafica -->
149-
<input type="hidden" name="id_record" value="0">';
149+
<input type="hidden" name="id_record" value="0">
150+
<input type="hidden" name="idzona" id="idzona_hidden" value="'.$id_zona.'">';
150151

151152
if (!empty($id_promemoria_contratto)) {
152153
echo '<input type="hidden" name="idcontratto_riga" value="'.$id_promemoria_contratto.'">';
@@ -339,6 +340,10 @@
339340
340341
<h5 class="text-primary border-bottom pb-2 mb-4"><i class="fa fa-clock-o"></i> '.tr('Sessioni di lavoro').'</h5>
341342
<div class="row">
343+
<div class="col-md-4">
344+
{[ "type": "select", "label": "'.tr('Tipo attività').'", "name": "idtipointervento", "value": "'.$id_tipo.'", "ajax-source": "tipiintervento", "help": "'.tr('Seleziona il tipo di attività per calcolare automaticamente la durata prevista').'." ]}
345+
</div>
346+
342347
<div class="col-md-2">
343348
{[ "type": "timestamp", "label": "'.tr('Inizio attività').'", "name": "orario_inizio", "required": '.($origine_dashboard ? 1 : 0).', "value": "'.$inizio_sessione.'" ]}
344349
</div>
@@ -348,11 +353,22 @@
348353
</div>
349354
350355
<div class="col-md-4">
351-
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "values": "query=SELECT id, CONCAT_WS(\' - \', nome, descrizione) AS descrizione FROM an_zone ORDER BY nome", "placeholder": "'.tr('Nessuna zona').'", "help": "'.tr('La zona viene definita automaticamente in base al cliente selezionato').'.", "readonly": "1", "value": "'.$id_zona.'" ]}
356+
{[ "type": "select", "label": "'.tr('Tecnico').'", "name": "idtecnico", "required": '.($origine_dashboard ? 1 : 0).', "ajax-source": "tecnici", "value": "'.$id_tecnico.'", "icon-after": "add|'.$id_modulo_anagrafiche.'|tipoanagrafica=Tecnico&readonly_tipo=1||'.(empty($id_tecnico) ? '' : 'disabled').'" ]}
352357
</div>
358+
</div>
353359
360+
<div id="sessioni-aggiuntive"></div>
361+
362+
<div class="row mt-3">
363+
<div class="col-md-8">
364+
<div class="alert alert-info">
365+
<i class="fa fa-info-circle"></i> '.tr('Al clic su "Aggiungi sessione", verrà creata una nuova sessione che inizierà automaticamente alla fine della sessione precedente, utilizzando la durata prevista dal tipo di attività selezionato.').'
366+
</div>
367+
</div>
354368
<div class="col-md-4">
355-
{[ "type": "select", "label": "'.tr('Tecnici').'", "multiple": "1", "name": "idtecnico[]", "required": '.($origine_dashboard ? 1 : 0).', "ajax-source": "tecnici", "value": "'.$id_tecnico.'", "icon-after": "add|'.$id_modulo_anagrafiche.'|tipoanagrafica=Tecnico&readonly_tipo=1||'.(empty($id_tecnico) ? '' : 'disabled').'" ]}
369+
<button type="button" class="btn btn-success btn-block" onclick="aggiungiNuovaSessione()">
370+
<i class="fa fa-plus"></i> '.tr('Aggiungi sessione').'
371+
</button>
356372
</div>
357373
</div>
358374
@@ -424,7 +440,6 @@
424440
input("componenti").disable();
425441
input("idanagrafica").disable();
426442
input("idclientefinale").disable();
427-
input("idzona").disable();
428443
input("idtipointervento").disable();
429444
input("idstatointervento").disable();
430445
input("data_richiesta").disable();
@@ -439,7 +454,6 @@
439454
$(document).ready(function() {
440455
input("idanagrafica").disable();
441456
input("idclientefinale").disable();
442-
input("idzona").disable();
443457
input("idtipointervento").disable();
444458
});
445459
</script>';
@@ -563,7 +577,7 @@ function() {
563577
564578
let data = anagrafica.getData();
565579
if (data) {
566-
input("idzona").set(data.idzona ? data.idzona : "");
580+
$("#idzona_hidden").val(data.idzona ? data.idzona : "");
567581
// session_set("superselect,idzona", $(this).selectData().idzona, 0);
568582
569583
// Impostazione del tipo intervento da anagrafica
@@ -632,7 +646,7 @@ function() {
632646
633647
let data = sede.getData();
634648
if (data) {
635-
input("idzona").set(data.idzona ? data.idzona : "");
649+
$("#idzona_hidden").val(data.idzona ? data.idzona : "");
636650
// session_set("superselect,idzona", $(this).selectData().idzona, 0);
637651
638652
caricaMappa(data.lat, data.lng);
@@ -707,9 +721,24 @@ function() {
707721
let data = $("#idtipointervento").selectData();
708722
if (data && data.tempo_standard > 0) {
709723
let orario_inizio = input("orario_inizio").get();
710-
let tempo_standard = data.tempo_standard * 60;
711-
let nuovo_orario_fine = moment(orario_inizio, "DD/MM/YYYY HH:mm").add(tempo_standard, "m").format("DD/MM/YYYY HH:mm");
712-
input("orario_fine").set(nuovo_orario_fine);
724+
if (orario_inizio) {
725+
let tempo_standard = data.tempo_standard * 60;
726+
let nuovo_orario_fine = moment(orario_inizio, "DD/MM/YYYY HH:mm").add(tempo_standard, "m").format("DD/MM/YYYY HH:mm");
727+
input("orario_fine").set(nuovo_orario_fine);
728+
}
729+
}
730+
});
731+
732+
// Automatismo per calcolare orario di fine quando cambia l\'orario di inizio
733+
input("orario_inizio").change(function() {
734+
let data = $("#idtipointervento").selectData();
735+
if (data && data.tempo_standard > 0) {
736+
let orario_inizio = input("orario_inizio").get();
737+
if (orario_inizio) {
738+
let tempo_standard = data.tempo_standard * 60;
739+
let nuovo_orario_fine = moment(orario_inizio, "DD/MM/YYYY HH:mm").add(tempo_standard, "m").format("DD/MM/YYYY HH:mm");
740+
input("orario_fine").set(nuovo_orario_fine);
741+
}
713742
}
714743
});';
715744

@@ -793,14 +822,18 @@ function() {
793822
}
794823
795824
function calcolaConflittiTecnici() {
796-
let tecnici = input("idtecnico").get();
797-
798-
return $("#info-conflitti-add").load("'.$module->fileurl('occupazione_tecnici.php').'", {
799-
"id_module": globals.id_module,
800-
"tecnici[]": tecnici,
801-
"inizio": input("orario_inizio").get(),
802-
"fine": input("orario_fine").get(),
803-
});
825+
let tecnico = input("idtecnico").get();
826+
827+
if (tecnico) {
828+
return $("#info-conflitti-add").load("'.$module->fileurl('occupazione_tecnici.php').'", {
829+
"id_module": globals.id_module,
830+
"tecnici[]": [tecnico],
831+
"inizio": input("orario_inizio").get(),
832+
"fine": input("orario_fine").get(),
833+
});
834+
} else {
835+
$("#info-conflitti-add").html("");
836+
}
804837
}
805838
806839
function assegnaTuttiTecnici() {
@@ -823,6 +856,142 @@ function deassegnaTuttiTecnici() {
823856
input("tecnici_assegnati").getElement().selectReset();
824857
}
825858
859+
var sessioneCounter = 1;
860+
function aggiungiNuovaSessione() {
861+
sessioneCounter++;
862+
863+
// Calcola l\'orario di inizio della nuova sessione (fine dell\'ultima sessione)
864+
let ultimoOrarioFine = calcolaUltimoOrarioFine();
865+
866+
let nuovoOrarioFine = ""; // Sarà calcolato quando si seleziona il tipo attività
867+
868+
// Crea il HTML per la nuova sessione con le classi corrette
869+
let sessioneHtml = `
870+
<div class="row mt-3" id="sessione-${sessioneCounter}">
871+
<div class="col-md-4">
872+
{[ "type": "select", "label": "'.tr('Tipo attività').'", "name": "sessioni[${sessioneCounter}][idtipointervento]", "ajax-source": "tipiintervento", "extra": "onchange=\\"calcolaOrarioFineSessione(${sessioneCounter})\\"" ]}
873+
</div>
874+
<div class="col-md-2">
875+
{[ "type": "timestamp", "label": "'.tr('Inizio attività').'", "name": "sessioni[${sessioneCounter}][orario_inizio]", "value": "", "class": "text-center", "extra": "onchange=\\"calcolaOrarioFineSessione(${sessioneCounter})\\"" ]}
876+
</div>
877+
<div class="col-md-2">
878+
{[ "type": "timestamp", "label": "'.tr('Fine attività').'", "name": "sessioni[${sessioneCounter}][orario_fine]", "value": "${nuovoOrarioFine}", "class": "text-center" ]}
879+
</div>
880+
<div class="col-md-3">
881+
{[ "type": "select", "label": "'.tr('Tecnico').'", "name": "sessioni[${sessioneCounter}][idtecnico]", "ajax-source": "tecnici", "icon-after": "add|'.$id_modulo_anagrafiche.'|tipoanagrafica=Tecnico&readonly_tipo=1" ]}
882+
</div>
883+
<div class="col-md-1">
884+
<button type="button" class="btn btn-danger btn-block" onclick="rimuoviSessione(${sessioneCounter})" style="margin-top: 27px;">
885+
<i class="fa fa-trash"></i> '.tr('Elimina').'
886+
</button>
887+
</div>
888+
</div>
889+
`;
890+
891+
$("#sessioni-aggiuntive").append(sessioneHtml);
892+
893+
// Reinizializza i componenti della nuova sessione
894+
init();
895+
896+
// Aggiungi gli eventi specifici per il calcolo automatico e sistema lo styling
897+
setTimeout(function() {
898+
let sessioneSelector = `#sessione-${sessioneCounter}`;
899+
let tipoSelect = $(`${sessioneSelector} select[name="sessioni[${sessioneCounter}][idtipointervento]"]`);
900+
let inizioInput = $(`${sessioneSelector} input[name="sessioni[${sessioneCounter}][orario_inizio]"]`);
901+
902+
// Imposta il valore dell\'orario di inizio dopo l\'inizializzazione
903+
if (inizioInput.length > 0) {
904+
inizioInput.val(ultimoOrarioFine);
905+
inizioInput.trigger("change");
906+
}
907+
908+
// Collega gli eventi con selettori più specifici
909+
if (tipoSelect.length > 0) {
910+
tipoSelect.on("change", function() {
911+
calcolaOrarioFineSessione(sessioneCounter);
912+
});
913+
}
914+
915+
if (inizioInput.length > 0) {
916+
inizioInput.on("dp.change change", function() {
917+
calcolaOrarioFineSessione(sessioneCounter);
918+
});
919+
}
920+
921+
// Sistema lo styling dei componenti
922+
$(`${sessioneSelector} .select2-container`).css("width", "100%");
923+
$(`${sessioneSelector} .timestamp-picker`).css("text-align", "center");
924+
}, 1000);
925+
}
926+
927+
function rimuoviSessione(id) {
928+
$("#sessione-" + id).remove();
929+
930+
// Aggiorna gli orari delle sessioni rimanenti se necessario
931+
aggiornaOrariSessioni();
932+
}
933+
934+
function calcolaOrarioFineSessione(sessioneId) {
935+
let tipoSelect = $(`select[name="sessioni[${sessioneId}][idtipointervento]"]`);
936+
let inizioInput = $(`input[name="sessioni[${sessioneId}][orario_inizio]"]`);
937+
let fineInput = $(`input[name="sessioni[${sessioneId}][orario_fine]"]`);
938+
939+
let tipoId = tipoSelect.val();
940+
let orarioInizio = inizioInput.val();
941+
942+
if (tipoId && orarioInizio) {
943+
// Ottieni i dati del tipo attività selezionato
944+
$.ajax({
945+
url: "'.base_path().'/ajax_select.php",
946+
type: "GET",
947+
dataType: "json",
948+
data: {
949+
op: "tipiintervento",
950+
search: "",
951+
id: tipoId
952+
},
953+
success: function(response) {
954+
if (response && response.results && response.results.length > 0) {
955+
// Trova l\'elemento con l\'ID corrispondente
956+
let tipoData = response.results.find(item => item.id == tipoId);
957+
958+
if (tipoData && tipoData.tempo_standard && tipoData.tempo_standard > 0) {
959+
let tempoStandard = parseFloat(tipoData.tempo_standard) * 60; // Converti ore in minuti
960+
let nuovoOrarioFine = moment(orarioInizio, "DD/MM/YYYY HH:mm").add(tempoStandard, "m").format("DD/MM/YYYY HH:mm");
961+
962+
fineInput.val(nuovoOrarioFine);
963+
fineInput.trigger("change");
964+
fineInput.trigger("dp.change");
965+
}
966+
}
967+
},
968+
error: function(xhr, status, error) {
969+
// Gestione errori silenziosa
970+
}
971+
});
972+
}
973+
}
974+
975+
function calcolaUltimoOrarioFine() {
976+
// Inizia con l\'orario di fine della prima sessione
977+
let ultimoOrario = input("orario_fine").get();
978+
979+
// Se non c\'è un orario di fine nella prima sessione, usa l\'orario corrente
980+
if (!ultimoOrario) {
981+
ultimoOrario = moment().format("DD/MM/YYYY HH:mm");
982+
}
983+
984+
// Controlla tutte le sessioni aggiuntive
985+
$("#sessioni-aggiuntive input[name*=\'orario_fine\']").each(function() {
986+
let orario = $(this).val();
987+
if (orario && moment(orario, "DD/MM/YYYY HH:mm").isAfter(moment(ultimoOrario, "DD/MM/YYYY HH:mm"))) {
988+
ultimoOrario = orario;
989+
}
990+
});
991+
992+
return ultimoOrario;
993+
}
994+
826995
// Gestione ricorrenza
827996
$("#ricorsiva_add").on("change", function(){
828997
if ($(this).is(":checked")) {

0 commit comments

Comments
 (0)