Sunteți pe pagina 1din 39

UNIVERSITATEA „ALEXANDRU IOAN CUZA” IAŞI

FACULTATEA DE INFORMATICĂ

LUCRARE DE LICENŢĂ

Start2Travel

Travel Management System

propusă de

Tomniuc Andreea Iuliana

Sesiunea: Iunie, 2016

Coordonator ştiinţific

Asist. Dr. Vasile Alaiba


UNIVERSITATEA „ALEXANDRU IOAN CUZA” IAŞI

FACULTATEA DE INFORMATICĂ

Start2Travel

Travel Management System

Tomniuc Andreea Iuliana

Sesiunea: Iunie, 2016

Coordonator ştiinţific

Asist. Dr. Vasile Alaiba


DECLARAŢIE PRIVIND ORIGINALITATE ŞI RESPECTAREA

DREPTURILOR DE AUTOR

Prin prezenta declar că Lucrarea de licenţă cu titlul „Start2Travel – System


Management System” este scrisă de mine şi nu a mai fost prezentată niciodată la o altă
facultate sau instituţie de invăţământ superior din ţară sau străinătate. De asemenea,
declar că toate sursele utilizate, inclusiv cele preluate de pe Internet, sunt indicate in
lucrare, cu respectarea regulilor de evitare a plagiatului:

toate fragmentele de text reproduse exact, chiar şi in traducere proprie din altă
limbă, sunt scrise intre ghilimele şi deţin referinţa precisă a sursei;

reformularea in cuvinte proprii a textelor scrise de către alţi autori deţine


referinţa precisă;

codul sursă, imaginile etc. preluate din proiecte open-source sau alte surse sunt
utilizate cu respectarea drepturilor de autor şi deţin referinţe precise;

rezumarea ideilor altor autori precizează referinţa precisă la textul original.

Iaşi,

Absolvent Tomniuc Andreea Iuliana

_____________________
DECLARAŢIE DE CONSIMŢĂMÂNT

Prin prezenta declar că nu sunt de acord ca Lucrarea de licență cu titlul „


Start2Travel – System Management System”, codul sursă al programelor şi celelalte
conţinuturi (grafice, multimedia, date de test etc.) care insoţesc această lucrare să fie
utilizate in cadrul Facultăţii de Informatică.

De asemenea, nu sunt de acord ca Facultatea de Informatică de la Universitatea


„Alexandru Ioan Cuza” Iași să utilizeze, modifice, reproducă şi să distribuie in scopuri
necomerciale programele-calculator, format executabil şi sursă, realizate de mine in
cadrul prezentei lucrări de licenţă.

Iaşi,

Absolvent Tomniuc Andreea Iuliana

_______________
Cuprins

Introducere ...................................................................................................................... 1

I. Tehnologii ................................................................................................................... 3
A. Structura proiectului .............................................................................................. 6
B. Componente ........................................................................................................... 8

1. NgTable .............................................................................................................. 9
2. NgDialog .............................................................................................................. 10
3. File saver .......................................................................................................... 11
4. Moment............................................................................................................. 12
5. Angular loading spinner ................................................................................... 12
II. Arhitectura aplicației ................................................................................................ 13
A. Structura bazei de date ......................................................................................... 18
III. Structura aplicației în funcție de rol ....................................................................... 20
A. Rolul de Angajat .................................................................................................. 22

B. Rolul de Resurse umane....................................................................................... 23


C. Rolul de Manager de proiect ................................................................................ 25
D. Rolul de Asistent de birou ................................................................................... 28
E. Rolul de Finanţe................................................................................................... 31
IV. Concluzii ................................................................................................................ 33
V. Bibliografie .............................................................................................................. 34
Introducere

Având în vedere evoluția tehnologiei în domeniul informatic și dorința de


automatizare a proceselor în firmele de profil, a apărut necesitatea de a se dezvolta
diferite aplicații precum cele ce fac gestiunea delegațiilor dintr-o companie.

Tema curentă a fost propusă de către CENTRIC IT SOLUTIONS ROMANIA


și a fost dezvoltată într-o echipă de 5 dezvoltatori și un tester, pe perioada unui stagiu
cu scopul de a simula dezvoltarea unui proiect pentru producție și de a ne familiariza
cu modul de lucru AGILE.

Aplicația „Start2Travel” este construită să simuleze procesul de adăugare,


acceptare, ținere a evidenței tuturor călătoriilor și gestionarea diferitelor documente
necesare pentru a trimite un angajat într-o delegație. În organizarea oricărei firme de
IT se regăsesc diferite funcții precum: angajat, manager de proiect, asistent de birou,
resurse umane sau finanțe. Aplicația prezentă este construită pe aceste cinci roluri,
fiecare dintre acestea putând vizualiza doar partea din proces pentru care este
autorizat.

Responsabilitatea de adăugare a angajaților în baza de date, implicit în


aplicație, o are persoana din companie ce are rolul de resurse umane. Odată adăugați,
aceștia sunt disponibili pentru a fi asignați la o delegație și pot fi vizualizați în aplicație
de către toate rolurile.

O delegație nouă va trece prin mai multe stări. În primul pas este adăugată de
către managerul de proiect, în sistem. Următorul pas este ca asistentul de birou să
aleagă o listă cu zboruri disponibile pentru data și țara de destinație specificate de
manager, pentru ca acesta din urmă să aleagă și să aprobe cel mai potrivit zbor pentru
acea călătorie. După ce toate datele sunt disponibile, se pot descărca actele necesare
pentru departamentul de finanțe care vor fi automat completate cu datele delegației cât
și datele angajatului sau angajaților ce vor pleca.

