Files
roaauto/CLAUDE.md
Marius Mutu 9db4e746e3 feat: add clients nomenclator, order edit/delete/devalidate, invoice types, dashboard redesign
- 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>
2026-03-14 00:36:40 +02:00

5.9 KiB

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)

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)

cd frontend
npm run dev      # start dev server (port 5173)
npm run build    # production build

Docker (preferred for full stack)

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.jsSyncEngine 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
  • ReactivitynotifyTableChanged(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.pyget_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

DRAFTVALIDATFACTURAT

  • 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

  • DRAFTVALIDATFACTURAT (cu devalidare VALIDAT → DRAFT)
  • Stergere: orice nefacturat; FACTURAT = sterge factura intai
  • Edit header doar in DRAFT