. */ namespace Modules\Interventi\Components; use Common\SimpleModelTrait; use DateTime; use Illuminate\Database\Eloquent\Model; use InvalidArgumentException; use Modules\Anagrafiche\Anagrafica; use Modules\Interventi\Intervento; /* * Notazione: i costi sono rivolti all'azienda, i prezzi al cliente. * * @since 2.4.9 */ use Modules\Iva\Aliquota; use Modules\TipiIntervento\Tipo as TipoSessione; class Sessione extends Model { use SimpleModelTrait; use RelationTrait; protected $table = 'in_interventi_tecnici'; protected $aliquota_iva = null; /** * Crea un nuova sessione collegata ad un intervento. * * @param string $inizio * @param string $fine * * @return self */ public static function build(Intervento $intervento, Anagrafica $anagrafica, $inizio, $fine) { if (!$anagrafica->isTipo('Tecnico')) { throw new InvalidArgumentException('Anagrafica di tipo diverso da Tecnico'); } $model = new static(); $model->document()->associate($intervento); $model->anagrafica()->associate($anagrafica); $id_tipo = $intervento['idtipointervento']; $tipo_sessione = TipoSessione::find($id_tipo); $model->tipo()->associate($tipo_sessione); $model->orario_inizio = $inizio; $model->orario_fine = $fine; // Sede secondaria if (!empty($intervento['idsede_destinazione'])) { $sede = database()->fetchOne('SELECT km FROM an_sedi WHERE id = '.prepare($intervento['idsede_destinazione'])); $km = $sede['km']; } // Sede legale dell'anagrafica else { $km = $intervento->anagrafica->sedeLegale->km; } $model->km = empty($km) ? 0 : $km; $model->save(); $model->setTipo($id_tipo, true); $model->save(); return $model; } public function setTipo($id_tipo, $reset = false) { $previous = $this->idtipointervento; $tipo_sessione = TipoSessione::find($id_tipo); $this->tipo()->associate($tipo_sessione); if ($previous != $id_tipo || $reset) { $tariffa = $this->getTariffa($id_tipo); // Azzeramento forzato del diritto di chiamata nel caso la sessione non sia la prima dell'intervento nel giorno di inizio o fine $sessioni = database()->fetchArray('SELECT id FROM in_interventi_tecnici WHERE (DATE(orario_inizio) = DATE('.prepare($this->orario_inizio).') OR DATE(orario_fine) = DATE('.prepare($this->orario_fine).')) AND (prezzo_dirittochiamata != 0 OR prezzo_dirittochiamata_tecnico != 0) AND id != '.prepare($this->id).' AND idintervento = '.prepare($this->intervento->id)); if (!empty($sessioni)) { $tariffa['costo_dirittochiamata_tecnico'] = 0; $tariffa['costo_dirittochiamata'] = 0; // Fix se reset non attivo $this->prezzo_dirittochiamata = $tariffa['costo_dirittochiamata']; } // Modifica dei costi $this->prezzo_ore_unitario_tecnico = $tariffa['costo_ore_tecnico']; $this->prezzo_km_unitario_tecnico = $tariffa['costo_km_tecnico']; $this->prezzo_dirittochiamata_tecnico = $tariffa['costo_dirittochiamata_tecnico']; // Modifica dei prezzi if ($reset) { $this->prezzo_ore_unitario = $tariffa['costo_ore']; $this->prezzo_km_unitario = $tariffa['costo_km']; $this->prezzo_dirittochiamata = $tariffa['costo_dirittochiamata']; } } } public function getOreAttribute() { $inizio = new DateTime($this->orario_inizio); $diff = $inizio->diff(new DateTime($this->orario_fine)); $ore = $diff->i / 60 + $diff->h + ($diff->days * 24); return $ore; } /** * Salva la sessione, impostando i campi dipendenti dai singoli parametri. * * @return bool */ public function save(array $options = []) { $this->attributes['ore'] = $this->ore; $this->attributes['prezzo_ore_consuntivo'] = $this->prezzo_manodopera + $this->prezzo_diritto_chiamata; $this->attributes['prezzo_km_consuntivo'] = $this->prezzo_viaggio; $this->attributes['prezzo_ore_consuntivo_tecnico'] = $this->costo_manodopera + $this->costo_diritto_chiamata; $this->attributes['prezzo_km_consuntivo_tecnico'] = $this->costo_viaggio; $this->attributes['sconto'] = $this->sconto_totale_manodopera; $this->attributes['scontokm'] = $this->sconto_totale_viaggio; return parent::save($options); } public function getDocumentID() { return 'idintervento'; } // Relazioni Eloquent public function anagrafica() { return $this->belongsTo(Anagrafica::class, 'idtecnico'); } public function tipo() { return $this->belongsTo(TipoSessione::class, 'idtipointervento'); } public function parent() { return $this->belongsTo(Intervento::class, $this->getDocumentID()); } // Costi per l'azienda /** * Restituisce il costo orario (per l'azienda) per la sessione del tecnico. * * @return float */ public function getCostoOrarioAttribute() { return $this->attributes['prezzo_ore_unitario_tecnico']; } /** * Restituisce il costo del diritto di chiamata (per l'azienda) per la sessione del tecnico. * * @return float */ public function getCostoDirittoChiamataAttribute() { return $this->attributes['prezzo_dirittochiamata_tecnico']; } /** * Restituisce il costo chilometrico (per l'azienda) del viaggio del tecnico. * * @return float */ public function getCostoChilometricoAttribute() { return $this->attributes['prezzo_km_unitario_tecnico']; } /** * Restituisce il costo totale della manodopera escluso il diritto di chiamata (per l'azienda) per la sessione del tecnico. * * @return float */ public function getCostoManodoperaAttribute() { return $this->costo_orario * $this->ore; } /** * Restituisce il costo totale (per l'azienda) del viaggio del tecnico. * * @return float */ public function getCostoViaggioAttribute() { return $this->costo_chilometrico * $this->km; } // Prezzi per il cliente /** * Restituisce il prezzo del diritto di chiamata (per il cliente) per la sessione del tecnico. * * @return float */ public function getPrezzoDirittoChiamataAttribute() { return $this->attributes['prezzo_dirittochiamata']; } /** * Restituisce il prezzo del diritto di chiamata (per il cliente) per la sessione del tecnico. * * @return float */ public function getPrezzoChilometricoAttribute() { return $this->attributes['prezzo_km_unitario']; } /** * Restituisce il prezzo del diritto di chiamata (per il cliente) per la sessione del tecnico. * * @return float */ public function getPrezzoOrarioAttribute() { return $this->attributes['prezzo_ore_unitario']; } /** * Restituisce il prezzo totale della manodopera escluso il diritto di chiamata (per il cliente) per la sessione del tecnico. * * @return float */ public function getPrezzoManodoperaAttribute() { return $this->prezzo_orario * $this->ore; } /** * Restituisce lo sconto totale km in euro. * * @return float */ public function getScontoTotaleManodoperaAttribute() { return calcola_sconto([ 'sconto' => $this->sconto_unitario, 'prezzo' => $this->prezzo_orario, 'qta' => $this->ore, 'tipo' => $this->tipo_sconto, ]); } /** * Restituisce il prezzo totale scontato (per il cliente) del viaggio del tecnico. * * @return float */ public function getPrezzoManodoperaScontatoAttribute() { return $this->prezzo_manodopera - $this->sconto_totale_manodopera; } /** * Restituisce il prezzo totale (per il cliente) del viaggio del tecnico. * * @return float */ public function getPrezzoViaggioAttribute() { return $this->prezzo_chilometrico * $this->km; } /** * Restituisce lo sconto totale km in euro. * * @return float */ public function getScontoTotaleViaggioAttribute() { return calcola_sconto([ 'sconto' => $this->scontokm_unitario, 'prezzo' => $this->prezzo_chilometrico, 'qta' => $this->km, 'tipo' => $this->tipo_scontokm, ]); } /** * Restituisce il prezzo totale scontato (per il cliente) del viaggio del tecnico. * * @return float */ public function getPrezzoViaggioScontatoAttribute() { return $this->prezzo_viaggio - $this->sconto_totale_viaggio; } // Attributi di contabilità /** * Restituisce l'imponibile dell'elemento. * * @return float */ public function getImponibileAttribute() { return $this->prezzo_manodopera + $this->prezzo_viaggio + $this->prezzo_diritto_chiamata; } /** * Restituisce il totale imponibile dell'elemento. * * @return float */ public function getTotaleImponibileAttribute() { return $this->prezzo_manodopera_scontato + $this->prezzo_viaggio_scontato + $this->prezzo_diritto_chiamata; } /** * Restituisce il totale (imponibile + iva) dell'elemento. * * @return float */ public function getTotaleAttribute() { return $this->totale_imponibile + $this->iva; } /** * Restituisce la spesa (costo_unitario * qta) relativa all'elemento. * * @return float */ public function getSpesaAttribute() { return $this->costo_manodopera; } /** * Restituisce il margine totale (imponibile - spesa) relativo all'elemento. * * @return float */ public function getMargineAttribute() { return $this->imponibile - $this->spesa; } /** * Restituisce lo sconto della riga corrente in euro. * * @return float */ public function getScontoAttribute() { return $this->sconto_totale_manodopera + $this->sconto_totale_viaggio; } /** * Restituisce il margine percentuale relativo all'elemento. * * @return float */ public function getMarginePercentualeAttribute() { return $this->imponibile ? (1 - ($this->spesa / $this->imponibile)) * 100 : 100; } public function getIvaIndetraibileAttribute() { return $this->iva / 100 * $this->aliquota->indetraibile; } public function getIvaAttribute() { return ($this->totale_imponibile) * $this->aliquota->percentuale / 100; } public function getIvaDetraibileAttribute() { return $this->iva - $this->iva_indetraibile; } public function getAliquotaAttribute() { if (!isset($this->aliquota_iva)) { $id_iva = setting('Iva predefinita'); $this->aliquota_iva = Aliquota::find($id_iva); } return $this->aliquota_iva; } protected function getTariffa($id_tipo) { $database = database(); // Costi unitari dalla tariffa del tecnico $result = $database->fetchOne('SELECT * FROM in_tariffe WHERE idtecnico='.prepare($this->anagrafica->id).' AND idtipointervento = '.prepare($id_tipo)); // Costi unitari del contratto $id_contratto = $this->intervento->id_contratto; if (!empty($id_contratto)) { $tariffa_contratto = $database->fetchOne('SELECT costo_ore, costo_km, costo_dirittochiamata FROM co_contratti_tipiintervento WHERE idcontratto = '.prepare($id_contratto).' AND idtipointervento = '.prepare($id_tipo)); if (!empty($tariffa_contratto)) { $result = array_merge($result, $tariffa_contratto); } } return $result; } }