Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor...

62

Transcript of Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor...

Page 1: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het
Page 2: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

0

1

2

2.1

3

3.1

3.2

3.3

3.4

3.5

3.6

3.7

3.8

4

5

6

6.1

7

Table of ContentsDankwoord

Introductie

Bespreking

Opdracht

Technologie

Database

Backend

Frontend

Aanmelden

Configuratiescherm

Indienen

Beheer

Pdf-viewer

Resultaten

Besluit

Bijlagen

Functionele Analyse

Bronnen

2

Page 3: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

DankwoordAllereerst willen we het bedrijf 'ABC-groep' bedanken die het voor ons mogelijk gemaakt heeft om bij hen stage telopen.

De bachelorproef tot een goed einde brengen was geen gemakkelijke opdracht. Hiervoor hebben we een goedebegeleiding gekregen van Geert Bellemans en Stefaan Van Goubergen. Geert heeft de opdracht bedacht en defunctionele analyse uitgewerkt waarop we ons project moesten baseren. Verder stonden Geert en Stefaan steedsbereid om ons te helpen wanneer dit nodig was en raad te geven wanneer ze een beter zicht hadden op de zakendan wij.Rob Van Looke willen we bedanken om ons hulp aan te bieden wanneer hijzelf op het bedrijf aanwezig was. Robheeft ons geholpen om de Tomcat server op te zetten zodat we deze lokaal konden gebruiken. Verder heeft Rob decode ook gereviewed die we reeds hadden geschreven zodat deze kwalitatief verbeterd kon worden.Verder willen we onze ouders en naaste vrienden nog bedanken om onze scriptie na te lezen en feedback te geven.

Rijkevorsel, 8 juni 2016 Bart Kerstens & Ziggy Streulens

3

Page 4: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Situering

Het bedrijf: ABC-groepABC-groep is een IT-consultancy bedrijf gelegen in Kalmthout dat bestaat uit vier kleinere groepen. Deze groepenbehandelen ieder hun eigen technologieën, deze groepen zijn:

ACE voor Microsoft .NETBeyond-it voor Microsoft SharePointCereus voor Oracle en JavaDynApps voor Odoo en BI

De OpdrachtProbleemstelling van de klant

Het submIT-portaal is een portaal dat gebruikt wordt om timesheets in te dienen. De werknemers dienen elkemaand een timesheet in van de werkuren die ze die maand gepresteerd hebben.In het verleden moesten de werknemers steeds een mail sturen met daarin hun onkosten. Office moest deze danmail per mail controleren en intypen in een Excel-bestand, vervolgens moest er een mail gestuurd worden naar debetaler welke onkosten betaald mochten worden. Al deze mails handmatig versturen vraagt veel tijd en op dezemanier werden hier en daar wel eens onkosten overgeslagen die men vergat in te vullen in het Excel-bestand.Wanneer de onkost overgeslagen werd, werd deze dus ook niet uitbetaald. De werknemer heeft hier enkel weet vanals hij/zij zijn/haar bankrekening controleerde om te zien of de onkost al vergoed was of niet.Om de verwerking van onkosten vlotter te maken en de werknemer een duidelijk overzicht te geven van zijn/haaringediende onkosten werd het reeds bestaande submIT-portaal uitgebreid. De uitbreiding van het portaal steltoffice in staat om per werknemer een configuratie te maken die bepaalt welke onkosten er ingediend mogenworden en wat het maximum bedrag is dat ingediend mag worden. Als een werknemer zich aanmeld krijgt hij/zijeen overzicht van zijn/haar onkosten. Alsook is hij/zij in staat om onkosten waarvoor hij/zij recht heeft in te dienen.Wanneer de status van zijn onkost veranderd zal hij/zij via mail op de hoogte gehouden worden. Alle werknemersvan office en de betalers zullen ook op het einde van de dag een notificatie-mail krijgen met een telling van deonkosten die nog verwerkt dienen te worden.Om dit allemaal te kunnen realiseren werd de server-code van de reeds bestaande applicatie uitgebreid. Voor defrontend werd een webbundel opgebouwd die gemakkelijk te installeren is. De webbundel is opgebouwd uitverschillende modules die geïnstalleerd werden met NPM. De belangrijkste modules zijn AngularJS en Bootstrap.

ProjectverloopIn het begin van de bachelor proef werd er vooral research gedaan naar de technologieën die gebruikt dienden teworden. Zo werd er veel onderzoek gedaan naar Java en het Spring framework, maar ook naar Angular, Hibernate,Webpack...

Het project werd vervolgens gestart aan de hand van scrum13. Wekelijks werd er een sprint-meeting gepland omte overlopen wat er elke week diende gerealiseerd te worden en werden de reeds behaalde resultaten kortoverlopen. Na de sprint-meeting werd eerst de feedback van de meeting verwerkt om vervolgens de nieuweplanning uit te voeren.

4

Page 5: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

In de laatste week werd er een demo gegeven aan de dienst Office. Tijdens deze demosessie werd er nogfeedback en opmerkingen gegeven van de klant wat men graag verandert zag. De gevraagde aanpassingenwerden de laatste week nog verwerkt en op de acceptatie server gedeployed.

5

Page 6: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

OpdrachtDe submIT applicatie is een reeds bestaande applicatie die uitgebreid diende te worden om de mogelijkheid tecreeëren om onkosten in te dienen via dit portaal in plaats van onkosten iedere keer te moeten indienen via mail.Het uitbreiden van het submIT-portaal diende er dus voor te zorgen dat het indienen van onkosten overzichtelijkerwerd en het verwerken van de onkosten vlotter kon verlopen.

Bij het onkosten gedeelte van het submIT-portaal zijn er drie verschillende rollen die een werknemer kan hebben,deze zijn: werknemer, office medewerker en betaler.

De werknemer kan enkel onkosten indienen en het overzicht van zijn/haar onkosten bekijken.

Bij het onkosten gedeelte van het submIT-portaal zijn er reeds twee verschillende rollen die een werknemer kanhebben. Deze zijn: werknemer en office, de rol betaler wordt nu toegevoegd als extra rol.

De toegekende autoriteiten van de verschillende rollen zijn:

De werknemer kan enkel onkosten indienen en het overzicht van zijn onkosten bekijken.

Een office werknemer kan onkosten indienen, het overzicht van zijn onkosten bekijken, onkosten van werknemersgoed- of afkeuren, onkosten voor een andere werknemer indienen en aanduiden welke onkosten een werknemermag indienen.

Een betaler kan onkosten indienen, het overzicht van zijn onkosten bekijken en onkosten die goedgekeurd zijn doorde dienst Office aanduiden als betaald of alsnog afkeuren.

Er zullen vijf verschillende type onkosten ingediend kunnen worden. Elk van deze types zal zijn eigen ristrictieshebben van bepaalde velden die ingevuld dienen te worden alvorens de onkost ingediend kan worden. Deverschillende types van onkosten zijn:

InternetGsmKilometervergoedingVervoerDiverse

Wanneer de werknemer een onkost in wilt dienen navigeert de werknemer naar het gewenste type onkost, vult denodige gegevens in en dient zijn aanvraag tot terugbetaling in.Wanneer de aanvraag is ingediend krijgt de werknemer op het intranet-portaal een notificatie dat zijn aanvraag totterugbetaling is ingediend.Op het einde van de dag telt het systeem hoeveel terugbetalingsaanvragen er die dag zijn ingediend en wordt ereen mail naar office gestuurd met de boodschap dat er onkosten verwerkt dienen te worden.De volgende dag meldt een office medewerker zich aan op het systeem, wanneer hij/zij navigeert naar 'beheeronkosten' krijgt hij/zij een overzicht te zien van alle ingediende onkosten. Hier kan de office medewerker een lijstzien van alle werknemers die onkosten hebben ingediend en hun onkosten. De office medewerker keurt de onkosten print het betalingsbewijs eventueel af.Vervolgens meldt een werknemer met de rol betaler aan. Wanneer de betaler naar 'beheer onkosten' navigeert zalhij/zij een overzicht krijgen van alle werknemers die een goedgekeurde onkost hebben. De betaler kan aanduidendat de onkost betaald is of de onkost alsnog afkeuren.Wanneer er aangeduid is dat de onkost terugbetaald is krijgt de werknemer opnieuw een notificatie in het intranet-portaal.

6

Page 7: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

7

Page 8: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Gebruikte technologieën

Spring framework

Op spring framework1 staat alle Java code die we voor de backend hebben geschreven. Spring is een open sourceframework gericht op het ontwikkelen van backend applicaties in Java. Het framework combineert API's en ideeënwaardoor het een alternatief biedt voor de standaard manier van ontwikkelen. Dankzij diverse uitbreidingen wordthet vooral gebruikt als alternatief voor of uitbreiding op technologieën uit J2EE-platform. Versie 3.1, die uitgegevenwerd op 13 december 2011, bracht ondersteuning voor Java 7. Versie 4.0.3 dat uitkwam in maart 2014 brachtondersteuning voor Java 8. In het huidige project maken we gebruik van Spring versie 4.2.5 . Met Spring is hetmogelijk om op een object georiënteerde manier Enterprise Java applicaties te schrijven die flexibel, beterleesbaar en beter te testen zijn. Alle business logica wordt in gewone Java objecten geschreven, 'plumbing' codekan via aparte objecten geïmplementeerd worden. De configuratie voor deze 'plumbing' code kan worden gedaandoor XML files toe te voegen aan de business logica code. Dit kan tegenwoordig ook via annotations in gewonePOJO's.

Hibernate

Hibernate2 zorgt voor de connectie tussen de applicatie en de database. Hibernate is een ORM library die de linklegt tussen OOP en relationele databases. Het staat ons toe om een object-georiënteerd domeinmodel aanverschillende databasen te koppelen. We hoeven ons dus niet bezig te houden om constant verbindingen temaken met de SQL-database. Wanneer we tabellen willen toevoegen genereert hibernate de nodige SQLinstructies.

JUnit

JUnit3 is een testing framework dat we gebruiken voor alle testen te schrijven en uit te voeren. Elk stuk code datgeschreven is heeft een test. Het is mogelijk om tijdens het builden de testen te laten lopen. Dit heeft als voordeeldat er bij wijzigingen in de code een controle is die controleert of alles nog werkt zoals het hoort te werken. Dezetesten worden ook nog op een bepaald tijdsstip uitgevoerd door de test server. De build server draait Jenkinssoftware en kan worden ingesteld om meldingen naar de developers te sturen indien er testen falen.

Jenkins

Jenkins4) is een open source continuous integration tool geschreven in Java. Het levert services voor continuousintegratie. Continuous integratie wil zeggen dat er meerdere keren per dag een build gedaan van alle software datop een gekozen locatie staat. het doel is om compilatie problemen te vermijden en het melden van falende testen(na het samenvoegen van wijzigingen in het project). Ook zal Jenkins de testen die geschreven zijn in J Unit latenlopen. De server is ingesteld om na de testen (indien er falen) een rapport of melding te geven aan deontwikkelaar. Hierdoor is men constant op de hoogte als er zich problemen zouden voordoen.

8

Page 9: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Maven

Apache Maven5 is een software tool voor Java-projectmanagement en geautomatiseerde projectbouw. Het maaktgebruik van een POM.xml file voor het software ontwikkelingstraject te sturen. In de POM staan alle modules encomponenten waaruit de volgorde van het opbouwen bepaald wordt. In de POM worden ook andere instellingengeconfigureerd zoals de automatisatie van testen, compilaties en verificaties van de code. Een belangrijk aspectvan Maven is de zogenaamde "repository" waarin verschillende versies van componenten opgeslagen zijn. Ditkunnen componenten zijn waarvan de te bouwen software rechtstreeks afhankelijk is. Ook kunnen ditcomponenten zijn die het bouwproces zelf ondersteunen. Maven biedt ondersteuning om de repositoryautomatisch te vullen met versies die op het internet aangeboden worden, via Apache en andere organisaties.

Tomcat

Apache Tomcat6 is een opensource webcontainer ontwikkeld door de Apache Software Foundation (ASF). Tomcatvoert servlets en JavaServer-pagina's uit, het verzorgt de communicatie tussen JSP-pagina's en een webserver. Hetvoegt hulpmiddelen voor configuratie en beheer toe maar kan ook worden geconfigureerd doorconfiguratiebestanden die XML-geformatteerd zijn. Tomcat heeft zelf een HTTP-server aan boord. Tomcat wordtgebruikt om de software lokaal op te testen nadat de warfile door Maven omgebouwd is en als productieserver.Deze warfile wordt dan in de server geplaatst. Bij het wijzigen van code is het meestal niet nodig om de serveropnieuw op te starten. Bij wijzigingen in de front-end code dient wel de webpack opnieuw uitgevoerd te worden omzo de statische files op te bouwen.

AngularJS

AngularJS7, vaak aangeduid als Angular, is een opensource webapplicatieframework dat wordt onderhouden doorgoogle, en geschreven is in Javascript. Het is enorm aan het stijgen in populariteit , vooral voor Single PageApplications. Angular heeft als hoofddoel het vereenvoudigen van zowel de ontwikkeling als het testen vandergelijke applicaties. Dit door het aanbieden van een framework met een MVC-architectuur (Model ViewController). Het framework werkt door eerst de HTML-pagina te lezen, waarin aanvullende specifieke HTML-attributen zijn opgenomen. html tags en attributen geïnterpreteerd worden door Angular en verrijkt met zelfgeschreven javascript code. Een groot voordeel is ook two-way binding van (user)data tussen de html frontend ende achterliggende javascript code. . De waarden van die JavaScript-variabelen kunnen worden ingesteld binnen decode, of worden opgehaald uit statische of dynamische JSON-dataobjecten. Bij het veranderen van een paginawordt gewoon een andere pagina getoond zonder deze opnieuw aan te hoeven vragen aan de server (principe van

Single Page). Om data op te vragen die men nodig kan hebben worden er REST11 verzoeken naar de servergestuurd en wordt de verkregen data direct geüpdate zonder dat de pagina herladen hoeft te worden.

Bootstrap

Om de applicatie zo responsief mogelijk te maken zonder zelf css te hoeven schrijven wordt bootstrap8 gebruikt.Bootstrap staat de ontwikkelaar toe om zeer responsieve webapps te ontwikkelen zonder al te veel css te hoevenschrijven. het is een open source css framework voor het ontwikkelen van websites en applicaties. Het bevat HTML

9

Page 10: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

en css gebaseerde templates voor input elementen (zoals knoppen, tekstvelden, ...) en andere interfaceonderdelen. Alsook kan het extra Javascript uitbreidingen ondersteunen en biedt het speciale componenten aanzoals knoppen met drop-down, navigatielijsten, labels, ... .

Webpack

Webpack9 neemt modules met dependencies en genereert statische representaties van die modules. Dit staat

ons toe om een volledige SPA (Single Page Application10) te maken. Alle statische files worden in één grotebundel gestoken en verzonden naar de frontend van de gebruiker.

NodJs

We gebruiken Node, ofwel NodeJs12 genoemd, voor het installeren en laden/starten van node modules. Dezemodules bevatten de nodige bestanden voor uitbreidingen in het project. Het bevat onder andere webpack, angular, bootstrap en andere belangrijke modules die de ruggengraat van onze frontend omgeving vormen. Het is ook zeersimpel om andere modules toe te voegen. Wanneer je het Node commando venster hebt openstaan kan jesimpelweg een npm commando typen zoals: "npm install angular --save-dev" om de laatste nieuwe node modulete installeren. Natuurlijk draait node ook een server voor alle modules op de gepaste ogenblikken te laden/starten.

10

Page 11: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

DatabaseOp de database worden alle gegevens van de werknemer/administrator bewaard. Hiervoor wordt gebruik gemaakt

van een Oracle (Structured Query Language13) database. Door middel van Hibernate te gebruiken worden erautomatisch (mits de correcte configuratie opgesteld is) verbanden gelegd tussen entiteiten van de backend en detabellen in de database. Deze verbindingen worden opgesteld doormiddel van annotatie te gebruiken. Hiermeewordt duidelijk tegen Hibernate gezegd dat de klasse gekoppeld wordt aan een gekozen databasetabel. In springzijn er verschillende annotaties die gebruikt kunnen worden om dingen aan te duiden dus hieronder is eenvoorbeeld hoe een klasse aan een tabel wordt gekoppeld. Alsook is te zien hoe de attributen aan de velden van detabel worden gekoppeld.

