Files
roafacturare/docs/cercetare/linii_comanda_articol_nemembru.md
2026-09-09 22:19:22 +03:00

183 lines
11 KiB
Markdown

# Linii de comanda cu articol nemembru al politicii de pret — verificare facturare
Status: FINALIZAT.
## Verdict
**DA — s-a facturat cel putin o linie fara ca FACT-024 sa se declanseze.** Comanda `497`, linia
`4294507522` (VOUCHER DISCOUNT) / politica `7` (DISCOUNT), a fost facturata cu succes in factura
`ID_VANZARE=1028` (serie `SSS`, numar `535`, `FACTURAT=1`, `DATA_FACTURAT=2026-03-20`), desi
articolul **nu e membru** al politicii 7 in `CRM_POLITICI_PRET_ART` la data acestei cercetari
(10.08.2026). **Decizia 32 se REDESCHIDE partial**: nu pentru ca ar exista o cale de cod care ocoleste
verificarea (codul chiar cheama `contabilizeaza_articol` pentru acest tip de vanzare, cf. punctul 3),
ci pentru ca datele arata ca membru-ul politicii **s-a schimbat dupa facturare** — vezi punctul 4.
Pentru celelalte 34 de linii cu acelasi articol/politica (35 in total cu `CANTITATE<0`), **nu exista
nicio factura, nici macar stearsa** — la ele fisura ramane doar o stare inconsistenta nefacturata
(vezi punctul 1).
Observatie structurala separata de cea de mai sus: **inca 2 linii** (comenzile 114 si 115, alt articol,
alta politica) au `CANTITATE>0`, adica **nefacturate inca deloc** — pentru acestea afirmatia "ar trebui
sa cada la facturare" e neverificata pentru ca nu au fost niciodata trecute prin `contabilizeaza_articol`.
## 1. S-a facturat vreuna din ele fara eroare?
Interogare: pentru fiecare din cele 37 linii `COMENZI_ELEMENTE` cu `ID_POL NOT NULL` si articol
nemembru in `CRM_POLITICI_PRET_ART`, am cautat linii `VANZARI_DETALII` (prin `VANZARI.ID_COMANDA`)
cu acelasi `ID_ARTICOL`+`ID_POL`, **inclusiv cele sterse** (ca sa nu ratez o factura anulata):
```sql
select ce.id_comanda_element, ce.id_comanda, ce.id_articol, ce.id_pol, ce.cantitate,
(select count(*) from vanzari v join vanzari_detalii vd on vd.id_vanzare=v.id_vanzare
where v.id_comanda = ce.id_comanda and vd.id_articol=ce.id_articol and vd.id_pol=ce.id_pol) as nr_total_incl_sters
from comenzi_elemente ce
where ce.id_pol is not null and ce.cantitate < 0
and not exists (select 1 from crm_politici_pret_art cppa
where cppa.id_pol = ce.id_pol and cppa.id_articol = ce.id_articol);
```
Rezultat: **doar comanda 497** are potriviri (2 linii `VANZARI_DETALII`, id 1494 si 1495, ambele
`STERS=0`, `CANTITATE=-1` fiecare, apartinand facturii `ID_VANZARE=1028`). Toate celelalte 34 de
comenzi (349, 351, 352, 359, 360, 377, 388, 404, 412, 417, 429, 443, 447, 450, 451, 453, 455, 456,
457, 466, 471, 475, 486, 500, 501) au **0 potriviri**, inclusiv sters.
**Interpretare structurala a mecanismului** (cititul codului, nu presupunere): singurul loc care
insereaza randuri cu `CANTITATE<0` in `COMENZI_ELEMENTE` e procedura `inchide_comanda`
(`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:5769-5820`):
```sql
INSERT INTO COMENZI_ELEMENTE (... CANTITATE ...)
SELECT ..., NVL(C.CANTITATE, 0) + NVL(B.CANTITATE, 0) - A.CANTITATE AS CANTITATE, ...
FROM COMENZI_ELEMENTE A
LEFT JOIN (... FROM VANZARI_DETALII_TEMP ...) B ON ... -- lotul curent de facturare
LEFT JOIN (... FROM VANZARI JOIN VANZARI_DETALII ...) C ON ... -- deja facturat anterior
WHERE A.ID_COMANDA = :comanda
AND SIGN(A.CANTITATE) * A.CANTITATE >
SIGN(A.CANTITATE) * (NVL(C.CANTITATE, 0) + NVL(B.CANTITATE, 0));
```
Asta insemna ca randul negativ **nu dovedeste singur ca linia a fost facturata** — el reprezinta
*diferenta ramasa* fata de cantitatea comandata, la momentul **inchiderii** comenzii, chiar daca
`B` (lotul curent) si `C` (facturat anterior) sunt amandoua 0. O comanda inchisa fara sa i se
factureze o anumita linie tot primeste un rand `CANTITATE = -A.CANTITATE`. De-asta 34 din 35 de
linii "negative" nu au nicio factura in spate: comenzile respective au fost **inchise** (probabil
manual, ca "restanta anulata"), nu facturate pe acea linie. **Zero cazuri in date pentru acestea nu
demonstreaza ca nu se poate factura — demonstreaza doar ca nu s-a intamplat.**
Pentru comanda 497 insa, potrivirea cu 2 linii reale, active, `FACTURAT=1` in `VANZARI_DETALII`
e dovada directa (nu inferenta) ca acea combinatie articol/politica **a ajuns** intr-o factura emisa.
## 2. Reconfirmarea cifrei si lista liniilor
Cifra **37** se reconfirma exact (nu 6868/nemembru cum sugera masuratoarea anterioara — aceea era
alt numitor; numitorul corect pentru linii cu `ID_POL NOT NULL` e **7108**, nu 6868):
```sql
select count(*) from comenzi_elemente ce where ce.id_pol is not null; -- 7108
select count(*) from comenzi_elemente ce where ce.id_pol is not null
and not exists (select 1 from crm_politici_pret_art cppa
where cppa.id_pol = ce.id_pol and cppa.id_articol = ce.id_articol); -- 37
```
Compozitie (verificata, `select sign(cantitate), count(*) ... group by sign(cantitate)`):
- **35 linii** cu `CANTITATE=-1`: acelasi articol/politica in toate — `ID_ARTICOL=4294507522`
("VOUCHER DISCOUNT"), `ID_POL=7` ("DISCOUNT"). Comenzi: 349(x2), 351, 352(x2), 359, 360(x2), 377,
388, 404, 412(x2), 417, 429, 443, 447, 450, 451, 453, 455, 456, 457, 466, 471(x2), 475(x2),
486(x2), 497(x2), 500, 501(x2).
- **2 linii** cu `CANTITATE=+10` (nefacturate inca, nicio urma de consum):
- comanda 114, `ID_ARTICOL=4294507508` ("CAFEA TEST - PRODUS TEST PENTRU IMPORT WEB"), `ID_POL=2`
("LISTA 2"), data comanda 2025-09-10, `COMENZI.STERS` neverificat suplimentar dar randul e
prezent activ.
- comanda 115, `ID_ARTICOL=4171144217` ("CAFEA 1"), `ID_POL=2`. **Anomalie separata**: `COMENZI`
nu contine niciun rand cu `ID_COMANDA=115` — antetul comenzii lipseste, doar linia de element a
supravietuit. NEDETERMINABIL DIN DATE de ce (nu exista audit/istoric pe `COMENZI`); posibil
date de test/import, dat fiind ca articolul insusi e "CAFEA TEST ... PENTRU IMPORT WEB" pe
cealalta linie similara.
Toate cele 37 de linii au `COMENZI_ELEMENTE.STERS=0` (nicio linie de comanda marcata stearsa).
Stare de facturare per linie: singura cu urma reala de facturare e comanda 497 (vezi punctul 1);
restul de 36 sunt **nefacturate** pe aceasta combinatie articol/politica.
## 3. Verificare cod FACT-024 (`contabilizeaza_articol`)
Blocul citat in brief (`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:7278-7302`) e identic cu ce ruleaza
in productie — verificat direct in codul compilat, nu doar in scriptul istoric (fisierul `.sql` e un
istoric cumulativ cu **doua definitii** ale `contabilizeaza_articol` in text, la linia 746 si la
7173; doar a doua e cea vie):
```sql
select owner, line from all_source
where name='PACK_FACTURARE' and type='PACKAGE BODY'
and text like '%FACT-024%';
```
confirma acelasi text de eroare in schema `MARIUSM_AUTO` (Dev).
Verificarea foloseste view-ul `VCRM_POLITICI_PRET_ART`:
```sql
SELECT COMPUS, ID_POL_ART INTO ... FROM VCRM_POLITICI_PRET_ART
WHERE ID_ARTICOL = detalii_articol.id_articol AND ID_POL = detalii_articol.id_pol;
EXCEPTION WHEN NO_DATA_FOUND THEN ... RAISE_APPLICATION_ERROR(-20000, ... '(FACT-024)');
```
Am verificat textul view-ului (`user_views`): `VCRM_POLITICI_PRET_ART` are `CRM_POLITICI_PRET_ART PA`
ca tabel-sursa (driving table) al tuturor `LEFT JOIN`-urilor, fara niciun `WHERE` care sa filtreze
`PA` (nu exista coloana `STERS` pe `CRM_POLITICI_PRET_ART`). Deci view-ul are exact acelasi set de
perechi `(ID_POL, ID_ARTICOL)` ca tabelul de baza — verificarea mea prin `NOT EXISTS` pe
`CRM_POLITICI_PRET_ART` e echivalenta cu ce evalueaza codul. **Concluzie: pentru toate cele 37 de
linii, `SELECT ... INTO` ar da `NO_DATA_FOUND` -> `FACT-024`, daca ar trece prin
`contabilizeaza_articol` ACUM, cu starea curenta a `CRM_POLITICI_PRET_ART`.**
Apelul e neconditionat pentru facturi standard: am cautat toate apelurile
`pack_facturare.contabilizeaza_articol(tab_detalii(i))` in codul **compilat** (`all_source`, schema
`MARIUSM_AUTO`) — 6 aparitii, linii 4877, 4901, 5594, 5618, 5876, 5900. Linia 4901 e in procedura
`scrie_factura2` (facturarea principala), in ramura `ELSE` a unui `CASE pack_facturare.ntip` care
exclude doar transferurile intre subunitati (23,25,30,41), avizele de custodie (42,47) si facturile
cu rate (2,6,52 cu `id_rata<>0`) — **tip 3 (tipul facturii 1028) cade in ELSE, deci
`contabilizeaza_articol` chiar s-a executat pentru acea linie.**
Prin urmare, pentru comanda 497: fie (a) la data facturarii (20.03.2026) articolul 4294507522 CHIAR
era membru al politicii 7 si a fost scos ulterior din `CRM_POLITICI_PRET_ART`, fie (b) verificarea a
fost ocolita altfel. Nu am gasit dovada de tip (b) — vezi punctul 4.
## 4. Cauza
`CRM_POLITICI_PRET_ART` **nu are coloana `STERS`** si nu exista niciun tabel de istoric/audit pentru
ea (`select table_name from user_tables where table_name like '%POLITICI%' or ... '%AUDIT%'` — doar
tabelele de configurare curenta, niciunul de istoric). Stergerile din aceasta tabela sunt deci
**fizice, fara urma**. Nu pot reconstitui direct daca perechea (politica 7, articol 4294507522) a
existat la 20.03.2026.
Coloanele de audit disponibile pe randurile facturii/comenzii **nu arata nicio editare ulterioara**:
`VANZARI.ID_UTILS`/`DATAORAS` si `VANZARI_DETALII.ID_UTILS`/`DATAORAS` (1494, 1495) sunt toate NULL —
niciun `UPDATE` standard nu a atins aceste randuri dupa creare. Deci nu exista dovada ca linia de
factura ar fi fost modificata ulterior prin fluxul nou de "editare factura emisa" (adaugat recent in
proiect, cf. changelog 2.11.15) — desi asta nu exclude o editare care ar fi ocolit acele coloane de
audit, doar ca nu am gasit dovada ei.
Indiciu indirect, dar nu concludent: articolul 4294507522 e denumit **"VOUCHER DISCOUNT"**, iar
politica 7 e **"DISCOUNT"** — o pereche generica folosita ca linie de discount pe **35 de comenzi
diferite**, nu un caz izolat. Reutilizarea masiva a exact aceleiasi perechi sustine ipoteza unei
**modificari de catalog** (articolul-voucher scos ulterior din lista politicii DISCOUNT ca decizie de
business/curatare), mai degraba decat 35 de erori de introducere independente. **Aceasta ramane insa
o inferenta din tipar, nu o dovada directa — se marcheaza NEDETERMINABIL DIN DATE strict pe cauza si
data exacta a schimbarii.**
## Ce am incercat si ce a esuat
- Doua incercari de a delega cautarea codului sursa VFP/PL-SQL unui subagent `Explore` au esuat cu
raspunsuri goale/neinformative ("Nimic nou.", "No new input to act on.") — fara nicio dovada ca ar
fi rulat vreo cautare. Am renuntat la delegare si am facut cautarile direct cu Grep si Read.
- Interogarea `all_source` fara `owner=` a intors linii duplicate/interclasate (schema `ACN` are de
asemenea un `PACK_FACTURARE`) — a trebuit filtrat explicit pe `owner='MARIUSM_AUTO'` pentru
rezultate coerente.
- Un `prompt '---text---'` intre doua instructiuni SQL in acelasi fisier `.sql` a produs iesire
amestecata (headerul s-a lipit de urmatoarea instructiune) — am renuntat la `prompt` si am rulat
interogarile in fisiere separate.
## Date tehnice folosite
- Conexiune: `MARIUSM_AUTO/ROMFASTSOFT@ROA_CENTRAL` (Dev), via
`D:\ROA\instantclient_19_18\sqlplus.exe`, fisiere `.sql` ASCII in scratchpad, niciun `INSERT`/`UPDATE`/`DDL` rulat.
- Cod verificat: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`
(text istoric cumulativ) si pachetul compilat `MARIUSM_AUTO.PACK_FACTURARE` (`all_source`, sursa de
adevar pentru ce ruleaza efectiv).