# Plan: Implementare Auth SSO + Nomenclatoare Sync > **Plan Handover Document** - Salvat pentru continuare în altă sesiune > **Data**: 2025-12-13 | **Branch**: `feature/data-entry-receipts` ## Obiectiv Integrare autentificare SSO și sincronizare nomenclatoare Oracle în data-entry-app conform `IMPLEMENTATION_PLAN_AUTH_UNITAR.md`. --- ## Instrucțiuni Implementare ### Metodologie 1. **Execută fazele în paralel** unde e posibil (Faza 1+2 pot rula simultan, Faza 3+4 pot rula simultan) 2. **Folosește agenți Task** pentru viteza - lansează agenți în paralel pentru task-uri independente 3. **Testează după fiecare fază** - nu trece la următoarea fără validare 4. **Urmărește progresul** în acest fișier - marchează task-urile completate cu ✅ ### Comenzi de Start ```bash # Asigură-te că SSH tunnel rulează (pentru Oracle) ./ssh_tunnel.sh start # Backend reports (pentru auth API - port 8001) cd reports-app/backend && uvicorn app.main:app --reload --port 8001 # Backend data-entry (port 8003) cd data-entry-app/backend && uvicorn app.main:app --reload --port 8003 # Frontend data-entry (port 3010) cd data-entry-app/frontend && npm run dev ``` ### Progres Implementare - [x] **FAZA 1**: Auth Backend - ✅ 6/6 task-uri COMPLETE - [x] **FAZA 2**: Auth Frontend - ✅ 6/6 task-uri COMPLETE - [x] **FAZA 3**: Nomenclatoare Sync - ✅ 6/6 task-uri COMPLETE - [x] **FAZA 4**: OCR + Supplier Search - ✅ 2/2 task-uri COMPLETE > **Status**: ✅ **IMPLEMENTARE COMPLETĂ** - 2025-12-13 --- ## Stare Curentă (IMPLEMENTAT) ### Backend Data-Entry ✅ - ✅ Models: Receipt, ReceiptAttachment, AccountingEntry - complete - ✅ CRUD operations - complete - ✅ API Routers: receipts.py, ocr.py, **nomenclature.py** - ✅ Services: receipt_service, ocr_service, **sync_service** - ✅ Workflow: DRAFT → PENDING → APPROVED/REJECTED - ✅ **Auth**: Integrare shared/auth (middleware + CurrentUser) - ✅ **Nomenclatoare**: SQLite sync (SyncedSupplier, LocalSupplier, SyncedCashRegister) - ✅ `sys.path.insert` pentru shared/ în main.py ### Frontend Data-Entry ✅ - ✅ Views: List, Create, Detail, Approval, **LoginView** - ✅ Components: OCR components + **Create Supplier Dialog** - ✅ Store: receiptsStore.js + **auth.js** - ✅ Router: routes + **auth guards + /login** - ✅ **Auth Store**: `src/stores/auth.js` - creat - ✅ **Login View**: `src/views/LoginView.vue` - creat - ✅ **Router Guards**: beforeEach cu requiresAuth - ✅ **API Service**: `src/services/api.js` - creat cu interceptors ### Shared Auth (disponibil pentru integrare) - ✅ `shared/auth/routes.py` - `create_auth_router()` (linia 39-430) - ✅ `shared/auth/middleware.py` - `AuthenticationMiddleware` - ✅ `shared/auth/dependencies.py` - `get_current_user` - ✅ `shared/auth/models.py` - `CurrentUser`, `TokenResponse` ### Referință Reports-App (pentru copiere) - `reports-app/frontend/src/stores/auth.js` - 119 linii - `reports-app/frontend/src/services/api.js` - 141 linii - `reports-app/frontend/src/views/LoginView.vue` - 367 linii - `reports-app/frontend/src/router/index.js` - auth guard la liniile 96-114 --- ## Faze Implementare ### FAZA 1: Auth Backend (6 task-uri) #### Task 1.1: Adaugă AuthenticationMiddleware în main.py **Fișier**: `data-entry-app/backend/app/main.py` **Acțiune**: După CORS middleware (linia 75), adaugă: ```python from auth.middleware import AuthenticationMiddleware app.add_middleware( AuthenticationMiddleware, excluded_paths=["/docs", "/redoc", "/openapi.json", "/health", "/", "/api/auth/login", "/api/auth/refresh"] ) ``` #### Task 1.2: Adaugă Auth Router în main.py **Fișier**: `data-entry-app/backend/app/main.py` **Acțiune**: După include_router pentru ocr (linia 98), adaugă: ```python from auth.routes import create_auth_router auth_router = create_auth_router() app.include_router(auth_router, prefix="/api/auth", tags=["auth"]) ``` #### Task 1.3: Înlocuiește get_current_user în receipts.py **Fișier**: `data-entry-app/backend/app/routers/receipts.py` **Acțiune**: Șterge liniile 38-59 și înlocuiește cu: ```python from auth.dependencies import get_current_user from auth.models import CurrentUser ``` Apoi actualizează type hints: `current_user: str` → `current_user: CurrentUser` Și accesează `current_user.username` în loc de `current_user` #### Task 1.4: Înlocuiește get_current_user în ocr.py **Fișier**: `data-entry-app/backend/app/routers/ocr.py` **Acțiune**: Similar cu receipts.py, adaugă importurile auth și folosește `CurrentUser` #### Task 1.5: Actualizează type hints în toate endpoint-urile Actualizează toate funcțiile care folosesc `current_user: str` să folosească `current_user: CurrentUser` #### Task 1.6: Testare backend auth ```bash cd data-entry-app/backend uvicorn app.main:app --reload --port 8003 # Test: curl http://localhost:8003/api/receipts/ → 401 Unauthorized ``` --- ### FAZA 2: Auth Frontend (6 task-uri) #### Task 2.1: Crează API service **Fișier NOU**: `data-entry-app/frontend/src/services/api.js` **Acțiune**: Copiază din `reports-app/frontend/src/services/api.js` cu modificări: - Schimbă BASE_URL pentru a funcționa cu proxy-ul - Modifică refresh token URL #### Task 2.2: Crează Auth Store **Fișier NOU**: `data-entry-app/frontend/src/stores/auth.js` **Acțiune**: Copiază din `reports-app/frontend/src/stores/auth.js` - Modifică import apiService din `../services/api` #### Task 2.3: Crează LoginView **Fișier NOU**: `data-entry-app/frontend/src/views/LoginView.vue` **Acțiune**: Copiază din `reports-app/frontend/src/views/LoginView.vue` - Schimbă titlul: "ROA Reports" → "Data Entry" - Schimbă subtitle: "Rapoarte ERP" → "Introducere Bonuri Fiscale" - Schimbă redirect după login: "/dashboard" → "/" #### Task 2.4: Actualizează Router cu auth guards **Fișier**: `data-entry-app/frontend/src/router/index.js` **Acțiune**: Adaugă auth guard similar cu reports-app (liniile 96-114) ```javascript import { useAuthStore } from '@/stores/auth' // Adaugă rută login // Adaugă meta: { requiresAuth: true } la rutele protejate // Adaugă beforeEach guard ``` #### Task 2.5: Actualizează vite.config.js pentru auth proxy **Fișier**: `data-entry-app/frontend/vite.config.js` **Acțiune**: Adaugă proxy pentru auth: ```javascript '/api/auth': { target: 'http://localhost:8001', changeOrigin: true, } ``` #### Task 2.6: Testare frontend auth ```bash cd data-entry-app/frontend npm run dev # Test: Accesează http://localhost:3010 → Redirect la /login # Login cu credențiale Oracle → Redirect la / ``` --- ### FAZA 3: Nomenclatoare Oracle→SQLite (6 task-uri) #### Task 3.1: Crează modele SQLModel **Fișier NOU**: `data-entry-app/backend/app/db/models/nomenclature.py` - `SyncedSupplier` - furnizori sincronizați din Oracle - `LocalSupplier` - furnizori creați local (din OCR) - `SyncedCashRegister` - case/bănci sincronizate #### Task 3.2: Crează Alembic migration ```bash cd data-entry-app/backend alembic revision --autogenerate -m "add nomenclature tables" alembic upgrade head ``` #### Task 3.3: Crează Sync Service **Fișier NOU**: `data-entry-app/backend/app/services/sync_service.py` - `sync_suppliers(company_id, schema)` - sync furnizori Oracle→SQLite - `sync_cash_registers(company_id, schema)` - sync case/bănci - `get_schema_for_company(company_id)` - lookup schema #### Task 3.4: Crează Nomenclature Router **Fișier NOU**: `data-entry-app/backend/app/routers/nomenclature.py` - `GET /suppliers/search` - căutare furnizor (SQLite + Oracle live) - `POST /suppliers/local` - creare furnizor local - `POST /sync/suppliers` - trigger manual sync #### Task 3.5: Înregistrează router în main.py ```python from app.routers import nomenclature app.include_router(nomenclature.router, prefix="/api/nomenclature", tags=["nomenclature"]) ``` #### Task 3.6: Actualizare nomenclature_service.py existent Înlocuiește mock data cu query-uri din tabelele SQLite sincronizate --- ### FAZA 4: Integrare OCR + Supplier Search (2 task-uri) #### Task 4.1: Actualizare ReceiptCreateView.vue **Fișier**: `data-entry-app/frontend/src/views/receipts/ReceiptCreateView.vue` **Acțiune**: După OCR result, caută automat furnizor după CUI: ```javascript async function handleOCRResult(ocrData) { if (ocrData.cui) { const result = await receiptsStore.searchSupplier(ocrData.cui); if (result.found) { form.partner_id = result.supplier.id; form.partner_name = result.supplier.name; } else { showCreateSupplierDialog(ocrData); } } } ``` #### Task 4.2: Adaugă supplier search în receiptsStore.js **Fișier**: `data-entry-app/frontend/src/stores/receiptsStore.js` **Acțiune**: Adaugă action `searchSupplier(fiscalCode)` și `createLocalSupplier(data)` --- ## Sumar Fișiere ### De Modificat | Fișier | Faza | |--------|------| | `data-entry-app/backend/app/main.py` | 1, 3 | | `data-entry-app/backend/app/routers/receipts.py` | 1 | | `data-entry-app/backend/app/routers/ocr.py` | 1 | | `data-entry-app/frontend/src/router/index.js` | 2 | | `data-entry-app/frontend/vite.config.js` | 2 | | `data-entry-app/frontend/src/views/receipts/ReceiptCreateView.vue` | 4 | | `data-entry-app/frontend/src/stores/receiptsStore.js` | 4 | ### De Creat (NOU) | Fișier | Faza | |--------|------| | `data-entry-app/frontend/src/services/api.js` | 2 | | `data-entry-app/frontend/src/stores/auth.js` | 2 | | `data-entry-app/frontend/src/views/LoginView.vue` | 2 | | `data-entry-app/backend/app/db/models/nomenclature.py` | 3 | | `data-entry-app/backend/app/services/sync_service.py` | 3 | | `data-entry-app/backend/app/routers/nomenclature.py` | 3 | | `migrations/versions/xxx_nomenclature.py` | 3 | --- ## Ordine Execuție **Faza 1 + 2 (Auth)** → **Faza 3 + 4 (Nomenclatoare)** Fazele 1-2 sunt blocante pentru funcționalitatea completă, dar Faza 3-4 poate fi amânată dacă e nevoie (nomenclatoarele rămân mock data temporar). --- ## Strategie Execuție cu Agenți ### Agenți Paraleli Recomandați **Round 1 - Auth (Backend + Frontend simultan):** ``` Agent A: Faza 1 - Task 1.1-1.5 (Backend auth) Agent B: Faza 2 - Task 2.1-2.3 (Frontend auth files) ``` După Round 1, testare manuală auth flow. **Round 2 - Finalizare Auth + Start Nomenclatoare:** ``` Agent A: Faza 2 - Task 2.4-2.5 (Router guards, vite config) Agent B: Faza 3 - Task 3.1-3.2 (Modele SQLModel + migration) ``` **Round 3 - Nomenclatoare + Integration:** ``` Agent A: Faza 3 - Task 3.3-3.6 (Sync service + router) Agent B: Faza 4 - Task 4.1-4.2 (Frontend OCR supplier) ``` ### Validare După Fiecare Fază **După Faza 1:** ```bash curl http://localhost:8003/api/receipts/ # Expected: 401 Unauthorized ``` **După Faza 2:** ```bash # Browser: http://localhost:3010 # Expected: Redirect to /login # Login cu credențiale Oracle → Redirect la / ``` **După Faza 3:** ```bash curl http://localhost:8003/api/nomenclature/suppliers/search?fiscal_code=RO12345678 # Expected: Search result sau sugestie creare local ``` **După Faza 4:** ``` # Browser: Crează bon nou → Upload poză → OCR # Expected: Furnizor găsit automat sau dialog creare ``` --- ## Context pentru Sesiune Următoare ### Fișiere Cheie de Citit 1. Acest plan: `/home/marius/.claude/plans/unified-orbiting-sonnet.md` 2. CLAUDE.md principal: `/mnt/e/proiecte/roa2web/CLAUDE.md` 3. CLAUDE.md data-entry: `/mnt/e/proiecte/roa2web/data-entry-app/CLAUDE.md` ### Comenzi Quick Start ```bash cd /mnt/e/proiecte/roa2web git status # Verifică branch feature/data-entry-receipts ./ssh_tunnel.sh start # SSH tunnel pentru Oracle ``` ### Dependențe Servicii - **reports-backend:8001** - NECESAR pentru auth API (login, refresh) - **data-entry-backend:8003** - Backend principal - **Oracle DB** - Via SSH tunnel, necesar pentru auth + nomenclatoare