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++;