# 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` ```sql 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.