diff --git a/web/templates/index.html b/web/templates/index.html index 5a4749f..214fdf5 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -259,10 +259,20 @@

Вставьте таблицу из Excel (Ctrl+V в область ниже)

-

Поддерживаемые форматы:

-

PN Кол-во — минимальный (2 колонки)

-

PN Описание Кол-во Цена ед. — расширенный

-

Строка-заголовок определяется автоматически (пропускается если первая ячейка — текст). Порядок колонок: первая текстовая = PN, первая числовая = Кол-во, следующая числовая = Цена.

+

Колонки строго по порядку:

+

+ PN + Кол-во + — минимальный +

+

+ PN + Кол-во + Описание + Цена ед. + — полный +

+

Строка-заголовок пропускается автоматически если во 2-й колонке не число.

l.trim()); const parsed = []; + // Fixed positional format: PN | qty | [description] | [price] + // Skip header: if col[1] is not numeric on the first row → skip that row for (let i = 0; i < lines.length; i++) { - const cols = lines[i].split('\t'); + const cols = lines[i].split('\t').map(c => c.trim()); if (cols.length < 2) continue; - // Auto-detect columns: - // 2 cols → [PN, qty] - // 3+ cols → first text=PN, first numeric=qty, subsequent numeric=prices - let pn = '', qty = 0, description = '', unit_price = null, total_price = null; + const pn = cols[0]; + const rawQty = cols[1].replace(/[, ]/g, ''); - if (cols.length === 2) { - pn = cols[0].trim(); - qty = parseInt(cols[1]) || 0; - // Skip header row if qty is NaN - if (!qty && i === 0) continue; - } else { - pn = cols[0].trim(); - // Find first numeric column for qty - let qtyIdx = -1, priceIdx = -1; - for (let c = 1; c < cols.length; c++) { - const v = cols[c].trim().replace(/[, ]/g, ''); - if (!isNaN(parseFloat(v)) && v !== '') { - if (qtyIdx === -1) { qtyIdx = c; } - else if (priceIdx === -1) { priceIdx = c; } - } - } - // If first row has non-numeric qty → likely header, skip - if (qtyIdx === -1) continue; - const rawQty = cols[qtyIdx].trim().replace(/[, ]/g, ''); - if (i === 0 && isNaN(parseInt(rawQty))) continue; - qty = parseInt(rawQty) || 1; + // Skip header row + if (i === 0 && isNaN(parseInt(rawQty))) continue; - // Description: columns between PN and first numeric - const descParts = []; - for (let c = 1; c < qtyIdx; c++) { descParts.push(cols[c].trim()); } - description = descParts.join(' ').trim(); - - if (priceIdx !== -1) { - const rawPrice = cols[priceIdx].trim().replace(/[, ]/g, ''); - unit_price = parseFloat(rawPrice) || null; - if (unit_price && qty) total_price = unit_price * qty; - } + const qty = parseInt(rawQty) || 1; + const description = cols.length >= 3 ? cols[2] : ''; + let unit_price = null, total_price = null; + if (cols.length >= 4) { + const rawPrice = cols[3].replace(/[, ]/g, ''); + unit_price = parseFloat(rawPrice) || null; + if (unit_price) total_price = unit_price * qty; } if (!pn) continue; parsed.push({ sort_order: (parsed.length + 1) * 10, vendor_pn: pn, - quantity: qty || 1, + quantity: qty, description, unit_price, total_price,