161 lines
7.0 KiB
Markdown
161 lines
7.0 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Tilbudgivern is an AI-powered quote calculator for the carpentry trade (tømrerfaget). It generates detailed professional quotes based on project descriptions, using OpenAI GPT-4 for AI-powered quote generation.
|
|
|
|
**Tech Stack:**
|
|
- Frontend: React 18 with Material-UI, served as static build
|
|
- Backend: Node.js/Express unified server (~400K lines in `backend/unified-server.js`)
|
|
- Database: MariaDB/MySQL (running on host, not containerized)
|
|
- AI: OpenAI GPT-4 API (default budget: $9/month)
|
|
- Process Manager: PM2 (process name: `tilbudgivern-unified`)
|
|
|
|
## Common Commands
|
|
|
|
### Development
|
|
```bash
|
|
npm run dev # Start development server with hot reload
|
|
npm run build # Build frontend for production
|
|
pm2 restart tilbudgivern-unified # Restart PM2 after changes
|
|
pm2 logs tilbudgivern-unified # View logs
|
|
```
|
|
|
|
### Testing
|
|
```bash
|
|
npm run test:pw # Playwright UI tests against production
|
|
npm run test:pw:local # Playwright tests against local server
|
|
npm run test:pw:ui # Playwright interactive UI mode
|
|
npm run test:pw:headed # Playwright with visible browser
|
|
npm run test:selenium # Selenium UI tests
|
|
cd backend && npm test # Backend unit tests (Jest)
|
|
```
|
|
|
|
### Single Test Execution
|
|
```bash
|
|
cd tests && PLAYWRIGHT_BASE_URL=https://tilbudsgiveren.alw.dk playwright test <test-file>.spec.js
|
|
cd tests && PLAYWRIGHT_BASE_URL=https://tilbudsgiveren.alw.dk playwright test <test-file>.spec.js --headed
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Unified Server Pattern
|
|
The application uses a unified server (`backend/unified-server.js`) that:
|
|
- Serves the React frontend build from `frontend/build/`
|
|
- Provides all API endpoints on port 4032 (configured in `.env`)
|
|
- Handles WebSocket connections via Socket.IO
|
|
- Includes structured logging with correlation IDs
|
|
|
|
### Key Backend Services (`backend/src/services/`)
|
|
- `openaiService.js` - AI quote generation via GPT-4, budget tracking
|
|
- `databaseService.js` - MariaDB connection pool and queries
|
|
- `smartPackageManagementService.js` - Smart package CRUD (15 carpenter packages)
|
|
- `ordrestyringSyncService.js` - GraphQL integration with Ordrestyring API
|
|
- `pdfGenerationService.js` - Quote PDF generation via Puppeteer
|
|
- `roofGeometryService.js` - Roof area calculations for 7 roof types
|
|
- `starkImportService.js` - Stark material catalog import
|
|
- `bygmaPrisbogImportService.js` - Bygma price book import
|
|
|
|
### Key Backend Routes (`backend/src/routes/`)
|
|
- `smartPackagesRoutes.js` - Smart package management API
|
|
- `customerProjects.js` - Customer and project CRUD
|
|
- `quotes.js` - Quote generation and management
|
|
- `pricing.js` - Price database endpoints
|
|
- `starkImport.js` - Stark CSV import endpoint
|
|
|
|
### Key Frontend Components (`frontend/src/components/`)
|
|
- `InlineSmartPackage.js` - Smart package wizard with step-by-step flow
|
|
- `EnhancedGeometry.js` - Roof geometry input with SVG visualizations for 7 roof types
|
|
- `MaterialsManager.js` - Material selection with cached API searches
|
|
- `PlanningDashboard.js` - Project planning calendar
|
|
- `FinalReview.js` - Quote review and Ordrestyring offer creation
|
|
- `ProjectCreation.js` - Project form with autosave, validation, tooltips
|
|
|
|
### Smart Packages System
|
|
15 pre-configured carpenter packages for roofing work:
|
|
- Auto-calculation based on geometry (tagareal, rygningslængde, facadelængde)
|
|
- Includes materials with prices and labor hours
|
|
- Categories: Tagdækning, Tagrende/Nedløb, Tagvinduer, Brædder, Specialarbejde
|
|
|
|
### Roof Types (7 supported)
|
|
1. Sadeltag (pitched roof) - default
|
|
2. Valmtag (hip roof)
|
|
3. Københavnertag (Copenhagen roof)
|
|
4. Fladtag (flat roof)
|
|
5. Pulttag (shed roof)
|
|
6. Tag med Kviste (roof with dormers)
|
|
7. Mansardtag (mansard roof)
|
|
|
|
## External Integrations
|
|
|
|
### Ordrestyring API
|
|
- GraphQL endpoint: `https://beta7-api.ordrestyring.dk/graphql`
|
|
- Used for: customers, cases, offers, calendar, hours tracking
|
|
- Token: `ORDRESTYRING_API_TOKEN` in `.env`
|
|
- API test scripts: `apitest/examples/`
|
|
|
|
### Material Suppliers
|
|
- **Bygma**: Price book import, installation manuals
|
|
- **Stark**: CSV catalog import via `/api/stark/upload`
|
|
|
|
## Database
|
|
- MariaDB on localhost:3306
|
|
- Database: `tilbudgivern`
|
|
- Key tables: `smart_packages`, `package_tasks`, `package_materials`, `materials`, `customers`, `projects`
|
|
- Schema files: `database/schema_system_logs.sql`
|
|
- Migrations: `database/migrations/`, `backend/migrations/`
|
|
|
|
## Environment Configuration
|
|
- Main config: `backend/.env`
|
|
- Required:
|
|
- `OPENAI_API_KEY` - for AI features
|
|
- `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` - database
|
|
- Optional:
|
|
- `ORDRESTYRING_API_TOKEN` - order management integration
|
|
- `OPENAI_ADMIN_KEY` - for cost tracking API
|
|
|
|
## Logging System
|
|
- Structured JSON logs with correlation IDs
|
|
- Database persistence in `system_logs` table
|
|
- Error codes: DB_001 (connection), DB_002 (query), VAL_001 (validation), API_001 (Ordrestyring), etc.
|
|
- Admin endpoints: `/api/admin/logs`
|
|
|
|
## Deployment
|
|
|
|
**This machine is the production server.** There is no separate deploy target: `backend/unified-server.js` runs directly out of this git working directory via PM2, serving the built frontend from `frontend/build/`. There is no CI/CD pipeline that deploys automatically on merge — deploying means running these steps here, on this host, after `main` has the commit you want live.
|
|
|
|
```bash
|
|
git checkout main && git pull # Get the commit you want live
|
|
cd frontend && npm ci && npm run build # Sync frontend deps and rebuild static assets
|
|
cd ../backend && npm ci --omit=dev # Sync backend deps (skip if unchanged)
|
|
pm2 restart tilbudgivern-unified # Restart the running process
|
|
pm2 logs tilbudgivern-unified --lines 30 --nostream # Confirm a clean startup (no errors)
|
|
curl -sf http://localhost:4032/api/health # Should return {"status":"ok",...}
|
|
curl -sI https://tilbudsgiveren.alw.dk # Should return HTTP/2 200
|
|
```
|
|
|
|
Other useful commands:
|
|
```bash
|
|
pm2 status # Check process status
|
|
pm2 logs tilbudgivern-unified # Tail live logs
|
|
```
|
|
|
|
Daily database backups configured via cron at 02:00, retention: 7 days.
|
|
|
|
Note: `.github/workflows/deploy-prod.yml` (an SSH/rsync-to-a-remote-server pipeline) was removed — it targeted a `PROD_SERVER_HOST`/`PROD_SERVER_USER`/`PROD_SERVER_PATH`/`PROD_SSH_PRIVATE_KEY` setup that was never configured (no repo or `production`-environment secrets ever existed), and every historical run of it failed. If a real separate deploy target is ever set up, that pipeline's steps (versioned releases dir, atomic symlink swap, pre-deploy DB backup, health-check retries, smoke tests) are a reasonable starting point to resurrect from git history.
|
|
|
|
## Danish Terminology
|
|
- Tilbud = Quote/Offer
|
|
- Tømrer = Carpenter
|
|
- Materiale = Material
|
|
- Pakke = Package
|
|
- Pris = Price
|
|
- Tag = Roof
|
|
- Spær = Rafters
|
|
- Tagrende = Rain gutter
|
|
- Nedløb = Downspout
|
|
- Vindsked = Barge board
|
|
- Sternbræt = Fascia board
|