Conturi cu parteneri cu analitice functionale: BALANTA per acont
Cand analiticele unui cont cu parteneri primesc acont prin corectii (461.SGR -> 461/SGR, 461.RESTUL -> 461/1), generatorul scrie cate un BALANTA per (cont, acont) si FACTURA cu acelasi acont (pct. 16); postarile direct pe sintetic merg pe acontul de diferenta, ca la banca. Inainte, acontul ajungea doar pe FACTURA, nu si pe BALANTA agregat - dezacord tacut. Fara astfel de corectii, iesirea e neschimbata (etalonul trece). LACERTA: 4092.1 -> 4092/1, identic cu REF; 50/53 frunze identice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYeAtVxeS8m4oXekjX8Am2
This commit is contained in:
@@ -58,6 +58,10 @@ Exemple: `419.NETOPIA -> 419 / 2`, `4428.TOATE -> 4428 / 01` = strange toate ana
|
||||
pe unul singur (lasa `acont` gol doar daca sinteticul nu are si postari directe).
|
||||
Cand un analitic nu incape in 4 caractere, genereaza se opreste si iti cere corectia.
|
||||
|
||||
Cont cu parteneri care are si analitice functionale (ex. `461.SGR`): pastrezi analiticul
|
||||
cu `461.SGR -> 461 / SGR` si pui partenerii pe alt acont cu `461.RESTUL -> 461 / 1`. Iese cate
|
||||
un rand BALANTA pe fiecare acont, cu facturile lui.
|
||||
|
||||
## Reguli de stiut
|
||||
|
||||
- Conturile cu parteneri sunt in `config/conturi_parteneri.csv` (autoritatea).
|
||||
|
||||
@@ -127,13 +127,15 @@ Corectiile folosite (in test, ca in REF): `419.NETOPIA -> 419 / 2`, `4428.TOATE
|
||||
care insumeaza 129,44). Descrierea lui `4092` e corectata.
|
||||
4. Coloana `data` = ultima zi a lunii.
|
||||
|
||||
Frunze BALANTA identice cu REF dupa aceste decizii: **49 din 53**.
|
||||
5. Analiticele functionale pe conturi cu parteneri (`4092.1`, `461.SGR`) se pastreaza prin
|
||||
corectii (`decizii_import.md` pct. 17). Pe LACERTA: `4092.1 -> 4092 / 1`, acum identic cu
|
||||
REF, iar notele direct pe sintetic (1.563,37) merg pe `4092 / 99`. `461.SGR` exista in plan,
|
||||
dar fara note: cele 2.250 de pe 461 sunt postate doar pe sintetic. Cazul mixt e acoperit
|
||||
de `tests/test_integrare.py::TestAcontPeAnaliticePartener`.
|
||||
|
||||
**Ramas deschis:** `461` si `4092` sunt conturi cu parteneri, dar pot avea analitice
|
||||
functionale sau geografice (`461.SGR` "AMBALAJE SGR", `4092.1`). Azi un astfel de analitic
|
||||
devine un pseudo-partener cu cod fiscal provizoriu (`461.SGR`).
|
||||
Frunze BALANTA identice cu REF dupa aceste decizii: **50 din 53**.
|
||||
|
||||
## 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`,
|
||||
38 de teste, toate trec. Fisierele LACERTA din `exemple/` sunt ignorate de git.
|
||||
39 de teste, toate trec. Fisierele LACERTA din `exemple/` sunt ignorate de git.
|
||||
|
||||
@@ -128,7 +128,12 @@ Consecinte:
|
||||
- Analitice nenumerice stranse pe sintetic (`4428.M/TI/TP` prin `.TOATE`) primesc un acont
|
||||
(`01`), ca sa nu stea langa analiticul de diferenta (`99`) un rand fara acont.
|
||||
- `461` si `4092` raman conturi cu parteneri, desi pot avea si analitice functionale sau
|
||||
geografice (`461.SGR`, `4092.1`). Tratarea acestora e deschisa (docs/analiza_lacerta_fdb.md).
|
||||
geografice (`461.SGR`, `4092.1`). Acestea se pastreaza prin corectii, de exemplu
|
||||
`461.SGR -> 461 / SGR` si `461.RESTUL -> 461 / 1` pentru parteneri. Cand analiticele unui
|
||||
cont cu parteneri primesc `acont` prin corectii, generatorul scrie cate un BALANTA per
|
||||
`(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.
|
||||
|
||||
## Divergenta fata de CONFIG_CONT_IREG (constatata 21.09.2026)
|
||||
|
||||
|
||||
@@ -354,22 +354,58 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None,
|
||||
|
||||
# 401/4092/4111/461/462/4551 si 5311
|
||||
if direct:
|
||||
base_d = 0.0
|
||||
base_c = 0.0
|
||||
for k in direct:
|
||||
net = round(by[k]["total_d"] - by[k]["total_c"], 2)
|
||||
if net != 0 and not este_latura_formular(net, side):
|
||||
neg = -abs(net)
|
||||
negative.append((p, k, neg, side))
|
||||
if side == "D":
|
||||
base_d += neg
|
||||
else:
|
||||
base_c += neg
|
||||
else:
|
||||
base_d += by[k]["total_d"]
|
||||
base_c += by[k]["total_c"]
|
||||
d = diff_by_parent.get(p, 0.0)
|
||||
cont_p, ac_p = _mapare_cont(p, p, None, mapare, True)
|
||||
|
||||
def baza(kids):
|
||||
"""Totalurile BALANTA pentru analiticele date; netul pe latura opusa
|
||||
intra negativ (vezi `negative`)."""
|
||||
bd = bc = 0.0
|
||||
for k in kids:
|
||||
net = round(by[k]["total_d"] - by[k]["total_c"], 2)
|
||||
if net != 0 and not este_latura_formular(net, side):
|
||||
negative.append((p, k, -abs(net), side))
|
||||
if side == "D":
|
||||
bd -= abs(net)
|
||||
else:
|
||||
bc -= abs(net)
|
||||
else:
|
||||
bd += by[k]["total_d"]
|
||||
bc += by[k]["total_c"]
|
||||
return bd, bc
|
||||
|
||||
def facturi(kids, cont_f, ac_f):
|
||||
for k in kids:
|
||||
net = round(by[k]["total_d"] - by[k]["total_c"], 2)
|
||||
if net == 0:
|
||||
leaf_rep.add(k)
|
||||
continue
|
||||
sold = abs(net) if este_latura_formular(net, side) else -abs(net)
|
||||
cont_k, kac = _mapare_cont(k, cont_f, ac_f, mapare, True)
|
||||
factura(k, cont_k, kac, by[k]["denumire"], side, net, sold, k)
|
||||
|
||||
# Analitice cu acont dat prin corectii (461.SGR functional, 461.RESTUL ->
|
||||
# 461/1 pentru parteneri): cate un BALANTA per (cont, acont) si FACTURA cu
|
||||
# ACELASI acont (pct. 16); postarile direct pe sintetic -> acont de diferenta.
|
||||
grupuri = {}
|
||||
for k in direct:
|
||||
grupuri.setdefault(_mapare_cont(k, cont_p, ac_p, mapare, True), []).append(k)
|
||||
if any(ac != ac_p for _, ac in grupuri):
|
||||
for (cont_g, ac_g), kids in sorted(grupuri.items(), key=lambda g: str(g[0])):
|
||||
bd, bc = baza(kids)
|
||||
nume = by[kids[0]]["denumire"] if len(kids) == 1 else by[p]["denumire"]
|
||||
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:
|
||||
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))
|
||||
continue
|
||||
|
||||
base_d, base_c = baza(direct)
|
||||
if cont_p == p: # .TOATE/.RESTUL poate redenumi fara rand pe sintetic
|
||||
# BALANTA agregat si randurile FACTURA trebuie sa cada pe acelasi
|
||||
# cont. Daca analiticele sunt mapate pe conturi diferite, agregatul
|
||||
@@ -385,14 +421,7 @@ def genereaza(rows, header, an=AN, luna=LUNA, mapare=None, parteneri=None,
|
||||
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)))
|
||||
for k in direct:
|
||||
net = round(by[k]["total_d"] - by[k]["total_c"], 2)
|
||||
if net == 0:
|
||||
leaf_rep.add(k)
|
||||
continue
|
||||
sold = abs(net) if este_latura_formular(net, side) else -abs(net)
|
||||
cont_k, kac = _mapare_cont(k, cont_p, ac_p, mapare, True)
|
||||
factura(k, cont_k, kac, by[k]["denumire"], side, net, sold, k)
|
||||
facturi(direct, cont_p, ac_p)
|
||||
else:
|
||||
net = round(by[p]["total_d"] - by[p]["total_c"], 2)
|
||||
if net != 0 and not este_latura_formular(net, side):
|
||||
|
||||
@@ -167,3 +167,28 @@ class TestMapareSinteticPartener(unittest.TestCase):
|
||||
mapare=mapare)
|
||||
conturi = {r["cont"] for r in out}
|
||||
self.assertEqual({"4011"}, conturi)
|
||||
|
||||
|
||||
class TestAcontPeAnaliticePartener(unittest.TestCase):
|
||||
"""Cont cu parteneri care are si analitice functionale (461.SGR) si parteneri
|
||||
(461.RESTUL -> 461/1): cate un BALANTA per (cont, acont), FACTURA cu acelasi acont
|
||||
(decizii_import.md pct. 16), postarea direct pe sintetic pe acontul de diferenta."""
|
||||
|
||||
ROWS = [
|
||||
{"cont": "461", "denumire": "DEBITORI DIVERSI", "total_d": 350.0, "total_c": 0.0},
|
||||
{"cont": "461.SGR", "denumire": "AMBALAJE SGR", "total_d": 100.0, "total_c": 0.0},
|
||||
{"cont": "461.00001", "denumire": "PARTENER X", "total_d": 200.0, "total_c": 0.0},
|
||||
]
|
||||
MAPARE = {"461.SGR": {"cont": "461", "acont": "SGR"},
|
||||
"461.00001": {"cont": "461", "acont": "1"}}
|
||||
|
||||
def test_balanta_si_factura_pe_acelasi_acont(self):
|
||||
out, _, _, _, _ = genereaza_xlsx.genereaza(
|
||||
self.ROWS, genereaza_xlsx.citeste_header(), 2026, 6, mapare=self.MAPARE)
|
||||
bal = {(r["cont"], r["acont"]): r["totdeb"] for r in out if r["TIP"] == "BALANTA"}
|
||||
fac = {(r["cont"], r["acont"]): (r["nume"], r["sold"])
|
||||
for r in out if r["TIP"] == "FACTURA"}
|
||||
self.assertEqual(bal, {("461", "SGR"): 100.0, ("461", "1"): 200.0,
|
||||
("461", "9999"): 50.0})
|
||||
self.assertEqual(fac, {("461", "SGR"): ("AMBALAJE SGR", 100.0),
|
||||
("461", "1"): ("PARTENER X", 200.0)})
|
||||
|
||||
@@ -39,15 +39,17 @@ CORECTII = [
|
||||
["419.NETOPIA", "419", "2", None, "ca in REF"],
|
||||
# REF are un singur rand 4428; 01 ca sa iasa frunze curate langa diferenta 4428/99
|
||||
["4428.TOATE", "4428", "01", None, "decizie 26.09.2026"],
|
||||
# analitic functional pe cont cu parteneri: ramane analitic (decizie 27.09.2026).
|
||||
# 461.SGR exista in plan, dar fara note: 461 e postat doar pe sintetic.
|
||||
["4092.1", "4092", "1", None, "analitic functional"],
|
||||
]
|
||||
|
||||
# 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 e cont cu parteneri in config; REF l-a pus pe analitic si a pierdut 1563.37
|
||||
("4092", ""): (None, (4170.23, 0.0)),
|
||||
("4092", "1"): ((2606.86, 0.0), None),
|
||||
# 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
|
||||
("419", "9999"): (None, (0.0, 900.0)),
|
||||
# 4428: analiticele M/TI/TP pe 01 (corectie), postarile direct pe sintetic pe 99;
|
||||
|
||||
Reference in New Issue
Block a user