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
This commit is contained in:
2026-09-27 16:58:46 +03:00
parent d188c76c7f
commit 7ac40f9a34
7 changed files with 73 additions and 22 deletions

View File

@@ -46,7 +46,7 @@ automat in temporar.
## Corectii (`corectii_FIRMA.xlsx`) ## Corectii (`corectii_FIRMA.xlsx`)
Coloane: `cont_saga`, `cont`, `acont`, `exclus`, `motiv`. `cont` are maxim 4 caractere, 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 | | `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`). - 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 - 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. 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. - Nu ajusta cifre ca sa treaca o verificare. Raporteaza.
## Teste ## Teste

View File

@@ -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 dar fara note: cele 2.250 de pe 461 sunt postate doar pe sintetic. Cazul mixt e acoperit
de `tests/test_integrare.py::TestAcontPeAnaliticePartener`. 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 ## Starea pe disc
Cod: `citire_fdb.py` (P1-P3), `tests/test_citire_fdb.py` (poarta restransa la sintetice), 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`, `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.

View File

@@ -134,6 +134,11 @@ Consecinte:
`(cont, acont)`. FACTURA are acelasi `acont` (pct. 16), iar partenerul unui analitic `(cont, acont)`. FACTURA are acelasi `acont` (pct. 16), iar partenerul unui analitic
functional poarta numele analiticului. Postarile direct pe sintetic merg pe acontul de 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. 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) ## Divergenta fata de CONFIG_CONT_IREG (constatata 21.09.2026)

View File

@@ -92,7 +92,9 @@ def main():
out, diffs, leaf_map, leaf_rep, negative = generator.genereaza( out, diffs, leaf_map, leaf_rep, negative = generator.genereaza(
rows, header, an=a.an, luna=a.luna, mapare=override, 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" xlsx_path = os.path.join(a.dir_iesire, "init_%s_%d_%d.xlsx"
% (a.firma, a.an, a.luna)) % (a.firma, a.an, a.luna))

View File

