Files
QuoteForge/CLAUDE.md
Michael Chus be77256d4e Add background sync worker and complete local-first architecture
Implements automatic background synchronization every 5 minutes:
- Worker pushes pending changes to server (PushPendingChanges)
- Worker pulls new pricelists (SyncPricelistsIfNeeded)
- Graceful shutdown with context cancellation
- Automatic online/offline detection via DB ping

New files:
- internal/services/sync/worker.go - Background sync worker
- internal/services/local_configuration.go - Local-first CRUD
- internal/localdb/converters.go - MariaDB ↔ SQLite converters

Extended sync infrastructure:
- Pending changes queue (pending_changes table)
- Push/pull sync endpoints (/api/sync/push, /pending)
- ConfigurationGetter interface for handler compatibility
- LocalConfigurationService replaces ConfigurationService

All configuration operations now run through SQLite with automatic
background sync to MariaDB when online. Phase 2.5 nearly complete.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 22:17:00 +03:00

4.8 KiB
Raw Blame History

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

Local-first architecture: приложение ВСЕГДА работает с SQLite, MariaDB только для синхронизации.

Принцип работы:

  • ВСЕ операции (CRUD) выполняются в SQLite
  • При создании конфигурации:
    1. Если online → проверить новые прайслисты на сервере → скачать если есть
    2. Далее работаем с local_pricelists (и online, и offline одинаково)
  • Background sync: push pending_changes → pull updates

DONE:

  • Sync queue table (pending_changes) - internal/localdb/models.go
  • Model converters: MariaDB ↔ SQLite - internal/localdb/converters.go
  • LocalConfigurationService: все CRUD через SQLite - internal/services/local_configuration.go
  • Pre-create pricelist check: SyncPricelistsIfNeeded() - internal/services/sync/service.go
  • Push pending changes: PushPendingChanges() - sync service + handlers
  • Sync API endpoints: /api/sync/push, /pending/count, /pending
  • Integrate LocalConfigurationService in main.go (replace ConfigurationService)
  • Add routes for new sync endpoints (/api/sync/push, /pending/count, /pending)
  • ConfigurationGetter interface for handler compatibility
  • Background sync worker: auto-sync every 5min (push + pull) - internal/services/sync/worker.go

TODO:

  • Conflict resolution (last-write-wins or manual)
  • UI: pending counter in header
  • UI: manual sync button
  • UI: offline indicator (middleware already exists)
  • RefreshPrices for local mode (via local_components)

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

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