Calculatoare si Tehnologia Informației [626987]

Universitatea “Politehnica” din Timișoara
Facultatea de Automatica si Calculatoare
Calculatoare si Tehnologia Informației

Fresh Market
Aplicatie Web pentru tranzacț ionarea
produselor agricole și de origine
animală

PROIECT DE DIPLOMĂ

Candidat: [anonimizat]:
Ș. L. dr. ing. Oana Iulia Casandra HOLOTESCU

Timișoara
2019

1
Cuprins

1. Introducere ………………………….. ………………………….. ………………………….. ………….. 5
1.1. Motivație ………………………….. ………………………….. ………………………….. …………….. 5
1.2. Contextul problemei ………………………….. ………………………….. …………………………. 5
1.3. Descrierea proiectului ………………………….. ………………………….. ………………………. 6
1.3.1 . Funcționalitățile c umpărător ului ………………………….. ………………………….. 7
1.3.2 . Funcționalitățile producătorului ………………………….. ………………………….. . 7
1.3.3 . Funcționalitățile administratorului ………………………….. ……………………….. 7
2. Tehnologii utilizate ………………………….. ………………………….. ……………………….. 9
2.1. Tehnologii utilizate pe partea de server ………………………….. ………………………….. .. 10
2.1.1 . Java ………………………….. ………………………….. ………………………….. ………… 10
2.1.2 . Spring ………………………….. ………………………….. ………………………….. ……… 10
2.1.3 . Spring Security ………………………….. ………………………….. …………………….. 15
2.1.3 . Spring Boot ………………………….. ………………………….. ………………………….. 17
2.2. Tehnologii utilizate pe partea de client ………………………….. ………………………….. .. 17
2.2.1 . Angular ………………………….. ………………………….. ………………………….. ……. 17
3. Specificațiile p roiect ului ………………………….. ………………………….. …………….. 19
3.1. Analiza și specificarea cerințelor ………………………….. ………………………….. ……… 19
3.2. Baza de date ………………………….. ………………………….. ………………………….. ……… 23
4. Implementare ………………………….. ………………………….. ………………………….. ……. 25
4.1. Arhitectura aplicației ………………………….. ………………………….. ………………………….. …25
4.2. Implementarea funcționalităților comune ………………………….. ………………………….. 27
4.2.1 . Autentificare utilizatorului ………………………….. ………………………….. …….. 27
4.2.2 . Înregistrarea utilizatorului ………………………….. ………………………….. …….. 28
4.2.3 . Opinia utilizatorului ………………………….. ………………………….. ……………… 29
4.2.4 . Mesajele utilizatorului ………………………….. ………………………….. …………… 30
4.2.5 . Profilul utilizatorului ………………………….. ………………………….. …………….. 33
4.3. Implementarea funcționalităților specifice producătorului ………………………….. ..35
4.3.1 . Adăugarea unei oferte noi ………………………….. ………………………….. ……… 35
4.3.2 . Editarea unei oferte ………………………….. ………………………….. ………………. 37
4.3.3 . Ștergerea unei oferte ………………………….. ………………………….. ……………… 37
4.4. Implementarea funcționalităților specifice cumpărătorului ………………………….. .37
4.4.1 . Lista de oferte și adăugarea în coșul de cumpărături ………………………… 37
4.4.2 . Coșul de cumpărături și trimiterea comenzilor ………………………….. ……… 38
4.4.3 . Adăugarea comentariilor și oferirea ratingului ………………………….. ……. 39
4.4.4 . Lista de favoriți ………………………….. ………………………….. …………………….. 40

2
5. Utilizarea aplicației ………………………….. ………………………….. ………………………. 41
6. Concluzii și viitoare îmbunătățiri ………………………….. …………………………. 45
6.1. Concluzii ………………………….. ………………………….. ………………………….. ……………… 45
6.2. Viitoare îmbunătățiri ………………………….. ………………………….. ………………………… 45
7. Referințe ………………………….. ………………………….. ………………………….. …………….. 47

3

Listă de figuri

2.1.1 Frameworkul Spring 11
2.1.2 Arhitectura JPA 13
2.1.3 Procesul JWTs 16
2.2.1 Modul NG 18
2.2.2 Serviciul de legare 19
2.2.3 Frameworkul Angular 20
3.1.1 Cazuri de utilizare producător 22
3.1.2 Cazuri de utilizare cumpărător 22
3.1.3 Cazuri de utilizare administrator 23
3.2.1 Diagrama bazei de date 23
4.1.1 Arhitectura client -server a aplicației 25
4.1.2 Comunicarea din cadrul aplicației 27
4.2.1 Generarea unui token 28
4.2.2 Validarea unui token 28
4.2.3 Organizarea datelor pentru cererea de înregistrare 29
4.2.4 Înregistrarea utilizatorului 29
4.2.5 Cererea de încărcare a mesajelor unui utilizator 30
4.2.6 Afișarea tuturor mesajelor unui utilizator 30
4.2.7 Cererea de încărcare a unei conversații 31
4.2.8 Cererea de ștergere a unui mesaj 31
4.2.9 Returnarea mesajelor unui utilizator 32
4.2.10 Extragerea mesajelor din baza de date 32
4.2.11 Returnar ea mesajelor unei conversații 32
4.2.12 Extragerea mesajelor unei conversații din baza de date 33
4.2.1 3 Ștergerea unui mesaj 33
4.2.14 Cererea de încărcare a datelor de profil 33
4.2.15 Cererea de editare a profilului 34
4.2.16 Returnarea info rmațiilor utilizatorului 34

4
4.2.17 Editarea utilizatorului 35
4.3.1 Organizarea datelor p entru crearea unei oferte 35
4.3.2 Inițierea cererii de creare a ofertei către aplicația server 36
4.3.3 Salvarea unei noi oferte 36
4.3.4 Rezolvarea cererii de editare a unei oferte 37
4.4.1 Afișarea ofertelor 38
4.4.2 Cererea de ad ăugare în coșul de cumpărături 38
4.4.3 Salvar ea comenzii unui produs 38
4.4.4 Cererea de ștergere a comenzii unui produs 39
4.4.5 Modifi carea stării comenzilor 39
4.4.6 Extragerea comen tariilor din baza de date 39
4.4.7 Structura sistemului de acordare a notei 39
4.4.8 Actualizarea sistemului de notare în baza de date 40
4.4.9 Salvarea unui producător ca favorit 40
5.1 Pagina de autentificare 41
5.2 Meniul p rincipal al aplicației 41
5.3 Pagina de oferte și adăugar e în coșul de cumpărături 42
5.4 Înregistrarea sa u retragerea une comenzi 42
5.5 Pagina de d etalii a unei oferte 43
5.6 Cititrea și trimiterea mesajelor 43
5.7 Adăugarea unei oferte 44
5.8 Oferirea unei opinii 44

Listă de tabele

2.1.1 Adnotări JPA 14

5
1. Introducere

1.1 Motivație
Fiecare persoană și-ar dori să acorde o atenție cât mai mare stilului ei de viață și să
adopte o nutriție cât mai echilibrată însă, cea mai mare problemă o reprezintă timpul, calitatea
produselor, dar și costul ridicat al produselor naturale aflate pe piață
Cel mai important factor in alcătuir ea unei alimentații corespunzătoare îl reprezintă
alimentele folosite in pregătirea preparatelor. În acest sens, este indicat să utilizăm produse
provenite din mediul rural , deoarece prezintă un grad mai mare de încredere în privința
nivelului scăzut de pe sticide folosit în cultivarea și tratarea fructelor și legumelor. De asemea,
un alt factor important îl reprezintă calitatea hranei animalelor care, influențează în mod
direct produsele de origine animală.
1.2 Contextul problemei
În viața de zi cu zi suntem acaparați de diferite activități care ne mențin ocupați și nu
ne permit să respectăm un program bine stabilit pentru a ne aproviziona cu produse care să ne
asigure necesarul de minerale și vitamine. La nivel național, consumul mediu anual de fructe
si legume pentru un locuitor este de aproximativ 70 – 80 de kg, în timp ce media europeană
este de 90 – 100 kg.
Agricultura și creșterea animalelor au constituit unele din cele mai importante surse
de venit, hrană si materii prime, pentru o persoană din m ediul rural și, în unele zone ,
principala activitate pentru asigura rea traiul ui și a dezvoltării populației.
Atât în creșterea animalelor, cât și în cultivarea produselor agricole, timpul și piața de
desfacere reprezintă două priorități de bază. În mare pa rte, produsele fiind perisabile, este
indicat ca acestea să fie livrate într -un timp cât mai scurt după recoltare. Același lucru se
aplică și pentru produsele animale care, păstrate într -un mediu nepotrivit sau pentru o
perioadă îndelungată de timp se pot altera.
În priv ința distribuirii produselor și a punerii lor pe piață există problema
intermediarilor și adaosului de preț adăugat de aceștia. Astfel, se poate ajunge la situația
dublării sau chiar triplării prețului inițial, stabilit de producător. Acest lucru nu este benefic
nici din perspectiva clientului, dar nici din cea a producătorului, ambii, având anumite
pierderi în urma acestor tranzacții intermediare.
Totodată, problem a prețului mărit poate apărea și datorită faptului că un producător
nu benefic iază de suficiente resurse și încredere acordată pentru a putea pătrunde pe piața
agricolă și a -și expune produsele publicului larg.

