Replaces hardcoded JS category filters and config-type buttons with server-pushed settings synced from qt_settings (MariaDB) → local_qt_settings (SQLite). - new table local_qt_settings (AutoMigrate) — synced after component sync - GET /api/configurator-settings returns config_types, tab_config, always_visible_tabs, required_categories with hardcoded fallbacks - new-config modal: type buttons rendered from server data (Сервер/СХД static fallback) - configurator: TAB_CONFIG and category filter driven by server; required-category badge on tabs - SyncQtSettings wired into SyncComponents and SyncAll handlers (non-fatal on old server) - bible-local/server-contract-qt-settings.md — contract for server-side agent - page titles: OFS → QFS Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
166 lines
4.9 KiB
Markdown
166 lines
4.9 KiB
Markdown
# Server contract: qt_settings
|
|
|
|
## Purpose
|
|
|
|
`qt_settings` is a general-purpose key→JSON-value table that the price management
|
|
application uses to push configuration into QuoteForge clients. QF reads it during
|
|
component sync and caches the result in `local_qt_settings` (SQLite).
|
|
|
|
## Required MariaDB changes (implemented by server-side agent)
|
|
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS qt_settings (
|
|
name VARCHAR(100) NOT NULL PRIMARY KEY,
|
|
value TEXT NOT NULL -- JSON-encoded value
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
|
|
GRANT SELECT ON RFQ_LOG.qt_settings TO 'qfs_user'@'%';
|
|
```
|
|
|
|
## Settings consumed by QuoteForge
|
|
|
|
All values are JSON. Missing or unparseable entries are silently skipped; QF
|
|
falls back to hardcoded defaults for each missing key.
|
|
|
|
---
|
|
|
|
### `config_types`
|
|
|
|
Defines the available device configuration types, their localized names, and the
|
|
category codes that are allowed for each type. QF uses this for:
|
|
- the new-config modal (button list + labels);
|
|
- the configurator's category filter per `config_type`.
|
|
|
|
**Value format:** JSON array of objects.
|
|
|
|
```json
|
|
[
|
|
{
|
|
"code": "server",
|
|
"name_ru": "Сервер",
|
|
"display_order": 10,
|
|
"categories": [
|
|
"MB","CPU","MEM","RAID",
|
|
"SSD","HDD","M2","EDSFF","HHHL",
|
|
"GPU","NIC","HCA","DPU","HBA",
|
|
"PSU","PS","ACC","RISERS","CARD","BB"
|
|
]
|
|
},
|
|
{
|
|
"code": "storage",
|
|
"name_ru": "СХД",
|
|
"display_order": 20,
|
|
"categories": [
|
|
"DKC","CPU","MEM","PS",
|
|
"SSD","HDD","M2","EDSFF","HHHL",
|
|
"NIC","HBA","HCA","ACC","CARD"
|
|
]
|
|
}
|
|
]
|
|
```
|
|
|
|
Fields:
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `code` | string | Identifier stored on `qt_configurations.config_type`. Must be stable. |
|
|
| `name_ru` | string | Display name in Russian for the QF UI. |
|
|
| `display_order` | int | Sort order for the modal button list. |
|
|
| `categories` | string[] | Allowlist of LOT category codes visible in this config type. A category absent from ALL entries is visible in all types. |
|
|
|
|
---
|
|
|
|
### `tab_config`
|
|
|
|
Defines the configurator tab layout: which tabs exist, which categories each tab
|
|
contains, optional sub-sections within a tab, and whether the tab uses
|
|
single-select mode.
|
|
|
|
**Value format:** JSON array of tab objects (ordered — defines tab bar order).
|
|
|
|
```json
|
|
[
|
|
{
|
|
"key": "base",
|
|
"label": "Base",
|
|
"single_select": true,
|
|
"categories": ["MB","CPU","MEM","ENC","DKC","CTL"],
|
|
"sections": null
|
|
},
|
|
{
|
|
"key": "storage",
|
|
"label": "Storage",
|
|
"single_select": false,
|
|
"categories": ["RAID","M2","SSD","HDD","EDSFF","HHHL"],
|
|
"sections": [
|
|
{ "title": "RAID Контроллеры", "categories": ["RAID"] },
|
|
{ "title": "Диски", "categories": ["M2","SSD","HDD","EDSFF","HHHL"] }
|
|
]
|
|
},
|
|
{
|
|
"key": "pci",
|
|
"label": "PCI",
|
|
"single_select": false,
|
|
"categories": ["GPU","DPU","NIC","HCA","HBA","HIC"],
|
|
"sections": [
|
|
{ "title": "GPU / DPU", "categories": ["GPU","DPU"] },
|
|
{ "title": "NIC / HCA", "categories": ["NIC","HCA"] },
|
|
{ "title": "HBA", "categories": ["HBA"] },
|
|
{ "title": "HIC", "categories": ["HIC"] }
|
|
]
|
|
},
|
|
{ "key": "power", "label": "Power", "single_select": false, "categories": ["PS","PSU"] },
|
|
{ "key": "accessories", "label": "Accessories", "single_select": false, "categories": ["ACC","CARD"] },
|
|
{ "key": "sw", "label": "SW", "single_select": false, "categories": ["SW"] }
|
|
]
|
|
```
|
|
|
|
The QF frontend always appends an "other" tab for any categories not listed here.
|
|
|
|
---
|
|
|
|
### `always_visible_tabs`
|
|
|
|
Tab keys that are always shown in the configurator regardless of whether they
|
|
contain any items. Other tabs are hidden when empty.
|
|
|
|
**Value format:** JSON string array.
|
|
|
|
```json
|
|
["base", "storage", "pci"]
|
|
```
|
|
|
|
---
|
|
|
|
### `required_categories`
|
|
|
|
Category codes that must have at least one LOT selected for a configuration to
|
|
be considered complete. Keyed by `config_type` code. QF uses this to show a
|
|
badge on the tab label when required categories are missing.
|
|
|
|
**Value format:** JSON object mapping config_type code → string array.
|
|
|
|
```json
|
|
{
|
|
"server": ["CPU", "MEM", "BB"],
|
|
"storage": ["DKC", "CPU", "MEM"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Backward compatibility
|
|
|
|
- If `qt_settings` does not exist (old server): QF logs `Warn` during sync and
|
|
leaves `local_qt_settings` empty. The frontend falls back to hardcoded defaults
|
|
for all four settings. No crash, no data loss.
|
|
- If a specific key is absent from `qt_settings`: QF falls back to the hardcoded
|
|
default for that key only.
|
|
- Old QF clients that do not know about `local_qt_settings` continue to use their
|
|
hardcoded JS constants unchanged.
|
|
|
|
## Note on `qt_categories`
|
|
|
|
`qt_categories.name` and `qt_categories.name_ru` are being removed.
|
|
QF runtime does not depend on them — `GetCategories` derives `Name` from the
|
|
category code string stored in `local_components`.
|