Прайслисты: добавлено поле price_quality (0-9, выставляется внешней
утилитой ценообразования на основе количества/свежести котировок за
период — QF только отображает, не считает сам). В карточке прайслиста
рядом с ценой показывается предупреждение (жёлтый/красный «!») при
quality < 7.
price_method/price_period_days/price_coefficient/manual_price/meta_prices
убраны из контракта QF (models.PricelistItem, local_pricelist_items,
API, колонка «Настройки» на странице прайслиста) — эти поля принадлежат
внешнему движку ценообразования и нигде не использовались в клиенте.
Сами колонки в qt_pricelist_items не трогаем — оставлены для обратной
совместимости с внешней системой.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Вкладка «Аренда»: добавлены колонки Estimate и Цена продажи (+ итоги),
чекбокс «БУ» перенесён первым слева, таблица переведена на тот же
разметку/классы, что и таблицы вкладки «Ценообразование».
Прайслисты: local_pricelist_items получает lot_description (синхронизируется
из qt_pricelist_items.lot_description) вместо устаревших available_qty/
partnumbers, которые нигде не заполнялись.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Новая вкладка «Аренда» в конфигураторе (доступна для проектов с флагом
rental_enabled): расчёт по методичке "Регламент расчёта стоимости
платного тестирования и аренды GPU-серверов" — Разовый + Еженедельный
платёж по каждому компоненту (New/БУ чекбоксом), с аплифтом к Estimate.
Заодно: поддержка (support_code) в Base-вкладке теперь добавляется как
обычный LOT в спеку (SVC_{срок}y{уровень}_{платформа}) через
autocomplete-пикер вместо выпадающего списка — партномер собирается
тем же lot_name-based механизмом, что и для GPU/CPU/памяти, справочная
цена по регламенту техподдержки хранится в qt_settings.support_pricing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- SQLite-запросы по lot_name теперь используют UPPER(lot_name) IN/= для
совместимости с легаси-данными, синхронизированными до нормализации регистра
- Удалена таблица local_components и весь связанный код синхронизации;
источник данных для компонентов — local_pricelist_items
- Удалена функция getCategoryFromLotName из JS: категория берётся только
из прайслиста, без инференса из имени лота
- Регистронезависимые сравнения lot_name в JS (warehouse stock set,
addedLots, cartLots, allComponents.find, _bomLotValid)
- В support bundle добавлены: latest_pricelist_items.json, local.db,
autocomplete_lots.json для диагностики
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- Добавлена таблица sync_log (до 100 записей на тип): фиксирует каждый
запуск синхронизации с типом, статусом, ошибкой, кол-вом и временем
- AppendSyncLog вызывается из SyncComponents, SyncPricelists (service и
handler), SyncAll и SyncComponentsIfEmpty
- Bundle теперь включает sync_log.json (200 последних записей) и
pricelists.json (все скачанные прайслисты, сгруппированные по source)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add config_type field ("server"|"storage") to Configuration and LocalConfiguration
- Create modal: Сервер/СХД segmented control in configs.html and project_detail.html
- Configurator: ENC/DKC/CTL categories in Base tab, HIC section in PCI tab hidden for server configs
- Add SW tab (categories: SW) to configurator, visible only when components present
- TAB_CONFIG.pci: add HIC section for storage HIC adapters (separate from server HBA/NIC)
- Migration 029: ALTER TABLE qt_configurations ADD COLUMN config_type
- Fix: skip Error 1833 (Cannot change column used in FK) in GORM AutoMigrate
- Operator guide: docs/storage-components-guide.md with LOT naming rules and DE4000H catalog template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Overview
Removed the CurrentPrice and SyncedAt fields from local_components, transitioning to a
pricelist-based pricing model where all prices are sourced from local_pricelist_items
based on the configuration's selected pricelist.
## Changes
### Data Model Updates
- **LocalComponent**: Now stores only metadata (LotName, LotDescription, Category, Model)
- Removed: CurrentPrice, SyncedAt (both redundant)
- Pricing is now exclusively sourced from local_pricelist_items
- **LocalConfiguration**: Added pricelist selection fields
- Added: WarehousePricelistID, CompetitorPricelistID
- These complement the existing PricelistID (Estimate)
### Migrations
- Added migration "drop_component_unused_fields" to remove CurrentPrice and SyncedAt columns
- Added migration "add_warehouse_competitor_pricelists" to add new pricelist fields
### Component Sync
- Removed current_price from MariaDB query
- Removed CurrentPrice assignment in component creation
- SyncComponentPrices now exclusively updates based on pricelist_items via quote calculation
### Quote Calculation
- Added PricelistID field to QuoteRequest
- Updated local-first path to use pricelist_items instead of component.CurrentPrice
- Falls back to latest estimate pricelist if PricelistID not specified
- Maintains offline-first behavior: local queries work without MariaDB
### Configuration Refresh
- Removed fallback on component.CurrentPrice
- Prices are only refreshed from local_pricelist_items
- If price not found in pricelist, original price is preserved
### API Changes
- Removed CurrentPrice from ComponentView
- Components API no longer returns pricing information
- Pricing is accessed via QuoteService or PricelistService
### Code Cleanup
- Removed UpdateComponentPricesFromPricelist() method
- Removed EnsureComponentPricesFromPricelists() method
- Updated UnifiedRepository to remove offline pricing logic
- Updated converters to remove CurrentPrice mapping
## Architecture Impact
- Components = metadata store only
- Prices = managed by pricelist system
- Quote calculation = owns all pricing logic
- Local-first behavior preserved: SQLite queries work offline, no MariaDB dependency
## Testing
- Build successful
- All code compiles without errors
- Ready for migration testing with existing databases
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Implement RefreshPrices for local-first mode
- Update prices from local_components.current_price cache
- Graceful degradation when component not found
- Add PriceUpdatedAt timestamp to LocalConfiguration model
- Support both authenticated and no-auth price refresh
- Fix sync duplicate entry bug
- pushConfigurationUpdate now ensures server_id exists before update
- Fetch from LocalConfiguration.ServerID or search on server if missing
- Update local config with server_id after finding
- Add application auto-restart after settings save
- Implement restartProcess() using syscall.Exec
- Setup handler signals restart via channel
- Setup page polls /health endpoint and redirects when ready
- Add "Back" button on setup page when settings exist
- Fix setup handler password handling
- Use PasswordEncrypted field consistently
- Support empty password by using saved value
- Improve sync status handling
- Add fallback for is_offline check in SyncStatusPartial
- Enhance background sync logging with prefixes
- Update CLAUDE.md documentation
- Mark Phase 2.5 tasks as complete
- Add UI Improvements section with future tasks
- Update SQLite tables documentation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>