# QuoteForge - Claude Code Instructions ## Overview Корпоративный конфигуратор серверов и формирование КП. MariaDB (RFQ_LOG) + SQLite для оффлайн. ## Development Phases ### Phase 1: Pricelists in MariaDB ✅ DONE ### Phase 2: Local SQLite Database ✅ DONE ### Phase 2.5: Full Offline Mode 🔶 IN PROGRESS Приложение должно полностью работать без MariaDB, синхронизация при восстановлении связи. **Architecture:** - Dual-source pattern: все операции идут через unified service layer - Online: read/write MariaDB, async cache to SQLite - Offline: read/write SQLite, queue changes for sync **TODO:** - ❌ Unified repository interface (online/offline transparent switching) - ❌ Sync queue table (pending_changes: entity_type, entity_uuid, operation, payload, created_at) - ❌ Background sync worker (push local changes when online) - ❌ Conflict resolution (last-write-wins by updated_at, or manual) - ❌ Initial data bootstrap (first sync downloads all needed data) - ❌ Handlers use context.IsOffline to choose data source - ❌ UI: pending changes counter, manual sync button, conflict alerts **Sync flow:** 1. Online → Offline: continue work, changes saved locally with sync_status='pending' 2. Offline → Online: background worker pushes pending_changes, pulls updates 3. Conflict: if server version newer, mark as 'conflict' for manual resolution ### Phase 3: Projects and Specifications - qt_projects, qt_specifications tables (MariaDB) - Replace qt_configurations → Project/Specification hierarchy - Fields: opty, customer_requirement, variant, qty, rev - Local projects/specs with server sync ### Phase 4: Price Versioning - Bind specifications to pricelist versions - Price diff comparison - Auto-cleanup expired pricelists (>1 year, usage_count=0) ## Tech Stack Go 1.22+ | Gin | GORM | MariaDB 11 | SQLite (glebarez/sqlite) | htmx + Tailwind CDN | excelize ## Key Tables ### READ-ONLY (external systems) - `lot` (lot_name PK, lot_description) - `lot_log` (lot, supplier, date, price, quality, comments) - `supplier` (supplier_name PK) ### MariaDB (qt_* prefix) - `qt_lot_metadata` - component prices, methods, popularity - `qt_categories` - category codes and names - `qt_pricelists` - version snapshots (YYYY-MM-DD-NNN format) - `qt_pricelist_items` - prices per pricelist - `qt_projects` - uuid, opty, customer_requirement, name (Phase 3) - `qt_specifications` - project_id, pricelist_id, variant, rev, qty, items JSON (Phase 3) ### SQLite (data/quoteforge.db) - `connection_settings` - encrypted DB credentials - `local_pricelists/items` - cached from server - `local_components` - lot cache for offline search - `local_configurations` - with sync_status (pending/synced/conflict) - `local_projects/specifications` - Phase 3 - `pending_changes` - sync queue (entity_type, uuid, op, payload, created_at) ## Business Logic **Part number parsing:** `CPU_AMD_9654` → category=`CPU`, model=`AMD_9654` **Price methods:** manual | median | average | weighted_median **Price freshness:** fresh (<30d, ≥3 quotes) | normal (<60d) | stale (<90d) | critical **Pricelist version:** `YYYY-MM-DD-NNN` (e.g., `2024-01-31-001`) ## API Endpoints | Group | Endpoints | |-------|-----------| | Setup | GET/POST /setup, POST /setup/test | | Components | GET /api/components, /api/categories | | Pricelists | CRUD /api/pricelists, GET /latest, POST /compare | | Projects | CRUD /api/projects/:uuid (Phase 3) | | Specs | CRUD /api/specs/:uuid, POST /upgrade, GET /diff (Phase 3) | | Sync | GET /status, POST /components, /pricelists, /push, /pull, /resolve-conflict | | Export | GET /api/specs/:uuid/export, /api/projects/:uuid/export | ## Commands ```bash go run ./cmd/server # Dev server go run ./cmd/cron -job=X # cleanup-pricelists | update-prices | update-popularity CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/quoteforge ./cmd/server ``` ## Code Style - gofmt, structured logging (slog), wrap errors with context - snake_case files, PascalCase types - RBAC disabled: DB username = user_id via `models.EnsureDBUser()` ## UI Guidelines - htmx (hx-get/post/target/swap), Tailwind CDN - Freshness colors: green (fresh) → yellow → orange → red (critical) - Sync status + offline indicator in header