6
1.3 Descrierea proiectului
În acest context a fost dezvoltată o aplicație web destinată comerțului de produse
naturale, cu scopul de a ajuta atât producătorii, prin introducerea pe piață a produselor
acestora, cât cumpărători i, prin ușurarea procesului de achiziție a produselor naturale.
Această aplicație pune in contact ambele categorii de utilizatori, producătoii și
cumpă rătorii, favorizând crearea relației directe între aceștia si totodata eliminarea posibililor
intermediari care ar putea intervenii în procesul de comercializare al acestor produse.
Orice persoană care deține un calculator și are acces la internet va putea utiliza
aplicația, prin crearea simplă a unui cont și introducerea unor date personale de bază. Acestea
sunt necesare pentru a putea realiza profilul utilizatorului și a -i permite să beneficieze de
serviciile oferite de aplicație. Detaliile tehn ice se reg ăsesc în secțiunea 4.2.2 .
Pentru a descuraja si împiedica apariția intermediarilor, utilizatorul va fi nevoit să
aleagă în momentul creării contului tipul acestuia : produc ător sau cumpărator. În funcție de
această alegere, va avea posibilitatea să acceseze anumite funcționlități, specifice fiecărui tip
de cont în parte.
În prezent, majoritatea populației dorește să reducă timpul și efortul depus în
achiziționarea produselor alimentare. Pentru a atrage utilizatorii, este esențial ca navigarea si
găsirea inf ormației dorite în cadrul aplicației să fie cât mai rapidă . În acest sens, aplicația a
fost structurată pe diferite secțiuni comune ambelor tipuri de conturi : acas ă, contul
utilizatorului, mesaje, contact, despre. Fiecare dintre aceste secțiuni este prezen tă în bara de
navigare aflată in partea de sus a fiecărei pagini. Mai multe detalii despre acestea vor fi
prezentate în secțiunea 4 .
Secțiunile comune ale aplicației :
Secțiunea acasa oferă utilizatorului o prezentare scurtă a aplicației și îi oferă o primă
impresie asupra calității și siguranței oferite.
Secțiunea contul utilizatorului conține în primul rând informațiile de bază ale
acestuia, structurate sub forma unui profil, iar pe lângă acestea, în funcție de categoria
utilizatorului , alte funcționalități descrise în următoarele sub -capitolele.
Secțiunea mesaje permite utilizatorilor, de orice tip, să comunice în orice moment.
Acest lucru este esențial, de exemplu, în momentul în care un cumpărător dorește să
primească mai m ulte informații despre produsele unui producător sau cel din urmă să își
mențină cumpărătorii la curent cu noile sale produse.
Secțiunea contact încurajează utilizatorii să își exprime părerile, nemulțumirile și
ideile pentru îmbunătățirea aplicației.
Secțiunea despre oferă utilizatorilor un scurt ghid de folosire a aplicațtiei în privința
înscrierii, conectării sau modului de utilizare a funcționalităților prezente in cadrul aplicației.

7
1.3.1 Funcționalitățile cumpărătorului
Suplimentar față de servic iile de bază ale aplicației, cumpărătorii vor dispune de
secțiuni precum oferte, coșul meu, dar și de servicii ca listă de favoriți și posibilitatea
acordării unei note producătorilor pentru a arăta satisfacerea oferită de produse și
profesionalismul acest ora sau, din contră, lipsa de seriozitate a acestora, astfel atenționând
alți cumpărători.
Secțiunea oferte permite clientului să vizualizeze toate oferte disponibile postate de
producători, dar și adăugarea acestora direct de pe pagină în coșul de cumpăr ături, fără a mai
fi nevoie să acceseze pagina ofertei. Acest lucru este totuși posibil, în cazul în care clientul
dorește să afle mai multe informații despre ofertă, dar și despre producătorul de care aparține.
Secțiunea coșul meu îi acordă cumpărătorului posibilitatea de a plasa comenzi cu
produsele dorite, achiziționate de pe pagina de oferte. Dacă acesta se răzgândește și nu mai
dorește plasarea comenzii își poate retrage comanda, atât timp cât nu este încă procesată de
administrator.
Serviciul lista d e favoriți îi permite clientului să vizualizeze ofertele producătorilor
din această listă chiar în profilul său. Astfel, acestuia îi este mult mai ușor să caute produsele
dorite și să le adauge în coșul de cumpărături în vederea plasării unei comenzi.

1.3.2 Funcționalitățile producătorului
Pe lângă funcționalitățile de bază, asemenea cumpărătorului , producătorul beneficiază
de anumite servicii, specifice tipului său de cont.
Funcționalitaea care va fi cel mai des utilizată de către producător este repreze ntată de
posibilitatea adăugării diferitelor oferte ale propriilor produse . Acestuia îi este, de asemenea,
permis să le editeze pe cele exi stente sau să le elimine.

1.3.3 Funcționalitățile administratorului
Administratorul este cel care menține ordinea î n cadrul aplicației la nivel de utilizatori
și oferte. În cazul în care apare o neregularitate acesta poate elimina oferte, mesaje și chiar
utilizatori. Secțiunile acestuia sunt :
Secțiunea utlizatori , unde sunt afișați, sub forma unei liste, toți utilizat orii și datele
acestora.
Secțiunea ofertele utilizatorilor permite vizualizarea tuturor ofertelor existente și
informațiilor despreacestea.
Secțiunea comenzile utilizatorilor oferă posibilitatea administratorului de a valida
comenzile clienților.

8

9
2. Tehnologii utilizate

Sir Tim Berners -Lee a fost cel care a stat la baza apariției serviciului World Wide
Web. Acesta își dorea să poată distribuii datele obținute în urma experimentelor științifice.
Atat internetul, cât și hypertext -ul deja existau, însă nimeni nu se gândise să le folosească
pentru unirea documentelor între ele folosind legături.
Termenul de World Wide Web (www sau web) se referă la totalitatea site -urilor web
ce sunt conectate la internet și a dispozitivel or (calculatoare, telefoane) prin care se poate
accesa conținutul acestor site -uri. [1] WWW -ul are la bază următoarele tehnologii :
HTML – Hypertext Markup Language, este un standard de concepere și prezentare a
unui site web.
URL – Uniform Resource Locator , utilizat pentru definirea unei adrese.
Componentele acestuia sunt în general un nume de protocol, locația site -ului, numele(ales de
către deținătorul site -ului) si o terminație care arată tipul de proprietar.
HTTP – Hypertext Transfer Protocol, stivă de protoco ale de tip text, utilizat pentru a
transmite informații între un program de navigare web (browser) și un server web. Există
două tipuri și anume : HTTP Server, cel care furnizează pagini web si HTTP Client, care cere
pagini web. Caracteristic acestui protocol este faptul că legătura client -server nu este
reprezentată de o succesiune de stări prestabilite ci, fiecare tranzacție este independentă astfel
când clientul trimite o cerere, serverul răspunde cu resursa cerută [2]
În dec ursul timpului au fost definite și introduse alte standarde precum :
CSS – Cascade Style Sheets, utilizat pentru a edita elementele definite cu ajutorul
HTML -ului prin intermediul unor fisiere externe sau chiar in cadrul documentului.
JS – JavaScript, este un limbaj de programare folosit pentru a îmbunătăți pagina web
cu diverse funcționalități. Codul scris prin acest limbaj este rulat de către browser.
HTTPS – Hypertext Transfer Protocol Secure, reprezintă același protocol HTTP însă,
acesta criptează datele transmise de la programul de navigare la serverul web cu scopul de a
oferi o siguranță la server. În general, acest tip de conexiune este utilizat pentru a realiza
operații de plată. [3]
În continuare, vor fi descrise tehnologiile utilizate pentru dezvoltarea site -ului astfel
încât, înțelege rea modul ui de funcționare al acestuia să fie cât mai facilă .
Pentru backend s -au utilizat : Java/SpringBoot , Spring Data, Spring Security – JWTs,
Hibe rnate .
Pentru frontend a fost folosit: Angular, TypeScript, Bootstrap, JavaScript , HTML,
CSS.
Baza de date a fost modelata utilize ând MySQL.

10
2.1 Tehnologii utilizate pe partea de Server

2.1.1 Java

Java este un limbaj de programare orientat pe obiecte, g ândit de James Gosling, creat
în cadrul compani ei Sun Microsystems la începutul anilor ’90 și lansat în anul 1995. Java stă
la baza dezvoltării majorității aplicațiilor distribuite.
Avantajul utilizării acestui limbaj îl reprezintă faptul că după compilarea codului,
acesta poate rula pe orice platformă unde este prezentă o mașină virtuală (JVM) fară nicio
modificare, spre deosebire de alte limbaje. Acest lucru este posibil deoarece su rsele Java sunt
compilate într -un format standard numit byte -code(cod de octeți). Acest cod este interpretat
de JVM (Java Virtual Machine). Codul de octeți este un intermediar între codul
mașină(dependent de tipul c alculatorului) și codul sursă. [4 ]

2.1.2 Spring

Framework -ul Spring este o platformă care permite utilizatorilor să intervină în
procesul de dezvoltare (open source) astfel , putând fi utilizat împreună cu diferite limbaje de
programare. Apărut în anul 2002, odată cu cartea “Expert One -on-One: J2EE Design and
Development” , redactat ă de către Rod Johnson , Spring asigură un model comprehensiv de
programare și configurare pentru aplicații enterprise moderne bazate pe Java – pe orice tip de
platformă de dezvoltare . Un element cheie al Spring -ului es te suportul infrastructural la
nivelul aplicației. Spring se concentrează pe ajustarea aplicațiilor enterprise în așa fel încât
echipele să se poată concentra pe logica aplicației, fără legături nedorite la medii de
dezvoltare specifice. Facilitățile prin cipale oferite de Spring sunt :
 injectarea dependen țelor
 principala tehnologie pentru aplicaț ii web și service web RESTful
 suport pentru JDBC, JPA
 și altele [5]

