fix: BOM — cart-LOT priority в дропдауне + корректный qtyMismatch при lot_qty_per_pn > 1
- filterAutocompleteBOM: LOT из текущего конфигуратора выводятся первыми с разделителем «── прочие ──», остальные — по popularity_score - qtyMismatch теперь сравнивает cartQty с pn_qty × lot_qty_per_pn во всех трёх местах рендера BOM-таблицы; «8 LOT = 1 PN» больше не даёт ложного жёлтого предупреждения Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1656,6 +1656,10 @@ function renderAutocomplete() {
|
|||||||
|
|
||||||
// Build autocomplete items based on mode
|
// Build autocomplete items based on mode
|
||||||
dropdown.innerHTML = autocompleteFiltered.map((comp, idx) => {
|
dropdown.innerHTML = autocompleteFiltered.map((comp, idx) => {
|
||||||
|
if (comp.isDivider) {
|
||||||
|
return `<div class="px-3 py-1 text-xs text-gray-400 border-t border-gray-200 select-none cursor-default" style="pointer-events:none">── прочие ──</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
let onmousedown;
|
let onmousedown;
|
||||||
|
|
||||||
if (autocompleteMode === 'section') {
|
if (autocompleteMode === 'section') {
|
||||||
@@ -2039,14 +2043,24 @@ function showAutocompleteBOM(rowIdx, input) {
|
|||||||
|
|
||||||
function filterAutocompleteBOM(rowIdx, search) {
|
function filterAutocompleteBOM(rowIdx, search) {
|
||||||
const searchLower = (search || '').toLowerCase();
|
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();
|
const text = (c.lot_name + ' ' + (c.description || '')).toLowerCase();
|
||||||
return text.includes(searchLower);
|
return text.includes(searchLower);
|
||||||
}).sort((a, b) => {
|
});
|
||||||
|
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);
|
const popDiff = (b.popularity_score || 0) - (a.popularity_score || 0);
|
||||||
if (popDiff !== 0) return popDiff;
|
if (popDiff !== 0) return popDiff;
|
||||||
return a.lot_name.localeCompare(b.lot_name);
|
return a.lot_name.localeCompare(b.lot_name);
|
||||||
});
|
});
|
||||||
|
if (inCart.length && notInCart.length) {
|
||||||
|
autocompleteFiltered = [...inCart, {isDivider: true}, ...notInCart];
|
||||||
|
} else {
|
||||||
|
autocompleteFiltered = [...inCart, ...notInCart];
|
||||||
|
}
|
||||||
renderAutocomplete();
|
renderAutocomplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2071,7 +2085,7 @@ function handleAutocompleteKeyBOM(event, rowIdx) {
|
|||||||
|
|
||||||
function selectAutocompleteItemBOM(index, rowIdx) {
|
function selectAutocompleteItemBOM(index, rowIdx) {
|
||||||
const comp = autocompleteFiltered[index];
|
const comp = autocompleteFiltered[index];
|
||||||
if (!comp) return;
|
if (!comp || comp.isDivider) return;
|
||||||
const row = bomRows.find(r => r.source_row_index === rowIdx) || bomRows[rowIdx];
|
const row = bomRows.find(r => r.source_row_index === rowIdx) || bomRows[rowIdx];
|
||||||
if (!row) return;
|
if (!row) return;
|
||||||
row.manual_lot = comp.lot_name;
|
row.manual_lot = comp.lot_name;
|
||||||
@@ -3209,7 +3223,7 @@ function _bomRawLotCell(rowIdx) {
|
|||||||
cart.forEach(item => { cartMap[item.lot_name] = item.quantity; });
|
cart.forEach(item => { cartMap[item.lot_name] = item.quantity; });
|
||||||
const isUnresolved = !map.resolved_lot || map.resolution_source === 'unresolved';
|
const isUnresolved = !map.resolved_lot || map.resolution_source === 'unresolved';
|
||||||
const cartQty = map.resolved_lot ? (cartMap[map.resolved_lot] ?? null) : null;
|
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;
|
const notInCart = map.resolved_lot && cartQty === null;
|
||||||
|
|
||||||
if (isUnresolved) {
|
if (isUnresolved) {
|
||||||
@@ -3595,7 +3609,7 @@ function _renderBOMParsedTable() {
|
|||||||
const tr = document.createElement('tr');
|
const tr = document.createElement('tr');
|
||||||
const isUnresolved = !row.resolved_lot || row.resolution_source === 'unresolved';
|
const isUnresolved = !row.resolved_lot || row.resolution_source === 'unresolved';
|
||||||
const cartQty = row.resolved_lot ? (cartMap[row.resolved_lot] ?? null) : null;
|
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;
|
const notInCart = row.resolved_lot && cartQty === null;
|
||||||
if (isUnresolved) unresolved++;
|
if (isUnresolved) unresolved++;
|
||||||
if (qtyMismatch || notInCart) mismatches++;
|
if (qtyMismatch || notInCart) mismatches++;
|
||||||
@@ -3662,7 +3676,7 @@ function _renderBOMRawTable() {
|
|||||||
else if (parsed) {
|
else if (parsed) {
|
||||||
const isUnresolved = !parsed.resolved_lot || parsed.resolution_source === 'unresolved';
|
const isUnresolved = !parsed.resolved_lot || parsed.resolution_source === 'unresolved';
|
||||||
const cartQty = parsed.resolved_lot ? (cartMap[parsed.resolved_lot] ?? null) : null;
|
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;
|
const notInCart = parsed.resolved_lot && cartQty === null;
|
||||||
if (isUnresolved) unresolved++;
|
if (isUnresolved) unresolved++;
|
||||||
if (qtyMismatch || notInCart) mismatches++;
|
if (qtyMismatch || notInCart) mismatches++;
|
||||||
|
|||||||
Reference in New Issue
Block a user