Curatenie ceruta dupa inchiderea lui #6. Folderul cercetare\ NU se putea sterge in bloc: plan_13 se sprijina pe el cu 85 de trimiteri, deci e baza de dovezi a planului aflat in lucru. Impartirea: - 14 cercetari trans-proiect trec in COMUN\docs\cercetare\ - valuta si curs, TVA/VANZARI, consumatorii VANZARI din toata suita, integrarile #10/#11/#12, watchdog VFP, proiectarea Oracle a lui S5, view-ul VVANZARI_ARTICOLE. Nu sunt ale ROAFACTURARE, iar #10/#11/#12 se reiau chiar din ele. - 20 de rapoarte de executie ale lui #6, nereferite de nimic viu, sterse. - 91 raman, neatinse. Trimiterile catre handoff-urile si diff-urile intermediare deja desfiintate au fost curatate peste tot (39 de fisiere): 50 catre handoff-uri, 37 catre diff-uri aplicate, plus caile celor mutate in COMUN. Zero trimiteri rupte ramase. progres.md preia rolul de predare: ce ramane din #6 (cele sase documente parazite, cele doua esecuri reale din S8 pe factura din aviz), cifrele de test citite din log, si cele doua capcane de mediu platite - .FXP vechi executat in locul .prg-ului, si GETFONT() care atarna un formular instantiat fara goApp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
53 KiB
CORESP_CONT_VENCHELT ca sursa de cont de venit pentru articole fara politica de pret (decizia 27)
Cercetare pe cod, read-only, fara modificari. Continua cont_venit_articol_fara_politica.md si
cont_venit_corespondente.md (care stabilisera ca SCC vine azi din NOTE_CONTABILE prin lantul
politicii de pret) si nota_contabila_fara_politica.md (care stabilise ca contabilizeaza_articol
ridica FACT-024 si opreste tranzactia cand nu exista politica).
9. Intrebarea care putea rasturna tot: "in ROAACNPRO si pe factura din comanda/contract se adauga articole fara politica de preturi — de ce nu si aici?"
Raspuns scurt, verificat pe cod: impresia e explicabila, dar niciunul din cele doua exemple nu e de
fapt un articol fara politica trecut cu bine prin contabilizeaza_articol. FACT-024 ramane blocantul
real — nu exista azi, in productie, niciun flux in care un articol ajunge la contabilizeaza_articol
fara sa fie membru al unei politici si sa treaca fara eroare.
9a) Ce verifica de fapt FACT-024 — apartenenta articolului la politica liniei, nu "id_pol e gol"
Blocul (D:\ROA\ROAFACTURARE\docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:7278-7302, citat integral
la sectiunea 6) face:
SELECT COMPUS, ID_POL_ART
INTO V_COMPUS, V_ID_POL_ART
FROM VCRM_POLITICI_PRET_ART
WHERE ID_ARTICOL = detalii_articol.id_articol
AND ID_POL = detalii_articol.id_pol;
Mesajul confirma exact asta: 'Articolul ' || ... || ' nu este definit in politica de preturi ' || ...
— verifica apartenenta articolului la politica id_pol care a ajuns pe linie, nu doar "exista vreun
id_pol". Insa id_pol nu e derivat de Oracle din client/contract/tip document — e parametru de
intrare explicit (V_ID_POL IN NUMBER, adauga_articol_factura, ff_...:4993, citat integral la
sectiunea 8a), trimis de VFP pe fiecare linie. Deci sunt doua cauze distincte care duc la aceeasi
eroare:
id_pole NULL/gol pe linie (articolul a fost ales dintr-o cautare care nu are deloc coloanaid_pol— cazulcaut_articol, sectiunea 9d) —NO_DATA_FOUNDtrivial (X = NULLnu se potriveste niciodata).id_pole o valoare reala, dar articolul nu e in lista acelei politici — la felNO_DATA_FOUND, cu acelasi mesaj. Ambele cauze converg spre FACT-024; codul nu le distinge in eroare. Formularea din intrebarea lui Marius ("nu se cauta politica articolului, ci apartenenta articolului la politica documentului") e partial corecta: verificarea e de apartenenta, darid_polnu vine din "antetul documentului" ca o singura valoare fixa — vine per-linie, de la formularul de adaugare a articolului (sectiunea 9d).
9b) ROAACNPRO — importul Roris/Contracte NU trece deloc prin contabilizeaza_articol
Verificat direct in D:\ROA\ROAACNPRO\Programe\proceduri_acnpro.prg (read-only). Cautare
pack_facturare\.|pack_acn\.|pack_contafin\. in tot fisierul — apelurile de la salvarea facturii
(factura_salvare_db, :3331-3467) sunt:
proceduri_acnpro.prg:3332 lcSql = [begin pack_facturare.initializeaza_scriere_actrul(NULL,1); end;]
proceduri_acnpro.prg:3343 lcSql = [begin pack_facturare.initializeaza_date_factura(...
proceduri_acnpro.prg:3382 lcSql = [begin pack_facturare.adauga_articol_factura_deviz(...
proceduri_acnpro.prg:3412 lcSql = [begin pack_facturare.scrie_in_vanzari(0,...
proceduri_acnpro.prg:3430 lcSql = [begin pack_acn.salveaza_regdoc(?.id, ?.id_vanzare, ?.tip, ...
Exact tiparul deja documentat pentru ROAAUTO "Alte servicii" in nota_contabila_fara_politica.md:
adauga_articol_factura_deviz (insereaza doar in VANZARI_DETALII_TEMP, fara ID_POL — semnatura
n-are acest parametru) urmat de scrie_in_vanzari (copiaza in VANZARI_DETALII, fara sa scrie vreo
nota contabila de venit) — contabilizeaza_articol nu apare deloc in acest fisier (cautare
directa contabilizeaza_articol in proceduri_acnpro.prg: zero rezultate). Nota contabila a
documentului ACN o scrie pack_acn.salveaza_regdoc, o procedura complet separata, specifica ACN,
apelata cu parametri proprii (?.id_articol, ?.id_locatia, ?.id_valuta, ?.id_client, ?.id_contract, ?.pret, ?.curs, ?.cantitate, ?.valval, ?.tvaval, ?.totval, ...) — fara id_pol in lista de
parametri. Confirmat si de raportul deja existent COMUN\docs\cercetare\import_roris_roaacnpro.md
(sectiunea 3): "nicio procedura Oracle stocata (pack_*) nu e apelata in etapa de import ...
acestea sunt apelate abia la salvarea finala", si articolele/preturile vin din dialoage de calcul tarife
proprii ACN (frm_calcul_tranzit, vctr_articole2), nu din CRM_POLITICI_PRET_ART.
Concluzie 9b: ROAACNPRO nu e un exemplu de "articol fara politica trecut cu bine prin
contabilizeaza_articol" — e un produs care nu foloseste deloc acest mecanism de contabilizare
pentru facturile lui. Impresia lui Marius e intemeiata pe experienta ("acolo merge fara sa aleg vreo
politica"), dar explicatia e alta decat "FACT-024 se poate evita" — e ca acel flux nu ruleaza deloc
codul care ar putea da FACT-024.
9c) Factura din comanda/contract in ROAFACTURARE — articolul "liber" e de fapt din lista de preturi
Deja cercetat, cu dovezi, in docs\cercetare\retur_si_lista_preturi.md sectiunea B (citit integral aici,
nu doar rezumat). Punctul central (retur_si_lista_preturi.md sectiunea B7):
- Contract (tip 2,6,26,52):
crsarticole(grila principala de articole, folosita si pentru adaugare "libera") e populat depack_facturare.cursor_contract(...), care da lista de preturi completa, nerestrictionata la continutul contractului — "azi se poate deja adauga liber din lista de preturi pe un document contract". - Comanda (tip 3):
crsarticolee populat decursor_comanda, doar articolele comenzii — nu exista adaugare libera in fluxul normal (doar prin copiere de document, care re-adauga tot dincursor_preturi).
Verificat aici, suplimentar, ca cursor_preturi (folosit si de cursor_contract, structura identica)
selecteaza explicit A.ID_POL ca coloana de output:
-- ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:2162-2167 (cursor_preturi, ramura V_TIP = 45, tipic pentru toate ramurile CASE)
OPEN V_CURSOR FOR
SELECT rownum as id_c,
B.ID_ARTICOL,
NULL AS LOT,
NULL as SERIE,
A.ID_POL,
...
si ca cursorul insusi porneste, la fiecare apel, prin pack_facturare.completare_politica_stoc()
(ff_...:2151), care garanteaza deja randuri in CRM_POLITICI_PRET_ART pentru toate articolele
IN_STOC=1 (procedura citata integral la sectiunea 8c2). Deci fiecare articol afisat in grila
"lista de preturi"/"contract" vine deja cu un id_pol valid, dintr-o politica reala, exact pentru ca
e extras printr-un join pe CRM_POLITICI_PRETURI/CRM_POLITICI_PRET_ART. "Adaugare libera pe contract"
nu inseamna "articol fara politica" — inseamna "orice articol din lista de preturi, nu doar cele din
contract", dar tot cu politica ceruta, doar aleasa implicit prin cursor, nu prin dialogul manual
do_cauta_politica.
Concluzie 9c: nu e un contraexemplu la FACT-024 — e acelasi mecanism (articol + politica), livrat
printr-o alta grila de selectie (crsarticole populat de cursor_contract in loc de caut_articol),
care intampla sa nu ceara utilizatorului sa caute manual politica pentru ca cursorul o aduce deja
atasata pe fiecare rand.
9d) Ce diferentiaza de fapt "adaugare din nomenclator" (cazul #13) de "adaugare din lista de preturi/contract" (cazul care merge azi)
Diferenta e cursorul sursa al gridului de articole, nu tipul de document:
caut_articol(COMUN\programe\ocautare.prg:1636-1735, folosit pentru cautare libera in nomenclator) — SELECT-ul confirmat laocautare.prg:1671-1689(vnom_articole_crm/vnom_articole): nu are coloanaid_polin nicio ramura (tlCRMsau nu). Un articol ales prin acest dialog ajunge inpoArticol(scatter dincrsarticole,ofacturare.vc2:12850-12851) faraid_pol— exact cazul care da FACT-024 azi, si exact cazul cerut de povestea #13 ("adaugat direct din nomenclator").cursor_preturi/cursor_contract(Oracle, sectiunea 9c) — id_pol e parte din rezultat, pentru ca interogarea porneste de la politica de pret, nu de la nomenclator.
Deci povestea #13 cere exact ce nu exista azi: un articol ales prin cautarea de nomenclator
(fara trecere prin vreo politica), caruia i se cere totusi sa treaca prin contabilizeaza_articol fara
eroare. Niciunul din exemplele lui Marius (ROAACNPRO, contract) nu demonstreaza ca asta functioneaza deja
undeva — primul nu foloseste deloc functia, al doilea nu e de fapt "fara politica".
Verdict 9
FACT-024 ramane blocantul real, confirmand (nu contrazicand) analiza din sectiunile 6-8. Nu exista
azi, pe niciun flux de productie cercetat, un caz in care un articol trece prin
pack_facturare.contabilizeaza_articol fara sa fie membru al unei politici de pret si nu cade cu
eroare. Impresia lui Marius e intemeiata pe doua experiente reale, dar explicatia lor e alta:
- ROAACNPRO: alt produs, alta procedura de contabilizare (
pack_acn.salveaza_regdoc), niciodatacontabilizeaza_articol; - Contract in ROAFACTURARE: articolul PARE liber, dar e adus printr-un cursor care il livreaza deja cu
o politica reala atasata (
cursor_contract/cursor_preturi+completare_politica_stoc).
Asta nu inseamna ca planul A (sectiunea 8, VFP alege singur un id_pol) sau planul B (sectiunea 6,
fallback in pachet) sunt de abandonat — arata insa ca niciuna din cele doua nu se poate simplifica
la "nu faceti nimic, functioneaza deja": mecanismul de protectie e real si consecvent, nu un artefact
uitat.
Constrangere noua (Marius, aparuta in timpul cercetarii): pack_facturare e plan B
Marius prefera sa nu se scrie cod nou in pack_facturare — e pachetul comun folosit de toata
suita, si orice ramura noua acolo e risc peste tot, nu doar in ROAFACTURARE. Sectiunea 6 (punctul de
injectie in pachet) ramane in raport ca informatie, dar devine plan B. Intrebarea reala, tratata in
sectiunea 8 de mai jos: se poate obtine acelasi rezultat din VFP, alegand singur un id_pol potrivit,
fara sa se modifice pack_facturare? Raspuns scurt: da, ingredientele exista deja, dar solutia nu
e "zero cod" — e cod VFP nou (nu Oracle), care se sprijina pe 3 mecanisme deja functionale in productie.
Detalii in sectiunea 8.
Concluzie: fezabil cu conditii, si conditiile sunt mai mari decat pare din formularea deciziei 27
- Verificare prioritara (sectiunea 9, ceruta de Marius in timpul cercetarii): FACT-024 ramane
blocantul real. Nu exista azi niciun flux de productie in care un articol trece prin
contabilizeaza_articolfara sa fie membru al unei politici de pret si nu cade cu eroare. ROAACNPRO nu e un contraexemplu — nu foloseste deloccontabilizeaza_articol(alta procedura de contabilizare,pack_acn.salveaza_regdoc). Contractul in ROAFACTURARE nu e un contraexemplu — articolele "libere" vin dincursor_contract/cursor_preturi, care le ataseaza deja o politica reala. Detalii complete in sectiunea 9. - Tabelul exista, e populat cu date reale si e folosit activ in productie — dar niciodata pentru
CONT_VENIT. Toti consumatorii gasiti (pack_vin, pack_devize, gestiune_pack_gest_import, gestiune_rapoarte) citescCONT_CHELT(sauCONT_APROVIZIONARE), niciunulCONT_VENIT. ColoanaCONT_VENITe completata cu date reale (o migrare din 2023 acopera 20 de conturi de gestiune), dar n-are niciun consumator — nici Oracle, nici VFP. Cititul ei pentru facturare ar fi un consumator nou, nu o reteta deja rulata in productie. - Cheia de join e stabila si testata: mereu
CONT(contul de gestiune al liniei), cu filtruSTERS = 0, prinLEFT JOIN. Pattern-ul se poate copia identic pentruCONT_VENIT. - Punctul care schimba verdictul de la "fezabil simplu" la "fezabil cu conditii mari": in
contabilizeaza_articol, ramura "articol simplu" nu executa nimic (niciscrie_nota, nicidescarca_gestiune) dacacursor_articol(care citeste dinCRM_POLITICI_PRET_ART) nu gaseste niciun rand — si nu gaseste niciun rand exact in cazurile in care azi se ridica FACT-024. Un simplu "prinde exceptia si continua" ar produce o linie facturata fara nota contabila si fara descarcare de gestiune, fara nicio eroare — mai rau decat blocajul actual. Fallback-ul cere o ramura noua, paralela cursorului, nu doar inlocuirea unei valori. - Chiar cu ramura noua,
CU_TVAsiIN_VALUTA(cota TVA inclusa in pret / linie in valuta) nu au nicio sursa alternativa in afaraNOTE_CONTABILE. Corespondentele siNOM_ARTICOLE.CONTdau doar un cont, nu aceste doua semnale de interpretare a pretului — ele trebuie fie hardcodate (risc de calcul gresit al bazei/TVA), fie cerute ca intrare noua de la utilizator/articol. - 704 ca literal de fallback are un precedent real in suita, dar in alt subsistem: proprietatea
cconte = 704("cont implicit articol client") dinfrm_configurare_efactura(COMUN\clase\anaf_efactura.vc2:8376), folosita la import eFactura, nu inpack_facturare. Nu e o reteta gata scrisa pentru facturare, dar arata ca alegerea lui Marius nu e arbitrara in suita.
1. CORESP_CONT_VENCHELT exista? Structura, DDL, consumatori
Exista. Nu are CREATE TABLE in arhiva D:\ROA\DATABASE\SCRIPTURI_CLAR (arhiva incepe 2009-2010,
tabelul e mai vechi — acelasi motiv pentru care NOTE_CONTABILE/CRM_NOTE_VANZARI nu au CREATE TABLE
in arhiva, documentat deja in cont_venit_corespondente.md).
Coloane confirmate din ALTER TABLE + CREATE OR REPLACE VIEW (cronologic):
CONT,CONT_CHELT,CONT_VENIT,STERS— preexistente arhivei (folosite direct in view-ul din 2010 faraALTER TABLEpremergator vizibil).CONT_APROVIZIONARE varchar2(4)— adaugata 19.02.2010 (D:\ROA\DATABASE\SCRIPTURI_CLAR\2010\02\ff_2010_02_19_03_GESTIUNI.sql:9:alter table CORESP_CONT_VENCHELT add CONT_APROVIZIONARE varchar2(4);).CONT_DIFERENTE varchar2(4)— adaugata 05.02.2015 (D:\ROA\DATABASE\SCRIPTURI_CLAR\2015\02\ff_2015_02_05_01_GESTIUNE.sql:6-7:alter table coresp_cont_venchelt add cont_diferente varchar2(4);+comment on column CORESP_CONT_VENCHELT.cont_diferente is 'cont diferente de pret pe NIR fata de pretul din factura de achizitie (ex: 6588 = 401 sau 308 = 401)';).- Nu am gasit
ID_CCV/DATAORASin DDL-ul cercetat (cautare directa, zero rezultate inSCRIPTURI_CLAR) — interogarea din decizia 27 (select id_ccv, cont, cont_chelt, cont_venit, sters, dataoras, cont_aprovizionare, cont_diferente from coresp_cont_venchelt) le presupune, dar tabelul fiind pre-arhiva, DDL-ul complet nu e in cod static. Ramane de verificat pe baza vie (vezi sectiunea finala) — probabilID_CCVe cheia surogat (PK) siDATAORASun timestamp tehnic, tipar comun in suita ROA pentru tabelele de configurare, dar neconfirmat din DDL. - Toate coloanele
CONT*suntvarchar2(4)(confirmat dinALTER TABLEexplicit pentruCONT_APROVIZIONARE/CONT_DIFERENTE; consistent cu tratarea lor ca cod de cont in tot codul citit).
View-ul consumat de VFP, VCORESP_CONT_VENCHELT, filtreaza deja STERS = 0 (deci VFP nu mai trebuie
sa filtreze separat):
-- D:\ROA\DATABASE\SCRIPTURI_CLAR\2015\02\ff_2015_02_05_01_GESTIUNE.sql:10-13
create or replace view vcoresp_cont_venchelt as
select cont, cont_chelt, cont_venit, cont_aprovizionare, cont_diferente
from coresp_cont_venchelt
where sters = 0;
Populare cu date reale — CONT_VENIT e completat, nu doar declarat. Migrare dedicata 23.02.2023
(D:\ROA\DATABASE\SCRIPTURI_CLAR\2023\02\ff_2023_02_23_01_COMUN.sql:1-21, titlul chiar din fisier:
-- Completare cont venit pe corespondenta 3xx - 6xx/7xx):
update CORESP_CONT_VENCHELT set cont_venit = '707' where cont = '301';
update CORESP_CONT_VENCHELT set cont_venit = '707' where cont = '302';
update CORESP_CONT_VENCHELT set cont_venit = '707' where cont = '3021';
... (3022,3023,3024,3025,3026,3028, 303 -> tot '707')
update CORESP_CONT_VENCHELT set cont_venit = '711' where cont = '331';
update CORESP_CONT_VENCHELT set cont_venit = '711' where cont = '332';
update CORESP_CONT_VENCHELT set cont_venit = '702' where cont = '341';
update CORESP_CONT_VENCHELT set cont_venit = '7015' where cont = '345';
update CORESP_CONT_VENCHELT set cont_venit = '703' where cont = '346';
update CORESP_CONT_VENCHELT set cont_venit = '7015' where cont = '348';
update CORESP_CONT_VENCHELT set cont_venit = '7018' where cont = '361';
update CORESP_CONT_VENCHELT set cont_venit = '707' where cont = '371';
update CORESP_CONT_VENCHELT set cont_venit = '707' where cont = '381';
Deci pentru conturile de gestiune uzuale (marfuri 371/381, materii prime 301-303/3021-3028, produse
finite 345/348, semifabricate 341, animale 346, ambalaje 381) exista deja o valoare CONT_VENIT
configurata in Oracle, de 3 ani. Datele exista — intrebarea e doar cine le citeste.
Ecran de configurare in VFP: NU exista. Cautare exhaustiva CORESP_CONT_VENCHELT (case-insensitive)
in D:\ROA\ROAFACTURARE\COMUN -> exact 3 fisiere, niciunul un formular de editare:
COMUN\clase\ointroduceri.vc2:2— un comentariu de istoric (19.02.2010, mentioneazacrsconfigcvc (coresp_cont_venchelt)), nu cod.COMUN\programe\ointroduceri.prg:733(proceduraupdate_corespondente_cvc, citata integral mai jos) — unSELECTcare reincarca un cursor local, nu scrie in tabel.COMUN\programe\updateserver.prg:733— acelasiSELECT, alt loc de apel.
-- COMUN\programe\ointroduceri.prg:727-743
Procedure update_corespondente_cvc
If Used('crsconfigcvc')
Use In crsconfigcvc
Endif
*!* 19.02.2010
lcSql = [select cont,cont_chelt,cont_venit, cont_aprovizionare, cont_diferente from vcoresp_cont_venchelt order by cont]
*!* 19.02.2010 ^
lnSucces = goExecutor.oExecute(lcSql,[crsconfigcvc])
If lnSucces < 0
amessagebox(goExecutor.cEroare,16,"Eroare")
Endif
goExecutor.oReset()
Return lnSucces
Endproc
Deci tabelul e intretinut exclusiv prin scripturi SQL manuale (cele din SCRIPTURI_CLAR, rulate de un
DBA/dezvoltator la nevoie), nu printr-un formular VFP — la fel ca alte tabele tehnice de configurare mai
vechi din suita. Nu exista niciun INSERT INTO CORESP_CONT_VENCHELT in arhiva (randurile de baza,
CONT/CONT_CHELT/CONT_VENIT, predateaza arhiva); doar UPDATE/ALTER TABLE pentru coloanele
adaugate ulterior (CONT_APROVIZIONARE in 2010, CONT_DIFERENTE in 2015, valorile CONT_VENIT in
2023).
2. Cheia de cautare
CONT = contul de gestiune al liniei, mereu. Confirmat prin 4 exemple reale de JOIN, in module
diferite:
- pack_vin (
D:\ROA\DATABASE\SCRIPTURI_CLAR\2023\07\ff_2023_07_18_02_VIN_PACK_VIN.sql:1579-1589, procedurainregistreaza_materiale):aiciFROM (SELECT SUM(...) as suma, A.CONT as SCC, A.ACONT as ASCC, A.ID_GESTIUNE FROM VIN_RULAJE_TEMP A WHERE A.TIP = V_TIP GROUP BY A.ID_GESTIUNE, A.CONT, A.ACONT) A LEFT JOIN CORESP_CONT_VENCHELT B ON A.SCC = B.CONT AND B.STERS = 0;A.SCCe de fapt contul de gestiune (aliasulSCCvine din contextul rulajului de stoc, nu dinNOTE_CONTABILE) — deci join-ul e totcont_gestiune = B.CONT. - pack_devize (14+ aparitii identice intre 2013-2014, ex.
D:\ROA\DATABASE\SCRIPTURI_CLAR\2014\01\ff_2014_01_22_01_DEVIZE_PACK_DEVIZE.sql:3214-3217):from rul_temp a left join coresp_cont_venchelt b on a.cont = b.cont and b.sters = 0rul_temp.conte contul de gestiune al articolului din rulajul de stoc. - gestiune_pack_gest_import (5+ aparitii 2013-2017, ex.
D:\ROA\DATABASE\SCRIPTURI_CLAR\2017\05\ff_2017_05_31_01_GESTIUNE_PACK_GEST_IMPORT.sql:512):left join coresp_cont_venchelt b— pea.cont = b.cont(acelasi tipar). - Raport recent, 2026 (
D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\ff_2026_07_23_01_GESTIUNE_RAPOARTE.sql:25-29, viewVRUL_ACT_CHELTUIELI):cel mai recent consumator gasit (23.07.2026), deci tabelul e inca "viu" in productie — dariesiri AS ( SELECT R.*, CC.CONT_CHELT AS CONT_CHELT_CORESP FROM VRUL_TOT R LEFT JOIN CORESP_CONT_VENCHELT CC ON CC.CONT = R.CONT AND CC.STERS = 0 WHERE R.STERS = 0 AND R.CANTE <> 0 )CONT_CHELT_CORESPcalculat aici nici nu apare inSELECT-ul final al view-ului (e calculat si abandonat), semn ca tiparul de "join pe CONT, ia campul de care ai nevoie" e suficient de standard incat sa fie reutilizat fara alta discutie de design. - In VFP:
Select crsconfigcvc; Locate For Cont = Upper(Alltrim(...))— vezi sectiunea 3, mereu aceeasi cheieCONT.
Nu am gasit nicio discriminare suplimentara pe gestiune/tip document. Toate JOIN-urile/LOCATE
sunt strict pe CONT (+ STERS = 0), fara ID_GESTIUNE, fara TIP_DOC. ID_CCV nu apare folosit ca
FK in niciun cod cercetat — pare o simpla cheie surogata a tabelului, neexpusa in VCORESP_CONT_VENCHELT
(view-ul nu o include).
Ambiguitate / mai multe randuri active pentru acelasi CONT: nu exista UNIQUE/PRIMARY KEY
vizibil in cod (DDL-ul e pre-arhiva), dar toate cele ~20 de utilizari reale presupun un singur rand
activ per CONT — niciun cod cercetat foloseste DISTINCT, ROW_NUMBER(), MAX(...) sau alt
mecanism de dezambiguizare pe rezultatul join-ului. Daca ar exista doua randuri active cu acelasi CONT,
LEFT JOIN-ul ar multiplica randurile din interogarea principala (risc de dublare de suma in
pack_vin/pack_devize) — nu exista protectie in cod contra acestui caz. Presupunerea de unicitate e
implicita in tot codul care exista deja, nu doar in propunerea lui Marius.
3. Cine il foloseste azi — CONT_CHELT are 4 module consumatoare, CONT_VENIT are zero
| Consumator | Fisier | Coloana citita |
|---|---|---|
pack_vin.inregistreaza_materiale |
ff_2023_07_18_02_VIN_PACK_VIN.sql:1567 (si variante 2010/2012/2014) |
CONT_CHELT |
pack_devize (procedura de calcul cost material, 14+ export-uri 2013-2014) |
ff_2014_01_22_01_DEVIZE_PACK_DEVIZE.sql:3222 (si altele) |
CONT_CHELT (in GROUP BY, folosit ca SCD) |
pack_gest_import (5+ export-uri 2013-2017) |
ff_2017_05_31_01_GESTIUNE_PACK_GEST_IMPORT.sql:512 |
CONT_CHELT (deductie din context, tipar identic) |
VRUL_ACT_CHELTUIELI (raport, 2026) |
ff_2026_07_23_01_GESTIUNE_RAPOARTE.sql:26 |
CONT_CHELT (calculat, needatat in output final) |
VFP ointroduceri.vc2 (bon consum, finalizare aprovizionare, transfer) |
:5476-5490 (oinventar.vc2), :14663-14681, :15327-15332 |
CONT_CHELT, CONT_APROVIZIONARE |
VFP ointroduceri.vc2 (diferente NIR vs factura) |
:15395-15403 (bloc dezactivat IF .F.) |
CONT_DIFERENTE (cod comentat/mort, nu ruleaza azi) |
Niciun consumator pentru CONT_VENIT — cautare directa CONT_VENIT (case-insensitive) in tot
D:\ROA\DATABASE\SCRIPTURI_CLAR (arhiva completa 2009-2026): doar 3 fisiere, toate deja citate (2 view-uri
care includ coloana in SELECT fara sa o consume, 1 script de populare cu date). In VFP, cautare
cont_venit (case-insensitive) in COMUN si ROAGEST: un singur hit, SELECT ... cont_venit ... in
update_corespondente_cvc/updateserver.prg (fetch in cursor), zero utilizari ale campului dupa
fetch (nicio referinta .cont_venit/crsconfigcvc.cont_venit gasita).
Concluzie: propunerea lui Marius ar fi primul consumator real al CONT_VENIT in toata suita,
desi coloana e populata din 2023. Reteta "citeste corespondenta pe cont de gestiune" e deja rulata in
productie de 10+ ani, dar mereu pentru latura CONT_CHELT (cheltuiala la consum de stoc), niciodata
pentru CONT_VENIT (venit la vanzare). Riscul tehnic al join-ului (cheie, filtru STERS, tipul
LEFT JOIN) e deja validat de utilizarea existenta; riscul de date (daca valorile CONT_VENIT
completate in 2023 sunt corecte/complete pentru toate conturile de gestiune folosite azi in facturare,
nu doar cele 20 acoperite explicit) e nou si neverificat pe baza vie.
4. Semantica coloanelor
Dedusa din utilizari reale, nu din nume:
CONT: contul de gestiune/stoc al liniei (clasa 3xx: 301-303, 331/332, 341, 345/346/348, 361, 371, 381) — cheia de cautare in toate cazurile vazute (sectiunea 2).CONT_CHELT: contul de cheltuiala (6xx) care se debiteaza cand marfa/materialul iese din gestiune (consum, bon de consum, productie) — confirmat de toti cei 4+ consumatori din sectiunea 3, unde e folosit mereu caSCD(debit) pe o nota de tip "iesire din gestiune".CONT_VENIT: prin simetrie de nume si migrarea din 2023 ("cont venit pe corespondenta 3xx-7xx"), e menit sa fie contul de venit (7xx) corespunzator vanzarii aceluiasi cont de gestiune — dar nu are niciun consumator care sa confirme comportamentul in executie (nicio ramura de cod care sa arate ce se intampla laNULL, la vanzare partiala, la retur). Semantica e dedusa din nume + date, nu din utilizare, contrar regulii "nu presupune semantica dupa nume" — de aceea marchez ca ipoteza, nu fapt verificat pe comportament.CONT_APROVIZIONARE: contul folosit la operatia "finalizare aprovizionare" (ID_SET264/265), cand se transfera valoarea din contul de tranzit (401 sau alt cont de gestiune) intr-un cont de gestiune specific de tranzit intern (32x) — confirmat de comentariul din DDL 2010 si de utilizarea inointroduceri.vc2:15323-15332(Case Alltrim(Upper(oSet.explicatia)) = 'FINALIZARE APROVIZIONARE' ... lcContC = Alltrim(cont_aprovizionare)).CONT_DIFERENTE: contul folosit pentru diferentele de pret intre NIR si factura de achizitie — confirmat de comentariul DDL 2015 ("cont diferente de pret pe NIR fata de pretul din factura de achizitie, ex: 6588 = 401 sau 308 = 401") si de codulointroduceri.vc2:15394-15403, dar acel bloc e dezactivat (IF .F. THEN ... ENDIF), deci in executia curenta ramane mereu fallback-ul hardcodat'6588'— dovada ca chiar si un camp cu semantica clara si comentariu explicit poate ajunge neutilizat in productie, ceea ce intareste incertitudinea despreCONT_VENIT.STERS: flag boolean soft-delete, filtrat explicit= 0in toate utilizarile gasite (view-ulVCORESP_CONT_VENCHELTil filtreaza deja la nivel de view; join-urile Oracle directe pe tabel il filtreaza explicitAND B.STERS = 0/AND CC.STERS = 0). Niciun cod cercetat citeste randuri cuSTERS = 1.DATAORAS: nu apare in niciun cod cercetat (Oracle sau VFP) — nu am gasit nicio referinta directa la aceasta coloana in afara interogarii propuse in decizia 27. Tipic in suita ROA e un timestamp tehnic de audit (data ultimei modificari a randului), dar neconfirmat aici — ramane de verificat pe schema vie.- Ambiguitate pe
CONT: vezi sectiunea 2 — niciun cod nu trateaza cazul "mai multe randuri active pentru acelasi CONT"; presupunerea de unicitate e implicita, nu impusa de o constrangere vizibila.
5. NOM_ARTICOLE.CONT pentru articole negestionabile si fallback pe 704
NOM_ARTICOLE.CONTnu e restrans la clasa 3 — reconfirmat (vezi dejacont_venit_corespondente.mdsectiunea 2): validareaverific_cont(COMUN\programe\oproceduri_comune.prg:2389-2415) verifica doar ca contul exista in planul de conturi al anului, fara filtru de clasa; niciunCHECK CONSTRAINTin DDL. Deci campul poate contine legitim un cont 6xx/7xx pentru un articol negestionabil, exact cum presupune decizia 27.- Niciun fallback pe
704existent inpack_facturare— cautare'704'(literal SQL) inD:\ROA\ROAFACTURARE\docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql(17000+ linii, exportul curent al pachetului): zero rezultate. Cautare in totD:\ROA\DATABASE\SCRIPTURI_CLAR\2026(toate scripturile din 2026): zero rezultate. Fallback-ul pe 704 propus de Marius ar fi cod nou, nu o reteta deja scrisa inpack_facturare. - Exista totusi un precedent independent pentru 704 ca "cont implicit de venit", in alt subsistem:
E o proprietate cu valoare implicita
COMUN\clase\anaf_efactura.vc2:8370-8376 (clasa "frm_configurare_efactura") *p: cconte && cont implicit articol client *p: ccontp && cont implicit articol furnizor ... cconte = 704 ccontp = 628704("cont implicit articol client", deci un cont de venit implicit pentru liniile generate la import eFactura) intr-un ecran de configurare a modulului ANAF eFactura. Nu am gasit cod care sa citeasca explicit.cconte(cautare\.cconte\bin totCOMUN: zero rezultate) — proprietatea e definita cu valoare implicita, dar consumatorul ei concret n-a fost gasit in timpul alocat (posibil legat generic la un camp de configurare cu acelasi nume, tipar comun in suita, dar neconfirmat aici). Ce arata cu certitudine: alegerea704ca implicit pentru "cont articol client" nu e o inventie a acestei cereri — a mai fost aleasa o data, independent, de altcineva din echipa (sau de Marius insusi, in alt moment), pentru un scop asemanator. Nu e insa o reteta de cod reutilizabila direct inpack_facturare— e in alt pachet/clasa, alt flux (import, nu emitere).
6. Punctul de injectie in contabilizeaza_articol
Sursa: D:\ROA\ROAFACTURARE\docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql (exportul curent al
pachetului, 17548+ linii). Numerotarea de mai jos e din acest fisier, verificata prin citire directa
(difera cu cateva linii fata de exportul mai vechi citat in rapoartele anterioare, care avea FACT-024 la
7301 in loc de 7311 — normal, fisierul a mai fost actualizat intre timp).
Structura exacta a blocului care ridica FACT-024 (:7275-7302, inceputul functiei):
7275 BEGIN
7276
7277 -- 05.07.2011
7278 BEGIN
7279 SELECT COMPUS, ID_POL_ART
7280 INTO V_COMPUS, V_ID_POL_ART
7281 FROM VCRM_POLITICI_PRET_ART
7282 WHERE ID_ARTICOL = detalii_articol.id_articol
7283 AND ID_POL = detalii_articol.id_pol;
7284 EXCEPTION
7285 WHEN NO_DATA_FOUND THEN
7286 SELECT DENUMIRE
7287 INTO lcArticol
7288 FROM NOM_ARTICOLE
7289 where id_articol = detalii_articol.id_articol;
7290
7291 SELECT NUME_LISTA_PRETURI
7292 INTO lcPolitica
7293 FROM CRM_POLITICI_PRETURI
7294 where id_pol = detalii_articol.id_pol;
7295
7296 RAISE_APPLICATION_ERROR(-20000,
7297 'Articolul ' || detalii_articol.id_articol || '|' ||
7298 lcArticol ||
7299 ' nu este definit in politica de preturi ' ||
7300 detalii_articol.id_pol || '|' || lcPolitica ||
7301 '! (FACT-024)');
7302 END;
Acesta e locul unde s-ar decide "articolul nu are politica" — dar NU e suficient sa se schimbe doar acest bloc. Motivul, cu citate exacte:
- Dupa acest bloc, codul verifica
IF V_COMPUS = 1 THEN(articol compus,:7305, ridica alta eroare, FACT-016)ELSE(:7391) — ramura "articol simplu" care e cea relevanta pentru cazul cerut. - Ramura "articol simplu" deschide un cursor nou,
cursor_articol(definit la:7218-7271), filtrat exact pe aceeasi cheie care a datNO_DATA_FOUNDmai sus:7261 FROM CRM_POLITICI_PRET_ART A ... 7268 WHERE 7269 -- A.STERS = 0 AND 7270 A.ID_POL = detalii_articol.id_pol 7271 AND A.ID_ARTICOL = detalii_articol.id_articol; - Tot corpul de lucru real (calculul
V_SCD/V_ASCD/V_SCC/V_ASCC/V_EXPLICATIE, apelulpack_facturare.scrie_nota(...)la:7443-7467, apelulpack_facturare.descarca_gestiune(...)la:7476-7498, scrierea discountului la:7501-7518) e in interiorulWHILE cursor_articol%FOUND LOOP(:7396-7541). Daca articolul nu are politica de pret, acest cursor nu returneaza niciun rand (e exact aceeasi conditie care a datNO_DATA_FOUNDla pasul 1, pe acelasi(id_pol, id_articol)), deci bucla ruleaza zero iteratii.
Concluzia tehnica: daca s-ar modifica doar blocul EXCEPTION WHEN NO_DATA_FOUND (pasul 1) ca sa nu
mai ridice RAISE_APPLICATION_ERROR si sa lase V_COMPUS := 0 implicit, executia ar trece la ramura
"articol simplu", ar deschide cursor_articol, acesta ar gasi tot zero randuri (aceeasi cauza), bucla nu
ar rula deloc, si functia ar reveni RETURN V_INCASAT_CALCUL cu valoarea initiala 0
(declarata la :7178), fara sa scrie nicio nota contabila si fara sa descarce gestiunea — silentios,
fara nicio eroare. Asta e o regresie mai grava decat FACT-024: azi tranzactia se opreste vizibil; cu un
fallback naiv, factura s-ar emite fara inregistrare contabila si fara descarcare de stoc, nedetectabil
fara audit manual.
Ce ar cere de fapt fallback-ul, pentru a pastra comportamentul actual cand politica exista:
- Blocul de la pasul 1 ar trebui sa distinga explicit cazul "politica lipseste" (continua cu
fallback) de cazul "articol compus fara politica" (probabil tot eroare, nu e in scopul cerut) —
posibil punand un flag local (
V_ARE_POLITICA := FALSE) in loc deRAISE_APPLICATION_ERROR. - Ar trebui adaugata o ramura noua, in afara/inainte de bucla
cursor_articol, activa doar candV_ARE_POLITICA = FALSE, care sa:- calculeze
V_SCD/V_ASCDreutilizandCASE-ul existent pe tip document (:7398-7423— acesta nu depinde decursor_articol, poate fi extras/reutilizat identic); - calculeze
V_SCCdin sursa noua (corespondente pentru articol gestionabil /NOM_ARTICOLE.CONTsau704pentru negestionabil) — doar acest pas e cel descris de decizia 27; - decida un
V_ASCC(azi vine dinNVL(crs_rand_articol.ascc, GetAnaliticByGrupUtilizatori(...))— fara rand din cursor, ar trebui sa cada direct peGetAnaliticByGrupUtilizatori(...), posibil fara modificare, pentru ca aceasta functie nu depinde de cursor); - decida
V_EXPLICATIE,ID_VENCHELT,ID_SECTIE,CU_TVA,IN_VALUTA— vezi sectiunea 7, aici e gaura reala, nu doar cod de rescris. - apeleze explicit
pack_facturare.scrie_nota(...)si, conditionat,descarca_gestiune(...), cu parametrii calculati mai sus, duplicand (nu reutilizand) logica din interiorul buclei existente.
- calculeze
Asta confirma exact avertismentul din decizia 27 insasi ("modificare in COMUN, cu impact peste toata
suita") — nu e un IF adaugat pe o linie, e o ramura noua de ~40-60 linii care trebuie sa reproduca o
parte din logica ramurii existente, cu surse diferite pentru fiecare camp.
7. Ce se pierde fata de lantul complet CRM_POLITICI_PRET_ART -> ... -> NOTE_CONTABILE
Aceasta e partea centrala a raspunsului: fallback-ul pe cont de venit (corespondente + nomenclator +
704) acopera doar SCC, nu si restul campurilor pe care lantul de politica de pret le aduce azi din
NOTE_CONTABILE fara efort. Campurile aduse azi de D.EXPLICATIE, D.SCD, D.ASCD, D.SCC, D.ASCC, D.CU_TVA, D.IN_VALUTA (cursor_articol, :7248-7253, 7259-7260) si ce se intampla cu fiecare fara
politica:
SCD/ASCD(contul debitor si analiticul lui): nu se pierde —V_SCDse calculeaza deja independent deNOTE_CONTABILE, dintr-unCASEpe tipul de document (:7398-7423, ex.461pt aviz catre debitori,418pt aviz simplu,crs_rand_articol.scddoar pt factura normala — dar acesta din urma tot vine dinNOTE_CONTABILE.SCDprin cursor, deci pt factura normala SCD s-ar pierde la fel ca SCC). Corectie necesara fata de formularea initiala a intrebarii: nu doar SCC vine dinNOTE_CONTABILEpt factura normala — si SCD (contul de creante, tipic 411) vine de acolo. Decizia 27 vorbeste doar de "cont de venit", nu de contul debitor — inseamna ca si sursa luiV_SCDpentru factura normala ar trebui rezolvata (probabil un cont fix, gen 411/4111, dar nu e in scopul deciziei 27 asa cum e formulata azi).CU_TVA: se pierde, fara alta sursa in cod. Controleaza daca pretul de pe linie e interpretat cu sau fara TVA la scrierea sumei (pack_facturare.scrie_nota(...), parametrucrs_rand_articol.cu_tvala:7463). Nu exista nicio coloana echivalenta inCORESP_CONT_VENCHELTsauNOM_ARTICOLE. Fara ea, fallback-ul trebuie sa aleaga o valoare hardcodata sau sa o deriveze din alt camp deja disponibil pedetalii_articol(ex.pret_cu_tva, vazut ca parametru separat la:7447— posibil suficient, dar necesita verificare separata, nu facuta aici).IN_VALUTA: se pierde, fara alta sursa. Controleaza daca linia e tratata ca fiind in valuta la nivel de nota contabila (V_IN_VALUTA := crs_rand_articol.in_valuta;la:7470, folosit apoi la discount:7507). La fel caCU_TVA, nicio coloana echivalenta in corespondente/nomenclator.EXPLICATIE: se pierde ca sablon configurat, dar are deja fallback partial in cod —V_EXPLICATIEe calculat cu unCASEpe tipul de operatie (:7430-7439, ex. concateneazapack_facturare.cdescrierept facturi tip 7) folosindcrs_rand_articol.explicatieca baza; fara cursor, baza ar fi goala/NULL, dar structuraCASEinsasi nu depinde de cursor — impact moderat, nu blocant.ID_VENCHELT: are deja un fallback la nivel de sesiune —NVL(pack_facturare.nid_venchelt, NVL(A.ID_VENCHELT, C.ID_VENCHELT))(:7244-7245) — dacapack_facturare.nid_venchelte setat global (parametru de sesiune), fallback-ul functioneaza deja fara politica; daca nu e setat, ramaneNULL(fara eroare in cod, dar posibil relevant pentru rapoarte care folosesc aceasta dimensiune, neverificat).ID_SECTIE: acelasi tipar —NVL(pack_facturare.nid_sectie_stoc, C.ID_SECTIE)(:7246), cu fallback pe variabila de sesiune.ID_SET(identificatorul setului de nota folosit la scriere): nu se pierde — parametrul trimis efectiv lascrie_notaepack_facturare.nid_set(variabila de sesiune,:7462), nucrs_rand_articol.id_setdin cursor (acel camp e citit la:7247dar nu e folosit la apelul de scriere in ramura articol simplu — verificat direct in cod). Deci acest camp special nu depinde de politica de pret.
Rezumat sectiunea 7: din cele 7 campuri aduse de lantul politicii de pret, 2 (ID_VENCHELT,
ID_SECTIE) au deja fallback pe variabile de sesiune si ar functiona fara politica; EXPLICATIE are
impact moderat (structura de calcul ramane, doar baza se pierde); ID_SET nu depinde deloc de politica
in ramura articol simplu; dar CU_TVA si IN_VALUTA nu au nicio sursa alternativa — sunt gaura reala
pe care simpla adaugare a unui cont de venit din corespondente/nomenclator nu o umple. Confirmarea
finala a intrebarii din cerere: da, fallback-ul pe cont de venit e insuficient pentru o nota contabila
completa — nu pentru ca "SCC" ar fi gresit, ci pentru ca doua campuri de control (TVA, valuta) raman fara
sursa.
8. Varianta VFP, fara sa se atinga pack_facturare (plan A, cerut de Marius)
Ideea de verificat: daca contabilizeaza_articol deriva SCC din id_pol, VFP ar putea sa aleaga
singur, inainte de a trimite articolul, un id_pol a carui nota are deja SCC = contul de venit
calculat dupa regula lui Marius — pachetul ar rula neschimbat. Raspunsul, punct cu punct:
a) id_pol vine din VFP? Da — e trimis explicit, pe fiecare linie
Semnatura efectiva a procedurii apelate pe fluxul principal (verificat direct in export, nu presupus):
D:\ROA\ROAFACTURARE\docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:4989-5015
PROCEDURE adauga_articol_factura(V_ID_TEMP IN NUMBER,
V_ID_ARTICOL IN NUMBER,
V_SERIE IN VARCHAR2,
V_EXPLICATIE IN VARCHAR2,
V_ID_POL IN NUMBER,
V_ID_GESTIUNE IN NUMBER,
...
V_CONT IN VARCHAR2,
...
V_ID_POL e parametru de intrare explicit — Oracle nu il deriva din client/contract/tip document, il
primeste ca atare de la VFP. Niciun alt parametru din aceasta lista nu ofera un canal pentru
SCC/id_set (raspuns si la punctul d — vezi mai jos).
De unde il ia azi VFP: din controlul de cautare obligatoriu al formularului frm_articol_factura
(clasa ofacturare.vc2):
COMUN\clase\ofacturare.vc2:6822-6825
ADD OBJECT 'Ct_clb_politici_preturi' AS ct_clb_cautare WITH ;
cconditie = ISNULL(poDate.id_pol) or EMPTY(poDate.id_pol), ;
cprocedura = thisform.do_cauta_politica, ;
cvar_afisata = poDate.nume_politica, ...
COMUN\clase\ofacturare.vc2:7167-7182
PROCEDURE do_cauta_politica
Local loCauta
loCauta = caut_politici_curente_util()
If !Isnull(loCauta) And !Empty(Nvl(loCauta.id_pol,0))
poDate.id_pol = loCauta.id_pol
poDate.nume_politica = loCauta.nume
...
cconditie = ISNULL(poDate.id_pol) or EMPTY(poDate.id_pol) e exact starea "articol fara politica" din
cererea #13 — controlul UI cere explicit utilizatorului sa caute o politica cand campul e gol. VFP
controleaza integral valoarea: azi vine din alegerea utilizatorului, dar nimic tehnic nu impiedica sa fie
setata programatic, fara interactiune, la un id_pol calculat.
b) Drumul invers e interogabil? Da — e simetricul exact al cursorului deja documentat la sectiunea 6
Cursorul din contabilizeaza_articol (ff_...:7261-7267) merge
CRM_POLITICI_PRET_ART -> CRM_POLITICI_PRETURI -> CRM_NOTE_VANZARI -> NOTE_CONTABILE prin
A.ID_POL = B.ID_POL, B.ID_NOTA = C.ID_NOTA, C.ID_SET = D.ID_SET. Interogarea inversa, plecand de la
un SCC dorit catre id_pol-urile candidate, foloseste aceleasi coloane de legatura, doar fara filtrul
pe articol:
SELECT DISTINCT PP.ID_POL
FROM CRM_POLITICI_PRETURI PP
JOIN CRM_NOTE_VANZARI NV ON NV.ID_NOTA = PP.ID_NOTA
JOIN NOTE_CONTABILE NC ON NC.ID_SET = NV.ID_SET
WHERE NC.SCC = :cont_venit_calculat; -- '707'/'711'/'702'/'703'/'7015'/'7018' (gestionabil) sau valoarea din NOM_ARTICOLE.CONT/'704' (negestionabil)
E o interogare noua (nu am gasit-o deja scrisa nicaieri in cod), dar foloseste exclusiv coloane si
relatii deja confirmate ca existente si corecte (sectiunea 1 din cont_venit_corespondente.md + citirea
directa a cursor_articol la sectiunea 6 a acestui raport). Neverificat pe date reale: cate randuri
returneaza pentru fiecare SCC candidat — zero (nicio politica configurata cu acel SCC azi), unul
(cazul ideal) sau mai multe (ambiguitate: care id_pol se alege?). Interogarea de rulat pe baza vie e
chiar cea de mai sus, cu :cont_venit_calculat inlocuit pe rand cu 707, 711, 702, 703, 7015,
7018, 704.
c) Se poate insera din VFP un rand in CRM_POLITICI_PRET_ART? Da — cod existent, functional, deja rulat in productie
Doua mecanisme distincte, ambele reale:
c1. RPC direct, apelabil din VFP azi — pack_preturi.adauga_politica_pret_art, apelat din
ofacturare.vc2 in procedura de modificare a listei de preturi la NIR (ID_SET = 231):
COMUN\clase\ofacturare.vc2:15551-15587
*!* verific daca exista articolul in politica de preturi
lcSql = [Select id_pol_art, id_venchelt, proc_tvav from crm_politici_pret_art where id_pol = ] + Alltrim(Str(tnIdPol)) + [ and id_articol = ] + Alltrim(Str(tnIdArticol))
lnSucces = goExecutor.oExecute(m.lcSql, "cPoliticiPretArt")
...
If Nvl(loPoliticaPretArt.id_pol_art,0) = 0
lcSql = [begin pack_preturi.adauga_politica_pret_art(] + ;
ALLTRIM(Str(tnIdPol)) + [,] + ; && id_pol
Alltrim(Str(tnIdArticol)) + [,] + ; && id_articol
Alltrim(Str(tnPretLista,20,4)) + [,] + ; && pret
Alltrim(Str(tnPretftvaLista,20,4)) + [,] + ; && pretftva
Alltrim(Str(tnPretvtvaLista ,20,4)) + [,] + ; && pretctva
[NULL, ] + ; && id_valuta
Alltrim(Str(tnProcTvav,20,4)) + [,] + ; && proc_tvav
[NULL, ] + ; && procent
[NULL, ] + ; && id_venchelt
Alltrim(Str(gnIdUtil)) + ; && id_util
[); end;]
Verifica intai daca exista deja un rand (id_pol, id_articol), si daca nu, insereaza unul nou prin RPC
existent — exact tiparul necesar pentru punctul (c): "adauga articolul X in politica de pret Y",
apelabil din VFP fara nicio modificare de pachet (pack_preturi nu e pack_facturare).
c2. Auto-populare in masa, deja existenta in pack_facturare insusi, dar fara parametru nou — o
procedura care nu ar necesita nicio modificare de cod pentru ca deja exista si e apelabila ca atare:
D:\ROA\ROAFACTURARE\docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:2093-2120
PROCEDURE completare_politica_stoc IS
BEGIN
IF pack_facturare.nid_politica_stoc IS NOT NULL THEN
MERGE INTO CRM_POLITICI_PRET_ART A
USING (SELECT ID_ARTICOL FROM NOM_ARTICOLE
WHERE STERS = 0 AND INACTIV = 0 AND IN_STOC = 1) B
ON (A.ID_POL = pack_facturare.nid_politica_stoc AND A.ID_ARTICOL = B.ID_ARTICOL)
WHEN NOT MATCHED THEN
INSERT (ID_POL, ID_ARTICOL, ID_VALUTA)
VALUES (pack_facturare.nid_politica_stoc, B.ID_ARTICOL, pack_facturare.nid_moneda_nationala);
...
END IF;
END completare_politica_stoc;
Aceasta e o functie existenta, apelabila fara nicio modificare, care garanteaza deja un rand in
CRM_POLITICI_PRET_ART pentru orice articol cu IN_STOC = 1 sub o singura politica "de stoc"
(pack_facturare.nid_politica_stoc). Acest id_pol e la randul lui o optiune de configurare controlata
din VFP:
COMUN\clase\ofacturare.vc2:21733-21734 (Init-ul ecranului de optiuni facturare)
actualizeaza_politica_pret(23,@gnId_pol_pret_tr,@lcPolPretTr)
actualizeaza_politica_pret(1,@gnId_pol_pret_stoc,@lcPolPretStoc)
...
COMUN\clase\ofacturare.vc2:21753
This.nidpolpretstoc = Nvl(gnId_pol_pret_stoc,0)
gnId_pol_pret_stoc e o optiune globala (ID_POL_PRET_STOC, salvata/citita prin
actualizeaza_politica_pret), care alimenteaza pack_facturare.nid_politica_stoc la initializarea
sesiunii Oracle. Avertisment: aceasta politica pare deja folosita azi pentru un scop specific
(vanzare/evaluare la pret de stoc — nin_valuta, nTipVanzareRetail sunt tratate diferentiat pentru ea
la ff_...:7223-7260), cu o singura nota/SCC configurata pentru toate articolele IN_STOC=1. Nu e
direct reutilizabila pentru reteta pe 6 conturi diferite (707/711/702/703/7015/7018) ceruta de decizia
27 — dar arata modelul exact ("o politica tehnica, configurata o singura data, populata automat"),
model care se poate replica de cate ori e nevoie (o politica tehnica per SCC distinct), fara sa se
toate cod in pack_facturare.
d) Alte cai de bypass la nivel de parametru — cautate explicit, nu gasite
Semnatura completa a adauga_articol_factura (sectiunea a) si a variantelor _deviz/_stoc (deja
citate in cont_venit_articol_fara_politica.md) nu au niciun parametru pentru cont de venit sau
id_set direct — singurul levier disponibil la nivelul acestui apel e V_ID_POL. Nu exista un
parametru V_SCC/V_ID_SET/V_COD_VENIT pe nicio varianta citita. Concluzie: id_pol e singura
cale de influenta din VFP asupra contului de venit, exact premisa din care a pornit intrebarea.
e) Verdict onest
Cale VFP posibila, dar nu "zero cod" si nu fara pasi de configurare o singura data:
- VFP calculeaza
SCC-ul dorit exact ca in decizia 27 (interogare simpla, deja tipul de cod scris inupdate_corespondente_cvc— sectiunea 1 a acestui raport):CORESP_CONT_VENCHELT.CONT_VENITpe contul de gestiune pentru articol gestionabil,NOM_ARTICOLE.CONT(daca e 6xx/7xx) sau'704'pentru negestionabil. - VFP cauta (interogarea de la punctul b) o
id_polexistenta a carei nota are deja acelSCC. Daca gaseste una (plauzibil pentru conturile comune 707/711/702/703, care probabil se folosesc deja in politici de pret reale ale firmei) — trece la pasul 3 direct, fara nicio configurare noua. - VFP se asigura (RPC
pack_preturi.adauga_politica_pret_art, punctul c1, deja existent) ca exista un randCRM_POLITICI_PRET_ARTpentru (acelid_pol, articolul curent) — insereaza unul cu pretul tastat manual de utilizator (tnPretLista= pretul liniei) daca nu exista. - VFP trimite acel
id_polinadauga_articol_factura, exact ca pe fluxul actual (cu politica).contabilizeaza_articolruleaza neschimbat — si, bonus fata de varianta plan B (sectiunea 7), campurileCU_TVA/IN_VALUTA/EXPLICATIE/ASCD/ASCCvin corect din nota reala configurata, nu raman goale ca in fallback-ul partial din pachet.
Ce nu e gratuit:
- Pasul 2 poate rata (nicio politica existenta cu acel
SCC) — pentru unSCCfara precedent (de ex.704, pentru care nu am gasit nicio nota configurata azi, sectiunea 5), ar trebui creat manual, o singura data, un lant nouCRM_POLITICI_PRETURI+CRM_NOTE_VANZARI+NOTE_CONTABILE(contabilul configureaza nota dinfrm_config_note_contabile[2007], deja documentat incont_venit_corespondente.mdsectiunea 1) — asta e configurare (ecran existent), nu cod nou, dar e un pas manual, nu automat. - Efect lateral real: o "politica tehnica" (creata special pentru acest mecanism) ar aparea in
ecranul de cautare politici al utilizatorului (
caut_politici_curente_util(), aceeasi functie folosita la cautarea normala) — trebuie fie exclusa explicit din acel cursor de cautare (filtru pe un flag/prefix dedicat), fie acceptata ca vizibila, cu riscul ca un utilizator sa o aleaga din greseala pentru o factura normala. Nu am verificat dacacaut_politici_curente_util()are deja un filtru care ar exclude automat politici fara preturi reale/marcate altfel. - Ambiguitatea de la pasul 2 (mai multe
id_polcu acelasiSCC) ar cere o regula de departajare (cea mai recenta? prima gasita? o marcare explicita "politica implicita pentru SCC X"?) — neverificat pe date reale, vezi sectiunea "Ramas de verificat". - Aceasta varianta schimba
id_pol-ul scris pe linie (aziNULL/gol pentru articol fara politica, ar deveni id-ul politicii tehnice) — orice raport/ecran care azi presupune "id_polgol = articol fara politica" (de ex. eventuale filtre in rapoarte de vanzari) ar vedea unid_polpopulat; nu am gasit cod care sa faca aceasta presupunere explicit, dar nici n-am cautat-o exhaustiv (in afara bugetului).
Concluzie e): nu e nevoie de "niciuna dintre cai" pentru un "nu" — exista o cale VFP verificabila si
construita din piese deja functionale in productie (RPC de inserare in politica de pret, plus o
interogare de cautare inversa noua dar directa). E fezabila, probabil mai completa decat plan B
(rezolva si CU_TVA/IN_VALUTA, nu doar SCC), dar cere: (i) o interogare noua de cautare id_pol pe
SCC, (ii) reutilizarea unui RPC existent pentru inserarea articolului in politica, (iii) potential
configurare manuala o singura data (nota noua) pentru SCC-urile fara precedent, (iv) o decizie explicita
despre cum se exclude/trateaza politica tehnica in ecranele de cautare vizibile utilizatorului.
Ramas de verificat pe baza de date vie
- Structura completa DDL a
CORESP_CONT_VENCHELT(DESC coresp_cont_vencheltsau echivalent): confirmarea coloanelorID_CCV(probabil PK surogat) siDATAORAS(probabil timestamp tehnic), tipurile exacte, nullability, si daca exista o constrangereUNIQUE/index peCONT(relevant pentru ambiguitatea discutata in sectiunea 2 si 4) — DDL-ul nu e in arhivaSCRIPTURI_CLAR(tabel pre-2009). Interogare de verificat:SELECT column_name, data_type, nullable FROM user_tab_columns WHERE table_name = 'CORESP_CONT_VENCHELT' ORDER BY column_id;siSELECT index_name, uniqueness FROM user_indexes WHERE table_name = 'CORESP_CONT_VENCHELT';. - Continutul complet al
CONT_VENIT— migrarea din 2023 acopera 20 de conturi de gestiune; ramane de verificat daca acopera toate conturile de gestiune folosite azi inNOM_ARTICOLE.CONT/STOC.CONTin productie (altfel fallback-ul ar produceCONT_VENIT = NULLpentru conturi de gestiune neacoperite). Interogare:SELECT DISTINCT cont FROM (SELECT cont FROM nom_articole UNION SELECT cont FROM stoc) WHERE cont NOT IN (SELECT cont FROM coresp_cont_venchelt WHERE sters = 0);. - Daca exista mai mult de un rand activ (
STERS = 0) pentru acelasiCONT— cod critic pentru join-uri fara dezambiguizare. Interogare:SELECT cont, COUNT(*) FROM coresp_cont_venchelt WHERE sters = 0 GROUP BY cont HAVING COUNT(*) > 1;. - Valorile reale din
NOM_ARTICOLE.CONTpentru articole negestionabile — cate au deja un cont 6xx/7xx explicit vs. cate au un cont 3xx "gresit" (articol marcat negestionabil dar cu cont de gestiune ramas din import) vs. cate auNULL/gol, ceea ce ar decide cat de des s-ar folosi de fapt fallback-ul pe704. Interogare:SELECT SUBSTR(cont,1,1) AS clasa, COUNT(*) FROM nom_articole WHERE gestionabil = 0 GROUP BY SUBSTR(cont,1,1);(numele exact al coloaneigestionabilde verificat pe schema). Verificat si numele exact al coloaneiNOM_ARTICOLE.CONT— vezi sicont_venit_articol_fara_politica.md. - Cine citeste efectiv proprietatea
ccontedinfrm_configurare_efactura— nu am gasit consumatorul in codul static cercetat (\.cconte\b, zero rezultate inCOMUN); posibil legata generic la o configuratie pe nume de camp, tipar comun in suita, dar neconfirmat. - Comportamentul
scrie_nota/ACT_TEMPlaSCD/SCCNULL sau laCU_TVA/IN_VALUTANULL — codul PL/SQL nu are validare (confirmat innota_contabila_fara_politica.md, sectiunea 2), dar constrangerile reale de tabel (ACT/ACT_TEMP,NOT NULL?) nu au fost verificate — ar decide daca o implementare pe jumatate facuta a fallback-ului ar da eroare Oracle explicita (ORA-01400) sau ar trece silentios.