Files
roa2web-service-auto/CLAUDE.md
Marius Mutu c5fde510a8 feat: Add JWT auth and nomenclature sync to data-entry-app
Integrate shared JWT authentication into data-entry-app:
- Add Oracle pool initialization for auth service
- Add AuthenticationMiddleware to protect API routes
- Update all receipt endpoints to use CurrentUser from JWT
- Add shared auth router (/api/auth/login, /api/auth/refresh)

Add nomenclature synchronization feature:
- Create SQLite models for synced suppliers, local suppliers, and cash registers
- Add nomenclature router with sync triggers and CRUD endpoints
- Add sync service for Oracle → SQLite nomenclature data
- Update nomenclature_service to use synced SQLite data with fallbacks

Create shared frontend components:
- Add shared/frontend/ with LoginView.vue, auth store factory, login.css
- Integrate shared login and auth into data-entry-app frontend
- Add axios-based API service with token refresh interceptor

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 18:36:24 +02:00

16 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

🚀 Project Overview

ROA2WEB - Modern ERP Application with two main modules:

  1. Reports App (reports-app/) - Read-only reports from Oracle (raportări)
  2. Data Entry App (data-entry-app/) - Data input with approval workflow (introduceri date)

Main Branch: main (use for PRs) Working Directory: Repository root

Quick Reference: See README.md for complete setup, commands, deployment, and testing instructions.


📁 Application-Specific Instructions

Important

: When working on a specific application, ALWAYS read its dedicated CLAUDE.md first!

Application CLAUDE.md Location Description
Data Entry data-entry-app/CLAUDE.md Bonuri fiscale, chitanțe, workflow aprobare
Reports This file (below) Rapoarte Oracle read-only
Telegram Bot reports-app/telegram-bot/README.md Bot Telegram

When to Use Which Instructions

Working on data-entry-app/: → FIRST read data-entry-app/CLAUDE.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

Working on reports-app/ or shared/: → Use instructions from this file (below)

Working on shared components (shared/auth/, shared/database/, shared/frontend/): → These are used by BOTH apps - be careful with changes! → shared/frontend/ contains: LoginView.vue, auth store factory, login styles


🏗️ Architecture

Microservices Structure

.
├── shared/                    # Shared components (DB pool, auth, frontend)
│   ├── database/             # Oracle pool (used by both apps)
│   ├── auth/                 # JWT auth (used by both apps)
│   └── frontend/             # Shared Vue components, stores, styles
│       ├── components/       # LoginView.vue
│       ├── stores/           # auth.js (Pinia store factory)
│       └── styles/           # login.css
│
├── reports-app/              # READ-ONLY reports from Oracle
│   ├── backend/              # FastAPI API (port 8001)
│   ├── frontend/             # Vue.js 3 UI (port 3000-3005)
│   └── telegram-bot/         # Telegram bot (port 8002 internal)
│
├── data-entry-app/           # DATA INPUT with approval workflow
│   ├── backend/              # FastAPI API (port 8003) - SQLite + SQLModel
│   ├── frontend/             # Vue.js 3 UI (port 3010)
│   └── CLAUDE.md             # ⚠️ READ THIS for data-entry work!
│
├── docs/                     # Architecture & style guides
├── deployment/               # Production deployment scripts
└── ssh-tunnel/              # SSH tunnel for Oracle DB access

Starting Services

# Reports App (Oracle reports)
./start-test.sh              # Backend :8001, Frontend :3000-3005, Telegram :8002

# Data Entry App (fiscal receipts)
./start-data-entry.sh        # Backend :8003, Frontend :3010

Key Architectural Decisions

  • 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
  • Two-Tier Cache System: Hybrid L1 (Memory) + L2 (SQLite) cache in backend/app/cache/ - MANDATORY for all new endpoints
  • SSH Tunnel: Required for Oracle DB connections (development/Linux) - see Database Setup
  • FastAPI Structure: Services in backend/app/services/ with @cached decorator, routers in backend/app/routers/, models in backend/app/models/ or schemas/
  • Telegram Bot: Standalone SQLite database for bot data, communicates with backend via HTTP API

🗄️ Database Setup

Schema: CONTAFIN_ORACLE (authentication and user management) Connection: SSH tunnel required (Oracle on remote network)

SSH Tunnel (Development/Linux)

./ssh_tunnel.sh start     # localhost:1526 → remote:1521
./ssh_tunnel.sh status    # Check tunnel
./ssh_tunnel.sh stop      # Stop tunnel

IMPORTANT: Always ensure SSH tunnel is running before starting backend services.

Environment Variables (reports-app/backend/.env)

# Oracle Database (through SSH tunnel)
ORACLE_USER=CONTAFIN_ORACLE
ORACLE_PASSWORD=your_password
ORACLE_HOST=localhost
ORACLE_PORT=1526
ORACLE_SID=ROA

# JWT Authentication
JWT_SECRET_KEY=your_secret_key
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=30

# Telegram Bot Integration
TELEGRAM_BOT_INTERNAL_API=http://localhost:8002

Windows Production: Direct Oracle connection, no SSH tunnel required. Ensure TELEGRAM_BOT_INTERNAL_API is set for auth code management.


🔑 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
  • reports-app/backend/app/main.py - Auth router inline definition

📝 Common Development Tasks

Adding a New API Endpoint

