"""Teste pentru citire_xlsx: contractul intern produs din foaia de calcul SAGA. Rulare: py -m unittest discover -s tests -v """ import os import pathlib 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 citire_xlsx EXEMPLE = RADACINA / "exemple" XLSX = EXEMPLE / "saga-sqlite-balanta-09-2026.xlsx" XLS = EXEMPLE / "saga-sqlite-balanta-09-2026.xls" DANUBE = RADACINA.parent / "saga2roa_danube" / "balanta.xls" TOL = 0.01 NUMERICE = ["prec_d", "prec_c", "rulaj_d", "rulaj_c", "total_d", "total_c", "sold_d", "sold_c"] def frunze(rows): """Randurile care nu sunt parintele niciunui alt cont din balanta.""" conts = [r["cont"] for r in rows if r["cont"]] parinti = {c.rsplit(".", 1)[0] for c in conts if "." in c} return [r for r in rows if r["cont"] and r["cont"] not in parinti] def scrie_xlsx(cale, antet, randuri): wb = openpyxl.Workbook() ws = wb.active ws.append(antet) for rand in randuri: ws.append(rand) wb.save(cale) wb.close() class TestCitireXlsx(unittest.TestCase): def _verifica_relatii(self, rows, eticheta): self.assertTrue(rows, "%s: nicio linie citita" % eticheta) for r in rows: self.assertAlmostEqual( r["total_d"], r["prec_d"] + r["rulaj_d"], delta=TOL, msg="%s %s: total_d != prec_d + rulaj_d" % (eticheta, r["cont"])) self.assertAlmostEqual( r["total_c"], r["prec_c"] + r["rulaj_c"], delta=TOL, msg="%s %s: total_c != prec_c + rulaj_c" % (eticheta, r["cont"])) self.assertAlmostEqual( r["sold_d"] - r["sold_c"], r["total_d"] - r["total_c"], delta=TOL, msg="%s %s: sold_d - sold_c != total_d - total_c" % (eticheta, r["cont"])) def _verifica_frunze(self, rows, eticheta): f = frunze(rows) sd = sum(r["sold_d"] for r in f) sc = sum(r["sold_c"] for r in f) self.assertAlmostEqual(sd, sc, delta=TOL, msg="%s: SUM(sold_d)=%s != SUM(sold_c)=%s" % (eticheta, sd, sc)) def test_xlsx_si_xls_identice(self): rows_xlsx = citire_xlsx.citeste_balanta(str(XLSX)) rows_xls = citire_xlsx.citeste_balanta(str(XLS)) self.assertTrue(rows_xlsx) self.assertEqual(len(rows_xlsx), len(rows_xls)) for a, b in zip(rows_xlsx, rows_xls): self.assertEqual(a["cont"], b["cont"]) self.assertEqual(a["denumire"], b["denumire"]) self.assertEqual(a["tip"], b["tip"]) for col in ("pagina", "este_total"): self.assertEqual(a[col], b[col]) for col in NUMERICE: self.assertAlmostEqual(a[col], b[col], delta=TOL, msg="%s %s: %s xlsx=%s xls=%s" % (a["cont"], col, a["cont"], a[col], b[col])) def test_relatii_si_frunze(self): for eticheta, cale in (("xlsx", XLSX), ("xls", XLS)): rows = citire_xlsx.citeste_balanta(str(cale)) self._verifica_relatii(rows, eticheta) self._verifica_frunze(rows, eticheta) def test_cont_ramane_text(self): for eticheta, cale in (("xlsx", XLSX), ("xls", XLS)): rows = citire_xlsx.citeste_balanta(str(cale)) for r in rows: self.assertIsInstance(r["cont"], str, "%s: cont nu e text" % eticheta) def test_danube_analitice(self): if not DANUBE.exists(): self.skipTest("lipseste %s" % DANUBE) rows = citire_xlsx.citeste_balanta(str(DANUBE)) self._verifica_relatii(rows, "danube") self._verifica_frunze(rows, "danube") analitice = [r for r in rows if "." in r["cont"]] self.assertTrue(analitice, "danube ar trebui sa aiba conturi analitice") for r in analitice: self.assertIsInstance(r["cont"], str, "cont analitic nu e text") # .xls-ul SAGA nu are CODEPAGE: fara encoding_override, xlrd cade pe iso-8859-1 # si denumirile ies cu caractere de control in loc de diacritice. stricate = [r["denumire"] for r in rows if any(ord(c) < 32 or 127 <= ord(c) < 160 for c in str(r["denumire"]))] self.assertEqual([], stricate, "denumiri decodate gresit (codepage)") cautat = [r for r in rows if r["cont"] == "105.10"] self.assertTrue(cautat, "lipseste contul analitic 105.10") self.assertIsInstance(cautat[0]["cont"], str) self.assertEqual(cautat[0]["cont"], "105.10") def test_cont_numeric_devine_text(self): with tempfile.TemporaryDirectory() as d: cale = os.path.join(d, "numeric.xlsx") scrie_xlsx( cale, ["CONT", "DENUMIRE", "TIP", "DEB_PREC", "CRED_PREC", "RULAJ_D", "RULAJ_C", "TOTAL_DEB", "TOTAL_CRED", "FIN_D", "FIN_C"], [[401.00002, "PARTENER", "P", 0, 0, 0, 0, 0, 100, 0, 100]], ) rows = citire_xlsx.citeste_balanta(cale) self.assertEqual(len(rows), 1) self.assertIsInstance(rows[0]["cont"], str) self.assertEqual(rows[0]["cont"], "401.00002") def test_coloana_lipsa_si_fara_substring(self): antet = ["CONT", "DENUMIRE", "TIP", "DEB_PREC", "CRED_PREC", "RULAJ_D", "RULAJ_C", "TOTAL_DEB_1", "TOTAL_CRED", "FIN_D", "FIN_C"] with tempfile.TemporaryDirectory() as d: cale = os.path.join(d, "lipsa.xlsx") scrie_xlsx(cale, antet, [["401", "FURNIZORI", "P", 0, 0, 0, 0, 0, 0, 0, 0]]) with self.assertRaises(ValueError) as cm: citire_xlsx.citeste_balanta(cale) self.assertIn("TOTAL_DEB", str(cm.exception)) if __name__ == "__main__": unittest.main()