#6 editare factura emisa: S4 runda 3 completa (pagina de articole editabila)

frm_modific2024, pgfArticole.PAGE3 - editare in memorie, fara scriere in Oracle
(aceea ramane S5).

- sub-blocul A: cantitate/pret/pret_cu_tva editabile inline, marcaj lmodificat
  pe linie, coloana valoare pe linie
- sub-blocul B: stergere logica de linii (sters/DynamicForeColor gri) si adaugare
  de linii prin frm_articol_factura, cu alegerea articolului prin caut_articol()
- sub-blocul C: bara de totaluri sub grid (total linii convertit RON la cursul
  documentului, discount de antet editabil, total net), ascunsa pe
  transfer/custodie; verdict de corelatie ACT/RUL informativ, cu 3 stari
- suma ACT: sold net debit-credit, cont pe tip de document (4111 / 418 / 461,
  iar pe rate/contract 4111, 411 sau 461)
- suma RUL: doar ID_TIP_RULAJ = 0, adica miscarile reale; perechile
  ID_TIP_RULAJ = 3 sunt virtuale (tin locul procesului verbal de schimbare de
  pret) si nu intra in suma. Corectie cu liniile nestocate, marcata "ajustat"
- adaugarea de linii pe document in valuta: dialogul primeste tip_valuta si
  cursul documentului de pe tvanz, deci pretul se introduce direct in valuta;
  ofacturare.vc2 ramane neatins
- cei 5 apelanti frm_modific2024 (afisjurcom, anaf_efactura, cele doua .sc2 de
  import) pregatesc cursorul de articole inainte de Createobject, gardat pe
  SET PROCEDURE - registrul jurnal din ROACONT/ROAGEST ramane neschimbat

Teste headless pe MARIUSM_AUTO, suite care isi descopera singure documentele:
test_page3_articole 14/2 (cele 2 = artefact de grid nematerializat headless,
acoperit pe ecran), test_incarca_vanzare_din_nota 5/0,
test_adauga_linie_articol 20/0, test_adauga_linie_valuta 16/0,
test_ui_sterge_linie 8/0, test_verdict_act_rul 26/0.

docs/todos.txt: punctele 13 si 20, scrise de Marius.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
2026-08-09 20:48:42 +03:00
parent 13b4f65723
commit b9eba29ebe
26 changed files with 3310 additions and 172 deletions

View File

