sync SVN r18026

This commit is contained in:
2026-08-20 22:44:52 +03:00
parent ca3c5d7eea
commit 5b52cb3999
9 changed files with 1481 additions and 3 deletions

218
docs/brief_r6_punct6_vfp.md Normal file
View File

@@ -0,0 +1,218 @@
# Brief de implementare — runda 6, punctul 6, partea VFP
Explicatia TVA in dialogul de modificare a articolului din `frm_facturi`. Proiectarea completa:
`docs\propunere_runda6_punct6_plsql.md`, sectiunea "Ce ramane de facut in VFP". Acest brief e
executabil: contine liniile exacte, valorile exacte si ce s-a verificat deja.
## Interdictii (citeste-le inainte de orice)
- **NU rula `git_sync.ps1`, `roa_sync.bat`, `svn update`, `svn commit`, `git commit`, `git push`.**
- **NU atinge alt fisier** in afara de `COMUN\clase\ofacturare_comun.vc2` (+ binarul lui prin
write-back) si `docs\raport_r6_punct6_vfp.md` (raportul tau).
- **NU modifica PL/SQL** — pachetul e deja aplicat pe `MARIUSM_AUTO` si verificat.
- **NU schimba `Text1.ReadOnly` nicaieri**, nu atinge grid-ul de articole, nu atinge `omodificari.vc2`.
- Esti **singurul scriitor** pe `ofacturare_comun.vc2`. Daca gasesti modificari necomise pe el la
start, opreste-te si raporteaza.
## Starea de plecare
- `svn`/`git` curate, r18025. Textele `.??2` sunt la zi (git_sync: 0 convertite, 463 la zi).
- Oracle: `MARIUSM_AUTO.PACK_FACTURARE` are deja semnatura noua, verificata pe sursa vie:
```
PROCEDURE modifica_explicatie_articol(V_ID_VANZARE_DET IN NUMBER,
V_EXPLICATIE IN VARCHAR2,
V_ID_UTIL IN NUMBER,
V_TAXCODE IN NUMBER DEFAULT NULL,
V_ID_JTVA_COLOANA IN NUMBER DEFAULT NULL);
```
Al 5-lea parametru lipsa/NULL => ramura veche (se scriu doar `EXPLICATIE` si `TAXCODE`).
## Fapte verificate pe cod — nu le re-investiga
1. `crsDetalii` (`oproceduri_facturare.prg:382-400`) are: `id_vanzare`, `id_vanzare_det`,
`proc_tvav`, `id_jtva_coloana`, `jtva_coloana`, `taxcode`, `taxname`, `sters`, `explicatie`.
**Nu are `data_act` si nu are `id_part`.**
2. `crsfacturi` (`oproceduri_facturare.prg:339-360`) are `data_act`, `id_part`, `id_vanzare`.
Randul curent din `crsfacturi` **este** antetul liniei editate: `crsDetalii` se filtreaza pe
`id_vanzare=` al randului curent din `crsfacturi` (`ofacturare_comun.vc2:3621-3623`).
3. `proc_tvav` e **multiplicator** (1.19), `cota_tva` din `vjtva_coloane` e **procent** (19).
Cota liniei = `Round((Nvl(poRec.proc_tvav,0) - 1) * 100, 2)`.
4. Filtrul de explicatii e cel din `caut_explicatie_tva` (`ocautare.prg:3193, 3220`):
`id_jtva_coloana > 0` + `cota_tva = <cota>`, pe view-ul `vjtva_coloane`.
**Nu** folosi `update_jtva_coloane` — acela adauga restrictii pe `afisat` si pe `cote_tva` de
an/luna curenta, care nu sunt in proiectarea aprobata.
5. `GetTaxCodeIdPart` (`oproceduri_comune.prg:6059-6125`) e apelabila din `frm_facturi`, isi
gestioneaza singura cursorul `jtva_coloane`, si **returneaza `.NULL.` daca `gl406` e `.F.`**
(`:6086-6088`) — de aceea apelul se face doar sub garda `gl406`, altfel ar sterge `taxcode`-ul.
6. `tlNeexigibil` = `.F.` (parametru **omis**). Confirmat, nu presupus: calea de emitere a
facturii foloseste `GetTaxCode(gnAn, gnLuna, ldDataAct, lnIdJtva, .F.)` cu ultimii trei
parametri impliciti (`ofacturare.vc2:2529` si `:3101`), iar pe jurnal de vanzari (`jv`)
`GetTaxCodeIdPart` degenereaza exact in acel apel (ramura `llJC` e `.F.`, `:6098-6110`).
Deci butonul produce acelasi `taxcode` pe care l-ar produce emiterea.
7. `n50`/`n100` = `.F.` (parametri omisi), ca in `ointroduceri.vc2:11488`.
## Modificarile — fisier `COMUN\clase\ofacturare_comun.vc2`
Ruleaza intai `vfp_symbols.ps1 -Where` ca sa confirmi domeniul fiecarei metode inainte sa editezi;
numerele de linie de mai jos sunt de la starea r18025 si se pot deplasa dupa prima editare.
### M1 — `frm_facturi.do_modifica_explicatie` (~`:4642-4659`)
Dupa `Scatter Name poRec Memo` si inainte de `If poRec.sters = 0`, ataseaza antetul pe `poRec`
(vezi faptul 1 si 2 — campurile nu exista pe `crsDetalii`):
```foxpro
AddProperty(poRec, 'data_act', crsfacturi.data_act)
AddProperty(poRec, 'id_part', Nvl(crsfacturi.id_part, 0))
```
Restul metodei ramane neschimbat (`update_saft_taxtable()` ramane unde e).
### M2 — layout `frm_modifica_articol_factura` (~`:5131`)
Randul existent cu `cbo_saft` coboara, iar deasupra lui intra randul nou de explicatie TVA.
Valori exacte:
| obiect | proprietate | din | in |
|---|---|---|---|
| `frm_modifica_articol_factura` | `Height` | 370 | **431** |
| `_shape3` | `Top` | 323 | **384** |
| `cbo_saft` | `Top` | 329 | **390** |
| `lbSaft` | `Top` | 332 | **393** |
Obiecte noi (toate in `*<PropValue>` / `ADD OBJECT`, plus linii `*< OBJECTDATA ... >` in blocul de
ZOrder de la inceputul clasei):
- `_shape4` AS `_shape` OF `_baza.vcx` — `BackStyle=0, Left=13, Top=323, Height=58, Width=348`
- `lbExplTva` AS `_label` OF `_baza.vcx` — `Caption="Explicatie TVA", Left=24, Top=332`
(diacriticele: vezi sectiunea de encoding mai jos; textul afisat corect e `Explicație TVA`)
- `cbo_expl_tva` AS `_cbbase` OF `_cb_base.vcx` — modelat dupa `cbo_saft`:
`BoundColumn=3, BoundTo=.T., ColumnCount=2, ColumnWidths="400,60", Height=24, Left=110,`
`Top=329, Width=238, RowSourceType=3`.
**`ControlSource` ramane gol** (nu legam direct de `poRec.id_jtva_coloana` — valoarea aleasa se
preia in `InteractiveChange`, ca sa putem distinge "userul a atins combo-ul" de "n-a atins").
`RowSource` se construieste in `Init` (vezi M3), nu se scrie in `ADD OBJECT`.
- `lbExplTvaInfo` AS `_label` OF `_baza.vcx` — `Caption="", Left=24, Top=355, Width=324,`
`Height=20, WordWrap=.T., ForeColor=RGB(128,0,0), Visible=.F.`
Proprietate noua de formular: `nidjtvaales`.
**Obligatoriu si intrarea `*p: nidjtvaales` in `*<DefinedPropArrayMethod>`, nu doar valoarea in
`*<PropValue>`** — fara `*p:` valoarea trece fidelity-check-ul, ajunge in binar, dar VFP nu
materializeaza proprietatea si orice acces cade cu eroarea 1734. Valoare initiala: `nidjtvaales = 0`.
### M3 — `frm_modifica_articol_factura.Init`
La finalul metodei `Init` existente (dupa blocul care citeste `citeste_lungcampexplart`), adauga
popularea combo-ului. Comportamentul cerut de proiectare, in trei ramuri:
```foxpro
Local lnCota, lcSqlTva, lcCursorTva
Thisform.nidjtvaales = 0
If Isnull(poRec.proc_tvav) Or Nvl(poRec.proc_tvav, 0) = 0
Thisform.cbo_expl_tva.Enabled = .F.
Thisform.lbExplTvaInfo.Caption = [Cota de TVA a acestei linii nu este cunoscuta; explicatia TVA nu poate fi modificata prin acest buton.]
Thisform.lbExplTvaInfo.Visible = .T.
Return
Endif
lnCota = Round((poRec.proc_tvav - 1) * 100, 2)
lcCursorTva = [crsExplTvaArt]
lcSqlTva = [select id_jtva_coloana, denumire, cota_tva from vjtva_coloane where id_jtva_coloana > 0 ] + ;
[and cota_tva = ] + Alltrim(Str(lnCota, 10, 2)) + [ order by denumire]
If goExecutor.oExecuta(lcSqlTva, lcCursorTva) And Reccount(lcCursorTva) > 0
Thisform.cbo_expl_tva.RowSource = [select denumire, cota_tva, id_jtva_coloana from ] + lcCursorTva + [ into cursor crsExplTvaCbo]
Thisform.cbo_expl_tva.Requery()
Thisform.cbo_expl_tva.Value = Nvl(poRec.id_jtva_coloana, 0)
Else
Thisform.cbo_expl_tva.Enabled = .F.
Thisform.lbExplTvaInfo.Caption = [Nu exista nicio explicatie TVA activa cu aceeasi cota ca linia facturata (cota: ] + ;
Alltrim(Str(lnCota, 10, 2)) + [ %).]
Thisform.lbExplTvaInfo.Visible = .T.
Endif
```
Note de implementare, nu le sari:
- `Alltrim(Str(lnCota,10,2))` produce `19.00`; comparatia cu `cota_tva` (NUMBER(10,0)) e corecta
in Oracle. Nu formata cu virgula.
- daca `Init` are `Return` propriu / `NODEFAULT`, verifica sa nu scurtcircuitezi codul existent.
- inchide cursorul `crsExplTvaArt` in `Destroy` daca ramane deschis (`If Used(...) : Use In ...`).
- textul mesajelor **fara diacritice** (asa sunt scrise si celelalte mesaje din aceasta clasa,
ex. `:4635`) — evita complet problema de encoding pe siruri noi.
### M4 — `cbo_expl_tva.InteractiveChange` (metoda noua)
```foxpro
PROCEDURE cbo_expl_tva.InteractiveChange
Local lnIdJtva
lnIdJtva = Nvl(This.Value, 0)
If lnIdJtva <= 0
Return
Endif
Thisform.nidjtvaales = lnIdJtva
poRec.id_jtva_coloana = lnIdJtva
If Type('gl406') = 'L' And m.gl406
poRec.taxcode = GetTaxCodeIdPart(m.gnAn, m.gnLuna, poRec.data_act, m.lnIdJtva, poRec.id_part)
Thisform.cbo_saft.Refresh()
Endif
ENDPROC
```
### M5 — `inainte_de_do_termin` (~`:5227-5235`)
Al 5-lea parametru pozitional, **literal, nu bind** — ca sa poata fi `null` curat cand userul n-a
atins combo-ul (atunci procedura ramane pe ramura veche):
```foxpro
Local lcParamJtva
lcParamJtva = Iif(Vartype(Thisform.nidjtvaales) = 'N' And Thisform.nidjtvaales > 0, ;
Alltrim(Str(Thisform.nidjtvaales)), [null])
lcSql = [begin pack_facturare.modifica_explicatie_articol(] + Alltrim(Str(poRec.id_vanzare_det)) + [,] + ;
['] + Nvl(Alltrim(OracleSpecialCharacters(poRec.explicatie)),'') + [',?gnIdUtil,?poRec.taxcode,] + lcParamJtva + [); end;]
llReturn = goExecutor.oExecuta(lcSql)
```
Restul metodei (confirmarea `amessagebox`, `Return llReturn`) ramane neschimbat. Erorile
`FACT-026..029` ies deja vizibil prin `goExecutor.oExecuta` — nu adauga cod de afisare.
### M6 — refresh dupa salvare
**Nimic de facut.** `Thisform.actualizeaza_grid2()` din `do_modifica_explicatie` (`:4654`) e
suficient: headerul nu se schimba, totalurile nu se recalculeaza.
## Encoding — capcana platita deja
Fisierele `.vc2` din acest arbore au diacriticele in **cp1250, nu cp1252**. Tool-ul `Edit` le
transforma in U+FFFD si strica textul din alte proprietati.
- **numara octetii > 0x7F inainte si dupa fiecare editare** — trebuie sa iasa acelasi numar;
- daca s-au stricat, repara cu encoding `28591`;
- pentru sirurile **noi** pe care le scrii tu: **fara diacritice**, deci problema nu apare de la
tine — dar poate aparea de la o rescriere a fisierului.
## Write-back si verificare
1. `txt2vcx.ps1 ... -AllowComun` — se ruleaza **direct, fara aprobare** (regula lui Marius).
2. Fidelity-check: FoxBin2Prg **nu pastreaza ordinea textuala** pentru `ADD OBJECT` multiple si
proprietati custom, si sorteaza cu `_` **dupa** litere. Daca primul write-back da FAIL pe
ordine: **adopta ca sursa textul regenerat din `<staging>\verify\*.vc2`**, nu incerca sa
ghicesti ordinea corecta.
3. **`mtime` nu dovedeste sincronizarea text/binar** — `txt2vcx.ps1` rescrie mtime-ul textului.
Dovada ceruta: reconverteste binarul intr-un cache temporar si fa `diff` cu textul din arbore;
raporteaza numarul de linii diferenta (trebuie 0).
## Ce raportezi
Scrie **pe disc**, la `D:\ROA\ROAFACTURARE\docs\raport_r6_punct6_vfp.md`, si raspunde in chat doar
cu `GATA` + calea. In raport:
- inventarul modificarilor cu `fisier:linie` (dupa write-back, deci pe numerotarea finala);
- confirmarea explicita ca write-back-ul e facut si **numarul de linii diferenta** la reconversie;
- numarul de octeti > 0x7F inainte si dupa;
- ce n-ai putut face si de ce;
- **nu comite nimic**; nu rula sincronizari.
Daca te apropii de ~200-250k tokens de context, opreste-te la o stare consistenta pe disc, scrie
raportul cu ce ai facut si ce ramane, si anunta — nu continua.