sync SVN r18041
This commit is contained in:
58
docs/README.md
Normal file
58
docs/README.md
Normal file
@@ -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.
|
||||
@@ -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 '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>'
|
||||
|
||||
# include și rapoartele (.frx) și meniurile (.mnx)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -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 '<RADACINA_PROIECT>\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 '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -Clean
|
||||
```
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot <root>
|
||||
```
|
||||
|
||||
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\<nume_proiect>"
|
||||
grep -rln "factura_salvare" "D:\ROA\_vfp_textcache\<nume_proiect>" # 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\<nume_proiect>', '-ProjectRoot', '<RADACINA_PROIECT>')
|
||||
$c = @('-CacheRoot', '<root>', '-ProjectRoot', '<root>')
|
||||
|
||||
# căutare etichetată cu clasa.metoda; -CodeOnly taie potrivirile din metadata/proprietăți
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine deține linia
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>' # moștenire + metode
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly # etichetat clasa.metoda, doar cod
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine detine linia
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>' # 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\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\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\<proiect>\Clase\odevize.VCT"
|
||||
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\<proiect>\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 <pjx> -ProjectRoot <root> -CacheRoot <cache>
|
||||
```
|
||||
|
||||
`-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`.
|
||||
|
||||
@@ -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("<path>.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 <path>.vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
|
||||
od -An -tx1 <fisier> | 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:<cale>.vcx > /tmp/head.vcx
|
||||
git show HEAD:<cale>.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 <commit>:<cale>` (din Bash, niciodată cu `>` din PowerShell 5.1 — adaugă
|
||||
BOM și re-encodează) sau `svn cat <fișier>` — 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 <fisier>` sau `git cat-file blob <commit>:<cale>`, 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 $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 '<cale>\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 '<cale>\<TS>.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)
|
||||
|
||||
|
||||
@@ -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<cale>`
|
||||
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 <handler> 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 `<script>.ERR`); scriptul se
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Flux editare .vcx/.scx pe text (comun proiectelor VFP)
|
||||
|
||||
Textul .vc2/.sc2 e sursa de editare; write-back in binar cu `txt2vcx.ps1`, fara VFP IDE.
|
||||
Detalii complete: `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`. Parametrii per proiect: sectiunea de mai jos.
|
||||
Detalii complete: `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`. Parametrii per proiect (nemigrate):
|
||||
`cautare_vcx_vct.md`.
|
||||
|
||||
**Proiecte migrate (ROACONT, COMUN, …): flux in-arbore.** Textul .??2 sta langa binare, il
|
||||
improspateaza `git_sync.ps1 -ProjectRoot <root>` (nu cache extern) — la inceput de sesiune si
|
||||
@@ -20,18 +21,57 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
||||
'utile\foxcharts\foxcharts.vcx','utile\web\_webview.vcx')` - si apeleaza scriptul cu `&`, nu cu
|
||||
`powershell -File` (acolo lista nu se leaga ca array).
|
||||
|
||||
## Parametri per proiect (nemigrate, cache extern)
|
||||
## Invariante — se verifica la FIECARE editare, inainte de write-back
|
||||
|
||||
- **ROAGEST**: `-Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST'
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\roagest'`; patch-uri de review in
|
||||
`docs/diff_runda<N>_<subiect>.patch`.
|
||||
1. **Membru nou de clasa (proprietate SAU metoda) are intrare in `*<DefinedPropArrayMethod>`**:
|
||||
`*p: nume` / `*m: nume`. Sectiunea "Membri noi de clasa" mai jos.
|
||||
2. **Ordinea alfabetica FoxBin2Prg**: `_` vine DUPA litere, nu inainte (ASCII). Ordinea canonica se
|
||||
citeste din `<staging>\verify\*.vc2`, nu se deduce.
|
||||
3. **CRLF, zero LF izolati**:
|
||||
`perl -e 'local $/; open F,"<:raw",$ARGV[0]; $d=<F>; $crlf=()=$d=~/\r\n/g; $lf=()=$d=~/\n/g; print $lf-$crlf' <fisier>`
|
||||
trebuie sa dea 0.
|
||||
4. **Cens de octeti >= 0x80 identic** cu cel de dinainte de editare:
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`
|
||||
(detalii: `conventie_encoding_cp1252.md`).
|
||||
|
||||
**Nici fidelity-check-ul, nici `-DryRun` nu acopera punctele 1, 3 si 4** — trec cu OK peste toate
|
||||
trei. Sunt verificari separate, de facut de mana.
|
||||
|
||||
## Membri noi de clasa: `*p:` / `*m:`
|
||||
|
||||
Orice proprietate sau metoda NOUA cere, pe langa valoarea din `*<PropValue>` / corpul `PROCEDURE`,
|
||||
o intrare in blocul `*<DefinedPropArrayMethod>` al clasei: `*p: nume` pentru proprietate, `*m: nume`
|
||||
pentru metoda. Override-urile de metode mostenite (Init, Show, hook-uri) NU au nevoie de `*m:`.
|
||||
|
||||
Fara acea intrare, esecul e tacut in patru pasi:
|
||||
|
||||
1. textul se scrie si `txt2vcx.ps1` **trece fidelity-check-ul** — fidelity compara text-sursa cu
|
||||
text-regenerat, deci nu are cum sa observe lipsa; binarul primeste valoarea/corpul ca text;
|
||||
2. VFP nu materializeaza membrul pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.`, iar accesul cade cu
|
||||
eroarea 1734 "Property ... is not found" (proprietate) sau "Data type mismatch" la
|
||||
`Createobject` (metoda). Dovedit in ambele sensuri pe o clasa de proba izolata;
|
||||
3. **prima salvare din IDE-ul VFP peste acel binar sterge tacit membrul** — la metode raman doar
|
||||
corpurile `PROCEDURE` orfane, la proprietati dispare si valoarea;
|
||||
4. urmatorul `git_sync` regenereaza textul din binarul deja ciuntit, deci pierderea intra si in
|
||||
`.??2`, si in backup-urile de runda.
|
||||
|
||||
Pasul 3 loveste si definitii `*m:` **deja existente si corecte** (patit pe ROAGEST:
|
||||
`import_adauga_factura.recalc_tva`, `import_nota.do_adauga/do_copie/do_reface`; simptom: crash la
|
||||
`Createobject` cu "Data type mismatch" raportat la linia apelanta). Deci dupa ORICE sesiune IDE pe
|
||||
o clasa atinsa: `git_sync` + compara lista `*p:`/`*m:` cu starea de dinainte.
|
||||
|
||||
Verificare inainte de write-back: `grep -n '\*[pm]: <nume>' <fisier>.vc2`.
|
||||
Pozitia in fisier nu e libera — FoxBin2Prg regenereaza membrul la pozitia lui alfabetica din
|
||||
`*<DefinedPropArrayMethod>` (cu `_` dupa litere); o intrare sau o metoda scrisa in alta parte pica
|
||||
fidelity-check-ul. Sursa de adevar pentru ordine si pozitie: textul din `<staging>\verify\*.vc2`.
|
||||
|
||||
## Pasii unei runde
|
||||
|
||||
0. Refresh cache (obligatoriu dupa orice sesiune IDE — staleness pe mtime):
|
||||
`vcx2txt.ps1 -Project <pjx> -ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`
|
||||
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (in cache; la runde succesive
|
||||
necomise, diff-ul fata de HEAD ar amesteca rundele).
|
||||
0. Refresh text (obligatoriu la inceput de sesiune si dupa orice sesiune IDE — staleness pe
|
||||
mtime): `git_sync.ps1 -ProjectRoot <root>` (proiecte nemigrate: `vcx2txt.ps1 -Project <pjx>
|
||||
-ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`).
|
||||
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (langa binar, in arbore; la runde
|
||||
succesive necomise, diff-ul fata de HEAD ar amesteca rundele).
|
||||
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))` -
|
||||
doar pentru round-trip pe octeti, NU pentru retastat literal diacritice (antetul zice
|
||||
`CPID="1252"`, dar octetii diacriticelor sunt de fapt cp1250: `conventie_encoding_cp1252.md`).
|
||||
@@ -56,7 +96,8 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
||||
(`Test-ExclusiveAccess` pe `.vcx`+`.vct`) si refuza cu mesaj clar daca e lock. NU conteaza
|
||||
existenta altor instante `vfp9` — utilizatorul poate lucra in paralel in alt proiect VFP —
|
||||
si NU se omoara procese: cand lock-ul exista, se cere utilizatorului sa inchida sesiunea.
|
||||
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>`
|
||||
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root>` (`-CacheRoot` implicit =
|
||||
`-ProjectRoot`; pentru proiecte nemigrate cu cache separat, paseaza-l explicit)
|
||||
(+ `-AllowComun` pentru tinte COMUN — afecteaza toate aplicatiile ROA, deci schimbarea in sine
|
||||
se propune explicit, dar write-back-ul local nu asteapta aprobarea; nimic nu pleaca la celelalte
|
||||
aplicatii pana la commit+push).
|
||||
@@ -75,29 +116,6 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
||||
- `.mnx`/`.frx` raman read-only (GENMENU in IDE / round-trip fragil).
|
||||
- Linii complet goale in metode pica fidelity doar pe whitespace; fix: preia `verify\*.vc2`
|
||||
din staging peste cache si reia write-back-ul.
|
||||
- Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare
|
||||
din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri).
|
||||
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
|
||||
- **Proprietate noua de clasa cere identic `*p: nume` in `*<DefinedPropArrayMethod>`** — nu doar
|
||||
valoarea in `*<PropValue>`. Fara `*p:`, valoarea se scrie in text, **trece fidelity-check-ul**
|
||||
(fidelity compara doar text-sursa cu text-regenerat) si ajunge in binar ca text, dar VFP nu o
|
||||
materializeaza pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.` si orice acces cade cu eroarea 1734
|
||||
"Property ... is not found". Dovedit in ambele sensuri pe o clasa de proba izolata (cu `*p:` ->
|
||||
`.T.`, fara -> `.F.`).
|
||||
- **FoxBin2Prg sorteaza alfabetic cu `_` DUPA literele obisnuite**, nu in ordine ASCII brut (unde
|
||||
`'_' (0x5F) < 'v' (0x76)` pe litere mici). O intrare `*p:`/`*m:` scrisa de mana in ordine "ASCII
|
||||
corecta" pica fidelity-check-ul; ordinea canonica se citeste din textul regenerat in
|
||||
`<staging>\verify\*.vc2` (vezi punctul de mai jos despre pozitia metodelor noi — se aplica identic
|
||||
proprietatilor).
|
||||
- FoxBin2Prg NU pastreaza pozitia in text a unei metode noi: o regenereaza la pozitia
|
||||
alfabetica din `*<DefinedPropArrayMethod>`. O metoda scrisa in alta parte a fisierului
|
||||
face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din
|
||||
`<staging>\verify\` - muta metoda unde apare acolo si reia write-back-ul.
|
||||
- Salvarea din VFP IDE peste un binar scris de txt2vcx poate PIERDE si definitii `*m:` deja
|
||||
existente, desi corpurile PROCEDURE raman (patit pe ROAGEST: `import_adauga_factura.recalc_tva`,
|
||||
`import_nota.do_adauga/do_copie/do_reface`); simptom: crash la Createobject cu
|
||||
"Data type mismatch" raportat la linia apelanta. Dupa orice sesiune IDE pe clasa: refresh
|
||||
cache + compara lista `*m:` cu starea de dinainte.
|
||||
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
|
||||
`.vcx`/`.vct` din proiect si le rescrie antetul (timestamp compilare) si posibil p-code-ul
|
||||
intern si la librarii neatinse efectiv, aparand fals ca "modificate" in diff — de aici
|
||||
|
||||
@@ -163,3 +163,21 @@ noua are pretul de achizitie 0, respectiv daca toate liniile facturii au fost st
|
||||
sus.
|
||||
- Documentele care nu sunt facturi de vanzare nu sunt atinse de aceasta ramura - pagina de articole
|
||||
nu apare si scrierea in `VANZARI_DETALII` nu se declanseaza (garda: `Reccount('tvanz') = 1`).
|
||||
|
||||
## Ce e strict necesar de stiut despre PACK_CONTAFIN
|
||||
|
||||
Pachetul central de **scriere a documentelor** - clientul VFP populeaza tabelele temporare
|
||||
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
|
||||
|
||||
- `SCRIE_IN_FISIERE` - orchestratorul (apelat per document).
|
||||
- `SCRIE_IN_ACT` - `ACT_TEMP` -> `ACT` (notele contabile).
|
||||
- `SCRIE_IN_RUL` - `RUL_TEMP` -> `RUL` (miscarile de stoc); completeaza `COD`, `DATAORA`, `ID_FACT`
|
||||
(min. `id_fact` fara conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, optional
|
||||
`ID_RUL_AUX` pe furnizor (optiunea de firma `RULAJFURNIZOR`). **Scrie exact ce e in RUL_TEMP - nu
|
||||
deriva rulaje din ACT**, deci filtrarea liniilor de rulaj se face in clientul VFP.
|
||||
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` - variantele pentru obiecte de
|
||||
inventar si actualizarea stocului.
|
||||
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
|
||||
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
|
||||
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, ...)
|
||||
+ `PACK_SESIUNE` (an/luna, optiuni firma).
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
# Inventar COMUN - functii/clase reutilizabile (ROAGEST)
|
||||
|
||||
Scop: reutilizare comune la plan/code-review (ex. cursor2lista() in loc de Scan manual pe cursor).
|
||||
Consulta acest fisier la plan (inainte de cod/obiecte noi) si la code-review (Scan manual pt.
|
||||
liste, MESSAGEBOX direct, SQLEXEC direct, buton cu Click suprascris in loc de `caction`, export/
|
||||
listare construite manual in loc de `goExport.export2*`/FoxyPreview, dialog de alegere nomenclator
|
||||
din SELECT+grid in loc de `caut_*`).
|
||||
|
||||
Generat prin grep pe COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest. Numerele =
|
||||
nr. aparitii grep in proiect (indiciu cat de "canonic" e functia).
|
||||
nr. aparitii grep **in ROAGEST** (indiciu cat de "canonic" e functia) - dar `COMUN\` e partajat de
|
||||
8 produse ROA si lista de functii/clase de mai jos e valabila pentru toate; doar cifrele de uz sunt
|
||||
masurate pe ROAGEST.
|
||||
|
||||
## 1. Functii comune - COMUN\programe\oproceduri_comune.prg (clasa Oracle/executor + utilitare)
|
||||
|
||||
@@ -285,30 +292,7 @@ Proprietate cheie comuna: `pcobj` (leaga containerul de camp/proprietate din obi
|
||||
- Fisiere `.vc2`/`.sc2`: TAB-uri semnificative, proprietatile in blocul `*<PropValue>` sunt
|
||||
alfabetizate - orice editare manuala trebuie sa respecte formatul (vezi CLAUDE.md, flux editare text).
|
||||
|
||||
## 7. Ce am lasat pe dinafara (intentionat)
|
||||
|
||||
- `proceduri_comune.prg` (varianta veche) - acoperita in nota sect. 1 (2 functii unice folosite,
|
||||
restul dublate/moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
|
||||
make_sectii_utilizator, recompune_optiuni, cere*/compara*, debug_*_eventtracking, ...) - omise.
|
||||
- `oproceduri_comune_imob.prg` - varianta specifica ROAIMOB, nu ROAGEST.
|
||||
- `xdate.prg` - script procedural (incarca cursoarele xsets/xrequest/xnote la DO), nu expune functii.
|
||||
- Metoda `getUserRepPath` din oExportConfig - complet comentata (moarta); varianta activa e functia
|
||||
libera omonima din `proceduri_rapoarte.prg` (cod diferit).
|
||||
- Clase de nomenclatoare mari (`onomenclatoare.vcx`, `onom_articole.vcx`, `stocuri.vcx`, `rulaje.vcx`,
|
||||
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic gestiune, prea voluminos pt. acest inventar
|
||||
(candidat pt. inventar separat per-flux, daca devine necesar).
|
||||
- Clasele de configurare/serii (`configurare.vcx`, `serii_numere.vcx`, `ferestre_oracle.vcx`,
|
||||
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz rar in
|
||||
fluxurile curente (`excelxml.vcx` e acoperita la sect. 3).
|
||||
- Functiile din `COMUN\programe` fara nicio aparitie prin grep in ROAGEST (posibil doar alte
|
||||
aplicatii ROA) - omise.
|
||||
|
||||
## 8. Cum se foloseste
|
||||
|
||||
- **La plan**: inainte de cod/obiecte noi, scaneaza acest fisier + un grep tintit
|
||||
(`grep -rn "<nume_functie_candidata>" COMUN/programe D:\ROA\_vfp_textcache\roagest`) ca sa
|
||||
confirmi ca nu exista deja o comuna echivalenta.
|
||||
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC
|
||||
direct, un buton cu Click suprascris in loc de `caction`, export Excel/listare construite manual
|
||||
in loc de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator din SELECT+grid
|
||||
in loc de `caut_*` (ocautare.prg), semnaleaza comuna corespunzatoare din tabelele de mai sus.
|
||||
La un grep tintit fara rezultat aici (`grep -rn "<nume_functie_candidata>" COMUN/programe
|
||||
D:\ROA\_vfp_textcache\roagest`), functia poate exista tot in `COMUN\` dar sub alt nume istoric
|
||||
(vezi duplicatele din nota sect. 1) sau in clasele mari de business (nomenclatoare, stocuri,
|
||||
rulaje, introduceri, inventar) - neinventariate aici, prea voluminoase.
|
||||
|
||||
@@ -77,8 +77,9 @@ ALTE OPȚIUNI: -Force (reconvertește tot), -Clean (șterge cache-ul întâi).
|
||||
|
||||
PAS 3 — modificare de cod în .vcx/.scx (flux write-back pe text). Ordinea e obligatorie:
|
||||
|
||||
a. Investighează pe cache, propune modificarea și AȘTEAPTĂ ACORDUL pe abordare înainte să
|
||||
editezi ceva.
|
||||
a. Investighează pe cache. Ordinea write-back/aprobare/commit urmează `reguli_lucru.md`
|
||||
(write-back-ul și testele se fac imediat, fără să aștepți răspunsul; aprobarea
|
||||
condiționează COMMIT-ul, nu write-back-ul).
|
||||
b. Refresh cache (PAS 1) dacă a rulat vreo sesiune de IDE de la ultimul refresh (staleness-ul
|
||||
se verifică pe mtime și txt2vcx refuză corect scrierea peste modificări nevăzute). Înainte
|
||||
de write-back închide COMPLET VFP IDE și exe-ul aplicației — procesele reziduale țin lock
|
||||
@@ -1,43 +1,34 @@
|
||||
# Export surse Oracle (PACK_CONTAFIN & co.) — cum se face
|
||||
# Export surse Oracle (PACK_CONTAFIN & co.) - cum se face
|
||||
|
||||
`PACK_CONTAFIN.pck` din acest folder este exportul sursei pachetului PL/SQL `PACK_CONTAFIN`.
|
||||
Claude Code își face singur exportul/reîmprospătarea — nu mai e nevoie de export manual din
|
||||
Claude Code isi face singur exportul/reimprospatarea - nu mai e nevoie de export manual din
|
||||
PL/SQL Developer.
|
||||
|
||||
## Conexiune
|
||||
|
||||
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` deja setat spre același folder).
|
||||
- Alias TNS: `ROA_CENTRAL` → `10.0.20.121:1521`, `SERVICE_NAME=ROA` (vezi `tnsnames.ora`).
|
||||
- Schema/utilizator: `MARIUSM_AUTO` (schema de dezvoltare a lui Marius).
|
||||
- **Schema de lucru pentru verificari: `MARIUSM_AUTO` pe `ROA_CENTRAL`** - nu `ACN` sau altele.
|
||||
- **Parola nu e versionată în git** — în `COMUN\docs\local\oracle.md` (ignorat de git, există în SVN).
|
||||
Conectare, alias TNS, schema (`MARIUSM_AUTO` pe `ROA_CENTRAL`) si capcana BOM la SQL prin pipe:
|
||||
vezi `conventie_mediu_oracle.md` sectiunea 4. Aici doar ce e specific exportului:
|
||||
|
||||
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus sinonim `PUBLIC`.
|
||||
Exportul de referință se face din `MARIUSM_AUTO`.
|
||||
`PACK_CONTAFIN` exista in schemele `MARIUSM_AUTO` (dev) si `ACN`, plus sinonim `PUBLIC`. Exportul
|
||||
de referinta se face din `MARIUSM_AUTO`.
|
||||
|
||||
Înainte de a lua o sursă de acolo ca referință pentru o modificare, verifică că `MARIUSM_AUTO` are
|
||||
toate scripturile aplicate — procedura e în `scripturi-migrare-db.md`, secțiunea
|
||||
"Sursa de referință pentru DDL".
|
||||
|
||||
## Gotcha sqlplus pe Windows/PowerShell
|
||||
|
||||
Nu trimite SQL prin pipe din PowerShell (`'select...' | sqlplus`) — BOM-ul UTF-16 sparge parserul
|
||||
(`SP2-0734: unknown command beginning "select..."`). Scrie un fișier `.sql` cu encoding **ASCII**
|
||||
și rulează-l cu `@fisier.sql`.
|
||||
Inainte de a lua o sursa de acolo ca referinta pentru o modificare, verifica ca `MARIUSM_AUTO` are
|
||||
toate scripturile aplicate - procedura si regula "sursa de referinta pentru DDL e MARIUSM_AUTO, nu
|
||||
productia" sunt in `scripturi-migrare-db.md`, sectiunea "Sursa de referinta pentru DDL".
|
||||
|
||||
## Comanda de export (re-generare .pck)
|
||||
|
||||
> **`linesize` prea mic corupe tăcut sursa.** SQL\*Plus face **wrap** la coloana `linesize`, deci o
|
||||
> linie de cod mai lungă e ruptă în două — inclusiv **prin mijlocul unui identificator**. Fișierul
|
||||
> pare întreg, `diff` față de el nu arată nimic, dar recompilarea lui dă erori la linii care n-au
|
||||
> nicio legătură cu ce ai modificat (`ORA-00920`, `PLS-*`). `PACK_FACTURARE` are linii de peste
|
||||
> **1000** de caractere, iar un export la `linesize 400` i-a rupt 8. Folosește `linesize 32767` și
|
||||
> verifică după export că nicio linie nu atinge exact valoarea `linesize`.
|
||||
> **`linesize` prea mic corupe tacut sursa.** SQL*Plus face **wrap** la coloana `linesize`, deci o
|
||||
> linie de cod mai lunga e rupta in doua - inclusiv **prin mijlocul unui identificator**. Fisierul
|
||||
> pare intreg, `diff` fata de el nu arata nimic, dar recompilarea lui da erori la linii care n-au
|
||||
> nicio legatura cu ce ai modificat (`ORA-00920`, `PLS-*`). `PACK_FACTURARE` are linii de peste
|
||||
> **1000** de caractere, iar un export la `linesize 400` i-a rupt 8. Foloseste `linesize 32767` si
|
||||
> verifica dupa export ca nicio linie nu atinge exact valoarea `linesize`.
|
||||
>
|
||||
> **Exportul e bun pentru CITIT, nu ca bază pentru un script de migrare.** Pentru un script de
|
||||
> pachet, pleacă de la ultimul script aplicat din `SCRIPTURI_CLAR` (fișier real, care n-a trecut
|
||||
> niciodată printr-un spool) și confirmă că e la zi comparându-l cu exportul **ignorând spațiul
|
||||
> alb** — așa wrap-ul nu mai contează:
|
||||
> **Exportul e bun pentru CITIT, nu ca baza pentru un script de migrare.** Pentru un script de
|
||||
> pachet, pleaca de la ultimul script aplicat din `SCRIPTURI_CLAR` (fisier real, care n-a trecut
|
||||
> niciodata printr-un spool) si confirma ca e la zi comparandu-l cu exportul **ignorand spatiul
|
||||
> alb** - asa wrap-ul nu mai conteaza:
|
||||
> `tr -d ' \t\r\n' < fisier | md5sum` pe ambele.
|
||||
|
||||
```sql
|
||||
@@ -56,23 +47,5 @@ exit
|
||||
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/<parola>@ROA_CENTRAL' '@export_pack.sql'
|
||||
```
|
||||
|
||||
Același tipar merge pentru orice alt pachet/procedură (`PACK_SESIUNE`, `PACK_PRETURI`, …) sau
|
||||
Acelasi tipar merge pentru orice alt pachet/procedura (`PACK_SESIUNE`, `PACK_PRETURI`, ...) sau
|
||||
pentru DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
|
||||
|
||||
## Ce e strict necesar de știut despre PACK_CONTAFIN
|
||||
|
||||
Pachetul central de **scriere a documentelor** — clientul VFP populează tabelele temporare
|
||||
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
|
||||
|
||||
- `SCRIE_IN_FISIERE` — orchestratorul (apelat per document).
|
||||
- `SCRIE_IN_ACT` — `ACT_TEMP` → `ACT` (notele contabile).
|
||||
- `SCRIE_IN_RUL` — `RUL_TEMP` → `RUL` (mișcările de stoc); completează `COD`, `DATAORA`, `ID_FACT`
|
||||
(min. `id_fact` fără conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, opțional
|
||||
`ID_RUL_AUX` pe furnizor (opțiunea de firmă `RULAJFURNIZOR`). **Scrie exact ce e în RUL_TEMP — nu
|
||||
derivă rulaje din ACT**, deci filtrarea liniilor de rulaj se face în clientul VFP.
|
||||
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` — variantele pentru obiecte de
|
||||
inventar și actualizarea stocului.
|
||||
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
|
||||
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
|
||||
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, …)
|
||||
+ `PACK_SESIUNE` (an/lună, opțiuni firmă).
|
||||
|
||||
@@ -4,44 +4,8 @@ Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o mi
|
||||
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias —
|
||||
calitate degradata, cost mare. Nu se lucreaza asa.
|
||||
|
||||
## REGULA ZERO: predarea contextului e OBLIGATORIE, nu optionala
|
||||
|
||||
Se aplica **identic sesiunii principale si oricarui subagent**. Nu e o recomandare de eficienta,
|
||||
e o conditie de corectitudine: un context supraincarcat pierde tacut decizii deja luate si reia
|
||||
investigatii deja platite.
|
||||
|
||||
**Declansatoare — la oricare dintre ele, predarea porneste imediat:**
|
||||
|
||||
1. contextul propriu a trecut de **~50% din fereastra** (orchestrator) sau de **~200-250k tokens**
|
||||
(subagent);
|
||||
2. harness-ul anunta compactare automata (`PreCompact`) — **prea tarziu ca sa mai amani, dar nu
|
||||
prea tarziu ca sa scrii fisierul**; scrie handoff-ul inainte sa raspunzi orice altceva;
|
||||
3. utilizatorul semnaleaza ca s-a atins limita;
|
||||
4. s-a terminat un bloc de lucru — indiferent cat context a mai ramas.
|
||||
|
||||
**Procedura, in ordine, fara exceptii:**
|
||||
|
||||
1. **Opreste lucrul.** Nu incepe o sarcina noua, nu porni o rulare noua. Daca esti in mijlocul unei
|
||||
editari, du-o pana la o stare **consistenta pe disc** (text si binare sincronizate) si atat.
|
||||
2. **Scrie handoff-ul pe disc** (`docs\handoff_<subiect>.md`). Nu in mesaj, nu in raport — **pe
|
||||
disc**. Un mesaj catre orchestrator se pierde; fisierul nu.
|
||||
3. **Confirma in doua randuri** ce ai lasat in urma si daca ceva e intr-o stare periculoasa
|
||||
(fisier editat fara write-back, tranzactie deschisa, proces ramas viu, date de test consumate).
|
||||
4. **Opreste-te.** Blocul urmator il ia un agent proaspat. "Mai am putin" nu e motiv de amanare —
|
||||
exact acolo se pierd lucrurile.
|
||||
|
||||
**Obligatia e a fiecaruia, nu doar a orchestratorului.** Un subagent care simte ca se apropie de
|
||||
prag **anunta singur** si cere predarea; nu asteapta sa fie oprit. Un orchestrator care se apropie
|
||||
de prag isi scrie propriul handoff si preda orchestrarea unei sesiuni noi — regula nu are portita
|
||||
pentru "eu doar coordonez".
|
||||
|
||||
**Ce intra obligatoriu in handoff**: inventarul livrabilelor cu `fisier:linie`; ce e terminat si ce
|
||||
nu; **daca write-back-ul e facut** pentru fiecare fisier atins; comanda exacta de rulare a testelor
|
||||
si unde scriu logurile; ce s-a stabilit deja (ca sa nu se reia); ce e interzis; starea datelor de
|
||||
test consumate; capcanele de mediu platite. Fara analize noi — doar stare.
|
||||
|
||||
Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste prag (`s5-nivel2`
|
||||
533k, `s2d-modifica-gestiuni` 434k). Predarea e aproape gratuita: raportul e oricum deja scris.
|
||||
Predarea contextului la prag (REGULA ZERO, declansatoare, procedura, ce intra in handoff) e
|
||||
regula globala din `~/.claude/CLAUDE.md`, se aplica identic sesiunii principale si subagentilor.
|
||||
|
||||
## Cum se lucreaza
|
||||
|
||||
@@ -69,6 +33,27 @@ Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste p
|
||||
Sonnet; ORCHESTRATORUL subagentilor (cel care imparte, monitorizeaza, deblocheaza,
|
||||
decide) -> Opus (sau sesiunea principala). Commit doar dupa review-ul diff-ului de
|
||||
catre om (vezi reguli_lucru.md).
|
||||
- Un agent tinut peste prag costa scump: doua cazuri platite, aceeasi cauza (`s5-nivel2` 533k,
|
||||
`s2d-modifica-gestiuni` 434k tokens) — predarea la timp e aproape gratuita, raportul e oricum
|
||||
deja scris.
|
||||
|
||||
## Verificarea a ce se intoarce
|
||||
|
||||
Pentru executie delegarea merge, pentru concluzii nu:
|
||||
|
||||
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
|
||||
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
|
||||
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
|
||||
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
|
||||
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
|
||||
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
|
||||
refolosirea lui in alta parte.
|
||||
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
|
||||
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
|
||||
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
|
||||
agent care nu e intrebat explicit va prezenta amandoua la fel.
|
||||
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
|
||||
descoperit ca nu e nevoie de ea.
|
||||
|
||||
## Semne ca ai gresit impartirea
|
||||
|
||||
@@ -97,8 +82,8 @@ diagnostic, fixuri aplicate direct in loc de delegate.
|
||||
care intoarce da/nu, nu continutul din care ai deduce singur.
|
||||
- **Nu aplica fixuri direct** decat sub ~5 linii si doar daca ai deja contextul in sesiune.
|
||||
- **Prag si pe orchestrator**: la ~50% din fereastra, scrie handoff-ul si reia orchestrarea
|
||||
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi **Regula zero**
|
||||
de la inceputul fisierului: obligatia e aceeasi ca pentru subagenti, fara portita pentru
|
||||
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi REGULA ZERO din
|
||||
`~/.claude/CLAUDE.md`: obligatia e aceeasi ca pentru subagenti, fara portita pentru
|
||||
"eu doar coordonez".
|
||||
|
||||
## Model de lucru: backlog de story-uri mici, context mic per story
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
comentariu se scrie acolo unde explica o **ramura** sau un **filtru** care nu se citeste singur,
|
||||
ca sa se inteleaga codul; unde codul e limpede, nu se comenteaza. O linie de regula, 2-3 doar
|
||||
pentru metode cu contract nebanal (parametri, cursor asteptat/lasat deschis, pozitionare la
|
||||
iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are). Istoricul
|
||||
modificarilor sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg`, in `.sql`
|
||||
si in PL/SQL Oracle.
|
||||
iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are).
|
||||
INTERZIS in comentariu: nume de agent ("claude"), referinte la planuri, stories, propuneri,
|
||||
decizii, etape sau erori (`docs/plan_*.md`, `docs/propuneri_*.md`, "#6", "S4", "M2", "T3",
|
||||
"dec.6", "runda27", "E7", "D-H2"), trimiteri la rapoartele din `docs/` ("vezi raportul,
|
||||
@@ -29,10 +27,11 @@
|
||||
date si autori pe cod nou.
|
||||
Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins
|
||||
sau la cerere explicita.
|
||||
Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` /
|
||||
`*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta; autorul e cine
|
||||
semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul final — fara
|
||||
revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
|
||||
Istoricul modificarilor sta DOAR in antetul fisierului (niciodata inline, la fel in `.prg`,
|
||||
`.sql` si PL/SQL Oracle): o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` /
|
||||
`*!* autor` / `*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta;
|
||||
autorul e cine semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul
|
||||
final — fara revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
|
||||
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
||||
Changelog (`changelog_<aplicatie>.txt`): strictul necesar, pe limba utilizatorului, non-tehnic
|
||||
— 1-3 fraze/intrare, fara detalii de implementare, fara enumerarea locurilor atinse. Cat timp
|
||||
@@ -59,54 +58,25 @@
|
||||
6. Delegare: implementarile, testele, verificarile si cercetarile se dau unor subagenti Sonnet in
|
||||
background (lane-uri paralele); sesiunea principala doar orchestreaza si verifica, ca sa nu i
|
||||
se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k
|
||||
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc:
|
||||
`orchestrare-subagenti.md`.
|
||||
**Verificarea a ce se intoarce** — pentru executie delegarea merge, pentru concluzii nu:
|
||||
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
|
||||
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
|
||||
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
|
||||
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
|
||||
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
|
||||
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
|
||||
refolosirea lui in alta parte.
|
||||
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
|
||||
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
|
||||
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
|
||||
agent care nu e intrebat explicit va prezenta amandoua la fel.
|
||||
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
|
||||
descoperit ca nu e nevoie de ea.
|
||||
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc. Verificarea a
|
||||
ce se intoarce si modelul de lucru (backlog de story-uri mici): `orchestrare-subagenti.md`.
|
||||
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
||||
- editezi fisiere `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`, unde `s`-urile cu
|
||||
virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> `conventie_encoding_cp1252.md`.
|
||||
Antetul FoxBin2Prg declara `CPID="1252"`, dar octetii diacriticelor sunt de fapt **cp1250**
|
||||
(`0xE3`=a cu caciula, `0xFE`=t cu virgula, `0xAA`=S majuscul cu virgula, `0xBA`=s minuscul cu
|
||||
virgula) - nu trata eticheta din antet ca adevarul despre encoding. Orice write cu un tool ce
|
||||
nu pastreaza octetii nativ (Edit/Write) corupe caracterele >= 0x80 din TOT fisierul (`0xBA` ->
|
||||
`EF BF BD`), chiar la o singura linie schimbata, si o repeta la FIECARE scriere - **nu
|
||||
re-encoda niciodata fisierul: lucreaza pe octeti (`byte[]`) sau scrie strict ASCII in
|
||||
continutul nou**; editeaza tot ce ai de editat, verifica byte-level si repara o singura data
|
||||
DUPA ultima scriere.
|
||||
Cens obligatoriu **inainte SI dupa** fiecare editare, care trebuie sa ramana identic:
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Atentie
|
||||
la sens: la stricare censul **CRESTE**, nu scade - un octet cp1250 devine 3 octeti `EF BF BD`
|
||||
(U+FFFD) la o re-encodare UTF-8 gresita; cauta explicit secventa `EF BF BD`, nu doar tiparul
|
||||
generic de mojibake `C3`/`C4`/`C5`/`C8` + octet de continuare (acela da fals-pozitiv pe text
|
||||
UTF-8 legitim sau pe comentarii intr-o alta limba, deja intalnite in cod). Verificare veche
|
||||
(orice octet >=0x80, utila cand cauti pozitia exacta): `perl -ne 'print "$.\n" if
|
||||
/[\x80-\xFF]/' <fisier>`; reparare (pt. `0xBA`): `perl -e
|
||||
'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
|
||||
`EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel; ia octetul corect
|
||||
per pozitie din `svn cat <fisier>` (necorupt) sau din git history (`git cat-file blob
|
||||
<commit>:<cale>`, **din Bash, niciodata cu `>` din PowerShell 5.1** - adauga BOM si
|
||||
re-encodeaza) inainte sa inlocuiesti - o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula
|
||||
(`0xE3`, `0xFE`) din alte fisiere;
|
||||
- editezi `.vc2`/`.sc2` sau `.prg` cu diacritice (ex. `programe\ocautare.prg`) -> fisierele
|
||||
sunt **cp1250** desi antetul FoxBin2Prg declara `CPID="1252"`; Edit/Write corup TOT fisierul
|
||||
(nu doar linia atinsa) la fiecare scriere - scrie continut nou strict ASCII. Cens obligatoriu
|
||||
**inainte SI dupa** fiecare editare (la stricare CRESTE, nu scade):
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Tabel
|
||||
de octeti si reparare -> `conventie_encoding_cp1252.md`;
|
||||
- adaugi o PROPRIETATE sau o METODA noua intr-o clasa `.vc2`/`.sc2` -> `flux-editare-vfp-text.md`,
|
||||
sectiunea "Membri noi de clasa": fara intrarea `*p:`/`*m:` in `*<DefinedPropArrayMethod>`
|
||||
membrul trece fidelity-check-ul, dar VFP nu-l vede si prima salvare din IDE il sterge tacut;
|
||||
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
|
||||
- grid needitabil pe formular cu 2+ grid-uri -> `capcana_grid_controlsource.md`;
|
||||
- adaugi o coloana intr-un grid deja livrat (ordinea din clasa e neutralizata de
|
||||
preferintele salvate per utilizator) -> `capcana_grid_preferinte_utilizator.md`;
|
||||
- `GO` pe un `Recno()` capturat/primit ca parametru -> `conventie_go_recno.md`;
|
||||
- `ALTER TABLE` pe cursorul intors de `goExecutor.oExecute()` -> `conventie_goexecutor_alter_table.md`;
|
||||
- testare UI / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;
|
||||
- testare UI -> `testare-ui-vfp.md`;
|
||||
- te conectezi la Oracle pe dev/test, alegi schema sau rulezi un script de pachet ->
|
||||
`conventie_mediu_oracle.md`;
|
||||
- garzi pe valori NULL din Oracle -> `conventie_null_vfp.md`;
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
Harness reutilizabil pentru teste care afiseaza un formular REAL (cu dependinte dummy, fara
|
||||
Oracle), executa actiuni si valideaza vizual prin capturi. Valabil pentru toate proiectele VFP
|
||||
din suita ROA. Alternativa la `testare-vfp-mcp.md` (care porneste programul principal intreg);
|
||||
capcanele generale de rulare headless (`-A -T`, SAFETY, script agatat) sunt in
|
||||
din suita ROA. Capcanele generale de rulare headless (`-A -T`, SAFETY, script agatat) sunt in
|
||||
`depanare_testare_vfp.md`.
|
||||
|
||||
Fisiere in `COMUN\utile\Teste\`: `vfp_ui_harness.ps1` (orchestrator generic, parametrizat),
|
||||
@@ -85,10 +84,9 @@ Doua non-dovezi, ca sa nu se piarda timp pe ele:
|
||||
|
||||
## Capcane / deblocari
|
||||
|
||||
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`.** Cu SAFETY ON, scrierea
|
||||
log-ului existent scoate un dialog modal care blocheaza rularea (proces viu, "instanta
|
||||
moarta"). Cu TALK ON, `SUM`/`CALCULATE` isi echo-eaza rezultatele peste formular in
|
||||
screenshots.
|
||||
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`** - capcana completa in
|
||||
`depanare_testare_vfp.md` sectiunea 7. Specific UI: cu TALK ON, `SUM`/`CALCULATE` isi
|
||||
echo-eaza rezultatele peste formular in screenshots.
|
||||
b. **Lansarea orchestratorului**: prin tool cu timeout implicit (~120s) e omorat inainte de
|
||||
final. Ruleaza-l in background + asteapta `done.txt`, sau timeout 300-600s. NU porni VFP
|
||||
separat de orchestrator - si-l lanseaza singur.
|
||||
@@ -209,6 +207,6 @@ s. **Dialoguri native care nu apar in log si nu sunt prinse de `ON ERROR`/mock-u
|
||||
tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare, altfel `WM_COMMAND IDCANCEL` ->
|
||||
ESCAPE ca mesaj `WM_KEYDOWN`/`WM_KEYUP` -> `WM_CLOSE`); pe dialogurile proprii VFP owner-drawn
|
||||
(butoane desenate, nu HWND-uri reale) dismiss-ul poate esua cinstit — captura PNG + dump text
|
||||
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Sterge intotdeauna `.fxp`-ul
|
||||
vechi inainte de FIECARE rulare (watchdog-ul o face singur la lansare) — altfel VFP ruleaza
|
||||
tacut codul compilat vechi si rulari "identice" dau rezultate diferite, fara nicio urma in log.
|
||||
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Watchdog-ul sterge singur
|
||||
`.fxp`-ul vechi la lansare - capcana completa (de ce e obligatoriu) in `depanare_testare_vfp.md`
|
||||
sectiunea 7.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# Testare automata VFP prin IDE + MCP (windows-mcp)
|
||||
|
||||
Valabil pentru toate proiectele VFP din suita ROA; exemplele de mai jos sunt pe ROAGEST —
|
||||
inlocuieste caile, numele programului principal si titlul ferestrei pentru alt proiect.
|
||||
|
||||
Pentru verificare vizuala dupa modificari pe `.vc2`/`.sc2`, nu se porneste `roagest.exe`
|
||||
(ar cere rebuild complet — vezi `COMUN\docs\flux-editare-vfp-text.md`), ci se lanseaza `vfp9.exe`
|
||||
interpretat peste `Programe\roagest.prg`:
|
||||
|
||||
```powershell
|
||||
Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" `
|
||||
-ArgumentList '-c"D:\ROA\ROAGEST\config.fpw"','D:\ROA\ROAGEST\Programe\roagest.prg' `
|
||||
-WorkingDirectory "D:\ROA\ROAGEST"
|
||||
```
|
||||
|
||||
- Gate-ul de pornire (`gcNumeProgram = 'ROAGEST'` in `roagest.prg`) verifica
|
||||
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele procesului
|
||||
`.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
|
||||
- Fereastra rezultata are titlul `ROA - Gestiuni` (setat din `NUMEPROGRAM`).
|
||||
|
||||
## Capcana: focus furat de terminal
|
||||
|
||||
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza, fereastra
|
||||
terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal — `Screenshot`/`Snapshot`
|
||||
din `windows-mcp` pot raporta "No windows found" desi procesul si fereastra exista (verificabil
|
||||
cu `Get-Process vfp9 | Select MainWindowTitle`).
|
||||
|
||||
Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
||||
|
||||
```
|
||||
mcp__windows-mcp__App mode=switch name="ROA - Gestiuni"
|
||||
```
|
||||
|
||||
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand ai lansat
|
||||
procesul chiar in runda curenta de comenzi.
|
||||
|
||||
## Curatare dupa test
|
||||
|
||||
Proces de omorat la final: `mcp__windows-mcp__Process mode=kill pid=<pid>` (gasit prin
|
||||
`mode=list name=vfp9` sau `Get-Process vfp9`).
|
||||
Reference in New Issue
Block a user