Lucrarea 11

Implementarea structurilor ierarhice

1. Reprezentarea structurilor ierarhice

2. Exemplu de implementare

   

Exemplu:
    Se va scrie un program care sa permita adaugarea si stergerea de produse pentru o comanda, respectiv listarea tuturor produselor de pe o comanda. Tabelele sunt cele prezentate anterior. Tabela Furnizor va fi indexata dupa codF în iFCodF.ndx, tabela CatP va fi indexata dupa codP în iCPcodP.ndx, iar tabela Comenzi dupa nrC în iCnrC.
    Pentru aceasta se vor proiecta patru formulare, dintre care unul principal si trei pentru implementarea operatiilor. Formularul principal va avea un meniul orizontal care va permite apelarea celor trei formulare pentru operatii si, în plus va permite închiderea aplicatiei. Toate formularele vor fi de tip modal.
    Deoarece crearea formularului principal se încadreaza în subiectele tratate în capitolele anterioare se vor prezenta în continuare doar formularele pentru operatii.
    Formularul pentru adaugarea unui produs pe o comanda va apela o fereastra de citire din exemplul CitVal.PRG pentru citi codul comenzii la care se adauga produsul. El va permite introducerea si verificarea valorilor pentru cod produs, cantitate, data livrarii si pret si va completa automat câmpurile de legatura PRIM si URM. Adaugarea se va face la începutul listei.


*** Fisierul AddProd.WFM **************
*************************************

CLASS adprodFORM OF FORM
this.OnOpen = CLASS::FORM_ONOPEN

this.OnClose = CLASS::FORM_ONCLOSE
this.Text = "Adaugare produs pe comanda"

DEFINE TEXT TEXT1 OF THIS;
PROPERTY;
Text "Nr. comada",;

DEFINE TEXT TXNRC OF THIS;
PROPERTY;
Text "",;

DEFINE TEXT TEXT3 OF THIS;
PROPERTY;
Text "Cod produs",;

DEFINE TEXT TEXT4 OF THIS;
PROPERTY;
Text "Cantitate",;

DEFINE ENTRYFIELD EFCODP OF THIS;
PROPERTY;
Valid CLASS::EFCODP_VALID,;
Value "",;
ValidErrorMsg "Produsul nu exista in catalog!",;
MaxLength 3,;

DEFINE ENTRYFIELD EFCANTITATE OF THIS;
PROPERTY;
Value "",;
MaxLength 8,;
Picture "99999.99",;

DEFINE TEXT TEXT2 OF THIS;
PROPERTY;
Text "Data livrarii",;

DEFINE ENTRYFIELD EFDATA OF THIS;
PROPERTY;
Value "01.01.00",;
MaxLength 8,;
Function "E",;

DEFINE TEXT TEXT5 OF THIS;
PROPERTY;
Text "Pret unitar",;

DEFINE ENTRYFIELD EFPRET OF THIS;
PROPERTY;
Value "",;
MaxLength 12,;
Picture "999999999.99",;

DEFINE PUSHBUTTON BUADAUGA OF THIS;
PROPERTY;
Group .T.,;
Text "&Adauga",;
OnClick CLASS::BUADAUGA_ONCLICK,;

DEFINE PUSHBUTTON BURENUNT OF THIS;
PROPERTY;
Group .T.,;
Text "&Renunta",;
OnClick CLASS::BURENUNT_ONCLICK,;

