unified app plan

This commit is contained in:
2025-12-22 01:01:58 +02:00
parent ee239eb3f3
commit 215fd72ac2
6 changed files with 2637 additions and 0 deletions

5
.claude/settings.json Normal file
View File

@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"ab@roa2web-tools": true
}
}

32
.claude_settings.json Normal file
View File

@@ -0,0 +1,32 @@
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true
},
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Read(./**)",
"Write(./**)",
"Edit(./**)",
"Glob(./**)",
"Grep(./**)",
"Bash(*)",
"mcp__puppeteer__puppeteer_connect_active_tab",
"mcp__puppeteer__puppeteer_navigate",
"mcp__puppeteer__puppeteer_screenshot",
"mcp__puppeteer__puppeteer_click",
"mcp__puppeteer__puppeteer_fill",
"mcp__puppeteer__puppeteer_select",
"mcp__puppeteer__puppeteer_hover",
"mcp__puppeteer__puppeteer_evaluate",
"mcp__context7__resolve-library-id",
"mcp__context7__get-library-docs",
"mcp__graphiti-memory__search_nodes",
"mcp__graphiti-memory__search_facts",
"mcp__graphiti-memory__add_episode",
"mcp__graphiti-memory__get_episodes",
"mcp__graphiti-memory__get_entity_edge"
]
}
}

3
.gitignore vendored
View File

@@ -510,3 +510,6 @@ TELEGRAM_EMAIL_AUTH_PLAN*.md
secrets-backup/**/*.env secrets-backup/**/*.env
secrets-backup/**/.env.* secrets-backup/**/.env.*
!secrets-backup/**/*.gpg !secrets-backup/**/*.gpg
.playwright-mcp/*
data-entry-app/backend/data/*

View File

@@ -0,0 +1,285 @@
# Plan: Consolidare ROA2WEB - Pragmatic Monolith
> **Branch**: `feature/unified-app-pragmatic-monolith`
> **Status**: APROBAT - Ready for Implementation
> **Efort estimat**: ~2.5 zile
---
## Context și Problema
### Situația Curentă
- 2 aplicații frontend separate în IIS: `/roa2web/` și `/data-entry/`
- Deploy greoi (2 build-uri, 2 configurații IIS separate)
- Componentele shared cauzează probleme CSS cross-app (text alb pe fundal alb)
- Nu există meniu unificat între aplicații
### Obiectiv
- Un singur meniu cu ambele aplicații (Reports + Data Entry)
- Deploy simplificat (un build, un site IIS)
- Izolare între module (bug în Reports să nu afecteze DataEntry)
- URL-uri pe root: `/reports/*`, `/data-entry/*`
---
## Decizie Arhitecturală: Pragmatic Monolith
### De ce NU Micro-frontends?
| Criteriu pentru MFE | ROA2WEB | Necesită MFE? |
|---------------------|---------|---------------|
| 20+ dezvoltatori | 1 dev | ❌ Nu |
| Deploy de multe ori/zi | Săptămânal | ❌ Nu |
| Milioane de utilizatori | 1-5 concurenți | ❌ Nu |
| Framework-uri diferite | Vue only | ❌ Nu |
**Verdict**: Module Federation / Single-SPA = OVERKILL
### Abordare Aleasă: Monolith cu Mecanisme de Izolare
- **Error Boundaries** per modul (bug în Reports nu strică DataEntry)
- **Lazy Loading** (bundle-uri separate, încărcate la nevoie)
- **Stores izolate** per modul
- **Feature flags** pentru control
**Blast radius cu protecții: 50-70%** (aproape ca 2 apps separate!)
---
## Arhitectura Finală
```
┌─────────────────────────────────────────────────────────────┐
│ ROA2WEB Unified SPA │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Reports Module │ │ DataEntry Module │ │ Shared │ │
│ │ /reports/* │ │ /data-entry/* │ │ - Auth │ │
│ │ (lazy loaded) │ │ (lazy loaded) │ │ - Company │ │
│ │ │ │ │ │ - Period │ │
│ │ ErrorBoundary │ │ ErrorBoundary │ │ - Header │ │
│ └────────┬────────┘ └────────┬─────────┘ └──────────────┘ │
│ │ │ │
│ ┌────────┴────────────────────┴─────────┐ │
│ │ Vue Router + Global Error Handler │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────┴─────────┐
│ IIS Proxy │
└─────────┬─────────┘
┌───────────────┴───────────────┐
│ │
┌────────▼────────┐ ┌──────────▼────────┐
│ Reports Backend │ │ DataEntry Backend │
│ port 8001 │ │ port 8003 │
│ (Oracle RO) │ │ (SQLite + Oracle) │
└─────────────────┘ └───────────────────┘
```
---
## Structura Proiect Unified
```
roa2web/
├── src/
│ ├── main.js
│ ├── App.vue # Meniu unificat
│ ├── router/index.js # Rute unificate cu lazy loading
│ │
│ ├── modules/
│ │ ├── reports/ # MODUL IZOLAT
│ │ │ ├── ReportsLayout.vue # Error boundary pentru modul
│ │ │ ├── views/
│ │ │ │ ├── DashboardView.vue
│ │ │ │ ├── InvoicesView.vue
│ │ │ │ ├── BankCashRegisterView.vue
│ │ │ │ ├── TrialBalanceView.vue
│ │ │ │ ├── TelegramView.vue
│ │ │ │ └── CacheStatsView.vue
│ │ │ ├── stores/
│ │ │ └── services/
│ │ │
│ │ └── data-entry/ # MODUL IZOLAT
│ │ ├── DataEntryLayout.vue
│ │ ├── views/
│ │ │ ├── ReceiptsListView.vue
│ │ │ └── ReceiptCreateView.vue
│ │ ├── stores/
│ │ └── services/
│ │
│ ├── shared/ # Shared între module
│ │ ├── components/ # AppHeader, SlideMenu, CompanySelector, etc.
│ │ ├── stores/ # Auth, Company, Period
│ │ └── styles/
│ │
│ └── config/
│ ├── menu.js # Configurație meniu unificat
│ └── features.js # Feature flags
├── vite.config.js
└── package.json
```
---
## Pași Implementare
### Faza 1: Setup Proiect (0.5 zile)
1. Creează directorul `roa2web/`
2. Setup `package.json` cu dependencies combinate din ambele apps
3. Setup `vite.config.js` cu:
- Dual proxy: `/api/reports/*``:8001`, `/api/data-entry/*``:8003`
- Lazy loading chunks configuration
- Base path `/`
4. Setup `main.js` cu Pinia, PrimeVue, Router
### Faza 2: Migrare Module (1 zi)
1. Copiază views din `reports-app/frontend/src/views/``modules/reports/views/`
2. Copiază views din `data-entry-app/frontend/src/views/``modules/data-entry/views/`
3. Copiază stores specifice fiecărui modul
4. Creează `ReportsLayout.vue` și `DataEntryLayout.vue` cu error boundaries
5. Setup router unificat:
```javascript
const routes = [
{ path: '/login', component: LoginView },
{
path: '/reports',
component: () => import('./modules/reports/ReportsLayout.vue'),
children: [
{ path: 'dashboard', component: () => import('./modules/reports/views/DashboardView.vue') },
{ path: 'invoices', component: () => import('./modules/reports/views/InvoicesView.vue') },
// ...
]
},
{
path: '/data-entry',
component: () => import('./modules/data-entry/DataEntryLayout.vue'),
children: [
{ path: '', component: () => import('./modules/data-entry/views/ReceiptsListView.vue') },
{ path: 'create', component: () => import('./modules/data-entry/views/ReceiptCreateView.vue') },
]
},
{ path: '/', redirect: '/reports/dashboard' }
]
```
### Faza 3: Izolare și Resilience (0.5 zile)
1. Implementează `ErrorBoundary.vue`:
```vue
<template>
<div v-if="error" class="module-error">
<h3>⚠️ {{ moduleName }} a întâmpinat o eroare</h3>
<p>{{ error.message }}</p>
<button @click="retry">Reîncearcă</button>
</div>
<slot v-else />
</template>
```
2. Separă stores per modul (nu global)
3. Adaugă feature flags în `config/features.js`
4. Testează izolarea: introduce bug în Reports, verifică că DataEntry funcționează
### Faza 4: Build & Deploy (0.5 zile)
1. Verifică bundle splitting cu `npm run build`:
```
dist/assets/
├── index-[hash].js # Shell + shared (~150KB)
├── reports-[hash].js # Reports module (~200KB)
└── data-entry-[hash].js # DataEntry module (~100KB)
```
2. Update IIS web.config pentru SPA routing (toate rutele → index.html)
3. Update deployment scripts pentru single app
4. Test end-to-end pe server
5. Deploy în producție
---
## Meniu Unificat
```javascript
// config/menu.js
export const menuSections = [
{
title: 'Rapoarte',
items: [
{ to: '/reports/dashboard', icon: 'pi pi-home', label: 'Dashboard' },
{ to: '/reports/invoices', icon: 'pi pi-file', label: 'Facturi' },
{ to: '/reports/bank-cash', icon: 'pi pi-money-bill', label: 'Casa și Banca' },
{ to: '/reports/trial-balance', icon: 'pi pi-calculator', label: 'Balanță' },
]
},
{
title: 'Introduceri Date',
items: [
{ to: '/data-entry', icon: 'pi pi-list', label: 'Lista Bonuri' },
{ to: '/data-entry/create', icon: 'pi pi-plus', label: 'Bon Nou' },
]
},
{
title: 'Sistem',
items: [
{ to: '/reports/telegram', icon: 'pi pi-telegram', label: 'Telegram' },
{ to: '/reports/cache-stats', icon: 'pi pi-chart-bar', label: 'Cache Stats' },
]
}
];
```
---
## Fișiere de Referință
### Fișiere Existente (sursă pentru copiere)
- `reports-app/frontend/src/views/*.vue` - Views Reports
- `reports-app/frontend/src/stores/*.js` - Stores Reports
- `reports-app/frontend/src/services/api.js` - API service Reports
- `data-entry-app/frontend/src/views/*.vue` - Views DataEntry
- `data-entry-app/frontend/src/stores/*.js` - Stores DataEntry
- `data-entry-app/frontend/src/services/api.js` - API service DataEntry
- `shared/frontend/components/` - Componente shared (AppHeader, SlideMenu, etc.)
- `shared/frontend/stores/` - Stores shared (auth, companies, accountingPeriod)
### Configurații de Referință
- `reports-app/frontend/vite.config.js` - Pentru proxy și build config
- `reports-app/frontend/package.json` - Pentru dependencies
- `data-entry-app/frontend/vite.config.js` - Pentru proxy config
- `data-entry-app/frontend/package.json` - Pentru dependencies
---
## URL-uri Finale
| Path | Descriere |
|------|-----------|
| `/` | Redirect la `/reports/dashboard` |
| `/login` | Pagină login |
| `/reports/dashboard` | Dashboard principal |
| `/reports/invoices` | Facturi |
| `/reports/bank-cash` | Casa și Banca |
| `/reports/trial-balance` | Balanță de Verificare |
| `/reports/telegram` | Telegram Bot |
| `/reports/cache-stats` | Statistici Cache |
| `/data-entry` | Lista Bonuri |
| `/data-entry/create` | Bon Nou |
| `/data-entry/:id` | Detalii Bon |
| `/data-entry/:id/edit` | Editare Bon |
---
## Note Importante
1. **Backend-urile rămân separate** - port 8001 (Reports) și port 8003 (DataEntry)
2. **IIS proxy routing** - trebuie configurat pentru a ruta API calls corect
3. **Error Boundaries** - critice pentru izolarea modulelor
4. **Lazy Loading** - asigură bundle splitting corect
5. **Feature flags** - permit dezactivarea unui modul fără redeploy
---
## Handover Notes
Această implementare va înlocui cele 2 aplicații separate cu o aplicație unificată.
După implementare, directoarele `reports-app/frontend/` și `data-entry-app/frontend/`
pot fi arhivate/șterse, păstrând doar `unified-app/`.
Backend-urile rămân neschimbate în `reports-app/backend/` și `data-entry-app/backend/`.

File diff suppressed because it is too large Load Diff

Binary file not shown.