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

156 lines
8.4 KiB
Markdown

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