Pentru toate acțiunile ce necesită atenția celor implicați în proces, se vor trimite
notificări prin email către utilizatorii vizați.
Motivaţia alegerii temei şi a modului de lucru

Datorită interesului propriu pentru metodologia AGILE de management al


proiectului în ingineria software, acest proiect a fost dezvoltat într-o echipă de 5
dezvoltatori și un tester, urmărind principii SCRUM unde s-a simulat procesul de
dezvoltare a unui proiect complet dintr-o companie.

Dintre cei 5 dezvoltatori, 4 erau responsabili cu partea de back-end și eu cu


partea de front-end. Pentru managementul codului sursă, versionare, managementul
cerințelor și a distribuțiilor, testare și raportarea bug1-urilor, s-a folosit TFS.2

Urmărind principiile SCRUM folosite în aplicarea metodologiei AGILE,


aplicația a fost împărțită pe module pentru a putea livra funcționalități finite la finalul
unei serii scurte de timp denumită și sprint. În cazul prezentat sprintul a avut o durată
de 2 săptămâni, acesta începând cu o întâlnire de planificare în care se stabilea ceea ce
urma să fie realizat pe parcursul sprintului, se setau ținte de atins și se faceau estimări
pentru fiecare sarcină de lucru disponibilă. Fiecare zi de lucru începea cu o întâlnire
denumită și stand-up sau scrum, în care fiecare membru prezenta echipei progresul
făcut, impedimentele întâlnite și la ce urma să lucreze.

Într-o echipă ce folosește această metodologie, cheia succesului este


comunicarea. Se păstrează frecvent contactul cu clientul pentru ca dorințele acestuia sa
ajungă la echipă în timp util pentru ca aceasta să adopte strategii și să realizeze in timp
util cerința. Pentru a păstra o comunicare eficientă între toți membrii implicați în acest
proces de dezvoltare, la finalul unui sprint avea loc o altă întâlnire numită și
retrospectivă, în care se discuta despre ce a mers bine, ce a mers greu și ce se poate
imbunătăți pentru ca procesul să fie cât mai corect, ușor și să aibă cele mai bune
rezultate.

1 Eroare in aplicație.
2 Team Foundation Server (Microsoft)
Impărțirea pe sprint-uri este un mare avantaj atât pentru echipă cât și pentru
clienții ce doresc un produs finit de cea mai bună calitate, deoarece erorile în
dezvoltare și în modul de lucru nu se vor propaga în viitor, aceastea putând fi raportate
și fixate imediat. Din punctul de vedere al echipei, aceasta se va concentra să producă
funcționalități mici, ceea ce previne pierderea concentrării sau pierderea motivației.

I. Tehnologii

Tehnologiile utilizate în elaborarea prezentului proiect, sunt:

- Servicii REST3: data layer (Entity Framework Code First), business layer
(CQRS4) şi service layer (ASP.NET Web API);

- SQL Server: folosit pentru gestionarea bazelor de date relaționale;

- AngularJS (v1.4.3) – bibliotecă de JavaScript utilă în crearea de aplicații


single-page (SPA) ce extinde meta-limbajul HTML prin crearea de tag-uri
proprii;

- HTML5 – limbaj de marcare utilizat pentru a crea scheletul de prezentare a


informaţiilor paginilor web afişate în navigator;

- CSS6 - standard pentru formatarea elementelor dintr-un document HTML ce


ajută la dezvoltarea conceptelor de webdesign.

Pentru proiectul de front-end am ales AngularJS deoarece este o bibliotecă


peste JavaScript cu limbaj flexibil, concepte ușoare de înțeles și cel mai important,
independent de platforma pe care rulează, fapt pentru care aplicația prezentă poate fi
accesată și de pe tabletă. Un alt avantaj al acestei tehnologii este că aduce

3 Representational State Transfer – protocol de comunicare Client – Server.


4 Command Query Responsibility Segregation – pattern ce exprimă ideea că o metodă trebuie
ori să schimbe starea unui obiect ori să returneze un rezultat, dar nu trebuie să le facă pe
amândouă în același timp.
5 HyperText Markup Language.
6 Cascading Style Sheets.
funcționalitate nouă meta-limbajului HTML prin crearea de directive personalizate, cu
alte cuvinte permite inventarea de noi elemente sau atribute HTML.

Orice dezvoltator își dorește să scrie cod puțin, dar de calitate, iar acest lucru se
poate realiza folosind biblioteca în discuție, deoarece ea implementează eficient
conceptul MVC7. În timpul implementării dezvoltatorul nu trebuie să se preocupe de
legarea explicită a celor 3 componente.

Pentru interactivitarea paginilor s-a folosit un serviciu AngularJS ce simplifică


acțiunile uzuale precum get, post, delete sau update8. Acest modul se numește
Restangular şi permite lucrul cu promises9, cereri multiple de tip AJAX10 precum şi
înlănțuirea acestora pentru a permite ca o cerere să aștepte răspunsul alteia.

În comparație cu serviciile implicite $http și $resource ce vin odată cu


biblioteca, Restangular oferă servicii mai complexe, oferă suport pentru toate metodele
HTTP, este mai explicit, mai ușor de folosit și spre deosebire de $resource este
nevoie sa fie creată o singură dată, o instanță a obiectului de resurse Restangular.

În continuare va fi prezentat un bloc de cod ce reprezintă utilizarea serviciilor


Restangular, ce poate fi găsit în fișierul users.services.js la calea app/scripts/users.

