# Architecture ## Tech Stack | Component | Technology | |-----------|------------| | Backend | Go 1.22+ (go.mod: 1.24.0) | | Web framework | Gin | | ORM | GORM | | Database | MariaDB 11 | | Frontend | htmx + Tailwind CDN (no build step) | | Excel | excelize | | Go module | `git.mchus.pro/mchus/priceforge` | --- ## Directory Structure ``` PriceForge/ ├── bible/ # Architectural documentation (you are here) ├── bin/ # Build output ├── cmd/ │ ├── pfs/ # Main server (main.go ~749 lines) │ ├── cron/ # Cron job runner │ ├── importer/ # Stock import utility │ ├── migrate/ # Migration tool │ └── migrate_ops_projects/ # Legacy project migrator ├── data/ # Data files ├── internal/ # Application code │ ├── appmeta/ # Application metadata │ ├── appstate/ # Global state │ ├── config/ # YAML config loading │ ├── db/ # DB connection, connection pool │ ├── dbutil/ # DB utilities │ ├── handlers/ # HTTP handlers (7 files) │ ├── localdb/ # SQLite for local settings │ ├── lotmatch/ # LOT mapping resolver │ ├── middleware/ # HTTP middleware │ ├── models/ # GORM models and migrations │ ├── repository/ # Data access layer (11 files) │ ├── services/ # Business logic │ │ ├── alerts/ # Alert service │ │ ├── pricelist/ # Pricelist service │ │ ├── pricing/ # Price calculation │ │ ├── sync/ # Sync (diagnostics only) │ │ ├── stock_import.go # Stock file import │ │ ├── vendor_mapping.go # Vendor mapping service │ │ └── component.go # Component service │ ├── tasks/ # Background Task Manager │ └── warehouse/ # Warehouse price calculation ├── migrations/ # SQL migrations (25 files) ├── scripts/ # Build and release scripts ├── web/ │ ├── static/ # app.css (Tailwind) │ └── templates/ # HTML templates (9 files) ├── CLAUDE.md # AI agent instructions ├── README.md # Quick start └── todo.md # Operational task list ``` --- ## Application Layers (3-tier) ``` HTTP Request │ ▼ ┌─────────────┐ │ Handlers │ internal/handlers/ — request parsing, validation, response └──────┬──────┘ │ ▼ ┌─────────────┐ │ Services │ internal/services/ — business logic, orchestration └──────┬──────┘ │ ▼ ┌─────────────┐ │ Repository │ internal/repository/ — SQL queries via GORM └──────┬──────┘ │ ▼ MariaDB 11 ``` --- ## Key Modules ### internal/handlers/ (7 files) | File | Purpose | |------|---------| | `web.go` | Page rendering: Index, Lot, AdminPricing, Pricelists, VendorMappings | | `component.go` | Component list and detail endpoints | | `pricing.go` | Pricing admin: stats, components, recalc, stock, vendor mappings, alerts | | `pricelist.go` | Pricelist CRUD and CSV export | | `setup.go` | DB connection setup and test | | `sync.go` | Sync diagnostic endpoints | (6 files; `sync_readiness_test.go` is a test file) ### internal/services/ | File/dir | Purpose | |----------|---------| | `pricelist/` | Create Estimate, Warehouse, Competitor pricelists | | `pricing/` | Price calc: median, weighted_median, coefficients | | `alerts/` | Alert generation (price staleness, demand) | | `stock_import.go` | Import .mxl/.xlsx, seen-tracking, batch processing | | `vendor_mapping.go` | Resolve partnumber → LOT, bundles, ignore | | `component.go` | Component listing and search | ### internal/warehouse/ `snapshot.go` — warehouse pricelist creation: weighted average, bundle expansion, allocation. ### internal/lotmatch/ `matcher.go` — vendor partnumber → LOT resolver: 1. Exact match `(vendor, partnumber)` 2. Fallback: `(vendor='', partnumber)` ### internal/tasks/ Task Manager: Submit, status polling, task types. See [background-tasks.md](background-tasks.md). --- ## HTML Templates (web/templates/) | Template | Route | Purpose | |----------|-------|---------| | `base.html` | — | Layout, navigation | | `admin_pricing.html` | `/admin/pricing` | Tabs: Estimate, Warehouse, Alerts | | `lot.html` | `/lot` | Tabs: LOT components, Mappings | | `pricelists.html` | `/pricelists` | Pricelist listing | | `pricelist_detail.html` | `/pricelists/:id` | Pricelist detail view | | `vendor_mappings.html` | `/vendor-mappings` | Vendor mapping UI | | `components_list.html` | `/partials/components` | Components partial | | `setup.html` | `/setup` | DB connection setup | | `sync_status.html` | partial | Online/offline indicator | --- ## Navigation (base.html) ``` LOT → /lot Pricing Admin → /admin/pricing Settings → /setup ``` Configurator, projects, and export links must **not** appear in the menu. --- ## Database - **Primary**: MariaDB 11 (all operational data) - **Local**: SQLite (only app settings and technical data; not used in `pfs` runtime) - **Migrations**: `migrations/` — 25 SQL files, applied automatically on startup ### Key Tables | Table | Purpose | |-------|---------| | `lot` | Components / articles (primary) | | `qt_lot_metadata` | Component price metadata | | `qt_pricelist_items` | Pricelist item rows | | `stock_log` | Stock import data | | `lot_partnumbers` | partnumber → LOT mappings (canonical contract) | | `qt_lot_bundles` | Bundle definitions | | `qt_lot_bundle_items` | Bundle composition: `(bundle_lot_name, lot_name, qty)` | | `qt_vendor_partnumber_seen` | Seen registry (unique by `partnumber`) + `is_ignored` flag | --- ## Startup Flow 1. Parse flags (`--config`, `--migrate`, `--version`) 2. Load `config.yaml` 3. **Fail-fast**: connect to MariaDB; exit on failure 4. Apply SQL migrations 5. Start Gin router on `host:port` 6. Auto-open browser (if loopback address)