feat(telegram): bot bonuri fiscale — OCR → preview → Oracle write

- US-001: mută queue_client.py în data_entry/services/ocr/
- US-002/003/004: oracle_receipt_writer + oracle_server_id în DB
- US-005: receipt_handlers.py (PDF/photo/callback flow)
- US-006: wire handlers în main.py, per-schema connect, seq_cod.nextval
- US-007: .gitignore secrets/*.oracle_pass
- US-008/009/010: teste unit + integration + E2E
- setup-secrets.sh helper + template
- docs/telegram/README.md actualizat cu arhitectura nouă

Testat E2E pe DB live (MARIUSM_AUTO). COD din seq_cod.nextval.
pypdfium2 fallback pentru PDF decode (fără poppler).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 09:26:58 +00:00
parent 8234103884
commit e257fa5d5f
35 changed files with 4531 additions and 227 deletions

View File

@@ -7,28 +7,17 @@ import sys
sys.path.insert(0, "/workspace/roa2web")
import asyncio
import oracledb
from datetime import datetime
from decimal import Decimal
from pathlib import Path
from backend.modules.data_entry.services.oracle_receipt_writer import write_receipt
ORACLE_CONFIG = {
"user": "MARIUSM_AUTO",
"password": "ROMFASTSOFT",
"dsn": "10.0.20.121:1521/ROA"
}
CUI_TO_CONT = {
"11201891": "6022", # MOL
"1590082": "6022", # OMV Petrom
"14991381": "6022", # MOL Romania
"10562600": "6021", # Dedeman
}
def get_cont_cheltuiala(cui: str) -> str:
cui_clean = cui.upper().replace("RO", "").strip()
return CUI_TO_CONT.get(cui_clean, "6028")
async def process_pdf(pdf_path: Path):
from backend.modules.data_entry.services.ocr_service import ocr_service
@@ -57,109 +46,27 @@ def save_to_oracle_with_pack(result, do_commit: bool = False):
mode = "SAVE" if do_commit else "DRY RUN"
print(f"\n[Oracle + PACK_CONTAFIN] {mode}")
print("-" * 50)
conn = oracledb.connect(**ORACLE_CONFIG)
cursor = conn.cursor()
receipt_dict = {
"partner_name": result.partner_name,
"cui": result.cui,
"receipt_date": result.receipt_date,
"receipt_number": result.receipt_number,
"amount": result.amount,
"tva_total": result.tva_total,
}
try:
an = result.receipt_date.year if result.receipt_date else datetime.now().year
luna = result.receipt_date.month if result.receipt_date else datetime.now().month
receipt_date = result.receipt_date or datetime.now().date()
# Parametri
id_util = 0 # ID utilizator implicit
id_sucursala = 0
# 1. INITIALIZEAZA
print("[1] INITIALIZEAZA_SCRIERE_ACT_RUL...")
cursor.callproc('PACK_CONTAFIN.INITIALIZEAZA_SCRIERE_ACT_RUL', [
id_util,
datetime.now(),
an,
luna,
0, # suprascriere_cod
0, # suprascriere_anluna
0, # scrie_sterge (0=scrie)
id_sucursala
])
print(" OK")
# Obține COD din secvență sau calculează
cursor.execute("SELECT NVL(MAX(COD), 0) + 1 FROM ACT WHERE AN = :an AND LUNA = :luna", an=an, luna=luna)
cod = cursor.fetchone()[0]
# Partner
cui_clean = (result.cui or "").upper().replace("RO", "").strip()
cursor.execute("SELECT ID_PART FROM NOM_PARTENERI WHERE COD_FISCAL = :cui OR COD_FISCAL = :cui2",
cui=cui_clean, cui2="RO"+cui_clean)
row = cursor.fetchone()
id_part = row[0] if row else 0
total = float(result.amount or 0)
tva = float(result.tva_total or 0)
fara_tva = total - tva
nract = int(result.receipt_number) if result.receipt_number and result.receipt_number.isdigit() else 0
cont = get_cont_cheltuiala(result.cui or "")
expl = f"OCR: {result.partner_name or 'N/A'}"
print(f" COD: {cod}, Partner ID: {id_part}, Cont: {cont}")
# 2. INSERT în ACT_TEMP
print("[2] INSERT ACT_TEMP...")
lines = [
(cont, "401", fara_tva, expl, id_part, 0), # cheltuială - partener pe credit
("401", "5311", total, f"Plata {expl}", 0, id_part), # plată - partener pe debit
]
if tva > 0:
lines.insert(1, ("4426", "401", tva, f"TVA {expl}", id_part, 0)) # TVA - partener pe credit
for scd, scc, suma, e, id_partc, id_partd in lines:
cursor.execute("""
INSERT INTO ACT_TEMP (
LUNA, AN, COD, DATAIREG, DATAACT, NRACT,
EXPLICATIA, SCD, SCC, SUMA,
ID_PARTC, ID_PARTD, ID_UTIL, DATAORA
) VALUES (
:luna, :an, :cod, TRUNC(SYSDATE), :dataact, :nract,
:expl, :scd, :scc, :suma,
:id_partc, :id_partd, :id_util, SYSDATE
)
""", luna=luna, an=an, cod=cod, dataact=receipt_date, nract=nract,
expl=e, scd=scd, scc=scc, suma=suma,
id_partc=id_partc, id_partd=id_partd, id_util=id_util)
print(f" {scd} = {scc}: {suma:.2f}")
# 3. FINALIZEAZA
print("[3] FINALIZEAZA_SCRIERE_ACT_RUL...")
mesaj = cursor.var(oracledb.STRING, 4000)
cursor.callproc('PACK_CONTAFIN.FINALIZEAZA_SCRIERE_ACT_RUL', [
id_util,
cod,
0, # scrie_sterge
0, # modificare_nota
0, # scrie_cump_vanz
mesaj
])
result_msg = mesaj.getvalue()
print(f" Mesaj: {result_msg}")
cod, mesaj = write_receipt(receipt_dict, ORACLE_CONFIG, commit=do_commit)
print(f" Mesaj: {mesaj}")
if do_commit:
conn.commit()
print(f"\n✅ SALVAT în Oracle (COD={cod})")
else:
conn.rollback()
print(f"\n⚠️ DRY RUN - rollback (COD ar fi fost {cod})")
return cod, result_msg
return cod, mesaj
except Exception as e:
print(f"❌ Eroare: {e}")
conn.rollback()
raise
finally:
cursor.close()
conn.close()
async def main():
if len(sys.argv) < 2: