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
95 lines
6.0 KiB
Markdown
95 lines
6.0 KiB
Markdown
# De ce la test crapa (View Parameter) si in productie merge — INAINTE_DE_STOC
|
|
|
|
Investigatie read-only, 08.08.2026. Intrebare de la Marius: acelasi tipar `DO ... WITH gnAn, gnLuna`
|
|
exista in productie la `COMUN\programe\oproceduri_stocuri.prg:35,130,207` — de ce nu s-a manifestat
|
|
niciodata acolo?
|
|
|
|
## Raspuns
|
|
|
|
**Varianta 1, confirmata prin citirea intregului cod al procedurii apelate: inofensiv prin
|
|
constructie.** Pe acest lant nu exista niciun `?gnAn`/`?gnLuna` (bind marker SQL) — deci pasarea prin
|
|
referinta, desi masca numele `gnAn`/`gnLuna` in interiorul procedurii apelate, nu are ce sa strice.
|
|
|
|
## Dovada, pas cu pas
|
|
|
|
1. **Apelul**: `oproceduri_stocuri.prg:35,130,207` —
|
|
`DO INAINTE_DE_STOC WITH gnAn, gnLuna, tnTipGest, lnStocObinv in oinainte_de.prg`.
|
|
2. **Procedura apelata**: `COMUN\programe\oinainte_de.prg:356-411`, `PROCEDURE INAINTE_DE_STOC`,
|
|
semnatura `Parameters tnAn, tnLuna, tnTipGest, tnStocObinv, tcListaIdGestiuni`. Deci `gnAn` ajunge
|
|
accesibil in interior **doar** sub numele local `tnAn` (si `gnLuna` sub `tnLuna`) — exact tiparul
|
|
care facea `TYPE('gnAn')='U'` in testul de ieri.
|
|
3. **Singurul SQL din procedura** e la `oinainte_de.prg:389-390`:
|
|
```
|
|
lcSql = "select pack_inainte_de.inainte_de_stoc(" + Alltrim(Str(tnAn)) + "," + Alltrim(Str(tnLuna)) + "," + ;
|
|
Alltrim(Str(tnTipGest)) + "," + Alltrim(Str(tnStocObinv)) + "," + Iif(Isnull(gnIdSucursala), "null", Alltrim(Str(gnIdSucursala))) + "," + ;
|
|
Iif(Empty(Nvl(m.lnIdGestiune, '')), "null", Alltrim(Str(lnIdGestiune))) + ") as valoare from dual"
|
|
```
|
|
Toti termenii intra prin **concatenare** (`Alltrim(Str(...))`), inclusiv `tnAn`/`tnLuna` — cele
|
|
masate. **Zero caractere `?` in acest string.** `gnIdSucursala` apare si el, dar tot prin
|
|
concatenare, nu ca bind marker — deci nici acolo nu conteaza ca e vizibil sau nu global.
|
|
4. **Procedura nu face niciun alt `DO ... WITH` mai departe** — bucla `For lnGestiune = 1 To
|
|
lnGestiuni` apeleaza direct `goExecutor.oExecute(lcSql, lcCursor)` (executie Oracle), nu alta
|
|
procedura VFP. Lantul se opreste aici; nu exista o veriga suplimentara unde `tnAn`/`tnLuna` sa
|
|
piarda contextul.
|
|
|
|
Concluzie: mecanismul care bloca testul (VFP incearca sa lege `?gnAn` la o variabila devenita `'U'`
|
|
si deschide dialogul nativ "View Parameter") **nu are niciun `?gnAn`/`?gnLuna` de legat** pe acest
|
|
lant — nu pentru ca variabila ar fi vizibila, ci pentru ca nimeni nu o cere prin acel mecanism.
|
|
Utilizatorul nu vede dialogul pentru ca bug-ul latent (pasarea prin referinta) exista, dar
|
|
consecinta lui (bind marker nelegat) nu e declansata de acest cod.
|
|
|
|
## Verdict
|
|
|
|
**Inofensiv, cazul specific din intrebare.** Nu e bug latent — e cod scris corect din intamplare
|
|
(sau prin obisnuinta autorului de a concatena SQL-ul in loc sa foloseasca bind markers), care
|
|
absoarbe fara sa observe efectul secundar al `DO ... WITH`.
|
|
|
|
## Cautare extinsa: aceeasi familie in restul `COMUN\programe` si `COMUN\clase`
|
|
|
|
Cautat tiparul complet (ambele conditii): `DO ... WITH <variabila globala>` (fara paranteze, deci
|
|
prin referinta) **si** acelasi nume aparand ca `?<variabila>` undeva accesibil pe lantul de apel.
|
|
|
|
Inventarul complet de apeluri `DO ... WITH <global g*>` neconditionate (comentariile `*DO ...` nu
|
|
conteaza, cod mort):
|
|
|
|
| Apel | Fisier:linie | Verdict |
|
|
|---|---|---|
|
|
| `DO INAINTE_DE_STOC WITH gnAn, gnLuna, tnTipGest, lnStocObinv` | `oproceduri_stocuri.prg:35,130,207` | **Inofensiv** — vezi mai sus |
|
|
| `DO fisa_magazie_fifo WITH gnTipGest,pnIdGestiune,pcNumeGestiune,PcCodul` | `rulaje.vc2:8243` | **Inofensiv** — vezi mai jos |
|
|
| `*DO schimba_firma WITH gnHandle,GCS,lcschemaParola` | `ostartfirma.prg:168` | cod mort (comentat) |
|
|
| `*DO schimba_firma WITH gnHandle,lcSchema,...` | `ferestre_comune.vc2:859`, `ferestre_oracle.vc2:858` | cod mort (comentat) |
|
|
|
|
**`fisa_magazie_fifo`** (`orapoarte.prg:266-...`, `Lparameters tnTipGest, tnIdGestiune,
|
|
tcNumeGestiune, tnIdArticol, tcSerie`): `gnTipGest` ajunge accesibil doar sub `tnTipGest`. Cautare
|
|
`\?gnTipGest\b` in tot `COMUN` gaseste 8 hituri, **niciunul in `orapoarte.prg`** — toate in fisiere
|
|
fara legatura cu acest lant de apel (`gest_selectii.db2`, `oproceduri_facturare.prg`,
|
|
`configurare.vc2`, `oschimbare_pret.vc2`, apeluri din alte fluxuri, nu din `fisa_magazie_fifo`).
|
|
Functia foloseste `tnTipGest` doar prin comparatie directa (`If tnTipGest = 6`) si transmis mai
|
|
departe ca parametru catre `caut_gestiune(tnTipGest, gnIdUtil)` — niciodata ca bind marker SQL.
|
|
Inofensiv, acelasi motiv ca la INAINTE_DE_STOC.
|
|
|
|
**Nu exista alt caz** in `COMUN\programe` / `COMUN\clase` unde ambele conditii (DO...WITH pe un
|
|
global + `?acelasi_nume` pe lantul de apel) sa se intalneasca simultan.
|
|
|
|
### Gasit in cautare, dar NU pe acest tipar (semnalat totusi)
|
|
|
|
`oinainte_de.prg:258`, procedura `test_casa`:
|
|
```
|
|
lcSql = [select PACK_INAINTE_DE.TEST_CASA(?gnAn,?gnLuna,?pcContTestCasa,?gnIdSucursala) AS VALOARE FROM DUAL]
|
|
```
|
|
Foloseste `?gnAn`/`?gnLuna`/`?gnIdSucursala` ca bind markers reali. **Dar** apelul catre `test_casa`
|
|
(`ocasabanca.prg:66`: `Do test_casa With lcCont In oinainte_de.prg`) paseaza **doar** `lcCont` —
|
|
`gnAn`/`gnLuna` nu sunt deloc argumente, deci nu sunt mascate pe acest lant. Nu se incalca conditia
|
|
ceruta (ambele trebuie sa se intample **impreuna**), deci nu e cazul cautat — dar e o structura
|
|
fragila: daca in viitor cineva ar adauga `gnAn`/`gnLuna` ca parametri suplimentari la `test_casa`
|
|
fara paranteze, ar reproduce exact blocajul de ieri, de data asta in productie (dialogul "View
|
|
Parameter" vazut de utilizator). Nu e remediat — doar semnalat, in afara scopului intrebarii.
|
|
|
|
## Remediu propus (NEAPLICAT)
|
|
|
|
Niciunul necesar pentru cazurile gasite — sunt inofensive prin constructie. Daca se doreste totusi
|
|
o plasa de siguranta impotriva viitoarelor regresii de acest tip: paranteze la orice `DO ... WITH`
|
|
care paseaza globale catre o procedura ale carei SQL-uri sunt necunoscute/in schimbare —
|
|
`DO INAINTE_DE_STOC WITH (gnAn), (gnLuna), tnTipGest, lnStocObinv` — cost zero, elimina clasa de bug
|
|
la sursa. **Nu s-a aplicat nicio modificare de cod** — cod de productie neatins, conform interdictiei.
|