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:
320
docs/propunere_runda6_punct6_plsql.md
Normal file
320
docs/propunere_runda6_punct6_plsql.md
Normal 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` |
|
||||
Reference in New Issue
Block a user