- import_nota / import_adauga_factura: flux unificat note contabile + articole, sincronizare automata, total factura automat, TVA impartit pe conturile creditoare ale notelor (rundele 1-31) - runda 32: totalurile import_nota pe _label/_textbox din _baza.vcx (Arial 10), fara containerele clb_tx_simplu si fara bifa "Recalculeaza TVA" (recalcul mereu automat); "Sincronizeaza facturile secundare" mutata sub butoane - utile/Teste: harness UI VFP headless (vfp_ui_harness.ps1, ui_harness.prg, precompilare, mock-uri) in radacina; suitele e2e pentru achizitia din import grupate in utile/Teste/achizitie_import/ - docs: flux editare text vcx/scx, testare-ui-vfp si testare-vfp-mcp (mutate din ROAGEST, general valabile), inventar comun, orchestrare subagenti, conventie GO recno, depanare testare VFP Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019DGibQKa5uK4P2TNSFFQNh
172 lines
7.8 KiB
Plaintext
172 lines
7.8 KiB
Plaintext
* mock_cauta_alfa_dialog.prg - inlocuieste DOAR PROCEDURE cauta_alfa (COMUN\programe\cauta_alfa.prg,
|
|
* linia 16), NU cauta_nom_articole/XML2ListaIDDescriere/do_adauga_articol - acelea raman REALE,
|
|
* neatinse. Se incarca PRIMUL (inaintea "SET PROCEDURE TO cauta_alfa ADDITIVE") - la nume duplicat
|
|
* de procedura VFP foloseste fisierul incarcat PRIMUL (vezi docs/testare-ui-vfp.md capcana j).
|
|
*
|
|
* De ce: cauta_alfa() reala populeaza cursorul din Oracle prin gencursor->ca_baza.afisare(), care
|
|
* foloseste This.CursorFill() (CursorAdapter/conexiune reala) - nu goExecutor, deci nu poate fi
|
|
* mock-uit ca restul infrastructurii (vezi COMUN\clase\decabaza.vc2:36-99). Acest shadow inlocuieste
|
|
* DOAR sursa de date (Oracle -> cursor mock pre-populat de test) si bucla de asteptare modala
|
|
* (WindowType=1, Show() blocheaza pana la Release -> WindowType=0 + actiuni conduse programatic
|
|
* dupa Show(), vezi docs/testare-ui-vfp.md capcana g). Formularul e clasa REALA cauta_alfa_form
|
|
* (COMUN\clase\cauta_alfa_forms.vcx), metodele apelate (do_alege, do_termin, do_renunt) sunt cele
|
|
* REALE, neschimbate - doar interactiunea utilizatorului e simulata in loc de bucla de evenimente.
|
|
*
|
|
* IMPORTANT (capcana l, docs/testare-ui-vfp.md): CREATEOBJECT apelat DINTR-O PROCEDURA (nu din
|
|
* programul principal) intoarce un obiect stricat in acest runtime headless (verificat empiric -
|
|
* "OFORM_CAUTARE is not an object" la prima folosire). De aceea formularele NU se creeaza aici -
|
|
* testul principal le PRE-CONSTRUIESTE inline (goDlgA/goDlgB/goDlgC) INAINTE sa apeleze
|
|
* do_adauga_articol, iar acest shadow doar SELECTEAZA obiectul potrivit dupa gcTestScenariu si ii
|
|
* apeleaza metodele reale (asta e simpla dispecerizare de metoda, nu CREATEOBJECT - functioneaza
|
|
* din procedura fara probleme).
|
|
*
|
|
* Control test (setate de testul principal INAINTE de fiecare apel):
|
|
* goDlgA / goDlgB / goDlgC - formularele REALE pre-construite (vezi test_picker_real_212.prg)
|
|
* gcTestScenariu - 'A' (marcheaza BULDOEXCAVATOR + OK), 'B' (nimic marcat + OK),
|
|
* 'C' (dublu-click pe denumire), altfel Cancel
|
|
* Rezultat expus (citit de testul principal dupa apel):
|
|
* gcTestGnButon, gcTestXML, gcTestLenXML, gcTestCAles, gcTestPcAles, gcTestRandiuriMarcate
|
|
|
|
Procedure cauta_alfa
|
|
Parameters tcselect,tcfiltru,tcschema,tcorder,tccoloana,tcTitlu,tcTitluColoane, ;
|
|
tcNume_Proc,tl_AllInList,tcFiltruOriginal,tcPrimaColoana, tnPornire, tnTipReturn, ;
|
|
tcIdColumn, tlDesktop, tcGroup, tcGridDynamicBackColor, tcGridToolTip, tlModParam, tcStringCriterii, ;
|
|
tcProceduraVerifica, tcProceduraCopiaza,tcLocate
|
|
|
|
LOCAL lcCursor, lcCursorXML, lcCAlesDupaMarcare
|
|
LOCAL oForm_cautare, oReturnScattObj
|
|
Private pcAles
|
|
pcAles = ""
|
|
gcTestRandiuriMarcate = 0
|
|
|
|
IF USED('crsReturnAlfa')
|
|
USE IN ('crsReturnAlfa')
|
|
ENDIF
|
|
|
|
*-- === selecteaza obiectul PRE-CONSTRUIT (vezi capcana l mai sus - fara CREATEOBJECT aici) ===
|
|
DO CASE
|
|
CASE gcTestScenariu == 'A'
|
|
oForm_cautare = goDlgA
|
|
CASE gcTestScenariu == 'B'
|
|
oForm_cautare = goDlgB
|
|
CASE gcTestScenariu == 'C'
|
|
oForm_cautare = goDlgC
|
|
OTHERWISE
|
|
oForm_cautare = goDlgA
|
|
ENDCASE
|
|
lcCursor = oForm_cautare.crs_cursor
|
|
|
|
*-- pcAles trebuie sa reflecte marcajul curent INAINTE de a incepe (formularul e deja afisat,
|
|
*-- creat in main); il sincronizez manual cu cAles-ul formularului la pornire, exact cum face
|
|
*-- BINDEVENT(Thisform,"lAles",...) + do_alege() in fluxul real (do_alege scrie in AMBELE,
|
|
*-- Thisform.cAles si pcAles - vezi cauta_alfa_forms.vc2:405-418).
|
|
pcAles = oForm_cautare.cAles
|
|
|
|
*-- === FAZA 1: marcare - simuleaza interactiunea utilizatorului cu formularul REAL ===
|
|
*-- IMPORTANT: NU se atinge oForm_cautare dupa do_termin()/do_renunt() - acele metode fac
|
|
*-- this.Release, care DISTRUGE efectiv formularul VFP (verificat empiric: accesarea unei
|
|
*-- proprietati dupa Release da eroare 1924 "is not an object", chiar daca alta variabila
|
|
*-- (goDlgA) inca "tine" referinta) - de-aia cauta_alfa.prg REAL insusi nu mai citeste nimic
|
|
*-- de pe oForm_cautare dupa .Show() decat prin pcAles/gnButon (variabile libere, nu proprietati
|
|
*-- de obiect). Orice diagnostic despre cAles trebuie capturat AICI, inainte de faza 2.
|
|
DO CASE
|
|
CASE gcTestScenariu == 'A'
|
|
*-- marcheaza randul BULDOEXCAVATOR prin mecanismul real (echivalentul click pe denumire /
|
|
*-- SPACE): do_alege() citeste RECNO() curent al cursorului si toggle-uie cAles la acea pozitie.
|
|
SELECT (lcCursor)
|
|
LOCATE FOR ALLTRIM(denumire) == 'BULDOEXCAVATOR'
|
|
IF FOUND()
|
|
oForm_cautare.do_alege()
|
|
ENDIF
|
|
lcCAlesDupaMarcare = oForm_cautare.cAles
|
|
IF TYPE('gcUILog') = 'C'
|
|
DO HarnessStep WITH 1, 'scenariul A: BULDOEXCAVATOR marcat (Thisform.cAles=[' + lcCAlesDupaMarcare + ']), inainte de OK real'
|
|
ENDIF
|
|
|
|
CASE gcTestScenariu == 'B'
|
|
*-- nimic marcat
|
|
SELECT (lcCursor)
|
|
GO TOP
|
|
lcCAlesDupaMarcare = oForm_cautare.cAles
|
|
|
|
CASE gcTestScenariu == 'C'
|
|
*-- "dublu-click pe denumire": in modul multi-select (lAles=.T., cazul cauta_nom_articole),
|
|
*-- BindEvent(dblClick->do_termin) NU se armeaza (cauta_alfa_forms.vc2:652 "If !Thisform.lales"),
|
|
*-- deci dublu-click = 2x acelasi Click -> do_alege() de 2 ori (marcheaza, apoi demarcheaza) -
|
|
*-- NU exista submit rapid pe dublu-click in acest dialog. Simulez exact gestul (2 click-uri pe
|
|
*-- Column1.Text1, handler-ul REAL) si documentez ca cursorul ramane nemarcat.
|
|
SELECT (lcCursor)
|
|
LOCATE FOR ALLTRIM(denumire) == 'BULDOEXCAVATOR'
|
|
IF FOUND()
|
|
oForm_cautare._GRID1.Column1.Text1.Click()
|
|
oForm_cautare._GRID1.Column1.Text1.Click()
|
|
ENDIF
|
|
lcCAlesDupaMarcare = oForm_cautare.cAles
|
|
IF TYPE('gcUILog') = 'C'
|
|
DO HarnessLog WITH 'scenariul C: dupa 2x Click (dublu-click simulat) cAles=[' + lcCAlesDupaMarcare + '] (astept ramas needecis, fara submit automat)'
|
|
ENDIF
|
|
|
|
OTHERWISE
|
|
lcCAlesDupaMarcare = oForm_cautare.cAles
|
|
ENDCASE
|
|
|
|
*-- diagnostic cerut de team lead: pcAles (variabila PRIVATE folosita mai jos in filtrul WHERE al
|
|
*-- XML-ului) vs Thisform.cAles (marcajul vizual/albastrit vazut de Marius) - trebuie sa fie
|
|
*-- SINCRONE la acest punct, INAINTE de faza 2 (inchidere), pentru ca acolo se pierde accesul.
|
|
gcTestPcAlesInainte = pcAles
|
|
gcTestCAlesInainte = lcCAlesDupaMarcare
|
|
|
|
*-- === FAZA 2: inchidere - butonul OK/Cancel REAL (this.Release -> oForm_cautare devine inert) ===
|
|
DO CASE
|
|
CASE gcTestScenariu == 'A' OR gcTestScenariu == 'B' OR gcTestScenariu == 'C'
|
|
oForm_cautare.do_termin() && butonul OK REAL (_frm_base.do_termin: gnButon=1, Release)
|
|
OTHERWISE
|
|
oForm_cautare.do_renunt()
|
|
ENDCASE
|
|
DOEVENTS FORCE
|
|
|
|
*-- === de aici incolo: cod IDENTIC cu cauta_alfa.prg original (COMUN\programe\cauta_alfa.prg,
|
|
*-- liniile 218-249) - aceeasi conditie, acelasi filtru (pcAles), acelasi CURSORTOXML. NU se mai
|
|
*-- atinge oForm_cautare (a fost Release-uit de do_termin/do_renunt mai sus). ===
|
|
lcCursorXML = ""
|
|
SELECT (lcCursor)
|
|
IF gnButon=1
|
|
Do Case
|
|
Case tnTipReturn = 0
|
|
Scatter Name oReturnScattObj Memo
|
|
Otherwise
|
|
Select * From (lcCursor) With (Buffering = .T.) Where Substr(pcAles,Recno(),1) = 'X' ;
|
|
INTO Cursor crsReturnAlfa
|
|
Cursortoxml("crsReturnAlfa", "lcCursorXML", 2, 0+2+8, 0, "1")
|
|
gcTestRandiuriMarcate = RECCOUNT('crsReturnAlfa')
|
|
Use In crsReturnAlfa
|
|
Endcase
|
|
Else
|
|
Do Case
|
|
Case tnTipReturn = 0
|
|
Scatter Name oReturnScattObj Blank
|
|
Otherwise
|
|
lcCursorXML = ""
|
|
Endcase
|
|
Endif
|
|
|
|
*-- expus pentru diagnostic in testul principal (cAles luat din snapshot-ul de dinainte de
|
|
*-- Release - vezi FAZA 1 - NU de pe oForm_cautare, care e deja inert dupa do_termin/do_renunt)
|
|
gcTestGnButon = gnButon
|
|
gcTestXML = lcCursorXML
|
|
gcTestLenXML = LEN(m.lcCursorXML)
|
|
gcTestCAles = lcCAlesDupaMarcare
|
|
gcTestPcAles = pcAles
|
|
|
|
*-- NU dau Release aici (obiectul e deja Release-uit de do_termin/do_renunt mai sus)
|
|
Use In (lcCursor)
|
|
|
|
Do Case
|
|
Case tnTipReturn = 0
|
|
Return oReturnScattObj
|
|
Otherwise
|
|
Return lcCursorXML
|
|
Endcase
|
|
|
|
Endproc && cauta_alfa (shadow test)
|