@Entity@Table(name = Expense.DB_TABLE_EXPENSES)@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)public abstract class Expense extends BaseEntity {

public static final String DB_TABLE_EXPENSES = "expenses"; public static final String DB_COLUMN_DATE = "paydate"; public static final String DB_COLUMN_DISTANCE = "kilometers"; public static final String DB_COLUMN_DESCRIPTION = "description"; public static final String DB_COLUMN_REMARKS = "remarks"; public static final String DB_COLUMN_USER_ID = "user_id"; public static final String DB_COLUMN_STATUS = "status"; public static final String DB_COLUMN_YEAR = "exp_year"; public static final String DB_COLUMN_MONTH = "exp_month"; public static final String DB_COLUMN_ADMIN_REMARK = "admin_remark"; public static final String DB_COLUMN_CURRENCY = "currency";

@Column(name = DB_COLUMN_ADMIN_REMARK) private String adminRemark;

@Column(name = "type", insertable = false, updatable = false) private String type;

@Column(nullable = false, name = DB_COLUMN_YEAR) private Integer year;

@Column(nullable = false, name = DB_COLUMN_MONTH) private Integer month;

@Column(name = DB_COLUMN_REMARKS) private String remark;

@Column(nullable = false, name = DB_COLUMN_USER_ID) private String userId;

@Column(nullable = false, name = DB_COLUMN_STATUS) @Enumerated(EnumType.STRING)

Bij het koppelen van de attributen en de velden van de tabel is het belangrijk dat de restricties van de velden van detabel gerespecteerd worden. In een veld dat een getal verwacht, mag geen woord aangeboden worden. Dit kanleiden tot server problemen zoals foutmeldingen, verkeerde interpretatie van code,... . Ook is het belangrijk datvelden die niet leeg mogen zijn daadwerkelijk data aangeboden krijgen bij het aanmaken van een item in de tabel.Moest dit niet gebeuren zal dit te merken zijn door de foutmeldingen op de server te bekijken. In het programma zijnde nodige beschermingen geschreven om deze fouten op database niveau te voorkomen. Van voorafgaande codekan je enkele van deze maatregelen zien (bv. nullable = false, dit veld mag niet leeg in de database wordengestoken).

11

Page 12: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Gebruikte annotaties@Entity : Java annotatie die gebruikt wordt om te laten weten dat de klasse een entiteit is.@Table : Hier komt de naam van de tabel te staan waaraan de entiteit gekoppeld is.@Inheritance : de entiteit is een abstracte klasse waar andere entiteiten van overerven. Er zijn 5 verschillendetypes onkosten, elk met een paar unieke attributen maar vooral ook met een hoop gelijke. Deze gezamenlijkeattributen worden in de abstracte klasse gestoken en door de te laten overerven van abstracte klasse hebbenze deze basis attributen ter beschikking. Omdat alle onkosten in één tabel komen te staan, met een type veldals onderverdeling, wordt deze annotatie gebruikt ( in combinatie met volgende ).@DiscriminatorColumn : dient vooral zodat hibernate weet naar welke subclass (subentity) hij de databaseentry moet mappen

EntiteitEen entiteit is een domein object dat een tabel uit de relationele database voorstelt. Elke instantie van deze entiteitstelt een rij uit de tabel voor. Wanneer we dus data uit de database halen steken we de data uit de rij/rijen ininstanties van de entiteit (die dus elk een rij uit de database voorstellen). Deze instanties kunnen we dan in hetprogramma gebruiken voor data uit te halen of om bewerkingen op uit te voeren.

Tabellen in de database

EXPENSE

ExpenseID (unieke nummering van de onkost)USER_ID (gebruikersnaam van persoon die onkost heeft aangemaakt)CURRENCY (bedrag van de onkost)DESCRIPTION (beschrijving van de onkost)REMARKS (eventuele opmerkingen bij het indienen van een onkost)TYPE (type van de onkost, wordt automatisch ingevuld bij het aanmaken van een bepaald type onkost)KILOMETERS (bij kilometervergoeding worden het aantal gereden kilometers hierin bewaard)STATUS (de huidige status waarin de onkost zich bevindt)EXP_YEAR (jaartal waarin de onkost aangemaakt werd)EXP_MONTH (maand waarin de onkost aangemaakt werd)ADMIN_REMARK (bij het keuren of betalen kan de administrator commentaar toevoegen)

Deze tabel bevat alle onkosten die worden ingediend. Afhankelijk van het type van onkost worden bepaalde veldenleeg gelaten (een diverse onkost heeft bv. geen kilometers die afgelegd zijn). Om een onkost uit te tabel op tezoeken wordt meestal de ID of de USER_ID gebruikt.

12

Page 13: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Opvragen van data uit te tabel:

Opvragen van alle onkosten voor een bepaalde gebruiker

@Override public List <Expense> findByUserAndDate(final String userId, final Integer year, final Integer month) { Criteria criteria = getCurrentSession().createCriteria(getDomain()); criteria.add(Restrictions.eq("userId", userId)); criteria.add(Restrictions.eq("year", year)); criteria.add(Restrictions.eq("month", month));

return (List<Expense>) criteria.list(); }

In de code is te zien dat de Query opgesteld werd om een klasse van het type Expense op te halen. Alsvoorwaarden worden er een USER_ID (naam bepaalde gebruiker) en een tijdperiode (in vorm van een maand eneen jaar) aan meegegeven. Vervolgens wordt er in de database gekeken of er onkosten aan de voorwaardenvoldoen. Alle onkosten waarbij dit het geval is worden samengenomen en in een lijst gestoken. Deze lijst wordtdan doorgestuurd naar waar de vraag vandaan kwam.

Opvragen van alle onkosten die in een bepaalde tijdsperiode gebeurd zijn

@Override public List <Expense> findByDate(Integer month, Integer year) {

Criteria criteria = getCurrentSession().createCriteria(getDomain()); criteria.add(Restrictions.eq("year", year)); criteria.add(Restrictions.eq("month", month)); criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); return (List<Expense>) criteria.list();

}

Deze query wordt hetzelfde opgebouwd als de voorgaande met als verschil dat de USER_ID niet wordtmeegegeven. Dit zal dus alle onkosten teruggeven die voldoen aan de datum die werd meegegeven. Hier wordenook alle onkosten teruggegeven in een lijst die vol zit met entiteiten van het type Expense.

13

Page 14: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

EXPENSE_UPLOAD_FILE

Expense_upload_fileID (unieke nummering van de onkost)EXP_ID (unieke nummering van de bijhorende onkost)EXP_FILENAME (naam van de bijlage)EXP_FILEPATH (locatie van het bestand op de file server)CREATED_ON (datum wanneer de bijlage opgeslagen werd)IS_PDF (true/false, duidt aan of de bijlage een pdf is)ORDER_DATA (volgorde waarin de bijlage opgeslagen werd)

Van alle onkosten waarbij een bijlage wordt meegegeven (pdf, afbeelding,...) wordt de bijlage bewaard op eenaparte server. Deze tabel is opgesteld om op latere tijden de bijlage van de onkosten terug te vinden. Op deze tabelworden dan de nodige query's uitgevoerd die resulteren in het terugvinden van de locatie van deze bijlagen. Delocatie kan dan door andere services gebruikt worden om de daadwerkelijke bijlagen terug op te vragen.

Opvragen van data uit te tabel:

Opvragen b ijlage van een onkost

@Override public ExpenseFile findByExpenseId(final String expenseId){ Criteria criteria = getCurrentSession().createCriteria(getDomain()); criteria.add(Restrictions.eq("expUploadId", expenseId));

return (ExpenseFile) criteria.uniqueResult(); }

Voor het opzoeken van de data van een bijlage (locatie naar de fileserver, filename,...) wordt een query gebruikt diedeze uitvoert met behulp van de EXP_ID (expUploadId). Dit geeft een uniek (er kan dan maximaal één bijlagegevonden worden) resultaat terug in de vorm van een ExpenseFile (entiteit die alle attributen bevat van de tabel). Ditresultaat wordt dan teruggegeven aan de aanvrager van de query.

EXPENSE_CONFIG

expense_configUSER_ID (gebruikersnaam waar de configuratie aan toe behoort)GSM (true/false bepaalt of de gebruiker recht heeft om GSM onkosten in te dienen)GSM_CURRENCY (het bedrag waar de gebruiker maximaal recht op heeft bij het indienen van een gsmonkost)INTERNET (true/false bepaalt of de gebruiker recht heeft om internet onkosten in te dienen)INTERNET_CURRENCY (bedrag waar de gebruiker maximaal recht op heeft bij het indienen van eeninternet onkost)KILOMETER (true/false bepaalt of de gebruiker recht heeft om kilometervergoeding in te dienen)TRANSPORT (true/false bepaalt of de gebruiker recht heeft om vervoersonkosten in te dienen)OTHER (true/false bepaalt of de gebruiker recht heeft om diverse/andere onkosten in te dienen)CREATED_ON (datum wanneer de onkost de configuratie aangemaakt werd)

Tabel die de configuratie van elke werknemer bevat die al een onkost heeft willen indienen. De configuratie wordt,zoals eerder vermeld in de opgave, ingesteld door een administrator. Wanneer de werknemer een onkost wenst inte dienen wordt de configuratie opgevraagd om te controleren of er geen onkosten worden aangemaakt waar hijgeen recht op heeft. Om de configuratie op te vragen wordt onderstaande query gebruikt.

14

Page 15: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Opvragen van data uit te tabel:

opvragen van configuratie van een gebruiker

@Override public ExpenseConfig findByUserId(String userId){

Criteria criteria = getCurrentSession().createCriteria(getDomain()) .add(Restrictions.eq("userId", userId)); return (ExpenseConfig) criteria.uniqueResult(); }

De query gebruikt de USER_ID (userId) als parameter voor het opzoeken in de tabel. Dit geeft een (unieke) entiteitvan het type ExpenseConfig terug.

EXPENSE_TICKET_QUEUE_MAIL

expense_ticket_queue_mailID (unieke nummering)EXPENSE_ID (unieke nummering van de bijbehorende onkost)ORIGINAL_STATE (originele status van de onkost bij het aanmaken)NEW_STATE (laatst verkregen status van de onkost)CREATED_ON (datum wanneer de onkost werd aangemaakt)

De applicatie bevat een geautomatiseerd mailsysteem. Om gebruikers niet te overladen met mails worden allemails die verstuurd dienen te worden bewaard in een tabel. Dit met als doel om mails die een status veranderingmelden maar één keer een melding te laten geven tussen de verschillende veranderingen door (bv. als een onkostvan status 1 naar 2 verandert zou er normaal direct een mail gestuurd worden met de melding van de veranderingen hetzelfde wanneer de onkost van status 2 naar 3 zou veranderd.) . In de tabel zullen dus constant veranderingengebeuren. Op het einde van de dag worden de mails verzonden naar de eindgebruiker, en als verandering zalgemeld worden dat de onkost van status 1 naar 3 veranderd is i.p.v. alle veranderingen.

Opvragen van data uit te tabel:

_opvragen van statussen van ticket voor mail

@Override public ExpenseMailState findByExpenseId(final String expenseId) { Criteria criteria = getCurrentSession().createCriteria(getDomain()); criteria.add(Restrictions.eq("expenseId", expenseId).ignoreCase());

return (ExpenseMailState) criteria.uniqueResult();

}

De query gebruikt de EXPENSE_ID (expenseId) als parameter voor het opzoeken in de tabel. Dit geeft een (unieke)entiteit van het type ExpenseMailState.

15

Page 16: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Backend(Spring framework)

Frontend moet data kunnen ophalen en opslaanWanneer de frontend bepaalde data uit de database nodig heeft (zoals bv. onkosten voor een bepaaldetijdsperiode) wordt er een http-verzoek gestuurd naar de backend. Deze zal op zijn beurt de nodige servicesaanroepen die de data dan uit de database zullen halen en deze omzetten naar het gewenste formaat dat defrontend verwacht te krijgen. Elk van deze services zit achter een bepaalde URL en kan niet door iedereen gebruiktworden. Zo kan een gebruiker geen verzoeken sturen voor onkosten van andere gebruikers te zien, dit kan enkeldoor een administrator. Om dit in te stellen is er de nodige beveiliging geschreven. Wanneer een verzoek gestuurdwordt naar de backend zullen de geschreven filters op enkele zaken controleren en eventueel het verzoek afwijzenmoest hier niet aan voldaan worden. In een XML file dat 'SecurityContext' heet worden alle verzoeken gecontroleerdof ze door de correcte persoon verzonden worden. Elke URL voor verschillende gebruikers (werknemer,administrator, betaler) wordt anders opgebouwd maar wordt door eenzelfde filter gecontroleerd. Elk verzoek bevateen unieke token waar een gebruiker aan gekoppeld is. Wanneer een verzoek door een administrator wordtgestuurd zal de filter controleren of de token die in een verzoek header zit overeenkomt met een gebruiker dieadministrator rechten heeft. Wanneer dit het geval is wordt het verzoek verder gestuurd naar eventuele andere filtersdie er aan gekoppeld zijn (dit heet een filter-chain). Wanneer een verzoek niet door de filter geraakt dooronvoldoende rechten of foutieve informatie zal de gebruiker die het verzoek stuurde op de hoogte gebracht wordendoor een foutmelding te sturen naar de frontend. Deze foutmelding zal dan een omschrijving/reden geven waarom

het verzoek afgekeurd werd. Een andere filter in de ketting is een CORS (Cross-origin Resource sharing[link]) filter.Deze zal de verzoeken controleren op de inhoud van zijn headers (welke headers toegelaten zijn en welke nietzoals bv. Content-type), het type van verzoek dat gestuurd werd (POST, DELETE, GET, PUT, ...) en of de verzoeken opandere domeinen gestuurd mogen worden of niet (bv. www.abc.be stuurt een verzoek naar www.def.be).

Mappen van verzoeken

Gezien een verzoek bepaalde services wil aanspreken worden ze gekoppeld via een mapper. In de mapper wordtde URL in een tekst variabele gestoken. Dit geeft voor het ontwikkelen in de code een duidelijk overzicht van alleURL's die kunnen ontvangen worden. Deze variabele wordt dan aan een controller gehangen. De controller zalniets doen tot er een verzoek wordt ontvangen die overeenstemt met zijn URL. Dus als de URL van controller A dewaarde "/rest/users/login" heeft zal deze pas acties uitvoeren wanneer men surft naar "/rest/users/login". Wanneerde URL waarden bevat die kunnen veranderen (zoals een gebruikersnaam) worden deze in de mapper aangeduidop de volgende manier: {username}. In de controller wordt de waarde dan uitgelezen door een @Pathvariableannotatie te gebruiken (@PathVariable String username). De gebruikersnaam wordt dan in een tekst variabelegestoken met dezelfde naam als dat van de variabele.

Controller

Een controller wordt opgebouwd door een @RequestMapping annotatie te gebruiken. In deze annotatie geef je eenvalue mee. Deze value komt dan overeen met de URL waar de controller aan gekoppeld wordt (tekst variabele vande mapper). Vervolgens wordt de methode waar hij op moet reageren ingesteld (method = POST, PUT, ...). Als extrainstellingen krijgen sommige controllers ook nog een "produces" en "consumes" mee ingesteld. Deze vertellen decontroller wat voor soort data hij te verwerken krijgt en in welk formaat hij ze terug moet geven. Dit kan verschillenvan controller tot controller. Als er gewone data uit de database wordt gelezen krijgt de controller JSON data binnenen produceert deze ook. Bij het opvragen van een bijlage aan de file server kan het zijn dat een controller JSONaanvaardt (kan bepaalde info van het verzoek nodig hebben en dit staat dan in JSON formaat), maar een multipartfile als resultaat terug geeft.

16

Page 17: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Wanneer een verzoek ontvangen wordt op de controller zullen nodige services worden aangeroepen. Deze servicesvoeren alle logica uit die nodig is om de verzochte data op te vragen, te verwerken en terug te geven in een pakketdat de controller terug kan sturen naar de verzender van het verzoek. Elke controller geeft ook een bepaalde HTTP-code terug. Deze zijn afhankelijk van de acties die de controller moet uitvoeren. Een controller die moet aanmakenzal een code "201" teruggeven wanneer dit succesvol gebeurd is. Hierdoor wordt de verzender van het verzoek opde hoogte gebracht dat zijn verzoek met succes afgehandeld is (vooral belangrijk voor de frontend logica).

voorbeeld van een controller

@RequestMapping(value = RequestMappings.USER_EXPENSES_CONFIG, method = RequestMethod.PUT, consumes = ContentType.APPLICATION_JSON, produces = ContentType.APPLICATION_JSON) public ResponseEntity<Void> editExpenseConfig(@RequestBody final ExpenseConfigDto body, @PathVariable final String userId) expenseConfigService.setExpenseConfig(body, userId); return new ResponseEntity<>(HttpStatus.OK); }

Service

Een service bestaat uit twee klassen. Eén klasse bevat alle abstracte interfaces die aangesproken kunnen wordenen die geïmplementeerd worden door de tweede klasse (methoden). De tweede klasse heeft dezelfde benamingals de eerste klasse maar met "Imp" (van implementatie) er aan toegevoegd. De implementatie klasse gaat alleinterfaces van de eerste klasse implementateren. In de tweede klasse worden alle interfaces van de éérste klassegeïmplementeerd, dit om de logica toe te voegen aan de interfaces. Eén van de doelen van de geschreven logica isom de data dat in de database zit op te vragen. Wanneer de data in een entiteit zit, zal de logica deze data uit de

entiteit halen en deze in de gepaste DTO (data-transfer objects16 ) steken. Wanneer alle logica is uitgevoerd, wordthet resultaat terug aan de controller gegeven die de service aanriep.

DTO (Data transfer object)

Object waar we de informatie van verschillende entiteiten in kunnen plaatsen om dit zo aan de front-end de kunnenpresenteren in een object. Op de frontend heeft dit als grote voordeel dat men altijd zeker is dat bepaalde data altijddezelfde benaming hebben (tenzij dit in de DTO zelf veranderd wordt). Dit zou niet het geval zijn moest de entiteiteen andere attribuutnaam krijgen. Door de DTO te gebruiken mogen de velden van de entiteit constant van naamveranderen, de frontend zal altijd dezelfde benaming kunnen gebruiken. In de DTO wordt de data van de instantievan de entiteit gestoken op vooraf ingestelde velden (dezelfde waar de frontend afhankelijk van is). In onderstaandvoorbeeld kan je zien dat er gebruik wordt gemaakt van getter en setter voor de data van de entiteiten uit te lezen ofin te vullen. Erboven staat een annotatie met een naam. Als de frontend zich afhankelijk maakt van de benamingenvan de annotaties dan wordt er altijd de correcte data uitgelezen. Alsook kunnen er annotaties worden ingesteld diekijken of de velden in de DTO niet leeg zijn, deze zullen de gepaste foutmelding geven indien er niet voldaan wordtaan de voorwaarden.

17

Page 18: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

voorbeeld van een dto

@JsonProperty("type") private String expensetype; @NotNull @JsonProperty("month") private Integer month; @JsonProperty("state") private String state; @JsonProperty("expense_id") String expense_id;

public String getState() { return state; }

public void setState(String state) { this.state = state; }

public Integer getMonth() { return month; }

public void setMonth(Integer month) { this.month = month; }

DAO (Data Acces Object)

Het opzoeken van data is via query’s al besproken in het hoofdstuk van de database. Om data in de database testeken worden er specifieke services aangeroepen. Deze zullen de DTO die ze ontvangen van de controller of vaneen andere service omvormen naar een entiteit. Dit wordt gedaan door alle data van de DTO over te plaatsen naargelijknamige attributen van de entiteit. Nadat dit succesvol volbracht is kan de service de gewenste actie uitvoerenvoor de data te updaten/toevoegen aan de database. Hier komt de DAO aan te pas. Het zorgt voor een abstracteinterface naar de database waar die een relatief simpele scheiding vormt tussen twee belangrijke onderdelen ineen applicatie. Volgende methoden kunnen aangeroep worden:

dao.persist(entiteit) : een nieuwe rij aanmaken in de tabel met de data van de entiteit.dao.update(entiteit) : rij met dezelfde ID wordt gezocht, gegevens van de huidige rij worden vervangen met degegevens in de huidige entiteit.dao.delete(entiteit) : rij met dezelfde ID wordt gezocht en uit de tabel verwijderd.

18

Page 19: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Automatische servicesEnkele services dienen automatisch op tijdsafhankelijke momenten geactiveerd worden. Hiervoor is een "tasks"klasse gemaakt. Hieronder staan de nodige services die op ingestelde tijdsstippen hun logica uitvoeren. Om aante duiden dat ze tijdsafhankelijk zijn wordt de @Scheduled annotatie gebruikt. Hier wordt de trigger waar de servicedoor aangeroepen wordt ingesteld. Deze services worden vooral gebruikt voor het automatisch versturen van mailsnaar de werknemers en maakt gebruikt van CRON (tijd gebaseerde job planner). Hieronder een voorbeeld van eengetimede service.

voorbeeld van een getimede service

@Scheduled(cron = "${adminMailJob}") public void sendAdminMessage() { LOGGER.info("Admin Message job started"); messageService.sendAdminMessage();

}

Er kunnen door dezelfde CRON meerdere timers worden ingesteld. Daarom is er een configuratiefile waar dezeaan variabele worden gehangen ("${adminMailJob}"). Wanneer de tijd van de variabele wordt bereikt worden alleservices die aan dezelfde variabele hangen geactiveerd (cron = "${adminMailJob}"). Ook wordt er een logger in deservice gestoken. Bij het openen van een log file van de server kan men duidelijk zien wanneer er welke job gestartwerd (handig voor het zoeken van fouten).

Mailservice

De mailservice wordt aangesproken door de CRON timer en zal op ingestelde tijdstippen de service aanroepen. Erzijn drie getimede services die geactiveerd worden door de CRON.

Update status onkost naar gebruiker