Procedure Form_OnOpen
SET EXACT ON
USE comenzi IN 1 ALIAS com INDEX iCnrC
USE prodC IN 2 ALIAS prod
USE furnizor IN 3 ALIAS furni INDEX iFcodF
USE catP IN 4 ALIAS cat INDEX iCPcodP
* stabilirea relatiei intre comenzi si furnizori
SELECT com
SET RELATION TO codF INTO furni
* stabilirea relatiei intre produse si catalog
SELECT prod
SET RELATION TO codP INTO cat
*citirea si verificarea comenzii
SET PROCEDURE TO CitVal ADDITIVE
SELECT com
DO
sNrC = cittext("Introduceti numarul comenzii", "Numar Comanda", "0", 3)
IF sNrC = ""
* s-a apasat butonul Renunt
form.Close()
RETURN
ENDIF
SEEK TRIM(sNrC)
IF .NOT. FOUND()
MsgBox("Comanda "+sNrC+"Nu exista !")
ENDIF
UNTIL FOUND()
form.txNrC.text = sNrC
form.efData.value = DATE()
RETURN
Procedure EFCODP_Valid
SELECT cat
SEEK form.efCodP.value
RETURN FOUND()
Procedure BURENUNT_OnClick
form.Close()
RETURN
Procedure BUADAUGA_OnClick
* verifica daca se poate folosi o inregistrare
* din lista de inregistrari sterse
SELECT prod
GO 1
IF URM <> -1
nRecNou = URM
GO nRecNou
* scoate inregistrarea din lista de sterse
nRecSters = URM
GO 1
REPLACE URM WITH nRecSters
GO nRecNou
ELSE
APPEND BLANK
ENDIF
* se va adauga in inregistrarea curenta
nRec = RECNO()
REPLACE codp WITH form.efCodP.value
REPLACE cantitate WITH val(form.efCantitate.value)
REPLACE dataL WITH form.efData.value
REPLACE pret WITH val(form.efPret.value)
* adauga inregistrarea pe comanda
SELECT com
SEEK form.txNrC.text
nOld = prim
REPLACE prim WITH nRec
SELECT prod
REPLACE urm WITH nOld
form.Close()
RETURN
Procedure Form_OnClose
CLOSE DATABASE
RETURN
ENDCLASS
************************************************

    Formularul de stergere produse de pe o comanda va folosi algoritmul de stergere prin mutarea înregistrarii într-o lista de înregistrari sterse.

*** Fisierul StProd.WFM ******************
***************************************

CLASS stprodFORM OF FORM
this.OnOpen = CLASS::FORM_ONOPEN
this.OnClose = CLASS::FORM_ONCLOSE
this.Text = "Stergere produs de pe comanda"

DEFINE TEXT TEXT1 OF THIS;
PROPERTY;
Text "Nr Comanda",;

DEFINE TEXT TEXT2 OF THIS;
PROPERTY;
Text "Data",;

DEFINE TEXT TXDATA OF THIS;
PROPERTY;
Text "",;
Picture "99.99.9999",;
Function "D",;

DEFINE TEXT TEXT3 OF THIS;
PROPERTY;
Text "Furnizor",;

DEFINE TEXT TXFURNIZOR OF THIS;
PROPERTY;
Text "",;

DEFINE PUSHBUTTON BUSTERGE OF THIS;
PROPERTY;
Group .T.,;
Text "&Sterge",;
OnClick CLASS::BUSTERGE_ONCLICK,;

DEFINE TEXT TXNRC OF THIS;
PROPERTY;
Text "0",;

DEFINE TEXT TEXT4 OF THIS;
PROPERTY;
Text "Produs",;

DEFINE COMBOBOX CBPRODUSE OF THIS;
PROPERTY;
Style 1,;

DEFINE PUSHBUTTON PUSHBUTTON1 OF THIS;
PROPERTY;
Group .T.,;
Text "&Renunt",;
OnClick CLASS::PUSHBUTTON1_ONCLICK,;

