- README: updated Telegram integration description to mention OCR bonuri - docs/telegram/README.md: rewrote in Romanian, added bonuri fiscale workflow (PDF/foto → OCR → preview → Oracle) - .claude/settings.json: fix statusline path for current user Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
226 lines
6.9 KiB
Markdown
226 lines
6.9 KiB
Markdown
# ROA2WEB Telegram Bot
|
|
|
|
> **Architecture:** Ultrathin Monolith — bot rulează ca background task în backend-ul unificat pe portul 8000.
|
|
> Vezi `docs/telegram/DEPLOYMENT.md` pentru cerința single-worker.
|
|
|
|
## Overview
|
|
|
|
Botul Telegram ROA2WEB oferă acces la sistemul ERP financiar prin comenzi simple și procesare bonuri fiscale prin OCR.
|
|
|
|
### Funcționalități principale
|
|
|
|
- **Autentificare** prin cod de legătură (Deep Link / QR Code / Manual)
|
|
- **Date financiare**: dashboard, facturi, trezorerie, sold clienți/furnizori
|
|
- **Bonuri fiscale**: trimite PDF sau fotografie → OCR → preview → salvare în Oracle
|
|
|
|
---
|
|
|
|
## Arhitectură
|
|
|
|
Modulul este integrat în monolitul unificat:
|
|
|
|
```
|
|
backend/modules/telegram/
|
|
├── agent/
|
|
│ └── session.py # Gestionare sesiune (firma activă)
|
|
├── api/
|
|
│ └── client.py # HTTP client pentru ROA2WEB backend
|
|
├── auth/
|
|
│ ├── email_auth.py
|
|
│ └── linking.py # Legare cont Oracle ↔ Telegram
|
|
├── bot/
|
|
│ ├── handlers.py # Handlere comenzi (/dashboard, /facturi, etc.)
|
|
│ ├── formatters.py # Formatare răspunsuri Markdown
|
|
│ ├── keyboards.py # Taste inline
|
|
│ ├── helpers.py
|
|
│ └── menus.py
|
|
├── db/
|
|
│ ├── database.py # SQLite — schemă și conexiune
|
|
│ └── operations.py # CRUD operații
|
|
├── handlers/
|
|
│ └── receipt_handlers.py # Procesare bonuri fiscale (OCR flow)
|
|
├── routers/
|
|
│ ├── auth_codes.py
|
|
│ └── internal_api.py # FastAPI endpoint pentru backend callbacks
|
|
└── bot_main.py # Punct intrare bot (ApplicationBuilder)
|
|
```
|
|
|
|
### Flux date — Bonuri fiscale
|
|
|
|
```
|
|
User trimite PDF/foto
|
|
↓
|
|
handle_document_message() / handle_photo_message()
|
|
↓
|
|
submit_ocr_job() → OCR Worker Pool (docTR + pypdfium2)
|
|
↓
|
|
wait_for_result() — polling până la 120s
|
|
↓
|
|
_format_receipt_preview() → mesaj Telegram cu butoane Confirmă/Anulează
|
|
↓
|
|
handle_receipt_callback() → confirm
|
|
↓
|
|
_resolve_schema() → CONTAFIN_ORACLE.v_nom_firme (schema firmei active)
|
|
↓
|
|
_save_to_oracle() → write_receipt() → PACK_CONTAFIN (COD din seq_cod.nextval)
|
|
↓
|
|
"✅ Bon salvat! Cod document: XXXXXXX"
|
|
```
|
|
|
|
### Flux date — Comenzi financiare
|
|
|
|
```
|
|
User → Comandă Telegram → handlers.py → API client → Backend API → Oracle DB → Formater → User
|
|
```
|
|
|
|
---
|
|
|
|
## Setup
|
|
|
|
### Configurare `.env`
|
|
|
|
```bash
|
|
# backend/.env sau backend/.env.test
|
|
MODULE_TELEGRAM_ENABLED=true
|
|
TELEGRAM_BOT_TOKEN=your_bot_token_from_botfather
|
|
```
|
|
|
|
### Pornire
|
|
|
|
```bash
|
|
./start.sh prod # Pornește tot (backend + frontend + bot)
|
|
./start.sh test # Mod test (conexiune Oracle directă, fără SSH tunnel)
|
|
```
|
|
|
|
Botul pornește automat ca background task când `MODULE_TELEGRAM_ENABLED=true`.
|
|
|
|
> **Important:** Backend-ul trebuie rulat cu `--workers 1`. Vezi `docs/telegram/DEPLOYMENT.md`.
|
|
|
|
---
|
|
|
|
## Comenzi disponibile
|
|
|
|
| Comandă | Descriere |
|
|
|---------|-----------|
|
|
| `/start [cod]` | Pornire bot sau legare cont cu cod 8 caractere |
|
|
| `/help` | Afișează comenzile disponibile |
|
|
| `/companies` | Lista firme accesibile |
|
|
| `/selectcompany [nume]` | Selectează firma activă |
|
|
| `/dashboard` | Dashboard financiar pentru firma activă |
|
|
| `/sold` | Sold (alias `/dashboard`) |
|
|
| `/facturi [filtru]` | Facturi (filtre: `neplatite`, `platite`) |
|
|
| `/trezorerie` | Date trezorerie (casă + bancă) |
|
|
| `/clear` | Șterge selecția firmei active |
|
|
| `/unlink` | Deconectează contul Telegram de la Oracle |
|
|
|
|
### Bonuri fiscale (fără comandă explicită)
|
|
|
|
Trimite direct un **fișier PDF** sau o **fotografie** a bonului fiscal → botul pornește automat fluxul OCR.
|
|
|
|
---
|
|
|
|
## Autentificare
|
|
|
|
### Metoda 1: Deep Link (recomandat)
|
|
|
|
1. Login în aplicația ROA2WEB → `/telegram`
|
|
2. Click "Generează Cod"
|
|
3. Click "🚀 Deschide în Telegram" → Telegram se deschide cu codul pre-completat
|
|
4. Gata — cont legat în ~30 secunde
|
|
|
|
### Metoda 2: QR Code (cross-device)
|
|
|
|
1. Login pe desktop → `/telegram` → "Generează Cod"
|
|
2. Scanează QR Code-ul afișat cu Telegram pe mobil
|
|
3. Gata
|
|
|
|
### Metoda 3: Manual
|
|
|
|
1. Login → `/telegram` → "Generează Cod" → copiază codul
|
|
2. Trimite codul la bot (ex: `ABC123XY`)
|
|
|
|
**Detalii tehnice:**
|
|
- Cod 8 caractere, valabil 15 minute
|
|
- Backend salvează codul via `POST /internal/save-code`
|
|
- Bot verifică codul și leagă conturile în SQLite
|
|
- User primește JWT token
|
|
|
|
---
|
|
|
|
## Bonuri fiscale — detalii tehnice
|
|
|
|
### OCR Pipeline
|
|
|
|
- **Engine principal:** docTR (CPU-only, fără NVIDIA/CUDA)
|
|
- **PDF decode:** pypdfium2 (fallback când poppler-utils nu e instalat)
|
|
- **Profil fallback:** GENERIC când CUI-ul furnizorului nu are profil dedicat
|
|
- **Timeout OCR:** 120 secunde
|
|
- **Pending TTL:** 600 secunde (bon în așteptare expiră după 10 minute)
|
|
|
|
### Scriere Oracle
|
|
|
|
- COD unic generat din `seq_cod.nextval` (nu MAX+1 — evită race conditions)
|
|
- Conexiunea se face AS schema owner (nu read user) — cerut de `PACK_CONTAFIN` care folosește `SESSION_USER` în SQL dinamic
|
|
- Pool per `(server_id, schema)` — fiecare schemă Oracle are propriul connection pool
|
|
- 3 linii contabile per bon: cheltuială (6x/401), TVA (4426/401), plată (401/5311 sau 401/5121)
|
|
|
|
### Câmpuri extrase de OCR → preview Telegram
|
|
|
|
| Câmp OCR | Afișat în preview |
|
|
|----------|-------------------|
|
|
| `partner_name` | Furnizor |
|
|
| `cui` | CUI furnizor |
|
|
| `receipt_date` | Data |
|
|
| `receipt_number` | Nr. bon |
|
|
| `amount` | Total RON |
|
|
| `tva_total` | TVA RON |
|
|
|
|
---
|
|
|
|
## Teste
|
|
|
|
```bash
|
|
# Toate testele modulului Telegram
|
|
pytest backend/modules/telegram/tests/ -v
|
|
|
|
# Teste cu DB live Oracle
|
|
ORACLE_INTEGRATION_USER=MARIUSM_AUTO \
|
|
PASSWORD=ROMFASTSOFT \
|
|
DSN=10.0.20.121:1521/ROA \
|
|
pytest backend/modules/telegram/tests/ -v
|
|
|
|
# Doar testele E2E (necesită DB)
|
|
pytest backend/modules/telegram/tests/test_e2e_receipt_flow.py -v
|
|
```
|
|
|
|
**Stare teste (la merge):** 48 pass + 2 skipped (real DB, rulează cu env vars).
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Botul nu răspunde
|
|
|
|
- Verifică log: `tail -f /tmp/unified_backend_test.log`
|
|
- Verifică `MODULE_TELEGRAM_ENABLED=true` în `.env`
|
|
- Backend rulează cu `--workers 1`?
|
|
|
|
### OCR eșuat / timeout
|
|
|
|
- Worker pool se pre-warmează la pornire (~11 secunde)
|
|
- Dacă modifici `ocr_worker_process.py`, restart complet necesar (`./start.sh test stop && ./start.sh test`) — uvicorn --reload nu reîncarcă procesele separate
|
|
|
|
### Oracle write eșuat
|
|
|
|
- `ORA-01017`: credențiale incorecte — verifică `backend/secrets/<server_id>.oracle_pass`
|
|
- `ORA-00001`: bon duplicat (constraint unique)
|
|
- `ORA-28000`: user Oracle blocat — prea multe login-uri eșuate; DBA trebuie să deblocheze
|
|
- **Nu schimba** `secrets/*.oracle_pass` cât botul rulează — provoacă spam failed logins → ORA-28000
|
|
|
|
### SSH Tunnel warnings (inofensive în test)
|
|
|
|
```
|
|
[SSH-MONITOR] [vending] FAIL — Restart failed (code 1)
|
|
```
|
|
Normal în modul test dacă `sshpass` nu e instalat. Nu afectează funcționalitatea.
|