diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b5317da2..76c5c3aad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k - [Deprecato (Deprecated)](#deprecato-deprecated) - [Rimosso (Removed)](#rimosso-removed) - [Sicurezza (Security)](#sicurezza-security) +- [2.4.1 (2018-08-01)](#241-2018-08-01) + - [Aggiunto (Added)](#aggiunto-added) + - [Modificato (Changed)](#modificato-changed) + - [Fixed](#fixed) - [2.4 (2018-03-30)](#24-2018-03-30) - [Aggiunto (Added)](#aggiunto-added) - [Modificato (Changed)](#modificato-changed) @@ -68,6 +72,55 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k - Abilitata protezione contro attacchi CSRF +## 2.4.1 (2018-08-01) + +### Aggiunto (Added) + - Supporto alla generazione PDF/A + - Gestione di Note di accredito e di addebito per le Fatture + - Salvataggio AJAX delle righe in Fatture + - Cambio automatico dello stato dei documenti + - Nomi per i filtri di accesso ai moduli + - Anteprime degli upload (per immagini e PDF) + - Validazione di indirizzi email e codici fiscali + - Test della connessione al server email + - Widget *Attività da pianificare* per individuare le attività senza tecnici + - Esportazione tabelle in PDF ed Excel (impostazione *Abilita esportazione Excel e PDF*) + - Stampa dedicata al calendario attività in **Dashboard** + - Operazioni rapide su **Anagrafiche** di tipo *Cliente* + - Campi aggiuntivi nella creazione di nuove **Anagrafiche** + - Possibilità di specificare tempi standard per *Tipologia di intervento* + - Seriali nella stampa **Interventi** + - Quantità calcolata tramite movimenti in data attuale per **Articoli** + - Movimenti manuali con causale degli **Articoli** + +### Modificato (Changed) + - Miglioramento della gestione di installazione/aggiornamento + - Migliorata la procedura per i moduli (esempi: https://github.com/devcode-it/example) + - Aggiunto supporto all'installazione dei plugin (esempio: https://github.com/devcode-it/example/tree/master/sedi) + - Aggiunto supporto a file ZIP con vari moduli/plugin (installazione in ordine alfabetico) + - Miglioramento dei pre-requisiti di installazione + - Gestione degli upload tramite AJAX + - Gestione del logo per le stampe come un allegato + - Gestione delle immagini di **Articoli** e **Impianti** come allegati + - Miglioramento del plugin *Pianificazione interventi* in **Contratti** + - Miglioramento della ritenuta d'acconto (calcolo impostabile su Imponibile o Rivalsa INPS) + - Ripristinati plugin *Pianificazione fatturazione* e widget *Rate contrattuali* + - Miglioramento della tabella dei *Costi Totali* in **Interventi** + - Collegamento ad un'anagrafica obbligatorio per i nuovi utenti + - Ridenominazione delle tabelle `co_righe_contratti` e `co_righe2_contratti` in `co_contratti_promemoria` e `co_righe_contratti` + - I movimenti articoli utilizzano la data del documento relativo + - I chilometri del cliente vengono riportati nell'intervento + - I tecnici possono aggiungere **Interventi** solo a loro nome + +### Fixed + - Correzione dei link alle stampe sulle tabelle dei moduli + - Correzione della scontistica per la stampa **Interventi** + - Correzione degli arrotondamenti su IVA e imponibili nei documenti + - Correzione del budget dei **Contratti** + - Correzione della scadenza "Data fattura fine mese" + - Correzione del plugin *Statistiche* in **Anagrafiche** + - Correzione del widget *Debiti verso fornitori* + - Correzioni minori ## 2.4 (2018-03-30) diff --git a/core.php b/core.php index a605c82de..704d133f3 100644 --- a/core.php +++ b/core.php @@ -235,10 +235,6 @@ if (!API::isAPIRequest()) { Permissions::addModule($id_module); } - if (!empty($skip_permissions)) { - Permissions::skip(); - } - Permissions::check(); } diff --git a/lib/functions.js b/lib/functions.js index f4ed06c56..c0ebc6f6b 100644 --- a/lib/functions.js +++ b/lib/functions.js @@ -1277,7 +1277,6 @@ function message(element) { preConfirm: function () { $('#swal-form').find(':input').each(function () { data[$(this).attr('name')] = $(this).val(); - console.log($(this).attr('name')); }); return new Promise(function (resolve) { diff --git a/modules/anagrafiche/edit.php b/modules/anagrafiche/edit.php index bb573c66e..505c8d9f7 100644 --- a/modules/anagrafiche/edit.php +++ b/modules/anagrafiche/edit.php @@ -450,10 +450,12 @@ if (empty($record['deleted_at'])) { SELECT `in_interventi`.`id`, `in_interventi`.`data_richiesta`, `in_interventi`.`codice` AS numero, 0 AS numero_esterno, "Intervento" AS tipo_documento, 0 AS dir FROM `in_interventi` JOIN `in_interventi_tecnici` ON `in_interventi`.`id` = `in_interventi_tecnici`.`idintervento` WHERE `in_interventi`.`id` IN (SELECT `idintervento` FROM `in_interventi_tecnici` WHERE `idtecnico` = '.prepare($id_record).' OR `in_interventi`.`idanagrafica` = '.prepare($id_record).' ) UNION - SELECT `co_contratti`.`id`, `co_contratti`.`data_bozza`, `co_contratti`.`numero`, 0 AS numero_esterno , "Contratto" AS tipo_documento, 0 AS dir FROM `co_contratti` WHERE `co_contratti`.`id` IN (SELECT `idcontratto` FROM `co_promemoria` WHERE `idanagrafica` = '.prepare($id_record).') + SELECT `co_contratti`.`id`, `co_contratti`.`data_bozza`, `co_contratti`.`numero`, 0 AS numero_esterno , "Contratto" AS tipo_documento, 0 AS dir FROM `co_contratti` WHERE `co_contratti`.`idanagrafica` = '.prepare($id_record).' UNION - SELECT `co_preventivi`.`id`, `co_preventivi`.`data_bozza`, `co_preventivi`.`numero`, 0 AS numero_esterno , "Preventivo" AS tipo_documento, 0 AS dir FROM `co_preventivi` WHERE `co_preventivi`.`id` IN (SELECT `idpreventivo` FROM `co_righe_preventivi` WHERE `idanagrafica` = '.prepare($id_record).') ORDER BY `data`'); + SELECT `co_preventivi`.`id`, `co_preventivi`.`data_bozza`, `co_preventivi`.`numero`, 0 AS numero_esterno , "Preventivo" AS tipo_documento, 0 AS dir FROM `co_preventivi` WHERE `co_preventivi`.`idanagrafica` = '.prepare($id_record).' + + ORDER BY `data`'); if (!empty($elementi)) { echo ' diff --git a/modules/banche/actions.php b/modules/banche/actions.php index 0f7d3093e..8ba612743 100644 --- a/modules/banche/actions.php +++ b/modules/banche/actions.php @@ -4,7 +4,6 @@ include_once __DIR__.'/../../core.php'; switch (filter('op')) { case 'update': - $nome = filter('nome'); if (isset($nome)) { @@ -51,7 +50,7 @@ switch (filter('op')) { case 'delete': $documenti = $dbo->fetchNum('SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_vendite='.prepare($id_record).' - UNION SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_acquisti='.prepare($id_record)); + UNION SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_acquisti='.prepare($id_record)); if (isset($id_record) && empty($documenti)) { $dbo->query('DELETE FROM `co_banche` WHERE `id`='.prepare($id_record)); diff --git a/modules/banche/edit.php b/modules/banche/edit.php index b3483ca5b..9fae96a0b 100644 --- a/modules/banche/edit.php +++ b/modules/banche/edit.php @@ -22,7 +22,7 @@ include_once __DIR__.'/../../core.php'; {[ "type": "text", "label": "", "name": "filiale", "value": "$filiale$" ]}
- {[ "type": "select", "label": "", "name": "id_pianodeiconti3", "value": "$id_pianodeiconti3$", "values": "query=SELECT id, descrizione FROM co_pianodeiconti3 WHERE idpianodeiconti2 = 1 AND ( id NOT IN (SELECT id_pianodeiconti3 FROM co_banche) OR id = '' )" ]} + {[ "type": "select", "label": "", "name": "id_pianodeiconti3", "value": "$id_pianodeiconti3$", "values": "query=SELECT id, descrizione FROM co_pianodeiconti3 WHERE idpianodeiconti2 = 1 AND ( id NOT IN (SELECT id_pianodeiconti3 FROM co_banche WHERE id != '' ) )" ]}
@@ -47,7 +47,7 @@ include_once __DIR__.'/../../core.php'; fetchNum('SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_vendite='.prepare($id_record).' - UNION SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_acquisti='.prepare($id_record)); +UNION SELECT idanagrafica FROM an_anagrafiche WHERE idbanca_acquisti='.prepare($id_record)); if (!empty($documenti)) { echo ' diff --git a/modules/ddt/bulk.php b/modules/ddt/bulk.php index b72ab0f8f..b11314261 100644 --- a/modules/ddt/bulk.php +++ b/modules/ddt/bulk.php @@ -10,7 +10,7 @@ switch (post('op')) { $totale_n_ddt = 0; // Informazioni della fattura - if( $dir == 'entrata' ){ + if ($dir == 'entrata') { $tipo_documento = $dbo->selectOne('co_tipidocumento', 'id', ['descrizione' => 'Fattura immediata di vendita'])['id']; $module_name = 'Fatture di vendita'; $idconto = setting('Conto predefinito fatture di vendita'); @@ -29,7 +29,7 @@ switch (post('op')) { $segments = Modules::getSegments($id_fatture); $_SESSION['module_'.$id_fatture]['id_segment'] = isset($segments[0]['id']) ? $segments[0]['id'] : null; } - $id_segment = $_SESSION['m'.$id_fatture]['id_segment']; + $id_segment = $_SESSION['module_'.$id_fatture]['id_segment']; // Lettura righe selezionate foreach ($id_records as $id) { diff --git a/modules/fatture/actions.php b/modules/fatture/actions.php index eef234d35..9910af966 100644 --- a/modules/fatture/actions.php +++ b/modules/fatture/actions.php @@ -125,13 +125,13 @@ switch (post('op')) { if ($rs[0]['descrizione'] == 'Bozza' or $rs[0]['descrizione'] == 'Annullata') { elimina_scadenza($id_record); elimina_movimento($id_record, 0); - //elimino movimento anche prima nota (se pagata o parzialmente pagata) + // elimino movimento anche prima nota (se pagata o parzialmente pagata) elimina_movimento($id_record, 1); } elseif ($rs[0]['descrizione'] == 'Emessa') { elimina_scadenza($id_record); elimina_movimento($id_record, 0); - } elseif (($rs[0]['descrizione'] == 'Pagato' or $rs[0]['descrizione'] == 'Parzialmente pagato') and ($dbo->fetchNum('SELECT id FROM co_scadenziario WHERE iddocumento = '.prepare($id_record)) == 0)) { - //aggiungo la scadenza come già pagata + } elseif (($rs[0]['descrizione'] == 'Pagato' or $rs[0]['descrizione'] == 'Parzialmente pagato') and ($dbo->fetchNum("SELECT id FROM co_scadenziario WHERE iddocumento = ".prepare($id_record)) == 0)) { + // aggiungo la scadenza come già pagata aggiungi_scadenza($id_record, $pagamento, 1); aggiungi_movimento($id_record, $dir); } @@ -257,219 +257,11 @@ switch (post('op')) { $idiva = post('idiva'); $idconto = post('idconto'); - // Leggo l'anagrafica del cliente - $rs = $dbo->fetchArray('SELECT idanagrafica, codice, (SELECT MIN(orario_inizio) FROM in_interventi_tecnici WHERE idintervento='.prepare($idintervento).') AS data FROM `in_interventi` WHERE id='.prepare($idintervento)); - $idanagrafica = $rs[0]['idanagrafica']; - $data = $rs[0]['data']; - $codice = $rs[0]['codice']; + aggiungi_intervento_in_fattura($idintervento, $id_record, $descrizione, $idiva, $idconto); - //Fatturo le ore di lavoro raggruppate per costo orario - $rst = $dbo->fetchArray('SELECT SUM( ROUND( TIMESTAMPDIFF( MINUTE, orario_inizio, orario_fine ) / 60, '.setting('Cifre decimali per quantità').' ) ) AS tot_ore, SUM(prezzo_ore_consuntivo) AS tot_prezzo_ore_consuntivo, SUM(sconto) AS tot_sconto, prezzo_ore_unitario FROM in_interventi_tecnici WHERE idintervento='.prepare($idintervento).' GROUP BY prezzo_ore_unitario'); - - //Aggiunta riga intervento sul documento - if (sizeof($rst) == 0) { - flash()->warning(tr("L'intervento _NUM_ non ha sessioni di lavoro!", [ - '_NUM_' => $idintervento, - ])); - } else { - for ($i = 0; $i < sizeof($rst); ++$i) { - $ore = $rst[$i]['tot_ore']; - - // Calcolo iva - $query = 'SELECT * FROM co_iva WHERE id='.prepare($idiva); - $rs = $dbo->fetchArray($query); - - $sconto = $rst[$i]['tot_sconto']; - $subtot = $rst[$i]['tot_prezzo_ore_consuntivo']; - $iva = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; - $desc_iva = $rs[0]['descrizione']; - - // Calcolo rivalsa inps - $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); - $rs = $dbo->fetchArray($query); - $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - - // Calcolo ritenuta d'acconto - $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); - $rs = $dbo->fetchArray($query); - if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { - $ritenutaacconto = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - } else { - $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale']; - } - - $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_record).', '.prepare($idintervento).', '.prepare($idconto).', '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($descrizione).', '.prepare($subtot).', '.prepare($sconto).', '.prepare($sconto).", 'UNT', 'ore', ".prepare($ore).', '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))'; - $dbo->query($query); - } - } - - $costi_intervento = get_costi_intervento($idintervento); - - // Fatturo i diritti di chiamata raggruppati per costo - $rst = $dbo->fetchArray('SELECT COUNT(id) AS qta, SUM(prezzo_dirittochiamata) AS tot_prezzo_dirittochiamata FROM in_interventi_tecnici WHERE idintervento='.prepare($idintervento).' AND prezzo_dirittochiamata > 0 GROUP BY prezzo_dirittochiamata'); - - // Aggiunta diritto di chiamata se esiste - for ($i = 0; $i < sizeof($rst); ++$i) { - // Calcolo iva - $query = 'SELECT * FROM co_iva WHERE id='.prepare($idiva); - $rs = $dbo->fetchArray($query); - - $iva = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; - $desc_iva = $rs[0]['descrizione']; - - // Calcolo rivalsa inps - $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); - $rs = $dbo->fetchArray($query); - $rivalsainps = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; - - // Calcolo ritenuta d'acconto - $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); - $rs = $dbo->fetchArray($query); - $ritenutaacconto = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; - - $dbo->insert('co_righe_documenti', [ - 'iddocumento' => $id_record, - 'idintervento' => $idintervento, - 'idconto' => $idconto, - 'idiva' => $idiva, - 'desc_iva' => $desc_iva, - 'iva' => $iva, - 'iva_indetraibile' => $iva_indetraibile, - 'descrizione' => 'Diritto di chiamata', - 'subtotale' => $rst[$i]['tot_prezzo_dirittochiamata'], - 'sconto' => 0, - 'sconto_unitario' => 0, - 'tipo_sconto' => 'UNT', - 'um' => '-', - 'qta' => $rst[$i]['qta'], - 'idrivalsainps' => setting('Percentuale rivalsa INPS'), - 'rivalsainps' => $rivalsainps, - 'idritenutaacconto' => setting("Percentuale ritenuta d'acconto"), - 'ritenutaacconto' => $ritenutaacconto, - '#order' => '(SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).')', - ]); - } - - // Collego in fattura eventuali articoli collegati all'intervento - $rs2 = $dbo->fetchArray('SELECT mg_articoli_interventi.*, idarticolo FROM mg_articoli_interventi INNER JOIN mg_articoli ON mg_articoli_interventi.idarticolo=mg_articoli.id WHERE idintervento='.prepare($idintervento).' AND (idintervento NOT IN(SELECT idintervento FROM co_righe_preventivi WHERE idpreventivo IN(SELECT idpreventivo FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).')) AND idintervento NOT IN(SELECT idintervento FROM co_promemoria WHERE idcontratto IN(SELECT idcontratto FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).')) )'); - for ($i = 0; $i < sizeof($rs2); ++$i) { - $riga = add_articolo_infattura($id_record, $rs2[$i]['idarticolo'], $rs2[$i]['descrizione'], $rs2[$i]['idiva'], $rs2[$i]['qta'], $rs2[$i]['prezzo_vendita'] * $rs2[$i]['qta'], $rs2[$i]['sconto'], $rs2[$i]['sconto_unitario'], $rs2[$i]['tipo_sconto'], $idintervento, 0, $rs2[$i]['um']); - - // Lettura lotto, serial, altro dalla riga dell'ordine - $dbo->query('INSERT INTO mg_prodotti (id_riga_documento, id_articolo, dir, serial, lotto, altro) SELECT '.prepare($riga).', '.prepare($rs2[$i]['idarticolo']).', '.prepare($dir).', serial, lotto, altro FROM mg_prodotti AS t WHERE id_riga_intervento='.prepare($rs2[$i]['id'])); - } - - // Aggiunta spese aggiuntive come righe generiche - $query = 'SELECT * FROM in_righe_interventi WHERE idintervento='.prepare($idintervento).' AND (idintervento NOT IN(SELECT idintervento FROM co_righe_preventivi WHERE idpreventivo IN(SELECT idpreventivo FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).')) AND idintervento NOT IN(SELECT idintervento FROM co_promemoria WHERE idcontratto IN(SELECT idcontratto FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).')) )'; - $rsr = $dbo->fetchArray($query); - if (sizeof($rsr) > 0) { - for ($i = 0; $i < sizeof($rsr); ++$i) { - // Calcolo iva - $query = 'SELECT * FROM co_iva WHERE id='.prepare($rsr[$i]['idiva']); - $rs = $dbo->fetchArray($query); - $desc_iva = $rs[0]['descrizione']; - - $subtot = $rsr[$i]['prezzo_vendita'] * $rsr[$i]['qta']; - $sconto = $rsr[$i]['sconto']; - $iva = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; - - // Calcolo rivalsa inps - $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); - $rs = $dbo->fetchArray($query); - $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - - // Calcolo ritenuta d'acconto - $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); - $rs = $dbo->fetchArray($query); - if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { - $ritenutaacconto = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - } else { - $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale']; - } - - $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_record).', '.prepare($idintervento).', '.prepare($idconto).', '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($rsr[$i]['descrizione']).', '.prepare($subtot).', '.prepare($rsr[$i]['sconto']).', '.prepare($rsr[$i]['sconto_unitario']).', '.prepare($rsr[$i]['tipo_sconto']).', '.prepare($rsr[$i]['um']).', '.prepare($rsr[$i]['qta']).', '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))'; - $dbo->query($query); - } - } - - // Aggiunta km come "Trasferta" (se c'è) - if ($costi_intervento['viaggio_addebito'] > 0) { - // Calcolo iva - $query = 'SELECT * FROM co_iva WHERE id='.prepare($idiva); - $dati = $dbo->fetchArray($query); - $desc_iva = $dati[0]['descrizione']; - - $subtot = $costi_intervento['viaggio_addebito']; - $sconto = $costi_intervento['viaggio_addebito'] - $costi_intervento['viaggio_scontato']; - $iva = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $dati[0]['indetraibile']; - - // Calcolo rivalsa inps - $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); - $dati = $dbo->fetchArray($query); - $rivalsainps = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; - - // Calcolo ritenuta d'acconto - $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); - $dati = $dbo->fetchArray($query); - if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { - $ritenutaacconto = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; - } else { - $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $dati[0]['percentuale']; - } - - $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_record).', '.prepare($idintervento).', '.prepare($idconto).', '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare('Trasferta intervento '.$codice.' del '.Translator::dateToLocale($data)).', '.prepare($subtot).', '.prepare($sconto).', '.prepare($sconto).", 'UNT', '', 1, ".prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))'; - $dbo->query($query); - } - - // Aggiunta sconto - if (!empty($costi_intervento['sconto_globale'])) { - $subtot = -$costi_intervento['sconto_globale']; - - // Calcolo iva - $query = 'SELECT * FROM co_iva WHERE id='.prepare($idiva); - $rs = $dbo->fetchArray($query); - $desc_iva = $rs[0]['descrizione']; - - $iva = ($subtot) / 100 * $rs[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; - - // Calcolo rivalsa inps - $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); - $rs = $dbo->fetchArray($query); - $rivalsainps = ($subtot) / 100 * $rs[0]['percentuale']; - - // Calcolo ritenuta d'acconto - $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); - $rs = $dbo->fetchArray($query); - if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { - $ritenutaacconto = $subtot / 100 * $rs[0]['percentuale']; - } else { - $ritenutaacconto = ($subtot + $rivalsainps) / 100 * $rs[0]['percentuale']; - } - - $idconto = ($dir == 'entrata') ? setting('Conto predefinito fatture di vendita') : setting('Conto predefinito fatture di acquisto'); - - $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_record).', NULL, '.prepare($idconto).', '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare('Sconto '.$descrizione).', '.prepare($subtot).', 1, '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))'; - $dbo->query($query); - } - - // Ricalcolo inps, ritenuta e bollo - if ($dir == 'entrata') { - ricalcola_costiagg_fattura($id_record); - } else { - ricalcola_costiagg_fattura($id_record); - } - - // Metto l'intervento in stato "Fatturato" - $dbo->query("UPDATE in_interventi SET idstatointervento=(SELECT idstatointervento FROM in_statiintervento WHERE descrizione='Fatturato') WHERE id=".prepare($idintervento)); - - flash()->info(tr('Intervento _NUM_ aggiunto!', [ + $_SESSION['infos'][] = tr('Intervento _NUM_ aggiunto!', [ '_NUM_' => $idintervento, - ])); + ]); } break; @@ -531,7 +323,7 @@ switch (post('op')) { $sconto = $riga['sconto']; - //Ricalcolo ritenuta per ogni singola riga + // Ricalcolo ritenuta per ogni singola riga if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { $ritenutaacconto = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; } else { @@ -665,7 +457,7 @@ switch (post('op')) { '_NUM_' => $numero, ])); - //Scalo le qta degli articoli nel contratto + // Scalo le qta degli articoli nel contratto $righe = $dbo->fetchArray('SELECT * FROM co_righe_contratti WHERE idcontratto='.prepare($idcontratto)); foreach ($righe as $key => $riga) { if (!empty($riga['idarticolo'])) { @@ -1091,7 +883,7 @@ switch (post('op')) { $numero_esterno = get_new_numerosecondariofattura($data); $tipo_documento = 'Fattura immediata di vendita'; - //Info contratto + // Info contratto $rs_contratto = $dbo->fetchArray('SELECT * FROM co_contratti WHERE id='.prepare($idcontratto)); $idanagrafica = $rs_contratto[0]['idanagrafica']; $idpagamento = $rs_contratto[0]['idpagamento']; @@ -1103,7 +895,7 @@ switch (post('op')) { $dbo->query('INSERT INTO co_documenti(numero, numero_esterno, data, idanagrafica, idtipodocumento, idstatodocumento, idpagamento, idconto, id_segment) VALUES('.prepare($numero).', '.prepare($numero_esterno).', '.prepare($data).', '.prepare($idanagrafica).', (SELECT id FROM co_tipidocumento WHERE descrizione='.prepare($tipo_documento)."), (SELECT id FROM co_statidocumento WHERE descrizione='Bozza'), ".prepare($idpagamento).', '.prepare($idconto).','.prepare($id_segment).')'); $id_record = $dbo->lastInsertedID(); - //Righe contratto + // Righe contratto $rs_righe = $dbo->fetchArray('SELECT * FROM co_righe_contratti WHERE idcontratto='.prepare($idcontratto)); for ($i = 0; $i < sizeof($rs_righe); ++$i) { @@ -1200,11 +992,11 @@ switch (post('op')) { } // Lettura interventi collegati - //$query = 'SELECT id, idintervento FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).' AND idintervento IS NOT NULL'; - //$rs = $dbo->fetchArray($query); + // $query = 'SELECT id, idintervento FROM co_righe_documenti WHERE iddocumento='.prepare($id_record).' AND idintervento IS NOT NULL'; + // $rs = $dbo->fetchArray($query); // Se ci sono degli interventi collegati li rimetto nello stato "Completato" - //for ($i = 0; $i < sizeof($rs); ++$i) { + // for ($i = 0; $i < sizeof($rs); ++$i) { $dbo->query("UPDATE in_interventi SET idstatointervento='OK' WHERE id=".prepare($idintervento)); // Rimuovo dalla fattura gli articoli collegati all'intervento @@ -1212,9 +1004,9 @@ switch (post('op')) { for ($j = 0; $j < sizeof($rs2); ++$j) { rimuovi_articolo_dafattura($rs[0]['idarticolo'], $id_record, $rs[0]['idrigadocumento']); } - //} + // } - //rimuovo riga da co_righe_documenti + // rimuovo riga da co_righe_documenti $query = 'DELETE FROM `co_righe_documenti` WHERE iddocumento='.prepare($id_record).' AND id='.prepare($idriga); $dbo->query($query); @@ -1259,9 +1051,9 @@ switch (post('op')) { $is_preventivo = $rsp[0]['is_preventivo']; $idarticolo = $rsp[0]['idarticolo']; - //preventivo su unica riga, perdo il riferimento dell'articolo quindi lo vado a leggere da co_righe_preventivi + // preventivo su unica riga, perdo il riferimento dell'articolo quindi lo vado a leggere da co_righe_preventivi if (empty($idarticolo) && $is_preventivo) { - //rimetto a magazzino gli articoli collegati al preventivo + // rimetto a magazzino gli articoli collegati al preventivo $rsa = $dbo->fetchArray('SELECT idarticolo, qta FROM co_righe_preventivi WHERE idpreventivo = '.prepare($idpreventivo)); for ($i = 0; $i < sizeof($rsa); ++$i) { if (!empty($rsa[$i]['idarticolo'])) { @@ -1352,8 +1144,8 @@ switch (post('op')) { } } - //Riporto a magazzino gli articoli nelle righe del contratto - $rsa = $dbo->fetchArray('SELECT idarticolo, qta FROM co_righe_contratti WHERE idcontratto='.prepare($idcontratto)); + // Riporto a magazzino gli articoli nelle righe del contratto + $rsa = $dbo->fetchArray("SELECT idarticolo, qta FROM co_righe_contratti WHERE idcontratto=".prepare($idcontratto)); for ($i = 0; $i < sizeof($rsa); ++$i) { if (!empty($rsa[$i]['idarticolo'])) { add_movimento_magazzino($rsa[$i]['idarticolo'], $rsa[$i]['qta'], ['iddocumento' => $id_record]); diff --git a/modules/fatture/edit.php b/modules/fatture/edit.php index 8424318a6..72820e0f2 100644 --- a/modules/fatture/edit.php +++ b/modules/fatture/edit.php @@ -279,7 +279,7 @@ if ($record['stato'] != 'Pagato' && $record['stato'] != 'Emessa') { } echo ' -
+
Intervento diff --git a/modules/interventi/bulk.php b/modules/interventi/bulk.php index 5ff9fddc4..b04939bc9 100644 --- a/modules/interventi/bulk.php +++ b/modules/interventi/bulk.php @@ -54,170 +54,94 @@ switch (post('op')) { break; - case 'creafatturavendita': - - $rs_idanagrafica = $dbo->fetchArray('SELECT idanagrafica FROM in_interventi WHERE id='.prepare($id_records[0])); - - $idanagrafica = $rs_idanagrafica[0]['idanagrafica']; - $data = date('Y-m-d'); - $dir = 'entrata'; - $idtipodocumento = '2'; - $accodare = post('accodare'); - - if (empty($_SESSION['module_'.Modules::get('Fatture di vendita')['id']]['id_segment'])) { - $rs = $dbo->fetchArray('SELECT id FROM zz_segments WHERE predefined = 1 AND id_module = '.prepare(Modules::get('Fatture di vendita')['id']).'LIMIT 0,1'); - $_SESSION['module_'.Modules::get('Fatture di vendita')['id']]['id_segment'] = $rs[0]['id']; - } - - $id_segment = $_SESSION['module_'.Modules::get('Fatture di vendita')['id']]['id_segment']; - - $numero = get_new_numerofattura($data); - - $numero_esterno = get_new_numerosecondariofattura($data); - $idconto = setting('Conto predefinito fatture di vendita'); - - $campo = ($dir == 'entrata') ? 'idpagamento_vendite' : 'idpagamento_acquisti'; - - // Tipo di pagamento predefinito dall'anagrafica - $query = 'SELECT id FROM co_pagamenti WHERE id=(SELECT '.$campo.' AS pagamento FROM an_anagrafiche WHERE idanagrafica='.prepare($idanagrafica).')'; - $rs = $dbo->fetchArray($query); - $idpagamento = $rs[0]['id']; - - // Se la fattura è di vendita e non è stato associato un pagamento predefinito al cliente leggo il pagamento dalle impostazioni - if ($dir == 'entrata' && $idpagamento == '') { - $idpagamento = setting('Tipo di pagamento predefinito'); - } - + case 'crea_fattura': + $id_documento_cliente = []; $n_interventi = 0; - //inserisco righe - for ($i = 0; $i < sizeof($id_records); ++$i) { - $idintervento = $id_records[$i]; + $data = date('Y-m-d'); + $dir = 'entrata'; + $tipo_documento = $dbo->selectOne('co_tipidocumento', 'id', ['descrizione' => 'Fattura immediata di vendita'])['id']; - $q = 'SELECT id, in_interventi.descrizione, in_interventi.codice, - IFNULL( (SELECT MIN(orario_inizio) FROM in_interventi_tecnici WHERE in_interventi_tecnici.idintervento=in_interventi.id), data_richiesta) AS data, - (SELECT costo_orario FROM in_tipiintervento WHERE idtipointervento=in_interventi.idtipointervento) AS costo_ore_unitario, - (SELECT costo_km FROM in_tipiintervento WHERE idtipointervento=in_interventi.idtipointervento) AS costo_km_unitario, - (SELECT SUM(prezzo_dirittochiamata) FROM in_interventi_tecnici GROUP BY idintervento HAVING idintervento=in_interventi.id) AS dirittochiamata, - (SELECT SUM(km) FROM in_interventi_tecnici GROUP BY idintervento HAVING idintervento=in_interventi.id) AS km, - (SELECT SUM(TIME_TO_SEC(TIMEDIFF(orario_fine, orario_inizio))) FROM in_interventi_tecnici GROUP BY idintervento HAVING idintervento=in_interventi.id) AS t1, - (SELECT SUM(prezzo_ore_consuntivo) FROM in_interventi_tecnici GROUP BY idintervento HAVING idintervento=in_interventi.id) AS `tot_ore_consuntivo`, - (SELECT SUM(prezzo_km_consuntivo) FROM in_interventi_tecnici GROUP BY idintervento HAVING idintervento=in_interventi.id) AS `tot_km_consuntivo` - FROM in_interventi WHERE id="'.$idintervento.'" AND idanagrafica="'.$idanagrafica."\" AND id NOT IN (SELECT idintervento FROM co_righe_documenti WHERE idintervento != 'NULL') "; + $id_iva = setting('Iva predefinita'); + $id_conto = setting('Conto predefinito fatture di vendita'); - $rs = $dbo->fetchArray($q); + $accodare = post('accodare'); - if (count($rs) > 0) { - //al primo ciclo preparo la fattura - if ($n_interventi == 0) { - //verifico se ho già fatture nello stato bozza per questo cliente - $iddocumento = $dbo->fetchArray('SELECT co_documenti.id AS iddocumento FROM co_documenti INNER JOIN co_statidocumento ON co_documenti.idstatodocumento = co_statidocumento.id WHERE co_statidocumento.descrizione = \'Bozza\' AND idanagrafica = '.prepare($idanagrafica))[0]['iddocumento']; + $module_name = 'Fatture di vendita'; - //preparo fattura - if (empty($iddocumento) or empty($accodare)) { - $dbo->query('INSERT INTO co_documenti (numero, numero_esterno, idanagrafica, idconto, idtipodocumento, idpagamento, data, idstatodocumento, idsede, id_segment) VALUES ('.prepare($numero).', '.prepare($numero_esterno).', '.prepare($idanagrafica).', '.prepare($idconto).', '.prepare($idtipodocumento).', '.prepare($idpagamento).', '.prepare($data).", (SELECT `id` FROM `co_statidocumento` WHERE `descrizione`='Bozza'), (SELECT idsede_fatturazione FROM an_anagrafiche WHERE idanagrafica=".prepare($idanagrafica).'), '.prepare($id_segment).')'); - $iddocumento = $dbo->lastInsertedID(); - } else { - $numero_esterno = $dbo->fetchArray('SELECT numero_esterno FROM co_documenti WHERE id = '.prepare($iddocumento))[0]['numero_esterno']; - } + // Segmenti + $id_fatture = Modules::get($module_name)['id']; + if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) { + $segments = Modules::getSegments($id_fatture); + $_SESSION['module_'.$id_fatture]['id_segment'] = isset($segments[0]['id']) ? $segments[0]['id'] : null; + } + $id_segment = $_SESSION['module_'.$id_fatture]['id_segment']; + + $interventi = $dbo->fetchArray('SELECT *, IFNULL((SELECT MIN(orario_inizio) FROM in_interventi_tecnici WHERE in_interventi_tecnici.idintervento = in_interventi.id), in_interventi.data_richiesta) AS data, in_statiintervento.descrizione AS stato FROM in_interventi INNER JOIN in_statiintervento ON in_interventi.idstatointervento=in_statiintervento.idstatointervento WHERE in_statiintervento.completato=1 AND in_interventi.id NOT IN (SELECT idintervento FROM co_righe_documenti WHERE idintervento IS NOT NULL) AND in_interventi.id NOT IN (SELECT idintervento FROM co_preventivi_interventi WHERE idintervento IS NOT NULL) AND in_interventi.id NOT IN (SELECT idintervento FROM co_contratti_promemoria WHERE idintervento IS NOT NULL) AND in_interventi.id IN ('.implode(',', $id_records).')'); + + // Lettura righe selezionate + foreach ($interventi as $intervento) { + $id_anagrafica = $intervento['idanagrafica']; + + $id_documento = $id_documento_cliente[$id_anagrafica]; + + // Se non c'è già una fattura appena creata per questo cliente, creo una fattura nuova + if (empty($id_documento)) { + if (!empty($accodare)) { + $documento = $dbo->fetchOne('SELECT co_documenti.id FROM co_documenti INNER JOIN co_statidocumento ON co_documenti.idstatodocumento = co_statidocumento.id WHERE co_statidocumento.descrizione = \'Bozza\' AND idanagrafica = '.prepare($id_anagrafica)); + + $id_documento = $documento['id']; + $id_documento_cliente[$id_anagrafica] = $id_documento; } - ++$n_interventi; + if (empty($id_documento)) { + $numero = get_new_numerofattura($data); + $numero_esterno = get_new_numerosecondariofattura($data); - $subtot_consuntivo = $rs[0]['tot_ore_consuntivo'] + $rs[0]['tot_km_consuntivo']; + $campo = ($dir == 'entrata') ? 'idpagamento_vendite' : 'idpagamento_acquisti'; - //Calcolo sconto se è stato arrotondato il prezzo - $subtot = $subtot_consuntivo; - $sconto = 0; + // Tipo di pagamento predefinito dall'anagrafica + $query = 'SELECT id FROM co_pagamenti WHERE id=(SELECT '.$campo.' AS pagamento FROM an_anagrafiche WHERE idanagrafica='.prepare($id_anagrafica).')'; + $rs = $dbo->fetchArray($query); + $idpagamento = $rs[0]['id']; - //Aggiungo un'eventuale sconto in base al listino del cliente - if ($prc_sconto < 0) { - $sconto += $subtot / 100 * abs($prc_sconto); - } - - $descrizione = 'Intervento numero '.$rs[0]['codice'].' del '.date('d/m/Y', strtotime($rs[0]['data']))."\n".html_entity_decode($rs[0]['descrizione']); - - //Aggiunta impianti - $rsi = $dbo->fetchArray('SELECT * FROM my_impianti_interventi INNER JOIN my_impianti ON my_impianti.id=my_impianti_interventi.idimpianto WHERE idintervento="'.$rs[0]['id'].'"'); - if (sizeof($rsi) > 0) { - $descrizione .= "\nIMPIANTI:\n"; - - for ($b = 0; $b < sizeof($rsi); ++$b) { - $descrizione .= $rsi[$b]['matricola'].' - '.str_replace('"', '&quot;', $rsi[$b]['nome'])."\n"; - } - } - //Aggiunta articoli utilizzati - $rsa = $dbo->fetchArray('SELECT mg_articoli.descrizione, mg_articoli.codice, mg_articoli.prezzo_vendita, mg_articoli_interventi.qta, mg_articoli_interventi.sconto FROM mg_articoli_interventi INNER JOIN mg_articoli ON mg_articoli_interventi.idarticolo=mg_articoli.id WHERE idintervento="'.$rs[0]['id'].'"'); - - if (sizeof($rsa) > 0) { - $descrizione .= "\nARTICOLI UTILIZZATI:\n"; - - for ($a = 0; $a < sizeof($rsa); ++$a) { - $descrizione .= $rsa[$a]['codice'].' - '.$rsa[$a]['descrizione'].' (x'.number_format($rsa[$a]['qta'], 2, ',', '.').")\n"; - $subtot += $rsa[$a]['prezzo_vendita']; - $sconto += $rsa[$a]['sconto'] * $rsa[$a]['qta']; - } - } - - //Aggiunta spese aggiuntive - $rsa = $dbo->fetchArray('SELECT descrizione, qta, prezzo_vendita FROM in_righe_interventi WHERE idintervento="'.$rs[0]['id'].'"'); - - if (sizeof($rsa) > 0) { - $descrizione .= "\nALTRI COSTI:\n"; - - for ($a = 0; $a < sizeof($rsa); ++$a) { - $descrizione .= $rsa[$a]['descrizione'].' (x'.number_format($rsa[$a]['qta'], 2, ',', '.').")\n"; - $subtot += $rsa[$a]['prezzo'] * $rsa[$a]['qta']; - $sconto += $rsa[$a]['sconto']; - } - } - - //Leggo l'anagrafica del cliente - $rs = $dbo->fetchArray("SELECT idanagrafica, (SELECT MIN(orario_inizio) FROM in_interventi_tecnici WHERE idintervento='".$rs[0]['id']."') AS data FROM `in_interventi` WHERE id='".$rs[0]['id']."'"); - $idanagrafica = $rs[0]['idanagrafica']; - $data = $rs[0]['data']; - - //Calcolo iva - $idiva = setting('Iva predefinita'); - $query = "SELECT * FROM co_iva WHERE id='".$idiva."'"; - $rs = $dbo->fetchArray($query); - - $iva = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; - $desc_iva = $rs[0]['descrizione']; - - //Calcolo rivalsa inps - $query = "SELECT * FROM co_rivalsainps WHERE id='".setting('Percentuale rivalsa INPS')."'"; - $rs = $dbo->fetchArray($query); - $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; - - //Calcolo ritenuta d'acconto - $query = "SELECT * FROM co_ritenutaacconto WHERE id='".setting("Percentuale ritenuta d'acconto")."'"; - $rs = $dbo->fetchArray($query); - $ritenutaacconto = ($subtot + $rivalsainps) / 100 * $rs[0]['percentuale']; - - //Aggiunta riga intervento sul documento - $query1 = "INSERT INTO co_righe_documenti( iddocumento, idintervento, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto ) VALUES( \"$iddocumento\", \"$idintervento\", \"".$idiva."\", \"$desc_iva\", \"$iva\", \"$iva_indetraibile\", \"$descrizione\", \"$subtot\", \"".$sconto.'", "ore", "1", "'.setting('Percentuale rivalsa INPS').'", "'.$rivalsainps.'", "'.setting("Percentuale ritenuta d'acconto").'", "'.$ritenutaacconto.'" )'; - if ($dbo->query($query1)) { - //Ricalcolo inps, ritenuta e bollo - if ($dir == 'entrata') { - ricalcola_costiagg_fattura($iddocumento); - } else { - ricalcola_costiagg_fattura($iddocumento, 0, 0, 0); + // Se alla non è stato associato un pagamento predefinito al cliente, leggo il pagamento dalle impostazioni + if (empty($idpagamento)) { + $idpagamento = setting('Tipo di pagamento predefinito'); } - //Metto l'intervento in stato "Fatturato" - $dbo->query("UPDATE in_interventi SET idstatointervento='FAT' WHERE id='$idintervento'"); + // Creazione nuova fattura + $dbo->insert('co_documenti', [ + 'numero' => $numero, + 'numero_esterno' => $numero_esterno, + 'idanagrafica' => $id_anagrafica, + 'idconto' => $id_conto, + 'idtipodocumento' => $tipo_documento, + 'idpagamento' => $idpagamento, + 'data' => $data, + 'id_segment' => $id_segment, + '#idstatodocumento' => "(SELECT `id` FROM `co_statidocumento` WHERE `descrizione`='Bozza')", + '#idsede' => 'IFNULL((SELECT idsede_fatturazione FROM an_anagrafiche WHERE idanagrafica='.prepare($id_anagrafica).'), 0)', + ]); + + $id_documento = $dbo->lastInsertedID(); + $id_documento_cliente[$id_anagrafica] = $id_documento; + ++$totale_n_ddt; } } + + $descrizione = tr('Intervento numero _NUM_ del _DATE_ [_STATE_]', [ + '_NUM_' => $intervento['codice'], + '_DATE_' => Translator::dateToLocale($intervento['data']), + '_STATE_' => $intervento['stato'], + ]); + + aggiungi_intervento_in_fattura($intervento['id'], $id_documento, $descrizione, $id_iva, $id_conto); + $n_interventi++; } if ($n_interventi > 0) { - flash()->info(tr('Fattura _NUM_ creata!', [ - '_NUM_' => $numero_esterno, - ])); - - flash()->info(tr('_NUM_ interventi fatturati!', [ + flash()->info(tr('_NUM_ interventi fatturati.', [ '_NUM_' => $n_interventi, ])); } else { @@ -239,7 +163,7 @@ return [ ], ], - 'creafatturavendita' => [ + 'crea_fattura' => [ 'text' => tr('Crea fattura'), 'data' => [ 'title' => tr('Vuoi davvero generare le fatture per questi interventi?'), diff --git a/modules/interventi/modutil.php b/modules/interventi/modutil.php index 3d2c93d35..2004cb936 100644 --- a/modules/interventi/modutil.php +++ b/modules/interventi/modutil.php @@ -340,3 +340,216 @@ function calcola_ore_intervento($orario_inizio, $orario_fine) return $ore; } + +function aggiungi_intervento_in_fattura($id_intervento, $id_fattura, $descrizione, $id_iva, $id_conto) +{ + $dbo = Database::getConnection(); + + // Leggo l'anagrafica del cliente + $rs = $dbo->fetchArray('SELECT idanagrafica, codice, (SELECT MIN(orario_inizio) FROM in_interventi_tecnici WHERE idintervento='.prepare($id_intervento).') AS data FROM `in_interventi` WHERE id='.prepare($id_intervento)); + $idanagrafica = $rs[0]['idanagrafica']; + $data = $rs[0]['data']; + $codice = $rs[0]['codice']; + + // Fatturo le ore di lavoro raggruppate per costo orario + $rst = $dbo->fetchArray('SELECT SUM( ROUND( TIMESTAMPDIFF( MINUTE, orario_inizio, orario_fine ) / 60, '.setting('Cifre decimali per quantità').' ) ) AS tot_ore, SUM(prezzo_ore_consuntivo) AS tot_prezzo_ore_consuntivo, SUM(sconto) AS tot_sconto, prezzo_ore_unitario FROM in_interventi_tecnici WHERE idintervento='.prepare($id_intervento).' GROUP BY prezzo_ore_unitario'); + + // Aggiunta riga intervento sul documento + if (sizeof($rst) == 0) { + $_SESSION['warnings'][] = tr('L\'intervento _NUM_ non ha sessioni di lavoro!', [ + '_NUM_' => $id_intervento, + ]); + } else { + for ($i = 0; $i < sizeof($rst); ++$i) { + $ore = $rst[$i]['tot_ore']; + + // Calcolo iva + $query = 'SELECT * FROM co_iva WHERE id='.prepare($id_iva); + $rs = $dbo->fetchArray($query); + + $sconto = $rst[$i]['tot_sconto']; + $subtot = $rst[$i]['tot_prezzo_ore_consuntivo']; + $iva = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; + $desc_iva = $rs[0]['descrizione']; + + // Calcolo rivalsa inps + $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); + $rs = $dbo->fetchArray($query); + $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + + // Calcolo ritenuta d'acconto + $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); + $rs = $dbo->fetchArray($query); + if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { + $ritenutaacconto = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + } else { + $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale']; + } + + $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_fattura).', '.prepare($id_intervento).', '.prepare($id_conto).', '.prepare($id_iva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($descrizione).', '.prepare($subtot).', '.prepare($sconto).', '.prepare($sconto).", 'UNT', 'ore', ".prepare($ore).', '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_fattura).'))'; + $dbo->query($query); + } + } + + $costi_intervento = get_costi_intervento($id_intervento); + + // Fatturo i diritti di chiamata raggruppati per costo + $rst = $dbo->fetchArray('SELECT COUNT(id) AS qta, SUM(prezzo_dirittochiamata) AS tot_prezzo_dirittochiamata FROM in_interventi_tecnici WHERE idintervento='.prepare($id_intervento).' AND prezzo_dirittochiamata > 0 GROUP BY prezzo_dirittochiamata'); + + // Aggiunta diritto di chiamata se esiste + for ($i = 0; $i < sizeof($rst); ++$i) { + // Calcolo iva + $query = 'SELECT * FROM co_iva WHERE id='.prepare($id_iva); + $rs = $dbo->fetchArray($query); + + $iva = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; + $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; + $desc_iva = $rs[0]['descrizione']; + + // Calcolo rivalsa inps + $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); + $rs = $dbo->fetchArray($query); + $rivalsainps = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; + + // Calcolo ritenuta d'acconto + $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); + $rs = $dbo->fetchArray($query); + $ritenutaacconto = $rst[$i]['tot_prezzo_dirittochiamata'] / 100 * $rs[0]['percentuale']; + + $dbo->insert('co_righe_documenti', [ + 'iddocumento' => $id_fattura, + 'idintervento' => $id_intervento, + 'idconto' => $id_conto, + 'idiva' => $id_iva, + 'desc_iva' => $desc_iva, + 'iva' => $iva, + 'iva_indetraibile' => $iva_indetraibile, + 'descrizione' => 'Diritto di chiamata', + 'subtotale' => $rst[$i]['tot_prezzo_dirittochiamata'], + 'sconto' => 0, + 'sconto_unitario' => 0, + 'tipo_sconto' => 'UNT', + 'um' => '-', + 'qta' => $rst[$i]['qta'], + 'idrivalsainps' => setting('Percentuale rivalsa INPS'), + 'rivalsainps' => $rivalsainps, + 'idritenutaacconto' => setting("Percentuale ritenuta d'acconto"), + 'ritenutaacconto' => $ritenutaacconto, + '#order' => '(SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_fattura).')', + ]); + } + + // Collego in fattura eventuali articoli collegati all'intervento + $rs2 = $dbo->fetchArray('SELECT mg_articoli_interventi.*, idarticolo FROM mg_articoli_interventi INNER JOIN mg_articoli ON mg_articoli_interventi.idarticolo=mg_articoli.id WHERE idintervento='.prepare($id_intervento).' AND (idintervento NOT IN(SELECT idintervento FROM co_righe_preventivi WHERE idpreventivo IN(SELECT idpreventivo FROM co_righe_documenti WHERE iddocumento='.prepare($id_fattura).')) AND idintervento NOT IN(SELECT idintervento FROM co_contratti_promemoria WHERE idcontratto IN(SELECT idcontratto FROM co_righe_documenti WHERE iddocumento='.prepare($id_fattura).')) )'); + for ($i = 0; $i < sizeof($rs2); ++$i) { + $riga = add_articolo_infattura($id_fattura, $rs2[$i]['idarticolo'], $rs2[$i]['descrizione'], $rs2[$i]['idiva'], $rs2[$i]['qta'], $rs2[$i]['prezzo_vendita'] * $rs2[$i]['qta'], $rs2[$i]['sconto'], $rs2[$i]['sconto_unitario'], $rs2[$i]['tipo_sconto'], $id_intervento, 0, $rs2[$i]['um']); + + // Lettura lotto, serial, altro dalla riga dell'ordine + $dbo->query('INSERT INTO mg_prodotti (id_riga_documento, id_articolo, dir, serial, lotto, altro) SELECT '.prepare($riga).', '.prepare($rs2[$i]['idarticolo']).', '.prepare($dir).', serial, lotto, altro FROM mg_prodotti AS t WHERE id_riga_intervento='.prepare($rs2[$i]['id'])); + } + + // Aggiunta spese aggiuntive come righe generiche + $query = 'SELECT * FROM in_righe_interventi WHERE idintervento='.prepare($id_intervento).' AND (idintervento NOT IN(SELECT idintervento FROM co_righe_preventivi WHERE idpreventivo IN(SELECT idpreventivo FROM co_righe_documenti WHERE iddocumento='.prepare($id_fattura).')) AND idintervento NOT IN(SELECT idintervento FROM co_contratti_promemoria WHERE idcontratto IN(SELECT idcontratto FROM co_righe_documenti WHERE iddocumento='.prepare($id_fattura).')) )'; + $rsr = $dbo->fetchArray($query); + if (sizeof($rsr) > 0) { + for ($i = 0; $i < sizeof($rsr); ++$i) { + // Calcolo iva + $query = 'SELECT * FROM co_iva WHERE id='.prepare($rsr[$i]['idiva']); + $rs = $dbo->fetchArray($query); + $desc_iva = $rs[0]['descrizione']; + + $subtot = $rsr[$i]['prezzo_vendita'] * $rsr[$i]['qta']; + $sconto = $rsr[$i]['sconto']; + $iva = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; + + // Calcolo rivalsa inps + $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); + $rs = $dbo->fetchArray($query); + $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + + // Calcolo ritenuta d'acconto + $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); + $rs = $dbo->fetchArray($query); + if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { + $ritenutaacconto = ($subtot - $sconto) / 100 * $rs[0]['percentuale']; + } else { + $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale']; + } + + $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_fattura).', '.prepare($id_intervento).', '.prepare($id_conto).', '.prepare($id_iva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($rsr[$i]['descrizione']).', '.prepare($subtot).', '.prepare($rsr[$i]['sconto']).', '.prepare($rsr[$i]['sconto_unitario']).', '.prepare($rsr[$i]['tipo_sconto']).', '.prepare($rsr[$i]['um']).', '.prepare($rsr[$i]['qta']).', '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_fattura).'))'; + $dbo->query($query); + } + } + + // Aggiunta km come "Trasferta" (se c'è) + if ($costi_intervento['viaggio_addebito'] > 0) { + // Calcolo iva + $query = 'SELECT * FROM co_iva WHERE id='.prepare($id_iva); + $dati = $dbo->fetchArray($query); + $desc_iva = $dati[0]['descrizione']; + + $subtot = $costi_intervento['viaggio_addebito']; + $sconto = $costi_intervento['viaggio_addebito'] - $costi_intervento['viaggio_scontato']; + $iva = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; + $iva_indetraibile = $iva / 100 * $dati[0]['indetraibile']; + + // Calcolo rivalsa inps + $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); + $dati = $dbo->fetchArray($query); + $rivalsainps = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; + + // Calcolo ritenuta d'acconto + $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); + $dati = $dbo->fetchArray($query); + if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { + $ritenutaacconto = ($subtot - $sconto) / 100 * $dati[0]['percentuale']; + } else { + $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $dati[0]['percentuale']; + } + + $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_fattura).', '.prepare($id_intervento).', '.prepare($id_conto).', '.prepare($id_iva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare('Trasferta intervento '.$codice.' del '.Translator::dateToLocale($data)).', '.prepare($subtot).', '.prepare($sconto).', '.prepare($sconto).", 'UNT', '', 1, ".prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_fattura).'))'; + $dbo->query($query); + } + + // Aggiunta sconto + if (!empty($costi_intervento['sconto_globale'])) { + $subtot = -$costi_intervento['sconto_globale']; + + // Calcolo iva + $query = 'SELECT * FROM co_iva WHERE id='.prepare($id_iva); + $rs = $dbo->fetchArray($query); + $desc_iva = $rs[0]['descrizione']; + + $iva = ($subtot) / 100 * $rs[0]['percentuale']; + $iva_indetraibile = $iva / 100 * $rs[0]['indetraibile']; + + // Calcolo rivalsa inps + $query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(setting('Percentuale rivalsa INPS')); + $rs = $dbo->fetchArray($query); + $rivalsainps = ($subtot) / 100 * $rs[0]['percentuale']; + + // Calcolo ritenuta d'acconto + $query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(setting("Percentuale ritenuta d'acconto")); + $rs = $dbo->fetchArray($query); + if (setting("Metodologia calcolo ritenuta d'acconto predefinito") == 'Imponibile') { + $ritenutaacconto = $subtot / 100 * $rs[0]['percentuale']; + } else { + $ritenutaacconto = ($subtot + $rivalsainps) / 100 * $rs[0]['percentuale']; + } + + $query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, calcolo_ritenutaacconto, `order`) VALUES('.prepare($id_fattura).', NULL, '.prepare($id_conto).', '.prepare($id_iva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare('Sconto '.$descrizione).', '.prepare($subtot).', 1, '.prepare(setting('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(setting("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', '.prepare(setting("Metodologia calcolo ritenuta d'acconto predefinito")).', (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_fattura).'))'; + $dbo->query($query); + } + + // Ricalcolo inps, ritenuta e bollo + if ($dir == 'entrata') { + ricalcola_costiagg_fattura($id_fattura); + } else { + ricalcola_costiagg_fattura($id_fattura); + } + + // Metto l'intervento in stato "Fatturato" + $dbo->query("UPDATE in_interventi SET idstatointervento=(SELECT idstatointervento FROM in_statiintervento WHERE descrizione='Fatturato') WHERE id=".prepare($id_intervento)); +} diff --git a/src/Backup.php b/src/Backup.php index 58937db1c..ab4ddcae4 100644 --- a/src/Backup.php +++ b/src/Backup.php @@ -170,7 +170,7 @@ class Backup $files = Symfony\Component\Finder\Finder::create() ->files() ->exclude($ignores['dirs']) - ->ignoreDotFiles(true) + ->ignoreDotFiles(false) ->ignoreVCS(true) ->in(DOCROOT) ->in(self::getDatabaseDirectory()); diff --git a/templates/fatture/footer.php b/templates/fatture/footer.php index 9700ba1d8..0f205cdf9 100644 --- a/templates/fatture/footer.php +++ b/templates/fatture/footer.php @@ -380,6 +380,26 @@ echo ' $dicitura_fissa_fattura$ - +'; -$default_footer$'; + + + +if ($options['hide_footer']) { + + echo ' + + + + + +
+   + +   +
'; + +} +else{ + echo '$default_footer$'; +} \ No newline at end of file diff --git a/templates/fatture/header.php b/templates/fatture/header.php index 06cb5b34e..4f94a1795 100644 --- a/templates/fatture/header.php +++ b/templates/fatture/header.php @@ -1,10 +1,22 @@ +
+
+
+
+
+
'; +}else{ + echo ' + + $default_header$'; +} + echo ' - -$default_header$
-
diff --git a/update/2_4_1.sql b/update/2_4_1.sql index 1c45a40ce..1384b1e35 100644 --- a/update/2_4_1.sql +++ b/update/2_4_1.sql @@ -487,3 +487,9 @@ UPDATE `zz_views` SET `query` = '\'Intervento\'' WHERE `id_module` = (SELECT `id -- Flag per definire i segmenti di note di accredito e di addebito ALTER TABLE `zz_segments` ADD `predefined_accredito` TINYINT(1) NOT NULL AFTER `predefined`, ADD `predefined_addebito` TINYINT(1) NOT NULL AFTER `predefined_accredito`; + +-- Fattura di vendita senza intestazione (per carta intestata) +INSERT INTO `zz_prints` (`id`, `id_module`, `is_record`, `name`, `title`, `directory`, `previous`, `options`, `icon`, `version`, `compatibility`, `order`, `main`, `default`, `enabled`) VALUES +(NULL, (SELECT id FROM zz_modules WHERE name='Fatture di vendita'), 1, 'Fattura di vendita (senza intestazione)', 'Fattura di vendita (senza intestazione)', 'fatture', 'iddocumento', '{"hide_header":true, "hide_footer":true}', 'fa fa-print', '', '', 0, 0, 1, 1); +UPDATE `zz_prints` SET `main` = '1' WHERE `name` = 'Fattura di vendita'; +