De gebruiker zal op het einde van de werkdag een update krijgen van alle onkosten die een statuswijziging hebbenondergaan. Dit wil zeggen dat de onkost door de administrator of door de betaler verwerkt is. De functie die wordtaangeroepen door de mailservice leest alle rijen uit van de EXPENSE_TICKET_QUEUE_MAIL tabel en steekt dezein een lijst van entiteiten (expenseMailState). Elke entiteit heeft volgende attributen:

ID (unieke ID van de rij)expense_id (unieke ID van de onkost waar de rij voor is toegevoegd)original_state (status van de onkost wanneer hij voor het eerst wordt toegevoegd aan de tabel)current_state (de huidige status van de onkost)created_on (wanneer de entiteit aan de tabel werd toegevoegd)

Voor elke rij in de tabel wordt er een mail verzonden naar de bijbehorende gebruiker. Deze wordt gevonden door inde onkosten database de user_id op te vragen van de expense_id die verkregen wordt van de expenseMailStateentiteit. Om de mail op te bouwen wordt een template uit een template tabel gehaald. In deze template zijnbepaalde velden te vervangen en zijn ze gekoppeld aan een 'Key'. Wanneer een waarde (dus bv. naam van degebruiker is gekoppeld aand ${firstname}) aan de 'Key' wordt gehangen zal deze in de mail zichtbaar zijn.

Template mail gebruiker inlichten over statusverandering

Beste ${firstname},Je ${exp_type} onkost van ${expense_date} die u hebt ingediend op ${exp_created_on} is veranderd van ${exp_original_state} naar ${exp_new_state}Met vriendelijke groeten, Submit

19

Page 20: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Alle keys krijgen de gepaste waarde ingevuld en de mail wordt dan doorgegeven aan de mail verzender. De mailzender zal kijken of de gebruiker geen administrator of betaler is, indien dit niet zo is zal de mail via het Intranetportaal ontvangen worden als 'notificatie'. Anders zal de mailserver worden aangesproken en krijgt hij demailtemplate en de ontvanger meegestuurd.

Na het verzenden van de mail zal de rij van de expenseMailState uit de EXPENSE_TICKET_QUEUE_MAIL tabelverwijderd worden om dubbele mails te vermijden. De enige rijen die nog in de tabel kunnen staan zijn vanonkosten waarvan de status niet veranderd is.

Telling van werk voor betaler en administrator

Op het einde van de dag krijgen alle betalers en administrators een mail met een telling in. Deze telling meldthoeveel onkosten er nog betaald of gekeurd dienen te worden. De mailservice roept een functie aan die alleonkosten uit de database haalt. Vervolgens wordt van elke onkost de status bekeken en een telling bijgehouden opde statussen die zeggen of een administrator/betaler de onkost nog dient te keuren/betalen.

Vervolgens worden alle gebruikers met de gebruikersrol 'Admin'/'Betaler' opgehaald. Voor elke gebruiker wordt dande gepaste mailtemplate opgehaald en ingevuld met de nodige gegevens. Deze mailtemplate wordt vervolgensbezorgd aan de mailserver die de mail zal versturen naar de gepaste persoon.

20

Page 21: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Frontend

Angular en bootstrap (single page en responsive)Alle content die aan de gebruiker getoond wordt bevindt zich in een view, alles wordt geladen bij de eerste keer datde pagina wordt opgevraagd. Wanneer de gebruiker klikt op een link in het venster wordt enkel de view vervangen.Hiermee wordt ervoor gezorgd dat er geen laadtijden zijn en de applicatie heel soepel tussen verschillendepagina's kan veranderen. De view is eigenlijk een verzamelingen van directives die elk verantwoordelijk zijn voor decontent die zij laten zien. Elke directive heeft een controller die de nodige data uit de back-end zal opvragen en denodige logica uitvoert om content andere vormen te geven of te transformeren (bv. filteren). Wanneer logicameermaals gebruikt moet worden door verschillende controllers wordt deze in services gestoken. Het navigerentussen verschillende pagina's wordt geregeld door een controller waar alle andere views in worden geplaatst. Decontroller zal ook controle uitvoeren met als doel dat de gebruiker enkel de gepaste pagina's kan bezoeken en of hijal aangemeld is.

Om alle content er goed uit te laten zien op elk formaat van scherm wordt er ook gebruik gemaakt van bootstrap.Hierdoor kan de lay-out aangepast worden voor elk verschillende schermgrootte.

Directive

Een Angular directive bestaat uit een html pagina waar alle velden in staan die we nodig hebben voor de input enoutput van informatie. Ook bevat het bootstrap code voor de content responsive te houden. Aan de directive wordtook nog een controller gehangen die de nodige informatie van de velden verwerkt en data kan ophalen van anderelocaties.

Controller

De controller hangt aan een directive. Hierin wordt de informatie van de velden op de HTML-pagina verwerkt enwordt andere data opgevraagd. Wanneer de data verandert in de controller wordt de view automatisch ge-updatezonder dat de pagina moet herladen. Andere informatie (zoals data uit een database) wordt verkregen doorverzoeken naar de back-end te sturen. De data die dan verkregen wordt kan in een variabele worden gestoken engekoppeld worden aan een veld op de HTML-pagina. Gezien verschillende controllers verzoeken sturen wordt dezefunctie in een service gestoken.

Service

Alle functies die in meerdere controllers gebruikt worden, worden in services gestoken. Deze service krijgt eengepaste benaming voor de acties die moeten gebeuren (bv. back-end service, deze service regelt alle verzoeken)en zal dus enkel functies bevatten die bij de benaming passen. De services die worden aangemaakt zitten indezelfde module als de rest van de directives en hoeven dus niet extra toegevoegd te worden in de hoofdcontroller.Om een service te kunnen gebruiken wordt deze toegevoegd in de paramaters van de controller van de directivewaar deze gebruikt dient te worden. De paramater die wordt meegegeven is de naam van de service.

21

Page 22: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Services die nodig zijn in de directive komen in function() te staan

