Paisprezece rapoarte care nu erau ale ROAFACTURARE traiau in docs\cercetare\ al acelui proiect: valuta si curs in ofacturare, TVA calculat vs salvat plus denormalizarea VANZARI, inventarul consumatorilor VANZARI din toata suita ROA, integrarile de contracte/politici/nomenclator (#10, #11, #12), watchdog-ul VFP de testare, proiectarea Oracle a scrierii din S5 si view-ul VVANZARI_ARTICOLE. Motivul mutarii, nu doar al pastrarii: planurile #10, #11 si #12 sunt amanate, iar indexul lor spune explicit ca se reiau din aceste rapoarte - deci sunt punct de plecare, nu istoric. Iar tinta lor e COMUN plus ROAPRETURI/ROACONTRACTE. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
12 KiB
Anatomia butonului "Import Roris & Contracte" (ROAACNPRO)
Cercetare read-only in D:\ROA\ROAACNPRO, ca model pentru un buton generic
"importa articole din sursa" intr-un formular de facturare unificat in ROAFACTURARE.
Nicio editare de fisiere, niciun git_sync.ps1/txt2vcx.ps1, niciun commit — doar investigatie.
1. Localizare
Concluzie: Butonul e cmdImport (clasa cmd_executa) pe formularul frm_factura, definit in
Clase\oacnpro.vc2. Nu are Click propriu — mosteneste Click din clasa de baza a butoanelor,
care ruleaza metoda numita in proprietatea caction; cmdImport nu suprascrie caction, deci
ramane valoarea implicita do_executa mostenita de la clasa cmd_executa
(COMUN\clase\cmd_butoane.vc2:474). Codul efectiv e in PROCEDURE do_executa a formularului
frm_factura.
Dovezi:
Clase\oacnpro.vc2:6894-6905— definirea controlului:ADD OBJECT 'cmdImport' AS cmd_executa WITH ... Caption = "\<Import Roris & Contracte", ... Left = 597, Top = 65, Width = 169COMUN\clase\cmd_butoane.vc2:474—caction = do_executa(mostenit decmd_executa).COMUN\clase\_cmd_base.vc2:120-159—PROCEDURE Clicka clasei de baza: construiestelcCommand = [this.Parent.] + lcAction + ...si il executa cu macro (&lcCommand).Clase\oacnpro.vc2:7814-7836—PROCEDURE do_executaa luifrm_factura(clasa incepe laoacnpro.vc2:6398 DEFINE CLASS frm_factura, se termina la8383).
2. Preconditii
Concluzie: Butonul e activ doar daca (a) factura nu e inca salvata (llFacturaEditabila) si
(b) tipul facturii (poDate.cTip, ales din cboTip) e unul din
TRANZIT, CHEIAJ, CHIRII, APA, PENALITATI. In plus, la Click, do_executa verifica separat ca a
fost ales clientul.
Dovezi:
Clase\oacnpro.vc2:8117-8145:llFacturaEditabila = !This.lFacturaSalvata llRorisSauContracte = INLIST(poDate.cTip, 'TRANZIT', 'CHEIAJ', 'CHIRII', 'APA', 'PENALITATI') && butonul import RORIS&Contracte este activ doar pentru RORIS sau contracte ... .cmdImport.Enabled = m.llFacturaEditabila and m.llRorisSauContracteClase\oacnpro.vc2:7820-7823:IF EMPTY(NVL(this.nIdClient,0)) AMESSAGEBOX('Alegeti clientul!',0+48,_screen.Caption) RETURN ENDIF- Fara client ales, butonul e vizibil/activ dar Click-ul se opreste cu acest mesaj.
3. Ce face efectiv
Concluzie: do_executa -> factura_import() (Programe\proceduri_acnpro.prg:3151) ramifica
dupa poDate.cTip:
- TRANZIT/CHEIAJ:
vizualizare_tranzit()-> deschide dialogulfrm_tranzit(selectie convoaie din vederea Oracleips_vvoyages) -> la confirmare,calcul_tranzit()/calcul_cheiaj()interogheaza direct (SELECT-uri simple, nu pachete PL/SQL) tabelele/vederileips_vvoyage_members_calcul,ips_vvoyage_locks, apoi deschide un al doilea dialog de editare tarife (frm_calcul_tranzit). - CHIRII/APA:
vizualizare_contract()->calcul_contract()-> SELECT din vedereavctr_articole2(articole de contract) -> dialogfrm_calcul_contract. - PENALITATI:
vizualizare_penalitati()->frm_penalitaticu cursorulcrsCalculPenalitaticalculat in VFP din vederilevanzari/ireg_parteneri/penalitati.
Dupa confirmarea dialogului (validat prin variabila globala gnButon = 1, standard framework
pentru formulare modale), se apeleaza make_factura_tranzit / make_factura_cheiaj /
make_factura_contracte / make_factura_penalitati, care insereaza direct in crsFactura.
Important: nicio procedura Oracle stocata (pack_*) nu e apelata in etapa de import — acestea
(pack_facturare.*, pack_acn.salveaza_regdoc, pack_contafin.*) sunt apelate abia la
salvarea finala a facturii (factura_salvare_db, Programe\proceduri_acnpro.prg:3290+), nu
la import.
Dovezi:
Programe\proceduri_acnpro.prg:3151-3212(Procedure factura_import),740-771(calcul_tranzit, sursaips_vvoyage_members_calcul),1127-1161(calcul_contract, sursavctr_articole2).Programe\proceduri_acnpro.prg:939-943:loFrmTranzit = Crea("frm_calcul_tranzit", ...); loFrmTranzit.Show(1); llSucces = (m.gnButon = 1).Programe\proceduri_acnpro.prg:3331-3467— apelurilepack_facturare.*/pack_acn.salveaza_regdocsunt infactura_salvare_db, nu infactura_import.
4. Cum populeaza factura
Concluzie: Scrie direct in cursorul de articole al facturii, crsFactura, prin
INSERT INTO crsFactura(...) in fiecare make_factura_* — nu trece prin vreo metoda generica
"adauga articol" a formularului (exista o metoda separata do_adauga_articol pentru adaugare
manuala de linie, dar importul n-o foloseste). Liniile se adauga peste cele existente (nu
sterge/inlocuieste crsFactura inainte). Protectia la dublu-import e partiala:
- dupa un import reusit,
This.cmdImport.Enabled = .F.dezactiveaza butonul (nu se mai poate importa a doua oara in aceeasi sesiune de editare a facturii); - pentru TRANZIT/CHEIAJ exista un avertisment (nu blocaj) daca pe convoaiele alese exista deja
facturi (
ips_vvoyages_vanzari.numar_act IS NOT NULL) — utilizatorul poate continua oricum.
Dovezi:
Clase\oacnpro.vc2:7827-7834:llSucces = factura_import(m.tlImportCalculat) IF m.llSucces This.cmdImport.Enabled = .F. && nu mai import altceva This.chkIntern.Enabled = .F. This.ActiveazaSalvare() ...Programe\proceduri_acnpro.prg:3601(TRANZIT) /3677-3678(CHEIAJ) /3764-3765(CHIRII/APA):Insert Into crsFactura(nrcrt, id_articol, denumire, ...).Clase\oacnpro.vc2:14915-14930— avertisment dublu-import infrm_tranzit.do_executa:(mesaj informativ, apoi continua oricum cuSELECT numar_act, data_act, client FROM ips_vvoyages_vanzari WHERE vye_id in (...) AND numar_act is NOT null ... IF RECCOUNT('cFacturiTranzitTemp') > 0 lcMesaj = 'Atentie! Exista facturi pe tranzitele alese!' + CHR(13)+CHR(10) + ... AMESSAGEBOX(m.lcMesaj,0+48,_screen.Caption) ENDIFcalcul_tranzit/calcul_cheiaj).
5. Feedback catre utilizator
Concluzie: Mesaje punctuale prin AMESSAGEBOX, nu un sistem unitar de raportare:
- Client lipsa:
'Alegeti clientul!'(oacnpro.vc2:7821). - Convoi/liniile de import lipsa dupa dialog:
'Alegeti un convoi!'inmake_factura_tranzitdacapoDate.uuid(id-urile alese) e gol (proceduri_acnpro.prg:3530); analog pentru CHIRII/APA prinfactura_salvare('Alegeti convoiul'/'Adaugati prestatii',proceduri_acnpro.prg:3221, dar aceasta e verificare la salvare, nu la import). - Facturi deja existente pe convoaiele alese: avertisment neblocant (vezi punctul 4).
- Zero rezultate in dialogul de selectie (
frm_tranzit/frm_calcul_contract): niciun mesaj explicit gasit — grila ramane goala, iar laCalculare/Terminatfara nimic bifatlcVyeIdsramane vid siIF !EMPTY(m.lcVyeIds)(oacnpro.vc2:14912) sare peste tot calculul, fara mesaj catre utilizator (comportament implicit: butonul pare sa nu faca nimic). - Eroare Oracle: nu exista tratare
TRY/CATCHexplicita infactura_import/calcul_tranzit/make_factura_*; erorile SQL se propaga prin returul.F.al luigoExecutor.oExecuta/oSelecteaza2Value, iar afisarea erorii tine de comportamentul standard algoExecutor(framework comun, neexaminat in detaliu aici).
Dovezi: citatele de mai sus; pentru "zero rezultate fara mesaj" — Clase\oacnpro.vc2:14898-14943.
6. Selectivitate
Concluzie: Da, exista dialoage intermediare cu selectie, diferite pe tip:
- TRANZIT/CHEIAJ:
frm_tranzit(oacnpro.vc2:14492-15003) — gridgrdTranzitcu coloaneDeclaratia,Data decl.,Convoi,Origin,Destinatiesi o coloana checkboxcAles(ControlSource='crsConvoaie.ales'), plus criterii de cautare (Cb_tx_cautare1,But_start_criterii1/But_reset_criterii1) si butoncmdCalculeaza("Calculare Tarife"). Utilizatorul bifeaza unul sau mai multe convoaie; daca nu bifeaza niciunul, se ia randul curent (lcVyeIddincrsConvoaiela pozitia curenta). DupaCalculare Tarife, se deschide al doilea nivel —frm_calcul_tranzit/frm_calcul_cheiaj— pentru editarea/confirmarea tarifelor calculate, inainte de a reveni in factura. - CHIRII/APA:
calcul_contract()deschidefrm_calcul_contractcu cursorulcrsArticoleContract(articol, perioada, um, pret, cantitate, valoare, valuta, locatie) din vedereavctr_articole2filtrata peid_ctr— practic toate articolele contractului curent, editabile in acel dialog. - PENALITATI:
frm_penalitaticu gridgrdPenalitati(crsCalculPenalitati), coloane vizibile precumcNrDoc,cSuma("Sold restant" in modul evaluare),cDataDoc.
Deci nu e un "importa tot" fara interventie — e mereu mediat de un dialog de vizualizare/calcul/
confirmare (gnButon = 1 = utilizatorul a confirmat).
Dovezi: Clase\oacnpro.vc2:14500-14515 (obiecte grid + cAles), 14801
(ControlSource='crsConvoaie.ales'), 14594-14601 (cmdCalculeaza);
Programe\proceduri_acnpro.prg:1137-1153 (crsArticoleContract din vctr_articole2);
Programe\proceduri_acnpro.prg:545-555 (frm_penalitati, grdPenalitati.cSuma, .cNrDoc,
.cDataDoc).
7. Butoanele vecine
Concluzie: Pe frm_factura, cmdImport e plasat in zona antetului facturii
(Left=597, Top=65), langa cboTip (Left=507, Top=67 — combo cu tipul facturii) si
chkIntern (Left=412, Top=70) — nu langa bara principala de butoane. Bara principala de sus
(Top=0) contine, in ordinea Left: but_factura_noua ("Nou", Left=688), But_salveaza1
("Salveaza", Left=719), But_renunt1 ("Renunta", Left=749). Separat, langa grila
grdFactura, exista butoane de linie (Top=120): But_nou1 ("Adauga linie", Left=707) si
But_sterge1 ("Sterge linie", Left=737). Mai sunt but_cautare_client/but_cautare_beneficiar
(lupa cautare partener, langa campurile de client/beneficiar).
Dovezi: Clase\oacnpro.vc2:6779-6818 (definitiile but_factura_noua, But_nou1,
But_renunt1, But_salveaza1, But_sterge1 cu Left/Top), 6836-6851 (cboTip),
6853-6863 (chkIntern), 6894-6905 (cmdImport).
Ce e transferabil in ROAFACTURARE
Tiparul general merita copiat ca model de arhitectura pentru un buton generic "importa articole din sursa":
- Buton activ conditionat de (a) factura editabila (nesalvata) si (b) tip de document care are o
sursa de import — exact ca
llFacturaEditabila and llRorisSauContracte. - O metoda de intrare unica (
do_executa/factura_import) care ramifica dupa tipul documentului catre functii specializate de "vizualizare/selectie" — fiecare deschide un dialog modal de selectie (grid cu coloana checkboxales, criterii de cautare), returneaza succes/esec prin variabila globala tipgnButon = 1. - Populare prin
INSERT INTO <cursor_articole>direct, aditiv (nu sterge liniile existente), cu dezactivarea butonului dupa import reusit ca protectie minimala la dublu-import — plus (optional) un avertisment neblocant daca sursa a mai fost deja folosita in alta factura. - Separarea neta intre etapa de calcul/import (SELECT-uri simple pe vederi Oracle, fara proceduri stocate) si etapa de salvare (unde intra pachetele PL/SQL) — util ca principiu: importul nu trebuie sa scrie definitiv in baza, doar sa populeze cursorul local.
Ce e strict specific ACN/RORIS si nu se transfera: sursele de date (ips_vvoyages,
ips_voyage_members_vanzari, ips_vberthing_details_vanzari, vctr_articole2), logica de calcul
tarife/ecluzari/porturi, formularele frm_tranzit/frm_calcul_tranzit/frm_calcul_contract/
frm_penalitati ca atare, si valorile poDate.cTip (TRANZIT/CHEIAJ/CHIRII/APA/PENALITATI).
Necunoscute ramase
- Comportamentul exact al
goExecutor.oExecuta/oSelecteaza2Valuela eroare Oracle (mesaj afisat, retry, log) — n-a fost verificat in profunzime (functie framework comun). - Continutul complet al dialogului
frm_calcul_tranzit/frm_calcul_cheiaj(al doilea nivel, editare tarife) — am confirmat doar ca exista si cagnButon=1marcheaza confirmarea, dar nu am detaliat coloanele/campurile lui. - Detaliile
frm_calcul_contract(butoane, posibilitate de deselectare articole individuale) nu au fost citite integral — doar sursa cursorului. - Nu am verificat daca exista vreo validare suplimentara de "acelasi convoi importat de doua ori in aceeasi factura" dincolo de avertismentul cross-factura mentionat la punctul 4.