Injectarea dependențelor

Inversiune a controlului este un principiu în ingineria software prin care controlul
obiectelor sau porțiuni din program sunt transferate spre un container. Esențial pentru Spring
este containerul de inversiune a controlului ce aduce un mod consistent de a configura și
administra obiecte Java folos ind reflexia. Acest container este utilizat pentru a administra
ciclul de viață ale unor obiecte prin crearea acestora, apelarea metodelor de inițializare și
configurarea acestor.

11

Fig. 2 .1.1 Framework ul Spring [6]

Containerul creeaz ă obiecte numite obiecte administrate sau boabe (beans). Acesta
poate fi configurat prin fișiere XML sau folosind anumite adnotări specifice Java asupra
claselor de configurare. Aceste surse de date cunosc structura bean -urilor și colectează datele
necesare pentru crearea acestora.

Accesul la aceste obiecte se face utilizând injectarea dependențelor , o tehnic ă prin
care un obiect sau o metodă furnizează dependența unui alt obiect. Containerul Srping
injectează obiecte în funcție de nume altor obi ecte, prin intermediul constructorului,
proprietăților sau tiparului factory method. [7]

În cadrul frameworkului Spring, toate cererile sunt interceptate și gestionate de un
singur servlet, numit DispatcherServlet . Dispatcherul invocă handler -ul „Handle rMapping”
pentru a identifica un controller care s ă proceseze cererea utilizatorului. Următorul pas îl
reprezintă trimiterea cererii de la dispatcher spre controller -ul găsit de handler pentru a
rezolva și efectua operațiile necesare cererii utilizatorulu la nivel de logică a aplicației.
Controllerul utilizează instațe injectate ale serviciilor, iar acestea la rândul lor au acces la
datele din baza de date prin instanțe ale depozitelor definite pentru fiecare entitate.

Fiecare metodă din controler poate rezolva o posibilă cerere a clientului. Acestea
trebuie să aibă o adnotare HTTP pentru a specifica tipul cererii si UR I-ul relativ . O adnotare
reprezintă o formă de metadata, folosită în programe, dar care nu influențează acel cod.

Exemple de adnotări pentru rezolvarea cererilor HTTP sunt :
• @GetMapping utilizând această adnotare , metoda devine similara cu o cerere HTTP
GET. O cerere GET este utilizată pentru a verifica st area resurselor necesare la momentul
actual.
@GetMapping( “getmethod ”)
public String getMethod(){…}

12
• @PostMapping utilizând această adnotare , metoda devine similara cu o cerere
HTTP POST . Folosind această metodă, clientul trimite o stare nouă, editată a resursei
respective pentru a fi actualizată. Ca răspuns, clientul este anunț at dacă cererea s -a încheiat cu
succes sau nu.
@PostMapping( “postmethod ”)
public boolean postMethod (Resource resource ){…}

• @PutMapping utilizând această adnotare , metoda de vine similara cu o cerere HTTP
PUT. Clientul apelează la această cerere pentru a crea sau suprascrie resursa specificată. Ca
răspuns, clientul este anunțat dacă cererea s -a încheiat cu succes sau nu.
@PutMapping( “putmethod ”)
public boolean putMethod(Resource resource ){…}

• @Delete Mapping utilizând această adnotare , metoda devine similara cu o cerere
HTTP DELETE . În cazul în care se dorește ștergerea unei resurse, clientul apelează la acest
tip de cerere. Ca răspuns, clientul este anunțat dacă ștergerea s -a încheiat cu succes sau nu.
@DeleteMapping( “deletemethod ”)
public boolean deleteMethod (Resource resource )

Pentru a ajuta la recunoașterea resurselor sau a utiliza parametrii transmiși prin UR I-
ul cererii au mai fost implementate și adnotările următoare :
• @Path valoarea acestei adnotări reprezintă URI-ul relativ unde poate fi accesată
resursa. Această adnotare se folosește atât la clasele Java cât ș i la serviciile publice oferite de
aceastea . Se marchează faptul că servicul se găsește la URI -ul relativ : https://ip:por t/testpath ,
iar metoda poate fi apelat ă folosind https://ip:port/testpath/path (ip-ul și portul sunt
configurate de către cel care pune la dispoziție serviciul).
@Path(“testpath”)
public class Test{

@Path(“/path”)
public void method(){}
}

• @PathVariable prin această adnotare, valoarea parametrului trimis în URL devine
valoarea paramentr ului adnotat, utilizat în metodă. Se folosesc blocurile de înlocuire in URL
marcate prin {}. Un exemplu de URL: http://id:port/testpath/path/id1
@Path(“testpath”)
public class Test {
@GetMapping (“/path/{id}”)
public String getmethod(@PathVariable(“id” String id) ){}
}

13

