Skip to content
Open
83 changes: 83 additions & 0 deletions modules/interventi/ajax_automezzo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

include_once __DIR__.'/../../core.php';

header('Content-Type: application/json');

$op = post('op');

if ($op === 'default') {
$id_tecnico = post('id_tecnico');

$automezzi = database()->table('zz_user_sedi')
->join('zz_users', 'zz_user_sedi.id_user', '=', 'zz_users.id')
->join('an_sedi', 'zz_user_sedi.id_sede', '=', 'an_sedi.id')
->where('zz_users.id_anagrafica', $id_tecnico)
->where('an_sedi.is_automezzo', 1)
->distinct()
->limit(2)
->pluck('an_sedi.id')
->toArray();

echo json_encode([
'id_automezzo' => count($automezzi) === 1 ? reset($automezzi) : null,
]);
exit;
}

if ($op === 'set') {
$id_sessione = post('id_sessione');
$id_record = post('id_record');
$id_automezzo = post('id_automezzo') ?: null;

if (!is_numeric($id_sessione) || !is_numeric($id_record) || (!empty($id_automezzo) && !is_numeric($id_automezzo))) {
http_response_code(422);
echo json_encode(['error' => tr('Parametri non validi')]);
exit;
}

$sessione = database()->table('in_interventi_tecnici')
->where('id', (int) $id_sessione)
->where('id_intervento', (int) $id_record)
->first();

if (empty($sessione)) {
http_response_code(404);
echo json_encode(['error' => tr('Sessione non trovata')]);
exit;
}

if (!empty($id_automezzo)) {
$automezzo = database()->table('an_sedi')
->where('id', (int) $id_automezzo)
->where('is_automezzo', 1)
->first();

if (empty($automezzo)) {
http_response_code(422);
echo json_encode(['error' => tr('Automezzo non valido')]);
exit;
}
}

database()->table('in_interventi_tecnici')
->where('id', (int) $id_sessione)
->where('id_intervento', (int) $id_record)
->update(['id_automezzo' => empty($id_automezzo) ? null : (int) $id_automezzo]);

echo json_encode(['success' => true]);
exit;
}

http_response_code(400);
echo json_encode(['error' => tr('Operazione non valida')]);
60 changes: 48 additions & 12 deletions modules/interventi/modals/manage_sessione.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_sessione" value="'.$sessione['id'].'">';

// Tecnico
// Tecnico, tipo attività e automezzo
echo '
<div class="row">
<div class="col-md-4">
Expand All @@ -51,6 +51,10 @@
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Tipo attività').'", "name": "id_tipo_interventot", "value": "'.$sessione['id_tipo_intervento'].'", "required": 1, "ajax-source": "tipiintervento-tecnico", "select-options": '.json_encode(['id_tecnico' => $sessione['id_tecnico'], 'id_intervento' => $id_record, 'id_anagrafica' => $intervento['id_anagrafica'], 'id_contratto' => $intervento['id_contratto']]).' ]}
</div>

<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Automezzo').'", "name": "id_automezzo", "value": "'.$sessione['id_automezzo'].'", "values": "query=SELECT `id`, `nome_sede` AS descrizione FROM `an_sedi` WHERE `is_automezzo` = 1 ORDER BY `nome_sede`" ]}
</div>
</div>';

$class = $show_prezzi ? '' : 'hide';
Expand Down Expand Up @@ -134,11 +138,12 @@
}
});

// Quando cambio il tecnico, aggiorno le select-options del tipo attività
// Quando cambio il tecnico, aggiorno tipo attività e propongo l\'automezzo assegnato.
$("#id_tecnico").change(function() {
var id_tecnico = $(this).val();

if (!id_tecnico) {
$("#id_automezzo").val(null).trigger("change");
return;
}

Expand All @@ -148,6 +153,19 @@

// Resetto e ricarico il select dei tipi di intervento
$("#id_tipo_interventot").selectReset();

$.ajax({
url: globals.rootdir + "/modules/interventi/ajax_automezzo.php",
type: "POST",
dataType: "json",
data: {
op: "default",
id_tecnico: id_tecnico,
},
success: function(response) {
$("#id_automezzo").val(response.id_automezzo || null).trigger("change");
}
});
});

// Quando cambio il tipo di intervento, aggiorno i prezzi
Expand All @@ -162,14 +180,21 @@
});
});

function chiudiSalvataggioSessione() {
renderMessages();
$("#modals > div").modal("hide");
caricaCosti();
caricaTecnici();
}