1. function usersService(Restangular) {

2. var usersService = {};

3.

4. function getUsers() {

5. return Restangular.all('api/employees').customGET("");

6. };

7.

8. function getEmployeeById(employeeId) {

7 Mai mult MVVM spre MVW.


8 Acţiuni din protocolul HTTP.
9 Un promise este un concept prezent în JavaScript ce reprezintă eventualul rezultat al unei

operații. Acesta se poate folosi pentru a specifica ce urmează să se întâmple cand o operație
reușește sau cand nu.
10 Asynchronous JavaScript and XML.
9. return Restangular.one('/api/employees', employeeId).get();

10. };

11.

12. function putEmployee(employeeObject) {

13. return Restangular.one('api/employees').customPUT(employeeObject);

14. };

15.

16. function postEmployee(employeeObject) {

17. return Restangular.all('api/employees').post(employeeObject);

18. };

19. usersService = {

20. guid: generateUUID,

21. getUsers: getUsers,

22. getEmployeeById: getEmployeeById,

23. putEmployee: putEmployee,

24. postEmployee: postEmployee

25. };

26.

27. return usersService;

Motivul folosirii tehnicii de programare AJAX a venit din dorința de a face


paginile să se încarce mai rapid, să fie mai ușor de utilizat şi mai interactive pentru
utilizatori. Acest lucru se realizează prin actualizarea unor date în fundal şi schimbarea
unor porțiuni mai mici din pagină, ce utilizează implicit cantități mai mici de date în
comunicarea cu serverul.

O altă bibliotecă folosită în prezenta aplicație este UI-Router ce permite rutarea


aplicațiilor de tip single-page. Aceasta actualizează URL-ul din navigator în timp ce
utilizatorul navigheaza prin aplicație. Prin comparație cu modulul implicit de rutare
din AngularJS ( NgRoute ), UI-Router este mult mai puternic și mai complex, acesta
cuprinzând tot ce conține NgRoute plus multe alte funcții extra.
UI-Router suportă imbricarea view-urilor, lucru foarte util în aplicațiile foarte
mari unde se pot regăsi pagini ce sunt moștenite din alte secțiuni. Acesta mai are și
conceptul de decorator, ce poate fi folosit pentru a permite rutelor să fie create
dinamic în funcție de url-ul care se încearcă a fi accesat.

Stările permit maparea și accesarea informațiilor despre diferitele stări, seturi de


date fiind ușor de transmis de la o stare spre alta prin intermediul lui $stateParams.

1. .state('main.delegationsByName.add-del', {

2. url: '/add-del/:id',

3. controller: 'delegationsByNameAddController',

4. controllerAs: 'vm'

5. });

În cazul prezentat anterior, pe starea main.delegationsByName.add-del


avem parametrul de stare :id ce poate fi accesat ulterior în controller prin injectarea
lui $stateParams și accesarea id-ului prin $stateParams.id.

A. Structura proiectului

Aplicația “Start2Travel” este compusă din partea ce conține serviciile şi partea


responsabilă cu interfața către utilizator. Pentru generarea proiectului pe partea de
client s-a folosit generatorul Yeoman11 ce oferă accesul rapid la o structură completă a
unui proiect Angular și care odată cu crearea acestuia impune anumite practici de
urmat. Generatorul poate fi folosit și pentru a genera diferite componente precum
controllere, servicii, directive sau filtre.

11 http://yeoman.io/
În proiectul prezentat s-a mai folosit și GruntJS12 – un tool pentru
automatizarea sarcinilor precum: minificarea codului, rularea locală a aplicației,
crearea unei distribuții sau personalizarea precum și adăugarea unor noi sarcini dorite
de utilizator precum: copierea de fișiere ce provin din surse externe, crearea de
distribuții pentru diferite platforme, etc.

Pentru partea de client, se remarcă următoarea structură de foldere /fișiere:


- app: folderul ce conține codul sursa pentru aplicația prezentată. În acest folder
se găsesc imaginile folosite în proiect, librariile externe, scripturile ce conferă
funcționalitatea şi structura (HTML), stilurile folosite pentru crearea interfeței
şi fișierul index.html. Structura acestui folder va fi detaliată într-un capitol
ulterior;

- bower-components: folderul ce conține toate pachetele instalate prin


intermediul tool-ului Bower, ce face managementul tuturor bibliotecilor și
directivelor adăugate în aplicație;

- node-modules: folderul ce conține toate pachetele instalate cu npm, folosite de


aplicație;

- bower.json: este fișierul de configurare pentru managerul de pachete. În el vom


găsi numele modulelor instalate şi versiunile acestora.

- Gruntfile.js: este fișierul de configurare al tool-ului de automatizare a


sarcinilor. În acest fișier se pot adăuga sarcini noi ce doresc a fi utilizate în
proiect, se poate modifica portul de pe care va rula local aplicația, se pot
modifica sau adăuga diferite sarcini de creare a unei distribuții, etc;

- package.json: este fișierul de configurare pentru pachetele instalate cu Node.

12 http://gruntjs.com/
B. Componente

În aplicația “Start2Travel” au fost folosite o serie de componente, directive


pentru diferite functionalități. Motivul alegerii integrării acestor componente externe
este acela de a face codul reutilizabil şi de a scurta timpul de implementare.

Unele companii au decis să işi creeze propriile componente pentru un set de


funcționalități uzuale, pe care le folosesc în diferitele proiecte care le produc, cu
scopul de a reduce timpul de a reimplementa de fiecare dată acelaşi set de
functionalități. Acestea sunt create după un style-guide13 strict, pentru a preveni
apariția erorilor în timp şi pentru a se păstra o consistență în scrierea codului, ceea ce îl
va face ușor de înțeles pentru viitorii dezvoltatori. După o testare amănunțită, acestea
se pot reutiliza în diferite aplicații, dacă cerințele permit integrarea lor.

Crearea unor noi funcționalități poate genera o serie de erori în gândire, ceea ce
necesită testare amănunțită, deci implicit resurse consumate. Atunci când resursele nu
ne permit reimplementarea unei funcționalități probabil existente, soluția cea mai bună
este să căutăm o componentă open-source pe care să o putem folosi cu încredere,
aceasta de obicei fiind testată de către cei ce au oferit codul sau de către alți utilizatori
care au raportat problemele găsite.

O componentă cu multe accesări şi pentru care se oferă suport semnalează că


este o alegere bună. După ce integrarea s-a făcut şi aceasta este disponibilă pentru ca
dezvoltatorul să o testeze şi să decidă dacă îndeplinește toate cerințele dorite, se poate
hotarî copierea ei în proiect pentru a nu mai depinde de serverul care o servește14. De
asemenea se recomandă folosirea unor tool-uri de descărcare a componentelor precum
bower sau npm, în locul integrării prin cdn15 ce poate încetini aplicația datorită
așteptării unui răspuns din partea serverului pe care îl contacteaza.

13 Sau coding style-guide – set de reguli pentru anumite tehnologii ce prezintă un standard
sau cea mai bună abordare pe anumite teme
14 Lucru recomandat a se face înainte de a lansa produsul în producție. În timpul dezvoltării

vor apărea frecvent modificări a unor versiuni sau chiar a componentelor.


15 Content Delivery Network - reprezintă un sistem de servere ce conţin copii ale datelor

plasate la diferite noduri ale unei reţele. Nodurile rețelei conlucreaza pentru a satisface rapid
și eficient cererile de conținut Web ale utilizatorilor
În continuare se vor prezenta pe scurt câteva dintre componentele folosite în
implementarea aplicației prezentate. Acestea au fost integrate cu bower al cărui avantaj
este că avem fișierul de configurare cu toate modulele adăugate în proiect, prin urmare
este necesar să avem pe TFS doar acest fișier, nu tot folderul ce conține codul sursa a
tututor componentelor. Atunci când un alt dezvoltator va prelua proiectul local, acesta
va trebui doar să ruleze comanda bower install16 ce îi va aduce automat toate pachetele
dependință a proiectului. La fel se va proceda şi pentru modulele dependință pentru
Node17.

1. NgTable

Este o directivă ce implementează un tabel simplist dar cu funcționalități de


sortare, paginare, filtrare sau grupare ce au facut parte din funcționalitățile cerință a
aplicației. Capetele de tabel şi filtrele se generează automat la compilare.

Inițializarea unui tabel de acest tip se face ca în exemplul ce urmează:

1. $scope.tableParams = new NgTableParams({

2. page: 1,

3. count: 5,

4. }, {

5. counts: [5, 10, 25, 50],

6. total: vm.users.length,

7. getData: function ($defer, params) {

8. // se aduc date ce vor fi folosite în tabel

9. // se pot implementa reguli pentru validare

10. $defer.resolve(users);

11. }

12. }

13. });

