A bérszámfejtő elefánt: hogyan lesz egy relációs adatbázis a bérjelentés motorja?

A szélesebb közönséget megszólító technikai esszék bizonyára jól megfontolják az első néhány mondatot, amivel ki lehet puhatolni az olvasók érdeklődését. Ha a szóban forgó téma azonban nem kevésbé megmozgató, mint egy relációs adatbázismenedzsment rendszer funkcionális felszereltsége, ez az óvatosság minden írásjel után még inkább elkél. Mégis hogyan kerülhetne egy ilyen "mezei" technológia az érdeklődésünk központjába?

Két évvel ezelőtt kirajzolódott előttünk egy levegőért kapkodó probléma. Azt tapasztaltuk, hogy a vállalatok vezetői – függetlenül a szervezetük méretétől – nehezen, és sokszor csak késve jutnak hozzá olyan kulcsfontosságú adatokhoz, amelyek alapján megalapozott operatív döntéseket tudnak hozni. A hétről-hétre és hónapról-hónapra visszatérő kérdések úgy hangoztak: mennyi volt az elmúlt időszak bérköltsége? Ezért cserébe mennyi munkaidő állt rendelkezésre? Azt milyen hatásfokkal sikerült valódi értékké alakítani? A válasz – ha meg is érkezett – gyakran csak elavult és elszigetelt Excel-táblákból állt.

Ha létezik nagyon rossz cégstratégia, azt kétségkívül ilyen elavult és elszigetelt fájlkupacból a legkönnyebb létrehozni.

crosssec norma

Az információáramlás hatékonyabbá tételéhez szemléletmódot kell váltani. Az ezt felkarolni képes eszköznek ismernie kell nem csupán a cég felépítését, a munkatársak bérezési paramétereit, de összefüggéseiben kell kezelnie a már elkészült és a tervezett munkát is. Ezt a rengeteg szétszórt ismeretmorzsát összegyűjteni, egybegyúrni és könnyen emészthető módon tálalni már önmagában roppant nagy kihívás.

Sőt, a saját fejlesztésű költségelemző szoftverünk, a Norma megalkotásakor még egy merész ötlettel álltunk elő: nincs benne hónapzárás. Ez ellentétes szinte az összes, általunk látott munkaügyi adatokat felsorakoztató szoftverekkel, amelyekben a végfelhasználók megkötött keze csak a tárgyhavi rekordokig ér el, és hosszabb időszakokat érintő adatokat leginkább körülményes feloldásokat követően, gyakran csak rendszergazdai bűbájok kántálásával lehet megváltoztatni. Ezzel szemben a Norma – szigorú auditnaplót vezetve – a vállalat teljes életútjában engedi az előzmények módosítását, ha rögzítési hiba felfedése után a valósághoz igazodás azt megkívánja.

bérszámfejtő

Ezt a feladatot egy harcedzett eszközre bíztuk, így a PostgreSQL nevű adatbázismotort választottuk a Norma háttérországának. A méltán kedvelt technológia mellett nem csupán azért döntöttünk, mert betonbiztos mérnöki garanciákat ad a strukturált adatok tárolására és visszanyerésére, hanem mert néhány ügyes funkció révén a teljes feldolgozási fázist is el tudja látni.

A lezárt hónapok hiánya, valamint a felhasználók jogköreiken belüli, ám időben teljes felhatalmazása miatt ugyanis nincsenek olyan részeredmények, amelyekben tartósan meg lehet bízni. Ezen felül a Norma megengedő a tetszőleges törthavi jelentésekre gondolva is, ahol szintén kiemelkedő fontosságú, hogy aprólékos részösszegek a legfrissebb törzsinformációkból álljanak elő.

Tekintsünk egy egyszerű példát, melyben egy munkavállaló szeptember közepén 6 órás részmunkaidős beosztásból átkerül teljes általános (8 órás) munkarendbe. Ekkor a Normában a dolgozói aktájának egy részlete így fest majd:

munkarend változás

Rögtön lehívható egy vezetői bérösszesítő, ami pl. szeptember első felét öleli fel, és aminek az előállítása során többek között a következő segédtábla keletkezik:

vezetői bérösszesítő táblázat

A műszerfalon máris felvillan három nagyon fontos Postgres-kellék indikátora.

Az első azért felel nemes egyszerűséggel, hogy a dátumintervallum sorait, tehát a képen látható tábla első és második oszlopát összeállítsa. Ez noha első ránézésre nem tűnik egy komoly attrakciónak, mégis pironkodásra késztet több, igen népszerű adatbázismotort, amelyekben hasonló kiinduló dátumsorozatot nem lehet "csak úgy a légből" kapni.