IMPORTANT: Always use the cache system for database queries to improve performance.

  1. Create service in reports-app/backend/app/services/your_service.py (NOT in router!)
  2. Define Pydantic schemas in app/schemas/ or app/models/
  3. Add caching using @cached decorator in service methods
  4. Create router in reports-app/backend/app/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):

# 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)

Router Example (calls service):

# 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):

# 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 <Column> 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 <button> for filter actions (use PrimeVue <Button>)
  • Never put action buttons on same row as filters (separate row!)
  • Never export only current page (must fetch all data for export)
  • 📖 See: CSS_PATTERNS.md → Table Patterns → Unified Table Column Structure & Filter/Action Buttons

Adding a New Telegram Bot Command

IMPORTANT: Follow established command patterns and formatting.

Before coding: Read reports-app/telegram-bot/TELEGRAM_COMMANDS.md for command patterns → See "Documentation Index" for complete guides.

Standard Pattern (add handler in app/bot/handlers.py):

async def your_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    telegram_id = update.effective_user.id

    # 1. Check authentication (use helpers.py)
    user = await get_user_by_telegram_id(telegram_id)
    if not user:
        await update.message.reply_text("⚠️ Account not linked. Use /start with code.")
        return

    # 2. Check active company (use session.py)
    active_company = await get_active_company(telegram_id)
    if not active_company:
        await update.message.reply_text("⚠️ Select company first: /selectcompany")
        return

    # 3. Call backend API (use api/client.py)
    # 4. Format response (use formatters.py)
    # 5. Add tests + update MANUAL_TESTING_CHECKLIST.md

Adding Shared Functionality

  1. Place in shared/{database|auth|utils}/
  2. Import using sys.path.append() pattern (see backend/app/main.py:21)
  3. Add tests in shared/tests/

Frontend API Integration

// Store pattern (src/stores/yourStore.js)
import axios from 'axios';

const api = axios.create({
  baseURL: 'http://localhost:8001/api',
  headers: { 'Authorization': `Bearer ${token}` }
});

const response = await api.get('/endpoint');

🔒 Security

  • Git Hooks: Security scanning in security/install_hooks.sh
  • Environment Files: Never commit .env (use .env.example as template)
  • SSH Keys: In ssh-tunnel/secrets/ (gitignored)
  • JWT Secrets: Generate strong secrets for production
  • Rate Limiting: Built into auth middleware (5 requests per 5 minutes)

📚 Documentation Index

Quick Start & Commands

README.md - Project overview, setup, development commands, testing, deployment

Data Entry App (Bonuri Fiscale)

  • data-entry-app/CLAUDE.md - ⚠️ READ FIRST when working on data-entry
  • data-entry-app/README.md - Quick start guide
  • docs/data-entry/REQUIREMENTS.md - Functional requirements
  • docs/data-entry/ARCHITECTURE.md - Technical architecture (SQLModel, workflow)

Architecture & Planning

  • docs/ARCHITECTURE_SCHEMA.md - Architecture diagrams, cache system, and schemas
  • docs/MICROSERVICES_GUIDE.md - Microservices architecture details
  • DEVELOPMENT_BLUEPRINT.md - Detailed development plan

Frontend Development

  • docs/ONBOARDING_CSS.md - CSS system quick start (START HERE for new components)
  • docs/CSS_PATTERNS.md - Complete CSS patterns library (cards, forms, buttons, etc.)
  • docs/DESIGN_TOKENS.md - Design tokens (colors, spacing, typography)
  • docs/STYLING_GUIDELINES.md - CSS best practices and conventions
  • docs/COMPONENT_STYLING.md - Component-specific styling guide
  • docs/FORM_TEMPLATE.md - Standardized form template
  • reports-app/frontend/README.md - Frontend architecture and setup
  • reports-app/frontend/tests/README.md - Playwright E2E testing guide

Backend Development

  • reports-app/backend/README.md - Backend architecture and API details
  • API endpoints documented in README.md (Authentication, Companies, Dashboard, Invoices, Treasury, Telegram)

Telegram Bot Development

  • reports-app/telegram-bot/README.md - Complete bot architecture and development guide (START HERE)
  • reports-app/telegram-bot/TELEGRAM_COMMANDS.md - Command reference and patterns
  • tests/MANUAL_TESTING_CHECKLIST.md - Manual testing procedures

Deployment

  • DEPLOYMENT_GUIDE.md - Production deployment (Linux/Docker & Windows/IIS)
  • deployment/windows/README.md - Windows deployment quick start
  • deployment/windows/docs/WINDOWS_DEPLOYMENT.md - Complete Windows guide
  • deployment/windows/docs/TELEGRAM_BOT_TROUBLESHOOTING.md - Bot troubleshooting

Troubleshooting

README.md - Common issues (SSH tunnel, backend, frontend, database) → Backend: Check .env, SSH tunnel status, port 8001 availability → Frontend: Clear node_modules, check Node.js version (16+), Vite auto-ports → Database: Verify SSH tunnel, Oracle listener, credentials, test /health


🔧 Tech Stack

Backend: FastAPI, python-oracledb, JWT (PyJWT), Pydantic, pytest Frontend: Vue.js 3 (Composition API), PrimeVue, Pinia, Vite, Axios, Chart.js, Playwright Telegram Bot: python-telegram-bot, SQLite + aiosqlite, httpx, FastAPI (internal), pytest Infrastructure: Oracle Database, SSH Tunnel, Nginx (Linux prod), Docker (Linux prod), IIS + NSSM (Windows prod)


For detailed information on any topic, always check the Documentation Index above first.