@@ -218,11 +218,29 @@ def _iso(s):
return None 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, def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None,
facturi=None): facturi=None, brut=False):
by, children = arbore(rows) by, children = arbore(rows)
diffs = diferente(by, children) diffs = diferente(by, children)
diff_by_parent = dict(diffs) diff_by_parent = dict(diffs)
dif = diferente_dc(by, children, diffs, brut)
# parteneri/facturi reale (doar pe drumul FDB); lipsa = comportamentul de azi # parteneri/facturi reale (doar pe drumul FDB); lipsa = comportamentul de azi
part_map = {} part_map = {}
@@ -299,6 +317,9 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None,
for r in rows: for r in rows:
if este_partener(r["cont"]) or r["cont"] in children: if este_partener(r["cont"]) or r["cont"] in children:
continue 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 = split_cont(r["cont"])
cont4, ac = _mapare_cont(r["cont"], cont4, ac, mapare, partener=False) cont4, ac = _mapare_cont(r["cont"], cont4, ac, mapare, partener=False)
add(rand(header, an, luna, TIP="BALANTA", cont=cont4, acont=ac, numar=1, 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). # A. analitic de diferenta pe parinte nepartener (postare directa pe sintetic).
# Randurile de diferenta raman calculate aici, nu trec prin mapare. # 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): if este_partener(cont):
continue continue
ac = acont_diferenta(cont, children[cont]) ac = acont_diferenta(cont, children[cont])
add(rand(header, an, luna, TIP="BALANTA", cont=cont.split(".")[0], acont=ac, add(rand(header, an, luna, TIP="BALANTA", cont=cont.split(".")[0], acont=ac,
numar=1, nume="DIFERENTA SINTETIC SAGA", numar=1, nume="DIFERENTA SINTETIC SAGA",
totdeb=d if d > 0 else None, totdeb=dd or None, totcred=dc or None))
totcred=-d if d < 0 else None))
parteneri_activi = sorted({c.split(".")[0] for c in by if este_partener(c)}) parteneri_activi = sorted({c.split(".")[0] for c in by if este_partener(c)})
for p in parteneri_activi: for p in parteneri_activi:
@@ -343,18 +363,17 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None,
continue continue
sold = abs(net) if este_latura_formular(net, side) else -abs(net) sold = abs(net) if este_latura_formular(net, side) else -abs(net)
factura(k, cont_k, kac, kd["denumire"], side, net, sold, None) factura(k, cont_k, kac, kd["denumire"], side, net, sold, None)
if p in diff_by_parent: if p in dif:
d = diff_by_parent[p] dd, dc = dif[p]
ac = acont_diferenta(p, direct) ac = acont_diferenta(p, direct)
add(rand(header, an, luna, TIP="BALANTA", cont=p, acont=ac, numar=1, add(rand(header, an, luna, TIP="BALANTA", cont=p, acont=ac, numar=1,
nume="DIFERENTA SINTETIC SAGA", nume="DIFERENTA SINTETIC SAGA",
totdeb=d if d > 0 else None, totdeb=dd or None, totcred=dc or None))
totcred=-d if d < 0 else None))
continue continue
# 401/4092/4111/461/462/4551 si 5311 # 401/4092/4111/461/462/4551 si 5311
if direct: 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) cont_p, ac_p = _mapare_cont(p, p, None, mapare, True)
def baza(kids): 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, 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))) numar=1, nume=nume, totdeb=round(bd, 2), totcred=round(bc, 2)))
facturi(kids, cont_g, ac_g) facturi(kids, cont_g, ac_g)
if d: if dd or dc:
add(rand(header, an, luna, TIP="BALANTA", cont=cont_p, add(rand(header, an, luna, TIP="BALANTA", cont=cont_p,
acont=acont_diferenta(p, direct), numar=1, acont=acont_diferenta(p, direct), numar=1,
nume="DIFERENTA SINTETIC SAGA", nume="DIFERENTA SINTETIC SAGA",
totdeb=d if d > 0 else None, totdeb=dd or None, totcred=dc or None))
totcred=-d if d < 0 else None))
continue continue
base_d, base_c = baza(direct) 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() cont_p = variante.pop()
add(rand(header, an, luna, TIP="BALANTA", cont=cont_p, acont=ac_p, add(rand(header, an, luna, TIP="BALANTA", cont=cont_p, acont=ac_p,
numar=1, nume=by[p]["denumire"], numar=1, nume=by[p]["denumire"],
totdeb=round(base_d + (d if d > 0 else 0.0), 2), totdeb=round(base_d + dd, 2),
totcred=round(base_c + (-d if d < 0 else 0.0), 2))) totcred=round(base_c + dc, 2)))
facturi(direct, cont_p, ac_p) facturi(direct, cont_p, ac_p)
else: else:
net = round(by[p]["total_d"] - by[p]["total_c"], 2) net = round(by[p]["total_d"] - by[p]["total_c"], 2)

View File

@@ -192,3 +192,26 @@ class TestAcontPeAnaliticePartener(unittest.TestCase):
("461", "9999"): 50.0}) ("461", "9999"): 50.0})
self.assertEqual(fac, {("461", "SGR"): ("AMBALAJE SGR", 100.0), self.assertEqual(fac, {("461", "SGR"): ("AMBALAJE SGR", 100.0),
("461", "1"): ("PARTENER X", 200.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)})

View File

@@ -46,8 +46,6 @@ CORECTII = [
# frunza -> (REF, NOI), cu (totdeb, totcred); None = frunza lipseste # frunza -> (REF, NOI), cu (totdeb, totcred); None = frunza lipseste
DIFERENTE_ASTEPTATE = { 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: note direct pe sintetic -> acont de diferenta; REF le-a pierdut
("4092", "99"): (None, (1563.37, 0.0)), ("4092", "99"): (None, (1563.37, 0.0)),
# nota de 900 direct pe 419: analitic de diferenta; REF a pierdut-o # 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", ""): ((40801.41, 35876.25), None),
("5121", "1"): (None, (40601.41, 35876.25)), ("5121", "1"): (None, (40601.41, 35876.25)),
("5121", "2"): (None, (200.0, 0.0)), ("5121", "2"): (None, (200.0, 0.0)),
# 891 are rulaj zero; REF nu-l scrie
("891", ""): (None, (0.0, 0.0)),
} }