function salvaSessione() {
// Validazione del form
var valid = $("#add_form").parsley().validate();
if (!valid) {
return false;
}

// Invio dei dati via AJAX
// Invio dei dati standard della sessione via AJAX
$("#add_form").ajaxSubmit({
url: globals.rootdir + "/actions.php",
data: {
Expand All @@ -179,17 +204,28 @@ function salvaSessione() {
},
type: "post",
success: function(response) {
renderMessages();

// Chiusura del modale
$("#modals > div").modal("hide");

// Ricaricamento dei costi
caricaCosti();
caricaTecnici();
// Salvataggio dell\'automezzo separato per mantenere la modifica poco invasiva sul core Interventi.
$.ajax({
url: globals.rootdir + "/modules/interventi/ajax_automezzo.php",
type: "POST",
dataType: "json",
data: {
op: "set",
id_sessione: '.$sessione['id'].',
id_record: globals.id_record,
id_automezzo: $("#id_automezzo").val(),
},
success: function() {
chiudiSalvataggioSessione();
},
error: function(xhr) {
var response = xhr.responseJSON || {};
Swal.fire("'.tr('Errore').'", response.error || "'.tr('Errore durante il salvataggio dell’automezzo').'", "error");
}
});
},
error: function() {
alert("'.tr('Errore durante il salvataggio').'");
Swal.fire("'.tr('Errore').'", "'.tr('Errore durante il salvataggio della sessione').'", "error");
}
});
}
Expand Down
32 changes: 32 additions & 0 deletions modules/interventi/src/Components/Sessione.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public static function build(?Intervento $intervento = null, ?Anagrafica $anagra

$model->document()->associate($intervento);
$model->anagrafica()->associate($anagrafica);
$model->setAutomezzoPredefinito();

$id_tipo = $intervento['id_tipo_intervento'];
$tipo_sessione = TipoSessione::find($id_tipo);
Expand Down Expand Up @@ -148,12 +149,38 @@ public function setTecnico($id_tecnico)
$anagrafica = Anagrafica::find($id_tecnico);
$this->anagrafica()->associate($anagrafica);

if ($previous != $id_tecnico) {
$this->setAutomezzoPredefinito(true);
}

// Se il tecnico è cambiato, ricarico le tariffe per il tipo di intervento corrente
if ($previous != $id_tecnico && !empty($this->id_tipo_intervento)) {
$this->setTipo($this->id_tipo_intervento, false);
}
}

/**
* Propone automaticamente l'automezzo quando il tecnico ha un solo mezzo assegnato.
* In presenza di zero o più automezzi la scelta rimane manuale.
*/
public function setAutomezzoPredefinito($force = false)
{
if (!$force && !empty($this->id_automezzo)) {
return;
}

$automezzi = database()->table('zz_user_sedi')
->join('zz_users', 'zz_user_sedi.id_user', '=', 'zz_users.id')
->join('an_sedi', 'zz_user_sedi.id_sede', '=', 'an_sedi.id')
->where('zz_users.id_anagrafica', $this->id_tecnico)
->where('an_sedi.is_automezzo', 1)
->distinct()
->pluck('an_sedi.id')
->toArray();

$this->id_automezzo = count($automezzi) === 1 ? reset($automezzi) : null;
}

public function getOreCalcolateAttribute()
{
$inizio = new \DateTime($this->orario_inizio);
Expand Down Expand Up @@ -198,6 +225,11 @@ public function anagrafica()
return $this->belongsTo(Anagrafica::class, 'id_tecnico');
}

public function automezzo()
{
return $this->belongsTo(Sede::class, 'id_automezzo');
}

public function tipo()
{
return $this->belongsTo(TipoSessione::class, 'id_tipo_intervento');
Expand Down
5 changes: 5 additions & 0 deletions update/2_12.sql
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,8 @@ INSERT INTO `zz_settings` (`nome`, `valore`, `tipo`, `editable`, `sezione`, `ord
INSERT INTO `zz_settings_lang` (`id_lang`, `id_record`, `title`, `help`) VALUES
(1, (SELECT `id` FROM `zz_settings` WHERE `nome` = 'Tipologia anagrafica predefinita'), 'Tipologia anagrafica predefinita', 'Tipologia (Azienda, Ente pubblico o Privato) preselezionata automaticamente nella finestra di aggiunta di una nuova anagrafica. Se non impostata, nessuna tipologia viene preselezionata.'),
(2, (SELECT `id` FROM `zz_settings` WHERE `nome` = 'Tipologia anagrafica predefinita'), 'Default entity classification', 'Classification (Company, Public entity or Private) automatically preselected in the new entity creation window. If not set, no classification is preselected.');

-- Associazione automezzo alle singole sessioni delle attività (#1693)
ALTER TABLE `in_interventi_tecnici`
ADD `id_automezzo` INT NULL AFTER `id_tecnico`,
ADD INDEX `idx_in_interventi_tecnici_automezzo` (`id_automezzo`);