Mistä käsityö oikeasti syntyy
Tyypillinen kuukausiraportti syntyy näin: joku kirjautuu taloushallinnon järjestelmään, ottaa pääkirjan ulos, avaa viime kuun taulukon, liittää uudet luvut ja tarkistaa että summat täsmäävät. Sen jälkeen luvut jaotellaan raporttiriveille, budjetti liitetään viereen ja kokonaisuus lähetetään eteenpäin PDF:nä.
Kun tätä pyydetään automatisoimaan, huomio menee lähes aina väärään kohtaan. Vienti järjestelmästä ei ole se työläs osa — se vie minuutteja. Aika kuluu kolmeen muuhun asiaan: tilien jaotteluun raporttiriveille, siihen että edellisen kuukauden luvut ovat muuttuneet takautuvasti, ja siihen että joku joutuu selittämään miksi ne muuttuivat.
Tämä on syy, miksi pelkkä rajapintaintegraatio ei ratkaise ongelmaa. Se poistaa nopeimman vaiheen ja jättää hitaat. Automatisointi kannattaa suunnitella niin päin, että se ratkaisee jaottelun ja kausien muuttumisen — datan hakeminen on siitä pienin osa.
Automatisoi vasta kun raportista on sovittu
Sama sääntö kuin kaikessa raportoinnissa: käsin tehty raportti, josta ei ole sovittu, muuttuu automatisoituna raportiksi josta ei ole sovittu. Ero on vain se, että nyt se on väärässä muodossa nopeammin ja useammin.
Kirjatkaa ennen toteutusta auki mitä raportilta kysytään. Talousraportoinnissa kysymykset ovat harvinaisen vakioita, mikä tekee tästä nopean: mikä on kauden tulos ja miten se suhteutuu budjettiin, mistä ero syntyy, miten kassa kehittyy, ja mitkä ovat suurimmat yksittäiset erät.
- Kuka raporttia lukee — hallitus, toimitusjohtaja ja talouspäällikkö tarvitsevat eri tarkkuustason.
- Millä tarkkuudella: yhtiö, kustannuspaikka, projekti vai kaikki kolme.
- Mitä verrataan: budjettiin, edelliseen vuoteen, ennusteeseen — vai kaikkiin.
- Millä viiveellä raportti on riittävän hyvä. Kolmantena arkipäivänä valmis raportti on eri toteutus kuin reaaliaikainen.
- Kuka omistaa jokaisen rivin määritelmän. Käyttökate lasketaan eri tavoilla, ja se pitää päättää kerran.
Kolme tapaa saada luvut ulos, joista yksi kestää
Ensimmäinen on käsin otettu vienti, joka tallennetaan levylle tai Driveen. Se toimii, kunnes tekijä on lomalla tai tiedostomuoto muuttuu. Toinen on ajastettu tiedostosiirto, jossa järjestelmä pudottaa aineiston sovittuun paikkaan. Se on parempi, mutta tiedostot katoavat, tulevat kahteen kertaan ja hajoavat hiljaa kun sarake vaihtaa nimeä.
Kolmas on rajapinta. Se on ainoa, jossa haku on toistettavissa: sama pyyntö samoilla parametreilla tuottaa saman aineiston, ja epäonnistunut ajo voidaan ajaa uudelleen ilman että kukaan tekee mitään käsin. Sekä Fennoassa että Procountorissa on rajapinta, joten tähän ei ole hyvää syytä olla menemättä.
Tiedostosiirrolle on silti yksi kunnollinen käyttötapaus: aineisto, jota rajapinta ei anna lainkaan. Näitä on aina jokunen — vanha järjestelmä, pankin aineisto, käsin ylläpidetty jaotteluluettelo. Ne kannattaa käsitellä poikkeuksina eikä rakentaa niiden varaan koko putkea.
Fennoan rajapinta käytännössä
Fennoan rajapinta on suoraviivainen ja sen kutsut löytyvät accounting_api-polun alta. Raportoinnin kannalta olennaisin on pääkirjan haku, jolla saa vientirivit halutulta ajanjaksolta. Lisäksi saatavilla on muun muassa tilikartta, ALV-koodit, kauden lukitustiedot ja budjetit — budjetteja voi myös kirjoittaa rajapinnan kautta.
Tunnukset luodaan Fennoassa erillisenä API-käyttäjänä valikosta Käyttäjät → Luo uusi API-käyttäjä, ja luonti vaatii pääkäyttäjäoikeudet. Käyttäjätunnus ja avain näytetään vain kerran luonnin yhteydessä: jos ne katoavat, käyttäjä on poistettava ja luotava uudelleen. Ottakaa ne siis heti talteen salaisuuksien hallintaan, älkääkä sähköpostiin.
Käytännön este on harvoin tekninen. Fennoa-ympäristöä hallinnoi useimmiten tilitoimisto, ja API-käyttäjän luominen on heidän päätöksensä. Tämä keskustelu kannattaa käydä ennen kuin mitään aikatauluja luvataan — se on kokemuksemme mukaan projektin pisin yksittäinen odotus.
import os, requests
# Osoitteen ja autentikoinnin tarkka muoto: katso Fennoan tietopankki.
# Tunnukset ympäristömuuttujista — ei koskaan koodiin.
BASE = os.environ['FENNOA_BASE_URL']
AUTH = (os.environ['FENNOA_API_USER'], os.environ['FENNOA_API_KEY'])
def paakirja(alku, loppu):
r = requests.get(f'{BASE}/accounting_api/get/ledger',
params={'start_date': alku, 'end_date': loppu},
auth=AUTH, timeout=60)
r.raise_for_status()
return r.json()
# Tämä on se kutsu, joka kannattaa hakea ennen kaikkea muuta:
# se kertoo mihin asti kirjanpito on lukittu. Lukitun kauden luvut
# eivät enää muutu — avoimen kauden luvut muuttuvat vielä.
def lukitustilanne():
r = requests.get(f'{BASE}/accounting_api/get/locking_periods',
auth=AUTH, timeout=30)
r.raise_for_status()
return r.json()Procountorin rajapinta käytännössä
Procountorin rajapinta on REST-muotoinen ja käyttää JSONia, ja autentikointi tehdään OAuth 2.0:lla. Tarjolla on kaksi kulkua: client credentials -kulku konetta varten sekä authorization code -kulku käyttäjän puolesta toimimiseen. Automaattiseen raportointiin oikea valinta on client credentials, ja se on myös se, jota Procountor itse suosittelee. Saatu tunniste ei ole sidottu tiettyyn rajapintaversioon.
Raportoinnin kannalta keskeisiä ovat tositteet eli ledger receipts. Yksittäisiä tositteita voi hakea tunnuksella, ja tiheästi käytetyille resursseille on erikseen eräpäätepisteet, joilla saa haettua jopa 200 resurssia yhdellä kutsulla. Sivutus toimii kahdella tavalla: joko kertomalla viimeksi saadun tunnisteen previousId-parametrilla tai antamalla sivukoko ja sivunumero. Oletussivukoko on tyypillisesti 50.
Kutsutahdille on rajat: tuotannossa enintään 60 pyyntöä sekunnissa asiakasta kohden, julkisella testipalvelimella 90 pyyntöä minuutissa. Nämä ovat käytännössä väljät, kunhan haku ei ole rakennettu tekemään yksi kutsu per tosite — siihen eräpäätepisteet ovat olemassa.
import os, requests
# Tarkat osoitteet ja parametrit: dev.procountor.com.
TOKEN_URL = os.environ['PROCOUNTOR_TOKEN_URL']
API = os.environ['PROCOUNTOR_API_URL']
def token():
r = requests.post(TOKEN_URL, timeout=30, data={
'grant_type': 'client_credentials',
'client_id': os.environ['PROCOUNTOR_CLIENT_ID'],
'client_secret': os.environ['PROCOUNTOR_CLIENT_SECRET'],
})
r.raise_for_status()
return r.json()['access_token']
def tositteet(alku, loppu):
"""Sivuta previousId:llä, älä sivunumerolla: jos aineistoon
tulee uusi rivi kesken haun, sivunumerointi hyppää yli."""
headers = {'Authorization': f'Bearer {token()}'}
previous_id, kaikki = None, []
while True:
params = {'startDate': alku, 'endDate': loppu, 'size': 200}
if previous_id:
params['previousId'] = previous_id
r = requests.get(f'{API}/ledgerreceipts', headers=headers,
params=params, timeout=60)
r.raise_for_status()
era = r.json().get('results', [])
if not era:
return kaikki
kaikki += era
previous_id = era[-1]['id']Yksi asia kannattaa tietää etukäteen: Procountorilla on rajapinnan sertifiointiprosessi, joka on edellytys kumppaniohjelmaan pääsemiselle. Omaan käyttöön rakennettavassa raportointi-integraatiossa se ei yleensä ole este, mutta jos integraatiosta on tarkoitus tulla osa myytävää tuotetta, se kannattaa selvittää ennen kuin ensimmäistäkään riviä kirjoitetaan.
Toinen: kirjoittavat kutsut eivät ole ilmaisia. Rajapinnan kautta luodut tositteet lasketaan ympäristön kiintiöihin ja hinnoitellaan kuten käyttöliittymässä tehdyt. Raportointi on lukemista, joten tämä ei koske useimpia — mutta se koskee heti, jos putkeen lisätään kirjauksia takaisin päin.
Kumpikaan ei anna valmista tuloslaskelmaa
Tämä on se kohta, jossa projekti yleensä yllättää. Molemmat rajapinnat antavat vientirivejä: tositteen, päivämäärän, tilin, kustannuspaikan ja summan. Ne eivät anna tuloslaskelmaa siinä muodossa, jossa hallitus sen haluaa nähdä. Raportti syntyy siitä, että vientirivit jaotellaan raporttiriveille — ja se jaottelu on teidän, ei järjestelmän.
Tämä on hyvä uutinen kahdesta syystä. Ensinnäkin jaottelu on tarkalleen se asia, jonka takia raportti nyt tehdään käsin, joten sen automatisointi tuottaa suurimman hyödyn. Toiseksi kun jaottelu on kirjoitettu auki datamalliin, se on ensimmäistä kertaa olemassa yhdessä paikassa sen sijaan että se olisi yhden ihmisen taulukossa.
Rakenne on sama kuin missä tahansa datamallinnuksessa: raakavientirivit omaan kerrokseensa sellaisenaan, jaottelu ja liiketoimintalogiikka omaansa, ja raportointitaulu valmiiksi laskettuna päälle. Data Studio tai mikä tahansa raportointityökalu lukee vain viimeistä kerrosta.
Tilikartta on se, mikä ratkaisee raportin
Jaottelu tehdään mappaustaululla, joka kertoo mille raporttiriville kukin tili kuuluu. Se on pieni taulu ja houkuttelevan helppo tehdä raportointityökalun laskentakenttänä — mutta juuri siellä se katoaa. Mappaus kuuluu versionhallintaan, koska se on liiketoimintalogiikkaa: siitä näkee myöhemmin milloin jokin tili siirtyi riviltä toiselle ja kenen päätöksellä.
Suomalaisessa tilikartassa tilit on useimmiten numeroitu niin, että väli vastaa raporttiriviä. Se tekee mappauksesta lyhyen, mutta myös hauraan: yksi päällekkäinen väli tuottaa saman viennin kahdesti, ja yksi puuttuva väli pudottaa vientejä pois hiljaa.
-- Etumerkki käännetään kerran täällä, ei raportilla:
-- tuotot ovat pääkirjassa kredit-puolella eli negatiivisia.
select
k.raporttirivi,
k.jarjestys,
date_trunc(v.tositepvm, month) as kausi,
coalesce(v.kustannuspaikka, 'Kohdistamaton') as kustannuspaikka,
sum(v.summa * k.etumerkki) as summa
from `talous.stg_paakirja` v
join `talous.dim_tilikartta` k
on v.tili between k.tili_alku and k.tili_loppu
group by k.raporttirivi, k.jarjestys, kausi, kustannuspaikka
order by kausi, k.jarjestysTähän kuuluu kaksi testiä, ja ne ovat tärkeämpiä kuin itse kysely. Ensimmäinen: mapattujen rivien summa on täsmälleen sama kuin pääkirjan rivien summa — jos ei ole, jokin tili putosi pois. Toinen: yksikään tili ei osu kahteen väliin. Molemmat ovat yhden rivin tarkistuksia, ja molemmat kaatavat ajon ennen kuin väärä luku ehtii raportille.
Kohdistamaton-rivi kannattaa jättää raportille näkyviin sen sijaan että se suodatettaisiin pois. Se on ainoa tapa, jolla puuttuva kustannuspaikkatieto tulee kenenkään tietoon — ja sen näkyminen raportilla korjaa kirjausrutiinit nopeammin kuin mikään muistutus.
Kustannuspaikat ja muut dimensiot
Kustannuspaikka, projekti ja muut dimensiot ovat se, mikä tekee raportista kiinnostavan — ja ne ovat myös se osa, joka on täytetty epätasaisesti. Tyypillinen tilanne on, että myyntilaskuilla dimensio on aina, ostolaskuilla useimmiten ja muistiotositteilla ei koskaan.
Ratkaisu ei ole täydentää puuttuvia arvoja arvaamalla, eikä pudottaa rivejä pois. Kumpikin tuottaa raportin, joka on hiljaa väärässä. Näyttäkää puuttuvat omana rivinään, ja sopikaa erikseen kirjaussäännöt niille tositelajeille, joilla dimensio jää tyhjäksi.
Jos dimensioita on useita, kannattaa varautua siihen että niiden nimet muuttuvat. Kustannuspaikkoja yhdistetään ja jaetaan organisaatiomuutosten mukana, ja historian vertailukelpoisuus edellyttää että vanha ja uusi tunnetaan. Tämä hoidetaan dimensiotaululla, jossa on voimassaolopäivämäärät — ei sillä, että vanha nimi korvataan uudella.
Kausi ei ole valmis silloin kun se loppuu
Tämä on talousraportoinnin se ominaisuus, joka yllättää dataa tekevän ihmisen useimmin — ja se on syy useimpiin epäonnistuneisiin toteutuksiin. Verkkoanalytiikassa eilinen päivä on valmis tänään. Kirjanpidossa elokuu ei ole valmis elokuun lopussa, eikä välttämättä syyskuussakaan.
Vientejä kirjataan takautuvasti: ostolasku saapuu myöhässä, jaksotus siirtää kulun sille kaudelle jolle se kuuluu, virhe korjataan kolmen kuukauden päästä. Kaikki nämä muuttavat jo raportoitua lukua. Elokuun tulos on syyskuussa eri luku kuin marraskuussa, ja molemmat ovat oikein.
Väärä ratkaisu on laskea kausi kerran ja tallentaa se. Silloin raportti jää pysyvästi eri lukuun kuin kirjanpito, ja ero kasvaa joka kuukausi. Oikea ratkaisu on laskea historia uudelleen joka ajossa. Talousdatan määrä on pieni — muutamia kymmeniä tuhansia rivejä kuukaudessa — joten koko historian uudelleenlaskenta maksaa senttejä eikä sitä kannata optimoida pois.
Kun aineisto kasvaa niin suureksi että uudelleenlaskenta alkaa maksaa, apu tulee kauden lukituksesta. Fennoan lukitustiedot kertovat mihin asti kirjanpito on lukittu; lukittu kausi ei enää muutu, joten se voidaan laskea kerran ja jättää rauhaan. Avoimet kaudet lasketaan joka ajossa uudelleen.
- Näytä raportilla kauden tila: lukittu vai avoin. Se yksi merkintä poistaa suurimman osan kysymyksistä, joissa luku on muuttunut.
- Näytä myös milloin raportti on päivitetty. Ilman sitä katsoja ei tiedä katsooko hän eilistä vai viime viikkoa.
- Älä lupaa, että luku ei muutu. Lupaa sen sijaan, että luku vastaa kirjanpitoa sillä hetkellä kun raportti päivitettiin.
- Kun luku muuttuu paljon, syy on kirjanpidossa eikä putkessa. Tarkista se ensin — se säästää päivän virheenetsintää.
Budjetti, toteuma ja ennuste samassa taulussa
Toteuma tulee kirjanpidosta, mutta budjetti ei useimmiten tule sieltä. Se tehdään taulukkolaskennassa, ja se on täysin kelvollinen paikka sen tekemiseen — budjetointi on neuvottelua, ja siihen taulukko on oikea työkalu. Ongelma syntyy vasta, jos taulukko on myös se paikka, josta raportti lukee lukunsa.
Toimiva ratkaisu on ottaa budjetti Sheetsistä sovitussa muodossa datavarastoon ja yhdistää se toteumaan siellä. Fennoassa budjetit voi myös lukea ja kirjoittaa rajapinnan kautta, jolloin ne saa samasta lähteestä kuin toteuman — se on siistimpi ratkaisu silloin kun budjetti muutenkin ylläpidetään järjestelmässä.
Tärkein yksityiskohta on tarkkuustaso. Budjetti tehdään usein karkeammalla tasolla kuin toteuma kertyy: budjetti kustannuspaikalle ja kuukaudelle, toteuma tilille ja päivälle. Yhdistäminen tehdään sillä tasolla, jolla molemmat ovat olemassa — ei sillä, jolla toteuma sattuu olemaan tarkin. Muuten budjettiluku monistuu jokaiselle toteumariville ja summa on moninkertainen.
Ennuste on kolmas taso ja se muuttuu jatkuvasti. Säilyttäkää ennusteista versiot päivämäärällä sen sijaan että viimeisin korvaisi edellisen. Ilman versiointia ei voi jälkikäteen vastata kysymykseen "mitä me arvioimme kesäkuussa", joka on ennusteen ainoa mielekäs arviointitapa.
Mitä kuukausiraportilla kannattaa näyttää
Rakenne, joka vastaa niihin kysymyksiin joita oikeasti kysytään, ja joka mahtuu yhdelle sivulle. Porautuminen kuuluu omille sivuilleen.
- Ylärivi: liikevaihto, käyttökate, tulos ja kassa — kukin kauden luku ja ero budjettiin.
- Tuloslaskelma raporttiriveittäin: kausi, kumulatiivinen, budjetti, ero ja ero-%. Kumulatiivinen sarake on se, jota johto katsoo eniten.
- Ero budjettiin suurimmasta pienimpään. Tämä on raportin ainoa elementti, joka kertoo mistä pitää puhua kokouksessa.
- Kehitys kuukausittain 13 kuukauden ikkunassa, jotta edellinen vuosi on samassa kuvassa.
- Kustannuspaikkataulukko, jos organisaatiossa on useampi vastuualue.
- Merkintä kauden tilasta ja päivitysajankohdasta. Pieni teksti, iso vaikutus luottamukseen.
Mitä tähän ei kuulu: tilikohtainen erittely, tositelistat ja kaikki mikä vaatii selityksen. Ne ovat porautumisnäkymiä, ja ne kannattaa rakentaa — mutta omalle sivulleen, ei johdon näkymään.
Ajastus, virheet ja se että joku huomaa
Automatisoitu raportti on tuotantojärjestelmä, vaikka se ei siltä tunnu. Sillä on samat vaatimukset kuin millä tahansa ajolla: se ajetaan säännöllisesti, se epäonnistuu joskus, ja epäonnistumisen pitää tulla jonkun tietoon ennen kuin raporttia luetaan.
Talousdatan tapauksessa ajotahti on kevyt. Kerran vuorokaudessa aamuyöllä riittää lähes aina, koska kirjanpito ei muutu tunneittain. Tämä on hyvä uutinen: kevyt ajotahti tarkoittaa, ettei orkestrointiin tarvita raskasta ratkaisua ennen kuin lähteitä on useita.
Olennaisempaa kuin ajastus on se, että virheellinen ajo ei tuota puolivalmista raporttia. Kirjoita raportointitaulu vasta kun kaikki tarkistukset ovat menneet läpi — muuten ensimmäinen tieto ongelmasta tulee talouspäälliköltä, joka huomasi että liikevaihto puuttuu.
- Ajo kerran vuorokaudessa, ja mahdollisuus käynnistää se käsin kun kirjanpitäjä on tehnyt korjauksen.
- Tarkistukset ennen julkaisua: rivimäärä järkevällä välillä, mapattujen summa vastaa pääkirjaa, kausi ei ole tyhjä.
- Hälytys, joka menee ihmiselle eikä lokitiedostoon. Epäonnistunut ajo, josta kukaan ei tiedä, on sama kuin ei ajoa.
- Vanhan raportin säilyttäminen näkyvissä epäonnistuneen ajon jälkeen — vanha luku päivitysleimoineen on parempi kuin tyhjä sivu.
- Rajapintakutsut uudelleenyrityksellä. Molemmat järjestelmät ovat välillä poissa, eikä se saa olla syy siihen ettei raporttia ole.
Käyttöoikeudet: talousdata ei ole kuin muu data
Kuukausiraportti sisältää tietoa, jota kaikkien ei kuulu nähdä. Kustannuspaikkatason kuluista voi pienessä organisaatiossa päätellä yksittäisen ihmisen palkan, ja katetiedot ovat liikesalaisuutta. Tämä kannattaa ratkaista ennen ensimmäistä jakelua eikä sen jälkeen.
Data Studiossa on tähän liittyen ansa, joka kannattaa tuntea: datalähde voidaan jakaa joko omistajan tai katsojan oikeuksilla. Omistajan oikeuksilla jaettu raportti näyttää kaikille saman datan riippumatta siitä, mihin heillä olisi pääsy. Talousraportissa tämä ero ei ole tekninen yksityiskohta vaan koko jakelupäätös.
Käytännössä toimiva malli on rakentaa erilliset raportointitaulut eri yleisöille sen sijaan että yritettäisiin suodattaa yhtä taulua käyttäjän mukaan. Johdon taulu on karkeampi, vastuualueen taulu sisältää vain sen alueen rivit. Se on yksinkertaisempi ylläpitää ja huomattavasti vaikeampi vahingossa vuotaa.
Yleisimmät virheet lyhyesti
- Automatisoidaan haku mutta jätetään jaottelu käsin tehtäväksi. Se poistaa työstä nopeimman vaiheen ja jättää hitaimman.
- Kausi lasketaan kerran ja tallennetaan. Raportti ja kirjanpito eroavat toisistaan pysyvästi, ja ero kasvaa joka kuukausi.
- Tilikartan mappaus tehdään raportointityökalun laskentakenttänä. Se ei ole versionhallinnassa, sitä ei voi testata eikä kukaan löydä sitä kahden vuoden päästä.
- Mappauksen välit menevät päällekkäin, jolloin osa vienneistä lasketaan kahteen kertaan. Summa näyttää uskottavalta eikä kukaan huomaa.
- Puuttuvat kustannuspaikat suodatetaan pois raportilta. Luvut näyttävät siisteiltä ja ovat väärin.
- Budjetti liitetään toteumaan väärällä tarkkuustasolla, jolloin budjettiluku monistuu ja ero näyttää järjettömältä.
- Raportilla ei näy päivitysaikaa eikä kauden tilaa, joten jokainen muuttunut luku johtaa selvityspyyntöön.
- Ajo epäonnistuu hiljaa ja raportti jää vanhaksi. Ensimmäinen tieto asiasta tulee siltä, joka ehti tehdä päätöksen vanhalla luvulla.
- API-tunnukset ovat sähköpostissa tai koodissa. Fennoan avain näytetään vain kerran, joten sen katoaminen tarkoittaa uuden käyttäjän luomista tilitoimiston kautta.
- Projekti aikataulutetaan olettaen, että rajapintatunnukset saadaan samana päivänä kun niitä pyydetään.
Halutaanko teillä kuukausiraportti ilman käsityötä?
Rakennamme integraatiot taloushallinnon järjestelmiin, mallinnamme raporttirivit ja teemme raportin, joka päivittyy itsestään. Kartoituskeskustelu on maksuton.
Katso taloushallinnon BI-raportit