668 lines
26 KiB
Markdown
668 lines
26 KiB
Markdown
# Plan: Introducere Bonuri Fiscale - Faza 1 (MVP SQLite)
|
|
|
|
> **Plan Handover** - Acest document conține planul complet pentru implementare.
|
|
> Creat: 2025-12-11 | Status: Ready for implementation
|
|
|
|
## Obiectiv
|
|
Sistem de introducere bonuri fiscale cu:
|
|
- **Upload poze** bonuri de la utilizatori
|
|
- **Generare automată** note contabile (staging area)
|
|
- **Aprobare de contabil** înainte de finalizare
|
|
- SQLite + ORM (SQLModel) + Migrări (Alembic)
|
|
- Pregătit pentru integrare Oracle în Faza 2
|
|
|
|
---
|
|
|
|
## Setup Proiect
|
|
|
|
### Branch de dezvoltare
|
|
```bash
|
|
git checkout -b feature/data-entry-receipts
|
|
```
|
|
|
|
### Structură Directoare (SEPARAT de reports-app)
|
|
```
|
|
.
|
|
├── reports-app/ # EXISTENT - Raportări (read-only din Oracle)
|
|
│ ├── backend/
|
|
│ ├── frontend/
|
|
│ └── telegram-bot/
|
|
│
|
|
├── data-entry-app/ # NOU - Introduceri date (write în SQLite → Oracle)
|
|
│ ├── backend/ # FastAPI pentru introduceri
|
|
│ ├── frontend/ # Vue.js pentru introduceri
|
|
│ └── docs/ # Documentație și cerințe
|
|
│
|
|
├── shared/ # EXISTENT - Componente partajate
|
|
│ ├── database/
|
|
│ └── auth/
|
|
│
|
|
└── docs/ # Documentație generală proiect
|
|
└── data-entry/ # Documentație specifică data-entry
|
|
├── REQUIREMENTS.md # Cerințe inițiale (acest plan)
|
|
└── ARCHITECTURE.md # Decizii arhitecturale
|
|
```
|
|
|
|
### Documentație Salvată
|
|
La finalizarea planului, se vor crea:
|
|
1. `docs/data-entry/REQUIREMENTS.md` - Cerințe funcționale și tehnice
|
|
2. `docs/data-entry/ARCHITECTURE.md` - Decizii arhitecturale (ORM, workflow)
|
|
3. `data-entry-app/README.md` - Quick start pentru dezvoltare
|
|
|
|
---
|
|
|
|
## Workflow Principal
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 1. UTILIZATOR uploadează bon │
|
|
│ ├─ Poză bon fiscal / chitanță │
|
|
│ ├─ Date de bază: sumă, dată, furnizor │
|
|
│ └─ Status: DRAFT │
|
|
└──────────────────────┬──────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 2. SISTEM generează propunere note contabile │
|
|
│ ├─ Debit: Cont cheltuială (6022, 6024, etc.) │
|
|
│ ├─ Credit: Casă (5311) sau Bancă (5121) │
|
|
│ └─ Status: PENDING_REVIEW │
|
|
└──────────────────────┬──────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 3. CONTABIL revizuiește │
|
|
│ ├─ Verifică poza + datele │
|
|
│ ├─ Ajustează conturi dacă e nevoie │
|
|
│ ├─ APROBĂ → Status: APPROVED │
|
|
│ └─ RESPINGE → Status: REJECTED (cu motiv) │
|
|
└──────────────────────┬──────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 4. FAZA 2: Sync în Oracle │
|
|
│ ├─ INSERT ACT_TEMP │
|
|
│ ├─ pack_contafin.finalizeaza_scriere_act_rul() │
|
|
│ └─ Status: SYNCED │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Decizie Tehnică: ORM + Migrări
|
|
|
|
### Recomandare: **SQLModel + Alembic**
|
|
|
|
**Motivație:**
|
|
1. **Creat de autorul FastAPI** (Sebastian Ramirez) - integrare perfectă
|
|
2. **Un model = Pydantic + SQLAlchemy** - nu duplici definiții
|
|
3. **Async support** nativ
|
|
4. **Alembic** - standard industrial pentru migrări
|
|
5. **Validare automată** - Pydantic validează input, SQLAlchemy gestionează DB
|
|
|
|
---
|
|
|
|
## Arhitectură Propusă
|
|
|
|
### Backend Structure (`data-entry-app/backend/`)
|
|
```
|
|
data-entry-app/backend/
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── main.py # FastAPI app entry point
|
|
│ ├── config.py # Settings & env vars
|
|
│ │
|
|
│ ├── db/ # Database layer (SQLModel)
|
|
│ │ ├── __init__.py
|
|
│ │ ├── database.py # Engine, SessionLocal, init
|
|
│ │ ├── models/
|
|
│ │ │ ├── __init__.py
|
|
│ │ │ ├── receipt.py # Receipt, ReceiptAttachment
|
|
│ │ │ └── accounting_entry.py # AccountingEntry
|
|
│ │ └── crud/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── receipt.py
|
|
│ │ ├── attachment.py
|
|
│ │ └── accounting_entry.py
|
|
│ │
|
|
│ ├── schemas/
|
|
│ │ └── receipt.py # Request/Response Pydantic schemas
|
|
│ │
|
|
│ ├── services/
|
|
│ │ ├── receipt_service.py # Business logic + workflow
|
|
│ │ └── nomenclature_service.py # Nomenclatoare din Oracle
|
|
│ │
|
|
│ └── routers/
|
|
│ └── receipts.py # API endpoints
|
|
│
|
|
├── migrations/ # Alembic migrations
|
|
│ ├── env.py
|
|
│ ├── alembic.ini
|
|
│ └── versions/
|
|
│ └── 001_initial_receipts.py
|
|
│
|
|
├── data/
|
|
│ ├── receipts.db # SQLite database
|
|
│ └── uploads/ # Poze bonuri
|
|
│
|
|
├── requirements.txt
|
|
└── README.md
|
|
```
|
|
|
|
### Frontend Structure (`data-entry-app/frontend/`)
|
|
```
|
|
data-entry-app/frontend/
|
|
├── src/
|
|
│ ├── views/receipts/
|
|
│ │ ├── ReceiptsListView.vue
|
|
│ │ ├── ReceiptCreateView.vue
|
|
│ │ ├── ReceiptDetailView.vue
|
|
│ │ └── ReceiptApprovalView.vue
|
|
│ │
|
|
│ ├── components/receipts/
|
|
│ │ ├── ReceiptForm.vue
|
|
│ │ ├── ReceiptImageUpload.vue
|
|
│ │ └── AccountingEntriesTable.vue
|
|
│ │
|
|
│ ├── stores/
|
|
│ │ └── receiptsStore.js
|
|
│ │
|
|
│ └── router/
|
|
│ └── index.js
|
|
│
|
|
├── package.json
|
|
└── vite.config.js
|
|
```
|
|
|
|
---
|
|
|
|
## Modele de Date
|
|
|
|
### 1. Receipt (Bon Fiscal / Chitanță)
|
|
|
|
```python
|
|
# app/db/models/receipt.py
|
|
from sqlmodel import SQLModel, Field, Relationship
|
|
from datetime import datetime, date
|
|
from decimal import Decimal
|
|
from enum import Enum
|
|
from typing import Optional, List
|
|
|
|
class ReceiptType(str, Enum):
|
|
BON_FISCAL = "bon_fiscal"
|
|
CHITANTA = "chitanta"
|
|
|
|
class ReceiptDirection(str, Enum):
|
|
CHELTUIALA = "cheltuiala" # Plată (bon primit de la furnizor)
|
|
INCASARE = "incasare" # Încasare (bon emis către client)
|
|
|
|
class ReceiptStatus(str, Enum):
|
|
DRAFT = "draft" # Utilizator completează
|
|
PENDING_REVIEW = "pending_review" # Așteaptă aprobare contabil
|
|
APPROVED = "approved" # Aprobat de contabil
|
|
REJECTED = "rejected" # Respins de contabil
|
|
SYNCED = "synced" # Sincronizat în Oracle (Faza 2)
|
|
|
|
class Receipt(SQLModel, table=True):
|
|
"""Bon fiscal sau chitanță cu workflow aprobare"""
|
|
__tablename__ = "receipts"
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
|
|
# Identificare document
|
|
receipt_type: ReceiptType
|
|
direction: ReceiptDirection
|
|
receipt_number: Optional[str] = None
|
|
receipt_series: Optional[str] = None
|
|
|
|
# Date principale
|
|
receipt_date: date
|
|
amount: Decimal
|
|
description: Optional[str] = None
|
|
|
|
# Referințe Oracle (nomenclatoare)
|
|
company_id: int
|
|
partner_id: Optional[int] = None
|
|
partner_name: Optional[str] = None # Cache pentru display
|
|
cash_register_id: Optional[int] = None # ID casă/bancă Oracle
|
|
cash_register_name: Optional[str] = None # Cache pentru display
|
|
|
|
# Workflow
|
|
status: ReceiptStatus = Field(default=ReceiptStatus.DRAFT)
|
|
created_by: str # Username creator
|
|
created_at: datetime = Field(default_factory=datetime.utcnow)
|
|
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
|
submitted_at: Optional[datetime] = None # Când a fost trimis spre aprobare
|
|
|
|
# Aprobare
|
|
reviewed_by: Optional[str] = None # Username contabil
|
|
reviewed_at: Optional[datetime] = None
|
|
rejection_reason: Optional[str] = None # Motiv respingere
|
|
|
|
# Faza 2 - Oracle sync
|
|
oracle_synced_at: Optional[datetime] = None
|
|
oracle_act_id: Optional[int] = None
|
|
oracle_error: Optional[str] = None
|
|
|
|
# Relații
|
|
attachments: List["ReceiptAttachment"] = Relationship(back_populates="receipt")
|
|
entries: List["AccountingEntry"] = Relationship(back_populates="receipt")
|
|
```
|
|
|
|
### 2. ReceiptAttachment (Poze bonuri - OBLIGATORIU)
|
|
|
|
```python
|
|
class ReceiptAttachment(SQLModel, table=True):
|
|
"""Poză sau PDF bon fiscal"""
|
|
__tablename__ = "receipt_attachments"
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
receipt_id: int = Field(foreign_key="receipts.id")
|
|
|
|
filename: str # Nume original fișier
|
|
stored_filename: str # Nume pe disk (UUID)
|
|
file_path: str # Cale relativă
|
|
file_size: int # Bytes
|
|
mime_type: str # image/jpeg, application/pdf
|
|
uploaded_at: datetime = Field(default_factory=datetime.utcnow)
|
|
|
|
receipt: Optional["Receipt"] = Relationship(back_populates="attachments")
|
|
```
|
|
|
|
### 3. AccountingEntry (Note Contabile - Staging)
|
|
|
|
```python
|
|
class EntryType(str, Enum):
|
|
DEBIT = "debit"
|
|
CREDIT = "credit"
|
|
|
|
class AccountingEntry(SQLModel, table=True):
|
|
"""Notă contabilă propusă pentru bon"""
|
|
__tablename__ = "accounting_entries"
|
|
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
receipt_id: int = Field(foreign_key="receipts.id")
|
|
|
|
# Cont
|
|
entry_type: EntryType # Debit sau Credit
|
|
account_code: str # Ex: 6022, 5311, 4426
|
|
account_name: Optional[str] # Cache: "Cheltuieli combustibil"
|
|
|
|
# Valori
|
|
amount: Decimal
|
|
|
|
# Analitice (opțional)
|
|
partner_id: Optional[int] = None
|
|
cost_center_id: Optional[int] = None
|
|
|
|
# Auto-generat sau modificat manual
|
|
is_auto_generated: bool = True
|
|
modified_by: Optional[str] = None
|
|
modified_at: Optional[datetime] = None
|
|
|
|
receipt: Optional["Receipt"] = Relationship(back_populates="entries")
|
|
```
|
|
|
|
### Exemplu Note Contabile Generate
|
|
|
|
```
|
|
BON FISCAL BENZINĂ - 200 RON:
|
|
┌──────────┬────────┬──────────────────────────┬─────────┐
|
|
│ Tip │ Cont │ Denumire │ Sumă │
|
|
├──────────┼────────┼──────────────────────────┼─────────┤
|
|
│ DEBIT │ 6022 │ Cheltuieli combustibil │ 168.07 │
|
|
│ DEBIT │ 4426 │ TVA deductibilă │ 31.93 │
|
|
│ CREDIT │ 5311 │ Casă în lei │ 200.00 │
|
|
└──────────┴────────┴──────────────────────────┴─────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
### Bonuri (CRUD + Workflow)
|
|
```
|
|
POST /api/receipts/ # Creare bon nou (cu upload poză)
|
|
GET /api/receipts/ # Listă bonuri (filtrare, paginare)
|
|
GET /api/receipts/{id} # Detalii bon + note contabile
|
|
PUT /api/receipts/{id} # Modificare bon (doar DRAFT)
|
|
DELETE /api/receipts/{id} # Ștergere bon (doar DRAFT)
|
|
|
|
# Workflow
|
|
POST /api/receipts/{id}/submit # Trimite spre aprobare (DRAFT → PENDING)
|
|
POST /api/receipts/{id}/approve # Aprobă (PENDING → APPROVED) [Contabil]
|
|
POST /api/receipts/{id}/reject # Respinge (PENDING → REJECTED) [Contabil]
|
|
POST /api/receipts/{id}/resubmit # Re-trimite după corecții (REJECTED → PENDING)
|
|
```
|
|
|
|
### Note Contabile
|
|
```
|
|
GET /api/receipts/{id}/entries # Liste note contabile propuse
|
|
PUT /api/receipts/{id}/entries # Modificare note (contabil ajustează conturi)
|
|
POST /api/receipts/{id}/entries/regenerate # Re-generare automată
|
|
```
|
|
|
|
### Atașamente
|
|
```
|
|
POST /api/receipts/{id}/attachments # Upload poză/PDF
|
|
GET /api/receipts/{id}/attachments # Listă atașamente
|
|
GET /api/attachments/{id}/download # Download fișier
|
|
DELETE /api/attachments/{id} # Ștergere atașament
|
|
```
|
|
|
|
### Nomenclatoare (din Oracle - read only)
|
|
```
|
|
GET /api/receipts/partners # Furnizori/Clienți pentru dropdown
|
|
GET /api/receipts/accounts # Conturi sintetice (6xxx, 7xxx, etc.)
|
|
GET /api/receipts/cash-registers # Case și bănci
|
|
GET /api/receipts/expense-types # Tipuri cheltuieli predefinite (cu cont asociat)
|
|
```
|
|
|
|
---
|
|
|
|
## Frontend Views
|
|
|
|
```
|
|
frontend/src/views/receipts/
|
|
├── ReceiptsListView.vue # Listă bonuri cu filtrare pe status
|
|
├── ReceiptCreateView.vue # Form creare + upload poză
|
|
├── ReceiptDetailView.vue # Vizualizare + editare note contabile
|
|
└── ReceiptApprovalView.vue # View pentru contabil (aprobare în masă)
|
|
```
|
|
|
|
### ReceiptCreateView - Form utilizator
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ UPLOAD POZĂ BON [Drag & Drop sau Click] │
|
|
│ ┌────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ [Previzualizare imagine] │ │
|
|
│ │ │ │
|
|
│ └────────────────────────────────────────────┘ │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ Tip document: ○ Bon fiscal ○ Chitanță │
|
|
│ Direcție: ○ Cheltuială ○ Încasare │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ Data: [DatePicker] │
|
|
│ Suma: [InputNumber] RON │
|
|
│ Furnizor: [Dropdown - din Oracle] │
|
|
│ Tip cheltuială:[Dropdown - Benzină, Materiale...] │
|
|
│ Casă/Bancă: [Dropdown - din Oracle] │
|
|
│ Descriere: [Textarea] │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ [Salvează Draft] [Trimite spre aprobare]│
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### ReceiptApprovalView - View Contabil
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ BONURI DE APROBAT (3) [Aprobă selectate] │
|
|
├────────────────────────────────────────────────────────────────┤
|
|
│ ☑ │ Data │ Furnizor │ Sumă │ Status │ Acțiuni │
|
|
├───┼──────────┼───────────────┼─────────┼─────────┼───────────┤
|
|
│ ☑ │ 10.12.24 │ OMV Petrom │ 200 RON │ PENDING │ [👁️][✓][✗]│
|
|
│ ☑ │ 09.12.24 │ Dedeman │ 450 RON │ PENDING │ [👁️][✓][✗]│
|
|
│ ☐ │ 08.12.24 │ Kaufland │ 85 RON │ PENDING │ [👁️][✓][✗]│
|
|
└────────────────────────────────────────────────────────────────┘
|
|
|
|
[👁️] = Deschide detalii + poză + note contabile editabile
|
|
[✓] = Aprobă
|
|
[✗] = Respinge (cu motiv)
|
|
```
|
|
|
|
---
|
|
|
|
## Pași Implementare
|
|
|
|
### Etapa 0: Setup Proiect și Documentație
|
|
1. [ ] Creare branch: `git checkout -b feature/data-entry-receipts`
|
|
2. [ ] Creare structură directoare: `data-entry-app/{backend,frontend,docs}`
|
|
3. [ ] Creare documentație:
|
|
- `docs/data-entry/REQUIREMENTS.md` - Cerințe funcționale
|
|
- `docs/data-entry/ARCHITECTURE.md` - Decizii tehnice (ORM, workflow)
|
|
4. [ ] Creare `data-entry-app/README.md` - Quick start
|
|
5. [ ] Creare `data-entry-app/CLAUDE.md` - Instrucțiuni pentru Claude Code
|
|
|
|
### Etapa 1: Setup Backend (SQLModel + Alembic)
|
|
6. [ ] Creare `data-entry-app/backend/requirements.txt`:
|
|
- `fastapi`, `uvicorn`, `sqlmodel`, `alembic`, `python-multipart`
|
|
- `aiosqlite`, `pydantic`, `python-dotenv`
|
|
7. [ ] Creare `app/main.py` - FastAPI app cu CORS, lifespan
|
|
8. [ ] Creare `app/config.py` - Settings (DB path, upload path)
|
|
9. [ ] Creare `app/db/database.py` - engine async, session factory
|
|
10. [ ] Setup Alembic: `alembic init migrations`
|
|
|
|
### Etapa 2: Modele și Migrări
|
|
11. [ ] Creare `app/db/models/receipt.py` - Receipt, ReceiptAttachment
|
|
12. [ ] Creare `app/db/models/accounting_entry.py` - AccountingEntry
|
|
13. [ ] Prima migrare: `001_initial_receipts.py`
|
|
14. [ ] Creare folder `data/uploads/` pentru fișiere
|
|
|
|
### Etapa 3: Backend CRUD + Upload
|
|
15. [ ] Creare `app/db/crud/receipt.py` - operații CRUD
|
|
16. [ ] Creare `app/db/crud/attachment.py` - upload/download fișiere
|
|
17. [ ] Creare `app/db/crud/accounting_entry.py` - note contabile
|
|
18. [ ] Creare `app/schemas/receipt.py` - request/response Pydantic
|
|
|
|
### Etapa 4: Business Logic + Workflow
|
|
19. [ ] Creare `app/services/receipt_service.py`:
|
|
- `create_receipt()` - creare + upload poză
|
|
- `generate_accounting_entries()` - generare automată note
|
|
- `submit_for_review()` - DRAFT → PENDING
|
|
- `approve_receipt()` - PENDING → APPROVED
|
|
- `reject_receipt()` - PENDING → REJECTED
|
|
|
|
### Etapa 5: API Endpoints
|
|
20. [ ] Creare `app/routers/receipts.py` - toate endpoint-urile
|
|
21. [ ] Register router în `main.py`
|
|
22. [ ] Middleware pentru upload fișiere
|
|
|
|
### Etapa 6: Nomenclatoare Oracle
|
|
23. [ ] Creare `app/services/nomenclature_service.py`:
|
|
- `get_partners()` - furnizori/clienți din Oracle
|
|
- `get_expense_accounts()` - conturi 6xxx
|
|
- `get_cash_registers()` - case/bănci
|
|
- `get_expense_types()` - tipuri cheltuieli predefinite
|
|
|
|
### Etapa 7: Frontend Setup
|
|
24. [ ] `npm create vite@latest frontend -- --template vue`
|
|
25. [ ] Instalare dependențe: `pinia`, `vue-router`, `primevue`, `axios`
|
|
26. [ ] Copy configurație PrimeVue din reports-app
|
|
27. [ ] Copy CSS shared din reports-app (design tokens, patterns)
|
|
|
|
### Etapa 8: Frontend Views
|
|
28. [ ] Creare `views/receipts/ReceiptsListView.vue` - listă cu filtre
|
|
29. [ ] Creare `views/receipts/ReceiptCreateView.vue` - form + upload
|
|
30. [ ] Creare `views/receipts/ReceiptDetailView.vue` - detalii + note
|
|
31. [ ] Creare `views/receipts/ReceiptApprovalView.vue` - view contabil
|
|
32. [ ] Creare `stores/receiptsStore.js` - Pinia store
|
|
33. [ ] Configurare router și layout
|
|
|
|
### Etapa 9: Testing & Finalizare
|
|
34. [ ] Unit tests pentru CRUD
|
|
35. [ ] Integration tests pentru API
|
|
36. [ ] Manual testing checklist
|
|
37. [ ] Actualizare documentație
|
|
38. [ ] Commit și push pe branch
|
|
39. [ ] Creare PR către main
|
|
|
|
---
|
|
|
|
## Fișiere de Creat
|
|
|
|
### Documentație (Etapa 0):
|
|
```
|
|
docs/data-entry/
|
|
├── REQUIREMENTS.md # Cerințe funcționale (din acest plan)
|
|
└── ARCHITECTURE.md # Decizii tehnice (ORM, workflow)
|
|
|
|
data-entry-app/
|
|
├── CLAUDE.md # Instrucțiuni pentru Claude Code
|
|
└── README.md # Quick start pentru dezvoltare
|
|
```
|
|
|
|
### Conținut `data-entry-app/CLAUDE.md`:
|
|
```markdown
|
|
# CLAUDE.md - Data Entry App
|
|
|
|
## Scop
|
|
Aplicație pentru introducere date în ERP (bonuri fiscale, chitanțe) cu workflow de aprobare.
|
|
|
|
## Documentație de Referință
|
|
- **Cerințe**: `docs/data-entry/REQUIREMENTS.md`
|
|
- **Arhitectură**: `docs/data-entry/ARCHITECTURE.md`
|
|
- **Quick Start**: `README.md`
|
|
|
|
## Decizii Tehnice
|
|
- **ORM**: SQLModel (Pydantic + SQLAlchemy)
|
|
- **Migrări**: Alembic
|
|
- **Database**: SQLite (Faza 1) → Oracle (Faza 2)
|
|
- **Frontend**: Vue.js 3 + PrimeVue (consistent cu reports-app)
|
|
|
|
## Workflow Bonuri
|
|
1. DRAFT → utilizator completează + upload poză
|
|
2. PENDING_REVIEW → sistem generează note contabile
|
|
3. APPROVED/REJECTED → contabil aprobă sau respinge
|
|
4. SYNCED → (Faza 2) date în Oracle
|
|
|
|
## Structură Directoare
|
|
- `backend/` - FastAPI API (port 8003)
|
|
- `frontend/` - Vue.js UI (port 3010)
|
|
- `docs/` - Documentație specifică
|
|
|
|
## Componente Partajate
|
|
- `shared/database/oracle_pool.py` - Conexiune Oracle
|
|
- `shared/auth/` - JWT authentication
|
|
|
|
## Comenzi Dezvoltare
|
|
```bash
|
|
# Backend
|
|
cd backend && pip install -r requirements.txt
|
|
uvicorn app.main:app --reload --port 8003
|
|
|
|
# Frontend
|
|
cd frontend && npm install && npm run dev
|
|
|
|
# Migrări
|
|
cd backend && alembic upgrade head
|
|
```
|
|
|
|
## Integrare Oracle (Faza 2)
|
|
Vezi `docs/PACK_CONTAFIN.pck` pentru procedurile stocate:
|
|
- `pack_contafin.init_scriere_act_rul_local()`
|
|
- `INSERT INTO ACT_TEMP (...)`
|
|
- `pack_contafin.finalizeaza_scriere_act_rul()`
|
|
```
|
|
|
|
---
|
|
|
|
## Tipuri Cheltuieli Predefinite
|
|
|
|
Pentru dropdown "Tip cheltuială" - mapare automată la conturi:
|
|
|
|
| Tip Cheltuială | Cont Debit | TVA | Descriere |
|
|
|----------------|------------|-----|-----------|
|
|
| Combustibil | 6022 | 4426 (19%) | Benzină, motorină |
|
|
| Materiale consumabile | 6028 | 4426 (19%) | Diverse materiale |
|
|
| Rechizite birou | 6024 | 4426 (19%) | Papetărie, toner |
|
|
| Telefonie | 626 | 4426 (19%) | Telefon, internet |
|
|
| Parcare | 6022 | 4426 (19%) | Taxe parcare |
|
|
| Alimentație | 6028 | - | Fără TVA deductibilă |
|
|
| Transport | 624 | 4426 (19%) | Taxi, transport |
|
|
| Altele | 628 | 4426 (19%) | Alte cheltuieli |
|
|
|
|
**Logica generare note:**
|
|
```python
|
|
def generate_entries(receipt):
|
|
expense_type = EXPENSE_TYPES[receipt.expense_type_code]
|
|
|
|
entries = []
|
|
|
|
if expense_type.has_vat:
|
|
net_amount = receipt.amount / 1.19
|
|
vat_amount = receipt.amount - net_amount
|
|
|
|
entries.append(AccountingEntry(
|
|
entry_type=EntryType.DEBIT,
|
|
account_code=expense_type.account_code, # ex: 6022
|
|
amount=net_amount
|
|
))
|
|
entries.append(AccountingEntry(
|
|
entry_type=EntryType.DEBIT,
|
|
account_code="4426", # TVA deductibilă
|
|
amount=vat_amount
|
|
))
|
|
else:
|
|
entries.append(AccountingEntry(
|
|
entry_type=EntryType.DEBIT,
|
|
account_code=expense_type.account_code,
|
|
amount=receipt.amount
|
|
))
|
|
|
|
# Credit - casă sau bancă
|
|
entries.append(AccountingEntry(
|
|
entry_type=EntryType.CREDIT,
|
|
account_code=receipt.cash_register_account, # 5311 sau 5121
|
|
amount=receipt.amount
|
|
))
|
|
|
|
return entries
|
|
```
|
|
|
|
---
|
|
|
|
## Faza 2 Preview (Oracle Integration)
|
|
|
|
După ce Faza 1 funcționează, Faza 2 va adăuga:
|
|
|
|
```python
|
|
# receipt_service.py - metodă nouă
|
|
async def sync_to_oracle(receipt_id: int):
|
|
"""
|
|
Sincronizează bon APPROVED în Oracle:
|
|
|
|
1. pack_contafin.init_scriere_act_rul_local()
|
|
2. Pentru fiecare AccountingEntry:
|
|
INSERT INTO ACT_TEMP (
|
|
ID_ACT, DATAIREG, DATAACT, SCD, ASCD, SCC, ASCC,
|
|
SUMA, ID_CTR, ID_PARTD, EXPLICATIA, ...
|
|
)
|
|
3. pack_contafin.finalizeaza_scriere_act_rul()
|
|
→ SCRIE_IN_ACT()
|
|
→ SCRIE_IN_RUL()
|
|
→ Actualizare situații (BV, BP, TVA, etc.)
|
|
4. Update receipt.status = SYNCED, oracle_act_id = ...
|
|
"""
|
|
pass
|
|
```
|
|
|
|
---
|
|
|
|
## Riscuri și Mitigări
|
|
|
|
| Risc | Impact | Mitigare |
|
|
|------|--------|----------|
|
|
| SQLModel e relativ nou | Mediu | Fallback la SQLAlchemy pur dacă e nevoie |
|
|
| Upload fișiere mari | Mic | Limit 10MB, compresie imagini |
|
|
| Workflow complex | Mediu | Începem cu workflow simplu, adăugăm features gradual |
|
|
| Generare note greșite | Mare | Contabilul poate edita înainte de aprobare |
|
|
|
|
---
|
|
|
|
## Success Criteria (Faza 1)
|
|
|
|
- [ ] Utilizator poate uploada poză bon + date de bază
|
|
- [ ] Sistem generează automat note contabile
|
|
- [ ] Contabil poate vedea, edita și aproba note
|
|
- [ ] Bonurile aprobate sunt vizibile în listă
|
|
- [ ] Migrările Alembic funcționează corect
|
|
- [ ] Poze bonuri se salvează și se afișează corect
|
|
|
|
---
|
|
|
|
## Context Handover
|
|
|
|
**Pentru sesiunea următoare:**
|
|
1. Citește acest fișier `PLAN_DATA_ENTRY_RECEIPTS.md`
|
|
2. Începe cu Etapa 0 - creare branch și structură directoare
|
|
3. Referință pentru proceduri Oracle: `docs/PACK_CONTAFIN.pck`, `docs/PACK_FACTURARE.pck`
|
|
4. Pattern-uri existente pentru SQLite: `reports-app/telegram-bot/app/db/`
|