This commit is contained in:
MatteoPistorello 2020-11-30 10:33:28 +01:00
commit aef44daa1e
24 changed files with 470 additions and 191 deletions

View File

@ -573,19 +573,19 @@ if (!Auth::check() && (!empty($messages['info']) || !empty($messages['warning'])
</div>';
}
// Controllo sullo spazio disponibile
// Messaggio informativo per l'esaurimento dello spazio totale disponibile nel server
$free_space = disk_free_space('.');
$space_limit = 200; // MB
$space_limit = 1; // GB
if ($free_space < ($space_limit * 1024 ^ 3)) {
echo '
<div class="callout callout-warning">
<h4>
<i class="fa fa-warning"></i> '.tr('Spazio in esaurimento').'
</h4>
<p>'.tr('Lo spazio a disposizione del gestionale è in esaurimento: sono al momento disponibili _TOT_', [
'_TOT_' => FileSystem::formatBytes($free_space),
<div class="callout callout-warning">
<h4>
<i class="fa fa-warning"></i> '.tr('Spazio in esaurimento').'
</h4>
<p>'.tr('Lo spazio a disposizione del gestionale è in esaurimento: sono al momento disponibili _TOT_', [
'_TOT_' => FileSystem::formatBytes($free_space),
]).'.</p>
<p>'.tr('Questo può risultare un serio problema per la continuità di funzionamento del software, poichè le operazioni più espansive riguardanti lo spazio di archiviazione possono provocare malfunzionamento imprevedibili').'. '.tr('Operazioni di backup, caricamento di allegati o anche il semplice utilizzo del gestionale possono rendere i dati inaffidabili, provocando pertanto una perdita irreversibile delle informazioni salvate').'.</p>
<p>'.tr("Contatta gli amministratori di sistema oppure l'assistenza tecnica per risolvere il problema").'.</p>
</div>';
<p>'.tr('Questo può risultare un serio problema per la continuità di funzionamento del software, poichè le operazioni più espansive riguardanti lo spazio di archiviazione possono provocare malfunzionamento imprevedibili').'. '.tr('Operazioni di backup, caricamento di allegati o anche il semplice utilizzo del gestionale possono rendere i dati inaffidabili, provocando pertanto una perdita irreversibile delle informazioni salvate').'.</p>
<p>'.tr("Contatta gli amministratori di sistema oppure l'assistenza tecnica per risolvere al più presto il problema").'.</p>
</div>';
}

View File

@ -528,3 +528,33 @@ if (!function_exists('readSQLFile')) {
return $queryLine;
}
}
if (!function_exists('temp_file')) {
/**
* Crea un file temporaneo e lo imposta per la rimozione alla fine dell'esecuzione.
*
* @param $name
* @param $content
*
* @return string
*/
function temp_file($name = null, $content = null)
{
if (empty($name)) {
$name = secure_random_string();
}
$file = DIRECTORY_SEPARATOR.
trim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).
DIRECTORY_SEPARATOR.
ltrim($name, DIRECTORY_SEPARATOR);
file_put_contents($file, $content);
register_shutdown_function(function () use ($file) {
unlink($file);
});
return $file;
}
}

View File

