Arena Kundereskontro Høgskolen i Oslo og Akershus Institutt for Informasjonsteknologi Av: Roger Ommedal, Andreas Åkesson, Ashkan Vahidishams og Simen Trippestad PROSJEKT NR. 2015-25 Studieprogram: Informasjonsteknologi Postadresse: Postboks 4 St. Olavs plass, 0130 Oslo Besøksadresse: Holbergs plass, Oslo TILGJENGELIGHET Åpent Telefon: 22 45 32 00 Telefaks: 22 45 32 05 BACHELORPROSJEKT HOVEDPROSJEKTETS TITTEL Arena Kundereskontro DATO 26.05.2015 ANTALL SIDER / BILAG 160/ 4 PROSJEKTDELTAKERE Roger Ommedal – s188879 Andreas Åkesson – s188900 Ashkan Vahidishams – s188872 Simen Trippestad – s188891 INTERN VEILEDER OPPDRAGSGIVER KONTAKTPERSON Kredinor Tor-Morten Grønli Ole Marius Thorstensen SAMMENDRAG Arena Kundereskontro er et klassebibliotek utviklet i C# for Kredinor. Dette biblioteket skal brukes i deres nye saksbehandlingssystem Arena. Hensikten med denne løsningen er å ta vare på alle transaksjoner og posteringer som skjer i de systemene som implementerer den. Et viktig prinsipp er at ingen transaksjoner skal slettes, og at alle posteringer skal være sporbare i ettertid. Dette skal gi Kredinor en forbedret løsning for transaksjonshåndtering. Rapporten vil gi et innblikk i hvordan løsningen er utviklet ved bruk av smidig metodikk, det gis også en kort innføring i sentrale regnskapsprinsipper som har vært viktige for prosjektet. Det er også utviklet et Web-API for demonstrasjon og testing av klassebiblioteket. Front end som benytter Web-API er utviklet ved hjelp av AngularJS og Bootstrap CSS. Rapporten inneholder også dokumentasjon og brukermanual til dette. 3 STIKKORD C# Klassebibliotek Regnskap INNHOLD Dette dokumentet inneholder følgende delrapporter og vedlegg. Presentasjon Prosessrapport Produktrapport Testrapport Brukermanual (Vedlegg 1) Web-API (Vedlegg 2) Fremdriftsplan (Vedlegg 3) Ordliste (Vedlegg 4) PRESENTASJON FORORD Dette er en rapport som tar for seg arbeidet vi i gruppe 25 har avlagt i vårt avsluttende hovedprosjekt i vår bachelor utdannelse i informasjonsteknologi våren 2015. Hovedprosjektet har gått ut på å utvikle et klassebibliotek kalt “Arena Kundereskontro” for inkassoselskapet Kredinor. Rapporten består av en produktrapport, en prosessrapport, brukerveiledning og vedlegg. Alt arbeid er utført i perioden 16.01.15 - 26.05.15 og alt arbeid er utviklet av gruppen. Gruppe 25 består av følgende medlemmer: Ashkan Vahidishams - s188872 Andreas Åkesson - s188900 Roger Ommedal - s188879 Simen Trippestad - s188891 Vi vil takke Kredinor, Ole Marius Thoresen og Øyvind Andersen for å ha gitt oss muligheten til å utvikle denne modulen, og veileder Tor-Morten Grønli for hjelp underveis. Presentasjon INNHOLD Forord .......................................................................................................................... 1 1 2 Innledning ............................................................................................................. 3 1.1 Om gruppen ................................................................................................... 3 1.2 Om oppdragsgiver ......................................................................................... 4 1.3 Veiledere ....................................................................................................... 4 Bakgrunn for oppgaven ......................................................................................... 5 2.1 Oppgavens mål.............................................................................................. 5 2.2 Regnskap ...................................................................................................... 6 2.2.1 Regnskapsprinsipper .............................................................................. 6 2.2.2 Sporbarhet .............................................................................................. 7 Side 2|8 Presentasjon 1 INNLEDNING Hensikten med dette dokumentet er å presentere de involverte parter, bakgrunn for oppgaven og gi leseren et innblikk i hva oppgaven går ut på. Ved lesing av de andre dokumentene i rapporten, legges det til grunn at dette dokumentet er lest først. For å kunne beskrive klassebiblioteket, også referert til som modul, mest mulig korrekt var det nødvendig å benytte en del fremmede ord og uttrykk. Disse er beskrevet i medfølgende ordliste (vedlegg 1). 1.1 OM GRUPPEN Gruppen som har løst oppgaven består av fire studenter som alle tar “Informasjonsteknologi” ved Høgskolen i Oslo og Akershus. Studentene er i alderen 21 - 36 år og er alle bosatt i Oslo området. Vi ble kjent så tidlig som fadderperioden i oppstart av studiet, og flere av gruppens medlemmer har samarbeidet under tidligere prosjektoppgaver. Ettersom tidligere samarbeid har gått bra, og vi kommer godt overens, bestemte vi oss i høst for at vi skulle levere hovedoppgaven sammen. Vi kjenner hverandre godt og har erfaring med å føre åpen kommunikasjon med ærlige tilbakemeldinger og konstruktiv kritikk. Vi følte dessuten at det faglige nivået var jevnt, og at dette la et godt grunnlag for vellykket gruppearbeid. Figur 1 –[Organisasjonskart] Side 3|8 Presentasjon 1.2 OM OPPDRAGSGIVER Oppgaven er utviklet for det nasjonale inkasso- og fakturaservice selskapet Kredinor. Kredinor er et inkassoselskap som hjelper bedrifter med betalingsoppfølging, og har bransjespesialisering innen energi, bank/finans og handel. Selskapet har ca. 400 ansatte fordelt på ti lokale kontor og et hovedkontor lokalisert i Oslo. Figur 2 -[Kredinor-logo] Et av gruppens medlem, Roger Ommedal, arbeider i Kredinor. Da prosjektet nærmet seg var det hensiktsmessig å forhøre seg med selskapet i forhold til å bli tildelt en prosjektoppgave fra Kredinor. Selskapet har mange ansatte innen IT og dermed mange relevante problemstillinger. Rundt oktober måned 2014 hadde Roger vært i kontakt med IT sjef Ole Marius Thorstensen og systemarkitekt Øyvind Andersen. Når det senere i rapporten refereres til Kredinor som kunde er det disse personene vi refererer til. 1.3 VEILEDERE Følgende personer har fungert som veiledere og kontaktpersoner igjennom prosjektet: Tor Krattebøl: ansvarlig for grupper og bachelor prosjektet sett fra HIOA sin side. Ansatt på Høgskolen i Oslo ved Teknologi, kunst og design, fakultet Computer Science. Tor-Morten Grønli: tildelt veileder fra Høgskolen i Oslo. Ansatt på Westerdals School of Arts, Communication & Technology ved fakultetet Computer Science Ole Marius Thorstensen: kontaktperson hos Kredinor Figur 3 – [HiOA-logo] Øyvind Andersen: kontaktperson hos Kredinor, ansvarlig for besvarelse på henvendelser vedrørende kode og generelle spørsmål om produktet Side 4|8 Presentasjon 2 BAKGRUNN FOR OPPG AVE N Pr. dags dato har Kredinor tre forskjellige kjernesystem som alle benytter sine egne metoder for å holde oversikt over transaksjoner. Dette gir dårlig oversikt og høy vedlikeholdskostnad, og er derfor lite hensiktsmessig. Dagens kjernesystem innenfor inkasso, K90, har vært i drift de siste 25 årene, altså siden 1990. Systemet har blitt videreutviklet med ny funksjonalitet etterhvert som nye krav har oppstått, og er som følge av dette blitt svært uoversiktlig og lite sammenhengende. Total oversikt og god sporbarhet for alle transaksjoner er noe selskapet savner ved dagens system. I denne sammenheng har selskapet et ønske om å utvikle en ny modul for reskontroføringer. Modulen skal gi god sporbarhet, tilfredsstille lovens krav om bokføring og gi god dokumentasjon ved eventuelle tilsyn fra Finanstilsynet. Gruppemedlem Roger Ommedal er ansatt i Kredinor og som følge av studiet mottok han tilbud om å utvikle denne modulen som bachelorprosjekt. Dette danner bakgrunnen for vår prosjektoppgave. 2.1 OPPGAVENS MÅL Arena Kundereskontro er en modul som er utviklet som en selvstendig del av Kredinors nåværende system Arena1. Modulens hovedoppgave er å holde oversikt over alle økonomiske transaksjoner som går inn og ut av Kredinor, og kontinuerlig bokføre posteringene ettersom de ankommer modulen. Et system kan ta i bruk modulen for å sikre sporbarhet og rettmessig behandling av transaksjoner. Dette gjøres ved å sende inn transaksjoner for behandling i modulen, hvor disse blir postert i henhold til Bokføringsloven. Modulen forhindrer sletting eller endring av allerede førte transaksjoner. Formålet på sikt med Arena Kundereskontro er å erstatte den eksisterende løsningen som er i bruk hos Kredinor. Kredinors eksisterende system har noen vesentlige mangler da det er mulig å fjerne, slette og korrigere data som har blitt satt inn i databasen. Modulen skal blant annet: Ta imot innbetalinger mottatt hos Kredinor. Oppnå sporbarhet til transaksjonen. Postere transaksjonen mot gitt kontoplan. Overføre transaksjoner til regnskapssystem. 1 Arena – Navnet på Kredinors nye datasystem utviklet i .NET Side 5|8 Presentasjon Søke etter transaksjoner og posteringer. Forhindre sletting av data. 2.2 REGNSKAP Dette avsnittet vil forklare bakgrunnen til oppgaven fra et økonomisk ståsted, hvilke regnskapsprinsipper som benyttes ved postering i Arena Kundereskontro, og hvordan man ved hjelp av denne modulen kan oppnå full sporbarhet av alle transaksjoner som sendes inn. Alt som omhandler penger som Kredinor mottar, både til seg selv eller som skal videresendes oppdragsgiver, blir registrert i Axapta. Transaksjoner som ikke fysisk er innom Kredinor vil imidlertid ikke overføres dit. Dette vil eksempelvis være innbetaling fra en skyldner direkte til oppdragsgiver, og hvor Kredinor kun får en melding om denne innbetalingen. Denne meldingen vil medføre en reduksjon av gjenstående krav, og føres som en innbetaling i kjernesystemet, men vil ikke medføre noen overføring av transaksjon til Axapta. Disse bør likevel spores, da det hender at man i ettertid endrer eller sletter disse, dersom opplysningene som man mottok fra oppdragsgiver i første omgang viser seg å være feil. Det samme vil gjelde fakturagrunnlag som opprettes, endres eller slettes. Pr i dag finnes det ikke noe logikk som ivaretar sporing eller historikk for slike transaksjoner, men det er noe den nye modulen vil tilby, og som er sårt tiltrengt i Kredinor. 2.2.1 REGNSKAPSPRINSI PPER I et regnskap føres det bilag. Hvert bilag blir ført både til debet(pluss) og kredit(minus), og mot en konto. All kontoføring er basert på T-konto prinsippet, hvor man fører ett beløp til debet mot en eller flere kontoer, og tilsvarende beløp til kredit mot en eller flere kontoer. Summen av alle kontoer i systemet skal til enhver tid være i balanse. Vår modul har det samme prinsippet innebygd, det sjekkes først at en transaksjon er i balanse før den godkjennes til postering, og deretter sørger modulen for at enten hele transaksjonen lagres, eller ingenting. I vår modul vil en transaksjon være ett bilag, og posteringene utgjør det som føres til debet(pluss) og kredit(minus) i regnskapet, alltid like mye til pluss som til minus. Eksempel på T-kontoer kan ses i [Figur 4]. Side 6|8 Presentasjon Figur 4 - [Kilde: T-Kontoer fra Jusleksikon2] Det er også viktig at et bilag kun føres en gang, slik at ikke dobbeltføring forekommer. Det er derfor behov for å vite hvilke transaksjoner som er bokført og hvilke som ikke er det. Vi har løst det ved å lagre checksum3 av alle filer som kjøres gjennom modulen i en egen database. Checksumen av filen lagres når filen sendes inn, og etterhvert som transaksjonene blir verifisert, behandlet og lagret, blir Guid 4tilhørende transaksjonen lagret i det samme basen. Når en ny fil sendes inn, blir den alltid sjekket mot denne tabellen før man prosessere transaksjonene, og man kan derfor være trygg på at det ikke oppstår dobbeltføring. Sender man inn den samme filen på nytt vil modulen kun behandle transaksjoner som ikke er bokført tidligere. 2.2.2 SPORBARHET Ett av de viktigste prinsippene innenfor regnskap er sporbarhet, og det var også et absolutt krav i forbindelse med denne oppgaven. §6 fra Bokføringsloven [Figur 5] er gjengitt under. Vi har innført Guid som unik identifikator til hver enkelt transaksjon, denne garanterer unikhet. I kvitteringen tilbake til klienten, sendes Guid med slik at den kan lagres av det systemet som benytter modulen. Dersom det senere foretas en korrigering, reversering eller annet knyttet til den samme transaksjonen, så sender systemet utenfor med Guid’en slik at modulen knytter etterfølgende transaksjon til mortransaksjonen (Parent-Guid). På denne måten kan man alltid finne tilbake til opprinnelig transaksjon, og også lett finne alle transaksjoner som hører sammen, disse har samme mor (Parent-Guid). 2 http://www.jusleksikon.no/wiki/Fil:T-kontoer3.jpg Checksum - en kort kode som brukes til å sjekke integriteten av data, eller den matematiske funksjonen av dataene, algoritmen, som genererer koden, ofte kalt hash-funksjon. 4 Guid – En global unik identifikator der det totale antallet unike nøkler er 2 128. Sannsynligheten for at det samme tallet genereres er svært lav. 3 Side 7|8 Presentasjon § 6. Sporbarhet Bokførte opplysninger skal lett kunne følges fra dokumentasjonen via spesifikasjoner frem til pliktig regnskapsrapportering. Det skal likeledes på en lett kontrollerbar måte være mulig med utgangspunkt i pliktig regnskapsrapportering å kunne finne tilbake til dokumentasjonen for de enkelte bokførte opplysningene. Dokumentasjon av bokførte opplysninger skal være nummererte eller identifisert på annen måte som gjør det mulig å kontrollere at den er fullstendig. Dokumentasjon av kontrollsporet, herunder hvordan system genererte poster kan etterprøves, skal foreligge i de tilfellene det er nødvendig for å kunne kontrollere bokførte opplysninger på en enkel måte. Kilde: Lovdata5 Figur 5 -[§6 fra Bokføringsloven] 5 http://lovdata.no/lov/2004-11-19-73/§6 Side 8|8 Arena Kundereskontro Prosessrapport Prosessrapport PROSESSRAPPORT FORORD Denne rapporten beskriver prosessen gruppe 25 gjennomgikk i planleggingen og gjennomføringen av vårt hovedprosjekt på Høgskolen i Oslo våren 2015. Rapporten vil blant annet ta for seg alle steg i utviklingsprosessen, utfordringer underveis, løsninger på problemer, fremgang underveis og strategi. En refleksjon rundt oppgaven tar til slutt for seg spørsmål rundt hva gruppen gjorde bra, hvilke erfaringer som er verdifulle og andre konklusjoner som er blitt erfart. Ordbruken i rapporten forutsetter at leser er kjent med utviklingsmetodikker og teknologi som er benyttet i oppgaven. Dette innebærer først og fremst bruk av fagterminologi, referanser til eksisterende utviklingsmetodikker og uttrykk. Dersom det skulle oppstå forvirring rundt visse uttrykk kan leser se om ordet finnes i vedlagt referanseliste. Rapporten er strukturert i til sammen seks deler: Oppstart: Kort introduksjon om hvem gruppen er, hvordan oppgaven ble til og litt om oppdragsgiveren Kredinor. Planlegging: Går inn på alle deler av forarbeidet vi som gruppe har gjennomgått. Her dokumenteres utarbeidelse av kravspesifikasjonen, omfang og begrensninger, valg av metodikk og teknologi, arbeidsmiljø og fremdriftsplan. Parallellitet; Beskriver utfordringene vi hadde rundt effektivisering av modulen, og hvordan vi løste dette ved bruk av asynkron programmering. Utviklingsprosessen: Beskriver hvordan hele prosessen har blitt gjennomført og drøfter i hvilken grad vi fulgte valgt metodikk og fastsatt fremdriftsplan. Konklusjon: Er en oppsummering av hele prosessen hvor alle valg, endringer, avgjørelser og steg underveis drøftes. Her beskrives både deler som har fungert godt, og deler som ikke har fungert fullt så godt. S i d e 2 | 30 Prosessrapport INNHOLD Forord .......................................................................................................................... 2 1 Planlegging og metode ........................................................................................... 5 1.1 Forløp til prosjektstart ....................................................................................... 5 1.2 Omfang ............................................................................................................ 6 1.3 Arbeidsteknikker og utviklingsmetoder ............................................................. 7 1.3.1 Planlegging av sprinter............................................................................... 8 1.3.2 Arbeidsfordeling ......................................................................................... 9 1.3.3 Scrum ........................................................................................................ 9 1.3.4 Prosjektstyringsverktøy ............................................................................ 11 1.4 Prosjektstyringsdokumenter ........................................................................... 12 1.4.1 Prosjektdagbok ........................................................................................ 12 1.4.2 Møtereferat .............................................................................................. 13 1.4.3 Fremdrift .................................................................................................. 14 1.4.4 Fremdriftsplan .......................................................................................... 14 1.4.5 Arbeidslogg .............................................................................................. 15 1.5 Arbeidsforhold ................................................................................................ 15 1.6 Verktøy .......................................................................................................... 16 1.6.1 Visual Studio 2013 ................................................................................... 16 1.6.2 Versjonskontroll ....................................................................................... 16 1.6.3 C#/.NET ................................................................................................... 17 1.6.4 AngularJS og Bootstrap 3 ........................................................................ 17 1.6.5 Dropbox ................................................................................................... 18 1.6.6 Facebook Messenger .............................................................................. 18 1.6.7 yEd Graph Editor ..................................................................................... 18 S i d e 3 | 30 Prosessrapport 1.6.8 Google Docs ............................................................................................ 18 1.7 IT-faglig forankring av prosjektet .................................................................... 18 2 Utviklingsprosessen ............................................................................................. 19 2.1 Benyttet metodikk........................................................................................... 19 2.2 Design og Arkitektur ....................................................................................... 20 2.3 Uavhengiget ................................................................................................... 23 2.4 Paralellitet ...................................................................................................... 24 2.4.1 GUID........................................................................................................ 24 2.4.2 Sync vs Async ......................................................................................... 24 2.5 Demonstrasjon for Kredinor............................................................................ 25 2.6 Samarbeid...................................................................................................... 26 3 Kravspesifikasjonen og dens rolle ........................................................................ 26 3.1 Bakgrunn for kravspesifikasjonen ................................................................... 26 3.1.1 Utarbeidelse............................................................................................. 26 3.2 Vår erfaring med kravspesifikasjonen............................................................. 27 3.2.1 Endringer av kravspesifikasjonen ............................................................. 27 3.3 Konklusjon ..................................................................................................... 28 4 Konklusjon............................................................................................................ 29 4.1 Resultat .......................................................................................................... 29 4.2 Læringsutbytte ............................................................................................... 29 4.3 Videreutvikling ................................................................................................ 30 4.4 Hva ville bli gjort annerledes?......................................................................... 30 S i d e 4 | 30 Prosessrapport 1 PLANLEGGING OG METODE Planleggingen var en viktig del av prosjektet. Her la vi til rette for absolutt alt som skulle gjøres, og forsøkte å forutse alle kommende steg i så tilstrekkelig omfang som mulig. Dette innebar å dele hele prosessen i så konkrete steg som mulig, planlegge hvert individuelle steg og deretter prioritere disse i logisk rekkefølge. Det var naturlig å starte planleggingen med å utrette en kravspesifikasjon, noe som beskrives i kapitel 4 [Kravspesifikasjonen og dens rolle]. Følgendearbeid ble utarbeidet under planleggingen: Kravspesifikasjon Risikoanalyse Sprintoversikt Grovskisse av systemet Oversikt over klasser og namespaces Valg av metodikk Store deler av planleggingsprosessen foregikk ved at gruppen satt samlet i lokalene til HiOA. Vi benyttet verktøy for å lage skisser av klasse-diagram, tenkte så kreativt vi kunne og forsøkte å definere så store deler av prosessen som mulig. Alle stegene under planleggingen ble gjort i fellesskap. Ingen vesentlige uenigheter oppstod under planleggingen, da ettersom vi hadde samme formeninger om de fleste avgjørelser som ble tatt. 1.1 FORLØP TIL PROSJEKTS TART To viktige deler av forløpet til prosjektet var å danne en gruppe og deretter finne en oppgave. Gruppen ble dannet av fire studenter som kjente hverandre fra før, og på grunnlag av flere faktorer som tilsa at samarbeidet ville bli vellykket. Oppgaven ble tildelt igjennom et av gruppemedlemmene som er ansatt i inkassoselskapet Kredinor. Detaljer rundt dannelsen av gruppen, kontakten med Kredinor og bakgrunnen for den endelige oppgaven beskrives i Presentasjon-rapporten [Dannelse av gruppen]. Kredinor presenterte to alternativ vi kunne velge mellom: Utvikle en ny intranettside for selskapets ansatte som inneholder nyheter, informasjon til ansatte, dokumentarkiv, personalhåndbok og andre relevante lenker. Utvikle en .NET modul for deres nye saksbehandlingsklient, Arena. På gitt tidspunkt syntes vi begge oppgavene virket interessante. Arbeidet med intranettsiden ville bestått av mye front-end utvikling og linking til andre portaler, slik at S i d e 5 | 30 Prosessrapport ulike ansatte ville hatt hver sine innfallsporter til informasjon. Alle i gruppen hadde på dette tidspunktet erfaring med front-end utvikling og webapplikasjoner fra tidligere kurs, og vi så for oss en intranett side spekket med spennende funksjonalitet. På tross av dette fristende alternativet endte avgjørelsen på den andre oppgaven. Vi syntes oppgaveteksten virket innbydende, og så for oss en lærerik prosess med et sluttprodukt som ville være til stor nytte hos oppdragsgiver. Produktet ble presentert som et klassebibliotek, noe som gjorde oss nysgjerrige ettersom det var en oppgave ulik alle oppgaver vi tidligere hadde gjennomført i skolesammenheng. Vi fikk inntrykk av at oppdragsgiver hadde en relativt klar formening om hva som skulle utvikles, men at vi stod fritt til å bestemme omfang og sentrale deler selv. Det faktum at denne oppgaven var mer back-end orientert enn det første alternativet hadde dessuten stor innflytelse på vår beslutning, ettersom samtlige medlemmer hadde størst interesse for back-end utvikling. 1.2 OMFANG Oppgaven ble tildelt med mye ønsket funksjonalitet, men det var oss til oss selv å definere omfanget. Ønsket produkt var et klassebibliotek som på sikt skulle være med på å erstatte mye av funksjonaliteten i systemet K901. Modulen skulle støtte alle kravene til oppdragsgiver, men vi bestemte selv hvor stor del av funksjonaliteten vi skulle implementere. Etter å det første møtet med oppdragsgiver hadde vi dannet oss et klarere bilde av hva oppgaven gikk ut på. Vi bestemte så overordnet omfang. Vi vedtok at oppgaven skulle bestå av å implementere et klassebibliotek som ga funksjonalitet for å ta imot innsendte filer med transaksjoner, postere disse med full sporbarhet og overgi bokførte posteringer til eksterne regnskapssystem. I planlegging av omfanget tok vi tid, krav og ønsket funksjonalitet i betraktning Foruten klassebibliotekets kjernefunksjonalitet bestemte vi oss tidlig for at vi ville utvikle et Web API som benyttet klassebibliotekets funksjonalitet. Vi så på dette som en nødvendighet både for å kunne teste og vise frem modulens funksjonalitet, og for å utvide funksjonalitet. Foruten dette så vi det også som en spennende mulighet til å utvide oppgavens omfang. Web API er detaljert i eget vedlegg. Prosjektet innebar også god planlegging, og estimering av tid, for å komme i mål til fristen. Prosjektets offisielle start var januar 2015, og innleveringsfrist var 26. mai 2015. 1 K90 – Kjernesystem i Kredinor som bokfører transaksjoner S i d e 6 | 30 Prosessrapport Vi definerte omfanget til følgende deler: Oppgavens hovedfokus skulle ligge på implementasjonen av klassebiblioteket. Alle krav i kravspesifikasjonen skal oppfylles, og implementasjonen skal foregå i henhold til rangering av viktigst funksjonalitet. Klassebiblioteket skal leveres som en fullstendig løsning, men det skal være enkelt å videreutvikle modulen for oppdragsgiver Et Web-API skal benytte seg av klasse-biblioteket på samme måte som en fremtidig klient. Web-API’et skal i første omgang gjøre det mulig å gjennomføre bokføringer av innsendte transaksjoner, men det skal også muliggjøre videre funksjonalitet. 1.3 ARBEIDSTEKNIKKER OG UTVIKLINGSMETODER Ved prosjektstart var valg av metodikk en stor og viktig avgjørelse vi måtte ta. Dette valget preget hele prosjektet ved å bestemme selve måten vi skulle gjennomføre arbeidet på. Vi var alle enige i at vi ville gå fult inn for å følge den metodikken vi valgte på korrekt vis, både for erfaringens- og prosjektets skyld. Vi var alle enige i at vi ville benytte smidig utviklingsmetodikk. Smidig metodikk er svært populært og begreper som Scrum, Kanban og Extreme Programming dukker ofte opp utviklingssammenhenger. Begrepet smidig utvikling kan være vanskelig å forstå, men disse tre påstandene kan være med å synliggjøre behovet: Det vil aldri gå å samle alle krav til en løsning før du begynner! Kravene vil mest sannsynlig endre seg underveis! Det vil alltid være mer å gjøre enn man har tid til2! Ved smidig utviklingsmetodikk rettes fokuset mot full kontroll på arbeid, god kommunikasjon i gruppen og ferdige biter av produktet levert ved fastsatte datoer. Vi diskuterte bruken av de metodikkene vi visste om (med erfaring fra faget systemutvikling) og kom frem til at Scrum var en metodikk som tilfredsstilte alle våre krav samtidig som det var en metodikk med mange gode anbefalinger. Et av gruppens medlem hadde erfaring med Scrum etter å ha jobbet med utviklingsprosjekt hos Kredinor, og hadde da både erfaring og kunnskap han overførte til resten av gruppen. Vi fikk inntrykk av at Scrum ga god oversikt, basert på uttalelser som at metodikken gjør det blir enklere å håndtere kompleksitet gjennom tverrfaglig samarbeid (teoretisk, men ikke praktisk sett i vårt tilfelle) og at gruppemedlemmene høster lærdom av resultatet etter hver sprint. 2 http://blog.kjempekjekt.com/2012/02/24/hva-er-smidig-utvikling/ S i d e 7 | 30 Prosessrapport En anen grunn til at valget falt på denne utviklingsmetodikken var at den var godt dokumentert3, slik at det var enklere for gruppen, som uerfarne Scrum-utviklere, å sette seg inn i og følge metodikken. 1.3.1 PLANLEGGING AV SPRI N TER Med Scrum arbeider man i “sprinter” (korte perioder), der man ved slutten av hver sprint ønsker å ha et “fullstendig” produkt å vise frem til oppdragsgiver, for å avdekke eventuelle misforståelser når kravspesifikasjonen ble utarbeidet. De arbeidsoppgavene som blir satt opp til en sprint skal være gjennomført når sprinten er ferdig. Til sammen syv sprinter på to uker hver ble gjennomført i prosjektets løp. Sprintene bestod av utvalgte deler av selve backloggen4 til prosjektet. Backloggen ble definert som et sett av brukerhistorier ut ifra den ferdige kravspesifikasjonen, og vi rangerte brukerhistoriene etter prioritet og logisk rekkefølge før vi fordelte disse til ulike sprinter. Brukerhistoriene ble rangert etter graden de utgjorde av viktighet og den rekkefølgen vi følte var mest logisk. Vi benyttet verktøyet Trello5 i denne planleggingen, og la alle brukerhistorier vi hadde definert i en To-Do tabell. Dette var en omfattende prosess som krevde stor innsikt i det kommende arbeidet, og vi benyttet kravspesifikasjonen i stor grad. Den endelige backloggen bestod av over 120 brukerhistorier med hvert sitt Trello-kort, hvorav mange av disse inneholdt detaljerte sjekklister og omfattende beskrivelser. Vi brukte mye tid på å gjøre hvert kort så grundig som mulig, da vi følte at det ville lette utviklingsprosessen senere. Sprintene ble definert etter at backloggen var klar. Vi planla en sprint fordele brukerhistoriene på syv bolker som til sammen inneholdt hele backloggen. De brukerhistoriene vi syntes hørte sammen ble lagt i samme sprint. For hver sprint foretok vi en realistisk vurdering rundt sannsynligheten for gjennomføring av sprinten. Her tok vi både høyde for estimert arbeidsmengde, varighet av implementasjon og vanskelighetsgrad. Vi tok også høyde for at nye oppgaver ville dukke opp underveis. Figur 1 - [Skjermbilde av et kort] 3 Mye benyttet kilde: http://scrumreferencecard.com/scrum-reference-card/ Backlog - En prioritert liste med kravspesifikasjonen av produktet presentert som brukerhistorier 5 Trello – Beskrevet i kapittel [2.1.4 Utviklingsverktøy] 4 S i d e 8 | 30 Prosessrapport Bruken av de planlagte sprintene beskrives i utviklingsprosessen. 1.3.2 ARBEIDSFORDELING I planleggingsperioden brukte vi mye tid på å organisere oppgaven i henhold til Scrums prinsipper. Gruppemedlemmet som var ansatt hos oppdragsgiver hadde oftere kontakt med kontaktpersonen der enn resten av gruppen, og det ble derfor naturlig å utnevne han til Scrum-master. Dette innebar at han fikk et overordnet ansvar for å tilse at prosessen gikk som den skulle, sørge for at alle hadde nødvendige verktøy og i det hele tatt legge alt til rette for at prosessen skulle gå så smidig som mulig. Det faktum at han hadde benyttet Scrum i tidligere jobb-sammenheng gjorde han dessuten mer erfaren enn resten av gruppen. Arbeidsfordelingen har vært preget av selvgående arbeid, frihet til å ta tak i de oppgavene vi selv har villet og jevn ansvarsfordeling. Dette foregikk ved at vi i starten av hver sprint gikk igjennom alle kort i back-loggen, før hver og en av gruppen ga kall på de oppgavene han ville arbeide med. Selvstendigheten denne arbeidsfordelingen medførte ga hvert medlem ansvar for å bidra til felles utbytte. Denne fordelingen viste seg å fungere svært bra. Etter hvert som prosessen utviklet seg begynte vi å finne våre egne interessefelt, samtidig som vi la merke til hverandres interessefelt. En potensiell svakhet ved denne type arbeidsfordeling er at noen gruppemedlem kan sluntre unna arbeid og gjør mindre enn andre. Dette unngikk vi ved å benytte Trello til å sette hvert medlem til sitt sett med oppgaver og ved å ha standup-møter de dagene vi jobbet sammen. De dagene vi ikke jobbet sammen kommuniserte vi ofte på web, og oppdaterte sprint-backloggen. På denne måten hadde vi alltid oversikt over hvem som gjorde hva. Oppdatering av prosjekt-dokumenter, utarbeidelse av møte-agendaer og diskusjon av alle steg underveis ble gjennomført med hele gruppen til stede. På denne måten fikk alle bidra til utviklingen av produktet, og alle fikk bidra med sine meninger og ideer. 1.3.3 SCRUM Arbeid med Scrum var nytt for flere i gruppen. Vi hadde enkelte startvansker og tok oss selv i å unnvike bruk av sentrale prinsipper i metodikken under oppstart. Metodikken vi fulgte var ikke utelukkende tradisjonell Scrum. Det viktigste for oss var å fokusere på smidige prinsipper og ha fokus på fremgang i utviklingen. Dette var noe vi fikk til. I løpet av prosjektets gang avholdt vi mange “Stand-up” møter. Disse møtene ble som oftest gjennomført i lokalene til Kredinor alt fra 3 til 5 dager i uken. Møtene varte i alt fra 10 – 60 minutter, og der presenterte vi hva hver av oss hadde gjort dagen før, hva S i d e 9 | 30 Prosessrapport vi skulle jobbe med den dagen og eventuelle hindringer som stoppet oss fra å utføre arbeidet. Fra tid til annen ble disse møtene holdt etter endt arbeidsdag, og det var som oftest da de kunne vare lengre enn planlagt. Dette skyltes ofte det siste punktet, hvor diskusjoner rundt funksjonaliteten og implementasjonen til modulen tok lang tid. Noen ganger kunne disse diskusjonene fortsette på Facebook helt frem til vi møttes neste dag. Selv om vi ikke holdt oss helt tro til «oppskriften» på stand-up møter fulgte vi prinsippet om uformell og daglig kommunikasjon. Det faktum at alle i gruppen kjente hverandre fra før bidro til å senke formaliteten. Vi snakket fritt hele veien og hadde alltid oversikt over hverandres oppgaver. 1.3.3.1 BRUK AV TRELLO Bruken av Trello var svært sentralt under hele planleggingsprosessen. Vi benyttet dette verktøyet til å planlegge hele produkt-backloggen, til å dele denne opp i sprinter, og etter hvert til å fordele alle arbeidsoppgavene imellom gruppen. En svakhet ved bruk av Trello som prosjektstyringsverktøy, er at Trello ikke loggførte antall timer hver gruppemedlem brukte på de forskjellige brukerhistoriene. Det kunne ha vært interessant å få ut statistikk på tidsbruk tilknyttet de forskjellige brukerhistoriene, for bruk ved fremtidig tidsestimering. En fordel ved bruk av Trello er at det er mulig å tildele flere gruppemedlemmer den samme oppgaven. Det er også mulig å implementere sjekklister til hver brukerhistorie. På den måten kunne man se hva som var fullført, og hva som ikke var det. 1.3.3.2 FORBEDRINGSPOTENSI AL I retrospekt er gruppen enige om at vi burde vært flinkere til å følge den fastsatte Scrum rutinen. Vi kunne vært strengere mot oss selv og fokusert mer på å holde faste standup-møter for å opprettholde god rutine. I enkelte perioder hadde vi ikke formelle standup-møter. Dette førte ikke til store problemer, men vi erfarte at når man først begynner å gå vekk fra enkelte rutiner, er det fort gjort å gå vekk fra andre rutiner. I de periodene vi ikke hadde like mange arbeidsmøter, merket vi at produksjonshastigheten sank. Ved å ha et fast sted (Kredinor/HiOA) å jobbe på, ble det enklere å holde fokus på arbeidsoppgavene, og ikke bli forstyrret av eksterne faktorer. S i d e 10 | 30 Prosessrapport 1.3.4 PROSJEKTSTYRI NGSVERK TØY Etter å ha bestemt oss for å utvikle i Scrum fikk vi noen råd fra veileder om hvilke verktøy som var tilgjengelige. Vi bestemte oss for å benytte Trello6 som prosjektstyringsverktøy. Dette verktøyet gjorde det enkelt å organisere prosjektet. Med Trello kan man flytte brukerhistorier mellom selvdefinerte kolonner. Vi endte opp med å bruke fem forskjellige kolonner som fungerte som vår Sprint-backlog7 (se også figur 2): Backlog: To Do: In Progress: Testing: Finished: Alle brukerhistoriene/kravene en sprint består av. Konkrete oppgaver som følge av kravene/brukerhistoriene. Arbeidsoppgaver som er under arbeid. Arbeidsoppgaver som testes. Fullførte oppgaver. En tendens vi fort la merke til var at "Testing" tabellen økte hyppig i innehold sammenlignet med resten av tabellene. Dette var fordi det var vanskelig å si seg 100% ferdig med en arbeidsoppgave etter at den var implementert, og dessuten var det fristende å starte på nye oppgaver så fort et kort ble flyttet vekk fra «In-progress». 6 http://www.trello.com Sprint backlog - En liste med alt arbeid som skal fullføres i løpet av en gitt sprint. Opprettes under planleggingen av en sprint ved å velge et antall brukerhistorier og dele disse opp til konkrete oppgaver. 7 S i d e 11 | 30 Prosessrapport Figur 2 - [Skjermbilde av Trello] Trello var både nyttig i planleggingsfasen og i utviklingsfasen. Det forble vårt mest nyttige utviklingsverktøy i både planlegging og utviklingsprosess. 1.4 PROSJEKTSTYRINGSDOKU MENTER I løpet av prosjektet opprettet vi mange dokumenter relatert til fremgangen. Noen av disse ble utviklet under planleggingen, andre ble utviklet kontinuerlig igjennom hele prosjektet. Disse dokumentene var: prosjektdagbok, møtereferater, fremdriftsplan. 1.4.1 PROSJEKTDAGBOK Vi hadde på forhånd planlagt å skrive detaljerte dags-referat underveis. Dette ble gjort fra dag til dag og alle i gruppen bidro. Dagbøkene ble skrevet i MS Word og vi fikk tilgang via en delt mappe på Dropbox. Der skrev vi hvem som jobbet med hva og problemer og løsninger vi støtte på underveis. Bruken viste seg å være nyttig av flere årsaker. Vi fikk bedre kontroll på hva som ble gjort, hvem som hadde gjort hva, og hvilke problem vi hadde støtt på fra dag til dag. Senere i prosessen, når vi begynte å skrive rapporten, benyttet vi dagboken for dokumentere det arbeidet vi hadde gjort flere måneder i forveien. S i d e 12 | 30 Prosessrapport 1.4.2 MØTEREFERAT I løpet av prosjektet hadde vi flere møter med både Kredinor og veileder på HiOA med jevne mellomrom. I forkant av hvert møte utarbeidet vi en møteagenda som ble sendt til veileder eller oppdragsgiver på epost. Under møtet ble dette dokumentet fylt ut med referat og en kort oppsummering, slik at vi skulle få så mye ut av møtene som mulig. Vi hadde stor nytte av møtene og møtereferatene. Problem vi støtte på og spørsmål relatert til programmeringen ble først og fremst avklart med veileder fra HiOA. Vi stilte spørsmål, fremviste arkitektur og kode og mottok tilbakemeldinger, eksempler og kommentarer på det arbeidet vi hadde gjort. Figur 3 - [Referat Mal] Spørsmål vi hadde som mer rettet mot løsningens funksjonalitet, krav og innhold, avklarte vi i møte med veiledere fra Kredinor. Vi avtalte møter som ble gjennomført i Kredinors lokaler. Vi hadde stor nytte at dette, særlig under planleggingsfasen. Vi avholdt et møte helt i starten, hvor vi stilte alle grunnleggende spørsmål, og utarbeidet så en kravspesifikasjon og klassearkitektur ut ifra det vi lærte dette møtet. Vi fikk så tilbakemeldinger på det vi hadde gjort, og laget nye utgaver av både kravspesifikasjon og arkitektur med de mottatte innspillene tatt i betraktning. Vi fikk også innføring i sentrale økonomiske prinsipper og begreper i disse møtene. Noen av gruppemedlemmene hadde aldri før hørt begreper som «posteringer» og «reskontromeldinger», og disse møtene var derfor svært lærerike. S i d e 13 | 30 Prosessrapport 1.4.3 FREMDRIFT Figur 4 - [Gant Diagram] Bildet over viser vår faktiske fremgang i prosjektet, de forskjellige fasene og hvor mye tid som ble brukt på hver aktivitet. Sprint én endte opp på 2 uker og 2 dager. Vi ville ha sprintperioder som endte på onsdager, fordi det den dagen passet best for alle gruppemedlemmene å møtes. 1.4.4 FREMDRIFTSPLAN Etter beslutning av valgt metodikk, teknologi og verktøy var tatt, satte vi i gang med oppsett av en fremdriftsplan. Vi ble enige om at utviklingen av produktet skulle pågå frem til 10. mai, og at produktet skulle være ferdigstilt til dette tidspunktet. På grunn av uforutsette hendelser ble denne fristen flyttet til den 13. mai. Dokumentasjonen skulle utarbeides når sprint 7 avsluttes og frem til den 25.mai. Figur 5 - [Fremdriftsplan] Vi startet selve utviklingen 02 februar. Vi opprettet databasemodeller og leverte det til godkjenning ved utløp av sprint 1. De neste sprintene frem til siste sprint skulle bygge på brukerhistorier hentet fra backlog. S i d e 14 | 30 Prosessrapport En mer beskrivende fremdriftsplan er lagt til som vedlegg. 1.4.5 ARBEIDSLOGG Vår arbeidslogg har i hovedsak vært historien over Changesets8 på Visual Studio Online. Vi har fra starten av vært nøye på at Changesets skulle ha gode beskrivelser. På denne måten er det lett å se hva som er gjort til hvilken tid, og av hvem. 1.5 ARBEIDSFORHOLD Som den sammensveisede gjengen vi etter hvert ble var det lett å arbeide sammen. Vi viste godt på forhånd hva hver enkelt likte å jobbe med best. Selv om alle jobbet med forskjellige deler av modulen nølte vi ikke med å spørre hverandre om hjelp, og vi lærte av hverandre. Arbeidsforholdet var preget av en uformell tone, noe som gjorde prosessen behagelig og til tider morsom. Når vi arbeidet sammen møttes vi i Kredinors lokaler. Dette var en fin måte å arbeide på, da vi fikk Figur 6 - [Kredinors lokaler i Rådhusgata 27] en følelse av å gå på jobb når vi skulle arbeide med oppgaven. Lokalene er lyse og fine, og den nære avstanden til kontaktpersonene var dessuten en fordel. I flere tilfeller hvor vi støtte på problemer fikk vi rask hjelp og løsninger. 8 https://msdn.microsoft.com/en-us/library/ms181408.aspx S i d e 15 | 30 Prosessrapport 1.6 VERKTØY Da kravspesifikasjonen var ferdigstilt og godkjent av oppdragsgiver, måtte vi bestemme oss for hvilken teknologi som skulle benyttes i utviklingen. Siden Kredinors Arena system blir utviklet med C#/.NET, var det en forutsetning for prosjektoppgaven at Arena Kundereskontro også skulle utvikles med C#/.NET, for det skulle bli lettere å implementere modulen i deres system. Web API, som er laget for teste modulen, brukes av et brukergrensesnitt laget i AngularJS og Bootstrap CSS. 1.6.1 VISUAL STUDIO 2013 Visual Studio9 er et utviklingsverktøy når man skal lage programvare i Microsofts rammeverk ASP.NET, og brukes av de ansatte hos Kredinor hver dag. Det ble derfor et naturlig valg for gruppen å bruke Visual Studio under utvikling av produktet. Visual Studio er et veldig utbredt verktøy for programmering i .NET og det gav verdifull erfaring å benytte dette i prosjektet. 1.6.2 VERSJONSKONTRO LL Et versjonskontrollsystem er programvare laget for å dele filer i prosjekter, og sørger for at endringene blir «sammensmeltet». Versjonskontrollsystemer er essensielle for prosjekter med flere utviklere. Etter hvert som vi programmerte, ble vi flinkere på bruken av versjonskontroll. I begynnelsen følte det var vrient å samkjøre våre lokale versjoner. Vi rotet med samkjøringen fordi vi glemte å laste ned seneste versjonen før vi lastet vår lokale opp på serveren. Det ble gradvis enklere, ettersom vi ble vant med nedlasting før opplasting. 1.6.2.1 TEAM FOUNDATION VERS ION CONTRO L Team Foundation Version Control10(TFVC) er et sentralisert versjonskontroll system. Gruppemedlemmene har typisk en versjon av en spesifikk fil på arbeidsmaskinen, og prosjekthistorien er opprettholdt på serveren. 9 https://www.visualstudio.com https://www.visualstudio.com/en-us/products/what-is-visual-studio-online-vs.aspx 10 S i d e 16 | 30 Prosessrapport TFVC er et gratis sky basert verktøy som er bygd inn i Visual Studio Online og som gjør det mulig for brukerne å jobbe på det samme prosjektet på hver sin maskin. Ved hjelp av TFVC har vi oversikt over hvem som har tilgang til hvem som jobber med prosjektet og hvilke endringer som har blitt gjort. Ved commit av endringer (Changesets) skrives en beskrivelse av endringen inn, som igjen kan sees av alle medlemmene under «history» i Visual Studio. Fra «history» vinduet er det mulig å sammenligne endringer, sjekke om det er konflikter og laste ned en eldre versjon av prosjektet. 1.6.3 C#/.NET C# er et objekt orientert programmeringsspråk som bygger på Java og C++. Vi ble nødt til å benytte dette språket da det var en forutsetning for oppgaven. Vi hadde god erfaring med språket fra faget Webapplikasjoner med C#/.NET fra HiOA og dessuten god erfaring med Java. 1.6.4 ANGULARJS OG BOOTSTR AP 3 AngularJS11 er et ‘open source’ JavaScript-rammeverk, som blir vedlikeholdt av Google og deler av brukermassen i fellesskap. Målet med AngularJS er å endre statiske HTML-sider til å støtte dynamisk endring. Vi ønsket å benytte AngularJS til å lage brukergrensesnittet til WEB-API’et, da vi både har tidligere erfaring med bruk av dette rammeverket gjennom kurs på skolen, og vi mener det gir gode muligheter til å lage interaktive websider. Nettsiden til rammeverket lover blant annet god støtte for testing av logikken, enkel data-binding og en fornuftig modell. Vi mener at det kan være svært aktuelt å lære seg AngularJS godt for fremtidige muligheter i arbeidslivet. Bootstrap12 er et rammeverk for å gjøre det enkelt å tilpasse nettsider til mobil og nettbrett. Det inneholder både JavaScript-, HTML- og CSS-funksjonalitet for å modellere et passende utseende. Selv om tilpasning av Web-API til mobil ikke er nødvendig, brukte vi Bootstrap da dette gjorde designet til nettsiden mer brukervennlig. 11 12 https://angularjs.org http://www.getbootstrap.com S i d e 17 | 30 Prosessrapport 1.6.5 DROPBOX Dropbox13 er en sky basert lagringsenhet, der du kan lagre filer på web. Disse filene kan deles mellom andre. Gruppen opprettet en delt mappe i Dropbox slik at vi kunne legge ut arbeid som alle hadde tilgang til å se. 1.6.6 FACEBOOK MESSENGER Facebook Messenger er et Instant Message program utviklet av Facebook som gjør at personer kan kommunisere via private meldinger. Dette ble brukt av gruppen for å kommunisere når vi ikke var på samme sted. Det ble også brukt til å dele nyttige lenker til nyttige sider. 1.6.7 YED GRAPH EDITOR yEd Graph Editor14 er et diagram verktøy, som gruppen brukte flittig til å lage ulike diagrammer, som sekvensdiagram og klassediagram, samt skisser av modulen. 1.6.8 GOOGLE DOCS Google Docs15 er et web basert tekst-redigeringsprogram som ble brukt til å skrive rapporter. Programmet gjorde det mulig for gruppemedlemmene å jobbe samtidig på de samme dokumentene. 1.7 IT-FAGLIG FORANKRING AV PROSJEKTET Da planleggingen nærmet seg slutt hadde vi klare retningslinjer å følge, og visste godt hva vi måtte sette oss inn i. Oppgaven innebar bruk av både prinsipper, teknologier og utviklingsmetodikker som var nye for oss, både relatert til utvikling og økonomi. Allerede i første møte med oppdragsgiver ble bokføringsloven nevnt som en viktig del av prosjektet. Vi ble bedt om å sette oss inn de prinsipper denne loven innebærer, og 13 https://www.dropbox.com http://www.yworks.com/en/products/yfiles/yed/ 15 https://www.google.no/intl/no/docs/about/ 14 S i d e 18 | 30 Prosessrapport vi ble gjort oppmerksomme på at oppgaven skulle løses på en måte som stod i samsvar med loven. Det var også et krav at vi behersket .NET programmering, da dette er det rammeverket Kredinor benytter hos seg. Ryddig og selvforklarende kode, bruk av objekt orientert programmering, fornuftig klassedesign og generell programmeringsforståelse var også et krav. Sist, men ikke minst, var utviklingsmetodikken en viktig del av oppgaven. Som beskrevet i kapittel 2. Planlegging og metode, valgte vi å benytte metodikken Scrum. Ettersom vi ikke hadde tidligere erfaring med denne metodikken måtte vi lære oss Scrums viktigste prinsipper, og hvordan de følges. Dette gjorde vi ved å benytte oss av veiledninger på nettet, lese oss frem og ved å avklare prinsipper med veileder fra HiOA. 2 UTVIKLINGSPROSESSEN I dette kapittelet går vi igjennom utviklingsprosessen, der vi tar for oss arbeidsformen, gruppens samarbeidsevne og avgjørelser som ble tatt underveis. Utfordringer og løsninger vil også nevnes. 2.1 BENYTTET METODIKK Gjennom nesten hele prosjektet, sett bort i fra enkelte dager der vi jobbet ekstra for å nå en tidsfrist, la gruppen opp arbeidsdagene etter en semi-tradisjonell modell, med arbeidsdag fra 10-17. Gruppen møtte enten opp hos Kredinor eller HiOA for å jobbe sammen. I startfasen av prosjektet møttes vi ikke veldig ofte. De første to månedene av prosjektet jobbet vi for det meste hjemmefra. Etter hvert som prosjektet utviklet seg møttes vi ca. 3 dager i uken for å jobbe sammen. De ukene vi hadde en tidsfrist møttes vi 4 dager i uken. På grunn av andre fag, jobb og andre uforutsette hendelser var vi ikke fulltallig hver gang. Vi kommuniserte med gruppemedlemmene som ikke var til stede over Facebook Messenger for å fortelle hva som var gjort, og hva som måtte gjøres. S i d e 19 | 30 Prosessrapport 2.2 DESIGN OG ARKITEKTUR Etter å ha fullført kravspesifikasjonen til modulen og omfanget til Web-API’et analyserte vi all info vi hadde om modulen til da og satte i gang med å planlegge klassebibliotekets arkitektur. Vi måtte beskrive hendelsesforløp og planlegge alle modeller forløpet ville ta i bruk, sette disse i kontekst, og bestemme hvilke klasser som utføre hvilke deler av funksjonaliteten. Dette var en stor, tidskrevende og vanskelig prosess, da den innebar at vi måtte dele opp systemet i så små bolker at vi fikk full oversikt over hva som foregikk hvor. Vi begynte med å lage en grovskisse av systemet hvor vi delte de viktigste stegene i hendelsesforløpet opp til de klassene og metodene vi anså som mest vesentlige. Vi benyttet graf-editoren yEd til å lage grovskissen. Skissen er fremvist i figur 1. Skissen var hjelpsom da den ga oss et litt klarere helhetlig inntrykk av hvordan systemet måtte konstrueres. Figur 7 - [Skisse av modulen] S i d e 20 | 30 Prosessrapport Vi forsøkte å lage en ryddig arkitektur som stod i samsvar med prinsipper rundt bruk av polymorfi der det var hensiktsmessig, logisk navngivning av klasser og muligheter for videreutvikling/integrasjon. Skissen var nyttig og hjalp oss med neste steg: definisjon av modeller. Vi brukte skissen til å se for oss et standard hendelsesforløp, og skrev ned de ulike objektene klassene ville arbeide med underveis. Vi brukte så hendelsesforløpet, klassene vi hadde til da og de modellene vi så som vesentlige, til å utarbeide et klassediagram som beskrev arkitekturen til kjernefunksjonaliteten (Se figur 8). Figur 8 - [Det første klassediagrammet] Vi bestemte oss for å ta utgangspunkt i dette klassediagrammet først, og heller lage nye diagram for funksjonalitet utover kjernefunksjonaliteten etter at kjernefunksjonaliteten var implementert. Vi så derfor ikke bort ifra at klassediagrammet ville endre seg i takt med utviklingsprosessen. Etter klassediagrammet delte vi all funksjonalitet opp i ulike deler og definerte så disse til individuelle prosjekter. Dette var hensiktsmessig av rent praktiske grunner, ettersom vi kunne bruke resultatet av denne estimeringen direkte ved implementasjonen senere. Vi bestemte at løsningen skulle bestå av fire prosjekter (illustrert ved figur 9): S i d e 21 | 30 Prosessrapport ArenaKundereskontro: Selve klassebiblioteket. Prosjektet er selvstendig og har ingen avhengigheter. Web-API: Web-API’et. Benytter koden til klassebiblioteket, altså er den avhengig av tilgang til ArenaKundereskontro. ArenaKundereskontro.Tests: Alle enhetstestene. Vi var enige i at enhetstester skulle implementeres, og at disse testene ikke skulle være en del av selve produktet. Testene er avhengige av tilgang funksjonaliteten til ArenaKundereskontro, men befinner seg i sitt eget prosjekt. Test: Test-prosjekt benyttet under utviklingen av produktet. Vi viste at produktet måtte testet kontinuerlig, og i denne klassen ville vi ha en main-metode for å simulere en klient. Prosjektet var derfor avhengig av tilgang til ArenaKundereskontro. Figur 9 - [Lagdeling av prosjektet] Etter at både klassediagram og overordnet lagdeling var fullført gikk vi videre på å planlegge oppbyggingen til klassebiblioteket. Neste steg var derfor å dele klasser inn i ulike lag. Vi så på lagdeling som en helt vesentlig del av planleggingen og klassebiblioteket, da utelatelse av dette ville resultert i kaotisk oppbygging og fullstendig mangel på struktur. Vi la klasser med relatert funksjonalitet i samme kategori. Deretter bestemte vi navnene til namespacene basert på funksjonaliteten og innholdet til kategoriene. Igjennom prosjektets løp hadde vi mange diskusjoner om navngivningen av namespacene, og ved prosessens slutt var utfallet helt ulikt det vi opprinnelig startet med. Det var mange grunner til dette, blant annet klassebibliotekets eksplosive vekst fra start til slutt og vår klarere oppfatning av all funksjonalitet. S i d e 22 | 30 Prosessrapport Namespace Innhold API Klasser som kommuniserer med klienten Core Alle klasser tilknyttet kjernefunksjonalitet IO Konverterings-klasser for input/output filer Models Alle objektene I løpet av utviklingsprosessen gjennomgikk både arkitektur, klasse/namespace/metode-navn og kravspesifikasjon flere endringer. Sprintene ble gjennomført i planlagt rekkefølge, men vi innså etter noen uker at klassediagrammet vi hadde måtte utvides for å få inkludere ny funksjonalitet. Vi var innforstått med dette da vi startet utviklingen av klassediagrammet, noe som gjorde det til en kontinuerlig prosess. Funksjonaliteten til klassebiblioteket ble tydeligere etter hvert som implementasjonen av backloggen startet. Vi var klare over hva som skulle gjøres, men det var ikke før vi startet implementasjonen at vi brukte tid på å finne ut av hvordan det skulle gjøres. Disse valgene omhandlet både valg av filformat, oppbygning av klasser og avgjørelser i forbindelse med hendelsesforløpet til enkelte prosesser. Klasser gjennomgikk forandringer både i form av innhold, funksjon og navn. Et stykke inn i prosessen tok vi oss selv i å ha programmert noen klasser med for mye ansvar og funksjonalitet. Disse stykket vi ned til mindre klasser med mer konkrete oppgaver. Namespacene gjennomgikk også store forandringer. Vi så etter hvert at de namespacene vi hadde planlagt ikke på langt nær var tilstrekkelig for å holde løsningen ryddig. Vi brukte derfor mye tid på å bestemme nye, beskrivende namespaces. Denne prosessen skapte den største uenigheten under hele prosessen, da vi var uenige om navngivningen og nytten disse namespacene skulle ha. Etter å ha diskutert i flere dager kom vi frem til en løsning alle var enige i. 2.3 UAVHENGIGET Modulen skulle ha et design som gjorde den uavhengig, som beskrevet i kravspesifikasjonen. Dette innebar at vi måtte ta hensyn til at løsningen skulle være selvstendig, men samtidig lett å ta i bruk av andre system. Dette betyr at det ikke stilles noe annet krav til systemet som skal ta i bruk modulen enn at oppsettet må gjennomgås. S i d e 23 | 30 Prosessrapport Konkrete valg vedtatt som følge av dette kravet var blant annet: Klassebiblioteket skal ikke har noen eksterne avhengigheter Klassebiblioteket skal ha et design som gjør det enkelt for et hvilket som helst system å ta det i bruk 2.4 PARALELLITET 2.4.1 GUID For å kunne oppnå parallellitet måtte vi ta i bruk globalt unike identifikatorer, også kalt GUID16. Datatype GUID er en 16byte binær datatype som er generert av en algoritme utviklet av Microsoft. GUID blir benyttet som primærnøkkel i Transaksjonstabellen istedenfor en inkrementell integer. To tråder kunne tildele den samme primærnøkkelen til to forskjellige databaserader ved bruk av inkrementell integer. Dette unngikk vi ved å bruke GUID som primærnøkkel. Når primærnøkkelen i tabellen er globalt unik, spiller det liten rolle hvilken tråd som først skriver til databasen. Ved bruk av GUID som primærnøkkel åpnet det opp muligheten for Async databaseskriving [Kapittel 3.4.2]. 2.4.2 SYNC VS ASYNC For å møte kravet om effektivitet måtte vi finne en måte å kunne lagre store mengder data på kort tid, uten at det går ut over integriteten til dataene som skal bli lagret. Ved å søke på nettet fant vi ut av at Async17 metoder var riktig vei å gå. En synkron Tråd vil låse en prosess frem til prosesseringen har fullført, noe som ikke er ideelt for modulen. Ved prosessering av store mengder data, vil vi unngå å låse tråden, slik at data kan bli prosessert samtidig. Asynkron håndtering innebærer (ved korrekt bruk) at hver transaksjon tildeles sin egen tråd i operativsystemet og på denne måten håndteres når CPU’en har mulighet til det. Antall tråder som blir kjørt samtidig avhenger av kapasiteten til CPU’en. I vår modul vil det bli opprettet et likt antall tråder som det er transaksjoner som skal bli gjennomført. 16 17 https://msdn.microsoft.com/en-us/library/dd354925.aspx https://msdn.microsoft.com/en-us/library/hh191443.aspx S i d e 24 | 30 Prosessrapport Asynkron programmering er enkelt å håndtere i .NET som følge av at Microsoft så den store etterspørselen som fantes etter enklere håndtering av multithreading. Vi har implementert både asynkron og synkron av to like metoder i vår løsning. Dette for å kunne tilby kunden den løsningen som passer best. Ved å ha to fungerende alternativ står kunden selv fritt til å benytte seg av den funksjonaliteten som er mest hensiktsmessig i gitt kontekst. For at løsningen skal være asynkron/synkron “hele” veien (hele hendelsesforløpet, og ikke bare et sted) er det implementert asynkrone og synkrone metoder med samme funksjonalitet flere steder i modulen. Sammenlignet med synkron håndtering kan asynkron håndtering vise seg å være svært hensiktsmessig i forhold til effektivitet. Tester i forbindelse med sammenligning av de to metodene kan studeres i Testrapporten. Disse testene viser også at modulen oppnår kravet om effektivitet. Etter hvert som vi kodet fant vi ut at håndtering av feil (Exceptions) ikke ble fanget opp av modulen. Hovedtråden ville ikke fange opp feilene, og kvitteringene ville ikke nå frem til brukeren av systemet. Det viste seg at feilhåndteringen måtte skje inne i tråden som ble opprettet og ikke av hovedtråden. Asynkrone metoder vil kunne prosessere data raskere, men det økte også faren for at feilsituasjoner kunne oppstå. Det var en tidkrevende prosess å få asynkron håndtering av transaksjoner å fungere riktig. 2.5 DEMONSTRASJON FOR KREDINOR En demonstrasjon av produktet utføres for å avgjøre om et produkt oppfyller kundens behov, og stemmer overens med kravspesifikasjonen og annen dokumentasjon. Demonstrasjonen er siste mulighet for en kunde å avvise et utilstrekkelig produkt, før det settes i drift. Demonstrasjonen ble utført uformelt med et møte mellom gruppemedlemmene og Kredinor, der gruppen presenterte modulen for Kredinor. Gruppemedlemmene forklarte hvordan backend fungerte og viste hvordan XML ble mottatt ved å bruke WEB-API’et til å laste opp en XML-fil. Kredinor mente at produktet var tilstrekkelig og utfylte de kravene som ble satt i begynnelsen av prosjektet. Kunde mente også at produktet var greit som en betaversjon. Det har i senere tid kommet andre forutsetninger for denne modulen, som har gjort at modulen blir vanskelig å implementere med en gang. Modulen må videreutvikles før den kan driftsettes. S i d e 25 | 30 Prosessrapport 2.6 SAMARBEID Etterhvert som prosjektet vedvarte, ble vi bedre kjent. Vi lærte hverandres arbeidsvaner, som første til at det ble et enklere og mer effektivt samarbeid utover i prosjektperioden. De største utfordringene vi hadde var å skille arbeidstid og sosial tid. Dette var spesielt vanskelig de dagene deler av gruppen måtte jobbe med et annet fag, men vi likevel valgte å sitte sammen. 3 KRAVSPESIFIKAS JONEN OG DENS ROLLE 3.1 BAKGRUNN FOR KRAVSPE SIFIKASJONEN Utarbeidelse av kravspesifikasjonen stod som noe av det viktigste som måtte være på plass før programmeringen kunne starte. Vi tok utgangspunkt i oppgaveteksten gitt av Kredinor, og laget et førsteutkast i januar 2015. Vi fremla her sentrale deler av funksjonaliteten til det eksisterende systemet, pluss ny ønsket funksjonalitet. Kravene ble presentert som brukerhistorier, hvor vi i tillegg til selve kravet beskrev viktigheten og detaljer om det aktuelle kravet. 3.1.1 UTARBEIDELSE Utkastet ble utarbeidet og levert i januar 2015 som en del av forprosjektet. Deler av denne kravspesifikasjonen er gjengitt (kun som krav) under: Løsningen skal være uavhengig. Alle transaksjoner skal være sporbare. Alle transaksjoner skal til enhver tid være i balanse. Det skal ikke være lov å slette transaksjoner. Gjeldende lover/forskrifter om bokføringsloven skal følges. Klassebiblioteket skal ha god ytelse. Klassebiblioteket skal utvikles i .NET. Etter utarbeidelse av utkastet arrangerte vi et møte med Kredinor hvor vi presenterte kravspesifikasjonen. Sammen gikk vi trinnvis gjennom dokumentet. Oppdragsgiver var enige i de punktene vi hadde definert, men ga også utrykk for at det var mye vi ikke hadde tatt høyde for. Utkastet definerte de viktigste kravene rundt kjernefunksjonaliteten, men ikke om selve utførelsen eller videre funksjonalitet. S i d e 26 | 30 Prosessrapport Vi diskuterte så ønsket funksjonalitet og relasjonen slutt-produkt og Kredinor ideelt sett villa ha. Ved møtets slutt hadde vi forlenget kravspesifikasjonen med nye punkter. I tillegg til kravene i førsteutkastet hadde vi nå definert konkrete krav til modulens input/output håndtering og viktig tilleggs funksjonalitet: Modulen skal ta imot transaksjoner tilsendt som fil. Modulen skal kunne håndtere individuelle transaksjoner. Modulen skal dokumentere prosesserte transaksjoners status. Modulen skal gi alle transaksjoner unike Guid-verdier. Alle transaksjoner skal være søkbare i ettertid. Bokførte betalinger skal kunne overlates til et eksternt regnskapssystem. Oppdragsgiver gikk god for denne versjonen, og det var den vi tok utgangspunkt i under resten av prosjektet. Kravspesifikasjon ligger i sin helhet i vedlegget. 3.2 VÅR ERFARING MED KRAVSPE SIFIKASJONEN Kravspesifikasjonen har gitt oss generelle retningslinjer for hva som skulle lages, hvordan oppgaven skulle struktureres og hvilke funksjonaliteter som skulle implementeres. Denne informasjonen forenklet planleggingen av prosjektet. Det har også vært betryggende å ha gitte retningslinjer man kunne forholde seg til. 3.2.1 ENDRING ER AV KRAVSPE SIFIKASJO NEN Ettersom vi har jobbet smidig under utviklingsprosessen har noen krav forandret seg under prosessen. Noen krav har utgått fordi implementasjonen av kravene var overflødige. Vi kan ta for oss kravet «Ta imot melding om innbetaling mottatt direkte hos arbeidsgiver». Vi så for oss først at vår modul skulle ta imot informasjonen direkte, for så å videresende det til inkassosystemet, men vi snudde heller om på problemstillingen. Inkassosystemet tar imot informasjonen, for så å sende de kontoene det skal posteres mot til vår modul. Selv om dette kravet har utgått, så støtter vår modul funksjonaliteten. Vi trenger for eksempel å ikke motta en hel del informasjon for så å lagre en bit av informasjonen. Vi tar heller imot transaksjoner og posteringer fra systemene rundt, deriblant inkassosystemet. S i d e 27 | 30 Prosessrapport 3.3 KONKLUSJON Kravspesifikasjonen har spilt en stor rolle for utviklingen av modulen, spesielt for hva som gjaldt omfang av oppgaven. Mesteparten av funksjonaliteten det ble stilt krav til ble innfridd, mens noen av elementene utgikk. S i d e 28 | 30 Prosessrapport 4 KONKLUSJON I denne delen av dokumentet vil vi komme med egne meninger om forskjellige deler av hovedprosjektet og vår opplevelse av prosjektet, samt hvilke muligheter Kredinor har for videreutvikling av modulen. 4.1 RESULTAT Gruppen er godt fornøyd med resultatet av produktet. Vi satt for det meste i lokalene til Kredinor, der arbeidsmiljøet var veldig aktivt. Selv om vi gjerne skulle ha hatt mer tid til denne utviklingen, så føler vi at vi har utviklet et produkt vi kan være fornøyde med. Det er mange timers arbeid som ligger bak utviklingen av systemet, og vi mener det er skrevet på en slik måte at det er lett å vedlikeholde, utvide eller gjenbruke deler av koden i andre prosjekter. 4.2 LÆRINGSUTBYTTE Vi har blitt utfordret til å sette oss dypere inn i .NET rammeverket, noe som har vært interessant og lærerikt både for hobby-basis og for videre karriere. Vi er alle enige i at vi har forbedret vår kompetanse rundt språket betydelig i løpet av prosessen. Vi har også lært hvordan vi skal bruke teknologi i et større prosjekt, og ikke bare simulere problemstillinger, slik studenter vanligvis gjør på HiOA. Vi har også fått erfaring i å jobbe selvstendig, men samtidig evne til å samarbeide i gruppe. For vår personlige utvikling har det vært lærerikt å kunne jobbe med et større prosjekt, der vi har fått en god smakebit på hva som venter oss ute i arbeidslivet. I og med at prosjektet har blitt utviklet for en oppdragsgiver har vi fått følelsen av å jobbe for et firma. Vi ser på dette som en positiv erfaring, og takker igjen både Kredinor og våre veiledere der for muligheten de ga oss. Benyttet metodikk har også gitt stort læringsutbytte. Vi har nå erfaring med hvordan Scrum benyttes i et prosjekt, og vi er godt innforstått med alle prinsipper og retningslinjer metodikken tar i bruk. I og med at denne metodikken daglig tas i bruk i stort omfang i den «virkelige verden» ser vi på det som en stor fordel å kunne bekrefte at vi nå har gjennomført et prosjekt hvor vi har tatt denne metodikken i bruk. Sist, men ikke minst har vi fått erfare hvordan et prosjekt gjennomføres, hele veien fra første møte med oppdragsgiver frem til endelig overlevering av produkt. Denne prosessen er verdifull på veldig mange måter, og vi føler alle at vi har vokst i løpet av de fem månedene prosjektet har pågått. S i d e 29 | 30 Prosessrapport 4.3 VIDEREUTVIKLING Ved prosjektets slutt brukte vi tid på reflektere rundt videreutvikling av det endelige sluttproduktet. Ved prosjektets start ble klassebiblioteket beskrevet som en selvstendig del av et større system som i fremtiden vil erstatte K90. Som beskrevet i kapitel 2.2 Omfang var det vi som selv bestemte omfanget til prosjektet. Ettersom modulen senere skal implementeres i en større kontekst, måtte vi ta høyde for at implementasjon og videreutvikling av biblioteket skulle være enkelt. Oppdragsgiver kan derfor videreutvikle klassebiblioteket med all ønsket funksjonalitet. Vi satte oss det målet at vi skulle levere et fungerende klassebibliotek med hovedfokus på håndtering av transaksjoner. Sluttproduktet lever opp til de kravene vi satte oss selv. Da vi var ferdige diskuterte vi potensielle ideer til videreutvikling og kom frem til noen punkter: Generering av statistikk. Utvide filtrering og mulighetene for uthenting av data. Utvidelse av datamodellene, det er trolig ønskelig å lagre mer informasjon i modulen enn det som gjøres i dag. 4.4 HVA VILLE BLI GJORT ANNERLEDES? Selv om vi er godt fornøyde med resultatet er det noen ting vi ville gjort annerledes dersom vi fikk sjansen til å starte prosjektet på nytt. Vi ville lagt mer tid i å utforme et detaljert og fullstendig klassediagram. Å lage diagrammer og planlegge hvilken funksjonalitet som passet inn hvor var en utfordring. Vi laget flere diagrammer som tok for seg mindre deler av funksjonaliteten, men som etterhvert viste seg å være feil, f.eks. fordi bokføringsprinsipper ikke var blitt overholdt. Dette førte igjen til at vi måtte omstrukturere deler av prosjektet for å ta høyde for alle krav. Vi er enige i at testdreven utvikling hadde passet prosjektet godt. Ved å jobbe testdrevet kan utviklere endre kode uten at det oppstår problemer. Testene ville gjort oss oppmerksomme på endringer som førte til rar eller annerledes oppførsel. S i d e 30 | 30 Arena Kundereskontro Produktrapport Produktrapport FORORD Dette er en rapport skrevet med det formål å dokumentere produktet Arena kundereskontro. Kjært barn har mange navn, og klassebiblioteket vil refereres til ved bruk av flere betegnelser. Både «Arena Kundereskontro», «modulen» og «klassebiblioteket» vil forekomme, og alle sikter til samme produkt, nemlig klassebiblioteket. Bakgrunn, utvikling og endelig produkt vil beskrives og analyseres. Produktet består av et klassebibliotek (modul) som kan implementeres i et nåværende system. Rapporten er laget for de som skal drifte og videreutvikle systemet og vil gi en detaljert innføring i modulens funksjonalitet, oppbygning og virkemåte. ORDBRUK I RAPPORTEN Rapporten forutsetter at leseren har en grunnleggende teknologisk forståelse for den teknologien som er benyttet i prosjektet. Dette omfatter programmeringsspråket C# og rammeverket .NET. Grunnleggende kunnskap om applikasjonsutvikling i .NET vil dessuten være en fordel. Foruten teknologisk forståelse forutsetter rapporten også at leseren besitter en viss kunnskap om økonomi. Rapporten vil inneholde terminologi som omhandler lagdeling av prosjekter, logiske navngivninger og dessuten referanser til kode som er utviklet i prosjektet. S i d e 2 | 53 Produktrapport INNHOLD Forord .......................................................................................................................... 2 Ordbruk i rapporten ...................................................................................................... 2 1 Kravspesifikasjon .................................................................................................. 6 2 sammendrag ......................................................................................................... 6 3 Funksjonalitet og egenskaper ............................................................................... 7 3.1 Config / Oppsett ............................................................................................. 7 3.1.1 3.2 Databasetilkobling .................................................................................. 8 Kontekst......................................................................................................... 8 3.2.1 AKContext .............................................................................................. 9 3.2.2 RequestContext .................................................................................... 10 3.3 Oppsett av kontoer....................................................................................... 11 3.3.1 3.4 Klient............................................................................................................ 12 3.4.1 3.5 Importere konto fra CSV ....................................................................... 11 Implementasjon av IArenakundereskontroClient ................................... 12 Generering av Transaksjonsforespørsel ...................................................... 12 3.5.1 XML Formatering .................................................................................. 14 3.5.2 Hash av forespørsel – Checksum ......................................................... 15 3.6 Håndtering av Transaksjonsforespørsel ....................................................... 16 3.6.1 Kontrollere Transaksjonsforespørsel ..................................................... 18 3.6.2 Validering .............................................................................................. 22 3.6.3 Lagring av Transaksjon......................................................................... 24 3.6.4 Oppdatere Request med guid ............................................................... 27 3.6.5 Utsendelse av kvittering ........................................................................ 27 3.7 Kvitteringer .................................................................................................. 28 S i d e 3 | 53 Produktrapport 3.7.1 ReceiptSender ...................................................................................... 29 3.7.2 IMessageReceiver ................................................................................ 30 3.8 Hente ut data ............................................................................................... 31 3.8.1 3.9 Feilhåndtering .............................................................................................. 34 3.9.1 4 Exceptions ............................................................................................ 35 3.10 Sporbarhet ................................................................................................... 36 3.11 Async/Sync håndtering ................................................................................ 37 Oppbygging ........................................................................................................ 38 4.1 Prosjektstruktur ............................................................................................ 38 4.2 Organisering av klasser - Namespaces........................................................ 39 4.3 Benyttede biblioteker & rammeverk ............................................................. 41 4.3.1 Microsoft .NET Framework ................................................................... 41 4.3.2 Entity Framework .................................................................................. 42 4.3.3 LINQ ..................................................................................................... 42 4.3.4 MOQ ..................................................................................................... 42 4.3.5 FileHelpers ........................................................................................... 42 4.4 Modeller ....................................................................................................... 43 4.4.1 Domenemodeller .................................................................................. 43 4.4.2 XML Modeller........................................................................................ 44 4.5 Datalagring/dataaksessering ........................................................................ 46 4.6 Sikkerhet...................................................................................................... 46 4.6.1 4.7 5 Uttak av data til regnskapssystem......................................................... 31 Access Modifiers................................................................................... 47 Programmerings standard............................................................................ 47 Retningslinjer ...................................................................................................... 48 5.1 Oppdragsgivers retningslinjer ...................................................................... 48 S i d e 4 | 53 Produktrapport 6 5.1.1 programmeringsstandard ...................................................................... 48 5.1.2 kommentering av kode.......................................................................... 48 5.1.3 Navngivning .......................................................................................... 49 Kravspesifikasjon ................................................................................................ 50 6.1 Funksjonelle Krav ........................................................................................ 50 6.2 Ikke funksjonelle krav................................................................................... 53 S i d e 5 | 53 Produktrapport 1 KRAVSPESIFIKAS JON Produktet er et resultat av Kredinors etterspørsel etter et system som kan holde oversikt over transaksjoner og sørge for sporbarhet av posteringer tilknyttet disse. Produktet er en selvstendig modul som består av et klassebibliotek. Kravspesifikasjonen til produktet ble utarbeidet i samarbeid med Kredinor, med utgangspunkt i funksjonalitet i daværende system samt ønskene om ny funksjonalitet. Modulen skal være generisk og gjøre implementasjon hos flere klienter mulig, eksempelvis skal den kunne benyttes for både inkasso-, fakturaservice- og kundekontosystemer. Det skal også være enkelt å implementere fremtidige system som brukere av modulen. Modulen skal derfor designes og utvikles som en generell kundereskontro, og ikke være rettet mot en spesiell bransje. Hele kravspesifikasjonen befinner seg i slutten av denne rapporten, punkt 6. De mest sentrale delene av kravspesifikasjonen er gjengitt her: 2 Modulen skal implementeres som en selvstendig modul Modulen skal motta transaksjoner fra klient Modulen skal postere transaksjoner i mottatt fil Alle posterte transaksjoner skal være i balanse Alle transaksjoner/posteringer skal være sporbare Ingen transaksjoner/posteringer skal kunne slettes S AMMENDRAG Modulens kjernefunksjonalitet går ut på å behandle transaksjonsforespørsler mottatt fra en klient som har implementert klassebiblioteket. En forespørsel kan inneholde en eller flere transaksjoner. En forespørsel mottas normalt som en XML fil som konverteres til et objekt som modulen kan behandle. Modulen sjekker først om en transaksjon er behandlet og postert tidligere, i så fall blir den avvist. Transaksjoner som ikke er postert tidligere vil bli behandlet av modulen. Kvittering vil bli sendt til klientens kvitteringsmottaker uavhengig av resultat. Det er også mulig å hente ut posterte transaksjoner til eksternt regnskapssystem. En klient kan velge om den ønsker at transaksjoner skal behandles synkront eller asynkront da modulen tilbyr begge løsninger. S i d e 6 | 53 Produktrapport Figur 1 – [Skisse av modulens hovedfunksjonalitet] 3 FUNKSJONALITET OG EG ENSKAPER I følgende kapittel beskrives funksjonaliteten til Arena Kundereskontro. Kapittelet vil beskrive hvordan modulen gjøres klar til bruk, deretter gi en detaljert beskrivelse av funksjonalitet og virkemåte til hvert steg i hendelsesforløpet. 3.1 CONFIG / OPPSETT Modulen krever at klienten som skal ta den i bruk gjennomgår et oppsett, for at modulen skal kunne utføre ønsket arbeid med forventet resultat. Her blir en klient omtalt som et system som skal ta modulen i bruk. Dette oppsettet definerer blant annet hvor prosessert data skal lagres i klientens system, hvordan mottak og videre håndtering av transaksjons-kvitteringer skal foregå, hvilken identifikator klient skal refereres via i modulen og hvilke kontoer posteringer skal kunne bokføres til. Følgende punkter må gjennomføres av brukeren før modulen kan tas i bruk: Bruker må implementere logikk for XML-filformattering (TransactionRequest) S i d e 7 | 53 Produktrapport Bruker må konfigurere tilkobling til databasen. (ConnectionString1) Bruker må importere kontoer til modulen, dersom disse ikke er importert fra før Bruker må implementere interfacet IArenakundereskontroClient for å identifisere seg som en klient 3.1.1 DATABASETILKOBLING Modulen er nødt til å vite hvor databasen ligger. Dette definerer systemet som implementerer klassebiblioteket i form av en «connection string». Figur 2 – [ConnectionString] En connection string kan inneholde mange elementer, men som minimum må den inneholde navn, databaselokasjon og providerName. Systemet må definere connection string til de to kontekstene (databasene) som benyttes; «AKContext» og «RequestContext». 3.2 KONTEKST I sammenheng med programmering er konteksten en viktig del av en løsning. En kontekst kan defineres som en klasse som inneholder grunnleggende data i forbindelse med den løsningen den er tilknyttet, primært data med informasjon om forbindelse til database og hvilke objekter den inneholder. Konteksten har flere viktige funksjoner: 1 Refererer til connection stringen. Inneholder metadata som beskriver modellene. Holder kontroll på alle endringer som skjer i objektene via en kontroll-tracker. http://www.connectionstrings.com/ S i d e 8 | 53 Produktrapport Modulen inneholder en kontekst for sentral funksjonalitetshåndtering navngitt AKContext og en kontekst for funksjonalitetshåndtering av forespørsler navngitt RequestContext. Figur 3 - [Hver klient har sin egen RequestContext] 3.2.1 AKCO NTEXT AKContext inneholder en databasesett for alle objektene modulen benytter internt. Dette innebærer alle objektene som er tilknyttet hendelsesforløpet rundt kjernefunksjonaliteten. Disse settene er: DbSet<Account> Accounts DbSet<Transaction> Transactions DbSet<Posting> Postings DbSet<Client> Clients DbSet<Reference> References S i d e 9 | 53 Produktrapport Figur 4 - [AKContext] All dataflyt fra og til databasen går via denne konteksten, noe som gjør den svært sentral i modulen. Hvert DbSet håndteres i sine egne repositories. Dette er hensiktsmessig ettersom hvert objekt har unike attributter og metoder, og hvert repository er derfor en skreddersydd aksessor med all nødvendig funksjonalitet for å håndtere dataflyt for sitt objekt. Figur 5 - [Relasjoner mellom Objekt, Repository og AKContext] 3.2.2 REQUESTCONTEXT En RequestContext holder oversikt over henvendelser som er sendt inn til modulen. Når en henvendelse blir prosessert hashes denne og sammenlignes mot tidligere henvendelser og på den måten unngår man at den samme henvendelsen blir prosessert flere ganger. Hver enkelt klient har sin egen RequestContext, for å holde oversikt på sine henvendelser. Det er hensiktsmessig fordi det gjør oppslag mot databasen raskere, og en klient vil normalt sett kun være interessert i de forespørslene klienten har sendt selv. S i d e 10 | 53 Produktrapport 3.3 OPPSETT AV KONTOER Modulen bokfører transaksjoner som inneholder posteringer som skal posteres mot en gitt konto med et gitt beløp. Kontoene ligger lagret internt i modulen og må eksistere for å kunne benyttes. En konto består av et navn, et kontonummer, et attributt som tilsier om kontoen er aktiv, og et attributt som tilsier om posteringer på kontoen skal kunne overføres til et eksternt regnskapssystem. Dersom en konto er inaktiv vil det ikke være mulig å postere mot denne. Figur 6 - [Konvertering av kontoplan til Konto-objekter] Dersom en fil under prosessering benytter en konto som ikke eksisterer i systemet vil dette resultere i en feilmelding. Mer informasjon om feilhåndtering befinner seg i [feilhåndtering]. Klassen som håndterer kontoer og kommuniserer med AccountRepository heter AccountWriter. Her finnes metoder for å legge til nye kontoer individuelt eller via csv fil, endre egenskapene til eksisterende kontoer og konvertere kontoer til CSV. Figur 7 - [AccountWriter] 3.3.1 I MPORTERE KONTO FRA CS V Dersom klient velger å importere kontoene til sitt system ved hjelp av en CSV fil gjøres dette i AccountWriter ved bruk av AccountCSV. Det er en klasse som utgjør en CSVrepresantasjon av et konto objekt. Hver linje i filen vil leses ut som et AccountCSV objekt, før den oversettes til et Account objekt og til slutt lagres i databasen. S i d e 11 | 53 Produktrapport 3.4 KLIENT Klienten er som tidligere nevnt et system som tar klassebiblioteket i bruk. For at modulen skal vite hvor transaksjonen kommer fra, må alle transaksjoner knyttes til en klient. Dette gjørs gjennom at en klient sin id sendes sammen med transaksjonsforespørselen. For at modulen skal akseptere en forespørsel må klienten være registrert i modulen. 3.4.1 I MPLEMENTASJON AV IA RENAKUNDERESKO NTROCL IENT IArenakundereskontroClient er et interface ment for klientene. Interfacet inneholder metoder for å identifisere klienten internt i modulen og for å gi klienten muligheten til å motta transaksjonskvitteringene modulen returnerer. Etter endt postering av en transaksjon sendes en kvittering tilbake til klienten. Kvitteringen mottas i klienten, og det er opp til klienten å implementere funksjonalitet for videre håndtering. Detaljer om TransactionReceipt beskrives i [2.1.7 Transasksjonskvitteringer]. 3.5 GENERERING AV TRANSAKSJONSFORESPØR SEL Kjernefunksjonaliteten til modulen dreier seg om håndtering av transaksjoner. En klient vil sende inn en samling av transaksjoner som en transaksjonsforespørsel. En transaksjonsforespørsel ankommer normalt modulen i XML format, se underpunkt om XML formattering, og vil her bli omgjort til et TransactionRequest objekt. For å generere en TransactionRequest brukes klassen med navn TransactionRequestCreator. Klassen inneholder funksjonalitet for å konvertere en strøm, en filsti eller en liste av transaksjonsdata til en TransactionRequest som returneres til klienten. Denne kan deretter sendes inn til en annen klasse for behandling. En forespørsel består av: TransactionRequest - Data om selve Transaksjonsforespørselen TransactionData - Data om en gitt transaksjon PostingData - Data om en gitt posering S i d e 12 | 53 Produktrapport Figur 8 - [Parsing av transaksjonsforespørsel] S i d e 13 | 53 Produktrapport 3.5.1 XML FORMATERI NG En forespørsel blir utformet i XML ved hjelp av et XSD-skjema som modulen tilbyr. <?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsd:element name="transactionRequest"> <xsd:complexType> <xsd:sequence> <xsd:element name="transactions"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="unbounded" name="transaction"> <xsd:complexType> <xsd:sequence> <xsd:element name="date" type="xsd:dateTime" /> <xsd:element name="amount" type="xsd:double" /> <xsd:element name="financial_year" type="xsd:integer" /> <xsd:element name="financial_period"> <xsd:simpleType> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="1" /> <xsd:maxInclusive value="6" /> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="postings"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="unbounded" name="posting"> <xsd:complexType> <xsd:sequence> <xsd:element name="account_no" type="xsd:unsignedShort" /> <xsd:element name="parent_guid" /> <xsd:element name="reference" type="xsd:string" /> <xsd:element name="amount" type="xsd:double" /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="id" type="xsd:unsignedShort" use="required" /> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xs:schema> S i d e 14 | 53 Produktrapport Formatet som sendes inn må stå i samsvar med det formatet som forventes, ref. XSDskjemaet. Filer i feil format vil bli avvist av modulen, ved hjelp av en exception som må fanges opp av klienten. Data er pakket inn i en TransactionRequest tag som signaliserer at alt innhold er del av en forespørsel. En forespørsel kan inneholde en eller flere transaksjoner, Transaction, pakket inn i tag’en Transactions. En transaksjon kan igjen inneholde to eller flere posteringer, Posting, pakket inn i tag’en Postings. Figur 9 - [Beskrivelse av TransactionRequest] 3.5.2 HASH AV FORESPØRSEL – CHECKSUM Etter at forespørsel er omgjort til et TransactionRequest blir hele forespørselen hashet, og hashen lagret som et attributt kalt Checksum. Denne benyttes både når modulen sender kvitteringer tilbake til klienten, slik at klienten skal vite hvilken forespørsel kvitteringen gjelder, og for å kontrollere om en forespørsel er sendt inn fra før. Mer om det i neste kapittel. S i d e 15 | 53 Produktrapport 3.6 HÅNDTERING AV TRANSAKSJONSFORESPØR SEL Etter at data er vellykket omgjort til et TransactionRequest objekt kan klienten sende dette inn til klassen RequestHandler som vil utføre jobben med å prosessere forespørselen. Klassen fungerer som en kontroller i behandlingen av TransactionRequest objektet, og styrer hele prosessen fra mottak av objekt til kvittering er sendt. Den både tar imot objektet, verifiserer data, oppretter transaksjoner og posteringer, fullfører bokføringen og gir tilbakemelding til klienten uavhengig av om resultatet er positivt eller negativt. Alt via kall til andre klasser og metoder. Figur 10 - [RequestHandler - flyt] Hvordan RequestHandler benytter andre klasser er vist i tabellen under. Flyten er svært konsis, noen klasser aksesseres indirekte via klasser RequestHandler kaller direkte. Kolonner markert grønn aksesseres direkte fra RequestHandler klassen, imens kolonner markert med orange farger aksesseres indirekte. S i d e 16 | 53 Produktrapport # Klassenavn Metoder i bruk Hovedhensikt TransactionValidator( ) void VerifyPostings(List<PostingData> list, double transactionAmount) Verifisering av kontoer og beløp i transaksjonen TransactionRequestHan dler() bool ExistsAndTrim(TransactionRequest transactionRequest,IMessageReceiver messageReceiver) Kontrollerer om en forespørsel er behandlet fra før. void StoreTransactionRequest(TransactionR equest transactionRequest) Lagrer nye forespørsler i databasen til klienten (RequestContext). Oppdaterer denne basen med Guid når transaksjonen er behandlet. bool UpdateCompletedTransactionRequest(St ring checksum, int Id, Guid transactionGuid) TransactionHandler() Guid CreateTransaction(TransactionData data, int clientID) Kontroller for opprettelse av transaksjon og posteringer ut fra mottatt data, samt lagring av transaksjon til databasen. TransactionCreator() Transaction MapTransactionData(TransactionData data, int clientID) Oppretter og returnerer en transaction ut fra mottatt data PostingCreator() List<Posting> VerifyAndMapPostings(List<Postingdat a> list, Guid transactionId) Oppretter og returnerer en liste med postinger ut fra mottatt data Verifiserer parentId og oppretter Reference objekt, som settes inn i Posting objektet. TransactionRepository () void TryInsert(Transaction transaction) Lagrer transaksjon i databasen (AKContext). ReceiptSender() void SendReceipt(IMessageReceiver receiver, int transactionId, Guid success, string errorMessage = null) Kalles enten som følge av at en transaksjon har blitt innsatt i tabellen, eller som følge av at det har oppstått en feil på veien. S i d e 17 | 53 Produktrapport 3.6.1 KONTROLLERE TRANSAKSJONSFORESPØR SEL For å forhindre redundans og ubalanse i regnskapet må ikke samme forespørsel behandles flere ganger, med mindre alle transaksjonene ikke har blitt fullført. Alle forespørsler som mottas blir derfor lagret i databasen RequestContext, og en forespørsel vil alltid bli kontrollert mot denne databasen før modulen forsøker å prosessere den. Kontroll, lagring og oppdatering av forespørsler mot denne databasen vil bli utført i TransactionRequestHandler klassen. En beskrivelse av de forskjellige funksjonene i denne klassen følger nå, før rapporten fortsetter med dette avsnittet. 3.6.1.1 SJEKK O M FO RESPØRSEL ER BEHANDLET TIDLIGERE Checksummen i TransactionRequest sjekkes mot en tabell med alle tidligere prosesserte forespørsler, som ligger lagret i klientens RequestContext. Dersom checksummen finnes fra før tilsier dette at samme forespørsel har blitt behandlet tidligere. I dette tilfellet trimmes TransactionRequest objektet, hvilket tilsier at tidligere fullførte transaksjoner fjernes fra objektet. Dersom alle transaksjoner er behandlet tidligere og TransactionRequest objektet nå ikke inneholder transaksjoner avsluttes hendelsesforløpet. Hvis det fortsatt inneholder ubehandlet transaksjoner vil disse bli forsøkt behandlet. 3.6.1.2 TRIMMING AV FORESPØ R SEL Med trimming av forespørsel så menes det at man går gjennom alle transaksjoner i TransactionRequest objektet, og fjerner de transaksjonene som er vellykket behandlet fra før. Dersom er en transaksjon blir fjernet så sendes det en kvittering til klient om at denne er behandlet fra før, med melding «Transacion handled before». S i d e 18 | 53 Produktrapport Figur 11 - [Trimming av TransactionRequest] 3.6.1.3 LAGRING AV FORESPØRS EL En forespørsel som ikke er behandlet før må lagres til RequestContext databasen. Det opprettes et Request objekt, med en liste av RequestTransaction objekter. Dette objektet settes inn i databasen og tilsvarer en forespørsel med tilhørende transaksjoner. Request inneholder: RequestChecksum o Checksummen (hash av forespørselen) som ble generert tidligere. NumberOfTransactions o Antall transaksjoner i forespørselen. RequestTransactions o En liste med RequestTransaction objekt (transaksjoner) RequestTransaction inneholder: RequestChecksum S i d e 19 | 53 Produktrapport o Checksummen (hash av forespørselen) som ble generert tidligere. TransactionId o Id til transaksjonen, satt av klienten før innsending. TransactionGuid o Unik Guid som settes når transaksjonen er lagret. Denne vil alltid være lik Guid.empty ved opprettelse. Det betyr at transaksjonen ikke er behandlet enda. Figur 12 - [Request and RequestTransactions] Fortsettelse til avsnittet over: Modulen har nå fullført all validering av selve filen. Dersom for eksempel et strømbrudd inntreffer idet en forespørsel er under behandling, men kun har fullført 189 av 200 transaksjoner, vil klienten enkelt kunne fullføre resterende transaksjoner. Forespørselen sendes inn på nytt, modulen fjerner de 189 første transaksjonene, og sender klienten kvittering på at disse er behandlet fra før. Transaksjon nr. 190 til 200 vil bli behandlet på vanlig måte. S i d e 20 | 53 Produktrapport Figur 13 - [TransactionRequestHandler] Hovedhensikten til denne klassen kan sammenlignes med en dørvakt på en hipp nattklubb hvor ingen som har vært der før tillates inngang senere. Uten denne klassen ville transaksjoner kunne blitt behandlet igjen og igjen, noe som vil bryte med essensielle regnskapsprinsipper. Modulen ville kort sagt ikke vært pålitelig uten denne funksjonaliteten. Dørvakten(klassen) stopper gjester(transaksjoner) som har vært der før, men slipper inn nye «ansikt», selv om de ankommer med et gammelt følge (forespørsel). S i d e 21 | 53 Produktrapport Figur 13 - [Dørvakt metafor] 3.6.2 VALI DERING Etter at forespørselen er sjekket opp mot tidligere innsendte forespørsler, og eventuelt trimmet for behandlede transaksjoner, er neste steg validering av data. Dette er påkrevd for å sikre korrekt informasjon i modulen og regnskapet, samt oppfylling av vilkår i Bokføringsloven. For å spare ressurser er validering lagt etter kontrollen som sjekker om en forespørsel er behandlet fra før. Det er lite hensiktsmessig å validere en forespørsel som likevel ikke skal behandles. Valideringen skjer i en klasse som heter TransactionValidator, som igjen benytter seg av klassen AmountValidator. Alle posteringer tilhørende en transaksjon valideres, og krav stilles: S i d e 22 | 53 Produktrapport # Krav Kommentar Exception 1 Konto må eksistere i modulen, og den må være aktiv Dersom en transaksjon forsøker å benytte en ugyldig konto, vil det kastes exception. InvalidAccountException 2 Beløpet i transaksjonen må stemme overens med beløpene i posteringene. Dersom en transaksjon inneholder en sum som ikke stemmer overens med det som bes postert, så er det feil og det kastes exception. InvalidTransactionBalance Exception(sumPostings, sumAmount) 3 Summen av alle posteringsbeløp må være 0 En transaksjon består av et beløp som skal posteres mot debet (pluss) og kredit(minus) i regnskapet. Dersom disse ikke går i balanse, så er det feil og exception kastes. InvalidPostingBalanceExce ption(sumPostings) 4 En transaksjon må inneholde posteringer En transaksjon som ikke inneholder noen posteringer har ingen hensikt og det kastes exception EmptyPostingDataException Dersom en transaksjon stoppes, så kastes det en fielmelding (exception) som modulen behandler. Denne vil medføre at det genereres en kvittering til klienten, med informasjon om at transaksjonen ikke kunne gjennomføres. Grunnen til at transaksjonen er stoppet vil fremgå av kvitteringen. S i d e 23 | 53 Produktrapport Figur 14- [TransactionValidator] 3.6.3 LAGRING AV T RANSAKSJON Selve lagringen av en transaksjon håndteres i en egen klasse, TransactionHandler. Lagringen er det siste steget i prosessen en transaksjon gjennomgår. TransactionHandler benytter klassene TransactionCreator og PostingCreator til å opprette transaksjon med tilhørende posteringer, ut ifra data som mottas. Forløpet i TransactionHandler kan oppsummeres i 6 følgende steg: 1. 2. 3. 4. 5. 6. TransactionData og clientId ankommer TransactionHandler Et Transaction objekt opprettes ut ifra mottatt data En liste med Posting objekter opprettes med tilhørende Reference objekt Posteringene kobles til transaksjonen Transaksjonen blir forsøkt satt inn i databasen Guid’en til transaksjonen returneres S i d e 24 | 53 Produktrapport Figur 15 - [Oppbygging av en Transaction] Dersom en feil inntreffer under utførelsen av stegene avbrytes hendelsesforløpet. En feilmelding kastes til RequestHandler, som sørger for at det blir sendt en kvittering til klienten med informasjon om feilen. Steg 1: TransactionData objekt og klientens id mottas fra kallende rutine. TransactionData tilsvarer en enkelt transaksjon. Steg 2: Transaction objektet lages ved å kalle på klassen TransactionCreator. Denne oppretter objekt med bakgrunn i innsendt transaksjonsdata og klientId. Steg 3: En liste med Posting objekt opprettes ved å kalle på klassen PostingCreator. En liste med PostingData og en transaksjonsId sendes inn til klassen. For hver enkelt PostingData i listen sjekkes følgende: Et Posting objekt opprettes med bakgrunn i PostingData og transaksjonsId. Dersom posteringen inneholder en parentTransaction så betyr det at denne posteringen referer til en tidligere transaksjon. o ParentTransaction blir verifisert ved at strengen omgjøres til en Guid (parentGuid). Dersom dette ikke lar seg gjøre kastes det en feilmelding. S i d e 25 | 53 Produktrapport o Reference objektet knyttet til parentGuid hentes fra databasen. Finnes ikke dette kastes det en feilmelding av typen PostingParentNotFoundException med meldingen «Cannot find Posting Parent». o Reference objektet knyttes til posteringen. Dersom posteringen ikke har en parentTransaction betyr det at den selv blir en parent. Det betyr videre at det ikke eksisterer et Reference objekt tilhørende denne posteringen fra før, og et nytt Reference objekt opprettes og knyttes til posteringen. Steg 4: Listen med posteringer kobles til transaksjonen. Steg 5: For å fullføre operasjonen må transaksjonen settes inn i databasen, dette gjøres via TryInsert metoden i TransactionRepository. Dersom dette ikke går blir en feilmelding kastet og behandlet av modulen, som sender en kvittering med feilinformasjon til klienten. Steg 6: Dersom innsettingen er vellykket returnerer metoden Guid’en til transaksjonen den nettopp har satt inn i databasen. S i d e 26 | 53 Produktrapport Figur 16 - [Lagring av en Transaction] 3.6.4 OPPDATERE REQUEST MED GUID Etter at transaksjonen er vellykket lagret gjenstår det kun å oppdatere RequestContext databasen med transaksjonens Guid, slik at transaksjonen ikke blir behandlet på nytt dersom forespørsel sendes inn en gang til. Dette gjøres ved at TransactionRequestHandler kalles på nytt, og via metoden UpdateCompletedTransactionRequest blir transaksjonen oppdatert med Guid. 3.6.5 UTSENDELSE AV KVITTE RING Det siste som gjøres etter at en transaksjon er vellykket lagret, er å sende kvittering til klienten. ReceiptSender klassen benyttes til dette, den genererer en kvittering som blir sendt til klientens kvitteringsmottaker. S i d e 27 | 53 Produktrapport Klient vil altså motta en kvittering uavhengig av om transaksjonen er vellykket eller ikke. Kvitteringen vil inneholde en Guid dersom vellykket, eventuelt en tom Guid og feilmelding dersom en feil oppstår underveis. 3.7 KVITTERINGER En kvittering sendes klienten som følge av tre mulige årsaker: En transaksjon er behandlet fra før En transaksjon er vellykket postert En feil har oppstått under behandlingen av en transaksjon Klienten vil motta like mange kvitteringer som antallet transaksjoner som er sendt inn, dette uavhengig i utfallet under behandlingen. Figur 18 - [Kvittering - flyt] S i d e 28 | 53 Produktrapport Kvitteringen inneholder fire element som vist i Figur 18. Figur 18 - [Kvitteringens innhold] Klient kan ved hjelp av disse kvitteringene oppdage potensielle problemer, eksempelvis manglende posteringer, ubalanse i transaksjon eller posteringer, ugyldige kontoer eller feil parentId. Modulen sender ut kvitteringer til klientes kvitteringsmottaker, det er imidlertid opp til klienten å håndtere mottaket av kvitteringene og behandle eventuelle feilmeldinger. Modulen tar altså ikke noe ansvar for at disse blir behandlet. 3.7.1 RECEIPTSENDER For at en kvittering skal kunne sendes må den klassen som tar seg av leveransen først ha en mottaker. Denne mottakeren er naturligvis hos klienten, og klienten må implementere denne for å kunne ta i bruk modulen. Sending av kvittering skjer i metoden SendReceipt i klassen ReceiptSender. TransactionReceipt receipt = new TransactionReceipt { RequestChecksum = _requestChecksum, Success = success, TransactionId = transactionId, ErrorMessage = errorMessage }; receiver.ReceiveTransactionReceipt(receipt); Her opprettes først en kvittering, før kvitteringen sendes med kallet receiver.RecieveTransactionReceipt. En receiver er direkte oversatt en mottaker, og dette er altså klientens mottaker for kvitteringer. S i d e 29 | 53 Produktrapport 3.7.2 I MESSAG ERECEIVER Klassen IMessageReceiver er et interface brukeren av modulen må implementere i sin klient. Klassen består kun av en metode, ReceiveTransactionReceipt, som tar imot en kvittering. Denne metoden kalles fra flere steder i modulen og sett fra dens perspektiv er dette kun en brevsprekk i en postkasse. Modulen er kun interessert i å sende kvittering avgårde, og overlater videre håndteringen av kvitteringen til klienten. Figur 19 - [Kvitteringsmottaker] S i d e 30 | 53 Produktrapport 3.8 HENTE UT DATA Modulen har implementert diverse klasser for å hente ut data, dette skjer via egne leseklasser. Klassene inneholder kun metoder for uthenting av eksisterende data, det er ikke mulig å skrive til databasen via disse. Alle klassene benytter tilhørende Repository for å aksessere databasen. Modulen inneholder fire reader-klasser: TransactionReader PostingReader ReferenceReader AccountReader Figur 20 – [Oversikt over reader klassene] 3.8.1 UTTAK AV DATA TIL RE GNSKAPSSYSTEM I dagens inkassosystem, K90, overføres posteringene til et eksternt regnskapssystem. Det skjer i nattkjøringen, hvor alle aktuelle posteringer fra forrige dag eksporteres. Tilsvarende funksjonalitet var naturligvis et krav for den nye løsningen, og det er løst i modulen ved å tilby uthenting av de aktuelle posteringene. Logikken er implementert i en egen klasse, ExtractDataToAccountingSystem. Aktuelle posteringer skrives til en strøm (stream) som klienten sender inn ved kall til klassen. S i d e 31 | 53 Produktrapport Aktuelle posteringer overføres til et regnskapssystem via et AccountingRequest objekt, bestående av antall posteringer og selve posteringene. Hver postering er gjengitt i et AccountingData objekt som inneholder: Transaksjonsdato Regnskapsår Regnskapsperiode Kontonummer ParentTransaction (Guid) Beløp Klassen har følgende metoder og funksjonalitet: Returverdi Metodenavn Parametere Funksjonalitet AccountingReq est ConvertToAccounting Request() (List<Posting> postings) En liste med posteringer konverteres til en liste med AccountingData. Disse legges så til et AccountingRequest objekt som returneres List<Posting> GetAllNonWritten() List<Posting> GetAllWritten() (DateTime date) bool WriteAllNonWritten( ) (Stream stream, bool update = true) Returnerer en liste med alle posteringer for alle kontoene som har sin TransferToAccountingSystem satt true. Henter kun de posteringer som ikke er overført til regnskapssystemet fra før (posting.TransferedToAccounting System = null) Returnerer en liste med alle posteringer som ble overført til regnskapssystemet på oppgitt dato Henter alle ubehandlede posteringer og serialiserer disse til en stream. Dersom update er true settes alle posteringene som S i d e 32 | 53 Produktrapport behandlet. 1.Kaller GetAllNonWritten() sender listen med ubehandlede posteringer til ConvertToAccounting Request() bool WriteAllWritten() (Stream stream, DateTime date) bool WriteToStream() (Stream stream, AccountingReque st accountingReque st) bool MarkPostingsAsUpdat ed() List<Posting> postings) 2. Alle posteringene returneres som et AccountingReqest-objekt 3. AccountingReqest sendes til WriteToStream() med streamen metoden mottok 5. WriteToStream() sjekker om objektet er tomt og om det er mulig å skrive til den mottatte streamen 6. En XmlSerializer av typen AccountingReqest opprettes og serialiserer AccountingReqest objektet til streamen 7. Dersom update er true settes TransferedToAccountingSystem lik dagens dato for alle posteringer som er sendt til streamen 7. Bool returneres i henhold til resultat Henter alle posteringer som ble behandlet på den oppgitt datoen og serialiserer disse til streamen 1. Mottar en liste fra GetAllWritten(date) over alle posteringer som ble overført den dagen date tilsier 2. Sender de behandlede posteringen til ConvertToAccounting Request() 3. Sender listen med AccountingRequest objekter videre til WriteToStream() 4. Returnerer samme returvedi som WriteToStream() Tar imot en stream og en AccountingRequest, sjekker at objektet ikke er tomt og at streamen er skrivbar, serialiserer AccountingRequesten til streamen og returnerer bool basert på utfall Tar imot en liste med posteringer (som nettopp har blitt overført til S i d e 33 | 53 Produktrapport regnskapssystemet) og markerer alle disse som overført ved å sette TransferedToAccountingSystem lik dagens dato Funksjonaliteten tas i bruk ved at regnskapssystemet tilbyr en datastrøm posteringene kan mottas på. Figur 21 - [Uthenting av regnskapsdata] 3.9 FEILHÅNDTERING Dersom modulen ble levert uten feilhåndtering ville den minste lille feil ført til at hendelsesforløpet hadde stoppet, og det på en måte som ikke hadde gitt hint om hva det var som hadde gått feil. S i d e 34 | 53 Produktrapport For at run-time errors ikke skal inntreffe har vi definert og fulgt et sett med prinsipper som er implementert i koden til modulen. Disse prinsippene identifiserer potensielle farer ved visse handlinger/bruk av kodemønstre, beskriver graden av fare dette utgjør og løsning på faren. # Fare Faregrad Løsning 1 Databasekall kaster exception Alvorlig Håndter alle databasekall i try-catch blokk, håndter exceptions på en forsvarlig måte 2 Innsendt forespørsel inneholder feil Alvorlig Valider hver forespørsel helt ned på posteringsnivå før forespørselen bokføres 3.9.1 EXCEPTIONS For nøyaktig identifiering av potensielle feil har vi implementert våre egne exceptions. Hensikten med dette er å innsnevre identifiseringen av et inntruffet problem. Samtlige exceptions kalles på et punkt under validering av forespørsler, dersom gitt scenario inntreffer. Følgende unntak har fått sine egne exceptions: Exception EmptyPostingData InvalidAccount InvalidPostingBalance InvalidTransactionBalance InvalidRequest Bruksområde Message Kastes hvis en transaksjon ikke inneholder noen posteringer Kastes hvis en postering inneholder en konto som ikke eksisterer i modulen Kastes hvis et sett med posteringer ikke er i balanse Kastes hvis posteringene ikke stemmer med transaksjonens beløp «Transaction has no Postings» Kastes hvis et TransactionRequest ikke er PostingParentNotFound TransactionHandledBefore gyldig formatert Kastes hvis en oppgitt parentID ikke finnes i databasen Kastes hvis en transaksjon som er ferdig behandlet i systemet tidligere blir sendt inn på nytt «Invalid Account: {int accountno}» «Postings are not in balanse{double balance}» «Invalid Transaction balance: [Sum Transaction: {double transactionAmount}] [Sum Postings: {double postingsAmount}]» «Invalid request: {string requestChecksum}» «Cannot find Posting Parent: {Guid parentGuid}» «Transaction handled before» S i d e 35 | 53 Produktrapport Alle unntakene arver standard exception, og hvert exception har unik implementasjon. 3.10 SPORBARHET Et viktig krav til modulen er at transaksjoner og posteringer er sporbare i ettertid, det vil si at man skal lett finne tilbake til den opprinnelige kilden til posteringen. For å løse dette innførte vi Guid i modulen siden denne er garantert unik, og i vår kontekst er det parentTransactionID (Guid) som garanterer sporbarhet. Alle posteringer blir stemplet med parentTransactionID, og på den måten er det enkelt å finne alle posteringer knyttet til en gitt betaling eller annen form for transaksjon. Ved å sortere alle posteringer som har samme parentTransactionID vil man kunne se historikken til en gitt betaling fra start til slutt. Figur 22 - [Sporbarhet] S i d e 36 | 53 Produktrapport 3.11 ASYNC/SYNC HÅNDTERING Modulen er utviklet med to mulig løp, et synkront og et asynkront2. Begge har nøyaktig samme funksjonalitet, men den asynkrone vil kjøre flere tråder samtidig og derfor behandle forespørsler raskere. Eksempelvis inneholder RequestHandler to metoder som i prinsippet utfører de samme handlingene, dette er forklart litt nærmere under. Metoden CreateTransactions håndterer hver transaksjon sekvensielt. Dette innebærer at listen med transaksjoner itereres igjennom fra start til slutt og håndteres en av gangen. Klienten vil derfor motta kvitteringer på behandlet transaksjon i samme rekkefølge som de er arrangert i innsendt forespørsel. En transaksjon fullføres før modulen tar tak i en ny. CreateTransactionsAsync behandler transaksjonene i en forespørsel asynkront. Asynkron håndtering innebærer (ved korrekt bruk) at hver transaksjon tildeles sin egen tråd i operativsystemet. På denne måten kan flere transaksjoner (tråder) håndteres tilsvarende samtidig av CPU’en. Operativsystemet behøver altså ikke vente på at en transaksjon er ferdig behandlet før en ny kan tas tak i. Synkron Transactions håndtering eks. Asynkron Transaction håndtering eks. foreach (var trans in request.Transactions) { try { TransactionValidator.VerifyPostings(); TransactionHandler.CreateTransaction(); TransactionRequestHandlerUpdateRequestGuid(); ReceiptSender.SendReceipt(); } catch (Exception e) { ReceiptSender.SendReceipt(); } List<Task> tasks = new List<Task>(); foreach (var trans in request.Transactions) { tasks.Add(Task.Run(() => CreateTask(trans, request.RequestChecksum))); } Task.WaitAll(tasks.ToArray()); … Async Task CreateTask(TransactionData trans, string requestChecksum) { //Do same as in sync method } 2 http://blogs.infosupport.com/c-5-0-async-explained-as-simple-as-possible/ S i d e 37 | 53 Produktrapport Hensikten med implementasjon av både sync og async metoder er å kunne tilby klienten den løsningen som passer best. Klienten kan nå selv fritt benytte seg av den funksjonaliteten som er mest hensiktsmessig. For at modulen skal være asynkron/synkron gjennom hele hendelsesforløpet er det implementert asynkrone og synkrone metoder med samme funksjonalitet flere steder i modulen. 4 OPPBYGGING Dette kapittelet beskriver Arena Kundereskontros interne oppbygging. Kapittelet vil beskrive klasser, modeller og namespaces, sammenhengen mellom disse, prosjekter og deres dependencies og dataflyten ved sentrale prosesser i modulen. Kapitelets formål er å gi leseren en tilstrekkelig innføring i modulens struktur og oppbygning. 4.1 PROSJEKTSTRUKTUR Løsningen består av fire prosjekter: ArenaKundereskontro ArenaKundereskontro.Tests Test WebAPI Her inneholder det første prosjektet modulen, det andre enhetstester og testmetoder til modulen, det tredje et testprogram gruppen benyttet under utviklingen av produktet, og det fjerde et Web API. ArenaKundereskontro er helt selvstendig og er uavhengig av de andre prosjektene. De øvrige benytter seg alle av klassebiblioteket, og er derfor avhengige av ArenaKundereskontro. Figur 23 - [Prosjektstruktur] S i d e 38 | 53 Produktrapport 4.2 ORGANISERING AV KLAS SER - NAMESPACES ArenaKundereskontro består av åtte ulike namespaces. Formålet med innføringen av disse var å kategorisere funksjonaliteten til modulen i ulike bruksområder. Foruten det faktum at bruk av namespaces anses til å være god generell kodestandard bidrar det dessuten i å holde prosjektet ryddig og strukturert. Dersom navngivningen til disse namespacene er logiske vil en utestående deltaker kunne sette seg inn i et prosjekts ulike egenskaper og på den måten enklere danne seg et bilde av hvordan prosjektet fungerer. Vi har bruk mye tid på å gjøre navngivningen så logisk som mulig, og mener navnene står i samsvar med det vi prøver å formidle. En komplett oversikt over alle namespaces og tilhørende klasser er gjengitt i tabellen nedenfor. Klassetype Datamodell Databaseaksessor Context Interface Databehandler Exceptions Færgekode Grønn Sort Sort Lyseblå Blå Rød Namespace Klasser Innehold Accounts Account AccountCsv AccountReader AccountWriter AccountRepository Alt som omhandler en «Konto» i modulen. Inkluderer domenemodellen Account, CSVrepresentasjon av en konto og aksessorer for å skrive og lese en konto. Clients Client ClientManager ClientRepository IArenaKundereskontroClient Alt som omhandler en «Klient» i modulen. Inkluderer domenemodellen Client, aksessor for å skrive og lese, samt implementasjonen en bruker av klassebiblioteket må implementere for å identifisere seg. Context AKContext RequestContext De to kontekstene – datastrukturen i modulen. S i d e 39 | 53 Produktrapport Exceptions EmptyPostingDataException InvalidAccountException InvalidPostingBalanceException InvalidRequestException InvalidTransactionBalanceException PostingParentNotFoundException TransactionHandledBeforeException Alle egendefinerte Exceptions som indikerer feilsituasjoner i henhold til innlesing av forespørsler i systemet. Export ExtractDataToAccountingSystem Funksjonalitetet for å hente ut data til regnskapssystem. Requests Request RequestTransaction TransactionRequestCreator TransactionRequestHandler RequestRepository RequestHandler Alt som omhandler en «Request» i modulen. Innkluderer de to modellen som lagres i klientens sin database, Request og RequestTransaction, samt klasser som utfører logikk på disse. Transactions Transaction Posting Reference TransactionCreator PostingCreator TransactionHandler TransactionValidator AmountValidator TransactionReader PostingReader ReferenceReader TransactionRepository PostingRepository RefenceRepository Alt som omhandler en «Transaksjon» i modulen. Innkluderer modellene knyttet til en transaksjon, klasser for lesing og skriving, samt logikk for validering i henhold til regnskapsprinsipper. Transmission AccountingData TransactionData PostingData AccountingRequest TransactionRequest TransactionReceipt IMessageReceiver ReceiptSender Alt som skal sendes mellom klient og modulen. Her ligger XMLrepresentasjonene som modulen støtter. Disse klassene vil fungere som «beholdere» og ansvare over at «flytte» data. S i d e 40 | 53 Produktrapport Figur 24 - [Klasseoversikt] 4.3 BENYTTEDE BIBLIOTEKE R & RAMMEVERK Modulen er et produkt fullstendig utviklet av oss i gruppen. Dette innebærer at alt fra start til slutt, systemarkitektur og kode, er et resultat av gruppens arbeid. All kode er med andre ord egenprodusert. Vi har på tross av dette naturligvis benyttet oss av eksisterende biblioteker og rammeverk. 4.3.1 MICROSOFT .NET FRAMEW ORK Det mest sentrale rammeverket benyttet i oppgaven er .NET Framework3. Dette rammeverket er integrert i utviklermiljøet vi har tatt i bruk (Visual Studio) og er utviklet av Microsoft. Dette inneholder blant annet ASP.NET, Entity Framework, LINQ og Framework Class Library, som alle benyttes i stor skala. 3 http://en.wikipedia.org/wiki/.NET_Framework S i d e 41 | 53 Produktrapport 4.3.2 ENTITY FRAMEW ORK Entity Framework4 er et ORM (Object-relation mapper) som benyttes i produktet. Hensikten med dette er å konvertere databasetabeller til objekter for at siden å operere med disse objektene i stedet for at implementere egen dataaksesseringskode. 4.3.3 LINQ LINQ (Language Intergrated Query) benyttes for utføre «spørringsuttrykk», som ligner på SQL, for å ekstrahere data fra forskjellige datastrukturer som arrays og lister. Det brukes også sammen med Entity Framework i repositoriene for å filtre uthentingen av data fra konteksten. 4.3.4 MOQ MOQ5 er et «mocking-rammeverk» som benyttes for enhetstesting av klassene i modulen. Mocking kan beskrives som at simulere dataobjekter, hvilket er nødvendig når testing av klasser som er avhengig av data skal utføres. Data som ellers må ligge i en database er med MOQ mulig å simulere. Dette er brukt i testprosjektet ArenaKundereskontro.Test og nevnt i [Testrapporten]. 4.3.5 FILEHELPERS FileHelpers6 er et .NET bibliotek som gjør det mulig å importere og eksportere data fra bland annet CSV filer, og parse/oversette disse til et objekt. Dette er benyttet for å importere en kontoplan i modulen. 4 http://www.codeproject.com/Articles/683942/An-Absolute-Beginners-Tutorial-forunderstanding-E 5 https://github.com/Moq/moq4 6 http://filehelpers.sourceforge.net/ S i d e 42 | 53 Produktrapport 4.4 MODELLER 4.4.1 DO MENEMODELLER Lagring av data skjer via modeller. Vi har benyttet «Code First», et mye brukt prinsipp i Entity Framework. Dette prinsippet går ut på å definere objekter i gjennom kode, deretter koble disse objektene til en kontekst, for deretter å kunne foreta lesing/skriving mot objektene via konsteksten. Modulen har følgende syv domenemodeller, hver av fem eksisterer i AKContext og to i RequestContext: Klasse Representerer Nytte Transaction AKContext Representerer en bokført transaksjon med tilhørende posteringer Alle transaksjoner lagres som et Transaction-objekt i databasen Posting AKContext Representerer en bokført postering med beløp og konto Hver transaksjon har to/flere posteringer lagret som egne posterings-objekter Client AKContext Representerer en klient som benytter seg av systemet Gjør det mulig å finne ut hvem som har opprettet en transaksjon i modulen. Reference AKContext Representerer en referanse knyttet til en transaksjon Som regel vil alle klienter ha en referanse i sitt system knyttet til en transaksjon (sak). Denne refereansen knyttes til en foreldertransaksjon for å gjøre en transaksjon sporbar. Account AKContext Representerer en konto Alle gyldige posterings-kontoer skal være lagres som selvstendige Account objekt RequestTransaction Representerer en RequestContext Transaksjons-forespørsel Lagres i request-tabellen, hvor henvendelser lagres med id og guid. Request RequestContext Benyttes for å identifisere og behandle en fullstendig forespørsel. Representerer et sett med RequestTransactionobjekter S i d e 43 | 53 Produktrapport Figur 25 - [Domenemodeller i AKContext] Figur 26 - [Domenemodeller i RequestContext] 4.4.2 XML MODELLER Modulen benytter i tillegg til domenemodellene også XML-objekter. Et XML-objekt er en klasse som innholder XML-attributter for å definere hvordan klassen ser ut i som XML. Disse taggene gjør det mulig å konvertere et objekt til og fra XML med klassene XmlSerializer og XmlDeserializer i .NET. For å konvertere til et objekt er XMLdatan nødt til å være utformet som definert i objektet. Klasse Representerer Nytte TransactionRequest Representerer en forespørsel sendt fra klient med transaksjoner og tilhørende posteringer Xml-filen som sendes til modulen konverteres til et TransactionRequest objekt før det behandles videre TransactionData I prosessen fra en forespørsel Representerer en S i d e 44 | 53 Produktrapport Transaksjonsforespørsel sett ifra xml-filens definisjon på en transaksjon ankommer til den posteres behandles dataene i transaksjonen som et TransactionData-objekt PostingData Representerer en Posteringsforespørsel sett ifra xml-filens definisjon på en gitt postering Inneholder dataen til en individuell postering tilhørende et TransactionData objekt AccountingData Representerer en postering som overføres til et eksternt regnskapssystem Innholder informasjon om posteringen, i tilegg til nødvendig data fra dens transaksjon. Eksisterer i en AccountRequest. AccountingRequest Representerer et sett med AccountingData Holder oversikt over hele sett med posteringer (AccountingData-objekter) som er overført til regnskapssystem TransactionReceipt Representerer en transaksjonskvittering Sendes som dokumentasjon på en behandlet transaksjon. Figur 27 - [XML modeller] S i d e 45 | 53 Produktrapport 4.5 DATALAGRING/DATAAKSE SSERING Håndtering av dataflyten til og fra databasen er en viktig del av løsningen. Flyten må også implementeres på et sett som opprettholder god programmerings-standard i henhold til ryddig og strukturert kode. Bruk av repositories oppfyller alle kravene vi hadde til trygg data-aksessering. Et repository inneholder skreddersydde metoder for et spesifikt objekt, og kan inneholde alle metoder et system trenger for å legge til/aksessere eksisterende/modifisere eksisterende objekter. Repositoriene fungerer som mellom-stadier imellom «databasen (konteksten) og «brukeren (systemet via repository-metodene). Vi har implementert repositories for alle domenemodeller, som gjengitt i følgende tabell: Repository Aksess-klasser AccountRepository AccountReader AccountWriter ClientRepository ClientManager TransactionRepository TransactionReader PostingRepository PostingsReader RequestRepository TransactionRequestHandler ReferenceRepository ReferenceReader Aksess-klasser er implementert for å kun gi enten skrive-tilgang eller lese-tingang. Dette er hensiktsmessig i tilfeller hvor en gitt klasse har behov for å benytte seg av en del av funksjonaliteten i et repository, men ikke alt (for eksempel kun lesefunksjonalitet). Disse klassene er resultatet av programmering i henhold til prinsippet on minste privilegium, altså at en bruker kun skal gis tilgang til nødvendig funksjonalitet. 4.6 SIKKERHET Aksess til kontekst skjer alltid via de forskjellige repository-klassene. Gjennom å forhindre brukere av klassebibliotek direkt aksessering til kontekst er det ikke mulig å slette eksisterende data. I og med at det ikke skal være mulig å fjerne posteringer/transaksjoner (etter oppdragsgivers krav) inneholder ikke noen av S i d e 46 | 53 Produktrapport repository-klassene funksjonalitet for å slette data. Produktet er derfor sikkret mot at data ikke kan bli slettet. Detsamme gjelder innsetting av data i modulen. For å lagre noe til databasen er man nødt til å bruke en klasse som i forkant vil prosessere å validere uppgiftene før disse blir lagret. Det forsikkrer at det er kun reell data som blir lagret i databasen. Det er også tatt et bevisst valg om å sette restriksjoner av hva en bruker har adgang til og ikke med hjelp av access modifiers. 4.6.1 ACCESS MO DIFIERS «Access Modifiers» er nøkkelord som brukes i objektorienterte språk for å bestemme aksessibilitet av klasser, metoder og attributter. C# har følgende nøkkelord som klassebiblioteket benytter: Attributt Kan aksessers av Private Klassen Internal Kun klassebiblioteket Public Alle De klasser som kun skal aksesseres av Arena Kundereskontro har fått nøkkelordet internal. Dette er brukt på klasser der tanken er at de ikke skal brukes utenfør kjernen, deriblandt repositories. Metoder som utgjør en intern jobb i en klasse er satt til private, og er kun en jobb som skal utføres av klassen selv. Alt som skal være mulig å aksessere av de som implementerer klassebiblioteket er satt til public. 4.7 PROGRAMMERINGS STANDARD Programmerings standard beskriver retningslinjer og bevisste valg vi har fulgt under utviklingen av produktet. Disse standardene er direkte resultat av retningslinjer mottatt av arbeidsgiver, og er definert i kapittel 7 [Retningslinjer]. S i d e 47 | 53 Produktrapport 5 RETNINGSLINJER For å gjøre oppdragsgiver fornøyd har vi så godt det går prøvd å følge de retningslinjer oppdragsgiver har gitt oss. 5.1 OPPDRAGSGIVERS RETNI NGSLINJER Ettersom prosjektet har vært avsluttende oppgave på vår bachelor-utdanning har vi lagt mye fokus på at produktet skal levere opp til de krav og forventninger Kredinor har satt. For at overgangen fra utvikling til eventuell videreutvikling/vedlikehold skal gå mest mulig effektivt mottok vi retningslinjer tidlig i prosessen. Dette ble gjort ved at vår kontaktperson på Kredinor systematisk gjennomgikk ulike standarder som følges på huset, og spesifiserte hvilke av disse vi burde ta ibruk. Disse retningslinjene beskrev i hovedsak tre kategorier; programmeringsstandard, kommentering av kode og navngivning. 5.1.1 PROGRAMMERINGSSTANDA RD De retningslinjene vi har fulgt i forhold til programmering står ramset opp som individuelle setninger her: Modulen skal ha klasser med konkrete formål. Benytt svært logiske navn, både for namespaces, klasser og metoder. Komposisjon over arv. Konsistens over ytelse, men god ytelse over tid er også svært viktig. Programmere sån at koden er enkel at forstå, drifte og videreutvikle. 5.1.2 KO MMENTERING AV KODE Fra Høgskolen i Oslo og Akershus er alle gruppens medlem vant til at alle deler av kode som ikke er vesentlige skal kommenteres. Kommentarer i koden skal da være konsise og beskrivende slik at det blir vanskelig å misforstå en kommentert funksjons hensikt. Gruppen har derfor benyttet kommentarer i koden ved tidligere skolerelaterte prosjekter. S i d e 48 | 53 Produktrapport I det første møte gruppen gjennomførte med Kredinor ble kommentering av kode tatt opp som tema. Kredinor oppga da at de ikke benytter kommentering i kode på huset, og at de ikke ønsket at prosjektet skal gjøre det heller. Deres syn på kommentarer var at dette er unødvendig så lenge prosjektet har logisk og beskrivende navngivning av klasser og funksjoner. 5.1.3 NAVNGIVNI NG Et av de første kravene vi fikk i forhold til programmeringsstandard var at programmeringen skulle foregå på engelsk. Dette var ikke nytt for oss, ettersom all tidligere programmering på studiet til gruppen også har foregått på engelsk. Ettersom kommentering av kode var uønsket fra oppdragsgivers side la dette press på at navngivningen i prosjektet måtte være så beskrivende som mulig. Følgende punkter ble fulgt under utviklinger av prosjektet: Programmering skal navngis på engelsk. Klassenavn skal være så beskrivende at det ikke står tvil om hva klassen inneholder/gjør. Metoder/funksjoner skal ha beskrivene navn som sammen med eventuelle parametere utaleter all tvil om deres funksjonalitet. Prosjektet skal fordeles på en logisk og hensiktsmessig måte. S i d e 49 | 53 Produktrapport 6 KRAVSPESIFIKAS JON Her følger kravspesifikasjon med funksjonelle og ikke funksjonelle krav. Disse er alle implementert i en eller annen form, selv om ikke alt er implementert slik som beskrevet i spesifikasjon. Eventuelle Avvik er avklart med Kredinor. For å gi et klart bilde av hva det er vi skal utvikle har vi definert tre overordnede mål: Utvikle en modul som er uavhengig Utvikle en modul som posterer transaksjoner og gir full sporbarhet Utvikle en modul med hensiktsmessig design 6.1 FUNKSJONELLE KRAV # Tittel Brukerhistorie Grad Kommentar 1 Mottak av innbetalinger Systemet skal kunne ta imot nye innbetalinger mottat hos Kredinor Høy OCR filer med betalinger mottas fra banken. Disse blir lest inn hos Kredinor, og skal gjøres om til posteringer i den nye modulen. OCR filene skal ha likt format (eksternt-ansvar) KID eller saksnr er normalt identifikator 2 Mottak av reskontromeldinger Systemet skal kunne motta melding om innbetaling mottatt direkte hos oppdragsgiver Høy Meldingene om betaling fra oppdragsgiver skal kunne mottas på forskjellige vis: Melding via nettløsning (InfoBank) Melding via filer som mottas via InfoBank eller SFTP server Melding viaWebservice meldinger Meldingene skal kunne S i d e 50 | 53 Produktrapport mottas i forskjellige filformater, og mappes om i bizTalk KID, fakturanr, kundenr eller saksnr kan være identifikator 3 Postering mot kontoplan Transaksjoner skal Høy posteres mot gitt kontoplan for å lagres i regnskapet til Kredinor De transaksjonene som ikke vil kunne knyttes mot en reell konto, må knyttes mot en fiktiv kontoplan for å kunne bli en del av systemet. Disse transaksjonene skal også være sporbare, på lik linje med andre betalinger. 4 Stempling og sporbarhet Alle transaksjoner Høy knyttet til en innbetaling skal være sporbare i ettertid Transaksjonene må ha en unik transaksjons-ID som gjør det mulig å finne alle posteringer som er knyttet til den gitte transaksjonen 5 Motposteringer Ingen transaksjoner skal kunne slettes. Alternativt kan de motposteres Høy Dersom det muliggjøres å fjerne transaksjoner vil dette gi store feil i regnskapet til Kredinor 6 Fordeling av innbetalinger Fordeling av innbetaling må kunne mottas i retur Høy Når en betaling er fordelt i saksbehandlermodul må disse føres tilbake i reskontromodulen, med informasjon om hvordan de er fordelt. De vil bli gjenkjent via medfølgende GUID som ble sendt med den opprinnelige betalingen til saksbehandlermodulen. S i d e 51 | 53 Produktrapport 7 Omfordeling av innbetalinger Omfordeling av innbetaling må kunne mottas i retur Høy 8 Melding om utbetaling Melding om utbetaling skal kunne tas imot og posteres Høy 9 Melding om gebyrbelastning Melding om gebyrbelastninger fra rettsinstanser skal kunne tas imot og posteres Lav 10 Manuelle posteringer Systemet skal kunne ta imot manuelle posteringer Middels 11 Søkbarhet Alle transaksjoner skal være søkbare Høy En betaling som tidligere er er fordelt kan bli omfordelt i saksbehandlermodulen. Nye transaksjoner vil da mottas i reskontromodulen med samme GUID som tidligere. Saksbehandlermodulen må altså lagre GUID til hver enkelt betaling For kjernen er dette det samme som en vanlig transaksjon. Skjer via Web-API S i d e 52 | 53 Produktrapport 6.2 IKKE FUNKSJONELLE KRAV # Tittel Krav Kommentar 1 Soliditet Modulen skal ha en solid kjernefunksjonalitet Modulen skal oppfylle alle krav på en pålitelig måte som gir lite rom for feil 2 Oppetid Modulen skal være tilgjengelig hele døgnet, og ha en oppetid på minimum 95% Som et oppfølgende krav til #1 skal modulen kjøres kontinuerlig og ha svært liten nedetid. 3 Stressnivå Modulen skal ha høyt stress-nivå og skal kunne prosessere minimum 10.000 transaksjoner i timen Moduelen skal tåle svært stor pågang uten systemkræsj 4 Oppstart Modulen skal kunne tas opp igjen innen svært kort tid ved systemkræsj Ved systemkræsj skal modulen kjapt være tilbake i drift uten problemer 5 Clientoppkobling Det skal være enkelt å koble på en ny Client Modulen forutsetter oppsett før bibliotekets funksjonalitet kan tas i bruk. Denne oppkoblingen skal være enkel 6 Konstant balanse Ved systemkrasj skal alle transaksjoner fremdeles være i balanse etter restart For at modulen skal være pålitelig må alle transaksjoner alltid være i balanse. Modulen må også ta hensyn til systemkræsj 7 Bokføringsloven Modulen skal fullføre jobben i henhold til bokføringsloven Posteringer skal gjennomføres og dokumenteres som beskrevet i bokføringsloven S i d e 53 | 53 Arena Kundereskontro Testrapport Testrapport FORORD Denne testrapporten gir leseren innblikk i de ulike tester som er blitt gjennomført, formålet med testene, gjennomføringen av testene og utfall. Testrapporten beskriver hele test-prosessen av modulen fra planlegging til gjennomføring. Arena Kundereskontro er et komplekst bibliotek bestående av sammensatt funksjonalitet fordelt på mange ledd (klasser). Hoved funksjonaliteten til modulen er forsvarlig og rett håndtering av transaksjoner. Løsningen skal være tilfredsstillende i bruk og bokføring må utføres i henhold til Bokføringsloven. Modulen vil være i bruk døgnet rundt og strømmen av filer vil potensielt sett kunne være konstant. Modulen må derfor være pålitelig og stabil i drift. Dersom en feilsituasjon skulle inntreffe må modulen sørge for at alle transaksjoner enten gjennomføres helt, eller ikke i det hele tatt. Foruten pålitelig funksjonalitet, må modulen være robust nok til å håndtere store menger data så effektivt som mulig. Asynkron programmering er benyttet for å kunne prosessere flere transaksjoner samtidig, og vil testes i forhold til synkrone metoder med samme funksjonalitet. Testingen foregikk ved å implementere enhetstester, og ved å benytte Web-API’et og konsoll til å dokumentere effektivitet og forventet adferd. S i d e 2 | 15 Testrapport INNHOLD Forord .......................................................................................................................... 2 1 Testmål ................................................................................................................. 4 2 Enhetstesting ........................................................................................................ 5 3 2.1 Moq rammeverk ............................................................................................. 5 2.2 Testene.......................................................................................................... 9 Modultesting ....................................................................................................... 10 3.1 Test - enkeltfiler ........................................................................................... 11 3.1.1 3.2 Test - større filer / stresstest ........................................................................ 13 3.2.1 3.3 Konklusjon ............................................................................................ 12 Konklusjon ............................................................................................ 14 Test - verifisering av feilsituasjoner .............................................................. 14 3.3.1 Konklusjon ............................................................................................ 15 S i d e 3 | 15 Testrapport 1 TESTMÅL Tanken bak testene som er utført mot Arena Kundereskontro er å forsikre at funksjonaliteten fungerer som ønsket ved operasjoner som utføres ofte. Under planleggingsfasen i utviklingsprosessen var TDD et tema som ble tatt opp til diskusjon. Gruppen ble enige om å utelate TDD i denne omgang, og heller implementere tester som verifiserer funksjonalitet til eksisterende metoder. Overordnede mål for hva som skulle testet ble inndelt i fem punkter: # Mål Kommentar 1 Testene skal dokumentere at kjernefunksjonalitet fungerer som ønsket Testene skal ikke utelate viktig funksjonalitet, men forsikre forventet resultat av alle vesentlige deler av koden 2 Testene skal dokumentere modulens kapasitet Testene skal teste og dokumentere modulens kapasitet ved å lese inn mange og store filer samtidig og i rask rekkefølge. Ved å danne en kø av filer ønsker vi å teste kapasiteten, og at den lever opp til kravene fra oppdragsgiver. 3 Testene skal simulerer input og lagring av data i modulen. Testene skal simulere innsendt data i forventet kontekst. Dataen skal både være rett og galt formatert, testene skal dokumentere feilhåndtering. 4 Testene skal ikke modifisere/erstatte/slette eksisterende data Testene skal benytte samme objekter og tabeller som modulen, men aksessere en separat database 5 Testene skal ha beskrivende navn Det skal være mulig å forstå formålet til en test kun ved å lese testens navn 6 Testene skal være pålitelige En godkjent test skal være bevis nok på av testet funksjonalitet er pålitelig S i d e 4 | 15 Testrapport 2 ENHETSTESTING En enhetstest tester en så liten del av en gitt samling kode som mulig, eksempelvis en metode, og sjekker at atferd og returnert data er som forventet. Tidlig i prosessen benyttet vi interfaces i prosjektet. Ved testing ble hvert interface implementert i såkalte stub-metoder, hvor metodene hadde samme signatur, men ulik adferd. Adferden til stub-tester skal simulere det originale utgangspunktet, men uten å aksessere database eller foreta tidskrevende spørringer. Parameter-sjekk, retur av konstanter og bool-verdier basert på uvesentlige parameter er eksempler på hva stubtestene dokumenterer. Nyttigheten av disse testene ble minimal da vi forstod at mange av testene kun fungerte som parameter-sjekker og get-metoder. Etter å diskutert funksjonaliteten til stub-testene nærmere oppsto det etterhvert enighet i gruppen om at disse testene ikke dokumenter forventet funksjonalitet tilstrekkelig. 2.1 MOQ RAMMEVERK Vi kom frem til at vi ved hjelp av testrammeverket Moq ville kunne tilfredsstille alle overordnede krav til testingen. Moq er et rammeverk utviklet for .NET og C# som tillater bruker å simulere et objekts egenskaper og oppførsel, uten å opprette en reel instans av objektet. Det samme gjelder kontekster, noe som innebærer at en MockContext kun er en kopi av den originale konteksten, som vil befinne seg i minnet. S i d e 5 | 15 Testrapport MockContexten vil inneholde de samme tabellene som den konteksten den simulerer, men data i disse tabellene vil ikke overføres. Data må opprettes i minnet dersom det er ønskelig å gjøre spørringer mot eksisterende elementer. Bruken av Moq er svært nyttig da det tillater spørringer mot database uten å påvirke eksisterende data. Likevel er det den samme funksjonaliteten som testes, ettersom enhetstestene og modulen i prinsippet benytter de samme metodene. Moq testene ble inndelt i to kategorier: 1. Tester som ikke benyttet spørringer 2. Tester som benyttet spørringer (queryable) En moq-test består av et herme-Sett (MockSet) og en herme-Kontekst (MockContext). Mock-settet er en kopi av et databasesett, som settes til å inneholde den objektinstansen aktuell testmetode skal teste funksjonalitet på. Dersom en metode som returnerer alle posteringer med gitt dato skal testes, må DbSet altså settes til å inneholde Posting-objekter. Mock-konteksten er en kopi av løsningens kontekst, og kobles til mock-settet for å spesifisere hvilke typer objekter det skal være mulig å bruke i konteksten. Opprettelse av mock-Context og mock-Object er likt for både spørring-tester og ikkespørring tester. I tilfeller hvor det er hensiktsmessig å foreta spørringer (eksempelvis for å hente ut data fra metoder som bruker konteksten) må data som eksisterer i databasen simuleres og gjøres Queryable 1først. Dette gjøres ved å opprette en liste 1 Queryable – Et sett med instrukser som kan sendes til database S i d e 6 | 15 Testrapport med all data, bestående av samme objekt-instanser som skal hentes, sette denne til AsQueryable(), for så å gjøre dette til en del av Mock-settet. Figur 1 [Moq-test] Med illustrasjonen over som utgangspunkt skjer følgende i en mock-test uten queryfunksjonalitet: ● ● ● ● ● ● ● 1. Et DbSet<Posting> opprettes, 2. Et Posting-objekt opprettes, 3. En mock-context opprettes 4. DbSet<Posting> og mockContext kobles sammen 5. Konteksten brukes til å lage en service av PostingRepository 6. Posting-objektet settes inn i servicens Insert-metode 7. Testen verifiserer at innsettingen skjedde og at SaveChanges ble kalt etterpå S i d e 7 | 15 Testrapport Figur 2 [Moq-test med query] Med illustrasjonen over som utgangspunkt skjer følgende i en mock-test med queryfunksjonalitet: ● ● ● ● ● ● ● ● ● ● ● 1. En liste med posteringer opprettes i minnet. Ettersom Kontonummer er den eneste attributten det skal gjøres spørringer imot her inkluderes kun denne. 2. Et MockSet opprettes 3. MockSettet blir satt til å returnere listen av sin provider 4.Oppsett 5.Oppsett 6.Oppsett 7. En MockContext opprettes 8. MockContext og MockSet kobles sammen 9. En service for klassen PostingRepositoryopprettes med MockContexten som parameter 10. Servicens GetPostingsForAccount returnerer en liste med alle posteringer med kontonummer gitt det medsendt som parameter 11. En assert test kjøres for å se om resultatet er som forventet S i d e 8 | 15 Testrapport 2.2 TESTENE Vi implementerte 23 enhetstester i prosjektet, følgende deler ble testet: ● Henting av alle kontonummer for overføring til regnskapssystem ● Henting av alle aktive kontoer ● Henting av alle aktive kontonummer ● Opprettelse av ny konto ● Deaktiver konto ● Aktivere konto for overføring til regnskapssystem ● Sjekker om en request er sendt inn fra før ● Henter alle postings for en spesifikk konto ● Henter alle postings for en gitt reference ● Henter alle postings ● Sjekker feilmelding dersom det ikke eksisterer noen postings i transaction ● Henter alle transactions for en gitt regnskapsperiode ● Henter alle transactions som er opprettet fra og med en gitt dato ● Henter alle transactions som er opprettet i en gitt periode ● Setter inn en transaction ● Forsøker å parse ugyldig fil fra path ● Forsøker å parse gyldig fil fra path ● Forsøker å parse ugyldig fil fra stream ● Forsøker å parse gyldig fil fra stream ● Forsøker å parse gyldig fil fra TransactionData S i d e 9 | 15 Testrapport 3 MODULTESTING Testingen er foretatt med XML filer av forskjellige størrelser, og med forskjellig innhold. Gjennom denne testingen skal modulens hastighet måles, og det vil bli foretatt innlesing av filer med og uten parentID, og hvor mengden av transaksjoner i hver fil er 10, 100 eller 1.000. De samme filene testes både via webklienten (Web-API), og via program direkte i Visual Studio, hvor resultatet vises i konsollvinduet. En hypotese vi har er at testingen er raskere via konsollen, og at asynkron innlesing er raskere enn synkron innlesing. Vi vil også utføre testing med større filer i konsollen, både enkeltvis og flere samtidig. Dette for å stressteste modulen, og samtidig få noen svar på antatt kapasitet. All testing er utført på en Samsung laptop, Intel(R) Core(™) i5-3337U CPU @ 1.80GHz. Den har 2 kjerner og 4 logiske prosessorer. S i d e 10 | 15 Testrapport 3.1 TEST - ENKELTFILER Testresultat Konsoll Web-API Sync Async Sync Async Test 1 30 s 14 s 46 s 10 s Test 2 33 s 14 s 43 s 11 s Test 3 34 s 16 s 45 s 14 s Snitt 32 s 15 s 45 s 12 s Test 1 31 s 14 s 46 s 10 s Test 2 33 s 14 s 43 s 11 s Test 3 33 s 16 s 45 s 14 s Snitt 32 s 15 s 45 s 12 s Fil med 100 transaksjoner - uten Test 1 parent transaksjon 34 s 17 s 60 s 17 s Test 2 35 s 15 s 46 s 15 s Test 3 34 s 14 s 48 s 19 s Snitt 34 15 s 51 s 17 s Fil med 100 transaksjoner - med Test 1 parent transaksjon 37 s 18 s 20 s 14 s Test 2 34 s 19 s 21 s 17 s Test 3 35 s 17 s 31 s 12 s Fil med 10 transaksjoner - uten parent transaksjon Fil med 10 transaksjoner - med parent transaksjon S i d e 11 | 15 Testrapport Fil med 1.000 transaksjoner uten parent transaksjon Fil med 1.000 transaksjoner med parent transaksjon Snitt 35 s 18 s 24 s 14 s Test 1 536 s 52 s 1188 s 32 s Test 2 398 s 51 s 533 s 37 s Test 3 537 s 52 s 551 s 86 s Snitt 490 s 52 s 757 s 52 s Test 1 282 s 96 s 304 s 116 s Test 2 263 s 91 s 292 s 57 s Test 3 278 s 100 s 306 s 58 s Snitt 274 s 96 s 301 s 77 s 3.1.1 KONKLUSJON Testen avdekket flere interessante resultat, følgende kan leses ut fra rapporten: ● Vi ser at det omtrent ikke er tidsforskjell mellom prosessering av 10 og 100 transaksjoner. ● Vi ser også at det asynkron innlesing bruker omtrent halve tiden for 10 og 100 transaksjoner i forhold til synkron innlesing, mens det ved 1.000 transaksjoner er en betydelig forbedring for asynkron innlesing, opp mot 10 ganger så raskt. ● Innlesing via konsoll gir ganske stabile resultat, mens det for innlesing via WebAPI varierer litt mer. Vi ser at hypotesen om at asynkron innlesing er raskere enn synkron innlesing stemmer bra. Når det gjelder hypotesen om at innlesing via konsoll er raskere enn innlesing via Web-API så er resultatene mer usikre. Hypotesen er basert på erfaring ved testing underveis i prosjektet, men vi fant en ganske interessant effekt under testingen. Det viste seg at tidsbruken falt drastisk dersom man lot nettleseren (WebAPI) jobbe i bakgrunnen i stedet for å følge med på den under innlesing. Vi har ikke noen god forklaring på hvorfor det er slik. Det viser seg også å være en del variasjon i tidsforbruk ellers også, noe som vi antar har med belastning av webserveren å gjøre. S i d e 12 | 15 Testrapport Konklusjonen etter testingen er at vi asynkron innlesing er vesentlig raskere enn synkron innlesing, og at tidsgevinsten ved asynkron innlesing stiger betraktlig jo større filene er. Vi vurderer det også slik at resultatene fra konsoll innlesing er mest korrekt, og velger derfor å benytte konsoll for stresstesting og testing med enda større filer. 3.2 TEST - STØRRE FILER / STRES STEST Testresultat - større filer / stresstest Konsoll Async Innlesing av 5 x 1.000 transaksjoner 453 s Innlesing av 5 x 1.000 transaksjoner 467 s Innlesing av 10 x 1.000 transaksjoner 429 s Innlesing av 10 x 1.000 transaksjoner 626 s Innlesing av 1 x 10.000 transaksjoner 620 s Innlesing av 2 x 10.000 transaksjoner 1383 s Innlesing av 5 x 10.000 transaksjoner 4203 s Innlesing av 30 x (3 x 1.000) transaksjoner 3316 s Totalt 200.000 transaksjoner 10638 s Snitt 57 s / 1.000 transaksjoner S i d e 13 | 15 Testrapport 3.2.1 KONKLUSJON Testen viser at modulen leverer gode resultat også på store filer ved asynkron innlesing. Vi valgte kun å teste asynkront her, siden vi anser det som den meste aktuelle måten å benytte. Konklusjon er at den leverer godt over kravet om 10.000 transaksjoner i timen. Ved innlesing av 10 filer med 1.000 transaksjoner hver tok det ca. 7 min før alt var innlest. En fil på 10.000 transaksjoner tok ca. 10 min. Flere filer på 10.000 transaksjoner hver ser ut til å ta lengre tid i snitt, så man kan anta at maskinen sliter litt med for mange tasks/tråder samtidig. Vi vil derfor anbefale og ikke kjøre for mange store filer parallelt, men ytelsen kan også forventes å være mye bedre på en kraftig server. Stresstesten viser at modulen prosesserer transaksjoner godt selv etter hvert som basen fyller seg opp, og ligger godt innenfor kravene til 10.000 transaksjoner i timen. Vi antar at modulen vil takle fra 50.000 transaksjoner og oppover pr. time, alt etter hvilken maskinvare og prosessorkraft den kjører på. 3.3 TEST - VERIFISERING AV FEIL SITUASJONER Testresultat Leser samme fil om igjen Web-API Transaction handled before Sum postering ulik beløp i transaksjon Invalid Transaction balance: [Sum Transaction: 246] [Sum Postings: 245] Postering ikke i balanse Postings are not in balance: -1 Feil kontonummer Invalid Account: 9999 Feil parentID (eksisterer ikke) Cannot find Posting Parent: c0f2885a-69c6-419dbb1d-5f1e256c8565 Transaction uten postings Transaction has no Postings. S i d e 14 | 15 Testrapport Feil formattering av XML filen Returnerer HttpStatusCode.InternalServerError med Exception objekt (Det er en feil i XMLdokumentet) 3.3.1 KONKLUSJON Til slutt testet vi diverse feilsituasjoner som kan oppstå underveis når en transaksjon blir forsøkt lest inn. Vi laget en testfil med diverse feil, og verifiserte at disse ga forventet feilmelding. Testene over viser at de gjør det, og vi kan derfor være sikre på at modulen gir korrekt tilbakemelding til brukeren (klienten) ved de konkrete feilsituasjonene. S i d e 15 | 15 Arena Kundereskontro Vedlegg 1: Brukermanual Vedlegg 1: Brukermanual BRUKERMANUAL FORORD Dette er en brukermanual til klassebiblioteket Arena Kundereskontro, heretter også kalt modulen. Denne er ment brukt for de som skal implementere klassebiblioteket, og vil forklare hvordan man gjør nødvendig oppsett og implementering for å kunne ta i bruk modulen. Manualen vil også forklare hvilke klasser og metoder i biblioteket man forholder seg til, og hvordan disse kan brukes. Til slutt vil det gis litt informasjon om hvilke typer kvittering / feilmeldinger som kan mottas tilbake, og hva de forskjellige statusene betyr. S i d e 2 | 11 Vedlegg 1: Brukermanual INNHOLD Forord .......................................................................................................................... 2 1 ConnectionString .................................................................................................. 4 2 Registrere ny klient ............................................................................................... 4 3 Implementering av klient og mottak av kvitteringer ................................................ 4 4 Importere kontoplan .............................................................................................. 5 5 Genere transaksjonsforespørsel ........................................................................... 6 6 Postering av transaksjonsforespørsel ................................................................... 6 7 Exportere posterte posteringer til regnskapssystem .............................................. 6 8 Aktivere/deaktivere kontoer ................................................................................... 7 9 Hente ut data ........................................................................................................ 7 10 Kvitteringer / Feilmeldinger .............................................................................. 10 S i d e 3 | 11 Vedlegg 1: Brukermanual 1 CONNECTIONSTRING Det første som må gjøres er å sette opp connectionString til databasene, det gjøres ved å lage en egen XML fil i prosjektet som kalles “ConnectionStrings”. Eksempel: <connectionStrings> <add name="AKContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=AKContext;Integrated Security=SSPI;Pooling=false" providerName="System.Data.SqlClient" /> <add name="RequestContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=RequestContext;Integrated Security=SSPI;;Pooling=false" providerName="System.Data.SqlClient" /> </connectionStrings> 2 REGISTRERE NY KLIENT Før man kan ta i bruk modulen må også klienten som skal bruke den registreres, uten registrering vil ikke modulen akseptere transaksjoner. Det gjøres ved å kalle på ClientManager og metoden AddNewClient o Man sender inn navn på klienten, samt at man kan sende med om klienten skal være aktiv eller ikke. Default er aktive (true), noe den må være for at modulen skal godta oppdrag fra klienten. Metodesignatur: public Client AddNewClient(string name, bool active = true) 3 IMPLEMENTERING AV KL IENT OG MOTTAK AV KVITTERINGER Klient må deretter implementere interface IArenaKundereskontroClient og IMessageReceiver, som sørger for at modulen kan hente ut Id’en til klienten, og at kvitteringer blir mottatt av klienten. Hva man videre gjør med kvitteringene er opp til klienten. Eksempel på implementasjon: class TestClient : IArenaKundereskontroClient, IMessageReceiver { public int ClientId() { return client.id; S i d e 4 | 11 Vedlegg 1: Brukermanual } public IMessageReceiver MessageReceiver() { return this; } public void ReceiveTransactionReceipt(TransactionReceipt receipt) { Console.WriteLine("[" + receipt.TransactionId + "] " + receipt.Success + " " + receipt.ErrorMessage); } } 4 IMPORTERE KONTOPLAN Dersom klient har egne kontoer som skal benyttes, og disse ikke allerede er registrert i modulen, så må dette gjøres før det er mulig å postere mot de. Det gjøres ved kall til AccountWriter og metodene: InsertNewAccount o For innsetting av en enkelt konto. Kontonummer, navn (beskrivelse) og om posteringer på kontoen skal overføres til regnskapssystem må være med. Alle nye kontoer settes default til aktiv. InsertAccountFromFile o For innsetting av flere kontoer fra en csv fil. Denne må være formatert på korrekt måte, med feltene “Konto,Navn,OverføringTilAxapta,Aktiv” Eksempel: 1000,“Trondheim Konverteringsfeil”,False,True Metodesignatur: public Account InsertNewAccount(int accountNo, string name, bool transferToAccountingSystem) public int InsertAccountFromFile(Stream stream) S i d e 5 | 11 Vedlegg 1: Brukermanual 5 GENERE TRANS AKSJONSF ORESPØRSEL Etter at de fire foregående punktene er gjennomført, og oppsettet er i orden, så er det klart til å lage en TransactionRequest. Det gjøres ved kall til TransactionRequestCreator og metodene: CreateTransactionRequest o Det er tre metoder med dette navnet, enten kan man sende inn en path(string), en stream, eller en liste med TransactionData. Benytter man den siste metoden må man altså mappe forespørsler til TransactionData selv. Metodesignatur: public TransactionRequest CreateTransactionRequest(string path) public TransactionRequest CreateTransactionRequest(Stream stream) public TransactionRequest CreateTransactionRequest(List<TransactionData> transactions) 6 POSTERING AV TRANS AKSJONSFORES PØRSEL Når request er mottatt tilbake fra TransactionRequestCreator, så skal dette sendes videre inn til RequestHandler og metodene: CreateTransactions o Utfører innlesing og postering synkront. CreateTransactionsAsync o Utfører innlesing og postering asynkront. Metodesignatur: public void CreateTransactions(TransactionRequest request) public async Task CreateTransactionsAsync(TransactionRequest request) 7 EXPORTERE POSTERTE P OSTERINGER TIL REGNSKAPSSYSTEM Når man oppretter kontoer kan man angi om posteringer mot denne kontoen skal overføres til regnskapssytemet, via feltet transferToAccountingSystem. Posteringer som føres mot slike kontoer kan hentes ut via kall til ExtractDataToAccountingSystem og metodene: WriteAllNonWritten o Ber om å få alle nye posteringer som ikke er oppdatert som eksportert fra tidligere. Disse blir skrevet til den streamen som sendes inn. I tillegg S i d e 6 | 11 Vedlegg 1: Brukermanual kan man angi om disse skal oppdateres som eksportert eller ikke, default er oppdatert (true). WriteAllWritten o Ber om å få alle posteringer som ble eksportert en gitt dato. Metodesignatur: public bool WriteAllNonWritten(Stream stream, bool update = true) public bool WriteAllWritten(Stream stream, DateTime date) 8 AKTIVERE/DE AKTIVERE KONTOER Det er mulig å aktivere/deaktivere kontoer. En konto som skal benyttes må være aktiv. Kontoer kan ikke slettes, men man kan altså deaktiver den dersom det ikke skal være lov å postere til den lenger. Dette gjøres via AccountWriter og metoden: SetActive o Kontoer kan både aktiveres og deaktiveres via denne metoden. Metodesignatur: public bool SetActive(int accountNumber, bool active) 9 HENTE UT DAT A Det finnes diverse klasser og metoder for å hente ut informasjon/data fra modulen. Disse forklares kort her: AccountReader o GetAllAccounts Henter en liste av alle kontoer. o FindAccount Henter en gitt konto. Metodesignatur: public List<Account> GetAllAccounts() public Account FindAccount(int id) ClientManager o FindClientByName Henter ut klientId til en klient. S i d e 7 | 11 Vedlegg 1: Brukermanual Metodesignatur: public Client FindClientByName(string name) PostingReader o GetAll Henter alle postings i modulen. o FindByParentTransactionId Henter alle postings med en gitt parentId. o FindByAccount Henter alle postings for en gitt konto. o FindByReference Henter alle postings for en gitt reference. Metodesignatur: public public public public List<Posting> List<Posting> List<Posting> List<Posting> GetAll() FindByParentTransactionId(Guid parent) FindByAccount(int accountNo) FindByReference(string reference) ReferenceReader o FindReference Henter reference til en gitt parentId, den vil også inneholde alle postings. public Reference FindReference(Guid parent) TransactionReader o FindTransaction Henter en gitt transaction. o GetTransactions Henter alle transactions i modulen. o GetTransactionsForPeriod Henter alle transactions for en gitt periode, dersom bare fra dato oppgis så hentes alt til og med i dag. Dato det sjekkes mot her er registreringsdato i modulen. o GetTransactionsForAccountingPeriod S i d e 8 | 11 Vedlegg 1: Brukermanual Henter alle transactions for en gitt regnskapsperiode. Her kan man f.eks. hente alle for regnskapsåret 2014, uavhengig av registreringstidspunkt. public Transaction FindTransaction(Guid id) public List<Transaction> GetTransactions() public List<Transaction> GetTransactionsForPeriod(DateTime from) public List<Transaction> GetTransactionsForPeriod(DateTime from, DateTime to) public List<Transaction> GetTransactionsForAccountingPeriod(int fromYear, int toYear, int fromPeriod, int toPeriod) S i d e 9 | 11 Vedlegg 1: Brukermanual 10 KVITTERINGER / FEILMELDINGER Dersom det er feil format i filen man forsøker å lese inn, slik at denne blir avvist ved parsing, så fil modulen kaste en InvalidRequestException med informasjon om at det er feil i XML filen. Denne må fanges opp og behandles av klienten. Hvis filen derimot er korrekt formatert, og parsing går greit, så vil feilmelding blir behandlet av modulen. Modulen vil returnere kvitteringer med feilmeldinger, som klienten kan behandle som den ønsker (ref. punkt 3 over). De aktuelle feilmeldingene er listet opp her: TransactionHandledBeforeException o Transaksjonen er lest inn fra før Returnerer kvittering med error message: Transaction handled before. EmptyPostingDataException o Transaction inneholder ingen postings, og det er derfor ikke noe å postere. Returnerer kvittering med error message: Transaction has no postings. InvalidAccountException o En av kontoen man prøver å postere til er ugyldig. Returnerer kvittering med error message: Invalid Account. InvalidPostingBalanceException o Posteringene er ikke i balanse, total debet for posteringene er ulik total kredit for posteringene. Returnerer kvittering med error message: Postings are not in balance. InvalidTransactionBalanceException o Transaksjonen er ikke i balanse med posteringene. Beløp i transaksjonen er ulik samlet beløp for posteringene. Returnerer kvittering med error message: Invalid Transaction balance. PostingParentNotFoundException o Når man oppgir en parentId i posteringen, så må denne også eksisterer i databasen. Feilmeldingen betyr at modulen ikke finner oppgitt parentId. Returnerer kvittering med error message: Cannot find Posting Parent. S i d e 10 | 11 Vedlegg 1: Brukermanual Eksempel på hvordan en kvitteringsmelding kan vises: S i d e 11 | 11 Arena Kundereskontro Vedlegg 2: Dokumentasjon av Web-API Vedlegg 2: Dokumentasjon av Web-API DOKUMENTASJON AV WEB-API FORORD Web API virker som en bruker av modulen ArenaKundereskontro. Denne består av to deler: Et ASP.NET Web API som behandler HTTP forespørsler En web-applikasjon laget med AngularJS, HTML og CSS, som er et brukergrensesnitt mot web-servicen. Rapporten er derfor delt opp i to hoveddeler som henviser til de to delene; Back End og Front End. Denne rapporten bygger på rapporten ArenaKundereskontro, og forutsetter at leseren har kjennskap til dette klassebibliotek. S i d e 2 | 19 Vedlegg 2: Dokumentasjon av Web-API INNHOLD Forord .......................................................................................................................... 2 1 Bakgrunn ................................................................................................................ 4 2 Kravspesifikasjon ................................................................................................... 5 3 Back End ................................................................................................................ 6 3.1 ASP.NET Web API ........................................................................................ 6 3.1.1 3.2 Controllers ..................................................................................................... 6 3.2.1 Implementasjon av ArenaKundereskontro ..................................................... 7 3.4 Funksjonalitet................................................................................................. 8 Behandling av transaksjonsforespørsel................................................... 8 Front End ............................................................................................................. 12 4.1 Overordnet struktur ...................................................................................... 13 4.2 AngularJS-applikasjonen ............................................................................. 13 4.2.1 Controllers ............................................................................................ 14 4.2.2 Services ................................................................................................ 14 4.2.3 Polling ................................................................................................... 15 4.3 5 JSON ...................................................................................................... 6 3.3 3.4.1 4 REST ...................................................................................................... 6 Views ........................................................................................................... 16 4.3.1 Valgmuligheter ...................................................................................... 17 4.3.2 Bootstrap CSS ...................................................................................... 17 4.4 Validering ..................................................................................................... 18 4.5 Tilbakemeldinger ......................................................................................... 18 Vedlegg: Brukermanual for Web-API .................................................................... 19 S i d e 3 | 19 Vedlegg 2: Dokumentasjon av Web-API 1 BAKGRUNN Web-API inkluderes ikke i skopet til prosjektoppgaven, men ble utviklet som et sideprosjekt av følgende grunner. En måte å demonstrere bruket av klassebiblioteket ArenaKundereskontro. Gi gruppen et grensesnitt for å teste ut funksjonaliteten til modulen og enklere kunne populere databasen med data. Utvide størrelsen til prosjektoppgaven. Ta i bruk ny teknologi (AngularJS). Valget at det blev just et web API er at det gjør dataen tilgjengelig for flere plattformer. Det gjør det også mulig å lage et grensesnitt i HTML, hvilket vi alle har mye erfaring med. Dette er ikke noe oppdragsgiver har hatt som krav, men som vi håper de kan finne noen verdi i. S i d e 4 | 19 Vedlegg 2: Dokumentasjon av Web-API 2 KRAVSPESIFIKAS JON Etter å har tatt beslutningen å lage et ASP.NET Web-API som tester ut funksjonaliteten for klassebiblioteket ble det utarbeidet en kravspesifikasjon for denne. Kravene bygger i utgangspunktet på kravspesifikasjonen til ArenaKundereskontro, da hensikten med Web-API er å teste ut funksjonaliteten til klassebiblioteket. Kravspesifikasjonen er delt opp etter de forskjellige resursene som skal være tilgjengelige. Transaction Finne Transaction (med Postings) med gitt GUID. Finne alle Postings med en gitt ParentTransaction. Opprette en Transaction ut ifra en enkel web-form i form av en transaksjonsforespørsel. Laste opp XML fil med flere transaksjoner. Finne en Transaction i en gitt tidsperiode. Posting Finne alle Postings med en gitt ParentTransaction. Finne alle Postings med en gitt Reference. Finne alle Postings på en gitt Account. Account Hente ut en oversikt på alle kontoer. Laste opp CSV fil med kontoplan og lagre disse. Aktivere/inaktivere en gitt konto. Opprette ny konto ut ifra en enkel web-form. Aktivere/inaktivere om en konto skal være merket som overførbar til regnskapssystem. Client Registrere klient (bruker) med unikt navn. AccountingSystem Laste ned fil med alle Postings som skal overføres til regnskapsystemet og merke disse som overført. Laste ned fil med alle Postings som blitt overført på en gitt dato. S i d e 5 | 19 Vedlegg 2: Dokumentasjon av Web-API 3 BACK END 3.1 ASP.NET W EB API ASP.NET Web API er en del av ASP.NET MVC Framework1 og brukes for å lage REST Web API. Web API vil ha som oppgave å oversette HTTP-forespørsler og delegere disse til riktig controller, for i sin tur returnere en melding til klienten som foretatt forespørselen. 3.1.1 REST “Representational state transfer” er den ledende arkitekturen for å bygge et moderne API. Et REST API baserer seg på tjenere og klienter. Klientene gjør spørringer mot tjenerne, tjenerne prosesserer og behandler spørringene for så å returnere med korrekt svar tilbake til klienten. 3.2 CONTROLLERS Web-API er bygget opp slik at hver controller har ansvar for sin egen resurs, med unntak av FilesController som har ansvar for filhåndtering. Nærmere beskrivelse av tilgjengelige service kall finnes i Brukermanual for Web API. Alle controllers følger den samme URL-standarden; api/<resursens navn i flertall> Det er brukt Attribute Routing2 for å gi mer fleksibilitet over hvordan URI3, i dette fallet URLen, til resursen skal se ut. [RoutePrefix("api/transactions")] public class TransactionsController : ApiController [Route("{guid:guid}")] [HttpGet] public HttpResponseMessage Get(Guid guid) 3.2.1 JSON Resultatet av en forespørsel vil returneres til klienten som JSON4. Dette er enkelt å parse for våren web-klient og er dessuten lettleselig for et menneske, hvilket underletter utvikling og testing. 1 2 3 4 http://www.asp.net/mvc http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2 URI (Uniform Resource Identifier) er en kompakt streng av tegn som identifiserer en resurs. http://json.org/ S i d e 6 | 19 Vedlegg 2: Dokumentasjon av Web-API 3.3 IMPLEMENTASJON AV AR ENAKUNDERESKONTRO For å få bruke tjenestene til klassebiblioteket ArenaKundereskontro så er Web-API nødt til å registrere seg som klient for å identifisere seg ved skriving av transaksjoner. Web-API må også fortelle hvordan den skal behandle kvitteringer den mottar for alle forespørsler som gjøres. Dette gjøres med klassen ArenaKundereskontroClient. public class ArenaKundereskontroClient : IArenaKundereskontroClient, IMessageReceiver som er nødt til å brukes Denne klassen implementerer IArenaKundereskontroClient for å utføre tranksaksjonsforespørsler ved hjelp av biblioteket. public static int CLIENT_ID = 1; public int ClientId() { return CLIENT_ID; } public IMessageReceiver MessageReceiver() { return this; } Klassen implementerer også IMessageReceiver som gjør det mulig for den å motta kvitteringer med ReceiveTransactionReceipt(). Kvitteringene blir her lagret i listen Receipts på klienten, og en kopi av listen kan hentes ut med funksjonen GetReceipts(). private List<TransactionReceipt> Receipts; public ArenaKundereskontroClient() { Receipts = new List<TransactionReceipt>(); } public void ReceiveTransactionReceipt(TransactionReceipt receipt) { Receipts.Add(receipt); } public List<TransactionReceipt> GetReceipts() { return new List<TransactionReceipt>(Receipts); } S i d e 7 | 19 Vedlegg 2: Dokumentasjon av Web-API For å gjøre det enkelt å dele prosjektet i gruppen, initialiseres klienten i Web-API ved hver oppstart med følgende klasse. public class Setup { private ClientManager _clientManager = new ClientManager(); public void Init() { var client = _clientManager.FindClientByName(ArenaKundereskontroClient.CLIENT_NAME); if (client == null) client = _clientManager.AddNewClient(ArenaKundereskontroClient.CLIENT_NAME); ArenaKundereskontroClient.CLIENT_ID = client.Id; } } Det gjørs her ett oppslag mot klientens navn, CLIENT_NAME, og hvis denne ikke finnes fra før så vil klienten registreres. Deretter blir klient-iden satt i ArenaKundereskontroClient. 3.4 FUNKSJONALITET Web-API oppfyller alle kravene som er stilt i kravspesifikasjonen. Vi har valgt å kun beskrive den viktigeste/mest avanserte funksjonaliteten i rapporten. For en full oversikt på all funksjonalitet, og hvordan den skal brukes – se Brukermanual. 3.4.1 BEHANDLI NG AV TRANSA KSJONSFORESPØ RSEL Det viktigeste hendelsesforløpet i klassebiblioteket, og derav i Web-API, er å lagre mange transaksjoner i modulen på en gang. Dette skjer i form av at XML-data blir lest in av ArenaKundereskontro. Da det dreier seg om XML som er lagret i fil, er dette en jobb til FilesController. S i d e 8 | 19 Vedlegg 2: Dokumentasjon av Web-API For å lese ut filens innhold blir brukes den private metoden GetTransactionRequestStream() som returnerer en minnesstrøm av data. private Stream GetTransactionRequestStream() { if (HttpContext.Current.Request.Files.AllKeys.Any()) { try { // Get uploaded file var file = HttpContext.Current.Request.Files["transactionRequest"]; // Read file content to buffer var buffer = new byte[file.InputStream.Length]; file.InputStream.Read(buffer, 0, (int)file.InputStream.Length); file.InputStream.Dispose(); return new MemoryStream(buffer); } catch (Exception) { throw; } } else { throw new FileNotFoundException("Cannot find file."); } } Når en fil blir lastet opp til Web-API på POST api/files/transactionrequest vil metoden UploadTransactionRequest(bool) brukes til å prosessere tranksaksjonsforespørselen med hjelp av klassebiblioteket. Her er det mulig å bestemme om transaksjonen skal utføres sekvensielt eller asynkron med hjelp av bool-verdien (dette er for å kunne sammenligne de to forskjellige prosessene). Det vil først bli opprettet en klient (IArenaKundereskontroClient). Deretter brukes metoden ovenfor til å prøve å hente minnesstrømmen. TransactionRequestCreator vil siden opprettes med klienten som parameter, og deretter lage en transaksjonsforespørsel (TransactionRequest) fra strømmen. Hvis det er mulig å lage en forespørsel vil denne siden bli prosessert med RequestHandler. Når alle transaksjoner i forespørselen er ferdig behandlet vil controlleren returnere alle kvitteringer sammen med en kode om at filen er ferdigbehandlet. S i d e 9 | 19 Vedlegg 2: Dokumentasjon av Web-API Hvis noen feil skulle skje underveis vil en feilmelding returneres av controlleren med en Exception som beskriver feilet. [Route("transactionrequest")] [HttpPost] public async Task<HttpResponseMessage> UploadTransactionRequest(bool async = false) { try { client = new ArenaKundereskontroClient(); // Create stream and parse TransactionRequest TransactionRequest request; using (var stream = GetTransactionRequestStream()) { request = new TransactionRequestCreator(client).CreateTransactionRequest(stream); var handler = new RequestHandler(client); if (async) { await handler.CreateTransactionsAsync(request); } else { handler.CreateTransactions(request); } } return Request.CreateResponse(HttpStatusCode.Created, client.GetReceipts(), Configuration.Formatters.JsonFormatter); } catch (FileNotFoundException fne) { return Request.CreateErrorResponse(HttpStatusCode.BadRequest, fne); } catch (Exception e) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); } } S i d e 10 | 19 Vedlegg 2: Dokumentasjon av Web-API Det er også mulig å hente ut kvitteringer underveis med metoden GetReceipts(int) på urlen api/files/transactionreceipts. [Route("transactionreceipts")] [HttpGet] public HttpResponseMessage GetReceipts(int offset = 0) { if(client != null) return Request.CreateResponse(HttpStatusCode.OK, client.GetReceipts().Skip(offset).ToList(), Configuration.Formatters.JsonFormatter); return Request.CreateResponse(HttpStatusCode.NoContent, 0, Configuration.Formatters.JsonFormatter); } S i d e 11 | 19 Vedlegg 2: Dokumentasjon av Web-API 4 FRONT END For å konsumere Web API blev det utviklet en relativt simpel Single-page Application5 i HTML og AngularJS. Denne webapplikasjonen «lever» i samme prosjekt som Web API og kjøres på root (localhost:2200/index.html). Figur 1 – [Illustrasjon av Web API og web-applikasjon] Single-page Application – En web-applikasjon som befinner seg på en side som gir en bedre brukeropplevelse. 5 S i d e 12 | 19 Vedlegg 2: Dokumentasjon av Web-API 4.1 OVERORDNET STRUKTUR Web-applikasjonen er bygget opp på følgende måte. Her brukes mappene som opprettes av ASP.NET Web-API prosjektet. I root-mappen finner vi index.html som er «inngangen» til applikasjonen. Denne inneholder menyen og har til ansvar for å laste inn alt som trengs for å kjøre web-applikasjonen. Content inneholder stilene (stylesheetsen) til siden og her er det kun Bootstrap som brukes (det vil si at det ikke er noen egendefinert stil). Scripts inneholder alle JavaScript-filer. Her er alle benyttede biblioteker plassert. I undermappen app ligger AngularJSapplikasjonen. Views inneholder de forskjellige websidene (viewsen). Content bootstrap.css Scripts app AccountController.js app.js ClientController.js CreateController.js ExportController.js ImportController.js SearchController.js services.js angular.js angular-resource.js angular-route.js bootstrap.js jquery-2.1.4.js index.html Views account.html client.html create.html export.html import.html search.html 4.2 ANGULARJS -APPLIKASJONEN For å gjøre forespørsler mot et web API trengte vi JavaScript, og vi endte derfor opp med å bruke AngularJS til å utvikle våren web-applikasjonen. AngularJS bruker HTML til å definere et brukergrensesnittet til applikasjonen, hvilket gjør det enkelt å utvikle og få det til å se bra ut men også tilgjengelig for alle bruker med en webleser. I tillegg er Angular et MVC6-rammeverk, hvilket er en standard vi har erfaring med og egner seg godt til utvikling av applikasjoner med et brukergrensesnitt. 6 MVC (Model-View-Controler) - populært systemutviklingsmønster for implementasjon av brukergrensesnitt, som deler opp applikasjonen i tre komponenter; model, view og controller. S i d e 13 | 19 Vedlegg 2: Dokumentasjon av Web-API 4.2.1 CONTROLLERS En controller i Angular har ansvar for hver sin side. Den inneholder funksjoner og modeller som er direkte knyttet til viewet. I konfigurasjonen til applikasjonen bestemmer modulen ngRoute7 hvilken controller som hør til hvilket view ved bruk av $routeProvider. akApp.config(function ($routeProvider, $locationProvider) { var viewsPath = '/View/'; $routeProvider .when('/', { templateUrl: viewsPath + 'search.html', controller: 'SearchCtrl' }) 4.2.2 SERVICES Applikasjonen gjør kall mot Web-API med hjelp av ulike “services” som behandler en egen resurs. Dette gjør en service gjenbrukbar og gjør koden mer “DRY8”. En eller flere services blir siden “injected” i en controller og den kan deretter direkte kalle på servicens funksjoner. // services.js arenaServices.factory('FileUploader', ['$http', function ($http) { return { uploadTransactionRequest: function (xml) { return $http.post('api/files/transactionrequest', xml, { processData: false, headers: { 'Content-Type': undefined }, transformRequest: angular.identity, }); }, … } // ImportController.js function uploadTransactionRequest(data) { // data: binary read from XML file startUpload(); FileUploader.uploadTransactionRequest(data) .success(function (success) { stopPolling(); $scope.receipts = success; uploadFinished(); }) .error(function (error) { stopPolling(); console.debug(error); uploadFinished(); }); } 7 https://docs.angularjs.org/api/ngRoute DRY (Don’t Repeat Yourself) - prinsipp innenfor systemutvikling som sier at den samme koden ikke skal repeteres. http://en.wikipedia.org/wiki/Don%27t_repeat_yourself 8 S i d e 14 | 19 Vedlegg 2: Dokumentasjon av Web-API 4.2.2.1 NGRESOURCE ngResource9 er en modul til Angular som tilbyr interaksjon til RESTful services via $resource. Denne modul brukes i mange av våre services for å kommunisere med Web-API. // services.js angular.module('AK.services', ['ngResource']) .factory('Client', ['$resource', function ($resource) { return $resource('api/Clients/:clientId', {}, {}); }]); // ClientController.js angular.module('AK.controllers') .controller("ClientCtrl", function ($scope, $http, Client) { // inject Clientservice // Creates resource $scope.newClient = new Client({ Name: "Demo", Active: true}); $scope.registerDemoClient = function () { // Save resource (POST api/Clients) $scope.newClient.$save(); }; }); 4.2.3 POLLING Når en transaksjonsforespørsel blir sendt inn til Web-API vil web-applikasjonen ikke få svar før alle transaksjoner er prosessert. En transaksjonskvittering vil tas mot av klienten fortløpende så fort en transaksjon blitt ferdig behandlet. For å vise dette er web-applikasjonen nødt til å spørre om kvitteringer underveis. Dette gjøres med polling10, som innefatter at controlleren vil spørre Web API om alle nye kvitteringer en gang i sekundet og oppdatere viewet med nye kvitteringer. Brukeren vil med hjelp av viewet foreta en transaksjonsforespørsel gjennom å laste opp en XMLfil (rød linje i Figur 2). Controlleren i webapplikasjonen vil siden laste opp filen til Web-API som i sin tur leser ut dataen og foretar en innsetning av Figur 2 – [Polling Figur 2 av - [Beskrivelse] kvitteringer] 9 https://docs.angularjs.org/api/ngResource http://en.wikipedia.org/wiki/Polling_%28computer_science%29 10 S i d e 15 | 19 Vedlegg 2: Dokumentasjon av Web-API forespørselen med hjelp av klassebiblioteket ArenaKundereskontro. Controlleren vil samtidig starte å polle Web-API om kvitteringer en gang i sekundet (blå linje i Figur 2). Web-API vil sende med implementasjonen av sin klient og der motta kvitteringene fortløpende. Polling blir siden avbrudd etter at Controlleren har fått beskjed om at jobben er ferdigbehandlet. function pollReceipts() { if (!$scope.receiptPollingActive) return; $http.get("api/files/transactionreceipts?offset=" + $scope.receipts.length) .success(function (success) { angular.forEach(success, function (item) { $scope.receipts.push(item); }); }) .error(function (error) { console.log(error); }); } 4.3 VIEW S Presentasjonslaget til web-applikasjonen utgjøres av en rekke views. Disse er delt opp slik at de behandler de forskjellige funksjonene til ArenaKundereskontro, og vil ligge tilgjengelige i en meny som følger med på hver sidevisning. Figur 3 – [Viewet ”Import”] S i d e 16 | 19 Vedlegg 2: Dokumentasjon av Web-API 4.3.1 VALG MULIGHETER Valgene som presenteres for brukeren er følgende: Search Transaction – demonstrer sporbarheten i systemet. Register Transaction – oppretter en enkel transaksjon med flere posteringer. Gjør det mulig å knytte eksiterende posteringer til en transaksjon for å simulere hvordan «forelder-barn»-relasjonen fungerer. Account Management – gir en oversikt på alle kontoer, og muligheten til å endre aktiviteten på disse. Her får man også opprettet en enkel konto. Upload Files – mulighet til å laste opp filer til systemet. I Web-API er det to anledninger til å laste opp filer: o Laste opp en XML-fil med en transaksjonsforespørsel for å siden motta kvitteringer underveis og sjekke hvor lang tid prosesseringen av forespørselen tar. o Laste opp en CSV-fil med kontoer som skal brukes i klassebiblioteket. Er aktuelt første gangen klassebiblioteket tas i bruk for å populere databasen med kontoer. Register Client – registrere en klient i ArenaKundereskontro. Biblioteket er avhengig av at brukeren kan identifisere seg som en klient for at det skal være mulig å finne ut hvem som er ansvarlig for hvilken transaksjon. Export to Accounting – laste ned filer med posteringer. Vil kunne vise på funksjonaliteten et eksternt regnskapssystem vil bruke til å eksportere data fra klassebiblioteket. 4.3.2 BOOTSTRAP CSS For å gi siden et ryddig inntrykk og øke brukervennligheten er CSS-rammeverket Bootstrap brukt. Dette gjør det veldig enkelt å gi siden et bra inntrykk gjennom en rekke forhåndsdefinerte CSS-komponenter, noe som ellers er en tidskrevende jobb. S i d e 17 | 19 Vedlegg 2: Dokumentasjon av Web-API 4.4 VALIDERING Input-validering er utelatt derfor vi skal kunne teste opp mot feilsituasjoner som kan oppstå når data ikke er riktig. Feil i data vil bli validert av klassebiblioteket og det vil mottas en kvittering der feilen er beskrevet. Figur 4 – [Kvittering på front end] 4.5 TILBAKEMELDINGER Web-applikasjonen gir tilbakemelding i siden på valg som utføres og resultatet av disse. I tillegg er Chrome Developer Tools11 brukt under utvikling av web-applikasjonen, og vil gi mer detaljert beskrivelse av hva som har gått galt. Figur 5 – [Debugging i Chrome Developer Tools] 11 https://developer.chrome.com/devtools S i d e 18 | 19 Vedlegg 2: Dokumentasjon av Web-API 5 VEDLEGG: BRUKERMANUAL FOR WEB-API På neste side ligger brukermanualen for Web-API. S i d e 19 | 19 BRUKERMANUAL WEB-API INNHOLD Endpoints ..................................................................................................................... 3 Accounts .................................................................................................................. 3 GET /accounts ...................................................................................................... 3 POST /accounts .................................................................................................... 3 GET /accounts/:id ................................................................................................. 4 PATCH /accounts/:id/activity/:active ...................................................................... 4 PATCH /accounts/:id/transfer/:active ..................................................................... 5 Client ........................................................................................................................ 6 POST /clients ........................................................................................................ 6 Files ......................................................................................................................... 6 POST /files/transactionrequest?async .................................................................. 6 POST /files/accounts ............................................................................................ 7 GET /files/transactionreceipts ............................................................................... 8 GET /files/accountingrequest?date ....................................................................... 9 POST /files/accountingrequest .............................................................................. 9 Postings ................................................................................................................. 10 GET /postings ..................................................................................................... 10 GET /postings/transaction/:guid .......................................................................... 10 GET /postings/parent/:guid ................................................................................. 11 GET /postings/account/:id ................................................................................... 11 GET /postings/reference/:reference .................................................................... 12 Transactions ........................................................................................................... 13 Brukermanual Web-API GET /transactions/:guid....................................................................................... 13 GET /transactions/date/?start&end ..................................................................... 13 POST /transactions ............................................................................................. 14 Responses ................................................................................................................. 15 Account model........................................................................................................ 15 Client model ........................................................................................................... 15 Posting model......................................................................................................... 15 Transaction model .................................................................................................. 16 TransactionReceipt model ...................................................................................... 16 HTTP status-koder ................................................................................................. 17 S i d e 2 | 17 Brukermanual Web-API ENDPOINTS ACCOUNTS GET /accounts Beskrivelse Hente ut alle kontoer. Parameter Navn Lokasjon Verdi Beskrivelse active query boolean Aktive/inaktive kontoer. Response Kode Beskrivelse 200 En array av Account. POST /accounts Beskrivelse Registrer en ny konto. Parameter Navn Lokasjon Verdi Beskrivelse AccountNo body string (required) Kontonummer. Name body String (required) Navn på konton TransferToAc countingSyst em body boolean (required) Hvis en konto skal være overførbar till regnskapssystem. Response Kode Beskrivelse 201 Retunerer den opprettet konton. 500 Klarer ikke å opprette konton. S i d e 3 | 17 Brukermanual Web-API GET /accounts/:id Beskrivelse Hente ut account med gitt account number. Parameter Navn Lokasjon Verdi Beskrivelse id url integer (required) Kontonummer. Response Kode Beskrivelse 200 En account med gitt kontonummer. PATCH /accounts/:id/activity/:active Beskrivelse Endrer aktiviteten til en konto. Dvs. om den skal være i bruk eller ikke. Parameter Navn Lokasjon Verdi Beskrivelse id url integer (required) Kontonummer. active url boolean (required) Aktiviteten til en konto. Response Kode Beskrivelse 200 Konton har blitt oppdatert. 500 Kan ikke oppdatere aktiviteten til konton. S i d e 4 | 17 Brukermanual Web-API PATCH /accounts/:id/transfer/:active Beskrivelse Endrer om en konto skal være aktiv for overføring av posteringer. Parameter Navn Lokasjon Verdi Beskrivelse id url integer (required) Kontonummer. active url boolean (required) Overføringsaktiviteten til en konto. Response Kode Beskrivelse 200 Konton har blitt oppdatert. 500 Kan ikke oppdatere overføringsaktiviteten til konton. S i d e 5 | 17 Brukermanual Web-API CLIENT POST /clients Beskrivelse Registrer en ny klient. Parameter Navn Lokasjon Verdi Beskrivelse Name body string (required) Navn på klienten Active body boolean Om klienten skal være aktiv. Default: true Response Kode Beskrivelse 201 Retunerer en Client. 500 Klarer ikke å opprette klienten. FILES POST /files/transactionrequest?async Beskrivelse Brukes til å laste opp en XML-fil som utgjør en TransactionRequest med en eller flere transaksjoner som skal skrives i sentralt. Parameter Navn Lokasjon Verdi Beskrivelse async query boolean Bestemmer hvis forespørseln skal utføres synkront eller asynkront. Default: false transactionRequest upload multipart/formdata (required) XML-fil som utgjør en transaksjonsforespørsel. Response Kode Beskrivelse 201 Array bestående av alle TransactionReceipt for gitt forespørsel. 400 Finner ikke fil. 500 Exception av feil som oppstått underveis. S i d e 6 | 17 Brukermanual Web-API POST /files/accounts Beskrivelse Brukes til å laste opp en CSV-fil med en liste av kontoer. Mal: Kontonr,”Kontonavn”,Active,TransferToAccountingSystem Eksempel: 1000,”Trondheim Konverteringsfeil”,True,True NB! Første rad i filen vil ignoreres da denne tolkes som header. Parameter Navn Lokasjon Verdi Beskrivelse accountsFile body multipart/formdata (required) CSV-fil som består av en liste av kontoer formatert som beskrevet i beskrivelsen. Response Kode Beskrivelse 201 Antallet kontoer som blev opprettet. 400 Finner ikke fil. 500 Exception av feil som oppstått underveis. S i d e 7 | 17 Brukermanual Web-API GET /files/transactionreceipts Beskrivelse Hente ut kvitteringer knyttet til den aktive forespørseln. Brukes for å polle kvitteringer under veis i et gitt tidsintervall. Parameter Navn Lokasjon Verdi Beskrivelse offset query integer Hvor mange kvitteringer som skal skippes. Default: 0 Response Kode Beskrivelse 200 En array av kvitteringer. 204 Retunerer null, da det ikke eksisterer en aktiv forespørsel. S i d e 8 | 17 Brukermanual Web-API GET /files/accountingrequest?date Beskrivelse Laster ned en accounting-forespørsel i form av en xml-fil som innholder alle postinger som er overført på en gitt dato. Parameter Navn Lokasjon Verdi Beskrivelse date query DateTime (required) Dato da posteringene er overført. Response Kode Beskrivelse 200 En array av kvitteringer. 404 Melding om at det ikke finnes noen overførte posteringer på gitt dato. POST /files/accountingrequest Beskrivelse Laster ned en accounting-forespørsel i form av en xml-fil som innholder alle postinger som tidligere ikke blitt overført og som er postert på en “overførbar” konto. Response Kode Beskrivelse 200 export_for_accounting.xml 404 Melding om at det ikke finnes noen posteringer at overføre. 500 Melding om hva for feil som oppstått underveis. S i d e 9 | 17 Brukermanual Web-API POSTINGS GET /postings Beskrivelse Hente ut alle posteringer. Response Kode Beskrivelse 200 Retunerer en liste med Posting. GET /postings/transaction/:guid Beskrivelse Hente ut alle posteringer til en gitt transaksjon. Parameter Navn Lokasjon Verdi Beskrivelse guid url Guid (required) Id til transaksjonen. Response Kode Beskrivelse 200 Retunerer en liste med Posting. S i d e 10 | 17 Brukermanual Web-API GET /postings/parent/:guid Beskrivelse Hente ut alle posteringer til en gitt forelder (transaksjon). Parameter Navn Lokasjon Verdi Beskrivelse guid url Guid (required) Id til forelder (transaksjon). Response Kode Beskrivelse 200 Retunerer en liste med Posting. GET /postings/account/:id Beskrivelse Hente ut alle posteringer på en gitt konto. Parameter Navn Lokasjon Verdi Beskrivelse id url integer (required) Id til konton (kontonummer). Response Kode Beskrivelse 200 Retunerer en liste med Posting. S i d e 11 | 17 Brukermanual Web-API GET /postings/reference/:reference Beskrivelse Hente ut alle posteringer med en gitt referanse. Parameter Navn Lokasjon Verdi Beskrivelse reference url string (required) Referensen til posteringen. Response Kode Beskrivelse 200 Retunerer en liste med Posting. S i d e 12 | 17 Brukermanual Web-API TRANSACTIONS GET /transactions/:guid Beskrivelse Hente ut en gitt transaksjon (med alle posteringer inkludert). Parameter Navn Lokasjon Verdi Beskrivelse guid url Guid (required) Id til transaksjonen. Response Kode Beskrivelse 200 Retunerer en liste med Transaction. GET /transactions/date/?start&end Beskrivelse Hente ut alle transaksjoner (med alle posteringer inkludert) i en gitt tidsperiode. Parameter Navn Lokasjon Verdi Beskrivelse start query DateTime Start dato. Default: 0001-01-01 end query DateTime Start dato. Default: Dagens dato Response Kode Beskrivelse 200 Retunerer en liste med Transaction. S i d e 13 | 17 Brukermanual Web-API POST /transactions Beskrivelse Utfører en transaksjonsforespørsel med gitt transaksjonsdata. Parameter Navn Lokasjon Verdi Beskrivelse TransactionDate body DateTime (required) Dato når transaksjon er lagd. Amount body double (required) Beløpet på transaksjonen. FinancialYear body integer (required) Finansår. (4 siffer) FinancialPeriod body integer (required) Finansperiode. (1-12) Postings body PostingData (array) Liste med posteringene som tilhører en transaksjonen. Formatet er beskrevet i neste tabell. PostingData Navn Lokasjon Verdi Beskrivelse AccountNo body integer (required) Kontonummer. Amount body double (required) Beløpet på posteringen. ParentTransaction body Guid Id til ursprunglig transaksjonsforelder. Reference body string Referanse til transaksjonsforelder. Response Kode Beskrivelse 200 Retunerer en TransactionReceipt med utfallet av registreringen. 500 Kan ikke opprette transaksjonen. S i d e 14 | 17 Brukermanual Web-API RESPONSES ACCOUNT MODEL Beskrivelse En konto i modulen. Eksempel Type application/json { "AccountNo" : 1000, "Active" : true, "Name" : "Trondheim Konverteringsfeil", "TransferToAccountingSystem" : true } CLIENT MODEL Beskrivelse En klient i modulen. Eksempel Type application/json { "Id" : 1, "Name" : "Test Client", "Active" : true, "Transactions" : null } POSTING MODEL Beskrivelse En postering i modulen. Eksempel Type application/json { "TransactionId" : "050fea39-b054-4d6f-bcd1-001b6f835362", "AccountNo" : 2802, "ParentTransactionId" : "050fea39-b054-4d6f-bcd1-001b6f835362", "Amount" : -146.0, "TransferedToAccountingSystem" : null, "Transaction" : null, "ParentTransaction" : null, "Account" : null, "Reference" : null } S i d e 15 | 17 Brukermanual Web-API TRANS ACTION MODEL Beskrivelse En transaksjon i modulen. Eksempel Type application/json { "Id" : "050fea39-b054-4d6f-bcd1-001b6f835362", "Created" : "2015-05-13T12:54:15.32", "TransactionDate" : "2015-05-11T10:37:05.807", "Amount" : 146.0, "FinancialYear" : 2015, "FinancialPeriod" : 1, "ClientId" : 2, "Postings" : [], "Client" : null } “Postings” vil innholde en liste med Posting. TRANS ACTIONRECEIPT MODEL Beskrivelse En kvittering som beskriver utfallet om en transaksjon har blitt utført. Eksempel Type application/json { "RequestChecksum" : "0A-2C-C4-4B-D5-B0-A2-2B-6B-42-3E-B4-FE-44-72-61", "TransactionId" : 2, "Success" : "c62e8646-1715-487c-ad01-a35c773fb9b6", "ErrorMessage" : "Transaction handled before" } S i d e 16 | 17 Brukermanual Web-API HTTP STATUS-KODER Kode Beskrivelse 200 – OK Forespørselen var av gyldig format og ble utført uten feil. 201 – Created Når en ny ressurs vellykket har blitt opprettet. 204 – No Content Forespørselen var gyldig, men resultatet er tomt. 400 – Bad Request Formatet på forespørselen var ugyldig, det vil si en brukerfeil. 404 – Not Found Resursen som er forespurt eksisterer ikke. 500 - Internal Server Error Generell feil om at noe har gått galt i systemet under utførselen av forespørselen. S i d e 17 | 17 Milepælsplan.Gruppe.25.>.Arena.Kundereskonto,.2015 jan Aktivitet Deadline Avhengig.av 1.1,Første,innlevering,=,Forprosjektrapport,&,Arbeidsplan 23.01.2015 = 1.2,Utarbeide,kravspesifikasjon 30.01.2015 = 1.3,Risikoanalyse,&,Milepælsplan 23.01.2015 = 1.4,Klassediagram,og,databasedesign,etc. 30.01.2015 = 1.5,Føre,prosjektdagbok Fortløpende + 2.1,Godkjenning,av,design/diagrammer 02.02.2015 1.2,,1.4 2.2,Kodestart 04.02.2015 2.1 2.3,Implementasjon,av,domene,(modeller/db) 13.02.2015 2.1 2.4,Implementasjon,av,transaksjonsmodul 20.03.2015 2.1 2.5,Implementasjon,av,API,(inn/ut) 20.03.2015 2.1 2.6/Implementasjon:/Frittstående/moduler/mot/API 16.04.2015 2.5 2.7,Beta,#1 27.03.2015 2.1 2.8,Beta,#2 23.04.2015 3.1 2.9,Finpussing/forbedring 09.05.2015 3.3 2.10,Sluttprodukt,=,final 10.05.2015 2.9 3.1,Kundekontroll/Brukertesting,#1 01.04.2015 2.7 3.2,Testemodul,for,internt,bruk,(GUI) 21.04.2015 2.1 3.3,Kundekontroll/Brukertesting,#2 24.04.2015 2.8 3.4,Testing,=,fortløpende Fortløpende + 1.,Dokumenter 2.,Programmering 3.,Testing 4.,Sluttrapport 4.1,Sluttrapport,=,mal/utkast 10.04.2015 = 4.2,Produktdokumentasjon 15.05.2015 3.1 4.3,Brukermanual,(FAQ) 15.05.2015 3.1 4.4,Testdokumentasjon 15.05.2015 3.4 4.5,Prosessdokumentasjon Fortløpende + 4.6,Sluttrapport,=,sammeslåing 22.05.2015 4.1=4.5 4.7,Innlevering,Sluttrapport,=,final 26.05.2015 4.6 4.8/Presentasjon 05.06.2015 2.10,/4.7 Notat Uke.14:.Påske,02.04.15,=,06.04.15 2 3 feb 4 5 6 7 mars 8 9 10 11 12 april 13 14 15 16 17 mai 18 19 20 21 22 Vedlegg 4: Ordliste ORDLISTE A Asynkron – Muliggjør andre prosesser å kjøre samtidig, parallellitet. Axapta - Finansiell regnskap programvare laget av Microsoft. B Balanse - I denne rapporten vil begrepet primært omfatte balanse i forbindelse med transaksjoner, det betyr at debetsiden er like stor som kreditsiden i en transaksjon. Bokføring - Betyr å registrere verdibevegelser eller transaksjoner, og må oppfylle spesielle bokføringsregler (ref. “Bokføringsloven”). C Checksum - er en kort kode som brukes til å sjekke integriteten av data, eller den matematiske funksjonen av dataene, algoritmen, som genererer koden, ofte kalt hash-funksjon. D Debet - Begrep innenfor regnskapsføring som betyr å postere på venstresiden av en konto, dvs. “pluss” siden. G Guid – En global unik identifikator der det totale antallet unike nøkler er 2128. Sannsynligheten for at det samme tallet genereres er svært lav. H HiOA – Høyskolen i Oslo og Akershus HTTP statuskode - Et nummer som blir returnert med en HTTP-spørring for å beskrive utfallet. HTTP-POST - En metode på HTTP-protokollen med hensikt å levere data til mottaker. HTTP-GET - En metode på HTTP-protokollen med hensikt å hente data fra mottaker. Ordliste Vedlegg 4: Ordliste K Klassebibliotek - kjørbar kode (programvarepakke), som kan importeres og benyttes i andre system. Klient - Et system som implementerer klassebiblioteket. Kredit - Begrep innenfor regnskapsføring som betyr å postere på høyresiden av en konto, dvs. “minus” siden. K90 – Kreidnors inkassosystem M Modul - En mindre selvstendig del, som kan implementeres i et større system. P Postering - Enhver føring av bilag man gjør i et regnskap, i denne sammenheng en mindre del av en transaksjon. R Reskontro - er en oppsplitting av en hovedbokskonto i regnskapssystemet i flere underkontoer. S Scrum – Smidig utviklingsmetodikk. T Transaksjon - En overførsel i økonomisk sammenheng fra en part til en annen, for eksempel når en vare byttes mot penger ved kjøp og salg. T-konto – Tradisjonell måte å føre regnskap på, med kontonavn og kontonummer over streken. Debet og Kredit på hver side. Side 2|3 Vedlegg 4: Ordliste X XML – Extensible Markup Language. Et universelt og utvidbart markeringsspråk. XML brukes til deling av strukturert data. Side 3|3
© Copyright 2024