verificare partener: garda pe cont NULL, hook-uri de disciplina, docs compactate
- ooperatii_comune: verific_partener nu mai construieste SQL NULL cand contul primit e NULL (EMPTY(.NULL.) e .F. in VFP) - utile\context_watch.ps1 si utile\docs_revizie_check.ps1: masurarea contextului sesiunii si cadenta reviziei de documentatie, prin hook-uri Claude Code (instalare in docs\monitorizare-context.md) - reguli_lucru: delegare la subagenti, modificari minime si scoped, scrierea si revizuirea documentatiei, changelog strictul necesar (regulile 3, 6, 9, 11, 12) - scripturi-migrare-db: continutul unui script (scoped, fara select, idempotent) - teste noi pentru cele doua erori din achizitia de import - restul documentatiei compactata, fara pierdere de reguli Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYbiinqXxdEqXi53x4Ro7K
This commit is contained in:
1
docs/.ultima_revizie
Normal file
1
docs/.ultima_revizie
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2026-08-02
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
# Prompt: căutare și editare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
# Prompt: căutare și editare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
||||||
|
|
||||||
Acest fișier conține un **prompt gata de copiat** pentru Claude Code (sau alt agent), care
|
**Prompt gata de copiat** pentru Claude Code (sau alt agent), care configurează și folosește
|
||||||
configurează și folosește sistemul `foxbin2prg` ca să poată **căuta** cod-sursă aflat **în interiorul
|
sistemul `foxbin2prg` ca să poată **căuta** cod-sursă aflat **în interiorul fișierelor binare VFP**
|
||||||
fișierelor binare VFP** (`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un
|
(`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un proiect nou — și, pentru
|
||||||
proiect nou — și, pentru `.vcx`/`.scx`, să poată și **modifica** acel cod direct pe text, cu
|
`.vcx`/`.scx`, să poată și **modifica** acel cod direct pe text, cu write-back în binar
|
||||||
write-back în binar (`txt2vcx.ps1`), fără trecere prin IDE-ul VFP.
|
(`txt2vcx.ps1`), fără trecere prin IDE-ul VFP.
|
||||||
|
|
||||||
Unealta e partajată și stă la `D:\ROA\UTIL\foxbin2prg\` — nu trebuie copiată per proiect. Doar
|
Unealta e partajată, la `D:\ROA\UTIL\foxbin2prg\` — nu se copiază per proiect. Doar spui agentului
|
||||||
spui agentului care e proiectul curent (folderul + fișierul `.pjx`).
|
care e proiectul curent (folderul + fișierul `.pjx`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ spui agentului care e proiectul curent (folderul + fișierul `.pjx`).
|
|||||||
|
|
||||||
1. Deschide proiectul VFP în Claude Code.
|
1. Deschide proiectul VFP în Claude Code.
|
||||||
2. Copiază blocul de mai jos în prompt.
|
2. Copiază blocul de mai jos în prompt.
|
||||||
3. Înlocuiește cele **3 valori** marcate `<<...>>` cu datele proiectului tău:
|
3. Înlocuiește cele **3 valori** marcate `<<...>>`:
|
||||||
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
||||||
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
||||||
- `<<NUME_PROIECT>>` = etichetă scurtă pentru folderul de cache (ex. `roagest`)
|
- `<<NUME_PROIECT>>` = etichetă scurtă pentru folderul de cache (ex. `roagest`)
|
||||||
@@ -104,15 +104,15 @@ fișier:linie din cache.
|
|||||||
|
|
||||||
## Note pentru adaptare
|
## Note pentru adaptare
|
||||||
|
|
||||||
- `<<NUME_PROIECT>>` îl poți pune orice etichetă scurtă (ex. `roagest`), doar ca numele
|
- `<<NUME_PROIECT>>` poate fi orice etichetă scurtă (ex. `roagest`), unică per proiect (numele
|
||||||
folderului de cache să fie unic per proiect.
|
folderului de cache).
|
||||||
- Ține cache-ul în `D:\ROA\_vfp_textcache\`, adică **în afara** folderului `foxbin2prg`. Motiv:
|
- Ține cache-ul în `D:\ROA\_vfp_textcache\`, adică **în afara** folderului `foxbin2prg`. Motiv:
|
||||||
`ReCreate_FoxBin2Prg.prg` face `Prg2Bin` recursiv pe tot folderul tool-ului și ar reconverti
|
`ReCreate_FoxBin2Prg.prg` face `Prg2Bin` recursiv pe tot folderul tool-ului și ar reconverti
|
||||||
`.??2`-urile din orice cache aflat sub el înapoi în binare parazitare.
|
`.??2`-urile din orice cache aflat sub el înapoi în binare parazitare.
|
||||||
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește **doar** ce folosește
|
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește doar ce folosește efectiv
|
||||||
efectiv proiectul (rapid), nu tot `COMUN\`.
|
proiectul (rapid), nu tot `COMUN\`.
|
||||||
- Cache-ul (`D:\ROA\_vfp_textcache\<proiect>`) e regenerabil și e în afara arborelui de versionare
|
- Cache-ul e regenerabil, în afara arborelui de versionare al proiectului (și al clonei
|
||||||
al proiectului (și în afara clonei foxbin2prg) — poate fi șters oricând.
|
foxbin2prg) — poate fi șters oricând.
|
||||||
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
||||||
- Fără backup-uri `.bak` lângă binarele din proiect — git e mecanismul de restore; `txt2vcx.ps1`
|
- Fără backup-uri `.bak` lângă binarele din proiect — git e mecanismul de restore; `txt2vcx.ps1`
|
||||||
ține o copie de siguranță doar în folderul temp al rulării.
|
ține o copie de siguranță doar în folderul temp al rulării.
|
||||||
|
|||||||
@@ -1,49 +1,44 @@
|
|||||||
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
||||||
|
|
||||||
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder,
|
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder —
|
||||||
care e varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
||||||
|
|
||||||
Cum se caută cod-sursă (proceduri, metode, parametri) care **nu** stă în fișiere `.prg`, ci
|
Căutare de cod-sursă (proceduri, metode, parametri) care **nu** stă în `.prg`, ci în interiorul
|
||||||
în interiorul fișierelor binare VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`),
|
binarelor VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte (`.frx`+`.frt`),
|
||||||
rapoarte (`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
|
meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
|
||||||
|
|
||||||
## De ce e nevoie de asta
|
## De ce e nevoie de asta
|
||||||
|
|
||||||
Un `.vcx` este de fapt o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. Un
|
Un `.vcx` e o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. `grep` direct pe
|
||||||
`grep` direct pe `.vct` *găsește* textul, dar îl vede ca fișier binar (octeți `\0` între linii),
|
`.vct` găsește textul dar ca binar (octeți `\0` între linii), fără numere de linie și greu de
|
||||||
fără numere de linie utile și greu de citit. Soluția: convertim binarul în reprezentarea lui
|
citit. Soluția: convertim binarul în reprezentarea lui **TEXT** (`.vc2`, `.sc2`, …) — PRG-style
|
||||||
**TEXT** (`.vc2`, `.sc2`, …) — un PRG-style lizibil, cu metode sortate alfabetic — și căutăm
|
lizibil, metode sortate alfabetic — și căutăm în text cu `grep`/`Grep`.
|
||||||
în text cu `grep`/`Grep`.
|
|
||||||
|
|
||||||
> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru
|
> **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
|
> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi
|
||||||
> `PROMPT_cautare_vfp.md` pasul 3 pentru fluxul complet (ordine obligatorie, encoding,
|
> `PROMPT_cautare_vfp.md` pasul 3 (ordine obligatorie, encoding, fidelity check). Pentru
|
||||||
> fidelity check). Pentru `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot
|
> `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot în **IDE-ul VFP**.
|
||||||
> în **IDE-ul VFP**.
|
|
||||||
|
|
||||||
## Unelte disponibile (verificate)
|
## Unelte disponibile (verificate)
|
||||||
|
|
||||||
| Unealtă | Cale | Rol | Recomandare |
|
| Unealtă | Cale | Rol | Recomandare |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Complet, fidel, include corpul metodelor, parametri, comentarii |
|
| **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 vechi, doar clase, necesită IDE VFP deschis pentru a rula forma |
|
| 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 (e direcția opusă) |
|
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (direcție opusă) |
|
||||||
|
|
||||||
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
||||||
toate tipurile de container, și produce text mult mai fidel decât vcx2prg.
|
toate tipurile de container, text mai fidel decât vcx2prg.
|
||||||
|
|
||||||
> Dacă `FoxBin2Prg.EXE` lipsește, se compilează o singură dată: deschide
|
> Dacă `FoxBin2Prg.EXE` lipsește: deschide `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și
|
||||||
> `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și *Build > Build Executable*. Lângă EXE trebuie
|
> *Build > Build Executable*. Lângă EXE trebuie să existe `filename_caps.exe` și `props*.txt`
|
||||||
> să existe `filename_caps.exe` și fișierele `props*.txt` (sunt deja în folder).
|
> (deja în folder).
|
||||||
|
|
||||||
## Mod recomandat: scriptul `vcx2txt.ps1`
|
## Mod recomandat: scriptul `vcx2txt.ps1`
|
||||||
|
|
||||||
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` automatizează tot: copiază binarul + memo-ul într-un
|
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` copiază binarul + memo-ul într-un **cache** care oglindește
|
||||||
**cache** care oglindește structura proiectului (ca să nu murdărească arborele SVN), rulează
|
structura proiectului (nu murdărește arborele SVN), rulează FoxBin2Prg, păstrează doar textul.
|
||||||
FoxBin2Prg, păstrează doar fișierul text. E **incremental** (sare peste ce e deja la zi).
|
**Incremental** (sare peste ce e deja la zi).
|
||||||
|
|
||||||
Parametrizează scriptul cu proiectul curent și un cache separat per proiect (nu amesteca
|
|
||||||
cache-urile mai multor proiecte ROA):
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
|
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
|
||||||
@@ -56,7 +51,7 @@ powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
|||||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||||
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Types vcx,scx,frx,mnx
|
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Types vcx,scx,frx,mnx
|
||||||
|
|
||||||
# conversie punctuală a unui fișier sau folder (chiar dacă NU e în proiect, ex. o clasă din COMUN)
|
# 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'
|
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
|
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
|
||||||
@@ -65,7 +60,7 @@ powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
|||||||
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Clean
|
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Clean
|
||||||
```
|
```
|
||||||
|
|
||||||
Exemplu concret (ROAAUTO):
|
Exemplu (ROAAUTO):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||||
@@ -73,19 +68,17 @@ powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
|||||||
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_roaauto
|
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_roaauto
|
||||||
```
|
```
|
||||||
|
|
||||||
Rezultatul ajunge în cache-ul indicat, cu aceeași structură de directoare ca proiectul (ex.:
|
Rezultatul ajunge în cache, cu aceeași structură de directoare ca proiectul (ex.:
|
||||||
`_textcache_roaauto\Clase\odevize.vc2`, `_textcache_roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
`_textcache_roaauto\Clase\odevize.vc2`, `_textcache_roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# cu unealta Grep (preferat) sau grep:
|
|
||||||
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>"
|
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>"
|
||||||
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>" # ce clase ating subiectul
|
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>" # ce clase ating subiectul
|
||||||
```
|
```
|
||||||
|
|
||||||
Flux tipic pentru o problemă: rulează scriptul cu parametrii de mai sus o dată (populează
|
Flux tipic: rulează scriptul o dată (populează cache-ul), apoi caută cu `Grep` în cache. La
|
||||||
cache-ul), apoi caută cu `Grep` în cache. La sesiuni următoare rescrie doar ce s-a schimbat
|
sesiuni următoare rescrie doar ce s-a schimbat (incremental). Pentru o librărie din `COMUN\` care
|
||||||
(incremental). Dacă ai nevoie de o librărie din `COMUN\` care nu e în proiect, convertește-o
|
nu e în proiect, convertește-o punctual cu `-Source`.
|
||||||
punctual cu `-Source`.
|
|
||||||
|
|
||||||
## Alternativă manuală (fără script)
|
## Alternativă manuală (fără script)
|
||||||
|
|
||||||
@@ -99,23 +92,23 @@ Copy-Item D:\ROA\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\Clase\odevize.vct
|
|||||||
# => D:\tmp\odevize.vc2
|
# => D:\tmp\odevize.vc2
|
||||||
```
|
```
|
||||||
|
|
||||||
Pozițiile parametrilor folosite: `fișier, cType, cTextName, lGenText, cDontShowErrors=1,
|
Poziții parametri: `fișier, cType, cTextName, lGenText, cDontShowErrors=1, cDebug=0,
|
||||||
cDebug=0, cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția.
|
cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția. (Nu da explicit
|
||||||
(Nu da explicit `"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
|
`"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`.
|
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
|
||||||
|
|
||||||
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
|
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
|
||||||
|
|
||||||
Pentru o verificare rapidă „există metoda X undeva în librărie?", `grep` merge direct pe `.vct`
|
Pentru „există metoda X undeva în librărie?", `grep` merge direct pe `.vct` (îl vede ca binar, dar
|
||||||
(o vede ca binar, dar găsește potrivirile):
|
găsește potrivirile):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||||
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "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 citit corpul/contextul, folosește conversia în text.
|
Bun pentru „da/nu" și nume de metode; pentru corp/context, folosește conversia în text.
|
||||||
|
|
||||||
## Corespondență extensii binar → text
|
## Corespondență extensii binar → text
|
||||||
|
|
||||||
@@ -130,10 +123,9 @@ Bun pentru „da/nu" și nume de metode; pentru citit corpul/contextul, foloseș
|
|||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
- Codul aplicației stă mai ales în `Clase\*.vcx`; o mare parte din `.vcx`-uri sunt în
|
- Codul aplicației stă mai ales în `Clase\*.vcx`; multe `.vcx`-uri sunt în `COMUN\` (framework
|
||||||
`COMUN\` (framework partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
||||||
- Cache-ul text e regenerabil și e în afara arborelui SVN/git al proiectului — poate fi șters
|
- Cache-ul text e regenerabil, în afara arborelui SVN/git al proiectului — poate fi șters oricând.
|
||||||
oricând.
|
|
||||||
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).
|
- 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
|
- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la
|
||||||
editarea `.sc2`/`.vc2` (nu doar la căutare).
|
editarea `.sc2`/`.vc2` (nu doar la căutare).
|
||||||
|
|||||||
@@ -1,27 +1,18 @@
|
|||||||
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
|
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
|
||||||
|
|
||||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md` din acest folder) — capcana
|
Partajat între proiectele ROA* — capcana ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg,
|
||||||
ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg, nu de un proiect anume.
|
nu de un proiect anume.
|
||||||
|
|
||||||
Descoperit de 2 ori în aceeași sesiune (2026-07-10, în ROAAUTO): odată în
|
|
||||||
`COMUN/clase/cmd_butoane.vc2` (clasa `cmd_select_adv`), odată în `Clase/ofundal_dev.vc2`
|
|
||||||
(meniul principal) — de fiecare dată un agent anterior a editat text-cache-ul cu un tool care
|
|
||||||
nu scrie cp1252 nativ, și a corupt TOATE caracterele cu diacritice din fișier, nu doar linia
|
|
||||||
pe care voia s-o schimbe.
|
|
||||||
|
|
||||||
## De ce se întâmplă
|
## De ce se întâmplă
|
||||||
|
|
||||||
Fișierele `.sc2`/`.vc2` generate de FoxBin2Prg sunt **cp1252 (Windows-1252)**, nu UTF-8
|
Fișierele `.sc2`/`.vc2` sunt **cp1252** (Windows-1252), nu UTF-8 (vezi antetul: `CPID="1252"`).
|
||||||
(vezi antetul fiecărui fișier: `CPID="1252"`). Dacă un editor/tool citește fișierul ca UTF-8
|
Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid
|
||||||
(sau alt encoding), fiecare byte >= 0x80 (diacritic) devine invalid ca secvență UTF-8 și e
|
ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi **salvează tot ca UTF-8**, acel
|
||||||
înlocuit cu caracterul de replacement U+FFFD. Dacă apoi tool-ul **salvează rezultatul tot ca
|
U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1252 (cum face
|
||||||
UTF-8**, acel U+FFFD e scris ca 3 octeți UTF-8 (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca
|
FoxBin2Prg la write-back), apar ca `�`. Caracterul original e **ireversibil pierdut**
|
||||||
cp1252 (cum face FoxBin2Prg la write-back), apar ca `�`. Rezultatul: caracterul original e
|
(recuperabil DOAR din altă sursă: git history, backup).
|
||||||
**ireversibil pierdut** (nu mai există în fișier sub nicio formă) — recuperabil DOAR din altă
|
|
||||||
sursă (git history, backup).
|
|
||||||
|
|
||||||
Codebase-ul ROA folosește un hack vechi de "reciclare" a unor caractere cp1252 needependente
|
Codebase-ul ROA "reciclează" caractere cp1252 fără echivalent direct pentru Ș/ă/ț:
|
||||||
de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice românești:
|
|
||||||
|
|
||||||
| Literă românească | Caracter folosit (cp1252) | Byte |
|
| Literă românească | Caracter folosit (cp1252) | Byte |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -30,10 +21,10 @@ de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice române
|
|||||||
| ț | þ (thorn minuscul) | `0xFE` |
|
| ț | þ (thorn minuscul) | `0xFE` |
|
||||||
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
|
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
|
||||||
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
|
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
|
||||||
| î, â | î, â (existente nativ în cp1252) | `0xEE`, `0xE2` |
|
| î, â | î, â (native cp1252) | `0xEE`, `0xE2` |
|
||||||
|
|
||||||
Aceste caractere par "gunoi"/typo la prima vedere într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) —
|
Par "gunoi"/typo într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) — **sunt corecte, nu le "corecta"
|
||||||
**sunt corecte, nu le "corecta" fără să verifici encoding-ul.**
|
fără să verifici encoding-ul.**
|
||||||
|
|
||||||
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
||||||
|
|
||||||
@@ -43,40 +34,38 @@ $text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
|
|||||||
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
|
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
|
||||||
```
|
```
|
||||||
|
|
||||||
Dacă apare `�` (sau `$text` conține U+FFFD) în output — fișierul are corupere de encoding.
|
Dacă apare `�` (sau `$text` conține U+FFFD) — fișierul are corupere de encoding.
|
||||||
|
|
||||||
## Cum se repară
|
## Cum se repară
|
||||||
|
|
||||||
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul
|
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul curent.
|
||||||
curent.
|
2. Dacă corupera s-a întâmplat într-o sesiune anterioară necomisă (HEAD-ul git încă e curat):
|
||||||
2. Dacă fișierul e sub control de versiune (git) și corupera s-a întâmplat **într-o sesiune
|
recuperează originalul convertind binarul din HEAD în text:
|
||||||
anterioară necomisă** (deci HEAD-ul git încă are versiunea curată): recuperează originalul
|
|
||||||
convertind binarul din HEAD în text și comparând:
|
|
||||||
```bash
|
```bash
|
||||||
git show HEAD:<cale>.vcx > /tmp/head.vcx
|
git show HEAD:<cale>.vcx > /tmp/head.vcx
|
||||||
git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz)
|
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
|
powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out
|
||||||
```
|
```
|
||||||
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
|
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
|
||||||
linie (PowerShell, nu `diff` direct — `diff`/Bash nu decodează cp1252 corect pentru afișare,
|
linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1252 corect la afișare, deși
|
||||||
deși detectează totuși diferența de octeți).
|
detectează totuși diferența de octeți).
|
||||||
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), și reaplică DOAR
|
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), reaplicând DOAR
|
||||||
modificările intenționate din sesiunea curentă peste ea (nu invers — nu încerca să "cârpești"
|
modificările intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt
|
||||||
fișierul corupt caracter cu caracter, e mai sigur să repornești de la baza curată).
|
caracter cu caracter).
|
||||||
4. Scrie rezultatul înapoi ca bytes cp1252 (`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`),
|
4. Scrie rezultatul înapoi ca bytes cp1252
|
||||||
NU ca string UTF-8/`Out-File` implicit (care scrie UTF-8 sau UTF-16 după caz).
|
(`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`), NU ca string UTF-8/`Out-File`
|
||||||
|
implicit.
|
||||||
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
||||||
|
|
||||||
## Cum se evită pe viitor
|
## Cum se evită pe viitor
|
||||||
|
|
||||||
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
|
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ă a
|
conține diacritice (`ã`, `þ`, `ª`, `º`, `î`, `â` etc.) — dacă da, **orice rescrie completă
|
||||||
fișierului trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând
|
trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând UTF-8.
|
||||||
UTF-8 implicit. Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul
|
Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul păstrează restul
|
||||||
păstrează restul fișierului byte-identic (nu rescrie tot fișierul reîncodat).
|
fișierului byte-identic (nu rescrie tot fișierul reîncodat).
|
||||||
|
|
||||||
## Vezi și
|
## Vezi și
|
||||||
|
|
||||||
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează deja riscul ("Headerul
|
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează riscul pe scurt; acest fișier
|
||||||
CPID="1252" poate minți...") pe scurt; acest fișier e detalierea completă (tabel de caractere,
|
e detalierea completă (tabel de caractere, pași de recuperare din git).
|
||||||
pași de recuperare din git).
|
|
||||||
|
|||||||
@@ -12,23 +12,14 @@ lnSucces = goExecutor.oExecute(lcSql, lcCursor)
|
|||||||
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
||||||
```
|
```
|
||||||
|
|
||||||
Cursorul întors de `oExecute()` (rezultatul unui `SQLExec`) poate refuza comenzi DDL
|
Cursorul întors de `oExecute()` poate refuza comenzi DDL ulterioare, cu erori în lanț
|
||||||
ulterioare, cu erori în lanț (descoperite empiric, în această ordine, în ROAAUTO
|
(descoperite empiric, în această ordine):
|
||||||
`autopass_cursor_comenzi`/`autopass_cursor_operatii`):
|
|
||||||
|
|
||||||
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul
|
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul original.
|
||||||
original.
|
2. Chiar și după rematerializare (`SELECT * FROM (cursor) INTO CURSOR (acelasi_nume) READWRITE`)
|
||||||
2. Chiar și după o încercare de rematerializare (`SELECT * FROM (cursor) INTO CURSOR
|
→ `Alias name is already in use.` (sursa și ținta nu pot avea același nume).
|
||||||
(acelasi_nume) READWRITE`) → `Alias name is already in use.` (sursa și ținta nu pot
|
3. Cu alias scratch diferit ca țintă → tot `Invalid operation for the cursor.` pe `ALTER TABLE`,
|
||||||
avea același nume într-un `SELECT...INTO CURSOR`).
|
chiar dacă țintă ar trebui să fie deja un cursor local obișnuit.
|
||||||
3. Cu un alias scratch diferit ca țintă (`SELECT * FROM (cursor) INTO CURSOR
|
|
||||||
(nume_final_diferit_de_sursa) READWRITE`) → tot `Invalid operation for the cursor.` pe
|
|
||||||
`ALTER TABLE`, chiar dacă acum cursorul final teoretic ar trebui să fie unul local
|
|
||||||
obișnuit.
|
|
||||||
|
|
||||||
Nu există niciun alt loc în codul ROA* care să facă `ALTER TABLE` imediat după
|
|
||||||
`goExecutor.oExecute()` — deci acest pattern nu avea niciun precedent testat înainte de
|
|
||||||
funcțiile AUTOPASS.
|
|
||||||
|
|
||||||
## Ce funcționează
|
## Ce funcționează
|
||||||
|
|
||||||
@@ -55,9 +46,8 @@ USE IN (lcCursorRaw)
|
|||||||
```
|
```
|
||||||
|
|
||||||
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
|
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
|
||||||
normal pe el DUPĂ ACEEA (ex. dintr-o altă funcție care primește cursorul deja gata construit,
|
normal pe el DUPĂ ACEEA (ex. într-o altă funcție care primește cursorul deja gata construit),
|
||||||
nu direct rezultatul unui `oExecute`), doar comanda imediat următoare unui `oExecute()` e
|
doar comanda imediat următoare unui `oExecute()` e restricționată.
|
||||||
restricționată.
|
|
||||||
|
|
||||||
## Vezi și
|
## Vezi și
|
||||||
|
|
||||||
|
|||||||
21
docs/conventie_null_vfp.md
Normal file
21
docs/conventie_null_vfp.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Garzi pe valori NULL (VFP)
|
||||||
|
|
||||||
|
Campurile din cursoarele intoarse de Oracle pot fi `.NULL.`. In VFP `EMPTY(.NULL.)` intoarce
|
||||||
|
`.F.`, deci o garda scrisa doar cu `EMPTY()` **nu prinde NULL**, iar concatenarea cu NULL face
|
||||||
|
tot sirul NULL (inclusiv un SQL construit prin `+`).
|
||||||
|
|
||||||
|
Forma corecta, cu tipul evaluat primul ca sa opreasca acolo:
|
||||||
|
|
||||||
|
```foxpro
|
||||||
|
If Type('tcCont') # 'C' Or Empty(Nvl(tcCont, ''))
|
||||||
|
Return
|
||||||
|
Endif
|
||||||
|
```
|
||||||
|
|
||||||
|
- `Nvl(x, '')` in interiorul lui `Empty()`, nu `Isnull(x) Or Empty(x)`.
|
||||||
|
- `TYPE()` pe o variabila cu NULL de tip caracter intoarce tot `'C'` - nu tine loc de `Nvl`.
|
||||||
|
- Acelasi tratament la orice text construit prin `+` din campuri de cursor
|
||||||
|
(SQL, mesaje, chei): un singur camp NULL anuleaza tot sirul.
|
||||||
|
|
||||||
|
Simptom tipic cand lipseste garda: `SQL statement parameter is required for non-prepared
|
||||||
|
SQLEXEC() calls` in `OEXECUTOR.OEXECUTE` - SQL-ul ajuns la `SQLEXEC` era `.NULL.`.
|
||||||
@@ -1,37 +1,26 @@
|
|||||||
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
||||||
|
|
||||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md`, `prompt_project_insights_docs.md`
|
Partajat între proiectele ROA* — `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul
|
||||||
din acest folder) — pentru că `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.
|
corect pentru o convenție de design care nu ține de un singur proiect.
|
||||||
|
|
||||||
Origine: confirmat de Marius pe `frm_autopass.scx` (ROAAUTO) după o rundă de regrupare vizuală
|
|
||||||
(2026-07-10) — "imi place designul acesta" pe layout-ul cu rânduri clar separate pe funcție,
|
|
||||||
butoane grupate la margini, fără elemente lipite unele de altele.
|
|
||||||
|
|
||||||
## Ce înseamnă in practică, pe proprietăți VFP
|
## Ce înseamnă in practică, pe proprietăți VFP
|
||||||
|
|
||||||
- **Fiecare grup funcțional pe rândul lui** — nu înghesui controale fără legătură directă pe
|
- **Fiecare grup funcțional pe rândul lui**, nu înghesuit pe același `Top` cu altul fără
|
||||||
același `Top`. Ex: rândul de perioadă (date + Actualizează) separat de rândul de
|
legătură (ex: perioadă / statistici / configurare, pe rânduri separate).
|
||||||
statistici (Declarabile/Transmise/Blocate), separat de panoul de configurare.
|
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din aceeași
|
||||||
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din
|
acțiune la 6-10px unele de altele; gap de 20-30px față de următorul grup funcțional.
|
||||||
aceeași acțiune (ex. Validează dry-run → Transmite → Renunță) la 6-10px unele de altele;
|
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**, nu
|
||||||
gap de 20-30px față de următorul grup funcțional (ex. Selectează tot vs. grupul
|
lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting ca acțiune
|
||||||
Validare/Transmitere vs. Actualizează statusuri).
|
separată de câmpul de input.
|
||||||
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**,
|
- **Acțiunea principală + oprirea ei alăturate** (ex. Transmite + Renunță), nu împrăștiate în
|
||||||
nu lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting vizual ca
|
|
||||||
acțiune separată de câmpul de input.
|
|
||||||
- **Acțiunea principală + oprirea ei alăturate** — un buton de tip "Renunță/Oprește" trebuie
|
|
||||||
poziționat lângă acțiunea pe care o anulează (ex. Transmite + Renunță), nu împrăștiat în
|
|
||||||
altă parte a rândului.
|
altă parte a rândului.
|
||||||
- **Un singur rând de acțiuni cât se poate** — dacă mai multe grupuri de butoane încap pe
|
- **Un singur rând de acțiuni cât se poate** — un rând orizontal in loc de rânduri noi
|
||||||
lățimea formei, preferă un singur rând orizontal în loc să adaugi rânduri noi dedesubt;
|
dedesubt; formele rămân compacte pe verticală.
|
||||||
păstrează formele compacte pe verticală.
|
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE". ALL
|
||||||
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE";
|
CAPS/text lung pe un buton citește ca zgomot, nu ca ierarhie.
|
||||||
"Dashboard AutoPass" nu "Deschide dashboard AUTOPASS". ALL CAPS/text lung pe un buton
|
- **Culoare = semnal, nu decor** — doar pentru acțiuni cu semnificație clară (verde =
|
||||||
citește ca zgomot, nu ca ierarhie.
|
pozitiv/transmite, roșu = oprire/pericol, albastru = navigare/link extern); restul butoanelor
|
||||||
- **Culoare = semnal, nu decor** — folosește culoare distinctă doar pentru acțiuni cu
|
rămân stilul implicit din `_baza.vcx`.
|
||||||
semnificație clară (verde = acțiune pozitivă/transmite, roșu = oprire/pericol, albastru =
|
|
||||||
navigare/deschidere link extern); restul butoanelor rămân stilul implicit din `_baza.vcx`.
|
|
||||||
|
|
||||||
## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT)
|
## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT)
|
||||||
|
|
||||||
@@ -51,9 +40,9 @@ butoane grupate la margini, fără elemente lipite unele de altele.
|
|||||||
|
|
||||||
## Vocabular
|
## Vocabular
|
||||||
|
|
||||||
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, aer aerisit,
|
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, modern —
|
||||||
modern — asta e reperul calitativ pentru orice formular nou sau refacere de layout, dincolo de
|
asta e reperul calitativ pentru orice formular nou sau refacere de layout, pe orice
|
||||||
regulile mecanice de mai sus, pe orice aplicație ROA*.
|
aplicație ROA*.
|
||||||
|
|
||||||
## Vezi și
|
## Vezi și
|
||||||
|
|
||||||
|
|||||||
@@ -26,22 +26,20 @@ $p = Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -
|
|||||||
$p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
|
$p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
|
||||||
```
|
```
|
||||||
- `-A` ignora config.fpw implicit, `-T` sare peste splash; **ambele obligatorii** - fara `-T`
|
- `-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).
|
procesul ramane pe ecranul de intampinare (simptom identic cu o eroare de compilare). `-c<cale>`
|
||||||
Un `-c<cale>` explicit (lipit de flag) e preluat chiar si impreuna cu `-A`.
|
explicit (lipit de flag) e preluat si cu `-A`.
|
||||||
- **SAFETY**: sub `-A` porneste ON, deci primul `STRTOFILE` peste un log existent (sau
|
- **SAFETY**: sub `-A` porneste ON - primul `STRTOFILE` peste un log existent (sau `COMPILE` peste
|
||||||
`COMPILE` peste un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul
|
un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul pare agatat. Pune
|
||||||
pare agatat. Pune `SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF` +
|
`SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF`+`RESOURCE=OFF` intr-un config.fpw
|
||||||
`RESOURCE=OFF` intr-un config.fpw propriu pasat cu `-c`. Verificare: logheaza
|
propriu pasat cu `-c`. Verificare: logheaza `SET("SAFETY")`/`SET("RESOURCE")` la start.
|
||||||
`SET("SAFETY")`/`SET("RESOURCE")` la start.
|
|
||||||
- In script: logare cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
|
- In script: logare cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
|
||||||
`ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza si
|
`ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza si
|
||||||
continua (mimeaza ErrorHandler); `QUIT` obligatoriu la final.
|
continua (mimeaza ErrorHandler); `QUIT` obligatoriu la final.
|
||||||
- `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata +
|
- `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata +
|
||||||
linia `PROCEDURE`.
|
linia `PROCEDURE`.
|
||||||
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi
|
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi dupa
|
||||||
daca ai editat scriptul intre rulari. Daca nu-l stergi, VFP ruleaza codul vechi din `.fxp`
|
editarea scriptului - altfel VFP ruleaza codul vechi din `.fxp` fara niciun semn (testul poate
|
||||||
fara niciun semn - testul poate trece si raportul poate parea valid, desi modificarea nu a
|
trece fals; se prinde doar cand lipseste din log o linie scrisa doar de codul nou).
|
||||||
fost executata; se prinde doar dupa ce lipseste din log o linie pe care o scrie doar codul nou.
|
|
||||||
- Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau
|
- Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau
|
||||||
seteaza `WindowType = 0`.
|
seteaza `WindowType = 0`.
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ Cel mai ieftin test dupa o modificare: `COMPILE` headless, fara aplicatie si far
|
|||||||
|
|
||||||
## 5. Bisectia versiunilor de clase (regresii)
|
## 5. Bisectia versiunilor de clase (regresii)
|
||||||
|
|
||||||
Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
Cand un bug apare "de azi", compara cu clasa veche fara sa atingi SVN:
|
||||||
1. `git show <rev>:clase\fisier.vcx > temp\fisier.vcx` (+ `.vct`); pentru diff lizibil,
|
1. `git show <rev>:clase\fisier.vcx > temp\fisier.vcx` (+ `.vct`); pentru diff lizibil,
|
||||||
`vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt`.
|
`vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt`.
|
||||||
2. In harness incarca DOAR copia (`SET CLASSLIB TO temp\fisier.vcx`), **nu ADDITIVE peste cea
|
2. In harness incarca DOAR copia (`SET CLASSLIB TO temp\fisier.vcx`), **nu ADDITIVE peste cea
|
||||||
@@ -89,8 +87,8 @@ Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
|||||||
pe copie crapa; recreeaza indexul dupa copiere. Acelasi lucru pentru cursorii creati intr-un
|
pe copie crapa; recreeaza indexul dupa copiere. Acelasi lucru pentru cursorii creati intr-un
|
||||||
test: trebuie sa aiba EXACT indecsii pe care ii creeaza fluxul real inainte de instantiere,
|
test: trebuie sa aiba EXACT indecsii pe care ii creeaza fluxul real inainte de instantiere,
|
||||||
altfel ordinea/logica difera si testul da rezultat fals.
|
altfel ordinea/logica difera si testul da rezultat fals.
|
||||||
- **Un grid isi pierde TOATE coloanele** (`ColumnCount` devine 0, fara eroare in log) daca un
|
- **Un grid isi pierde TOATE coloanele** (`ColumnCount` devine 0, fara eroare in log) daca
|
||||||
ControlSource crapa la re-evaluare in timp ce coloanele sunt atinse programatic (ex. font per
|
ControlSource crapa la re-evaluare cat timp coloanele sunt atinse programatic (ex. font per
|
||||||
coloana la Init). Simptome in aval: `attachtogrid` copiaza 0 coloane, apoi `calctotal` da
|
coloana la Init). Simptome in aval: `attachtogrid` copiaza 0 coloane, apoi `calctotal` da
|
||||||
"Property <cColWithLabel> is not found". Similar, un cursor legat la grid recreat de Init
|
"Property <cColWithLabel> is not found". Similar, un cursor legat la grid recreat de Init
|
||||||
lasa grid-ul fara coloane (eroare 1925).
|
lasa grid-ul fara coloane (eroare 1925).
|
||||||
@@ -100,25 +98,24 @@ Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
|||||||
- **Coloana de grid cu ControlSource EXPRESIE (nu camp) cere `Bound = .F.`** Fara el: eroare 9
|
- **Coloana de grid cu ControlSource EXPRESIE (nu camp) cere `Bound = .F.`** Fara el: eroare 9
|
||||||
"Data type mismatch" la `CREATEOBJECT`-ul formei (faza de constructie, raportata la linia
|
"Data type mismatch" la `CREATEOBJECT`-ul formei (faza de constructie, raportata la linia
|
||||||
apelanta, Details gol).
|
apelanta, Details gol).
|
||||||
- **Erorile de instantiere sunt raportate la linia `CREATEOBJECT`, nu la `.Init`**: daca
|
- **Erorile de instantiere se raporteaza la linia `CREATEOBJECT`, nu la `.Init`**: daca
|
||||||
`Procedure` = scriptul apelant, eroarea vine din evaluarea definitiei clasei (`ADD OBJECT ...
|
`Procedure` = scriptul apelant, eroarea vine din evaluarea definitiei clasei (`ADD OBJECT ...
|
||||||
WITH RowSource`, ControlSource-expresie), pentru ca bind-ul controalelor native se rezolva la
|
WITH RowSource`, ControlSource-expresie) - bind-ul controalelor native se rezolva la
|
||||||
CONSTRUCTIE, inainte de `Init`.
|
CONSTRUCTIE, inainte de `Init`.
|
||||||
- **Literal string > 255 caractere = eroare de COMPILARE, nu de runtime** (masurat 24.07.2026:
|
- **Literal string > 255 caractere = eroare de COMPILARE, nu runtime** (255 trece, 256 pica).
|
||||||
255 trece, 256 pica). Mesaj: `Unrecognized command verb` daca linia incepe cu un apel de
|
Mesaj: `Unrecognized command verb` daca linia incepe cu un apel de metoda,
|
||||||
metoda, `Command contains unrecognized phrase/keyword` la o atribuire. Insidios: restul
|
`Command contains unrecognized phrase/keyword` la o atribuire. Insidios: restul programului
|
||||||
programului ruleaza, doar linia aceea lipseste din `.fxp` si da eroare 16 cand se ajunge la
|
ruleaza, doar linia lipseste din `.fxp` si da eroare 16 cand se ajunge la ea. De aceea SQL-ul
|
||||||
ea. De aceea SQL-ul lung se scrie cu `TEXT TO <var> [TEXTMERGE] NOSHOW ... ENDTEXT` sau
|
lung se scrie cu `TEXT TO <var> [TEXTMERGE] NOSHOW ... ENDTEXT` sau concatenat. Verificare:
|
||||||
concatenat. Verificare: `awk 'length($0) > 260 {print NR": "length($0)}' fisier.prg`.
|
`awk 'length($0) > 260 {print NR": "length($0)}' fisier.prg`.
|
||||||
- **Linie de COD (nu doar literal string) prea lunga intr-o metoda de clasa `.vc2` poate
|
- **Linie de COD (nu doar literal string) prea lunga intr-o metoda de clasa `.vc2` poate arunca
|
||||||
arunca eroarea 11 ("Function argument value, type, or count is invalid") pe PRIMA
|
eroarea 11 ("Function argument value, type, or count is invalid") pe PRIMA instructiune a
|
||||||
instructiune a metodei, nu pe linia vinovata** - simptom complet derutant. Se exclude prin
|
metodei, nu pe linia vinovata** - simptom derutant. Se exclude prin diagnostic: aceeasi
|
||||||
diagnostic: aceeasi expresie merge normal la nivel de program, in alta clasa, intr-o
|
expresie merge normal la nivel de program, in alta clasa, intr-o subclasa cu metoda noua, si
|
||||||
subclasa cu metoda noua, si pe instanta virgina - deci nu tine de tipul datelor, de context
|
pe instanta virgina - deci nu tine de tipul datelor, de context sau de clasa parinte. Reper
|
||||||
sau de clasa parinte. Reper practic: linii preexistente >200 caractere intr-o clasa mare
|
practic: linii preexistente >200 caractere intr-o clasa mare functioneaza pana la ~250; pragul
|
||||||
functioneaza pana la ~250; pragul real e in jur de 255, ca la literalii de string. Remediu:
|
real e in jur de 255, ca la literalii de string. Remediu: sparge expresia in pasi cu variabile
|
||||||
sparge expresia in pasi cu variabile locale. Verificare (comparat intre fisierul curent si
|
locale. Verificare (comparat intre fisierul curent si un backup anterior):
|
||||||
un backup anterior):
|
|
||||||
```powershell
|
```powershell
|
||||||
$l=[IO.File]::ReadAllLines($p,[Text.Encoding]::GetEncoding(28591))
|
$l=[IO.File]::ReadAllLines($p,[Text.Encoding]::GetEncoding(28591))
|
||||||
for($i=0;$i -lt $l.Length;$i++){ if($l[$i].Length -gt 200){ "{0}: len={1}" -f ($i+1), $l[$i].Length } }
|
for($i=0;$i -lt $l.Length;$i++){ if($l[$i].Length -gt 200){ "{0}: len={1}" -f ($i+1), $l[$i].Length } }
|
||||||
@@ -126,27 +123,31 @@ Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
|||||||
- **Un UDF care citeste campul curent (`Nvl(camp,0)=1` sau similar) nu e de incredere intr-o
|
- **Un UDF care citeste campul curent (`Nvl(camp,0)=1` sau similar) nu e de incredere intr-o
|
||||||
clauza de filtrare** (`SELECT ... WHERE`, `LOCATE FOR`, `SCAN FOR`, `DELETE FOR`) - pointerul
|
clauza de filtrare** (`SELECT ... WHERE`, `LOCATE FOR`, `SCAN FOR`, `DELETE FOR`) - pointerul
|
||||||
nu e garantat pe randul evaluat la fiecare apel, deci filtrul devine practic o valoare
|
nu e garantat pe randul evaluat la fiecare apel, deci filtrul devine practic o valoare
|
||||||
constanta (fie nu se declanseaza niciodata, fie loveste tot). Simptome vazute: o comasare de
|
constanta (nu se declanseaza deloc, sau loveste tot). Simptome vazute: comasare de randuri
|
||||||
randuri care nu se mai producea deloc; un test agatat. Remediu: in clauze de filtrare
|
care nu se mai producea deloc; test agatat. Remediu: in clauze de filtrare foloseste expresia
|
||||||
foloseste expresia INLINE pe camp (`Nvl(camp,0) <> 1`); pastreaza helper-ul doar in cod
|
INLINE pe camp (`Nvl(camp,0) <> 1`); pastreaza helper-ul doar in cod procedural (`If`,
|
||||||
procedural (`If`, `Replace` pe randul curent), unde pointerul e garantat pozitionat.
|
`Replace` pe randul curent), unde pointerul e garantat pozitionat.
|
||||||
|
|
||||||
|
- **`SET PROCEDURE TO x.prg`**: in `.exe` se rezolva din modulele compilate (orice `.prg` din
|
||||||
|
`.pjx`), din IDE doar prin `SET PATH`. O cale lipsa din `SET PATH` se vede deci doar necompilat,
|
||||||
|
iar in `Try` trece tacut.
|
||||||
|
|
||||||
## 7. Capcane la SCRIEREA scriptului de test
|
## 7. Capcane la SCRIEREA scriptului de test
|
||||||
|
|
||||||
- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`** (plus
|
- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`** (plus
|
||||||
`SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascrierea fisierului de
|
`SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascriere, iar headless
|
||||||
log, iar headless dialogul blocheaza procesul pana la timeout. Suitele existente il au deja -
|
dialogul blocheaza procesul pana la timeout. Suitele existente il au deja - capcana apare la
|
||||||
capcana apare la scripturile ad-hoc, scrise repede pentru o masuratoare.
|
scripturile ad-hoc, scrise repede pentru o masuratoare.
|
||||||
- **`DEFINE CLASS ... ENDDEFINE` nu poate sta la mijlocul programului principal.** Toate liniile
|
- **`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
|
de DUPA `ENDDEFINE` dau "Statement is not in a procedure" (vezi `<script>.ERR`); scriptul se
|
||||||
ruleaza doar pana acolo si se opreste silentios, fara sa ajunga la `QUIT` - simptom: vfp9.exe
|
opreste silentios, fara sa ajunga la `QUIT` - simptom: vfp9.exe pare agatat la nesfarsit. Pune
|
||||||
pare agatat la nesfarsit. Pune orice `DEFINE CLASS` auxiliar la FINALUL fisierului.
|
orice `DEFINE CLASS` auxiliar la FINALUL fisierului.
|
||||||
- **Dummy-uri cu metode**: `CREATEOBJECT('Custom')` + `AddProperty()` adauga doar PROPRIETATI.
|
- **Dummy-uri cu metode**: `CREATEOBJECT('Custom')` + `AddProperty()` adauga doar PROPRIETATI.
|
||||||
Daca clasa testata apeleaza `goExecutor.oExecute(...)`, dummy-ul trebuie sa fie
|
Daca clasa testata apeleaza `goExecutor.oExecute(...)`, dummy-ul trebuie sa fie
|
||||||
`DEFINE CLASS dummyexecutor AS Custom` cu `PROCEDURE oExecute` reala.
|
`DEFINE CLASS dummyexecutor AS Custom` cu `PROCEDURE oExecute` reala.
|
||||||
- **Diagnostic "script agatat"**, in ordine: (1) exista `<script>.ERR` langa `.prg`? => s-a
|
- **Diagnostic "script agatat"**, in ordine: (1) exista `<script>.ERR` langa `.prg`? => s-a
|
||||||
oprit la compilare; (2) CPU-ul procesului ~0 dupa cateva secunde (`Get-Process | select CPU`)
|
oprit la compilare; (2) CPU-ul procesului ~0 dupa cateva secunde (`Get-Process | select CPU`)
|
||||||
=> asteapta un dialog modal, nu proceseaza; confirma enumerand ferestrele procesului cu
|
=> asteapta un dialog modal; confirma enumerand ferestrele procesului cu
|
||||||
`EnumWindows`/`GetWindowText`/`GetWindowThreadProcessId` (`Add-Type`, user32) filtrat pe PID -
|
`EnumWindows`/`GetWindowText`/`GetWindowThreadProcessId` (`Add-Type`, user32) filtrat pe PID -
|
||||||
daca vezi doar fereastra principala + "Command", nu e dialog, cauta alta cauza (tipic `-T`
|
daca vezi doar fereastra principala + "Command", nu e dialog, cauta alta cauza (tipic `-T`
|
||||||
lipsa). Confirma mereu cauza inainte de a schimba scriptul.
|
lipsa). Confirma mereu cauza inainte de a schimba scriptul.
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
|||||||
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
|
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
|
||||||
- Salvarea din VFP IDE peste un binar scris de txt2vcx poate PIERDE si definitii `*m:` deja
|
- 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`,
|
existente, desi corpurile PROCEDURE raman (patit pe ROAGEST: `import_adauga_factura.recalc_tva`,
|
||||||
`import_nota.do_adauga/do_copie/do_reface`, 07.2026); simptom: crash la Createobject cu
|
`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
|
"Data type mismatch" raportat la linia apelanta. Dupa orice sesiune IDE pe clasa: refresh
|
||||||
cache + compara lista `*m:` cu starea de dinainte.
|
cache + compara lista `*m:` cu starea de dinainte.
|
||||||
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
|
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
|
||||||
|
|||||||
@@ -5,55 +5,36 @@ git primește de la SVN, niciodată invers.
|
|||||||
|
|
||||||
## Reguli
|
## Reguli
|
||||||
|
|
||||||
1. **Munca reală se comite DOAR în SVN.** Nu face `git commit` cu o modificare nouă care n-a trecut prin SVN.
|
1. **Munca reală se comite DOAR în SVN.** Nu face `git commit` cu o modificare noua care n-a
|
||||||
|
trecut prin SVN.
|
||||||
2. **git se împrospătează DIN svn**, într-o singură direcție.
|
2. **git se împrospătează DIN svn**, într-o singură direcție.
|
||||||
3. **COMUN se publică pe git dintr-UN SINGUR folder** (publisher, ex. `ROAAUTO\COMUN`). Celelalte doar se aliniază la origin.
|
3. **COMUN se publică pe git dintr-UN SINGUR folder** (publisher, ex. `ROAAUTO\COMUN`). Celelalte
|
||||||
|
doar se aliniază la origin.
|
||||||
|
|
||||||
## Lucrat în paralel în 2 proiecte (ex. roagest + roaauto), fișiere diferite
|
## Lucrat în paralel în 2 proiecte (ex. roagest + roaauto), fișiere diferite
|
||||||
|
|
||||||
### 1. Împaci în SVN
|
1. **Împaci în SVN**: `svn commit` in ROAGEST\COMUN -> `svn update` in ROAAUTO\COMUN (aduce
|
||||||
```
|
fisierele din roagest, fara conflict pe fisiere diferite) -> `svn commit` acolo -> `svn update`
|
||||||
# ROAGEST\COMUN
|
inapoi in ROAGEST\COMUN. Acum ambele copii SVN au tot — e sursa de adevăr.
|
||||||
svn commit -m "modificari roagest"
|
2. **Oglindești în git, doar din folderul publisher**: `git add -A` + `git commit` + `git push`
|
||||||
# ROAAUTO\COMUN
|
in ROAAUTO\COMUN.
|
||||||
svn update # aduce fisierele din roagest (alte fisiere -> fara conflict)
|
3. **Celălalt folder: aliniere, NU commit** — in ROAGEST\COMUN: `git fetch origin` +
|
||||||
svn commit -m "modificari roaauto"
|
`git reset --hard origin/main`. Sigur: fișierele sunt deja identice cu origin (le-a făcut svn),
|
||||||
# ROAGEST\COMUN
|
`reset` doar mută pointerul.
|
||||||
svn update # aduce fisierele din roaauto
|
|
||||||
```
|
|
||||||
Acum ambele copii SVN au tot. E sursa de adevăr.
|
|
||||||
|
|
||||||
### 2. Oglindești în git (doar din folderul publisher)
|
Când te muți dintr-un proiect în altul: `svn update` in proiectul unde intri, apoi
|
||||||
```
|
`git reset --hard origin/main` in COMUN, ca git-ul sa fie curat.
|
||||||
cd ROAAUTO\COMUN
|
|
||||||
git add -A
|
|
||||||
git commit -m "sync svn"
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Celălalt folder: aliniere, NU commit
|
|
||||||
```
|
|
||||||
cd ROAGEST\COMUN
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
```
|
|
||||||
Sigur: fișierele sunt deja identice cu origin (le-a făcut svn), `reset` doar mută pointerul.
|
|
||||||
|
|
||||||
## Când te muți dintr-un proiect în altul
|
|
||||||
```
|
|
||||||
svn update # in proiectul unde intri
|
|
||||||
git reset --hard origin/main # in COMUN, ca git-ul sa fie curat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Regula care rezumă tot
|
## Regula care rezumă tot
|
||||||
|
|
||||||
> Un singur folder publică în git (commit+push). Celelalte doar `git reset --hard origin/main`.
|
> Un singur folder publică în git (commit+push). Celelalte doar `git reset --hard origin/main`.
|
||||||
> Munca circulă prin SVN; git fotografiază rezultatul.
|
> Munca circulă prin SVN; git fotografiază rezultatul.
|
||||||
|
|
||||||
## Model de branching (git urmareste text .??2)
|
## Model de branching (git urmareste text .??2)
|
||||||
|
|
||||||
git urmareste versiunile text FoxBin2Prg (.vc2/.sc2/…), improspatate in-arbore cu
|
git urmareste versiunile text FoxBin2Prg (.vc2/.sc2/…), improspatate in-arbore cu `git_sync.ps1`
|
||||||
`git_sync.ps1` la inceput de sesiune si inainte de orice commit; nu comite cat timp
|
la inceput de sesiune si inainte de orice commit; nu comite cat timp `git_sync` raporteaza esecuri
|
||||||
`git_sync` raporteaza esecuri (exit nenul). Doua benzi:
|
(exit nenul). Doua benzi:
|
||||||
|
|
||||||
- **`main` = oglinda SVN**: primeste DOAR commit-uri `sync SVN rN`, facute din stare curata
|
- **`main` = oglinda SVN**: primeste DOAR commit-uri `sync SVN rN`, facute din stare curata
|
||||||
(imediat dupa `svn update`, inainte de lucru local).
|
(imediat dupa `svn update`, inainte de lucru local).
|
||||||
|
|||||||
@@ -1,48 +1,46 @@
|
|||||||
# Inrolarea unui proiect ROA (Visual FoxPro) in fluxul git-text FoxBin2Prg
|
# Inrolarea unui proiect ROA (Visual FoxPro) in fluxul git-text FoxBin2Prg
|
||||||
|
|
||||||
Instructiuni pas cu pas pentru o sesiune Claude Code care inroleaza un proiect ROA
|
Pasi pentru o sesiune Claude Code care inroleaza un proiect ROA in fluxul in care git urmareste
|
||||||
in fluxul in care git urmareste DOAR versiunile text FoxBin2Prg (.vc2/.sc2/.fr2/.mn2/
|
DOAR versiunile text FoxBin2Prg (.vc2/.sc2/.fr2/.mn2/.lb2/.pj2/.dc2/.db2) generate in arbore,
|
||||||
.lb2/.pj2/.dc2/.db2) generate in arbore, langa binarele VFP. SVN ramane sursa de
|
langa binarele VFP. SVN ramane sursa de adevar si nu se atinge (niciun svn commit fara acordul
|
||||||
adevar si nu se atinge (niciun svn commit fara acordul explicit al utilizatorului).
|
explicit al utilizatorului).
|
||||||
|
|
||||||
Proiecte deja inrolate (16.07.2026): ROACONT, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO,
|
Proiecte deja inrolate: ROACONT, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO, ROAFACTURARE + COMUN
|
||||||
ROAFACTURARE + COMUN (romfast/comun.git). Modelul de referinta este ROACONT.
|
(romfast/comun.git). Modelul de referinta e ROACONT.
|
||||||
|
|
||||||
## Reguli pentru sesiunea care executa
|
## Reguli pentru sesiunea care executa
|
||||||
|
|
||||||
- Foloseste EXCLUSIV PowerShell pentru comenzi (NU tool-ul Bash — bash.exe crapa pe
|
- Foloseste EXCLUSIV PowerShell (NU Bash — bash.exe crapa pe aceste masini si lasa stackdump-uri).
|
||||||
aceste masini si lasa stackdump-uri).
|
- NU face niciun `svn commit`. NU modifica binarele VFP. La final binarele trebuie sa fie
|
||||||
- NU face niciun `svn commit`. NU modifica binarele VFP. La final binarele trebuie sa
|
byte-identice (`svn status`: niciun binar M).
|
||||||
fie byte-identice (verificabil cu `svn status`: niciun binar M).
|
- Rularile de conversie dureaza zeci de minute pe proiecte mari: sunt incrementale, daca expira
|
||||||
- Rularile de conversie dureaza zeci de minute pe proiecte mari: sunt incrementale,
|
timeout-ul tool-ului se reiau pana la capat.
|
||||||
daca expira timeout-ul tool-ului se reiau pana la capat.
|
|
||||||
- Nu rula doua conversii git_sync in paralel pe acelasi arbore.
|
- Nu rula doua conversii git_sync in paralel pe acelasi arbore.
|
||||||
|
|
||||||
## Preconditii
|
## Preconditii
|
||||||
|
|
||||||
1. Tooling-ul partajat exista in `D:\ROA\UTIL\foxbin2prg\`: `git_sync.ps1`,
|
1. Tooling partajat in `D:\ROA\UTIL\foxbin2prg\`: `git_sync.ps1`, `vfp_filemap.ps1`,
|
||||||
`vfp_filemap.ps1`, `txt2vcx.ps1`, `test_git_sync.ps1`,
|
`txt2vcx.ps1`, `test_git_sync.ps1`, `test_roundtrip.ps1`. Citeste-le inainte (macar help-ul
|
||||||
`test_roundtrip.ps1`. Citeste-le inainte (macar help-ul din git_sync.ps1).
|
din git_sync.ps1). `roa_sync.ps1` (+ `test_roa_sync.ps1`) traieste in `COMUN\scripts\` si
|
||||||
`roa_sync.ps1` (+ `test_roa_sync.ps1`) traieste in `COMUN\scripts\` si vine
|
vine singur cu svn update; in foxbin2prg a ramas doar un stub de compatibilitate.
|
||||||
singur cu svn update; in foxbin2prg a ramas doar un stub de compatibilitate.
|
2. Proiectul e working copy SVN valid (`svn info D:\ROA\<PROIECT>`), cu `COMUN\` inauntru
|
||||||
2. Proiectul e working copy SVN valid (`svn info D:\ROA\<PROIECT>`), cu `COMUN\`
|
(external SVN).
|
||||||
inauntru (external SVN).
|
3. Repo-ul gitea exista: `git ls-remote git@gitea.romfast.ro:romfast/<proiect>.git`. Daca nu
|
||||||
3. Repo-ul gitea exista: `git ls-remote git@gitea.romfast.ro:romfast/<proiect>.git`.
|
exista, cere utilizatorului sa-l creeze din interfata gitea (NU crea repo-uri prin API din
|
||||||
Daca nu exista, cere utilizatorului sa-l creeze din interfata gitea (NU crea
|
proprie initiativa).
|
||||||
repo-uri prin API din proprie initiativa).
|
4. SVN global-ignores pe masina contine `*.vc2 *.sc2 *.fr2 *.mn2 *.lb2 *.pj2 *.dc2 *.db2
|
||||||
4. SVN global-ignores pe masina contine `*.vc2 *.sc2 *.fr2 *.mn2 *.lb2 *.pj2 *.dc2
|
*.dbf.cfg` (in `%APPDATA%\Subversion\config`, sectiunea [miscellany]). Fara asta, textele apar
|
||||||
*.db2 *.dbf.cfg` (in `%APPDATA%\Subversion\config`, sectiunea [miscellany]).
|
ca `?` in svn status si risca svn add accidental.
|
||||||
Fara asta, textele apar ca `?` in svn status si risca svn add accidental.
|
5. Daca proiectul ARE deja git cu istoric si urmeaza reset: confirmarea utilizatorului ca nu
|
||||||
5. Daca proiectul ARE deja git cu istoric si urmeaza reset: confirmarea utilizatorului
|
exista clone active pe alte masini (force-push rescrie istoria).
|
||||||
ca nu exista clone active pe alte masini (force-push rescrie istoria).
|
|
||||||
|
|
||||||
## Pasi
|
## Pasi
|
||||||
|
|
||||||
### 1. Inventar prealabil (inainte de orice stergere)
|
### 1. Inventar prealabil (inainte de orice stergere)
|
||||||
|
|
||||||
- Exista `.git`? Noteaza `git remote -v` si branch-ul. Exista `COMUN\.git`?
|
- Exista `.git`? Noteaza `git remote -v` si branch-ul. Exista `COMUN\.git`?
|
||||||
- `git ls-files *.dbf` (daca exista repo vechi): tabelele urmarite azi ca binare sunt
|
- `git ls-files *.dbf` (daca exista repo vechi): tabelele urmarite azi ca binare sunt candidate
|
||||||
candidate la conversie .db2 (cerinta: tot ce e convertibil trece pe text).
|
la conversie .db2 (cerinta: tot ce e convertibil trece pe text).
|
||||||
|
|
||||||
### 2. Conversia completa
|
### 2. Conversia completa
|
||||||
|
|
||||||
@@ -50,25 +48,25 @@ ROAFACTURARE + COMUN (romfast/comun.git). Modelul de referinta este ROACONT.
|
|||||||
& D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot D:\ROA\<PROIECT>
|
& D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot D:\ROA\<PROIECT>
|
||||||
```
|
```
|
||||||
|
|
||||||
- DbfList implicit acopera `Locale\locale*.dbf`, `Help\*.dbf`, `DATE\Optiuni_*.dbf`
|
- DbfList implicit acopera `Locale\locale*.dbf`, `Help\*.dbf`, `DATE\Optiuni_*.dbf` si toate
|
||||||
si toate dbf-urile COMUN. Tabele de configurare specifice proiectului se adauga cu
|
dbf-urile COMUN. Tabele de configurare specifice proiectului se adauga cu `-DbfList` explicit
|
||||||
`-DbfList` explicit (ATENTIE: parametrii array NU se pot pasa prin
|
(ATENTIE: parametrii array NU se pot pasa prin `powershell -File` — invoca scriptul in-process
|
||||||
`powershell -File` — invoca scriptul in-process cu `&`, altfel array-ul se
|
cu `&`, altfel array-ul se colapseaza). Tabele operationale mari nu se adauga; un .db2 peste
|
||||||
colapseaza). Tabele operationale mari nu se adauga; un .db2 peste 5 MB ramane binar.
|
5 MB ramane binar.
|
||||||
- Esecuri de conversie — se investigheaza fiecare:
|
- Esecuri de conversie — se investigheaza fiecare:
|
||||||
- meniuri pre-VFP9 ("NOT in VFP 9 Format"): raman binare, cu exceptii negate `!` in
|
- meniuri pre-VFP9 ("NOT in VFP 9 Format"): raman binare, cu exceptii negate `!` in
|
||||||
.gitignore; intra in flux doar dupa re-salvare in VFP9 (MODIFY MENU -> save);
|
.gitignore; intra in flux doar dupa re-salvare in VFP9 (MODIFY MENU -> save);
|
||||||
- clase FFC/third-party cu roundtrip fals-negativ (#INCLUDE lipsa in staging izolat,
|
- clase FFC/third-party cu roundtrip fals-negativ (#INCLUDE lipsa in staging izolat, ex. cele
|
||||||
ex. cele 6 din COMUN deja scutite implicit): se adauga la `-RoundtripExempt`;
|
6 din COMUN deja scutite implicit): se adauga la `-RoundtripExempt`;
|
||||||
- alte esecuri reale: fisierul ramane binar urmarit (exceptie `!`) si se raporteaza.
|
- alte esecuri reale: fisierul ramane binar urmarit (exceptie `!`) si se raporteaza.
|
||||||
- Regula: nu se trece mai departe cu esecuri neexplicate (exit code nenul).
|
- Regula: nu se trece mai departe cu esecuri neexplicate (exit code nenul).
|
||||||
|
|
||||||
### 3. .gitignore si .gitattributes
|
### 3. .gitignore si .gitattributes
|
||||||
|
|
||||||
- Copiaza `D:\ROA\ROACONT\.gitignore` ca model si adapteaza: sectiunea machine-local
|
- Copiaza `D:\ROA\ROACONT\.gitignore` ca model si adapteaza: sectiunea machine-local (exe-ul
|
||||||
(exe-ul proiectului, <proiect>_ref.DBF/FPT/CDX, FOXUSER, .ini/.ARM, log-uri) si
|
proiectului, <proiect>_ref.DBF/FPT/CDX, FOXUSER, .ini/.ARM, log-uri) si sectiunea dbf: fiecare
|
||||||
sectiunea dbf: fiecare .dbf care are .db2 se ignora INDIVIDUAL (plus .fpt-ul lui).
|
.dbf care are .db2 se ignora INDIVIDUAL (plus .fpt-ul lui). NU ignora: `*.??2`, `*.dbf.cfg`,
|
||||||
NU ignora: `*.??2`, `*.dbf.cfg`, grafica (bmp/ico/jpg/png), ocx, tmpl.
|
grafica (bmp/ico/jpg/png), ocx, tmpl.
|
||||||
- `.gitattributes` cu `* -text` (SVN ramane autoritatea EOL; git nu normalizeaza).
|
- `.gitattributes` cu `* -text` (SVN ramane autoritatea EOL; git nu normalizeaza).
|
||||||
|
|
||||||
### 4. Init/reset repo proiect
|
### 4. Init/reset repo proiect
|
||||||
@@ -81,13 +79,12 @@ git -C D:\ROA\<PROIECT> add -A
|
|||||||
```
|
```
|
||||||
|
|
||||||
VERIFICARE OBLIGATORIE inainte de commit (`git ls-files` pe staged):
|
VERIFICARE OBLIGATORIE inainte de commit (`git ls-files` pe staged):
|
||||||
- 0 binare convertibile urmarite (vcx/vct/scx/sct/frx/frt/mnx/mnt/lbx/lbt/pjx/pjt/
|
- 0 binare convertibile urmarite (vcx/vct/scx/sct/frx/frt/mnx/mnt/lbx/lbt/pjx/pjt/dbc/dct/cdx/dcx),
|
||||||
dbc/dct/cdx/dcx), cu exceptia celor cu `!` justificate;
|
cu exceptia celor cu `!` justificate;
|
||||||
- textele .??2 prezente; 0 fisiere din COMUN/ (are repo-ul lui).
|
- textele .??2 prezente; 0 fisiere din COMUN/ (are repo-ul lui).
|
||||||
|
|
||||||
Commit: `Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP
|
Commit: `Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP git-ignored)`
|
||||||
git-ignored)` + linia Co-Authored-By a sesiunii. Push: `git push -u origin main`
|
+ linia Co-Authored-By a sesiunii. Push: `git push -u origin main` (`--force` doar la reset).
|
||||||
(`--force` doar la reset).
|
|
||||||
|
|
||||||
### 5. Clona COMUN a proiectului
|
### 5. Clona COMUN a proiectului
|
||||||
|
|
||||||
@@ -100,35 +97,34 @@ git -C D:\ROA\<PROIECT>\COMUN reset origin/main # mixed: pastreaza disc
|
|||||||
git -C D:\ROA\<PROIECT>\COMUN checkout origin/main -- .gitignore
|
git -C D:\ROA\<PROIECT>\COMUN checkout origin/main -- .gitignore
|
||||||
```
|
```
|
||||||
|
|
||||||
Diferentele ramase in `git status` = revizii SVN diferite ale clonei (normal).
|
Diferentele ramase in `git status` = revizii SVN diferite ale clonei (normal). NU comite nimic in
|
||||||
NU comite nimic in comun.git dintr-o clona decalata — comun se comite doar din clona
|
comun.git dintr-o clona decalata — comun se comite doar din clona in care s-a lucrat efectiv,
|
||||||
in care s-a lucrat efectiv, dupa svn update.
|
dupa svn update.
|
||||||
|
|
||||||
### 6. roa_sync.bat
|
### 6. roa_sync.bat
|
||||||
|
|
||||||
Copiaza `D:\ROA\ROAFACTURARE\roa_sync.bat` in radacina proiectului (e generic,
|
Copiaza `D:\ROA\ROAFACTURARE\roa_sync.bat` in radacina proiectului (generic, foloseste `%~dp0` si
|
||||||
foloseste `%~dp0` si cheama `COMUN\scripts\roa_sync.ps1`) si include-l in commit.
|
cheama `COMUN\scripts\roa_sync.ps1`) si include-l in commit. Utilizatorul il ruleaza la inceput de
|
||||||
Utilizatorul il ruleaza la inceput de sesiune: svn update -> git_sync -> commit
|
sesiune: svn update -> git_sync -> commit "sync SVN rN" pe main (proiect + COMUN) -> reconciliere
|
||||||
"sync SVN rN" pe main (proiect + COMUN) -> reconciliere cu origin + push (doar
|
cu origin + push (doar commit-uri de sync) -> inchide branch-urile claude/* cu diff gol.
|
||||||
commit-uri de sync) -> inchide branch-urile claude/* cu diff gol.
|
|
||||||
|
|
||||||
### 7. Verificari finale
|
### 7. Verificari finale
|
||||||
|
|
||||||
- Acoperire: fiecare binar convertibil din arbore (inclusiv COMUN) are text .??2
|
- Acoperire: fiecare binar convertibil din arbore (inclusiv COMUN) are text .??2 langa el
|
||||||
langa el (exceptiile `!` enumerate si justificate).
|
(exceptiile `!` enumerate si justificate).
|
||||||
- `svn status`: niciun binar modificat, niciun .??2 adaugat in SVN.
|
- `svn status`: niciun binar modificat, niciun .??2 adaugat in SVN.
|
||||||
- `git ls-remote origin main` = HEAD-ul local.
|
- `git ls-remote origin main` = HEAD-ul local.
|
||||||
- Raport final: numar texte per tip, esecuri/scutiri, commit hash, push status.
|
- Raport final: numar texte per tip, esecuri/scutiri, commit hash, push status.
|
||||||
|
|
||||||
## Note operationale
|
## Note operationale
|
||||||
|
|
||||||
- Dialogurile modale FoxBin2Prg sunt suprimate de scripturi printr-un `foxbin2prg.cfg`
|
- Dialogurile modale FoxBin2Prg sunt suprimate de scripturi printr-un `foxbin2prg.cfg` cu
|
||||||
cu `DontShowErrors: 1` scris per-director de staging (cfg-ul global de langa exe NU
|
`DontShowErrors: 1` scris per-director de staging (cfg-ul global de langa exe NU e fiabil).
|
||||||
e fiabil). Daca utilizatorul vede totusi un MessageBox, e un dialog nativ VFP —
|
Daca utilizatorul vede totusi un MessageBox, e un dialog nativ VFP — watchdog-ul din
|
||||||
watchdog-ul din Invoke-FoxBin2PrgSafe il omoara la timeout.
|
Invoke-FoxBin2PrgSafe il omoara la timeout.
|
||||||
- Tabelele legate de un DBC au nevoie de .dbc/.dct/.dcx si .cdx langa ele la conversie
|
- Tabelele legate de un DBC au nevoie de .dbc/.dct/.dcx si .cdx langa ele la conversie
|
||||||
(git_sync face asta automat in staging).
|
(git_sync face asta automat in staging).
|
||||||
- `DBF_Conversion_Support: 4` (scris de git_sync in cfg-ul de staging) exporta DATELE
|
- `DBF_Conversion_Support: 4` (scris de git_sync in cfg-ul de staging) exporta DATELE in .db2, nu
|
||||||
in .db2, nu doar structura.
|
doar structura.
|
||||||
- Fisierele doar-git (docs, .bat, .gitignore) se comit separat, inainte de sync-ul
|
- Fisierele doar-git (docs, .bat, .gitignore) se comit separat, inainte de sync-ul "sync SVN rN",
|
||||||
"sync SVN rN", altfel nimeresc in commit-ul de sincronizare.
|
altfel nimeresc in commit-ul de sincronizare.
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# Inventar COMUN - functii/clase reutilizabile (ROAGEST)
|
# Inventar COMUN - functii/clase reutilizabile (ROAGEST)
|
||||||
|
|
||||||
Scop: referinta rapida pt. plan/code-review, ca sa refoloseasca comunele in loc sa se reinventeze
|
Scop: reutilizare comune la plan/code-review (ex. cursor2lista() in loc de Scan manual pe cursor).
|
||||||
(ex: Scan manual pt. lista dintr-un cursor, cand exista deja cursor2lista()). Generat prin grep pe
|
Generat prin grep pe COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest. Numerele =
|
||||||
COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest (nu presupuneri). Numerele = nr.
|
nr. aparitii grep in proiect (indiciu cat de "canonic" e functia).
|
||||||
aparitii grep in tot proiectul (indiciu de cat de "canonic" e functia).
|
|
||||||
|
|
||||||
## 1. Functii comune - COMUN\programe\oproceduri_comune.prg (clasa Oracle/executor + utilitare)
|
## 1. Functii comune - COMUN\programe\oproceduri_comune.prg (clasa Oracle/executor + utilitare)
|
||||||
|
|
||||||
@@ -90,14 +89,14 @@ aparitii grep in tot proiectul (indiciu de cat de "canonic" e functia).
|
|||||||
| GetUserDocPath | - | folder documente utilizator curent | - |
|
| GetUserDocPath | - | folder documente utilizator curent | - |
|
||||||
| aleg_document_pereche | (vezi ooperatii_comune) | vezi sectiune 2 | - |
|
| aleg_document_pereche | (vezi ooperatii_comune) | vezi sectiune 2 | - |
|
||||||
|
|
||||||
Nota: multe din functiile de mai sus exista **dublat** in `proceduri_comune.prg` (varianta veche,
|
Nota: multe functii de mai sus exista **dublat** in `proceduri_comune.prg` (varianta veche,
|
||||||
non-obiect) - ex. NEW_ID, SAVE_GRID*, XMENU, cursor2lista*, lista2array/cursor, get_mask, Get_Version,
|
non-obiect) - ex. NEW_ID, SAVE_GRID*, XMENU, cursor2lista*, lista2array/cursor, get_mask, Get_Version,
|
||||||
Get_Hexa, format_msg, C_LUNA/cluna, get_trimestru/semestru, GETCALLSTACK, CloneObj/CopyProps,
|
Get_Hexa, format_msg, C_LUNA/cluna, get_trimestru/semestru, GETCALLSTACK, CloneObj/CopyProps,
|
||||||
ceretitlu_rap. La duplicat castiga fisierul adaugat **cel mai recent** cu SET PROCEDURE ADDITIVE -
|
ceretitlu_rap. La duplicat castiga fisierul incarcat **cel mai recent** cu SET PROCEDURE ADDITIVE -
|
||||||
in roagest.prg OPROCEDURI_COMUNE.PRG (linia 238) vine dupa proceduri_comune (linia 218), deci
|
in roagest.prg OPROCEDURI_COMUNE.PRG (linia 238) vine dupa proceduri_comune (linia 218), deci activa
|
||||||
varianta activa e cea din `oproceduri_comune.prg`. Din varianta veche raman folosite doar 2 functii
|
e varianta din `oproceduri_comune.prg`. Unice din varianta veche: `extrage_optiuni(cLista,nId)`
|
||||||
unice: `extrage_optiuni(cLista,nId)` (valoare dintr-o lista "id::val;id::val", 11 uz) si
|
(valoare din lista "id::val;id::val", 11 uz), `myScatter(tcBlank)` (SCATTER generic in obiect, 3 uz);
|
||||||
`myScatter(tcBlank)` (SCATTER generic in obiect, 3 uz); restul functiilor unice de acolo = moarte.
|
restul functiilor unice de acolo = moarte.
|
||||||
|
|
||||||
## 2. Functii comune - COMUN\programe\ooperatii_comune.prg (contabilitate/analitice/balanta)
|
## 2. Functii comune - COMUN\programe\ooperatii_comune.prg (contabilitate/analitice/balanta)
|
||||||
|
|
||||||
@@ -142,12 +141,12 @@ Preview rapoarte: FoxyPreviewer (`gcReportPreviewer = "FoxyPreview"` in roagest.
|
|||||||
| PreviewerConfig (clasa) | SetValue/GetValue | property-bag optiuni FoxyPreviewer (param toPreviewerConfig la export2frx) | - |
|
| PreviewerConfig (clasa) | SetValue/GetValue | property-bag optiuni FoxyPreviewer (param toPreviewerConfig la export2frx) | - |
|
||||||
|
|
||||||
### Export Excel - 3 mecanisme paralele (atentie la confuzii)
|
### Export Excel - 3 mecanisme paralele (atentie la confuzii)
|
||||||
1. `goExport.export2xls/export2xlsx` (mai sus) - preferat pt. cod nou (export2xlsx).
|
1. `goExport.export2xls/export2xlsx` (mai sus) - preferat pt. cod nou.
|
||||||
2. `export_excel` / `export_excel_grid` / `exportare` / `LIST_EXCEL` (proceduri_excel.prg) - OLE
|
2. `export_excel` / `export_excel_grid` / `exportare` / `LIST_EXCEL` (proceduri_excel.prg) - OLE
|
||||||
Automation, scrie celula cu celula, necesita Excel instalat; uz mic (2-12). `get_excel_mask` de
|
Automation celula-cu-celula, cere Excel instalat; uz mic (2-12). `get_excel_mask` acolo =
|
||||||
acolo = conversie masca VFP -> format Excel (nu confunda cu `get_mask` din sect. 1).
|
masca VFP -> format Excel (nu confunda cu `get_mask` din sect. 1).
|
||||||
3. Clasa `excelxml` (excelxml.vcx, COMUN\UTILE\excel) - Excel XML direct din `gridobject`, fara
|
3. Clasa `excelxml` (excelxml.vcx, COMUN\UTILE\excel) - Excel XML direct din `gridobject`, fara
|
||||||
Excel instalat (proprietati: file, sheetname, openaftersaving; metoda `save`); 73 uz.
|
Excel instalat (proprietati file/sheetname/openaftersaving, metoda `save`); 73 uz.
|
||||||
Plus functiile libere `export_xls`/`ExportToXMLExcel` din oproceduri_comune.prg (sect. 1) - cod
|
Plus functiile libere `export_xls`/`ExportToXMLExcel` din oproceduri_comune.prg (sect. 1) - cod
|
||||||
diferit de metoda `goExport.export_xls`, doar nume identic.
|
diferit de metoda `goExport.export_xls`, doar nume identic.
|
||||||
|
|
||||||
@@ -288,28 +287,28 @@ Proprietate cheie comuna: `pcobj` (leaga containerul de camp/proprietate din obi
|
|||||||
|
|
||||||
## 7. Ce am lasat pe dinafara (intentionat)
|
## 7. Ce am lasat pe dinafara (intentionat)
|
||||||
|
|
||||||
- `proceduri_comune.prg` (varianta veche) - acoperita acum in nota de la sect. 1 (2 functii unice
|
- `proceduri_comune.prg` (varianta veche) - acoperita in nota sect. 1 (2 functii unice folosite,
|
||||||
folosite, restul dublate sau moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
|
restul dublate/moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
|
||||||
make_sectii_utilizator, recompune_optiuni, cere*/compara*, debug_*_eventtracking, ...) - omise.
|
make_sectii_utilizator, recompune_optiuni, cere*/compara*, debug_*_eventtracking, ...) - omise.
|
||||||
- `oproceduri_comune_imob.prg` - varianta specifica ROAIMOB, nu ROAGEST.
|
- `oproceduri_comune_imob.prg` - varianta specifica ROAIMOB, nu ROAGEST.
|
||||||
- `xdate.prg` - script procedural (incarca cursoarele xsets/xrequest/xnote la DO), nu expune functii.
|
- `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
|
- Metoda `getUserRepPath` din oExportConfig - complet comentata (moarta); varianta activa e functia
|
||||||
libera omonima din `proceduri_rapoarte.prg` (cod diferit).
|
libera omonima din `proceduri_rapoarte.prg` (cod diferit).
|
||||||
- Clase de nomenclatoare mari (`onomenclatoare.vcx`, `onom_articole.vcx`, `stocuri.vcx`, `rulaje.vcx`,
|
- Clase de nomenclatoare mari (`onomenclatoare.vcx`, `onom_articole.vcx`, `stocuri.vcx`, `rulaje.vcx`,
|
||||||
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic specific gestiune, prea voluminos pt. acest
|
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic gestiune, prea voluminos pt. acest inventar
|
||||||
inventar (candidat pt. un inventar separat, per-flux, daca devine necesar).
|
(candidat pt. inventar separat per-flux, daca devine necesar).
|
||||||
- Clasele de configurare/serii (`configurare.vcx`, `serii_numere.vcx`, `ferestre_oracle.vcx`,
|
- Clasele de configurare/serii (`configurare.vcx`, `serii_numere.vcx`, `ferestre_oracle.vcx`,
|
||||||
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz mai rar
|
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz rar in
|
||||||
in fluxurile curente de lucru (`excelxml.vcx` e acoperita la sect. 3).
|
fluxurile curente (`excelxml.vcx` e acoperita la sect. 3).
|
||||||
- Functiile din `COMUN\programe` fara nicio aparitie gasita prin grep in ROAGEST (posibil folosite
|
- Functiile din `COMUN\programe` fara nicio aparitie prin grep in ROAGEST (posibil doar alte
|
||||||
doar de alte aplicatii ROA) - omise.
|
aplicatii ROA) - omise.
|
||||||
|
|
||||||
## 8. Cum se foloseste
|
## 8. Cum se foloseste
|
||||||
|
|
||||||
- **La plan**: inainte de a scrie cod/obiecte noi, scaneaza acest fisier + un grep tintit
|
- **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
|
(`grep -rn "<nume_functie_candidata>" COMUN/programe D:\ROA\_vfp_textcache\roagest`) ca sa
|
||||||
confirmi ca nu exista deja o comuna echivalenta.
|
confirmi ca nu exista deja o comuna echivalenta.
|
||||||
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC direct,
|
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC
|
||||||
un buton cu Click suprascris in loc de `caction`, un export Excel/listare construite manual in loc
|
direct, un buton cu Click suprascris in loc de `caction`, export Excel/listare construite manual
|
||||||
de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator facut din SELECT+grid in
|
in loc de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator din SELECT+grid
|
||||||
loc de `caut_*` (ocautare.prg), semnaleaza reutilizarea comunei corespunzatoare din tabelele de mai sus.
|
in loc de `caut_*` (ocautare.prg), semnaleaza comuna corespunzatoare din tabelele de mai sus.
|
||||||
|
|||||||
42
docs/monitorizare-context.md
Normal file
42
docs/monitorizare-context.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Hook-uri de disciplina (regulile 9 si 12)
|
||||||
|
|
||||||
|
## Monitorizare context sesiune (regula 9)
|
||||||
|
|
||||||
|
Agentul nu-si vede singur consumul de context. `COMUN\utile\context_watch.ps1` il citeste din
|
||||||
|
transcriptul sesiunii (ultimul `usage`: `input_tokens + cache_read + cache_creation`) si avertizeaza
|
||||||
|
peste prag: 250k = pregateste predarea, 275k = handoff acum.
|
||||||
|
|
||||||
|
Instalare, o data per calculator, in `%USERPROFILE%\.claude\settings.json` (nivel utilizator, prinde
|
||||||
|
toate proiectele):
|
||||||
|
|
||||||
|
```json
|
||||||
|
"hooks": {
|
||||||
|
"UserPromptSubmit": [
|
||||||
|
{ "hooks": [ { "type": "command",
|
||||||
|
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"D:\\ROA\\ROAGEST\\COMUN\\utile\\context_watch.ps1\" -Stdout" } ] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Ruleaza la fiecare mesaj al utilizatorului (~1s); sub prag nu scrie nimic.
|
||||||
|
- `-Stdout` e obligatoriu pe `UserPromptSubmit` (mesajul intra in context, exit 0). Fara el scrie pe
|
||||||
|
stderr si iese cu 2 - forma pentru `PostToolUse`.
|
||||||
|
- Praguri configurabile: `-Prag`, `-PragMax`.
|
||||||
|
- Verificare manuala: `powershell -File ...\context_watch.ps1 -Prag 900000 -PragMax 950000 -Intotdeauna`
|
||||||
|
(afiseaza `CONTEXT <n>k` indiferent de prag).
|
||||||
|
|
||||||
|
## Revizuire periodica a docs (regula 12)
|
||||||
|
|
||||||
|
`COMUN\utile\docs_revizie_check.ps1` compara data din markerul `COMUN\docs\.ultima_revizie` cu ziua
|
||||||
|
curenta si, peste 30 de zile, cere o runda de compactare. Se pune ca hook `SessionStart`, in acelasi
|
||||||
|
`settings.json`, cu `-Stdout`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"SessionStart": [
|
||||||
|
{ "hooks": [ { "type": "command",
|
||||||
|
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"D:\\ROA\\ROAGEST\\COMUN\\utile\\docs_revizie_check.ps1\" -Stdout" } ] }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Dupa o revizie aplicata: `powershell -File ...\docs_revizie_check.ps1 -Marcheaza` (rescrie markerul).
|
||||||
|
Interval configurabil cu `-Zile`.
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
# 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`.
|
`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 își face singur exportul/reîmprospătarea — nu mai e nevoie de export manual din
|
||||||
PL/SQL Developer.
|
PL/SQL Developer.
|
||||||
|
|
||||||
## Conexiune
|
## Conexiune
|
||||||
|
|
||||||
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` e deja setat spre același folder).
|
- 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`).
|
- 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/utilizator: `MARIUSM_AUTO` (schema de dezvoltare a lui Marius).
|
||||||
- **Parola nu e versionată** — se află local, în `D:\ROA\ROAGEST\docs\local\oracle.md`
|
- **Schema de lucru pentru verificari: `MARIUSM_AUTO` pe `ROA_CENTRAL`** - nu `ACN` sau altele.
|
||||||
(folder ignorat de git), pe mașina de lucru.
|
- **Parola nu e versionată** — local, în `D:\ROA\ROAGEST\docs\local\oracle.md` (ignorat de git).
|
||||||
|
|
||||||
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus un sinonim `PUBLIC`.
|
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus sinonim `PUBLIC`.
|
||||||
Exportul de referință se face din `MARIUSM_AUTO`.
|
Exportul de referință se face din `MARIUSM_AUTO`.
|
||||||
|
|
||||||
## Gotcha sqlplus pe Windows/PowerShell
|
## Gotcha sqlplus pe Windows/PowerShell
|
||||||
@@ -39,8 +39,8 @@ exit
|
|||||||
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/<parola>@ROA_CENTRAL' '@export_pack.sql'
|
& '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 pentru
|
Același tipar merge pentru orice alt pachet/procedură (`PACK_SESIUNE`, `PACK_PRETURI`, …) sau
|
||||||
DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
|
pentru DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
|
||||||
|
|
||||||
## Ce e strict necesar de știut despre PACK_CONTAFIN
|
## Ce e strict necesar de știut despre PACK_CONTAFIN
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Orchestrare cu subagenti: context mic, misiuni descompuse
|
# Orchestrare cu subagenti: context mic, misiuni descompuse
|
||||||
|
|
||||||
Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o misiune lunga
|
Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o misiune lunga
|
||||||
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias
|
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias —
|
||||||
(s-a ajuns la ~800k tokens) — calitate degradata, cost mare. Nu se lucreaza asa.
|
calitate degradata, cost mare. Nu se lucreaza asa.
|
||||||
|
|
||||||
## Cum se lucreaza
|
## Cum se lucreaza
|
||||||
|
|
||||||
@@ -42,11 +42,10 @@ Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o mi
|
|||||||
## Disciplina de context a ORCHESTRATORULUI
|
## Disciplina de context a ORCHESTRATORULUI
|
||||||
|
|
||||||
Pragul de ~200-250k e pentru subagenti, dar orchestratorul se umple la fel de repede daca isi
|
Pragul de ~200-250k e pentru subagenti, dar orchestratorul se umple la fel de repede daca isi
|
||||||
lasa in sesiune munca de CITIT. Masurat pe o runda reala (implementare + 4 rulari ale unei suite
|
lasa in sesiune munca de CITIT (masurat: o runda de implementare + 4 rulari de teste a dus
|
||||||
de 25 de teste): sesiunea principala a ajuns la ~570k desi tot codul fusese scris de subagenti.
|
sesiunea principala la ~570k desi tot codul fusese scris de subagenti). Principalii consumatori:
|
||||||
Consumul, in ordinea marimii: (1) citirea rezultatelor de test dupa fiecare test terminat, cu tot
|
citirea rezultatelor de test dupa fiecare rulare (cu tot cu liniile "OK"), citirea codului pentru
|
||||||
cu liniile "OK"; (2) citirea codului ca sa diagnosticheze esecurile; (3) diagnostic si fixuri
|
diagnostic, fixuri aplicate direct in loc de delegate.
|
||||||
aplicate direct in loc de delegate.
|
|
||||||
|
|
||||||
- **Nu citi log-uri brute.** Scripturile de raportare afiseaza DOAR esecurile plus un total
|
- **Nu citi log-uri brute.** Scripturile de raportare afiseaza DOAR esecurile plus un total
|
||||||
("22 OK, 3 FAIL: <nume + linia de esec>"). Tabelul complet se citeste o singura data, la
|
("22 OK, 3 FAIL: <nume + linia de esec>"). Tabelul complet se citeste o singura data, la
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Prompt: seteaza conventia docs/ (insight-uri de proiect) intr-un proiect ROA
|
# Prompt: seteaza conventia docs/ (insight-uri de proiect) intr-un proiect ROA
|
||||||
|
|
||||||
Template partajat intre proiectele ROA* (similar cu `changelog_template.txt`). Origine: ROAIMOB, 08/07/2026. Copiaza blocul de mai jos (adaptat, daca e nevoie) intr-o sesiune Claude Code din radacina oricarui proiect ROA* pentru a initializa aceeasi conventie.
|
Template partajat intre proiectele ROA* (similar cu `changelog_template.txt`). Copiaza blocul de mai jos (adaptat, daca e nevoie) intr-o sesiune Claude Code din radacina oricarui proiect ROA* pentru a initializa aceeasi conventie.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,60 +1,81 @@
|
|||||||
# Reguli de lucru agent (comune proiectelor ROA VFP)
|
# Reguli de lucru agent (comune proiectelor ROA VFP)
|
||||||
|
|
||||||
1. Modificari de cod: livreaza FISIER de diff `docs\diff_runda<N>_<subiect>.patch`
|
1. Modificari de cod: diff ca FISIER `docs\diff_runda<N>_<subiect>.patch`
|
||||||
(`git diff --no-index <baseline.bak> <editat>`), nu diff in terminal.
|
(`git diff --no-index <baseline.bak> <editat>`), nu in terminal. Write-back in binar (txt2vcx)
|
||||||
Write-back in binar (txt2vcx) si commit DOAR dupa aprobarea patch-ului de catre utilizator.
|
si commit DOAR dupa aprobarea patch-ului. Patch-urile (in .gitignore, `docs/diff_runda*.patch`)
|
||||||
Patch-urile sunt intermediare de review: NU se comit NICIODATA in git (sunt in
|
nu se comit niciodata, raman local. Dupa commit: sterge patch-urile si backup-urile
|
||||||
.gitignore ca `docs/diff_runda*.patch`); raman doar local, pe disc.
|
`*.pre_runda*.bak`.
|
||||||
Curatenie: dupa commit se sterg patch-urile de review si backup-urile de lucru
|
2. Comentarii in cod: minime, strict functionale, descriu comportamentul CURENT (ca si cum ar fi
|
||||||
(`*.pre_runda*.bak`).
|
scris asa de la inceput) — o linie de regula, 2-3 doar pentru metode cu contract nebanal
|
||||||
2. Comentarii in cod: minime si strict functionale - descriu comportamentul CURENT, ca si cum
|
(parametri, cursor asteptat/lasat deschis, pozitionare la iesire). Istoricul modificarilor
|
||||||
codul ar fi fost scris asa de la inceput. O linie de regula; 2-3 linii doar pentru o metoda
|
sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg` si in PL/SQL Oracle.
|
||||||
cu contract nebanal (parametri, cursorul asteptat/lasat deschis, pozitionarea la iesire).
|
INTERZIS in comentariu: nume de agent ("claude"), referinte la propuneri/decizii/etape
|
||||||
Istoricul modificarilor sta DOAR in ANTETUL fisierului, niciodata inline; se aplica la fel
|
(`docs/propuneri_*.md`, "M2", "T3", "dec.6", "runda27", "E7", "D-H2"), istoricul modificarii
|
||||||
in `.prg` si in package-urile/procedurile PL/SQL Oracle.
|
("inlocuieste...", "nu mai depinde de...", "mutat din..."), date si autori pe cod nou.
|
||||||
INTERZIS in comentariu: nume de agent ("claude"), referinte la documente de propuneri sau la
|
Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins
|
||||||
decizii/etape (`docs/propuneri_*.md`, "M2", "T3", "dec.6", "runda27", "E7", "D-H2"), istoricul
|
sau la cerere explicita.
|
||||||
modificarii ("inlocuieste ...", "nu mai depinde de ...", "mutat din ..."), date si autori pe
|
Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` /
|
||||||
cod nou. Comentariile vechi in stil jurnal nu se rescriu din oficiu - doar cand blocul e
|
`*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta; autorul e cine
|
||||||
oricum atins, sau la cerere explicita.
|
semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul final — fara
|
||||||
In ANTETUL fisierului se tine o singura intrare CUMULATIVA per functionalitate, in stilul
|
revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
|
||||||
existent (`*!* DD.MM.YYYY` / `*!* autor` / `*!* ce face, 1-2 fraze`): la revenirea pe aceeasi
|
|
||||||
lucrare se rescrie intrarea, nu se adauga alta. Autorul e persoana care semneaza livrarea
|
|
||||||
(ex. `marius.mutu`) - niciodata "claude" sau alt nume de agent.
|
|
||||||
Se descrie doar comportamentul final, fara referinte la revizii, runde, patch-uri sau la
|
|
||||||
corectii facute pe parcurs. La rezolvari de erori NU se adauga comentarii deloc.
|
|
||||||
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
||||||
Changelog (`changelog_<aplicatie>.txt`): text minimal, pe limba utilizatorului, nu tehnic,
|
Changelog (`changelog_<aplicatie>.txt`): strictul necesar, pe limba utilizatorului, non-tehnic
|
||||||
o fraza scurta per intrare. Cat timp lucrarea nu a ajuns la utilizatori (fara deploy),
|
— 1-3 fraze/intrare, fara detalii de implementare, fara enumerarea locurilor atinse. Cat timp
|
||||||
erorile introduse si corectate in interiorul ei NU se pomenesc - intrarea descrie
|
lucrarea n-a ajuns la utilizatori, erorile introduse si corectate in interior NU se mentioneaza
|
||||||
functionalitatea asa cum ajunge la utilizator, `:nou:`/`:modificare:`; `:eroare:` ramane
|
— intrarea descrie functionalitatea finala, `:nou:`/`:modificare:`; `:eroare:` doar pentru erori
|
||||||
doar pentru erori care au fost in productie.
|
care au fost in productie.
|
||||||
3. Modificari minime: doar ce s-a cerut; fara refactorizari sau curatenie din oficiu.
|
3. Modificari minime si SCOPED: doar ce s-a cerut, doar pe cazul cu problema, fara refactorizari
|
||||||
|
din oficiu. Cauta intai ce exista (`inventar-comun.md`) si refoloseste; daca lipseste ceva,
|
||||||
|
propune COMPLETAREA unei functii/tabele/view comune, nu o varianta paralela. 80/20: solutia cea
|
||||||
|
mai simpla care rezolva cazul real. Completeaza `inventar-comun.md` la orice descoperire/creare
|
||||||
|
de element comun nedocumentat.
|
||||||
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
|
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
|
||||||
Mediu, sabloane, capcane si metoda de depanare: `depanare_testare_vfp.md`.
|
Mediu, sabloane, capcane, depanare: `depanare_testare_vfp.md`.
|
||||||
5. Editare .vcx/.scx pe text (cache, cp1252 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
5. Editare .vcx/.scx pe text (cache, cp1252 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
||||||
Cautare in binare: `cautare_vcx_vct.md`.
|
Cautare in binare: `cautare_vcx_vct.md`. Versiunile `.??2` sunt instantanee, pot fi mai vechi
|
||||||
Versiunile `.??2` sunt instantanee si pot fi mai vechi decat binarul - verifica mtime-ul
|
decat binarul — verifica mtime inainte de concluzii; continutul real e in `.PJX`.
|
||||||
inainte de a trage concluzii din ele; continutul real al proiectului se citeste din `.PJX`.
|
6. Delegare: implementarile, testele, verificarile si cercetarile se dau unor subagenti Sonnet in
|
||||||
6. Misiuni lungi (teste, investigatii, sarcini inlantuite): NU un singur subagent cu context
|
background (lane-uri paralele); sesiunea principala doar orchestreaza si verifica, ca sa nu i
|
||||||
acumulat — orchestrator + subagenti proaspeti per sarcina (max ~200-250k tokens/subagent),
|
se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k
|
||||||
handoff compact pe disc: `orchestrare-subagenti.md`.
|
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc:
|
||||||
|
`orchestrare-subagenti.md`.
|
||||||
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
||||||
- editezi orice fisier cu octeti cp1252 - `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`,
|
- editezi fisiere cu octeti cp1252 - `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`,
|
||||||
unde `s`-urile cu virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) ->
|
unde `s`-urile cu virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) ->
|
||||||
`conventie_encoding_cp1252.md`. Orice write cu un tool care nu scrie cp1252 nativ (Edit/Write)
|
`conventie_encoding_cp1252.md`. Orice write cu un tool ce nu scrie cp1252 nativ (Edit/Write)
|
||||||
corupe caracterele >= 0x80 din TOT fisierul (`0xBA` -> `EF BF BD`), chiar daca schimbi o singura
|
corupe caracterele >= 0x80 din TOT fisierul (`0xBA` -> `EF BF BD`), chiar la o singura linie
|
||||||
linie, si o face din nou la FIECARE scriere. Deci: editezi tot ce ai de editat, si abia DUPA ultima
|
schimbata, si o repeta la FIECARE scriere — editeaza tot ce ai de editat, verifica byte-level
|
||||||
scriere verifici byte-level si repari o singura data; daca mai editezi dupa reparare, se strica iar.
|
si repara o singura data DUPA ultima scriere. Verificare: `perl -ne 'print "$.\n" if
|
||||||
Verificare: `perl -ne 'print "$.\n" if /[\x80-\xFF]/' <fisier>`; reparare (aici pentru `0xBA`):
|
/[\x80-\xFF]/' <fisier>`; reparare (pt. `0xBA`): `perl -e
|
||||||
`perl -e 'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
|
'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
|
||||||
ATENTIE: `EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel. Ia octetul
|
`EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel; ia octetul corect
|
||||||
corect per pozitie din `svn cat <fisier>` (SVN are versiunea necorupta) si abia apoi inlocuieste;
|
per pozitie din `svn cat <fisier>` (necorupt) inainte sa inlocuiesti - o inlocuire oarba cu
|
||||||
o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere;
|
`0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere;
|
||||||
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
|
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
|
||||||
- scrii cod cu `GO` pe un `Recno()` capturat sau primit ca parametru -> `conventie_go_recno.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`;
|
- `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 / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;
|
||||||
|
- garzi pe valori NULL din Oracle -> `conventie_null_vfp.md`;
|
||||||
- export date din Oracle -> `oracle_export.md`;
|
- export date din Oracle -> `oracle_export.md`;
|
||||||
- modifici schema Oracle (tabele/view-uri/pachete) -> `scripturi-migrare-db.md`
|
- modifici schema Oracle (tabele/view-uri/pachete) -> `scripturi-migrare-db.md`.
|
||||||
(unde stau scripturile de migrare si modelele pentru scripturi noi).
|
8. Eroare raportata de utilizator: nu analiza statica indelungata — scrie intai un test care o
|
||||||
|
reproduce pe fluxul real; el da cauza si confirma remedierea. Analiza statica doar cat sa stii
|
||||||
|
ce sa pui in test.
|
||||||
|
9. Context sesiune principala: la peste **250k** salveaza contextul intr-un handoff pe disc, il
|
||||||
|
predai unei sesiuni noi si te opresti. Limita maxima absoluta: **275k**. Nu estima - masoara:
|
||||||
|
hook-ul din `monitorizare-context.md` anunta pragul la fiecare mesaj.
|
||||||
|
10. Fisier de progres MASTER per proiect (`docs\progres.md`): la zi pe tot parcursul, nu doar la
|
||||||
|
predare — stare curenta, facut/testat, ipoteze excluse (cu dovada), ce urmeaza, fisiere atinse,
|
||||||
|
comenzi de rulat. O sesiune noua porneste de acolo, fara sa reia investigatia.
|
||||||
|
11. La final de lucrare/cercetare: **propune** actualizarea documentatiei — `COMUN\docs\` daca e
|
||||||
|
comun tuturor aplicatiilor, `docs\` al proiectului daca e specific (plus `inventar-comun.md`,
|
||||||
|
regula 3). Doar relevant si reutilizabil (80/20): flux ascuns, capcana, procedura/tabela cheie
|
||||||
|
— nu tot ce ai atins, nu verbose. Cateva randuri; propui, nu scrii din oficiu.
|
||||||
|
O notita = regula + strictul de context ca sa fie aplicabila: fara cazul particular in care ai
|
||||||
|
gasit-o, fara simptomele lantului de erori, fara ce se deduce din cod (cititorul stie deja).
|
||||||
|
12. Revizuire periodica a documentatiei (`COMUN\docs\`, `docs\` al proiectului, inclusiv acest
|
||||||
|
fisier): compacteaza pastrand semantica — taie ce se deduce din cod, exemplele repetate,
|
||||||
|
istoricul, tot ce nu mai schimba o decizie. Scopul: docs + reguli sa ocupe cat mai putin context
|
||||||
|
la incarcare. Propui rezultatul, nu rescrii din oficiu; nu pierzi nicio regula/capcana, doar
|
||||||
|
cuvintele in plus. Fisierele de reguli/conventii se completeaza doar cu ce e super-util,
|
||||||
|
simplu si concis. Cadenta o da hook-ul din `monitorizare-context.md` (marker la 30 de zile).
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
# Scripturi migrare baza de date Oracle
|
# Scripturi migrare baza de date Oracle
|
||||||
|
|
||||||
Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in
|
Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in
|
||||||
`DATABASE\SCRIPTURI_CLAR` de sub radacina suitei ROA (folderul parinte al aplicatiei,
|
`DATABASE\SCRIPTURI_CLAR` de sub radacina suitei ROA (`gcDirMare`/`dirgen` — ex.
|
||||||
`gcDirMare`/`dirgen` — ex. `D:\ROA\DATABASE\SCRIPTURI_CLAR`).
|
`D:\ROA\DATABASE\SCRIPTURI_CLAR`). Sursa SVN: `http://svnroa:3001/svn/ROA/DATABASE/Branches/RB-1.00`.
|
||||||
Sursa SVN: `http://svnroa:3001/svn/ROA/DATABASE/Branches/RB-1.00`.
|
|
||||||
Pentru un script nou, urmeaza formatul/conventiile celor recente de acolo.
|
Pentru un script nou, urmeaza formatul/conventiile celor recente de acolo.
|
||||||
|
|
||||||
Reguli confirmate de Marius (24.07.2026):
|
Reguli confirmate de Marius (24.07.2026):
|
||||||
|
|
||||||
- **Line-endings CRLF obligatoriu** in scripturile `.sql` — tool-urile agentului scriu
|
- **Line-endings CRLF obligatoriu** in scripturile `.sql` — tool-urile agentului scriu implicit
|
||||||
implicit LF; dupa orice scriere, verifica si converteste byte-safe LF -> CRLF (fara
|
LF; dupa orice scriere, verifica si converteste byte-safe LF -> CRLF (fara decodare/reincodare).
|
||||||
decodare/reincodare). Parsarea pe fluxul ROA (ex. `ALINES` pe `CHR(13)+CHR(10)`)
|
Parsarea pe fluxul ROA (ex. `ALINES` pe `CHR(13)+CHR(10)`) esueaza silentios pe LF: tot fisierul
|
||||||
esueaza silentios pe LF: tot fisierul devine un singur rand.
|
devine un singur rand.
|
||||||
- `versiune_db.txt` (marker-ul `YYYY_MM_DD_NN` din radacina aplicatiei) se scrie fara
|
- `versiune_db.txt` (marker-ul `YYYY_MM_DD_NN` din radacina aplicatiei) se scrie fara newline la
|
||||||
newline la final (conventia existenta).
|
final (conventia existenta).
|
||||||
- Aplicarea prin ODBC/`goExecutor`: sintaxa SQL*Plus `exec pachet.procedura(...)` nu
|
- Aplicarea prin ODBC/`goExecutor`: sintaxa SQL*Plus `exec pachet.procedura(...)` nu functioneaza
|
||||||
functioneaza — foloseste `begin pachet.procedura(...); end;`.
|
— foloseste `begin pachet.procedura(...); end;`.
|
||||||
|
|
||||||
|
## Continutul unui script
|
||||||
|
|
||||||
|
- **Minimul necesar si intotdeauna SCOPED**: `update`/`insert` doar pe randurile cazului tratat
|
||||||
|
(setul, codul, firma anume), niciodata pe toate randurile care "seamana" cu el.
|
||||||
|
- **Fara `select` de raportare in script** — nu-l citeste nimeni la aplicare si poate da eroare.
|
||||||
|
Verificarile se fac inainte, separat, pe schema de lucru.
|
||||||
|
- **Idempotent**: rulat de doua ori nu mai schimba nimic (`merge`, `where <coloana> is null`).
|
||||||
|
|
||||||
## Numerotare si versiune_db.txt
|
## Numerotare si versiune_db.txt
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ Fisiere in `COMUN\utile\Teste\`: `vfp_ui_harness.ps1` (orchestrator generic, par
|
|||||||
`mock_amessagebox.prg` (mock dialog) — infrastructura sta in radacina `Teste\`; suitele stau in
|
`mock_amessagebox.prg` (mock dialog) — infrastructura sta in radacina `Teste\`; suitele stau in
|
||||||
subfoldere pe subiect. Exemplu complet: `achizitie_import\test_import_nota_ui.prg` + `.ps1`.
|
subfoldere pe subiect. Exemplu complet: `achizitie_import\test_import_nota_ui.prg` + `.ps1`.
|
||||||
|
|
||||||
**REGULA (Marius, 17/07/2026): testele pe aplicatii frontend exerseaza fluxul REAL al
|
**REGULA (Marius): testele pe aplicatii frontend exerseaza fluxul REAL al
|
||||||
utilizatorului** — formularul/butonul/metoda pe care o apeleaza aplicatia, NU introducerea
|
utilizatorului** — formularul/butonul/metoda pe care o apeleaza aplicatia, NU introducerea
|
||||||
directa a randurilor in cursoare/tabele. Popularea directa sare peste validari/filtre/efecte
|
directa a randurilor in cursoare/tabele. Popularea directa sare peste validari/filtre/efecte
|
||||||
laterale si da PASS fals (caz real: un articol "adaugat" direct in cursor trecea testul, dar
|
laterale si da PASS fals (caz real: articol "adaugat" direct in cursor trecea testul, dar prin
|
||||||
prin fluxul real nu se adauga deloc). Mock-urile raman permise doar pe INFRASTRUCTURA (Oracle,
|
fluxul real nu se adauga deloc). Mock-urile raman permise doar pe INFRASTRUCTURA (Oracle,
|
||||||
dialoguri modale), nu pe pasii fluxului testat.
|
dialoguri modale), nu pe pasii fluxului testat.
|
||||||
|
|
||||||
## Test UI nou in 5 pasi
|
## Test UI nou in 5 pasi
|
||||||
@@ -33,7 +33,7 @@ dialoguri modale), nu pe pasii fluxului testat.
|
|||||||
5. `powershell -File vfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0',...)`.
|
5. `powershell -File vfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0',...)`.
|
||||||
PNG-uri in `screenshots\step_<n>_<eticheta>.png`; log in `<test>_log.txt`.
|
PNG-uri in `screenshots\step_<n>_<eticheta>.png`; log in `<test>_log.txt`.
|
||||||
|
|
||||||
## Capcane / deblocari (toate confirmate in sesiune)
|
## Capcane / deblocari
|
||||||
|
|
||||||
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`.** Cu SAFETY ON, scrierea
|
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
|
log-ului existent scoate un dialog modal care blocheaza rularea (proces viu, "instanta
|
||||||
@@ -51,22 +51,20 @@ d. **`vfp9 -A test.prg` deschide INTERMITENT editorul** in loc sa ruleze (log go
|
|||||||
`.fxp`-ul PRECOMPILAT. Precompilarea (`COMPILE`+`QUIT`) atarna dupa COMPILE si, rulata in
|
`.fxp`-ul PRECOMPILAT. Precompilarea (`COMPILE`+`QUIT`) atarna dupa COMPILE si, rulata in
|
||||||
ACEEASI sesiune powershell, otraveste lansarile ulterioare - ruleaza-o intr-un proces copil
|
ACEEASI sesiune powershell, otraveste lansarile ulterioare - ruleaza-o intr-un proces copil
|
||||||
izolat (`Start-Process -Wait _precompile.ps1`).
|
izolat (`Start-Process -Wait _precompile.ps1`).
|
||||||
e. **Suitele NU se ruleaza in paralel** intre ele: harness-ul isi omoara instantele `vfp9`
|
e. **Suitele NU se ruleaza in paralel**: harness-ul omoara instantele `vfp9` ramase inainte de
|
||||||
ramase inainte de fiecare lansare, deci un al doilea test pornit peste primul il ucide.
|
fiecare lansare, deci un al doilea test pornit peste primul il ucide. Omorarea e filtrata pe
|
||||||
Omorarea e INSA filtrata pe linia de comanda (`Win32_Process.CommandLine` care contine
|
linia de comanda (`Win32_Process.CommandLine` contine folderul de teste): instantele `vfp9`
|
||||||
folderul de teste): instantele `vfp9` straine — sesiunea IDE a utilizatorului sau teste
|
straine (sesiunea IDE a utilizatorului, teste dintr-un ALT proiect VFP) nu sunt atinse. Nu
|
||||||
dintr-un ALT proiect VFP — nu sunt atinse si nu blocheaza rularea. Nu reintroduce
|
reintroduce `Get-Process vfp9 | Stop-Process -Force` fara filtru.
|
||||||
`Get-Process vfp9 | Stop-Process -Force` fara filtru.
|
f. **FARA FURT DE FOCUS**: `Graphics.CopyFromScreen` fura focus si se corupe daca
|
||||||
f. **FARA FURT DE FOCUS (17/07/2026)**: `Graphics.CopyFromScreen` fura focus si se corupe daca
|
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile: `PrintWindow` (user32,
|
||||||
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile se fac cu `PrintWindow`
|
P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT` (fallback `0` daca
|
||||||
(user32, P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT`
|
iese goala); merge cu fereastra acoperita, NU minimizata. Fereastra se muta OFF-SCREEN
|
||||||
(fallback `0` daca iese goala); merge cu fereastra acoperita, dar NU minimizata. Fereastra
|
(`SetWindowPos`, `HWND_BOTTOM`, x=-4000, `SWP_NOACTIVATE`) la aparitia handle-ului si SE
|
||||||
se muta OFF-SCREEN (`SetWindowPos`, `HWND_BOTTOM`, x=-4000, `SWP_NOACTIVATE`) imediat ce
|
RE-IMPINGE la fiecare pas (VFP se reactiveaza singur la `Show()`/dialoguri). Consolele
|
||||||
apare handle-ul si SE RE-IMPINGE la fiecare pas (VFP se reactiveaza singur la
|
powershell copil: `-WindowStyle Hidden` (sigur pentru consola, NU pentru GUI VFP ascunsa -
|
||||||
`Show()`/dialoguri). Consolele powershell copil sunt `-WindowStyle Hidden` (sigur pentru
|
`PrintWindow` poate reda gol). Implementat in `vfp_ui_harness.ps1` (Take-Screenshot,
|
||||||
consola, NU pentru GUI VFP - ascunsa, `PrintWindow` poate reda gol). Implementat in
|
Push-Offscreen, Wait-MainWindowHandle) si `_precompile.ps1`.
|
||||||
`vfp_ui_harness.ps1` (Take-Screenshot, Push-Offscreen, Wait-MainWindowHandle) si
|
|
||||||
`_precompile.ps1`.
|
|
||||||
g. **Mock de messagebox**: `FUNCTION amessagebox` care returneaza direct valoarea butonului
|
g. **Mock de messagebox**: `FUNCTION amessagebox` care returneaza direct valoarea butonului
|
||||||
(6=Da), incarcat cu `SET PROCEDURE ... ADDITIVE` **PRIMUL**, inaintea fisierelor aplicatiei:
|
(6=Da), incarcat cu `SET PROCEDURE ... ADDITIVE` **PRIMUL**, inaintea fisierelor aplicatiei:
|
||||||
la nume duplicat de procedura VFP foloseste fisierul cautat PRIMUL (verificat empiric).
|
la nume duplicat de procedura VFP foloseste fisierul cautat PRIMUL (verificat empiric).
|
||||||
@@ -83,25 +81,23 @@ i. **Cursorii trebuie sa aiba EXACT indecsii creati de fluxul real** inainte de
|
|||||||
uneori in cascada la apeluri repetate. Verifica in codul apelant ce indecsi se creeaza si
|
uneori in cascada la apeluri repetate. Verifica in codul apelant ce indecsi se creeaza si
|
||||||
replica-i identic.
|
replica-i identic.
|
||||||
j. **Mock-urile de date trebuie sa reproduca structura si semantica REALA a sursei** (view
|
j. **Mock-urile de date trebuie sa reproduca structura si semantica REALA a sursei** (view
|
||||||
Oracle: toate coloanele; relatii intre randuri: toate randurile implicate, nu unul singur cu
|
Oracle: toate coloanele; relatii intre randuri: toate randurile implicate, nu una singura cu
|
||||||
valori "compuse" manual in test). Un mock incomplet lasa campuri mereu NULL sau ascunde
|
valori "compuse" manual). Un mock incomplet lasa campuri NULL sau ascunde pasul testat. Cand
|
||||||
pasul care se testeaza. Cand un flag global activeaza cod suplimentar (ex. `gl406`), acel
|
un flag global activeaza cod suplimentar (ex. `gl406`), acel cod cere mock-uri in plus -
|
||||||
cod cere mock-uri in plus - verifica ce apeleaza si adauga metodele lipsa din dummy.
|
verifica ce apeleaza si adauga metodele lipsa din dummy. Cu `gl406=.T.` (SAFT),
|
||||||
Cu `gl406=.T.` (SAFT), `GetTaxCodeIdPart`/`GetTaxCode` cer: `goApp.ReadIni`/`WriteIni`
|
`GetTaxCodeIdPart`/`GetTaxCode` cer: `goApp.ReadIni`/`WriteIni` (clasa `dummyapp` are nevoie
|
||||||
(proprietate simpla nu ajunge, clasa `dummyapp` are nevoie de METODE), `goExecutor.oReset`
|
de METODE, nu doar proprietate), `goExecutor.oReset` (no-op e suficient), si cursor
|
||||||
(no-op e suficient), si un cursor `saft_taxtable` real (nu doar mock pe `goExecutor` -
|
`saft_taxtable` real (nu doar mock pe `goExecutor` - `update_jtva_coloane` face
|
||||||
`update_jtva_coloane` face `USE saft_taxtable` direct pe alias). Fara ele, simptomul e un
|
`USE saft_taxtable` direct pe alias). Fara ele, simptomul e dialog nativ Windows "Open" (cauta
|
||||||
dialog nativ Windows "Open" (cauta `saft_taxtable.dbf`) care blocheaza headless la nesfarsit,
|
`saft_taxtable.dbf`) care blocheaza headless la nesfarsit, fara linie noua in log si CPU 0% -
|
||||||
fara nicio linie noua in log si CPU 0% - vezi `depanare_testare_vfp.md` pentru diagnosticul
|
vezi `depanare_testare_vfp.md` pentru diagnostic cu `EnumWindows`/`PrintWindow`.
|
||||||
cu `EnumWindows`/`PrintWindow` pe fereastra ascunsa cand simptomul e "ecran gol, fara eroare".
|
|
||||||
k. **`LOCATE FOR camp == 'literal'` pe camp `C(n)` padded nu gaseste nimic** (`==` e exact) -
|
k. **`LOCATE FOR camp == 'literal'` pe camp `C(n)` padded nu gaseste nimic** (`==` e exact) -
|
||||||
foloseste `ALLTRIM(camp) == 'literal'`.
|
foloseste `ALLTRIM(camp) == 'literal'`.
|
||||||
l. **`CREATEOBJECT`/`ADDPROPERTY` se comporta gresit apelate DINTR-O PROCEDURA in acest runtime
|
l. **`CREATEOBJECT`/`ADDPROPERTY` se comporta gresit apelate DINTR-O PROCEDURA in acest runtime
|
||||||
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din
|
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din programul
|
||||||
programul PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper.
|
PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper. Cauza
|
||||||
Cauza confirmata intr-un caz concret: linie de cod prea lunga in ACEEASI metoda de clasa -
|
confirmata intr-un caz concret: linie de cod prea lunga in ACEEASI metoda de clasa - vezi
|
||||||
vezi `depanare_testare_vfp.md` sectiunea 6. Remediul (constructie inline) ramane valabil
|
`depanare_testare_vfp.md` sectiunea 6; remediul (constructie inline) ramane valabil oricum.
|
||||||
oricum, indiferent de cauza exacta dintr-un caz punctual.
|
|
||||||
m. **Fara `SELECT-SQL` pe cursorul legat de grid**: `SELECT ... FROM <cursor> INTO CURSOR` cat
|
m. **Fara `SELECT-SQL` pe cursorul legat de grid**: `SELECT ... FROM <cursor> INTO CURSOR` cat
|
||||||
timp cursorul e RecordSource-ul unui grid viu poate omori procesul vfp9 silentios (fara
|
timp cursorul e RecordSource-ul unui grid viu poate omori procesul vfp9 silentios (fara
|
||||||
eroare catchabila, fara semafor). Foloseste xBase nativ (`COUNT FOR ... TO`, `CALCULATE`,
|
eroare catchabila, fara semafor). Foloseste xBase nativ (`COUNT FOR ... TO`, `CALCULATE`,
|
||||||
@@ -113,9 +109,9 @@ n. **Wrapper-ul `.ps1` trebuie sa paseze `-SyncDir` daca `.prg`-ul isi seteaza p
|
|||||||
asteapta un fisier care nu vine). Timeout minim: ~30s x numarul de pasi din `-Steps`
|
asteapta un fisier care nu vine). Timeout minim: ~30s x numarul de pasi din `-Steps`
|
||||||
(auto-continue per checkpoint din `HarnessWaitContinue`), plus marja de pornire.
|
(auto-continue per checkpoint din `HarnessWaitContinue`), plus marja de pornire.
|
||||||
o. **Formularul resincronizeaza singur dupa o alegere din grid** (`lSyncPending` + `tmrSync`,
|
o. **Formularul resincronizeaza singur dupa o alegere din grid** (`lSyncPending` + `tmrSync`,
|
||||||
ex. `do_modifica_explicatie_tva` din `ointroduceri.vcx`): starea de imediat dupa actiune NU e
|
ex. `do_modifica_explicatie_tva` din `ointroduceri.vcx`): starea imediat dupa actiune NU e
|
||||||
observabila - `DOEVENTS FORCE` lasa timer-ul sa porneasca, iar resincronizarea rescrie ce
|
observabila - `DOEVENTS FORCE` lasa timer-ul sa porneasca, iar resincronizarea rescrie ce
|
||||||
tocmai s-a aplicat (la explicatia TVA: randul S revine la familia documentului si randurile T
|
tocmai s-a aplicat (la explicatia TVA: randul S revine la familia documentului, randurile T se
|
||||||
se realiniaza dupa el). Scrie assert-urile pe starea de DUPA resincronizare si alege un efect
|
realiniaza dupa el). Scrie assert-urile pe starea de DUPA resincronizare, pe un efect pe care
|
||||||
pe care resincronizarea NU il repara (acolo: `scc`-ul randului T, atins doar cand se schimba
|
resincronizarea NU il repara (acolo: `scc`-ul randului T, atins doar la schimbarea explicatiei)
|
||||||
explicatia). Altfel testul pica fara sa fie ceva gresit in cod.
|
- altfel testul pica fara sa fie ceva gresit in cod.
|
||||||
|
|||||||
@@ -14,16 +14,16 @@ Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.e
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Gate-ul de pornire (`gcNumeProgram = 'ROAGEST'` in `roagest.prg`) verifica
|
- Gate-ul de pornire (`gcNumeProgram = 'ROAGEST'` in `roagest.prg`) verifica
|
||||||
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele
|
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele procesului
|
||||||
procesului `.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
|
`.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
|
||||||
- Fereastra rezultata are titlul `ROA - Gestiuni` (setat din `NUMEPROGRAM`).
|
- Fereastra rezultata are titlul `ROA - Gestiuni` (setat din `NUMEPROGRAM`).
|
||||||
|
|
||||||
## Capcana: focus furat de terminal
|
## Capcana: focus furat de terminal
|
||||||
|
|
||||||
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza,
|
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza, fereastra
|
||||||
fereastra terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal —
|
terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal — `Screenshot`/`Snapshot`
|
||||||
`Screenshot`/`Snapshot` din `windows-mcp` pot raporta "No windows found" desi procesul
|
din `windows-mcp` pot raporta "No windows found" desi procesul si fereastra exista (verificabil
|
||||||
si fereastra exista (verificabil cu `Get-Process vfp9 | Select MainWindowTitle`).
|
cu `Get-Process vfp9 | Select MainWindowTitle`).
|
||||||
|
|
||||||
Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
|||||||
mcp__windows-mcp__App mode=switch name="ROA - Gestiuni"
|
mcp__windows-mcp__App mode=switch name="ROA - Gestiuni"
|
||||||
```
|
```
|
||||||
|
|
||||||
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand
|
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand ai lansat
|
||||||
ai lansat procesul chiar in runda curenta de comenzi.
|
procesul chiar in runda curenta de comenzi.
|
||||||
|
|
||||||
## Curatare dupa test
|
## Curatare dupa test
|
||||||
|
|
||||||
|
|||||||
@@ -12,3 +12,9 @@ Vreau ca verificarile de coduri fiscale din D406, D394, Registrele de TVA sa fol
|
|||||||
4. ROACONT - overificari.vcx > formularul istoric coduri fiscale are coloane care nu mai au relavanta sau nu mai sunt completate din tabel. in tabelul contafin_oracle.istoric_coduri_fiscale, campul regcom are spatii si nu se afiseaza in formularul istoric. verifica
|
4. ROACONT - overificari.vcx > formularul istoric coduri fiscale are coloane care nu mai au relavanta sau nu mai sunt completate din tabel. in tabelul contafin_oracle.istoric_coduri_fiscale, campul regcom are spatii si nu se afiseaza in formularul istoric. verifica
|
||||||
|
|
||||||
5. ROACONT - VERIFICARE cod fiscal, label-ul de sub grid-ul cu rezultate si detalii F4 sa contina si status "TVA Incasare"
|
5. ROACONT - VERIFICARE cod fiscal, label-ul de sub grid-ul cu rezultate si detalii F4 sa contina si status "TVA Incasare"
|
||||||
|
|
||||||
|
6. ROAFACTURARE - EDITARE FACTURA EMISA ANTERIOR, CARE NU A FOST TRIMISA INCA IN EFACTURA (anaf_efactura.id_fact). punctul critic este ca notele contabile si eventual rulajele generate se genereaza complicat la emiterea facturii prin pack_facturare, iar editarea este o simpla editare, si nu sincronizeaza si notele contabile si rulajele. si sunt diverse tipuri de facturi sau de avize (pe baza de lista de preturi, pe baza de comanda, pe baza de contract, pe baza de aviz) si fiecare genereaza note contabile sau rulaje si articole de vanzare (vanzari si vanzari_detalii)
|
||||||
|
|
||||||
|
7. ROAFACTURARE - TVA unitar si valoarea TVA pe o linie de articol este calculata si nu salvata in vanzari si vanzari_detalii. din aceasta cauza, daca o factura are valoare totala 99.99 lei, dar utilizatorul doreste 100.00 lei total cu tva (pentru ca politica de preturi are bifat preturi fara TVA si se porneste calculul incepand de la pretul fara TVA al articolului) tva-ul se calculeaza rotunjit si nu se poate edita, ca sa dea factura fix 100.00 lei. implicatiile calculului TVA in loc de salvare sunt foarte mari si adanci in program, la introducerea facturii, listarea facturii initiale, relistarea facturii
|
||||||
|
|
||||||
|
8. ROAFACTURARE - in pack_facturare am salvat in vanzari valori totale denormalizat (fara tva, tva, cu tva, numarul avizului/comanda/contract etc.) ca sa nu le calculez in view din vanzari_detalii pentru ca view-ul de facturi este foarte complex, cu functii si expresii si nu era optimizabil si acceseaza total tabelele vanzari si vanzari_detalii. folosesc un view pe modelul original, si un view cu valorile totale din vanzari. doar ca am observat un bug, la facturile din avize, nu se salveaza corect in vanzari avizul sau numarul/data/suma chitantei daca factura este achitata numerar. trebuie depanat. schema de verificare productie este VENDING@ROA_VENDING
|
||||||
@@ -397,7 +397,7 @@ Function verific_partener
|
|||||||
|
|
||||||
ll_l=.F.
|
ll_l=.F.
|
||||||
|
|
||||||
If Empty(tcCont) Or Type('tccont')#'C'
|
If Type('tccont')#'C' Or Empty(Nvl(tcCont,''))
|
||||||
Return ll_l
|
Return ll_l
|
||||||
Else
|
Else
|
||||||
lcCont = Alltrim(tcCont)
|
lcCont = Alltrim(tcCont)
|
||||||
|
|||||||
543
utile/Teste/achizitie_import/test_repro_partener_scc_null.prg
Normal file
543
utile/Teste/achizitie_import/test_repro_partener_scc_null.prg
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
* test_repro_partener_scc_null.prg
|
||||||
|
* REPRODUCERE: "achizitie din import > interna", dublu click pe coloana "Partener credit"
|
||||||
|
* (Grid1.cPartC.Text1.DblClick -> LostFocus(.T.) -> verific_partener in ooperatii_comune.prg).
|
||||||
|
* Cand contul creditor al randului (introdc.scc) vine NULL din nota contabila configurata,
|
||||||
|
* SQL-ul construit prin concatenare in verific_partener devine .NULL., iar garda din
|
||||||
|
* oExecutor.oExecute (If Empty(tcSql)) NU il prinde - EMPTY(.NULL.) e .F. in VFP - deci
|
||||||
|
* SQLEXEC primeste un statement NULL si da eroarea
|
||||||
|
* "SQL statement parameter is required for non-prepared SQLEXEC() calls." (OEXECUTOR.OEXECUTE)
|
||||||
|
*
|
||||||
|
* Ramura cu valuta merge pentru ca acolo nota contabila are contul creditor completat (401).
|
||||||
|
*
|
||||||
|
* Scenarii, pe formularul real import_nota(.T.) + dialogul real import_adauga_factura:
|
||||||
|
* A. rand cu scc NULL -> dublu click pe Partener credit: SQL-ul ajuns la executor e NULL (BUG)
|
||||||
|
* B. acelasi rand cu scc = '401' -> dublu click: SQL valid (comportamentul ramurii cu valuta)
|
||||||
|
*
|
||||||
|
* Rulare: powershell -ExecutionPolicy Bypass -File test_repro_partener_scc_null.ps1
|
||||||
|
|
||||||
|
SET SAFETY OFF
|
||||||
|
SET TALK OFF
|
||||||
|
SET DELETED ON
|
||||||
|
SET EXACT ON
|
||||||
|
SET CENTURY ON
|
||||||
|
SET DATE DMY
|
||||||
|
SET DECIMALS TO 4
|
||||||
|
SET NULLDISPLAY TO ''
|
||||||
|
CLOSE DATABASES
|
||||||
|
|
||||||
|
PUBLIC gcUILog
|
||||||
|
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_repro_partener_scc_null_log.txt"
|
||||||
|
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||||
|
|
||||||
|
PUBLIC gnAsserts, gnPass, gcSqlPrimit, glSqlNull, gnApeluri
|
||||||
|
STORE 0 TO gnAsserts, gnPass, gnApeluri
|
||||||
|
gcSqlPrimit = ''
|
||||||
|
glSqlNull = .F.
|
||||||
|
|
||||||
|
ON ERROR DO PnErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||||
|
ON SHUTDOWN QUIT
|
||||||
|
|
||||||
|
TRY
|
||||||
|
LOCAL gcAppPath, lcPath
|
||||||
|
gcAppPath = "D:\ROA\ROAGEST\"
|
||||||
|
SET DEFAULT TO (gcAppPath)
|
||||||
|
|
||||||
|
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||||
|
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||||
|
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||||
|
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||||
|
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||||
|
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||||
|
SET PATH TO &lcPath ADDITIVE
|
||||||
|
DO PnLog WITH 'SET PATH OK'
|
||||||
|
|
||||||
|
*----- CLASE -----
|
||||||
|
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||||
|
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||||
|
SET CLASSLIB TO CAUT ADDITIVE
|
||||||
|
SET CLASSLIB TO BAZA ADDITIVE
|
||||||
|
SET CLASSLIB TO comun ADDITIVE
|
||||||
|
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO messagebox ADDITIVE
|
||||||
|
SET CLASSLIB TO registry ADDITIVE
|
||||||
|
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||||
|
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||||
|
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||||
|
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||||
|
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||||
|
SET CLASSLIB TO overificari ADDITIVE
|
||||||
|
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||||
|
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO caut_ora ADDITIVE
|
||||||
|
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||||
|
SET CLASSLIB TO otoolbar ADDITIVE
|
||||||
|
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||||
|
SET CLASSLIB TO onom_articole ADDITIVE
|
||||||
|
SET CLASSLIB TO onom_retete ADDITIVE
|
||||||
|
SET CLASSLIB TO orapoarte ADDITIVE
|
||||||
|
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||||
|
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||||
|
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||||
|
SET CLASSLIB TO ctl32_statusbar_fals.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ctl32_balloontip.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||||
|
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||||
|
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||||
|
DO PnLog WITH 'SET CLASSLIB OK'
|
||||||
|
|
||||||
|
*----- PROCEDURI (mock-urile PRIMELE) -----
|
||||||
|
SET PROCEDURE TO PROCEDURI
|
||||||
|
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||||
|
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||||
|
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||||
|
SET PROCEDURE TO pmenu ADDITIVE
|
||||||
|
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||||
|
SET PROCEDURE TO quitapp ADDITIVE
|
||||||
|
SET PROCEDURE TO init_program ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO mesaje ADDITIVE
|
||||||
|
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO validare.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||||
|
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||||
|
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO osecurity ADDITIVE
|
||||||
|
SET PROCEDURE TO ocautare ADDITIVE
|
||||||
|
SET PROCEDURE TO orefaceri ADDITIVE
|
||||||
|
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO ini.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO regex.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO version.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||||
|
DO PnLog WITH 'SET PROCEDURE OK'
|
||||||
|
|
||||||
|
*----- Globale -----
|
||||||
|
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPPretV, gnPPretVal
|
||||||
|
STORE 2 TO gnPc, gnPval
|
||||||
|
gnPcant = 3
|
||||||
|
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||||
|
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||||
|
gl406 = .T.
|
||||||
|
gcS = 'CONTAFIN'
|
||||||
|
gnAn = YEAR(DATE())
|
||||||
|
gnLuna = MONTH(DATE())
|
||||||
|
gnIdFirma = 110
|
||||||
|
gnIdSucursala = 110
|
||||||
|
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||||
|
gcFirma = gcS
|
||||||
|
PUBLIC nror(65000)
|
||||||
|
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
|
||||||
|
gnMockRaspuns = 6
|
||||||
|
gcMockUltimMesaj = ''
|
||||||
|
gnMockUltimTip = 0
|
||||||
|
PUBLIC gnButon, gcTempPath, gnHandle, gnTipGest, gcCondSucursala
|
||||||
|
gnButon = 1
|
||||||
|
gcTempPath = ADDBS(SYS(2023))
|
||||||
|
gnHandle = -1
|
||||||
|
gnTipGest = 0
|
||||||
|
gcCondSucursala = ''
|
||||||
|
|
||||||
|
PUBLIC goExecutor, goApp
|
||||||
|
goExecutor = CREATEOBJECT('spionexecutor')
|
||||||
|
goApp = CREATEOBJECT('dummyapp')
|
||||||
|
|
||||||
|
*----- poAct: antetul notei interne (lei) -----
|
||||||
|
PUBLIC poAct
|
||||||
|
poAct = CREATEOBJECT('Custom')
|
||||||
|
poAct.AddProperty('nume_val', '')
|
||||||
|
poAct.AddProperty('curs', 1)
|
||||||
|
poAct.AddProperty('proc_tva', 1.21)
|
||||||
|
poAct.AddProperty('nnir', 0)
|
||||||
|
poAct.AddProperty('id_valuta', 0)
|
||||||
|
poAct.AddProperty('id_fdoc', 1)
|
||||||
|
poAct.AddProperty('fdoc', 'FACTURA')
|
||||||
|
poAct.AddProperty('id_partc', 463)
|
||||||
|
poAct.AddProperty('partc', 'R.A.J.A. C-TA')
|
||||||
|
poAct.AddProperty('serie_act', '')
|
||||||
|
poAct.AddProperty('dataact', DATE())
|
||||||
|
poAct.AddProperty('tva_incasare', 1)
|
||||||
|
poAct.AddProperty('id_set', 1)
|
||||||
|
poAct.AddProperty('id_gestin', 1)
|
||||||
|
|
||||||
|
IF USED('jtva_coloane2')
|
||||||
|
USE IN ('jtva_coloane2')
|
||||||
|
ENDIF
|
||||||
|
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||||
|
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||||
|
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||||
|
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. NEEX. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||||
|
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. NEEX. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||||
|
|
||||||
|
IF USED('saft_taxtable')
|
||||||
|
USE IN ('saft_taxtable')
|
||||||
|
ENDIF
|
||||||
|
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||||
|
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||||
|
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||||
|
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||||
|
INDEX ON taxcode TAG taxcode
|
||||||
|
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||||
|
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||||
|
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||||
|
VALUES ('301104-Achizitii interne cota 21%', 301104, '', 21, 1, 0, 1, 0)
|
||||||
|
|
||||||
|
*----- introdc gol + sablonul notei interne: contul creditor (scc) vine NULL din nomenclator -----
|
||||||
|
DO CreeazaIntrodcNull WITH 'introdc'
|
||||||
|
DO CreeazaIntrodcNull WITH 'introdc_sablon'
|
||||||
|
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||||
|
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||||
|
VALUES ('371', .NULL., 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. NEEX. 21%')
|
||||||
|
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||||
|
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||||
|
VALUES ('4428', .NULL., 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. NEEX. 21%')
|
||||||
|
GO TOP IN introdc_sablon
|
||||||
|
|
||||||
|
IF USED('rul_temp')
|
||||||
|
USE IN ('rul_temp')
|
||||||
|
ENDIF
|
||||||
|
CREATE CURSOR rul_temp (denumire C(100), codmat C(30), cant N(14,3), pret_val N(18,4), ;
|
||||||
|
pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), acont C(20), serie C(30), ;
|
||||||
|
lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||||
|
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||||
|
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||||
|
|
||||||
|
SELECT introdc
|
||||||
|
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||||
|
SET ORDER TO ord_doc
|
||||||
|
|
||||||
|
PRIVATE tlIntern
|
||||||
|
tlIntern = .T.
|
||||||
|
|
||||||
|
DO PnLog WITH 'CREATEOBJECT(import_nota, .T. - achizitie interna)'
|
||||||
|
SELECT introdc
|
||||||
|
PUBLIC goObj
|
||||||
|
goObj = CREATEOBJECT('IMPORT_nota', .T.)
|
||||||
|
IF VARTYPE(goObj) <> 'O'
|
||||||
|
DO PnLog WITH 'FAIL: instantiere import_nota'
|
||||||
|
QUIT
|
||||||
|
ENDIF
|
||||||
|
goObj.lDialogAratat = .T.
|
||||||
|
goObj.oact = poAct
|
||||||
|
goObj.WindowType = 0
|
||||||
|
goObj.Visible = .T.
|
||||||
|
goObj.Show()
|
||||||
|
goObj.WindowState = 2
|
||||||
|
DOEVENTS FORCE
|
||||||
|
|
||||||
|
SELECT rul_temp
|
||||||
|
ZAP
|
||||||
|
goObj.gridart.Refresh()
|
||||||
|
DOEVENTS FORCE
|
||||||
|
|
||||||
|
*========================= factura interna, prin dialogul real =========================
|
||||||
|
PUBLIC goDlg
|
||||||
|
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||||
|
goDlg.cFelDoc = 'FACTURA'
|
||||||
|
goDlg.nIdFdoc = 1
|
||||||
|
goDlg.nNract = 15000
|
||||||
|
goDlg.dDataAct = DATE()
|
||||||
|
goDlg.nIdPartener = 463
|
||||||
|
goDlg.cPartener = 'R.A.J.A. C-TA'
|
||||||
|
goDlg.cExplicatia = 'Achizitie interna'
|
||||||
|
goDlg.nSuma = 1000
|
||||||
|
goDlg.nSumaLei = 0
|
||||||
|
goDlg.nCurs = 0
|
||||||
|
goDlg.nIdValuta = 0
|
||||||
|
goDlg.cValuta = ''
|
||||||
|
goDlg.chkInValutaCont.Value = 0
|
||||||
|
goDlg.chkParticipaValuta.Value = 1
|
||||||
|
goDlg.nIdExplicatieTva = 208
|
||||||
|
goDlg.cExplicatieTva = 'ACH. INT. NEEX. 21%'
|
||||||
|
goDlg.nProcentTva = 21
|
||||||
|
goDlg.optTipTva.Value = 1
|
||||||
|
goDlg.optTipTva.InteractiveChange()
|
||||||
|
goDlg.WindowType = 0
|
||||||
|
goDlg.Visible = .T.
|
||||||
|
goDlg.Show()
|
||||||
|
DOEVENTS FORCE
|
||||||
|
DO PnLog WITH 'dialog completat, valideaza() = ' + TRANSFORM(goDlg.valideaza())
|
||||||
|
|
||||||
|
PUBLIC goT
|
||||||
|
goT = CREATEOBJECT('Empty')
|
||||||
|
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||||
|
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||||
|
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||||
|
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||||
|
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||||
|
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||||
|
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||||
|
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||||
|
=ADDPROPERTY(goT,'suma',goDlg.nSuma)
|
||||||
|
=ADDPROPERTY(goT,'suma_val',0)
|
||||||
|
=ADDPROPERTY(goT,'in_valuta',0)
|
||||||
|
=ADDPROPERTY(goT,'participa_valuta',.T.)
|
||||||
|
=ADDPROPERTY(goT,'id_valuta',0)
|
||||||
|
=ADDPROPERTY(goT,'curs',0)
|
||||||
|
=ADDPROPERTY(goT,'nume_val','')
|
||||||
|
=ADDPROPERTY(goT,'cTipTva','F')
|
||||||
|
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||||
|
=ADDPROPERTY(goT,'disc_baza_lei',0)
|
||||||
|
=ADDPROPERTY(goT,'disc_baza_val',0)
|
||||||
|
DO PnLog WITH 'do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||||
|
goDlg.Hide()
|
||||||
|
DOEVENTS FORCE
|
||||||
|
|
||||||
|
DO DumpIntrodc
|
||||||
|
|
||||||
|
*========================= SCENARIU A: scc NULL (asa vine din nota interna) =========================
|
||||||
|
SELECT introdc
|
||||||
|
LOCATE FOR tip_rand == 'B'
|
||||||
|
DO Assert WITH 'A0-randul B al facturii exista', IIF(FOUND(),1,0), 1
|
||||||
|
DO Assert WITH 'A1-introdc.scc este NULL pe randul B (ca in nota interna)', IIF(ISNULL(introdc.scc),1,0), 1
|
||||||
|
|
||||||
|
gcSqlPrimit = ''
|
||||||
|
glSqlNull = .F.
|
||||||
|
gnApeluri = 0
|
||||||
|
DO PnLog WITH 'SCENARIU A: dublu click pe Partener credit, cu scc NULL'
|
||||||
|
TRY
|
||||||
|
goObj.Grid1.cPartC.Text1.DblClick()
|
||||||
|
CATCH TO loExcA
|
||||||
|
DO PnLog WITH ' EXCEPTIE ' + TRANSFORM(loExcA.ErrorNo) + ' [' + loExcA.Message + '] in ' + loExcA.Procedure + ':' + TRANSFORM(loExcA.LineNo)
|
||||||
|
ENDTRY
|
||||||
|
DOEVENTS FORCE
|
||||||
|
DO PnLog WITH ' apeluri executor = ' + TRANSFORM(gnApeluri) + ' SQL NULL/gol = ' + TRANSFORM(glSqlNull)
|
||||||
|
DO Assert WITH 'A2-executorul NU primeste SQL NULL/gol la dublu click (scc NULL)', IIF(glSqlNull,1,0), 0
|
||||||
|
SELECT introdc
|
||||||
|
LOCATE FOR tip_rand == 'B'
|
||||||
|
DO Assert WITH 'A3-partenerul randului ramane neschimbat dupa dublu click (scc NULL)', NVL(introdc.id_partc,0), 463
|
||||||
|
|
||||||
|
*========================= SCENARIU B: scc = 401 (ca pe ramura cu valuta) =========================
|
||||||
|
SELECT introdc
|
||||||
|
LOCATE FOR tip_rand == 'B'
|
||||||
|
REPLACE scc WITH '401'
|
||||||
|
gcSqlPrimit = ''
|
||||||
|
glSqlNull = .F.
|
||||||
|
gnApeluri = 0
|
||||||
|
DO PnLog WITH 'SCENARIU B: dublu click pe Partener credit, cu scc = 401'
|
||||||
|
TRY
|
||||||
|
goObj.Grid1.cPartC.Text1.DblClick()
|
||||||
|
CATCH TO loExcB
|
||||||
|
DO PnLog WITH ' EXCEPTIE ' + TRANSFORM(loExcB.ErrorNo) + ' [' + loExcB.Message + '] in ' + loExcB.Procedure + ':' + TRANSFORM(loExcB.LineNo)
|
||||||
|
ENDTRY
|
||||||
|
DOEVENTS FORCE
|
||||||
|
DO PnLog WITH ' apeluri executor = ' + TRANSFORM(gnApeluri) + ' SQL NULL/gol = ' + TRANSFORM(glSqlNull)
|
||||||
|
DO PnLog WITH ' ultimul SQL = [' + LEFT(NVL(gcSqlPrimit,'<NULL>'), 200) + ']'
|
||||||
|
DO Assert WITH 'B1-executorul NU primeste SQL NULL/gol la dublu click (scc = 401)', IIF(glSqlNull,1,0), 0
|
||||||
|
|
||||||
|
DO PnLog WITH '========================================================='
|
||||||
|
DO PnLog WITH 'REZULTAT: ' + TRANSFORM(gnPass) + '/' + TRANSFORM(gnAsserts) + ' assert-uri PASS'
|
||||||
|
IF gnPass = gnAsserts
|
||||||
|
DO PnLog WITH 'REZULTAT: PASS'
|
||||||
|
ELSE
|
||||||
|
DO PnLog WITH 'REZULTAT: FAIL'
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
CATCH TO loExc
|
||||||
|
DO PnLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||||
|
ENDTRY
|
||||||
|
|
||||||
|
QUIT
|
||||||
|
|
||||||
|
*==================================================================================
|
||||||
|
PROCEDURE PnLog
|
||||||
|
LPARAMETERS tcMsg
|
||||||
|
SET SAFETY OFF
|
||||||
|
LOCAL lcL
|
||||||
|
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||||
|
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE PnErr
|
||||||
|
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||||
|
DO PnLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE Assert
|
||||||
|
LPARAMETERS tcNume, tnActual, tnAsteptat
|
||||||
|
gnAsserts = gnAsserts + 1
|
||||||
|
IF tnActual = tnAsteptat
|
||||||
|
gnPass = gnPass + 1
|
||||||
|
DO PnLog WITH ' PASS ' + tcNume
|
||||||
|
ELSE
|
||||||
|
DO PnLog WITH ' FAIL ' + tcNume + ' (actual=' + TRANSFORM(tnActual) + ', asteptat=' + TRANSFORM(tnAsteptat) + ')'
|
||||||
|
ENDIF
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE DumpIntrodc
|
||||||
|
LOCAL lnSel
|
||||||
|
lnSel = SELECT()
|
||||||
|
DO PnLog WITH 'DUMP introdc:'
|
||||||
|
SELECT introdc
|
||||||
|
SCAN
|
||||||
|
DO PnLog WITH ' recno=' + TRANSFORM(RECNO()) + ' tip_rand=' + tip_rand + ' nract=' + TRANSFORM(nract) + ;
|
||||||
|
' scd=[' + NVL(ALLTRIM(scd),'<NULL>') + '] scc=' + IIF(ISNULL(scc),'<NULL>','[' + ALLTRIM(NVL(scc,'')) + ']') + ;
|
||||||
|
' id_partc=' + TRANSFORM(NVL(id_partc,0)) + ' partc=[' + ALLTRIM(NVL(partc,'')) + '] suma=' + TRANSFORM(suma)
|
||||||
|
ENDSCAN
|
||||||
|
SELECT (lnSel)
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
*-- introdc ca in productie: coloanele de conturi vin NULLABLE din Oracle (vnote_contabile)
|
||||||
|
PROCEDURE CreeazaIntrodcNull
|
||||||
|
LPARAMETERS tcAlias
|
||||||
|
IF USED(tcAlias)
|
||||||
|
USE IN (tcAlias)
|
||||||
|
ENDIF
|
||||||
|
CREATE CURSOR (tcAlias) ( ;
|
||||||
|
id_note N(14), explicatia C(100), scd C(10) NULL, ascd C(20) NULL, scc C(10) NULL, ascc C(20) NULL, ;
|
||||||
|
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||||
|
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||||
|
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||||
|
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||||
|
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||||
|
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||||
|
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||||
|
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||||
|
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE CreeazaJtvaColoaneView
|
||||||
|
LPARAMETERS tcCursor
|
||||||
|
IF USED(m.tcCursor)
|
||||||
|
USE IN (m.tcCursor)
|
||||||
|
ENDIF
|
||||||
|
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||||
|
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||||
|
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||||
|
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||||
|
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||||
|
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||||
|
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||||
|
VALUES (208, 'ACH. INT. NEEX. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||||
|
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||||
|
VALUES (209, 'TVA ACH. INT. NEEX. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
DEFINE CLASS dummyapp AS Custom
|
||||||
|
PROCEDURE ReadIni
|
||||||
|
LPARAMETERS tcSection, tcKey
|
||||||
|
RETURN ''
|
||||||
|
ENDPROC
|
||||||
|
PROCEDURE WriteIni
|
||||||
|
LPARAMETERS tcSection, tcKey, tcValue
|
||||||
|
RETURN .T.
|
||||||
|
ENDPROC
|
||||||
|
ENDDEFINE
|
||||||
|
|
||||||
|
*-- Acelasi contract ca oExecutor.oExecute pe parametrul SQL: in productie, un statement
|
||||||
|
*-- NULL/gol ajunge la SQLEXEC si da eroarea 1466. Aici doar il inregistram.
|
||||||
|
DEFINE CLASS spionexecutor AS Custom
|
||||||
|
cEroare = ''
|
||||||
|
PROCEDURE oExecute
|
||||||
|
LPARAMETERS tcSql, tcCursor
|
||||||
|
gnApeluri = gnApeluri + 1
|
||||||
|
gcSqlPrimit = tcSql
|
||||||
|
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
|
||||||
|
glSqlNull = .T.
|
||||||
|
DO PnLog WITH ' >>> executor: SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL') + ;
|
||||||
|
' (EMPTY(tcSql)=' + TRANSFORM(EMPTY(m.tcSql)) + ' - garda din oExecute nu il prinde)'
|
||||||
|
RETURN -1
|
||||||
|
ENDIF
|
||||||
|
IF !EMPTY(m.tcCursor) AND USED(m.tcCursor)
|
||||||
|
USE IN (m.tcCursor)
|
||||||
|
ENDIF
|
||||||
|
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||||
|
CREATE CURSOR (m.tcCursor) (valoare N(10))
|
||||||
|
INSERT INTO (m.tcCursor) VALUES (0)
|
||||||
|
RETURN 1
|
||||||
|
ENDIF
|
||||||
|
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||||
|
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||||
|
RETURN 1
|
||||||
|
ENDIF
|
||||||
|
IF UPPER(ALLTRIM(NVL(m.tcCursor,''))) == 'RUL_TEMP'
|
||||||
|
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||||
|
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||||
|
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||||
|
RETURN 1
|
||||||
|
ENDIF
|
||||||
|
IF !EMPTY(m.tcCursor)
|
||||||
|
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||||
|
ENDIF
|
||||||
|
RETURN 1
|
||||||
|
ENDPROC
|
||||||
|
PROCEDURE oExecuta
|
||||||
|
LPARAMETERS tcSql, tcCursor
|
||||||
|
gnApeluri = gnApeluri + 1
|
||||||
|
gcSqlPrimit = tcSql
|
||||||
|
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
|
||||||
|
glSqlNull = .T.
|
||||||
|
DO PnLog WITH ' >>> executor(oExecuta): SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL')
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
IF !EMPTY(m.tcCursor)
|
||||||
|
IF USED(m.tcCursor)
|
||||||
|
USE IN (m.tcCursor)
|
||||||
|
ENDIF
|
||||||
|
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||||
|
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||||
|
ELSE
|
||||||
|
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
RETURN .T.
|
||||||
|
ENDPROC
|
||||||
|
PROCEDURE oSelect2Value
|
||||||
|
LPARAMETERS tcSql, toValue
|
||||||
|
gnApeluri = gnApeluri + 1
|
||||||
|
gcSqlPrimit = tcSql
|
||||||
|
IF ISNULL(m.tcSql) OR EMPTY(NVL(m.tcSql,''))
|
||||||
|
glSqlNull = .T.
|
||||||
|
DO PnLog WITH ' >>> executor(oSelect2Value): SQL ' + IIF(ISNULL(m.tcSql),'NULL','GOL')
|
||||||
|
RETURN -1
|
||||||
|
ENDIF
|
||||||
|
toValue = ''
|
||||||
|
RETURN 1
|
||||||
|
ENDPROC
|
||||||
|
PROCEDURE oReset
|
||||||
|
ENDPROC
|
||||||
|
ENDDEFINE
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# test_repro_partener_scc_null.ps1 - rulare headless (fara harness/screenshots) a testului de
|
||||||
|
# reproducere pentru dublu click pe "Partener credit" cu contul creditor NULL.
|
||||||
|
# Rulare: powershell -ExecutionPolicy Bypass -File test_repro_partener_scc_null.ps1
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$Teste = $PSScriptRoot
|
||||||
|
$Prg = Join-Path $Teste 'test_repro_partener_scc_null.prg'
|
||||||
|
$Fxp = [IO.Path]::ChangeExtension($Prg, '.fxp')
|
||||||
|
$Log = Join-Path $Teste 'test_repro_partener_scc_null_log.txt'
|
||||||
|
$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
|
||||||
|
|
||||||
|
Remove-Item $Fxp, $Log -ErrorAction SilentlyContinue
|
||||||
|
$p = Start-Process -FilePath $Vfp -ArgumentList '-A', '-T', "`"$Prg`"" -PassThru
|
||||||
|
if (-not $p.WaitForExit(240000)) {
|
||||||
|
$p.Kill()
|
||||||
|
throw 'TIMEOUT: testul nu s-a terminat in 240s'
|
||||||
|
}
|
||||||
|
if (-not (Test-Path $Log)) { throw "Lipseste logul $Log" }
|
||||||
|
Get-Content $Log
|
||||||
223
utile/Teste/partener_anaf/test_repro_anaf_path_nfjson.prg
Normal file
223
utile/Teste/partener_anaf/test_repro_anaf_path_nfjson.prg
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
* test_repro_anaf_path_nfjson.prg
|
||||||
|
* REPRODUCERE: in ROAGEST, la alegerea partenerului, banda arata mereu
|
||||||
|
* "ANAF nu a raspuns - verificare sarita", desi ANAF raspunde 200 pe aceeasi masina.
|
||||||
|
* Ipoteza testata: SET PATH din Programe\roagest.prg NU contine COMUN\UTILE\NFJSON,
|
||||||
|
* deci VerificareANAF.Init (validare.prg:1877, "Set Procedure To nfjsonread.prg Additive")
|
||||||
|
* arunca, CREATEOBJECT('VerificareANAF') esueaza in ANAF_VerificaCuiSingle si clasa de
|
||||||
|
* esec devine FARA_RASPUNS -> banda gri + serviciul ANAF marcat CAZUT pentru 10 minute.
|
||||||
|
*
|
||||||
|
* Scenarii:
|
||||||
|
* A. path ca in roagest.prg (fara NFJSON) -> CREATEOBJECT esueaza, clasa esec = FARA_RASPUNS
|
||||||
|
* B. acelasi path + COMUN\UTILE\NFJSON -> verdict ANAF real pentru CUI 13791411 (ARAFURA)
|
||||||
|
*
|
||||||
|
* Rulare: powershell -ExecutionPolicy Bypass -File test_repro_anaf_path_nfjson.ps1
|
||||||
|
|
||||||
|
SET SAFETY OFF
|
||||||
|
SET TALK OFF
|
||||||
|
SET DELETED ON
|
||||||
|
SET EXACT ON
|
||||||
|
SET CENTURY ON
|
||||||
|
SET DATE DMY
|
||||||
|
SET DECIMALS TO 4
|
||||||
|
SET NULLDISPLAY TO ''
|
||||||
|
CLOSE DATABASES
|
||||||
|
|
||||||
|
PUBLIC gcUILog, gnAsserts, gnPass
|
||||||
|
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\partener_anaf\test_repro_anaf_path_nfjson_log.txt"
|
||||||
|
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||||
|
STORE 0 TO gnAsserts, gnPass
|
||||||
|
|
||||||
|
ON ERROR DO PnErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||||
|
ON SHUTDOWN QUIT
|
||||||
|
|
||||||
|
LOCAL lcCui, llNegasit, lcClasa, loRez, loEx, lcPath, gcAppPath
|
||||||
|
lcCui = '13791411'
|
||||||
|
|
||||||
|
TRY
|
||||||
|
*----- SET PATH exact ca in Programe\roagest.prg (fara COMUN\UTILE\NFJSON) -----
|
||||||
|
gcAppPath = "D:\ROA\ROAGEST\"
|
||||||
|
SET DEFAULT TO (gcAppPath)
|
||||||
|
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||||
|
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||||
|
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||||
|
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||||
|
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||||
|
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||||
|
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||||
|
SET PATH TO &lcPath
|
||||||
|
DO PnLog WITH 'SET PATH (ca in roagest.prg) OK'
|
||||||
|
|
||||||
|
SET PROCEDURE TO validare.prg
|
||||||
|
SET PROCEDURE TO ocautare.prg ADDITIVE
|
||||||
|
SET PROCEDURE TO regex.prg ADDITIVE
|
||||||
|
DO PnLog WITH 'SET PROCEDURE OK: ' + SET('Procedure')
|
||||||
|
|
||||||
|
PUBLIC gnIdUtil, goExecutor, goLog, poLog
|
||||||
|
gnIdUtil = -3
|
||||||
|
goExecutor = CREATEOBJECT('executor_spion')
|
||||||
|
LOCAL lcLogApp
|
||||||
|
lcLogApp = "D:\ROA\ROAGEST\COMUN\utile\Teste\partener_anaf\test_repro_anaf_path_nfjson_applog.txt"
|
||||||
|
STRTOFILE('', lcLogApp)
|
||||||
|
poLog = NEWOBJECT("Log_Mesaje", "Log_Mesaje.prg", "", lcLogApp)
|
||||||
|
goLog = poLog
|
||||||
|
|
||||||
|
*===== A1: CREATEOBJECT('VerificareANAF') pe path-ul din roagest.prg =====
|
||||||
|
loEx = .NULL.
|
||||||
|
TRY
|
||||||
|
LOCAL loVerif
|
||||||
|
loVerif = CREATEOBJECT('VerificareANAF')
|
||||||
|
DO PnLog WITH 'A1 CREATEOBJECT(VerificareANAF): OK (nu reproduce)'
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'A1 CREATEOBJECT(VerificareANAF): EXCEPTIE ' + loEx.Message + ;
|
||||||
|
' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
DO PnAssert WITH 'A1 VerificareANAF nu se poate instantia fara NFJSON pe path', !ISNULL(loEx)
|
||||||
|
|
||||||
|
*===== A2: fluxul real ANAF_VerificaCuiSingle -> clasa de esec =====
|
||||||
|
llNegasit = .F.
|
||||||
|
lcClasa = ''
|
||||||
|
loRez = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegasit, @lcClasa)
|
||||||
|
DO PnLog WITH 'A2 ANAF_VerificaCuiSingle: VARTYPE=' + VARTYPE(loRez) + ;
|
||||||
|
' negasit=' + TRANSFORM(llNegasit) + ' clasa_esec=[' + lcClasa + ']'
|
||||||
|
DO PnAssert WITH 'A2 clasa esec = FARA_RASPUNS (banda "ANAF nu a raspuns")', lcClasa == 'FARA_RASPUNS'
|
||||||
|
|
||||||
|
*===== A3: banda din ocautare - ANAF_StarePartener pe acelasi cod =====
|
||||||
|
LOCAL llNecesita, lcClasa3, loStare3
|
||||||
|
llNecesita = .F.
|
||||||
|
llNegasit = .F.
|
||||||
|
lcClasa3 = ''
|
||||||
|
loStare3 = ANAF_StarePartener(m.lcCui, DATE(), .F., @llNecesita, @llNegasit, @lcClasa3, 0)
|
||||||
|
DO PnLog WITH 'A3 ANAF_StarePartener: VARTYPE=' + VARTYPE(loStare3) + ' clasa_esec=[' + lcClasa3 + ']' + ;
|
||||||
|
' stare_serviciu=' + ANAF_StareServiciu()
|
||||||
|
DO PnAssert WITH 'A3 stare serviciu ANAF = CAZUT dupa primul cod', ANAF_StareServiciu() == 'CAZUT'
|
||||||
|
|
||||||
|
*===== B: acelasi mediu + COMUN\UTILE\NFJSON pe path =====
|
||||||
|
SET PATH TO (gcAppPath + 'COMUN\UTILE\NFJSON') ADDITIVE
|
||||||
|
DO PnLog WITH 'B SET PATH ... COMUN\UTILE\NFJSON ADDITIVE'
|
||||||
|
RELEASE goCacheANAF_Sesiune
|
||||||
|
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reluare scenariu B')
|
||||||
|
|
||||||
|
loEx = .NULL.
|
||||||
|
TRY
|
||||||
|
LOCAL loVerifB
|
||||||
|
loVerifB = CREATEOBJECT('VerificareANAF')
|
||||||
|
DO PnLog WITH 'B1 CREATEOBJECT(VerificareANAF): OK'
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'B1 CREATEOBJECT(VerificareANAF): EXCEPTIE ' + loEx.Message
|
||||||
|
ENDTRY
|
||||||
|
DO PnAssert WITH 'B1 VerificareANAF se instantiaza cu NFJSON pe path', ISNULL(loEx)
|
||||||
|
|
||||||
|
llNegasit = .F.
|
||||||
|
lcClasa = ''
|
||||||
|
loRez = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegasit, @lcClasa)
|
||||||
|
IF VARTYPE(loRez) = 'O'
|
||||||
|
DO PnLog WITH 'B2 ANAF_VerificaCuiSingle: denumire=[' + ALLTRIM(NVL(loRez.denumire, '')) + ;
|
||||||
|
'] scpTVA=' + TRANSFORM(loRez.scpTVA) + ' clasa_esec=[' + lcClasa + ']'
|
||||||
|
ELSE
|
||||||
|
DO PnLog WITH 'B2 ANAF_VerificaCuiSingle: VARTYPE=' + VARTYPE(loRez) + ' clasa_esec=[' + lcClasa + ']'
|
||||||
|
ENDIF
|
||||||
|
DO PnAssert WITH 'B2 verdict ANAF primit pentru ' + m.lcCui, VARTYPE(loRez) = 'O'
|
||||||
|
DO PnAssert WITH 'B3 denumire ANAF = ARAFURA', VARTYPE(loRez) = 'O' AND 'ARAFURA' $ UPPER(ALLTRIM(NVL(loRez.denumire, '')))
|
||||||
|
|
||||||
|
*===== C: corpul lui ANAF_VerificaCuiSingle replicat inline, pas cu pas =====
|
||||||
|
LOCAL loVerifC, loHttpC, lcJson, loParsed, lnSalvate, llNegC, lcClasaC, loRezC
|
||||||
|
loVerifC = CREATEOBJECT('VerificareANAF')
|
||||||
|
TRY
|
||||||
|
loHttpC = ANAF_CreeazaCerereANAF(INT(VAL(m.lcCui)), DATE(), .F.)
|
||||||
|
lcJson = ALLTRIM(loHttpC.responseText)
|
||||||
|
DO PnLog WITH 'C1 ANAF_CreeazaCerereANAF: Status=' + TRANSFORM(loHttpC.Status) + ' raspuns(120)=' + LEFT(lcJson, 120)
|
||||||
|
CATCH TO loEx
|
||||||
|
lcJson = ''
|
||||||
|
DO PnLog WITH 'C1 ANAF_CreeazaCerereANAF: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
TRY
|
||||||
|
loParsed = nfjsonread(m.lcJson)
|
||||||
|
DO PnLog WITH 'C2 nfjsonread: OK, TYPE=' + VARTYPE(loParsed)
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'C2 nfjsonread: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
TRY
|
||||||
|
USE IN (SELECT('crsANAFDiag'))
|
||||||
|
loVerifC.ParseJsonANAFv8(loParsed, 'crsANAFDiag')
|
||||||
|
DO PnLog WITH 'C3 ParseJsonANAFv8: OK, RECCOUNT=' + IIF(USED('crsANAFDiag'), TRANSFORM(RECCOUNT('crsANAFDiag')), '-')
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'C3 ParseJsonANAFv8: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
TRY
|
||||||
|
lnSalvate = loVerifC.SalveazaIstoricDinCursor('crsANAFDiag', gnIdUtil)
|
||||||
|
DO PnLog WITH 'C4 SalveazaIstoricDinCursor: OK, salvate=' + TRANSFORM(lnSalvate)
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'C4 SalveazaIstoricDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
TRY
|
||||||
|
llNegC = .F.
|
||||||
|
lcClasaC = ''
|
||||||
|
loRezC = ANAF_VerdictDinCursor('crsANAFDiag', INT(VAL(m.lcCui)), @llNegC, @lcClasaC)
|
||||||
|
DO PnLog WITH 'C5 ANAF_VerdictDinCursor: VARTYPE=' + VARTYPE(loRezC) + ' negasit=' + TRANSFORM(llNegC) + ;
|
||||||
|
' clasa=[' + lcClasaC + ']' + IIF(VARTYPE(loRezC) = 'O', ' denumire=[' + ALLTRIM(NVL(loRezC.denumire, '')) + ']', '')
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'C5 ANAF_VerdictDinCursor: EXCEPTIE ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
|
||||||
|
*===== D: path-ul REAL, construit din blocul lcPath din Programe\roagest.prg =====
|
||||||
|
LOCAL lcSursa, lnStart, lnStop, lcBloc, lcScript, lcPathReal, loVerifD, loRezD, lcClasaD, llNegD
|
||||||
|
lcSursa = FILETOSTR("D:\ROA\ROAGEST\Programe\roagest.prg")
|
||||||
|
lnStart = ATC("lcPath = gcAppPath + 'Date;'", lcSursa)
|
||||||
|
lnStop = ATC("COMUNROA\]", SUBSTR(lcSursa, lnStart)) + lnStart - 1
|
||||||
|
lcBloc = SUBSTR(lcSursa, lnStart, lnStop - lnStart + LEN("COMUNROA\]"))
|
||||||
|
lcScript = "LPARAMETERS gcAppPath" + CHR(13)+CHR(10) + "LOCAL lcPath" + CHR(13)+CHR(10) + ;
|
||||||
|
lcBloc + CHR(13)+CHR(10) + "RETURN lcPath"
|
||||||
|
lcPathReal = EXECSCRIPT(lcScript, gcAppPath)
|
||||||
|
DO PnLog WITH 'D path din roagest.prg: ' + lcPathReal
|
||||||
|
RELEASE PROCEDURE nfjsonread.prg, nfjsoncreate.prg
|
||||||
|
RELEASE goCacheANAF_Sesiune
|
||||||
|
ANAF_SeteazaStareServiciu('NECUNOSCUT', 'reluare scenariu D')
|
||||||
|
SET PATH TO &lcPathReal
|
||||||
|
DO PnAssert WITH 'D1 nfjsonread descarcat inainte de test', !('NFJSONREAD' $ UPPER(SET('Procedure')))
|
||||||
|
|
||||||
|
llNegD = .F.
|
||||||
|
lcClasaD = ''
|
||||||
|
loRezD = ANAF_VerificaCuiSingle(m.lcCui, DATE(), @llNegD, @lcClasaD)
|
||||||
|
IF VARTYPE(loRezD) = 'O'
|
||||||
|
DO PnLog WITH 'D2 ANAF_VerificaCuiSingle pe path-ul real: denumire=[' + ALLTRIM(NVL(loRezD.denumire, '')) + '] clasa_esec=[' + lcClasaD + ']'
|
||||||
|
ELSE
|
||||||
|
DO PnLog WITH 'D2 ANAF_VerificaCuiSingle pe path-ul real: VARTYPE=' + VARTYPE(loRezD) + ' clasa_esec=[' + lcClasaD + ']'
|
||||||
|
ENDIF
|
||||||
|
DO PnAssert WITH 'D2 verdict ANAF pe path-ul din roagest.prg', VARTYPE(loRezD) = 'O'
|
||||||
|
DO PnAssert WITH 'D3 fara clasa de esec (banda arata verdictul, nu "ANAF nu a raspuns")', lcClasaD == ''
|
||||||
|
|
||||||
|
CATCH TO loEx
|
||||||
|
DO PnLog WITH 'EXCEPTIE NEPRINSA: ' + loEx.Message + ' [' + loEx.Procedure + ':' + TRANSFORM(loEx.LineNo) + ']'
|
||||||
|
ENDTRY
|
||||||
|
|
||||||
|
DO PnLog WITH 'REZULTAT: ' + TRANSFORM(gnPass) + '/' + TRANSFORM(gnAsserts) + ' PASS'
|
||||||
|
QUIT
|
||||||
|
|
||||||
|
PROCEDURE PnAssert
|
||||||
|
LPARAMETERS tcNume, tlOk
|
||||||
|
gnAsserts = gnAsserts + 1
|
||||||
|
IF tlOk
|
||||||
|
gnPass = gnPass + 1
|
||||||
|
ENDIF
|
||||||
|
DO PnLog WITH IIF(tlOk, 'PASS ', 'FAIL ') + tcNume
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE PnErr
|
||||||
|
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||||
|
DO PnLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
PROCEDURE PnLog
|
||||||
|
LPARAMETERS tcMsg
|
||||||
|
STRTOFILE(TRANSFORM(tcMsg) + CHR(13)+CHR(10), gcUILog, .T.)
|
||||||
|
ENDPROC
|
||||||
|
|
||||||
|
DEFINE CLASS executor_spion AS Custom
|
||||||
|
*-- tine locul lui goExecutor: salvarea in ISTORIC_CODURI_FISCALE nu face obiectul testului
|
||||||
|
PROCEDURE oExecuta
|
||||||
|
LPARAMETERS tcSql, tcAlias
|
||||||
|
RETURN .T.
|
||||||
|
ENDPROC
|
||||||
|
ENDDEFINE
|
||||||
18
utile/Teste/partener_anaf/test_repro_anaf_path_nfjson.ps1
Normal file
18
utile/Teste/partener_anaf/test_repro_anaf_path_nfjson.ps1
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# test_repro_anaf_path_nfjson.ps1 - rulare headless a testului de reproducere pentru
|
||||||
|
# "ANAF nu a raspuns - verificare sarita" in ROAGEST (COMUN\UTILE\NFJSON lipsa din SET PATH).
|
||||||
|
# Rulare: powershell -ExecutionPolicy Bypass -File test_repro_anaf_path_nfjson.ps1
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$Teste = $PSScriptRoot
|
||||||
|
$Prg = Join-Path $Teste 'test_repro_anaf_path_nfjson.prg'
|
||||||
|
$Fxp = [IO.Path]::ChangeExtension($Prg, '.fxp')
|
||||||
|
$Log = Join-Path $Teste 'test_repro_anaf_path_nfjson_log.txt'
|
||||||
|
$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
|
||||||
|
|
||||||
|
Remove-Item $Fxp, $Log -ErrorAction SilentlyContinue
|
||||||
|
$p = Start-Process -FilePath $Vfp -ArgumentList '-A', '-T', "`"$Prg`"" -PassThru
|
||||||
|
if (-not $p.WaitForExit(240000)) {
|
||||||
|
$p.Kill()
|
||||||
|
throw 'TIMEOUT: testul nu s-a terminat in 240s'
|
||||||
|
}
|
||||||
|
if (-not (Test-Path $Log)) { throw "Lipseste logul $Log" }
|
||||||
|
Get-Content $Log
|
||||||
62
utile/context_watch.ps1
Normal file
62
utile/context_watch.ps1
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# context_watch.ps1 - cat context ocupa sesiunea curenta Claude Code.
|
||||||
|
# Citeste ultimul "usage" din transcriptul JSONL al sesiunii (input + cache_read + cache_creation).
|
||||||
|
# Utilizare:
|
||||||
|
# - ca hook (PostToolUse): primeste pe stdin JSON-ul hook-ului, cu transcript_path;
|
||||||
|
# - manual: powershell -File context_watch.ps1 [-TranscriptPath <cale.jsonl>] [-Prag 250000]
|
||||||
|
# Iese cu 2 si scrie pe stderr cand contextul depaseste pragul (asa ajunge mesajul la agent).
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$TranscriptPath,
|
||||||
|
[int]$Prag = 250000,
|
||||||
|
[int]$PragMax = 275000,
|
||||||
|
[switch]$Intotdeauna,
|
||||||
|
[switch]$Stdout # UserPromptSubmit: mesajul se scrie pe stdout si se iese cu 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not $TranscriptPath) {
|
||||||
|
$stdin = [Console]::In.ReadToEnd()
|
||||||
|
if ($stdin) {
|
||||||
|
try { $TranscriptPath = (ConvertFrom-Json $stdin).transcript_path } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) {
|
||||||
|
$dir = Join-Path $env:USERPROFILE ".claude\projects\$((Get-Location).Path -replace '[:\\/]','-')"
|
||||||
|
if (Test-Path $dir) {
|
||||||
|
$f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||||
|
if ($f) { $TranscriptPath = $f.FullName }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) { exit 0 }
|
||||||
|
|
||||||
|
# doar coada fisierului - transcriptul poate avea zeci de MB
|
||||||
|
$fs = [IO.File]::Open($TranscriptPath, 'Open', 'Read', 'ReadWrite')
|
||||||
|
try {
|
||||||
|
$len = [Math]::Min(400KB, $fs.Length)
|
||||||
|
$fs.Seek(-$len, 'End') | Out-Null
|
||||||
|
$buf = New-Object byte[] $len
|
||||||
|
$fs.Read($buf, 0, $len) | Out-Null
|
||||||
|
} finally { $fs.Close() }
|
||||||
|
$coada = [Text.Encoding]::UTF8.GetString($buf)
|
||||||
|
|
||||||
|
$m = [regex]::Matches($coada, '"usage":\{.*?"output_tokens":\d+')
|
||||||
|
if ($m.Count -eq 0) { exit 0 }
|
||||||
|
$ultim = $m[$m.Count - 1].Value
|
||||||
|
$total = 0
|
||||||
|
foreach ($camp in @('input_tokens', 'cache_creation_input_tokens', 'cache_read_input_tokens')) {
|
||||||
|
if ($ultim -match ('"' + $camp + '":(\d+)')) { $total += [int]$Matches[1] }
|
||||||
|
}
|
||||||
|
$k = [Math]::Round($total / 1000)
|
||||||
|
|
||||||
|
$mesaj = ''
|
||||||
|
if ($total -ge $PragMax) {
|
||||||
|
$mesaj = "CONTEXT ${k}k - peste limita de $([Math]::Round($PragMax/1000))k (regula 9): scrie handoff-ul in docs\progres.md si preda sesiunea acum."
|
||||||
|
} elseif ($total -ge $Prag) {
|
||||||
|
$mesaj = "CONTEXT ${k}k - peste $([Math]::Round($Prag/1000))k (regula 9): actualizeaza docs\progres.md si pregateste predarea; deleaga la subagenti ce mai ai de citit/testat."
|
||||||
|
}
|
||||||
|
if ($mesaj) {
|
||||||
|
if ($Stdout) { Write-Output $mesaj; exit 0 }
|
||||||
|
[Console]::Error.WriteLine($mesaj)
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
if ($Intotdeauna) { Write-Output "CONTEXT ${k}k" }
|
||||||
|
exit 0
|
||||||
27
utile/docs_revizie_check.ps1
Normal file
27
utile/docs_revizie_check.ps1
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# docs_revizie_check.ps1 - reaminteste revizuirea periodica de compactare a documentatiei (regula 12).
|
||||||
|
# Marker: COMUN\docs\.ultima_revizie (data ultimei revizii, YYYY-MM-DD).
|
||||||
|
# Utilizare:
|
||||||
|
# ca hook (SessionStart): powershell -File docs_revizie_check.ps1 -Stdout
|
||||||
|
# dupa o revizie: powershell -File docs_revizie_check.ps1 -Marcheaza
|
||||||
|
param(
|
||||||
|
[int]$Zile = 30,
|
||||||
|
[switch]$Stdout,
|
||||||
|
[switch]$Marcheaza
|
||||||
|
)
|
||||||
|
|
||||||
|
$marker = Join-Path (Split-Path $PSScriptRoot -Parent) 'docs\.ultima_revizie'
|
||||||
|
|
||||||
|
if ($Marcheaza) {
|
||||||
|
Set-Content $marker (Get-Date -Format 'yyyy-MM-dd') -Encoding ascii
|
||||||
|
Write-Output "marcat: $(Get-Content $marker)"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$ultima = if (Test-Path $marker) { [datetime]::ParseExact((Get-Content $marker -Raw).Trim(), 'yyyy-MM-dd', $null) } else { [datetime]'2000-01-01' }
|
||||||
|
$vechime = [int]((Get-Date) - $ultima).TotalDays
|
||||||
|
if ($vechime -lt $Zile) { exit 0 }
|
||||||
|
|
||||||
|
$mesaj = "DOCS: ultima revizuire de compactare acum $vechime zile (regula 12). Propune-i utilizatorului o runda pe COMUN\docs si docs\ ale proiectului; dupa aplicare ruleaza docs_revizie_check.ps1 -Marcheaza."
|
||||||
|
if ($Stdout) { Write-Output $mesaj; exit 0 }
|
||||||
|
[Console]::Error.WriteLine($mesaj)
|
||||||
|
exit 2
|
||||||
Reference in New Issue
Block a user