- New clients table with PF/PJ support, fiscal data (CUI, IBAN, eFactura fields) - Full CRUD API for clients with search, sync integration - Order lifecycle: edit header (DRAFT), devalidate (VALIDAT→DRAFT), delete order/invoice - Invoice types: FACTURA (B2B) vs BON_FISCAL (B2C) with different nr formats - OrderCreateView redesigned as multi-step flow (client→vehicle→details) - Autocomplete from catalog_norme/catalog_preturi in OrderLineForm - Dashboard now combines stats + full orders table with filter tabs and search - ClientPicker and VehiclePicker with inline creation capability - Frontend schema aligned with backend (missing columns causing sync errors) - Mobile responsive fixes for OrderDetailView buttons Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
108 lines
5.9 KiB
Markdown
108 lines
5.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
ROA AUTO is a multi-tenant auto service management PWA. The architecture is **offline-first**: the Vue 3 frontend uses wa-sqlite (WebAssembly SQLite) running entirely in the browser as `:memory:`, with a sync engine that pulls from and pushes to the FastAPI backend. All business data lives locally in the browser's in-memory SQLite DB and is periodically synced.
|
|
|
|
## Development Commands
|
|
|
|
### Backend (FastAPI)
|
|
```bash
|
|
cd backend
|
|
source .venv/bin/activate
|
|
uvicorn app.main:app --port 8000 --reload # start dev server
|
|
pytest tests/ -v # run all tests
|
|
pytest tests/test_orders.py -v # run single test file
|
|
pytest tests/test_orders.py::test_name -v # run single test
|
|
```
|
|
|
|
### Frontend (Vue 3 + Vite)
|
|
```bash
|
|
cd frontend
|
|
npm run dev # start dev server (port 5173)
|
|
npm run build # production build
|
|
```
|
|
|
|
### Docker (preferred for full stack)
|
|
```bash
|
|
make dev # start all services (docker-compose.dev.yml)
|
|
make test # run backend tests in container
|
|
make migrate # run alembic migrations
|
|
make seed # seed demo data
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Sync Model (critical to understand)
|
|
- **Frontend writes locally first**, then queues changes in `_sync_queue` (SQLite table)
|
|
- `SyncEngine` (`frontend/src/db/sync.js`) handles three operations:
|
|
- `fullSync()` — downloads all tenant data from `/api/sync/full` on login
|
|
- `incrementalSync()` — downloads changes since `last_sync_at`
|
|
- `pushQueue()` — uploads queued local changes to `/api/sync/push`
|
|
- The backend sync service (`backend/app/sync/service.py`) defines `SYNCABLE_TABLES` — only these tables are synced
|
|
- IDs are `crypto.randomUUID()` generated client-side; backend uses `INSERT OR REPLACE`
|
|
|
|
### Frontend (`frontend/src/`)
|
|
- **`db/database.js`** — singleton wa-sqlite instance. Uses `:memory:` only (no IndexedDB persistence). `execSQL(sql, params)` is the only query interface. Parameterized queries **must** use `sqlite3.statements()` async generator — `exec()` does not support `?` params. Do NOT use `prepare_v2` (doesn't exist in this library).
|
|
- **`db/schema.js`** — full SQLite schema as a string constant, applied on init
|
|
- **`db/sync.js`** — `SyncEngine` class, exported as singleton `syncEngine`
|
|
- **`stores/`** — Pinia stores (`auth.js`, `orders.js`, `vehicles.js`) wrapping `execSQL` calls
|
|
- **`views/`** — one file per route; data loaded via `execSQL` directly or through stores
|
|
- **Reactivity** — `notifyTableChanged(table)` / `onTableChange(table, cb)` in `database.js` provide a pub/sub for cross-component updates. Call `notifyTableChanged` after any write.
|
|
|
|
### Backend (`backend/app/`)
|
|
- **Multi-tenant**: every model has `tenant_id`. All queries filter by `tenant_id` from the JWT.
|
|
- **Auth**: JWT in `Authorization: Bearer` header. `get_tenant_id` dep extracts tenant from token.
|
|
- **`deps.py`** — `get_current_user` and `get_tenant_id` FastAPI dependencies used across all routers
|
|
- **`sync/`** — The most complex module. `apply_push` does `INSERT OR REPLACE` for all ops.
|
|
- **`pdf/`** — WeasyPrint + Jinja2 HTML templates to generate PDF deviz/factura
|
|
- **`client_portal/`** — Public routes (no auth) for client-facing deviz view via `token_client`
|
|
- **DB**: SQLite via SQLAlchemy async (`aiosqlite`). Alembic for migrations (files in `alembic/versions/`).
|
|
|
|
### Key Data Flow: Order Lifecycle
|
|
`DRAFT` → `VALIDAT` → `FACTURAT`
|
|
- Order lines (manopera/material) added only in DRAFT
|
|
- PDF deviz available after VALIDAT
|
|
- Invoice created locally in `handleFactureaza()` then queued for sync
|
|
|
|
## Critical wa-sqlite Notes
|
|
- Import: `wa-sqlite.mjs` (sync WASM build), NOT `wa-sqlite-async.mjs`
|
|
- All API methods (`open_v2`, `exec`, `step`, `finalize`) return Promises — always `await`
|
|
- For parameterized queries: `for await (const stmt of sqlite3.statements(db, sql))` then `sqlite3.bind_collection(stmt, params)`
|
|
- `vite.config.js` excludes `@journeyapps/wa-sqlite` from `optimizeDeps`
|
|
- COOP/COEP headers (`Cross-Origin-Opener-Policy: same-origin` + `Cross-Origin-Embedder-Policy: require-corp`) are required for SharedArrayBuffer used by wa-sqlite — set in vite dev server and nginx
|
|
|
|
## WSL2 Note
|
|
Running on WSL2 with code on Windows NTFS (`/mnt/e/`): Vite is configured with `server.watch.usePolling: true, interval: 1000` to work around inotify not firing on NTFS mounts.
|
|
|
|
## Testing
|
|
- Backend tests use an in-memory SQLite DB (overrides `get_db` via `app.dependency_overrides`)
|
|
- `asyncio_mode = auto` set in `pytest.ini` — no need to mark tests with `@pytest.mark.asyncio`
|
|
- `auth_headers` fixture registers a user and returns `Authorization` header for authenticated tests
|
|
- Demo credentials (after `make seed`): `demo@roaauto.ro` / `demo123`
|
|
|
|
## Execution Preferences
|
|
- Executia task-urilor se face cu **team agents** (nu cu skill superpowers subagents)
|
|
- **Playwright testing obligatoriu**: orice implementare majora trebuie testata E2E cu Playwright
|
|
- Desktop: 1280x720, Mobile: 375x812
|
|
- Verificari: responsive, elemente nu se suprapun, nu ies din ecran, butoane cu gap suficient
|
|
- Raportul Playwright se salveaza in `docs/playwright-report-YYYY-MM-DD.md`
|
|
|
|
## Data Model: Clients
|
|
- Tabel `clients` - nomenclator clienti cu date eFactura ANAF, separat de vehicule
|
|
- Un client poate avea mai multe vehicule (1:N prin client_id pe vehicles)
|
|
- `tip_persoana`: PF (persoana fizica) / PJ (persoana juridica)
|
|
- Campuri eFactura: cod_fiscal, reg_com, adresa, judet, oras, cod_postal, cont_iban, banca
|
|
|
|
## Data Model: Invoices
|
|
- `tip_document`: FACTURA (B2B, eFactura ANAF) sau BON_FISCAL (B2C, casa de marcat)
|
|
- Factura: necesita date client complete (CUI, adresa)
|
|
- Bon fiscal: format simplificat
|
|
|
|
## Order Lifecycle
|
|
- `DRAFT` → `VALIDAT` → `FACTURAT` (cu devalidare VALIDAT → DRAFT)
|
|
- Stergere: orice nefacturat; FACTURAT = sterge factura intai
|
|
- Edit header doar in DRAFT
|