# 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 SSH tunnel status (for servers requiring SSH) ./ssh-tunnel.sh status # Restart with correct environment ./start.sh prod # or ./start.sh test (test uses direct connection) ``` ### 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.sh prod 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.sh prod # Production Oracle server # OR ./start.sh test # 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)