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

11 KiB

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):

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):

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):

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):

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:

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