Procedure PUSHBUTTON1_OnClick
form.Close()
RETURN
Procedure Form_OnOpen
PUBLIC aProd && tablou de produse
SET EXACT ON
USE comenzi IN 1 ALIAS com INDEX iCnrC
USE prodC IN 2 ALIAS prod
USE furnizor IN 3 ALIAS furni INDEX iFcodF
USE catP IN 4 ALIAS cat INDEX iCPcodP
* stabilirea relatiei intre comenzi si furnizori
SELECT com
SET RELATION TO codF INTO furni
* stabilirea relatiei intre produse si catalog
SELECT prod
SET RELATION TO codP INTO cat
*citirea si verificarea comenzii
SET PROCEDURE TO CitVal ADDITIVE
SELECT com
DO
sNrC = cittext("Introduceti numarul comenzii", "Numar Comanda", "0", 3)
IF sNrC = ""
* s-a apasat butonul Renunt
form.Close()
RETURN
ENDIF
SEEK sNrC
IF .NOT. FOUND()
MsgBox("Comanda "+sNrC+"Nu exista !")
ENDIF
UNTIL FOUND()
IF prim = -1
MsgBox ("Nu exista produse pe comanda!")
form.Close()
RETURN
ENDIF
form.txNrC.text = sNrC
form.txData.text = com->data
form.txFurnizor.text = furni->numeF
aProd = new ARRAY(0)
SELECT prod
GO com->prim
bEnd = .F.
DO
aProd.Add(1)
aProd[aProd.size] = cat->denumire
IF urm<>-1
GO urm
ELSE
bEnd=.T.
ENDIF
UNTIL bEnd
form.cbProduse.dataSource = "Array aProd"
form.cbProduse.value = aProd[1]
RETURN
Procedure Form_OnClose
CLOSE DATABASE
RELEASE aProd, aProdC
RETURN
Procedure BUSTERGE_OnClick
* Cauta locul produsului
SELECT com
SEEK form.txNrc.text
SELECT prod
GO com->prim
nAnt = com->prim
DO WHILE .T.
IF cat->denumire=form.cbProduse.value
EXIT
ELSE
IF urm=-1
MsgBox("Lista de produse este corupta!")
form.Close()
ELSE
nAnt=RECNO()
GO urm
ENDIF
ENDIF
ENDDO
nSters=RECNO()
IF nSters = com->prim
*stergere primul element din lista
SELECT com
REPLACE prim WITH prod->urm
ELSE
* sterge un element din interioarul listei
nUrm = urm
GO nAnt
REPLACE urm WITH nUrm
ENDIF
* trece produsul sters in lista de inreg. sterse
SELECT prod
GO 1
nPrecSters = urm
REPLACE urm WITH nSters
GO nSters
REPLACE urm WITH nPrecSters
form.Close()
RETURN
ENDCLASS
************************************

    Formularul de vizualizare produse de pe o comanda va afisa lista într-un control de tip LISTBOX. Pentru alinierea coloanelor s-a folosit fontul TERMINAL pentru lista.


*** Fisierul ListProd.WFM ****************
***************************************
CLASS listprodFORM OF FORM
this.OnOpen = CLASS::FORM_ONOPEN
this.OnClose = CLASS::FORM_ONCLOSE
this.Text = "Lista de produse de pe o comanda"

DEFINE TEXT TEXT1 OF THIS;
PROPERTY;
Text "Nr. comanda",;

DEFINE TEXT TXNRC OF THIS;
PROPERTY;
Text "",;

DEFINE TEXT TEXT2 OF THIS;
PROPERTY;
Text "Data",;

DEFINE TEXT TXDATA OF THIS;
PROPERTY;
Text "",;
Picture "99.99.9999",;
Function "D",;

DEFINE TEXT TEXT4 OF THIS;
PROPERTY;
Text "Furnizor",;

DEFINE TEXT TXFURNIZOR OF THIS;
PROPERTY;
Text "",;

DEFINE TEXT TEXT3 OF THIS;
PROPERTY;
Text "Produse",;

DEFINE LISTBOX LBPRODUSE OF THIS;
PROPERTY;
FontName "Terminal",;

DEFINE PUSHBUTTON BUOK OF THIS;
PROPERTY;
Group .T.,;
Text "&OK",;
OnClick CLASS::BUOK_ONCLICK,;

