Plugin Statistiche per gli Articoli

This commit is contained in:
Thomas Zilio 2019-07-09 18:29:40 +02:00
parent 7eda6ad01b
commit 250c642f4e
12 changed files with 202 additions and 59 deletions

View File

@ -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

View File

@ -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',
]; ];

View File

@ -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$" )}

View File

@ -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'];

View File

@ -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>';

View File

@ -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>';

View File

@ -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,
];
}
}

View File

@ -510,6 +510,5 @@ class Prints
// Creazione effettiva del PDF // Creazione effettiva del PDF
$mpdf->Output($filename, $mode); $mpdf->Output($filename, $mode);
} }
} }

View File

@ -56,4 +56,3 @@ echo '
</tr> </tr>
</tbody> </tbody>
</table>'; </table>';

View File

@ -7,7 +7,7 @@ $dir = $_GET['dir'];
$date_start = $_SESSION['period_start']; $date_start = $_SESSION['period_start'];
$date_end = $_SESSION['period_end']; $date_end = $_SESSION['period_end'];
$tipo = $dir == 'entrata' ? 'vendite': 'acquisti'; $tipo = $dir == 'entrata' ? 'vendite' : 'acquisti';
$report_name = 'registro_iva_'.$tipo.'.pdf'; $report_name = 'registro_iva_'.$tipo.'.pdf';
$v_iva = []; $v_iva = [];

View File

@ -5,7 +5,7 @@ include_once __DIR__.'/../../core.php';
$year_start = date('Y', strtotime($date_start)); $year_start = date('Y', strtotime($date_start));
$year_end = date('Y', strtotime($date_end)); $year_end = date('Y', strtotime($date_end));
$esercizio = $year_start == $year_end ? ' - '.tr('Esercizio _YEAR_',[ $esercizio = $year_start == $year_end ? ' - '.tr('Esercizio _YEAR_', [
'_YEAR_' => $year_end, '_YEAR_' => $year_end,
]) : ''; ]) : '';
@ -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>

View File

@ -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', '');