16 Se va deschide cmd-ul în folderul în care se regăsește proiectul si se rulează comanda.


17 Se va rula în cmd comanda npm install.
Opțiunea count reprezintă numărul inițial de elemente pe pagină, utilizatorul
putând seta din interfață opțiunea preferată. Acest lucru este specificat programatic în
proprietatea counts ce primește un tablou de elemente cu valorile dorite. Se înmâneaza
lui NgTableParams o funcție ce va fi chemată sa aducă date pentru tabel. În interiorul
acestei funcții se pot structura datele în forma dorită.

2. NgDialog
NgDialog este o componentă ce furnizează dialoguri şi ferestre de tip pop-up
pentru aplicații AngularJS, aceasta fiind singura dependință a modulului.

1. function usersAddController($scope, $state, $location, ngDialog,


2. usersService) {
3. var dialog = ngDialog.open({
4. className: 'ngdialog-theme-default custom-adduser-width',
5. closeByDocument: false,
6. templateUrl: 'scripts/users/users.add.html',
7. controller: /*@ngInject*/

8. function Ctrl($scope, $state, $cookies, usersService) {


9. /*se manipuleaza datele si se adauga functionalitati pentru modal*/
10. });
11. dialog.closePromise.then(function() {
12. $state.go("^", {}, {
13. reload: true
14. });
15. });
16. };

Pentru a deschide un dialog se folosește funcția ngDialog.open() şi cu


ajutorul anumitor proprietăți se pot adăuga clase personalizate pentru dialogul creat.
De asemenea se specifică template-ul , controllerul şi se poate specifica dacă se
dorește ca dialogul să poată fi închis atunci când se dă click în afara lui.
Componenta prezentată poate avea de asemenea proprietatea resolve ce va aduce
datele necesare pentru dialog şi previne deschiderea aceastuia pana în momentul în
care datele au fost aduse cu succes.

dialog.closePromise este un promise ce va fi rezolvat atunci cand dialogul

este închis, iar în acest caz se redirecționează către starea (ruta) precedenta şi se
reactualizează datele pentru starea respectivă.

În mod implicit modulul NgDialog este servit cu directiva ngDialog, care poate
fi utilizată ca atribut pentru butoane sau link-uri ca în următorul exemplu:

1. <button type="button"
2. ng-dialog="templateId.html”
3. ng-dialog-class="ngdialog-theme-flat"
4. ng-dialog-controller="ModalCtrl"
5. ng-dialog-close-previous>
6. Open modal text
7. </button>

3. File saver

Angular File Saver este un serviciu AngularJS ce folosește FileSaver.js şi


Blob.js pentru a implementa interfața HTML5 W3C18 SaveAs(), în navigatoarele care
nu oferă suport nativ. În aplicația “Start2Travel” această funcționalitate a fost necesară
pentru ca utilizatorii cu rolurile resurse umane şi finanţe să poate descărca rapoarte
autocompletate sau acte adiționale necesare angajaților ce pleacă într-o delegație.

1. $scope.additionalpaper = function () {
2. var blob = new Blob([AdditionalPaper], {
3. type:'application/vnd.openxmlformats-
officedocument.wordprocessingml.document'
4. });

18World Wide Web Consortium – consorțiu internațional care are ca scop dezvoltarea de
standarde pentru Worl Wide Web
5. var filename = "additionalpaper.docx"
6. saveAs(blob, filename);
7. };

4. Moment

Este o bibliotecă folosită pentru parsarea, validarea, manipularea sau afișarea


datelor în JavaScript. Pentru formatarea datelor se folosește funcția format() ca în
exemplul următor:

1. moment().format('MMMM Do YYYY, h:mm:ss a');

Formatarea se poate face şi direct din view:

1. <td class="rowTd" data-title="'Hired date'" sortable="'HiredDate'"


2. filter="{ 'HiredDate': 'HiredDate' }">
3. {{user.HiredDate | moment:'DD.MM.YYYY'}}
4. </td>

5. Angular loading spinner

Angular-loading-spinner este o directivă AngularJS ce detecteaza toate cererile


de tip AJAX şi afișează un spinner în timpul încărcării lor. Directiva se folosește ca în
exemplul ce urmează și va produce un rezultat precum cel prezentat în Figura 1:

1. <span us-spinner="{radius:40, width:8, length: 16, color: '#339933',


2. lines: 15}" spinner-key="spinner-1">
3. </span>
Figura 1. Loader

