# 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 = 169
  ```
- `COMUN\clase\cmd_butoane.vc2:474` — `caction = do_executa` (mostenit de `cmd_executa`).
- `COMUN\clase\_cmd_base.vc2:120-159` — `PROCEDURE Click` a clasei de baza: construieste
  `lcCommand = [this.Parent.] + lcAction + ...` si il executa cu macro (`&lcCommand`).
- `Clase\oacnpro.vc2:7814-7836` — `PROCEDURE do_executa` a lui `frm_factura` (clasa incepe la
  `oacnpro.vc2:6398 DEFINE CLASS frm_factura`, se termina la `8383`).

## 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.llRorisSauContracte
  ```
- `Clase\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 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 <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.
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.
