date/ - intrari de la client (PDF-urile, exportul SAGA) si balanta intermediara iesiri/ - xlsx-urile generate si verificare_<FIRMA>.md (ignorat de git) sablon/ - sablonul ROA Punctele de intrare scriu acolo implicit: extrage.py --dir=date, genereaza.py citeste din date/ si scrie in iesiri/ (--dir-iesire), ca radacina sa nu se murdareasca la fiecare rulare. Sablonul e cautat langa script, in sablon/. Actualizate: TEMPLATE, cele trei teste care tin caile, .gitignore, CLAUDE.md si handoff-ul. Poarta capat-la-capat incepuse sa sara tacut dupa mutarea PDF-urilor (skipTest pe "lipsesc PDF-urile"); acum arata din nou catre date/ si ruleaza. 33 de teste trec, zero skip-uri. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
170 lines
6.0 KiB
Python
170 lines
6.0 KiB
Python
"""Test de integrare: capat-la-capat pe firma de joaca, din ambele surse.
|
|
|
|
Ruleaza `extrage.py` apoi `genereaza.py` in directoare temporare (nu scrie nimic in
|
|
radacina proiectului), din:
|
|
- exportul de foaie de calcul SAGA (exemple/saga-sqlite-balanta-09-2026.xlsx);
|
|
- copia bazei Firebird D:\\SAGA250909\\0001\\CONT_BAZA.FDB.
|
|
|
|
Verifica: xlsx-ul de import exista, are randuri de date si SUM(totdeb) = SUM(totcred).
|
|
|
|
Pe o masina fara baza / fbclient.dll / driver, teste FDB se sar, nu esueaza.
|
|
|
|
Rulare: py -m unittest discover -s tests -v
|
|
"""
|
|
import os
|
|
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
import openpyxl
|
|
|
|
RADACINA = pathlib.Path(__file__).resolve().parent.parent
|
|
if str(RADACINA) not in sys.path:
|
|
sys.path.insert(0, str(RADACINA))
|
|
|
|
import extrage
|
|
import genereaza_xlsx
|
|
|
|
EXTRAGE = RADACINA / "extrage.py"
|
|
GENEREAZA = RADACINA / "genereaza.py"
|
|
XLSX_EXEMPLU = RADACINA / "exemple" / "saga-sqlite-balanta-09-2026.xlsx"
|
|
FBCLIENT = pathlib.Path(r"C:\Program Files\Firebird\Firebird30_Saga\fbclient.dll")
|
|
BAZA = pathlib.Path(r"D:\SAGA250909\0001\CONT_BAZA.FDB")
|
|
|
|
FIRMA = "JOACA"
|
|
AN, LUNA = 2026, 9
|
|
TOL = 0.01
|
|
|
|
|
|
def _driver_disponibil():
|
|
try:
|
|
import firebird.driver # noqa: F401
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def _ruleaza(script, arg, dir_iesire):
|
|
"""Ruleaza un punct de intrare cu `--dir` in directorul temporar si verificat.
|
|
|
|
genereaza.py scrie implicit in iesiri/; in test totul sta in acelasi temporar.
|
|
"""
|
|
iesire = ["--dir-iesire", str(dir_iesire)] if script.name == "genereaza.py" else []
|
|
return subprocess.run(
|
|
[sys.executable, str(script), "--firma", FIRMA,
|
|
"--an", str(AN), "--luna", str(LUNA), "--dir", str(dir_iesire)]
|
|
+ iesire + arg,
|
|
cwd=str(dir_iesire), capture_output=True, text=True)
|
|
|
|
|
|
def _sume_xlsx(cale):
|
|
wb = openpyxl.load_workbook(cale)
|
|
try:
|
|
ws = wb.active
|
|
header = [c.value for c in ws[1]]
|
|
i_deb = header.index("totdeb")
|
|
i_cred = header.index("totcred")
|
|
deb = cred = 0.0
|
|
if ws.max_row > 1:
|
|
for row in ws.iter_rows(min_row=2, values_only=True):
|
|
deb += row[i_deb] or 0
|
|
cred += row[i_cred] or 0
|
|
return ws.max_row, deb, cred
|
|
finally:
|
|
wb.close()
|
|
|
|
|
|
class TestIntegrare(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self._tmp = tempfile.TemporaryDirectory(prefix="integrare_")
|
|
self.dir = pathlib.Path(self._tmp.name)
|
|
|
|
def tearDown(self):
|
|
self._tmp.cleanup()
|
|
|
|
def _flux(self, sursa, fisier):
|
|
r = _ruleaza(EXTRAGE, ["--sursa", sursa, "--fisier", str(fisier)], self.dir)
|
|
self.assertEqual(r.returncode, 0, "extrage.py a picat:\n%s\n%s"
|
|
% (r.stdout, r.stderr))
|
|
self.assertTrue((self.dir / ("balanta_%s.csv" % FIRMA)).exists(),
|
|
"extrage.py nu a scris balanta")
|
|
|
|
r = _ruleaza(GENEREAZA, [], self.dir)
|
|
self.assertEqual(r.returncode, 0, "genereaza.py a picat:\n%s\n%s"
|
|
% (r.stdout, r.stderr))
|
|
|
|
xlsx = self.dir / ("init_%s_%d_%d.xlsx" % (FIRMA, AN, LUNA))
|
|
self.assertTrue(xlsx.exists(), "lipseste xlsx-ul de import: %s" % xlsx)
|
|
n, deb, cred = _sume_xlsx(xlsx)
|
|
self.assertGreater(n, 1, "xlsx-ul de import nu are randuri de date")
|
|
self.assertAlmostEqual(deb, cred, delta=TOL,
|
|
msg="SUM(totdeb)=%s != SUM(totcred)=%s" % (deb, cred))
|
|
return xlsx
|
|
|
|
def test_capat_la_capat_xlsx(self):
|
|
if not XLSX_EXEMPLU.exists():
|
|
self.skipTest("lipseste exportul %s" % XLSX_EXEMPLU)
|
|
self._flux("xlsx", XLSX_EXEMPLU)
|
|
|
|
def test_capat_la_capat_fdb(self):
|
|
if not FBCLIENT.exists():
|
|
self.skipTest("lipseste fbclient.dll: %s" % FBCLIENT)
|
|
if not BAZA.exists():
|
|
self.skipTest("lipseste baza Firebird: %s" % BAZA)
|
|
if not _driver_disponibil():
|
|
self.skipTest("lipseste pachetul firebird-driver")
|
|
copie = self.dir / "CONT_BAZA.FDB"
|
|
shutil.copy2(str(BAZA), str(copie))
|
|
self._flux("fdb", copie)
|
|
|
|
|
|
class TestDispecerSursa(unittest.TestCase):
|
|
|
|
def test_deducere_din_extensie(self):
|
|
self.assertEqual(extrage.deduce_sursa("balanta.pdf"), "pdf")
|
|
self.assertEqual(extrage.deduce_sursa("balanta.xls"), "xlsx")
|
|
self.assertEqual(extrage.deduce_sursa("balanta.XLSX"), "xlsx")
|
|
self.assertEqual(extrage.deduce_sursa("CONT_BAZA.FDB"), "fdb")
|
|
|
|
def test_extensie_necunoscuta_da_eroare(self):
|
|
with self.assertRaises(SystemExit):
|
|
extrage.deduce_sursa("balanta.csv")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|
|
|
|
|
|
class TestMapareSinteticPartener(unittest.TestCase):
|
|
"""Analiticele unui cont cu parteneri nu au voie sa cada pe conturi diferite:
|
|
BALANTA e agregat pe sintetic, FACTURA e per analitic, iar o redenumire
|
|
partiala ar rupe tacit corespondenta dintre ele."""
|
|
|
|
ROWS = [
|
|
{"cont": "401", "denumire": "FURNIZORI", "total_d": 0.0, "total_c": 300.0},
|
|
{"cont": "401.0001", "denumire": "A", "total_d": 0.0, "total_c": 100.0},
|
|
{"cont": "401.0002", "denumire": "B", "total_d": 0.0, "total_c": 200.0},
|
|
]
|
|
|
|
def setUp(self):
|
|
self.header = genereaza_xlsx.citeste_header()
|
|
|
|
def test_conturi_diferite_dau_eroare(self):
|
|
mapare = {"401.0001": {"cont": "4011", "acont": None},
|
|
"401.0002": {"cont": "4012", "acont": None}}
|
|
with self.assertRaises(genereaza_xlsx.Stop) as ctx:
|
|
genereaza_xlsx.genereaza(self.ROWS, self.header, 2025, 12, mapare=mapare)
|
|
self.assertIn("conturi diferite", str(ctx.exception))
|
|
|
|
def test_acelasi_cont_pe_toate_analiticele_e_legal(self):
|
|
mapare = {"401.0001": {"cont": "4011", "acont": None},
|
|
"401.0002": {"cont": "4011", "acont": None}}
|
|
out, _, _, _, _ = genereaza_xlsx.genereaza(self.ROWS, self.header, 2025, 12,
|
|
mapare=mapare)
|
|
conturi = {r["cont"] for r in out}
|
|
self.assertEqual({"4011"}, conturi)
|