Files
roafacturare/docs/cercetare/rec_gotop_tact_s4.md
Marius Mutu d9f5ca4226 docs: planurile, proiectarile si rapoartele de lucru intra in versionare
Folderul docs\ era pana acum in afara oricarui control de versiuni - nici git,
nici SVN - desi contine planurile pe puncte, proiectarile si rapoartele de
cercetare pe care se sprijina modificarile din cod. O stergere acolo era
definitiva.

Fisierele intermediare (handoff-uri intre sesiuni, diff-uri deja aplicate) au
fost sterse inainte, nu versionate: ce era durabil in ele a intrat in antetele
fisierelor de test la care se refereau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-11 22:17:17 +03:00

8.4 KiB

Cercetare: Go Top orb pe tact - blocantul #1 inainte de commit (S4 PAGE3)

Verificare pe date (MARIUSM_AUTO@ROA_CENTRAL, 08.08.2026) a riscului semnalat in rec_review_ancorare_s4.md pct. 1: omodificari.vc2:14171, Show(), face Go Top In tact apoi citeste tact.nract/tact.serie_act/tact.dataact pentru IncarcaVanzareNota. Read-only, nicio modificare de cod.

Verdict: BUG CONFIRMAT

Pe cele 62 de note din schema de dev unde primul rand (vact_tot, sters=0, ordonat dupa id_act) e o incasare si nota chiar are un rand de vanzare legat in VANZARI: filtrul compus din IncarcaVanzareNota (cod + nract + serie_act + dataact), rulat cu valorile de pe primul rand, intoarce 0 randuri pe 52 din 62 (84%) — lAreArticoleVanzari ar iesi .F. silentios desi vanzarea exista. Pe celelalte 10/62 filtrul nimereste din intamplare (randul de incasare are, pe acele note, aceleasi nract/serie_act ca factura).

1. Reconstructia multimii de risc

Prim rand din vact_tot (per an+luna+cod, sters=0, ordonat dupa id_act) cu Upper(explicatia) LIKE '%INCASARE%', legat de un rand real din VANZARI (exista v.id_fact care apare si pe un rand din nota, v.sters=0). Rezultat: 62 de note (2009-2024), fata de cele 39 raportate initial in rec_pozitionare_actactan.md — diferenta e metodologica (acolo criteriul de legatura era mai ingust, "id_fact minus 1"; aici orice id_fact comun intre nota si VANZARI), nu contrazice concluzia, o extinde.

Pe primul rand, serie_act e aproape mereu NULL (randul de incasare nu are serie proprie), in timp ce randul facturii are o serie reala (FFFFF, SSS, JOI1226 etc.) — vezi exemplele de mai jos. nract/dataact coincid uneori, serie_act aproape niciodata.

2. Testul decisiv: filtrul simulat direct pe VANZARI

SELECT COUNT(*) FROM vanzari v
WHERE v.cod = :cod
  AND NVL(v.numar_act,-1) = NVL(:nract_prim_rand,-1)
  AND NVL(v.serie_act,'~') = NVL(:serie_act_prim_rand,'~')
  AND TRUNC(v.data_act) = TRUNC(:dataact_prim_rand)
  AND v.sters = 0

Rulat cu valorile primului rand (INCASARE) pentru toate cele 62 de note: 52 → 0 randuri (bug), 10 → 1 rand corect (coincidenta valori identice pe ambele randuri).

3. Cazuri reproductibile

an luna cod prim rand (nract/serie/data) rand factura (nract/serie/data) id_vanzare real filtru cu Go Top
2009 8 1137874 5 / NULL / 27.08.2009 5 / FFFFF / 27.08.2009 506 0 randuri
2021 12 1139934 13 / NULL / 31.12.2021 13 / (serie reala) / 31.12.2021 882 0 randuri

cod=1139934 e deja cunoscut in proiect ca fiind cazul de coliziune pe VANZARI.COD folosit pentru validarea filtrului compus (docs\progres.md) — util unei sesiuni viitoare ca sa scrie testul fara sa mai caute alt caz.

4. Pozitionarea corecta recomandata

Constrangere: in Show() nu exista crsfacturi, deci ancorarea pe crsfacturi.id_fact (rec_pozitionare_actactan.md §5) nu se poate folosi aici. Criteriul trebuie evaluat strict din tact (deja incarcat, ordonat dupa id_act).

