Lane-urile citire-xlsx si mapare: cititorul de foaie SAGA si pasul de mapare
citire_xlsx.py citeste .xlsx (openpyxl) si .xls (xlrd) in acelasi contract intern
ca extract_balanta.py. Prima foaie, nu dupa nume; potrivire exacta a coloanelor,
niciodata pe substring (TOTAL_DEB vs TOTAL_DEB_1); CONT ramane text.
mapare.py: propunere automata, corectii_<FIRMA>.xlsx detinut de utilizator si
mapare_<FIRMA>.xlsx regenerat de unealta, .TOATE/.RESTUL in ordinea exact ->
RESTUL -> TOATE, redenumirea sinteticului. Se opreste cu eroare la cont/acont
peste 4 caractere, coliziune accidentala si cont_saga inexistent in corectii.
Corectat in orchestrare: .xls-ul SAGA nu are inregistrare CODEPAGE, deci xlrd
cadea pe iso-8859-1 si strica denumirile ("FURNIZORI \x97 DEBITORI"). Citirea se
face cu encoding_override="cp1250", cu o verificare in test care pica daca revine.
18 teste trec, inclusiv poarta de regresie pe etalon.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
This commit is contained in:
161
tests/test_mapare.py
Normal file
161
tests/test_mapare.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""Teste pentru mapare.py - propunere automata + corectii manuale.
|
||||
|
||||
Ruleaza pe date sintetice in director temporar; nu scrie mapare_*.xlsx /
|
||||
corectii_*.xlsx in radacina proiectului.
|
||||
|
||||
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 mapare
|
||||
|
||||
|
||||
def rand(cont, denumire="", sold=0.0):
|
||||
return {"cont": cont, "denumire": denumire, "sold": sold}
|
||||
|
||||
|
||||
class TestMapare(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self._tmp = tempfile.TemporaryDirectory(prefix="mapare_test_")
|
||||
self.dir = self._tmp.name
|
||||
|
||||
def tearDown(self):
|
||||
self._tmp.cleanup()
|
||||
|
||||
def _cale(self, nume):
|
||||
return os.path.join(self.dir, nume)
|
||||
|
||||
def _ruleaza(self, rows, firma="FIRMA"):
|
||||
return mapare.genereaza_mapare(rows, firma, self.dir)
|
||||
|
||||
def _scrie_corectii(self, randuri, firma="FIRMA"):
|
||||
cale = self._cale("corectii_%s.xlsx" % firma)
|
||||
wb = openpyxl.load_workbook(cale)
|
||||
ws = wb.active
|
||||
for r in randuri:
|
||||
ws.append(r)
|
||||
wb.save(cale)
|
||||
wb.close()
|
||||
|
||||
def _citeste_mapare(self, firma="FIRMA"):
|
||||
wb = openpyxl.load_workbook(self._cale("mapare_%s.xlsx" % firma))
|
||||
ws = wb.active
|
||||
header = [c.value for c in ws[1]]
|
||||
out = [dict(zip(header, [c.value for c in row]))
|
||||
for row in ws.iter_rows(min_row=2)]
|
||||
wb.close()
|
||||
return out
|
||||
|
||||
def test_corectie_supravietuieste_regenerarii(self):
|
||||
rows = [rand("2131.01", "CLADIRI", 100.0), rand("371.01", "MARFA", 50.0)]
|
||||
self._ruleaza(rows)
|
||||
cale = self._cale("corectii_FIRMA.xlsx")
|
||||
self.assertTrue(os.path.exists(cale))
|
||||
|
||||
self._scrie_corectii([["371.01", "3711", "99", "", "corectie marfa"]])
|
||||
inainte = pathlib.Path(cale).read_bytes()
|
||||
|
||||
rezultat = self._ruleaza(rows)
|
||||
dupa = pathlib.Path(cale).read_bytes()
|
||||
|
||||
self.assertEqual(inainte, dupa, "regenerarea a modificat corectii_*.xlsx")
|
||||
gasit = {r["cont_saga"]: r for r in rezultat}
|
||||
self.assertEqual(
|
||||
(gasit["371.01"]["cont"], gasit["371.01"]["acont"], gasit["371.01"]["sursa"]),
|
||||
("3711", "99", "CORECTAT"))
|
||||
self.assertEqual(gasit["2131.01"]["sursa"], "AUTO")
|
||||
|
||||
def test_ordine_exact_bate_restul_bate_toate(self):
|
||||
rows = [rand("409.01"), rand("409.02"), rand("409.03")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([
|
||||
["409.TOATE", "4091", "T", "", ""],
|
||||
["409.RESTUL", "4091", "R", "", ""],
|
||||
["409.01", "4091", "X", "", ""],
|
||||
])
|
||||
rezultat = self._ruleaza(rows)
|
||||
gasit = {r["cont_saga"]: (r["cont"], r["acont"]) for r in rezultat}
|
||||
self.assertEqual(gasit["409.01"], ("4091", "X"))
|
||||
self.assertEqual(gasit["409.02"], ("4091", "R"))
|
||||
self.assertEqual(gasit["409.03"], ("4091", "R"))
|
||||
|
||||
def test_toate_se_aplica_fara_exact(self):
|
||||
rows = [rand("2131.01"), rand("2131.02")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["2131.TOATE", "2131", "", "", ""]])
|
||||
rezultat = self._ruleaza(rows)
|
||||
for r in rezultat:
|
||||
self.assertEqual((r["cont"], r["acont"]), ("2131", None))
|
||||
self.assertEqual(r["sursa"], "CORECTAT")
|
||||
|
||||
def test_cont_saga_inexistent_da_eroare(self):
|
||||
rows = [rand("2131.01")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["9999.99", "9999", "99", "", "typo"]])
|
||||
with self.assertRaises(mapare.Stop):
|
||||
self._ruleaza(rows)
|
||||
|
||||
def test_coliziune_accidentala_da_eroare(self):
|
||||
rows = [rand("409.01"), rand("410.01")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([
|
||||
["409.01", "4091", "01", "", ""],
|
||||
["410.01", "4091", "01", "", ""],
|
||||
])
|
||||
with self.assertRaises(mapare.Stop):
|
||||
self._ruleaza(rows)
|
||||
|
||||
def test_colapsare_prin_toate_nu_da_eroare(self):
|
||||
rows = [rand("409.01"), rand("409.02")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["409.TOATE", "4091", "", "", "agregare intentionata"]])
|
||||
rezultat = self._ruleaza(rows)
|
||||
self.assertEqual([(r["cont"], r["acont"]) for r in rezultat],
|
||||
[("4091", None), ("4091", None)])
|
||||
|
||||
def test_redenumire_sintetic(self):
|
||||
rows = [rand("409"), rand("409.01")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["409.TOATE", "4091", "", "", "redenumire sintetic"]])
|
||||
rezultat = self._ruleaza(rows)
|
||||
gasit = {r["cont_saga"]: r["cont"] for r in rezultat}
|
||||
self.assertEqual(gasit["409"], "4091")
|
||||
self.assertEqual(gasit["409.01"], "4091")
|
||||
|
||||
def test_cont_prea_lung_da_eroare(self):
|
||||
rows = [rand("2131.01")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["2131.01", "12345", "01", "", ""]])
|
||||
with self.assertRaises(mapare.Stop):
|
||||
self._ruleaza(rows)
|
||||
|
||||
def test_acont_prea_lung_da_eroare(self):
|
||||
rows = [rand("2131.01")]
|
||||
self._ruleaza(rows)
|
||||
self._scrie_corectii([["2131.01", "2131", "12345", "", ""]])
|
||||
with self.assertRaises(mapare.Stop):
|
||||
self._ruleaza(rows)
|
||||
|
||||
def test_propunere_automata_si_partener(self):
|
||||
rows = [rand("1171.01.12"), rand("401.00002")]
|
||||
rezultat = mapare.aplica(rows, {}, parteneri={"401"})
|
||||
gasit = {r["cont_saga"]: r for r in rezultat}
|
||||
self.assertEqual((gasit["1171.01.12"]["cont"], gasit["1171.01.12"]["acont"]),
|
||||
("1171", "0112"))
|
||||
self.assertEqual((gasit["401.00002"]["cont"], gasit["401.00002"]["acont"]),
|
||||
("401", None))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user