Implements complete offline-first architecture with SQLite caching and MariaDB synchronization. Key features: - Local SQLite database for offline operation (data/quoteforge.db) - Connection settings with encrypted credentials - Component and pricelist caching with auto-sync - Sync API endpoints (/api/sync/status, /components, /pricelists, /all) - Real-time sync status indicator in UI with auto-refresh - Offline mode detection middleware - Migration tool for database initialization - Setup wizard for initial configuration New components: - internal/localdb: SQLite repository layer (components, pricelists, sync) - internal/services/sync: Synchronization service - internal/handlers/sync: Sync API handlers - internal/handlers/setup: Setup wizard handlers - internal/middleware/offline: Offline detection - cmd/migrate: Database migration tool UI improvements: - Setup page for database configuration - Sync status indicator with online/offline detection - Warning icons for pending synchronization - Auto-refresh every 30 seconds Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
4.3 KiB
4.3 KiB
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:
- Online → Offline: continue work, changes saved locally with sync_status='pending'
- Offline → Online: background worker pushes pending_changes, pulls updates
- 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, popularityqt_categories- category codes and namesqt_pricelists- version snapshots (YYYY-MM-DD-NNN format)qt_pricelist_items- prices per pricelistqt_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 credentialslocal_pricelists/items- cached from serverlocal_components- lot cache for offline searchlocal_configurations- with sync_status (pending/synced/conflict)local_projects/specifications- Phase 3pending_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
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