• @RequestBody prin această adnotare, se mapeaz ă valoarea din corpul cererii la
paramentr ul adnotat, utilizat în metodă. Corpul cererii este transmis folosind un convertor
pentru a rezova problema diferențelor de tip dintre valoarea trimisă și parametrul metodei la
care aceasta este mapată. Opțional, se poate adăuga o vali dare automată folosind adnotarea
@Valid.
@Path(“testpath”)
public class Test {
@GetMapping (“/path
public String getmethod( @RequestBody String id ){}
}

JPA

Java Persistence API este o specificație Java pentru accesarea, persistența și
administrarea datelor între obiecte/clase Java și o bază de date relațională. JPA a fost definit
ca parte a specificațiilor EJB 3.0 ca fiind înlocuitorul specificațiilor EJB 2 CMP Entity Beans.
JPA este acum considerată abordarea standard din industrie pentru Object to Relational
Mapping (ORM). [8]

Fig. 2 .1.2 Arhitectura JPA [9]
Fiind doar o specifica ție, nu un produs de sine stătător, JPA nu poate produce
persistență sau ceva independent. Este un set de interfețe care necesită implementare.
Entităților POJO (Plain Old Java Objects – obiecte simple Java) le este permis de
către JPA să persiste fără să necesite implementarea anumitor interfețe sau metode. JPA
permite ca mapările obiect -relaționale ale unui obiect să fie definite prin adnotări standard
sau XML, definind modul în care o clasă Java se mapează la un tabel dintr -o bază de date
relațională. De asemene a, JPA definește un API EntityManager la runtime pentru procesarea

14
query -urilor și tranzacțiilor obiectelor asupra bazei de date. JPA definește un limbaj de query –
uri la nivel de obiect, JPQL pentru a permite obținerea obiectelor din baza de date prin quer y-
uri. [10]

Adnotările esențiale în utilizarea JPA sunt prezentate în tabelul 2. 1.1.
Adnotarea Clasă/Câmp Descriere
@Entity Clasă Specifică faptul că clasa este
persistentă
@MappedSuperclass Clasă Specifică faptul că această clasă
conține informații persistente
care trebuie mapate
@Id Câmp/Metodă Definește un câmp ca fiind
(parte din) identitatea unei clase
@Version Câmp/Metodă Câmpul definește versiunea
clasei
@Basic Câmp/Metodă Definește un câmp ca persistent
@Transient Câmp/Metodă Câmpul nu este persistent (este
tranzitiv)
@OneToOne Câmp/Metodă Definește acest câmp ca fiind
într-o relație de 1 – 1 cu o altă
entitate persistentă
@OneToMany Câmp/Metodă Definește acest câmp ca fiind
într-o relație de 1 – N cu o altă
entitate persistentă
@ManyToOne Câmp/Metodă Definește acest câmp ca fiind
într-o relație de N – 1 cu o altă
entitate persistentă
@GeneratedValue Câmp/Metodă Valoarea acestui câmp a fost
generată cu un generator
@PrePersist Câmp/Metodă Definește o metodă ca fiind
callback pen tru evenimentul de
pre-persist
@PostPersist Câmp/Metodă Definește o metodă ca fiind
callback pentru evenimentul de
post-persist
Tabel 2 .1.1 Adnotări JPA
Există o interfață standard pentru interacțiunea cu o bază de date relațională, insă
există anumite funcționalități care nu sunt incluse de aceasta, cum ar fi :

15
 interogările de tip join (într -o interogare apelată pe o entitate părinte nu se
poate recurge la un câmp al unei entități copil pentru filtrare)
 relații de tip owned many -to-many
 interogări de agregare : group by, count, avg, max, min
 interog ări polimorfice (nu se poate interoga o clasă pentru a obține ca rezultat
instanțe ale subclasei, fiecare clasă este reprezentată de un tip separat de
entitate)
Tom cat
Tomcat este un server Web care permite u tilizatorilor să intervină în procesul de
dezvoltare (open source) dezvoltat de Apache Software Foundations (ASF). Oferă un server
web HTTP, unde codul Java poate rula. Protocolul HTTP este implementat în interiorul
serverului Tomcat, acesta având grijă de cerere și răspuns .

JDBC(Java DataBase Connectivity)
JDBC (Java DataBase Connectivity) este o interfață standard SQL de acces la baze de
date. Acesta ne furnizează un acces uniform la baze de date relaționale. JDBC este constituit
dintr -un set de clase și interfețe scrise în Java, furnizând un API standard pentru proiectanții
de aplicații baze de date. JDBC -ul este o interfață "low -level", adică este folosit pentr u a
executa direct comenzi SQL. [11]

SpringData
Spring Data oferă un model de programare bazat pe Spring ce îți permite accesul
datelor, păstrând în același timp trăsăturile speciale care stau la baza unei „data store” (bază
de date).

Hibernate
Hibernate este unul din comercianții de persistență care au lansat implementări ale
JPA, marcând astfel faptul că acesta a fost adoptat de industrie și utilizatori. Hibernate ORM
(object -relational mapping) este un tool, specific limbajului Java, utilizat pentru a mapa
modele orientate pe obiecte la bazele de date relațt ionale.

2.1.3 Spring Security
Spring Security este un framework de securitate ce oferă suport pent ru autentificare și
autorizare în scopul securizării aplicațiilor Spring. Principala caracteristică este ușurința cu
care poate fi extins pentru a îndeplini cerințele clientului.
JWTs (Json Web Tokens) sunt token -uri folosite pentru autentificarea utilizatorilor în
aplicație. În ultimii ani au devenit intens folosite datorită faptului că permit logicii aplicațiilor

16
să accepte și să valideze cererile mult mai s implu, doar prin validarea conținutului acestuia,
eliminând nevoia salvării unor date suplimentare în cookie -uri. Acest lucru favorizează
scalabilitatea aplicației și în același timp menține securitatea aplicației.
În timpul procesului de autentificare, î n momentul în care un utilizator reușește să se
conecteze cu succes (cu alte cuvinte a introdus date de identificare valide), un json web token
este returnat. Acesta conține datele utilizatorului codate folosind standardul Base64Url.
Tokenul va fi salvat l ocal (de obicei în spațiul de stocaer local). De fiecare dată când
utilizatorul dorește să acceseze o resursă, serverul de client va trimite acest token, de obicei în
antetul cererii, împreună cu aceasta, în vederea autorizării și rezolvării acesteia.
Prim ul lucru executat de către serverul de backend, atunci când primește o cerere, este
să valideze tokenul. Pentru a valida tokenul se execută o serie de pași, cum ar fi: verificare
formatului, verificarea semn ăturii, validitatea acestuia, verificare permisiu nilor utilizatorului.
Dacă oricare din acești pași nu este îndeplinit, cererea va fi respinsă.
Pentru a anunța serverul care tipuri de cereri și ce metode specifice acestora trebuie să
fie verificate se va folosi adnotare PreAuthorize sau PostAuthorize. A mbele adnotări primesc
ca parametrii rolurile cărora le este permis să acceseze metodele care rezolvă cererea primită.
PreAuthorize verifică tokenul înainte de a intra în metodă, iar PostAuthorize îl verifică după
ce încheie execuția acesteia.

@PreAutho rize("hasRole('ROLE_VIEWER')")
public String get Methode() {…}

Fig. 2 .1.3 Procesul JWTs [12]

17
2.1.4 Spring Boot
Spring Boot permite crearea, cu ușurință , a aplicații lor independente, bazate pe
framework -ul Spring. Oferă o serie de facilități printre care: încorporează Tomcat (nu este
necesară instalarea fișierelor de tipul WAR), configurează automat Spring oriunde este
posibil, nu este necesară o configurație XML, oferă fișierul de configurări inițial POM
(Project Object Model) pentru a simplifrica co nfigurația Maven.
Printre avantajele dezvoltatorilor care folosesc Spring Boot se numără :
 ușurința de a înțelege conceptele și modul de folosire pentru a crea aplicații
 sporește productivitatea
 reduce timpul de dezvoltare al aplicației
Spring Boot a fost c onceput pentru următoarele scopuri:
 evitarea configurațiilor XML mult prea complicate din cadrul Spring
 dezvoltarea unei aplicații Sprin pregătite de utilizare într -un mod foarte simplu
 reducerea timpului acordat dezvoltării software -ului și permiterea rulării
aplicației într -un mod cât mai independent posibil
Configurarea aut omată a Spring Boot -ului configurează aplicația Spring bazându -se
pe dependențele JAR pe care le -ați adăugat în proiect. De exemplu, dacă se folosește MySQL
pentru baza de date, în să nu ați configurat nicio conexiune la baza de date, atunci Spring
Boot -ul configurează o bază de date în memorie.
Pentru acest lucru e necesar să adăugăm adnotarea @SpringBootApplication în clasa
principală. Apoi, aplicația Spring Boot va fi automat conf igurată. Clasa decorată cu această
adnotare e considerată punctul de start al aplicației. Aici se va afla și metoda main a
aplicației.

@SpringBoot Application
public class MyApplication {

public static void main(String[] args) {
SpringApplication. run(MyApplication. class, args);
}
}

2.2 Tehnologii utilizate pe partea de Client

2.2.1 Angular

Angular este cea mai utilizată platformă și unul dintre cele mai populare framework –
uri al limbajului de programare Type Script, folosit de majoritatea companiilor pentru crearea
aplicațiilor web. TypeScript este un limbaj de programare „open -source” devoltat de

18
Microsoft. Este un superset al limbajului de programare JavaScript, adăugând limbajului un
mod de programarea orientat pe obiecte bazat pe clase și declarare statică opțională („static
typing”).
Angular implementează funcționalitățile de bază și altele opționale ca un set de
biblioteci scrise în limbajul TypeScript, astfel încât pentru utilizator să fie foarte ușor de
folosit, doar prin simpla importare a acestora.
Cea mai importantă structură în Angular este modulul Ng (NgModule). Modulul Ng
rădăcină este creat automat în momentul conceperii proiectului, iar scopul acestui a este de a
cunoaște și sumariza toate modulele și obiectele care vor exista în proiect. Acest modul
rădăcină ajută la utilizarea bootstrap -ului în proiect.
Bootstrap este cel mai popular framework HTML, CSS și JS pentru dezvoltarea
proiectelor mobile, r eceptive pe web. [ 13] Conține șabloane de design CSS și JS pentru
formulare, butoane si bări de navigare și alte componente utilizate în conceperea interfeței.
Un modul Ng este definit de o clasă , decorată cu adnotarea @NgModule().
Decoratorul @NgModule () este o funcție care preia un singur obiect de metadate, ale cărui
proprietăți descriu modulul. Cele mai importante proprietăți sunt după cum urmează.
 declarații: componentele, directivele și conductele care aparțin acestui modul Ng .
 exporturi: subsetul de declarații care ar trebui să fie vizibile și utilizabile în șabloanele
componente ale altor module Ng .
 importuri: a lte module ale căror clase exportate sunt necesare prin șabloanele
componentelor declarate în acest modul Ng .

Fig. 2 .2.1 Modul Ng [14 ]
Orice aplica ție Angular conține cel puțin o componentă, rădăcina, care con ectează o
ierarhie de componente cu pagina DOM ( document object model). Fiecar e componentă
definește o clasă care conține datele cu care lucrează aplicația și logica necesară, dar și un

19
șablon (template) HTML care definește interfața. Pentru a marca faptul că o clasă e
componentă se folosește adnotarea @Component().
Un șablon combină elemente din limbajul HTML cu simboluri specifice Angular, care
pot modifica elementele HTML înainte ca acestea să fie afișate. Prin funcționalitatea de
legare a datelor (binding data) se pot conecta datele aplicației de pagina DOM. Există două
tipuri de legare :
 legarea evenimt: aplica ția actualizează datele ca răspuns la acțiunea
utilizatorului de introd ucere a informațiilor
 legarea proprietate : permite interpolarea valorilor care sunt compuse din datele
aplicației în HTML
Înainte ca interfața să fie afișată, Angular evaluează și rezolvă sistemul de legare și
modifică elementele HTML si DOM în conformita te cu datele din program și logica
aplicației.

Fig. 2.2.2 Serviciul de legare [1 5]
Datele sau logica aplica ției care nu sunt asociate cu un șablon specific, dar care sunt
necesare pentru a fi folosite între componente se pot defini intr -un serviciu. Un serviciu este o
clasă decorată cu adnotarea @Injectable(). Această adnotare furnizează datele interne care
permit altor furnizori să fie in jectați ca dependențe în clasa în care sunt necesare.
Injectarea dependențelor permite să păstrăm clasele componentelor slab cuplate și
eficiente. Acestea nu prelucrează date de la server, nu validează informația de la utilizator, ci
deleagă astfel de sarcini serviciilor .
Modulul Ng Router oferă un serviciu care permite definirea căilor de navigare între
diferitele stări ale aplicației. Este modelat pe baza convețiilor de navigare ale unui motor de
căutare:

20
 introducerea unui URL în bara adresei și motorul de căutare navighează spre
pagina web corespunzătoare
 apăsarea într -o pagină pe un anumit link și navigarea spre pagina web respectivă
 folosirea butoanelor înainte și înapoi pentru navigarea între pagini web
Routerul mapează căile URL la șabloane în loc de pa gini. Când un utilizator execută o
acțiune cum ar fi apăsarea pe un link, care de obicei ar încărca o nouă pagină web în motorul
de căutare, routerul interceptează comportamenul acestuia și afișează sau ascunde interfețele .
Pentru a putea define regulile de navigare și pentru a ști care interfață trebuie să fie
afișat ă, se asociază căile de navigare cu componentele aplicației. O cale de navigare folosește
o sintaxă asemănătoare cu un link URL, în care sunt integrate datele de program. Utilizând
mai apoi aceste date, se alege interfața ce trebuie afișat ă sau ascuns ă, ca răspuns la acțiunile
utilizatorului.

Fig. 2.2.3 Frameworkul Angular [16]
O componentă, alături de un șablon, defines o interfață. O adnotare adăugată pe
component adaugă metadatele, inclusiv o adresă (pointer) spre șablonul asociat componentei.
Directivele și simbolurile de legare dintr -un șablon al unei componente modifică interfața pe
baza datelor apli cației și logicii programului. Injectorul de dependențe oferă servicii
componentelor, precum serviciul de routare care permite definirea navigării între interfețe.

21
3. Specificațiile proiectului
3.1 Analiza și specificarea cerințelor
Utilizatori
Persoanele care doresc să își comercializeze produsele , dar și cele care au intenția de a
le achiziționa sunt încadrate ca utilizatori ale aplicației dezvoltate. Astfel, putem defini două
categorii de utilizatori ai aplicați ei: produc ătorii și cumpărătorii.
Funcționalități
În vederea beneficierii de orice serviciu în cadrul aplicației , utilizatorii trebuie să își
creeze un cont. Cu acest a, utilizatorul se va autentifica și va avea acces la toate
funcționalitățile specifice tipului său de cont .
Pe baza informațiilor oferite la înregistrare, utilizatorului i se va crea un profil. Acest
profil va putea fi editat în cadrul aplicației, după autentificare.
Principala funcționalitate a aplicației o reprezintă serviciul de comercializare,
respectiv ach iziționare al produselor naturale. Pentru un producător va exista posibilitatea de
adăugă rii ofertelor, iar din perspectiva cumpărătorului se va putea analiza lista de oferte și
comanda produsele dorite.
Cumpărătorilor le este permis ă adăugarea diferitelo r produse în coșul propriu de
cumpărături, iar în momentul dorit , au opțiunea de a înregistra această comandă. Dacă acesta
se răzgândește și nu mai dorește respectivele produse, cumpărătorul își va putea retrage
comanda, cu condiția ca aceasta să nu fi fos t validată de către administrator.
O altă funcționalitate importantă o reprezintă posibilitatea de comunicare între
utilizatori, prin trimiter ea de mesaje tip email. Astfel, păstrându -se legătura dintre producători
și cumpărători.
Adăugarea producătorilor la o listă proprie de favoriți este, de asemenea, o
caracteristică utilă cumpărători lor. Astfel , acestora le vor fi afișate în primul rând ofertele
producătorilor aflați în această listă.
Administratorul va putea menține siguranța și buna funcționare a aplicației prin
inspectarea listei de utilizatori și cea a ofertelor. Acesta va fi responsabil și pentru validarea
comenzilor cumpărătorilor.

22

Fig. 3.1.1 Cazuri de utilizare producător

Fig. 3.1. 2 Cazuri de utilizare cumpărător

23

Fig. 3.1.3 Cazuri de utilizare administrator
3.2 Baza de date

Fig. 3.2 .1 Diagrama bazei de date

24
În Fig.3.2.1, prezentată anterior , este reprezentată diagram bazei de date. În
continuare vor fi descries tabelele și relațiile dintre acestea.
Tabela user conține un număr mare de câmpuri. În jurul acesteia și a tabelei offer ,
este structurată baza de date a aplicației. Datele utilizatorului sunt necesare pentru a putea
crea profilul acestuia. Un utilizator este creat doar după ce câmpul „enabled ” este acti vat.
Tabela offer stochează detaliile tuturor ofertelor utilizatorilor aplicației. Între tabele
user și tabela offer există o relație de 1..n, acest lucru semnificând că un utilizator poate să
aibă 1 sau n offer . Relația are loc doar dacă utilizatorul are rolul de producător . Rolul relației
este de a putea selecta ofertele care aparțin unui anumit utilizator.
Tabela messages memoreaz ă toate mesajele transmise între utilizatori. Există două
relații de 1..n între această tabelă și cea de user, deoarece este necesară cunoașterea identității
atât a expeditorului, cât și a destinatarului mesajului.
Tabela comments păstrează toate comentariile utilizatorilor pentru ofertelor existente.
Fiind nevoie de cunoașterea atât a utilizatorului care a lăsat comentariul, cât și a ofertei
asupra căreia s -a făcut comentariul s -au implementat două relații 1..n între tabela user și
comments , respectiv între tabela offer și comments .
Tabela user_favourites este tabela care stochează lista de producători favoriți ai
cumpărătorilor. Deoarece este necesar să știm cărui utilizator îi corespunde un anume
producător din listă, s -au implementat două relații one -to-many între tabela user_favourites și
user. Acest lucru se traduce prin faptul că un utilizator poate să aibă unul sau mai mulți
utilizatori în lista de favoriți.
Ultima tabelă, și cea mai simplă din punct de vedere al relațiilor, este reviews , unde se
rețin toate mesajele care conțin idei de îmbunătățire, apr ecieri sau critici primite de la
utilizatorii aplicației.

25
4. Implementare
4.1 Arhitectura aplica ției
Aplicația este formată din două componente majore :
 Aplica ția client , este responsabilă de operațiile aparținând interfeței cu
utilizatorul
 Aplicația server, este responsabilă de prelucrarea diverselor tipuri de cereri
venite din partea clientului și de opertațiile necesare fiecăreia. În acest mod
realizându -se noi intrări în baza de date, corespunzătoare acestor cereri.

Fig. 4.1 .1 Arhitectura Client -Server a aplicației – prelucrare dup ă [17]
Clientul Angular reprezintă nivelul de prezentare al aplicației, oferind interfața cu
utilizatorul. Acesta apelează la cererile de tip HTTP pentru a putea comunica cu serverul.
Nivelul logicii aplicației este asigurat de aplicația Spring care rulează pe server,
responsabilă de prelucrarea cererilor și oferirea obiectelor business necesare.
În cele din urmă, nivelul acesării datelor este realizat cu ajutorul JPA, care face
legătură cu baza de date pentru a obține informațiile care urmează să fie prelucrate.
 Comunicarea dintre aplicația client și aplicația server se realizează prin cereri de tip
HTTP GET, POST, PUT sau DELETE specifice s tilului arhitectural REST(Representation
State Transfer) . REST se referă la transferarea stării resurselor într -o formă reprezentativă
care este cea mai potrivită pentru client sau server – de la un server la un client (sau
viceversa).

26
Prin aceste cereri, aplicația client transmite către server informații despre intențiile
utilizatorului și diferite date necesare pentru rezolvarea acestora sub format JSON sau XML .
Aceste cereri sunt interceptate de DispatcherServlet , iar HandlerMapping -ul va alege, în
funcț ie de structura URL -ului cererii și de tipul de date cu care se va lucra, controlerul și
metoda care v or rezolva cererea. Controlerul va avea injectat din containerul de Spring
anumite instanțe ale serviciilor care vor procesa informațiile. Aceste vor avea acces la datele
din baza de date prin instanțele depozitelor definite pentru fiecare model.
Modelele sunt definite utilizând adnotarea @Entity asupra unei clase care reprezint ă
înfățișarea tabelelor din baza de date. Fiecare coloană a tabelului este definită de un câmp al
acestei clase. Modelele utilizate în cadrul aplicației sunt :
 User( id, nume, prenume, parolă, email, număr de telefon, tipul contului,
adresă, număr voturi, sumă voturi, activat)
 Ofertă( id, titlu, d escriere, id -ul userului, categorie, preț, unitate monetară,
cantitate, unitate de măsură a cantității, nume fișier)
 Mesaj ( id, id user expeditor, id user destinatar, mesaj)
 Comentariu ( id, id user care a lăsat comentariul, id ofertă, comentariu)
 Comandă ( id, id user care a făcut comanda, id ofertă, cantitate, întregistrat)
 User favorit ( id, id -ul userului căruia îi aparține lista,id user adăgat)
Controlerele sunt definit folosind adnotarea @RestController și conțin o listă de
metode care vor rezolva cererile sosite de la client, pe adresa serverului care rulează. În
secțiunile următoare vor fi prezentate unele exemple ale astfel de metode.
Folosind adnotarea @Service se poate define un serviciu. Acesta va comunica cu
depozitul si va prelua informații din baza de date, prelucrându -le astfel încât cererea
clientului să fie îndeplinită.
Depozitele sunt definite pentru a opera cu ușurință asupra bazei de date. Fiecare
depozit definit pentru model va trebui să extindă interfața pusă la dispoziție de către Spring,
JpaRepository , adaptându -o la modelul pentru care a fost definit. Pentru a crea un depozit se
va folosi decorația @RepositoryRestResource .
Aplicația server răspunde cu datele necesare pentru cererile de tip GET sau cu
rezultatul finalizării cererii, caz pozitiv sau negativ. Dacă cererea este de autentificăre și
datele de autentificare sunt valide, aplicația server trimite ca răspuns al cererii token -ul în
care se găsesc datele utilizatorului, iar pentru date de autentificare invalide este returnat un
mesaj care înștiințează aplicația client că autentificarea a eșuat.

27

Fig. 4.1.2 Comunicarea din cadrul aplicației
4.2 Implementarea func ționalităților comune
În subcapitolele următoare va fi descrisă modalitatea de implementare a
funcționalităților comune celor două categorii principale de utilizatori : producători și
cumpărători.
4.2.1 Autentificarea utilizatorilor
Pentru accesarea aplicație este necesară autentificarea utilizatorului. În acest scop, s -a
utilizat JWTs(Json Web Tokens). În metoda configure(HttpSecurity httpSecurity) , oferită de
WebSecurityConfigurerAdapter s -au definit anumite pattern -uri URL pe care orice utilizator
le poate accesa, nefiind nevoie de autentificare . Orice utilizator poate accesa o cerere dacă
URL începe cu / registration, /login . Folosind metoda permitAll() li se permite tuturor
utilizatorilor să acceseze pagina de autentificare.
În momentul interceptării unei cereri de autentificare, adică U RL-ul cererii are
formatul https://localhost:8443 /login , aceasta va fi redirecționată de către HandlerMapping
spre AuthenticationController, mai exact spre metoda rezolvant ă a cererii, login . Această
metodă va returna, în cazul în care credențialele introduse au fost valide, token -ul care va fi
folosit pentru a permite accesarea altor servicii. Acest token este generat în cadrul metodei
generateToken(JwtUser userDetails) și conține numele de utilizator, în cazu l nostru email -ul
și momentul de timp la care acesta devine invalid și nu va mai putea fi utilizat.

28

Fig. 4.2 .1 Generarea unui token

Pentru o cerere venită după autentificarea utilizatorului, a fost configurat un filtru al
token -urilor, folosind metoda addFilterBefore() oferită de HttpSecurity . Acest filtru constă în
compararea numelui utilizatorului, prezent în informațiile token -ului, cu cel din baza de date
și în același timp asigurarea faptului că validitatea token -ului este corectă.

Fig. 4.2 .2 Validarea unui token
În cadrul aplicației client, acest token este salvat în LocalStorage și trimis către
aplicația server ori de câte ori utilizatorul va face o anumită cerere.
localStorage .setItem( 'currentUserToken' ,JSON.stringify(response. token));

4.2.2 Înregistrarea utilizatorului
În cazul în care utilizatorul nu are un cont pentru a se autentifica, acestuia îi este
permisă crearea unuia, accesând pagina https ://localhost:8443 /registration , din meniul
aplicației . Formularul pe care utilizatorul va trebui s ă îl completeze în vederea creării unui
cont are toate câmpurile marcate cu proprietatea required ceea ce înseamnă că nu vor putea
fi lăsate necompletate. De asemenea, pentru adresa de email introdusă, s -au implementat
anumite verificări utilizând expresi ile regulate, pentru a ne asigura că este una validă. În
același context au fost implementate verificări și pentru numărul de telefon al utilizatorului.
Această cerere HTTP de tip POST va fi procesată în cadrul controler -ului
PreLoginController , aflat în containerul Spring datorită adnotării acestuia cu @Controller ,
mai exact în metoda registration , decorată cu adnotarea @PostMapping(value=“/registration”) .

29
Deoarece, pe lângă informațiile de bază despre noul utilizator cum sunt numele,
prenumel e, adresa, număr de telefon, etc. , este trimisă și o fotografie de profil, va fi nevoie să
o stocăm în memorie. Astfel, după salvarea utilizatorului în baza de date, se va salva în
memorie, fișierul sursă al pozei de profil, creând o cale unică pentru fiec are utilizator, pe baza
id-ului său.
Aceste date sunt trimis e din aplicația client prin cerere în corpul acesteia, utilizând un
formData. Acesta ne permite organizarea informațiilor sub forma cuplului (cheie, valoare).
Astfel, acesta stochează două seturi de informații și anume, informațiile text ale utilizatorului
și cealaltă , imaginea încărcată de acesta.

Fig. 4.2 .3 Organizarea datelor pentru cererea de înregistrare

Fig. 4.2 .4 Înregistrarea utilizatorului

4.2.3 Opinia utilizatorilor
Deoarece se dorește o continuă dezvoltare și îmbunătățire a aplicației, a fost definită
secțiunea de contact . Accesând https ://localhost:8443 /contact , orice utilizator va putea
trimite opinia, plângerea sau idea de îmbunătățire a aplicației.
Pe partea de client, este prezent un formular în cadrul căruia utilizatorul va introduce
adresa de e -mail, pentru a putea fi contactat pe viitor și mesajul pe ca re acesta dorește să îl
trimită.
În cadrul aplicației server, cererea Http de tip Post este interceptată de controler -ul
ReviewsController . Cererea este rezolvată de metoda saveReview( @RequestBody Reviews

30
message ). Parametru l este adnotat cu acea decorație pentru a ști că, în corpul cererii se găsesc
datele care trebuie procesate, mai exact e -mailul și mesajul utilizatorului .
Folosind adnotarea @Autowired , containerul Spring a injectat o instanță a
Reviews Repository , care va fi folosită pentru a putea realiza salvarea în baza de date. În
cadrul aceste metode se apelează metoda save declarată în interfața CrudRepository și
adaptată pentru entitatea Reviews .
4.2.4 Mesaje le utilizatorului
Pentru a putea comunica într -un mod simplu, utilizatorilor li s -a pus la dispoziție
funcționalitatea de a expedia și recepționa mesaje în cadrul aplicației. Acest lucru se poate
realiza doar după ce utilizatorul s -a autentificat.
Prin accesare secțiunii mesajele mele ,specifică componentei messages , utilizatorul va
putea verifica ultimele mesaje primite, mesajele trimise și va avea posibilitatea să răspundă
tuturor celor care i -au scris.
Din punct de vedere al părții de client, această pagină prezint ă mai multe servicii. Inițial
vor fi realizate cererei Http de tip Get pentru încăr carea mesajelor primite de către acest
utilizator, respectiv cele trimise. Cererea constă în trimiterea către server a id -ului
utilizatorului și de asemenea, a token -ului acestuia. Răsp unsul cererii îl reprezintă o listă de
mesaje, în a căror destinatar este utilizatorul curent. Mesajele sunt încărcate în interfață
folosind funcționalitatea de binding pusă la dispoziție de Angular și directivul pentru iterare a
unui tablou, *ngFor .

Fig. 4.2 .5 Cererea de obținere a mesajelor unui utilizator

Fig. 4.2 .6 Afișarea tuturor mesajelor unui utilizator

31
În momentul apăsării pe unul dintre mesaje, se va realiza o altă cerere Http de tipul Get,
pentru încărcarea întregii conversații. Aceasta va fi afișată în cadranul alăturat listei de
mesaje.
Pentru această cerere va fi nevoie atât de id -ul utilizatorulu i curent, cât și de id -ul celui
care a expediat mesajul și desigur, de token -ul validării cererii. Ca răspuns al cererii, va fi de
asemenea o listă de mesaje, încărcate sub aceeași formă ca cea prezentată mai sus.

Fig. 4.2 .7 Cererea de obținere a unei c onversații
Ultima funționalitate prezentă în cadrul aceste pagini este cea de ștergere a unui mesaj.
Fiecare mesaj din listă are asociat un buton de ștergere iar, în momentul apăsării acestuia se
va trimite o cerere Htpp de tip Delete către aplicația serv er. Cererea va conține id -ul
mesajului pentru care se face ștergerea și token -ul utilizatorului. După primirea răspunsului
de la aplicația server, se va face actualizarea listei de mesaje.

Fig. 4.2 .8 Cererea de ștergere a unui mesaj
În cadrul aplicației server, toate cererile venite de la aplicația client vor fi interceptate
de controlerul MessagesController , care are injectată o instanță a MessagesService pentru a
putea realiza operațiile cu baza de date.
Pentru încărcarea inițială a mesajelo r există două metode getMessagesForAUser și
getMessagesToAUser , singura diferență între acestea fiind calea URL -ului și modul de
obținere a mesajelor din baza de date. Pentru prima se vor extrage mesajele care au id -ul
utilizatorului primit ca parametru pe poziția expeditorului, iar pentru cea de a doua, se vor
extrage cele care au acest id pe poziția destinatarului. Răspunsul celor două metode îl
reprezintă o listă de mesaje, care vor fi prelucrate de aplicația client.

32

Fig. 4.2 .9 Returnarea mesajelor unui utilizator

Fig.4.2 .10 Extragerea mesajelor din baza de date
Pentru obținerea unei conversații există metoda getConversationForAUser , care
primește ca parametrii, în cadrul URL -ului, id -ul utilizatorilor între care are loc conversația.
Adnotările acestei metode arată structura URL -ului cererii pentru a fi accesată această
metodă, iar cea de a doua adnotare ne indică faptul că orice utilizator care are acele roluri vor
putea accesa metoda.
Folosind instanța messagesService , se vor extrag e din baza de date doar mesajele dintre
acești utilizatori, iar r ăspunsul acest ei metode îl reprezintă o listă de mesaje.

Fig. 4. 2.11 Returnarea mesajelor dintr -o conversație

33

Fig. 4. 2.12 Extragerea mesajelor unei conversații din baza de date
Ultima metodă definită, și anume cea de ștergere a unui mesaj, este un apel către
metoda delete existentă în interfața CrudRepository și adaptată pentru entitatea Messages . Ca
parametru, este id -ul mesajului din baza de date, obținut din structura URL -ului. Adnotarea a
doua permite apelarea metodei de către toate tipurile de utilizatori.

Fig. 4.2 .13 Ștergerea unui mesaj

4.2.5 Profilul utilizatorului
În cadrul acestei pagini , accesate la adresa https ://localhost:8443 /home , utilizatorul își
va putea vizualiza profilul și anume informații ca nume, prenume, adresă, număr de telefon,
tipul contului, etc.
Aplicația client va face cererea de obținere a datelor necesare, din fișierul de servicii
user.servic e.ts, transmițând id -ul utilizatorului curent și token -ul pentru validare. Din cadrul
componentei userprofile , se face cerere spre serviciul care va trimite aplicației server cererea.

Fig. 4.2 .14 Cererea de încărcare a datelor de profil
Posibilitatea de editare a profilului are loc în altă componentă, edit-user, iar după
apăsarea butonului de salvare se va activa cererea spre serviciul din același fișier

34
user.service.ts . Acesta va iniția cererea spre aplicația server. După confirmarea rea lizării
cererii, utililzatorul este redirecționat spre pagina de home .

Fig. 4.2 .15 Cererea de editare a profilului
Ambele cereri Http, cea de Get pentru obținerea datelor și cea de Put pentru editarea
profilului, sunt rezolvate de UserController . Cele două metode pentru aceste cereri sunt
getUserProfile(@PathVariable Long userId) , respectiv editUser(@PathVariable Long
userId, @RequestBody User user) . Pentru metoda de get avem adnotările care specifică
structura URL -ului și tipul utilizatorilor care vor putea accesa metoda. Răspunsul acestei
cereri este un DTO(data transfer object). Acesta va conține doar datele esențiale ale
utilizatorului și a fost utilizat pentru a nu trimite informații irelevante spre aplicația client. De
asemenea, în acest răspu ns este încărcată și imaginea de profil al utilizatorului.

Fig. 4. 2.16 Returnarea informațiilor utilizatorului
Pentru metoda de post avem adnotările care specifică structura URL -ului și tipul
utilizatorilor care vor putea accesa metoda. Aceasta este mult mai simplă, deoarece prezintă
doar un apel spre metoda de edit a serviciului care face legătura cu baza de date.

35

Fig. 4.2.17 Editarea utilizatorului
4.3 Implementarea funcționalităților specifice producătorului

În subcapitolele următoare va fi descrisă modalitatea de implementare a serviciilor și
funcționalităților specifice tipului de utilizator : producător.
4.3.1 Adăugarea unei oferte noi
Specifică și probabil cea mai utilizată funcționalitate a producătoru lui este adăugarea
unei oferte. Acest lucru este posibil doar din cadrul paginii de profil al utilizatorului.
Componenta specifică creării unei noi oferte se numește new-offer . În cadrul aplicației
client, utilizatorul va completa un formular cu datele specifice ofertei pe care dorește să o
publice. Acest formular a fost creat utilizând bootstrap, structuri html cum ar fi label, input,
select, div, aticle, textarea, button și css.
Folosind funcționalitatea de binding pusă la dispoziție de Angular, se va crea legătura
dintre datele introduse de utilizator, în interfață, cu cele declarate în codul typescript. În
această clasă este injectată o referință a OfferService , clasă în care se va realiza trimiterea
cererii către aplicația server. În constructor, es te preluat token -ul din local storage, folosit în
validarea cererii.
Transmiterea datelor către aplicația server se va face în momentul confirmării
utilizatorului. Acest lucru se realizează când utilizatorul va apăsa butonul Save . Datele se vor
transmite în corpul cererii, folosindu -ne de aceeași metodă ca în cazul înregistrării unui
utilizator, deoarece pe lângă informațiile ofertei, utilizatorul va trebui să încarce și o imagine
a produselor pe care le va comercializa în cadrul acelei oferte. Astfel, se va utiliza, din nou,
FormData , salvând sub cheia ‘offer’ datele text ale ofertei, cum ar fi: titlu, descriere, pre ț,
cantitate, etc., care vor fi salvate în baza de date și sub cheia ‘offerFile ’ imaginea încărcată de
către utilizator.

Fig. 4.3 .1 Organizarea datelor pentru crearea unei noi oferte

36
Cererea către aplicația server este una de tip Post, deoarece se dorește salvarea unei noi
înregistrări în baza de date. Alături de informațiile ofertei, se va mai utiliza token -ul
utilizatorului pentru a trece de nivelul de siguranță al aplicației.
Fig. 4.3.2 Inițierea cererii de creare a ofertei către aplica ția serv er
Cererea trimisă va fi interceptată în aplicația server de către DispatcherServlet și
rezolvată în cadrul OfferController , mai exact în metoda saveOfferNewForUser
(@PathVariable Long userId, @RequestParam("offerFile") MultipartFile file,
@RequestParam("offer") String offer ). Metoda este decorată cu adnotarea @PostMapping
(”user/{userId}/offer) , care definește calea URL -ului.
A doua adnotare este @PreAuthorize ("hasAnyRole('PRODUCER')") , care specifică
faptul că doar unui utilizator care are tipul producător îi este permis apelarea aceste
funcționalități. Orice alt utilizator va încerca apelarea acesteia va primi o eroare de t ip
neautorizat.
Primul parametru al metodei este în strânsă legătură cu URL -ul, deoarece id-ul
utilizatorului din URL va fi asociată ca valoare a parametrului , fiind nevoie să cunoaștem
utilizatorul pentru care se adaugă o nouă ofertă . Ceilalți doi param etrii ai metodei sunt legați
de datele ofertei transmise prin form data, informațiile și imaginea.
Pentru a recunoaște entitatea și a putea citi datele ofertei venite de la client, se va utiliza
un ObjectMapper . După salvarea noii înregistrări în baza de date, este nevoie să salvăm în
memorie și imaginea acesteia. Calea specifică va fi construită pe baza id -ului utilizatorului
care salvează oferta și id -ul ofertei.
Controllerul are injectată o instanță a Offer Service folosind adnotarea de @Autowired .
Serviciul acesta va apela metoda save definită în interfața CrudRepository , adaptată la
entitatea Offer .

Fig. 4.3.3 Salvarea unei noi oferte

37
4.3.2 Editarea unei oferte
Din cadrul paginii de detalii a ofertei, un produc ător este capabil să modifice
informațiile acesteia. Fiecare ofertă dispune de un buton pentru editare, care odată apăsat îl
conduce pe utilizator într -un formular similar celui de adăugare a unei oferte, însă cu datele
precompletate.
Utilizatorul va încheia editarea ofertei prin apăsarea butonului de salvare, care va activa
trimiterea cererii către aplicația server. Se vor trimite id-ul utilizatorului, datele noii oferte,
id-ul acesteia și token -ul utilizatorului. După efectuarea cere rii, utilizatorul va fi redirecționat
spre pagina de profil.
Aplicația server va intercepta cererea Http Put și o va atribui controler -ului
OfferController . Metoda updateOfferForUser are ca parametrii proveniți din structura URL –
ului id -ul utilizatorului și al ofertei, iar din corpul cererii primește noile informații ale ofertei.

Fig. 4.3 .4 Rezolvarea cererii de editare a unei oferte
4.3.3 Ștergerea unei oferte
Această funcționalitate nu dispune de o pagină specifică, fiecare ofertă având un buton
pentru a activa cererea de ștergere. În cadrul aplicației server cererea este captată și rezolvată
de metoda deleteOffer , din OfferController.
4.4 Implementarea funcționalităților specifice cumpărătorului
În subcapitolele următoare va fi descrisă modalitatea de implementare a serviciilor și
funcționalităților specifice tipului de utilizator : cumpărător.
4.4.1 Lista de oferte și adăugarea în coșul de cumpărătu ri
Accesând secțiunea oferte , utilizatorul va putea vizualiza toate ofertele existente.
Principala funcționalitate a acestei pagini o reprezintă afișarea ofertelor și posibilitatea
filtrării după categorie și ordonării acestora după preț sau cantitate, în funcție de preferințele
utilizatorului.
La accesarea paginii se va iniția o cerere de tip Get către aplicația server, care va aduce
toate ofertele existente în baza de date. Aceste oferte vor fi afișate în interfață utililzând
directiva *ngFor pentr u iterarea acestora și funcționalitatea de binding oferită de Angular .

38

Fig. 4.4 .1 Afișarea ofertelor
De asemenea, fiecărei oferte îi este asociat un câmp pentru introducerea cantității pe
care utilizatorul va dori să o achiziționeze și un buton pentru confirmarea adăugării acesteia
în coșul de cumpărături. Apăsarea acestui buton va iniția o cerere către aplicația server prin
care se va salv a opțiunea clientului , prin transmiterea id -ului utilizatorului, id -ul ofertei și
cantității dorite.

Fig.4.4 .2 Cererea de ad ăugare în coșul de cumpărături
Cererea este recepționată de către CommandsController și rezolvată de metoda
addCommandForUser. Adnotările cu care este decorată metoda prezintă structura URL -ului
cererii, din care se vor extrage valorile parametrilor și utilizatorii cărora le este permisp
accesarea metodei.

Fig.4.4 .3 Salvarea comenzii unui produs

4.4.2 Coșul de cumpărături și trimiterea comenzii
Pentru a accesa pagina specifiă coșului de cumpărături se va naviga la adresa
https ://localhost:8443 /mycart . În momentul accesării acestei pagini se va iniția o cerere de
tip Get către aplicația server, pentru a obține toate produsele salvate de cumpărător. Aceste
oferte vor fi afișate în interfață, în fișierul usercart.component.html al componentei usercart ,
utilizând directiva de iterare *ngFor .
Orice comandă a unui produs poate fi eliminată pe baza cereri Delete către aplicația
server, transmițând id -ul comenzii.

39

Fig. 4.4 .4 Cerere de ștergere a comenzii unui produs
Pentru a înregistra o comandă, utilizatorul va confirma prin apăsarea butonului de
înregistrar e a comenzii. Aplicația client va trimite o cerere către server care va modifica
starea comenzilor în baza de date, ele urmând a fi marcate ca înregistrate.

Fig. 4.4 .5 Modificarea stării comenzilor
4.4.3 Adăugarea comentariilor și oferirea ratingului
Pentru a putea adăuga comentarii unei oferte, cumpărătorul va trebui să acceseze pagina
de detalii a acesteia. La accesarea acestei pagini se va face o cerere către aplicația server,
pentru încărcarea tuturor comentariilor . Controleul CommentsController va prelua această
cerere, iar metoda getComments ForOffer va returna lista de entități de tip Comment .

Fig. 4.4 .6 Extragerea comentariilor din baza de date
Nota pentru un producător se va putea oferi din cadrul paginii de profil a acestuia,
folosind str ucturi input specifice html și stilizări oferite de bootstrap și css.

Fig. 4.4 .7 Structura sistemului de acordare a notei

40
Nota și id -ul utilizatorului pentru care se face notarea vor fi transmise prin cererea de
tip Put. În cadrul aplicației server, se va intercepta în controlerul UserController , în metoda
rateUser . În baza de date, nota se va adăuga la total , iar numărul de voturi va fi incrementat.

Fig. 4.4 .8 Actualizarea sistemului de notare în baza de date
Nota va fi calculată în momentul în care va apărea o cerere pentru afișarea profilului
producătorului în următorul mod : se verifică ca utilizatorul să aibă cel puțin o notă și se va
împărții totalul notelor la numărul total de voturi, rotunji nd la două zecimale .

4.4.4 Lista de favoriți
Cumpărătorul va putea adăuga un producător la lista de favoriți din cadrul profilului
acestuia, pentru a primi, de fiecare dată, cele mai noi oferte ale acestora.
Confirmarea adăugării unui producător la lista de favoriți se face prin intermediul
butonului de adăugare, care va trimite o cerere spre server, transmițând id -ul utilizatorului
curent și al celui care va fi adăugat.
Cererea este interceptată și rezolvată în controlerul UserFavouritesController, în
metoda addUserToF avourites . Aceasta apelează metoda addUserToFavourites din serviciul
UserFavouritesService, injectat de containerul Spring.

Fig. 4. 4.9 Salvarea unui producător ca favorit

41
5. Utilizarea aplicației
Primul pas pentru utilizarea sistemului este autentificarea în cadrul aplicației. Pentru
aceasta se vor introduce datele acestuia (email -ul și parola) pentru a fi verificate de sistem în
vederea autentificării.

Fig. 5.1 Pagina de autentificare
Odată ce utilizatorul este autentificat, va fi redirecționat către pagina principală a
aplicației, din care acesta poate alege una din opțiunile din bara de navigare. De asemenea,
utilizatorul poate alege să se deconecteze din aplicație, folosind opțiunea din partea dreapta
sus a paginii . În acest caz, utilizatorul va fi redirecționat la pagina de autentificare.

Fig. 5.2 Meniul principal al aplicației
Pentru un cumpărător, esențială este pagina de oferte. În cadrul acestei pagini,
utilizatorul va putea filtra și sorta ofertele pentru a găsi ceea ce caută. Acestuia îi va fi ușor să

42
achiziționeze produsele datorită comenzii rapide de adăugare în coșul de cumpărături (se
poate observa comanda de căpșuni).

Fig. 5.3 Pagina de oferte și adăugarea în coșul de cumpărături
Odată adăugate produsele în coșul de cumpărături se poate înainta comanda din cadrul
paginii acesteia. În cazul în care cumpărătorul a deci s să modifice cantitatea o va putea face și
din pagina coșului de cumpărături. Dacă utilizatorul decide că nu mai dorește comanda poate
face cerere ca aceasta să fie anulata.

Fig. 5.4 Înregistrarea sau retragerea unei comenzi

43
De asemena, de pe pagina ofertelor se va putea accesa individual pagina de detalii a
fiecărei oferte. Din cadrul acestei pagini, cumpărătorul va putea adăuga comentarii sau va
putea trimite un mesaj producătorului.

Fig. 5.5 Pagina de detalii ale unei oferte
Pagina de mesaje prezintă secțiunea în care sunt afișate toate mesajele primite și
trimise, iar în partea dreapta vor fi încărcate conversațiile dintre cei doi utilizatori.

Fig. 5.6 Citirea și trimiterea mesajelor
În cazul producătorului, acesta va putea adăuga o nouă o fertă din cadrul profilului
acestuia. Pagina specifică adăugării unei noi oferte prezintă un formular în care vor fi
completate datele acesteia.

44

Fig. 5.7 Adăugarea unei oferte
Pentru a putea transmite ideile , părerile sau recomandările lor, utilizatorii vor accesa pagina
de contact.

Fig. 5.8 Oferirea unei opinii

45
6. Concluzii și viitoare îmbunătățiri
6.1 Concluzii
În fiecare zi suntem acaparați de diferite activități care nu ne permit să păstr ăm o
nutriție echilibrată și să ne asigur ăm cantitatea zilnică de vitamine și minerale necesare. Pe
lângă factorul de timp, o altă problemă este reprezentată de ingredientele pe care le folosim
pentru prepararea hranei. Fie că sunt achiziționate de la supermarket sau uneori chiar din
piețele agricole, acestea prezintă un nivel ridicat de pesticide și substanțe care pot dăuna
organismului. De asemenea, prețul produselor naturale este mult ridicat datorită existenței
intermediarilor .
Aplicația FreshMarket este un sistem de comercializare a produselor naturale, ce
constă într -o aplicație web destinată atât producătorilor, prin funcționalități care îi ajută să își
expună produsele pe piață, cât și cumpărătorilor prin reducere a timpului petrecut pentru
achiziționarea ingredientelor și asigurarea prospețimii și calității produselor.
Aceste obiective au fost atinse prin : introducerea posibilității de creare a ofertelor
pentru diferite produse ale producătorului, organizarea în di ferite categorii ale ofertelor și
creare listei de favoriți și adpugarea producătorilor la aceasta pentru a reduce timpul de
căutarea al cumpărătorului, permiterea înregistrării de comenzi ale diferitelor produse și
implementarea sistemului de comunicare bazat pe mesaje în cadrul aplicației pentru a păstra
legătura dintre client și producător.
Această aplicație păstrează contactul cu utilizatorii permițându -le acestora să își
exprime opinia, idea de îmbunătățire sau nemulțumirea legată de aplicație.
Dezvol tarea acestui proiect a necesitate utilizarea multor cunoștințe practice și
teoretice dob ânite în facultate, cum ar fi: programarea orientată pe obiecte, folosirea
limbajului Java, baze de date, programare web. În plus au fost necesare acumularea unor
cuno ștințe noi și învățarea utilizării tehnologiilor noi, spre exempl ul framework -ul Spring,
Angular și Hibernate .
În concluzie, subiectul aceastei lucrări prezintă o idee de îmbunătățire a procesului de
achiziție a produselor și un ajutor oferit celor două categorii de utilizatori, avantajele putând
fi ușor observate.
6.2 Viitoare îmbunătățiri
Pe viitor, aplicația ar putea fi dezvoltată prin implementarea unui sistem de transport
al acestor produse, asemănător celui livrării de sortiment e de mâncare prin diverse companii
de livrare, astfel producătorul plătind o mică sumă care să suplinească acordul cu aceste
companii. Această funcționalitate ar necesita dezvoltarea unei aplicații mobile care să le
comunice transportatorilor comenzile pla sate. De asemenea, ar fi necesar o modalitate de
plată online sau de confirmare a plății, în cazul în care acesta se face la predarea comenzii.

46

47
7. Referințe

[1] (2019) World Wide Web [Online]
https://www.lifewire.com/history -of-world -wide -web-816583
[2] (2018) Uniform Resource Locator [Online]
http://www.sepoate.com/calculatoare/internet/index_9.php
[3] (2018) Hyper Text Transfer Protocol Secure [Online]
http://www.afahc.ro/ro/facultate/cursuri/retele_note_curs.pdf \
[4] (2018) Java [Online]
https://www.tutorialspoint.com/java/index.html
[5] (2017) Spring Framework [Online]
https://projects.spring.io/spring -framework/
[6] (2019) Spring Framework [Online]
https://www.edureka.co/blog/spring -tutorial/
[7] (2017) Spring Framework [Online]
https://en.wikipedia.org/wiki/Spring_Framework
[8] (2017) Java Persistence Api [Online]
https://en.wikibooks.org/wiki/Java_Persistence/What_is_JPA%3F
[9] (2018) Java Persistence Api Arhitecture [Online0
https://javabydeveloper.com/basic -terminology -to-know -before -coding/
[10] (2017) JPA Annotations Reference [Online]
http://www.datanucleus.org/products/datanucleus/jpa/annotations.html
[11] (2018) Java DataBase Connectivity [Online]
https://www.tutorialspoint.com/jdbc/
[12] (2019) Json Web Token [Online]
https://auth0.com/blog/implementing -jwt-authentication -on-spring -boot/
[13] (2019) Angular [Online]
https://angular.io/guide/architecture
[14] (2019) Angular Modules [Online]
https://angular.io/guide/architecture#modules
[15] (2019) Angular Routing [Online]
https://angular.io/guide/architecture#routing
[16] (2019) Angular Architecture [Online]
https://v2.angular.io/docs/ts/lates t/guide/architecture.html
[17] (2019) Angular – Spring Arhitecture [Online]
https://www.wavemaker.com/making -rad-good -for-developers/

48

49

DECLARAȚIE DE AUTENTICITATE A
LUCRĂRII DE FINALIZARE A STUDIILOR

Subsemnatul _____________________________________________________,
legitimat cu _______________seria ________nr. ________________________,
CNP _____________________autorul lucrării___________________________
________________________________________________________________
________________________________________________________________
elaborată în vederea susținerii examenului de finalizare a studiilor de licență
_______________________________________________ _________________
organizat de către Facultatea de Automatică și Calculatoare din cadrul
Universității Politehnica Timișoara, sesiunea ____________________ a anului
universitar________________________, luând în considerare conținutul art. 39
din RODPI – UPT , declar pe proprie răspundere, că această lucrare este
rezultatul propriei activități intelectuale, nu conține porțiuni plagiate, iar sursele
bibliografice au fost folosite cu respectarea legislației române și a convențiilor
internaționale privind dreptur ile de autor.

Timișoara,
Data Semnătura

_______________________ ______________________________
Declarația se completează „ de mână ” și se inserează în lucrarea de finalizare a studiilor, la sfârșitul acesteia, ca parte
integrantă.

Similar Posts