A Postgres viszont ilyen kiegészítőkkel egybeépítve érkezik a gyártótól:

postgres dátumintervallum

Ezt követően egy-egy dátumról a magyar rendeletek kibogarászása után lehet eldönteni, hogy ünnepnapról, ledolgozandó napról, avagy – az általános munkarend szerinti – pihenőnapról van-e szó.

Ahogy látható a soron következő oszlopban, a dolgozó aktáit megfelelő kronológiai sorrendben olvasva minden munkanaphoz megállapítható az érvényes beosztás szerinti munkaidő. Számottevő jelentősége van, hogy miért érdemes ezt az értéket megismételni ott is, ahol nem tér el az előző nap cellájában lévőtől: bármelyik konkrét sor önhordozóan jellemzi egyetlen dolgozó egyetlen naptári napját, így az alatta és felette lévő sorok közül kiragadva is teljes értékűen alkalmazható további műveletekhez, ami elősegítheti az algoritmus teljesítményét, és – azt hiszem, ami még ennél is lényegesebb – a rendszer működésének érthetőségét.

A második jelzőfényt, ami a Postgres hasznos funkcióját fémjelzi, a tárgyhónap munkanapjai oszlop kapcsolta fel. A példában egyetlen számfejtési időszak, a szeptember hónap érintett, ennek a munkanapjainak száma szerepel az oszlopban. Az úgynevezett ablakfüggvények (window functions) ezt egy lomha karlendítéssel kitöltik, amelyek úgy tudnak összegezni, összeszámlálni és más módon aggregálni, hogy közben a kiindulási segédtábla sorait is megtartjuk.

Pontosan azért volt égető szükségünk erre a funkcióra, mert a fenti mintára önálló adatsorokat szerettünk volna készíteni, amelyeknek azonban ismerniük kell a viszonyítási számaikat a csoportjukon – vagy a szakszóval élve: az ablakon – belül.

Tipikusan a számfejtett időszakot, a tárgyévet, és ezen belül is a szerződéses jogviszony időtartamát alkalmazzuk az összegzés ablakaként.

Az időszak munkanapjai például kifejezhető az alábbi módon:

postgres tárgyhónap munkanapjai

Ekkor a partícionálás révén az egyes ablakok az egyes számfejtési időszakokra adnak betekintést (pl. hónap sorszáma alapján), míg a szűrő felel azért, hogy a számlálásba csak a feltételnek megfelelő nap kerülhessen.

Ez az érték leggyakrabban csak egy mellékelt segédtáblában, kint a távoli margón jöhetne létre; viszont egy összetett algoritmusban gombamód szaporodnak az ilyen numerikus bravúrok, amiben nem megengedhető az efféle ködös külső hivatkozás.

Végezetül a harmadik, és egyben talán a legfontosabb összetevő a közös táblakifejezések. Ha – csak egy ábrándos pillanatra is – azt feltételezzük, hogy az intervallumképzés és az ablakfüggvények rengeteg visszafojtott lélegzet kiváltói, a közös táblakifejezések még ekkor is biztosan minden feszült várakozást alulmúlnak.

Pedig egy egyszerű és hasznos trükkről van szó. A közös táblakifejezések segítségével megoldható, hogy a segédtáblák az előttük lévőkre tudjanak építkezni, és ezt az egymásutániságot az adatbázismotor felé egyetlen kérésben megfogalmazva tudjuk eljuttatni, nagyvonalakban ebben a szerkezetben:

postgres segédtábla

Kísértetiesen hasonlít ez ahhoz a módszerhez, melyben egy Excel-munkafüzet úgy van felépítve, hogy mindegyik munkalap csak fejlécet és adatsorokat tartalmaz, és a munkalapok csak a tőlük balra lévő szomszédaikból foghatnak forrásadatot, és formálhatják tovább. Az utolsó munkalapon végül leolvasható a lekérdezésünk eredménye.

A Crosssec szoftverfejlesztői csapata nagyon meggyőzőnek találta, hogy kompakt kódrészletekkel milyen bonyolult adatillesztéseket lehet elvégezni, és hogy az itt bemutatott funkciókkal is mennyivel egyszerűbbé válhat egy-egy képlet kidolgozása.

Természetesen a Normának az így előállt értékes adathalmazzal még bokros teendői vannak, mielőtt az igényes külalakú jelentésként a vezetők digitális asztalára kerülhet.

Beregszászi István - Crosssec Blog
Szerző:
Beregszászi István
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram