feat: Add data-entry-app for fiscal receipts with approval workflow

New application for entering fiscal receipts (bonuri fiscale) with:

Backend (FastAPI + SQLModel + Alembic):
- Receipt, ReceiptAttachment, AccountingEntry models
- CRUD operations with async SQLite database
- Workflow: DRAFT → PENDING_REVIEW → APPROVED/REJECTED
- Auto-generation of accounting entries with VAT calculation
- File upload support (images, PDFs)
- Predefined expense types (Fuel, Materials, Office, etc.)
- Nomenclature service for partners, accounts, cash registers

Frontend (Vue.js 3 + PrimeVue + Pinia):
- ReceiptsListView with filters and stats
- ReceiptCreateView with image upload
- ReceiptDetailView with accounting entries
- ReceiptApprovalView for accountant approval

Documentation:
- REQUIREMENTS.md with functional specifications
- ARCHITECTURE.md with technical decisions
- CLAUDE.md for AI assistant guidance

Phase 1 MVP uses SQLite, prepared for Oracle integration in Phase 2.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-11 17:30:51 +02:00
parent 5823cedb94
commit 21c12ddb0f
45 changed files with 7524 additions and 0 deletions

View File

@@ -0,0 +1,275 @@
# Architecture: Data Entry App
## Overview
Aplicatie separata pentru introducere date in ERP, cu workflow de aprobare si staging area inainte de sincronizare in Oracle.
## Decizii Arhitecturale
### 1. SQLModel + Alembic
**Alegere**: SQLModel (Pydantic + SQLAlchemy) cu Alembic pentru migrari
**Motivatie**:
- Creat de autorul FastAPI - integrare perfecta
- Un model = Pydantic + SQLAlchemy - nu duplici definitii
- Async support nativ
- Alembic - standard industrial pentru migrari
- Validare automata - Pydantic valideaza input, SQLAlchemy gestioneaza DB
**Alternative considerate**:
- SQLAlchemy pur: Mai verbose, necesita scheme Pydantic separate
- Tortoise ORM: Async nativ dar comunitate mai mica
- Peewee: Simplu dar fara async
### 2. Separare de Reports-App
**Alegere**: Aplicatie separata in `data-entry-app/`
**Motivatie**:
- Responsabilitati diferite: reports = read-only, data-entry = write
- Lifecycle diferit: data-entry poate avea releases mai frecvente
- Risc izolat: bug in data-entry nu afecteaza raportarile
- Scalare independenta
**Shared Components**:
- `shared/database/oracle_pool.py` - conexiune Oracle pentru nomenclatoare
- `shared/auth/` - autentificare JWT comuna
### 3. Workflow cu Staging Area
**Alegere**: SQLite local ca staging, apoi sync in Oracle
**Motivatie**:
- Permite lucru offline (utilizator poate completa bonuri)
- Review de contabil inainte de date in Oracle
- Rollback simplu (stergem din SQLite)
- Audit trail complet
**Flow**:
```
User Input → SQLite (staging) → Contabil Review → Oracle (final)
```
### 4. Storage Fisiere
**Alegere**: Filesystem local cu referinte in DB
**Motivatie**:
- Simplu de implementat si backup
- Performanta buna pentru imagini
- Poate migra la S3/Azure Blob daca e nevoie
**Structura**:
```
data/uploads/
{year}/
{month}/
{uuid}.{ext}
```
## Diagrama Componente
```
┌─────────────────────────────────────────────────────────────────┐
│ data-entry-app │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │────▶│ Backend │────▶│ SQLite │ │
│ │ Vue.js │ │ FastAPI │ │ (staging) │ │
│ │ :3010 │ │ :8003 │ │ │ │
│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
│ │ │
│ │ Nomenclatoare │
│ ▼ │
│ ┌──────────────┐ │
│ │ Oracle │ │
│ │ (read-only) │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
## Model de Date
### Receipt (Bon Fiscal)
```
receipts
├── id (PK)
├── receipt_type: enum(bon_fiscal, chitanta)
├── direction: enum(cheltuiala, incasare)
├── receipt_number, receipt_series
├── receipt_date, amount, description
├── company_id, partner_id, partner_name
├── cash_register_id, cash_register_name
├── expense_type_code
├── status: enum(draft, pending_review, approved, rejected, synced)
├── created_by, created_at, updated_at
├── submitted_at, reviewed_by, reviewed_at
├── rejection_reason
└── oracle_synced_at, oracle_act_id, oracle_error
```
### ReceiptAttachment (Atasamente)
```
receipt_attachments
├── id (PK)
├── receipt_id (FK)
├── filename, stored_filename
├── file_path, file_size, mime_type
└── uploaded_at
```
### AccountingEntry (Note Contabile)
```
accounting_entries
├── id (PK)
├── receipt_id (FK)
├── entry_type: enum(debit, credit)
├── account_code, account_name
├── amount
├── partner_id, cost_center_id
├── is_auto_generated
└── modified_by, modified_at
```
## Workflow States
```
┌─────────┐
│ DRAFT │◀────────────────────┐
└────┬────┘ │
│ submit() │ (edit after reject)
▼ │
┌──────────────┐ │
│PENDING_REVIEW│──────────────────┤
└──────┬───────┘ │
│ │
┌─────┴─────┐ │
▼ ▼ │
┌────────┐ ┌────────┐ │
│APPROVED│ │REJECTED│──────────────┘
└────┬───┘ └────────┘ resubmit()
│ (Faza 2)
┌──────┐
│SYNCED│
└──────┘
```
## Generare Note Contabile
### Algoritm
```python
def generate_entries(receipt):
expense_type = EXPENSE_TYPES[receipt.expense_type_code]
entries = []
if expense_type.has_vat:
net_amount = receipt.amount / Decimal('1.19')
vat_amount = receipt.amount - net_amount
# Cheltuiala (debit)
entries.append(Entry(DEBIT, expense_type.account, net_amount))
# TVA (debit)
entries.append(Entry(DEBIT, "4426", vat_amount))
else:
entries.append(Entry(DEBIT, expense_type.account, receipt.amount))
# Credit casa/banca
entries.append(Entry(CREDIT, receipt.cash_register_account, receipt.amount))
return entries
```
### Exemplu: Bon Benzina 200 RON
```
Debit 6022 Cheltuieli combustibil 168.07
Debit 4426 TVA deductibila 31.93
Credit 5311 Casa in lei 200.00
```
## Integrare Oracle (Faza 2)
### Proceduri Stocate
```sql
-- 1. Initializare
pack_contafin.init_scriere_act_rul_local()
-- 2. Insert linii
INSERT INTO ACT_TEMP (
ID_ACT, DATAIREG, DATAACT, SCD, ASCD, SCC, ASCC,
SUMA, ID_CTR, ID_PARTD, EXPLICATIA, ...
)
-- 3. Finalizare
pack_contafin.finalizeaza_scriere_act_rul()
SCRIE_IN_ACT()
SCRIE_IN_RUL()
Actualizare situatii (BV, BP, TVA)
```
## Securitate
### Autentificare
- JWT tokens din shared auth
- Middleware valideaza token si injecteaza user
### Autorizare
- Permisiuni verificate in services
- Utilizator poate edita doar bonurile proprii in DRAFT
- Doar contabil poate aproba/respinge
### Upload Fisiere
- Validare MIME type (whitelist)
- Sanitizare nume fisier
- Limita dimensiune (10MB)
- Stocare cu UUID (previne path traversal)
## Configuratie
### Environment Variables
```bash
# SQLite Database
SQLITE_DATABASE_PATH=data/receipts.db
# File Storage
UPLOAD_PATH=data/uploads
MAX_UPLOAD_SIZE=10485760 # 10MB
# Oracle (pentru nomenclatoare)
ORACLE_USER=CONTAFIN_ORACLE
ORACLE_PASSWORD=***
ORACLE_HOST=localhost
ORACLE_PORT=1526
ORACLE_SID=ROA
# JWT (shared)
JWT_SECRET_KEY=***
JWT_ALGORITHM=HS256
```
## Testing Strategy
### Unit Tests
- CRUD operations
- Workflow transitions
- Entry generation logic
### Integration Tests
- API endpoints
- File upload/download
- Oracle nomenclature fetch
### E2E Tests
- Complete workflow: create → submit → approve
- File upload cu preview

View File

@@ -0,0 +1,155 @@
# Requirements: Data Entry - Bonuri Fiscale (Faza 1)
## Obiectiv
Sistem de introducere bonuri fiscale cu:
- **Upload poze** bonuri de la utilizatori
- **Generare automata** note contabile (staging area)
- **Aprobare de contabil** inainte de finalizare
- SQLite + ORM (SQLModel) + Migrari (Alembic)
- Pregatit pentru integrare Oracle in Faza 2
## Cerinte Functionale
### 1. Gestiune Bonuri Fiscale
#### 1.1 Creare Bon
- Utilizatorul poate uploada o poza a bonului fiscal
- Campuri obligatorii: tip document, directie, data, suma, furnizor, casa/banca
- Campuri optionale: numar bon, serie, descriere
- Tipuri document: Bon Fiscal, Chitanta
- Directii: Cheltuiala (plata), Incasare
#### 1.2 Upload Atasamente
- Suport pentru imagini (JPEG, PNG) si PDF
- Limita dimensiune: 10MB per fisier
- Multiple atasamente per bon
- Previzualizare imagine in UI
#### 1.3 Workflow Aprobare
```
DRAFT → PENDING_REVIEW → APPROVED/REJECTED → (Faza 2: SYNCED)
```
- **DRAFT**: Utilizator completeaza datele
- **PENDING_REVIEW**: Trimis spre aprobare, sistem genereaza note contabile
- **APPROVED**: Contabil a aprobat
- **REJECTED**: Contabil a respins (cu motiv)
- **SYNCED**: (Faza 2) Sincronizat in Oracle
### 2. Note Contabile
#### 2.1 Generare Automata
- La trimiterea spre aprobare, sistemul genereaza propuneri note contabile
- Logica bazata pe tip cheltuiala selectat
- Include calcul TVA automat (19%)
#### 2.2 Editare de Contabil
- Contabilul poate modifica conturile propuse
- Poate adauga/sterge linii
- Modificarile sunt logate
#### 2.3 Tipuri Cheltuieli Predefinite
| Tip Cheltuiala | Cont Debit | TVA | Descriere |
|----------------|------------|-----|-----------|
| Combustibil | 6022 | 4426 (19%) | Benzina, motorina |
| Materiale consumabile | 6028 | 4426 (19%) | Diverse materiale |
| Rechizite birou | 6024 | 4426 (19%) | Papetarie, toner |
| Telefonie | 626 | 4426 (19%) | Telefon, internet |
| Parcare | 6022 | 4426 (19%) | Taxe parcare |
| Alimentatie | 6028 | - | Fara TVA deductibila |
| Transport | 624 | 4426 (19%) | Taxi, transport |
| Altele | 628 | 4426 (19%) | Alte cheltuieli |
### 3. Roluri si Permisiuni
#### 3.1 Utilizator Standard
- Creare bonuri noi (DRAFT)
- Editare bonuri proprii in DRAFT
- Trimitere spre aprobare
- Vizualizare status bonuri proprii
#### 3.2 Contabil (Rol Aprobare)
- Toate permisiunile utilizator
- Vizualizare toate bonurile in asteptare
- Aprobare/Respingere bonuri
- Editare note contabile propuse
- Aprobare in masa
### 4. Nomenclatoare
Preluate din Oracle (read-only):
- **Parteneri**: Furnizori si clienti
- **Conturi**: Plan conturi sintetice
- **Case/Banci**: Registre casa si conturi bancare
- **Firme**: Lista firme disponibile
## Cerinte Non-Functionale
### Performance
- Timp raspuns API < 200ms (fara upload)
- Upload fisiere < 5s pentru 10MB
- Paginare pentru liste > 50 elemente
### Securitate
- Autentificare JWT (shared cu reports-app)
- Validare MIME type pentru fisiere
- Sanitizare nume fisiere
- Acces bazat pe rol
### Scalabilitate
- Arhitectura pregatita pentru Oracle (Faza 2)
- Separare clara intre storage local si DB
- API design RESTful consistent
## API Endpoints
### Bonuri
```
POST /api/receipts/ # Creare bon
GET /api/receipts/ # Lista bonuri
GET /api/receipts/{id} # Detalii bon
PUT /api/receipts/{id} # Modificare bon (DRAFT)
DELETE /api/receipts/{id} # Stergere bon (DRAFT)
```
### Workflow
```
POST /api/receipts/{id}/submit # DRAFT → PENDING
POST /api/receipts/{id}/approve # PENDING → APPROVED
POST /api/receipts/{id}/reject # PENDING → REJECTED
POST /api/receipts/{id}/resubmit # REJECTED → PENDING
```
### Note Contabile
```
GET /api/receipts/{id}/entries # Lista note
PUT /api/receipts/{id}/entries # Modificare note
POST /api/receipts/{id}/entries/regenerate # Re-generare
```
### Atasamente
```
POST /api/receipts/{id}/attachments # Upload
GET /api/receipts/{id}/attachments # Lista
GET /api/attachments/{id}/download # Download
DELETE /api/attachments/{id} # Stergere
```
### Nomenclatoare
```
GET /api/receipts/partners # Furnizori/Clienti
GET /api/receipts/accounts # Conturi
GET /api/receipts/cash-registers # Case/Banci
GET /api/receipts/expense-types # Tipuri cheltuieli
```
## Criterii de Succes (Faza 1)
- [ ] Utilizator poate uploada poza bon + date de baza
- [ ] Sistem genereaza automat note contabile
- [ ] Contabil poate vedea, edita si aproba note
- [ ] Bonurile aprobate sunt vizibile in lista
- [ ] Migrarile Alembic functioneaza corect
- [ ] Poze bonuri se salveaza si se afiseaza corect