Files
solduri2roa/tests/test_integrare.py
Marius Mutu 7ac40f9a34 FDB: postarile direct pe sintetic raman brute; conturile 0/0 nu intra
Pe drumul FDB sinteticul e suma bruta a notelor, deci diferenta fata de
analitice se scrie cu D si C separat, nu pe net: rulajul 401 LACERTA iese ca
in SAGA (8.991,55 / 57.253,22). PDF/xls raman pe net (etalonul trece).
Conturile nepartener fara sold si fara rulaj (891) nu mai intra in xlsx.

LACERTA: 51/53 frunze identice cu REF; restul sunt asezari alese (5121,
4428), cu totaluri egale pe cont.

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

218 lines
8.3 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)
class TestAcontPeAnaliticePartener(unittest.TestCase):
"""Cont cu parteneri care are si analitice functionale (461.SGR) si parteneri
(461.RESTUL -> 461/1): cate un BALANTA per (cont, acont), FACTURA cu acelasi acont
(decizii_import.md pct. 16), postarea direct pe sintetic pe acontul de diferenta."""
ROWS = [
{"cont": "461", "denumire": "DEBITORI DIVERSI", "total_d": 350.0, "total_c": 0.0},
{"cont": "461.SGR", "denumire": "AMBALAJE SGR", "total_d": 100.0, "total_c": 0.0},
{"cont": "461.00001", "denumire": "PARTENER X", "total_d": 200.0, "total_c": 0.0},
]
MAPARE = {"461.SGR": {"cont": "461", "acont": "SGR"},
"461.00001": {"cont": "461", "acont": "1"}}
def test_balanta_si_factura_pe_acelasi_acont(self):
out, _, _, _, _ = genereaza_xlsx.genereaza(
self.ROWS, genereaza_xlsx.citeste_header(), 2026, 6, mapare=self.MAPARE)
bal = {(r["cont"], r["acont"]): r["totdeb"] for r in out if r["TIP"] == "BALANTA"}
fac = {(r["cont"], r["acont"]): (r["nume"], r["sold"])
for r in out if r["TIP"] == "FACTURA"}
self.assertEqual(bal, {("461", "SGR"): 100.0, ("461", "1"): 200.0,
("461", "9999"): 50.0})
self.assertEqual(fac, {("461", "SGR"): ("AMBALAJE SGR", 100.0),
("461", "1"): ("PARTENER X", 200.0)})
class TestDiferentaBrutaFdb(unittest.TestCase):
"""Pe drumul FDB postarile direct pe sintetic intra cu D si C brute (rulajul ca in
SAGA); pe PDF/xls raman pe net. Soldul e acelasi in ambele cazuri."""
ROWS = [
{"cont": "401", "denumire": "FURNIZORI", "total_d": 100.0, "total_c": 600.0},
{"cont": "401.0001", "denumire": "A", "total_d": 0.0, "total_c": 300.0},
{"cont": "891", "denumire": "BILANT DE DESCHIDERE", "total_d": 0.0, "total_c": 0.0},
]
def _balanta(self, brut):
out, _, _, _, _ = genereaza_xlsx.genereaza(
self.ROWS, genereaza_xlsx.citeste_header(), 2026, 6, brut=brut)
return {(r["cont"], r["acont"]): (r["totdeb"], r["totcred"])
for r in out if r["TIP"] == "BALANTA"}
def test_brut(self):
self.assertEqual(self._balanta(True), {("401", None): (100.0, 600.0)})
def test_net(self):
self.assertEqual(self._balanta(False), {("401", None): (0.0, 500.0)})