II. Arhitectura aplicației

Cele două proiecte prezintă arhitecturi diferite. Partea de back-end


implementează CQRS pentru decuplarea modulelor și faciltarea creării de unit teste, pe
când partea de front-end implementează MVW19. Motivul alegerii acestui model
arhitectural este că prevede separarea preocupărilor, este rezistent la schimbări, un cod
fragil putând cauza probleme de întreținere pe termen lung. O separare clară între
logica aplicației şi interfața de utilizare permite ca dezvoltarea, întreținerea şi testarea
să fie mai facilă şi totodată îmbunătățește reutilizarea codului şi permite fluxul de
lucru între dezvoltator şi designer.

O perioadă de timp Angular a fost mai aproape de MVVM, decat de MVC,


obiectul $scope putând fi considerat a fi componenta ViewModel, ce este decorat de o
funcție numită Controller.

19 Model-view-whatever
preNav.directive.js

1. function preNavCtrl($scope) {

2. $scope.userRole = $cookies.get('role');

3. //continuarea funcționalității

4. };

preNav.template.html

1. <div class="user-container">

2. <span id="logged-user">{{userRole}}</span>

3. </div>

Prin exemplul dat se poate observa că atașarea obiectului userRole la $scope, îl


face pe acesta vizibil în view, iar pentru afișarea conținutului modelului se utilizează
acoladele duble. Acest fenomen se numește şi data binding20 şi se poate realiza şi prin
atașarea directivei ng-model la un element HTML.

În modelul MVW se disting 3 componente de bază denumite: Model, View şi


Whatever – ce poate fi reprezentat de controllere, directive sau unit teste, după cum se
poate observa in Figura 2. Asemănarea cu MVC este vizibilă, unde Controller-ul a fost
înlocuit cu o nouă componentă denumită Whatever. Comunicarea dintre View şi
Whatever se face prin data binding21.

20 Legarea modelului de view.


21 Asocierea datelor dintre controller si template.
Figura 2. Schema MVW22

Un plus al tehnologiei alese (AngularJS) este că permite lucrul cu


directive/componente şi impărțirea pe module. Continuând această practică am ales
împărțirea pe module independente a aplicației. Dacă se dorește înlăturarea unui modul
– a unei funcționalități – al aplicației, aceasta va continua să funcționeze, chiar dacă
fluxul de lucru va fi afectat.

Model-View-Whatever - http://www.edureka.co/blog/angularjs-superheroic-javascript-
22

mvw-framework
Structura arborescentă a folderului app este următoarea:

Figura 3. Structura de foldere

Un modul are structura prezentată în Figura 4.

Figura 4. Structura unui modul


Modulul dat ca exemplu este compus dintr-un fișier manager, ce conține
depedințele spre celelalte module precum service, controller și o funcție de
configurare în care se specifică rutarea pentru acel modul, controller-ul responsabil și
template-ul.

O altă facilitate a modulului de rutare UI-Router o reprezintă proprietatea


resolve ce furnizează date specifice stării, ce vor fi injectate pentru fi utilizate în
controller.

Dacă dependințele injectate sunt promises, acestea vor fi rezolvate înainte de a


se instanția controllerul și evenimentul $stateChangeSuccess va fi declanșat.
Folosirea acestei proprietăți previne încărcarea view-ului înainte ca toate datele
necesare să fie aduse sau în cazul apariției unor erori, lucruri ce pot confuza
utilizatorul.

1./*Numele modulului ce va fi inclus ca şi depedință la modulul aplicației,

2. în fisierul app.js*/

3. angular.module('travelingApp.configuration.configurationManager',

4. ['travelingApp.configuration.service', //module dependente

5. 'travelingApp.configuration.controller'])

