Plugin Statistiche per gli Articoli
This commit is contained in:
parent
7eda6ad01b
commit
250c642f4e
|
@ -31,7 +31,7 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
|
||||||
- Possibilità di ripristinare gli elementi eliminati dove l'eliminazione avviene a livello virtuale (**Anagrafiche**)
|
- Possibilità di ripristinare gli elementi eliminati dove l'eliminazione avviene a livello virtuale (**Anagrafiche**)
|
||||||
- Plugin **Rinnovi** in **Contratti**
|
- Plugin **Rinnovi** in **Contratti**
|
||||||
- Caricamento del **Piano dei conti** attraverso AJAX
|
- Caricamento del **Piano dei conti** attraverso AJAX
|
||||||
- Pannello *Prezzo medio acquisto* in **Articoli**
|
- Plugin *Statistiche* in **Articoli**, con visualizzazione del *Prezzo medio acquisto* in periodo personalizzabili
|
||||||
- Supporto ai select come **Campi personalizzati**
|
- Supporto ai select come **Campi personalizzati**
|
||||||
- Possibilità di generazione massiva delle fatture elettroniche
|
- Possibilità di generazione massiva delle fatture elettroniche
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
|
||||||
- Il modulo **Tecnici e tariffe** permette di definire le tariffe personalizzate per i diversi tecnici in relazione ai tipi di attività
|
- Il modulo **Tecnici e tariffe** permette di definire le tariffe personalizzate per i diversi tecnici in relazione ai tipi di attività
|
||||||
- Il modulo **Contratti** permette di definire le tariffe personalizzate per le *nuove sessioni* delle attività collegate
|
- Il modulo **Contratti** permette di definire le tariffe personalizzate per le *nuove sessioni* delle attività collegate
|
||||||
- La sezione di modifica delle sessioni permette la modifica manuale delle tariffe interessate; il cambiamento del tipo di sessione provoca l'utilizzo delle tariffe definite da **Tecnici e tariffe**
|
- La sezione di modifica delle sessioni permette la modifica manuale delle tariffe interessate; il cambiamento del tipo di sessione provoca l'utilizzo delle tariffe definite da **Tecnici e tariffe**
|
||||||
|
- Ottimizzazione delle stampe **Scadenzario** e **Registro IVA**, e della tabella principale del modulp **Fatture di vendita**
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,5 @@ return [
|
||||||
'plugins/exportFE' => 'Plugins\ExportFE',
|
'plugins/exportFE' => 'Plugins\ExportFE',
|
||||||
'plugins/importFE' => 'Plugins\ImportFE',
|
'plugins/importFE' => 'Plugins\ImportFE',
|
||||||
'plugins/receiptFE' => 'Plugins\ReceiptFE',
|
'plugins/receiptFE' => 'Plugins\ReceiptFE',
|
||||||
|
'plugins/statistiche_articoli' => 'Plugins\StatisticheArticoli',
|
||||||
];
|
];
|
||||||
|
|
|
@ -292,58 +292,6 @@ echo '
|
||||||
</div>
|
</div>
|
||||||
</div>';
|
</div>';
|
||||||
?>
|
?>
|
||||||
<?php
|
|
||||||
|
|
||||||
echo '<div class="panel panel-primary">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h3 class="panel-title">'.tr('Prezzo medio acquisto').'</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-body">';
|
|
||||||
$rs_prezzo_medio = $dbo->fetchOne('SELECT ((SUM(subtotale)-SUM(sconto))/SUM(qta)) AS prezzo FROM co_righe_documenti INNER JOIN co_documenti ON co_righe_documenti.iddocumento = co_documenti.id WHERE co_documenti.idtipodocumento IN (SELECT id FROM co_tipidocumento WHERE dir = \'uscita\') AND idarticolo='.prepare($id_record));
|
|
||||||
$rs_prezzo_min = $dbo->fetchOne('SELECT ((subtotale-sconto)/qta) AS prezzo, co_documenti.data FROM co_righe_documenti INNER JOIN co_documenti ON co_righe_documenti.iddocumento = co_documenti.id WHERE co_documenti.idtipodocumento IN (SELECT id FROM co_tipidocumento WHERE dir = \'uscita\') AND idarticolo='.prepare($id_record).' ORDER BY ((subtotale-sconto)/qta) ASC');
|
|
||||||
$rs_prezzo_max = $dbo->fetchOne('SELECT ((subtotale-sconto)/qta) AS prezzo, co_documenti.data FROM co_righe_documenti INNER JOIN co_documenti ON co_righe_documenti.iddocumento = co_documenti.id WHERE co_documenti.idtipodocumento IN (SELECT id FROM co_tipidocumento WHERE dir = \'uscita\') AND idarticolo='.prepare($id_record).' ORDER BY ((subtotale-sconto)/qta) DESC');
|
|
||||||
|
|
||||||
if (count($rs_prezzo_min) > 0) {
|
|
||||||
echo '
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12 col-lg-6">
|
|
||||||
<table class="table table-striped table-condensed table-bordered">
|
|
||||||
<tr>
|
|
||||||
<th>'.tr('Prezzo minimo').'</th>
|
|
||||||
<th>'.tr('Prezzio medio').'</th>
|
|
||||||
<th>'.tr('Prezzo massimo').'</th>
|
|
||||||
<th>'.tr('Oscillazione').'</th>
|
|
||||||
<th>'.tr('Oscillazione in %').'</th>
|
|
||||||
<th>'.tr('Andamento prezzo').'</th>
|
|
||||||
</tr>';
|
|
||||||
|
|
||||||
echo '
|
|
||||||
<tr>
|
|
||||||
<td>'.moneyFormat($rs_prezzo_min['prezzo']).'</td>
|
|
||||||
<td>'.moneyFormat($rs_prezzo_medio['prezzo']).'</td>
|
|
||||||
<td>'.moneyFormat($rs_prezzo_max['prezzo']).'</td>
|
|
||||||
<td>'.moneyFormat($rs_prezzo_max['prezzo'] - $rs_prezzo_min['prezzo']).'</td>
|
|
||||||
<td>'.Translator::numberToLocale(((($rs_prezzo_max['prezzo'] - $rs_prezzo_min['prezzo']) * 100) / $rs_prezzo_medio['prezzo']), '2').' %</td>
|
|
||||||
<td>'.((strtotime($rs_prezzo_min['data']) == strtotime($rs_prezzo_max['data'])) ? 'N.D.' : ((strtotime($rs_prezzo_min['data']) < strtotime($rs_prezzo_max['data'])) ? 'in aumento' : 'in diminuzione')).'</td>
|
|
||||||
</tr>';
|
|
||||||
|
|
||||||
echo '
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>';
|
|
||||||
} else {
|
|
||||||
echo '
|
|
||||||
<div class="alert alert-info">
|
|
||||||
'.tr('Questo articolo non è mai stato acquistato').'
|
|
||||||
</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '
|
|
||||||
</div>
|
|
||||||
</div>';
|
|
||||||
|
|
||||||
?>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{( "name": "filelist_and_upload", "id_module": "$id_module$", "id_record": "$id_record$" )}
|
{( "name": "filelist_and_upload", "id_module": "$id_module$", "id_record": "$id_record$" )}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
include_once __DIR__.'/../../../core.php';
|
include_once __DIR__.'/../../core.php';
|
||||||
|
|
||||||
$id_contratto_precedente = $record['idcontratto_prev'];
|
$id_contratto_precedente = $record['idcontratto_prev'];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__.'/../../core.php';
|
||||||
|
|
||||||
|
use Plugins\StatisticheArticoli\Stats;
|
||||||
|
|
||||||
|
$calendar = filter('calendar');
|
||||||
|
$direzione = filter('dir');
|
||||||
|
$start = filter('start');
|
||||||
|
$end = filter('end');
|
||||||
|
|
||||||
|
$prezzi = Stats::prezzi($id_record, $start, $end, $direzione);
|
||||||
|
$prezzo_min = $prezzi['min'];
|
||||||
|
$prezzo_max = $prezzi['max'];
|
||||||
|
$prezzo_medio = $prezzi['media'];
|
||||||
|
|
||||||
|
$oscillazione = $prezzo_max['prezzo'] - $prezzo_min['prezzo'];
|
||||||
|
$oscillazione_percentuale = $oscillazione * 100 / $prezzo_medio ?: 0;
|
||||||
|
|
||||||
|
$data_min = strtotime($prezzo_min['data']);
|
||||||
|
$data_max = strtotime($prezzo_max['data']);
|
||||||
|
if ($data_min == $data_max) {
|
||||||
|
$andamento = tr('N.D.');
|
||||||
|
} elseif ($data_min < $data_max) {
|
||||||
|
$andamento = tr('in aumento');
|
||||||
|
} else {
|
||||||
|
$andamento = tr('in diminuzione');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<tr id="row-'.$calendar.'">
|
||||||
|
<td>'.dateFormat($start).' - '.dateFormat($end).'</td>
|
||||||
|
<td>'.moneyFormat($prezzo_min['prezzo']).'</td>
|
||||||
|
<td>'.moneyFormat($prezzo_medio).'</td>
|
||||||
|
<td>'.moneyFormat($prezzo_max['prezzo']).'</td>
|
||||||
|
<td>'.moneyFormat($oscillazione).'</td>
|
||||||
|
<td>'.Translator::numberToLocale($oscillazione_percentuale, '2').' %</td>
|
||||||
|
<td>'.$andamento.'</td>
|
||||||
|
</tr>';
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include_once __DIR__.'/../../core.php';
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<hr>
|
||||||
|
<div class="box box-warning">
|
||||||
|
<div class="box-header">
|
||||||
|
<h4 class="box-title">
|
||||||
|
'.tr('Periodi temporali').'
|
||||||
|
</h4>
|
||||||
|
<div class="box-tools pull-right">
|
||||||
|
<button class="btn btn-warning btn-xs" onclick="add_period()">
|
||||||
|
<i class="fa fa-plus"></i> '.tr('Aggiungi periodo').'
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||||
|
<i class="fa fa-minus"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box-body collapse in" id="calendars">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">'.tr('Prezzo medio acquisto').'</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
<table class="table table-striped table-condensed table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>'.tr('Perido').'</th>
|
||||||
|
<th>'.tr('Prezzo minimo').'</th>
|
||||||
|
<th>'.tr('Prezzio medio').'</th>
|
||||||
|
<th>'.tr('Prezzo massimo').'</th>
|
||||||
|
<th>'.tr('Oscillazione').'</th>
|
||||||
|
<th>'.tr('Oscillazione in %').'</th>
|
||||||
|
<th>'.tr('Andamento prezzo').'</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="prezzi_acquisto">
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
add_period();
|
||||||
|
});
|
||||||
|
|
||||||
|
function change_period(calendar, start, end) {
|
||||||
|
add_prezzo("#prezzi_acquisto", calendar, "uscita", start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_prezzo(id, calendar, direzione, start, end) {
|
||||||
|
$.ajax({
|
||||||
|
url: "'.$structure->fileurl('add_prezzo.php').'",
|
||||||
|
type: "get",
|
||||||
|
data: {
|
||||||
|
id_module: globals.id_module,
|
||||||
|
id_record: globals.id_record,
|
||||||
|
calendar: calendar,
|
||||||
|
dir: direzione,
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
var row = $(id).find("#row-" + calendar);
|
||||||
|
|
||||||
|
if (!row.length) {
|
||||||
|
$(id).append(data);
|
||||||
|
} else {
|
||||||
|
row.after(data);
|
||||||
|
row.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#row-" + calendar).effect("highlight", {}, 3000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_period() {
|
||||||
|
var last = $("#calendars").find("input").last().attr("id");
|
||||||
|
var last_id = last ? last.split("-")[1] : 0;
|
||||||
|
last_id = parseInt(last_id) + 1;
|
||||||
|
|
||||||
|
var name = "calendar-" + last_id;
|
||||||
|
|
||||||
|
$("#calendars").append(\'<div class="col-md-4"><input class="form-control" type="text" name="\' + name + \'" id="\' + name + \'"/><br></div>\');
|
||||||
|
|
||||||
|
$("body").on("focus", "#" + name, function() {
|
||||||
|
$(this).daterangepicker({
|
||||||
|
locale: {
|
||||||
|
customRangeLabel: globals.translations.custom,
|
||||||
|
applyLabel: globals.translations.apply,
|
||||||
|
cancelLabel: globals.translations.cancel,
|
||||||
|
fromLabel: globals.translations.from,
|
||||||
|
toLabel: globals.translations.to,
|
||||||
|
},
|
||||||
|
startDate: globals.start_date,
|
||||||
|
endDate: globals.end_date,
|
||||||
|
applyClass: "btn btn-success btn-sm",
|
||||||
|
cancelClass: "btn btn-danger btn-sm",
|
||||||
|
linkedCalendars: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var id = $(this).attr("id").split("-")[1];
|
||||||
|
change_period(id, globals.start_date, globals.end_date);
|
||||||
|
|
||||||
|
$(this).on("apply.daterangepicker", function(ev, picker) {
|
||||||
|
var id = $(this).attr("id").split("-")[1];
|
||||||
|
var start = picker.startDate.format("YYYY-MM-DD");
|
||||||
|
var end = picker.endDate.format("YYYY-MM-DD");
|
||||||
|
|
||||||
|
console.log(id, start, end);
|
||||||
|
change_period(id, start, end);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#" + name).focus();
|
||||||
|
}
|
||||||
|
</script>';
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugins\StatisticheArticoli;
|
||||||
|
|
||||||
|
class Stats
|
||||||
|
{
|
||||||
|
public static function prezzi($id_articolo, $start, $end, $dir = 'uscita')
|
||||||
|
{
|
||||||
|
$database = database();
|
||||||
|
|
||||||
|
$from = 'FROM co_righe_documenti INNER JOIN co_documenti ON co_righe_documenti.iddocumento = co_documenti.id WHERE co_righe_documenti.subtotale != 0 AND co_documenti.idtipodocumento IN (SELECT id FROM co_tipidocumento WHERE dir = '.prepare($dir).') AND co_documenti.data BETWEEN '.prepare($start).' AND '.prepare($end).' AND co_righe_documenti.idarticolo='.prepare($id_articolo);
|
||||||
|
|
||||||
|
$prezzo_medio = $database->fetchOne('SELECT (SUM(subtotale) - SUM(sconto)) / SUM(qta) AS prezzo '.$from)['prezzo'];
|
||||||
|
|
||||||
|
$prezzo = 'SELECT (subtotale - sconto) / qta AS prezzo, co_documenti.data '.$from.' ORDER BY prezzo';
|
||||||
|
$prezzo_min = $database->fetchOne($prezzo.' ASC');
|
||||||
|
$prezzo_max = $database->fetchOne($prezzo.' DESC');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'media' => $prezzo_medio,
|
||||||
|
'max' => $prezzo_max,
|
||||||
|
'min' => $prezzo_min,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -510,6 +510,5 @@ class Prints
|
||||||
|
|
||||||
// Creazione effettiva del PDF
|
// Creazione effettiva del PDF
|
||||||
$mpdf->Output($filename, $mode);
|
$mpdf->Output($filename, $mode);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,3 @@ echo '
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>';
|
</table>';
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ if ('entrata' == $dir) {
|
||||||
], ['upper' => true]);
|
], ['upper' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tipo = $dir == "entrata" ? tr("Cliente") : tr("Fornitore");
|
$tipo = $dir == 'entrata' ? tr('Cliente') : tr('Fornitore');
|
||||||
|
|
||||||
echo '<h4><b>'.$titolo.'</b></h4>
|
echo '<h4><b>'.$titolo.'</b></h4>
|
||||||
|
|
||||||
|
|
|
@ -219,3 +219,6 @@ UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `co_scadenziario`
|
||||||
WHERE 1=1 AND ABS(`co_scadenziario`.`pagato`) < ABS(`co_scadenziario`.`da_pagare`) AND `co_statidocumento`.`descrizione` IN(''Emessa'',''Parzialmente pagato'')
|
WHERE 1=1 AND ABS(`co_scadenziario`.`pagato`) < ABS(`co_scadenziario`.`da_pagare`) AND `co_statidocumento`.`descrizione` IN(''Emessa'',''Parzialmente pagato'')
|
||||||
HAVING 2=2
|
HAVING 2=2
|
||||||
ORDER BY `scadenza` ASC' WHERE `name` = 'Scadenzario';
|
ORDER BY `scadenza` ASC' WHERE `name` = 'Scadenzario';
|
||||||
|
|
||||||
|
-- Plugin Statistiche per Articoli
|
||||||
|
INSERT INTO `zz_plugins` (`id`, `name`, `title`, `idmodule_from`, `idmodule_to`, `position`, `script`, `enabled`, `default`, `order`, `compatibility`, `version`, `options2`, `options`, `directory`, `help`) VALUES (NULL, 'Statistiche', 'Statistiche', (SELECT `id` FROM `zz_modules` WHERE `name` = 'Articoli'), (SELECT `id` FROM `zz_modules` WHERE `name` = 'Articoli'), 'tab', '', 1, 0, 0, '', '', NULL, 'custom', 'statistiche_articoli', '');
|
||||||
|
|
Loading…
Reference in New Issue