docs: runda 6 - cercetari, propuneri si conventia mediului Oracle

Cercetarile si propunerile rundelor 4-6 pe editarea facturii emise. Starea
rundei 6 si ce s-a stabilit intra in progres.md.

Nou: docs/conventii_mediu_oracle.md - pe dev/test se lucreaza numai cu
ROA_CENTRAL si schemele CONTAFIN_ORACLE si MARIUSM_AUTO; schema ACN nu se
foloseste. Scripturile de pachet sunt necalificate, deci schema tinta o
decide sirul de conectare, nu fisierul.

roafacturare.pj2 regenerat de git_sync.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gYCNE26G1G7UoGu2ju7aS
This commit is contained in:
2026-08-20 16:35:03 +03:00
parent b5a7108f34
commit ca3c5d7eea
26 changed files with 5316 additions and 103 deletions

View File

@@ -0,0 +1,320 @@
# Runda 6, punctul 6 — proiectare PL/SQL: explicatie TVA in butonul de modificare din `frm_facturi`
> **NOTA — decizie schimbata, 20.08.2026.** Prima varianta discutata cu Marius era "lista completa
> de explicatii TVA, CU recalcul": alegerea unei explicatii cu alta cota scria si `proc_tvav`, si
> recalcula totalurile documentului. **Varianta a fost respinsa de Marius** dupa ce consecinta
> (butonul nu mai era neutru valoric) a fost semnalata — cuvintele lui: *"nu vreau sa schimb cota
> de tva, maxim explicatia de tva si taxcode, aferente cotei de tva, ca sa nu se modifice
> totaluri"*. Documentul de fata reflecta **varianta finala, aprobata**: filtrata pe cota curenta,
> **fara** recalcul. Nu reintroduce varianta cu recalcul fara o decizie noua, explicita, a lui
> Marius.
Livrabile: scriptul PL/SQL (Partea B, mai jos) + acest document (Partea A). **Nimic nu s-a rulat
pe Oracle** in afara de `SELECT`-uri de investigatie. Niciun fisier VFP n-a fost atins.
---
## A1. Cum se face azi acelasi lucru in `frm_modific2024`
Sablonul complet, verificat pe cod (nu e in domeniul acestei livrari, doar citit, si e citat aici
doar ca sa arate *de ce* nu se copiaza 1:1 pentru `frm_facturi` — vezi A2):
```
COMUN\programe\ofacturare_editare.prg:1100-1105 (ArticoleNotaEditor.ModificaNomenclator)
CASE m.lcCamp == 'id_jtva_coloana'
REPLACE id_jtva_coloana WITH loCauta.id_jtva_coloana, ;
proc_tvav WITH (Nvl(loCauta.cota_tva, 0) + 100) / 100
This.oForm.UpdateExplicatieSAFTArt()
This.oForm.calculeaza_valori_articol()
```
Lantul, in ordine:
1. **`loCauta`** vine din `This.CautaExplicatieTva()` (`ofacturare_editare.prg:1142-1147`), care
cheama `caut_explicatie_tva(id_jtva_curent, , , , lnCotaFiltru)` — **filtrat pe cota liniei
curente** (`ocautare.prg:3174-3238`, filtrul la `:3218-3220`). Returneaza un obiect cu
`.id_jtva_coloana`, `.denumire`, `.cota_tva`.
2. **Scrierea locala** (pe cursorul `tvd`, in memorie, inca nesalvat): `id_jtva_coloana` primeste
valoarea aleasa, `proc_tvav` primeste `(cota_tva + 100) / 100` — calculat in VFP.
3. **`UpdateExplicatieSAFTArt()`** (`COMUN\clase\omodificari.vc2:15049-15074`) deriva `taxcode` din
`id_jtva_coloana` prin functia globala **`GetTaxCodeIdPart(an, luna, data_act, id_jtva, id_part,
n50, n100, neexigibil)`** (`COMUN\programe\oproceduri_comune.prg:6059-6125`).
4. **`calculeaza_valori_articol()`** recalculeaza valoarea liniei pe cursorul local `tvd`.
5. La salvarea intregului formular, `ScrieArticoleFacturaEditate()`
(`ofacturare_editare.prg:452-573`) scrie liniile si cheama o singura data, pentru tot
documentul, `pack_facturare.recalculeaza_totaluri_vanzari(id_vanzare, discount)`.
**Important pentru varianta finala**: acest sablon presupune ca `id_jtva_coloana` **poate** aduce
o cota diferita — de-asta exista filtrul pe cota in `caut_explicatie_tva` doar ca o *reducere* a
listei, nu ca o *garda*. Pentru `frm_facturi`, decizia lui Marius transforma filtrul de cota
dintr-o comoditate de UI intr-o **conditie obligatorie**, impusa si in baza (A5).
---
## A2. Unde cade validarea — nu mai exista recalcul de pus undeva
Cu decizia finala, **nu se recalculeaza nimic**: nici valoarea liniei, nici totalurile
documentului. `proc_tvav` nu se scrie. Intrebarea "VFP sau PL/SQL" din varianta initiala nu se mai
pune pentru un recalcul — dar ramane o intrebare echivalenta pentru **garda de neutralitate**
(cota explicatiei alese trebuie sa fie egala cu cota liniei): unde se impune?
**Raspuns: in PL/SQL**, in `pack_facturare.modifica_explicatie_articol` insusi.
Argumente:
1. **Neutralitatea valorica e chiar cerinta lui Marius** — nu un detaliu de implementare. Daca ar
fi impusa doar prin filtrarea combo-ului in VFP (cum era propunerea initiala, inainte de
recalcul), un bug de UI, un combo needitat corect, sau orice cale ocolitoare ar putea trimite
un `id_jtva_coloana` cu alta cota, iar baza ar scrie-o fara sa clipeasca — exact ce Marius nu
vrea.
2. **`frm_facturi` nu are, si acum nici nu are nevoie de**, un motor de calcul local — cererea nu
mai atinge `calculeaza_valori_articol()` sau echivalentul lui. PL/SQL are tot ce ii trebuie
pentru garda: `VANZARI_DETALII.PROC_TVAV` (linia) si `JTVA_COLOANE.COTA_TVA` (explicatia).
3. **E acelasi stil ca FACT-025** (runda 5): validare in baza, esec zgomotos cu rollback, nu o
validare "de bune maniere" doar in client.
**Ce pierde varianta "doar VFP"** (garda doar prin filtrarea combo-ului, fara verificare in
PL/SQL): nimic in flux normal — dar orice cale care ocoleste combo-ul (alt formular viitor, un
script, o corectie manuala printr-un alt ecran care cheama aceeasi procedura) ar putea scrie o
cota diferita nedetectat. Cum procedura oricum trebuie sa primeasca `id_jtva_coloana` ca sa-l
scrie, verificarea in PL/SQL nu costa un apel suplimentar — e in aceeasi tranzactie.
---
## A3. Semnatura noua
```sql
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);
```
Neschimbata fata de prima varianta ca lista de parametri — un singur parametru nou,
**`V_ID_JTVA_COLOANA`, `DEFAULT NULL`** — dar **semantica e diferita**: nu mai e "valoarea de
scris fara conditii", ci "valoarea de scris **doar daca** cota ei coincide cu cota liniei".
Procedura **nu** mai scrie `PROC_TVAV` si **nu** mai cheama `recalculeaza_totaluri_vanzari`.
**Compatibilitate inapoi — verificata, nu presupusa** (neschimbat fata de investigatia initiala):
- **Apelant unic in tot codul VFP**: `COMUN\clase\ofacturare_comun.vc2:5236`
(`inainte_de_do_termin`, dialogul `frm_modifica_articol_factura`). Cautare pe intregul working
copy (`.vc2`, `.sc2`, `.prg`) — niciun alt loc nu cheama
`pack_facturare.modifica_explicatie_articol`.
- **Niciun apelant PL/SQL**: `SELECT` pe `ALL_SOURCE`, text `MODIFICA_EXPLICATIE_ARTICOL`,
excluzand `PACK_FACTURARE` insusi — zero randuri, in orice schema din `ROA_CENTRAL`.
- Apelul existent trimite exact 3 parametri pozitionali + `?poRec.taxcode` — `V_ID_JTVA_COLOANA`
ramane `NULL`, neschimbat.
- **Ramura `V_ID_JTVA_COLOANA IS NULL` reproduce byte-cu-byte `UPDATE`-ul vechi** (aceleasi doua
coloane, acelasi `WHERE`, fara verificare noua) si face `RETURN` imediat.
---
## A4. Cazurile care nu trebuie sa treaca tacut
Pastrez regula din runda 5: cand nu se poate valida ceva desi exista date pentru validare,
procedura **nu scrie nimic** si arunca `RAISE_APPLICATION_ERROR` (rollback). Cod de eroare
urmator liber la momentul scrierii: **FACT-025** — confirmat direct pe sursa vie din
`MARIUSM_AUTO.PACK_FACTURARE` (comentariul `-- ultima eroare atribuita`), neschimbat fata de
runda 5 (runda 5 e deja aplicata, vezi nota din Partea B despre corectia facuta aici). Patru coduri
noi, FACT-026..029:
| Cod | Cand se arunca | De ce nu trece tacut |
|---|---|---|
| **FACT-026** | `V_ID_JTVA_COLOANA` dat, dar `V_ID_VANZARE_DET` nu (mai) exista sau are `STERS <> 0` | Fara o linie activa gasita nu exista `PROC_TVAV` de comparat — a continua ar insemna fie un `UPDATE` pe 0 randuri, fie o comparatie pe o valoare nedefinita |
| **FACT-027** | `V_ID_JTVA_COLOANA` dat, dar nu exista in `JTVA_COLOANE` (sau are `STERS <> 0`) | Fara `cota_tva` validata nu exista cu ce sa se compare cota liniei |
| **FACT-028** | Linia gasita (FACT-026 trecut), dar `PROC_TVAV` al ei e `NULL` | Comparatia `NULL <> x` nu e nici adevarata nici falsa in PL/SQL — a lasa `IF`-ul sa treaca tacut pe langa ea ar insemna sa scrii o explicatie fara sa stii daca respecta neutralitatea. Cazul e real: **2 randuri active au `PROC_TVAV IS NULL`** azi (confirmat cu `SELECT COUNT(*) FROM vanzari_detalii WHERE sters=0 AND proc_tvav IS NULL` — acelasi fapt semnalat in runda 5) |
| **FACT-029** | Ambele valori cunoscute, dar `ROUND(cota liniei, 4) <> ROUND(cota explicatiei, 4)` | Aceasta e garda de neutralitate ceruta de Marius — orice diferenta de cota inseamna ca alegerea ar schimba taxa liniei, deci si totalurile, daca s-ar scrie |
**Comparatia de cota** — decizie si motivare: `VANZARI_DETALII.PROC_TVAV` e `NUMBER(10,4)`,
`JTVA_COLOANE.COTA_TVA` e `NUMBER(10,0)` (confirmat pe dictionar: `ALL_TAB_COLUMNS`). Cota
explicatiei se converteste cu aceeasi formula ca in VFP, `(NVL(cota_tva,0)+100)/100`. Ambele
numere provin din fractii cu numitor 100 (19/100, 9/100, 5/100, 0/100) — reprezentabile exact in
tipul `NUMBER` (zecimal, nu binar) al Oracle, deci nu exista risc de eroare de rotunjire in
practica; `ROUND(..., 4)` pe ambele parti e adaugat ca **toleranta explicita, documentata**, nu ca
raspuns la o problema observata, ca o eventuala a cincea zecimala reziduala pe date vechi sa nu
produca un refuz fals. `NULL` pe linie **nu** e tratat ca "egal cu orice" si nici ca "diferit de
orice" prin comparatie implicita — e verificat explicit (`IF lnProcTvavLinie IS NULL THEN RAISE`),
inaintea comparatiei, tocmai ca sa nu se bazeze pe semantica NULL a lui `<>` din PL/SQL (care ar fi
lasat garda sa treaca tacut).
**Ce NU arunca eroare**: `V_ID_JTVA_COLOANA IS NULL` (apelul vechi — niciun comportament nou).
---
## A5. Riscul — categorii de documente, verdict pe fiecare
### a) Facturi intrate in e-Factura
**Nu exista azi nicio garda** pe acest flux (confirmat: `do_modifica_explicatie`/
`inainte_de_do_termin` nu verifica `EsteInEFactura`/`anaf_efactura` deloc). Cu varianta finala
(fara recalcul, fara scriere de `proc_tvav`), butonul **ramane neutru valoric** — `EXPLICATIE`,
`TAXCODE` si `ID_JTVA_COLOANA` sunt metadate de raportare, nu valori financiare ale liniei.
**Decizie: nu se adauga garda e-Factura**, nici in VFP, nici in PL/SQL — situatia de azi nu se
schimba, iar Marius nu a cerut-o.
**Observatie separata, semnalata, nu implementata**: `TAXCODE` **este** el insusi o valoare
raportata in SAF-T/e-Factura (coloana `taxcode` pe `VANZARI_DETALII`, folosita la generarea
declaratiei 406 si potential in fisierul e-Factura). Schimbarea lui pe o factura **deja trimisa**
in e-Factura (`ANAF_EFACTURA`) nu modifica totaluri, dar **poate produce o discrepanta reala**
intre ce s-a raportat/trimis deja si ce arata acum baza — factura trimisa nu se retrimite automat.
Daca acest risc conteaza pentru Marius, e o garda separata, de decis explicit (nu a fost ceruta
aici si nu blocheaza livrarea curenta).
### b) Facturi din seturi (`id_vanzare_set`)
Riscul din varianta initiala (agregarea `MAX(c.proc_tvav)` pe componentele de set in
`recalculeaza_totaluri_vanzari`) **dispare complet**, pentru ca `proc_tvav` nu mai e atins de
aceasta procedura. **Confirmat pe cod, nu presupus**: am recitit interogarea de agregare din
`recalculeaza_totaluri_vanzari` (`PACK_FACTURARE` body, ~liniile 14804-14979 din sursa vie) —
coloanele citite din `VANZARI_DETALII` pentru total sunt `pret`, `proc_tvav`, `cantitate`,
`diferenta`, `discount_unitar`, `id_valuta`, `pret_cu_tva`, `pret_achizitie`; **nici
`EXPLICATIE`, nici `TAXCODE`, nici `ID_JTVA_COLOANA` nu apar nicaieri in aceasta procedura** (si
oricum procedura de fata nu o mai cheama). Nu exista alt loc in `PACK_FACTURARE` unde
`recalculeaza_totaluri_vanzari` sau vreo alta procedura de agregare a totalurilor sa citeasca
aceste trei coloane.
**Decizie: fara garda pe `id_vanzare_set`.** Componentele de set isi pot schimba linistit
explicatia si taxcode-ul, ca orice alta linie — motivul pentru care runda 5/varianta initiala ar
fi blocat asta (efectul lui `proc_tvav` pe agregarea de set) nu se mai aplica.
### c) Facturi in valuta
Recalculul (singurul loc unde intra in joc `VANZARI_CURSURI`, scris doar la emitere — runda 5) nu
mai e apelat de aceasta procedura. **Fara relevanta pentru varianta finala** — nu exista nimic de
garda aici.
---
## Partea B — scriptul
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_20_02_COMUN_PACK_FACTURARE.sql` —
**suprascris** cu varianta finala (nu a ramas pe disc varianta cu recalcul, respinsa; a fost
inlocuita integral, nu lasata alaturi).
Pornit de la **sursa vie**, re-citita din `ALL_SOURCE` chiar pentru aceasta livrare (nu de la
scriptul anterior, respins): schema `MARIUSM_AUTO` (`current_schema` al conexiunii read-only
folosite). Diff fata de sursa vie, verificat cu `diff` linie-cu-linie:
- antetul (comentariu descriptiv, fara `*!*`/data/autor, ca la scriptul din runda 5)
- comentariul de tracking `FACT-025` -> `FACT-029`
- spec: parametrul nou `V_ID_JTVA_COLOANA IN NUMBER DEFAULT NULL` la
`modifica_explicatie_articol` (1 bloc, 4 -> 5 linii)
- body: acelasi parametru in antetul procedurii, plus corpul nou din A3/A4 — validare, **fara**
scriere de `PROC_TVAV`, **fara** apel de recalcul (1 bloc, 9 -> 49 linii); restul pachetului
(peste 16000 de randuri) neatins — verificat cu `diff`, nicio alta diferenta
- linia `exec pack_migrare.UpdateVersiune('ff_2026_08_20_02_COMUN_PACK_FACTURARE')` + `commit;`
(numele fisierului nu s-a schimbat, doar continutul)
Fisier scris in ASCII (0 octeti > 0x7F, verificat), CRLF pe toate liniile. **Scriptul nu a fost
rulat.**
**Corectie fata de raportul initial**: sectiunea A5(c) din prima versiune a acestui document
afirma ca `ff_2026_08_20_01_COMUN_PACK_FACTURARE.sql` (FACT-025, runda 5) trebuie aplicat
**inainte** de scriptul curent. Verificat direct pe baza: **`...20_01` e deja aplicat** — sursa
vie din `MARIUSM_AUTO.PACK_FACTURARE` contine deja `lnLiniiActive`/`FACT-025`. Deci **ordinea
corecta e: se aplica doar scriptul curent** (`...20_02`); re-aplicarea lui `...20_01` dupa el ar
suprascrie/sterge continutul de fata. (Fisierul `...20_01` insusi nu mai e prezent in
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\` la momentul acestei livrari — semnalat ca observatie,
nu afecteaza corectitudinea scriptului curent, care a fost construit din sursa vie din Oracle, nu
din acel fisier.)
---
## Ce ramane de facut in VFP
Pentru agentul care va scrie codul VFP (nu porneste inainte ca semnatura de mai sus sa fie
confirmata/aplicata, si nu in paralel cu `apply-meniu` — ambele ating `ofacturare_comun.vc2`):
1. **Combo nou in `frm_modifica_articol_factura`** (`ofacturare_comun.vc2:5129-5253`), langa
`cbo_saft` existent. Populat cu explicatii TVA **filtrate pe cota curenta a liniei** — apel
**`caut_explicatie_tva(poRec.id_jtva_coloana, , , , lnCotaFiltru)`**, cu `lnCotaFiltru` calculat
la fel ca in `CautaExplicatieTva` (`ofacturare_editare.prg:1142-1147`):
`Round((Nvl(poRec.proc_tvav, 0) - 1) * 100, 2)`. **Nu** lista completa — asta era varianta
respinsa. Filtrarea in UI e o comoditate (userul nu vede optiuni pe care oricum baza le va
refuza), garda reala e in PL/SQL (A2/A4). Sursa datelor: `poRec` are deja `id_jtva_coloana`,
`jtva_coloana`, `proc_tvav`, `taxcode` disponibile (schema `crsDetalii`,
`oproceduri_facturare.prg:382-387`).
2. **La alegere**: deriva `taxcode` in **VFP** (nu in PL/SQL — precizarea lui Marius confirma
directia, iar aici e verificat explicit ca se poate), prin
`GetTaxCodeIdPart(gnAn, gnLuna, poRec.data_act, ...)`, si trimite rezultatul prin parametrul
existent `V_TAXCODE`. **Verificat pe cod, nu presupus, ca `GetTaxCodeIdPart` e apelabila din
`frm_facturi`:**
- `GetTaxCodeIdPart` (`oproceduri_comune.prg:6059-6125`) nu presupune niciun cursor/formular
specific — ia doar parametri simpli si isi gestioneaza singura cursorul `jtva_coloane` (il
deschide cu `update_jtva_coloane()` daca nu e deja deschis, si il inchide la iesire daca ea
l-a deschis, `:6092-6118`).
- Lantul ei de apeluri interne — `update_jtva_coloane` (`updateserver.prg:553`),
`VERIFICA_RTVAI`/`GetCodFiscalPartenerById` (ambele in `oproceduri_comune.prg`), `GetTaxCode`
(`oproceduri_comune.prg:6130`) — sunt toate in fisiere **inregistrate necondiționat**
(`roafacturare.prg:187` `OPROCEDURI_COMUNE.PRG`, `:189` `updateserver.PRG`), spre deosebire de
`ofacturare_editare.prg` (`:214`, care e cel condiționat pe produs — de acolo vine restrictia
pe `EsteInEFactura`, nu de aici). Deci **taxcode-ul se deriva in VFP, in `frm_facturi`**, exact
ca in `frm_modific2024`, fara nicio schimbare de plan fata de propunerea initiala.
- `poRec` (din `crsDetalii`) are `data_act`? De verificat la implementare — schema confirmata
(`oproceduri_facturare.prg:382-387`) nu listeaza explicit `data_act` pe `crsDetalii`;
echivalentul e pe `crsfacturi` (headerul), de adus prin `id_vanzare`. `id_part` vine din
`crsfacturi.id_part` (`oproceduri_facturare.prg:341`). `n50`/`n100` = `.F.` (ca in
`UpdateExplicatieSAFTArt`, "nu se mai folosesc"); `neexigibil` — de stabilit explicit (sablonul
din `omodificari.vc2` il deriva din `tAct.scd`/`scc`, cursor care nu exista in `frm_facturi`;
probabil `.F.` e suficient, dar nu presupune, confirma).
3. **Lista/combo-ul poate iesi goala — trateaz-o explicit, nu lasa un dropdown gol fara
explicatie.** Verificat pe date (`SELECT` direct, read-only): pentru **toate cele 8 cote
distincte folosite azi pe linii active** (`0, 5, 9, 11, 19, 20, 21, 24` — 1122 linii in total),
**exista cel putin o explicatie TVA activa in `JTVA_COLOANE` cu aceeasi cota** (`id_jtva_coloana
> 0 AND NVL(sters,0)=0`) — deci lista **nu iese goala azi pentru nicio cota reala**. Singurele
**2 linii** unde interogarea ar iesi goala sunt exact cele cu `PROC_TVAV IS NULL` (acelasi 2
randuri de la FACT-028/runda 5) — pentru ele problema nu e "nicio explicatie cu aceasta cota", ci
"cota liniei insasi nu se cunoaste", un caz diferit si deja acoperit (PL/SQL va refuza oricum cu
FACT-028 daca s-ar incerca salvarea). Practic: **cazul "lista goala pentru o cota reala,
cunoscuta" e azi 0/1122 — teoretic posibil doar pentru o cota noua, adaugata pe o linie fara ca
nomenclatorul `JTVA_COLOANE` sa aiba inca o explicatie activa cu acea cota.**
**Recomandare de comportament** (proiectare, nu implementare): cand interogarea de populare
(`Reccount()` pe cursorul RowSource) iese cu 0 randuri, combo-ul ramane **dezactivat**
(`Enabled = .F.`), cu un text vizibil langa el (label sau tooltip, nu `messagebox` modal — nu
trebuie sa blocheze restul dialogului, care ramane editabil pe `explicatie`/`taxcode` ca azi):
> *Nu exista nicio explicatie TVA activa cu aceeasi cota ca linia facturata (cota: `<cota>` %).*
`<cota>` = `Round((Nvl(poRec.proc_tvav,0)-1)*100,2)`, acelasi calcul ca la filtrul de populare.
Daca `poRec.proc_tvav` e `NULL` (cele 2 linii identificate), afiseaza in loc:
> *Cota de TVA a acestei linii nu este cunoscuta; explicatia TVA nu poate fi modificata prin
> acest buton.*
4. **Fara garda e-Factura, fara garda de set** in aceasta parte (A5) — butonul ramane disponibil ca
azi pe orice linie/document.
4. **Apelul de salvare** (`inainte_de_do_termin`, `:5225-5233`): adauga al cincilea parametru
pozitional `?poRec.id_jtva_coloana` la textul SQL existent (`NULL`/`.NULL.` cand userul n-a
atins combo-ul nou, ca sa ramana pe ramura veche a procedurii).
5. **Trateaza eroarea FACT-029** (si FACT-026/027/028) ca orice alt esec `goExecutor.oExecuta` —
mesajul Oracle ajunge deja vizibil prin mecanismul existent (`amessagebox` in `oExecuta`), deci
nu trebuie cod nou de afisare, doar sa nu presupui ca apelul reuseste mereu.
6. **Refresh dupa salvare**: `Thisform.actualizeaza_grid2()` (apelat deja la `gnButon=1`) e
suficient acum — headerul (`crsfacturi`, totalurile) **nu se schimba**, deci nu mai e nevoie de
`Thisform.do_cauta()` suplimentar (recomandarea din varianta initiala nu se mai aplica).
**Nu s-a scris cod VFP in aceasta livrare** — punctele de mai sus sunt proiectare, nu
implementare.
---
## Rezumat surse
| ce | fisier:linie |
|---|---|
| sablonul de sincronizare (runda 5, `frm_modific2024`) | `COMUN\programe\ofacturare_editare.prg:1100-1147`, `COMUN\clase\omodificari.vc2:15049-15074` |
| `GetTaxCodeIdPart` | `COMUN\programe\oproceduri_comune.prg:6059-6125` |
| `caut_explicatie_tva` (filtru de cota la `:3218-3220`) | `COMUN\programe\ocautare.prg:3174-3238` |
| `do_modifica_explicatie` / dialog / salvare | `COMUN\clase\ofacturare_comun.vc2:4642-4659`, `:5129-5253`, `:5225-5233` |
| `crsDetalii` / `crsfacturi` (schema, populare) | `COMUN\programe\oproceduri_facturare.prg:340-412` |
| `EsteInEFactura` (doar ROAFACTURARE) | `COMUN\programe\ofacturare_editare.prg:1-30` |
| `recalculeaza_totaluri_vanzari` — nu mai e apelata din aceasta procedura, citata doar pentru A5(c) | `MARIUSM_AUTO.PACK_FACTURARE`, body linia 14784 (sursa vie) |
| garda FACT-025 (runda 5, deja aplicata) | `docs\raport_runda5_script_nvl_totaluri.md` |
| `modifica_explicatie_articol` — pristina, confirmata pe baza | `MARIUSM_AUTO.PACK_FACTURARE`, spec linia 939, body linia 13271 (sursa vie la momentul acestei livrari) |
| `PROC_TVAV`/`COTA_TVA` — precizie confirmata pe dictionar | `ALL_TAB_COLUMNS`: `VANZARI_DETALII.PROC_TVAV` = `NUMBER(10,4)`, `JTVA_COLOANE.COTA_TVA` = `NUMBER(10,0)` |
| 2 randuri active cu `PROC_TVAV IS NULL` | `SELECT COUNT(*) FROM vanzari_detalii WHERE sters=0 AND proc_tvav IS NULL` (verificat direct) |
| scriptul (suprascris) | `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_20_02_COMUN_PACK_FACTURARE.sql` |