# 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.
