135 lines
8.3 KiB
Markdown
135 lines
8.3 KiB
Markdown
# View-urile eFactura: ANAF_VEFACTURA_*
|
|
|
|
Cele sapte view-uri prin care ROA citeste facturile electronice descarcate/incarcate la ANAF, plus
|
|
regula de potrivire cu registrul de TVA. Suna simplu si nu e: potrivirea are doua ramuri, cateva
|
|
invariante de performanta si un istoric de fals-pozitive platite scump. Cine le atinge citeste
|
|
intai aici.
|
|
|
|
## Tabelele reale si view-urile peste ele
|
|
|
|
Tabelele sunt `ANAF_EFACTURA` (antetul, un rand per factura) si `ANAF_EFACTURA_DETALII` (liniile).
|
|
Coloana `FACTURA_EMISA` desparte cele doua lumi: `0` = achizitie (primita), `1` = vanzare
|
|
(trimisa). Restul sunt view-uri:
|
|
|
|
| View | Peste ce | La ce foloseste |
|
|
|---|---|---|
|
|
| `ANAF_VEFACTURA_PRIMIT` | `ANAF_EFACTURA` + `JC2007` + `NOM_PARTENERI` | achizitii, cu potrivirea in jurnalul de cumparari |
|
|
| `ANAF_VEFACTURA_TRIMIS` | `ANAF_EFACTURA` + `JV2007` + `NOM_PARTENERI` | vanzari, cu potrivirea in jurnalul de vanzari |
|
|
| `ANAF_VEFACTURA_EMIS` | + `VANZARI`, `VNOM_VALUTE` | facturile emise din ROA, legate de documentul intern |
|
|
| `ANAF_VEFACTURA_DETALII` | `ANAF_EFACTURA_DETALII` + `NOM_ARTICOLE`, `NOM_GESTIUNI` | liniile, cu articolul si gestiunea ROA potrivite |
|
|
| `..._PRIMIT_DETALIU`, `..._TRIMIS_DETALIU`, `..._EMIS_DETALIU` | detaliile filtrate pe view-ul de antet respectiv | griduri de detaliu |
|
|
|
|
Unde se consuma: **borderoul eFactura**, `COMUN\programe\import_efactura.prg`,
|
|
`PROCEDURE vizImportEFactura` - alege `anaf_vefactura_primit` sau `anaf_vefactura_trimis` dupa
|
|
parametrul `PRIMITE`/`TRIMISE` (linia 27) si coloreaza randurile dupa diferenta fata de jurnal.
|
|
Detaliile se iau din `anaf_vefactura_detalii` (linia 60). Vizualizarea XML e in
|
|
`COMUN\programe\anaf_efactura.prg`, `PROCEDURE viz_efactura_xml` / `viz_spv`.
|
|
|
|
Pe ecran, `jtotctva` e coloana `cJtotcTVA` din `COMUN\clase\anaf_efactura.vc2`, prezenta pe toate
|
|
cele trei griduri ale formularului: `pgfeFactura.Page1.grdFacturiEmise` (`anaf_efactura.vc2:1240`),
|
|
`Page2.grdFacturiPrimite` (`:2713`) si `Page3.grdFacturiTrimise` (`:4029`).
|
|
|
|
## Potrivirea cu registrul de TVA: jtotctva si jtva_ti
|
|
|
|
`jtotctva` = totalul cu TVA gasit in jurnal pentru factura respectiva. **`jtotctva IS NULL`
|
|
inseamna "documentul nu e in registrul de TVA"** - nu exista o coloana separata cu numarul de
|
|
potriviri, nulul e semnalul. `jtva_ti` (doar pe `PRIMIT`) e TVA-ul de taxare inversa, ca borderoul
|
|
sa nu coloreze fals facturile cu 4426=4427; pe `TRIMIS` e constanta 0.
|
|
|
|
Potrivirea are **doua ramuri legate prin `COALESCE`**, in ordinea asta:
|
|
|
|
1. **dupa numar** - aceeasi zi, acelasi partener, iar `NRACT` din jurnal e unul din grupurile de
|
|
cifre ale lui `XNUMAR_ACT` (sau concatenarea tuturor cifrelor). Ramura normala, acopera
|
|
aproape tot.
|
|
2. **rezerva pe valoare** - aceeasi zi, acelasi partener, aceeasi suma cu TVA. Ruleaza numai
|
|
pentru randurile unde prima a intors NULL.
|
|
|
|
## Ce NU se atinge - fiecare regula e platita
|
|
|
|
- **`COALESCE`, nu `NVL` si nu `OR`.** `COALESCE` isi evalueaza argumentele lene, deci a doua
|
|
ramura ruleaza doar unde prima n-a gasit nimic. Unite prin `OR` in aceeasi subinterogare:
|
|
peste 10 minute pe acelasi set de date, si potrivire nediferentiata a oricarui document cu
|
|
aceeasi suma la acelasi partener in aceeasi zi (masurat pana la 49 de documente pentru o
|
|
singura factura).
|
|
- **Forma predicatului pe numar.** Grupurile de cifre se extrag din `XNUMAR_ACT` (coloana din
|
|
exterior) si se compara cu `j.nract` prin `IN`, ca `NRACT` sa intre in `access()` pe
|
|
`IDX_JC2007_003` / `IDX_JV2007_003`. Scris invers, ca `REGEXP_LIKE` peste `j.nract`, nu mai e
|
|
sargabil: 97 de secunde in loc de 1,4 pe acelasi lot.
|
|
- **`avg`, nu `sum`, pe rezerva pe valoare.** Doua facturi cu aceeasi valoare, acelasi partener,
|
|
aceeasi zi potriveau fiecare ambele randuri din jurnal, iar `sum()` dadea valoare dubla.
|
|
- **`sum(NVL(j.totctva,0))`, nu `sum(j.totctva)`**, ca `sum()` sa fie NULL doar cand nu s-a
|
|
potrivit niciun rand - altfel `jtotctva` si `jtva_ti` pot alege ramuri diferite.
|
|
- **`HAVING`-ul de anti-ghicire pe rezerva pe valoare.** Se potriveste doar daca numarul de
|
|
eFacturi din aceeasi zi, cu acelasi cod fiscal si aceeasi valoare, nu depaseste numarul de
|
|
randuri de jurnal cu acea valoare. Mai multi pretendenti decat randuri = nu se ghiceste.
|
|
**`having count(*) = 1` e interzis**: exista cazul real a doua facturi cu aceeasi valoare,
|
|
acelasi partener, aceeasi zi, ambele in jurnal.
|
|
- **`ID_FACT` nu e utilizabil la achizitii** - se completeaza doar cand factura e inregistrata din
|
|
wizardul de import (13 randuri din 970 pe schema de test).
|
|
- **`SERIE_ACT` nu e cheie** - exista in `JC2007`/`JV2007`, dar e populat ~3%.
|
|
- Un document apare in `JC2007` cu mai multe randuri (`an`/`luna` diferite, reportarea
|
|
neexigibilului), de aceea view-urile filtreaza `j.an`/`j.luna` dupa `xdata_act` si ramura pe
|
|
numar foloseste `sum()`.
|
|
- **Fara obiecte noi si fara indecsi noi.** S-au respins deja: view ajutator cu numerele
|
|
candidate, `not exists` de anti-revendicare, ramura pe `ID_FACT`.
|
|
- Scris compatibil **Oracle 11g**.
|
|
|
|
## Codul fiscal: cand se cere egalitate si cand nu
|
|
|
|
Codul fiscal se normalizeaza pe **ambele** parti (`REGEXP_REPLACE(upper(...), '[^[:digit:]]','')`),
|
|
nu doar cel din `NOM_PARTENERI`.
|
|
|
|
La persoanele fizice care nu isi declara CNP-ul, XML-ul duce la ANAF `CompanyID`-ul cumparatorului
|
|
completat cu **13 de zero** (`0000000000000`) - eticheta nu poate lipsi - in timp ce partenerul din
|
|
`NOM_PARTENERI` are `COD_FISCAL` NULL. Egalitatea stricta nu se poate implini niciodata, deci
|
|
toate facturile catre persoane fizice ieseau cu `jtotctva` NULL. La un client de vending: 20780
|
|
din 47369 de facturi emise.
|
|
|
|
De aceea, **numai pe ramura pe numar din `ANAF_VEFACTURA_TRIMIS`**, pe langa egalitate se accepta
|
|
si cazul in care **ambele** parti sunt "fara cod fiscal" (normalizat: NULL, gol sau numai zerouri).
|
|
Garda pe ambele parti e esentiala: o factura cu cod fiscal real nu poate prinde randul unui
|
|
partener fara cod fiscal, si invers.
|
|
|
|
Relaxarea **nu costa indecsi**: conditia de cod fiscal era si inainte un filtru dupa jonctiune, nu
|
|
un predicat de acces - are `REGEXP_REPLACE` peste ambele coloane, deci nu putea intra niciodata in
|
|
`access()`. `EXPLAIN PLAN` pe productie da acelasi plan hash (`1870929383`) si acelasi cost inainte
|
|
si dupa: `NRACT` ramane in `access()` pe indexul din `JV2007`, `AN`/`LUNA` raman filtru pe tabela,
|
|
iar `OR`-ul nou apare doar in `filter()` peste randurile deja aduse. Ce alege randurile e tot
|
|
numarul plus data.
|
|
|
|
**Rezerva pe valoare ramane stricta**, si `ANAF_VEFACTURA_PRIMIT` la fel:
|
|
|
|
- la un client cu vanzare catre persoane fizice, valorile identice in aceeasi zi sunt frecvente,
|
|
iar la acelasi client 17034 din 24006 parteneri nu au cod fiscal - relaxata acolo, rezerva ar
|
|
potrivi documente nediferentiat;
|
|
- la achizitii nu exista niciun `COD_FISCAL_EMITENT` nul sau cu zerouri, furnizorii sunt persoane
|
|
juridice.
|
|
|
|
## Unde stau si cum se livreaza
|
|
|
|
View-urile se recreeaza integral din scripturile `ff_*_COMUN_EFACTURA.sql` din
|
|
`D:\ROA\DATABASE\SCRIPTURI_CLAR\<an>\<luna>\`. Fiecare script **isi poarta motivatia in antet** -
|
|
acolo sunt masuratorile si cazurile reale care au dus la forma actuala; se citeste inainte de orice
|
|
modificare si nu se rescrie fara motiv.
|
|
|
|
Ultimele: `ff_2026_07_29_01_COMUN_EFACTURA.sql` (potrivirea dupa numar, sargabila),
|
|
`ff_2026_08_28_01_COMUN_EFACTURA.sql` (`HAVING`-ul de anti-ghicire + cazul persoanelor fizice).
|
|
Rollback = se ruleaza pur si simplu scriptul anterior.
|
|
|
|
Sursa de referinta pentru DDL e schema `MARIUSM_AUTO` de pe `ROA_CENTRAL`, nu productia - vezi
|
|
`scripturi-migrare-db.md`. Publicarea la clienti: `COMUN\utile\publicare_scripturi.ps1`
|
|
(`publicare-scripturi-db.md`); fisierele trebuie **CRLF si ASCII pur**.
|
|
|
|
**Changelog: nu.** O modificare numai de baza de date, fara versiune noua de executabil, nu intra
|
|
in `changelog_roacont.txt` - changelog-ul insoteste livrarea unui `.exe`.
|
|
|
|
## Cum se verifica o modificare inainte de livrare
|
|
|
|
Comparatie rand-cu-rand intre view-ul curent si expresia corectata, pe o schema de productie cu
|
|
volum real, numarand patru lucruri: **reparate**, **pierdute**, **valoare schimbata**, **ramase
|
|
NULL**. "Pierdute" si "valoare schimbata" trebuie sa fie **zero** - orice altceva inseamna ca
|
|
modificarea atinge si cazuri la care nu te asteptai. Sablonul de interogare e in
|
|
`D:\ROA\ROACONT\docs\analiza_efactura_cnp_zerouri.md`.
|
|
|
|
Conectarea la productie prin tunel: `conexiuni-tunel-ssh-odbc.md`. Pe productie **doar `SELECT`**.
|