#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:
@@ -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).
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user