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