diff --git a/CHANGELOG.md b/CHANGELOG.md
index 564b0e7f2..8db9e1787 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,11 +4,8 @@ Tutti i maggiori cambiamenti di questo progetto saranno documentati in questo fi
Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://keepachangelog.com/), e il progetto segue il [Semantic Versioning](http://semver.org/) per definire le versioni delle release.
-## Tabella dei contenuti
-
-- [Tabella dei contenuti](#tabella-dei-contenuti)
- [2.3 (In sviluppo)](#23-in-sviluppo)
- [2.2 (2016-11-10)](#22-2016-11-10)
- [2.1 (2015-04-02)](#21-2015-04-02)
@@ -21,55 +18,26 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
- Creazione della documentazione ufficiale per sviluppatori (disponibile nel Wiki e in `docs/`)
- Creazione di un sistema API ufficiale
-- Creazione di un sistema per controllare gli accessi degli utenti
-- Nuovi moduli _Viste_, _Utenti e permessi_, _Opzioni_, con ulteriori moduli per la gestione di tabelle secondarie (_IVA_, _Pagamenti_, ...)
-- Nuova struttura per permettere il richiamo via AJAX delle procedure per la creazione di nuovi elementi all'esterno del modulo specifico (tramite il file `add.php`)
-- Possibilità di vedere se ci sono altri utenti che stanno visualizzando lo stesso record (opzione "Sessione avanzata" nel modulo _Opzioni_)
-- Nuove funzioni PHP (con commenti) in `lib/functions.php`
- - getRevision
- - str\_replace\_once
- - filter
- - post
- - get
- - readSQLFile
- - array\_pluck
- - starts_with
- - ends_with
- - slashes
- - prepare
- - tr (con aggiunta della funzione di gettext nel caso questi non sia abilitato - `_`)
- - safe\_truncate (in sostituzione a cut\_text)
- - secure\_random\_string
- - random\_string
- - safe\_truncate
- - force\_download
- - isHTTPS
-- Nuovi oggetti per la gestione delle operazioni di base (posizionati in `lib/classes/`)
- - Auth
- - Database
- - Filter (in sostituzione a HTMLHelper, ora deprecato ma ancora presente)
- - HTMLBuilder
- - Modules
- - Options
- - Permissions
- - Translator (per la futura internazionalizzazione e traduzione del progetto, inoltre disponibile in `locale/it/`)
- - Update
- - Widgtes (modificati per lavorare secondo una metodologia statica)
+- Creazione di sistemi centralizzati per la gestione della connessione al database, dell'autenticazione, degli input degli utenti, dei permessi, delle impostazioni, delle traduzioni e degli aggiornamenti (secondo una logica ad oggetti)
- Nuova gestione delle operazioni di debugging e logging
+- Nuovi plugins e widgets
+- Nuovi moduli _Viste_, _Utenti e permessi_, _Opzioni_, con ulteriori moduli per la gestione di tabelle secondarie (_IVA_, _Pagamenti_, ...)
+- Possibilità di vedere se ci sono altri utenti che stanno visualizzando lo stesso record (opzione "Sessione avanzata" nel modulo _Opzioni_)
+- Possibilità di creare nuovi elementi dei moduli all'interno del record (oltre che dalla visualizzazione generale del modulo)
+- Nuova struttura per permettere il richiamo via AJAX delle procedure per la creazione di nuovi elementi all'esterno del modulo specifico (tramite il file `add.php`)
+- Miglioramento della documentazione integrata delle funzioni PHP in `lib/functions.php`
- Nuovo file `lib/init.js` per permettere una rapida inizializzazione dei componenti JS
- Creazione di cartelle di default per i backup (`backup/`) e i log (`logs/`)
- Nuovo pulsante per resettare i filtri di ricerca (nella sezione generica dei moduli)
- Nuovo modulo per gestire i file `.ini` dei componenti degli impianti
-- Nuovi plugins e widgets
- Nuova gestione generalizzata degli upload
- Nuove funzioni relative ai diversi moduli
- - Possibilità di inserire in fattura un range di serial number
- Possibilità di individuare i componenti dell'impianto su cui l'intervento viene effettuato
- Possibilità di gestire le ritenute d'acconto
- Firma degli interventi
- Selezione della tipologia di attività per ogni sessione di lavoro
- Tabella riepilogativa più completa dei costi
- - Sconto incondizionato in _Interventi_
+ - Sconto globale in _Interventi_, _Fatture_, _DDT_, _Ordini_, _Preventivi_
### Modificato (Changed)
@@ -80,16 +48,16 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
- Miglioramenti delle informazioni disponibili sul progetto e della procedura di segnalazione dei bug
- Impianti ora identificati tramite numerazione univoca (non più tramite matricola)
- Sostituzione di Chosen con Select2
-- Miglioramento dell'interpretazione del template per la generazione degli input (`lib/htmlbuilder.php`), ora inoltre disponibile ovunque all'interno del progetto
+- Miglioramento dell'interpretazione del template per la generazione degli input, ora disponibile ovunque all'interno del progetto
- Miglioramento generale sull'identificazione del modulo attualmente in uso e sull'inclusione dei file necessari per il funzionamento
- Miglioramento della gestione dei permessi
-- Gestione della connessione al database tramite Medoo (possibile futuro ampliamento dei DMBS supportati)
+- Gestione della connessione al database tramite PDO (con possibile futuro ampliamento dei DMBS supportati)
- Gestione delle tabelle ora completamente basata su Datatables
- Ottimizzazione della schermata per aggiunta dell'intervento
- Miglioramento dei riquadri delle spese aggiuntive e degli articoli
- La prima anagrafica di tipo Azienda caricata viene impostata come Azienda predefinita
- Passaggio completo all'estensione `.php` per tutti i file dei moduli
-- Miglioramento dei permessi di visione per il modulo _MyImpianti_, per cui ora ogni cliente vede solo i propri impianti
+- Miglioramento dei permessi di visione per il modulo _MyImpianti_ (ora ogni cliente vede solo i propri impianti)
- Miglioramento della procedura di aggiornamento del gestionale
- Aggiunto sistema di ripresa dell'aggiornamento (se questi è stato bloccato in una fase intermedia tra i singoli aggiornamenti)
- Aggiunto sistema di bloccaggio dell'aggiornamento, per evitare problemi nel caso molteplici richieste di update
@@ -99,20 +67,7 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
### Deprecato (Deprecated)
- Classe HTMLHelper, a favore della nuova classe Filter
-- Funzioni PHP
- - readDateTime
- - readDateTimePrint
- - get\_permessi
- - saveDateTime
- - saveDate
- - fix\_str
- - clean
- - makeid
- - read
- - readTime
- - readDate
- - build\_html\_element
-
+- Funzioni PHP (`lib/deprecated.php`)
### Rimosso (Removed)
@@ -148,8 +103,9 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
### Sicurezza (Security)
-- Aggiunta protezione contro l'XSS
+- Aggiunta protezione contro attacchi di tipo XSS
- Aggiunta base per contrastare l'SQL Injection
+- Aggiunta protezione (temporaneamente disabilitata) contro attacchi CSRF
- Passaggio della codifica della password con algoritmo di hashing BCrypt
## 2.2 (2016-11-10)
diff --git a/modules/anagrafiche/actions.php b/modules/anagrafiche/actions.php
index 1bd7aa66c..271064a6a 100644
--- a/modules/anagrafiche/actions.php
+++ b/modules/anagrafiche/actions.php
@@ -68,14 +68,8 @@ switch (post('op')) {
$dbo->query('UPDATE an_anagrafiche SET codice='.prepare($post['codice']).' WHERE idanagrafica='.prepare($id_record));
}
- // Aggiorno gli agenti secondari collegati
- $dbo->query('DELETE FROM an_anagrafiche_agenti WHERE idanagrafica='.prepare($id_record));
-
- if (!empty($post['idagenti'])) {
- foreach ($post['idagenti'] as $idagente) {
- $dbo->query('INSERT INTO an_anagrafiche_agenti(idanagrafica, idagente) VALUES ('.prepare($id_record).', '.prepare($idagente).')');
- }
- }
+ // Aggiorno gli agenti collegati
+ $dbo->sync('an_anagrafiche_agenti', ['idanagrafica' => $id_record], ['idagente' => (array) $post['idagenti']]);
// Se l'agente di default è stato elencato anche tra gli agenti secondari lo rimuovo
if(!empty($post['idagente'])){
diff --git a/modules/anagrafiche/edit.php b/modules/anagrafiche/edit.php
index 6e5291f9c..994cd94bc 100644
--- a/modules/anagrafiche/edit.php
+++ b/modules/anagrafiche/edit.php
@@ -186,9 +186,6 @@ if ($fornitore) {
{[ "type": "select", "label": "", "name": "idtipointervento_default", "values": "query=SELECT idtipointervento AS id, descrizione FROM in_tipiintervento ORDER BY descrizione ASC", "value": "$idtipointervento_default$" ]}
-
{[ "type": "select", "label": "Agente principale", "name": "idagente", "values": "query=SELECT an_anagrafiche.idanagrafica AS id, IF(deleted=1, CONCAT(ragione_sociale, ' (Eliminato)'), ragione_sociale ) AS descrizione FROM an_anagrafiche INNER JOIN (an_tipianagrafiche_anagrafiche INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica) ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE (descrizione='Agente' AND deleted=0)ORDER BY ragione_sociale", "value": "$idagente$" ]}
diff --git a/modules/contratti/modutil.php b/modules/contratti/modutil.php
index 77ee95c9e..32d966b9c 100644
--- a/modules/contratti/modutil.php
+++ b/modules/contratti/modutil.php
@@ -170,6 +170,7 @@ function get_stato_preventivo($idpreventivo)
/**
* Aggiorna il budget del preventivo leggendo tutte le righe inserite.
+ * @deprecated 2.3
*/
function update_budget_preventivo($idpreventivo)
{
diff --git a/modules/fatture/actions.php b/modules/fatture/actions.php
index 2dc39a5eb..75d531cb6 100644
--- a/modules/fatture/actions.php
+++ b/modules/fatture/actions.php
@@ -197,6 +197,18 @@ switch (post('op')) {
rimuovi_articolo_dafattura($rs[$i]['idarticolo'], $id_record, $rs[$i]['id']);
}
+ // Se delle righe sono state create da un ordine, devo riportare la quantità evasa nella tabella degli ordini al valore di prima, riaggiungendo la quantità che sto togliendo
+ $rs = $dbo->fetchArray('SELECT qta, descrizione, idarticolo, idordine, idiva FROM co_righe_documenti WHERE iddocumento='.prepare($iddocumento));
+ foreach ($rs as $r) {
+ $dbo->query('UPDATE or_righe_ordini SET qta_evasa=qta_evasa-'.$r['qta'].' WHERE descrizione='.prepare($r['descrizione']).' AND idarticolo='.prepare($r['idarticolo']).' AND idordine='.prepare($r['idordine']).' AND idiva='.prepare($r['idiva']));
+ }
+
+ // Se delle righe sono state create da un ddt, devo riportare la quantità evasa nella tabella dei ddt al valore di prima, riaggiungendo la quantità che sto togliendo
+ $rs = $dbo->fetchArray('SELECT qta, descrizione, idarticolo, idddt, idiva FROM co_righe_documenti WHERE iddocumento='.prepare($iddocumento));
+ foreach ($rs as $r) {
+ $dbo->query('UPDATE dt_righe_ddt SET qta_evasa=qta_evasa-'.$r['qta'].' WHERE descrizione='.prepare($r['descrizione']).' AND idarticolo='.prepare($r['idarticolo']).' AND idddt='.prepare($r['idddt']).' AND idiva='.prepare($r['idiva']));
+ }
+
$dbo->query('DELETE FROM co_documenti WHERE id='.prepare($id_record));
$dbo->query('DELETE FROM co_righe_documenti WHERE iddocumento='.prepare($id_record));
$dbo->query('DELETE FROM co_scadenziario WHERE iddocumento='.prepare($id_record));
@@ -321,12 +333,12 @@ switch (post('op')) {
// Calcolo rivalsa inps
$query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(get_var('Percentuale rivalsa INPS'));
$rs = $dbo->fetchArray($query);
- $rivalsainps = $subtot / 100 * $rs[0]['percentuale'];
+ $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale'];
// Calcolo ritenuta d'acconto
$query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(get_var("Percentuale ritenuta d'acconto"));
$rs = $dbo->fetchArray($query);
- $ritenutaacconto = ($subtot + $rivalsainps) / 100 * $rs[0]['percentuale'];
+ $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale'];
$query = 'INSERT INTO co_righe_documenti(iddocumento, idintervento, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, idgruppo, `order`) VALUES('.prepare($id_record).', NULL, '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare('Trasferta intervento '.$codice.' del '.Translator::dateToLocale($data)).', '.prepare($subtot).", 'km' ".prepare($km).', '.prepare(get_var('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(get_var("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', (SELECT IFNULL(MAX(`idgruppo`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'), (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))';
$dbo->query($query);
@@ -377,12 +389,12 @@ switch (post('op')) {
// Calcolo rivalsa inps
$query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(get_var('Percentuale rivalsa INPS'));
$rs = $dbo->fetchArray($query);
- $rivalsainps = $subtot / 100 * $rs[0]['percentuale'];
+ $rivalsainps = ($subtot - $sconto) / 100 * $rs[0]['percentuale'];
// Calcolo ritenuta d'acconto
$query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(get_var("Percentuale ritenuta d'acconto"));
$rs = $dbo->fetchArray($query);
- $ritenutaacconto = ($subtot + $rivalsainps) / 100 * $rs[0]['percentuale'];
+ $ritenutaacconto = ($subtot - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale'];
// Aggiunta riga intervento sul documento
$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, idgruppo, `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_unitario).', '.prepare($tipo_sconto).", '-', ".prepare($qta).', '.prepare(get_var('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(get_var("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', (SELECT IFNULL(MAX(`idgruppo`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'), (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))';
@@ -542,12 +554,12 @@ switch (post('op')) {
// Calcolo rivalsa inps
$query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(get_var('Percentuale rivalsa INPS'));
$rs = $dbo->fetchArray($query);
- $rivalsainps = $prezzo / 100 * $rs[0]['percentuale'];
+ $rivalsainps = ($prezzo - $sconto) / 100 * $rs[0]['percentuale'];
// Calcolo ritenuta d'acconto
$query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(get_var("Percentuale ritenuta d'acconto"));
$rs = $dbo->fetchArray($query);
- $ritenutaacconto = ($prezzo) / 100 * $rs[0]['percentuale'];
+ $ritenutaacconto = ($prezzo - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale'];
// Aggiunta riga contratto sul documento
$query = 'INSERT INTO co_righe_documenti(iddocumento, idcontratto, idconto, idiva, desc_iva, iva, iva_indetraibile, descrizione, subtotale, sconto, sconto_unitario, tipo_sconto, um, qta, idrivalsainps, rivalsainps, idritenutaacconto, ritenutaacconto, idgruppo, `order`) VALUES('.prepare($id_record).', '.prepare($idcontratto).', '.prepare($idconto).', '.prepare($idiva).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($descrizione).', '.prepare($prezzo).', '.prepare($sconto).', '.prepare($sconto_unitario).', '.prepare($tipo_sconto).", '-', 1, ".prepare(get_var('Percentuale rivalsa INPS')).', '.prepare($rivalsainps).', '.prepare(get_var("Percentuale ritenuta d'acconto")).', '.prepare($ritenutaacconto).', (SELECT IFNULL(MAX(`idgruppo`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'), (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento='.prepare($id_record).'))';
@@ -627,7 +639,7 @@ switch (post('op')) {
// Calcolo rivalsa inps
$query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(post('idrivalsainps'));
$rs = $dbo->fetchArray($query);
- $rivalsainps = $prezzo * $qta / 100 * $rs[0]['percentuale'];
+ $rivalsainps = ($prezzo * $qta - $sconto) / 100 * $rs[0]['percentuale'];
// Calcolo ritenuta d'acconto
$query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(post('idritenutaacconto'));
@@ -692,12 +704,12 @@ switch (post('op')) {
// Calcolo rivalsa inps
$query = 'SELECT * FROM co_rivalsainps WHERE id='.prepare(post('idrivalsainps'));
$rs = $dbo->fetchArray($query);
- $rivalsainps = $prezzo * $qta / 100 * $rs[0]['percentuale'];
+ $rivalsainps = ($prezzo * $qta - $sconto) / 100 * $rs[0]['percentuale'];
// Calcolo ritenuta d'acconto
$query = 'SELECT * FROM co_ritenutaacconto WHERE id='.prepare(post('idritenutaacconto'));
$rs = $dbo->fetchArray($query);
- $ritenutaacconto = (($prezzo * $qta) + $rivalsainps) / 100 * $rs[0]['percentuale'];
+ $ritenutaacconto = (($prezzo * $qta) - $sconto + $rivalsainps) / 100 * $rs[0]['percentuale'];
// Modifica riga generica sul documento
$query = 'UPDATE co_righe_documenti SET idconto='.prepare($idconto).', idiva='.prepare($idiva).', desc_iva='.prepare($desc_iva).', iva='.prepare($iva).', iva_indetraibile='.prepare($iva_indetraibile).', descrizione='.prepare($descrizione).', subtotale='.prepare($subtot).', sconto='.prepare($sconto).', sconto_unitario='.prepare($sconto_unitario).', tipo_sconto='.prepare($tipo_sconto).', um='.prepare($um).', idritenutaacconto='.prepare(post('idritenutaacconto')).', ritenutaacconto='.prepare($ritenutaacconto).', idrivalsainps='.prepare(post('idrivalsainps')).', rivalsainps='.prepare($rivalsainps).' WHERE idgruppo='.prepare($idgruppo).' AND iddocumento='.prepare($iddocumento);
diff --git a/modules/partitario/dettagli_movimento.php b/modules/partitario/dettagli_movimento.php
new file mode 100644
index 000000000..d0a982b13
--- /dev/null
+++ b/modules/partitario/dettagli_movimento.php
@@ -0,0 +1,55 @@
+fetchArray($query);
+
+echo '
+
+
+ '._('Descrizione riga').' |
+ '._('Imponibile').' |
+ '._('Q.tà').' | '._('Um').'
+
';
+
+$totale_imponibile = 0;
+
+for ($i = 0; $i < sizeof($rs); ++$i) {
+ echo '
+
+
+ '.$rs[$i]['desc_riga'].'
+ |
+
+
+ '.Translator::numberToLocale($rs[$i]['imponibile']).' €
+ |
+
+ '.Translator::numberToLocale($rs[$i]['qta']).'
+ |
+
+
+ '.$rs[$i]['um'].'
+ |
+
';
+
+ $totale_imponibile += $rs[$i]['imponibile'];
+ $totale_qta += $rs[$i]['qta'];
+}
+
+echo '
+
+ '._('Totali').': |
+ '.Translator::numberToLocale($totale_imponibile).' € |
+ '.Translator::numberToLocale($totale_qta).' |
+ |
+
+
+
+
'.$rs[0]['desc_fatt'].'';
diff --git a/modules/partitario/edit.php b/modules/partitario/edit.php
index 21c3c671e..f6289b7b2 100644
--- a/modules/partitario/edit.php
+++ b/modules/partitario/edit.php
@@ -104,7 +104,8 @@ for ($x = 0; $x < $n1; ++$x) {
if ($rs[$i]['iddocumento'] != '') {
($rs[$i]['dir'] == 'entrata') ? $id_module = Modules::getModule('Fatture di vendita')['id'] : $id_module = Modules::getModule('Fatture di acquisto')['id'];
- echo " ".$rs[$i]['descrizione']."\n";
+ echo "".$rs[$i]['descrizione']."\n";
+ //echo " ".$rs[$i]['descrizione']."\n";
} else {
echo ' '.$rs[$i]['descrizione']."\n";
}
diff --git a/modules/preventivi/modutil.php b/modules/preventivi/modutil.php
index dfef46aba..d4a69c60b 100644
--- a/modules/preventivi/modutil.php
+++ b/modules/preventivi/modutil.php
@@ -180,6 +180,7 @@ function get_stato_preventivo($idpreventivo)
/**
* Aggiorna il budget del preventivo leggendo tutte le righe inserite.
+ * @deprecated 2.3
*/
function update_budget_preventivo($idpreventivo)
{