Consolidate 3 separate applications (reports-app, data-entry-app, telegram-bot) into a unified
architecture with single backend and frontend:
Backend Changes:
- Unified FastAPI backend at backend/ with modular structure
- Modules: reports, data_entry, telegram in backend/modules/
- Centralized config.py and main.py with all routers registered
- Single worker mode (--workers 1) for Telegram bot compatibility
- Shared Oracle connection pool and JWT authentication
- Unified requirements.txt and environment configuration
Frontend Changes:
- Single Vue.js SPA with module-based routing
- Unified frontend at src/ with modules in src/modules/{reports,data-entry}/
- Shared components and stores in src/shared/
- Error boundaries for module isolation
- Dual API proxy in Vite for module communication
Infrastructure:
- New unified startup scripts: start-prod.sh, start-test.sh, start-backend.sh
- Environment templates: .env.dev.example, .env.test.example, .env.prod.example
- Updated deployment scripts for Windows IIS
- Simplified SSH tunnel management
Documentation:
- Comprehensive CLAUDE.md with architecture overview
- Module-specific docs in docs/{data-entry,telegram}/
- Architecture decision records in docs/ARCHITECTURE-DECISIONS.md
- Deployment guides consolidated in deployment/windows/docs/
This migration reduces complexity, improves maintainability, and enables easier
deployment while maintaining all existing functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
18 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 ultrathin monolith architecture:
- Reports Module (
backend/modules/reports/) - Read-only reports from Oracle (raportări) - Data Entry Module (
backend/modules/data_entry/) - Data input with approval workflow (introduceri date) - 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.
📁 Module-Specific Instructions
Important
: When working on a specific module, read its documentation first!
| 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
🏗️ Architecture
Important Architecture Decisions: See
docs/ARCHITECTURE-DECISIONS.mdfor 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
Starting Services
Quick Start (Unified backend + frontend):
./start-prod.sh # Prod env: Backend :8001, Frontend :3000
./start-test.sh # Test env: Backend :8001, Frontend :3000
Individual Service Control:
./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:
./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 indocs/ARCHITECTURE-DECISIONS.md) - Shared Database Pool: Singleton
OraclePoolinshared/database/oracle_pool.py(python-oracledb with connection pooling) - Centralized Auth: JWT-based auth in
shared/auth/with middleware auto-injectingrequest.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
/roa2webpath, not root (production)
For detailed rationale and trade-offs, see
docs/ARCHITECTURE-DECISIONS.md
🗄️ Database Setup
Schema: CONTAFIN_ORACLE (authentication and user management)
Connection: SSH tunnel required (Oracle on remote network)
SSH Tunnel (Development/Linux)
./ssh-tunnel-prod.sh start # localhost:1526 → remote:1521
./ssh-tunnel-prod.sh status # Check tunnel
./ssh-tunnel-prod.sh stop # Stop tunnel
IMPORTANT: Always ensure SSH tunnel is running before starting backend services.
Environment Variables (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
# 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
- Login:
POST /api/auth/login→ callspack_drepturi.verificautilizator(username, password) - Token: JWT includes
username,user_id,companies[],permissions[],exp,iat,type - Middleware:
AuthenticationMiddlewareinshared/auth/middleware.pyvalidates tokens, injects user - Protected Routes: All routes except
excluded_pathsrequire valid JWT
Key Files:
shared/auth/middleware.py- FastAPI middleware with rate limiting (5 req/5 min)shared/auth/jwt_handler.py- Token creation/validationbackend/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.
- Create service in
backend/modules/reports/services/your_service.py(NOT in router!) - Define Pydantic schemas in
modules/*/schemas/ormodules/*/models/ - Add caching using
@cacheddecorator in service methods - Create router in
backend/modules/reports/routers/your_router.py(calls service) - 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
@cacheddecorator 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
usernameinkey_paramsfor user-specific data - ✅ Include filter parameters in
key_paramsfor 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-*) - checkCSS_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-valuefromstats.css - ❌ Never use
:deep()in components (usesrc/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 docs/telegram/TELEGRAM_BUTTON_INTERFACE_PLAN.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
- Place in
shared/{database|auth|utils}/ - Import using
sys.path.append()pattern (seebackend/app/main.py:21) - 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.exampleas 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)
docs/data-entry/CLAUDE.md- ⚠️ READ FIRST when working on data-entrydocs/data-entry/README.md- Quick start guidedocs/data-entry/REQUIREMENTS.md- Functional requirementsdocs/data-entry/ARCHITECTURE.md- Technical architecture (SQLModel, workflow)
Architecture & Planning
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 conventionsdocs/COMPONENT_STYLING.md- Component-specific styling guidedocs/FORM_TEMPLATE.md- Standardized form templateFrontend module documentation in src/modules/- Frontend architecture and setupPlaywright E2E testing (see tests/ directory)- Playwright E2E testing guide
Backend Development
Backend module documentation in backend/modules/- Backend architecture and API details- API endpoints documented in
README.md(Authentication, Companies, Dashboard, Invoices, Treasury, Telegram)
Telegram Bot Development
docs/telegram/README.md- Complete bot architecture and development guide (START HERE)docs/telegram/TELEGRAM_BUTTON_INTERFACE_PLAN.md- Command reference and patternstests/MANUAL_TESTING_CHECKLIST.md- Manual testing procedures
Deployment
deployment/windows/README.md- Windows deployment quick startdeployment/windows/docs/WINDOWS_DEPLOYMENT.md- Complete Windows guidedeployment/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.