Transa 1 ANAF TVA: changelog 2.11.67, plan corectat pe date, handoff-uri de verificare

Plan corectat in patru puncte confirmate pe Oracle:
- lista de coloane de taxare inversa are 13 termeni, nu 10 (TI19T/TI09T nu exista pe jc2007;
  expresia din oproceduri_decont.prg:8670 e scrisa peste view-ul VJC2025, cu aliasuri calculate)
- tva_incasare nu exista pe jc2007/jv2007; interogarea transei 3 merge pe VJC2025/VJV2025
- kill-switch-ul nu se face in Optiuni_FIRMA/PROGRAM.dbf, ci pe modelul RC_ANAF_VERIF_SELECTIE
  (INI + optiuni Oracle + intrare de meniu)
- oExecute deschide dialog de reconectare cu QUIT pe conexiune cazuta; apelul din transa 3 trebuie
  sa dezactiveze explicit reconectarea

SVN r17910/r17911.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhJwsrFFe1ZNAAtS8Twuti
This commit is contained in:
2026-07-28 00:50:26 +03:00
parent 58655dac6e
commit 7cd7d57708
6 changed files with 1358 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
# TRANSA 2 (L4) — inchidere conditii de intrare — verificare Oracle
Data: 27.07.2026. Conexiune: `MARIUSM_AUTO@ROA_CENTRAL` (schema dev), read-only, doar SELECT.
Fisiere sursa salvate: `docs/local/view_anaf_vefactura_primit.sql`, `docs/local/view_anaf_vefactura_trimis.sql`.
## VERDICT GENERAL
- **A — INCHISA.** Definitiile curente extrase din `USER_VIEWS.TEXT`.
- **B — INCHISA PARTIAL.** Mecanismul e confirmat pe date, dar NU dintr-o factura venita real din import eFactura (nu exista in schema dev). Demonstrat pe cel mai apropiat caz din `jc2007`.
- **C — INCHISA, cu recomandare concreta.** Forma subselectului unic e mai jos.
- **D — INCHISA.** Sonda recomandata: `user_tab_columns`.
**CONTRAZICE PLANUL (cel mai important gasit):** lista canonica de 10 coloane din plan
(`TI21T, TI11T, TI19T, TI09T, TI24T, TI20T, XX21TIT, XX11TIT, XX19TIT, XX9TIT`) **nu compileaza
direct pe `JC2007`**. `TI19T` si `TI09T` NU exista ca si coloane pe tabela — vezi B mai jos.
---
## A. Definitiile curente ale view-urilor
Extrase din `USER_VIEWS.TEXT` (nu din arhiva CLAR), salvate integral in:
- `docs/local/view_anaf_vefactura_primit.sql`
- `docs/local/view_anaf_vefactura_trimis.sql`
Confirmari:
- `anaf_vefactura_primit.jtotctva` = subselect corelat pe `jc2007 j` + `left join nom_parteneri p`,
cheie de potrivire an/luna/dataact + `REGEXP_SUBSTR(a.xnumar_act, '\d+[^[:digit:]]*$') LIKE '%'||TO_CHAR(j.nract)||'%'`
+ `REGEXP_REPLACE(p.cod_fiscal,'[^[:digit:]]','') = a.cod_fiscal_emitent`. Exact cum descrie planul.
- `anaf_vefactura_trimis.jtotctva` = acelasi tipar dar pe **`jv2007`** (nu `jc2007`), cheie pe
`cod_fiscal_beneficiar`, filtru `a.factura_emisa = 1`. Confirma ca planul are dreptate sa puna
`jtva_ti = 0` constant la trimis: la vanzari nu exista familia `TI*`/`XX*TIT` (verificat — acele
coloane sunt specifice achizitiilor, nu apar in `jv2007`, nu a fost nevoie sa fie recalculate).
**Views DETALIU** — exista amandoua, construite peste view-urile de baza prin `id_efactura`/`id`:
- `ANAF_VEFACTURA_PRIMIT_DETALIU` (VALID) — `SELECT f.* (coloane specifice), d.* FROM anaf_vefactura_primit f JOIN anaf_efactura_detalii d ON f.id = d.id_efactura`.
- `ANAF_VEFACTURA_TRIMIS_DETALIU` (VALID) — identic, pe `anaf_vefactura_trimis`.
- Bonus gasit: exista si `ANAF_VEFACTURA_EMIS_DETALIU`, dar e **INVALID** azi (preexistent, nelegat
de L4 — de semnalat, nu de reparat aici).
Important pentru scriptul de migrare: niciuna din cele doua DETALIU nu selecteaza `jtotctva` sau
orice coloana noua din view-ul de baza (`f.*` explicit enumerat, fara `jtotctva`/`jtva_ti`) — deci
adaugarea `jtva_ti` in view-urile de baza **nu le afecteaza structural**, doar le invalideaza
temporar (dependinta VFP) pana la recompilare automata pe urmatoarea referire. Se pastreaza
verificarea de obiecte invalide ceruta de plan la finalul scriptului.
---
## B. Trasare cap-coada — CONTRAZICE PLANUL pe lista de coloane
### Ce s-a confirmat
- `ProcentTva2IdJtva` (gasita real in `COMUN\programe\oproceduri_comune.prg:5836`, NU in
`anaf_efactura.vc2` cum spune planul — functia e apelata acolo la `:12093`/`:12636`, dar
**definita** in `oproceduri_comune.prg`) confirma exact id-urile din plan pentru taxare inversa
pe JC: 21%->216, 11%->218, 19%->141, 9%->145 (`:5864-5871`).
- `oproceduri_decont.prg:8670` (citat corect de plan) e o expresie SQL, dar **din view-ul
`VJC2025`**, nu direct pe `jc2007`. Am extras `USER_VIEWS.TEXT` pentru `VJC2025`: acolo
`ti19t` si `ti09t` sunt ALIASURI calculate — `SUM(a.ti19bct + a.ti19bvt + a.ti19bft) as ti19t`,
`SUM(a.ti09bvt + a.ti09bft) as ti09t` — NU coloane fizice.
### Verificare directa pe `JC2007` (`USER_TAB_COLUMNS`)
Din cele 10 coloane canonice din plan, gasite pe tabela **8/10**:
| Coloana plan | Exista pe JC2007? |
|---|---|
| TI21T, TI11T, TI24T, TI20T | DA (coloane simple) |
| XX21TIT, XX11TIT, XX19TIT, XX9TIT | DA (coloane simple) |
| **TI19T** | **NU** — pe tabela exista in schimb `TI19BCT`, `TI19BVT`, `TI19BFT` (3 subcoloane) |
| **TI09T** | **NU** — pe tabela exista in schimb `TI09BVT`, `TI09BFT` (2 subcoloane, fara varianta `BC`) |
Un `create or replace view` care scrie `nvl(j.TI19T,0)+nvl(j.TI09T,0)` direct pe `jc2007 j` **nu
compileaza** — `ORA-00904`. Lista corecta de termeni pentru `jc2007` (13 termeni, nu 10):
```
NVL(j.TI21T,0)+NVL(j.TI11T,0)+NVL(j.TI24T,0)+NVL(j.TI20T,0)
+ NVL(j.TI19BCT,0)+NVL(j.TI19BVT,0)+NVL(j.TI19BFT,0)
+ NVL(j.TI09BVT,0)+NVL(j.TI09BFT,0)
+ NVL(j.XX21TIT,0)+NVL(j.XX11TIT,0)+NVL(j.XX19TIT,0)+NVL(j.XX9TIT,0)
```
### Factura reala cu taxare inversa — NU exista una venita din import eFactura in schema dev
- `anaf_efactura` (schema `MARIUSM_AUTO`): 487 randuri primite, doar **8** au `id_fact` completat
(legatura catre `jc2007`/`act`). Niciunul dintre acele 8 `id_fact` se suprapune cu vreun rand din
`jc2007` care are coloane `TI*`/`XX*TIT` nenule (31 randuri in toata schema, toate din test/demo,
ani 2007-2022, fara `id_fact` legat de `anaf_efactura`). Interogarea de join explicit
(`jc2007 j JOIN anaf_efactura a ON a.id_fact = j.id_fact WHERE a.factura_emisa=0 AND <TI nenul>`)
a intors **0 randuri**.
- Cele 6 randuri din `anaf_vefactura_primit` cu `id_fact` legat au `total_cu_tva = jtotctva`
(diferenta 0) — niciuna dintre ele nu e taxare inversa, deci nu demonstreaza mecanismul.
**Cel mai apropiat caz gasit** (nu vine din eFactura, e din `jc2007` direct — demonstreaza doar
aritmetica pe care view-ul o va aplica):
```
an=2022 luna=4 dataact=30-APR-22 nract=222 id_part=614 id_fact=8007136
ti19bft=19 totctva=119
```
Daca acest rand ar fi venit dintr-un import eFactura cu linie `AE` (TVA XML = 0), XML-ul ar fi
avut `total_cu_tva = 100` (119 - 19 taxare inversa), in timp ce `jtotctva` (= `SUM(totctva)`) tot
ar da `119`. Cu view-ul curent: `diferenta = total_cu_tva - jtotctva = 100 - 119 = -19` (fals
pozitiv, exact cat e TVA de taxare inversa). Cu `jtva_ti` adaugat: `diferenta = total_cu_tva -
(jtotctva - jtva_ti) = 100 - (119 - 19) = 0`. Mecanismul se confirma numeric, dar **pe un caz
sintetic, nu pe o factura reala din import eFactura** — schema dev nu are asa ceva. De consemnat
in nota de release: verificare finala pe date reale ramane de facut la prima factura de taxare
inversa importata dupa aplicarea scriptului (sau pe schema de productie/testare cu date reale,
daca exista acces).
---
## C. Verdict performanta — forma subselectului unic
Confirmat: `jtotctva` e deja un subselect scalar corelat cu `REGEXP_SUBSTR`/`REGEXP_REPLACE` in
`WHERE`, neindexabil. Recomandare: `CROSS APPLY` (Oracle 12c+, disponibil pe 19c) in loc de doi
subselecti scalari separati — un singur scan per rand din urma, ambele sume calculate odata:
```sql
SELECT ...,
jt.jtotctva,
jt.jtva_ti
FROM anaf_efactura a
CROSS APPLY (
SELECT SUM(j.totctva) AS jtotctva,
SUM(NVL(j.TI21T,0)+NVL(j.TI11T,0)+NVL(j.TI24T,0)+NVL(j.TI20T,0)
+NVL(j.TI19BCT,0)+NVL(j.TI19BVT,0)+NVL(j.TI19BFT,0)
+NVL(j.TI09BVT,0)+NVL(j.TI09BFT,0)
+NVL(j.XX21TIT,0)+NVL(j.XX11TIT,0)+NVL(j.XX19TIT,0)+NVL(j.XX9TIT,0)) AS jtva_ti
FROM jc2007 j
LEFT JOIN nom_parteneri p ON j.id_part = p.id_part
WHERE j.an = EXTRACT(YEAR FROM a.xdata_act)
AND j.luna = EXTRACT(MONTH FROM a.xdata_act)
AND j.dataact = a.xdata_act
AND REGEXP_SUBSTR(a.xnumar_act, '\d+[^[:digit:]]*$') LIKE '%' || TO_CHAR(j.nract) || '%'
AND REGEXP_REPLACE(p.cod_fiscal, '[^[:digit:]]', '') = a.cod_fiscal_emitent
) jt
WHERE a.factura_emisa = 0
```
Motiv pentru `CROSS APPLY` (nu doi subselecti separati): pastreaza exact semantica actuala — fiind
un `SUM(...)` fara `GROUP BY`, subquery-ul `APPLY` intoarce mereu exact un rand (NULL pe ambele
sume cand nu exista potrivire), identic cu comportamentul scalar-subquery de azi. Nu necesita
restructurarea restului view-ului (multe coloane scalare + `detalii` tip `M`/CLOB, imposibil de
pus curat intr-un `GROUP BY` la nivel de view fara alte modificari). Nu e scriptul de migrare final
— doar forma recomandata, de validat de cine scrie scriptul.
Pe `anaf_vefactura_trimis`: `jtva_ti` ramane `0` constant (fara subselect), deci nu exista cost
suplimentar acolo — planul are dreptate aici, nimic de schimbat.
---
## D. Sonda de coloana
Confirmat azi (inainte de migrare):
```sql
SELECT jtva_ti FROM anaf_vefactura_primit WHERE 1=2;
-- ORA-00904: "JTVA_TI": invalid identifier
```
**Recomandare: `USER_TAB_COLUMNS`**, nu `TRY` pe `SELECT`:
```sql
SELECT COUNT(*) FROM user_tab_columns
WHERE table_name = 'ANAF_VEFACTURA_PRIMIT' AND column_name = 'JTVA_TI';
```
Motive:
- Confirmat ca views apar normal in `USER_TAB_COLUMNS` (40 coloane gasite pentru
`ANAF_VEFACTURA_PRIMIT`), deci interogarea functioneaza identic pe view ca pe tabela.
- E o interogare de dictionar, fara sa declanseze parsarea/executia interogarii principale — in VFP
nu necesita un bloc `TRY/CATCH` in jurul unui `SELECT` care ar putea arunca o eroare ANAF pe
conexiunea Oracle reala (goExecutor), doar un `SELECT ... FROM user_tab_columns`, mai usor de
facut robust si de logat separat daca lipseste catalogul.
- Cost neglijabil (interogare pe dictionar, nu pe date), rulata o singura data la deschiderea
ferestrei, nu per rand.
---
## Alte observatii utile pentru cine scrie scriptul de migrare
- `TI09` nu are deloc varianta `BC` (doar `BV`/`BF`) — asimetric fata de `TI19` care are toate 3
(`BC`/`BV`/`BF`). Nu e o eroare, tabela chiar arata asa; scriptul trebuie sa scrie exact
`TI09BVT + TI09BFT` (2 termeni), nu 3.
- `XX9TIT`/`XX9TIB` (fara zero la 9) sunt corecte, exista pe tabela — confirmat, la fel cum zice
planul.
- `ANAF_VEFACTURA_EMIS_DETALIU` e INVALID in schema dev azi, independent de L4 — de mentionat catre
echipa daca cineva verifica obiecte invalide global, ca sa nu fie confundat cu o stricare produsa
de scriptul L4.