diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..74e123e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,58 @@ +# COMUN\docs — index + +Documentatie comuna tuturor produselor ROA. Cititorul e un agent: fiecare fisier tine **regula + +strictul de context care o face aplicabila + comanda de verificare**. Fara "de ce", fara istoric, +fara studii de caz. + +**Se citeste primul: `reguli_lucru.md`** — regulile de livrare + lista de declansatoare ("cand +atingi zona X, citeste fisierul Y"). Restul se deschid doar la declansator. + +## Cand citesti fiecare + +| Fisier | Cand | +|---|---| +| `reguli_lucru.md` | intotdeauna, la inceput de sesiune | +| `orchestrare-subagenti.md` | cand delegi, cand verifici ce intoarce un subagent, la predarea contextului | +| `monitorizare-context.md` | instalarea hook-urilor de prag de context si de revizie a docs | +| `fluxul_svn_git.md` | orice commit / `svn update` / `roa_sync`; ce e interzis pe `main` in COMUN | +| `scripturi-uzuale.md` | exista deja un script pentru sarcina asta? (roa_sync, curatenie, livrare, diagnostice) | +| **VFP** | | +| `cautare_vcx_vct.md` | cauti cod in `.vcx`/`.scx`/`.frx`/`.mnx` | +| `flux-editare-vfp-text.md` | editezi `.vc2`/`.sc2` + write-back; **invariantele si `*p:`/`*m:`** | +| `conventie_encoding_cp1252.md` | fisierul editat are diacritice (cp1250, nu cp1252) | +| `inventar-comun.md` | inainte de cod nou: exista deja o functie/clasa comuna? | +| `conventie_ux_formulare.md` | adaugi/rearanjezi controale pe formular | +| `capcana_grid_controlsource.md` | grid needitabil pe formular cu 2+ grid-uri | +| `capcana_grid_preferinte_utilizator.md` | adaugi o coloana intr-un grid deja livrat | +| `conventie_go_recno.md` | `GO` pe un `Recno()` capturat | +| `conventie_null_vfp.md` | garzi pe valori NULL din Oracle | +| `conventie_goexecutor_alter_table.md` | `ALTER TABLE` pe cursorul de la `oExecute()` | +| **Testare** | | +| `depanare_testare_vfp.md` | rulare headless, depanare bug runtime, capcane VFP | +| `testare-ui-vfp.md` | test cu formular real + screenshots (harness UI) | +| **Oracle** | | +| `conventie_mediu_oracle.md` | te conectezi la dev/test, alegi schema, rulezi un script de pachet | +| `scripturi-migrare-db.md` | modifici schema (tabele/view-uri/pachete); compatibilitate 10.2 | +| `publicare-scripturi-db.md` | publici scripturile catre clienti | +| `oracle_export.md` | reexporti sursa unui pachet PL/SQL | +| `depanare-pack-update.md` | actualizarea ROA nu se finalizeaza la un client | +| `depanare-spatiu-oracle.md` | spatiu plin la un client | +| **Domeniu** | | +| `flux-modificare-stergere-nota-jurnal.md` | modificare/stergere nota; ce face `PACK_CONTAFIN` | +| `tipuri_documente_facturare.md` | `VANZARI.TIP` si seturile de contare `ID_SET` | +| `sold-neexigibil-reportat-jc2007-jv2007.md` | interogari pe sold TVA neexigibil | +| `email-thunderbird.md` | citirea mailurilor de pe conturile romfast | + +`onboarding\` — proceduri rulate o singura data per proiect (inrolare in fluxul git-text, +prompturi de configurare). Nu se citesc in sesiunile de lucru. + +`*.pck` — exporturi de referinta ale pachetelor PL/SQL, pentru grep tintit; nu se citesc intregi. +`cercetare\` — note de cercetare pe subiecte incheiate. + +## Cand adaugi ceva aici + +Doar reutilizabil (80/20): flux ascuns, capcana platita, procedura/tabela cheie. Cateva randuri. +Un subiect are **un singur proprietar** — celelalte fisiere primesc o trimitere de un rand, nu o +copie. Scrie **ASCII**, fara diacritice. Adauga si randul in tabelul de mai sus, plus +declansatorul in `reguli_lucru.md` punctul 7 daca regula se aplica la atingerea unei zone de cod — +fara declansator, regula nu e gasita la timp. diff --git a/docs/cautare_vcx_vct.md b/docs/cautare_vcx_vct.md index 245deaf..8f25eb0 100644 --- a/docs/cautare_vcx_vct.md +++ b/docs/cautare_vcx_vct.md @@ -1,183 +1,75 @@ -# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...) +# Cautare in codul din librariile/formele VFP (.vcx/.vct, .scx/.sct, ...) -Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder — -varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple). - -Căutare de cod-sursă (proceduri, metode, parametri) care **nu** stă în `.prg`, ci în interiorul -binarelor VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte (`.frx`+`.frt`), -meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`). +Partajat intre proiectele ROA*. Cod-sursa (proceduri, metode, parametri) care **nu** sta in +`.prg`, ci in binarele VFP: librarii de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte +(`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`). ## De ce e nevoie de asta -Un `.vcx` e o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. `grep` direct pe -`.vct` găsește textul dar ca binar (octeți `\0` între linii), fără numere de linie și greu de -citit. Soluția: convertim binarul în reprezentarea lui **TEXT** (`.vc2`, `.sc2`, …) — PRG-style -lizibil, metode sortate alfabetic — și căutăm în text cu `grep`/`Grep`. +Un `.vcx` e o tabela DBF: codul metodelor sta in campuri memo in `.vct`. `grep` direct pe `.vct` +gaseste textul dar ca binar (octeti `\0` intre linii), fara numere de linie si greu de citit. +Solutia: se converteste binarul in text (`.vc2`, `.sc2`, ...) si se cauta cu `Grep`. -> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru -> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi -> `PROMPT_cautare_vfp.md` pasul 3 (ordine obligatorie, encoding, fidelity check). Pentru -> `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot în **IDE-ul VFP**. +## Flux curent (proiecte migrate): in-arbore -## Unelte disponibile (verificate) +Migrate: ROACONT, COMUN, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO, ROAFACTURARE, ROACONTRACTE +(prezenta `roa_sync.bat` in radacina proiectului = migrat). -| Unealtă | Cale | Rol | Recomandare | -|---|---|---|---| -| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Fidel, include corpul metodelor, parametri, comentarii | -| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` compilabil | Alternativă mai veche, doar clase, necesită IDE VFP deschis | -| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (direcție opusă) | +Textul `.??2` sta langa binar. La inceput de sesiune si inainte de orice `git commit`: -FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă -toate tipurile de container, text mai fidel decât vcx2prg. - -> Dacă `FoxBin2Prg.EXE` lipsește: deschide `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și -> *Build > Build Executable*. Lângă EXE trebuie să existe `filename_caps.exe` și `props*.txt` -> (deja în folder). - -## Mod recomandat: scriptul `vcx2txt.ps1` - -`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` copiază binarul + memo-ul într-un **cache** care oglindește -structura proiectului (nu murdărește arborele SVN), rulează FoxBin2Prg, păstrează doar textul. -**Incremental** (sare peste ce e deja la zi). - -```powershell -# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu -powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` - -Project '\.pjx' -ProjectRoot '' ` - -CacheRoot 'D:\ROA\_vfp_textcache\' - -# include și rapoartele (.frx) și meniurile (.mnx) -powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` - -Project '\.pjx' -ProjectRoot '' ` - -CacheRoot 'D:\ROA\_vfp_textcache\' -Types vcx,scx,frx,mnx - -# conversie punctuală a unui fișier/folder (chiar dacă NU e în proiect, ex. o clasă din COMUN) -powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '\COMUN\clase\caut.vcx' - -# rebuild curat (șterge cache-ul întâi) / forțează reconversia -powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` - -Project '\.pjx' -ProjectRoot '' ` - -CacheRoot 'D:\ROA\_vfp_textcache\' -Clean +``` +powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot ``` -Exemplu (ROAAUTO): +Apoi cauta direct cu `Grep` in `.??2` din arbore (`PROCEDURE do_salvare`, etc.), citand +`fisier:linie`. -```powershell -powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` - -Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO ` - -CacheRoot D:\ROA\_vfp_textcache\roaauto -``` +## Indexul de simboluri: vfp_symbols.ps1 -> Cache-ul trebuie să stea **în afara** folderului `D:\ROA\UTIL\foxbin2prg`: `ReCreate_FoxBin2Prg.prg` -> face `Prg2Bin` recursiv pe tot folderul uneltei și ar reconverti `.??2`-urile din cache în binare -> rătăcite. - -Rezultatul ajunge în cache, cu aceeași structură de directoare ca proiectul (ex.: -`roaauto\Clase\odevize.vc2`, `roaauto\comun\clase\_frm_base.vc2`). Apoi: - -```bash -grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\_vfp_textcache\" -grep -rln "factura_salvare" "D:\ROA\_vfp_textcache\" # ce clase ating subiectul -``` - -Flux tipic: rulează scriptul o dată (populează cache-ul), apoi caută cu `Grep` în cache. La -sesiuni următoare rescrie doar ce s-a schimbat (incremental). Pentru o librărie din `COMUN\` care -nu e în proiect, convertește-o punctual cu `-Source`. - -## Indexul de simboluri: `vfp_symbols.ps1` - -`grep` spune *unde* e textul, nu *în ce metodă*. Într-un `.vc2` asta contează: fișierele au uzual -zeci de mii de linii, din care ~2/3 sunt proprietăți și metadata (nu cod), iar antetul clasei poate -fi cu mii de linii deasupra potrivirii. `D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1` reține intervalul -de linii al fiecărei clase/metode/proceduri — din cache-ul text **și** din `.prg`-urile proiectului -— și etichetează rezultatele. +`grep`/`Grep` spune *unde* e textul, nu *in ce metoda*. Intr-un `.vc2` cu zeci de mii de linii +(~2/3 proprietati/metadata, nu cod) si 15 clase care au fiecare `Init`/`Show`/`do_adauga`, fara +interval e usor sa nimeresti metoda gresita. ```powershell $s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' -$c = @('-CacheRoot', 'D:\ROA\_vfp_textcache\', '-ProjectRoot', '') +$c = @('-CacheRoot', '', '-ProjectRoot', '') -# căutare etichetată cu clasa.metoda; -CodeOnly taie potrivirile din metadata/proprietăți -powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly -powershell -ExecutionPolicy Bypass -File $s @c -Where '.vc2:' # cine deține linia -powershell -ExecutionPolicy Bypass -File $s @c -Find '' # unde e DEFINIT -powershell -ExecutionPolicy Bypass -File $s @c -Class '' # moștenire + metode +powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly # etichetat clasa.metoda, doar cod +powershell -ExecutionPolicy Bypass -File $s @c -Where '.vc2:' # cine detine linia +powershell -ExecutionPolicy Bypass -File $s @c -Find '' # unde e DEFINIT +powershell -ExecutionPolicy Bypass -File $s @c -Class '' # mostenire + metode ``` -Exemplu (ROAACNPRO — parametrii impliciți ai scriptului țintesc deja acest proiect): +**`-Where`/`-Class` sunt OBLIGATORII inainte de o editare cu `txt2vcx.ps1`** - dau intervalul +exact al metodei. Indexul se reconstruieste din text cand textul e mai nou: ruleaza `git_sync.ps1` +inainte, altfel nu vede modificari facute in IDE si neconvertite. -``` -> vfp_symbols.ps1 -Grep 'calcul_cheiaj' -CodeOnly -clase\oacnpro.vc2:14937: [frm_tranzit.do_executa] llSucces = calcul_cheiaj(m.lcVyeIds) -> vfp_symbols.ps1 -Class oApp -oApp (roaacnpro.prg:88) -> RoaApp (roa.prg:1) -> Custom (clasă de bază VFP) -``` +Limite: nu rezolva apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) - da candidati, nu +certitudine. Clasele de baza VFP (`form`, `custom`) apar neindexate (n-au sursa in proiect). +Copiile vechi de `.prg` din subfoldere sunt excluse implicit prin `-ExcludePrg`; da +`-ExcludePrg ''` ca sa vezi tot. -Când merită în locul unui `grep` direct: - -- **înainte de o editare cu `txt2vcx.ps1`** — `-Where`/`-Class` dau intervalul exact al metodei. - Într-un `.vc2` cu 15 clase, `Init`, `Show`, `do_adauga`, `do_executa2` există în aproape fiecare; - fără interval e ușor să nimerești metoda cu același nume din altă clasă; -- **rezultate multe** — `-CodeOnly` arată doar codul (pe `goExecutor` în ROAACNPRO: 1401 potriviri - de cod din 1505, restul metadata); -- **„definit sau doar apelat?"** — `-Find` dă doar definiția, `grep` dă tot; -- **moștenire** — `-Class` arată lanțul cu fișier:linie, deci se vede dacă o metodă e suprascrisă - local sau vine din `COMUN`. - -Indexul (`_symbols.tsv`, în rădăcina cache-ului) se reconstruiește singur când cache-ul e mai nou -(~4 s pentru ~200 de fișiere); e regenerabil, se poate șterge oricând. Rulează întâi `vcx2txt.ps1`: -indexul e derivat din cache, deci nu poate ști de modificări făcute în IDE și neconvertite. - -Limite: nu rezolvă apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) — dă candidații, nu -certitudinea. Clasele de bază VFP (`form`, `custom`) apar ca neindexate: normal, n-au sursă în -proiect. Copiile vechi de `.prg` din subfoldere (ex. `COMUN\programe\roa\`) sunt excluse implicit -prin `-ExcludePrg`; dă `-ExcludePrg ''` ca să vezi tot. - -## Alternativă manuală (fără script) - -FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului, -copiază perechea binar+memo într-un folder temporar și convertește acolo: - -```powershell -# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG) -Copy-Item D:\ROA\\Clase\odevize.vcx, D:\ROA\\Clase\odevize.vct D:\tmp\ -& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1' -# => D:\tmp\odevize.vc2 -``` - -Poziții parametri: `fișier, cType, cTextName, lGenText, cDontShowErrors=1, cDebug=0, -cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția. (Nu da explicit -`"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.) - -Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`. - -## Soluție rapidă „murdară" (un singur fișier, fără conversie) - -Pentru „există metoda X undeva în librărie?", `grep` merge direct pe `.vct` (îl vede ca binar, dar -găsește potrivirile): - -```bash -grep -c "PROCEDURE" "D:\ROA\\Clase\odevize.VCT" -grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\\Clase\odevize.VCT" -``` - -Bun pentru „da/nu" și nume de metode; pentru corp/context, folosește conversia în text. - -## Corespondență extensii binar → text +## Corespondenta extensii binar -> text | Container | Binar (+memo) | Text | |---|---|---| -| Librărie clase | `.vcx` + `.vct` | `.vc2` | -| Formă | `.scx` + `.sct` | `.sc2` | +| Librarie clase | `.vcx` + `.vct` | `.vc2` | +| Forma | `.scx` + `.sct` | `.sc2` | | Raport | `.frx` + `.frt` | `.fr2` | -| Etichetă | `.lbx` + `.lbt` | `.lb2` | +| Eticheta | `.lbx` + `.lbt` | `.lb2` | | Meniu | `.mnx` + `.mnt` | `.mn2` | -| Bază de date | `.dbc` + `.dct` | `.dc2` | +| Baza de date | `.dbc` + `.dct` | `.dc2` | -## Note +## Proiecte NEmigrate (cache extern) -- Codul aplicației stă mai ales în `Clase\*.vcx`; multe `.vcx`-uri sunt în `COMUN\` (framework - partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect). -- Cache-ul text e regenerabil, în afara arborelui SVN/git al proiectului — poate fi șters oricând. -- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat). -- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la - editarea `.sc2`/`.vc2` (nu doar la căutare). +``` +powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Project -ProjectRoot -CacheRoot +``` + +`-CacheRoot` trebuie sa stea **in afara** folderului `foxbin2prg`: `ReCreate_FoxBin2Prg.prg` face +`Prg2Bin` recursiv pe tot folderul uneltei si ar reconverti `.??2`-urile in binare parazitare. + +## Editare si write-back + +Vezi `flux-editare-vfp-text.md`. Regula de aur: `.frx`/`.mnx`/`.lbx`/`.pjx`/`.dbc`/`.dbf` sunt +read-only (editare doar in IDE-ul VFP); write-back suportat doar pentru `.vcx`/`.scx`. diff --git a/docs/conventie_encoding_cp1252.md b/docs/conventie_encoding_cp1252.md index e1a0b34..a9982d0 100644 --- a/docs/conventie_encoding_cp1252.md +++ b/docs/conventie_encoding_cp1252.md @@ -1,101 +1,57 @@ -# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` +# Capcana: corupere diacritice la editarea .sc2/.vc2 -Partajat între proiectele ROA* — capcana ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg, -nu de un proiect anume. +Comun tuturor proiectelor ROA* - tine de formatul .sc2/.vc2 (FoxBin2Prg), nu de un proiect anume. -## De ce se întâmplă +## Faptul -Fișierele `.sc2`/`.vc2` sunt **cp1250** (Windows-1250, Europa Centrală), nu UTF-8 — deși -antetul FoxBin2Prg declară `CPID="1252"`. Eticheta din antet nu corespunde conținutului: -controalele care poartă text cu diacritice au `FontCharSet = 238` (Europa de Est), adică VFP -le randează tot ca cp1250. Diferența nu e cosmetică — un `ă` real scris prin cp1252 nu are -echivalent în acel codepage și s-ar pierde; scris prin cp1250 (encoding-ul real al fișierului) -e pur și simplu octetul `0xE3`, corect și stabil. +Fisierele .sc2/.vc2 sunt cp1250 (Europa Centrala), nu UTF-8, desi antetul FoxBin2Prg declara +CPID="1252" - eticheta din antet nu e adevarul despre encoding. Controalele cu text diacritic +au FontCharSet = 238. -Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid -ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi **salvează tot ca UTF-8**, acel -U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1250 (cum face -FoxBin2Prg la write-back), apar ca `�`. Caracterul original e **ireversibil pierdut** -(recuperabil DOAR din altă sursă: git history, backup). +## Tabelul de octeti (cp1250 real -> aparenta daca decodezi gresit ca cp1252) -Octeții diacriticelor din codebase-ul ROA, cu adevărul (cp1250) și aparența dacă îi decodezi -greșit ca cp1252: - -| Literă românească | Byte | Aparență dacă decodezi ca cp1252 | +| Litera | Byte | Aparenta cp1252 gresita | |---|---|---| -| ă | `0xE3` | ã (a-tilde) | -| Ă | `0xC3` | à | -| î | `0xEE` | î (identic — zonă comună cp1250/cp1252) | -| Î | `0xCE` | Î (identic — zonă comună cp1250/cp1252) | -| â | `0xE2` | â (identic — zonă comună cp1250/cp1252) | -| ț | `0xFE` | þ (thorn minuscul) | -| Ș (majusculă) | `0xAA` | ª (ordinal masculin) | -| ș (minusculă) | `0xBA` | º (ordinal feminin) | +| a cu caciula minuscul | 0xE3 | a-tilde | +| A cu caciula majuscul | 0xC3 | A-tilde | +| i cu caciula minuscul | 0xEE | identic (zona comuna cp1250/cp1252) | +| I cu caciula majuscul | 0xCE | identic (zona comuna cp1250/cp1252) | +| a circumflex | 0xE2 | identic (zona comuna cp1250/cp1252) | +| t cu virgula minuscul | 0xFE | thorn minuscul | +| S cu virgula majuscul | 0xAA | ordinal masculin | +| s cu virgula minuscul | 0xBA | ordinal feminin | -Decodate cp1250 (encoding-ul real), aceste litere sunt diacritice românești normale — exact -ce apare în formular când fișierul e sănătos. Par "gunoi"/typo (`ã`, `þ`, `ª`, `º`) **doar -dacă le decodezi cu codepage-ul greșit** — nu le "corecta" fără să verifici encoding-ul real. +Nu "corecta" un s-cu-virgula crezand ca e typo - e litera corecta in cp1250. -## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt +## Regula operationala -Verificarea se face **pe octeți**, nu pe text decodat: un codepage single-byte (1250 sau 1252) -mapează fiecare octet la un caracter, deci nu produce niciodată U+FFFD — o căutare de -`[char]0xFFFD` în textul decodat nu găsește nimic nici pe un fișier stricat. Ce se caută e -secvența de trei octeți pe care a lăsat-o tool-ul care a stricat fișierul: +Orice scriere cu un tool care nu pastreaza octetii nativ (Edit/Write) corupe TOATE caracterele +>= 0x80 din TOT fisierul (0xBA -> EF BF BD), chiar la o singura linie schimbata, si se repeta +la FIECARE scriere. Nu re-encoda niciodata fisierul intreg: lucreaza pe octeti +([IO.File]::ReadAllBytes/WriteAllBytes cu GetEncoding(1250)) sau scrie strict ASCII in +continutul nou. Editeaza tot ce ai de editat, verifica, repara o singura data DUPA ultima +scriere. -```powershell -$b = [System.IO.File]::ReadAllBytes(".vc2") -$n = 0 -for ($i = 0; $i -lt $b.Length - 2; $i++) { - if ($b[$i] -eq 0xEF -and $b[$i+1] -eq 0xBF -and $b[$i+2] -eq 0xBD) { $n++; $i += 2 } -} -"EF BF BD (U+FFFD) x $n" # orice valoare > 0 = fisier stricat -``` - -Echivalentul din Bash, util și pentru censul complet înainte/după orice editare (vezi -`reguli_lucru.md`, punctul 7): +## Verificare (cens de octeti) ```bash -od -An -tx1 .vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c +od -An -tx1 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c ``` -Censul **crește** la stricare — un octet cp1250 devine trei octeți de U+FFFD — deci nu urmări -doar scăderile. Decodat cp1250, `EF BF BD` apare ca `ďż˝` în caption. +La stricare censul CRESTE (un octet devine trei) - nu urmari doar scaderile. Cauta explicit +secventa `EF BF BD`, nu tiparul generic `C3`/`C4`/`C5`/`C8` (acela apare si in UTF-8 legitim +din cod). -## Cum se repară +## Reparare -1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul curent. -2. Dacă corupera s-a întâmplat într-o sesiune anterioară necomisă (HEAD-ul git încă e curat): - recuperează originalul convertind binarul din HEAD în text: - ```bash - git show HEAD:.vcx > /tmp/head.vcx - git show HEAD:.vct > /tmp/head.vct # (sau .VCT, dupa caz) - powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out - ``` - Dacă și HEAD e deja corupt (corupera a fost comisă), caută ultima versiune curată cu - `git cat-file blob :` (din Bash, niciodată cu `>` din PowerShell 5.1 — adaugă - BOM și re-encodează) sau `svn cat ` — ambele surse independente de encoding-ul - curent al fișierului. - Apoi decodează ambele fișiere (versiunea curată + curent corupt) ca cp1250 și compară linie - cu linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1250 corect la afișare, deși - detectează totuși diferența de octeți). -3. Reconstruiește fișierul text pornind de la versiunea curată, reaplicând DOAR modificările - intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt caracter cu - caracter). -4. Scrie rezultatul înapoi ca bytes cp1250 - (`[System.Text.Encoding]::GetEncoding(1250).GetBytes(...)`), NU ca string UTF-8/`Out-File` - implicit. -5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe. +`EF BF BD` nu spune ce caracter s-a pierdut (toate diacriticele devin la fel) - inlocuirea +oarba cu 0xBA strica alte litere din alte pozitii. Ia octetul corect per pozitie din +`svn cat ` sau `git cat-file blob :`, din Bash, niciodata cu `>` din +PowerShell 5.1 (adauga BOM si re-encodeaza). Scrie inapoi ca bytes cp1250 explicit, apoi +`txt2vcx.ps1` + fidelity check. -## Cum se evită pe viitor +Cazul simplu (s-a pierdut doar 0xBA), inlocuire punctuala pe octet: -Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul -conține diacritice (`ă`, `ț`, `Ș`, `ș`, `î`, `â` etc.) — dacă da, **orice rescrie completă -trebuie făcută la nivel de octeți cu encoding cp1250 explicit**, nu presupunând UTF-8. -Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul păstrează restul -fișierului byte-identic (nu rescrie tot fișierul reîncodat). - -## Vezi și - -`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează riscul pe scurt; acest fișier -e detalierea completă (tabel de caractere, pași de recuperare din git). +```bash +perl -e 'binmode(STDIN);binmode(STDOUT);local $/;$_=;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp +``` diff --git a/docs/conventie_goexecutor_alter_table.md b/docs/conventie_goexecutor_alter_table.md index 3faf879..8be2b82 100644 --- a/docs/conventie_goexecutor_alter_table.md +++ b/docs/conventie_goexecutor_alter_table.md @@ -1,31 +1,24 @@ -# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()` +# Capcana: ALTER TABLE pe cursorul intors de goExecutor.oExecute() -Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în -`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru -interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*. +Comun tuturor proiectelor ROA*. -## Ce nu funcționează +## Ce nu functioneaza ```foxpro lnSucces = goExecutor.oExecute(lcSql, lcCursor) ... -ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică +ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pica ``` -Cursorul întors de `oExecute()` poate refuza comenzi DDL ulterioare, cu erori în lanț -(descoperite empiric, în această ordine): +Simptome intalnite, in aceasta ordine: `Function is not supported on remote tables.` (ALTER +TABLE direct pe cursorul original) / `Alias name is already in use.` (rematerializare cu +sursa si tinta acelasi nume) / `Invalid operation for the cursor.` (ALTER TABLE pe alias +scratch diferit ca tinta). -1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul original. -2. Chiar și după rematerializare (`SELECT * FROM (cursor) INTO CURSOR (acelasi_nume) READWRITE`) - → `Alias name is already in use.` (sursa și ținta nu pot avea același nume). -3. Cu alias scratch diferit ca țintă → tot `Invalid operation for the cursor.` pe `ALTER TABLE`, - chiar dacă țintă ar trebui să fie deja un cursor local obișnuit. +## Ce functioneaza -## Ce funcționează - -**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele -suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*` -(VFP suportă `SELECT *, expr AS coloana FROM ...`): +Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`. Include coloanele suplimentare +direct in `SELECT`-ul de rematerializare, ca expresii literale alaturi de `*`: ```foxpro lcCursorRaw = lcCursor + '_raw' @@ -45,11 +38,6 @@ USE IN (lcCursorRaw) * de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor) ``` -După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează -normal pe el DUPĂ ACEEA (ex. într-o altă funcție care primește cursorul deja gata construit), -doar comanda imediat următoare unui `oExecute()` e restricționată. - -## Vezi și - -Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`, -`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`. +Dupa acest pas cursorul (`lcCursor`) e un cursor local obisnuit - `ALTER TABLE` functioneaza +normal pe el DUPA ACEEA (ex. intr-o alta functie care primeste cursorul deja gata construit), +doar comanda imediat urmatoare unui `oExecute()` e restrictionata. diff --git a/docs/conventie_mediu_oracle.md b/docs/conventie_mediu_oracle.md index c763a91..61fba5b 100644 --- a/docs/conventie_mediu_oracle.md +++ b/docs/conventie_mediu_oracle.md @@ -48,11 +48,18 @@ select text from all_source ## 4. Conectare +Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` deja setat spre acelasi folder). +Alias TNS: `ROA_CENTRAL` -> `10.0.20.121:1521`, `SERVICE_NAME=ROA` (`tnsnames.ora` din acelasi +folder). + ``` & 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/ROMFASTSOFT@ROA_CENTRAL' '@fisier.sql' ``` -Fisierul `.sql` se scrie in **ASCII**. SQL trimis prin pipe din PowerShell e spart de BOM. +Fisierul `.sql` se scrie in **ASCII**. SQL trimis prin pipe din PowerShell e spart de BOM +(`SP2-0734: unknown command beginning "...select..."` - BOM UTF-16 sparge parserul). + +Parola nu e versionata in git - in `COMUN\docs\local\oracle.md` (ignorat de git, exista in SVN). ## 5. Ce inseamna "se ruleaza un script de pachet" diff --git a/docs/conventie_ux_formulare.md b/docs/conventie_ux_formulare.md index 6e4b370..56b191e 100644 --- a/docs/conventie_ux_formulare.md +++ b/docs/conventie_ux_formulare.md @@ -1,53 +1,36 @@ -# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*) +# Conventie UX pentru formulare VFP -Partajat între proiectele ROA* — `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul -corect pentru o convenție de design care nu ține de un singur proiect. +Comun tuturor proiectelor ROA*. -## Ce înseamnă in practică, pe proprietăți VFP +## Layout -- **Fiecare grup funcțional pe rândul lui**, nu înghesuit pe același `Top` cu altul fără - legătură (ex: perioadă / statistici / configurare, pe rânduri separate). -- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din aceeași - acțiune la 6-10px unele de altele; gap de 20-30px față de următorul grup funcțional. -- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**, nu - lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting ca acțiune - separată de câmpul de input. -- **Acțiunea principală + oprirea ei alăturate** (ex. Transmite + Renunță), nu împrăștiate în - altă parte a rândului. -- **Un singur rând de acțiuni cât se poate** — un rând orizontal in loc de rânduri noi - dedesubt; formele rămân compacte pe verticală. -- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE". ALL - CAPS/text lung pe un buton citește ca zgomot, nu ca ierarhie. -- **Culoare = semnal, nu decor** — doar pentru acțiuni cu semnificație clară (verde = - pozitiv/transmite, roșu = oprire/pericol, albastru = navigare/link extern); restul butoanelor - rămân stilul implicit din `_baza.vcx`. +- Fiecare grup functional pe randul lui, nu inghesuit pe acelasi Top cu altul fara legatura + (ex: perioada / statistici / configurare, pe randuri separate). +- Spatiere vizibila intre grupuri, stransa in interiorul unui grup: butoane din aceeasi actiune + la 6-10px unele de altele; gap de 20-30px fata de urmatorul grup functional. +- Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului, nu + lipite imediat dupa textbox-ul pe care il controleaza - altfel nu se disting ca actiune + separata de campul de input. +- Actiunea principala + oprirea ei alaturate (ex. Transmite + Renunta), nu imprastiate in alta + parte a randului. +- Un singur rand de actiuni cat se poate - un rand orizontal in loc de randuri noi dedesubt; + formele raman compacte pe verticala. +- Caption-uri scurte, sentence case, nu ALL CAPS - ex. "Transmite" nu "TRANSMITE". +- Culoare = semnal, nu decor - doar pentru actiuni cu semnificatie clara (verde = + pozitiv/transmite, rosu = oprire/pericol, albastru = navigare/link extern); restul + butoanelor raman stilul implicit din `_baza.vcx`. ## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT) -- **Intotdeauna controale din `_baza.vcx`, nu controale native VFP** — orice grid, label, +- Intotdeauna controale din `_baza.vcx`, nu controale native VFP - orice grid, label, textbox, checkbox etc. dintr-un formular nou se bazeaza pe clasa corespunzatoare din - `COMUN\clase\_baza.vcx`, nu pe clasa nativa Visual FoxPro. Clasele din `_baza.vcx` au - fontul default **Arial 10** — nu se suprascrie FontName pe controale (explicit: fara - Arial Narrow). -- **Butoanele de inchidere/confirmare stau in bara de titlu**, din `cmd_butoane.vcx` — - modelul Renunt/Termin (clasa de forma `frm_termin_renunt` din `_frm_child.vcx` le aduce - deja). Nu se dubleaza aceste actiuni cu butoane in corpul formei. -- **Actiunile care au corespondent `but_*` in `cmd_butoane.vcx`** (Nou/Adauga, Modifica, - Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*` - respectiva — nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei. -- **Doar actiunile FARA corespondent `but_*`** primesc butoane pe clasele `cmd_*` din - `cmd_butoane.vcx` (ex. `cmd_executa`) — nu clase improvizate si nu CommandButton nativ. - -## Vocabular - -Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, modern — -asta e reperul calitativ pentru orice formular nou sau refacere de layout, pe orice -aplicație ROA*. - -## Vezi și - -- `PROMPT_cautare_vfp.md` din acest folder — cum se caută/editează cod în binarele VFP text-cache - (relevant când aplici aceste reguli prin fluxul `.sc2`/`.vc2` + write-back). -- `conventie_encoding_cp1252.md` din acest folder — capcana de corupere a diacriticelor la - editarea `.sc2`/`.vc2`; relevantă ori de câte ori editezi text-cache-ul unui formular/librărie - pentru a aplica aceste reguli de UX. + `COMUN\clase\_baza.vcx`. Fontul default e Arial 10 - nu se suprascrie FontName pe controale + (explicit: fara Arial Narrow). +- Butoanele de inchidere/confirmare stau in bara de titlu, din `cmd_butoane.vcx` - modelul + Renunt/Termin (clasa `frm_termin_renunt` din `_frm_child.vcx` le aduce deja). Nu se + dubleaza aceste actiuni cu butoane in corpul formei. +- Actiunile care au corespondent `but_*` in `cmd_butoane.vcx` (Nou/Adauga, Modifica, + Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*` respectiva - + nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei. +- Doar actiunile FARA corespondent `but_*` primesc butoane pe clasele `cmd_*` din + `cmd_butoane.vcx` (ex. `cmd_executa`) - nu clase improvizate si nu CommandButton nativ. diff --git a/docs/depanare-pack-update.md b/docs/depanare-pack-update.md index e5c0849..3af7afd 100644 --- a/docs/depanare-pack-update.md +++ b/docs/depanare-pack-update.md @@ -62,30 +62,17 @@ Fisierul se poate citi si fara acces la desktopul serverului, prin `UTL_FILE` pe `DMPDIR` (`fopen(...,'R',32767)` + `get_line` in bucla; tine ultimele N linii intr-un tablou — partea utila e la sfarsit). -### Caz: nu orice esec de script e o problema de SQL (SIGMA, 03.08.2026) +### Un esec de script raportat nu inseamna neaparat o problema de SQL in script -`ff_2026_07_29_02_COMUN_TVA11.SQL` a picat pe `MARCU` cu `ORA-01653: unable to extend table -SYS.INFO ... in tablespace SYSTEM` (din `SYS.PINFO`/`SYS.AUTH_PACK`, recursiv). Tablespace-ul -`SYSTEM` era plin: autoextensibil, dar cu `maxbytes` atins la 600 MB, ~2 MB liberi. **Orice** -script ar fi picat identic — `AUTH_PACK` scrie in `SYS.INFO` la fiecare conectare. Cand eroarea nu -priveste obiectele scriptului, verifica intai spatiul. - -Ce a contat, pentru data viitoare: - -- **`maxbytes` mic nu e o limita XE.** Cele 11 GB ale XE sunt pe *date utilizator*; un plafon mic pe - `SYSTEM.DBF` e o setare de instalare. Se ridica din `contafin_oracle` (are `ALTER DATABASE`): - `alter database datafile '\SYSTEM.DBF' autoextend on next 50M maxsize 2000M;` -- **Spatiul pe discul serverului se verifica fara RDP**, cu `sys.ExecuteScriptOS` (vezi mai jos) — - `Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3"`, iesire in `DMPDIR`, citita cu `UTL_FILE`. - Job asincron, dar raspunde in cateva secunde. -- **`SYS.INFO` e tabel ROA, nu obiect de dictionar** (log de login scris de `PINFO`, ~7 randuri per - conectare, +16-17k randuri/luna, nimic din baza nu-l citeste). Se poate goli, **dar numai ca - `SYSDBA`**: privilegiile `ANY` (`DROP ANY TABLE`, `DELETE ANY TABLE`) nu se aplica pe obiectele - din schema `SYS` cat timp `O7_DICTIONARY_ACCESSIBILITY=FALSE`, deci din `contafin_oracle` iese - `ORA-01031`. -- Restul lui `SYSTEM` era dictionar Oracle (`IDL_UB1$`, `SOURCE$`, `IDL_UB2$`, `ARGUMENT$` ~207 MB) — - de neatins fara export/import. `AUD$`/`FGA_LOG$` erau goale. Recyclebin-ul si bloat-ul de scheduler - stateau in `ROA`/`SYSAUX`, nu in `SYSTEM`. +Eroarea Oracle poate veni din obiecte cu totul straine de ce modifica scriptul (ex. +`ORA-01653: unable to extend table SYS.INFO ... in tablespace SYSTEM`, ridicata din +`SYS.PINFO`/`AUTH_PACK` la conectare, nu din scriptul insusi) - orice script ar fi picat identic. +Cand mesajul de eroare nu priveste obiectele pe care scriptul chiar le atinge, verifica intai +spatiul (`maxbytes` pe tablespace-ul din mesaj nu e o limita XE - cele 11 GB XE sunt pe date +utilizator, plafonul mic e o setare de instalare, se ridica din `contafin_oracle` cu +`alter database datafile '\.DBF' autoextend on next 50M maxsize 2000M;`). Spatiul pe +discul serverului se verifica fara RDP cu `sys.ExecuteScriptOS` (vezi mai jos, sectiunea "Comenzi +OS pe serverul de baze de date"). ## Descarcarea (UpdateApp) diff --git a/docs/depanare_testare_vfp.md b/docs/depanare_testare_vfp.md index 7d9cfc5..6736083 100644 --- a/docs/depanare_testare_vfp.md +++ b/docs/depanare_testare_vfp.md @@ -28,18 +28,14 @@ $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() } - `-A` ignora config.fpw implicit, `-T` sare peste splash; **ambele obligatorii** - fara `-T` procesul ramane pe ecranul de intampinare (simptom identic cu o eroare de compilare). `-c` explicit (lipit de flag) e preluat si cu `-A`. -- **SAFETY**: sub `-A` porneste ON - primul `STRTOFILE` peste un log existent (sau `COMPILE` peste - un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul pare agatat. Pune - `SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF`+`RESOURCE=OFF` intr-un config.fpw - propriu pasat cu `-c`. Verificare: logheaza `SET("SAFETY")`/`SET("RESOURCE")` la start. +- **SAFETY**: sub `-A` porneste ON - vezi sectiunea 7 pentru capcana completa si remediu. - In script: logare cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola); `ON ERROR DO WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza si continua (mimeaza ErrorHandler); `QUIT` obligatoriu la final. - `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata + linia `PROCEDURE`. -- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi dupa - editarea scriptului - altfel VFP ruleaza codul vechi din `.fxp` fara niciun semn (testul poate - trece fals; se prinde doar cand lipseste din log o linie scrisa doar de codul nou). +- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare). Sterge `.fxp`-ul vechi dupa + editarea scriptului - vezi sectiunea 7 pentru simptomul complet de `.FXP`/`.ERR` stale. - Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau seteaza `WindowType = 0`. @@ -134,9 +130,12 @@ Cand un bug apare "de azi", compara cu clasa veche fara sa atingi SVN: ## 7. Capcane la SCRIEREA scriptului de test -- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`** (plus - `SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascriere, iar headless - dialogul blocheaza procesul pana la timeout. Suitele existente il au deja - capcana apare la +- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`/`COMPILE`** + (plus `SET TALK OFF`). Sub `-A` SAFETY porneste ON: primul `STRTOFILE` peste un log existent, sau + `COMPILE` peste un `.err`/`.fxp` existent, scoate dialogul modal "overwrite?" care blocheaza + procesul pana la timeout (proces viu, pare agatat). Alternativa/completare: `SAFETY=OFF`+ + `RESOURCE=OFF` intr-un config.fpw propriu pasat cu `-c`. Verificare: logheaza + `SET("SAFETY")`/`SET("RESOURCE")` la start. Suitele existente il au deja - capcana apare la scripturile ad-hoc, scrise repede pentru o masuratoare. - **`DEFINE CLASS ... ENDDEFINE` nu poate sta la mijlocul programului principal.** Toate liniile de DUPA `ENDDEFINE` dau "Statement is not in a procedure" (vezi `