"""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()