added permission matrici stats
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Permesso specifico per la pagina Matrici (prezzi di vendita per matrice e cliente).
|
||||
* Dopo la migrazione va assegnato ai ruoli dalla gestione permessi del portale.
|
||||
*/
|
||||
final class AddSalesMatriciPermission extends AbstractMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$exists = $this->fetchRow("SELECT id FROM auth_permissions WHERE name = 'sales.matrici.view'");
|
||||
if ($exists) return;
|
||||
|
||||
$this->table('auth_permissions')->insert([
|
||||
'name' => 'sales.matrici.view',
|
||||
'display_name' => 'Statistiche matrici',
|
||||
'description' => 'Vedere prezzi di vendita, clienti e mescole per matrice',
|
||||
'removable' => 1,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
])->saveData();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$this->execute("DELETE pr FROM auth_permission_role pr
|
||||
JOIN auth_permissions p ON p.id = pr.permission_id
|
||||
WHERE p.name = 'sales.matrici.view'");
|
||||
$this->execute("DELETE FROM auth_permissions WHERE name = 'sales.matrici.view'");
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ if (!userCan('sales.stats.view')) {
|
||||
exit;
|
||||
}
|
||||
$canDeliveries = userCan('sales.deliveries.view');
|
||||
$canMatrici = userCan('sales.matrici.view');
|
||||
|
||||
/* ============================================================
|
||||
* AJAX
|
||||
@@ -1203,6 +1204,9 @@ if ($action === 'data') {
|
||||
<a href="sales_orders_stats.php"><i class="fa-solid fa-list-check me-1"></i> Andamento ordini</a>
|
||||
<a href="sales_orders_years.php"><i class="fa-solid fa-chart-column me-1"></i> Confronto anni</a>
|
||||
<a href="sales_customer.php" class="active"><i class="fa-solid fa-address-card me-1"></i> Scheda cliente</a>
|
||||
<?php if (userCan('sales.matrici.view')) : ?>
|
||||
<a href="sales_matrici.php"><i class="fa-solid fa-shapes me-1"></i> Matrici</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($canDeliveries) : ?>
|
||||
<a href="sales_orders_deliveries.php"><i class="fa-solid fa-truck-fast me-1"></i> Consegne</a>
|
||||
<?php endif; ?>
|
||||
@@ -1252,6 +1256,9 @@ if ($action === 'data') {
|
||||
<button type="button" data-tab="open" class="active"><i class="fa-solid fa-truck-ramp-box me-1"></i> Da consegnare <span class="badge bg-light text-dark" id="nOpen">0</span></button>
|
||||
<button type="button" data-tab="orders"><i class="fa-solid fa-file-invoice me-1"></i> Ordini <span class="badge bg-light text-dark" id="nOrders">0</span></button>
|
||||
<button type="button" data-tab="items"><i class="fa-solid fa-cubes me-1"></i> Articoli <span class="badge bg-light text-dark" id="nItems">0</span></button>
|
||||
<?php if ($canMatrici) : ?>
|
||||
<button type="button" data-tab="matrici"><i class="fa-solid fa-shapes me-1"></i> Matrici <span class="badge bg-light text-dark" id="nMatrici">0</span></button>
|
||||
<?php endif; ?>
|
||||
<button type="button" data-tab="docs"><i class="fa-solid fa-receipt me-1"></i> Fatture <span class="badge bg-light text-dark" id="nDocs">0</span></button>
|
||||
<span class="ms-auto align-self-center pe-2" data-help="sc.tables"></span>
|
||||
</div>
|
||||
@@ -1271,6 +1278,14 @@ if ($action === 'data') {
|
||||
<table id="tItems" class="table table-striped align-middle w-100 sc-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($canMatrici) : ?>
|
||||
<div class="sc-pane" data-pane="matrici" style="display:none;">
|
||||
<div class="chart-hint mb-2">Matrici ordinate dal cliente dal 2020, con il prezzo per unità di vendita. Clic sul nome per il dettaglio e il confronto con gli altri clienti.</div>
|
||||
<div class="table-responsive">
|
||||
<table id="tMatrici" class="table table-striped align-middle w-100 sc-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="sc-pane" data-pane="docs" style="display:none;">
|
||||
<div class="table-responsive">
|
||||
<table id="tDocs" class="table table-striped align-middle w-100 sc-table"></table>
|
||||
@@ -1309,6 +1324,7 @@ if ($action === 'data') {
|
||||
const STORE_KEY = 'zibo_sales_customer_v1';
|
||||
const CUR_Y = new Date().getFullYear();
|
||||
const ZIBO_WEEK = <?= MagoSalesStats::ZIBO_IS_WEEK ? 'true' : 'false' ?>;
|
||||
const CAN_MATRICI = <?= $canMatrici ? 'true' : 'false' ?>;
|
||||
const ZIBO_END_DAYS = <?= (int)MagoSalesStats::ZIBO_WEEK_END_DAYS ?>;
|
||||
const ST_LABEL = {
|
||||
aperto: 'Aperto',
|
||||
@@ -1538,6 +1554,7 @@ if ($action === 'data') {
|
||||
</div>
|
||||
<div class="pactions">
|
||||
<a class="btn btn-outline-primary btn-sm" href="sales_orders_stats.php?q=${encodeURIComponent(i.code)}"><i class="fa-solid fa-list-check me-1"></i> Ordini in Andamento</a>
|
||||
${CAN_MATRICI ? `<a class="btn btn-outline-secondary btn-sm" href="sales_matrici.php?c=${encodeURIComponent(i.code)}"><i class="fa-solid fa-shapes me-1"></i> Matrici e prezzi</a>` : ''}
|
||||
</div>`);
|
||||
}
|
||||
|
||||
@@ -1876,9 +1893,74 @@ if ($action === 'data') {
|
||||
buttons: xls(`Fatture - ${name}`)
|
||||
});
|
||||
|
||||
if (CAN_MATRICI) loadMatrici(d.info.code, name);
|
||||
showTab(tab);
|
||||
}
|
||||
|
||||
function loadMatrici(code, name) {
|
||||
const ul = {
|
||||
m: 'm',
|
||||
kg: 'kg',
|
||||
pz: 'pz'
|
||||
};
|
||||
const fp = v => v === null || v === undefined ? '—' : fmtEur(v, Math.abs(v) >= 10 ? 2 : 3);
|
||||
$('#nMatrici').text('…');
|
||||
fetch('sales_matrici.php?action=list&from=2020-01-01&c=' + encodeURIComponent(code)).then(r => r.json()).then(m => {
|
||||
if (code !== current) return;
|
||||
const rows = (m && m.success) ? m.rows : [];
|
||||
$('#nMatrici').text(fmtNum(rows.length));
|
||||
makeTable('matrici', '#tMatrici', {
|
||||
data: rows,
|
||||
columns: [{
|
||||
title: 'Matrice',
|
||||
data: 'name',
|
||||
render: (v, t, r) => t === 'display' ? `<a class="ord-link" href="sales_matrici.php?c=${encodeURIComponent(code)}&k=${encodeURIComponent(r.key)}">${esc(v)}</a><div class="small text-muted">${esc((m.types || {})[r.type] || r.type)}</div>` : v
|
||||
}, {
|
||||
title: 'UM',
|
||||
data: 'uom'
|
||||
}, {
|
||||
title: 'Ordini',
|
||||
data: 'orders',
|
||||
className: 'text-end'
|
||||
}, {
|
||||
title: 'Quantità',
|
||||
data: 'qty',
|
||||
className: 'text-end text-nowrap',
|
||||
render: (v, t, r) => t === 'display' ? fmtNum(+v, +v % 1 ? 2 : 0) + (+r.open_qty ? `<div class="small text-muted">+${fmtNum(+r.open_qty)} da cons.</div>` : '') : +v
|
||||
}, {
|
||||
title: 'Valore',
|
||||
data: 'value',
|
||||
className: 'text-end amount',
|
||||
render: (v, t) => t === 'display' ? fmtEur(+v) : +v
|
||||
}, {
|
||||
title: 'Prezzo medio',
|
||||
data: 'price',
|
||||
className: 'text-end amount',
|
||||
render: (v, t, r) => t === 'display' ? `${fp(v)} <span class="small text-muted">/${ul[r.kind] || esc(r.uom)}</span>` : (v === null ? '' : +v)
|
||||
}, {
|
||||
title: 'Ultimo prezzo',
|
||||
data: 'last_price',
|
||||
className: 'text-end text-nowrap',
|
||||
render: (v, t, r) => t === 'display' ? `${fp(v)}<div class="small text-muted">${fmtDate(r.last_date)}</div>` : (v === null ? '' : +v)
|
||||
}, {
|
||||
title: 'Var. 12 mesi',
|
||||
data: 'var',
|
||||
className: 'text-end',
|
||||
render: (v, t) => t === 'display' ? (v === null ? '<span class="text-muted">—</span>' : deltaSpan(v, '')) : (v === null ? '' : +v)
|
||||
}, {
|
||||
title: 'Mescola stimata',
|
||||
data: 'kg',
|
||||
className: 'text-end',
|
||||
render: (v, t, r) => t === 'display' ? (r.kind === 'pz' ? '<span class="lvl watch">a pezzi: in attesa</span>' : (+v ? fmtNum(+v) + ' kg' : '<span class="text-muted">—</span>')) : +v
|
||||
}],
|
||||
order: [
|
||||
[4, 'desc']
|
||||
],
|
||||
buttons: xls(`Matrici - ${name}`)
|
||||
});
|
||||
}).catch(() => $('#nMatrici').text('—'));
|
||||
}
|
||||
|
||||
function showTab(t) {
|
||||
tab = t;
|
||||
$('#scTabs button').removeClass('active');
|
||||
@@ -1917,7 +1999,7 @@ if ($action === 'data') {
|
||||
});
|
||||
|
||||
const st = store();
|
||||
if (['open', 'orders', 'items', 'docs'].includes(st.tab)) tab = st.tab;
|
||||
if (['open', 'orders', 'items', 'docs'].concat(CAN_MATRICI ? ['matrici'] : []).includes(st.tab)) tab = st.tab;
|
||||
|
||||
loadFilters().then(() => {
|
||||
renderRecent();
|
||||
|
||||
@@ -12,7 +12,8 @@ $db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
if (!userCan('sales.stats.view')) {
|
||||
// Permesso specifico: prezzi di vendita per matrice e cliente (dati riservati)
|
||||
if (!userCan('sales.matrici.view')) {
|
||||
if (isset($_GET['action'])) {
|
||||
MagoSalesStats::jsonOut(['success' => false, 'message' => 'Non hai i permessi per questa pagina']);
|
||||
}
|
||||
|
||||
@@ -635,6 +635,9 @@ if ($action === 'data') {
|
||||
<a href="sales_orders_stats.php"><i class="fa-solid fa-list-check me-1"></i> Andamento ordini</a>
|
||||
<a href="sales_orders_years.php"><i class="fa-solid fa-chart-column me-1"></i> Confronto anni</a>
|
||||
<a href="sales_customer.php"><i class="fa-solid fa-address-card me-1"></i> Scheda cliente</a>
|
||||
<?php if (userCan('sales.matrici.view')) : ?>
|
||||
<a href="sales_matrici.php"><i class="fa-solid fa-shapes me-1"></i> Matrici</a>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<a href="sales_orders_deliveries.php" class="active"><i class="fa-solid fa-truck-fast me-1"></i> Consegne</a>
|
||||
<button type="button" class="sh-page ms-auto align-self-center mb-1" data-help-open="page.deliveries"><i class="fa-regular fa-circle-question me-1"></i> Come si legge</button>
|
||||
|
||||
@@ -1282,6 +1282,9 @@ if ($action === 'order') {
|
||||
<a href="sales_orders_stats.php" class="active"><i class="fa-solid fa-list-check me-1"></i> Andamento ordini</a>
|
||||
<a href="sales_orders_years.php"><i class="fa-solid fa-chart-column me-1"></i> Confronto anni</a>
|
||||
<a href="sales_customer.php"><i class="fa-solid fa-address-card me-1"></i> Scheda cliente</a>
|
||||
<?php if (userCan('sales.matrici.view')) : ?>
|
||||
<a href="sales_matrici.php"><i class="fa-solid fa-shapes me-1"></i> Matrici</a>
|
||||
<?php endif; ?>
|
||||
<?php if (userCan('sales.deliveries.view')) : ?>
|
||||
<a href="sales_orders_deliveries.php"><i class="fa-solid fa-truck-fast me-1"></i> Consegne</a>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -979,6 +979,9 @@ if ($action === 'data') {
|
||||
<a href="sales_orders_stats.php"><i class="fa-solid fa-list-check me-1"></i> Andamento ordini</a>
|
||||
<a href="sales_orders_years.php" class="active"><i class="fa-solid fa-chart-column me-1"></i> Confronto anni</a>
|
||||
<a href="sales_customer.php"><i class="fa-solid fa-address-card me-1"></i> Scheda cliente</a>
|
||||
<?php if (userCan('sales.matrici.view')) : ?>
|
||||
<a href="sales_matrici.php"><i class="fa-solid fa-shapes me-1"></i> Matrici</a>
|
||||
<?php endif; ?>
|
||||
<?php if (userCan('sales.deliveries.view')) : ?>
|
||||
<a href="sales_orders_deliveries.php"><i class="fa-solid fa-truck-fast me-1"></i> Consegne</a>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -1812,6 +1812,9 @@ if ($action === 'data') {
|
||||
<a href="sales_orders_stats.php"><i class="fa-solid fa-list-check me-1"></i> Andamento ordini</a>
|
||||
<a href="sales_orders_years.php"><i class="fa-solid fa-chart-column me-1"></i> Confronto anni</a>
|
||||
<a href="sales_customer.php"><i class="fa-solid fa-address-card me-1"></i> Scheda cliente</a>
|
||||
<?php if (userCan('sales.matrici.view')) : ?>
|
||||
<a href="sales_matrici.php"><i class="fa-solid fa-shapes me-1"></i> Matrici</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($canDeliveries) : ?>
|
||||
<a href="sales_orders_deliveries.php"><i class="fa-solid fa-truck-fast me-1"></i> Consegne</a>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in New Issue
Block a user