@ -91,7 +91,6 @@ if (!function_exists('base_dir')) {
}
}
// Aggiornamenti
if (setting('Attiva aggiornamenti')) {
$alerts = [];

View File

@ -252,9 +252,11 @@ switch ($resource) {
$where[] = 'idanagrafica='.prepare($superselect['idanagrafica']);
/*
if (!empty($search)) {
$search_fields[] = 'citta LIKE '.prepare('%'.$search.'%');
}
*/
}
break;

View File

@ -20,6 +20,7 @@
use Geocoder\Provider\GoogleMaps;
use Ivory\HttpAdapter\CurlHttpAdapter;
use Modules\Anagrafiche\Anagrafica;
use Modules\Anagrafiche\Export\CSV;
include_once __DIR__.'/../../core.php';
$google = setting('Google Maps API key');
@ -64,26 +65,18 @@ switch (post('op')) {
break;
case 'export-csv':
$file = temp_file();
$exporter = new CSV($file);
case 'download-csv':
$dir = base_dir().'/files/export_anagrafiche/';
directory($dir.'tmp/');
$file = secure_random_string().'.csv';
$dir_csv = slashes($dir.'tmp/'.$file);
$filename = 'anagrafiche.csv';
$t = new Modules\Anagrafiche\Export\CSV($dir_csv);
if($t->exportRecords()){
download($dir_csv, $filename);
delete($dir.'tmp/');
}
// Esportazione dei record selezionati
$anagrafiche = Anagrafica::whereIn('id', $id_records)->get();
$exporter->setRecords($anagrafiche);
$count = $exporter->exportRecords();
download($file, 'anagrafiche.csv');
break;
}
$operations = [];
@ -98,8 +91,8 @@ if (App::debug()) {
],
];
$operations['download-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta tutto').'</span> <span class="label label-danger" >beta</span>',
$operations['export-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta selezionati').'</span> <span class="label label-danger" >beta</span>',
'data' => [
'msg' => tr('Vuoi davvero esportare un CSV con tutte le anagrafiche?'),
'button' => tr('Procedi'),
@ -107,7 +100,6 @@ if (App::debug()) {
'blank' => true,
],
];
}
if (App::debug() && $google) {

View File

@ -114,7 +114,7 @@ class CSV extends CSVExporter
'label' => 'Note',
],
[
'field' => 'id_nazione',
'field' => 'nazione.nome',
'label' => 'Nazione',
],
[

View File

@ -36,7 +36,6 @@ switch (post('op')) {
break;
case 'delete-bulk':
foreach ($id_records as $id) {
$elementi = $dbo->fetchArray('SELECT `co_documenti`.`id`, `co_documenti`.`data`, `co_documenti`.`numero`, `co_documenti`.`numero_esterno`, `co_tipidocumento`.`descrizione` AS tipo_documento, `co_tipidocumento`.`dir` FROM `co_documenti` JOIN `co_tipidocumento` ON `co_tipidocumento`.`id` = `co_documenti`.`idtipodocumento` WHERE `co_documenti`.`id` IN (SELECT `iddocumento` FROM `co_righe_documenti` WHERE `idarticolo` = '.prepare($id).')

View File

@ -191,11 +191,11 @@ include_once __DIR__.'/../../core.php';
</div>
<div class="col-md-4">
{[ "type": "number", "label": "<?php echo tr('Fattore moltiplicativo'); ?>", "name": "fattore_um_secondaria", "value": "$fattore_um_secondaria$", "help": "<?php echo tr("Fattore moltiplicativo per l'unità di misura da utilizzare nelle stampe di Ordini fornitori"); ?>" ]}
{[ "type": "number", "label": "<?php echo tr('Fattore moltiplicativo'); ?>", "name": "fattore_um_secondaria", "value": "$fattore_um_secondaria$", "decimals": "qta", "help": "<?php echo tr("Fattore moltiplicativo per l'unità di misura da utilizzare nelle stampe di Ordini fornitori"); ?>" ]}
</div>
<div class="col-md-4">
{[ "type": "number", "label": "<?php echo tr('Q.tà multipla'); ?>", "name": "qta_multipla", "value": "$qta_multipla$", "help": "<?php echo tr('Quantità multipla di scorta da tenere a magazzino. Se lasciato a 0, la quantità proposta da riordinare verrà gestita con la semplice differenza fra quantità richiesta e quantità disponibile.'); ?>" ]}
{[ "type": "number", "label": "<?php echo tr('Q.tà multipla'); ?>", "name": "qta_multipla", "value": "$qta_multipla$", "decimals": "qta", "help": "<?php echo tr('Quantità multipla di scorta da tenere a magazzino. Se lasciato a 0, la quantità proposta da riordinare verrà gestita con la semplice differenza fra quantità richiesta e quantità disponibile.'); ?>" ]}
</div>
</div>
</div>

View File

@ -107,9 +107,15 @@ echo '
<ul class="dropdown-menu" role="menu">';
$tecnici_sessione = session_get('dashboard.idtecnici', []);
$tecnici_disponibili = $dbo->fetchArray("SELECT an_anagrafiche.idanagrafica AS id, ragione_sociale, colore 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
LEFT OUTER JOIN in_interventi_tecnici ON in_interventi_tecnici.idtecnico = an_anagrafiche.idanagrafica INNER JOIN in_interventi ON in_interventi_tecnici.idintervento=in_interventi.id
WHERE an_anagrafiche.deleted_at IS NULL AND an_tipianagrafiche.descrizione='Tecnico' ".Modules::getAdditionalsQuery('Interventi').' GROUP BY an_anagrafiche.idanagrafica ORDER BY ragione_sociale ASC');
$tecnici_disponibili = $dbo->fetchArray("SELECT an_anagrafiche.idanagrafica AS id, ragione_sociale, colore FROM an_anagrafiche
INNER JOIN
an_tipianagrafiche_anagrafiche ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica
INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica
LEFT OUTER JOIN in_interventi_tecnici ON in_interventi_tecnici.idtecnico = an_anagrafiche.idanagrafica
INNER JOIN in_interventi ON in_interventi_tecnici.idintervento=in_interventi.id
WHERE an_anagrafiche.deleted_at IS NULL AND an_tipianagrafiche.descrizione='Tecnico' ".Modules::getAdditionalsQuery('Interventi').'
GROUP BY an_anagrafiche.idanagrafica
ORDER BY ragione_sociale ASC');
foreach ($tecnici_disponibili as $tecnico) {
$attr = '';
if (in_array("'".$tecnico['id']."'", $tecnici_sessione)) {
@ -289,11 +295,11 @@ echo '
globals.dashboard = {
load_url: globals.rootdir + "/actions.php?id_module='.$id_module.'",
style: "'.$def.'",
show_sunday: "'.setting('Visualizzare la domenica sul calendario').'",
show_sunday: '.intval(setting('Visualizzare la domenica sul calendario')).',
start_time: "'.setting('Ora inizio sul calendario').'",
end_time: "'.((setting('Ora fine sul calendario') != '00:00:00' && !empty(setting('Ora fine sul calendario'))) ? setting('Ora fine sul calendario') : '23:59:59').'",
write_permission: "'.intval($modulo_interventi->permission == 'rw').'",
tooltip: "'.setting('Utilizzare i tooltip sul calendario').'",
write_permission: '.intval($modulo_interventi->permission == 'rw').',
tooltip: '.intval(setting('Utilizzare i tooltip sul calendario')).',
calendar: null,
/* timeFormat: {
hour: "2-digit",
@ -313,16 +319,16 @@ echo '
};
function aggiorna_contatore(counter_id) {
var counter = $(counter_id);
let counter = $(counter_id);
var dropdown = counter.find(".dropdown-menu");
var selected = dropdown.find("input:checked").length;
var total = dropdown.find("input").length;
let dropdown = counter.find(".dropdown-menu");
let selected = dropdown.find("input:checked").length;
let total = dropdown.find("input").length;
counter.find(".selected_counter").html(selected);
counter.find(".total_counter").html(total);
var object = counter.find(".counter_object");
let object = counter.find(".counter_object");
if (total === 0) {
object.addClass("btn-primary disabled");
@ -527,7 +533,7 @@ echo '
},
editable: globals.dashboard.write_permission,
eventDrop: function(event) {// info
eventDrop: function(event, delta, revertFunc ) {// info
// let event = info.event;
$.post(globals.dashboard.load_url, {
@ -539,8 +545,8 @@ echo '
}, function (data, response) {
data = $.trim(data);
if (response !== "success" || data !== "ok") {
alert(data);
info.revert();
swal("'.tr('Errore').'", data, "error");
revertFunc(); // info.revert();
}
});
},
@ -556,7 +562,7 @@ echo '
}, function (data, response) {
data = $.trim(data);
if (response !== "success" || data !== "ok") {
alert(data);
swal("'.tr('Errore').'", data, "error");
revertFunc(); // info.revert();
}
});
@ -566,7 +572,7 @@ echo '
eventAfterRender: function(event, element) {
// let event = info.event;
// let element = $(info.el);
element.find(".fc-title").html(event.title);
let id_intervento = event.idintervento;
if (globals.dashboard.tooltip == 1) {
@ -604,7 +610,7 @@ echo '
url: globals.dashboard.load_url + "&op=interventi_periodo",
type: "GET",
error: function () {
alert(globals.dashboard.error);
swal("'.tr('Errore').'", globals.dashboard.error, "error");
}
}
});

View File

@ -19,11 +19,12 @@
include_once __DIR__.'/../../core.php';
use Modules\Fatture\Export\CSV;
use Modules\Fatture\Fattura;
use Modules\Fatture\Stato;
use Plugins\ExportFE\FatturaElettronica;
use Util\XML;
use Plugins\ExportFE\Interaction;
use Util\XML;
use Util\Zip;
switch (post('op')) {
@ -275,13 +276,12 @@ switch (post('op')) {
]));
break;
case 'check-bulk':
$list = [];
$anomalie = collect();
foreach ($id_records as $id) {
$fattura_vendita = Fattura::vendita()
->whereNotIn('codice_stato_fe', ['ERR', 'NS', 'EC02', 'ERVAL'])
->where('data', '>=', $_SESSION['period_start'])
@ -289,175 +289,158 @@ switch (post('op')) {
->where('id', '=', $id)
->orderBy('data')
->get();
$fattura_vendita = $fattura_vendita[0];
if (!empty($fattura_vendita)){
try {
$fattura_vendita = $fattura_vendita[0];
if (!empty($fattura_vendita)) {
try {
$xml = XML::read($fattura_vendita->getXML());
$totale_documento_xml = null;
// Totale basato sul campo ImportoTotaleDocumento
$dati_generali = $xml['FatturaElettronicaBody']['DatiGenerali']['DatiGeneraliDocumento'];
if (isset($dati_generali['ImportoTotaleDocumento'])) {
$totale_documento_indicato = abs(floatval($dati_generali['ImportoTotaleDocumento']));
// Calcolo del totale basato sui DatiRiepilogo
if (empty($totale_documento_xml) && empty($dati_generali['ScontoMaggiorazione'])) {
$totale_documento_xml = 0;
$riepiloghi = $xml['FatturaElettronicaBody']['DatiBeniServizi']['DatiRiepilogo'];
if (!empty($riepiloghi) && !isset($riepiloghi[0])) {
$riepiloghi = [$riepiloghi];
}
foreach ($riepiloghi as $riepilogo) {
$totale_documento_xml = sum([$totale_documento_xml, $riepilogo['ImponibileImporto'], $riepilogo['Imposta']]);
}
$totale_documento_xml = abs($totale_documento_xml);
} else {
$totale_documento_xml = $totale_documento_indicato;
}
$totale_documento_xml = $fattura_vendita->isNota() ? -$totale_documento_xml : $totale_documento_xml;
$totale_documento_xml = $fattura_vendita->isNota() ? -$totale_documento_xml : $totale_documento_xml;
}
// Se riscontro un'anomalia
if ( $fattura_vendita->anagrafica->piva != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale'] || $fattura_vendita->totale != $totale_documento_xml ){
if ($fattura_vendita->anagrafica->piva != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale'] || $fattura_vendita->totale != $totale_documento_xml) {
/*echo json_encode([
'totale_documento_xml' => $totale_documento_xml,
'totale_documento' => $totale_documento,
]);*/
$anomalie->push([
'fattura_vendita' => $fattura_vendita,
'codice_fiscale_xml' => !empty($xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale']) ? $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['CodiceFiscale'] : null,
'codice_fiscale' => $fattura_vendita->anagrafica->codice_fiscale,
'piva_xml' => !empty($xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice']) ? $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici']['IdFiscaleIVA']['IdCodice'] : null,
'piva' => $fattura_vendita->anagrafica->piva,
'totale_documento_xml' => moneyFormat($totale_documento_xml,2),
'totale_documento' => moneyFormat($fattura_vendita->totale,2),
'totale_documento_xml' => moneyFormat($totale_documento_xml, 2),
'totale_documento' => moneyFormat($fattura_vendita->totale, 2),
'have_xml' => 1,
]);
}
}
} catch (Exception $e) {
$anomalie->push([
'fattura_vendita' => $fattura_vendita,
'have_xml' => 0,
]);
}
array_push($list, $fattura_vendita->numero_esterno);
}
}
// Messaggi di risposta
if (empty($list)){
if (empty($list)) {
flash()->warning(tr('Nessuna fattura utile per il controllo!'));
}else{
} else {
flash()->info(tr('Fatture _LIST_ controllate.', [
'_LIST_' => implode(',', $list),
]));
// Se ci sono anomalie
if ($anomalie->count()>0) {
function diff($old, $new){
$matrix = array();
if ($anomalie->count() > 0) {
function diff($old, $new)
{
$matrix = [];
$maxlen = 0;
foreach($old as $oindex => $ovalue){
foreach ($old as $oindex => $ovalue) {
$nkeys = array_keys($new, $ovalue);
foreach($nkeys as $nindex){
foreach ($nkeys as $nindex) {
$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
if($matrix[$oindex][$nindex] > $maxlen){
if ($matrix[$oindex][$nindex] > $maxlen) {
$maxlen = $matrix[$oindex][$nindex];
$omax = $oindex + 1 - $maxlen;
$nmax = $nindex + 1 - $maxlen;
}
}
}
}
if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
if ($maxlen == 0) {
return [['d' => $old, 'i' => $new]];
}
return array_merge(
diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
array_slice($new, $nmax, $maxlen),
diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}
function htmlDiff($old, $new){
function htmlDiff($old, $new)
{
$ret = '';
$diff = diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new));
foreach($diff as $k){
if(is_array($k))
$ret .= (!empty($k['d'])?"<del>".implode(' ',$k['d'])."</del> ":'').
(!empty($k['i'])?"<span>".implode(' ',$k['i'])."</span> ":'');
else $ret .= $k . ' ';
foreach ($diff as $k) {
if (is_array($k)) {
$ret .= (!empty($k['d']) ? '<del>'.implode(' ', $k['d']).'</del> ' : '').
(!empty($k['i']) ? '<span>'.implode(' ', $k['i']).'</span> ' : '');
} else {
$ret .= $k.' ';
}
}
return $ret;
}
$riepilogo_anomalie .= tr('Attenzione: Trovate _NUM_ anomalie! Le seguenti fatture non trovano corrispondenza tra XML e dati nel documento:', [ '_NUM_' => $anomalie->count() ]).' </br></br>';
foreach ($anomalie as $anomalia) {
$riepilogo_anomalie .= '<ul><li>'.reference($anomalia['fattura_vendita'], $anomalia['fattura_vendita']->getReference()).'</li>';
if (!empty($anomalia['have_xml'])){
$riepilogo_anomalie .= tr('Attenzione: Trovate _NUM_ anomalie! Le seguenti fatture non trovano corrispondenza tra XML e dati nel documento:', ['_NUM_' => $anomalie->count()]).' </br></br>';
foreach ($anomalie as $anomalia) {
$riepilogo_anomalie .= '<ul><li>'.reference($anomalia['fattura_vendita'], $anomalia['fattura_vendita']->getReference()).'</li>';
if (!empty($anomalia['have_xml'])) {
$riepilogo_anomalie .= '<li><table class="table table-bordered table-condensed">
<tr><th>Sorgente</th><th>P. Iva</th><th>Cod. fiscale</th><th>Totale</th></tr>';
$riepilogo_anomalie .= '<tr><td>XML</td> <td>'.$anomalia['piva_xml'].'</td> <td>'.$anomalia['codice_fiscale_xml'].'</td> <td>'.$anomalia['totale_documento_xml'].'</td></tr>';
$riepilogo_anomalie .= '<tr><td>Gestionale</td> <td>'.htmlDiff($anomalia['piva_xml'],$anomalia['piva']).'</td> <td>'.htmlDiff($anomalia['codice_fiscale_xml'],$anomalia['codice_fiscale']).'</td> <td>'.htmlDiff($anomalia['totale_documento_xml'],$anomalia['totale_documento']).'</td></tr></table></li>';
}else{
$riepilogo_anomalie .= '<tr><td>Gestionale</td> <td>'.htmlDiff($anomalia['piva_xml'], $anomalia['piva']).'</td> <td>'.htmlDiff($anomalia['codice_fiscale_xml'], $anomalia['codice_fiscale']).'</td> <td>'.htmlDiff($anomalia['totale_documento_xml'], $anomalia['totale_documento']).'</td></tr></table></li>';
} else {
$riepilogo_anomalie .= ' <li>'.tr('Impossibile verificare l\'XML di questa fattura.').'</li>';
}
$riepilogo_anomalie .= '</ul><br>';
}
flash()->warning($riepilogo_anomalie);
}else{
} else {
flash()->info(tr('Nessuna anomalia!'));
}
}
break;
case 'download-csv':
$dir = base_dir().'/files/export_fatture/';
directory($dir.'tmp/');
$file = secure_random_string().'.csv';
$dir_csv = slashes($dir.'tmp/'.$file);
case 'export-csv':
$file = temp_file();
$exporter = new CSV($file);
$filename = 'fatture.csv';
// Esportazione dei record selezionati
$fatture = Fattura::whereIn('id', $id_records)->get();
$exporter->setRecords($fatture);
$t = new Modules\Fatture\Export\CSV($dir_csv);
$count = $exporter->exportRecords();
if($t->exportRecords()){
download($dir_csv, $filename);
delete($dir.'tmp/');
}
download($file, 'fatture.csv');
break;
@ -479,8 +462,8 @@ if (App::debug()) {
'text' => '<span><i class="fa fa-trash"></i> '.tr('Elimina selezionati').'</span> <span class="label label-danger" >beta</span>',
];
$operations['download-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta tutto').'</span> <span class="label label-danger" >beta</span>',
$operations['export-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta selezionati').'</span> <span class="label label-danger" >beta</span>',
'data' => [
'msg' => tr('Vuoi davvero esportare un CSV con tutte le fatture?'),
'button' => tr('Procedi'),
@ -488,7 +471,6 @@ if (App::debug()) {
'blank' => true,
],
];
}
$operations['copy-bulk'] = [
@ -543,7 +525,6 @@ if ($module->name == 'Fatture di vendita') {
'blank' => true,
],
];
}
$operations['export-xml-bulk'] = [

View File

@ -46,7 +46,7 @@ class CSV extends CSVExporter
'label' => 'Data',
],
[
'field' => 'idanagrafica',
'field' => 'anagrafica.ragione_sociale',
'label' => 'Ragione sociale',
],
[
@ -54,7 +54,7 @@ class CSV extends CSVExporter
'label' => 'Totale',
],
[
'field' => 'idstatodocumento',
'field' => 'stato.descrizione',
'label' => 'Stato',
],
[
@ -66,11 +66,6 @@ class CSV extends CSVExporter
public function getRecords()
{
$id_module = filter('id_module');
$results = Fattura::all()->where('id_segment', $_SESSION['module_'.$id_module]['id_segment']);
return $results;
return Fattura::all();
}
}

View File

@ -17,35 +17,30 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
use Modules\Impianti\Export\CSV;
use Modules\Impianti\Impianto;
include_once __DIR__.'/../../core.php';
switch (post('op')) {
case 'download-csv':
$dir = base_dir().'/files/export_impianti/';
directory($dir.'tmp/');
$file = secure_random_string().'.csv';
$dir_csv = slashes($dir.'tmp/'.$file);
case 'export-csv':
$file = temp_file();
$exporter = new CSV($file);
$filename = 'impianti.csv';
// Esportazione dei record selezionati
$fatture = Impianto::whereIn('id', $id_records)->get();
$exporter->setRecords($fatture);
$t = new Modules\Impianti\Export\CSV($dir_csv);
$count = $exporter->exportRecords();
if($t->exportRecords()){
download($dir_csv, $filename);
delete($dir.'tmp/');
}
download($file, 'impianti.csv');
break;
}
if (App::debug()) {
$operations['download-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta tutto').'</span> <span class="label label-danger" >beta</span>',
$operations['export-csv'] = [
'text' => '<span><i class="fa fa-download"></i> '.tr('Esporta selezionati').'</span> <span class="label label-danger" >beta</span>',
'data' => [
'msg' => tr('Vuoi davvero esportare un CSV con tutti gli impianti?'),
'button' => tr('Procedi'),
@ -55,4 +50,4 @@ if (App::debug()) {
];
}
return $operations;
return $operations;

View File

@ -210,7 +210,7 @@ echo '
<div class="box-body">
<div class="row">
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "values": "query=SELECT id, CONCAT_WS(\' - \', nome, descrizione) AS descrizione FROM an_zone ORDER BY nome", "placeholder": "'.tr('Nessuna zona').'", "help":"'.tr('La zona viene definita automaticamente in base al cliente selezionato').'.", "readonly": "0", "value": "'.$id_zona.'" ]}
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "values": "query=SELECT id, CONCAT_WS(\' - \', nome, descrizione) AS descrizione FROM an_zone ORDER BY nome", "placeholder": "'.tr('Nessuna zona').'", "help": "'.tr('La zona viene definita automaticamente in base al cliente selezionato').'.", "readonly": "1", "value": "'.$id_zona.'" ]}
</div>
<div class="col-md-4">

View File

@ -19,6 +19,8 @@
include_once __DIR__.'/../../core.php';
use API\Services;
use Models\Cache;
use Util\FileSystem;
$id = post('id');
@ -181,4 +183,21 @@ switch (filter('op')) {
echo json_encode($results);
break;
case 'informazioni-fe':
$info = Cache::pool('Informazioni su spazio FE');
if (!$info->isValid()) {
$response = Services::request('POST', 'informazioni_fe');
$response = Services::responseBody($response);
$info->set($response['result']);
}
$informazioni = $info->content;
echo json_encode([
'invoice_number' => $informazioni['invoice_number'],
'size' => Filesystem::formatBytes($informazioni['size']),
]);
break;
}

View File

@ -18,6 +18,10 @@
*/
// Elenco moduli installati
use API\Services;
use Carbon\Carbon;
use Models\Cache;
echo '
<div class="row">
<div class="col-md-12 col-lg-6">
@ -41,6 +45,87 @@ echo '
</table>
</div>';
if (Services::isEnabled()) {
// Informazioni su Services
$servizi = Cache::pool('Informazioni su Services')->content;
// Elaborazione dei servizi in scadenza
$limite_scadenze = (new Carbon())->addDays(60);
$servizi_in_scadenza = [];
foreach ($servizi as $servizio) {
// Gestione per data di scadenza
$scadenza = new Carbon($servizio['expiration_at']);
if (
(isset($servizio['expiration_at']) && $scadenza->lessThan($limite_scadenze))
) {
$servizi_in_scadenza[] = $servizio['name'].' ('.$scadenza->diffForHumans().')';
}
// Gestione per crediti
elseif (
(isset($servizio['credits']) && $servizio['credits'] < 100)
) {
$servizi_in_scadenza[] = $servizio['name'].' ('.$servizio['credits'].' crediti)';
}
}
echo '
<div class="col-md-12 col-lg-6">
<div class="box box-info">
<div class="box-header">
<h3 class="box-title">
'.tr('Informazioni su Services').'
</h3>
</div>
</div>
<div class="box-body">';
if (empty($servizi_in_scadenza)) {
echo '
<p>'.tr('Nessun servizio in scadenza').'.</p>';
} else {
echo '
<p>'.tr('I seguenti servizi sono in scadenza:').'</p>
<ul>';
foreach ($servizi_in_scadenza as $servizio) {
echo '
<li>'.$servizio.'</li>';
}
echo '
</ul>';
}
echo '
<hr><br>
<h4>'.tr('Statistiche su Fatture Elettroniche').'</h4>
<ul>
<li>'.tr('Fatture transitate').': <span id="fe_numero"></span></li>
<li>'.tr('Spazio occupato').': <span id="fe_spazio"></span></li>
</ul>
</div>
</div>
<script>
$(document).ready(function (){
$.ajax({
url: globals.rootdir + "/actions.php",
type: "GET",
dataType: "json",
data: {
id_module: globals.id_module,
op: "informazioni-fe",
},
success: function (response) {
$("#fe_numero").html(response.invoice_number);
$("#fe_spazio").html(response.size);
}
});
});
</script>';
}
// Widgets
echo '
<div class="col-md-12 col-lg-6">

View File

@ -0,0 +1,75 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.n.c.
*
* 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/>.
*/
namespace Modules\StatoServizi;
use API\Services;
use Carbon\Carbon;
use Hooks\CachedManager;
class ServicesHook extends CachedManager
{
public function getCacheName()
{
return 'Informazioni su Services';
}
public function cacheData()
{
$response = Services::request('POST', 'informazioni_servizi');
$body = Services::responseBody($response);
return $body['services'];
}
public function response()
{
$servizi = $this->getCache()->content;
// Elaborazione dei servizi in scadenza
$limite_scadenze = (new Carbon())->addDays(60);
$servizi_in_scadenza = [];
foreach ($servizi as $servizio) {
// Gestione per data di scadenza
$scadenza = new Carbon($servizio['expiration_at']);
if (
(isset($servizio['expiration_at']) && $scadenza->lessThan($limite_scadenze))
) {
$servizi_in_scadenza[] = $servizio['name'].' ('.$scadenza->diffForHumans().')';
}
// Gestione per crediti
elseif (
(isset($servizio['credits']) && $servizio['credits'] < 100)
) {
$servizi_in_scadenza[] = $servizio['name'].' ('.$servizio['credits'].' crediti)';
}
}
$message = tr('I seguenti servizi sono in scadenza: _LIST_', [
'_LIST_' => implode(', ', $servizi_in_scadenza),
]);
return [
'icon' => 'fa fa-refresh text-warning',
'message' => $message,
'show' => !empty($servizi_in_scadenza),
];
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.n.c.
*
* 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/>.
*/
namespace Modules\StatoServizi;
use Hooks\CachedManager;
use Util\FileSystem;
class SpaceHook extends CachedManager
{
public function getCacheName()
{
return 'Spazio utilizzato';
}
public function cacheData()
{
if (!empty(setting('Soft quota'))) {
return FileSystem::folderSize(base_dir(), ['htaccess']);
}
return false;
}
public function response()
{
$osm_size = $this->getCache()->content;
$soft_quota = setting('Soft quota'); // Impostazione in MB
$space_limit = ($soft_quota / 100) * 95; // 95% dello spazio indicato
$space_limit = $space_limit * 1024 ^ 2; // Trasformazione in B
$message = tr('Attenzione: occupati _TOT_ dei _QUOTA_ previsti', [
'_TOT_' => FileSystem::formatBytes($osm_size),
'_QUOTA_' => FileSystem::formatBytes($space_limit),
]);
return [
'icon' => 'fa fa-database text-warning',
'message' => $message,
'show' => ($osm_size > $space_limit),
];
}
}

View File

@ -40,7 +40,7 @@ class Interaction extends Services
'filename' => $fattura->getFilename(),
]);
$body = static::responseBody($response);
// Aggiornamento dello stato
if ($body['status'] == 200 || $body['status'] == 301) {
database()->update('co_documenti', [

View File

@ -35,7 +35,7 @@ echo '
<ul class="nav nav-tabs nav-justified">
<li class="active"><a href="#periodi" data-tab="periodi" onclick="apriTab(this)" data-toggle="tab">'.tr('Periodi').'</a></li>
<li><a href="#righe" data-tab="righe" onclick="apriTab(this)" data-toggle="tab">'.tr('Righe').'</a></li>
<li><a href="#div_righe" data-tab="righe" onclick="apriTab(this)" data-toggle="tab">'.tr('Righe').'</a></li>
</ul>
<div class="tab-content">
@ -81,7 +81,7 @@ echo '
</div>
</div>
<div class="tab-pane" id="righe">';
<div class="tab-pane" id="div_righe">';
$iva_righe = $contratto->getRighe()->groupBy('idiva');
foreach ($iva_righe as $id_iva => $righe) {

View File

@ -64,6 +64,10 @@ abstract class CSVExporter implements ExporterInterface
public function exportRecords()
{
// Esportazione header
$fields = $this->getAvailableFields();
$this->csv->insertOne(array_column($fields, 'label'));
$records = $this->records ?: $this->getRecords();
foreach ($records as $record) {
// Esportazione del record
@ -81,7 +85,14 @@ abstract class CSVExporter implements ExporterInterface
foreach ($fields as $field) {
$nome = $field['field'];
$row[] = $record[$nome];
// Navigazione secondo dot notation
$dot_notation = explode('.', $nome);
$contenuto = $record;
foreach ($dot_notation as $segment) {
$contenuto = isset($contenuto[$segment]) ? $contenuto[$segment] : null;
}
$row[] = $contenuto;
}
return $this->csv->insertOne($row);

View File

@ -109,24 +109,17 @@ class SelectHandler implements HandlerInterface
$result .= '
</select>';
// Gestione delle proprietà "disabled" e "readonly"
if (in_array('disabled', $extras) || in_array('readonly', $extras)) {
$result .= '
<script>$("#'.$values['id'].'").prop("disabled", true);</script>';
// Rimozione proprietà "readonly" in favore di "disabled"
$pos = array_search('readonly', $extras);
if ($pos !== false) {
$extras[$pos] = 'disabled';
$extras = array_unique($extras);
}
// Ulteriore gestione della proprietà "readonly" (per rendere il select utilizzabile dopo il submit)
if (in_array('readonly', $extras) && empty($source)) {
// Gestione delle proprietà "disabled"
if (in_array('disabled', $extras)) {
$result .= '
<select class="hide" name="'.prepareToField($values['name']).'"'.((in_array('multiple', $extras)) ? ' multiple' : '').'>';
foreach ($values['value'] as $value) {
$result .= '
<option value="'.prepareToField($value).'" selected></option>';
}
$result .= '
</select>';
<script>$("#'.$values['id'].'").prop("disabled", true);</script>';
}
return $result;

View File

@ -24,7 +24,7 @@ $righe = $documento->getRighe();
$has_image = $righe->search(function ($item) {
return !empty($item->articolo->immagine);
});
}) !== false;
if ($has_image) {
$columns = 7;
@ -81,7 +81,7 @@ foreach ($righe as $riga) {
</td>';
if ($has_image) {
if ($riga->isArticolo()) {
if ($riga->isArticolo() && !empty($riga->articolo->image)) {
echo '
<td align="center">
<img src="'.$riga->articolo->image.'" style="max-height: 80px; max-width:120px">

View File

@ -34,14 +34,14 @@ foreach ($righe as $riga) {
}
$anagrafica = Anagrafica::find($documento['idanagrafica']);
$pagamento = $dbo->fetchOne('SELECT * FROM co_pagamenti WHERE id = '.$documento['idpagamento']);
$pagamento = $dbo->fetchOne('SELECT * FROM co_pagamenti WHERE id = '.prepare($documento['idpagamento']));
//Verifico se c'è una banca predefinita per il mio cliente
if (!empty($anagrafica->idbanca_vendite)) {
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche INNER JOIN co_pianodeiconti3 ON co_banche.id_pianodeiconti3 = co_pianodeiconti3.id WHERE co_pianodeiconti3.id = '.$pagamento['idconto_vendite'].' AND co_banche.id ='.$anagrafica->idbanca_vendite);
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche INNER JOIN co_pianodeiconti3 ON co_banche.id_pianodeiconti3 = co_pianodeiconti3.id WHERE co_pianodeiconti3.id = '.prepare($pagamento['idconto_vendite']).' AND co_banche.id ='.prepare($anagrafica->idbanca_vendite));
} elseif (!empty($pagamento['idconto_vendite'])) {
//Altrimenti prendo quella associata la metodo di pagamento selezionato
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche INNER JOIN co_pianodeiconti3 ON co_banche.id_pianodeiconti3 = co_pianodeiconti3.id WHERE co_pianodeiconti3.id = '.$pagamento['idconto_vendite'].' AND co_banche.deleted_at IS NULL');
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche INNER JOIN co_pianodeiconti3 ON co_banche.id_pianodeiconti3 = co_pianodeiconti3.id WHERE co_pianodeiconti3.id = '.prepare($pagamento['idconto_vendite']).' AND co_banche.deleted_at IS NULL');
}
// Creazione righe fantasma

View File

@ -71,4 +71,41 @@ UPDATE `zz_views` SET `format` = '1' WHERE `id` = (SELECT `id` FROM `zz_views` W
UPDATE `zz_modules` SET `icon` = 'fa fa-angle-right' WHERE `zz_modules`.`id` = (SELECT `id` FROM `zz_modules` WHERE `name` = 'Listini');
-- Modificato nome plugin dettagli in Prezzi specifici
UPDATE `zz_plugins` SET `name` = 'Prezzi specifici articolo', `title` = 'Prezzi specifici' WHERE `zz_plugins`.`id` = (SELECT `id` FROM `zz_plugins` WHERE `name` = 'Dettagli articolo');
UPDATE `zz_plugins` SET `name` = 'Prezzi specifici articolo', `title` = 'Prezzi specifici' WHERE `zz_plugins`.`id` = (SELECT `id` FROM `zz_plugins` WHERE `name` = 'Dettagli articolo');
-- Impostazione soft quota
INSERT INTO `zz_settings` (`id`, `nome`, `valore`, `tipo`, `editable`, `sezione`, `order`, `help`) VALUES (NULL, 'Soft quota', '', 'integer', '0', 'Generali', NULL, 'Soft quota in MB');
-- Relativo hook per il calcolo dello spazio utilizzato
INSERT INTO `zz_hooks` (`id`, `name`, `class`, `enabled`, `id_module`, `processing_at`, `processing_token`) VALUES (NULL, 'Spazio', 'Modules\\StatoServizi\\SpaceHook', '1', (SELECT `id` FROM `zz_modules` WHERE `name`='Stato dei servizi'), NULL, NULL);
INSERT INTO `zz_cache` (`id`, `name`, `content`, `valid_time`, `expire_at`) VALUES
(NULL, 'Spazio utilizzato', '', '15 minute', NOW());
-- Introduzione hook per informazioni su Services
INSERT INTO `zz_hooks` (`id`, `name`, `class`, `enabled`, `id_module`, `processing_at`, `processing_token`) VALUES (NULL, 'Informazioni su Services', 'Modules\\StatoServizi\\ServicesHook', '1', (SELECT `id` FROM `zz_modules` WHERE `name`='Stato dei servizi'), NULL, NULL);
INSERT INTO `zz_cache` (`id`, `name`, `content`, `valid_time`, `expire_at`) VALUES
(NULL, 'Informazioni su Services', '', '7 days', NOW()),
(NULL, 'Informazioni su spazio FE', '', '7 days', NOW());
-- Aggiunta colonna Tecnici assegnati in Attività
UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `in_interventi`
INNER JOIN `an_anagrafiche` ON `in_interventi`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`
LEFT JOIN `in_interventi_tecnici` ON `in_interventi_tecnici`.`idintervento` = `in_interventi`.`id`
LEFT JOIN `in_interventi_tecnici_assegnati` ON `in_interventi_tecnici_assegnati`.`id_intervento` = `in_interventi`.`id`
LEFT JOIN `in_statiintervento` ON `in_interventi`.`idstatointervento`=`in_statiintervento`.`idstatointervento`
LEFT JOIN (
SELECT an_sedi.id, CONCAT(an_sedi.nomesede, ''<br>'',an_sedi.telefono, ''<br>'',an_sedi.cellulare,''<br>'',an_sedi.citta, '' - '', an_sedi.indirizzo) AS info FROM an_sedi
) AS sede_destinazione ON sede_destinazione.id = in_interventi.idsede_destinazione
LEFT JOIN (
SELECT co_righe_documenti.idintervento, CONCAT(''Fatt. '', co_documenti.numero_esterno, '' del '', DATE_FORMAT(co_documenti.data, ''%d/%m/%Y'')) AS info FROM co_documenti INNER JOIN co_righe_documenti ON co_documenti.id = co_righe_documenti.iddocumento
) AS fattura ON fattura.idintervento = in_interventi.id
WHERE 1=1 |date_period(`orario_inizio`,`data_richiesta`)|
GROUP BY `in_interventi`.`id`
HAVING 2=2
ORDER BY IFNULL(`orario_fine`, `data_richiesta`) DESC' WHERE `name` = 'Interventi';
INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `format`, `default`, `visible`) VALUES
((SELECT `id` FROM `zz_modules` WHERE `name` = 'Interventi'), 'Tecnici assegnati', 'GROUP_CONCAT((SELECT DISTINCT(ragione_sociale) FROM an_anagrafiche WHERE idanagrafica = in_interventi_tecnici_assegnati.id_tecnico) SEPARATOR '', '')', 14, 1, 0, 1, 1);
UPDATE `zz_views` SET `default` = 1 WHERE `zz_views`.`id_module` = (SELECT `zz_modules`.`id` FROM `zz_modules` WHERE `zz_modules`.`name` = 'Interventi') AND (`zz_views`.`name` = 'Tecnici' OR `zz_views`.`name` = 'Rif. fattura');