Procedure Form_OnOpen
PUBLIC aProd && tablou de produse
SET EXACT ON
USE comenzi IN 1 ALIAS com INDEX iCnrC
USE prodC IN 2 ALIAS prod
USE furnizor IN 3 ALIAS furni INDEX iFcodF
USE catP IN 4 ALIAS cat INDEX iCPcodP
* stabilirea relatiei intre comenzi si furnizori
SELECT com
SET RELATION TO codF INTO furni
* stabilirea relatiei intre produse si catalog
SELECT prod
SET RELATION TO codP INTO cat
*citirea si verificarea comenzii
SET PROCEDURE TO CitVal ADDITIVE
SELECT com
DO
sNrC = cittext("Introduceti numarul comenzii", "Numar Comanda", "0", 3)
IF sNrC = ""
* s-a apasat butonul Renunt
form.Close()
RETURN
ENDIF
SEEK sNrC
IF .NOT. FOUND()
MsgBox("Comanda "+sNrC+"Nu exista !")
ENDIF
UNTIL FOUND()
IF prim = -1
MsgBox ("Nu exista produse pe comanda!")
form.Close()
RETURN
ENDIF
form.txNrC.text = sNrC
form.txData.text = com->data
form.txFurnizor.text = furni->numeF
aProd = new ARRAY(1)
* capul de tabel
aProd[aProd.size] = LEFT("CodP"+REPL(" ",5),5) + ;
LEFT("Denumire"+REPL(" ",16),16) + ;
RIGHT(REPL(" ",12)+"Cantitate",12) + ;
RIGHT(REPL(" ",12)+"Pret",12)
SELECT prod
GO com->prim
bEnd = .F.
DO
aProd.Add(1)
aProd[aProd.size] = LEFT(LTRIM(codp)+REPL(" ",5),5) + ;
LEFT(LTRIM(cat->denumire)+REPL(" ",16),16) + ;
STR(cantitate,12,2) + ;
STR(pret,12,2)
IF urm<>-1
GO urm
ELSE
bEnd=.T.
ENDIF
UNTIL bEnd
form.lbProduse.dataSource = "Array aProd"
form.lbProduse.value = aProd[1]
RETURN
Procedure BUOK_OnClick
form.Close()
RETURN
Procedure Form_OnClose
CLOSE DATABASE
RELEASE aProd
RETURN
ENDCLASS
*************************************

3. Probleme propuse

P1. Rulati exemplele prezentate în acest capitol.

P2. Adaugati formulare pentru adaugarea, stergerea si vizualizarea de produse din catalogul de produse, de furnizori în tabela de furnizori si de comenzi din fisierul de comenzi.

P3. Modificati algoritmul de stergere produse de pe o comanda astfel încât sa se realizeze stergerea fizica si refacerea listei.

P4. Implementati o baza de date pentru gestionarea pasagerilor unui aeroport. Informatiile despre pasageri sunt pastrate intr-o lista simplu inlantuita in tabela Pasageri, pe relatia UrmP (referinta la urmatorul pasager inscris la aceiasi cursa). Sa se implementeze operatiile:

a)  Adaugare si vizualizare pasageri pentru o cursa data prin CodC;
b)  Adaugare si vizualizare curse (inclusiv nr. locuri disponibile / nr. locuri ocupate);
c)  Adaugare si vizualizare avioane (inclusiv nr. de avioane din fiecare tip folosite pe acel aeroport, considerand ca fiecare cursa are un avion distinct).
d)  Cautare curse dupa destinatie sau interval de plecare, cu listarea tuturor pasagerilor inscrisi la respectivele curse, in genul:
   Cursa I307 spre Roma plecare la 8.30
   -----------------------------------------------
      Loc 12: Pop Vasile
      Loc 3: Ionescu Emilia
      Loc 7: Rus Dumitru

   Cursa I415 spre Roma plecare 12.45
   ----------------------------------------------
      Loc 4: Vasilescu Mircea
      Loc 11: Roiescu Georgeta

      ...

      


 

© s.l. dr. ing. Dan Pescaru '2004