Files
roa2web-service-auto/backend/modules/data_entry/services/oracle_receipt_writer.py
Marius Mutu e257fa5d5f 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>
2026-06-05 09:26:58 +00:00

146 lines
4.8 KiB
Python

"""Shared helper for writing receipts to Oracle via PACK_CONTAFIN."""
import logging
from datetime import datetime
import oracledb
logger = logging.getLogger(__name__)
_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")
def _build_conn_params(oracle_cfg) -> dict:
if isinstance(oracle_cfg, dict):
return oracle_cfg
return {
"user": oracle_cfg.user,
"password": oracle_cfg.password,
"dsn": oracle_cfg.get_dsn(),
}
def write_receipt(receipt_dict: dict, oracle_cfg, *, commit: bool = True) -> tuple[int, str]:
"""Write a receipt to Oracle ACT_TEMP via PACK_CONTAFIN.
Args:
receipt_dict: Keys: partner_name, cui, receipt_date, receipt_number, amount, tva_total
oracle_cfg: Dict with user/password/dsn, OracleServerConfig instance, or
oracledb.Connection (pre-acquired from pool — caller manages lifecycle)
commit: If False, rolls back after FINALIZEAZA (dry-run mode)
Returns:
(cod, mesaj) — Oracle document code and result message from PACK_CONTAFIN
"""
if isinstance(oracle_cfg, oracledb.Connection):
conn = oracle_cfg
own_conn = False
else:
conn_params = _build_conn_params(oracle_cfg)
conn = oracledb.connect(**conn_params)
own_conn = True
cursor = conn.cursor()
try:
receipt_date = receipt_dict.get("receipt_date")
_now = datetime.now()
an = receipt_date.year if receipt_date else _now.year
luna = receipt_date.month if receipt_date else _now.month
act_date = receipt_date or _now.date()
id_util = 0
id_sucursala = 0
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,
])
# Globally unique document COD from sequence (NOT MAX+1 per period —
# that races and reuses CODs across (AN, LUNA) tuples).
cursor.execute("SELECT seq_cod.nextval FROM DUAL")
cod = cursor.fetchone()[0]
cui = receipt_dict.get("cui") or ""
cui_clean = cui.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(receipt_dict.get("amount") or 0)
tva = float(receipt_dict.get("tva_total") or 0)
fara_tva = total - tva
receipt_number = str(receipt_dict.get("receipt_number") or "")
nract = int(receipt_number) if receipt_number.isdigit() else 0
cont = _get_cont_cheltuiala(cui)
partner_name = receipt_dict.get("partner_name") or "N/A"
expl = f"OCR: {partner_name}"
lines = [
(cont, "401", fara_tva, expl, id_part, 0),
("401", "5311", total, f"Plata {expl}", 0, id_part),
]
if tva > 0:
lines.insert(1, ("4426", "401", tva, f"TVA {expl}", id_part, 0))
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=act_date, nract=nract,
expl=e, scd=scd, scc=scc, suma=suma,
id_partc=id_partc, id_partd=id_partd, id_util=id_util)
mesaj_var = 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_var,
])
mesaj = mesaj_var.getvalue() or ""
if commit:
conn.commit()
logger.info("write_receipt: saved COD=%s mesaj=%r", cod, mesaj)
else:
conn.rollback()
logger.info("write_receipt: dry-run rollback COD would be %s", cod)
return cod, mesaj
except Exception:
conn.rollback()
raise
finally:
cursor.close()
if own_conn:
conn.close()