@@ -1,40 +1,66 @@
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2`
Partajat între proiectele ROA* — capcana ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg,
nu de un proiect anume.
## De ce se întâmplă
Fișierele `.sc2`/`.vc2` sunt **cp1252** (Windows-1252), nu UTF-8 (vezi antetul: `CPID="1252"`).
Fișierele `.sc2`/`.vc2` sunt **cp1250** (Windows-1250, Europa Centrală), nu UTF-8 — deși
antetul FoxBin2Prg declară `CPID="1252"`. Eticheta din antet nu corespunde conținutului:
controalele care poartă text cu diacritice au `FontCharSet = 238` (Europa de Est), adică VFP
le randează tot ca cp1250. Diferența nu e cosmetică — un `ă` real scris prin cp1252 nu are
echivalent în acel codepage și s-ar pierde; scris prin cp1250 (encoding-ul real al fișierului)
e pur și simplu octetul `0xE3`, corect și stabil.
Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid
ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi **salvează tot ca UTF-8**, acel
U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1252 (cum face
U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1250 (cum face
FoxBin2Prg la write-back), apar ca `�`. Caracterul original e **ireversibil pierdut**
(recuperabil DOAR din altă sursă: git history, backup).
Codebase-ul ROA "reciclează" caractere cp1252 fără echivalent direct pentru Ș/ă/ț:
Octeții diacriticelor din codebase-ul ROA, cu adevărul (cp1250) și aparența dacă îi decodezi
greșit ca cp1252:
| Literă românească | Caracter folosit (cp1252) | Byte |
| Literă românească | Byte | Aparență dacă decodezi ca cp1252 |
|---|---|---|
| ă | ã (a-tilde) | `0xE3` |
| Ă | Ã | `0xC3` |
| ț | þ (thorn minuscul) | `0xFE` |
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
| î, â | î, â (native cp1252) | `0xEE`, `0xE2` |
| ă | `0xE3` | ã (a-tilde) |
| Ă | `0xC3` | Ã |
| î | `0xEE` | î (identic — zonă comună cp1250/cp1252) |
| Î | `0xCE` | Î (identic — zonă comună cp1250/cp1252) |
| â | `0xE2` | â (identic — zonă comună cp1250/cp1252) |
| ț | `0xFE` | þ (thorn minuscul) |
| Ș (majusculă) | `0xAA` | ª (ordinal masculin) |
| ș (minusculă) | `0xBA` | º (ordinal feminin) |
Par "gunoi"/typo într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) — **sunt corecte, nu le "corecta"
fără să verifici encoding-ul.**
Decodate cp1250 (encoding-ul real), aceste litere sunt diacritice românești normale — exact
ce apare în formular când fișierul e sănătos. Par "gunoi"/typo (`ã`, `þ`, `ª`, `º`) **doar
dacă le decodezi cu codepage-ul greșit** — nu le "corecta" fără să verifici encoding-ul real.
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
Verificarea se face **pe octeți**, nu pe text decodat: un codepage single-byte (1250 sau 1252)
mapează fiecare octet la un caracter, deci nu produce niciodată U+FFFD — o căutare de
`[char]0xFFFD` în textul decodat nu găsește nimic nici pe un fișier stricat. Ce se caută e
secvența de trei octeți pe care a lăsat-o tool-ul care a stricat fișierul:
```powershell
$bytes = [System.IO.File]::ReadAllBytes("<path>.vc2")
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
$b = [System.IO.File]::ReadAllBytes("<path>.vc2")
$n = 0
for ($i = 0; $i -lt $b.Length - 2; $i++) {
if ($b[$i] -eq 0xEF -and $b[$i+1] -eq 0xBF -and $b[$i+2] -eq 0xBD) { $n++; $i += 2 }
}
"EF BF BD (U+FFFD) x $n" # orice valoare > 0 = fisier stricat
```
Dacă apare `�` (sau `$text` conține U+FFFD) — fișierul are corupere de encoding.
Echivalentul din Bash, util și pentru censul complet înainte/după orice editare (vezi
`reguli_lucru.md`, punctul 7):
```bash
od -An -tx1 <path>.vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
```
Censul **crește** la stricare — un octet cp1250 devine trei octeți de U+FFFD — deci nu urmări
doar scăderile. Decodat cp1250, `EF BF BD` apare ca `ďż˝` în caption.
## Cum se repară
@@ -46,22 +72,26 @@ Dacă apare `�` (sau `$text` conține U+FFFD) — fișierul are corupere de
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
```
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1252 corect la afișare, deși
Dacă și HEAD e deja corupt (corupera a fost comisă), caută ultima versiune curată cu
`git cat-file blob <commit>:<cale>` (din Bash, niciodată cu `>` din PowerShell 5.1 — adaugă
BOM și re-encodează) sau `svn cat <fișier>` — ambele surse independente de encoding-ul
curent al fișierului.
Apoi decodează ambele fișiere (versiunea curată + curent corupt) ca cp1250 și compară linie
cu linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1250 corect la afișare, deși
detectează totuși diferența de octeți).
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), reaplicând DOAR
modificările intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt
caracter cu caracter).
4. Scrie rezultatul înapoi ca bytes cp1252
(`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`), NU ca string UTF-8/`Out-File`
3. Reconstruiește fișierul text pornind de la versiunea curată, reaplicând DOAR modificările
intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt caracter cu
caracter).
4. Scrie rezultatul înapoi ca bytes cp1250
(`[System.Text.Encoding]::GetEncoding(1250).GetBytes(...)`), NU ca string UTF-8/`Out-File`
implicit.
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
## Cum se evită pe viitor
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
conține diacritice (`ã`, `þ`, `ª`, `º`, `î`, `â` etc.) — dacă da, **orice rescrie completă
trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând UTF-8.
conține diacritice (`ă`, `ț`, `Ș`, `ș`, `î`, `â` etc.) — dacă da, **orice rescrie completă
trebuie făcută la nivel de octeți cu encoding cp1250 explicit**, nu presupunând UTF-8.
Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul păstrează restul
fișierului byte-identic (nu rescrie tot fișierul reîncodat).

