feat: Nx BOM import — формат <qty>x <description>
Добавлен новый вариант импорта спеки: quantity-first формат, где каждая строка начинается с `<qty>x <description>` (например, «2x Intel Xeon 8570»). Порядок детекции: Inspur → Nx → Text BOM. Заголовок «, в составе:» работает так же, как в Text BOM — последний токен перед запятой становится server_model. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,41 @@ Rules:
|
||||
- lines that do not match `<description> - <quantity> шт.` are skipped;
|
||||
- no price data is present in the format; `unit_price` and `total_price` are left nil.
|
||||
|
||||
## Nx BOM import (quantity-first)
|
||||
|
||||
The same endpoint `POST /api/projects/:uuid/vendor-import` also accepts a quantity-first BOM
|
||||
where each item line begins with `<qty>x <description>`.
|
||||
|
||||
Format: an optional header line ending with `, в составе:` followed by one component per line as
|
||||
`<qty>x <description>`. The `x` separator is case-insensitive; parentheses, commas, and hyphens
|
||||
inside the description are preserved as-is.
|
||||
|
||||
Example:
|
||||
```
|
||||
Сервер G893-SD1-AAX3, в составе:
|
||||
1x 8U 2CPU 8GPU Server System (32x DDR5 DIMM Slots,8x 2.5" Hot-Swap Drive Bays, 4+4 3000W, 2x 10Gb/s RJ45, 2x IPMI RJ45)
|
||||
2x Intel Xeon 8570 (56 cores, 2.1GHz, 300MB, 350W)
|
||||
32x 64GB DDR5 ECC RDIMM
|
||||
1x GPU Nvidia HGX H200 141GB 8GPU
|
||||
3x 1.92TB NVMe PCIe SFF RI
|
||||
5x 7.68TB NVMe PCIe SFF RI
|
||||
8x 1-port 400G NDR OSFP CX7
|
||||
2x 2-port 100GbE QSFP56 CX6
|
||||
1x 2-port 10GbE RJ45
|
||||
```
|
||||
|
||||
Rules:
|
||||
- the entire file becomes a single configuration (`server_count = 1`);
|
||||
- the header (any line ending with `, в составе:`) supplies `server_model` and `name`; the model is the
|
||||
last whitespace-separated token before the comma;
|
||||
- without a header, `name` falls back to the uploaded filename (without extension) and `server_model` is empty;
|
||||
- the format carries no partnumbers — each line's description is stored as both `vendor_partnumber` and
|
||||
`description`, so rows resolve through the active partnumber book when matched and otherwise stay
|
||||
unresolved and editable in the UI;
|
||||
- lines that do not match `<qty>x <description>` are skipped;
|
||||
- no price data is present in the format; `unit_price` and `total_price` are left nil;
|
||||
- detection runs before Text BOM in the format switch (Inspur → Nx → Text).
|
||||
|
||||
## Pasted BOM text parsing
|
||||
|
||||
`POST /api/vendor-spec/parse-text` is a stateless endpoint that parses pasted single-column text BOM
|
||||
@@ -119,7 +154,7 @@ Rules:
|
||||
`{"rows": [{vendor_partnumber, quantity, description}], "format": "Inspur"|"Text"|""}`.
|
||||
|
||||
This shares the exact detectors and parsers used by the file-import path
|
||||
(`ParsePastedBOMText` → `IsInspurBOM`/`parseInspurBOM`, `IsTextBOM`/`parseTextBOM`), so paste and upload
|
||||
behave identically — there is no second parser in the frontend. The configurator's BOM paste box calls
|
||||
this endpoint; an empty `rows` result (or any payload containing tabs, i.e. a real spreadsheet table)
|
||||
falls back to the manual column-mapping grid.
|
||||
(`ParsePastedBOMText` → `IsInspurBOM`/`parseInspurBOM`, `IsNxBOM`/`parseNxBOM`, `IsTextBOM`/`parseTextBOM`),
|
||||
so paste and upload behave identically — there is no second parser in the frontend. The configurator's BOM
|
||||
paste box calls this endpoint; an empty `rows` result (or any payload containing tabs, i.e. a real
|
||||
spreadsheet table) falls back to the manual column-mapping grid.
|
||||
|
||||
Reference in New Issue
Block a user