11 KiB
Harta cod: adaugare/editare FACTURA si AVIZ (read-only)
Sursa: text FoxBin2Prg deja in-tree (.vc2/.prg), citit cu Grep/Read si indexat cu
vfp_symbols.ps1 (-CacheRoot/-ProjectRoot D:\ROA\ROAFACTURARE,
-IndexFile D:\ROA\_vfp_textcache\roafacturare\_symbols.tsv). Nicio modificare de fisier.
1. Formulare si clase implicate
Nu exista formular .scx pentru factura/aviz in acest proiect (.scx-urile din arbore sunt
doar utilitare: frm_borderou_facturi.scx, frm_import_efactura.scx etc.). Ecranul de
adaugare/editare e o clasa .vcx instantiata prin Createobject(), nu un DO FORM:
frm_facturare_articole2—COMUN\clase\ofacturare.vcx(textCOMUN\clase\ofacturare.vc2:15936-22614). Formularul unificat, curent, folosit in productie pentru factura SI aviz. Instantiat inCOMUN\programe\ofacturare.prg:248(ofrmdetaliifactura = Createobject('frm_facturare_articole2')) si inCOMUN\clase\ofacturare_comun.vc2:4028, doar candllFacturareNouae adevarat (COMUN\programe\ofacturare.prg:246-248).frm_facturare_articole— acelasi fisier,ofacturare.vc2:11123-15936. Varianta mai veche; in cod de productie nu mai e instantiata (doar in probele dinCOMUN\utile\Teste\facturare_unificat\*.prgsiCOMUN\utile\Teste\editare_factura\creeaza_documente_s8.prg:571,emite_document_stoc_s93.prg:264) — ramane in clasa dar calea curenta efrm_facturare_articole2.- Flux vechi, ne-unificat (
llFacturareNoua = .F.,ofacturare.prg:255-266) — alege un formular de antet separat pe tip de document, fara grila unificata de articole:frm_date_aviz_lucrare—ofacturare.vc2:7775— pentrutnTip27 sau 30.frm_date_factura—ofacturare.vc2:8637— pentrutnTip < 21sau in(45,48,49,51,52).frm_date_aviz—ofacturare.vc2:6721— altfel (aviz).
oAntetFacturare(Define Class ... As Custom) —COMUN\programe\ofacturare_antet.prg:14. Logica de antet a luifrm_facturare_articole2: cautari (do_cauta_*), validare (valideaza_antet), schimbarea tipului de document (alege_tipdoc,schimba_tipdoc). Header-ul fisierului (ofacturare_antet.prg:1-7) spune explicit ca a fost portata dinfrm_date_factura/frm_date_avizcand s-a facut unificarea. Instantiata infrm_facturare_articole2.Init:This.oAntet = Createobject('oAntetFacturare')(ofacturare.vc2:21365).oDateFactura(poDate) —COMUN\programe\ofacturare_comun.prg:131. Obiectul de stare al documentului curent (creat inofacturare.prg:196); tinenIdTipDoc,nIdTipDocFactura(=5),nIdTipDocAvizExpeditie(=6),id_gestiune_init,listaid,id_pol,zi_cursetc.ofacturare_editare.prg(COMUN\programe\ofacturare_editare.prg, 1444 linii) — flux separat, pentru editarea liniilor unei facturi/aviz deja emise (nu formularul de creare):IncarcaAntetFacturaEditare(63),IncarcaLiniiFacturaEditare(209),PregatesteArticoleFacturaEditare(605),ScrieArticoleFacturaEditate(741), clasaArticoleNotaEditor As Custom(1226). Inregistrat viaSet Procedure To ofacturare_editare.prg Additive(Programe\roafacturare.prg:219).combosql_cautare— clasa de baza pentru comboboxurile de cautare din grid (vezi pct. 2),ofacturare.vc2:407-531, mostenindcombosql As comboboxdinCOMUN\clase\_cb_base.vc2:519.
2. Zona de introducere articole (cautare cod material / denumire)
In grila grd_factura a lui frm_facturare_articole2, coloanele au cate un combobox de tip
combosql_cautare:
grd_factura.cCodMat.cboCodmat—ADD OBJECTlaofacturare.vc2:17524-17537,ncharcountbegin = 2,pcursorname = crsCodmat,pfieldactiv = codmat.grd_factura.cDenumire.cCboDenumire—ADD OBJECTlaofacturare.vc2:17560-17574,ncharcountbegin = 2,pcursorname = crsDenumire,pfieldactiv = denumire.
Pragul de caractere: logica e in combosql_cautare.refreshdata (ofacturare.vc2:463-496):
lnTip = Iif(Type('tnTip') = 'N', m.tnTip, 0)
If m.lnTip <> 0 And Len(Alltrim(This.cSearchString)) <= This.nCharCountBegin
Return .T. && nu cauta, iese
Endif
Cu ncharcountbegin = 2 pe ambele combo-uri, filtrarea porneste abia cand
Len(cSearchString) > 2, adica de la al treilea caracter tastat.
Interactivechange/Keypress: nu sunt suprascrise in combosql_cautare — vin din parintele
combosql (COMUN\clase\_cb_base.vc2:519):
InteractiveChange(linia 606-608): doar reseteazacSearchString.KeyPress(linia 610-776): construiestecsearchstringcaracter cu caracter (sageti, Del/Backspace tratate separat), apoi cheamaThis.RefreshData(1)= cautare "incepe cu" (linia 720) sau, la Ctrl+Enter,RefreshData(2)= cautare "contine" (liniile 636-649).
Filtrul/SQL aplicat: refreshdata seteaza cfiltrucod/cfiltruden in functie de tip
(ofacturare.vc2:476-489):
Case lnTip = 1 (incepe cu): cfiltrucod/cfiltruden = cSearchString + '%'
Case lnTip = 2 (contine): cfiltrucod/cfiltruden = '%' + cSearchString + '%'
apoi cursor_preturi_call() (ofacturare.vc2:446-461) construieste apelul catre pachetul
Oracle pack_facturare.cursor_preturi(?poDate.zi_curs,?poDate.tip,?poDate.id_valuta, ?poDate.id_gestiune_init sau ?poDate.listaid,?gnLuna,?gnAn,?gnIdUtil,?gnIdSucursala, ?pcFiltruCod,?pcFiltruDen) (sau pack_facturare.cursor_gestiune(...) cand poDate.tip = 41),
executat prin goExecutor.oExecuta in selectdata (linia 514-529). Corpul PL/SQL al
pachetului nu e in acest repo VFP (schema Oracle) — nu l-am putut citi read-only de aici.
Proprietatile csourcesql/csourcewhere de pe ADD OBJECT (ex. select codmat, denumire, ... from vnom_articole ... where inactiv = 0) sunt doar sablonul design-time al cursorului gol
(creeaza_cursor_gol, linia 426), nu interogarea reala rulata la tastare.
Sincronizare cod<->denumire dupa alegere: grd_factura.cCodMat.cboCodmat.LostFocus
(ofacturare.vc2:22088-22109) si perechea ei cDenumire.cCboDenumire.LostFocus
(22115-22136) cheama thisform.do_adauga_articol_cautat(loArticol, loArticol.cantitate)
si fortez re-creerea cursorului celeilalte combo (seteaza cSearchString cu valoarea gasita
si reseteaza RowSource), ca sa afiseze articolul ales in ambele coloane.
3. Lista de preturi / politici de pret
poDate.id_gestiune_inite parametrul implicit trimis lapack_facturare.cursor_preturi; candpoDate.tip = 45se trimitepoDate.listaidin loc (ofacturare.vc2:453-457).- De ce poate aparea un articol de mai multe ori: interogarea serverului (Oracle,
pack_facturare.cursor_preturi) uneste nomenclatorul de articole cu politicile de pret — confirmarea client-side ca politicile sunt cheia vine dinmodifica_lista_preturi(ofacturare.vc2:21735-21837), care interogheaza direct tabelele de politici:Select id_pol_art, id_venchelt, proc_tvav from crm_politici_pret_art where id_pol = ... and id_articol = ...(linia 21755) si scrie prinpack_preturi.adauga_politica_pret_art/pack_preturi.modifica_pret_pol_pret_art(21779, 21792). Corpul exact al join-ului dincursor_preturie in PL/SQL, nevizibil din acest working copy VFP — afirmatia despre "un rand per politica aplicabila" e o inferenta din tabelele folosite, nu o citire directa a interogarii.
4. Zona de jos: controale de discount/totaluri
Toate sunt copii directe ale formularului frm_facturare_articole2 (fara container
intermediar), clasa _textbox din _baza.vcx, asezate sub grila (Top ~742-792):
| Obiect | Top | Left | Width | Anchor | Note |
|---|---|---|---|---|---|
tx_total_baza_nat (18123) |
745 | 17 | (implicit) | 4 | ReadOnly, ControlSource=thisform.nbazaron |
tx_total_baza_val (18137) |
789 | 17 | (implicit) | 4 | ReadOnly, thisform.nbazaval |
tx_disc_factura_nat (18082) |
745 | 351 | (implicit) | 4 | ReadOnly, thisform.ndiscfactron |
tx_disc_factura_procent (18096) |
767 | 542 | 54 | 4 | editabil, Value=0 |
tx_disc_factura_val (18109) |
789 | 351 | (implicit) | 4 | ReadOnly, thisform.ndiscfactval |
tx_total_tva_nat (18181) |
742 | 689 | (implicit) | 12 | ReadOnly, thisform.ntvaron |
tx_total_tva_val (18195) |
792 | 689 | (implicit) | 12 | ReadOnly, thisform.ntvaval |
tx_total_factura_nat (18151) |
742 | 833 | (implicit) | 12 | ReadOnly, FontBold, thisform.ntotalron |
tx_total_factura_val (18166) |
792 | 835 | (implicit) | 12 | ReadOnly, FontBold, thisform.ntotalval |
(linii = COMUN\clase\ofacturare.vc2). Anchor=4 = ancorat de Bottom (coboara odata cu
formularul); Anchor=12 (4+8) = Bottom+Right, pe coloana totalurilor din dreapta. Niciun
Height/Width explicit pe majoritatea — mostenesc default-ul clasei _textbox; doar
tx_disc_factura_procent are Width=54 explicit. Nu am gasit cod care repozitioneaza
aceste controale la runtime in frm_facturare_articole2 — pozitionarea e strict design-time
Anchor(fara logica deResize/Movepe ele;Resizeal formularului, linia 21847-21854, nu le atinge explicit).
5. Diferente factura vs aviz pe frm_facturare_articole2
- Discriminator unic:
poDate.nIdTipDoc, comparat cupoDate.nIdTipDocFactura(=5) /poDate.nIdTipDocAvizExpeditie(=6). Helper:oAntetFacturare.EsteAviz()(ofacturare_antet.prg:16-18):Return poDate.nIdTipDoc = poDate.nIdTipDocAvizExpeditie. - Setare initiala, dupa
tnTipprimit la deschidere (COMUN\programe\ofacturare.prg:196-206):Case tnTip = 27 or 30 -> nIdTipDoc = 6 (AVIZ) Case tnTip < 21 sau tnTip in (45,48,49,51,52) -> nIdTipDoc = 5 (FACTURA) Otherwise -> nIdTipDoc = 6 (AVIZ) - Schimbare interactiva: combo
clb_fdoc.cboFdoc->do_schimba_tipdoc(ofacturare.vc2:20046-20071) ->oAntet.alege_tipdoc(valoare_combo)mapeaza textul ("FACTURA"/"AVIZ"/"PROFORMA"/"BON FISCAL") pe id-ul de tip, apoioAntet.schimba_tipdoc(id)(ofacturare_antet.prg:889-923) actualizeazapoDate.nIdTipDocsi seriile. Exista o garda: daca documentul e proforma si au fost deja adaugate articole, schimbarea tipului e blocata cuamessagebox(ofacturare.vc2:20050-20055). - Ramuri
EsteAviz()inoAntetFacturare(aceleasi metode de cautare/validare servesc ambele tipuri, dar cu cai diferite):do_cauta_altele(20-45),do_cauta_client(97-100),do_cauta_comanda(240-243),do_cauta_contract(296-299),do_cauta_gestiune_init(518-521),do_cauta_lucrare(553-556),do_cauta_sectie(633-636),do_cauta_venchelt(708-711),valideaza_antet(762-766) — toate inCOMUN\programe\ofacturare_antet.prg. - Fluxul vechi (ne-unificat) folosea deja formulare separate per tip pentru antet
(
frm_date_factura/frm_date_aviz/frm_date_aviz_lucrare, vezi pct. 1) — unificarea descrisa in header-ulofacturare_antet.prga mutat logica lor comuna intr-o singura clasa, ramura aleasa la runtime pepoDate.nIdTipDoc.