View File

@@ -32,7 +32,9 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
`vcx2txt.ps1 -Project <pjx> -ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (in cache; la runde succesive
necomise, diff-ul fata de HEAD ar amesteca rundele).
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))`;
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))` -
doar pentru round-trip pe octeti, NU pentru retastat literal diacritice (antetul zice
`CPID="1252"`, dar octetii diacriticelor sunt de fapt cp1250: `conventie_encoding_cp1252.md`).
NU tool-ul Edit/Write (UTF-8 strica diacriticele). Continut nou ASCII, TAB-uri ca in jur,
fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`.
3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.patch`

View File

@@ -45,7 +45,7 @@
de element comun nedocumentat.
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
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, cp1250 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
Cautare in binare: `cautare_vcx_vct.md`. Versiunile `.??2` sunt instantanee, pot fi mai vechi
decat binarul — verifica mtime inainte de concluzii; continutul real e in `.PJX`.
6. Delegare: implementarile, testele, verificarile si cercetarile se dau unor subagenti Sonnet in
@@ -68,17 +68,30 @@
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
descoperit ca nu e nevoie de ea.
7. Conventii obligatorii, de citit cand atingi zona respectiva:
- 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`) ->
`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 la o singura linie
schimbata, si o repeta la FIECARE scriere — editeaza tot ce ai de editat, verifica byte-level
si repara o singura data DUPA ultima scriere. Verificare: `perl -ne 'print "$.\n" if
- editezi fisiere `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`, unde `s`-urile cu
virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> `conventie_encoding_cp1252.md`.
Antetul FoxBin2Prg declara `CPID="1252"`, dar octetii diacriticelor sunt de fapt **cp1250**
(`0xE3`=a cu caciula, `0xFE`=t cu virgula, `0xAA`=S majuscul cu virgula, `0xBA`=s minuscul cu
virgula) - nu trata eticheta din antet ca adevarul despre encoding. Orice write cu un tool ce
nu pastreaza octetii nativ (Edit/Write) corupe caracterele >= 0x80 din TOT fisierul (`0xBA` ->
`EF BF BD`), chiar la o singura linie schimbata, si o repeta la FIECARE scriere - **nu
re-encoda niciodata fisierul: lucreaza pe octeti (`byte[]`) sau scrie strict ASCII in
continutul nou**; editeaza tot ce ai de editat, verifica byte-level si repara o singura data
DUPA ultima scriere.
Cens obligatoriu **inainte SI dupa** fiecare editare, care trebuie sa ramana identic:
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Atentie
la sens: la stricare censul **CRESTE**, nu scade - un octet cp1250 devine 3 octeti `EF BF BD`
(U+FFFD) la o re-encodare UTF-8 gresita; cauta explicit secventa `EF BF BD`, nu doar tiparul
generic de mojibake `C3`/`C4`/`C5`/`C8` + octet de continuare (acela da fals-pozitiv pe text
UTF-8 legitim sau pe comentarii intr-o alta limba, deja intalnite in cod). Verificare veche
(orice octet >=0x80, utila cand cauti pozitia exacta): `perl -ne 'print "$.\n" if
/[\x80-\xFF]/' <fisier>`; reparare (pt. `0xBA`): `perl -e
'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
`EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel; ia octetul corect
per pozitie din `svn cat <fisier>` (necorupt) inainte sa inlocuiesti - o inlocuire oarba cu
`0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere;
per pozitie din `svn cat <fisier>` (necorupt) sau din git history (`git cat-file blob
<commit>:<cale>`, **din Bash, niciodata cu `>` din PowerShell 5.1** - adauga BOM si
re-encodeaza) inainte sa inlocuiesti - o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula
(`0xE3`, `0xFE`) din alte fisiere;
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
- grid needitabil pe formular cu 2+ grid-uri -> `capcana_grid_controlsource.md`;
- adaugi o coloana intr-un grid deja livrat (ordinea din clasa e neutralizata de

View File

@@ -36,7 +36,7 @@ Ideea este sa se poata face configurarea mult mai repede, eficient, dintr-un sin
13. ROAFACTURARE - FORMULARUL DE FACTURARE SA INCLUDA SI FORMULARUL DATE_FACTURA/DATE_AVIZ ETC. SI SA NU MAI INCARCE DE PE SERVER TOATE ARTICOLELE DIN TOATE POLITICELE DE PRETURI - INTRUCAT ESTE POSIBIL SA FIE SI MII DE ARTICOLE SI DUREAZA MULT SA LE ADUCA DE PE SERVER. AM INCEPUT DEJA MAI DEMULT UN FORMULAR UNIFICAT frm_facturare_articole2, DAR ERA MULT DE INTEGRAT DIN FORMULARUL VECHI.
FRONTEND SIMILAR PE CARE IL DORESC ESTE IN ROAACPRO > FACTURA, SAU IN IMPORTUL DE EFACTURA, IN CARE AM INTEGRAT DATELE FACTURI, DOAR CA FACTURAREA DIN ROAFACTURARE ESTE MAI COMPLEXA - ESTE FOLOSITA SI PENTRU POLITICI DE PRETURI SI PENTRU CONTRACT/COMANDA/AVIZ/RETUR ETC.
INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FORMULARE PENTRU FACTURA, SA FAC MAI RAPID.
INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FORMULARE PENTRU FACTURA, SA FAC MAI RAPID. in plus vreau si editare factura/aviz in toate variantele (politici preturi, comanda, contract, aviz etc) prin regenerare, adica sa arate formularul completat ca si cum ar fi inainte de salvarea initiala, ca sa pot sa fac editari ca si cum as fi la introducerea initiala - bineinteles cu stergerea facturii initiale (sters = 1) si salvarea celei noi, pentru a se vedea ce s-a modificat
14. ROACONT - efactura se salveaza xml detaliat si xml zip efactura si ocupa mult spatiu. vreau sa stiu cand nu mai este nevoie de xml detaliat si daca se poate curata tabelul ca sa nu mai ocupe spatiu, cel putin pentru facturi mai vechi. este important zip pentru ca este factura originala anaf.
@@ -48,4 +48,7 @@ INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FOR
18. ROAFACTURARE - EMITERE FACTURA DIN PROFORMA
19. ROAFACTURARE - EDITARE PROFORMA
19. ROAFACTURARE - EDITARE PROFORMA
20. ROAFACTURARE - FACTURA DIN COMANDA, COMANDA SE CONSIDERA FACTURATA DACA EXISTA FACTURI CU ACELEASI CANTITATI. AS VREA SA PUN MARKER DE FACTURAT PE COMANDA, CA SA NU MAI CAUT FACTURI - ESTE COSTISITOR. DOAR CA TREBUIE SA FII ATENT CA O COMANDA SE POATE FACTURA TOTAL/PARTIAL, SAU DIN MAI MULTE FACTURI, SAU SE POATE INCHIDE FORTAT. ACUM INCHIDEREA FORTATA ADAUGA CANTITATI NEGATIVE PE COMANDA, CA SA FACA CANTITATILE NEFACTURATE ZERO.