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>
565 lines
24 KiB
Markdown
565 lines
24 KiB
Markdown
# ROA2WEB Ultrathin Monolith Architecture
|
|
|
|
**Version:** 1.0.0
|
|
**Last Updated:** 2025-12-29
|
|
**Status:** ✅ Active
|
|
|
|
---
|
|
|
|
## 🎯 Overview
|
|
|
|
ROA2WEB uses an **ultrathin monolith** architecture - a single unified backend and frontend application with modular organization. This architecture provides the simplicity of a monolith with the organizational benefits of microservices.
|
|
|
|
### Key Characteristics
|
|
|
|
- **Single Backend Process**: One FastAPI application serving all modules
|
|
- **Single Frontend Build**: One Vue.js SPA with lazy-loaded modules
|
|
- **Modular Organization**: Business logic separated into distinct modules
|
|
- **Shared Resources**: Database pools, auth, cache shared across modules
|
|
- **Independent Modules**: Each module can be developed and tested independently
|
|
|
|
---
|
|
|
|
## 🏗️ Architecture Diagram
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ 🌐 CLIENT BROWSER │
|
|
└────────────────────────────────┬────────────────────────────────────────────┘
|
|
│ HTTP/HTTPS Requests
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ 📦 UNIFIED VUE.JS FRONTEND │
|
|
│ Single-page application (SPA) served from /dist │
|
|
│ Port: 3000 (dev) / 80,443 (production) │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ Frontend Modules (Lazy Loaded) │ │
|
|
│ │ │ │
|
|
│ │ • src/modules/reports/ - Reports module UI │ │
|
|
│ │ • src/modules/data-entry/ - Data entry module UI │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ Shared Frontend Components │ │
|
|
│ │ │ │
|
|
│ │ • src/shared/components/ - Reusable Vue components │ │
|
|
│ │ • src/shared/stores/ - Pinia stores │ │
|
|
│ │ • src/assets/css/ - Global CSS system │ │
|
|
│ │ • shared/frontend/ - Login, auth components │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
└────────────────────────────────┬────────────────────────────────────────────┘
|
|
│ API Calls (Axios)
|
|
│ Authorization: Bearer <JWT>
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ 🚀 UNIFIED FASTAPI BACKEND │
|
|
│ Single Python process running all modules │
|
|
│ Port: 8000 (dev) / 8001 (production) │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ 🛡️ Global Middleware Layer │ │
|
|
│ │ │ │
|
|
│ │ • CORSMiddleware - CORS handling │ │
|
|
│ │ • AuthenticationMiddleware - JWT validation & user injection │ │
|
|
│ │ • Rate Limiting - 5 req/5 min per IP │ │
|
|
│ │ • Security Headers - XSS, CSP, Frame protection │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ 📊 Backend Modules (backend/modules/) │ │
|
|
│ │ │ │
|
|
│ │ reports/ │ │
|
|
│ │ ├── routers/ - API endpoints │ │
|
|
│ │ ├── services/ - Business logic with caching │ │
|
|
│ │ ├── models/ - Pydantic models │ │
|
|
│ │ └── cache/ - L1+L2 cache implementation │ │
|
|
│ │ │ │
|
|
│ │ data_entry/ │ │
|
|
│ │ ├── routers/ - API endpoints │ │
|
|
│ │ ├── services/ - Business logic │ │
|
|
│ │ ├── models/ - SQLModel ORM models │ │
|
|
│ │ └── db/ - SQLite database │ │
|
|
│ │ │ │
|
|
│ │ telegram/ │ │
|
|
│ │ ├── bot/ - Telegram bot handlers │ │
|
|
│ │ ├── api/ - Internal API for bot │ │
|
|
│ │ └── db/ - Bot session management │ │
|
|
│ │ │ │
|
|
│ │ data/ │ │
|
|
│ │ └── telegram_bot.db - Telegram bot SQLite database │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ 🔧 Shared Backend Components (shared/) │ │
|
|
│ │ │ │
|
|
│ │ database/ │ │
|
|
│ │ └── oracle_pool.py - Singleton Oracle connection pool │ │
|
|
│ │ │ │
|
|
│ │ auth/ │ │
|
|
│ │ ├── middleware.py - JWT authentication middleware │ │
|
|
│ │ ├── jwt_handler.py - Token creation/validation │ │
|
|
│ │ └── models.py - Auth data models │ │
|
|
│ │ │ │
|
|
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
└────────────────────────────────┬────────────────────────────────────────────┘
|
|
│ Database Queries
|
|
│ (Oracle + SQLite)
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ 🗄️ DATABASE LAYER │
|
|
│ │
|
|
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
|
|
│ │ Oracle Database │ │ SQLite Databases │ │
|
|
│ │ (via SSH Tunnel) │ │ (Local Files) │ │
|
|
│ │ │ │ │ │
|
|
│ │ • CONTAFIN_ORACLE │ │ • data_entry.db │ │
|
|
│ │ • Financial schemas │ │ • telegram_bot.db │ │
|
|
│ │ • User management │ │ • cache.db │ │
|
|
│ │ │ │ │ │
|
|
│ │ Port: 1521 (remote) │ │ Path: backend/modules/ │ │
|
|
│ │ 1526 (tunnel) │ │ /data/ │ │
|
|
│ │ │ │ │ │
|
|
│ └─────────────────────────┘ └─────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 📁 Directory Structure
|
|
|
|
### Backend Structure
|
|
|
|
```
|
|
backend/
|
|
├── main.py # FastAPI app entry point
|
|
├── config.py # Centralized configuration
|
|
├── .env # Environment variables
|
|
├── .env.dev # Development environment
|
|
├── .env.test # Test environment
|
|
├── .env.prod # Production environment
|
|
│
|
|
└── modules/ # Business logic modules
|
|
├── __init__.py
|
|
│
|
|
├── reports/ # Reports module (Oracle read-only)
|
|
│ ├── __init__.py
|
|
│ ├── routers/ # API endpoints
|
|
│ │ ├── dashboard.py
|
|
│ │ ├── invoices.py
|
|
│ │ └── treasury.py
|
|
│ ├── services/ # Business logic
|
|
│ │ ├── dashboard_service.py
|
|
│ │ └── invoice_service.py
|
|
│ ├── models/ # Pydantic models
|
|
│ ├── schemas/ # Response schemas
|
|
│ └── cache/ # Cache implementation
|
|
│ ├── decorators.py # @cached decorator
|
|
│ └── manager.py # L1+L2 cache manager
|
|
│
|
|
├── data_entry/ # Data entry module (SQLite + workflow)
|
|
│ ├── __init__.py
|
|
│ ├── routers/ # API endpoints
|
|
│ │ ├── receipts.py
|
|
│ │ └── entries.py
|
|
│ ├── services/ # Business logic
|
|
│ ├── models/ # SQLModel ORM models
|
|
│ │ ├── receipt.py
|
|
│ │ ├── attachment.py
|
|
│ │ └── accounting_entry.py
|
|
│ ├── db/ # Database
|
|
│ │ ├── session.py # SQLite session
|
|
│ │ └── migrations/ # Alembic migrations
|
|
│ └── utils/ # Helper functions
|
|
│
|
|
├── telegram/ # Telegram bot module
|
|
│ ├── __init__.py
|
|
│ ├── bot/ # Bot implementation
|
|
│ │ ├── handlers.py # Command handlers
|
|
│ │ ├── helpers.py # Helper functions
|
|
│ │ └── formatters.py # Message formatters
|
|
│ ├── api/ # Internal API
|
|
│ │ └── auth.py # Auth code management
|
|
│ ├── db/ # Bot database
|
|
│ │ └── session.py # Session management
|
|
│ └── bot_main.py # Bot entry point
|
|
│
|
|
└── data/ # Shared data
|
|
└── telegram_bot.db # Telegram bot database
|
|
```
|
|
|
|
### Frontend Structure
|
|
|
|
```
|
|
src/
|
|
├── main.js # App entry point
|
|
├── App.vue # Root component
|
|
│
|
|
├── modules/ # Feature modules
|
|
│ ├── reports/ # Reports module
|
|
│ │ ├── views/ # Page components
|
|
│ │ │ ├── DashboardView.vue
|
|
│ │ │ ├── InvoicesView.vue
|
|
│ │ │ └── TreasuryView.vue
|
|
│ │ ├── components/ # Module-specific components
|
|
│ │ ├── stores/ # Module-specific Pinia stores
|
|
│ │ │ ├── dashboard.js
|
|
│ │ │ └── invoices.js
|
|
│ │ ├── services/ # API client
|
|
│ │ │ └── api.js
|
|
│ │ └── utils/ # Helpers
|
|
│ │
|
|
│ └── data-entry/ # Data entry module
|
|
│ ├── views/ # Page components
|
|
│ │ ├── ReceiptsView.vue
|
|
│ │ └── EntriesView.vue
|
|
│ ├── components/ # Module-specific components
|
|
│ ├── stores/ # Module-specific Pinia stores
|
|
│ │ └── receipts.js
|
|
│ └── services/ # API client
|
|
│ └── api.js
|
|
│
|
|
├── shared/ # Shared components
|
|
│ ├── components/ # Reusable Vue components
|
|
│ │ ├── ErrorBoundary.vue
|
|
│ │ ├── CompanySelector.vue
|
|
│ │ └── PeriodSelector.vue
|
|
│ └── stores/ # Shared Pinia stores
|
|
│ ├── auth.js
|
|
│ ├── companies.js
|
|
│ └── accountingPeriod.js
|
|
│
|
|
├── router/ # Vue Router
|
|
│ ├── index.js # Main router
|
|
│ ├── reports.js # Reports routes
|
|
│ └── data-entry.js # Data entry routes
|
|
│
|
|
├── assets/ # Global assets
|
|
│ ├── css/ # Global CSS system
|
|
│ │ ├── core/ # Design tokens
|
|
│ │ ├── components/ # Component styles
|
|
│ │ ├── patterns/ # UI patterns
|
|
│ │ ├── layout/ # Layout styles
|
|
│ │ ├── utilities/ # Utility classes
|
|
│ │ └── vendor/ # PrimeVue overrides
|
|
│ └── images/ # Images
|
|
│
|
|
└── views/ # Global views
|
|
└── LoginView.vue # Login page
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 Request Flow
|
|
|
|
### 1. User Authentication Flow
|
|
|
|
```
|
|
User Login Request
|
|
↓
|
|
Frontend (LoginView.vue)
|
|
↓ POST /api/auth/login
|
|
Backend (main.py)
|
|
↓
|
|
AuthenticationMiddleware (excluded for /login)
|
|
↓
|
|
Auth Router (/api/auth/login)
|
|
↓
|
|
Oracle Database (pack_drepturi.verificautilizator)
|
|
↓
|
|
JWT Token Generation
|
|
↓
|
|
Response with access_token + refresh_token
|
|
↓
|
|
Frontend stores token in localStorage
|
|
↓
|
|
Subsequent requests include: Authorization: Bearer <token>
|
|
```
|
|
|
|
### 2. Reports Data Flow (with Cache)
|
|
|
|
```
|
|
User Request (Dashboard data)
|
|
↓
|
|
Frontend (DashboardView.vue)
|
|
↓ GET /api/reports/dashboard
|
|
Backend Middleware
|
|
├─ CORS check ✓
|
|
├─ JWT validation ✓
|
|
└─ User injection into request.state
|
|
↓
|
|
Reports Router (/api/reports/dashboard)
|
|
↓
|
|
DashboardService.get_dashboard_data()
|
|
↓
|
|
@cached decorator checks cache
|
|
├─ L1 Cache (Memory) HIT? → Return cached data
|
|
├─ L2 Cache (SQLite) HIT? → Store in L1, return data
|
|
└─ MISS → Query Oracle
|
|
↓
|
|
Oracle Database (via connection pool)
|
|
↓
|
|
Process and cache result (L1 + L2)
|
|
↓
|
|
Return data
|
|
↓
|
|
Response with cache metadata headers
|
|
↓
|
|
Frontend updates Pinia store
|
|
↓
|
|
Vue component reactively updates UI
|
|
```
|
|
|
|
### 3. Data Entry Flow (with Workflow)
|
|
|
|
```
|
|
User Creates Receipt
|
|
↓
|
|
Frontend (ReceiptsView.vue)
|
|
↓ POST /api/data-entry/receipts
|
|
Backend Middleware (JWT validation)
|
|
↓
|
|
Data Entry Router
|
|
↓
|
|
ReceiptService.create_receipt()
|
|
↓
|
|
SQLModel ORM
|
|
↓
|
|
SQLite Database (data_entry.db)
|
|
├─ Insert Receipt (status: DRAFT)
|
|
├─ Insert Attachments
|
|
└─ Generate AccountingEntries
|
|
↓
|
|
Response with receipt ID
|
|
↓
|
|
Frontend updates Pinia store
|
|
↓
|
|
UI shows new receipt in DRAFT state
|
|
↓
|
|
User submits for approval
|
|
↓ POST /api/data-entry/receipts/{id}/submit
|
|
Backend updates status: DRAFT → PENDING
|
|
↓
|
|
Workflow continues (PENDING → APPROVED/REJECTED)
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Module Independence
|
|
|
|
### Benefits of Modular Monolith
|
|
|
|
1. **Development**:
|
|
- Each module can be developed independently
|
|
- Clear boundaries between features
|
|
- Easy to understand and navigate
|
|
|
|
2. **Testing**:
|
|
- Modules can be tested in isolation
|
|
- Shared components tested once
|
|
- Integration tests verify module interactions
|
|
|
|
3. **Deployment**:
|
|
- Single deployment process
|
|
- No service coordination complexity
|
|
- Atomic updates (all or nothing)
|
|
|
|
4. **Performance**:
|
|
- No network latency between modules
|
|
- Shared connection pools
|
|
- Efficient resource utilization
|
|
|
|
### Module Communication
|
|
|
|
**Within Backend**:
|
|
- Modules can directly import from each other
|
|
- Use shared utilities from `shared/`
|
|
- Share database connections and auth
|
|
|
|
**Within Frontend**:
|
|
- Modules use shared Pinia stores
|
|
- Shared components in `src/shared/`
|
|
- Routing handles module navigation
|
|
|
|
---
|
|
|
|
## 🔧 Configuration Management
|
|
|
|
### Environment-Based Configuration
|
|
|
|
The backend supports multiple environment configurations:
|
|
|
|
```bash
|
|
# Development
|
|
backend/.env.dev # Local development settings
|
|
PORT=8000
|
|
DEBUG=True
|
|
ORACLE_HOST=localhost
|
|
ORACLE_PORT=1526
|
|
|
|
# Testing
|
|
backend/.env.test # Testing environment
|
|
PORT=8001
|
|
DEBUG=False
|
|
ORACLE_HOST=10.0.20.121
|
|
|
|
# Production
|
|
backend/.env.prod # Production settings
|
|
PORT=8001
|
|
DEBUG=False
|
|
ORACLE_HOST=10.0.20.36
|
|
```
|
|
|
|
### Module Toggle Configuration
|
|
|
|
Modules can be enabled/disabled via environment variables:
|
|
|
|
```bash
|
|
MODULE_REPORTS_ENABLED=true
|
|
MODULE_DATA_ENTRY_ENABLED=true
|
|
MODULE_TELEGRAM_ENABLED=true
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Shared Resources
|
|
|
|
### 1. Database Connection Pool
|
|
|
|
**Oracle Pool** (`shared/database/oracle_pool.py`):
|
|
- Singleton pattern
|
|
- Configured pool size (min=2, max=10)
|
|
- Automatic reconnection
|
|
- Connection health checks
|
|
- Used by Reports module
|
|
|
|
### 2. Authentication & Authorization
|
|
|
|
**JWT Authentication** (`shared/auth/`):
|
|
- Centralized token management
|
|
- Middleware auto-injection of user
|
|
- Rate limiting (5 req/5 min)
|
|
- Used by all modules
|
|
|
|
### 3. Cache System (Reports Module)
|
|
|
|
**Two-Tier Cache**:
|
|
- L1: In-memory (LRU, 1000 entries)
|
|
- L2: SQLite persistent cache
|
|
- Automatic TTL management
|
|
- Performance tracking
|
|
|
|
### 4. Frontend Shared Components
|
|
|
|
**Shared UI** (`src/shared/` and `shared/frontend/`):
|
|
- Authentication components
|
|
- Company/Period selectors
|
|
- Error boundaries
|
|
- Global CSS system
|
|
|
|
---
|
|
|
|
## 🎯 Migration from Microservices
|
|
|
|
### What Changed
|
|
|
|
**Before (Microservices)**:
|
|
```
|
|
reports-app/backend/ → Port 8001
|
|
data-entry-app/backend/ → Port 8003
|
|
telegram-bot/ → Port 8002
|
|
```
|
|
|
|
**After (Monolith)**:
|
|
```
|
|
backend/ → Single port 8000/8001
|
|
└── modules/
|
|
├── reports/
|
|
├── data_entry/
|
|
└── telegram/
|
|
```
|
|
|
|
### Migration Benefits
|
|
|
|
1. ✅ Simpler deployment (1 service instead of 3)
|
|
2. ✅ Faster startup (no multi-service coordination)
|
|
3. ✅ Easier debugging (single process)
|
|
4. ✅ Shared connection pools (better resource utilization)
|
|
5. ✅ No inter-service network latency
|
|
6. ✅ Atomic deployments (all modules update together)
|
|
|
|
### What Stayed the Same
|
|
|
|
- ✅ Module boundaries and organization
|
|
- ✅ Business logic and models
|
|
- ✅ Frontend structure
|
|
- ✅ Database schemas
|
|
- ✅ API contracts
|
|
- ✅ Authentication flow
|
|
|
|
---
|
|
|
|
## 🔒 Security Considerations
|
|
|
|
### Middleware Stack
|
|
|
|
All requests pass through:
|
|
1. CORS validation
|
|
2. JWT authentication
|
|
3. Rate limiting
|
|
4. Security headers injection
|
|
|
|
### Module Isolation
|
|
|
|
While modules share the same process:
|
|
- Each has its own routers
|
|
- Business logic is separated
|
|
- Database access is controlled
|
|
- Permissions are enforced at API level
|
|
|
|
---
|
|
|
|
## 📈 Scalability
|
|
|
|
### Horizontal Scaling
|
|
|
|
The monolith can be scaled horizontally:
|
|
- Multiple instances behind load balancer
|
|
- Stateless design (JWT, no sessions)
|
|
- Shared database (Oracle)
|
|
- Redis for distributed cache (future)
|
|
|
|
### Vertical Scaling
|
|
|
|
Optimize single instance:
|
|
- Increase worker processes
|
|
- Connection pool tuning
|
|
- Cache optimization
|
|
- Query optimization
|
|
|
|
### Future: Microservices Migration
|
|
|
|
If needed, modules can be extracted:
|
|
- Each module already has clear boundaries
|
|
- Services are independent
|
|
- API contracts are defined
|
|
- Database can be split (if needed)
|
|
|
|
---
|
|
|
|
## 📚 Related Documentation
|
|
|
|
- **Setup & Commands**: `README.md`
|
|
- **CSS Architecture**: `docs/ONBOARDING_CSS.md`
|
|
- **Data Entry Module**: `docs/data-entry/ARCHITECTURE.md`
|
|
- **Telegram Bot**: `docs/telegram/README.md`
|
|
- **Deployment**: `deployment/windows/README.md` (Windows) or `DOKPLOY_DEPLOYMENT.md` (Linux)
|
|
|
|
---
|
|
|
|
**For questions about this architecture, consult the development team or open an issue in the repository.**
|