diff --git a/.claude/rules/authentication.md b/.claude/rules/authentication.md index acc7546..bcbd857 100644 --- a/.claude/rules/authentication.md +++ b/.claude/rules/authentication.md @@ -1,3 +1,7 @@ +--- +paths: "{backend,shared}/**/*.py,src/**/*.{js,vue}" +--- + # Authentication Rules ## JWT Token Structure (IMMUTABLE) diff --git a/.claude/rules/auto-build-memory.md b/.claude/rules/auto-build-memory.md index b67dcf3..d645842 100644 --- a/.claude/rules/auto-build-memory.md +++ b/.claude/rules/auto-build-memory.md @@ -1,9 +1,9 @@ -# Auto-Build Learned Patterns & Gotchas +# Learned Patterns & Gotchas -**Last updated**: 2025-12-24T00:10:00Z -**Source**: `.auto-build/memory/*.json` (auto-synced) +**Last updated**: 2025-12-24 +**Maintained**: Manually (add new patterns/gotchas as discovered) -This file is automatically loaded by Claude Code and contains insights learned during feature implementations using the Auto-Build system. +This file contains insights learned during feature implementations. Claude Code auto-loads this file to prevent repeating past mistakes. --- diff --git a/.claude/rules/company-period.md b/.claude/rules/company-period.md index dc27ca8..70abb69 100644 --- a/.claude/rules/company-period.md +++ b/.claude/rules/company-period.md @@ -1,3 +1,7 @@ +--- +paths: "{backend,shared}/**/*.py,src/**/*.{js,vue}" +--- + # Company & Period Selection Rules ## Store Factories (MANDATORY) diff --git a/.claude/rules/css-design-system.md b/.claude/rules/css-design-system.md index 5c239b1..934cd14 100644 --- a/.claude/rules/css-design-system.md +++ b/.claude/rules/css-design-system.md @@ -14,20 +14,36 @@ paths: src/modules/**/*.{vue,css} - Check `CSS_PATTERNS.md` BEFORE writing any CSS - Import shared styles from `shared/frontend/styles/` -## Dark Mode Support (CRITICAL) -Dark mode is ACTIVE via `@media (prefers-color-scheme: dark)`. +## Theme System (3 Modes) - CRITICAL -**Use semantic surface tokens for backgrounds:** +ROA2WEB are **theme toggle în header**: auto → light → dark + +| Mode | Comportament | CSS Selector | +|------|--------------|--------------| +| `auto` | Urmează preferința OS | `@media (prefers-color-scheme: dark)` | +| `light` | Forțează light mode | `[data-theme="light"]` pe `` | +| `dark` | Forțează dark mode | `[data-theme="dark"]` pe `` | + +**Detalii implementare:** +- **Toggle:** `AppHeader.vue` (lines 137-175) +- **Persistență:** `localStorage['user-theme']` (valori: 'light', 'dark', sau absent=auto) +- **CSS Priority:** `[data-theme]` > `@media (prefers-color-scheme)` > default light + +**Testare OBLIGATORIE:** +1. Click buton temă în header (ciclează auto→light→dark) +2. DevTools → Rendering → Emulate CSS media → prefers-color-scheme: dark + +**Semantic surface tokens (funcționează în TOATE modurile):** | Token | Light | Dark | Use For | |-------|-------|------|---------| -| `--surface-card` | white | dark | Card/container backgrounds | -| `--surface-ground` | light gray | darker | Page background | -| `--surface-hover` | hover gray | dark hover | Hover states | -| `--surface-border` | light border | dark border | Borders | -| `--text-color` | dark | light | Primary text | -| `--text-color-secondary` | gray | light gray | Secondary text | +| `--surface-card` | white | #1e293b | Card/container backgrounds | +| `--surface-ground` | #f8fafc | #0f172a | Page background | +| `--surface-hover` | #f1f5f9 | #334155 | Hover states | +| `--surface-border` | #e2e8f0 | #475569 | Borders | +| `--text-color` | #111827 | #f9fafb | Primary text | +| `--text-color-secondary` | #6b7280 | #d1d5db | Secondary text | -**For status colors, use scales:** +**Status colors (scales 50-900):** - Success: `--green-50` to `--green-900` (bg: 50/100, text: 500/600) - Warning: `--yellow-50` to `--yellow-900` - Error: `--red-50` to `--red-900` @@ -79,4 +95,4 @@ color: var(--red-600); /* Error text */ - Use hardcoded colors like `#2563eb` (use `var(--color-primary)`) - Use hardcoded backgrounds like `#ffffff` or `white` (use `var(--surface-card)`) - Create scoped CSS for patterns that already exist in shared files -- Forget dark mode - always test with `prefers-color-scheme: dark` +- **Skip theme testing** - ALWAYS test cu toggle (auto/light/dark) + DevTools dark mode diff --git a/.claude/settings.json b/.claude/settings.json index 15376f4..67f17a4 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,7 +1,4 @@ { - "enabledPlugins": { - "ab@roa2web-tools": true - }, "statusLine": { "type": "command", "command": "input=$(cat); model=$(echo \"$input\" | jq -r '.model.display_name // \"Unknown\"'); usage=$(echo \"$input\" | jq '.context_window.current_usage'); if [ \"$usage\" != \"null\" ]; then current=$(echo \"$usage\" | jq '.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens'); size=$(echo \"$input\" | jq '.context_window.context_window_size'); pct=$((current * 100 / size)); ctx=$(printf '%d%% ctx' \"$pct\"); else ctx='0% ctx'; fi; branch=$(git -c core.useBuiltinFSMonitor=false branch --show-current 2>/dev/null || echo 'no-git'); cwd=$(basename \"$(pwd)\"); printf '\\033[36m%s\\033[0m | \\033[33m%s\\033[0m | \\033[32m%s\\033[0m | \\033[35m%s\\033[0m' \"$model\" \"$ctx\" \"$branch\" \"$cwd\"" diff --git a/CLAUDE.md b/CLAUDE.md index f8b9adf..a47b669 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,437 +1,119 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +This file provides guidance to Claude Code when working with code in this repository. -## 🚀 Project Overview +## Project Overview **ROA2WEB** - Modern ERP Application with ultrathin monolith architecture: -1. **Reports Module** (`backend/modules/reports/`) - Read-only reports from Oracle (raportări) -2. **Data Entry Module** (`backend/modules/data_entry/`) - Data input with approval workflow (introduceri date) -3. **Telegram Bot Module** (`backend/modules/telegram/`) - Telegram bot integration +- **Reports Module** (`backend/modules/reports/`) - Read-only reports from Oracle +- **Data Entry Module** (`backend/modules/data_entry/`) - Data input with approval workflow +- **Telegram Bot Module** (`backend/modules/telegram/`) - Telegram bot integration -**Main Branch**: `main` (use for PRs) -**Working Directory**: Repository root - -**Quick Reference**: See `README.md` for complete setup, commands, deployment, and testing instructions. +**Main Branch**: `main` | **Setup & Commands**: See `README.md` --- -## 📁 Module-Specific Instructions +## Module-Specific Instructions -> **IMPORTANT**: When working on a specific module, read its documentation first! +> **IMPORTANT**: Read module documentation FIRST before working on a module! -| Module | Documentation Location | Description | -|--------|----------------------|-------------| -| **Data Entry** | `docs/data-entry/DATA-ENTRY-MODULE.md` | Bonuri fiscale, chitanțe, workflow aprobare | -| **Reports** | This file (below) | Rapoarte Oracle read-only | -| **Telegram Bot** | `docs/telegram/README.md` | Bot Telegram | - -### When to Use Which Instructions - -**Working on Data Entry** (`backend/modules/data_entry/` or `src/modules/data-entry/`): -→ **FIRST read `docs/data-entry/DATA-ENTRY-MODULE.md`** for: - - SQLModel + Alembic patterns (NOT Oracle) - - SQLite database (NOT Oracle pool) - - Workflow states (DRAFT → PENDING → APPROVED) - - Receipt/Attachment/AccountingEntry models - - Expense types and auto-generation logic - - Oracle nomenclatures integration - -**Working on Reports Module** (`backend/modules/reports/` or `src/modules/reports/`): -→ Use instructions from this file (below) - -**Working on shared components** (`shared/auth/`, `shared/database/`, `shared/frontend/`): -→ These are used by ALL modules - be careful with changes! -→ `shared/frontend/` contains: LoginView.vue, auth store factory, login styles +| Module | Documentation | Key Points | +|--------|--------------|------------| +| **Data Entry** | `docs/data-entry/DATA-ENTRY-MODULE.md` | SQLModel, SQLite, workflow states | +| **Reports** | This file + `README.md` | Oracle read-only, caching | +| **Telegram** | `docs/telegram/README.md` | Bot commands, formatting | --- -## 🏗️ Architecture +## Quick Reference -> **Important Architecture Decisions:** See `docs/ARCHITECTURE-DECISIONS.md` for critical decisions about: -> - Why single worker (`--workers 1`) is required for Telegram bot -> - Ultrathin monolith vs microservices rationale -> - IIS sub-application deployment strategy -> - Performance characteristics and scaling considerations - -### Ultrathin Monolith Structure -``` -. -├── backend/ # Unified FastAPI backend (port 8000/8001) -│ ├── modules/ # Business logic modules -│ │ ├── reports/ # Reports module (Oracle read-only) -│ │ ├── data_entry/ # Data entry module (SQLite + workflow) -│ │ ├── telegram/ # Telegram bot module -│ │ └── data/ # Shared data (telegram_bot.db) -│ ├── config.py # Centralized configuration -│ └── main.py # FastAPI app entry point -│ -├── src/ # Unified Vue.js 3 frontend -│ ├── modules/ # Feature modules -│ │ ├── reports/ # Reports frontend -│ │ └── data-entry/ # Data entry frontend -│ ├── shared/ # Shared frontend components -│ │ ├── components/ # Reusable Vue components -│ │ └── stores/ # Pinia stores -│ ├── assets/ # Global CSS, images -│ ├── router/ # Vue Router -│ └── App.vue # Root component -│ -├── shared/ # Shared backend components -│ ├── database/ # Oracle pool -│ ├── auth/ # JWT auth & middleware -│ └── frontend/ # Shared frontend assets -│ ├── components/ # LoginView.vue -│ ├── stores/ # Auth store factory -│ └── styles/ # Login CSS -│ -├── docs/ # Architecture & style guides -├── deployment/ # Production deployment scripts -└── ssh-tunnel/ # SSH tunnel for Oracle DB access -``` +### Architecture +See `docs/ARCHITECTURE-DECISIONS.md` for: +- Single worker (`--workers 1`) - required for Telegram bot +- Ultrathin monolith rationale +- IIS deployment strategy ### Starting Services - -**Quick Start** (Unified backend + frontend): ```bash -./start-prod.sh # Prod env: Backend :8001, Frontend :3000 -./start-test.sh # Test env: Backend :8001, Frontend :3000 +./start-prod.sh # Backend :8001 + Frontend :3000 +./ssh-tunnel-prod.sh # Oracle DB tunnel (REQUIRED on Linux) +./status.sh # Check services ``` -**Individual Service Control**: -```bash -./start-frontend.sh restart # Restart frontend only (~7s - fastest!) -./start-backend.sh # Start unified backend :8000 or :8001 -./status.sh # Show services status + health checks -``` - -**Infrastructure**: -```bash -./ssh-tunnel-prod.sh start # Oracle DB tunnel (production: 10.0.20.36) -./ssh-tunnel-test.sh start # Oracle TEST tunnel (LXC: 10.0.20.121) -``` - -**Benefits**: -- **Single backend process**: All modules in one FastAPI app -- **Faster startup**: No multi-service coordination overhead -- **Easier debugging**: Single process to monitor -- **Shared resources**: Connection pools, cache, and middleware - -### Key Architectural Decisions - -**Core Architecture:** -- **Ultrathin Monolith**: Single backend process with modular structure (`backend/modules/`) -- **Single Worker Mode**: `--workers 1` (required for Telegram bot - see ADR-002 in `docs/ARCHITECTURE-DECISIONS.md`) -- **Shared Database Pool**: Singleton `OraclePool` in `shared/database/oracle_pool.py` (python-oracledb with connection pooling) -- **Centralized Auth**: JWT-based auth in `shared/auth/` with middleware auto-injecting `request.state.user` - -**Module-Specific:** -- **Module-Based Cache**: Each module can have its own cache strategy (Reports uses L1+L2 hybrid cache) -- **Telegram Bot**: Integrated module with SQLite database (`backend/modules/data/telegram_bot.db`) -- **FastAPI Structure**: Modules in `backend/modules/*/`, each with services, routers, models/schemas - -**Infrastructure:** -- **SSH Tunnel**: Required for Oracle DB connections (development/Linux) - see Database Setup -- **IIS Sub-Application**: Deployed at `/roa2web` path, not root (production) - -> **For detailed rationale and trade-offs**, see `docs/ARCHITECTURE-DECISIONS.md` +### Database +- **Schema**: `CONTAFIN_ORACLE` +- **Connection**: SSH tunnel required (Linux dev) +- **Env**: `backend/.env` (see `backend/ENV-SETUP.md`) --- -## 🗄️ Database Setup +## Key Rules (ALWAYS FOLLOW) -**Schema**: `CONTAFIN_ORACLE` (authentication and user management) -**Connection**: SSH tunnel required (Oracle on remote network) +### Frontend Development +**Before writing CSS**: Read `docs/ONBOARDING_CSS.md` (5 min) -### SSH Tunnel (Development/Linux) -```bash -./ssh-tunnel-prod.sh start # localhost:1526 → remote:1521 -./ssh-tunnel-prod.sh status # Check tunnel -./ssh-tunnel-prod.sh stop # Stop tunnel -``` +- Use design tokens: `var(--color-primary)` not `#2563eb` +- Use shared CSS from `src/assets/css/` - NEVER duplicate +- Check `docs/CSS_PATTERNS.md` for existing patterns +- **Theme toggle**: App has 3 modes (auto/light/dark) - test BOTH themes! -**IMPORTANT**: Always ensure SSH tunnel is running before starting backend services. +**Tables**: +- Use separate columns (Debit | Credit, not stacked) +- Filter buttons on separate row below filters +- Export ALL data, not just current page -### Environment Variables (`backend/.env`) -```bash -# Oracle Database (through SSH tunnel) -ORACLE_USER=CONTAFIN_ORACLE -ORACLE_PASSWORD=your_password -ORACLE_HOST=localhost -ORACLE_PORT=1526 -ORACLE_SID=ROA +### Backend Development +- Place logic in **services**, not routers +- Use `@cached` decorator for ALL database queries +- Cache schema lookups separately (24h TTL) -# JWT Authentication -JWT_SECRET_KEY=your_secret_key -JWT_ALGORITHM=HS256 -JWT_EXPIRE_MINUTES=30 - -# Module Configuration -MODULE_REPORTS_ENABLED=true -MODULE_DATA_ENTRY_ENABLED=true -MODULE_TELEGRAM_ENABLED=true -``` - -**Windows Production**: Direct Oracle connection, no SSH tunnel required. -**Environment Files**: Multiple .env files available (.env.dev, .env.test, .env.prod) - see `backend/ENV-SETUP.md` for details. - ---- - -## 🔑 Authentication Flow - -1. **Login**: `POST /api/auth/login` → calls `pack_drepturi.verificautilizator(username, password)` -2. **Token**: JWT includes `username`, `user_id`, `companies[]`, `permissions[]`, `exp`, `iat`, `type` -3. **Middleware**: `AuthenticationMiddleware` in `shared/auth/middleware.py` validates tokens, injects user -4. **Protected Routes**: All routes except `excluded_paths` require valid JWT - -**Key Files**: -- `shared/auth/middleware.py` - FastAPI middleware with rate limiting (5 req/5 min) -- `shared/auth/jwt_handler.py` - Token creation/validation -- `backend/main.py` - Main FastAPI app with auth router registration - ---- - -## 📝 Common Development Tasks - -### Adding a New API Endpoint -**IMPORTANT**: Always use the cache system for database queries to improve performance. - -1. Create **service** in `backend/modules/reports/services/your_service.py` (NOT in router!) -2. Define Pydantic schemas in `modules/*/schemas/` or `modules/*/models/` -3. **Add caching** using `@cached` decorator in service methods -4. Create router in `backend/modules/reports/routers/your_router.py` (calls service) -5. Register router in `app/main.py`: `app.include_router(your_router, prefix="/api/your_prefix")` - -**Service Example with Caching** (RECOMMENDED): +**Service pattern**: ```python -# app/services/your_service.py from app.cache.decorators import cached -from database.oracle_pool import oracle_pool class YourService: @staticmethod - @cached(cache_type='schema', key_params=['company_id']) - async def _get_schema(company_id: int) -> str: - """Get schema for company (CACHED 24h)""" - async with oracle_pool.get_connection() as connection: - with connection.cursor() as cursor: - cursor.execute(""" - SELECT schema FROM CONTAFIN_ORACLE.v_nom_firme - WHERE id_firma = :company_id - """, {'company_id': company_id}) - result = cursor.fetchone() - return result[0] if result else None - - @staticmethod - @cached(cache_type='your_data', key_params=['filter_params', 'username']) - async def get_your_data(filter_params: YourFilter, username: str) -> YourResponse: - """ - Get your data from Oracle (CACHED 10 min) - - Cache automatically: - - Generates unique key from filter_params + username - - Stores in L1 (memory) + L2 (SQLite) - - Returns cached data on subsequent calls - - Tracks performance metrics - """ - schema = await YourService._get_schema(filter_params.company_id) - - async with oracle_pool.get_connection() as connection: - with connection.cursor() as cursor: - cursor.execute(f""" - SELECT * FROM {schema}.your_table - WHERE your_condition = :param - """, {'param': filter_params.param}) - rows = cursor.fetchall() - # Process results... - return YourResponse(data=processed_data) + @cached(cache_type='your_data', key_params=['company_id', 'username']) + async def get_data(company_id: int, username: str): + # Query Oracle here ``` -**Router Example** (calls service): -```python -# app/routers/your_router.py -from app.services.your_service import YourService - -@router.get("/", response_model=YourResponse) -async def get_your_data( - filter_params: YourFilter = Depends(), - current_user: CurrentUser = Depends(get_current_user) -): - """Get your data - delegated to service with caching""" - return await YourService.get_your_data(filter_params, current_user.username) -``` - -**Cache Configuration** (add to `app/cache/config.py` if new cache type): -```python -# Add TTL for your cache type -ttl_your_data: int = int(os.getenv('CACHE_TTL_YOUR_DATA', '600')) # 10 min default - -# Add to get_ttl_for_type() method: -'your_data': self.ttl_your_data, -``` - -**Cache Best Practices**: -- ✅ Use `@cached` decorator for ALL database queries -- ✅ Place logic in services (NOT routers) -- ✅ Cache schema lookups separately (long TTL: 24h) -- ✅ Choose appropriate TTL (frequently changing data: 5-10 min, static data: 30 min - 24h) -- ✅ Include `username` in `key_params` for user-specific data -- ✅ Include filter parameters in `key_params` for query variations -- ❌ Don't query Oracle directly in routers (use services with caching) -- ❌ Don't skip caching for performance-critical endpoints - -### Adding a New Frontend Page/Component -**IMPORTANT**: Follow the established CSS architecture and design system. - -**Before writing ANY CSS**: Read **`docs/ONBOARDING_CSS.md`** (5-minute quick start) → See "Documentation Index" below for complete guide list. - -**Golden Rules**: -- ✅ Use global patterns first (`.roa-card`, `.roa-metric`, `.roa-badge-*`) - check `CSS_PATTERNS.md` -- ✅ Use design tokens (`var(--color-primary)`) not hardcoded values (`#2563eb`) -- ✅ **Use shared CSS** from `src/assets/css/` - NEVER create new CSS when shared classes exist -- ✅ For inline stats/totals use `.summary-stats-inline`, `.stat-item`, `.stat-label`, `.stat-value` from `stats.css` -- ❌ Never use `:deep()` in components (use `src/assets/css/vendor/` for PrimeVue overrides) -- ❌ Never duplicate CSS (write once, use everywhere) -- ❌ Never add new scoped CSS for patterns that already exist in shared CSS files - -**Tables - Unified Column Structure & Filter Buttons**: -- ✅ **ALWAYS use separate columns** for related data (Debit | Credit, not Debit+Credit stacked) -- ✅ **Use PrimeVue DataTable** with one value per `` component -- ✅ **Add filter/action buttons** (clear, export Excel, export PDF, refresh) **on separate row below filters** -- ✅ **PrimeVue Button** components with **icon + label** (not icon-only!) -- ✅ **Export ALL data** from backend (page_size: 999999), not just current page -- ❌ **Never group multiple values** vertically in a single column -- ❌ **Never use HTML `