diff --git a/README.md b/README.md index c2ab6ae..44ed5f1 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ automat in temporar. ## Corectii (`corectii_FIRMA.xlsx`) Coloane: `cont_saga`, `cont`, `acont`, `exclus`, `motiv`. `cont` are maxim 4 caractere, -`acont` la fel. +`acont` la fel. `exclus` = da scoate contul din import, cu tot cu analiticele lui. | `cont_saga` | se aplica la | |---|---| @@ -70,6 +70,8 @@ un rand BALANTA pe fiecare acont, cu facturile lui. - Data soldurilor este ultima zi a lunii (`30.06.2026` pentru `--luna 6`). - Diferenta dintre sintetic si suma analiticelor (note puse direct pe sintetic) iese pe un analitic de diferenta (`9999`, `99`) sau, la parteneri, pe `NEREPARTIZAT` in ROA. + Din FDB intra cu debitul si creditul brute (rulaj ca in SAGA); din PDF/xls, pe net. +- Conturile fara sold si fara rulaj nu intra in xlsx. - Nu ajusta cifre ca sa treaca o verificare. Raporteaza. ## Teste diff --git a/docs/analiza_lacerta_fdb.md b/docs/analiza_lacerta_fdb.md index ef33a04..5b9d367 100644 --- a/docs/analiza_lacerta_fdb.md +++ b/docs/analiza_lacerta_fdb.md @@ -133,9 +133,14 @@ Corectiile folosite (in test, ca in REF): `419.NETOPIA -> 419 / 2`, `4428.TOATE dar fara note: cele 2.250 de pe 461 sunt postate doar pe sintetic. Cazul mixt e acoperit de `tests/test_integrare.py::TestAcontPeAnaliticePartener`. -Frunze BALANTA identice cu REF dupa aceste decizii: **50 din 53**. +6. 401: notele direct pe sintetic intra brute pe drumul FDB, deci rulajul e identic cu SAGA. + Randurile 0 / 0 (`891`) nu mai intra. + +Frunze BALANTA identice cu REF dupa aceste decizii: **51 din 53**. Diferentele ramase: +`5121` pe banci (regula de banca) si `4428` pe `01` + `99` (decizie), cu totaluri egale pe cont. +Separat, doua sume pe care REF le-a pierdut: `4092/99` = 1.563,37 si `419/9999` = 900,00. ## Starea pe disc Cod: `citire_fdb.py` (P1-P3), `tests/test_citire_fdb.py` (poarta restransa la sintetice), `tests/test_lacerta.py` (P4), `.gitignore` (P5). Suita: `py -m unittest discover -s tests`, -39 de teste, toate trec. Fisierele LACERTA din `exemple/` sunt ignorate de git. +41 de teste, toate trec. Fisierele LACERTA din `exemple/` sunt ignorate de git. diff --git a/docs/decizii_import.md b/docs/decizii_import.md index ee4d3a0..bf25edf 100644 --- a/docs/decizii_import.md +++ b/docs/decizii_import.md @@ -134,6 +134,11 @@ Consecinte: `(cont, acont)`. FACTURA are acelasi `acont` (pct. 16), iar partenerul unui analitic functional poarta numele analiticului. Postarile direct pe sintetic merg pe acontul de diferenta, ca la banca. Fara astfel de corectii, comportamentul e cel de dinainte. +- Pe drumul FDB postarile direct pe sintetic intra cu D si C **brute**, nu pe net: acolo + sinteticul e suma bruta a notelor, deci rulajul iese ca in SAGA (401 LACERTA: 8.991,55 / + 57.253,22). Daca o latura ar iesi negativa, se revine la net. PDF/xls raman pe net + (pct. 13), pentru ca SAGA neteaza deja sinteticul in raport. +- Conturile nepartener cu 0 / 0 (fara sold si fara rulaj, ex. `891`) nu intra in xlsx. ## Divergenta fata de CONFIG_CONT_IREG (constatata 21.09.2026) diff --git a/genereaza.py b/genereaza.py index bc46c31..4af8b3b 100644 --- a/genereaza.py +++ b/genereaza.py @@ -92,7 +92,9 @@ def main(): out, diffs, leaf_map, leaf_rep, negative = generator.genereaza( rows, header, an=a.an, luna=a.luna, mapare=override, - parteneri=parteneri, facturi=facturi) + parteneri=parteneri, facturi=facturi, + # drumul FDB (exista parteneri_): postarile direct pe sintetic raman brute + brut=os.path.exists(os.path.join(a.dir, "parteneri_%s.csv" % a.firma))) xlsx_path = os.path.join(a.dir_iesire, "init_%s_%d_%d.xlsx" % (a.firma, a.an, a.luna)) diff --git a/genereaza_xlsx.py b/genereaza_xlsx.py index b5e0807..0cf4d1a 100644 --- a/genereaza_xlsx.py +++ b/genereaza_xlsx.py @@ -218,11 +218,29 @@ def _iso(s): return None +def diferente_dc(by, children, diffs, brut): + """{parinte: (D, C)} al postarilor direct pe sintetic. Pe net (ca pana acum), sau, + cu brut=True (drumul FDB, unde sinteticul e suma bruta a tuturor notelor), cu D si C + separat, ca rulajul sa ramana cel din SAGA. Daca vreo latura iese negativa (netarea + soldului initial pe analitic), se revine la net.""" + out = {} + for cont, d in diffs: + out[cont] = (d, 0.0) if d > 0 else (0.0, -d) + if brut: + for cont, kids in children.items(): + dd = round(by[cont]["total_d"] - sum(by[k]["total_d"] for k in kids), 2) + dc = round(by[cont]["total_c"] - sum(by[k]["total_c"] for k in kids), 2) + if dd >= 0 and dc >= 0 and (dd > 0.005 or dc > 0.005): + out[cont] = (dd, dc) + return out + + def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, - facturi=None): + facturi=None, brut=False): by, children = arbore(rows) diffs = diferente(by, children) diff_by_parent = dict(diffs) + dif = diferente_dc(by, children, diffs, brut) # parteneri/facturi reale (doar pe drumul FDB); lipsa = comportamentul de azi part_map = {} @@ -299,6 +317,9 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, for r in rows: if este_partener(r["cont"]) or r["cont"] in children: continue + if round(r["total_d"], 2) == 0 and round(r["total_c"], 2) == 0: + leaf_rep.add(r["cont"]) # fara sold si fara rulaj: nimic de importat + continue cont4, ac = split_cont(r["cont"]) cont4, ac = _mapare_cont(r["cont"], cont4, ac, mapare, partener=False) add(rand(header, an, luna, TIP="BALANTA", cont=cont4, acont=ac, numar=1, @@ -307,14 +328,13 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, # A. analitic de diferenta pe parinte nepartener (postare directa pe sintetic). # Randurile de diferenta raman calculate aici, nu trec prin mapare. - for cont, d in diffs: + for cont, (dd, dc) in dif.items(): if este_partener(cont): continue ac = acont_diferenta(cont, children[cont]) add(rand(header, an, luna, TIP="BALANTA", cont=cont.split(".")[0], acont=ac, numar=1, nume="DIFERENTA SINTETIC SAGA", - totdeb=d if d > 0 else None, - totcred=-d if d < 0 else None)) + totdeb=dd or None, totcred=dc or None)) parteneri_activi = sorted({c.split(".")[0] for c in by if este_partener(c)}) for p in parteneri_activi: @@ -343,18 +363,17 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, continue sold = abs(net) if este_latura_formular(net, side) else -abs(net) factura(k, cont_k, kac, kd["denumire"], side, net, sold, None) - if p in diff_by_parent: - d = diff_by_parent[p] + if p in dif: + dd, dc = dif[p] ac = acont_diferenta(p, direct) add(rand(header, an, luna, TIP="BALANTA", cont=p, acont=ac, numar=1, nume="DIFERENTA SINTETIC SAGA", - totdeb=d if d > 0 else None, - totcred=-d if d < 0 else None)) + totdeb=dd or None, totcred=dc or None)) continue # 401/4092/4111/461/462/4551 si 5311 if direct: - d = diff_by_parent.get(p, 0.0) + dd, dc = dif.get(p, (0.0, 0.0)) cont_p, ac_p = _mapare_cont(p, p, None, mapare, True) def baza(kids): @@ -397,12 +416,11 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, add(rand(header, an, luna, TIP="BALANTA", cont=cont_g, acont=ac_g, numar=1, nume=nume, totdeb=round(bd, 2), totcred=round(bc, 2))) facturi(kids, cont_g, ac_g) - if d: + if dd or dc: add(rand(header, an, luna, TIP="BALANTA", cont=cont_p, acont=acont_diferenta(p, direct), numar=1, nume="DIFERENTA SINTETIC SAGA", - totdeb=d if d > 0 else None, - totcred=-d if d < 0 else None)) + totdeb=dd or None, totcred=dc or None)) continue base_d, base_c = baza(direct) @@ -419,8 +437,8 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None, cont_p = variante.pop() add(rand(header, an, luna, TIP="BALANTA", cont=cont_p, acont=ac_p, numar=1, nume=by[p]["denumire"], - totdeb=round(base_d + (d if d > 0 else 0.0), 2), - totcred=round(base_c + (-d if d < 0 else 0.0), 2))) + totdeb=round(base_d + dd, 2), + totcred=round(base_c + dc, 2))) facturi(direct, cont_p, ac_p) else: net = round(by[p]["total_d"] - by[p]["total_c"], 2) diff --git a/tests/test_integrare.py b/tests/test_integrare.py index 36b6e9e..f072481 100644 --- a/tests/test_integrare.py +++ b/tests/test_integrare.py @@ -192,3 +192,26 @@ class TestAcontPeAnaliticePartener(unittest.TestCase): ("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)}) diff --git a/tests/test_lacerta.py b/tests/test_lacerta.py index 8d2f64b..98fcb76 100644 --- a/tests/test_lacerta.py +++ b/tests/test_lacerta.py @@ -46,8 +46,6 @@ CORECTII = [ # frunza -> (REF, NOI), cu (totdeb, totcred); None = frunza lipseste DIFERENTE_ASTEPTATE = { - # postarile direct pe sinteticul 401 intra pe net (regula stabilita), deci rulajul scade - ("401", ""): ((8991.55, 57253.22), (5536.75, 53798.42)), # 4092: note direct pe sintetic -> acont de diferenta; REF le-a pierdut ("4092", "99"): (None, (1563.37, 0.0)), # nota de 900 direct pe 419: analitic de diferenta; REF a pierdut-o @@ -61,8 +59,6 @@ DIFERENTE_ASTEPTATE = { ("5121", ""): ((40801.41, 35876.25), None), ("5121", "1"): (None, (40601.41, 35876.25)), ("5121", "2"): (None, (200.0, 0.0)), - # 891 are rulaj zero; REF nu-l scrie - ("891", ""): (None, (0.0, 0.0)), }