fixed sales matrici2
This commit is contained in:
@@ -1273,7 +1273,7 @@ if ($action === 'list' || $action === 'detail') {
|
|||||||
renderMix();
|
renderMix();
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
$('#loading').html('<div class="text-danger">Errore nel caricamento</div>');
|
$('#loading').html('<div class="text-danger">Errore nel caricamento: ' + esc(e && e.message ? e.message : e) + '</div>');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1784,46 +1784,62 @@ if ($action === 'list' || $action === 'detail') {
|
|||||||
|
|
||||||
function mixPane(d) {
|
function mixPane(d) {
|
||||||
const h = d.head;
|
const h = d.head;
|
||||||
if (h.kind === 'pz') return '<div class="alert alert-warning mb-0"><span class="tb tb-pz">A pezzi</span> Le righe vendute a pezzi aspettano la conversione pezzi → metri: le mescole non sono ancora stimate.</div>';
|
const cost = d.cost || {};
|
||||||
if (!d.mix.length) return `<div class="alert alert-light mb-0">${h.id ? 'Nessuna mescola collegata: completa la scheda di lavoro della matrice.' : 'Non collegata a una matrice dell\'anagrafica.'}</div>`;
|
const ul = UOM_LABEL[h.kind] || esc(h.uom);
|
||||||
const src = h.mix_source === 'scheda' ? 'dall\'ultima scheda di lavoro' : 'dall\'anagrafica matrice (senza g/m)';
|
if (h.kind === 'pz') {
|
||||||
return `<div class="chart-hint mb-2">Mescole ${src}. ${h.kind === 'm' ? 'Kg = metri × g/m ÷ 1000.' : 'I kg venduti si dividono in base alla quota.'}</div>
|
return '<div class="alert alert-warning mb-0"><span class="tb tb-pz">A pezzi</span> Le righe vendute a pezzi aspettano la conversione pezzi → metri: le mescole non sono ancora stimate.</div>';
|
||||||
<div class="table-responsive"><table class="table table-striped align-middle mx-table mb-0"><thead><tr><th>Mescola</th><th class="text-end">g/m</th><th class="text-end">Quota</th><th class="text-end">€/kg</th><th class="text-end">Costo /${UOM_LABEL[h.kind] || esc(h.uom)}</th><th class="text-end">Kg periodo</th><th class="text-end">Kg da produrre</th></tr></thead><tbody>
|
|
||||||
${d.mix.map(m => {
|
|
||||||
const pt = ((d.cost || {}).parts || []).find(x => x.id === m.id) || {};
|
|
||||||
const eur = pt.eur_kg !== null && pt.eur_kg !== undefined ?
|
|
||||||
`
|
|
||||||
$ {
|
|
||||||
fmtNum(pt.eur_kg, 3)
|
|
||||||
}
|
}
|
||||||
$ {
|
if (!d.mix.length) {
|
||||||
pt.old ? ' <span class="tb tb-gm" title="Ultimo acquisto ' + fmtDate(pt.last_date) + '">vecchio</span>' : ''
|
const msg = h.id ? 'Nessuna mescola collegata: completa la scheda di lavoro della matrice.' : 'Non collegata a una matrice dell'anagrafica.';
|
||||||
|
return '<div class="alert alert-light mb-0">' + msg + '</div>';
|
||||||
}
|
}
|
||||||
$ {
|
const src = h.mix_source === 'scheda' ? 'dall'ultima scheda di lavoro' : 'dall'anagrafica matrice (senza g/m)';
|
||||||
pt.check ? ' <span class="tb tb-check">da verificare</span>' : ''
|
const rule = h.kind === 'm' ? 'Kg = metri × g/m ÷ 1000.' : 'I kg venduti si dividono in base alla quota.';
|
||||||
} < div class = "small text-muted" > $ {
|
|
||||||
esc(pt.supplier || '')
|
let html = '<div class="chart-hint mb-2">Mescole ' + src + '. ' + rule + '</div>';
|
||||||
} < /div>` :
|
html += '<div class="table-responsive"><table class="table table-striped align-middle mx-table mb-0"><thead><tr>';
|
||||||
'<span class="tb tb-gm" title="Nessun acquisto abbinato: aggiungi il nome d\'acquisto nella pagina mescole">senza prezzo</span>';
|
html += '<th>Mescola</th><th class="text-end">g/m</th><th class="text-end">Quota</th><th class="text-end">€/kg</th>';
|
||||||
return `<tr style="cursor:default;"><td><b>${esc(m.name)}</b>${m.out ? `<div class="small text-muted">${esc(m.out)}</div>` : ''}</td>
|
html += '<th class="text-end">Costo /' + ul + '</th><th class="text-end">Kg periodo</th><th class="text-end">Kg da produrre</th>';
|
||||||
<td class="text-end">${m.gm ? fmtNum(m.gm, 1) : '<span class="tb tb-gm">mancante</span>'}</td>
|
html += '</tr></thead><tbody>';
|
||||||
<td class="text-end">${fmtNum(m.share, 1)}%</td>
|
d.mix.forEach(function(m) {
|
||||||
<td class="text-end">${eur}</td>
|
html += mixRow(m, cost);
|
||||||
<td class="text-end amount">${pt.part !== null && pt.part !== undefined ? '<b>' + fmtPrice(pt.part) + '</b>' : '—'}</td>
|
});
|
||||||
<td class="text-end amount">${fmtNum(m.kg)} kg</td>
|
if (cost.cost !== null && cost.cost !== undefined) {
|
||||||
<td class="text-end amount">${m.kg_open ? '<b style="color:#047857">' + fmtNum(m.kg_open) + ' kg</b>' : '—'}</td></tr>`;
|
html += '<tr class="table-light" style="cursor:default;"><td colspan="4" class="text-end fw-bold">Costo mescola totale</td>';
|
||||||
}).join('')
|
html += '<td class="text-end amount"><b>' + fmtPrice(cost.cost) + '</b></td><td colspan="2"></td></tr>';
|
||||||
}
|
}
|
||||||
$ {
|
html += '</tbody></table></div>';
|
||||||
(d.cost || {}).cost !== null && (d.cost || {}).cost !== undefined ? `<tr style="cursor:default;" class="table-light"><td colspan="4" class="text-end fw-bold">Costo mescola totale</td><td class="text-end amount"><b>${fmtPrice(d.cost.cost)}</b></td><td colspan="2"></td></tr>` : ''
|
html += '<div class="chart-hint mt-2">Costo = ' + (h.kind === 'm' ? 'g/m × €/kg ÷ 1000' : 'media dei €/kg pesata sulla quota') +
|
||||||
} <
|
', prezzi medi degli ultimi ' + (cost.price_months || 3) + ' mesi pagati in Mago. Solo mescola: senza scarto, lavorazione, energia.</div>';
|
||||||
/tbody></table > < /div> <
|
return html;
|
||||||
div class = "chart-hint mt-2" > Costo = $ {
|
|
||||||
h.kind === 'm' ? 'g/m × €/kg ÷ 1000' : 'media dei €/kg pesata sulla quota'
|
|
||||||
}, prezzi medi degli ultimi $ {
|
|
||||||
(d.cost || {}).price_months || 3
|
|
||||||
}
|
}
|
||||||
mesi pagati in Mago.Solo mescola: senza scarto, lavorazione, energia. < /div>`;
|
|
||||||
|
function mixRow(m, cost) {
|
||||||
|
const pt = (cost.parts || []).find(function(x) {
|
||||||
|
return x.id === m.id;
|
||||||
|
}) || {};
|
||||||
|
let eur;
|
||||||
|
if (pt.eur_kg !== null && pt.eur_kg !== undefined) {
|
||||||
|
eur = fmtNum(pt.eur_kg, 3);
|
||||||
|
if (pt.old) eur += ' <span class="tb tb-gm" title="Ultimo acquisto ' + fmtDate(pt.last_date) + '">vecchio</span>';
|
||||||
|
if (pt.check) eur += ' <span class="tb tb-check">da verificare</span>';
|
||||||
|
eur += '<div class="small text-muted">' + esc(pt.supplier || '') + '</div>';
|
||||||
|
} else {
|
||||||
|
eur = '<span class="tb tb-gm" title="Nessun acquisto abbinato: aggiungi il nome d'acquisto nella pagina mescole">senza prezzo</span>';
|
||||||
|
}
|
||||||
|
const gm = m.gm ? fmtNum(m.gm, 1) : '<span class="tb tb-gm">mancante</span>';
|
||||||
|
const part = (pt.part !== null && pt.part !== undefined) ? '<b>' + fmtPrice(pt.part) + '</b>' : '—';
|
||||||
|
const open = m.kg_open ? '<b style="color:#047857">' + fmtNum(m.kg_open) + ' kg</b>' : '—';
|
||||||
|
const out = m.out ? '<div class="small text-muted">' + esc(m.out) + '</div>' : '';
|
||||||
|
return '<tr style="cursor:default;">' +
|
||||||
|
'<td><b>' + esc(m.name) + '</b>' + out + '</td>' +
|
||||||
|
'<td class="text-end">' + gm + '</td>' +
|
||||||
|
'<td class="text-end">' + fmtNum(m.share, 1) + '%</td>' +
|
||||||
|
'<td class="text-end">' + eur + '</td>' +
|
||||||
|
'<td class="text-end amount">' + part + '</td>' +
|
||||||
|
'<td class="text-end amount">' + fmtNum(m.kg) + ' kg</td>' +
|
||||||
|
'<td class="text-end amount">' + open + '</td>' +
|
||||||
|
'</tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDetailChart(d) {
|
function renderDetailChart(d) {
|
||||||
@@ -2001,7 +2017,7 @@ if ($action === 'list' || $action === 'detail') {
|
|||||||
title: 'Margine',
|
title: 'Margine',
|
||||||
data: 'margin_pct',
|
data: 'margin_pct',
|
||||||
className: 'text-end',
|
className: 'text-end',
|
||||||
render: (v, t, r) => t === 'display' ? (v === null ? '<span class="text-muted">—</span>' : `${marginSpan(v)}<div class="small text-muted" title="Margine sull'ultimo prezzo">ultimo ${r.last_margin_pct === null ? '—' : fmtNum(r.last_margin_pct, 0) + '%'}</div>`) : (v === null ? (t === 'export' ? '' : -1e9) : (t === 'export' ? v / 100 : +v))
|
render: (v, t, r) => t === 'display' ? (v === null ? '<span class="text-muted">—</span>' : `${marginSpan(v)}<div class="small text-muted" title="Margine sull'ultimo prezzo">ultimo ${r.last_margin_pct === null ? '—' : fmtNum(r.last_margin_pct, 0) + '%'}</div>`) : (v === null ? (t === 'export' ? '' : -1e9) : (t === 'export' ? v / 100 : +v))
|
||||||
}],
|
}],
|
||||||
order: [
|
order: [
|
||||||
[3, 'desc']
|
[3, 'desc']
|
||||||
@@ -2170,7 +2186,7 @@ if ($action === 'list' || $action === 'detail') {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
loadFilters().then(load).then(() => {
|
loadFilters().catch(e => console.error('Filtri non caricati', e)).then(load).then(() => {
|
||||||
const k = new URLSearchParams(location.search).get('k');
|
const k = new URLSearchParams(location.search).get('k');
|
||||||
if (k) openDetail(k);
|
if (k) openDetail(k);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user