feat: Flexoptix section — speed formatting + Lagerbestand display
Speed display: fix raw Gbps decimals → formatted labels
- 1600.00G → 1.6T (≥1000 Gbps converted to T)
- 400G → 400G (clean integer, no trailing .00)
- Helper function fmtSpeed() added in dashboard JS
Lagerbestand: add stock availability per transceiver
- getFlexoptixSuggestions() extended with LEFT JOIN LATERAL on
stock_observations (latest row per transceiver)
- Returns warehouse_de_qty, warehouse_global_qty, backorder_qty,
backorder_estimated_date
- Dashboard renders color-coded badges per row:
green = DE-Lager quantity
blue = Global-Lager quantity
yellow = Zulauf with estimated delivery date if available
- Badges hidden when all quantities are null/zero (graceful fallback)
This commit is contained in:
parent
de179c4c7c
commit
9b8b03e783
@ -352,9 +352,20 @@ export async function getFlexoptixSuggestions(switchId: string) {
|
||||
CASE WHEN t.price_verified_eur IS NOT NULL THEN 'EUR'
|
||||
ELSE (SELECT po.currency FROM price_observations po
|
||||
WHERE po.transceiver_id = t.id ORDER BY po.time DESC LIMIT 1)
|
||||
END AS latest_currency
|
||||
END AS latest_currency,
|
||||
so.warehouse_de_qty,
|
||||
so.warehouse_global_qty,
|
||||
so.backorder_qty,
|
||||
so.backorder_estimated_date
|
||||
FROM transceivers t
|
||||
JOIN vendors v ON t.vendor_id = v.id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT warehouse_de_qty, warehouse_global_qty, backorder_qty, backorder_estimated_date
|
||||
FROM stock_observations
|
||||
WHERE transceiver_id = t.id
|
||||
ORDER BY time DESC
|
||||
LIMIT 1
|
||||
) so ON true
|
||||
WHERE LOWER(v.name) = 'flexoptix'
|
||||
AND t.form_factor IN (
|
||||
SELECT form_factor FROM switch_form_factors WHERE form_factor IS NOT NULL
|
||||
|
||||
@ -4310,10 +4310,18 @@ async function openSwitchDetail(id) {
|
||||
+ '</div>';
|
||||
fch += '<div style="font-size:0.72rem;color:var(--text-dim);margin-bottom:0.6rem">Passend für diesen Switch — FlexBox-Codierung möglich</div>';
|
||||
|
||||
// Format speed_gbps → "1.6T", "400G", "100G" etc.
|
||||
function fmtSpeed(gbps) {
|
||||
if (!gbps) return '?';
|
||||
var n = parseFloat(gbps);
|
||||
if (n >= 1000) return (n / 1000) + 'T';
|
||||
return Math.round(n) + 'G';
|
||||
}
|
||||
|
||||
// Group by speed class
|
||||
var foGroups = {};
|
||||
foAll.forEach(function(t) {
|
||||
var key = (t.speed_gbps ? t.speed_gbps + 'G' : (t.speed || '?')) + ' ' + (t.form_factor || '?');
|
||||
var key = fmtSpeed(t.speed_gbps) + ' ' + (t.form_factor || '?');
|
||||
if (!foGroups[key]) foGroups[key] = [];
|
||||
foGroups[key].push(t);
|
||||
});
|
||||
@ -4342,10 +4350,27 @@ async function openSwitchDetail(id) {
|
||||
var shopHref = t.product_page_url || ('https://www.flexoptix.net/en/search/ajax/suggest/?q=' + encodeURIComponent(t.part_number || t.standard_name || ''));
|
||||
var reach = t.reach_label ? '<span style="color:var(--text-dim);font-size:0.68rem;margin-left:0.25rem">' + esc(t.reach_label) + '</span>' : '';
|
||||
|
||||
// Stock badges
|
||||
var stockHtml = '';
|
||||
var deQty = parseInt(t.warehouse_de_qty) || 0;
|
||||
var glQty = parseInt(t.warehouse_global_qty) || 0;
|
||||
var boQty = parseInt(t.backorder_qty) || 0;
|
||||
if (deQty > 0 || glQty > 0 || boQty > 0) {
|
||||
stockHtml += '<div style="display:flex;gap:0.3rem;flex-wrap:wrap;margin-top:0.2rem">';
|
||||
if (deQty > 0) stockHtml += '<span style="font-size:0.62rem;background:rgba(16,185,129,0.12);color:#10b981;border:1px solid rgba(16,185,129,0.3);border-radius:3px;padding:1px 5px">DE ' + deQty + ' Stk</span>';
|
||||
if (glQty > 0) stockHtml += '<span style="font-size:0.62rem;background:rgba(59,130,246,0.12);color:#60a5fa;border:1px solid rgba(59,130,246,0.3);border-radius:3px;padding:1px 5px">Global ' + glQty + ' Stk</span>';
|
||||
if (boQty > 0) {
|
||||
var boDate = t.backorder_estimated_date ? ' bis ' + new Date(t.backorder_estimated_date).toLocaleDateString('de-DE', {day:'2-digit',month:'2-digit'}) : '';
|
||||
stockHtml += '<span style="font-size:0.62rem;background:rgba(245,158,11,0.12);color:#fbbf24;border:1px solid rgba(245,158,11,0.3);border-radius:3px;padding:1px 5px">Zulauf ' + boQty + boDate + '</span>';
|
||||
}
|
||||
stockHtml += '</div>';
|
||||
}
|
||||
|
||||
fch += '<div style="display:flex;align-items:center;padding:0.35rem 0.5rem;background:rgba(255,102,0,0.05);border:1px solid rgba(255,102,0,0.2);border-radius:6px;gap:0.35rem;cursor:pointer" onclick="openTxDetail(\'' + esc(t.id) + '\')">'
|
||||
+ '<div style="flex:1;min-width:0">'
|
||||
+ '<span style="font-weight:600;font-size:0.8rem;color:var(--text-bright)">' + esc(t.part_number || t.standard_name || t.slug) + '</span>'
|
||||
+ reach
|
||||
+ '<div><span style="font-weight:600;font-size:0.8rem;color:var(--text-bright)">' + esc(t.part_number || t.standard_name || t.slug) + '</span>'
|
||||
+ reach + '</div>'
|
||||
+ stockHtml
|
||||
+ '</div>'
|
||||
+ (priceStr
|
||||
? '<span style="font-weight:700;font-size:0.78rem;color:#ff6600;white-space:nowrap">' + priceStr + '</span>'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user