6. .config(function($stateProvider) {

7. $stateProvider.state('main.config', {

8. url: 'config',

9. controller: 'configurationController',

10. templateUrl: 'scripts/configuration/configuration.view.html',

11. resolve: {

12. /*Se injectează employees în controller pentru a putea

13. ultiliza obiectul*/

14. employees: function(usersService) {

15. return usersService.getUsers().then(function(results) {

16. return results;

17. });
18. },

19. /*Se injectează roles în controller pentru a putea

20. ultiliza obiectul*/

21. roles: function(configurationService) {

22. return configurationService.getRoles()

23. .then(function(results) {

24. return results;

25. });

26. },

27. /*Se injectează locations în controller pentru a putea

28. ultiliza obiectul*/

29. locations: function(configurationService) {

30. return configurationService.getLocations()

31. .then(function(results) {

32. return results;

33. });

34. }

35. }

36. });

37. });

A. Structura bazei de date

Baza de date este structurată în 8 tabele legate între ele după cum este prezentat
în Figura 5. Datele primite de la utilizator sunt stocate folosind SQL Server.

SQL Server este un produs Microsoft ce folosește o variantă de SQL numită


Transact-SQL, folosită pentru gestionarea bazelor de date relaționale.
Figura 5. Schema bazei de date

Despre relațiile dintre tabele putem specifica faptul ca între: Employees și


Roles, Delegations și States, Cities și Countries se observă o relație teoretică de tipul
one to one ceea ce înseamnă că un angajat poate avea un singur rol, o delegație poate
avea o singură stare și un oraș poate fi asignat unei singure țări. Cu toate acestea, în
SQL Server este imposibil din punct de vedere tehnic să se creeze o relație pură de
tipul one to one, ci doar one to many. Privind relațiile din sensul opus, un rol poate fi
asignat mai multor angajați, o stare poate fi definită pentru mai multe delegații, o țară
poate conține mai multe orașe, etc.
III. Structura aplicației în funcție de rol
La pagina Login au acces toți utilizatorii, dar aceștia se pot autentifica doar
după ce au fost introduși în sistem și o parolă implicită le este generată. După fiecare
adăugare în sistem, o notificare prin email va fi trimisă către noul utilizator, unde i se
aduce la cunoștință că a fost adăugat în aplicație și va fi rugat să modifice parola
implicită data de către server.

La autentificare, sistemul verifică datele introduse, iar utilizatorului i se


permite accesul în aplicație. Pentru utilizatorul autentificat se generează un token, cu
un timp de expirare, care este salvat într-un cookie alături de alte date pentru a putea fi
folosite în aplicație ulterior, precum: rolul utilizatorului logat, id-ul și numele acestuia.
Pentru implementarea autorizării s-a folosit protocolul OAuth 2.023.

În cazul în care sesiunea expiră sau utilizatorul încearcă să acceseze un url din
interiorul aplicației, fără ca acesta să fie logat, va fi redirecționat automat către pagina
Login. De asemenea s-a implementat și autorizarea pe cererile către server, ceea ce
înseamnă că pentru a putea primi răspuns de la server pe o anumită cerere, trebuie ca
utilizatorul să aibă rolul potrivit24.

Stabilirea autorizării se face pe o stare25 abstractă. Motivul folosirii unei astfel


de stări este pentru a ascunde o rută de utilizatori, aceasta fiind chemată atunci cand o
stare copil este încărcată. Un alt motiv ar fi definirea unor elemente din pagină fara ca
utilizatorul să fie conștient de asta. Acest lucru este posibil în modulul ales UI-Router,
spre deosebire de modulul implicit de routare oferit de Angular, NgRoute.

1. $stateProvider.state('main', {

2. url: '/',

3. abstract: true,

4. resolve: {

5. resolveUser: resolveUser,

23 Biblioteca de autorizare permite o autorizare sigură intre client și server.


24 Rolul trebuie să fie în lista de autorizare pentru acea cerere.
25 ruta
6. setServiceHeaderAuthorization:setServiceHeaderAuthorization

7. },

8. template: '<div ui-view></div>'

9. });

În campul Username se pot introduce doar numere, litere şi caracterele speciale


ce se regăsesc în componența unei adrese de email. Câmpul Password permite
introducerea unei parole cu lungimea cuprinsă între 4 şi 30 de caractere. Orice
încălcare a regulilor de validare va fi semnalată utilizatorului prin mesaje explicite sub
câmpurile în care s-au introdus datele invalide. De asemenea butonul Login devine
inaccesibil în momentul în care o eroare este afișată.

Figura 6. Erori la validare

Pentru a încheia o sesiune este disponibilă funcționalitatea de Logout ce va


șterge datele din Cookies, printre care și tokenul utilizatorului, iar acesta va fi
redirecționat automat către pagina Login.

1. $scope.logout = function() {

2. var userCookies = $cookies.getAll();


3. angular.forEach(userCookies, function(v, k) {

4. $cookies.remove(k);

5. $state.go('login');

6. });

7. };

A. Rolul de Angajat
Un angajat al companiei va avea acces la aplicație abia după ce a fost introdus
în sistem. După introducere, acestuia i se genereaza o parolă de start cu care se poate
autentifica pentru prima dată in aplicație. După prima accesare a aplicației i se
recomandă schimbarea parolei, acest lucru fiind posibil dacă acesta va face click pe
numele său, lucru care duce la deschiderea unui dialog precum cel prezentat în Figura
7, de unde utilizatorul își poate modifica parola contului.

Figura 7. Schimbarea parolei

