Files
roafacturare/docs/cercetare/rec_inainte_de_stoc.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

6.0 KiB

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.