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 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 21:12:22 +03:00
parent fc11f3e99a
commit 3d6f1644aa
5 changed files with 547 additions and 1 deletions

View File

@@ -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 <expr>` => 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 <handler> 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 <rev_vechi>: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 <cColWithLabel> 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).

View File

@@ -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, 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`. fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`.
3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.patch` 3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.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/<exe proiect> (tin lock pe binar); nu se omoara. 4. Preconditie write-back: niciun proces vfp9/<exe proiect> (tin lock pe binar); nu se omoara.
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>` 5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>`
(+ `-AllowComun` cu aprobare explicita pentru tinte COMUN — afecteaza toate aplicatiile ROA). (+ `-AllowComun` cu aprobare explicita pentru tinte COMUN — afecteaza toate aplicatiile ROA).

15
docs/reguli_lucru.md Normal file
View File

@@ -0,0 +1,15 @@
# Reguli de lucru agent (comune proiectelor ROA VFP)
1. Modificari de cod: livreaza FISIER de diff `docs\diff_runda<N>_<subiect>.patch`
(`git diff --no-index <baseline.bak> <editat>`), 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 "<script.prg>" <param>` 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`.

View File

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

View File

@@ -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