Acest rol poate vizualiza tabela de angajați, de angajați asignați unei delegații și
tabela de delegații curente sau trecute, dar nu are dreptul de a modifica, șterge sau
adăuga în tabelele precizate.
De asemenea datele cu caracter special, precum cnp-ul, adresa de email a altui angajat
sau actele disponibile completate, vor fi ascunse de acesta,.

Angajatul care este introdus în sistem, va fi notificat prin email despre orice
modificare survenită în delegația curentă şi poate să urmărească starea în care este
delegația lui, în pagina Delegations by name, în coloana intitulată Status, după cum se
poate observa în Figura 8.

Figura 8. Tabela cu delegații și statusul acestora

B. Rolul de Resurse umane


Acest rol este responsabil cu adăugarea şi editarea datelor despre angajații
companiei ce se face în dialogul Employees personal data, prezentat în Figura 9. După
ce un nou angajat este adăugat acesta poate fi editat, în cazul în care apar modificări
asupra lui sau se pot completa date aditionale despre acesta - precum data angajării,
data concedierii şi datele primei delegații -acolo unde este cazul.

Validările de pe acest formular se regăsesc pe toate campurile mai putin pe data


angajării. Restul de informații sunt obligatorii, adresa de email trebuie să aibă formatul
corespunzător, iar data de angajare nu trebuie să fie după data de demisie. Acest lucru
este blocat în interfață, utilizatorul neputând alege o dată de demisie anterioara celei de
angajare.

Figura 9. Editarea unui angajat

Dacă angajatul nu a plecat în nici o delegație, câmpul First delegation between


va fi lăsat necompletat, acesta fiind actualizat automat în momentul în care o delegație
pe numele angajatului va fi adăugată în sistem de către managerul de proiect. Este
important să se rețină dacă angajatul este la prima calatorie, deoarece un act adițional
va fi completat pentru acesta.

Pe pagina Delegations employees rolul de resurse umane are şi drept de editare


a datelor unui angajat asignat unei delegații, lucru care este posibil în dialogul Edit
employees delegation details, prezentat în Figura 10. Aici se poate seta câmpul Is first
leave ce atenționează sistemul şi celelalte roluri că un act adițional va trebui conpletat
pentru angajatul respectiv şi se pot modifica datele de plecare sau de întoarcere.
Numele delegației va putea fi modificat pe pagina Delegtion by name deoarece cele
două pagini reprezintă o grupare diferită a călătoriilor, în funcție de delegație şi în
funcție de angajat.
Figura 10. Editarea datelor unei delegații pentru un angajat

Pe pagina Delegations by name acest rol poate doar vizualiza detaliile unei
delegații.

C. Rolul de Manager de proiect


Utilizatorii cu rolul de Manager au și ei posibilitatea de a modifica datele
personale ale unui angajat și implicit drepturi de a vizualiza datele cu caracter special
ale acestora, dar nu au dreptul de a adăuga angajați noi în sistem.

Pe pagina Delegations employees acesta poate vizualiza angajații ce au plecat


sau vor pleca în delegații și poate căuta printre aceștia.

După cum a fost precizat anterior, Managerul este acel tip de utilizator ce poate
adăuga o delegație nouă în sistem după cum arată Figura 11.
Figura 11. Adăugarea unei noi delegații

Se cere introducerea angajatului sau angajaților ce urmează să plece, data de


început a delegației și cea de sfârșit, țara și orașul de destinație, numele și scopul
călătoriei, iar în final trebuie să se aleagă opțiunea potrivită pentru a informa sistemul
și celelalte roluri dacă se cere completarea de acte adiționale pentru delegația curentă.
Opțiunile pentru câmpul Addendum sunt: Mandatory for all – se informează
utilizatorul cu rolul resurse umane că trebuie completate acte adiționale pentru toți
angajații ce pleacă în delegație, deoarece delegația este una specială26, None for all –
informează același rol că nici un act adițional nu urmează a fi completat și Depends on
employee - informează că echipa ce pleacă în deplasare este un mixtă, iar actele
adiționale trebuie completate doar pentru anumiți angajați.

După ce datele au fost trimise către server, o notificare prin email va fi trimisă
către toți angajații ce vor participa la delegația adăugată, iar delegația primeste statusul
New.

26 Angajatul pleacă de urgentă cu un zbor scump sau pleacă în alte circumstanțe speciale.
O altă acțiune disponibilă pentru acest rol este de alegere a zborurilor adăugate
de Asistentul de birou pentru delegațiile cu statusul New. Pentru ca o delegație să aibă
disponibilă opțiunea Choose flights, ea trebuie să fie în starea Pending. După ce un
zbor a fost ales, Managerul completează numele hotelului și pretul pe noapte pentru
cazarea angajaților ce vor pleca în delegația respectivă. Aceste date sunt importante
deoarece vor apărea în raportul financiar descărcat de către utilizatorul cu rolul
Finanțe. În acest pas delegația a fost aprobată și toți angajații implicați în acest proces
vor primi câte o notificare prin email.

Orice delegație poate fi ștearsă, dar această acțiune poate fi realizată doar de
către un utilizator ce are rolul de Manager. O delegație care are orice alt status mai
puțin Cancelled poate fi modificată. Din diferite motive un angajat poate pleca mai
târziu sau poate să nu mai plece deloc, iar atunci se modifică datele corespunzător în
sistem pentru a ține evidența într-un mod corect.

Pentru acest rol este disponibilă pagina de configurări de unde managerul poate
schimba sau seta rolul unui utilizator (Figura 12) și adăuga sau șterge țări și orașe din
sistem (Figura 13).

Figura 12. Schimbarea rolului unui utilizator