(function () { angular.module('submITApp') .directive('abcExpenseUserDirective', function (userDataStorage, UserConfig, backendFacade, MessageHandler) { return { restrict: 'E', templateUrl: "expenseUserDirective.html", scope: { expense: "=", pdfMetadata: "=?" }, controller: Controller, controllerAs: "vm", bindToController: true };

Admin filter

De service 'adminFilter' wordt gebruikt om een filter toe te passen op de lijst van gebruikers die getoond wordt bijhet overzicht van de ingediende onkosten die de office medewerker en de betaler te zien krijgt. Bij hetconfiguratiescherm wordt ook een filter gebruikt. Er kan gefilterd worden op gebruikersnaam, bedrijfsnaam,onkosten die reeds verwerkt zijn en onkosten die nog verwerkt dienen te worden. Als parameter wordt er aan deservice meegegeven welke filter er gebruikt dient te worden. Wanneer er gefilterd wordt op onkosten die reedsverwerkt zijn wordt de filter om onkosten die nog verwerkt dienen te worden uitgeschakeld. Dit wordt gedaan omdatallebei deze filters toepassen hetzelfde is als geen filter toepassen. Wanneer de controle gedaan is van het typefilter er toegepast dient te worden wordt de functie 'activeFilters' aangeroepen. In deze functie worden de filtersaangeroepen en toegepast.Wanneer er gefilterd wordt op de gebruikersnaam zal de gebruikerslijst gecontroleerd op een overeenkomstigenaam in de lijst. Indien er een gebruiker overeenstemt met de naam die ingetypt wordt door de huidige gebruikerzal deze in een tijdelijke lijst worden gestopt en terug gestuurd naar de functie 'activeFilters'.Wanneer er gefilterd wordt op de bedrijfsnaam zal er eerst gecontroleerd worden of de waarde van de filter 'Allebedrijven' is. Als dit zo is word de filter op bedrijfsnaam gereset. Indien dit niet zo is zal er gecontroleerd worden ofer gebruikers in de gebruikerslijst zitten die voor het bedrijf werken dat ingevuld is door de gebruiker. Wanneer hetbedrijf waar de gebruiker voor werkt overeenstemt met het bedrijf dat ingevuld is in de filter wordt de gebruiker ineen tijdelijke lijst toegevoegd. Wanneer alle gebruikers overlopen zij en indien nodig aan de tijdelijke lijsttoegevoegd zijn wordt deze lijst terug bezorgd aan de functie 'activeFilters'.Bij het filteren op de status van de onkost word er bij zowel de filter voor reeds verwerkte onkosten als voor de filtervoor de onkosten die nog verwerkt dienen te worden gecontroleerd wat de rol is van de actieve gebruiker. Dit wasnodig omdat de reeds verwerkte onkosten en nog te verwerken onkosten van de office medewerker of de betalervaak verschillend zijn. Wanneer de onkost voor de office medewerker verwerkt is wil dit niet zeggen dat deze ookvoor de betaler al verwerkt is. Dit zijn dus twee verschillende lijsten. Wanneer er gecontroleerd is welke rol deactieve gebruiker heeft wordt er gecontroleerd in de gebruikerslijst van welke gebruiker alle onkosten al verwerktwaren of welke gebruiker nog onverwerkte onkosten heeft. Wanneer de gebruiker zijn status overeenstemde metde filter die geselecteerd is wordt de gebruiker toegevoegd aan een tijdelijke lijst. Wanneer de volledigegebruikerslijst gecontroleerd is zal de tijdelijke lijst terug bezorgd worden aan de functie 'activeFilters'.Vervolgens worden de tijdelijke lijsten samengevoegd om één gezamelijke gefilterde lijst op te bouwen. Deze wordtvervolgens terug bezorgd aan de directive die de service 'adminFilter' heeft aangeroepen. De gebruiker kon bij hetoverzicht ook op de reset knop klikken. Wanneer dit gebeurt, worden alle filters gereset en wordt de volledigegebruikerslijst getoond.

22

Page 23: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Backend configuratie

In de service 'backend-configuration' worden de algemene dingen ingesteld. De basis URL om requests op uit tevoeren wordt hier ingesteld, alsook de header 'x-submit-token'.

Backend facade

De service 'backendFacade' wordt gebruikt om de URLs op te bouwen om de REST-calls uit te voeren. Dezeservice wordt ook gebruikt om POST, PUT, GET en DELETE requests uit te voeren. Telkens word er in het begin vande request de user token opgevraagd. Deze token is nodig om toegang te hebben tot de server. Wanneer dezetoken niet geldig is krijgt de gebruiker een 401 error terug met de melding dat hij/zij geen geldige authenticatieheeft.

Kalender status

De service 'calendarStateService' wordt gebruikt om de kalender te regelen. De service heeft de functies 'setYear'en 'setMonth'. Deze functies worden gebruikt om de maand en het jaar in te stellen. De directive die deze functiesaanroept geeft een jaar of een maand mee als paramater bij het aanroepen van de functie. Omdat er meerdereviews zijn die de kalender gebruiken wordt er voor elke kalender een id aangemaakt. Deze id wordt gebruikt om tecommuniceren tussen de directive en de service. Wanneer de service het jaar of de maand instelt wordt dit gedaanop de kalender met de bijhorende id.De functies 'increaseYear' en 'decreaseYear' worden gebruikt om het jaartal met één te verhogen of te verlagen.De functie 'checkIfMonthIsValid' wordt gebruikt om te controleren of de gebruiker voor de geselecteerde maand nogonkosten kan indienen. De gebruiker heeft een beperking op het indienen van onkosten. Hij/zij kon namelijkonkosten indienen in de huidige maand en tot drie maanden terug. Dit wordt gedaan om te voorkomen dat eengebruiker een half jaar na datum nog een onkost in zou dienen. In deze functie wordt eerst gecontroleerd wat dehuidige datum is. Wanneer dit gedaan is wordt er drie maanden terug geteld. Voor de maande die onder dezeparamater vallen kan de gebruiker nog onkosten indienen. Vervolgens zijn er nog drie functies die gebruikt wordenom de maand, het jaar of beiden op te vragen. Deze functies geven enkel datgene terug waarachter gevraagd wordten doet verder niets.

Message handler

De service 'MessageHandler' werd gebruikt om de succes-, error- en authenticatie- errors op te bouwen. Wanneerde functie 'setSuccesMessage' aangeroepen wordt, wordt er als status bericht ingesteld dat deze 'De onkost issuccesvol ingediend.' zal tonen. Om dit bericht te tonen wordt er een broadcast uitgestuurd die opgevangen wordtdoor de directive die deze nodig heeft.Wanneer er iets fout gaat wordt de functie 'setErrorMessage' aangeroepen. Hierin werd het bericht ingesteld op 'Eris iets fout gegaan :-('. Vervolgens wordt hier ook een broadcast gestuurd die verwerkt wordt door de directive diedeze nodig had.Wanneer de gebruiker de verkeerde login gegevens invoert wordt de functie 'setAuthenticationError' aangeroepen.Hierin wordt het bericht ingesteld op 'Wrong username/password'. Van dit bericht wordt ook een broadcastverstuurd die verwerkt wordt door de directive die deze nodig had.

23

Page 24: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Pdf retriever

De service 'pdfRetriever' wordt gebruikt om alles van de pdf te verwerken. In de functie 'getPdfMetadata' wordt demetadata zoals de bestandsnaam en de bestandsgrootte opgehaald. In deze functie wordt eerst de URLopgebouwd door gebruik te maken van de service 'backendFacade' en de id van de bijhorende onkost. Vervolgenswordt er een GET-request naar de backend gestuurd. Hierna wordt de response data in een variabele gestoken enterug bezorgd aan de directive die deze functie aanriep.In de functie 'getPdfInView' wordt de URL opgebouwd om de pdf in de pdf-viewer te krijgen. Dit is het enige dat indeze functie gebeurt.

Sort by

De service 'sortBy' wordt gebruikt om de gebruikerslijst te sorteren. De gebruikerslijst kan gesorteerd worden opvoornaam, achternaam, bedrijf en op de status van de gebruiker zijn onkosten. In het begin bij elke sorteerfunctiewordt er een boolean aangepast naar het tegenovergestelde wat de boolean reeds bevat. Dit gebeurt om hetmogelijk te maken om in twee richtingen te sorteren.Vervolgens wordt de sorteerfunctie toegepast op de gebruikerslijst.

filteredUserList.sort(function (a, b) { var nameA = a.first_name.toLowerCase(), nameB = b.first_name.toLowerCase(); if (nameA < nameB) { if (self.sortedByFirstname === true) { return -1; } else if (self.sortedByFirstname === false) { return 1; } } else if (nameA > nameB) { if (self.sortedByFirstname === true) { return 1; } else if (self.sortedByFirstname === false) { return -1; } } });

Wanneer er op de status gecontroleerd wordt, wordt er een ander soort sorteerfunctie aangeroepen.

else if (sortBy === "statusAdmin") { self.sortedByStatusAdmin = !self.sortedByStatusAdmin; filteredUserList.sort(function (a, b) { if (self.sortedByStatusAdmin === true) { return a.aprovedByAdmin - b.aprovedByAdmin; } else if (self.sortedByStatusAdmin === false) { return b.aprovedByAdmin - a.aprovedByAdmin; } });

Daarna wordt de gesorteerde lijst terug bezorgd aan de directive die de functies aanroept.

User config

De service 'userConfig' wordt gebruikt om de configuratie van de gebruiker op te halen. De functie 'getUserConfig'wordt aangeroepen met een userId als parameter. Deze userId wordt gebruikt om de URL op te bouwen waaropeen GET-request gaat gebeuren om de configuratie van de gebruiker op te halen. Wanneer de GET-requestuitgevoerd wordt, wordt er gecontroleerd of de gebruiker recht heeft om minstens één type onkost in te dienen.

24

Page 25: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Indien dit het geval was wordt er een boolean op true gezet. Dit is nodig omdat er een melding tevoorschijn dient tekomen wanneer de gebruiker geen onkosten in kan dienen. Vervolgens wordt de configuratie van de gebruikerbezorgd aan de directive die deze functie aanriep.

Userdata storage

De service 'userDataStorage' wordt gebruikt om de gegevens van de gebruiker te verwerken. In deze service wordtde voornaam, achternaam, id, submitToken, gebruikersrollen enzovoort opgeslagen van de actieve gebruiker.Bovendien zijn er nog functies aanwezig in deze service om de gebruikersnaam, gebruikersrol, errors voor degebruiker, token te controleren en of de gebruiker extern of intern is, aan te vragen. Wanneer de gebruiker uitlogtwordt de functie 'clearUserData' aangeroepen. Zo wordt de volledige data van de gebruiker uit de variabelengehaald zodat het mogelijk is om aan te melden met een nieuwe gebruiker.

Util

De service 'Util' wordt gebruikt om de maanden om te vormen naar een integer of een string. Dit is nodig omdat inverschillende situaties de maanden gebruikt dienen te worden als integer of als string getoond dienen te worden.Vervolgens wordt in deze service de benaming van het type onkost omgezet. In de database worden deze in hetEngels opgeslagen. Om het voor de gebruiker duidelijker te maken wordt deze benaming omgezet naar eenNederlandse benaming om te tonen op het scherm. Deze bewerking gebeurt in deze service.

function convertExpenseTypeToName(type) { var nameOfType;

switch (type) { case "internet": nameOfType = "Internet"; break; case "GSM": nameOfType = "GSM"; break; case "Kilometerallowence": nameOfType = "Kilometervergoeding"; break; case "Transportation": nameOfType = "Vervoersvergoeding"; break; case "miscellaneous": nameOfType = "Diverse"; break; }

return nameOfType; }

WebpackWebpack is een module bundeler. Webpack neemt alle modules samen en bundelt deze in één grote file. In deoriginele staat zonder loaders of plugins kan webpack enkel JavaScript bestanden aannemen om in een bundel testoppen. Om het mogelijk te maken dat ook html-files, css-files en afbeeldingen in de bundel gezet kunnen wordenmoesten er dus loaders en plugins gebruikt worden.Om afbeeldingen te kunnen gebruiken wordt de loader 'image-webpack-loader' gebruikt. Om css-bestanden tekunnen gebruiken wordt de loader 'css-loader' toegevoegd. Vervolgens wordt er ook de plugin 'html-webpack-plugin' gebruikt om html-bestanden te kunnen toevoegen. Deze bestanden worden statisch behouden. In deconfiguratie file van webpack moet elke html-file toegevoegd worden door de 'html-webpack-plugin' aan te roepen.

25

Page 26: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Verder wordt in deze configuratie file het uitgangspad ingesteld. Dit is het pad waar de gebundelde file opgeslagenwordt. Om de JavaScript te gebruiken moet deze ook toegevoegd worden. Hiervoor is een bestand 'app'aangemaakt. In dit bestand worden alle JavaScript bestanden toegevoegd zodat deze gebruikt kunnen worden.

26

Page 27: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Aanmelden

De applicatie is een uitbreiding van het bestaande timesheet portaal, dat reeds beschikt over een login. Deze loginmaakt gebruik van het single sign-on systeem van de ADFS server. Enkel wanneer een externe gebruiker aanmeldtzal hij rechtstreeks verder kunnen gaan naar de timesheet applicatie. De externe gebruiker heeft geen recht omonkosten in te dienen en kan dus onze pagina niet zien na het inloggen. Als een interne gebruiker wenst aan temelden zal hij naar de intranet pagina moeten surfen en zich daar eerst aanmelden. Vervolgens kan hij op deintranet pagina een link aanklikken die hem doorverwijst naar de submit applicatie (timesheet en onkosten app).De link zal de gebruiker automatisch inloggen met de gegevens van de intranet pagina (dankzij ADSF). Indien eengebruiker rechtstreeks naar de onkosten applicatie surft krijgt hij de login-pagina te zien die gemaakt is voor hetonkosten gedeelte.

Het verschil tussen de twee login-schermen is dat een externe gebruiker zich niet kan aanmelden bij ons (geenrechten voor onkosten) en dat de pagina in angular geschreven is (andere login is knockout). Voor de internegebruiker blijft het hetzelfde zoals bij de timesheets (aanmelden op Intranet en dan terug surfen naar submit).

Aanmelden frontendWanneer de gebruiker de velden heeft ingevuld met zijn gegevens wordt een verzoek gestuurd naar de backend. Ditverzoek wordt door de controller van de log-directive opgebouwd. De gebruikersnaam en het wachtwoord wordengecodeerd via een base-64 ASCII string en worden in de header toegevoegd met de gepaste header-tag.Vervolgens wordt de URL opgehaald uit de back-end service en wordt het verzoek als een GET-verzoek verzonden.De data van de back-end bevat de informatie van de gebruiker en er wordt gekeken of de gebruiker een interne ofexterne werknemer is. Indien het een externe werknemer betreft wordt deze terug naar de login-pagina gestuurd,een interne werknemer wordt naar de Intranet pagina geleid waar hij zich kan aanmelden.

Alle data van een aangemelde gebruiker wordt bewaard in een service die overal beschikbaar is in de applicatie(mits de service wordt toegevoegd aan de directive controller).

27

Page 28: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Aanmelden backendIn de back-end roept de controller de gepaste service aan. In de service wordt de authenticatieheader gedecodeerden worden de gegevens van de gebruiker uit de database gehaald. Vervolgens wordt gekeken of degebruikersnaam en wachtwoord overeenkomen. Indien dit niet het geval is wordt de gepast error naar de front-endgestuurd. Als de gegevens correct zijn wordt de informatie van de gebruiker in een DTO gestoken en meegegevenaan de controller. De controller zal deze data terug doorgeven aan de front-end met de gepast http-status code.

28

Page 29: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

ConfiguratieschermVoor de office medewerker is het belangrijk dat hij kan instellen per werknemer op welke onkosten de werknemerrecht heeft. Ook is het bij bepaalde onkosten zoals internet- en gsmonkosten belangrijk dat er de mogelijkheid isom een maximaal bedrag in te voeren. Om dit mogelijk te maken wordt er een configuratiescherm opgebouwd.

FrontendBij het laden van de pagina wordt een GET-request naar de server gestuurd. Bij deze request worden allewerknemers opgevraagd om deze vervolgens in de lijst te tonen. Zo worden de voornaam, achternaam en hetbedrijf waarvoor ze werken in een lijst geplaatst. Deze velden zijn nodig zodat de office medewerker op deze veldenkan zoeken zodat de lijst aangepast wordt aan de hand van de naam van de werknemer of het bedrijf waarop deoffice medewerker zoekt. Om deze zoekfunctie mogelijk te maken wordt de gebruikerlijst in een bufferlijst gestoken.Hierdoor kan er op de bufferlijst filtering gebeuren en wordt volledige lijst bijgehouden voor wanneer de filterverwijdert zou worden. Met dit systeem kan de volledige lijst ten allertijde getoond worden.

Wanneer de office medewerker op een werknemer klikt wordt er een extra veld opengeklapt waar de configuratievan die werknemer in staat afgebeeld aan de hand van knoppen. Om dit mogelijk te maken moet er eerst eennieuwe GET-request gestuurd worden naar de server. Dit is nodig omdat de configuratie van de werknemeropgehaald moet worden. Vervolgens worden de knoppen ingekleurd aan de hand van de configuratie van dewerknemer. Als de werknemer recht heeft op de onkost wordt de knop 'vergoed' groen gekleurd, wanneer dewerknemer geen recht heeft op de onkost wordt de knop 'niet vergoed' rood gekleurd. Wanneer de werknemer rechtheeft op internet- of gsmvergoeding kan de office medewerker een maximum terug te betalen bedrag ingeven.Omdat de frontend de configuratie van de werknemer als JSON-string ontvangt van de server moet het maximumterug te betalen bedrag voor internet en gsm omgevormd worden naar een float. Dit is nodig omdat er op deinputvelden voor het maximaal terug te betalen bedrag een input type 'number' staat ingesteld. Dit wil zeggen dat erenkel getallen ingevoerd kunnen worden. Als het maximaal terug te betalen bedrag niet omgevormd wordt naareen float wordt het bedrag niet ingevuld en geeft dit errors. Om dit te voorkomen wordt er dus eerst een parseFloattoegepast.Wanneer de office medewerker op een knop klikt wordt er een POST-request naar de server gestuurd. Dit gebeurtook wanneer het maximaal terug te betalen bedrag wordt aangepast. In de POST-request wordt steeds devolledige configuratie naar de server gestuurd. Omdat de configuratie maximum zeven velden heeft waarvan er vijfenkel een boolean bevatten is dit maar een kleine hoeveelheid data dat naar de server gestuurd wordt waardoorhet mogelijk is om steeds de volledige configuratie naar de server te sturen.Wanneer er tussen twee werknemers gewisseld wordt, wordt de configuratie van de nieuwe aangeklikte

29

Page 30: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

werknemer opgehaald. Af en toe geeft de server hier wat vertraging op. Wanneer dit voorvalt en de officemedewerker begint de configuratie van de werknemer aan te passen wordt dus de verkeerde configuratie naar deserver verstuurd. Om dit te verhelpen wordt bij elke GET-request om de configuratie van een werknemer op te halende configuratie die reeds in het geheugen zit leeggemaakt. Vervolgens wordt er een spinner getoond met demelding dat de configuratie wordt opgehaald tot de configuratie effectief opgehaald is en de office medewerkergeen fouten meer kan maken door de vertraging die werd veroorzaakt door de request die naar de server werdgestuurd.

BackendOm de request van de frontend te kunnen verwerken wordt er in 'RequestMappings' gecontroleerd of de URL dieopgebouwd wordt in de frontend overeenkomt met een opgebouwde URL in deze klasse. In de url wordt de 'userId'meegegeven. In de bijhorende controller 'ExpenseConfigController' wordt de request op de URL verwerkt.

Wanneer er een GET-request verwerkt dient te worden roept de controller de functie 'getExpenseConfigUser' aanvan de service 'ExpenseConfigService'. Als parameter wordt de userId meegegeven die uit de URL gehaald wordt.In de 'expenseConfigService' wordt de functie 'findByUserId' aangeroepen van de DAO 'ExpenseConfigDao'. Alsparameter wordt de userId meegegeven die verkregen wordt bij het aanroepen van de functie'getExpenseConfigUser'. De DAO wordt vervolgens in de entiteit 'ExpenseConfig' ingevuld. Wanneer de entiteit danniet ingevuld is omdat de werknemer nog geen configuratie voor hem in de database had staan, wordt er eendefault configuratie ingesteld voor deze werknemer. Bij de default configuratie worden volgende velden ingevuld:

Internet: geen recht op vergoedingMaximaal bedrag voor internet: € 42Gsm: geen recht op vergoedingMaximaal bedrag voor gsm: € 0Kilometer: geen recht op vergoedingTransport: geen recht op vergoedingDiverse: recht op vergoeding

Vervolgens wordt deze data ingevuld in de DTO 'ExpenseConfigDto'. Wanneer de werknemer wel een configuratieop zijn naam had staan in de database wordt de dto 'ExpenseConfigDto' ingevuld met de data die uit de databasegehaald wordt. Wanneer de DTO is ingevuld wordt deze terug naar de frontend gestuurd, samen met een http-status '200'.

Wanneer er een PUT-request verwekt dient te worden roept de controller de functie 'setExpenseConfig' aan van deservice 'ExpenseConfigServic'. Als parameter wordt de body van de request en de userId die uit de URL gehaaldwordt mee gestuurd.In de 'expenseConfigService' wordt de functie 'findByUserId' aangeroepen van de DAO 'ExpenseConfigDao'. Alsparameter wordt de userId meegegeven die verkregen wordt bij het aanroepen van de functie 'setExpenseConfig'.De Dao wordt vervolgens in de entiteit 'ExpenseConfig' ingevuld. Als de entiteit 'ExpenseConfig' niet leeg zijnworden alle velden hiervoor ingevuld. De velden die altijd ingevuld worden zijn:

InternetGsmKilometerTransportDiverse

De velden die enkel ingevuld worden wanneer deze niet leeg zijn:

Maximaal bedrag internetMaximaal bedrag gsm

30

Page 31: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Vervolgens wordt de functie 'update' van de DAO 'ExpenseConfigDao' aangeroepen met als parameter de entiteit'ExpenseConfig'. Wanneer deze functie aangeroepen wordt, wordt de database ge-update met de nieuwe data.Nadit alles stuurt de controller nog een http-status '200' naar de frontend.

31

Page 32: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

IndienenBij het scherm indienen worden er twee views opgebouwd. De eerste view om in te dienen voor de werknemer,waarbij de gebruiker ook een overzicht te zien krijgt van zijn reeds ingediende onkosten, de tweede view is enkelzichtbaar voor de office medewerkers. In deze view kan de office medewerker een onkost indienen voor een anderewerknemer.

Indienen onkosten werknemerBij het indienen kan de gebruiker een maand selecteren. Vervolgens kan hij onderaan de pagina onder hetoverzicht van zijn reeds ingediende onkosten een nieuwe onkost indienen. Hier kan de gebruiker enkel een onkostindienen wanneer hij recht heeft op een terugbetaling van dat type onkost. Indien de gebruiker geen recht heeft opeen terugbetaling van een type onkost wordt dit type onkost verborgen voor hem. Het type onkost bepaalt welkvelden er ingevuld dienen te worden.

Frontend

Wanneer de pagina om onkosten in te dienen geladen is, wordt er meteen een GET-request naar de servergestuurd om de configuratie van de gebruiker op te halen. In de controller van de directive 'expenseSubmitDirective'wordt de functie 'getUserConfig' aangeroepen van de service 'UserConfig'. Als parameter wordt de userId van degebruiker meegestuurd. Vervolgens wordt in de service 'UserConfig' een GET-request naar de server gestuurd omde configuratie van de gebruiker op te halen. Wanneer deze ontvangen wordt van de server wordt dezedoorgestuurd naar de directive. In de directive wordt het maximaal terug te betalen bedrag van internet en gsmonkosten nog omgevormd naar een float. Dit is nodig om vervolgens het maximaal terug te betalen bedrag af teronden op twee decimalen. De configuratie van de gebruiker is nodig om de navigatiebalk onderaan op te bouwen.In deze tabbladen staan namelijk enkel de types onkosten waar de gebruiker recht op heeft om dat type onkostenin te dienen. Wanneer de gebruiker op geen enkele terugbetaling recht heeft wordt de boodschap 'U kanmomenteel geen onkosten indienen. Als u denkt dat dit een fout is, gelieve dan contact op te nemen [email protected]' getoond.Wanneer de gebruiker op een type onkost klikt wordt het bijbehorende tabblad geopend. Dit is voor elk type onkostanders opgebouwd. Dit is nodig omdat voor elk type onkost andere velden ingevuld dienen te worden.

Bij het indienen van een onkost wordt aangeduid met een rood sterretje welke velden verplicht zijn. Indien dezevelden niet ingevuld zijn kan de gebruiker niet op de knop 'Opslaan' klikken. Wanneer alle benodigde veldeningevuld zijn kan de gebruiker zijn onkost versturen naar de backend. Bij het indienen van een onkost is het ookverplicht om een betalingsbewijs mee op te slaan. Om dit mogelijk te maken wordt de bibliotheek 'ng-file-upload'

32

Page 33: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

gebruikt. Door deze bibliotheek te gebruiken wordt het mogelijk om een pop-up venster te openen wanneer er opde knop gedrukt wordt om bestanden op te selecteren. In dit pop-up venster kan de gebruiker dan een bestandselecteren om samen met de onkost in te dienen. Wanneer er een bestand geselecteerd is kan de gebruiker denaam en de grootte van het gekozen bestand zien. Indien de gebruiker een verkeerd bestand heeft geselecteerdheeft hij nog de mogelijkheid om het bestand weg te klikken en een ander te selecteren.Wanneer de gebruiker op de knop 'Opslaan' klikt wordt de functie 'uploadExpenses' aangeroepen. Als parameterwordt het type van de in te dienen onkost meegegeven. De URL wordt opgebouwd in de service 'backendFacade'.Dit gebeurt met de userId en het type onkost om zo de juiste URL op te bouwen die in de backend gebruikt kanworden. Vervolgens wordt er gecontroleerd wat het type van onkost is. Dit is nodig omdat er voor elk type onkostandere velden ingediend dienen te worden en er dus andere data naar de server gestuurd wordt. De data die doorde gebruiker ingevuld worden, worden omgevormd naar een JSON string om te kunnen versturen naar de server.Wanneer dit gebeurd is wordt er een POST-request uitgevoerd op de bijhorende link van het type onkost en met deingevulde data. Wanneer de POST-request uitgevoerd is wordt de functie 'uploadFiles' aangeroepen om het meeingediende bestand op te slaan.In de functie 'uploadFiles' wordt de URL opgebouwd, de benodigde headers ingevuld en de data ingevuld met hetbestand dat opgeslagen dient te worden. De URL wordt opgebouwd met de ID die men verkrijgt bij het opslaan vande onkost. Dit is nodig om de juiste bestanden aan de juiste onkosten te kunnen linken in de backend. Vervolgenswordt het bestand naar de server opgeladen door gebruik te maken van de bibliotheek 'ng-file-upload'. Wanneer hetbestand naar de server verstuurd is wordt de functie 'clearForm' aangeroepen. Deze functie maakt alle velden weerleeg zodat er een nieuwe onkost ingediend kan worden.

Backend

Bij het aanmaken van een onkost krijgt de backend een POST-request aan. Afhankelijk van het type onkost is dezeURL verschillend opgebouwd. Elk type onkost heeft namelijk zijn eigen URL om de onkost op te slaan. Vervolgenswordt de userId mee in de URL gezet in de frontend. Deze userId wordt uit de URL gehaald in de controller'ExpenseController'. De onkost zelf wordt uit de body gehaald van de POST-request. Vervolgens wordt de functieaangeroepen waar de onkost gemaakt werd. Hiervoor zijn er weer vijf verschillende functies omwille van deverschillende soorten onkosten. Deze vijf functies zijn beschreven in de 'ExpensesService'. Deze vijf verschillendefuncties hebben hetzelfde doel, namelijk de onkost opslaan in de database. Dit is opgesplitst in verschillendefuncties omdat er voor elke functie een andere DTO gebruikt dient te worden. De entiteit van het juiste type onkostwordt ingevuld met de DTO van het overeenstemmende type. Elke DTO van ieder type onkost is een uitbreiding opde 'DetailedExpenseDto'. Deze wordt ook steeds ingevuld met algemene data die voor elke onkost hetzelfde is.Wanneer de entiteit was ingevuld wordt deze data in de database geschreven door gebruik te maken van de'ExpensesDao'. Wanneer dit gebeurd is wordt de onkost toegevoegd aan de mailservice. De onkost krijgtautomatisch de status dat deze nog niet verwerkt is. Vervolgens wordt er een mail gestuurd naar de gebruiker datzijn onkost is aangemaakt.

Om het bestand mee op te slaan wordt er een afzonderlijke POST-request naar de server gestuurd op een andereURL, namelijk een URL enkel voorzien om REST-calls uit te voeren die te maken hebben met de bestanden die bijde onkosten hoorden. In 'ExpensesPdfController' wordt de POST-request verwerkt. De 'userId' en de 'expenseId'worden uit de URL gehaald en de effectieve bestanden worden uit de body gehaald. Deze requestmappingconsumeert namelijk multipart bestanden, terwijl bijna alle andere requestmappings JSON files consumeren.Vanuit de controller wordt de functie 'storeExpense' opgeroepen van de service 'multipartFileService'. Alsparameters worden de 'userId', 'expenseId' en het bestand meegegeven. In de functie 'storeExpense' wordt defunctie 'tryToReadFile' aangeroepen met het bestand als parameter. Vervolgens wordt het bestand geëncodeerdnaar een base64 en opgeslagen als een byte-array. De inhoud van het bestand wordt in een DTO gestopt en denaam van het bestand wordt overgenomen om mee op te slaan in de database.Om het juiste bestand terug te vinden dat bij een onkost hoort moet er een referentie meegegeven worden.Hiervoor wordt de 'expenseId' gebruikt. Vervolgens dient het bestand ook terug gevonden te kunnen wordenwanneer een gebruiker een onkost wil bekijken en het geüploade bestand dat erbij hoort ook wenst te zien. Om dit

33

Page 34: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

mogelijk te maken dient er een URL meegegeven te worden waar het bestand opgeslagen is. Om de URL teverkrijgen moest de onkost eerst ergens opgeslagen worden. De functie 'saveExpenseFileToDirectory' wordtaangeroepen van de service 'StorageService'. Als parameter wordt de byte-array meegegeven waar het bestand inzit en de entiteit van de onkost. In de functie 'saveExpenseFileToDirectory' wordt de functie'getNewFilePathForExpense' aangeroepen. In deze functie wordt de entiteit van de onkost meegegeven alsparameter, alsook wordt hier de URL naar het bestand opgebouwd. Dit op wordt opgebouwd op basis van deusername, het jaar, de maand en de huidige tijd in miliseconden. Op deze manier wordt er steeds een unieke URLopgebouwd naar het bestand zodat meerdere onkosten niet kunnen refereren naar hetzelfde bestand, tenzij ditbestand natuurlijk meerdere keren wordt geüpload voor verschillende onkosten. Vervolgens wordt het bestandweggeschreven in de map waar de URL naar refereert. Wanneer het bestand is opgeslagen wordt de URL naar hetbestand teruggestuurd naar de 'UploadService'.In de 'UploadService' wordt de functie 'isPdfFile' aangeroepen met de DTO 'TimeSheetAndExpenseFileDto' alsparameter. Hier wordt gecontroleerd of het bestandstype een pdf bestand is of niet. Dit gebeurt aan de hand van debestandsextensie.Als laatste functie wordt 'saveExpenseFile' aangeroepen met als parameters de ingevulde entiteit 'Expense', deURL naar het bestand, de naam van het bestand, het aantal bestanden en de boolean die aangeeft of het bestandeen pdf bestand is of niet. In de functie 'saveExpenseFile' wordt de entiteit 'ExpenseFile' ingevuld. In de entiteitworden volgende velden ingevuld:

isPdf: ingevuld aan de hand van de boolean isPdffilename: ingevuld aan de hand van de verkregen bestandsnaamexpUploadId: het ID van de bijhorende onkostfilePath: de locatie van het opgeslagen bestandorderData: de hoeveelheid bestanden

Vervolgens wordt de data opgeslagen in de database door gebruik te maken van de DAO 'ExpenseFileDao'.

Overzicht onkostenBij het overzicht kan de werknemer zijn reeds ingediende onkosten en hun statussen bekijken. Er wordt eenkalender opgebouwd met icoontjes die duidelijk maakt of er die maand nog onkosten in verwerking zijn of niet.Wanneer de werknemer een maand selecteert kreeg hij een overzicht van het aantal onkosten die reeds verwerktzijn of nog verwerkt dienen te worden. Onderaan krijgt hij een lijst met zijn reeds ingediende onkosten. In deze lijstkan hij een onkost aanklikken om hiervan een gedetailleerd overzicht te verkrijgen

34

Page 35: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Frontend

Wanneer de pagina van het overzicht geladen is, wordt er een GET-request naar de server gestuurd om tecontroleren of er voor de werknemer reeds onkosten ingediend zijn en welke status deze hebben. In de GET-request wordt er in de URL het geselecteerde jaar geplaatst en in de service 'backendFacade' wordt vervolgens deuserId ook in de URL geplaatst. Daarna worden de maanden overlopen om te zien wat de status van die maand isvoor de gebruiker. Eenmaal de gebruiker zijn onkosten allemaal verwerkt zijn wordt het vakje van de kalender groengekleurd en komt er een vinkje tevoorschijn. Als de gebruiker onkosten heeft ingediend maar deze nog nietverwerkt zijn, kleurt het kalendervakje blauw en komen er twee pijltjes tevoorschijn. Als de gebruiker voor diemaand geen onkosten heeft ingediend wordt het kleurt het vakje grijs zonder een icoontje erin. Bij het laden van depagina wordt de huidige maand opgevraagd via de service 'CalendarStateService' en wordt deze maandautomatisch geselecteerd. Bij het selecteren van een maand wordt het vakje omkaderd met een zwarte rand zodathet duidelijk is welke maand er geselecteerd is.Indien er een maand geselecteerd is, wordt het veld naast de kalender ook aangepast. Zo krijgt de gebruikermeteen een overzicht van de geselecteerde maand. In dit veld wordt getoond hoeveel onkosten er goedgekeurd,afgekeurd, in behandeling en onverwerkt zijn.Onder de kalender in het minieme overzicht wordt een lijst getoond van de reeds ingediende onkosten van degebruiker. In deze lijst krijgt de gebruiker een duidelijk overzicht van de status van de reeds ingediende onkosten.Wanneer een onkost afgekeurd is krijgt deze in het overzicht een rode kleur met een label 'Afgekeurd'. Wanneer eenonkost goedgekeurd is krijgt deze in het overzicht een groene kleur met een label 'Terugbetaald'. Wanneer eenonkost nog in verwerking is krijgt deze in het overzicht een gele kleur met een label 'In verwerking'. Wanneer eenonkost nog niet behandeld is krijgt deze in het overzicht een bruine kleur met een label 'Onverwerkt'.

Als de gebruiker op een onkost klikt uit de lijst wordt er een meer gedetailleerd overzicht getoond aan de gebruiker.In dit overzicht worden alle velden getoond die de gebruiker heeft ingevuld bij het indienen van zijn onkost. Wanneerde onkost behandeld wordt door een office medewerker wordt er een extra veld getoond dat de opmerkingen vande office medewerker bevat.

35

Page 36: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Om dit overzicht te tonen moet een nieuwe GET-request gestuurd worden naar de server. Deze request is nodig omde details van onkosten op te halen. In deze GET-request wordt de userID, de geselecteerde maand en hetgeselecteerde jaar toegevoegd. Vervolgens wordt de data die verkregen werd van de server verwerkt. Omdat deserver de data als JSON-string verstuurt moeten het bedrag en de afstand omgevormd worden naar een float omer verdere berekeningen mee te kunnen doen. Wanneer er een datum ingevuld is bij het indienen van de onkostwordt deze van de JSON-string ook omgevormd naar een date object. Op het einde wordt het type van de onkostomgevormd in de 'Util' service. Dit is nodig omdat de onkosten opgeslagen worden in het Engels. Om een mooieroverzicht te krijgen worden deze types omgevormd in de service 'Util' naar een Nederlandse benaming. Dezebenaming wordt gebruikt om de lijst op te bouwen die opengeklikt kan worden.Wanneer de gebruiker de onkost openklikt wordt er nog een tweede GET-request naar de server gestuurd. Dezewordt gestuurd om de naam van het geüploade bestand te verkrijgen dat bij de onkost hoort. Hiervoor wordt defunctie 'getPdfMetadata' aangeroepen van de service 'PdfRetriever'. Als parameter wordt de ID van de onkostmeegegeven. Vervolgens worden alle velden ingevuld met de verkregen data van de server.

Wanneer de onkost nog niet verwerkt is door een office medewerker kan de gebruiker zijn ingediende onkost nogaanpassen of verwijderen. Wanneer er een gedetailleerd overzicht van een onkost opgevraagd is, wordt er ook eenGET-request gestuurd om de configuratie van de gebruiker op te halen. Dit wordt gedaan om te controleren of degebruiker recht heeft om deze onkost in te dienen. Als de gebruiker hier geen recht toe heeft, kan hij de onkost nietbewerken. Als de gebruiker een onkost wil bewerken dient hij de velden die hij na aanpassing na aanpassing opde knop bewerken te klikken. Hierna wordt de functie 'updateExpense' aangeroepen met als parameter de ID vande onkost. In deze functie wordt gecontroleerd van welk type de onkost is zodat de juiste velden ingevuld kandenworden om naar de server te sturen. De URL die wordt opgebouwd om de PUT-request uit te voeren heeft alsparameter het type onkost en de ID van de onkost nodig. Deze wordten mee in de URL ingevuld. Wanneer deonkost succesvol is geüpdate komt er bovenaan een melding tevoorschijn die vermeldt dat de onkost succesvol isingediend. Wanneer de gebruiker op de knop verwijderen klikte wordt er een URL opgebouwd met de ID van deonkost als parameter. Vervolgens wordt er een DELETE-request naar de server gestuurd. Hierop volgend wordt ereen broadcast gestuurd om de kalender, notificaties en de lijst te updaten met de mogelijk veranderde statussendoor het bewerken van de onkost.

Backend

Wanneer de server een GET-request van de frontend aankrijgt om het jaaroverzicht op te vragen om de icoontjesvan de kalender in te vullen op de bijhorende URL, wordt er bij de 'ExpenseUserController' het jaar en de 'userId' uitde URL gehaald. Het jaar en de 'userId' worden vervolgens als parameter meegegeven wanneer de functie'getExpenseStateCountYearForUser' aangeroepen wordt van de service 'UploadService'. In deze functie wordt de

36

Page 37: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

'monthlyExpenseStateCountDto' opgevuld. Dit gebeurt met een for-loop zodat er over de twaalf maanden van hetaangegeven jaar wordt geloopt. Om deze op te vullen wordt in de for-loop de functie 'getUserExpenseState'aangeroepen. Als parameters worden de 'userId', maand en jaar toegevoegd bij het aanroepen van deze functie. Indeze functie wordt de DTO 'MonthlyExpenseStateCountDto' opgevuld. Dit gebeurde door de functie'findByUserAndDate' aan te roepen uit de DAO 'ExpensesDao'. Opnieuw wordt hier de 'userId', maand en jaarmeegegeven als parameter. Vervolgens controleert de DAO 'ExpensesDao' of er data in de database overeenstemtmet de 'userId', maand en jaar. Wanneer de data overeenstemt met de data uit de database wordt deze toegevoegdaan een lijst. Vervolgens wordt de status van de maand terug gestuurd naar de functie'getExpenseStateCountYearForUser'. Wanneer er over de twaalf maanden geloopt is wordt de status van elkemaand van het jaar in een lijst geplaatst en vervolgens als JSON data terug naar de frontend gestuurd om verwerktte worden.

Wanneer de server een GET-request van de frontend aankrijgt om de notificaties van de geselecteerde maand tetonen op de bijhorende URL wordt bij de 'ExpenseUserController' het jaar, de maand en de 'userId' uit de URLgehaald. Het jaar, de maand en de 'userId' worden vervolgens als parameter meegegeven wanneer de functie'getUserExpenseState' wordt aangeroepen van de service 'UploadService'. In de functie 'getUserExpenseState'wordt de DTO 'MonthlyExpenseStateCountDto' opgevuld. Dit gebeurt door de functie 'findByUserAndDate' aan teroepen uit de DAO 'ExpensesDao'. Opnieuw wordt hier de 'userId', maand en jaar meegegeven als parameter.Vervolgens controleerdt de DAO 'ExpensesDao' of er data in de database overeenstemt met de 'userId', maand enjaar. Wanneer de data overeenstems met de data uit de database wordt deze toegevoegd aan een lijst. Vervolgenswordt de status van de maand teruggestuurd naar de frontend om te verwerken.

Wanneer de server een GET-request van de frontend aankrijgt om een gedetailleerd overzicht te verkrijgen van deonkosten die de gebruiker die maand heeft ingediend op de bijhorende URL, wordt bij de 'ExpenseUserController'het jaar, de maand en de 'userId' uit de URL gehaald. Vervolgens worden het jaar, de maand en de 'userId' alsparameter meegegeven bij het aanroepen van de functie 'getDetailsExpenseUserForAdmin' van de service'UploadService'. In de functie 'getDetailsExpenseUserForAdmin' wordt een lijst opgevuld in de vorm van de entiteit'Expense'. Dit gebeurt door de functie 'findByUserAndDate' van de DAO 'ExpensesDao'. Bij het aanroepen van dezefunctie worden het jaar, de maand en de 'userId' meegegeven als parameter. Vervolgens wordt de lijst met deentiteiten van 'Expense' omgevormd naar een 'DetailedExpenseDto'. Hierna wordt de 'DetailedExpenseDto' teruggestuurd naar de frontend om daar verder verwerkt te worden.

Wanneer er een onkost geüpdatet dient te worden wordt er in de frontend in de URL reeds het type van onkostmeegegeven. Dit is nodig omdat bij elk type onkost andere velden dienen ingevuld te worden in de database. In decontroller 'ExpenseController' wordt bij elk type onkost de body van de PUT-request die door de server verkregenwordt uitgelezen en ingevuld in de overeenkomstige DTO van het juiste type onkost. De expenseId wordt uit de URLgehaald zodat de server weet welke onkost bewerkt dient te worden. Vervolgens wordt in de controller de juistefunctie aangeroepen die toebehoort bij het type onkost uit de service 'ExpensesService'. In de service'ExpensesService' wordt de functie 'update' aangeroepen. Als parameters worden meegestuurd: de bijhorendeDTO meegestuurd die ingevuld wordt met de data verkregen van de frontend, de 'expenseId' en de functie om allegemeenschappelijke velden van de DTO's om te zetten naar gemeenschappelijke velden van entiteiten.In de functie 'update' wordt eerst de huidige data van de onkost uit de database gehaald op basis van de expenseIddie meegegeven is als parameter bij het aanroepen van deze functie. Vervolgens wordt de status van de onkostgecontroleerd. Het is onmogenlijk om de onkost nog te bewerken indien deze in verwerking of reeds verwerkt is.Wanneer dit voorvalt wordt er een exception gestuurd waarin vermeld wordt dat de onkost niet meer bewerkbaar is.Indien de onkost nog bewerkbaar is wordt de data in de database geüpdate.

Wanneer de frontend een DELETE-request stuurt om een onkost te verwijderen wordt dit op de bijhorende URLgedaan. In de controller 'ExpenseController' wordt de 'userId' en de 'ExpenseId' uit de URL gehaald. Vervolgenswordt de functie 'deleteExpense' aangeroepen van de service 'ExpensesService'. Als parameters worden de useren de ExpenseId meegegeven. In de functie 'deleteExpense' wordt de entiteit 'Expense' opgebouwd door de juistedata op te halen met de DAO 'ExpensesDao'. De juiste data wordt verkregen door de 'expenseId' mee te geven metde GET-functie van de DAO. De juiste expense wordt uit de database opgehaald met behulp van de ExpenseId.

37

Page 38: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Vervolgens wordt ook de mailstatus opgehaald van deze onkost. Deze wordt ingevuld in de entiteit'ExpenseMailState' en dit gebeurt aan de hand van de DAO 'ExpenseTicketQueueDao'. De entiteit 'ExpenseFile'wordt ingevuld door de DAO 'ExpenseFileDao'. In deze DAO wordt ook de juiste expense aangeroepen door gebruikte maken van de 'expenseId'. Wanneer de 'userId' overeenstemt met de 'userId' die opgeslagen staat in dedatabase bij de onkost en de onkost nog niet in verwerking is, wordt deze verwijderd uit de database door de deletefunctie aan te roepen. Vervolgens wordt er gecontroleerd of de onkost reeds een mail in de database heeft staandie uitgestuurd zal worden en of er een bestand mee opgeladen is bij het indienen van de onkost. Wanneer dit hetgeval is wordt de mail en het bestand ook uit de database verwijdert.

Indienen onkosten andere gebruikerWanneer een office medewerker ingelogd is kan deze persoon ook een onkost indienen voor een anderewerknemer. Als dit gebeurt dient de onkost meteen goedgekeurd te worden. Dit is nodig omdat een officemedewerker de onkost voor een andere werknemer indient en dus automatisch hun goedkeuring hiervoor geeft.

Frontend

Om als office medewerker een onkost voor een andere gebruiker in te kunnen dienen moet de office medewerkernatuurlijk de juiste werknemer kunnen selecteren. Op deze pagina dient de office medewerker dus eerst eenwerknemer te selecteren alvorens een maand geselecteerd kan worden.

Om te zoeken naar een gebruiker wordt de directive 'md-autocomplete'14 gebruikt. Wanneer de directive geladenwordt, wordt meteen de functie 'getAllUsers' uitgevoerd. In deze functie wordt er een GET-request gestuurd. Om deURL op te bouwen wordt de functie 'getAllUserNamesAndIdsUrl' aangeroepen van de service 'backendFacade'. Alsheader wordt het Content-Type ingesteld op JSON. Vervolgens wordt de GET-request uitgevoerd. Nadien wordt deresponse data die verkregen is opgeslagen in een variabele. Waarna er een lijst opgebouwd wordt met allegebruikers in. Dit gebeurt nadat alle gebruikers in de variabele gemapt zijn. Dit is nodig om alle namen van degebruikers in kleine letters om te vormen. Zo kunnen er geen fouten optreden wanneer de gebruiker eenwerknemer zocht en bijvoorbeeld de hoofdletter vergeet in het begin van de naam.Wanneer men de selectie van de directive verandert, wordt er gecontroleerd of de selectie leeg is of niet. Wanneerer geen gebruiker geselecteerd is wordt de maand gedeselecteerd en wordt de boolean'UserSelectedPayForEmployee' op 'false' gezet. Deze boolean is nodig om te controleren of de gebruiker eenonkost voor zichzelf indient of dat de gebruiker een onkost indient voor een andere werknemer. Als er wel eengebruiker geselecteerd wordt, wordt de boolean 'UserSelectedPayForEmployee' op true gezet en vervolgens wordtde 'userId' van de geselecteerde gebruiker ingevuld in een variabele.Hierna wordt er een broadcast gestuurd metdaarin de boolean 'UserSelectedPayForEmployee' en de 'userId' van de geselecteerde werknemer.Wanneer de broadcast opgevangen wordt in de directive om een onkost voor een andere gebruiker in te dienenwordt de configuratie van de geselecteerde gebruiker opgehaald. Dit gebeurt door de 'userId' van de geselecteerde

38

Page 39: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

gebruiker in te vullen in de URL die opgebouwd is in de service 'backendFacade' om de configuratie van degebruiker op te halen. Vervolgens wordt weer het maximaal terug te betalen bedrag van internet-en gsmonkostenomgevormd naar een float om af te kunnen ronden op twee decimalen.

Bij het indienen van een onkost voor een andere gebruiker wordt dezelfde directive gebruikt om een onkost voorzichzelf in te dienen. Bij het laden van de directive wordt er gecontroleerd of er een onkost ingediend dient teworden voor de huidige gebruiker of voor een andere gebruiker. Wanneer de onkost voor een andere gebruikeringediend dient te worden wordt de 'userId' van de geselecteerde gebruiker ingesteld om de onkost in te kunnendienen. Wanneer de functie 'uploadExpenses' wordt aangeroepen wordt er gecontroleerd of er voor de huidigegebruiker of voor een geselecteerde gebruiker een onkost ingediend dient te worden. Als dit voor een anderegebruiker is wordt er een URL opgebouwd op basis van het type onkost en de 'userId' van de geselecteerdegebruiker. Verder wordt er gecontroleerd welk type onkost er ingediend is. Dit is nodig om de bijbehorende veldenin te vullen aangezien deze allemaal verschillend zijn voor elk type onkost. Nadien wordt de POST-request verstuurdnaar de server op de bijhorende URL met de correcte data.Aansluitend hierop wordt ook het bestand verstuurd naar de backend dat bij de ingediende onkost hoort. De ID dieverkregen wordt door de response van het indienen van de onkost wordt gebruikt om de URL op te bouwen om hetbestand op te slaan. Dit wordt gedaan zodat de juiste onkost aan het juiste bestand gelinkt kan worden. Hetbestand wordt vervolgens geüpload door gebruik te maken van de bibliotheek 'ng-file-upload'. Wanneer dit gebeurdis worden alle velden leeggemaakt zodat er een nieuwe onkost ingediend kan worden.

Backend

Wanneer de server een POST-request aankrijgt op de bijhorende URL om een onkost in te dienen voor een anderegebruiker, is er in de controller 'ExpenseAdminController' voor elk type onkost een andere URL voorzien. Uit de URLwordt de 'userId' gehaald en uit de body van de POST-request wordt de effectieve data gehaald. De data en de'userId' wordt meegegeven aan de functie die aangeroepen wordt die overeenstemt met het type onkost datingediend wordt. Vervolgens wordt de entiteit van het overeenkomstige onkosttype ingevuld door gebruik te makenvan de bijhorende DTO. Dit proces verliep exact hetzelfde als bij het opslaan van een onkost die een gebruiker voorzichzelf indiende. Het enige verschil tussen deze twee was terug te vinden in de controller. Bij het indienen van eenonkost voor een andere gebruiker wordt de status van de onkost aangepast. Wanneer een office medewerker eenonkost indient voor een andere gebruiker wordt de status van de onkost meteen ingesteld op goedgekeurd maarnog niet terugbetaald. Dit gebeurt in de functie 'adminChangeState' in de service 'ExpensesService'. Bij hetaanroepen van deze functie wordt de ID van de onkost meegegeven als parameter. De entiteit 'Expense' wordtingevuld door gebruik te maken van de DAO 'ExpensesDao' met als parameter de ID van de onkost. Wanneer dezeingevuld is in de entiteit wordt de status van de onkost veranderd naar goedgekeurd, maar nog niet betaald. Als ditgebeurd is wordt de data in de database geüpdate door opnieuw gebruik te maken van de DAO 'ExpensesDao'. Ophet einde geeft de controller een response op de POST-request met daarin de ID van de ingediende onkost en eenhttp-status 200.

39

Page 40: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Administrator en Betaler

De uitleg hieronder gaat over zowel administrator als betaler omdat de pagina's er totaal hetzelfde uitzien en doen.Enkel de statusveranderingen van de onkosten verschillen (administrator keurt goed en betaler betaalt). Deadministrator kan na het inloggen navigeren naar het beheermenu van de onkosten (administrator keurt onkostengoed of af, betaler betaalt onkosten of kan ze afwijzen). Hier krijgt men een overzicht dat je kan onderverdelen in vierdelen:

KalenderNotificatieschermFilterLijst (met werknemers)

De administrator krijgt direct alle gebruikers te zien die in de huidige maand onkosten hebben ingediend. In denotificatiebalk is ook een telling te zien waaruit hij kan afleiden hoeveel onkosten er dienen verwerkt te worden.Wanneer er op de kalender van datum veranderd wordt zullen de andere velden op de hoogte gebracht worden vande verandering van de maand. Deze zullen de nodige verzoeken naar de backend sturen om hun data bij te werken.Dankzij Angular te gebruiken zal de gebruiker enkel merken dat de velden andere waarden krijgen en dat de paginaniet herladen moet worden voor de update zichtbaar te maken. Nadat de administrator de gewenste maandgeselecteerd heeft kan hij in de filter gewenste filteringen toepassen (sorteren per bedrijf, nog te verwerken,...).Deze filteringen zijn direct merkbaar op de lijst eronder en kunnen ongedaan worden door op de reset knop teduwen. Alsook is het mogelijk om te filteren op naam, bedrijf,... door op de pijlen te duwen in elke hoofding van detabel. Nadat de gewenste persoon gevonden is drukt de administrator op zijn balk. Deze balk bevat de informatievan de werknemer zoals zijn naam, bedrijf en of alle onkosten verwerkt zijn voor hem of niet. Alsook kunnen debalken twee kleuren hebben: groen (alle onkosten voor de werknemer zijn verwerkt, dit kan goed- of afgekeurd zijn)en geel (er zijn nog onkosten die verwerkt dienen te worden).De balk zal openschuiven en alle onkosten weergevendie deze persoon heeft ingediend. In elke onkostenbalk is te zien over welk type onkost het gaat en de huidigestatus waarin de onkost zich bevindt. Bij alle onkosten zal ook een bedrag te zien zijn. Bij een internet-onkost eneen gsm-onkost is dit bedrag afhankelijk van de configuratie van de gebruiker. Indien de gebruiker een onkost heeftingediend dat de maximale waarde overschrijdt zal het maximale bedrag waar hij recht op heeft te zien zijn in debalk. Hierdoor weet de administrator dat hij maximaal dit bedrag hoeft te betalen (in onkost zelf staat ook nog extrainfo over het bedrag, hier later meer over). Indien de gebruiker een bedrag heeft ingediend dat minder was als hetmaximaal toegelaten bedrag, zal dit in de balk staan. Deze balken hebben dezelfde kleurencode als de grote balkmet de gebruikersinfo in, enkel kan hier nog een derde kleur bijkomen: rood (onkost is afgekeurd). Door op dekleinere balk van de onkost te duwen wordt deze opengevouwen. De administrator krijgt nu een duidelijk overzichtvan de informatie van de onkost. Indien hij de bijlage van de onkost wenst te bekijken kan hij (indien een pdf) op de

40

Page 41: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

link van de bijlage duwen en wordt deze geopend in een speciale pdf-viewer. In deze viewer kan de administratornavigeren tussen de verschillende pagina's van de pdf. Indien hij deze wenst af te drukken kan hiervoor op hetprint-icoontje gedrukt worden (links bovenaan). Dit zal alle pagina's van de pdf afdrukken met de datum van deafdrukdatum in de linker bovenhoek. Na het bekijken/afdrukken van de pdf kan deze terug gesloten worden door opde "sluiten" knop te duwen (rechts bovenaan). Indien de bijlage niet een pdf is zal de link de bijlage downloaden.Het is ook mogelijk om een download van de bijlage te starten door op de download knop te duwen rechts van debijlage.

Rechts onderaan (naast de goedkeuren/afkeuren knoppen bij administrator of betaler/afkeuren bij betaler) staathet bedrag dat ingediend is geweest en het bedrag dat terugbetaald dient te worden. Bij internet en gsm onkostenstaat er een extra veld met "Maximum bedrag" nog bij. Hierdoor weet de administrator of het maximaal bedragoverschreden is geweest of niet. Het is perfect mogelijk dat een gebruiker een hoger dan maximaal bedrag indient.De administrator betaalt dan enkel het maximaal toegewezen bedrag terug. Wanneer de administrator alle veldenheeft nagekeken kan hij de onkost goed- of afkeuren. Alsook kan hij een commentaar toevoegen aan de onkost.Veranderingen worden automatisch opgeslagen en geüpdate dus men kan direct naar een andere onkost gaanom deze te keuren zonder last te hebben van verloren data. Statusveranderingen van de onkost zijn ook directzichtbaar in het overzicht van de onkosten. Een onkost kan vier verschillende statussen hebben:

Onverwerkt: de onkost is ingediend, administrator moet deze nog goed- of afkeurenIn verwerking : de onkost is door de administrator goedgekeurd en doorverwezen naar de betalerTerugbetaald : de onkost is door de betaler betaaltAfgekeurd : de administrator of de betaler heeft de onkost afgekeurd

KalenderDe kalender geeft de administrator een duidelijk overzicht van alle maanden waar nog onkosten gekeurd dienen teworden. Een maand kan drie iconen hebben met elk een betekenis. De administrator kan de huidige maandveranderen door op de knop van een ander maand te duwen. Voor elk verschillend scherm wordt de datumopgeslagen in een kalenderservice. De datums worden in objecten opgeslagen met een ID die uniek is voor elkscherm. Hierdoor kan op elk moment de laatst geselecteerde datum opgevraagd worden van elk scherm.

Het grijze icoon stelt een maand voor waar geen werk voor gepland is. Wanneer er onkosten zijn die nog gekeurd ofbetaald dienen te worden wordt het blauwe icoon met dubbele pijlen gebruikt. Indien er voor de maand geenonkosten gekeurd of betaald dienen te worden zal er een groen icoon te zien zijn met een vinkje in.

Frontend

Als er op de knop van een maand gedrukt wordt zal de controller van de kalender een update naar de kalender-service doen. Deze update de datum van het huidige venster in de service naar de datum die men net heeftaangeklikt. De iconen van de kalender worden geladen zodra de pagina zichtbaar wordt voor de administrator. Omhet icoon te bepalen stuurt de kalender controller een verzoek naar de backend. Dit verzoek wordt opgebouwd in de

41

Page 42: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

controller die alle velden bevat van het administrator beheerscherm. Het begint met de correcte URL op te vragenaan de backendFacade service. Deze service zal dan de URL teruggeven die nodig is om de gewenste gegevensop te vragen. Wanneer de URL opgebouwd is worden de headers van het verzoek ingevuld en data toegevoegd.Deze toegevoegde data is leeg maar wel nodig. Indien we deze GET-request zouden verzenden zonder datazouden de headers vervallen. Dit zorgt er dan voor dat alle verzoeken worden afgekeurd omdat de token in deheaders zit. Alle info zoals de URL en headers wordt dan meegegeven aan de doGet() methode van debackendFacade service. Deze voegt de nodige token-header toe aan het verzoek en regelt de verdere afwerking vanhet verzenden.

Nadat het verzoek succesvol verwerkt is door de backend (en er dus data wordt verkregen) wordt het door debackendFacade (bij succes) teruggegeven aan de controller die de service aanriep. Indien er een foutmelding zouoptreden wordt dit door de 'backendFacade' service afgehandeld. De data die verkregen wordt van het verzoekbevat een telling voor de notificaties. Afhankelijk van de getallen wordt er uit afgeleid of de administrator/betaler nogwerk heeft. Dit wordt gedaan voor elke maand dus er moet een loop worden gedaan over de maanden.

response.data.forEach(function (monthNotification) { self.noWorkPlanned[self.IconForMonth] = monthNotification.TO_BE_PROCESSED === 0; self.noActionsDone[self.IconForMonth] = (monthNotification.PROCESSED_UNPAYED === 0 && monthNotification.TO_BE_PROCESSED === monthNotification.DENIED === 0 && monthNotification.PROCESSED_PAYED === 0); self.IconForMonth++; });

In de directive wordt dan gekeken of er waarden op true staan voor het overeenstemmende icoon. Indien eenmatch wordt gevonden wordt de css van de button vervangen door de bijhorende css.

<button class="btn btn-month" ng-if="vm.monthSelected[vm.monthsArr.indexOf(month)] == false || vm.monthSelected[vm.monthsArr.indexOf(month)] == undefined " ng-disabled="vm.userSelectedPayForEmployee == false" data-ng-class=" [vm.noActionsDone[vm.monthsArr.indexOf(month)] == true ? 'month-no-actions btn-calendar-no-actions' : vm.noWorkPlanned[vm.monthsArr.indexOf(month)] == true ? 'month-approved btn-calender-approved' : vm.noWorkPlanned[vm.monthsArr.indexOf(month)] == false ? 'month-in-progress btn-calender-work' :'month-no-actions btn-calendar-no-actions']" ng-click="vm.selectedMonth(month)">{{month}} </button>

De kalender update ook elke keer wanneer een onkost geüpdate wordt. Dit wordt gedaan om altijd het correctestatusicoon van een maand correct weer te geven. Hierdoor kan men er altijd van uitgaan dat het icoon de juistestatus van de maand aangeeft en men dus niet naar onkosten die verwerkt moeten worden aan het zoeken is alser geen meer zijn.

Backend

Wanneer het verzoek van de frontend binnenkomt zal de toegewezen controller het verzoek verwerken. Deze roeptdan de nodige services aan die de informatie ophalen en verwerken. Voor het bepalen van de iconen wordtdezelfde URL gebruikt als die voor het instellen van de notificaties van de administrator/betaler. De service diehierdoor aangeroepen wordt heeft ook een jaartal nodig. Deze wordt meegegeven in de URL en wordt door decontroller eruit gehaald en aan de service meegegeven in de methode als parameter. De service zal dan voor elkemaand van het meegegeven jaar een telling maken van alle statussen van een onkost. Dit wordt gedaan door in dedatabase te zoeken naar alle onkosten met hetzelfde jaartal (dat werd meegegeven) en maand (er wordt een loopgedaan voor elke maand) en deze in een lijst te steken. Deze lijst wordt dan aan vier verschillende functiesmeegegeven. Elk van deze functies controleert op een bepaalde status van de onkosten en zal een teller bijhoudenvoor elke keer wanneer een match gevonden wordt. Deze tellers worden dan terug aan de methode bezorgd. Allevier de resultaten van de telling worden dan in een object gestoken en toegevoegd aan de resultatenlijst. Deze lijst

42

Page 43: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

zal dan bestaan uit twaalf objecten (voor elke maand één object) en wordt teruggeven aan de controller nadat alletellingen voltooid zijn. De controller stuurt het resultaat dan terug naar de frontend samen met de bijpassende http-satus code.

controller die aangeroepen wordt

@RequestMapping(value = RequestMappings.EXPENSE_MANAGEMENT_YEAR_WORK, method = RequestMethod.GET, consumes = ContentType.APPLICATION_JSON, produces = ContentType.APPLICATION_JSON) public ResponseEntity<List<MonthlyExpenseStateCountDto>> getYearWork(@PathVariable final Integer year) { final List<MonthlyExpenseStateCountDto> result = uploadService.getExpenseStateCountForYear(year); return new ResponseEntity<>(result, HttpStatus.OK);

}

methode die door service wordt aangeroepen

@Override public List<MonthlyExpenseStateCountDto> getExpenseStateCountForYear(final Integer year){ int amountOfMonths; List<MonthlyExpenseStateCountDto> monthlyExpenseStateCountDtoList = new ArrayList<>(); for(amountOfMonths = 1; amountOfMonths <= 12; amountOfMonths++){ monthlyExpenseStateCountDtoList.add(getExpenseStateCount(amountOfMonths,year)); } return monthlyExpenseStateCountDtoList; }

opzoeken per maand en telling uitvoeren

@Override public MonthlyExpenseStateCountDto getExpenseStateCount(final Integer month, final Integer year) { final MonthlyExpenseStateCountDto monthlyExpenseStateCountDto = new MonthlyExpenseStateCountDto(); final List<Expense> expense = expensesDao.findByDate(month, year); stateCountExpense(monthlyExpenseStateCountDto, expense); return monthlyExpenseStateCountDto; }

NotificatieschermHet notificatievenster geeft de administrator/betaler een overzicht van de hoeveelheid werk er nog te doen is. Ditgebeurt aan de hand van enkele symbolen (die een status van de onkost voorstellen), gevolgd door debijpassende zin voor het type onkost (bv. Onkosten die goedgekeurd/betaald zijn: ). Hierachter een cijfer dat hetaantal onkosten voorstelt die aan de status voldoen.

43

Page 44: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Frontend

Deze waarden veranderen direct wanneer men de datum verandert. Dit gebeurt door een signaal uit te zenden naarde controllers die afhankelijk zijn van de tijd of van een status van de onkosten. Deze trigger kan dan wordeningesteld om specifieke controllers aan te spreken en enkel de controllers die actief zijn (dus het scherm datopenstaat, bv. betaler- of administratorscherm). Bij het ontvangen van deze trigger zal de controller van denotificaties een verzoek sturen naar de backend om de laatste update te krijgen van de notificaties. Hiervoor wordteen jaartal en een maand meegegeven (de huidig geselecteerde maand en het jaartal). Dit verzoek wordt opdezelfde manier opgebouwd als het verzoek dat de kalender stuurt naar de backend. De URL's lijken ook erg opelkaar met als verschil dat er nog een maand wordt aan toegevoegd. Nadat de backend het verzoek heeft verwerktzal de gewenste data teruggestuurd worden. De data die verkregen wordt is een object met de statussen van deonkosten als attributen en het resultaat van de telling in de backend naast het gepaste status-attribuut. Op dezevelden wordt dan een binding gedaan met Angular zodat deze automatisch de directive updaten nadat deinformatie veranderd is.

Verzoek voor notificaties van een maand (met jaartal)

function getNotificationForChosenMonthAndYear() { if (self.calendarId == 'admin_approve') { self.url = backendFacade.getNotificationUrlAdmin(CalendarStateService.getMonth("admin_approve"), CalendarStateService.getYear(self.calendarId)); } else if (self.calendarId == 'payer_approve') { self.url = backendFacade.getNotificationUrlPayer(CalendarStateService.getMonth("payer_approve"), CalendarStateService.getYear(self.calendarId)); } self.currentMonth = Util.getMonthString(CalendarStateService.getMonth(self.calendarId)); self.config = { headers: { 'Content-Type': 'application/json' }, data: '' };

backendFacade.doGet(self.url, self.config).then(function (response) { self.notifications = response.data; }); }

Het verzoek van de frontend wordt opgevangen door de bijhorende controller (die gemapt is door de request-mapper). De controller roept dan een service aan die een jaartal en maand verwacht. Deze worden aangebodendoor de controller die ze uit de URL haalt van het verzoek. De aangeroepen methode van de service zal een DAOaanspreken voor alle onkosten op te zoeken met de meegegeven maand en jaartal. Deze resultaten worden dan ineen lijst terugbezorgd aan de service. Nadat er een lijst is verkregen wordt deze meegegeven aan een functie diede tellingen zal uitvoeren voor alle types van onkosten. De tellingen worden gerealiseerd door de lijst mee te gevenaan een functie die een specifieke status verwacht van een onkost. In de functie wordt over de lijst gegaan en voorelke onkost wordt de status opgevraagd. Indien de status van de onkost voldoet aan de statuscheck van de functiezal de teller stijgen. Het resultaat van de telling wordt dan teruggegeven aan de functie die de teller functie aanriep.Alle resultaten van de verschillende tellers worden dan in een object gestoken met volgende attributen:

TO_BE_PROCESSED (komt overeen met QUEUED status van een onkost, te verwerken)PROCESSED_UNPAYED (komt overeen met aprover_unpayed status van een onkost, verwerkt maar nog nietbetaald)PROCESSED_PAYED (komt overeen met processed_payed status van een onkost, verwerkt en betaald)DENIED (komt overeen met denied status van een onkost, afgekeurd)

44

Page 45: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Elk van deze attributen krijgt dan de waarde van de tellingen nog toegevoegd. Dit object wordt dan terugbezorgdaan de controller. De controller zal op zijn beurt het resultaat terugbezorgen aan de frontend met bijhorende http-status code.

Controleren of een onkost de afgekeurd status heeft

private Integer countDenied(final List<Expense> allByYearAndMonth) { Integer denied = 0; for (final Expense expense : allByYearAndMonth) { if (ExpenseState.DENIED == expense.getStateOfTheExpense()) { denied++; } } return denied; }

Filter

Wanneer de administrator/betaler specifiek op een bepaalde manier wenst te zoeken kan hij gebruik maken van defilter. Hiermee is het mogelijk om op verschillende manieren te zoeken, zoals op bedrijf, nog te keuren (of alverwerkt), op naam of alles tesamen. De filter kan ook terug worden gereset door op de reset knop te duwen.

Frontend

Wanneer de gewenste maand geselecteerd is in de kalender zal de controller om de onkosten binnen te halen eenverzoek naar de backend sturen om alle gebruikers te geven die in de periode onkosten hebben ingediend. Dezelijst wordt dan doorgespeeld aan de filter door deze mee te geven aan de onderliggende directive van de filter . Delijst wordt dan in een variabele genaamd 'userDataStorage', hierdoor zal de originele lijst altijd beschikbaar zijndoor de variabele aan te roepen. Vervolgens wordt de 'userDataStorage' variabele in een andere variabelegestoken genaamd 'filteredUserDataStorage'. Deze variabele zal altijd het gefilterde resultaat bevatten. De bindingvan de lijst is dan ook op deze lijst gedaan, met als resultaat dat elke verandering op de variabele direct zichtbaar isop de frontend. De filter zit in een service en kan direct worden aangeroepen vanuit elke controller. Wanneer eenbepaalde filter gebruikt moet worden, wordt een lijst meegegeven waarop de filtering moet gebeuren en het typevan filtering dat uitgevoerd moet worden. De filter bestaat uit een lijst met attributen die op true/false worden gezetwanneer een filter geactiveerd dient te worden. Nadat deze lijst aangepast is om de gewenste filtering uit te voerenworden de geactiveerde filters aangeroepen om de lijst te filteren. Het resultaat wordt dan in de lijst terug bezorgdaan de controller die de service aanriep. In dit geval wordt het resultaat in de 'filteredUserDataStorage' gestoken.

Filter zoeken op naam

Er is een binding uitgevoerd op 'username.id', deze variabele wordt ingevuld door de administrator bij 'zoeken opnaam'. Indien de naam ingevuld is zal de filter worden aangesproken door een signaal te zenden (broadcast). Defilter is afgestemd om hiernaar te luisteren en zal hierop de filtering uitvoeren. De filter weet welke type filteringuitgevoerd dient te worden dankzij de 'filter' variabele die meegestuurd wordt.

45

Page 46: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

function selectedChanged(username) { if (username !== undefined) { self.filterData.userId = username.id; applyFilter('searchByName'); } else { self.filterData.userId = undefined; applyFilter('searchByName'); } }

function applyFilter(filter) { filter = { name: filter, userId: self.filterData.userId, company: self.filterData.selectedCompany }; if (filter.name == 'reset') { reset(); } $rootScope.$broadcast('apply-filter', filter); }

Lijst met werknemers

Geeft de administrator een overzicht van alle gebruikers die voor de geselecteerde tijdsperiode onkosten hebbeningediend. Deze lijst wordt ook direct vervangen wanneer men van maand veranderent of wanneer een onkost uitde lijst wordt goedgekeurd. Dit zorgt ervoor dat de lijst altijd up-to-date is met de laatste veranderingen die gebeurdzijn en dit zonder één pagina te hoeven herladen. De gebruikers in de lijst hebben een specifieke status enkleurcode om aan te duiden of er nog onkosten verwerkt dienen te worden. Wanneer men op de gebruiker klikt zaldeze openklappen en alle onkosten laten zien die de gebruiker voor deze tijdsperiode heeft ingediend. Bij het

46

Page 47: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

aanklikken van een gebruiker zal dan de lijst met onkosten te zien zijn van de gebruiker. Bij het openvouwen vaneen onkost kan de administrator/betaler de onkost keuren/betalen en een commentaar toevoegen. Na hetkeuren/betalen zal de lijst updaten.

Frontend

Bij het laden van de controller van de lijst wordt er een verzoek naar de backend gestuurd die alle gebruikersopvraagt die in de geselecteerde tijdsperiode een onkost hebben ingediend. Wanneer de backend de lijst aan defrontend geeft wordt de lijst in de 'filteredUserDataStorage' variabele gestoken en aan een Angular bindinggehangen. Dit zorgt ervoor dat de lijst constant up-to-date blijft bij wijzigingen aan de variabele waar de lijst zich inbevind. Elke gebruiker wordt ingevuld door te itereren over de lijst en voor elke gebruiker een rij in de tabel van delijst aan te maken. De info van de gebruiker wordt dan uit de attributen gehaald en in de overeenkomende rijgestoken. Om onkosten van de gebruiker op te vragen wordt bij de 'on-click' functie die op de lijst hangt de ID vande werknemer uitgelezen (gebruikmakend van de indexnummer die de werknemer in de lijst heeft). De ID wordtverkregen door de ID op te vragen uit de lijst van de werknemers op positie X (x stelt de indexnummer voor).Vervolgens wordt een verzoek gestuurd naar de backend om de onkosten van de gebruiker met overeenkomendeID op te halen (en met de huidige geselecteerde tijdsperiode). Dit wordt dan teruggegeven en in een tweede lijstgeplaatst (de lijst bevindt zich in de eerste lijst tussen de geselecteerde gebruiker en de volgende in de hoofdlijst).Wanneer de administrator/betaler een statuswijziging wenst te doen op een onkost wordt de ID van de onkost uitdeze lijst gehaald en in de url gestoken die nodig is om het verzoek naar de backend te sturen. De ID van de onkostwordt verkregen door de onkost op te vragen van IndexLijst-X van de Hoofdindex-X positie. Dit wil zeggen de onkostop de X positie (die aangeklikt is geweest en dus opengeklapt is) van de gebruiker die opengevouwen is. De IDwordt dan in een URL gestoken en als PUT-verzoek gestuurd naar de backend. Dit verzoek bevat in zijn body ook destatus die de onkost dient te krijgen en de commentaar van de administrator/betaler. Nadat de backend het verzoekheeft verwerkt zal de frontend opnieuw de onkosten inladen om de laatste nieuwe data te hebben.

Lijst met gebruikers

47

Page 48: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

<table class="table table-bordered table-striped panel-group" id="expenseUserMainTable"> <thead> <th class="row"> <span class="col-lg-9 col-md-9 col-sm-9 col-xs-12">Voornaam: </span> <i id="btn-firstname-sort" ng-click="vm.sort('firstname')" class="glyphicon glyphicon-sort col-lg-1 col-md-1 col-sm-1 col-xs-12 text-center-cs btn-no-background"></i> </th> <th class="row"> <span class="col-lg-9 col-md-9 col-sm-9 col-xs-12">Achternaam: </span> <i id="btn-lastname-sort" ng-click="vm.sort('lastname')" class="glyphicon glyphicon-sort col-lg-1 col-md-1 col-sm-1 col-xs-12 text-center-xs btn-no-background"></i> </th> <th class="row hidden-xs"> <span class="col-lg-9 col-md-9 col-sm-9 col-xs-12">Bedrijf: </span> <i id="btn-company-sort" ng-click="vm.sort('company')" class="glyphicon glyphicon-sort col-lg-1 col-md-1 col-sm-1 col-xs-12 text-center-xs btn-no-background"></i> </th> <th class="row"> <span class="col-lg-9 col-md-9 col-sm-9 col-xs-12">Status: </span> <i id="btn-status-sort" ng-click="vm.sort('statusAdmin')" class="glyphicon glyphicon-sort col-lg-1 col-md-1 col-sm-1 col-xs-12 text-center-xs btn-no-background"></i> </th> </thead> <tbody>

<tr data-target="#accordion-{{$index}}" ng-repeat-start="user in vm.filteredUserDataStorage" ng-click="vm.getDetailedExpenseForUser(user.user_id) ; vm.toggle($index); vm.getUserConfig(user.user_id)"> <td ng-style="user.aprovedByAdmin &&{'backgroundColor': '#dff0d8'} || {'backgroundColor': '#fcf8e3'}"> {{user.first_name}} </td> <td ng-style="user.aprovedByAdmin &&{'backgroundColor': '#dff0d8'} || {'backgroundColor': '#fcf8e3'}"> {{user.last_name}} </td> <td class="hidden-xs" ng-style="user.aprovedByAdmin &&{'backgroundColor': '#dff0d8'} || {'backgroundColor': '#fcf8e3'}"> {{user.company_name}} </td> <td class="col-lg-4" ng-style="user.aprovedByAdmin &&{'backgroundColor': '#dff0d8'} || {'backgroundColor': '#fcf8e3'}"> <div class="col-lg-12 col-md-12 hidden-sm-down"> <label ng-show="!user.aprovedByAdmin"> nog te verwerken</label> <label ng-show="user.aprovedByAdmin"> alles verwerkt </label> </div> </td> </tr> <tr ng-repeat-end id="accordion-{{$index}}" abc-admin-user-details-directive buffer-data="vm.bufferData" expense-type="vm.expenseType" user-config="vm.userConfig" index="{{$index}}" data-parent="#expenseUserMainTable" ng-show="vm.activePosition == $index"> </tr> </tbody></table>

Backend

48

Page 49: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Opvragen van alle gebruikers die een onkost hebben ingediend

Om de lijst met de gebruikers op te vragen wordt in de toegewezen controller de maand en het jaartal uit de URLgehaald. Vervolgens wordt een service aangeroepen waaraan de maand en het jaartal worden meegegeven. Dezeservicemethode gaat dan een database search uitvoeren met de 'expenseDao'. Hier wordt de tijdsperiode aanmeegegeven. Dit geeft als resultaat een lijst van onkosten die ingediend zijn geweest in die tijdsperiode. Numoeten alle gebruikers uit de onkosten worden gehaald en in een lijst worden gestoken. Dit wordt gedaan doorover de lijst met onkosten te itereren en voor elke onkost de gebruiker op te vragen uit de database. Dit wordtgedaan door de user DAO aan te spreken en als ID de 'user_id' mee te geven die verkregen wordt uit het 'user_id'attribuut van de onkost. Vervolgens wordt gekeken of de gebruiker al in de lijst zit van gebruikers. Indien dit zo iswordt hij genegeerd en wordt de volgende gebruiker opgehaald. Indien de gebruiker nog niet in de lijst istoegevoegd wordt de gebruiker entiteit omgezet naar een DTO waar de frontend de nodige data uit kan halen(bedrijf, naam, nog te verwerken/betalen). Nadat de conversie gebeurd is wordt de DTO aan een lijst toegevoegddie, wanneer alle gebruikers gevonden zijn, terug wordt bezorgd aan de controller. Deze zorgt ervoor dat hij geentwee keer in de lijst bij de DTO's verschijnt. De lijst met de gebruikers wordt dan door de service terugbezorgd aande controller. Deze zal op zijn beurt de lijst terug aan de frontend bezorgen met de gepaste http-status code.

Opbouwen gebruikerslijst

@Override public List<ExpenseOverviewDto> getExpenseAdminOverview(final Integer month, final Integer year) { List<String> userList = new ArrayList<>();

final List<ExpenseOverviewDto> expenseUploadOverview = new ArrayList<>(); List<Expense> expense = expensesDao.findByDate(month, year);

for (final Expense exp : expense) { User user = userService.getByUserId(exp.getUserId());

if (!userList.contains(user.getId())) { convertUserToExpenseOverviewDto(month, year, expenseUploadOverview, user); userList.add(user.getId()); }

} return expenseUploadOverview; }

Opvragen van alle onkosten van een gebruiker

Om alle onkosten van een gebruiker op te kunnen vragen wordt in de URL de tijdsperiode meegegeven (maand enjaar) en de 'user_id' van de betreffende gebruiker. Vervolgens wordt een DTO lijst aangemaakt waar alle onkostendie gevonden worden en zijn omgezet van entiteit naar DTO in geplaatst worden. De onkosten worden opgevraagddoor de onkosten DAO alle onkosten van de gebruiker te laten zoeken (door 'user_id' te gebruiken) in detijdsperiode die wordt meegegeven door de controller. Dit resultaat wordt bewaard in een onkostenlijst. Vervolgenswordt er een iteratie gedaan op deze lijst en wordt elke onkost omgezet van entiteit naar DTO. Deze conversie isvoor elk type onkost anders gezien de verschillende types andere attributen hebben. Dit houdt voornamelijk in omde waarden van de attributen van enititeit te kopiëren naar de attributen van de DTO. Het resultaat van de conversiewordt dan toegevoegd aan de DTO lijst. De DTO lijst wordt dan door de service terugbezorgd aan de controller.Deze zal op zijn beurt de lijst terug aan de frontend bezorgen met de gepaste http-status code.

Opvragen onkosten gebruiker

49

Page 50: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

@Override public List<DetailedExpenseDto> getDetailsExpenseUserForAdmin(final String userId, final Integer month, final Integer year) final List<DetailedExpenseDto> detailedExpenseDtos = new ArrayList<>(); List<Expense> expense = expensesDao.findByUserAndDate(userId, year, month);

for (final Expense exp : expense) { convertToDto(exp, detailedExpenseDtos); }

return detailedExpenseDtos; }

Keuren van de onkost

De controller zal uit de URL de ID van de onkost halen en uit de body van het verzoek worden dan de status die deonkost dient te krijgen en de commentaar van de administrator/betaler gehaald. Vervolgens wordt de gepasteservice aangeroepen. Deze service spreekt de onkosten DAO aan om de onkost met de meegegeven ID op tehalen. Wanneer deze gevonden is wordt de status van de onkost veranderd naar de status die meegegeven werd,alsook wordt de commentaar van de administrator/betaler toegevoegd. Nadat dit gebeurd is wordt de onkostgeüpdate in de database en wordt een rij toegevoegd in de mail-ticket tabel. Deze tabel houdt alle onkosten bij dieeen statusverandering hebben ondergaan. Indien een onkost al in de tabel staat (dus twee statusveranderingen inéén dag heeft geheeft wordt de attribuut 'currentState' aangepast naar de status die de onkost heeft na deverandering.) Op het einde van de dag zal de automatische mailservice de gebruikers op de hoogte brengen vanveranderingen (uitgelegd in Backend, Spring framework)

50

Page 51: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Pdf-viewerWanneer de gebruiker een onkost indient is hij/zij verplicht om een bestand mee in te dienen. Dit bestand bevat hetbetalingsbewijs van de ingediende onkost. Dit bestand kan verschillende type bestanden zijn en aan de hand vanhet bestandstype moes bepaald worden wat er mee gedaan kan worden. Wanneer het bestand een pdf-bestandis, moet het mogelijk zijn om het bestand online te bekijken. Wanneer dit een ander bestandsformaat is moet ditniet. Alle bestandstypen moeten gedownload kunnen worden. Dit moes bij elk overzicht mogelijk zijn, dus zowel bijhet overzicht voor de gebruiker, de office medewerker en de betaler.

Frontend

De gebruiker krijgt de naam van het bestand en een downloadknop te zien. Wanneer de gebruiker op dedownloadknop drukt wordt de functie 'downloadFile' aangeroepen met als parameter de ID van de onkost. In dezefunctie wordt de URL opgebouwd om de file te downloaden. Deze wordt opgebouwd met behulp van de ID van deonkost. Vervolgens wordt er gecontroleerd of het bestand een afbeelding of een pdf bestand is. Indien het een pdfbestand is wordt er een header meegegeven waarin staat dat de frontend een pdf-bestand terug verwacht.Wanneer het om een afbeelding gaat wordt er een header meegegeven waarin staat dat de frontend eenafbeelding terug verwacht. Er wordt een GET-request gestuurd met de bijhorende URL en de nodige headers.Wanneer de request rond is wordt een nieuw document aangemaakt. Het bestand dat gedownload dient te wordenkrijgt de naam van het bestand mee door deze uit de pdf metadata te halen die al in het overzicht van de onkostwerd opgehaald. Vervolgens wordt de data gedownload door gebruik te maken van een octet-stream met daarbijde response data die verkregen was in de GET-request.

Wanneer de gebruiker op de bestandsnaam klikt wordt de functie 'getPdfInView' aangeroepen met als parameterde ID van de onkost. Wanneer deze functie aangeroepen wordt, wordt er gecontroleerd of het bestand een pdf-bestand is of niet. Wanneer het bestand geen pdf is wordt de functie 'downloadFile' aangeroepen met alsparameter de ID van de onkost. Wanneer het bestand wel een pdf is wordt een variabele op de rootScopeveranderd. In deze variabele wordt de URL opgebouwd om de pdf op te halen. Vervolgens wordt er gebruik gemaaktvan de bibliotheek 'Angular-pdf'. Deze bibliotheek maakt gebruik van de bibliotheek 'pdf.js'. Deze bibliotheek isechter niet specifiek voor angular. Daarom dat de bibliotheek 'Angular-pdf' wordt gebruikt in plaats van debibliotheek 'pdf.js'. In de bibliotheek 'Angular-pdf' is een watch functie opgebouwd. Deze controleert wanneer devariable 'pdfUrl' wordt aangepast. Zodra deze aangepast wordt doet de bibliotheek verder zijn werk om het mogelijkte maken om de pdf in een pdf-viewer te tonen. De bibliotheek gebruikt een directive namelijk 'ng-pdf'. Het enigewat deze bibliotheek verder nog nodig heeft in deze directive is een canvas met een ID waarin de pdf getoond kanworden.

In de pdf-viewer ziet de gebruiker verschillende knoppen. Er zijn knoppen om de voorgaande of de volgende paginate tonen, een knop om de pdf te printen en een veld waar de gebruiker een paginanummer kan intypen. Hetnavigeren tussen de verschillende pagina's van de pdf is mogelijk door functies die reeds ingebouwd zijn in de

51

Page 52: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

bibliotheek 'angular-pdf'. De functie die nog geschreven diende te worden was de functie om te printen. Wanneerde gebruiker op de knop om te printen klikt wordt de functie 'printDoc' uitgevoerd.In deze functie worden in het begin de nodige headers ingesteld. Deze headers zijn het token om requests testuren naar de server en om duidelijk te maken dat de frontend een pdf-bestand verwacht van de backend. De URLwordt gelijkgesteld aan de URL die gebruikt is om de pdf te tonen in de pdf-viewer. Vervolgens wordt het bestandopgehaald door de functie 'getDocument' te gebruiken van de bibliotheek 'pdf.js'. Vervolgens wordt de pdf op deeerste pagina ingesteld, het aantal pagina's geteld, de pagina op de juiste manier gedraaid en op de juiste schaalgezet. Vervolgens wordt de pdf in een nieuw venster ingeladen door van elke pagina een afbeelding te tonen.Wanneer elke pagina in het venster ingeladen is wordt er een scherm getoond om het bestand af te drukken.

52

Page 53: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

BackendIn de backend zijn er twee GET-requests die verwerkt dienen te worden. Een eerste om het bestand te downloadenen een tweede die nodig is om het bestand weer te geven in de pdf-viewer van de frontend. In beide gevallen bevatde URL de ID van de onkost om het bijhorende bestand te vinden. De entiteit 'ExpenseFile' wordt opgevuld doorgebruik te maken van de functie 'getExpenseUploadFile' van de service 'UploadService'. Als parameter wordt de IDvan de onkost meegegeven. In deze functie wordt de entiteit 'ExpenseFile' opgevuld door gebruik te maken van dedao 'ExpenseFileDao'. Deze DAO gaat het juiste bestand ophalen door gebruik te maken van de ID van de onkost.Vervolgens wordt de juiste data bezorgd aan de service 'UploadService'. De service bezorgt op zijn beurt de data inde vorm van de entiteit 'ExpenseFile' aan de controller 'ExpensePdfController'.

Wanneer het bestand getoond dient te worden in de pdf-viewer wordt het bestand ingevuld in het type'FileSystemResource' en de bestandsnaam wordt ingevuld in de http-headers van de response. Vervolgens wordtdit terug bezorgd aan de frontend.

Wanneer het bestand gedownload dient te worden wordt het bestand in een byte-array gestopt. Vervolgens wordtde byte-array geëncodeerd in een base64 en opgeslagen als een string. De string wordt vervolgens bezorgd aande frontend.

53

Page 54: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

ResultatenDankzij de applicatie die we gemaakt hebben is het nu voor de werknemer gemakkelijker om een onkost in tedienen. Voordien moest dit per mail gedaan worden. Nu kan men dit doen op het submIT portaal. De gebruiker kanook meteen zien voor welke onkosten hij/zij recht heeft om een terugbetalingsaanvraag in te dienen. Vervolgenskrijgt de gebruiker ook een duidelijk overzicht van zijn/haar reeds ingediende onkosten. Voordien was het enigeoverzicht dat de gebruiker had zijn/haar bankrekening. De gebruiker moest op zijn/haar bankrekening nakijken ofhet bedrag al was teruggestort of niet.De office medewerker heeft nu ook meteen een duidelijk overzicht in de applicatie. Voordien kreeg de officemedewerker van elke gebruiker een mail aan om een terugbetalingsaanvraag in te dienen voor een onkost.Vervolgens moest de office medewerker de onkost dan intypen in een Excel-bestand. Door gebruik te maken vande applicatie heeft de office medewerker een duidelijk overzicht over de onkosten die nog verwerkt dienen teworden en die verwerkt zijn. Vervolgens kan de office medewerker een onkost goed- of afkeuren door een klik opeen knop en moet hij/zij deze onkost niet meer volledig intypen in een Excel-bestand. Doordat alle officemedewerkers deze applicatie gebruiken worden de onkosten door elke medewerker op dezelfde manier verwerkt.Dit heeft als positief gevolg dat de office medewerker de onkosten op een snelle en efficiënte manier kanverwerken.

Wanneer we net aan het project begonnen waren, hadden we veel tijd nodig om het reeds bestaande project en devoor ons nieuwe technologieën te leren kennen. In de eerste weken boekten we daardoor ook weinig vooruitgangen hadden we kwalitatief geen goede code geschreven. Na enkele weken werd onze kennis van de technologieënechter uitgebreid en waren we volledig wegwijs in het project. Hierdoor werd onze code kwalitatief beter en ging hetproject ook in een hogere versnelling vooruit. Omdat we merkten dat we kwalitatief betere code schreven hebbenwe ook heel het project nog eens bekeken en waar nodig een refactor uitgevoerd.Vandaag staan we nog steeds versteld van de grootte van het project en dat we van het project een volledigwerkende applicatie hebben kunnen maken die klaar is om getest te worden binnen het bedrijf.

54

Page 55: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

BesluitIn het begin van het project boekten we weinig vooruitgang omdat onze kennis omtrent de gebruikte technologieënerg klein was. De eerste weken hebben we enorm veel opzoekwerk moeten verrichten en moesten we nogwegwijs geraken in het reeds bestaande project. Beetje bij beetje geraakten we wegwijs in het project en in degebruikte technologieën. Na een vijftal weken voelden we ons volledig thuis in de nieuwe omgeving. Hierdoorbegonnen we zelfzekerder en sneller code te schrijven. De snelheid ging niet enkel omhoog, maar ook de kwaliteitvan de code ging omhoog. Om een goede kwaliteit van code te garanderen werden er de nodige refactorsuitgevoerd waardoor de kwaliteit aanzienlijk de hoogte inging ten opzichte van onze code die we in het beginhadden geschreven.

Op het einde van de stageperiode hebben we bijna alle doelstellingen die opgegeven waren bereikt. De applicatieis klaar om getest te worden in de realiteit. De productie van het project maakten we echter niet meer mee.Aangezien de submIT applicatie ook gebruikt wordt om timesheets in te dienen, die het einde van de maandingediend dienen te worden, konden we de eerste versie niet in productie zetten. Als er dan iets fout zou gaankonden de werknemers hun timesheets niet in dienen. Hierdoor hebben onze stagebegeleiders beslist om deproductie van het project uit te stellen naar juli of augustus. Dit doen ze omdat het dan een rustigere periode is. Indie periode is het de bedoeling dat de applicatie getest wordt met een kleine hoeveelheid gebruikers.

Doordat we met volledige nieuwe technologieën hebben gewerkt hebben we enorm veel bijgeleerd. De gebruiktetechnologieën zullen zeker terugkeren in onze toekomst, waardoor het een extra meerwaarde heeft dat we dezetechnologieën hebben leren gebruiken. Doordat de technologieën geleerd werden tijdens stage merken we beidendat we veel sneller hebben bijgeleerd dan dat we dit via school of cursussen geleerd zouden hebben. We merkenduidelijk dat onze bachelorproef een kickstart was om met deze technologieën aan het werk te gaan.

55

Page 56: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

Functionele Analyse

1. Actoren

1.1 Werknemer

Persoon die een onkost wil laten terugbetalen door ABC-Groep en hiervoor een aanvraag indient in de applicatie.

1.2 Administratief bediende

Administratief bediende (office) die onkostenvergoedingen goed- of afkeurt en de bijbehorende administratieverwerkt.

1.3 Betaler

Medewerker die goedgekeurde aanvragen terugbetaalt op de rekening van de werknemer.

2. Happy FlowDe algemene happy flow van het project in grote lijnen gaat als volgt:

1. De werknemer logt in op de timesheet applicatie en navigeert naar de 'Onkosten' tab.2. Hij selecteert het soort onkost dat hij wil ingeven, vult de nodige gegevens in en dient zijn aanvraag tot

terugbetaling in.3. Aan het einde van de dag telt het systeem hoeveel terugbetalingsaanvragen er die dag zijn ingediend en stuurt

een mail naar de administratie met de boodschap dat er onkosten verwerkt dienen te worden.4. De volgende werkdag logt een administratief bediende in op het systeem en ziet deze meteen een overzicht

van de ingediende en de nog niet verwerkte terugbetalingsaanvragen.5. De administratief bediende bekijkt de onkosten, print deze eventueel af en geeft deze in op de

bankingapplicatie en markeert de onkost als 'in verwerking'.6. Vervolgens logt de gebruiker met de rol 'payer' in op de applicatie en ziet meteen een overzicht van de

aanvragen die nog terugbetaald dienen te worden. De administratief bediende markeert deze als terugbetaaldna deze daadwerkelijk in de bankingapplicatie te hebben terugbetaald.

7. De werknemer krijgt een gestandaardiseerde mail met de melding dat de onkost terugbetaald is.

2.1 Afwijkingen

De administratief bediende beslist om voor een bepaalde reden de onkost niet te verwerken, maar dezemeteen af te keuren.

De werknemer wordt op de hoogte gesteld van deze afkeuring door een mail waarin de reden wordtbeschreven.De onkost wordt verder niet behandeld.

De betaler beslist om voor een bepaalde reden de onkost niet terug te betalen, maar om de onkost af tekeuren.

De werknemer wordt op de hoogte gesteld van deze afkeuring door een mail waarin de reden wordtbeschreven.De onkost wordt verder niet behandeld.

De werknemer realiseert zich alvorens de onkost werd goed- of afgekeurd dat de ingediende aanvraagincorrect is.

56

Page 57: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

De werknemer kan de aanvraag verwijderenDe werknemer kan een nieuwe aanvraag indienen

3. Functionaliteiten

3.1 Indienen van een onkost (werknemer)

Om een onkostenvergoeding aan te vragen dient de werknemer de onkost in te geven in de applicatie. Het moetook mogelijk zijn voor de administratief bediende om een onkost in te dienen voor een werknemer. In dit gevalwordt de onkost automatisch goedgekeurd (zie 'keuren van onkosten'). Elke onkost krijgt van het systeem eenreferentienummer (bijvoorbeeld: exp-123456). Dit nummer kan gebruikt worden in communicatie tussen dewerknemer en de administratief bediende en komt ook op de overschrijving te staan.Na het voltooien van de registratie wordt er naar de werknemer een mail gestuurd met de melding dat de onkostgeregistreerd werd in de applicatie en dat deze wacht op goedkeuring. In deze mail wordt ook hetreferentienummer vermeld. Naar de administratief bediende wordt dagelijks een overzicht via mail gestuurd methet aantal nieuwe registraties. Deze mail moet los van de 'timesheet mail' gestuurd worden.

Zolang een aanvraag nog niet verwerkt is door de administratief bediende kan deze nog steeds aangepast wordendoor de werknemer.

Bij het registreren van een onkost kan gekozen worden uit verschillende onkostentypes. Elk onkostentype heeftbepaalde eigenschappen zoals het maximaal terug te vragen bedrag of een verschil in invoervelden. Ook kunnenbepaalde types in- of uitgeschakeld worden per werknemer of kan het maximale bedrag veranderd worden voorelke werknemer. Deze gegevens dienen vooraf ingesteld te worden door de administratief bediende.

3.1.1 Internet

Voor elke werknemer kan ingesteld worden of hij recht heeft op een internetvergoeding, standaard staat dituitgeschakeld. Per werknemer kan ook het maximaal bedrag dat terugbetaald zal worden ingesteld worden,standaard wordt dit ingesteld op €42. Dit bedrag is tijdens de registratie van de onkost slechts informatief, maar ditmoet wel getoond worden.

Voor de registratie dienen volgende gegevens ingevoerd te worden:

De maand waarvoor de terugbetaling dient te gebeuren. Deze kan afwijken van de facturatiemaand (zie'afwijkingen').Bedrag van de factuur. Dit bedrag kan hoger zijn dan het bedrag waar de werknemer recht op heeft.Kopie van de factuur in pdf formaat.Opmerkingen (optioneel)

3.1.2 GSM

Voor elke werknemer kan ingesteld worden of hij recht heeft op een gsm vergoeding, standaard staat dituigeschakeld. Per werknemer kan ook het maximaal bedrag dat terugbetaald zal worden ingesteld worden,standaard wordt dit ingesteld op €0. Dit bedrag is tijdens de registatie van de onkost slechts informatief, maar ditmoet wel getoond worden.

Voor de registratie dienen volgende gegevens ingevoerd te worden:

De maand waarvoor de terugbetaling dient te gebeuren. Deze kan afwijken van de facturatiemaand (zie'afwijkingen').Bedrag van de factuur. Dit bedrag kan hoger zijn dan het bedrag waar de werknemer recht op heeft.Kopie van de factuur in pdf formaat.Opmerkingen (optioneel)

57

Page 58: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

3.1.3 Kilometervergoeding

Voor elke werknemer kan ingesteld worden of hij recht heeft op kilometervergoedingen, standaard staat dituitgeschakeld. Op dit onkostentype kan geen maximaal bedrag ingesteld worden. Het bedrag dat zal terugbetaaldworden per kilometer kan voor de gehele applicatie geconfigureerd worden en is dus gelijk voor alle werknemers.Dit bedrag moet getoond worden tijdens de registratie van de onkost. Tijdens de registratie kan dan ook 'live'berekend worden hoeveel de werknemer zal terugbetaald krijgen.

De werknemer kan meerdere 'ritten' ingeven per registratie, voor elke rit dienen volgende gegevens ingevoerd teworden:

Omschrijving van de ritDatum van de ritAantal afgelegde kilometersOpmerkingen (optioneel en voor de gehele registratie, niet per rit)

3.1.4 Vervoer

Voor elke werknemer kan ingesteld worden of hij recht heeft op de terugbetaling voor vervoer, standaard staat dituigeschakeld. Op dit onkostentype kan geen maximaal bedrag ingesteld worden. De werknemer kan meerdereuitgaven tegelijk registreren door deze samen te voegen, in dit geval mag de kopie van de kwintaties dus meerderekwitanties bevatten. Ook moet het mogelijk zijn om meerdere kopieën per registratie toe te voegen.

Voor elke gemaakte onkost voor vervoer dienen volgende gegevens ingevoerd te worden:

Omschrijving van de onkost(en)Totaal bedrag van de onkost(en)Kopie van de kwitantie(s) of factu(u)r(en). Deze mogen samengevoegd ingediend worden in eenzelfdedocument.Opmerkingen (optioneel)

3.1.5 Diverse

Voor elke werknemer kan ingesteld worden of hij diverse onkosten kan registreren, standaard staat ditingeschakeld. Per onkost dient de werknemer een nieuwe aanvraag te registreren.

Voor elke diverse onkost dienen volgende gegevens ingevoerd te worden:

Omschrijving van de onkostBedrag van de onkostKopie van de kwitantie of factuurOpmerkingen (optioneel)

3.1.6 Afwijkingen

Het kan voorkomen dat een werknemer zijn internet- of gsm-factuur slechts om de twee maanden of na langereperiode krijgt. Het facturatiebedrag en de terugbetaling moet dus verspreid worden over meerdere maanden. Dewerknemer is in dit geval verplicht om deze factuur toch elke maand in te dienen. Hij zal dus dezelfde factuurindienen voor meerdere maanden. De factuur dient hier dus enkel als een vorm van controle om te zien of deonkost wel degelijk heeft plaatsgevonden.

58

Page 59: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

3.2 Keuren van onkosten (administratief bediende)

Nadat een onkost is ingediend door de werknemer komt deze in de status 'in behandeling' en moet deze gekeurdworden door de administratief bediende. Hiervoor krijgt de administratief bediende dagelijks een overzichttoegemaild, ook indien er geen nieuwe aanvragen zijn geregistreerd. In deze mail wordt enkel het aantal teverwerken aanvragen vermeld en een link naar de applicatie.

In de applicatie krijgt de administratief bediende een overzicht met alle nog te verwerken aanvragen. Deadministratief bediende moet ook de mogelijkheid hebben om reeds verwerkte aanvragen te bekijken. Vanaf ditoverzicht kunnen de details van een aanvraag geopend worden van waaruit deze kan goed- of afgekeurd worden.

Bij het goedkeuren van een onkost wordt er een mail naar de betreffende werknemer gestuurd waarin degoedkeuring vermeld wordt, samen met het referentienummer. In deze mail wordt ook uitgelegd dat deaanvraag werd doorgestuurd naar de betaler en dat deze het verschuldige bedrag zal overschrijven op hetrekeningnummer van de werknemer.Bij het afkeuren van een onkost dient de administratief bediende een reden voor de afkeuring in te vullen. Dezereden wordt in een mail naar de werknemer gestuurd, samen met het referentienummer. Indien de werknemereen aangepaste aanvraag wil indienen dient er een nieuwe aanvraag geregistreerd te worden. Eens eenaanvraag dus is afgekeurd kan deze niet meer worden aangepast door de werknemer. De aanvraag kan nogwel op status 'goedgekeurd' gezet worden door de administratief bediende.

Na het goedkeuren van een onkost moet de administratief bediende de bijbehorende kwitantie(s) of factu(u)r(en)kunnen afdrukken voor de boekhouding. Hiervoor moet dus een printfunctie voorzien worden. Wanneer een onkostis afgedrukt moet de administratief bediende dit kunnen aanvinken op de detailpagina van de onkost. Deadministratief bediende moet ook de mogelijkheid hebben om dit terug af te vinken indien er problemen warentijdens het afdrukken.Op de afgedrukte documenten moet (indien technisch haalbaar) in een bovenhoek het referentienummertoegevoegd worden. Eens de documenten zijn afgedrukt moet de administratief bediende dit in de applicatiekunnen aangeven.

Het moet ook mogelijk zijn voor de administratief bediende om meerdere aanvragen samen te voegen. Dit magenkel mogelijk zijn voor aanvragen die nog de status 'in behandeling' hebben. De nieuwe aanvraag die zo ontstaatkrijgt een nieuw referentienummer. Dit nieuwe nummer moet net zoals bij andere aanvragen in een bovenhoektoegevoegd worden bij het afdrukken van de documenten. Indien dit technisch niet mogelijk is, moet als laatstepagina bij het afdrukken een overzicht van alle referentienummers toegevoegd worden. De oorspronkelijkereferentienummers dienen nog wel getoond te worden in de applicatie.Door het samenvoegen van meerdere aanvragen worden de verschuldigde bedragen als totaal aan de betalergetoond en ook zo overgemaakt aan de werknemer.

De administratief bediende moet tevens de mogelijkheid hebben om, naast 'goedgekeurd' en 'afgekeurd', deaanvraag terug in de status 'in behandeling' te zetten. Deze functionaliteit komt van pas indien er toch nog twijfel zouonstaan over het al dan niet goedkeuren van een aanvraag nadat deze al behandeld werd. Of indien de administriefbediende alsnog een reeds goedgekeurde aanvraag wilt samenvoegen met een andere.Indien de status voor de administratief bediende terug op 'in behandeling' wordt gezet mag het voor de werknemerniet meer mogelijk zijn om de aanvraag nog aan te passen. Dit kan enkel indien de adminstratief bediende noggeen enkele handeling heeft verricht op de aanvraag.

De mails die naar de werknemers worden gestuurd met de mededeling dat hun aanvraag werd goed- of afgekeurddienen pas op het einde van de dag verzonden te worden (best buiten de kantooruren). Dit om te voorkomen dat ermeerdere mails worden gestuurd indien een aanvraag nog enkele keren van status zou veranderen.

Indien een onkost door de administratief bediende is ingevoerd in naam van een werknemer, dan krijgt dezeautomatisch de status 'goedgekeurd' en wordt verder de normale flow gevolgd. De administratief bediende heeftwel de mogelijkheid om net als bij de andere onkosten de status te wijzigen. De werknemer dient geen mail te

59

Page 60: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

krijgen dat de onkost in behandeling is, maar moet meteen de mail krijgen met de melding dat de onkost isgoedgekeurd en in afwachting is van terugbetaling.

3.3 Terugbetalen van onkosten (betaler)

Wanneer de betaler zich aanmeldt in de applicatie moet er een overzicht getoond worden van alle onkosten diegoedgekeurd zijn en nog betaald moeten worden. Tevens moet er de mogelijkheid zijn om reeds betaaldeonkosten terug op te vragen.De betaler loopt de onkosten één voor één af en voert de desbetreffende overschrijving uit. De betaler moet alledetails van een onkost kunnen inkijken.Wanneer een onkost is terugbetaald markeert de betaler deze als 'betaald' en wordt er een mail gestuurd naar dewerknemer met de mededeling dat het bedrag is overgeschreven, in deze mail wordt ook het referentienummervermeldt. Bij samengevoegde onkosten mag de bevestigingsmail pas verstuurd worden wanneer alle aparteonkosten als 'betaald' gemarkeerd worden.

De betaler moet ook onkosten kunnen afkeuren, het proces hiervoor is hetzelfde als wanneer de administratiefbediende de onkost zou afkeuren.

3.4 Overzicht aanvragen werknemer

De werknemer moet een overzicht van alle aangevraagde terugbetalingen kunnen raadplegen. In dit overzicht moetaan de hand van kleuren duidelijk zijn in welke status de aanvraag zich bevindt:

Aangevraagd maar nog niet verwerktGoedgekeurd maar nog niet terugbetaaldAfgekeurdTerugbetaald

3.5 Lifecycle van een aanvraag tot terugbetaling

Een aanvraag voor onkosten vergoeding kan zich in één van volgende toestanden bevinden:

60

Page 61: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

3.6 E-mails

De applicatie stuurt op basis van gebruikersacties mails uit. Tevens worden er ook mails verstuurd op vastetijdstippen naar aanleiding van de gebruikersacties die gedurende een bepaalde dag ondernomen werden. Deinhoud van deze mails moet configureerbaar zijn door de administratief bediende.In een later stadium zullen sommige van deze mails vervangen worden door een HTTP call naar de "ABC Intranet"api.

Hieronder een opsomming van alle mails die verstuurd worden door de applicatie:

Type mail Ontvanger Wanneer Wordt vervangen doorREST call

Onkostenvergoeding geregistreerd doorwerknemer Werknemer Meteen Ja

Aanvraag goedgekeurd Werknemer Eindedag Ja

Aanvraag afgekeurd Werknemer Eindedag Ja

Onkost terugbetaald Werknemer Meteen Ja

Overzicht geregistreerde aanvragen Administratie Eindedag Nee

61

Page 62: Table of Contents - AP Hogeschoolbeta.eaict.ap.be/wp-content/uploads/2016/06/... · Beyond-it voor Microsoft SharePoint Cereus voor Oracle en Java DynApps voor Odoo en BI ... In het

BronnenSpring framework 1: http://www.vijfhart.nl/artikelen/artikel_4.pdf

Hibernate2: http://hibernate.org/orm/

J Unit3: http://www.tutorialspoint.com/junit/

Jenkins4: https://en.wikipedia.org/wiki/Jenkins_(software)

Maven5: https://nl.wikipedia.org/wiki/Apache_Maven

Tomcat6: http://tomcat.apache.org/

AngularJs7: https://nl.wikipedia.org/wiki/AngularJS

Bootstrap8: https://en.wikipedia.org/wiki/Bootstrap_(front-end_framework)

Single Page Application10: https://nl.wikipedia.org/wiki/Single_Page_Application

REST11: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

NodeJs 12: https://en.wikipedia.org/wiki/Node.js

SQL 13: https://nl.wikipedia.org/wiki/SQL

Md-autocomplete 14: https://material.angularjs.org/latest/api/directive/mdAutocomplete

Scrum 15: https://nl.wikipedia.org/wiki/Scrum_(softwareontwikkelmethode)

CORS 16 ; http://software.dzhuvinov.com/cors-filter.html

62