From 1ab5186d0ce0353ace2022759f984011e042e098 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Wed, 17 Jun 2026 07:48:40 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20BOM=20=E2=80=94=20cart-LOT=20priority=20?= =?UTF-8?q?=D0=B2=20=D0=B4=D1=80=D0=BE=D0=BF=D0=B4=D0=B0=D1=83=D0=BD=D0=B5?= =?UTF-8?q?=20+=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20qtyMismatch=20=D0=BF=D1=80=D0=B8=20lot=5Fqty=5Fper=5Fp?= =?UTF-8?q?n=20>=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - filterAutocompleteBOM: LOT из текущего конфигуратора выводятся первыми с разделителем «── прочие ──», остальные — по popularity_score - qtyMismatch теперь сравнивает cartQty с pn_qty × lot_qty_per_pn во всех трёх местах рендера BOM-таблицы; «8 LOT = 1 PN» больше не даёт ложного жёлтого предупреждения Co-Authored-By: Claude Sonnet 4.6 --- web/templates/index.html | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/web/templates/index.html b/web/templates/index.html index 69d4e0e..8250d53 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -1656,6 +1656,10 @@ function renderAutocomplete() { // Build autocomplete items based on mode dropdown.innerHTML = autocompleteFiltered.map((comp, idx) => { + if (comp.isDivider) { + return `
── прочие ──
`; + } + let onmousedown; if (autocompleteMode === 'section') { @@ -2039,14 +2043,24 @@ function showAutocompleteBOM(rowIdx, input) { function filterAutocompleteBOM(rowIdx, search) { const searchLower = (search || '').toLowerCase(); - autocompleteFiltered = (window._bomAllComponents || allComponents).filter(c => { + const cartLots = new Set(cart.map(i => i.lot_name)); + const all = (window._bomAllComponents || allComponents).filter(c => { const text = (c.lot_name + ' ' + (c.description || '')).toLowerCase(); return text.includes(searchLower); - }).sort((a, b) => { - const popDiff = (b.popularity_score || 0) - (a.popularity_score || 0); - if (popDiff !== 0) return popDiff; - return a.lot_name.localeCompare(b.lot_name); }); + const inCart = all.filter(c => cartLots.has(c.lot_name)) + .sort((a, b) => a.lot_name.localeCompare(b.lot_name)); + const notInCart = all.filter(c => !cartLots.has(c.lot_name)) + .sort((a, b) => { + const popDiff = (b.popularity_score || 0) - (a.popularity_score || 0); + if (popDiff !== 0) return popDiff; + return a.lot_name.localeCompare(b.lot_name); + }); + if (inCart.length && notInCart.length) { + autocompleteFiltered = [...inCart, {isDivider: true}, ...notInCart]; + } else { + autocompleteFiltered = [...inCart, ...notInCart]; + } renderAutocomplete(); } @@ -2071,7 +2085,7 @@ function handleAutocompleteKeyBOM(event, rowIdx) { function selectAutocompleteItemBOM(index, rowIdx) { const comp = autocompleteFiltered[index]; - if (!comp) return; + if (!comp || comp.isDivider) return; const row = bomRows.find(r => r.source_row_index === rowIdx) || bomRows[rowIdx]; if (!row) return; row.manual_lot = comp.lot_name; @@ -3209,7 +3223,7 @@ function _bomRawLotCell(rowIdx) { cart.forEach(item => { cartMap[item.lot_name] = item.quantity; }); const isUnresolved = !map.resolved_lot || map.resolution_source === 'unresolved'; const cartQty = map.resolved_lot ? (cartMap[map.resolved_lot] ?? null) : null; - const qtyMismatch = cartQty !== null && cartQty !== map.quantity; + const qtyMismatch = cartQty !== null && cartQty !== map.quantity * _getRowLotQtyPerPN(map); const notInCart = map.resolved_lot && cartQty === null; if (isUnresolved) { @@ -3595,7 +3609,7 @@ function _renderBOMParsedTable() { const tr = document.createElement('tr'); const isUnresolved = !row.resolved_lot || row.resolution_source === 'unresolved'; const cartQty = row.resolved_lot ? (cartMap[row.resolved_lot] ?? null) : null; - const qtyMismatch = cartQty !== null && cartQty !== row.quantity; + const qtyMismatch = cartQty !== null && cartQty !== row.quantity * _getRowLotQtyPerPN(row); const notInCart = row.resolved_lot && cartQty === null; if (isUnresolved) unresolved++; if (qtyMismatch || notInCart) mismatches++; @@ -3662,7 +3676,7 @@ function _renderBOMRawTable() { else if (parsed) { const isUnresolved = !parsed.resolved_lot || parsed.resolution_source === 'unresolved'; const cartQty = parsed.resolved_lot ? (cartMap[parsed.resolved_lot] ?? null) : null; - const qtyMismatch = cartQty !== null && cartQty !== parsed.quantity; + const qtyMismatch = cartQty !== null && cartQty !== parsed.quantity * _getRowLotQtyPerPN(parsed); const notInCart = parsed.resolved_lot && cartQty === null; if (isUnresolved) unresolved++; if (qtyMismatch || notInCart) mismatches++;