Vendor mapping: wildcard ignore patterns, bulk CSV import, multi-lot qty

- Add glob pattern support (* and ?) for ignore rules stored in
  qt_vendor_partnumber_seen (is_pattern flag, migration 041)
- Pattern matching applied in stock/competitor import, partnumber book
  snapshot, and vendor mappings list (Go-side via NormalizeKey)
- BulkUpsertMappings: replace N+1 loop with two batch SQL upserts,
  validating all lots in a single query (~1500 queries → 3-4)
- CSV import: multi-lot per PN via repeated rows, optional qty column
- CSV export: updated column format vendor;partnumber;lot_name;qty;description;ignore;notes
- UI: ignore patterns section with add/delete, import progress feedback
- Update bible-local/vendor-mapping.md with new CSV format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-03-19 09:41:48 +03:00
parent df14da2265
commit f73e3d144d
13 changed files with 653 additions and 51 deletions

View File

@@ -110,12 +110,32 @@ Contract notes:
---
## CSV Import (Global Vendor Mappings UI)
## CSV Import / Export (Global Vendor Mappings UI)
- Формат CSV для Excel (RU locale): разделитель `;`
- Кодировка: `UTF-8` (BOM допускается и поддерживается)
- Рекомендуемые колонки: `vendor;partnumber;lot_name;description;ignore`
- Колонки: `vendor;partnumber;lot_name;qty;description;ignore`
- Допустим импорт как с заголовком, так и без заголовка (в фиксированном порядке колонок выше)
- Пустые строки пропускаются
- Для строки обязательны `partnumber` и (`lot_name` или заполненный `ignore`)
- Если `ignore` заполнен и `lot_name` пустой, строка помечается как ignored в `qt_vendor_partnumber_seen`
### Маппинг один p/n → несколько lot
Один p/n можно привязать к нескольким lot через несколько строк с одинаковым `partnumber`.
Строки аккумулируются, затем сохраняются как один `lots_json` (upsert).
```
vendor;partnumber;lot_name;qty;description;ignore
Intel;E-2336;Server_Intel;1;Процессор Intel;
Intel;E-2336;Server_AMD;2;;
Samsung;MZ7L3480HCHQ-00A07;SSD_480GB;;;
```
- `qty` необязательно; если пусто или 0 — считается `1`
- `description` берётся из первой строки p/n
- Каждый повторный импорт того же p/n **перезаписывает** весь `lots_json`
### Экспорт незамапленных p/n
Кнопка «Выгрузить незамапленные» генерирует CSV в том же формате с пустыми `lot_name` и `qty` — для заполнения пользователем и последующего импорта.