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`)
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

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
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.

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)})

View File

@@ -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)),
}