# 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 = "\ `factura_import()` (`Programe\proceduri_acnpro.prg:3151`) ramifica dupa `poDate.cTip`: - TRANZIT/CHEIAJ: `vizualizare_tranzit()` -> deschide dialogul `frm_tranzit` (selectie convoaie din vederea Oracle `ips_vvoyages`) -> la confirmare, `calcul_tranzit()`/`calcul_cheiaj()` interogheaza direct (SELECT-uri simple, nu pachete PL/SQL) tabelele/vederile `ips_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 vederea `vctr_articole2` (articole de contract) -> dialog `frm_calcul_contract`. - PENALITATI: `vizualizare_penalitati()` -> `frm_penalitati` cu cursorul `crsCalculPenalitati` calculat in VFP din vederile `vanzari`/`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`, sursa `ips_vvoyage_members_calcul`), `1127-1161` (`calcul_contract`, sursa `vctr_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` — apelurile `pack_facturare.*`/`pack_acn.salveaza_regdoc` sunt in `factura_salvare_db`, nu in `factura_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 in `frm_tranzit.do_executa`: ``` SELECT 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) ENDIF ``` (mesaj informativ, apoi continua oricum cu `calcul_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!'` in `make_factura_tranzit` daca `poDate.uuid` (id-urile alese) e gol (`proceduri_acnpro.prg:3530`); analog pentru CHIRII/APA prin `factura_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 la `Calculare`/`Terminat` fara nimic bifat `lcVyeIds` ramane vid si `IF !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/CATCH` explicita in `factura_import`/`calcul_tranzit`/ `make_factura_*`; erorile SQL se propaga prin returul `.F.` al lui `goExecutor.oExecuta`/`oSelecteaza2Value`, iar afisarea erorii tine de comportamentul standard al `goExecutor` (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`) — grid `grdTranzit` cu coloane `Declaratia`, `Data decl.`, `Convoi`, `Origin`, `Destinatie` si o coloana checkbox `cAles` (`ControlSource='crsConvoaie.ales'`), plus criterii de cautare (`Cb_tx_cautare1`, `But_start_criterii1`/`But_reset_criterii1`) si buton `cmdCalculeaza` ("Calculare Tarife"). Utilizatorul bifeaza unul sau mai multe convoaie; daca nu bifeaza niciunul, se ia randul curent (`lcVyeId` din `crsConvoaie` la pozitia curenta). Dupa `Calculare 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()` deschide `frm_calcul_contract` cu cursorul `crsArticoleContract` (articol, perioada, um, pret, cantitate, valoare, valuta, locatie) din vederea `vctr_articole2` filtrata pe `id_ctr` — practic toate articolele contractului curent, editabile in acel dialog. - **PENALITATI**: `frm_penalitati` cu grid `grdPenalitati` (`crsCalculPenalitati`), coloane vizibile precum `cNrDoc`, `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"**: 1. Buton activ conditionat de (a) factura editabila (nesalvata) si (b) tip de document care are o sursa de import — exact ca `llFacturaEditabila and llRorisSauContracte`. 2. 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 checkbox `ales`, criterii de cautare), returneaza succes/esec prin variabila globala tip `gnButon = 1`. 3. Populare prin `INSERT INTO ` 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. 4. 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`/`oSelecteaza2Value` la 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 ca `gnButon=1` marcheaza 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.