From 3d6f1644aa56746eccd50bbfea81214239ba6cfb Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Wed, 15 Jul 2026 21:12:22 +0300 Subject: [PATCH] Reguli de lucru agent + testare headless (test_init_env_auto, harness repro CNRCRT, doc depanare); flux editare: aprobare pe patch inainte de write-back Co-Authored-By: Claude Fable 5 --- docs/depanare_testare_vfp.md | 106 ++++++++ docs/flux-editare-vfp-text.md | 4 +- docs/reguli_lucru.md | 15 ++ utile/Teste/test_init_env_auto.prg | 298 +++++++++++++++++++++++ utile/Teste/test_repro_cnrcrt_footer.prg | 125 ++++++++++ 5 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 docs/depanare_testare_vfp.md create mode 100644 docs/reguli_lucru.md create mode 100644 utile/Teste/test_init_env_auto.prg create mode 100644 utile/Teste/test_repro_cnrcrt_footer.prg diff --git a/docs/depanare_testare_vfp.md b/docs/depanare_testare_vfp.md new file mode 100644 index 0000000..8267abe --- /dev/null +++ b/docs/depanare_testare_vfp.md @@ -0,0 +1,106 @@ +# Depanare si testare VFP fara IDE (headless) + +Metoda folosita la depanarea erorii "Property CNRCRT is not found" (ROACONT 2.11.61, +15.07.2026) - reutilizabila pentru orice bug runtime VFP. Complementara cu +`flux-editare-vfp-text.md` (editare .vcx/.scx pe text) si `cautare_vcx_vct.md` (cautare). + +## 0. Reguli de lucru + +Vezi `reguli_lucru.md` (diff ca fisier + aprobare inainte de write-back, comentarii +max o linie, modificari minime). + +## Fisiere de testare (foloseste-le la orice depanare/testare viitoare) + +- `COMUN\utile\Teste\test_init_env_auto.prg` - initializare completa de mediu FARA + interactiune (parametri: host, schema, parola; implicit CENTRAL / MARIUSM_AUTO). + Echivalentul headless al `COMUN\programe\test_init_env.prg` (care ramane varianta + interactiva, cu INPUTBOX si meniu de lansare formulare). +- `COMUN\utile\Teste\test_repro_cnrcrt_footer.prg` - exemplu complet de harness: + init mediu -> replicare flux (cursoarele din modificanote) -> instantiere forma reala -> + executie pas cu pas cu logare -> verdict OK/BUG. Copiaza-i structura pentru bug-uri noi. +- `COMUN\utile\Teste\teste_roacont.prg` si `COMUN\utile\Teste\test.prg` - teste ad hoc istorice. +- Mediu de test standard: server `CENTRAL`, schema `MARIUSM_AUTO`, parola schemei + `ROMFASTSOFT`; utilizator de aplicatie "MARIUS M" / parola "123" (unde e nevoie de login). + +## 1. Citirea log-ului aplicatiei (log.txt in radacina proiectului) + +`ErrorHandler` (roacont.prg) scrie pentru fiecare eroare: `nErrror`, `cMethod`, +`line` (0 daca exe-ul e compilat fara debug info) si stack-ul complet. + +Semantica ON ERROR (esentiala la interpretare): +- Dupa ce handlerul face RETURN, executia CONTINUA de la linia urmatoare din metoda + care a crapat. O singura cauza produce deci CASCADE de erori. +- Tipar clasic: eroare pe linia `WITH ` => urmatoarele linii `.prop = ...` dau + 1940 "Expression is not valid outside of WITH/ENDWITH", apoi `ENDWITH` da + 1939 "WITH/ENDWITH mismatch". PRIMA eroare din secventa e cea reala; restul e zgomot. +- Erorile din interiorul TRY/CATCH nu ajung in log (inghitite). Un CATCH gol poate + ascunde ani de zile un defect latent, care "explodeaza" cand codul din jur se repara + (exact cazul typo-ului oMinHeaderHeight din cusfonthandler). +- In stack, liniile "ON..." sunt dispatch-uri (ON ERROR / READ EVENTS), nu metode reale. + +## 2. Rulare headless a scripturilor VFP + +Sablonul unui script de diagnostic (vezi `utile\Teste\test_repro_cnrcrt_footer.prg`): +- logare in fisier cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola); +- `ON ERROR DO WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza + si continua - mimeaza comportamentul ErrorHandler din aplicatie; +- `QUIT` obligatoriu la final (altfel ramane vfp9.exe agatat); +- lansare din PowerShell cu timeout: + `$p = Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -ArgumentList '-A','-T','"D:\...\script.prg" PARAM' -PassThru; $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }` +- `-A` ignora config, `-T` fara ecran de start; parametrul dupa .prg ajunge in LPARAMETERS. +- LINENO() din handler e relativ la inceputul metodei (utile pentru localizare in .vc2: + linia din metoda = linia raportata + linia PROCEDURE din .vc2). + +Precautii: nu rula cu VFP IDE sau exe-ul aplicatiei deschis (lock pe binare); +sterge .fxp-ul vechi de langa .prg daca ai editat scriptul intre rulari. + +## 3. Mediu complet cu Oracle, fara interactiune + +`utile\Teste\test_init_env_auto.prg` = varianta neinteractiva a +`programe\test_init_env.prg` (fara INPUTBOX/xmenu): primeste host/schema/parola ca +parametri, seteaza PATH/CLASSLIB/PROCEDURE ca roacont.prg, instantiaza +goConn/goExecutor/goApp/goLog, incarca goFirma/goCalendar/optiuni si pachetele de +sesiune Oracle. Dupa apel poti instantia forme reale (`CREATEOBJECT('frm_xxx', ...)`) +si apela metodele lor punctual, cu cursoarele pregatite ca in fluxul real. + +Pentru forme care se deschid modal (Show(1) blocheaza), nu apela Show: replica in +script doar liniile relevante din Show (attach, calcule) si logheaza starea intre ele. + +## 4. Bisectia versiunilor de clase (regresii) + +Cand un bug apare "de azi", compara comportamentul cu clasa veche fara a atinge SVN: +1. `git show :clase/fisier.vcx > temp\fisier.vcx` (+ .vct identic); +2. convertit la text pentru diff: `vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt`; +3. in scriptul de test, `SET CLASSLIB TO temp\fisier.vcx ADDITIVE` (varianta veche) + vs. cea din COMUN (varianta noua) - A/B pe acelasi flux; +4. cand difera rezultatul, cauza e in diff-ul acelei clase (sau intr-un defect latent + pe care noul cod il activeaza - vezi capcanele de mai jos). + +## 5. Capcane VFP descoperite (de verificat la bug-uri asemanatoare) + +- `SELECT ... INTO CURSOR` NU mosteneste indecsii cursorului sursa. Orice + `Seek(..., 'cursor', 'tag')` pe copie crapa. `update_jtva_coloane` creeaza + `INDEX ON id_jtva_coloana TAG id_jtva`; daca ii copiezi rezultatul, recreeaza indexul. +- Un grid isi pierde TOATE coloanele (ColumnCount devine 0, fara nicio eroare in log) + daca un ControlSource crapa la re-evaluare in timp ce coloanele sunt atinse + programatic (ex. FontName/FontSize per coloana in cusfonthandler.ApplyFontToGrid, + la Init-ul formei prin _frmbase.SetFont). Simptome tipice in aval: + `_grdfooter.attachtogrid` copiaza 0 coloane, apoi `calctotal` da + "Property is not found" la `Getpem(This, This.cColWithLabel)`. +- ControlSource-uri cu campuri inexistente in RecordSource sunt tolerate la afisare, + dar orice expresie care ARUNCA eroare la evaluare (Seek pe tag lipsa, functie + nedefinita) declanseaza comportamentul de mai sus. +- Fix-ul unui typo intr-o clasa partajata poate activa defecte latente in aval + (codul care nu rulase niciodata incepe sa ruleze). La regresii dupa fix-uri + "inofensive" in COMUN, cauta defectul latent, nu doar diff-ul. + +## 6. Studiu de caz: "Property CNRCRT is not found" (15.07.2026) + +Lant complet: `frm_import_extrase_banca.modificanote` copia `crsJTVATemp` fara index +(defect latent) -> coloana `cExplicatieTVA` din `frm_modific2024.grdRulaje` face +`Seek(trul.id_jtva_coloana,'crsJtvaTemp','id_jtva')` in ControlSource -> fix-ul +typo-ului `oMinHeaderHeight`->`nMinHeaderHeight` in `cusfonthandler` (r17869) a facut +ca ApplyFontToGrid sa atinga coloanele la Init -> grid-ul a ramas cu 0 coloane -> +footer-ul a crapat in calctotal. Fix: `INDEX ON id_jtva_coloana TAG id_jtva` dupa +SELECT INTO in modificanote. Repro/regresie: `utile\Teste\test_repro_cnrcrt_footer.prg` +(mod FARAINDEX reproduce bug-ul, mod CUINDEX valideaza fix-ul). diff --git a/docs/flux-editare-vfp-text.md b/docs/flux-editare-vfp-text.md index 091058a..f640c0e 100644 --- a/docs/flux-editare-vfp-text.md +++ b/docs/flux-editare-vfp-text.md @@ -14,7 +14,9 @@ Parametrii per proiect (pjx, CacheRoot, exe): in `docs\` proiectului. NU tool-ul Edit/Write (UTF-8 strica diacriticele). Continut nou ASCII, TAB-uri ca in jur, fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`. 3. Patch review: `git diff --no-index > docs/diff_runda_.patch` - (exit 1 = normal). Commit doar dupa confirmare pe patch + test in IDE. + (exit 1 = normal). Utilizatorul revizuieste FISIERUL de patch si aproba; write-back-ul + (pasul 5) se face DOAR dupa aprobare. Commit doar dupa confirmare pe patch + test in IDE. + Comentariile in cod: maxim o linie (`*!* DD.MM.YYYY autor - motiv scurt`), fara explicatii lungi. 4. Preconditie write-back: niciun proces vfp9/ (tin lock pe binar); nu se omoara. 5. Write-back: `txt2vcx.ps1 -TextFile -ProjectRoot -CacheRoot ` (+ `-AllowComun` cu aprobare explicita pentru tinte COMUN — afecteaza toate aplicatiile ROA). diff --git a/docs/reguli_lucru.md b/docs/reguli_lucru.md new file mode 100644 index 0000000..7dded0b --- /dev/null +++ b/docs/reguli_lucru.md @@ -0,0 +1,15 @@ +# Reguli de lucru agent (comune proiectelor ROA VFP) + +1. Modificari de cod: livreaza FISIER de diff `docs\diff_runda_.patch` + (`git diff --no-index `), nu diff in terminal. + Write-back in binar (txt2vcx) si commit DOAR dupa aprobarea patch-ului de catre utilizator. +2. Comentarii in cod: max o linie `*!* DD.MM.YYYY autor - motiv scurt`. + Explicatiile merg in docs/ sau in mesajul de commit, nu in cod. +3. Modificari minime: doar ce s-a cerut; fara refactorizari sau curatenie din oficiu. +4. Testare headless (fara IDE): `vfp9.exe -A -T "" ` din PowerShell, + logare cu STRTOFILE, `ON ERROR` care logheaza si continua, QUIT la final. + Init mediu neinteractiv: `utile\Teste\test_init_env_auto.prg` (CENTRAL / MARIUSM_AUTO; + user aplicatie "MARIUS M"/"123"). Exemplu harness complet: `utile\Teste\test_repro_cnrcrt_footer.prg`. + Metoda de depanare (log.txt, cascade ON ERROR, bisectie clase): `depanare_testare_vfp.md`. +5. Editare .vcx/.scx pe text (cache, cp1252 byte-safe, fidelity-check): `flux-editare-vfp-text.md`. + Cautare in binare: `cautare_vcx_vct.md`. diff --git a/utile/Teste/test_init_env_auto.prg b/utile/Teste/test_init_env_auto.prg new file mode 100644 index 0000000..0d22299 --- /dev/null +++ b/utile/Teste/test_init_env_auto.prg @@ -0,0 +1,298 @@ +* test_init_env_auto.prg +* Varianta NEINTERACTIVA a COMUN\programe\test_init_env.prg, pentru rulare headless +* (vfp9.exe -A -T "script.prg") din scripturi de depanare / teste automate. +* Nu are INPUTBOX/xmenu: primeste conexiunea ca parametri si NU lanseaza nimic la final. +* +* Utilizare (dintr-un script apelant, vezi test_repro_cnrcrt_footer.prg): +* DO test_init_env_auto WITH 'CENTRAL', 'MARIUSM_AUTO', 'parola' +* IF gnHandle <= 0 ... eroare conectare +* Mediu de test standard: server CENTRAL, schema MARIUSM_AUTO (parola schemei la MM); +* utilizatorul de aplicatie corespunzator: "MARIUS M" / parola "123" (pentru fluxurile +* care cer login de aplicatie; harness-ul nu trece prin frm_login). +* +* Dupa apel sunt disponibile: goConn/goExecutor/goApp/goLog/goApi, goFirma/goCalendar, +* gnAn/gnLuna/gcS/gnIdFirma etc., SET PATH/CLASSLIB/PROCEDURE ca in roacont.prg, +* pachetele Oracle de sesiune setate (pack_sesiune/pack_contafin). +* ATENTIE: mentine lista de SET CLASSLIB/PROCEDURE sincronizata cu test_init_env.prg. + +LPARAMETERS tcHost, tcSchema, tcPassword, tnAn, tnLuna + +tcHost = IIF(EMPTY(tcHost), 'CENTRAL', tcHost) +tcSchema = IIF(EMPTY(tcSchema), 'MARIUSM_AUTO', tcSchema) +tcPassword = IIF(EMPTY(tcPassword), 'ROMFASTSOFT', tcPassword) + +SET DELETED ON +SET ANSI ON +SET EXACT ON +SET SAFETY OFF +CLOSE DATABASES +SET CENTURY ON +SET DATE DMY +SET NULLDISPLAY TO '' + +PUBLIC CT_SUCCES, CT_INSUCCES, crlf, gnAn, gnLuna, gnIdUtil, glEMama, gnIdFirma, gcCondSucursala, ; + gnIdSucursala, gcS, gcFirma, gcUserName, gcNumeProgram, gcAppName, glLunaInchisa, ; + buton, gnButon, pnButon, gl406, gcAcces +CT_SUCCES = 1 +CT_INSUCCES = -1 +crlf = CHR(13) + CHR(10) +gnAn = IIF(EMPTY(tnAn), YEAR(DATE()), tnAn) +gnLuna = IIF(EMPTY(tnLuna), MONTH(DATE()), tnLuna) +gnIdUtil = -3 +gnIdFirma = 110 +gcCondSucursala = [] +gnIdSucursala = m.gnIdFirma +gcS = UPPER(ALLTRIM(tcSchema)) +gcFirma = m.gcS +gcUserName = m.gcS +gcNumeProgram = [ROACONT] +gcAppName = [ROACONT] +glLunaInchisa = .F. +glEMama = .F. +gl406 = .F. +* PUBLIC, nu Declare: acest program se termina cu RETURN, iar nrcrt() (oproceduri_comune.prg) +* citeste NROR din ControlSource-uri de grid mult dupa aceea (in roacont.prg, Declare traieste +* cat programul principal; aici ar muri la RETURN si gridurile si-ar pierde coloanele) +PUBLIC nror(65000) +buton = 1 +gnButon = 1 +pnButon = 1 + +LOCAL lcPath +PUBLIC gcAppPath, DIRGEN, gcBasePath, gcTempPath, gcGeneralIniFile, gcSettingsFile +gcAppPath = [D:\ROA\ROACONT\] +Set Default To (gcAppPath) +lcPath = gcAppPath + 'Date;' + ; + gcAppPath + 'Include;' + ; + gcAppPath + 'FERESTRE;' + ; + gcAppPath + 'GRAFICE;' + ; + gcAppPath + 'CLASE;' + ; + gcAppPath + 'MENIURI;' + ; + gcAppPath + 'PROGRAME;' + ; + gcAppPath + 'RAPOARTE;' + ; + gcAppPath + 'COMUN\CLASE;' + ; + gcAppPath + 'COMUN\FERESTRE;' + ; + gcAppPath + 'COMUN\PROGRAME;' + ; + gcAppPath + 'COMUN\GRAFICE;' + ; + gcAppPath + 'COMUN\RAPOARTE;' + ; + gcAppPath + 'COMUN\UTILE\CALENDAR;' + ; + gcAppPath + 'COMUN\UTILE\CTL32;' + ; + gcAppPath + 'COMUN\UTILE\HPDF;' + ; + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ; + gcAppPath + 'COMUN\UTILE\WEB;' + ; + gcAppPath + 'COMUN\UTILE\NFJSON;' + ; + gcAppPath + 'COMUN\UTILE\NFXML;' + ; + gcAppPath + 'COMUN\UTILE\EXCEL;' + ; + gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + ; + Addbs(Substr(gcAppPath,1,Rat([\],gcAppPath,2)))+[COMUNROA\] +SET PATH TO &lcPath ADDITIVE + +Set Classlib To clase\cont2000 Additive +Set Classlib To appwiz Additive +Set Classlib To CAUT Additive +Set Classlib To BAZA Additive +Set Classlib To contab Additive +Set Classlib To comun Additive +Set Classlib To registry Additive +Set Classlib To cauta_alfa_forms.vcx Additive +Set Classlib To obalanta Additive +Set Classlib To ocriterii.vcx Additive +Set Classlib To ctl32_statusbar.vcx Additive +Set Classlib To ctl32_common.vcx Additive +Set Classlib To ctl32_structs.vcx Additive +Set Classlib To ctl32_progressbar.vcx Additive + +Set Procedure To PROCEDURI Additive +Set Procedure To pmenu Additive +Set Procedure To proceduri_comune Additive +Set Procedure To mesaje Additive +Set Procedure To acces_meniu Additive +Set Procedure To quitapp Additive +Set Procedure To init_program Additive +Set Procedure To oproceduri_maintenance.PRG Additive +Set Procedure To gridproc Additive +Set Procedure To proceduri_excel Additive +Set Procedure To oserii_numere.PRG Additive +Set Procedure To cauta_alfa Additive +Set Procedure To oproceduri_parteneri Additive +Set Procedure To oproceduri_incasari Additive +Set Procedure To wwconfig Additive +Set Procedure To oexport Additive +SET PROCEDURE TO ocasabanca ADDITIVE +SET PROCEDURE TO importfromxlsx ADDITIVE +SET PROCEDURE TO appendfromxlsx.prg ADDITIVE +SET PROCEDURE TO overificari.prg ADDITIVE +SET PROCEDURE TO onomenclatoare.prg ADDITIVE +SET PROCEDURE TO excelxml.prg ADDITIVE +SET PROCEDURE TO saft_d406.prg ADDITIVE + +Set Classlib To DECABAZA Additive +Set Classlib To onomenclatoare Additive +Set Classlib To oparteneri Additive +Set Classlib To OCASABANCA Additive +Set Classlib To OVANZCUMP Additive +Set Classlib To oCompensari Additive +Set Classlib To oRapoarte_cont Additive +Set Classlib To oSit_Op Additive +Set Classlib To overificari Additive +Set Classlib To oteste Additive +Set Classlib To omodificari Additive +Set Classlib To ooptiuni Additive +Set Classlib To ointroduceri_cont Additive +Set Classlib To onote_contabile Additive +Set Classlib To odebcred Additive +Set Classlib To ferestre_oracle Additive +Set Classlib To caut_ora Additive +Set Classlib To otoolbar Additive +Set Classlib To inchideri_sal Additive +Set Classlib To serii_numere Additive +Set Classlib To contabilitate_rapoarte Additive +Set Classlib To oconversii Additive +Set Classlib To oactualizari Additive +Set Classlib To anaf_efactura Additive + +Set Classlib To Messagebox Additive +SET CLASSLIB TO wwdialogs ADDITIVE +SET CLASSLIB TO orapoarte.vcx additive +SET CLASSLIB TO orapoarte_contabilitate.vcx additive +SET CLASSLIB TO accessibility.vcx ADDITIVE +SET CLASSLIB TO _calendar.vcx ADDITIVE +SET CLASSLIB TO orapoarte_comun.vcx ADDITIVE +SET CLASSLIB TO saft_d406.vcx ADDITIVE + +Set Procedure To GENCURSOR.PRG Additive +Set Procedure To OPROCEDURI_COMUNE.PRG Additive +Set Procedure To OINIT_OPTIUNI.PRG Additive +Set Procedure To updateserver.PRG Additive +Set Procedure To oCompensari.PRG Additive +Set Procedure To oSituatii_Operative.PRG Additive +Set Procedure To oOperatii_comune.PRG Additive +Set Procedure To OCONT2003.PRG Additive +Set Procedure To OPROCEDURI_aMS.PRG Additive +Set Procedure To oparteneri.PRG Additive +Set Procedure To orapoarte.PRG Additive +Set Procedure To orap_trezorerie Additive +Set Procedure To ocautare Additive +Set Procedure To omeniu_initializari Additive +Set Procedure To osecurity Additive +Set Procedure To oheader Additive +Set Procedure To orefaceri Additive +Set Procedure To oproceduri_casademarcat Additive +Set Procedure To controllerecr Additive +Set Procedure To oproceduri_comune_imob.PRG Additive +Set Procedure To oproceduri_conversie.PRG Additive +Set Procedure To odocumente.PRG Additive +Set Procedure To oproceduri_actualizari.PRG Additive +SET PROCEDURE TO orapoarte_dinamice.prg additive +SET PROCEDURE TO update_imob.prg ADDITIVE +SET PROCEDURE TO oproceduri_import.prg ADDITIVE +Set Procedure To wwutils.PRG Additive +Set Procedure To wwxmlhttp.PRG Additive +Set Procedure To ini.PRG Additive +Set Procedure To regex.PRG Additive +Set Procedure To validare.PRG Additive +Set Procedure To oproceduri_evolutie Additive +Set Procedure To oproceduri_decont Additive +Set Procedure To proceduri_rapoarte.PRG Additive +SET PROCEDURE TO anaf_efactura.prg ADDITIVE +SET PROCEDURE TO iniacces.prg ADDITIVE +SET PROCEDURE TO oupdate.prg additive +SET PROCEDURE TO procese.prg additive +SET PROCEDURE TO version.prg additive +SET PROCEDURE TO xmlaccess.prg additive +SET PROCEDURE TO xmlparser.prg additive +SET PROCEDURE TO filebringer.prg additive +SET PROCEDURE TO wwcodeupdate.prg additive +SET PROCEDURE TO wwhttp.prg ADDITIVE +SET PROCEDURE TO wwapi.prg ADDITIVE + +Declare Integer GetPrivateProfileString In WIN32API ; + string, String, String, String @, Integer, String +Declare Integer WritePrivateProfileString In Win32Api ; + string, String, String, String +Declare Integer CopyFile In WIN32API ; + STRING lpExistingFileName, STRING lpNewFileName, INTEGER bFailIfExists +Declare Integer PathFileExists In shlwapi STRING pszPath + +If Type('goApi') = 'U' + Public goApi + goApi = Newobject("wwAPI", "wwAPI.prg") +ENDIF + +set procedure to oinit_optiuni.prg additive +set procedure to oproceduri_comune.prg additive + +PUBLIC gnHandle, goExecutor, goConn, goFirma, goCalendar, poLog, goLog, goApp +DIRGEN = [D:\ROA\] +gcBasePath = dirgen +gcGeneralIniFile = DIRGEN + "settings.ini" +gcSettingsFile = m.gcGeneralIniFile +gcTempPath = Addbs(shortpath(goApi.GetTempPath())) + gcS + [\] +If !Directory(gcTempPath) + Md (gcTempPath) +Endif +gcAcces = [1;2;3;4;5;6;7;8;] + +poLog = Newobject("Log_Mesaje","Log_Mesaje.prg") +goLog = poLog +goApp = Createobject("wzApplication") +gnHandle = 0 +goExecutor = createobject("oExecutor") +goConn = createobject("oConn") +goConn.Connect(m.tcHost, m.tcSchema, m.tcPassword) +IF m.gnHandle <= 0 + RETURN .F. +ENDIF + +LOCAL llSucces, lcSql +goFirma = null +llSucces = goExecutor.oExecuta("select * from syn_v_nom_firme where schema = ?gcS", "cFirma") +IF m.llSucces + SELECT cFirma + gnIdFirma = id_firma + gnIdSucursala = null + gcFirma = ALLTRIM(firma) + SCATTER NAME goFirma +ELSE + goFirma = CREATEOBJECT('custom') + goFirma.addproperty('cod_fiscal', '') + goFirma.addproperty('schema', m.gcS) + goFirma.addproperty('firma', m.gcS) +ENDIF +USE IN (SELECT('cFirma')) + +goCalendar = null +llSucces = goExecutor.oExecuta('SELECT anul, luna, tva_incasare FROM calendar WHERE an*12+luna = (select MAX(an*12+luna) FROM calendar)', 'cCalendar') +IF m.llSucces + SELECT cCalendar + GO TOP + IF EMPTY(m.tnAn) + gnAn = anul + gnLuna = luna + ENDIF + SCATTER NAME goCalendar +ENDIF +USE IN (SELECT('cCalendar')) + +CREATE CURSOR dual (dummy c(10)) +INSERT INTO dual (dummy) VALUES ("") + +actualizeaza_optiuni() +Do optiuni_firma IN oinit_optiuni.prg + +lcSql = [begin pack_sesiune.set_Id_Util(?gnIdUtil); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_sesiune.setluna(?gnLuna); pack_sesiune.setan(?gnAn); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_sesiune.setlunabal(?gnLuna); pack_sesiune.setanbal(?gnAn); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_contafin.SET_DATA_RON(?gcS); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_sesiune.set_data_ron(?gcS); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_contafin.set_id_sucursala(?gnIdSucursala); end;] +llSucces = goExecutor.oExecuta(lcSql) +lcSql = [begin pack_contafin.set_id_firma(?gnIdFirma); end;] +llSucces = goExecutor.oExecuta(lcSql) + +RETURN .T. diff --git a/utile/Teste/test_repro_cnrcrt_footer.prg b/utile/Teste/test_repro_cnrcrt_footer.prg new file mode 100644 index 0000000..d00ac3d --- /dev/null +++ b/utile/Teste/test_repro_cnrcrt_footer.prg @@ -0,0 +1,125 @@ +* test_repro_cnrcrt_footer.prg +* Repro/regresie pentru eroarea "Property CNRCRT is not found" din +* FRM_MODIFIC2024.PGFARTICOLE.PAGE1._GRDFOOTER1.CALCTOTAL +* (Import extrase bancare > Generare note, ROACONT 2.11.61, 15.07.2026). +* +* Cauza (dovedita prin bisectie, vezi COMUN\docs\depanare_testare_vfp.md): +* - frm_import_extrase_banca.modificanote crea crsJTVATemp prin +* SELECT * INTO CURSOR (copia pierde indexul TAG id_jtva creat de update_jtva_coloane); +* - coloana cExplicatieTVA din frm_modific2024.grdRulaje face Seek pe acel tag in ControlSource; +* - dupa repararea typo-ului oMinHeaderHeight->nMinHeaderHeight in cusfonthandler +* (accessibility.vcx, r17869), ApplyFontToGrid atinge coloanele la Init; +* evaluarea ControlSource-ului cu Seek pe tag inexistent face grid-ul sa-si piarda +* TOATE coloanele => footer-ul se ataseaza la 0 coloane => calctotal crapa la +* Getpem(This, cColWithLabel). +* +* Rulare headless (nu tine VFP IDE deschis; nu rula cu roacont.exe pornit): +* & "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T ; +* "D:\ROA\ROACONT\COMUN\utile\Teste\test_repro_cnrcrt_footer.prg" [MOD] +* MOD: +* CUINDEX (implicit) - fluxul corectat (index pe crsJTVATemp). Asteptat: 63 coloane, OK. +* FARAINDEX - fluxul vechi, fara index. Asteptat: 0 coloane + eroarea CNRCRT +* (reproduce bug-ul; util ca test de regresie al capcanei). +* Rezultatul se scrie in %TEMP%\test_repro_cnrcrt_footer.txt, ultima linie REZULTAT: OK/BUG. + +LPARAMETERS tcMode +tcMode = IIF(EMPTY(tcMode), 'CUINDEX', UPPER(ALLTRIM(tcMode))) + +PUBLIC gcLogFile, gnErrCNRCRT +gcLogFile = ADDBS(SYS(2023)) + 'test_repro_cnrcrt_footer.txt' +gnErrCNRCRT = 0 +STRTOFILE('START ' + tcMode + ' ' + TTOC(DATETIME()) + CHR(13)+CHR(10), gcLogFile) + +ON ERROR DO ReproErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() +ON SHUTDOWN QUIT + +DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT' +IF gnHandle <= 0 + DO ReproLog WITH 'EROARE: conectare Oracle esuata' + DO ReproLog WITH 'REZULTAT: NEDETERMINAT' + QUIT +ENDIF +DO ReproLog WITH 'mediu OK, gnAn=' + TRANSFORM(gnAn) + ' luna=' + TRANSFORM(gnLuna) + +* ===== replicare modificanote din frm_import_extrase_banca (partea non-UI) ===== +IF !Used('saft_taxtable') + update_saft_taxtable() +ENDIF +IF !Used('saft_mecanisme_plati') + update_saft_mecanisme_plati() +ENDIF +update_jtva_coloane("JV", 'crsExplicatiiTVATemp', 1) +SELECT * FROM crsExplicatiiTVATemp INTO CURSOR crsJTVATemp READWRITE +IF tcMode == 'CUINDEX' + * fix-ul din modificanote (15.07.2026): copia SELECT INTO pierde indexul + SELECT crsJTVATemp + INDEX ON id_jtva_coloana TAG id_jtva +ENDIF + +LOCAL llSucces, lcSql +lcSql = [SELECT * FROM vact WHERE 1=2] +llSucces = goExecutor.oExecuta(m.lcSql, 'actactan_temp') +lcSql = [select * from vrul_tot where 1=2] +llSucces = goExecutor.oExecuta(lcSql, 'v_rul') +Select *, valoare + valtva As valoarectva, valoarev + valtvav As valoarevctva From v_rul Into Cursor trul READWRITE +Use In (SELECT('v_rul')) +lcSql = [select * from vrul_obinv_tot where 1=2] +llSucces = goExecutor.oExecuta(lcSql, 'v_rul_obinv') +Select *, valoare + valtva As valoarectva, valoarev + valtvav As valoarevctva From v_rul_obinv Into Cursor trul_obinv READWRITE +Use In (SELECT('v_rul_obinv')) + +Select actactan_temp +Select .F. As ales, a.explicatia4 As iban, Iif(!Empty(Nvl(a.id_jtva_coloana, 0)), 1, 0) As Cu_tva, ; + Cast(0 As N(2)) As tipnota, a.*, b.denumire As explicatie_tva_2 ; + From actactan_temp a Left Join crsExplicatiiTVATemp b On a.id_jtva_coloana = b.id_jtva_coloana ; + Into Cursor tact Readwrite +gcAcces = "1;2;3;4;" +Select tact +Go Top + +* ===== forma reala + secventa relevanta din Show ===== +LOCAL loForm, i, lcNames, lnColSrc, lnColFooter +loForm = CREATEOBJECT([frm_modific2024], 90023, .T.) +IF VARTYPE(loForm) <> 'O' + DO ReproLog WITH 'EROARE: frm_modific2024 nu s-a instantiat' + DO ReproLog WITH 'REZULTAT: NEDETERMINAT' + QUIT +ENDIF +Select tact +loForm.grid1.SetFocus +loForm.gridextra1.setup() +loForm.CalculeazaTotal() + +lnColSrc = loForm.pgfArticole.Page1.grdRulaje.ColumnCount +DO ReproLog WITH 'grdRulaje coloane: ' + TRANSFORM(lnColSrc) + +loForm.pgfArticole.page1._grdfooter1.attachtogrid(loForm.pgfArticole.page1.grdRulaje) +lnColFooter = loForm.pgfArticole.Page1._grdfooter1.ColumnCount +DO ReproLog WITH 'footer coloane dupa attach: ' + TRANSFORM(lnColFooter) + +loForm.pgfArticole.page1._grdfooter1.calcTotal() +loForm.pgfArticole.page2._grdfooter1.attachtogrid(loForm.pgfArticole.page2.grdRulajeObinv) +loForm.pgfArticole.page2._grdfooter1.calcTotal() +loForm.Release() + +IF m.lnColSrc > 0 AND m.gnErrCNRCRT = 0 + DO ReproLog WITH 'REZULTAT: OK' +ELSE + DO ReproLog WITH 'REZULTAT: BUG (coloane pierdute sau eroare CNRCRT)' +ENDIF +QUIT + +PROCEDURE ReproErr + LPARAMETERS tnErr, tcMsg, tcProg, tnLine + IF 'CNRCRT' $ UPPER(tcMsg) + gnErrCNRCRT = gnErrCNRCRT + 1 + ENDIF + DO ReproLog WITH 'ERR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg +ENDPROC + +PROCEDURE ReproLog + LPARAMETERS tcMsg + LOCAL lcL + lcL = FILETOSTR(gcLogFile) + STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcLogFile) +ENDPROC