2017-08-04 16:28:16 +02:00
< ? php
2020-09-07 15:04:06 +02:00
/*
* OpenSTAManager : il software gestionale open source per l ' assistenza tecnica e la fatturazione
2021-01-20 15:08:51 +01:00
* Copyright ( C ) DevCode s . r . l .
2020-09-07 15:04:06 +02:00
*
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2017-08-04 16:28:16 +02:00
include_once __DIR__ . '/../../core.php' ;
2019-07-15 12:27:12 +02:00
use Modules\Anagrafiche\Anagrafica ;
2020-11-06 10:46:42 +01:00
use Modules\Articoli\Articolo as ArticoloOriginale ;
2019-08-29 10:25:14 +02:00
use Modules\Emails\Mail ;
use Modules\Emails\Template ;
2019-07-24 15:29:03 +02:00
use Modules\Fatture\Components\Descrizione ;
use Modules\Fatture\Components\Riga ;
2019-07-24 15:41:04 +02:00
use Modules\Fatture\Fattura ;
2023-08-04 14:54:28 +02:00
use Modules\Interventi\Components\Riga as RigaIntervento ;
2019-07-15 12:27:12 +02:00
use Modules\Interventi\Components\Sessione ;
use Modules\Interventi\Intervento ;
2024-03-06 17:26:58 +01:00
use Modules\Iva\Aliquota ;
2021-02-25 15:16:05 +01:00
use Util\Generator ;
2020-09-09 15:12:02 +02:00
use Util\Ini ;
2019-07-15 12:27:12 +02:00
2023-12-06 17:24:23 +01:00
/*
2017-08-04 16:28:16 +02:00
* Recupera il totale delle ore spese per un intervento .
*
2019-07-24 15:29:03 +02:00
* @ param int $id_intervento
2020-08-17 09:47:18 +02:00
*
* @ deprecated
2017-08-04 16:28:16 +02:00
*/
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'get_ore_intervento' )) {
2023-12-06 17:24:23 +01:00
function get_ore_intervento ( $id_intervento )
2023-12-06 16:48:54 +01:00
{
$intervento = Intervento :: find ( $id_intervento );
return $intervento -> ore_totali ;
}
2017-08-04 16:28:16 +02:00
}
2023-12-06 17:24:23 +01:00
/*
2017-08-04 16:28:16 +02:00
* Funzione per collegare gli articoli , usati in un intervento , ai rispettivi impianti .
*
2020-09-09 15:12:02 +02:00
* @ param int $id_intervento
* @ param int $id_impianto
* @ param int $id_articolo
2018-06-27 18:58:50 +02:00
* @ param int $qta
2021-08-05 18:17:26 +02:00
*
* @ deprecated 2.4 . 25
2017-08-04 16:28:16 +02:00
*/
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'link_componente_to_articolo' )) {
function link_componente_to_articolo ( $id_intervento , $id_impianto , $id_articolo , $qta )
{
if ( empty ( $id_impianto ) || empty ( $id_intervento )) {
return ;
}
2017-08-04 16:28:16 +02:00
2023-12-06 16:48:54 +01:00
$dbo = database ();
$intervento = Intervento :: find ( $id_intervento );
// Data di inizio dell'intervento (data_richiesta in caso di assenza di sessioni)
2024-02-07 14:18:13 +01:00
$data = $intervento -> inizio ;
2023-12-06 16:48:54 +01:00
// Se l'articolo aggiunto è collegato a un componente, aggiungo il componente all'impianto selezionato
2024-02-29 15:10:55 +01:00
$componente_articolo = $dbo -> fetchOne ( 'SELECT `componente_filename`, `contenuto` FROM `mg_articoli` WHERE `id` = ' . prepare ( $id_articolo ));
2023-12-06 16:48:54 +01:00
if ( ! empty ( $componente_articolo ) && ! empty ( $componente_articolo [ 'componente_filename' ])) {
$contenuto_ini = Ini :: read ( $componente_articolo [ 'contenuto' ]);
$nome_componente = Ini :: getValue ( $contenuto_ini , 'Nome' );
$dati = [
'idimpianto' => $id_impianto ,
'idintervento' => $id_intervento ,
'nome' => $nome_componente ,
'data' => $data ,
'filename' => $componente_articolo [ 'componente_filename' ],
'contenuto' => $componente_articolo [ 'contenuto' ],
];
// Inserisco il componente tante volte quante la quantità degli articoli inseriti
for ( $q = 0 ; $q < $qta ; ++ $q ) {
$dbo -> insert ( 'my_impianto_componenti' , $dati );
}
2017-08-04 16:28:16 +02:00
}
}
}
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'add_tecnico' )) {
function add_tecnico ( $id_intervento , $idtecnico , $inizio , $fine , $idcontratto = null )
{
$intervento = Intervento :: find ( $id_intervento );
$anagrafica = Anagrafica :: find ( $idtecnico );
2017-09-14 16:20:11 +02:00
2023-12-06 16:48:54 +01:00
$sessione = Sessione :: build ( $intervento , $anagrafica , $inizio , $fine );
2018-08-31 17:33:33 +02:00
2023-12-06 16:48:54 +01:00
// Notifica nuovo intervento al tecnico
if ( setting ( 'Notifica al tecnico l\'aggiunta della sessione nell\'attività' )) {
if ( ! empty ( $anagrafica [ 'email' ])) {
2024-04-18 17:44:05 +02:00
$template = ( new Template ()) -> getByField ( 'title' , 'Notifica intervento' , Models\Locale :: getPredefined () -> id );
2020-06-22 17:45:10 +02:00
2023-12-06 16:48:54 +01:00
if ( ! empty ( $template )) {
$mail = Mail :: build ( auth () -> getUser (), $template , $id_intervento );
$mail -> addReceiver ( $anagrafica [ 'email' ]);
$mail -> save ();
}
2020-06-22 17:45:10 +02:00
}
}
2018-09-20 11:39:03 +02:00
2024-01-15 15:30:45 +01:00
// Inserisco le righe aggiuntive previste dal tipo di intervento
2023-12-06 16:48:54 +01:00
$righe_aggiuntive = database () -> fetchArray ( 'SELECT * FROM in_righe_tipiinterventi WHERE id_tipointervento=' . prepare ( $sessione -> idtipointervento ));
2021-12-16 12:25:25 +01:00
2023-12-06 16:48:54 +01:00
foreach ( $righe_aggiuntive as $riga_aggiuntiva ) {
$riga = RigaIntervento :: build ( $intervento );
2021-12-16 12:25:25 +01:00
2023-12-06 16:48:54 +01:00
$riga -> descrizione = $riga_aggiuntiva [ 'descrizione' ];
$riga -> um = $riga_aggiuntiva [ 'um' ];
2021-12-16 12:25:25 +01:00
2023-12-06 16:48:54 +01:00
$riga -> costo_unitario = $riga_aggiuntiva [ 'prezzo_acquisto' ];
$riga -> setPrezzoUnitario ( $riga_aggiuntiva [ 'prezzo_vendita' ], $riga_aggiuntiva [ 'idiva' ]);
$riga -> qta = $riga_aggiuntiva [ 'qta' ];
2021-12-16 12:25:25 +01:00
2023-12-06 16:48:54 +01:00
$riga -> save ();
}
2021-12-16 12:25:25 +01:00
2023-12-06 16:48:54 +01:00
return true ;
}
2017-08-04 16:28:16 +02:00
}
2017-09-06 15:29:51 +02:00
2023-12-06 17:24:23 +01:00
/*
2018-07-17 12:05:21 +02:00
* Calcola le ore presenti tra due date .
*
* @ param string $orario_inizio
* @ param string $orario_fine
*
* @ return float
2020-08-17 09:47:18 +02:00
*
* @ deprecated
2018-07-17 12:05:21 +02:00
*/
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'calcola_ore_intervento' )) {
function calcola_ore_intervento ( $orario_inizio , $orario_fine )
{
$inizio = new DateTime ( $orario_inizio );
$diff = $inizio -> diff ( new DateTime ( $orario_fine ));
2018-09-18 18:21:54 +02:00
2023-12-06 16:48:54 +01:00
$ore = $diff -> i / 60 + $diff -> h + ( $diff -> days * 24 );
2018-07-17 12:05:21 +02:00
2023-12-06 16:48:54 +01:00
return $ore ;
}
2018-07-17 12:05:21 +02:00
}
2018-09-03 16:01:05 +02:00
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'aggiungi_intervento_in_fattura' )) {
function aggiungi_intervento_in_fattura ( $id_intervento , $id_fattura , $descrizione , $id_iva , $id_conto , $id_rivalsa_inps = false , $id_ritenuta_acconto = false , $calcolo_ritenuta_acconto = false )
{
$dbo = database ();
2018-09-04 17:59:12 +02:00
2023-12-06 16:48:54 +01:00
$id_rivalsa_inps = $id_rivalsa_inps !== false ? $id_rivalsa_inps : setting ( 'Cassa previdenziale predefinita' );
$id_ritenuta_acconto = $id_ritenuta_acconto !== false ? $id_ritenuta_acconto : setting ( " Ritenuta d'acconto predefinita " );
$calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto !== false ? $calcolo_ritenuta_acconto : setting ( " Metodologia calcolo ritenuta d'acconto predefinito " );
2018-08-31 12:33:48 +02:00
2023-12-06 16:48:54 +01:00
$fattura = Fattura :: find ( $id_fattura );
$intervento = Intervento :: find ( $id_intervento );
2018-08-31 12:33:48 +02:00
2023-12-06 16:48:54 +01:00
$data = $intervento -> fine ;
$codice = $intervento -> codice ;
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
// Riga di descrizione
$riga = Descrizione :: build ( $fattura );
$riga -> descrizione = $descrizione ;
$riga -> idintervento = $id_intervento ;
$riga -> save ();
2020-11-20 15:50:15 +01:00
2023-12-06 16:48:54 +01:00
// Ore di lavoro raggruppate per costo orario
$sessioni = $intervento -> sessioni ;
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
if ( empty ( $sessioni )) {
flash () -> warning ( tr ( " L'attività _NUM_ non ha sessioni di lavoro! " , [
2019-07-24 15:29:03 +02:00
'_NUM_' => $codice ,
2023-12-06 16:48:54 +01:00
]));
} else {
$decimals = setting ( 'Cifre decimali per quantità' );
2024-04-09 12:18:08 +02:00
$ore_di_lavoro = $sessioni -> groupBy ( fn ( $item , $key ) => $item [ 'prezzo_orario' ] . '|' . $item [ 'sconto_unitario' ] . '|' . $item [ 'tipo_sconto' ]);
2023-12-06 16:48:54 +01:00
foreach ( $ore_di_lavoro as $gruppo ) {
$sessione = $gruppo -> first ();
$riga = Riga :: build ( $fattura );
$riga -> descrizione = tr ( " Ore di lavoro dell'attività _NUM_ del _DATE_ " , [
'_NUM_' => $codice ,
'_DATE_' => dateFormat ( $data ),
]);
$riga -> idintervento = $id_intervento ;
$riga -> um = 'ore' ;
$riga -> id_iva = $id_iva ;
$riga -> idconto = $id_conto ;
$riga -> calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto ;
$riga -> id_ritenuta_acconto = $id_ritenuta_acconto ;
$riga -> id_rivalsa_inps = $id_rivalsa_inps ;
$riga -> prezzo_unitario = $sessione -> prezzo_orario ;
$riga -> costo_unitario = $sessione -> prezzo_ore_unitario_tecnico ;
2024-01-15 15:30:45 +01:00
// Calcolo lo sconto unitario della sessione in base all'impostazione sui prezzi ivati
2024-02-06 17:36:05 +01:00
$iva = Aliquota :: find ( $sessione -> id_iva );
2023-12-06 16:48:54 +01:00
if ( $sessione -> tipo_sconto == 'UNT' && setting ( 'Utilizza prezzi di vendita comprensivi di IVA' )) {
$sconto_unitario = $sessione -> sconto_unitario + (( $sessione -> sconto_unitario * $iva -> percentuale ) / 100 );
} else {
$sconto_unitario = $sessione -> sconto_unitario ;
}
$riga -> setSconto ( $sconto_unitario , $sessione -> tipo_sconto );
$qta_gruppo = $gruppo -> sum ( 'ore' );
$riga -> qta = round ( $qta_gruppo , $decimals );
// Riferimento al documento di origine
$riga -> original_document_type = get_class ( $intervento );
$riga -> original_document_id = $intervento -> id ;
$riga -> save ();
2021-09-27 10:27:17 +02:00
}
2023-12-06 16:48:54 +01:00
// Diritti di chiamata raggruppati per costo
2024-04-09 12:18:08 +02:00
$diritti_chiamata = $sessioni -> where ( 'prezzo_diritto_chiamata' , '>' , 0 ) -> groupBy ( fn ( $item , $key ) => $item [ 'prezzo_diritto_chiamata' ]);
2023-12-06 16:48:54 +01:00
foreach ( $diritti_chiamata as $gruppo ) {
$diritto_chiamata = $gruppo -> first ();
$riga = Riga :: build ( $fattura );
$riga -> descrizione = tr ( " Diritto di chiamata dell'attività _NUM_ del _DATE_ " , [
'_NUM_' => $codice ,
'_DATE_' => dateFormat ( $data ),
]);
$riga -> idintervento = $id_intervento ;
2024-01-15 15:30:45 +01:00
// $riga->um = 'ore';
2023-12-06 16:48:54 +01:00
$riga -> id_iva = $id_iva ;
$riga -> idconto = $id_conto ;
$riga -> calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto ;
$riga -> id_ritenuta_acconto = $id_ritenuta_acconto ;
$riga -> id_rivalsa_inps = $id_rivalsa_inps ;
$riga -> prezzo_unitario = $diritto_chiamata -> prezzo_diritto_chiamata ;
$riga -> costo_unitario = $sessione -> prezzo_dirittochiamata_tecnico ;
$riga -> qta = $gruppo -> count ();
// Riferimento al documento di origine
$riga -> original_document_type = get_class ( $intervento );
$riga -> original_document_id = $intervento -> id ;
$riga -> save ();
}
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
// Viaggi raggruppati per costo
2024-04-09 12:18:08 +02:00
$viaggi = $sessioni -> where ( 'prezzo_km_unitario' , '>' , 0 ) -> groupBy ( fn ( $item , $key ) => $item [ 'prezzo_km_unitario' ] . '|' . $item [ 'scontokm_unitario' ] . '|' . $item [ 'tipo_scontokm' ]);
2023-12-06 16:48:54 +01:00
foreach ( $viaggi as $gruppo ) {
$qta_trasferta = $gruppo -> sum ( 'km' );
if ( $qta_trasferta == 0 ) {
continue ;
}
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
$viaggio = $gruppo -> first ();
$riga = Riga :: build ( $fattura );
2021-09-17 10:30:36 +02:00
2023-12-06 16:48:54 +01:00
$riga -> descrizione = tr ( " Trasferta dell'attività _NUM_ del _DATE_ " , [
'_NUM_' => $codice ,
'_DATE_' => dateFormat ( $data ),
]);
$riga -> idintervento = $id_intervento ;
$riga -> um = 'km' ;
2018-08-31 12:33:48 +02:00
2023-12-06 16:48:54 +01:00
$riga -> id_iva = $id_iva ;
$riga -> idconto = $id_conto ;
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
$riga -> calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto ;
$riga -> id_ritenuta_acconto = $id_ritenuta_acconto ;
$riga -> id_rivalsa_inps = $id_rivalsa_inps ;
2018-08-31 12:33:48 +02:00
2023-12-06 16:48:54 +01:00
$riga -> prezzo_unitario = $viaggio -> prezzo_km_unitario ;
$riga -> costo_unitario = $sessione -> prezzo_km_unitario_tecnico ;
$riga -> setSconto ( $viaggio -> scontokm_unitario , $viaggio -> tipo_scontokm );
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
// Riferimento al documento di origine
$riga -> original_document_type = get_class ( $intervento );
$riga -> original_document_id = $intervento -> id ;
2021-09-17 10:30:36 +02:00
2023-12-06 16:48:54 +01:00
$riga -> qta = $qta_trasferta ;
2020-01-24 12:24:20 +01:00
2023-12-06 16:48:54 +01:00
$riga -> save ();
2020-11-20 15:23:52 +01:00
}
2023-12-06 16:48:54 +01:00
}
2020-11-20 15:23:52 +01:00
2023-12-06 16:48:54 +01:00
// Articoli, righe, sconti e descrizioni collegati all'intervento
$righe = $intervento -> getRighe ();
foreach ( $righe as $riga ) {
$qta = $riga -> qta ;
$copia = $riga -> copiaIn ( $fattura , $qta );
2020-01-24 12:24:20 +01:00
2023-12-06 16:48:54 +01:00
$copia -> id_conto = $id_conto ;
2020-01-24 12:24:20 +01:00
2023-12-06 16:48:54 +01:00
$copia -> calcolo_ritenuta_acconto = $calcolo_ritenuta_acconto ;
$copia -> id_ritenuta_acconto = $id_ritenuta_acconto ;
$copia -> id_rivalsa_inps = $id_rivalsa_inps ;
2021-09-17 10:30:36 +02:00
2023-12-06 16:48:54 +01:00
// Aggiornamento seriali dalla riga dell'ordine
if ( $copia -> isArticolo ()) {
$copia -> serials = $riga -> serials ;
$articolo = ArticoloOriginale :: find ( $copia -> idarticolo );
2024-04-08 15:44:33 +02:00
$copia -> id_conto = ( $articolo -> idconto_vendita ? : $id_conto );
2023-12-06 16:48:54 +01:00
}
2020-01-24 12:24:20 +01:00
2023-12-06 16:48:54 +01:00
$copia -> save ();
2020-01-24 12:24:20 +01:00
}
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
// Ricalcolo inps, ritenuta e bollo
ricalcola_costiagg_fattura ( $id_fattura );
2019-07-24 15:29:03 +02:00
2023-12-06 16:48:54 +01:00
// Metto l'intervento in stato "Fatturato"
2024-02-28 15:28:39 +01:00
$dbo -> query ( " UPDATE `in_interventi` SET `idstatointervento`=(SELECT `id` FROM `in_statiintervento` WHERE `codice`='FAT') WHERE `id`= " . prepare ( $id_intervento ));
2018-08-31 12:33:48 +02:00
}
}
2021-02-25 15:16:05 +01:00
2023-12-06 17:24:23 +01:00
/*
2021-02-25 15:16:05 +01:00
* Verifica che il numero_esterno della fattura indicata sia correttamente impostato , a partire dai valori delle fatture ai giorni precedenti .
* Restituisce il numero_esterno mancante in caso di numero errato .
*
* @ return bool | string
*/
2023-12-06 16:48:54 +01:00
if ( ! function_exists ( 'verifica_numero_intervento' )) {
2024-04-10 12:43:32 +02:00
function verifica_numero_intervento ( Intervento $intervento , $id_segment )
2023-12-06 16:48:54 +01:00
{
if ( empty ( $intervento -> codice )) {
return null ;
}
2021-02-25 15:16:05 +01:00
2023-12-06 16:48:54 +01:00
$data = $intervento -> data_richiesta ;
$documenti = Intervento :: whereDate ( 'data_richiesta' , '=' , $data -> format ( 'Y-m-d' ))
-> get ();
// Recupero maschera per questo segmento
2024-04-10 12:43:32 +02:00
$maschera = Generator :: getMaschera ( $id_segment );
2023-12-06 16:48:54 +01:00
if (( strpos ( $maschera , 'YYYY' ) == false ) or ( strpos ( $maschera , 'yy' ) == false )) {
$ultimo = Generator :: getPreviousFrom ( $maschera , 'in_interventi' , 'codice' , [
'DATE(data_richiesta) < ' . prepare ( $data -> format ( 'Y-m-d' )),
'YEAR(data_richiesta) = ' . prepare ( $data -> format ( 'Y' )),
], $data );
} else {
$ultimo = Generator :: getPreviousFrom ( $maschera , 'in_interventi' , 'codice' , [
'DATE(data_richiesta) < ' . prepare ( $data -> format ( 'Y-m-d' )),
]);
}
2021-02-25 15:16:05 +01:00
2023-12-06 16:48:54 +01:00
do {
$numero = Generator :: generate ( $maschera , $ultimo , 1 , Generator :: dateToPattern ( $data ), $data );
2021-02-25 15:16:05 +01:00
2024-04-09 12:18:08 +02:00
$filtered = $documenti -> reject ( fn ( $item , $key ) => $item -> codice == $numero );
2021-02-25 15:16:05 +01:00
2023-12-06 16:48:54 +01:00
if ( $documenti -> count () == $filtered -> count ()) {
return $numero ;
}
2021-02-25 15:16:05 +01:00
2023-12-06 16:48:54 +01:00
$documenti = $filtered ;
$ultimo = $numero ;
} while ( $numero != $intervento -> codice );
2021-02-25 15:16:05 +01:00
2023-12-06 16:48:54 +01:00
return null ;
}
2023-12-06 17:24:23 +01:00
}