# 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)
