feat: Migrate to ultrathin monolith architecture
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>
This commit is contained in:
595
docs/data-entry/DATA-ENTRY-MODULE.md
Normal file
595
docs/data-entry/DATA-ENTRY-MODULE.md
Normal file
@@ -0,0 +1,595 @@
|
||||
# Data Entry Module - Technical Reference
|
||||
|
||||
> **Part of ROA2WEB Ultrathin Monolith** - See `CLAUDE.md` for general architecture
|
||||
|
||||
## Module Overview
|
||||
|
||||
**Purpose:** Introducere date în ERP (bonuri fiscale, chitanțe) cu workflow de aprobare
|
||||
|
||||
**Location:**
|
||||
- Backend: `backend/modules/data_entry/`
|
||||
- Frontend: `src/modules/data-entry/`
|
||||
- Database: `backend/modules/data/receipts/receipts.db` (SQLite)
|
||||
- Uploads: `backend/modules/data/receipts/uploads/`
|
||||
|
||||
**API Base Path:** `/api/data-entry/`
|
||||
|
||||
---
|
||||
|
||||
## Technical Stack
|
||||
|
||||
**Backend:**
|
||||
- **ORM:** SQLModel (Pydantic + SQLAlchemy)
|
||||
- **Migrations:** Alembic
|
||||
- **Database:** SQLite (Phase 1) → Oracle integration (Phase 2)
|
||||
- **Validation:** Pydantic v2
|
||||
|
||||
**Frontend:**
|
||||
- **Framework:** Vue.js 3 Composition API
|
||||
- **UI Library:** PrimeVue
|
||||
- **State:** Pinia stores
|
||||
- **Routing:** Vue Router (integrated with main app)
|
||||
|
||||
---
|
||||
|
||||
## Workflow States
|
||||
|
||||
```
|
||||
1. DRAFT
|
||||
↓ User completes form + uploads receipt photo
|
||||
|
||||
2. PENDING_REVIEW
|
||||
↓ System auto-generates accounting entries
|
||||
|
||||
3. APPROVED / REJECTED
|
||||
↓ Accountant approves or rejects
|
||||
↓ (if rejected, user can resubmit)
|
||||
|
||||
4. SYNCED
|
||||
└→ (Phase 2) Data synced to Oracle ERP
|
||||
```
|
||||
|
||||
### State Transitions
|
||||
|
||||
| From | To | Allowed Action | Who |
|
||||
|------|----|----|-----|
|
||||
| DRAFT | PENDING_REVIEW | Submit for review | User |
|
||||
| DRAFT | DRAFT | Update/Delete | User |
|
||||
| PENDING_REVIEW | APPROVED | Approve | Accountant |
|
||||
| PENDING_REVIEW | REJECTED | Reject | Accountant |
|
||||
| REJECTED | PENDING_REVIEW | Resubmit | User |
|
||||
| APPROVED | SYNCED | Sync to Oracle | System (Phase 2) |
|
||||
|
||||
---
|
||||
|
||||
## Database Schema (SQLite)
|
||||
|
||||
### Main Tables
|
||||
|
||||
**receipts** - Receipt header
|
||||
- `id` (PK)
|
||||
- `receipt_number` - Document number
|
||||
- `receipt_date` - Document date
|
||||
- `partner_id` - Supplier ID (from Oracle)
|
||||
- `partner_name` - Supplier name
|
||||
- `partner_cui` - Supplier CUI/CIF
|
||||
- `receipt_type` - BON/CHITANTA/FACTURA
|
||||
- `operation_type` - EXPENSE/INCOME
|
||||
- `total_amount` - Total with VAT
|
||||
- `vat_amount` - VAT amount
|
||||
- `payment_method` - CASH/CARD/BANK
|
||||
- `payment_amount` - Amount paid
|
||||
- `expense_type_code` - Expense type (FUEL, MATERIALS, etc.)
|
||||
- `description` - Notes
|
||||
- `status` - DRAFT/PENDING/APPROVED/REJECTED/SYNCED
|
||||
- `rejection_reason` - If rejected
|
||||
- `created_by` - Username
|
||||
- `approved_by` - Accountant username
|
||||
- `company_id` - Company ID from Oracle
|
||||
|
||||
**attachments** - Receipt photos/PDFs
|
||||
- `id` (PK)
|
||||
- `receipt_id` (FK)
|
||||
- `filename` - Original filename
|
||||
- `file_path` - Storage path
|
||||
- `mime_type` - image/*, application/pdf
|
||||
- `file_size` - Bytes
|
||||
- `uploaded_at`
|
||||
|
||||
**accounting_entries** - Auto-generated entries
|
||||
- `id` (PK)
|
||||
- `receipt_id` (FK)
|
||||
- `account_code` - Cont contabil (e.g., "6022")
|
||||
- `debit_amount` - Debit
|
||||
- `credit_amount` - Credit
|
||||
- `description` - Entry description
|
||||
- `entry_order` - Sequence number
|
||||
|
||||
### Migrations
|
||||
|
||||
**Location:** `backend/modules/data_entry/migrations/`
|
||||
|
||||
```bash
|
||||
# Create new migration
|
||||
cd backend/modules/data_entry
|
||||
alembic revision --autogenerate -m "description"
|
||||
|
||||
# Apply migrations
|
||||
alembic upgrade head
|
||||
|
||||
# Rollback
|
||||
alembic downgrade -1
|
||||
```
|
||||
|
||||
**Important:** Migrations run automatically on module startup via `lifespan` event in `main.py`.
|
||||
|
||||
---
|
||||
|
||||
## Expense Types (Hardcoded - Phase 1)
|
||||
|
||||
| Code | Type | Account | VAT | Description |
|
||||
|------|------|---------|-----|-------------|
|
||||
| `FUEL` | Combustibil | 6022 | 19% | Combustibil auto |
|
||||
| `MATERIALS` | Materiale | 6028 | 19% | Materiale consumabile |
|
||||
| `OFFICE` | Rechizite | 6024 | 19% | Rechizite birou |
|
||||
| `PHONE` | Telefonie | 626 | 19% | Servicii telefonie |
|
||||
| `PARKING` | Parcare | 6022 | 19% | Taxe parcare |
|
||||
| `FOOD` | Alimentație | 6028 | 0% | Alimente (fără TVA) |
|
||||
| `TRANSPORT` | Transport | 624 | 19% | Transport marfă |
|
||||
| `OTHER` | Altele | 628 | 19% | Alte cheltuieli |
|
||||
|
||||
**Auto-generation Logic:**
|
||||
|
||||
When user submits receipt, system automatically generates:
|
||||
|
||||
```python
|
||||
# Entry 1: Expense account (Debit)
|
||||
account_code = expense_type.account # e.g., "6022"
|
||||
debit_amount = total_amount - vat_amount
|
||||
credit_amount = 0
|
||||
|
||||
# Entry 2: VAT account (Debit) - if VAT > 0
|
||||
account_code = "4426" # TVA deductibilă
|
||||
debit_amount = vat_amount
|
||||
credit_amount = 0
|
||||
|
||||
# Entry 3: Payment account (Credit)
|
||||
account_code = cash_register.account # e.g., "5311"
|
||||
debit_amount = 0
|
||||
credit_amount = total_amount
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Oracle Nomenclatures (Read-Only)
|
||||
|
||||
Module uses shared Oracle connection for nomenclatures:
|
||||
|
||||
### Partners (Suppliers)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
SELECT B.ID_PART, B.DENUMIRE, B.COD_FISCAL, B.ADRESA
|
||||
FROM {schema}.CORESP_TIP_PART A
|
||||
INNER JOIN {schema}.VNOM_PARTENERI B ON A.ID_PART = B.ID_PART
|
||||
WHERE A.ID_TIP_PART = 17 -- Furnizori
|
||||
AND (B.INACTIV = 0 OR B.INACTIV IS NULL)
|
||||
ORDER BY B.DENUMIRE
|
||||
```
|
||||
|
||||
**Partner Types** (`id_tip_part`):
|
||||
- `17` - Furnizori (Suppliers)
|
||||
- `22` - Casa LEI (Cash LEI)
|
||||
- `23` - Casa Valută (Cash FX)
|
||||
- `24` - Bancă LEI (Bank LEI)
|
||||
- `25` - Bancă Valută (Bank FX)
|
||||
|
||||
### Cash Registers & Bank Accounts
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
SELECT B.ID_PART, B.DENUMIRE, B.COD_FISCAL, B.CONT
|
||||
FROM {schema}.CORESP_TIP_PART A
|
||||
INNER JOIN {schema}.VNOM_PARTENERI B ON A.ID_PART = B.ID_PART
|
||||
WHERE A.ID_TIP_PART IN (22, 23, 24, 25)
|
||||
AND (B.INACTIV = 0 OR B.INACTIV IS NULL)
|
||||
ORDER BY B.DENUMIRE
|
||||
```
|
||||
|
||||
**Account Mapping:**
|
||||
- Casa LEI → Account `5311`
|
||||
- Casa Valută → Account `5314`
|
||||
- Bancă LEI → Account `5121`
|
||||
- Bancă Valută → Account `5124`
|
||||
|
||||
---
|
||||
|
||||
## Oracle Integration (Phase 2)
|
||||
|
||||
### Sync Process
|
||||
|
||||
When receipt is APPROVED, sync to Oracle using stored procedures:
|
||||
|
||||
```sql
|
||||
-- 1. Initialize
|
||||
EXEC {schema}.pack_contafin.init_scriere_act_rul_local(
|
||||
p_id_utilizator => :user_id,
|
||||
p_id_baza => :company_id,
|
||||
p_id_luna => :month_id
|
||||
);
|
||||
|
||||
-- 2. Insert temp document
|
||||
INSERT INTO {schema}.ACT_TEMP (
|
||||
ID_ACT, DATA_ACT, NR_DOCUMENT, ID_PART,
|
||||
TIP_ACT, STARE_ACT, ...
|
||||
) VALUES (
|
||||
:act_id, :receipt_date, :receipt_number, :partner_id,
|
||||
'CUMPARARE', 'TEMP', ...
|
||||
);
|
||||
|
||||
-- 3. Insert temp entries
|
||||
INSERT INTO {schema}.ACT_TEMP_RUL (
|
||||
ID_ACT, CONT, SUMA_D, SUMA_C, EXPLICATIE
|
||||
) VALUES (
|
||||
:act_id, :account_code, :debit, :credit, :description
|
||||
);
|
||||
|
||||
-- 4. Finalize
|
||||
EXEC {schema}.pack_contafin.finalizeaza_scriere_act_rul(
|
||||
p_id_utilizator => :user_id,
|
||||
p_id_act => :act_id
|
||||
);
|
||||
```
|
||||
|
||||
**Stored Procedures:**
|
||||
- `pack_contafin.init_scriere_act_rul_local()` - Initialize transaction
|
||||
- `pack_contafin.finalizeaza_scriere_act_rul()` - Commit to permanent tables
|
||||
- `pack_contafin.get_next_act_id()` - Get next document ID
|
||||
|
||||
**Reference:** See `docs/PACK_CONTAFIN.pck` for full stored procedure definitions.
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Receipts CRUD
|
||||
|
||||
**List Receipts**
|
||||
```
|
||||
GET /api/data-entry/receipts/
|
||||
Query params: page, page_size, status, search, date_from, date_to
|
||||
```
|
||||
|
||||
**Get Receipt**
|
||||
```
|
||||
GET /api/data-entry/receipts/{id}
|
||||
```
|
||||
|
||||
**Create Receipt**
|
||||
```
|
||||
POST /api/data-entry/receipts/
|
||||
Body: ReceiptCreate schema
|
||||
```
|
||||
|
||||
**Update Receipt** (DRAFT only)
|
||||
```
|
||||
PUT /api/data-entry/receipts/{id}
|
||||
Body: ReceiptUpdate schema
|
||||
```
|
||||
|
||||
**Delete Receipt** (DRAFT only)
|
||||
```
|
||||
DELETE /api/data-entry/receipts/{id}
|
||||
```
|
||||
|
||||
### Workflow Actions
|
||||
|
||||
**Submit for Review**
|
||||
```
|
||||
POST /api/data-entry/receipts/{id}/submit
|
||||
Status: DRAFT → PENDING_REVIEW
|
||||
Auto-generates accounting entries
|
||||
```
|
||||
|
||||
**Approve**
|
||||
```
|
||||
POST /api/data-entry/receipts/{id}/approve
|
||||
Body: { "notes": "Optional approval notes" }
|
||||
Status: PENDING_REVIEW → APPROVED
|
||||
```
|
||||
|
||||
**Reject**
|
||||
```
|
||||
POST /api/data-entry/receipts/{id}/reject
|
||||
Body: { "reason": "Rejection reason (required)" }
|
||||
Status: PENDING_REVIEW → REJECTED
|
||||
```
|
||||
|
||||
**Resubmit** (after rejection)
|
||||
```
|
||||
POST /api/data-entry/receipts/{id}/resubmit
|
||||
Status: REJECTED → PENDING_REVIEW
|
||||
```
|
||||
|
||||
### Attachments
|
||||
|
||||
**Upload**
|
||||
```
|
||||
POST /api/data-entry/receipts/{id}/attachments
|
||||
Content-Type: multipart/form-data
|
||||
Field: file (image/*, application/pdf, max 10MB)
|
||||
```
|
||||
|
||||
**Download**
|
||||
```
|
||||
GET /api/data-entry/attachments/{id}/download
|
||||
Response: File stream
|
||||
```
|
||||
|
||||
**Delete**
|
||||
```
|
||||
DELETE /api/data-entry/attachments/{id}
|
||||
```
|
||||
|
||||
### Nomenclatures
|
||||
|
||||
**Partners** (from Oracle)
|
||||
```
|
||||
GET /api/data-entry/receipts/nomenclature/partners
|
||||
Query: search (optional)
|
||||
```
|
||||
|
||||
**Cash Registers** (from Oracle)
|
||||
```
|
||||
GET /api/data-entry/receipts/nomenclature/cash-registers
|
||||
```
|
||||
|
||||
**Expense Types** (hardcoded)
|
||||
```
|
||||
GET /api/data-entry/receipts/nomenclature/expense-types
|
||||
```
|
||||
|
||||
**Statistics**
|
||||
```
|
||||
GET /api/data-entry/receipts/stats
|
||||
Response: { total, by_status: { DRAFT: N, ... } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Components
|
||||
|
||||
### Views
|
||||
|
||||
**Location:** `src/modules/data-entry/views/`
|
||||
|
||||
- `ReceiptListView.vue` - Main list with filters and status tabs
|
||||
- `ReceiptCreateView.vue` - Create/edit form
|
||||
- `ReceiptDetailView.vue` - View receipt details (future)
|
||||
|
||||
### Key Components
|
||||
|
||||
**Location:** `src/modules/data-entry/components/`
|
||||
|
||||
- `ReceiptForm.vue` - Main form component
|
||||
- `AttachmentUpload.vue` - Drag & drop file upload
|
||||
- `AccountingEntriesTable.vue` - Preview generated entries
|
||||
- `WorkflowActions.vue` - Approve/Reject buttons
|
||||
|
||||
### Stores
|
||||
|
||||
**Location:** `src/modules/data-entry/stores/`
|
||||
|
||||
- `receiptsStore.js` - Main receipts CRUD
|
||||
- `nomenclatureStore.js` - Partners, cash registers, expense types
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
|
||||
### 1. Nomenclatoare goale / furnizori lipsă
|
||||
|
||||
**Symptom:** Partner dropdown is empty
|
||||
|
||||
**Causes:**
|
||||
- Wrong Oracle server (PROD vs TEST)
|
||||
- Selected company doesn't exist on current server
|
||||
- No suppliers configured for company
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check which tunnel is running
|
||||
./ssh-tunnel-prod.sh status
|
||||
./ssh-tunnel-test.sh status
|
||||
|
||||
# Restart with correct tunnel
|
||||
./start-prod.sh # or ./start-test.sh
|
||||
```
|
||||
|
||||
### 2. SQLite locked errors
|
||||
|
||||
**Symptom:** `database is locked`
|
||||
|
||||
**Causes:**
|
||||
- Multiple backend instances accessing same DB
|
||||
- Alembic migration in progress
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check for multiple processes
|
||||
ps aux | grep uvicorn
|
||||
|
||||
# Kill duplicates, restart
|
||||
./start-prod.sh restart
|
||||
```
|
||||
|
||||
### 3. Upload fails
|
||||
|
||||
**Symptom:** 500 error on file upload
|
||||
|
||||
**Causes:**
|
||||
- File too large (>10MB)
|
||||
- Wrong MIME type
|
||||
- Upload directory permissions
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check upload directory
|
||||
ls -la backend/modules/data/receipts/uploads/
|
||||
|
||||
# Create if missing
|
||||
mkdir -p backend/modules/data/receipts/uploads/
|
||||
chmod 755 backend/modules/data/receipts/uploads/
|
||||
```
|
||||
|
||||
### 4. Migration errors
|
||||
|
||||
**Symptom:** Alembic fails on startup
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
cd backend/modules/data_entry
|
||||
|
||||
# Check migration status
|
||||
alembic current
|
||||
|
||||
# Rollback one version
|
||||
alembic downgrade -1
|
||||
|
||||
# Re-apply
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Backend Tests
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
pytest modules/data_entry/tests/
|
||||
```
|
||||
|
||||
### Frontend Tests
|
||||
|
||||
```bash
|
||||
cd src/modules/data-entry
|
||||
npm run test
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
|
||||
**Test Workflow:**
|
||||
1. Login as user (e.g., MARIUS M)
|
||||
2. Create receipt → status DRAFT
|
||||
3. Upload attachment
|
||||
4. Submit → status PENDING_REVIEW
|
||||
5. Login as accountant
|
||||
6. Approve/Reject
|
||||
7. Verify accounting entries generated correctly
|
||||
|
||||
---
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### 1. Start Development Environment
|
||||
|
||||
```bash
|
||||
# Start unified monolith (backend + frontend)
|
||||
./start-prod.sh # Production Oracle server
|
||||
# OR
|
||||
./start-test.sh # Test Oracle server
|
||||
```
|
||||
|
||||
### 2. Make Changes
|
||||
|
||||
**Backend:**
|
||||
- Edit files in `backend/modules/data_entry/`
|
||||
- Uvicorn auto-reloads on file changes
|
||||
|
||||
**Frontend:**
|
||||
- Edit files in `src/modules/data-entry/`
|
||||
- Vite HMR auto-updates browser
|
||||
|
||||
### 3. Database Changes
|
||||
|
||||
```bash
|
||||
cd backend/modules/data_entry
|
||||
|
||||
# Generate migration
|
||||
alembic revision --autogenerate -m "Add new field"
|
||||
|
||||
# Review migration file
|
||||
nano migrations/versions/xxx_add_new_field.py
|
||||
|
||||
# Apply
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
### 4. Testing
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
cd backend
|
||||
pytest modules/data_entry/tests/ -v
|
||||
|
||||
# Frontend
|
||||
cd src/modules/data-entry
|
||||
npm run test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Production Deployment
|
||||
|
||||
See `deployment/windows/` for Windows deployment scripts.
|
||||
|
||||
**Module Activation:**
|
||||
|
||||
Enabled via `.env` flag:
|
||||
```env
|
||||
MODULE_DATA_ENTRY_ENABLED=true
|
||||
```
|
||||
|
||||
**Database Location:**
|
||||
- Development: `backend/modules/data/receipts/receipts.db`
|
||||
- Production: `C:\inetpub\wwwroot\roa2web\backend\modules\data\receipts\receipts.db`
|
||||
|
||||
**Uploads Location:**
|
||||
- Development: `backend/modules/data/receipts/uploads/`
|
||||
- Production: `C:\inetpub\wwwroot\roa2web\backend\modules\data\receipts\uploads\`
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements (Phase 2)
|
||||
|
||||
1. **Oracle Sync Implementation**
|
||||
- Complete `sync_to_oracle()` function
|
||||
- Error handling and retry logic
|
||||
- Sync status tracking
|
||||
|
||||
2. **OCR Integration**
|
||||
- Automatic data extraction from photos
|
||||
- Pre-fill form fields
|
||||
- Confidence scores
|
||||
|
||||
3. **Approval Notifications**
|
||||
- Email notifications to accountants
|
||||
- User notifications on approval/rejection
|
||||
- Telegram bot integration
|
||||
|
||||
4. **Bulk Operations**
|
||||
- Batch approve/reject
|
||||
- Bulk upload
|
||||
- Excel import
|
||||
|
||||
5. **Advanced Reporting**
|
||||
- Expense analytics by type
|
||||
- Supplier spending reports
|
||||
- Monthly summaries
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-12-29
|
||||
**Architecture:** Ultrathin Monolith (integrated module)
|
||||
382
docs/data-entry/README.md
Normal file
382
docs/data-entry/README.md
Normal file
@@ -0,0 +1,382 @@
|
||||
# Data Entry App - Bonuri Fiscale
|
||||
|
||||
Aplicatie pentru introducere bonuri fiscale cu workflow de aprobare si extragere automata date prin OCR.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Python 3.10+
|
||||
- Node.js 18+
|
||||
- (Optional) SSH tunnel pentru Oracle nomenclatoare
|
||||
|
||||
### Using Start Script (Recommended)
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
./start-data-entry.sh
|
||||
|
||||
# Or individual commands:
|
||||
./start-data-entry.sh start # Start all
|
||||
./start-data-entry.sh stop # Stop all
|
||||
./start-data-entry.sh status # Check status
|
||||
./start-data-entry.sh restart backend # Restart backend only
|
||||
```
|
||||
|
||||
**Services:**
|
||||
- Backend: http://localhost:8003
|
||||
- Frontend: http://localhost:3010
|
||||
- API Docs: http://localhost:8003/docs
|
||||
|
||||
### Manual Setup
|
||||
|
||||
#### Backend Setup
|
||||
|
||||
```bash
|
||||
cd data-entry-app/backend
|
||||
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
source venv/bin/activate # Linux/Mac
|
||||
# sau: venv\Scripts\activate # Windows
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Create .env file
|
||||
cp .env.example .env
|
||||
# Edit .env with your settings
|
||||
|
||||
# Run migrations
|
||||
alembic upgrade head
|
||||
|
||||
# Start server
|
||||
uvicorn app.main:app --reload --port 8003
|
||||
```
|
||||
|
||||
#### Frontend Setup
|
||||
|
||||
```bash
|
||||
cd data-entry-app/frontend
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Start dev server
|
||||
npm run dev -- --port 3010
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Pentru Utilizatori
|
||||
- **OCR Automat** - Extragere automata date din poza bonului (suma, data, furnizor, CUI)
|
||||
- Upload poze bonuri fiscale
|
||||
- Completare date bon (suma, data, furnizor)
|
||||
- Selectie tip cheltuiala
|
||||
- Trimitere spre aprobare
|
||||
|
||||
### Pentru Contabili
|
||||
- Vizualizare bonuri in asteptare
|
||||
- Editare note contabile propuse
|
||||
- Aprobare/Respingere bonuri
|
||||
- Aprobare in masa
|
||||
|
||||
## OCR Feature
|
||||
|
||||
### Cum functioneaza
|
||||
|
||||
1. **Upload imagine** - Trage sau selecteaza poza bonului
|
||||
2. **Procesare OCR** - Click pe "Proceseaza cu OCR"
|
||||
3. **Previzualizare** - Datele extrase sunt afisate cu indicatori de incredere
|
||||
4. **Aplicare** - Click "Aplica datele in formular" pentru auto-fill
|
||||
|
||||
### Campuri extrase automat
|
||||
|
||||
| Camp | Acuratete estimata |
|
||||
|------|-------------------|
|
||||
| Suma (TOTAL) | 90-95% |
|
||||
| Data | 85-90% |
|
||||
| Numar bon | 80-85% |
|
||||
| Furnizor | 70-80% |
|
||||
| CUI | 85-90% |
|
||||
| Tip document | 95%+ |
|
||||
|
||||
### OCR System Dependencies (Linux/Docker)
|
||||
|
||||
Pentru functionarea OCR trebuie instalate:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
apt-get install -y \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-ron \
|
||||
tesseract-ocr-eng \
|
||||
poppler-utils \
|
||||
libgl1-mesa-glx \
|
||||
libglib2.0-0
|
||||
|
||||
# Fedora/RHEL
|
||||
dnf install -y \
|
||||
tesseract \
|
||||
tesseract-langpack-ron \
|
||||
tesseract-langpack-eng \
|
||||
poppler-utils
|
||||
```
|
||||
|
||||
**Note:** PaddleOCR (engine principal) se instaleaza automat cu pip. Tesseract este folosit ca fallback.
|
||||
|
||||
### OCR System Dependencies (Windows)
|
||||
|
||||
Pe Windows Server trebuie instalate manual urmatoarele componente:
|
||||
|
||||
#### 1. Poppler (pentru conversie PDF → imagini)
|
||||
|
||||
```powershell
|
||||
# Descarca Poppler pentru Windows
|
||||
# https://github.com/osborn/poppler-windows/releases
|
||||
# sau https://github.com/bblanchon/pdfium-binaries
|
||||
|
||||
# Extrage in C:\Program Files\poppler\
|
||||
# Adauga la PATH: C:\Program Files\poppler\Library\bin
|
||||
```
|
||||
|
||||
#### 2. Tesseract OCR (engine OCR backup)
|
||||
|
||||
```powershell
|
||||
# Descarca installer de la:
|
||||
# https://github.com/UB-Mannheim/tesseract/wiki
|
||||
|
||||
# Instaleaza cu limbile: English + Romanian
|
||||
# Default path: C:\Program Files\Tesseract-OCR\
|
||||
# Adauga la PATH
|
||||
```
|
||||
|
||||
#### 3. Python OCR Dependencies (in venv)
|
||||
|
||||
```powershell
|
||||
cd C:\inetpub\wwwroot\roa2web\data-entry-backend
|
||||
.\venv\Scripts\activate
|
||||
|
||||
# Instaleaza dependentele OCR
|
||||
pip install paddlepaddle>=2.5.0
|
||||
pip install paddleocr>=2.7.0
|
||||
pip install opencv-python>=4.8.0
|
||||
pip install pytesseract>=0.3.10
|
||||
pip install pdf2image>=1.16.0
|
||||
|
||||
# Sau din requirements.txt
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 4. Restart serviciu
|
||||
|
||||
```powershell
|
||||
nssm restart ROA2WEB-DataEntry
|
||||
```
|
||||
|
||||
**Note importante Windows:**
|
||||
- Prima rulare PaddleOCR descarca modele (~200MB) - poate dura cateva minute
|
||||
- PaddleOCR necesita ~2GB RAM disponibil
|
||||
- Verifica PATH-ul pentru Poppler si Tesseract dupa instalare
|
||||
- Restart serviciul backend dupa orice modificare PATH
|
||||
|
||||
### OCR API Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | /api/ocr/status | Check OCR service status |
|
||||
| POST | /api/ocr/extract | Extract data from uploaded image |
|
||||
| POST | /api/ocr/extract-attachment/{id} | Re-process existing attachment |
|
||||
|
||||
### Test OCR
|
||||
|
||||
```bash
|
||||
# Check OCR status
|
||||
curl http://localhost:8003/api/ocr/status
|
||||
|
||||
# Extract from image
|
||||
curl -X POST -F "file=@bon.jpg" http://localhost:8003/api/ocr/extract
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
```
|
||||
DRAFT → PENDING_REVIEW → APPROVED/REJECTED → (SYNCED in Oracle)
|
||||
```
|
||||
|
||||
1. **DRAFT**: Utilizator completeaza datele (manual sau via OCR)
|
||||
2. **PENDING_REVIEW**: Sistemul genereaza note contabile automat
|
||||
3. **APPROVED**: Contabil a aprobat bonul
|
||||
4. **REJECTED**: Contabil a respins (utilizatorul poate corecta)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
data-entry-app/
|
||||
├── backend/
|
||||
│ ├── app/
|
||||
│ │ ├── main.py # FastAPI entry point
|
||||
│ │ ├── config.py # Settings
|
||||
│ │ ├── db/
|
||||
│ │ │ ├── database.py # SQLite engine
|
||||
│ │ │ ├── models/ # SQLModel models
|
||||
│ │ │ └── crud/ # CRUD operations
|
||||
│ │ ├── schemas/ # Pydantic schemas
|
||||
│ │ │ └── ocr.py # OCR response schemas
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── receipt_service.py
|
||||
│ │ │ ├── ocr_service.py # OCR orchestration
|
||||
│ │ │ ├── ocr_engine.py # PaddleOCR/Tesseract
|
||||
│ │ │ ├── ocr_extractor.py # Regex patterns RO
|
||||
│ │ │ └── image_preprocessor.py # OpenCV pipeline
|
||||
│ │ └── routers/
|
||||
│ │ ├── receipts.py
|
||||
│ │ └── ocr.py # OCR endpoints
|
||||
│ ├── migrations/ # Alembic migrations
|
||||
│ ├── data/
|
||||
│ │ ├── receipts.db # SQLite database
|
||||
│ │ └── uploads/ # Uploaded files
|
||||
│ └── requirements.txt
|
||||
│
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── views/receipts/ # Page components
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── receipts/ # Receipt components
|
||||
│ │ │ └── ocr/ # OCR components
|
||||
│ │ │ ├── OCRUploadZone.vue
|
||||
│ │ │ ├── OCRPreview.vue
|
||||
│ │ │ └── OCRConfidenceIndicator.vue
|
||||
│ │ ├── stores/ # Pinia stores
|
||||
│ │ └── router/ # Vue Router
|
||||
│ ├── package.json
|
||||
│ └── vite.config.js
|
||||
│
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Backend (.env)
|
||||
|
||||
```bash
|
||||
# SQLite
|
||||
SQLITE_DATABASE_PATH=data/receipts.db
|
||||
|
||||
# File uploads
|
||||
UPLOAD_PATH=data/uploads
|
||||
MAX_UPLOAD_SIZE_MB=10
|
||||
|
||||
# Oracle (for nomenclatures)
|
||||
ORACLE_USER=CONTAFIN_ORACLE
|
||||
ORACLE_PASSWORD=your_password
|
||||
ORACLE_HOST=localhost
|
||||
ORACLE_PORT=1526
|
||||
ORACLE_SID=ROA
|
||||
|
||||
# JWT (shared with reports-app)
|
||||
JWT_SECRET_KEY=your_secret_key
|
||||
JWT_ALGORITHM=HS256
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Create new migration
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
alembic revision --autogenerate -m "Add new field"
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
### Run tests
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
cd backend && pytest
|
||||
|
||||
# Frontend
|
||||
cd frontend && npm run test
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
Full API documentation available at http://localhost:8003/docs when backend is running.
|
||||
|
||||
### Key Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| POST | /api/receipts/ | Create receipt |
|
||||
| GET | /api/receipts/ | List receipts |
|
||||
| GET | /api/receipts/{id} | Get receipt details |
|
||||
| POST | /api/receipts/{id}/submit | Submit for review |
|
||||
| POST | /api/receipts/{id}/approve | Approve receipt |
|
||||
| POST | /api/receipts/{id}/reject | Reject receipt |
|
||||
| POST | /api/receipts/{id}/attachments | Upload attachment |
|
||||
| GET | /api/ocr/status | OCR service status |
|
||||
| POST | /api/ocr/extract | OCR image extraction |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### OCR not working
|
||||
|
||||
1. Check OCR status: `curl http://localhost:8003/api/ocr/status`
|
||||
2. Install system dependencies (tesseract, poppler)
|
||||
3. Verify PaddleOCR installed: `python -c "from paddleocr import PaddleOCR"`
|
||||
|
||||
### OCR Windows - "poppler not in PATH"
|
||||
|
||||
```powershell
|
||||
# Eroare: "Unable to get page count. Is poppler installed and in PATH?"
|
||||
|
||||
# Solutie 1: Adauga Poppler la PATH
|
||||
# System Properties → Environment Variables → System variables → Path → New
|
||||
# Adauga: C:\Program Files\poppler\Library\bin
|
||||
|
||||
# Solutie 2: Restart serviciul dupa modificarea PATH
|
||||
nssm restart ROA2WEB-DataEntry
|
||||
|
||||
# Verificare:
|
||||
pdfinfo --version
|
||||
```
|
||||
|
||||
### OCR Windows - "tesseract not found"
|
||||
|
||||
```powershell
|
||||
# Eroare: "tesseract is not installed or it's not in your PATH"
|
||||
|
||||
# Solutie: Adauga Tesseract la PATH
|
||||
# C:\Program Files\Tesseract-OCR\
|
||||
|
||||
# Verificare:
|
||||
tesseract --version
|
||||
tesseract --list-langs # Trebuie sa arate 'ron' si 'eng'
|
||||
```
|
||||
|
||||
### OCR Windows - PaddleOCR import error
|
||||
|
||||
```powershell
|
||||
# Eroare: "No module named 'paddleocr'"
|
||||
|
||||
cd C:\inetpub\wwwroot\roa2web\data-entry-backend
|
||||
.\venv\Scripts\activate
|
||||
pip install paddlepaddle>=2.5.0
|
||||
pip install paddleocr>=2.7.0
|
||||
|
||||
# Restart serviciu
|
||||
nssm restart ROA2WEB-DataEntry
|
||||
```
|
||||
|
||||
### Low OCR accuracy
|
||||
|
||||
- Ensure good lighting when taking receipt photos
|
||||
- Keep receipt flat (no folds/wrinkles)
|
||||
- Try PDF instead of JPG for scanned documents
|
||||
- Check if text is in focus
|
||||
|
||||
## Phase 2 (Future)
|
||||
|
||||
- Oracle sync for approved receipts
|
||||
- Integration with pack_contafin procedures
|
||||
- Automatic posting to ACT/RUL tables
|
||||
Reference in New Issue
Block a user