Files
QuoteForge/bible-local/server-contract-qt-settings.md
Mikhail Chusavitin 4900cd073c feat: server-driven configurator settings via qt_settings
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>
2026-06-23 09:33:31 +03:00

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`.