În secțiunea Administrative roles se aduc în partea stângă toți angajații ce nu au
rolul de simplu angajat, iar cei cu un rol diferit de acesta vor apărea în partea dreaptă a
paginii. Pentru a modifica rolul unui angajat, utilizatorul trebuie să facă click pe
numele acestuia pentru a îl aduce în partea dreapta, unde i se va modifica rolul. Pentru
a se revoca un rol special pentru o persoana, este îndeajuns să i se seteze rolul de
simplu angajat, iar acesta se va întoarce în tabela de angajați.

Figura 13. Adăugarea și modificarea țărilor și a orașelor

La încercarea adăugarii unui oraș sau a unei țări deja existente în sistem, se va
genera o eroare, deoarece acestea nu pot fi duplicate.

D. Rolul de Asistent de birou

Responsabilitatea utilizatorului cu rolul de Asistent de birou27 este doar de a


căuta o lista cu zboruri disponibile pentru delegațiile adăugate noi și de a introduce
aceste zboruri în sistem pentru ca Managerul să aleagă și să aprobe varianta cea mai
buna.

27 eng. Office Assistant


Opțiunea Add flights va fi disponibilă automat pentru delegațiile ce au statusul
New și va deschide un dialog (Figura 14) unde se vor introduce date despre variantele
de zbor găsite pentru delegație.

Figura 14. Adăugarea zborurilor

Se vor completa: ruta de plecare, ruta de întoarcere și via (unde este cazul),
informații despre zbor, prețul și comentarii dacă sunt necesare. Câmpul Info permite
introducerea de date în format rich-text după cum este prezentat în Figura 14.

Această funcționalitate a fost furnizată de către componenta ngWYSIWYG28 ce a


fost inclusă în folderul libs pentru a evita suprascrierea modificărilor făcute în această
componentă. Aceste modificări presupun validarea pentru rich-text editor. Nefiind o
componentă clasică HTML, aceasta nu a putut fi validat adăugând atributul required.

28 What You See Is What You Get – Angular rich text editor.
Figura 15. Rich text editor

Dupa ce s-au adăugat mai multe opțiuni, acestea trebuie salvate, iar statusul
delegației va fi schimbat din New în Pending și opțiunea Add flights va fi înlocuită de
Edit flights. Starea Pending reprezintă că delegația asteaptă aprobarea Managerului
pentru a trece în starea Approved. O dată ajunsă în această stare nu se mai pot modifica
detaliile zborurilor sau a delegației ci doar se pot vizualiza (Figura 16).

Figura 16. Vizualizarea detaliilor unei delegaţii aprobate


E. Rolul de Finanţe
Utilizatorii cu acest rol au posibilitatea de a descărca rapoarte financiare pentru
angajații care sunt asignați unei delegații. Acest lucru este posibil în pagina
Delegations employees după cum este prezentat în Figura 17.

Figura 17. Descărcarea unui raport financiar

Salvarea datelor în format .xlsx29 se face cu ajutorul serviciului File Saver, care
a fost prezentat în subcapitolul I.A 3. File saver. Pentru salvarea în discuție, s-a
implementat funcţia următoare:

1. $scope.DownloadXlsx = function (userId) {

2. delegationsEmployeesService.getFinancialReportById(userId)

3. .then(function (results) {

4. $scope.FinancialResultMS = results;

29 Format Excel.
5. });

6. $timeout(function () {

7. var blob = new Blob([$scope.FinancialResultMS], {

8.type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

9. });

10. var filename = "FinancialReport.xlsx";

11. saveAs((blob), filename);

12. }, 1000);

13. };
Concluzii
La finalizarea acestei lucrări - atât partea teoretică cât și cea pratica - îmi
doream să îmi dau seamă de evoluția mea din punct de vedere tehnic, lucru care s-a și
întâmplat. În ciuda faptului că la momentul implementării aplicației am simțit că
provocarea este mare și că îmi va fi greu cu modul de lucru ales, odată cu trecerea
timpului și datorită implicării am reușit să mă integrez și să mă dezvolt pe domeniul
ales.

Privind în urmă consider că am făcut o alegere bună privind tehnologiile alese


ținând cont că acesta a fost un proiect de start pentru cariera mea, dar sunt conștientă
de îmbunătățirile ce pot fi aduse aplicației. Una dintre modificările pe care le-aș face ar
fi actualizarea versiunii de Angular la 1.5, apoi urmărirea strictă a unui style-guide30 și
crearea de directive31 acolo este posibil și util, pentru a preveni duplicarea codului și
manipulare DOM32.

Soluția aleasă pentru problema dată este una cu care se confruntă orice
instituţie, prin urmare acest sistem ar putea fi folosit în diferite firme, extins sau
adaptat pentru a se potrivi regulilor interne și organizatorice. Transpunerea unui proces
complex într-o sarcină automată poate deschide interesul pentru automatizarea unor
procese greoaie din viața de zi cu zi.

30 https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
31 Denumite componente în Angular 1.5
32 Document Object Model
Bibliografie

[1]. Dan Wahlin. AngularJS in 60 Minutes


[2]. Jon Duckett. HTML and CSS: Design and Build Websites
[3]. Angular docs.
https://docs.angularjs.org/guide/
[4]. NgTable doc.
https://github.com/esvit/ng-table
[5]. UI-Router doc.
https://github.com/angular-ui/ui-router
[6]. MVVM pattern.
https://msdn.microsoft.com/en-us/library/hh848246.aspx
[7]. NgDialog.
https://github.com/likeastore/ngDialog
[8]. Moment.
http://momentjs.com/
[9]. Restangular article
http://www.ng-newsletter.com/posts/restangular.html

S-ar putea să vă placă și