Files
solduri2roa/tests/test_citire_fdb.py
Marius Mutu b5773c9822 Decizii LACERTA: data = ultima zi, 542 cu parteneri, 4428/01, backup .fbk
- genereaza_xlsx: coloana data = ultima zi a lunii; etalonul de regresie
  actualizat doar pe aceasta coloana (verificat celula cu celula).
- config: 542 cont cu parteneri (acum identic cu REF); descrierea lui 4092
  corectata.
- extrage/citire_fdb: .fbk se restaureaza cu gbak -c in temporar; test ca
  da aceleasi fisiere ca FDB-ul.
- test_lacerta: 49/53 frunze identice cu REF, 4428.TOATE -> 4428/01.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
2026-09-27 16:43:54 +03:00

151 lines
6.1 KiB
Python

"""Teste pentru citire_fdb: balanta din Firebird identica cu exportul .xlsx.
Poarta: `balanta` produsa din copia unei baze `CONT_BAZA.FDB` trebuie sa fie
identica (pana la octet) cu cea produsa de `citire_xlsx.py` din exportul de foaie
de calcul, pe firma de joaca, luna 09/2026. Baza originala NU se deschide: se
copiaza intr-un director temporar.
Pe o masina fara SAGA (fara fbclient.dll, baza, driver sau export) testele se
sar, nu esueaza.
Rulare: py -m unittest discover -s tests -v
"""
import os
import subprocess
import pathlib
import shutil
import sys
import tempfile
import unittest
RADACINA = pathlib.Path(__file__).resolve().parent.parent
if str(RADACINA) not in sys.path:
sys.path.insert(0, str(RADACINA))
import citire_fdb
import citire_xlsx
FBCLIENT = pathlib.Path(r"C:\Program Files\Firebird\Firebird30_Saga\fbclient.dll")
BAZA = pathlib.Path(r"D:\SAGA250909\0001\CONT_BAZA.FDB")
XLSX = RADACINA / "exemple" / "saga-sqlite-balanta-09-2026.xlsx"
AN, LUNA = 2026, 9
TOL = 0.01
def _driver_disponibil():
try:
import firebird.driver # noqa: F401
return True
except Exception:
return False
class TestCitireFdb(unittest.TestCase):
@classmethod
def setUpClass(cls):
if not FBCLIENT.exists():
raise unittest.SkipTest("lipseste fbclient.dll: %s" % FBCLIENT)
if not BAZA.exists():
raise unittest.SkipTest("lipseste baza Firebird: %s" % BAZA)
if not _driver_disponibil():
raise unittest.SkipTest("lipseste pachetul firebird-driver")
cls._tmp = tempfile.TemporaryDirectory(prefix="citire_fdb_")
cls.baza = os.path.join(cls._tmp.name, "CONT_BAZA.FDB")
shutil.copy2(str(BAZA), cls.baza)
cls.dir = cls._tmp.name
@classmethod
def tearDownClass(cls):
cls._tmp.cleanup()
def test_poarta_identica_cu_xlsx(self):
if not XLSX.exists():
self.skipTest("lipseste exportul %s" % XLSX)
rows_xlsx = citire_xlsx.citeste_balanta(str(XLSX))
# exportul firmei de joaca e fara analitice; cititorul le emite si pe ele
rows_fdb = [r for r in citire_fdb.citeste_balanta(self.baza, AN, LUNA)
if "." not in r["cont"]]
self.assertTrue(rows_xlsx, "exportul xlsx nu are randuri")
self.assertEqual(rows_xlsx, rows_fdb,
"balanta din FDB difera de exportul xlsx")
# comparatie stricta: acelasi fisier CSV, la octet
cale_xlsx = os.path.join(self.dir, "din_xlsx.csv")
cale_fdb = os.path.join(self.dir, "din_fdb.csv")
citire_xlsx.scrie_csv(rows_xlsx, cale_xlsx)
citire_fdb.scrie_csv(rows_fdb, cale_fdb, citire_fdb.COLOANE_BALANTA)
with open(cale_xlsx, "rb") as f:
a = f.read()
with open(cale_fdb, "rb") as f:
b = f.read()
self.assertEqual(a, b, "CSV-urile difera la nivel de octet")
def test_sum_registru_egal_netul_balantei(self):
d_an, d_luna, d_urm = citire_fdb._limite(AN, LUNA)
con = citire_fdb._conecteaza(self.baza)
try:
deb, cred = citire_fdb._select(
con,
"SELECT "
"SUM(CASE WHEN TRIM(CONT_D) NOT IN ('', '%') THEN SUMA ELSE 0 END), "
"SUM(CASE WHEN TRIM(CONT_C) NOT IN ('', '%') THEN SUMA ELSE 0 END) "
"FROM REGISTRU WHERE DATA < ?", (d_urm,))[0]
finally:
con.rollback()
con.close()
self.assertAlmostEqual(float(deb), float(cred), delta=TOL,
msg="SUM(REGISTRU) nu e echilibrat pe laturi")
rows = citire_fdb.citeste_balanta(self.baza, AN, LUNA)
net_balanta = sum(r["total_d"] - r["total_c"] for r in rows
if "." not in r["cont"])
self.assertAlmostEqual(float(deb) - float(cred), net_balanta, delta=TOL,
msg="netul din REGISTRU != netul balantei")
def test_scadent_null_cade_pe_ultima_zi_a_lunii(self):
rows = citire_fdb.citeste_facturi(self.baza, AN, LUNA)
self.assertTrue(rows, "nu s-au citit facturi")
asteptat = citire_fdb._ultima_zi(AN, LUNA).isoformat()
# singura factura din firma de joaca are SCADENT NULL in INTRD
self.assertEqual(rows[0]["scadent"], asteptat)
def test_fbk_identic_cu_fdb(self):
"""Backupul gbak (.fbk) se restaureaza in temporar si da aceleasi fisiere."""
fbk = os.path.join(self.dir, "firma.fbk")
subprocess.run([citire_fdb.GBAK, "-b", self.baza, fbk, "-user",
citire_fdb.UTILIZATOR, "-password", citire_fdb.PAROLA], check=True)
a = citire_fdb.produce(self.baza, "A", AN, LUNA, os.path.join(self.dir, "a"))
b = citire_fdb.produce(fbk, "B", AN, LUNA, os.path.join(self.dir, "b"))
self.assertEqual(a, b)
def test_cont_colector_exclus(self):
rows = citire_fdb.citeste_balanta(self.baza, AN, LUNA)
self.assertNotIn("%", [r["cont"] for r in rows])
self.assertTrue(all(r["cont"] for r in rows), "rand fara cont")
def test_parteneri_si_facturi(self):
parteneri = citire_fdb.citeste_parteneri(self.baza)
self.assertTrue(parteneri, "nu s-au citit parteneri")
for r in parteneri:
self.assertTrue(r["cont_analitic"])
self.assertTrue(r["cod_fiscal"],
"cod fiscal gol pentru %s" % r["cont_analitic"])
# Codul fiscal lipsa in SAGA cade pe contul analitic (citire_fdb.py). Pe firma
# de joaca ROMFAST (401.00001) nu are COD_FISCAL, TRANSPORT (401.00002) are CUI
# real. Asta dovedeste ca drumul FDB NU scuteste de etapa 5b (cautarea ANAF).
provizorii = {r["cont_analitic"] for r in parteneri
if r["cod_fiscal"] == r["cont_analitic"]}
self.assertEqual(provizorii, {"401.00001"},
"s-a schimbat setul de parteneri fara CUI real")
facturi = citire_fdb.citeste_facturi(self.baza, AN, LUNA)
for r in facturi:
self.assertTrue(r["cont_analitic"])
self.assertTrue(r["scadent"])
if __name__ == "__main__":
unittest.main()