Recomandare: primul rand din tact (in ordinea existenta, id_act) a carui explicatia NU contine INCASARE (!("INCASARE" $ Upper(Nvl(tact.explicatia,''))); daca niciun rand nu indeplineste conditia (nota e o incasare pura, fara linie de factura), fallback la comportamentul actual (Go Top).

Locate For !("INCASARE" $ Upper(Nvl(explicatia,''))) In tact
IF !Found()
    Go Top In tact
ENDIF
IncarcaVanzareNota(tact.cod, tact.nract, tact.serie_act, tact.dataact)

Validat 62/62 (100%) pe toata multimea de risc — filtrul cu randul gasit astfel intoarce exact randul real (id_vanzare) pe fiecare din cele 62 de note, inclusiv pe cele 10 unde Go Top "nimerea" deja din intamplare.

Fallback-ul e sigur: exista 42 de note in schema unde TOATE randurile au explicatia de tip incasare (chitante fara linie de factura) — pe acestea nu exista o "linie de factura" de gasit, Go Top ramane comportamentul corect (cauta cu randul de incasare, nu gaseste vanzare, ceea ce e adevarat: nu exista).

5. Varianta respinsa: ancorare pe FDOC

Parea un candidat mai curat decat un filtru text pe explicatia (FDOC='FACTURA' — cautabil, fara enumerare de variante). Infirmata pe date: FDOC e un camp la nivel de nota, identic pe toate randurile ei (tipul documentului contabil: FACTURA, ABONAMENT, BON FISCAL etc.), nu un marcaj per rand al liniei de factura. Pe 40 din cele 62 de note din multimea de risc nota e de tip ABONAMENT/BON FISCAL, deci niciun rand nu are FDOC='FACTURA' desi nota chiar are o linie de factura validata (randul cu explicatia='NOTA 1' sau gol). Whitelist pe explicatia ('NOTA 1' etc.) ar fi si mai fragil — pe cele 62 de note, randul corect apare cu explicatia din cel putin 5 variante diferite (NOTA 1, gol/NULL, RATA 1, PRODUCTIE, TVA NOTA 1), imposibil de enumerat exhaustiv. Blacklist pe INCASARE (pct. 4) a fost singurul criteriu validat 100%.

6. Completare ceruta: cele 10/62 "nimerite din intamplare" gasesc documentul corect?

Da, pe toate 10. Verificat explicit prin join intre id_vanzare gasit de filtru (cu valorile primului rand INCASARE) si id_vanzare-ul real al facturii: 10/10 ACELASI document, 0 cazuri de document gresit. Filtrul compus nu a intors niciodata mai mult de 1 rand pe toata multimea de risc (MAX(randuri gasite) = 1, 0 cazuri cu 2+) — ipoteza de unicitate (cod, numar_act, serie_act, data_act), verificata deja pe toata tabela VANZARI (docs\progres.md), se confirma si pe aceasta submultime. Concluzie: bugul e strict "pagina lipseste" (fals negativ), nu "pagina arata datele altui document".

7. Alternativa fara euristica de text: toate tripletele distincte din tact

In loc sa aleaga un rand anume din tact (fie prin Go Top, fie prin filtrare pe explicatia), varianta testata ia toate combinatiile distincte (nract, serie_act, dataact) din randurile notei (sters=0) si cauta in VANZARI randul care se potriveste cu oricare dintre ele. Testata pe toate cele 419 de note din schema legate de VANZARI (nu doar cele 62 de risc):

rezultat note %
gaseste exact 1 rand, si e cel corect 400 95.5%
gaseste 1 rand, dar gresit 0 0%
gaseste 0 randuri 19 4.5%
gaseste 2+ randuri (ambiguu) 0 0%

Numar de triplete distincte per nota: minim 1, maxim 2, medie 1.17 — cost neglijabil pentru o bucla/OR in VFP sau Oracle (cel mult 2 incercari).

Cele 19 de "0 randuri" nu sunt cazuri de pozitionare gresita in tact — pe toate 19, VANZARI.DATA_ACT difera efectiv de orice dataact prezent in nota (majoritatea din 2019: VANZARI.DATA_ACT are placeholder-ul 01.01.2019 in loc de data reala de sfarsit de luna din ACT; restul au date decalate, NULL, sau vanzarea e stornata tip=-13). Nicio alegere de rand din tact poate rezolva asta — valoarea corecta pur si simplu nu exista in ACT. Nu e o regresie: Go Top de azi rateaza exact aceleasi 19.

Pe multimea de risc (cele 62), varianta cu tripletele iese 62/62 corecta, identic cu criteriul text de la punctul 4. Diferenta e robustetea: nu se bazeaza pe continutul textual al explicatia (orice limba/formulare/rand adaugat manual de utilizator), doar pe "care tripleta chiar exista in VANZARI" — nu poate fi pacalita de o eticheta scrisa altfel.

Recomandare finala (actualizata)

Renunta la criteriul bazat pe explicatia (pct. 4, respins in favoarea acestuia) si foloseste varianta cu toate tripletele distincte (nract, serie_act, dataact) din tact (sters=0), incercate pana la prima care gaseste un rand in VANZARI:

SELECT DISTINCT nract, serie_act, dataact FROM tact WHERE !sters INTO CURSOR tmp_triplete
SCAN
    IncarcaVanzareNota(tact.cod, tmp_triplete.nract, tmp_triplete.serie_act, tmp_triplete.dataact)
    IF Reccount('tvanz') > 0
        EXIT
    ENDIF
ENDSCAN

(sau echivalent, o singura interogare Oracle cu tripletele unite prin OR — decizie de implementare, nu schimba rezultatul masurat). Nu necesita crsfacturi, nu necesita schimbari de schema, nu depinde de text liber. Validat 62/62 pe multimea de risc si 400/400 (100%) pe restul notelor legate de VANZARI unde exista o potrivire posibila in date; cele 19 cazuri ramase sunt o limitare preexistenta a datelor (VANZARI.DATA_ACT incorect populat), nu a criteriului de pozitionare, si afecteaza identic si comportamentul de azi.