From 55003fead159d2cdd2fb31e945ba06a2cdc78bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Severi=20J=C3=A4=C3=A4skel=C3=A4inen?= Date: Thu, 13 Jul 2023 10:26:45 +0300 Subject: [PATCH] =?UTF-8?q?EH-1412=20&=20EH-1414:=20Ty=C3=B6paikkajakson?= =?UTF-8?q?=20keston=20laskentatavan=20muutokset=20(#240)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refaktoroitu kestonlaskentafunktiot luettavampaan muotoon ja lisätty dokumentaatiota. - Kestonlaskennassa huomiodaan kaikki viikonpäivät (aiemmin vain arkipäivät). - Osa-aikaisuus otetaan laskennassa huomioon. Osa-aikaisuustiedon ollessa pakollinen 1.7. alkaen, ei-validi osa-aikaisuustieto (jokin muu kuin kokonaisluku väliltä 1-100) tai tiedon puuttuminen tulkitaan osa-aikaisuudeksi nolla. --- .../amis/AMISherateEmailHandler.clj | 4 +- .../heratepalvelu/amis/AMISherateHandler.clj | 4 +- src/oph/heratepalvelu/external/arvo.clj | 2 +- src/oph/heratepalvelu/external/ehoks.clj | 2 +- src/oph/heratepalvelu/external/koski.clj | 2 +- src/oph/heratepalvelu/tep/jaksoHandler.clj | 2 +- src/oph/heratepalvelu/tep/niputusHandler.clj | 386 ++++--- .../tep/rahoitusLaskentaHandler.clj | 36 +- src/oph/heratepalvelu/util/date.clj | 12 + src/oph/heratepalvelu/util/dbChanger.clj | 9 +- .../amis/AMISherateHandler_test.clj | 2 +- .../oph/heratepalvelu/external/ehoks_test.clj | 8 +- .../oph/heratepalvelu/external/koski_test.clj | 5 +- .../tep/niputusHandler_i_test.clj | 31 +- .../heratepalvelu/tep/jaksoHandler_test.clj | 2 +- .../heratepalvelu/tep/niputusHandler_test.clj | 1009 +++++++++-------- test/oph/heratepalvelu/util/date_test.clj | 25 + 17 files changed, 843 insertions(+), 698 deletions(-) create mode 100644 src/oph/heratepalvelu/util/date.clj create mode 100644 test/oph/heratepalvelu/util/date_test.clj diff --git a/src/oph/heratepalvelu/amis/AMISherateEmailHandler.clj b/src/oph/heratepalvelu/amis/AMISherateEmailHandler.clj index 7b5e1953..379c743a 100644 --- a/src/oph/heratepalvelu/amis/AMISherateEmailHandler.clj +++ b/src/oph/heratepalvelu/amis/AMISherateEmailHandler.clj @@ -71,8 +71,8 @@ (if (:kyselylinkki herate) herate (let [oo-oid (:opiskeluoikeus-oid herate) - opiskeluoikeus (or (k/get-opiskeluoikeus-catch-404 oo-oid) - (k/get-opiskeluoikeus-catch-404 oo-oid))] + opiskeluoikeus (or (k/get-opiskeluoikeus-catch-404! oo-oid) + (k/get-opiskeluoikeus-catch-404! oo-oid))] (cond (not opiskeluoikeus) (do diff --git a/src/oph/heratepalvelu/amis/AMISherateHandler.clj b/src/oph/heratepalvelu/amis/AMISherateHandler.clj index e954a21f..2b8ed342 100644 --- a/src/oph/heratepalvelu/amis/AMISherateHandler.clj +++ b/src/oph/heratepalvelu/amis/AMISherateHandler.clj @@ -6,7 +6,7 @@ [oph.heratepalvelu.common :refer :all] [oph.heratepalvelu.external.koski :refer - [get-opiskeluoikeus-catch-404]] + [get-opiskeluoikeus-catch-404!]] [oph.heratepalvelu.log.caller-log :refer :all]) (:import (com.amazonaws.services.lambda.runtime.events SQSEvent$SQSMessage) (com.fasterxml.jackson.core JsonParseException) @@ -23,7 +23,7 @@ [^SQSEvent$SQSMessage msg] (try (let [herate (parse-string (.getBody msg) true) - opiskeluoikeus (get-opiskeluoikeus-catch-404 + opiskeluoikeus (get-opiskeluoikeus-catch-404! (:opiskeluoikeus-oid herate)) koulutustoimija (and opiskeluoikeus (get-koulutustoimija-oid opiskeluoikeus)) diff --git a/src/oph/heratepalvelu/external/arvo.clj b/src/oph/heratepalvelu/external/arvo.clj index 7b23de6a..709e6d93 100644 --- a/src/oph/heratepalvelu/external/arvo.clj +++ b/src/oph/heratepalvelu/external/arvo.clj @@ -91,7 +91,7 @@ (if (> (count oids) 1) (log/warn "Enemmän kuin yksi linkitetty opiskeluoikeus! HOKS-id:" ehoks-id) - (let [opiskeluoikeus (koski/get-opiskeluoikeus-catch-404 (first oids)) + (let [opiskeluoikeus (koski/get-opiskeluoikeus-catch-404! (first oids)) toteuttaja-oid (get-in opiskeluoikeus diff --git a/src/oph/heratepalvelu/external/ehoks.clj b/src/oph/heratepalvelu/external/ehoks.clj index 58be1fbb..dc67c37b 100644 --- a/src/oph/heratepalvelu/external/ehoks.clj +++ b/src/oph/heratepalvelu/external/ehoks.clj @@ -102,7 +102,7 @@ :end end :limit limit}})) -(defn get-tyoelamajaksot-active-between +(defn get-tyoelamajaksot-active-between! "Pyytää eHOKS-palvelusta työelämäjaksot, jotka ovat tai olivat voimassa tietyn aikavälin sisällä ja jotka kuuluvat tietylle oppijalle." [oppija start end] diff --git a/src/oph/heratepalvelu/external/koski.clj b/src/oph/heratepalvelu/external/koski.clj index 75cc9ab9..44d26894 100644 --- a/src/oph/heratepalvelu/external/koski.clj +++ b/src/oph/heratepalvelu/external/koski.clj @@ -21,7 +21,7 @@ [oid] (:body (koski-get (str "/opiskeluoikeus/" oid) {:as :json}))) -(defn get-opiskeluoikeus-catch-404 +(defn get-opiskeluoikeus-catch-404! "Hakee opiskeluoikeuden OID:n perusteella, ja palauttaa nil, jos ilmenee 404-virhe." [oid] diff --git a/src/oph/heratepalvelu/tep/jaksoHandler.clj b/src/oph/heratepalvelu/tep/jaksoHandler.clj index a5a95787..99cf2de7 100644 --- a/src/oph/heratepalvelu/tep/jaksoHandler.clj +++ b/src/oph/heratepalvelu/tep/jaksoHandler.clj @@ -280,7 +280,7 @@ (try (let [herate (parse-string (.getBody msg) true) oo (:opiskeluoikeus-oid herate) - opiskeluoikeus (koski/get-opiskeluoikeus-catch-404 oo)] + opiskeluoikeus (koski/get-opiskeluoikeus-catch-404! oo)] (if (nil? opiskeluoikeus) (log/warn "Ei löytynyt opiskeluoikeutta:" oo) (let [koulutustoimija (c/get-koulutustoimija-oid opiskeluoikeus) diff --git a/src/oph/heratepalvelu/tep/niputusHandler.clj b/src/oph/heratepalvelu/tep/niputusHandler.clj index 0534da9d..470556bb 100644 --- a/src/oph/heratepalvelu/tep/niputusHandler.clj +++ b/src/oph/heratepalvelu/tep/niputusHandler.clj @@ -3,17 +3,15 @@ (:require [clojure.tools.logging :as log] [environ.core :refer [env]] [oph.heratepalvelu.common :as c] + [oph.heratepalvelu.util.date :as d] [oph.heratepalvelu.db.dynamodb :as ddb] [oph.heratepalvelu.external.arvo :as arvo] [oph.heratepalvelu.external.ehoks :as ehoks] [oph.heratepalvelu.external.koski :as koski] [oph.heratepalvelu.log.caller-log :refer :all] [oph.heratepalvelu.tep.tepCommon :as tc]) - (:import (clojure.lang ExceptionInfo) - (com.amazonaws.services.lambda.runtime Context) - (java.lang Math) - (java.time DayOfWeek LocalDate) - (java.time.temporal ChronoUnit) + (:import (java.lang Math) + (java.time LocalDate) (software.amazon.awssdk.awscore.exception AwsServiceException) (software.amazon.awssdk.services.dynamodb.model ConditionalCheckFailedException))) @@ -24,6 +22,8 @@ [com.amazonaws.services.lambda.runtime.events.ScheduledEvent com.amazonaws.services.lambda.runtime.Context] void]]) +(defn round-vals [m] (reduce-kv #(assoc %1 %2 (Math/round ^Double %3)) {} m)) + (defn not-in-keskeytymisajanjakso? "Varmistaa, että annettu päivämäärä ei kuulu keskeytymisajanjaksoon." [^LocalDate date keskeytymisajanjaksot] @@ -32,31 +32,26 @@ (and (:loppu %) (.isAfter date (:loppu %)))) keskeytymisajanjaksot))) -; (defn not-before-or-after-opiskeluoikeus? -; "Varmistaa, että jakson alkamis- ja päättymispäivät eivät ole -; opiskeluoikeuden alku- ja loppuajankohdan ulkopuolella." -; [start end oo-tilat] -; (when-not (empty? oo-tilat) -; (let [oo-alku (:alku (first oo-tilat)) -; oo-loppu (:loppu (last oo-tilat))] -; (and (or (.isAfter start oo-alku) (.isEqual start oo-alku)) -; (or (not (:loppu (last oo-tilat))) -; (or (.isBefore end oo-loppu) (.isEqual end oo-loppu))))))) - -(defn is-weekday? - "Tarkistaa, onko annettu päivämäärä arkipäivä." - [^LocalDate date] - (not (or (= (.getDayOfWeek date) DayOfWeek/SATURDAY) - (= (.getDayOfWeek date) DayOfWeek/SUNDAY)))) - -(defn filtered-jakso-days - "Luo listan jakson arkipäivistä LocalDate:ina." +(defn osa-aikaisuuskerroin + "Hakee osa-aikaisuustiedon jaksosta ja varmistaa että se on validi (ts. + kokonaisluku väliltä 1 - 100). Palauttaa osa-aikaisuuskertoimen, joka + lasketaan jakamalla prosentuaalinen osa-aikaisuus 100 %:lla, + esim. 80 % / 100 % = 0.8. Jos osa-aikaisuustieto puuttuu tai on ei-validi, + palautetaan osa-aikaisuuskertoimena nolla." [jakso] - (filter is-weekday? - (let [start (LocalDate/parse (:jakso_alkupvm jakso)) - end (LocalDate/parse (:jakso_loppupvm jakso))] - (map #(.plusDays start %) - (range (inc (.between ChronoUnit/DAYS start end))))))) + (let [id (:hankkimistapa_id jakso) + osa-aikaisuus (:osa_aikaisuus jakso)] + (or (cond + (nil? osa-aikaisuus) + (log/error "Osa-aikaisuustieto puuttuu jakson" id "tiedoista. Jakson" + "kestoksi asetetaan nolla.") + (not (and (integer? osa-aikaisuus) + (pos? osa-aikaisuus) + (>= 100 osa-aikaisuus))) + (log/error "Jakson" id "osa-aikaisuus" (str "`" osa-aikaisuus "`") + "ei ole validi. Jakson kestoksi asetetaan nolla.") + :else (/ osa-aikaisuus 100.0)) + 0))) (defn add-loppu-to-jaksot "Lisää jokaiseen paitsi viimeiseen jaksoon kentän :loppu, joka on päivää @@ -69,178 +64,124 @@ (rest jaksot)) (last jaksot))) -(defn add-to-jaksot-by-day - "Lisää jaksoon viittaavan referenssin jokaiselle päivälle jaksot-by-day - -objektissa, jolloin jakso on voimassa eikä ole keskeytynyt. Objekti - jaksot-by-day on map LocalDate-päivämääristä sekvensseihin jaksoista, jotka - ovat voimassa ja keskeytymättömiä sinä päivänä." - [jaksot-by-day jakso opiskeluoikeus] - (let [oo-tilat (->> (:opiskeluoikeusjaksot (:tila opiskeluoikeus)) - (map c/alku-and-loppu-to-localdate) - (sort-by :alku) - (add-loppu-to-jaksot)) - kjaksot-parsed (map c/alku-and-loppu-to-localdate - (:keskeytymisajanjaksot jakso)) - kjaksot-oo (filter #(or (= "valiaikaisestikeskeytynyt" - (:koodiarvo (:tila %))) - (= "loma" (:koodiarvo (:tila %)))) - oo-tilat) - kjaksot (concat kjaksot-parsed kjaksot-oo)] - (reduce #(if (not-in-keskeytymisajanjakso? %2 kjaksot) - (assoc %1 %2 (cons jakso (get %1 %2))) - %1) - jaksot-by-day - (filtered-jakso-days jakso)))) +(defn get-opiskeluoikeusjaksot + [opiskeluoikeus] + (->> (:opiskeluoikeusjaksot (:tila opiskeluoikeus)) + (map c/alku-and-loppu-to-localdate) + (sort-by :alku) + add-loppu-to-jaksot)) -(defn add-to-jaksot-by-day-new - "Lisää jaksoon viittaavan referenssin jokaiselle päivälle jaksot-by-day - -objektissa, jolloin jakso on voimassa eikä ole keskeytynyt. Objekti - jaksot-by-day on map LocalDate-päivämääristä sekvensseihin jaksoista, jotka - ovat voimassa ja keskeytymättömiä sinä päivänä." - [jaksot-by-day jakso opiskeluoikeus] - (let [oo-tilat (->> (:opiskeluoikeusjaksot (:tila opiskeluoikeus)) - (map c/alku-and-loppu-to-localdate) - (sort-by :alku) - (add-loppu-to-jaksot)) - kjaksot-parsed (map c/alku-and-loppu-to-localdate - (:keskeytymisajanjaksot jakso)) - kjaksot-oo (filter #(= "valiaikaisestikeskeytynyt" - (:koodiarvo (:tila %))) - oo-tilat) - kjaksot (concat kjaksot-parsed kjaksot-oo)] - (reduce #(if (not-in-keskeytymisajanjakso? %2 kjaksot) - (assoc %1 %2 (cons jakso (get %1 %2))) - %1) - jaksot-by-day - (let [start (LocalDate/parse (:jakso_alkupvm jakso)) - end (LocalDate/parse (:jakso_loppupvm jakso))] - (map #(.plusDays start %) - (range (inc (.between ChronoUnit/DAYS start end)))))))) +(defn keskeytymisajanjaksot + [jakso opiskeluoikeus] + (let [keskeytynyt-tila? #{"valiaikaisestikeskeytynyt"} + kjaksot-in-jakso (map c/alku-and-loppu-to-localdate + (:keskeytymisajanjaksot jakso)) + kjaksot-in-opiskeluoikeus + (filter #(keskeytynyt-tila? (:koodiarvo (:tila %))) + (get-opiskeluoikeusjaksot opiskeluoikeus))] + (concat kjaksot-in-jakso kjaksot-in-opiskeluoikeus))) -(defn get-osa-aikaisuus - "Hakee osa-aikaisuutta jaksosta ja varmistaa, että se on sallittujen rajojen - sisällä." - [jakso] - (if (and (some? (:osa_aikaisuus jakso)) - (pos? (:osa_aikaisuus jakso)) - (> 100 (:osa_aikaisuus jakso))) - (:osa_aikaisuus jakso) - 100)) +(defn in-jakso? + "Tarkistaa sisältyykö päivämäärä `pvm` jaksoon `jakso`. Oletus on, että + sekä pvm että jakson avaimet :alku ja :loppu ovat tyyppiä `LocalDate`. + Palauttaa `true` jos päivämäärä sisältyy jaksoon, muuten `false`." + [^LocalDate pvm jakso] + (let [alku (:alku jakso) loppu (:loppu jakso)] + (and (or (.isAfter pvm alku) (.isEqual pvm alku)) + (or (nil? loppu) (.isBefore pvm loppu) (.isEqual pvm loppu))))) -(defn handle-one-day - "Jakaa yhden päivän aikaa silloin keskeytymättömien jaksojen välillä." - [jaksot] - (let [fraction (/ 1.0 (count jaksot))] - (into {} (map #(vector (:hankkimistapa_id %) - (/ (* fraction (get-osa-aikaisuus %)) 100)) - jaksot)))) +(defn jakso-active? + "Tarkistaa, onko `jakso` aktiivinen päivämääränä `pvm`. Ts. funktiossa + tarkistetaan, kuuluuko `pvm` jaksoon ja sisältyykö se mihinkään jakson tai + opiskeluoikeuden tiedoissa olevaan keskeytymisajanjaksoon." + [jakso opiskeluoikeus pvm] + (and (in-jakso? pvm jakso) + (some? opiskeluoikeus) + (not-any? #(in-jakso? pvm %) + (keskeytymisajanjaksot jakso opiskeluoikeus)))) -(defn handle-one-day-new - "Jakaa yhden päivän aikaa silloin keskeytymättömien jaksojen välillä." - [jaksot] - (let [fraction (/ 1.0 (count jaksot))] - (into {} (map #(assoc {} (:hankkimistapa_id %) - {:with-oa (/ (* fraction (get-osa-aikaisuus %)) 100) - :without-oa fraction}) ; ilman osa-aikaisuustietoa - jaksot)))) +(defn oppijan-jaksojen-yhden-paivan-kestot + "Laskee yhden oppijan aktiivisena olevien jaksojen kestot yhden päivän osalta, + eli suorittaa niin sanotun 'jyvityksen'. Tällä tarkoitetaan sitä, että yhden + päivän kesto jaetaan tasaisesti kaikille samanaikaisesti aktiivisena oleville + (ei keskeytyneille) jaksoille kyseisen päivän osalta. -(defn compute-kestot - "Laskee jaksojen kestot ja palauttaa mapin OHT ID:stä kestoihin. Olettaa, että - kaikki jaksot kuuluvat samalle oppilaalle." - [jaksot] - (let [first-start-date (first (sort (map :jakso_alkupvm jaksot))) - last-end-date (first (reverse (sort (map :jakso_loppupvm jaksot)))) - concurrent-jaksot (ehoks/get-tyoelamajaksot-active-between - (:oppija_oid (first jaksot)) - first-start-date - last-end-date) - ; FIXME: zipmap - oo-map (reduce #(assoc %1 %2 (koski/get-opiskeluoikeus-catch-404 %2)) - {} - (set (map :opiskeluoikeus_oid concurrent-jaksot))) - do-one #(add-to-jaksot-by-day %1 - %2 - (get oo-map (:opiskeluoikeus_oid %2)))] - ; FIXME: mapcat + merge-with - (reduce (fn [acc m] (reduce-kv #(assoc %1 %2 (+ %3 (get %1 %2 0.0))) acc m)) - {} - (map handle-one-day (vals (reduce do-one {} concurrent-jaksot)))))) + Funktio olettaa, että parametrina saadut `jaksot` ovat kaikki saman oppijan + jaksoja. `opiskeluoikeudet` hashmap (oid -> opiskeluoikeus) voi sisältää + muidenkin oppijoiden opiskeluoikeuksia, sillä kutakin jaksoa vastaava + opiskeluoikeus haetaan `opiskeluoikeudet` hashmapista käyttäen jakson + tiedoista löytyvää opiskeluoikeuden oid:ta. -(defn get-jaksojen-opiskeluoikeudet - "Funktiossa kokeillaan ensin hakea jaksojen opiskeluoikeuksia - `opiskeluoikeudet` mapista. Jos niitä ei löydy tästä, ne haetaan Koskesta." - [opiskeluoikeudet opiskeluoikeus-oidt] - (zipmap opiskeluoikeus-oidt - (map #(or (get opiskeluoikeudet %) - (koski/get-opiskeluoikeus-catch-404 %)) - opiskeluoikeus-oidt))) + Funktio palauttaa päivänä `pvm` aktiivisena olleiden jaksojen jyvittämällä + lasketut kestot hashmapissa, jossa avaimina jaksojen id:t + (osaamisenhankkimistapojen) ja arvoina lasketut kestot reaalilukuina. -(defn compute-kesto-old - "Laskee yksittäisen jakson keston." - [jakso concurrent-jaksot opiskeluoikeudet] - (let [do-one #(add-to-jaksot-by-day - %1 - %2 - (get opiskeluoikeudet (:opiskeluoikeus_oid %2)))] - (get (reduce - (fn [acc m] (reduce-kv #(assoc %1 %2 (+ %3 (get %1 %2 0.0))) acc m)) - {} - (map handle-one-day (vals (reduce do-one {} concurrent-jaksot)))) - (:hankkimistapa_id jakso)))) + Esimerkki: + `jaksot` listassa on 4 jaksoa id:illä 1, 2, 3 ja 4. Näistä 1, 2 ja 4 ovat + aktiivisia päivänä `pvm` ja 3 on keskeytynyt. Tällöin funktio palauttaa + {1 0.333... 2 0.333... 4 0.333...}. Keskeytyneen jakson nollakesto ei ole + siis mukana palautettavassa hashmapissa." + [jaksot opiskeluoikeudet pvm] + (let [active-jakso-ids ; Päivänä `pvm` aktiivisena olevien jaksojen id:t + (map :hankkimistapa_id + (filter #(jakso-active? % + (get opiskeluoikeudet + (:opiskeluoikeus_oid %)) + pvm) + jaksot)) + num-of-active-jaksos (count active-jakso-ids) + kesto (/ 1.0 num-of-active-jaksos)] ; Jyvitys + (zipmap active-jakso-ids (repeat kesto)))) -(defn compute-kesto-new - "Laskee yksittäisen jakson keston." - [jakso concurrent-jaksot opiskeluoikeudet] - (let [do-one #(add-to-jaksot-by-day-new - %1 %2 (get opiskeluoikeudet (:opiskeluoikeus_oid %2)))] - (get (reduce - (fn [acc m] - (reduce-kv #(assoc %1 %2 (merge-with + %3 (get %1 %2))) acc m)) - {} - (map handle-one-day-new (vals (reduce do-one {} concurrent-jaksot)))) - (:hankkimistapa_id jakso)))) +(defn harmonize-date-keys + "Harmonisoi jakson alku- ja loppupäivämääriä vastaavat avaimet, jotta + kestonlaskennassa voidaan hyödyntää mahdollisimman paljon samoja funktiota." + [jakso] + (cond-> jakso + (:jakso_alkupvm jakso) (assoc :alku (:jakso_alkupvm jakso)) + (:jakso_loppupvm jakso) (assoc :loppu (:jakso_loppupvm jakso)))) -(defn compute-kesto-old-and-new - "Laskee yksittäisen jakson keston, vanhalla ja uudella tavalla." - [jakso concurrent-jaksot opiskeluoikeudet] - (let [cc-jaksot-with-oo - (filter #(get opiskeluoikeudet (:opiskeluoikeus_oid %1)) - concurrent-jaksot)] - {:vanha (compute-kesto-old jakso cc-jaksot-with-oo opiskeluoikeudet) - :uusi (compute-kesto-new jakso cc-jaksot-with-oo opiskeluoikeudet)})) +(defn harmonize-alku-and-loppu-dates + "Harmonisoi :jakso_alkupvm ja :jakso_loppupvm avaimet avaimiksi + :alku ja :loppu myöhempää prosessointia varten. Muuttaa myös vastaavat + päivämäärät myös LocalDate-objekteiksi." + [jakso] + (c/alku-and-loppu-to-localdate (harmonize-date-keys jakso))) -(defn compute-kestot-new - "Laskee kestot kaikille jaksoille `jaksot` listassa." - [jaksot] - (loop [kestot {} - opiskeluoikeudet {} - jaksot jaksot] - (if-let [jakso (first jaksot)] - (let [concurrent-jaksot (ehoks/get-tyoelamajaksot-active-between - (:oppija_oid jakso) - (:jakso_alkupvm jakso) - (:jakso_loppupvm jakso)) - jaksojen-opiskeluoikeudet - (get-jaksojen-opiskeluoikeudet opiskeluoikeudet - (map :opiskeluoikeus_oid - concurrent-jaksot))] - (recur (assoc kestot - (:hankkimistapa_id jakso) - (compute-kesto-old-and-new - jakso concurrent-jaksot jaksojen-opiskeluoikeudet)) - (merge opiskeluoikeudet jaksojen-opiskeluoikeudet) - (rest jaksot))) - kestot))) +(defn oppijan-jaksojen-kestot + "Laskee kestot jaksoille `jaksot`. Funktio olettaa, että `jaksot` pitävät + sisällään ainoastaan yhden oppijan jaksoja. `opiskeluoikeudet` tulee olla + hashmap (oid -> opiskeluoikeus). Se voi sisältää muidenkin oppijoiden + opiskeluoikeuksia, sillä jaksoja `jaksot` vastaavat opiskeluoikeudet haetaan + `opiskeluoikeudet` hashmapista jakson tiedoista löytyvän opiskeluoikeus oid:n + perusteella. -(defn group-jaksot-and-compute-kestot - "Ryhmittää jaksot oppija_oid:n perusteella ja laskee niiden kestot." - [jaksot] - (->> (group-by :oppija_oid jaksot) - (vals) - (map (comp compute-kestot reverse)) - (apply merge))) + Funktio palauttaa yhden oppijan jaksojen kestot aikavälillä, missä aikavälin + alku on jaksojen `jaksot` alkupäivämääristä varhaisin ja loppu vastaavasi + päättymispäivistä myöhäisin. Palautuva arvo on hashmap, jossa avaimina + jaksojen id:t (osaamisenhankkimistapojen) ja arvoina kestot kokonaislukuina. + Yksittäisen jakson kesto voi olla nolla, jos kyseiselle jaksolle ei saada + opiskeluoikeutta Koskesta 404-virheen vuoksi, tai jos jakson + osa-aikaisuustieto puuttuu tai on virheellinen. Jakson kesto voi myös + pyöristyä nollaan, mikäli kokonaiskesto on jotain 0 ja 0.5 väliltä." + [oppijan-jaksot opiskeluoikeudet] + (when (not-empty oppijan-jaksot) + (let [jaksot (map harmonize-alku-and-loppu-dates oppijan-jaksot) + ids (map :hankkimistapa_id jaksot)] + (round-vals ; Pyöristetään kestot lähimpään kokonaislukuun. + (merge-with + * ; Kerrotaan kestot osa-aikaisuuskertoimilla + (reduce (partial merge-with +) ; Summataan yksittäisten päivien kestot + ; Alustetaan alla kaikki kestot nollaksi: + (zipmap ids (repeat 0)) + (map (partial oppijan-jaksojen-yhden-paivan-kestot + jaksot + opiskeluoikeudet) + (d/range (first (sort (map :alku jaksot))) + (last (sort (map :loppu jaksot)))))) + (zipmap ids (map osa-aikaisuuskerroin jaksot))))))) -(defn query-jaksot +(defn query-jaksot! "Hakee tietokannasta ne jaksot, jotka kuuluvat annettuun nippuun ja joiden viimeiset vastauspäivämäärät eivät ole menneisyydessä." [nippu] @@ -255,16 +196,71 @@ :expr-attr-vals {":pvm" [:s (str (c/local-date-now))]}} (:jaksotunnus-table env))) -(defn math-round "Wrapper Math/round:in ympäri" [^double x] (Math/round x)) +(defn get-concurrent-jaksot-from-ehoks! + "Hakee kaikki `jaksot` listassa olevien jaksojen kanssa päällekäin olevat + saman oppijan jaksot eHOKSista." + [jaksot] + (ehoks/get-tyoelamajaksot-active-between! + (:oppija_oid (first jaksot)) + (first (sort (map :jakso_alkupvm jaksot))) + (last (sort (map :jakso_loppupvm jaksot))))) + +(defn get-and-memoize-opiskeluoikeudet! + "Funktio hakee `jaksot` listan jaksojen opiskeluoikeuksia Koskesta. + Opiskeluoikeudet tallennetaan muistiin hakujen välillä, joten jos listassa on + jaksoja jotka jakavat saman opiskeluoikeuden, näiden opiskeluoikeudet + tarvitsee hakea Koskesta vain kerran. Näin vältetään turhia GET-pyyntöjä + Koskeen." + [jaksot] + (reduce + (fn [memoized-opiskeluoikeudet jakso] + (let [oht-id (:hankkimistapa_id jakso) + oo-oid (:opiskeluoikeus_oid jakso)] + (if (contains? memoized-opiskeluoikeudet oo-oid) + memoized-opiskeluoikeudet + (if-let [opiskeluoikeus (koski/get-opiskeluoikeus-catch-404! oo-oid)] + (conj memoized-opiskeluoikeudet [oo-oid opiskeluoikeus]) + (do (log/warn "Opiskeluoikeutta" (str "`" oo-oid "`") "ei saatu" + "Koskesta. Jakson" oht-id "kestoksi asetetaan nolla.") + memoized-opiskeluoikeudet))))) + {} + jaksot)) + +(defn jaksojen-kestot! + "Laskee kestot kaikille `jaksot` listan jaksoille. Lista jaksoista `jaksot` + voi pitää sisällään useamman oppijan työpaikkajaksoja: Kestonlaskenta tehdään + varsinaisesti aina saman oppijan jaksoille (kts. `oppijan-jaksojen-kestot`), + mutta tässä funktiossa `jaksot` ryhmitellään oppija oid:n mukaan ennen + `oppijan-jaksojen-kestot`-funktion tekemää kestojen laskemista. + + Palauttaa hashmapin, joka sisältää `jaksot` listan jaksoille lasketut kestot. + Hashmapin avaimina jaksojen id:t (osaamisenhankkimistapojen) ja arvoina kestot + kokonaislukuina." + [jaksot] + (->> (group-by :oppija_oid jaksot) ; Ryhmitellään jaksot oppijan perusteella + vals + ; Haetaan kunkin jakson tapauksessa päällekäiset jaksot eHOKSista + ; sekä viimeisin opiskeluoikeustieto Koskesta: + (map (fn [oppijan-jaksot] + (let [concurrent-jaksot (get-concurrent-jaksot-from-ehoks! + oppijan-jaksot) + opiskeluoikeudet (get-and-memoize-opiskeluoikeudet! + concurrent-jaksot)] + (oppijan-jaksojen-kestot concurrent-jaksot opiskeluoikeudet)))) + ; Yhdistetään eri oppijoiden jaksoille lasketut kestot yhdeksi + ; hashmapiksi: + (apply merge) + ; Palautetaan vain niiden jaksojen kestot, jotka ovat `jaksot` listassa: + (#(select-keys % (map :hankkimistapa_id jaksot))))) -(defn retrieve-and-update-jaksot +(defn retrieve-and-update-jaksot! "Hakee nippuun kuuluvat jaksot tietokannasta, laskee niiden kestot, päivittää kestotiedot tietokantaan, ja palauttaa päivitetyt jaksot." [nippu] - (let [jaksot (query-jaksot nippu) - kestot (group-jaksot-and-compute-kestot jaksot)] + (let [jaksot (query-jaksot! nippu) + kestot (jaksojen-kestot! jaksot)] (map #(let [oht-id (:hankkimistapa_id %) - kesto (math-round (get kestot oht-id 0.0))] + kesto (get kestot oht-id 0)] (log/info "Päivitetään jaksoon" oht-id "kesto" kesto) (tc/update-jakso % {:kesto [:n kesto]}) (assoc % :kesto kesto)) @@ -276,7 +272,7 @@ [nippu] (log/info "Niputetaan" nippu) (let [request-id (c/generate-uuid) - jaksot (retrieve-and-update-jaksot nippu) + jaksot (retrieve-and-update-jaksot! nippu) tunnukset (vec (map (fn [x] {:tunnus (:tunnus x) :tyopaikkajakson_kesto (:kesto x)}) jaksot))] diff --git a/src/oph/heratepalvelu/tep/rahoitusLaskentaHandler.clj b/src/oph/heratepalvelu/tep/rahoitusLaskentaHandler.clj index 85e2d8e2..217c4bfa 100644 --- a/src/oph/heratepalvelu/tep/rahoitusLaskentaHandler.clj +++ b/src/oph/heratepalvelu/tep/rahoitusLaskentaHandler.clj @@ -15,7 +15,6 @@ [oph.heratepalvelu.common :as c] [oph.heratepalvelu.db.dynamodb :as ddb] [oph.heratepalvelu.external.arvo :as arvo] - [oph.heratepalvelu.external.ehoks :as ehoks] [oph.heratepalvelu.external.koski :as koski] [oph.heratepalvelu.tep.jaksoHandler :as jh] [oph.heratepalvelu.tep.niputusHandler :as nh] @@ -74,16 +73,8 @@ :oppija_oid (:oppija-oid herate) :jakso_alkupvm (:alkupvm herate) :jakso_loppupvm (:loppupvm herate)} - concurrent-jaksot (ehoks/get-tyoelamajaksot-active-between - (:oppija_oid jakso) - (:jakso_alkupvm jakso) - (:jakso_loppupvm jakso)) - opiskeluoikeudet (nh/get-jaksojen-opiskeluoikeudet - (assoc {} (:opiskeluoikeus-oid herate) - opiskeluoikeus) - (map :opiskeluoikeus_oid concurrent-jaksot)) - kestot (nh/compute-kesto-old-and-new - jakso concurrent-jaksot opiskeluoikeudet) + [kesto kesto-vanha] (map #(get % (:hankkimistapa_id jakso)) + (nh/jaksojen-kestot! [jakso])) db-data {:hankkimistapa_id [:n tapa-id] :hankkimistapa_tyyppi [:s (last (str/split (:hankkimistapa-tyyppi herate) #"_"))] @@ -124,13 +115,12 @@ [:s (c/normalize-string (:tyopaikan-nimi herate))] :rahoitusryhma [:s rahoitusryhma] :existing-arvo-tunnus [:s (str existing-arvo-tunnus)] - :vanha-kesto - [:n (math-round (or (get kestot :vanha) 0.0))] - :uusi-kesto-with-oa - [:n (math-round (or (get-in kestot [:uusi :with-oa]) 0.0))] - :uusi-kesto-without-oa - [:n (math-round (or (get-in kestot [:uusi :without-oa]) - 0.0))] + :vanha-kesto [:n kesto-vanha] + ; NOTE: Uudessa laskutavassa osa-aikaisuutta ei oteta + ; huomioon + ; :uusi-kesto-with-oa [:n kesto] + ; :uusi-kesto-without-oa [:n kesto] + :uusi-kesto [:n kesto] :save-timestamp [:s (str start-time)]} results-table-data (cond-> db-data @@ -140,7 +130,8 @@ (assoc :ohjaaja_puhelinnumero [:s (:tyopaikkaohjaaja-puhelinnumero herate)]) (not-empty (:tutkinnonosa-koodi herate)) - (assoc :tutkinnonosa_koodi [:s (:tutkinnonosa-koodi herate)]) + (assoc :tutkinnonosa_koodi + [:s (:tutkinnonosa-koodi herate)]) (not-empty (:tutkinnonosa-nimi herate)) (assoc :tutkinnonosa_nimi [:s (:tutkinnonosa-nimi herate)]) (some? (:osa-aikaisuus herate)) @@ -151,7 +142,10 @@ (str/split (:oppisopimuksen-perusta herate) #"_"))]))] - (log/info "Uudelleenlaskettu kesto tapa-id:lle" tapa-id ":" kestot) + (log/info (str "Uudelleenlaskettu kesto tapa-id:lle " + tapa-id + ": " + kesto)) (when (jh/has-open-keskeytymisajanjakso? herate) (log/warn "Herätteellä on avoin keskeytymisajanjakso: " herate)) (try @@ -181,7 +175,7 @@ (log/info "heräte:" (.getBody msg)) (try (let [herate (parse-string (.getBody msg) true) - opiskeluoikeus (koski/get-opiskeluoikeus-catch-404 + opiskeluoikeus (koski/get-opiskeluoikeus-catch-404! (:opiskeluoikeus-oid herate))] (if (nil? opiskeluoikeus) (log/warn "No opiskeluoikeus found for oid" diff --git a/src/oph/heratepalvelu/util/date.clj b/src/oph/heratepalvelu/util/date.clj new file mode 100644 index 00000000..5bf4140d --- /dev/null +++ b/src/oph/heratepalvelu/util/date.clj @@ -0,0 +1,12 @@ +(ns oph.heratepalvelu.util.date + (:import (java.time LocalDate)) + (:refer-clojure :exclude [range])) + +(defn range + "Rakentaa laiskan sekvenssin päivämääristä alkupäivämäärän `start` ja + loppupäivämäärän `end` perusteella. `start` ja `end` kuuluvat mukaan + sekvenssiin." + [start end] + (let [end+1 (.plusDays ^LocalDate end 1)] + (take-while #(.isBefore ^LocalDate % end+1) + (iterate #(.plusDays ^LocalDate % 1) start)))) diff --git a/src/oph/heratepalvelu/util/dbChanger.clj b/src/oph/heratepalvelu/util/dbChanger.clj index f768d214..4cfa7c8f 100644 --- a/src/oph/heratepalvelu/util/dbChanger.clj +++ b/src/oph/heratepalvelu/util/dbChanger.clj @@ -47,7 +47,7 @@ :expr-attr-vals {":pvm" (attr "2022-08-11")}})] (doseq [item (map ddb/map-attribute-values-to-vals (.items resp))] (try - (let [opiskeluoikeus (koski/get-opiskeluoikeus-catch-404 + (let [opiskeluoikeus (koski/get-opiskeluoikeus-catch-404! (:opiskeluoikeus-oid item)) rahoitusryhma (c/get-rahoitusryhma opiskeluoikeus (LocalDate/parse (:alkupvm item)))] @@ -97,7 +97,7 @@ ":end" (attr "2021-12-31")}} (:table env)) uudelleenlasketut-kestot - (nip/compute-kestot oppijan-kaikki-jaksot)] + (nip/jaksojen-kestot! oppijan-kaikki-jaksot)] (println uudelleenlasketut-kestot) (doseq [jakso oppijan-kaikki-jaksot] (println "Päivitetään jaksolle" @@ -106,9 +106,8 @@ (println "Vanha kesto" (:kesto jakso) "- Uudelleen laskettu kesto" - (nip/math-round (get uudelleenlasketut-kestot - (:hankkimistapa_id jakso) - 0.0))))))) + (get uudelleenlasketut-kestot + (:hankkimistapa_id jakso))))))) (catch Exception e (log/error e)))) (when (.hasLastEvaluatedKey resp) (recur (scan diff --git a/test/oph/heratepalvelu/amis/AMISherateHandler_test.clj b/test/oph/heratepalvelu/amis/AMISherateHandler_test.clj index 3eb81e79..bb75122c 100644 --- a/test/oph/heratepalvelu/amis/AMISherateHandler_test.clj +++ b/test/oph/heratepalvelu/amis/AMISherateHandler_test.clj @@ -52,7 +52,7 @@ c/sisaltyy-toiseen-opiskeluoikeuteen? mock-sisaltyy-toiseen-opiskeluoikeuteen? - oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404 + oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404! mock-get-opiskeluoikeus-catch-404] (let [event (tu/mock-sqs-event {:alkupvm "2021-10-10" :opiskeluoikeus-oid "1234.5.6678" diff --git a/test/oph/heratepalvelu/external/ehoks_test.clj b/test/oph/heratepalvelu/external/ehoks_test.clj index e1dc480e..9a7d302b 100644 --- a/test/oph/heratepalvelu/external/ehoks_test.clj +++ b/test/oph/heratepalvelu/external/ehoks_test.clj @@ -221,7 +221,7 @@ expected)))))) (deftest test-get-tyoelamajaksot-active-between - (testing "Varmista, että get-tyoelamajaksot-active-between toimii oikein." + (testing "Varmista, että get-tyoelamajaksot-active-between! toimii oikein." (with-redefs [environ.core/env {:ehoks-url "example.com/"} oph.heratepalvelu.external.cas-client/get-service-ticket mock-get-service-ticket @@ -240,9 +240,9 @@ :start "2021-08-01" :end "2021-10-05"} :as :json}}}] - (is (= (ehoks/get-tyoelamajaksot-active-between "1.2.3.4" - "2021-08-01" - "2021-10-05") + (is (= (ehoks/get-tyoelamajaksot-active-between! "1.2.3.4" + "2021-08-01" + "2021-10-05") expected)))))) (deftest test-patch-amis-aloitus-ja-paattoheratteet-kasitellyt diff --git a/test/oph/heratepalvelu/external/koski_test.clj b/test/oph/heratepalvelu/external/koski_test.clj index c6c71a18..7dac4215 100644 --- a/test/oph/heratepalvelu/external/koski_test.clj +++ b/test/oph/heratepalvelu/external/koski_test.clj @@ -24,10 +24,11 @@ (testing "get-opiskeluoikeus-catch-404 käsittelee virheitä oikein" (with-redefs [oph.heratepalvelu.external.koski/get-opiskeluoikeus mock-throws-404] - (is (nil? (koski/get-opiskeluoikeus-catch-404 "1.2.3")))) + (is (nil? (koski/get-opiskeluoikeus-catch-404! "1.2.3")))) (with-redefs [oph.heratepalvelu.external.koski/get-opiskeluoikeus mock-throws-other-error] - (is (thrown? ExceptionInfo (koski/get-opiskeluoikeus-catch-404 "1.2")))))) + (is (thrown? ExceptionInfo + (koski/get-opiskeluoikeus-catch-404! "1.2")))))) (def test-get-updated-opiskeluoikeudet-saved-params (atom {})) diff --git a/test/oph/heratepalvelu/integration_tests/tep/niputusHandler_i_test.clj b/test/oph/heratepalvelu/integration_tests/tep/niputusHandler_i_test.clj index bc713ce0..f590ab6e 100644 --- a/test/oph/heratepalvelu/integration_tests/tep/niputusHandler_i_test.clj +++ b/test/oph/heratepalvelu/integration_tests/tep/niputusHandler_i_test.clj @@ -24,6 +24,7 @@ :tunnus [:s "AAjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-01"] :jakso_loppupvm [:s "2022-01-25"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} @@ -34,6 +35,7 @@ :tunnus [:s "ABjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-15"] :jakso_loppupvm [:s "2022-01-31"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} @@ -44,6 +46,7 @@ :tunnus [:s "ACjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-20"] :jakso_loppupvm [:s "2022-01-31"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} @@ -54,6 +57,7 @@ :tunnus [:s "BAjunk"] :oppija_oid [:s "bbb"] :opiskeluoikeus_oid [:s "oo-bbb"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-10"] :jakso_loppupvm [:s "2022-01-20"] :tyopaikan_nimi [:s "Testi Työpaikka 2"]}]) @@ -95,9 +99,9 @@ "\"tyonantaja\":\"123456-1\"," "\"tyopaikka\":\"Testi Työpaikka 1\"," "\"tunnukset\":[{\"tunnus\":\"AAjunk\"," - "\"tyopaikkajakson_kesto\":12}," + "\"tyopaikkajakson_kesto\":18}," "{\"tunnus\":\"ACjunk\"," - "\"tyopaikkajakson_kesto\":2}]," + "\"tyopaikkajakson_kesto\":5}]," "\"voimassa_alkupvm\":\"2022-02-18\"," "\"request_id\":\"test-uuid\"}")} {:body {:nippulinkki "kysely.linkki/123" @@ -114,7 +118,7 @@ "\"tyonantaja\":\"123456-2\"," "\"tyopaikka\":\"Testi Työpaikka 2\"," "\"tunnukset\":[{\"tunnus\":\"BAjunk\"," - "\"tyopaikkajakson_kesto\":1}]," + "\"tyopaikkajakson_kesto\":4}]," "\"voimassa_alkupvm\":\"2022-02-18\"," "\"request_id\":\"test-uuid\"}")} {:body {:errors "Jokin meni pieleen"}}) @@ -135,6 +139,7 @@ :tunnus "AAjunk" :oppija_oid "aaa" :opiskeluoikeus_oid "oo-aaa" + :osa_aikaisuus 100 :jakso_alkupvm "2022-01-01" :jakso_loppupvm "2022-01-25" :tyopaikan_nimi "Testi Työpaikka 1"} @@ -145,6 +150,7 @@ :tunnus "ABjunk" :oppija_oid "aaa" :opiskeluoikeus_oid "oo-aaa" + :osa_aikaisuus 100 :jakso_alkupvm "2022-01-15" :jakso_loppupvm "2022-01-31" :tyopaikan_nimi "Testi Työpaikka 1"} @@ -155,6 +161,7 @@ :tunnus "ACjunk" :oppija_oid "aaa" :opiskeluoikeus_oid "oo-aaa" + :osa_aikaisuus 100 :jakso_alkupvm "2022-01-20" :jakso_loppupvm "2022-01-31" :tyopaikan_nimi "Testi Työpaikka 1"}]}}) @@ -175,6 +182,7 @@ :tunnus "BAjunk" :oppija_oid "bbb" :opiskeluoikeus_oid "oo-bbb" + :osa_aikaisuus 100 :keskeytymisajanjaksot [{:alku "2022-01-12" :loppu "2022-01-14"}] :jakso_alkupvm "2022-01-10" @@ -185,6 +193,7 @@ :tunnus "BBjunk" :oppija_oid "bbb" :opiskeluoikeus_oid "oo-bbb" + :osa_aikaisuus 100 :keskeytymisajanjaksot [{:alku "2022-01-03" :loppu "2022-01-08"}] :jakso_alkupvm "2022-01-01" @@ -234,13 +243,14 @@ (mdb/clear-mock-db)) (def expected-jaksotunnus-table #{{:hankkimistapa_id [:n 11] - :kesto [:n 12] + :kesto [:n 18] :ohjaaja_ytunnus_kj_tutkinto [:s "oykt-1"] :niputuspvm [:s "2022-02-01"] :viimeinen_vastauspvm [:s "2022-03-31"] :tunnus [:s "AAjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-01"] :jakso_loppupvm [:s "2022-01-25"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} @@ -251,28 +261,31 @@ :tunnus [:s "ABjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-15"] :jakso_loppupvm [:s "2022-01-31"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} {:hankkimistapa_id [:n 13] - :kesto [:n 2] + :kesto [:n 5] :ohjaaja_ytunnus_kj_tutkinto [:s "oykt-1"] :niputuspvm [:s "2022-02-01"] :viimeinen_vastauspvm [:s "2022-02-25"] :tunnus [:s "ACjunk"] :oppija_oid [:s "aaa"] :opiskeluoikeus_oid [:s "oo-aaa"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-20"] :jakso_loppupvm [:s "2022-01-31"] :tyopaikan_nimi [:s "Testi Työpaikka 1"]} {:hankkimistapa_id [:n 21] :ohjaaja_ytunnus_kj_tutkinto [:s "oykt-2"] - :kesto [:n 1] + :kesto [:n 4] :niputuspvm [:s "2022-02-01"] :viimeinen_vastauspvm [:s "2022-03-31"] :tunnus [:s "BAjunk"] :oppija_oid [:s "bbb"] :opiskeluoikeus_oid [:s "oo-bbb"] + :osa_aikaisuus [:n "100"] :jakso_alkupvm [:s "2022-01-10"] :jakso_loppupvm [:s "2022-01-20"] :tyopaikan_nimi [:s "Testi Työpaikka 2"]}}) @@ -332,9 +345,9 @@ "\"tyonantaja\":\"123456-1\"," "\"tyopaikka\":\"Testi Työpaikka 1\"," "\"tunnukset\":[{\"tunnus\":\"AAjunk\"," - "\"tyopaikkajakson_kesto\":12}," + "\"tyopaikkajakson_kesto\":18}," "{\"tunnus\":\"ACjunk\"," - "\"tyopaikkajakson_kesto\":2}]," + "\"tyopaikkajakson_kesto\":5}]," "\"voimassa_alkupvm\":\"2022-02-18\"," "\"request_id\":\"test-uuid\"}") :basic-auth ["arvo-user" "arvo-pwd"] :as :json}} @@ -360,7 +373,7 @@ "\"tyonantaja\":\"123456-2\"," "\"tyopaikka\":\"Testi Työpaikka 2\"," "\"tunnukset\":[{\"tunnus\":\"BAjunk\"," - "\"tyopaikkajakson_kesto\":1}]," + "\"tyopaikkajakson_kesto\":4}]," "\"voimassa_alkupvm\":\"2022-02-18\"," "\"request_id\":\"test-uuid\"}") :basic-auth ["arvo-user" "arvo-pwd"] :as :json}}]) diff --git a/test/oph/heratepalvelu/tep/jaksoHandler_test.clj b/test/oph/heratepalvelu/tep/jaksoHandler_test.clj index e4cc8ac9..bb9ca52c 100644 --- a/test/oph/heratepalvelu/tep/jaksoHandler_test.clj +++ b/test/oph/heratepalvelu/tep/jaksoHandler_test.clj @@ -530,7 +530,7 @@ c/terminaalitilassa? mock-terminaalitilassa? oph.heratepalvelu.external.ehoks/patch-oht-tep-kasitelty mock-patch-oht-tep-kasitelty - oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404 + oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404! mock-get-opiskeluoikeus-catch-404 oph.heratepalvelu.tep.jaksoHandler/osa-aikaisuus-missing? mock-osa-aikaisuus-missing? diff --git a/test/oph/heratepalvelu/tep/niputusHandler_test.clj b/test/oph/heratepalvelu/tep/niputusHandler_test.clj index c6fae6a4..6f9bd8eb 100644 --- a/test/oph/heratepalvelu/tep/niputusHandler_test.clj +++ b/test/oph/heratepalvelu/tep/niputusHandler_test.clj @@ -1,10 +1,244 @@ (ns oph.heratepalvelu.tep.niputusHandler-test - (:require [clojure.test :refer :all] + (:require [clojure.test :refer [are deftest is testing]] [oph.heratepalvelu.common :as c] [oph.heratepalvelu.tep.niputusHandler :as nh] + [oph.heratepalvelu.external.ehoks :as ehoks] + [oph.heratepalvelu.external.koski :as koski] + [oph.heratepalvelu.external.arvo :as arvo] + [oph.heratepalvelu.db.dynamodb :as ddb] [oph.heratepalvelu.test-util :as tu]) (:import (java.time LocalDate))) +(def jakso-1 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 1 + :jakso_alkupvm "2021-10-22" + :jakso_loppupvm "2021-10-25" + :osa_aikaisuus 40 + :keskeytymisajanjaksot [{:id 1032 + :osaamisen-hankkimistapa-id 1 + :alku "2022-02-11" + :loppu "3022-03-01"}]}) + +(def jakso-2 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 2 + :jakso_alkupvm "2021-09-01" + :jakso_loppupvm "2021-12-15" + :osa_aikaisuus 80 + :keskeytymisajanjaksot [{:id 1033 + :osaamisen-hankkimistapa-id 2 + :alku "2021-10-22" + :loppu "2021-10-30"}]}) + +(def jakso-3 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 3 + :jakso_alkupvm "2021-10-11" + :jakso_loppupvm "2021-10-21" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1030 + :osaamisen-hankkimistapa-id 3 + :alku "2021-10-13" + :loppu "2021-10-14"}]}) + +(def jakso-4 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 4 + :jakso_alkupvm "2021-05-15" + :jakso_loppupvm "2021-12-01" + :osa_aikaisuus 70 + :keskeytymisajanjaksot []}) + +(def jakso-5 {:opiskeluoikeus_oid "1.2.3.7" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 5 + :jakso_alkupvm "2021-09-01" + :jakso_loppupvm "2023-12-15" + :osa_aikaisuus 60 + :keskeytymisajanjaksot []}) + +(def jakso-6 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 6 + :jakso_alkupvm "2021-10-11" + :jakso_loppupvm "2021-10-21" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1031 + :osaamisen-hankkimistapa-id 6 + :alku "2021-10-13" + :loppu "2021-10-14"}]}) + +(def jakso-7 {:opiskeluoikeus_oid "1.2.3.10" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 7 + :jakso_alkupvm "2021-01-15" + :jakso_loppupvm "2022-04-29" + :osa_aikaisuus 50 + :keskeytymisajanjaksot []}) + +(def jakso-8 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 8 + :jakso_alkupvm "2021-10-15" + :jakso_loppupvm "2021-12-11" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-9 {:opiskeluoikeus_oid "1.2.3.6" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 9 + :jakso_alkupvm "2021-07-03" + :jakso_loppupvm "2021-08-26" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-10 {:opiskeluoikeus_oid "1.2.3.7" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 10 + :jakso_alkupvm "2021-08-20" + :jakso_loppupvm "2021-09-10" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1191 + :osaamisen-hankkimistapa-id 10 + :alku "2021-08-25" + :loppu "2021-08-28"}]}) + +(def jakso-11 {:opiskeluoikeus_oid "1.2.3.7" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 11 + :jakso_alkupvm "2021-09-03" + :jakso_loppupvm "2021-09-30" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-12 {:opiskeluoikeus_oid "1.2.3.7" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 12 + :jakso_alkupvm "2021-11-12" + :jakso_loppupvm "2021-12-15" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1192 + :osaamisen-hankkimistapa-id 12 + :alku "2021-11-18" + :loppu "2021-11-25"}]}) + +(def jakso-13 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 13 + :jakso_alkupvm "2021-09-06" + :jakso_loppupvm "2021-10-19" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1029 + :osaamisen-hankkimistapa-id 13 + :alku "2021-10-13"}]}) + +(def jakso-14 {:opiskeluoikeus_oid "1.2.3.7" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 14 + :jakso_alkupvm "2021-09-01" + :jakso_loppupvm "2024-12-15" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-15 {:opiskeluoikeus_oid "1.2.3.8" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 15 + :jakso_alkupvm "2021-10-04" + :jakso_loppupvm "2021-10-19" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-16 {:opiskeluoikeus_oid "1.2.3.9" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 16 + :jakso_alkupvm "2021-02-01" + :jakso_loppupvm "2021-08-30" + :osa_aikaisuus 100 + :keskeytymisajanjaksot [{:id 1034 + :osaamisen-hankkimistapa-id 16 + :alku "2021-06-15"}]}) + +(def jakso-17 {:opiskeluoikeus_oid "1.2.3.10.onnea.etsintaan" + :oppija_oid "4.4.4.4" + :hankkimistapa_id 17 + :jakso_alkupvm "2021-08-27" + :jakso_loppupvm "2022-04-29" + :osa_aikaisuus 100 + :keskeytymisajanjaksot []}) + +(def jakso-21 {:hankkimistapa_id 21 + :oppija_oid "3.3.3.3" + :osa_aikaisuus 100 + :jakso_alkupvm "2022-01-03" + :jakso_loppupvm "2022-02-05" + :keskeytymisajanjaksot [] + :opiskeluoikeus_oid "1.2.3.1"}) + +(def jakso-22 {:hankkimistapa_id 22 + :oppija_oid "3.3.3.3" + :osa_aikaisuus 50 + :jakso_alkupvm "2022-02-07" + :jakso_loppupvm "2022-04-04" + :opiskeluoikeus_oid "1.2.3.2"}) + +(def jakso-23 {:hankkimistapa_id 23 + :oppija_oid "3.3.3.3" + :osa_aikaisuus 20 + :jakso_alkupvm "2022-01-31" + :jakso_loppupvm "2022-02-20" + :keskeytymisajanjaksot [{:alku "2022-02-16" + :loppu "2022-02-18"}] + :opiskeluoikeus_oid "1.2.3.3"}) + +(def jakso-24 {:hankkimistapa_id 24 + :oppija_oid "3.3.3.3" + :osa_aikaisuus 90 + :jakso_alkupvm "2022-01-17" + :jakso_loppupvm "2022-02-20" + :opiskeluoikeus_oid "1.2.3.4"}) + +(def jakso-25 {:hankkimistapa_id 25 + :oppija_oid "3.3.3.3" + :osa_aikaisuus 100 + :jakso_alkupvm "2022-01-01" + :jakso_loppupvm "2022-04-01" + :keskeytymisajanjaksot [{:alku "2022-01-12" :loppu "2022-01-12"} + {:alku "2022-01-16" :loppu "2022-01-18"}] + :opiskeluoikeus_oid "1.2.3.5"}) + +(def jaksot-1-17 + [jakso-1 jakso-2 jakso-3 jakso-4 jakso-5 jakso-6 jakso-7 jakso-8 jakso-9 + jakso-10 jakso-11 jakso-12 jakso-13 jakso-14 jakso-15 jakso-16 jakso-17]) + +(def jaksot-21-25 [jakso-21 jakso-22 jakso-23 jakso-24 jakso-25]) + +(def jaksot-1-25 (concat jaksot-1-17 jaksot-21-25)) + +(def opiskeluoikeudet + {"1.2.3.1" {:tila {:opiskeluoikeusjaksot + [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}}]}} + "1.2.3.2" {:tila {:opiskeluoikeusjaksot + [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}}]}} + "1.2.3.4" {:tila {:opiskeluoikeusjaksot + [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} + {:alku "2022-01-30" :tila {:koodiarvo "loma"}} + {:alku "2022-02-10" :tila {:koodiarvo "lasna"}}]}} + "1.2.3.5" {:tila {:opiskeluoikeusjaksot + [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} + {:alku "2022-02-02" + :tila {:koodiarvo "valiaikaisestikeskeytynyt"}}]}} + "1.2.3.6" {:tila {:opiskeluoikeusjaksot + [{:alku "2020-03-05", :tila {:koodiarvo "lasna"}}]}} + "1.2.3.7" {:tila {:opiskeluoikeusjaksot + [{:alku "2020-04-06", :tila {:koodiarvo "lasna"}}]}} + "1.2.3.8" {:tila {:opiskeluoikeusjaksot + [{:alku "2020-01-01", :tila {:koodiarvo "lasna"}}]}} + "1.2.3.9" {:tila {:opiskeluoikeusjaksot + [{:alku "2022-08-25", :tila {:koodiarvo "lasna"}}]}} + "1.2.3.10" {:tila {:opiskeluoikeusjaksot + [{:alku "2020-10-27", :tila {:koodiarvo "lasna"}}]}}}) + (deftest test-not-in-keskeytymisajanjakso? (testing "Varmistaa, että not-in-keskeytymisajanjakso? toimii oikein." (let [kjaksot [{:loppu (LocalDate/of 2022 4 1)} @@ -25,441 +259,315 @@ (is (false? (nh/not-in-keskeytymisajanjakso? (LocalDate/of 2022 4 10) kjaksot)))))) -(deftest test-is-weekday? - (testing "Varmistaa, että is-weekday? palauttaa true jos kyse on arkipäivästä" - (is (true? (nh/is-weekday? (LocalDate/of 2022 6 13)))) - (is (true? (nh/is-weekday? (LocalDate/of 2022 6 10)))) - (is (false? (nh/is-weekday? (LocalDate/of 2022 6 4)))) - (is (false? (nh/is-weekday? (LocalDate/of 2022 6 5)))))) - -(deftest test-filtered-jakso-days - (testing "Varmistaa, että filtered-jakso-days toimii oikein." - (let [test-jakso1 {:jakso_alkupvm "2022-04-27" :jakso_loppupvm "2022-05-02"} - test-jakso2 {:jakso_alkupvm "2022-04-24" :jakso_loppupvm "2022-04-30"} - days1 (seq [(LocalDate/of 2022 4 27) - (LocalDate/of 2022 4 28) - (LocalDate/of 2022 4 29) - (LocalDate/of 2022 5 2)]) - days2 (seq [(LocalDate/of 2022 4 25) - (LocalDate/of 2022 4 26) - (LocalDate/of 2022 4 27) - (LocalDate/of 2022 4 28) - (LocalDate/of 2022 4 29)])] - (is (= (nh/filtered-jakso-days test-jakso1) days1)) - (is (= (nh/filtered-jakso-days test-jakso2) days2))))) - -(deftest test-add-to-jaksot-by-day - (testing "Varmistaa, että add-to-jaksot-by-day toimii oikein." - (let [opiskeluoikeus {:tila - {:opiskeluoikeusjaksot - [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} - {:alku "2022-01-17" :tila {:koodiarvo "loma"}} - {:alku "2022-01-19" :tila {:koodiarvo "lasna"}} - {:alku "2022-01-21" - :tila {:koodiarvo "valiaikaisestikeskeytynyt"}} - {:alku "2022-02-25" :tila {:koodiarvo "lasna"}}]}} - existing-jakso {:jakso_alkupvm "2022-01-10" - :jakso_loppupvm "2022-01-16"} - jaksot-by-day {(LocalDate/of 2022 1 10) (seq [existing-jakso]) - (LocalDate/of 2022 1 11) (seq [existing-jakso]) - (LocalDate/of 2022 1 12) (seq [existing-jakso]) - (LocalDate/of 2022 1 13) (seq [existing-jakso]) - (LocalDate/of 2022 1 14) (seq [existing-jakso])} - jakso {:jakso_alkupvm "2022-01-09" - :jakso_loppupvm "2022-01-24" - :keskeytymisajanjaksot [{:alku "2022-01-12" - :loppu "2022-01-12"}] - :opiskeluoikeus_oid "asdf"} - results {(LocalDate/of 2022 1 10) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 11) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 12) (seq [existing-jakso]) - (LocalDate/of 2022 1 13) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 14) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 19) (seq [jakso]) - (LocalDate/of 2022 1 20) (seq [jakso])}] - (is (= (nh/add-to-jaksot-by-day jaksot-by-day jakso opiskeluoikeus) - results))))) - -(deftest test-add-to-jaksot-by-day-new - (testing "Varmistaa, että add-to-jaksot-by-day-new toimii oikein." - (let [opiskeluoikeus {:tila - {:opiskeluoikeusjaksot - [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} - {:alku "2022-01-17" :tila {:koodiarvo "loma"}} - {:alku "2022-01-19" :tila {:koodiarvo "lasna"}} - {:alku "2022-01-21" - :tila {:koodiarvo "valiaikaisestikeskeytynyt"}} - {:alku "2022-02-25" :tila {:koodiarvo "lasna"}}]}} - existing-jakso {:jakso_alkupvm "2022-01-10" - :jakso_loppupvm "2022-01-16"} - jaksot-by-day {(LocalDate/of 2022 1 10) (seq [existing-jakso]) - (LocalDate/of 2022 1 11) (seq [existing-jakso]) - (LocalDate/of 2022 1 12) (seq [existing-jakso]) - (LocalDate/of 2022 1 13) (seq [existing-jakso]) - (LocalDate/of 2022 1 14) (seq [existing-jakso]) - (LocalDate/of 2022 1 15) (seq [existing-jakso]) - (LocalDate/of 2022 1 16) (seq [existing-jakso])} - jakso {:jakso_alkupvm "2022-01-09" - :jakso_loppupvm "2022-01-28" - :keskeytymisajanjaksot [{:alku "2022-01-12" - :loppu "2022-01-12"}] - :opiskeluoikeus_oid "asdf"} - expected {(LocalDate/of 2022 1 9) (seq [jakso]) - (LocalDate/of 2022 1 10) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 11) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 12) (seq [existing-jakso]) - (LocalDate/of 2022 1 13) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 14) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 15) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 16) (seq [jakso existing-jakso]) - (LocalDate/of 2022 1 17) (seq [jakso]) - (LocalDate/of 2022 1 18) (seq [jakso]) - (LocalDate/of 2022 1 19) (seq [jakso]) - (LocalDate/of 2022 1 20) (seq [jakso])}] - (is (= expected (nh/add-to-jaksot-by-day-new - jaksot-by-day jakso opiskeluoikeus)))))) - -(deftest test-handle-one-day - (testing "Varmistaa, että handle-one-day toimii oikein." - (let [jaksot (seq [{:hankkimistapa_id 1 :osa_aikaisuus 100} - {:hankkimistapa_id 2 :osa_aikaisuus 50} - {:hankkimistapa_id 3 :osa_aikaisuus 10} - {:hankkimistapa_id 4}]) - results {1 0.25 - 2 0.125 - 3 0.025 - 4 0.25}] - (is (= (nh/handle-one-day jaksot) results))))) - -(def test-compute-kestot-results (atom [])) -(def test-compute-kestot-new-results (atom [])) +(def mock-get-opiskeluoikeus-catch-404-count (atom 0)) (defn- do-rounding [values] - ; FIXME: map-values - (reduce-kv #(assoc %1 %2 (/ (Math/round (* %3 1000.0)) 1000.0)) {} values)) - -(defn- do-rounding-new [value] - (/ (Math/round (* value 1000.0)) 1000.0)) + (reduce-kv #(assoc %1 %2 (/ (Math/round (* %3 100.0)) 100.0)) {} values)) (defn- mock-get-opiskeluoikeus-catch-404 [oo-oid] - (cond - (= oo-oid "1.2.3.4") {:tila - {:opiskeluoikeusjaksot - [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} - {:alku "2022-01-30" :tila {:koodiarvo "loma"}} - {:alku "2022-02-10" :tila {:koodiarvo "lasna"}}]}} - (= oo-oid "1.2.3.5") {:tila - {:opiskeluoikeusjaksot - [{:alku "2022-01-01" :tila {:koodiarvo "lasna"}} - {:alku "2022-02-02" - :tila {:koodiarvo "valiaikaisestikeskeytynyt"}}]}} - (= oo-oid "1.2.3.8") {:tila - {:opiskeluoikeusjaksot - [{:alku "2020-01-01", :tila {:koodiarvo "lasna"}}]}} - (= oo-oid "1.2.3.7") {:tila - {:opiskeluoikeusjaksot - [{:alku "2020-04-06", - :tila {:koodiarvo "lasna"}}]}} - (= oo-oid "1.2.3.9") {:tila - {:opiskeluoikeusjaksot - [{:alku "2022-08-25", - :tila {:koodiarvo "lasna"}}]}} - (= oo-oid "1.2.3.6") {:tila - {:opiskeluoikeusjaksot - [{:alku "2020-03-05", - :tila {:koodiarvo "lasna"}}]}} - (= oo-oid "1.2.3.10") {:tila - {:opiskeluoikeusjaksot - [{:alku "2020-10-27", - :tila {:koodiarvo "lasna"}}]}} - :else nil)) - -(deftest get-jaksojen-opiskeluoikeudet - (testing "Varmistaa, että get-jaksojen-opiskeluoikeudet toimii kuten pitää." - (with-redefs - [oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404 - mock-get-opiskeluoikeus-catch-404] - (let [opiskeluoikeudet {"1.2.3.a" "a" "1.2.3.b" "b"}] - (is (= {} (nh/get-jaksojen-opiskeluoikeudet {} []))) - (is (= {"1.2.3.a" "a"} - (nh/get-jaksojen-opiskeluoikeudet opiskeluoikeudet ["1.2.3.a"]))) - (is (= {"1.2.3.a" nil "1.2.3.b" nil} - (nh/get-jaksojen-opiskeluoikeudet {} ["1.2.3.a" "1.2.3.b"]))) - (is (= {"1.2.3.c" nil} - (nh/get-jaksojen-opiskeluoikeudet opiskeluoikeudet ["1.2.3.c"]))) - (is (= {"1.2.3.7" - {:tila {:opiskeluoikeusjaksot - [{:alku "2020-04-06", :tila {:koodiarvo "lasna"}}]}} - "1.2.3.9" - {:tila {:opiskeluoikeusjaksot - [{:alku "2022-08-25", :tila {:koodiarvo "lasna"}}]}} - "1.2.3.10.onnea.matkaan" nil} - (nh/get-jaksojen-opiskeluoikeudet - opiskeluoikeudet - ["1.2.3.7" "1.2.3.9" "1.2.3.10.onnea.matkaan"]))) - (is (= {"1.2.3.8" - {:tila {:opiskeluoikeusjaksot - [{:alku "2020-01-01", :tila {:koodiarvo "lasna"}}]}} - "1.2.3.a" "a" - "1.2.3.b" "b"} - (nh/get-jaksojen-opiskeluoikeudet - opiskeluoikeudet ["1.2.3.a" "1.2.3.8" "1.2.3.b"]))))))) - -(deftest test-compute-kestot - (testing "Varmistaa, että compute-kestot laskee kestot oikein." - (with-redefs - [oph.heratepalvelu.external.ehoks/get-tyoelamajaksot-active-between - (fn [oppija-oid start end] - (reset! test-compute-kestot-results - (cons {:type "gtab" :start start :end end :oppija oppija-oid} - @test-compute-kestot-results)) - (seq [{:hankkimistapa_id 1 - :oppija_oid "4.4.4.4" - :osa_aikaisuus 100 - :jakso_alkupvm "2022-01-03" - :jakso_loppupvm "2022-02-05" - :keskeytymisajanjaksot [] - :opiskeluoikeus_oid "1.2.3.1"} - {:hankkimistapa_id 2 - :oppija_oid "4.4.4.4" - :osa_aikaisuus 50 - :jakso_alkupvm "2022-02-07" - :jakso_loppupvm "2022-04-04" - :opiskeluoikeus_oid "1.2.3.2"} - {:hankkimistapa_id 3 - :oppija_oid "4.4.4.4" - :osa_aikaisuus 0 - :jakso_alkupvm "2022-01-31" - :jakso_loppupvm "2022-02-20" - :keskeytymisajanjaksot [{:alku "2022-02-16" - :loppu "2022-02-18"}] - :opiskeluoikeus_oid "1.2.3.3"} - {:hankkimistapa_id 4 - :oppija_oid "4.4.4.4" - :jakso_alkupvm "2022-01-17" - :jakso_loppupvm "2022-02-20" - :opiskeluoikeus_oid "1.2.3.4"} - {:hankkimistapa_id 5 - :oppija_oid "4.4.4.4" - :jakso_alkupvm "2022-01-01" - :jakso_loppupvm "2022-04-01" - :opiskeluoikeus_oid "1.2.3.5"}])) - oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404 - mock-get-opiskeluoikeus-catch-404] - (let [jaksot [{:oppija_oid "4.4.4.4" - :jakso_alkupvm "2022-01-05" - :jakso_loppupvm "2022-02-28"} - {:oppija_oid "4.4.4.4" - :jakso_alkupvm "2022-01-10" - :jakso_loppupvm "2022-03-03"}] - results {1 10.5 - 2 17.667 - 3 5.0 - 4 6.167 - 5 9.0} - call-results [{:type "gtab" - :start "2022-01-05" - :end "2022-03-03" - :oppija "4.4.4.4"}]] - (is (= (do-rounding (nh/compute-kestot jaksot)) results)) - (is (= (vec (reverse @test-compute-kestot-results)) call-results)))))) - -(deftest test-compute-kestot-new - (testing "Varmistaa, että compute-kestot-new laskee kestot oikein." - (with-redefs - [oph.heratepalvelu.external.ehoks/get-tyoelamajaksot-active-between - (fn [oppija-oid start end] - (reset! test-compute-kestot-new-results - (cons {:type "gtab" :start start :end end :oppija oppija-oid} - @test-compute-kestot-new-results)) - (seq [{:opiskeluoikeus_oid "1.2.3.6", - :hankkimistapa_id 9, - :jakso_alkupvm "2021-07-03", - :jakso_loppupvm "2021-08-26", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []}, - {:opiskeluoikeus_oid "1.2.3.7", - :hankkimistapa_id 14, - :jakso_alkupvm "2021-09-01", - :jakso_loppupvm "2024-12-15", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.7", - :hankkimistapa_id 5, - :jakso_alkupvm "2021-09-01", - :jakso_loppupvm "2023-12-15", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.7", - :hankkimistapa_id 11, - :jakso_alkupvm "2021-09-03", - :jakso_loppupvm "2021-09-30", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.7", - :hankkimistapa_id 10, - :jakso_alkupvm "2021-08-20", - :jakso_loppupvm "2021-09-10", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1191, - :osaamisen-hankkimistapa-id 10, - :alku "2021-09-21"}]} - {:opiskeluoikeus_oid "1.2.3.7", - :hankkimistapa_id 12, - :jakso_alkupvm "2021-11-12", - :jakso_loppupvm "2021-12-15", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1192, - :osaamisen-hankkimistapa-id 12, - :alku "2021-11-18", - :loppu "2021-11-25"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 13, - :jakso_alkupvm "2021-09-06", - :jakso_loppupvm "2021-10-19", - :osa_aikaisuus 60, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1029, - :osaamisen-hankkimistapa-id 13, - :alku "2021-10-13"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 3, - :jakso_alkupvm "2021-10-11", - :jakso_loppupvm "2021-10-21", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1030, - :osaamisen-hankkimistapa-id 3, - :alku "2021-10-13", - :loppu "2021-10-14"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 6, - :jakso_alkupvm "2021-10-11", - :jakso_loppupvm "2021-10-21", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1031, - :osaamisen-hankkimistapa-id 6, - :alku "2021-10-13"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 1, - :jakso_alkupvm "2021-10-22", - :jakso_loppupvm "2021-10-25", - :osa_aikaisuus 40, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1032, - :osaamisen-hankkimistapa-id 1, - :alku "2022-02-11", - :loppu "3022-03-01"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 15, - :jakso_alkupvm "2021-10-04", - :jakso_loppupvm "2021-10-19", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 8, - :jakso_alkupvm "2021-10-15", - :jakso_loppupvm "2021-12-11", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 2, - :jakso_alkupvm "2021-09-01", - :jakso_loppupvm "2021-12-15", - :osa_aikaisuus 80, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1033, - :osaamisen-hankkimistapa-id 2, - :alku "2021-10-22", - :loppu "2021-10-30"}]} - {:opiskeluoikeus_oid "1.2.3.8", - :hankkimistapa_id 4, - :jakso_alkupvm "2021-05-15", - :jakso_loppupvm "2021-12-01", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.9", - :hankkimistapa_id 17503, - :jakso_alkupvm "2021-02-01", - :jakso_loppupvm "2021-08-30", - :osa_aikaisuus nil, - :tyyppi "hato", - :keskeytymisajanjaksot [{:id 1034, - :osaamisen-hankkimistapa-id 17503, - :alku "2021-06-15"}]} - {:opiskeluoikeus_oid "1.2.3.10", - :hankkimistapa_id 7, - :jakso_alkupvm "2021-01-15", - :jakso_loppupvm "2022-04-29", - :osa_aikaisuus 50, - :tyyppi "hato", - :keskeytymisajanjaksot []} - {:opiskeluoikeus_oid "1.2.3.10.onnea.etsintaan", - :hankkimistapa_id 666, - :jakso_alkupvm "2021-08-27", - :jakso_loppupvm "2022-04-29", - :osa_aikaisuus 100, - :tyyppi "hato", - :keskeytymisajanjaksot []}])) - oph.heratepalvelu.external.koski/get-opiskeluoikeus-catch-404 - mock-get-opiskeluoikeus-catch-404] - (let [jaksot [{:hankkimistapa_id 4 - :oppija_oid "4.4.4.4" - :jakso_alkupvm "2021-05-15" - :jakso_loppupvm "2021-12-01"} - {:hankkimistapa_id 7 - :oppija_oid "4.4.4.4" - :jakso_alkupvm "2021-01-15" - :jakso_loppupvm "2022-04-29"}] - results {4 {:vanha 37.558 - :uusi {:with-oa 52.675 - :without-oa 52.675}} - 7 {:vanha 60.079 - :uusi {:with-oa 84.321 - :without-oa 168.641}}} - call-results [{:type "gtab" - :start "2021-05-15" - :end "2021-12-01" - :oppija "4.4.4.4"} - {:type "gtab" - :start "2021-01-15" - :end "2022-04-29" - :oppija "4.4.4.4"}]] - (is (= results (-> (nh/compute-kestot-new jaksot) - (update-in [4 :vanha] do-rounding-new) - (update-in [4 :uusi :with-oa] do-rounding-new) - (update-in [4 :uusi :without-oa] do-rounding-new) - (update-in [7 :vanha] do-rounding-new) - (update-in [7 :uusi :with-oa] do-rounding-new) - (update-in [7 :uusi :without-oa] do-rounding-new)))) - (is (= call-results - (vec (reverse @test-compute-kestot-new-results)))))))) - -(defn- mock-compute-kestot [jaksot] {(:oppija_oid (first jaksot)) (vec jaksot)}) - -(deftest test-group-jaksot-and-compute-kestot - (testing "Varmistaa, että group-jaksot-and-compute-kestot toimii oikein." - (with-redefs [oph.heratepalvelu.tep.niputusHandler/compute-kestot - mock-compute-kestot] - (let [jaksot [{:oppija_oid "1234" :other_field "A"} - {:oppija_oid "5678" :other_field "B"} - {:oppija_oid "1234" :other_field "C"} - {:oppija_oid "8900" :other_field "D"}] - results {"1234" [{:oppija_oid "1234" :other_field "C"} - {:oppija_oid "1234" :other_field "A"}] - "5678" [{:oppija_oid "5678" :other_field "B"}] - "8900" [{:oppija_oid "8900" :other_field "D"}]}] - (is (= (nh/group-jaksot-and-compute-kestot jaksot) results)))))) + (assert oo-oid "Opiskeluoikeus OID `oo-oid` puuttuu") + (swap! mock-get-opiskeluoikeus-catch-404-count inc) + (get opiskeluoikeudet oo-oid)) + +(deftest test-get-and-memoize-opiskeluoikeudet + (with-redefs + [clojure.tools.logging/log* tu/mock-log* + koski/get-opiskeluoikeus-catch-404! mock-get-opiskeluoikeus-catch-404] + (testing + (str "Funktio pitää entuudestaan haetut opiskeluoikeudet muistitssa, " + "eikä hae niitä toistamiseen. Funktio lokitaa varoituksen, jos " + "opiskeluoikeutta ei saada koskesta") + (is (= (nh/get-and-memoize-opiskeluoikeudet! []) {})) + (reset! mock-get-opiskeluoikeus-catch-404-count 0) + (is (= (nh/get-and-memoize-opiskeluoikeudet! + [jakso-1 ; 1.2.3.8 + jakso-2 ; 1.2.3.8 + jakso-5 ; 1.2.3.7 + jakso-6 ; 1.2.3.8 + jakso-10 ; 1.2.3.7 + {:hankkimistapa_id 123 :opiskeluoikeus_oid "1.2.3.4.ei.loydy"}]) + {"1.2.3.7" (get opiskeluoikeudet "1.2.3.7") + "1.2.3.8" (get opiskeluoikeudet "1.2.3.8")})) + (is (= @mock-get-opiskeluoikeus-catch-404-count 3)) + (is (tu/logs-contain? + {:level :warn + :message + (str "Opiskeluoikeutta `1.2.3.4.ei.loydy` ei saatu Koskesta. " + "Jakson 123 kestoksi asetetaan nolla.")}))))) + +(deftest test-get-opiskeluoikeusjaksot + (testing "Funktio hakee onnistuneesti opiskeluoikeuden opiskeluoikeusjaksot." + (are [oo-oid expected] (= (nh/get-opiskeluoikeusjaksot + (mock-get-opiskeluoikeus-catch-404 oo-oid)) + expected) + "1.2.3.4" (map c/alku-and-loppu-to-localdate + [{:tila {:koodiarvo "lasna"} + :alku "2022-01-01" + :loppu "2022-01-29"} + {:tila {:koodiarvo "loma"} + :alku "2022-01-30" + :loppu "2022-02-09"} + {:tila {:koodiarvo "lasna"} :alku "2022-02-10"}]) + "1.2.3.5" (map c/alku-and-loppu-to-localdate + [{:tila {:koodiarvo "lasna"} + :alku "2022-01-01" + :loppu "2022-02-01"} + {:tila {:koodiarvo "valiaikaisestikeskeytynyt"} + :alku "2022-02-02"}])))) + +(defn- mock-get-tyoelamajaksot-active-between! + [oppija-oid start end] + (assert oppija-oid "oppija-oid puuttuu") + (assert start "aikavälin alkupäivämäärä `start` puuttuu") + (assert end "aikavälin päättymispäivämäärä `end` puuttuu") + (filter #(and (= (:oppija_oid %) oppija-oid) + (<= (compare (:jakso_alkupvm %) end) 0) + (>= (compare (:jakso_loppupvm %) start) 0)) + jaksot-1-25)) + +(deftest test-in-jakso? + (testing "Funktio palauttaa" + (let [jakso {:alku (LocalDate/parse "2022-07-08") + :loppu (LocalDate/parse "2022-12-20")} + jakso-2 {:alku (LocalDate/parse "2022-05-01")}] + (testing "`true`, kun päivämäärä on" + (testing "suljetulla aikavälillä" + (are [pvm] (nh/in-jakso? (LocalDate/parse pvm) jakso) + "2022-07-08" "2022-12-20" "2022-10-18" "2022-08-31")) + (testing "puoliavoimella aikavälillä" + (are [pvm] (nh/in-jakso? (LocalDate/parse pvm) jakso-2) + "2022-05-01" "2022-05-02" "2022-10-18" "2024-01-01"))) + (testing "`false`, kun päivämäärä on" + (testing "suljetun aikavälin ulkopuolella" + (are [pvm] (not (nh/in-jakso? (LocalDate/parse pvm) jakso)) + "2022-07-07" "2022-12-21" "2021-07-08" "2022-12-30")) + (testing "puoliavoimen aikavälin ulkopuolella" + (are [pvm] (not (nh/in-jakso? (LocalDate/parse pvm) jakso-2)) + "2022-04-30" "2022-01-01" "2021-12-30" "2020-06-05")))))) + +(deftest test-jakso-active? + (let [jakso-1 {:alku (LocalDate/parse "2022-01-03") + :loppu (LocalDate/parse "2022-05-05") + :keskeytymisajanjaksot [{:alku "2022-02-20" + :loppu "2022-03-03"} + {:alku "2022-04-08"}]} + jakso-2 {:alku (LocalDate/parse "2022-01-01")} + opiskeluoikeus-1 (mock-get-opiskeluoikeus-catch-404 "1.2.3.4") + opiskeluoikeus-2 (mock-get-opiskeluoikeus-catch-404 "1.2.3.5")] + (testing "Funktio palauttaa" + (testing (str "`true`, kun päivämäärä on jakson sisällä, eikä se kuulu " + "mihinkään keskeytymisajanjaksoon.") + (are [pvm] (nh/jakso-active? jakso-1 opiskeluoikeus-1 + (LocalDate/parse pvm)) + "2022-01-03" "2022-02-19" "2022-03-04" "2022-04-07" "2022-02-10") + (are [pvm] (nh/jakso-active? jakso-2 + opiskeluoikeus-2 + (LocalDate/parse pvm)) + "2022-01-01" "2022-01-21" "2022-02-01")) + (testing "`false`," + (testing "kun opiskeluoikeus on `nil`." + (are [pvm] (not (nh/jakso-active? jakso-1 nil (LocalDate/parse pvm))) + "2022-01-03" "2022-02-19" "2022-03-04" "2022-04-07" "2022-02-10")) + (testing "kun päivämäärä" + (testing "sisältyy keskeytymisajanjaksoon." + (are [pvm] (not (nh/jakso-active? jakso-1 + opiskeluoikeus-1 + (LocalDate/parse pvm))) + "2022-02-20" "2022-03-01" "2022-03-03" "2022-04-08" "2022-05-04") + (are [pvm] (not (nh/jakso-active? jakso-2 + opiskeluoikeus-2 + (LocalDate/parse pvm))) + "2022-02-02" "2022-03-21" "2023-01-01")) + (testing "ei ole jakson alku- ja loppupäivämäärien välillä." + (are [pvm] (not (nh/jakso-active? jakso-1 + opiskeluoikeus-1 + (LocalDate/parse pvm))) + "2022-01-02" "2022-05-06" "2021-12-30" "2023-01-01") + (are [pvm] (not (nh/jakso-active? jakso-2 + opiskeluoikeus-1 + (LocalDate/parse pvm))) + "2021-12-31" "2021-03-21" "2019-01-01"))))))) + +(deftest test-osa-aikaisuuskerroin + (with-redefs [clojure.tools.logging/log* tu/mock-log*] + (testing (str "Jos osa-aikaisuustieto puuttuu jakson tiedosta, tulkitaan " + "jakson osa-aikaisuudeksi 0 %.") + (is (= (nh/osa-aikaisuuskerroin {:hankkimistapa_id 123}) 0)) + (is (tu/logs-contain? + {:level :error + :message (str "Osa-aikaisuustieto puuttuu jakson 123 tiedoista. " + "Jakson kestoksi asetetaan nolla.")}))) + (testing (str "Osa-aikaisuustiedon ollessa ei-validi, osa-aikaisuuden " + "katsotaan olevan 0 %.") + (are [oa] (true? (and (= (nh/osa-aikaisuuskerroin {:hankkimistapa_id 123 + :osa_aikaisuus oa}) + 0) + (tu/logs-contain? + {:level :error + :message (str "Jakson 123 osa-aikaisuus `" oa + "` ei ole validi. Jakson kestoksi " + "asetetaan nolla.")}))) + -1 0 120 5.5 "100"))) + (testing (str "Osa-aikaisuustiedon ollessa validi, funktio hakee " + "osa-aikaisuustiedon jaksosta ja palauttaa tämän " + "perusteella lasketun osa-aikaisuuskertoimen.") + (are [oa] (= (nh/osa-aikaisuuskerroin {:osa_aikaisuus oa}) + (/ oa 100.0)) + 1 15 50 98 100))) + +(deftest test-keskeytymisajanjaksot + (testing + (str "Funktio ei palauta yhtään keskeytymisajanjaksoa, kun parametreiksi " + "ei ole annettu yhtään jaksoa eikä opiskeluoikeutta.") + (is (= (nh/keskeytymisajanjaksot {} {}) '()))) + (testing + (str "Funktio ei palauta yhtään keskeytymisajanjaksoa, kun jakson eikä " + "opiskeluoikeuden tietoihin ole merkitty keskeytymisajanjaksoja.") + (is (= (nh/keskeytymisajanjaksot + jakso-4 {mock-get-opiskeluoikeus-catch-404 "1.2.3.8"}) + '()))) + (let [jakso-kjaksot [{:alku "2022-01-12" :loppu "2022-01-12"} + {:alku "2022-01-16" :loppu "2022-01-18"}] + opiskeluoikeus (mock-get-opiskeluoikeus-catch-404 "1.2.3.5") + oo-kjaksot (map c/alku-and-loppu-to-localdate + [{:alku "2022-02-02" + :tila {:koodiarvo "valiaikaisestikeskeytynyt"}}])] + (testing + (str "Keskeytymisajanjakso jaksossa, muttei opiskeluoikeudessa. Funktio " + "palauttaa pelkästään jakson keskeytymisajanjaksot.") + (is (= (nh/keskeytymisajanjaksot + {:keskeytymisajanjaksot jakso-kjaksot} {}) + (map nh/harmonize-alku-and-loppu-dates jakso-kjaksot)))) + (testing + (str "Keskeytymisajanjakso opiskeluoikeudessa, muttei jaksossa. Funktio " + "palauttaa pelkästään opiskeluoikeuden keskeytymisajanjaksot.") + (is (= (nh/keskeytymisajanjaksot {} opiskeluoikeus) oo-kjaksot))) + (testing + (str "Keskeytymisajanjaksoja sekä jaksossa että tämän " + "opiskeluoikeudessa. Funktio palauttaa molempien kjaksot.") + (is (= (nh/keskeytymisajanjaksot jakso-25 opiskeluoikeus) + (concat (map nh/harmonize-alku-and-loppu-dates jakso-kjaksot) + oo-kjaksot)))))) + +(deftest test-oppijan-jaksojen-yhden-paivan-kestot + (testing + (str "Yhden päivän kesto jaetaan tasaisesti aktiivisena oleville " + "jaksoille. Jos yksikään jaksoista ei ole aktiivinen, palautuu " + "tyhjä taulu.") + (are [y m d jaksot kestot] + (let [oos (map :opiskeluoikeus_oid jaksot)] + (= (do-rounding + (nh/oppijan-jaksojen-yhden-paivan-kestot + (map nh/harmonize-alku-and-loppu-dates jaksot) + (zipmap oos (map mock-get-opiskeluoikeus-catch-404 oos)) + (LocalDate/of y m d))) + kestot)) + 2021 10 13 [jakso-3] {} ; keskeytynyt (jakso) + 2021 10 14 [jakso-6] {} ; keskeytynyt (jakso) + 2021 10 14 [jakso-10] {} ; keskeytynyt (jakso) + 2022 2 2 [jakso-25] {} ; keskeytynyt (opiskeluoikeus) + 2021 10 12 [jakso-3] {3 1.0} + 2021 7 31 [jakso-9] {9 1.0} + 2021 10 13 [jakso-3 jakso-4] {4 1.0} ; 3 keskeytynyt + 2021 10 12 [jakso-3 jakso-4] {3 0.5 4 0.5} + ; 2 keskeytynyt, 3 päättynyt: + 2021 10 25 [jakso-1 jakso-2 jakso-3 jakso-4] {1 0.5 4 0.5} + ; 1 ei vielä alkanut: + 2021 10 21 [jakso-1 jakso-2 jakso-3 jakso-4] {2 0.33 3 0.33 4 0.33} + ; 1 ei vielä alkanut, 11 ei vielä alkanut: + 2021 9 1 + [jakso-1 jakso-5 jakso-10 jakso-11 jakso-14] + {5 0.33 10 0.33 14 0.33} + ; 1 ei vielä alkanut + 2021 9 9 + [jakso-1 jakso-5 jakso-10 jakso-11 jakso-14] + {5 0.25 10 0.25 11 0.25 14 0.25} + ; 10 päättynyt, 11 päättynyt + 2021 10 22 + [jakso-1 jakso-5 jakso-10 jakso-11 jakso-14] + {1 0.33 5 0.33 14 0.33}))) + +(deftest test-oppijan-jaksojen-kestot + (testing (str "Funktio palauttaa `nil`, jos jaksot sisältävässä HashMapissa " + "ei ole jaksoja.") + (is (= (nh/oppijan-jaksojen-kestot {} {:voi-sisaltaa-mita-tahansa nil}) + nil))) + (testing (str "Funktio antaa jakson kestoksi nollan, mikäli " + "osa-aikaisuustieto puuttuu tai ei ole validi.") + (are [oa] (let [oo-oid (:opiskeluoikeus_oid jakso-2)] + (= (nh/oppijan-jaksojen-kestot + [(assoc jakso-2 :osa_aikaisuus oa)] + {oo-oid (get opiskeluoikeudet oo-oid)}) + {2 0})) + nil -1 0 101 55.5 "merkkijono" true false {})) + (testing (str "Funktio antaa jakson kestoksi nollan, mikäli jakson " + "opiskeluoikeus on `nil` tai sitä ei löydy " + "`opiskeluoikeudet` hashmapista.") + (are [opiskeluoikeudet] + (= (nh/oppijan-jaksojen-kestot [jakso-2] opiskeluoikeudet) {2 0}) + {} {"1.2.3.8" nil})) + (testing "Yhden jakson tapauksessa jakson kesto on jakson päivien + yhteenlaskettu lukumäärä (pois lukien keskeytymisajanjakson päivät) + kerrottuna osa-aikaisuuskertoimella" + (are [jakso expected-kesto] + (let [oo-oid (:opiskeluoikeus_oid jakso)] + (= (nh/oppijan-jaksojen-kestot + [jakso] {oo-oid (get opiskeluoikeudet oo-oid)}) + expected-kesto)) + jakso-1 {1 2} ; 4 päivää • 0.4 = 1.6 päivää ≈ 2 päivää + jakso-2 {2 78} ; (107 päivää - 9 k.jakson. päivää) • 0.8 = 78.4 päivää + ; ≈ 78 päivää + jakso-3 {3 9} ; (10 päivää - 1 k.jakson. päivää) • 1.0 = 9 päivää + jakso-6 {6 9})) ; (10 päivää - 1 k.jakson. päivää) • 1.0 = 9 päivää + (testing + "Useamman jakson tapauksessa kestot ovat pienempiä jyvityksen seurauksena." + (are [jaksot expected-kestot] + (= (nh/oppijan-jaksojen-kestot + jaksot + (select-keys opiskeluoikeudet (map :opiskeluoikeus_oid jaksot))) + expected-kestot) + [jakso-2 jakso-3] {2 74 3 5} + [jakso-2 jakso-4 jakso-8] {2 35 4 104 8 23} + [jakso-1 jakso-4 jakso-9 jakso-16] {1 1 4 109 9 28 16 119}))) + +(deftest test-jaksojen-kestot! + (with-redefs + [ehoks/get-tyoelamajaksot-active-between! + mock-get-tyoelamajaksot-active-between! + koski/get-opiskeluoikeus-catch-404! mock-get-opiskeluoikeus-catch-404] + (testing "Funktio laskee kestot oikein" + (are [jaksot kestot] (= (nh/jaksojen-kestot! jaksot) kestot) + [jakso-2] {2 12} + [jakso-9] {9 18} + [jakso-21] {21 16} + [jakso-1 jakso-4] {1 0 4 37} + [jakso-9 jakso-21] {9 18 21 16} + jaksot-1-25 {1 0, 2 12, 3 1, 4 37, 5 215, 6 1, 7 85, 8 9, 9 18, 10 4, + 11 4, 12 4, 13 5, 14 725, 15 2, 16 62, 17 0, 21 16, + 22 25, 23 0, 24 14, 25 13})) + (testing (str "Lopputulos on sama kuin kestot laskettaisiin kunkin oppijan " + "jaksoille erikseen. Ts. funktio erottelee eri oppijoiden " + "jaksot kestoja laskiessaan.") + (are [jaksot] (= (nh/jaksojen-kestot! jaksot) + (zipmap (map :hankkimistapa_id jaksot) + (map #(get (nh/jaksojen-kestot! [%]) + (:hankkimistapa_id %)) + jaksot))) + [jakso-9 jakso-23] + [jakso-3 jakso-6 jakso-15 jakso-22 jakso-23] + jaksot-1-17 + jaksot-21-25 + jaksot-1-25)) + (testing (str "Funktio palauttaa tyhjän listan, jos eHOKSista ei saada " + "`get-tyoelamajaksot-active-between!`-kutsulla.") + (with-redefs + [ehoks/get-tyoelamajaksot-active-between! (constantly {})] + (is (= (nh/jaksojen-kestot! jaksot-1-25) {})))) + (testing "Kestot ovat nollia, jos Koskesta ei saada opiskeluoikeuksia." + (with-redefs + [koski/get-opiskeluoikeus-catch-404! (constantly nil)] + (is (= (nh/jaksojen-kestot! jaksot-1-25) + (zipmap (map :hankkimistapa_id jaksot-1-25) (repeat 0)))))))) (deftest test-query-jaksot (testing "Varmistaa, että query-jaksot toimii oikein." @@ -482,7 +590,7 @@ "#tunnus" "tunnus"} :expr-attr-vals {":pvm" [:s "2022-03-03"]}} :table "table-name"}] - (is (= (nh/query-jaksot nippu) results)))))) + (is (= (nh/query-jaksot! nippu) results)))))) (def trauj-results (atom [])) @@ -493,10 +601,10 @@ (add-to-trauj-results {:type "query-jaksot" :nippu nippu}) [{:hankkimistapa_id 1} {:hankkimistapa_id 2} {:hankkimistapa_id 3}]) -(defn- mock-trauj-group-jaksot-and-compute-kestot [jaksot] - (add-to-trauj-results {:type "group-jaksot-and-compute-kestot" +(defn- mock-trauj-jaksojen-kestot [jaksot] + (add-to-trauj-results {:type "jaksojen-kestot!" :jaksot jaksot}) - {1 0.0 2 0.3 3 0.5}) + {1 1 2 3 3 5}) (defn- mock-trauj-update-jakso [jakso updates] (add-to-trauj-results {:type "update-jakso" :jakso jakso :updates updates})) @@ -504,29 +612,28 @@ (deftest test-retrieve-and-update-jaksot (testing "Varmistaa, että retrieve-and-update-jaksot toimii oikein." (with-redefs - [oph.heratepalvelu.tep.niputusHandler/group-jaksot-and-compute-kestot - mock-trauj-group-jaksot-and-compute-kestot - oph.heratepalvelu.tep.niputusHandler/query-jaksot mock-trauj-query-jaksot + [nh/jaksojen-kestot! mock-trauj-jaksojen-kestot + nh/query-jaksot! mock-trauj-query-jaksot oph.heratepalvelu.tep.tepCommon/update-jakso mock-trauj-update-jakso] (let [nippu {:mock-nippu-contents "asdf"} results [{:type "query-jaksot" :nippu {:mock-nippu-contents "asdf"}} - {:type "group-jaksot-and-compute-kestot" + {:type "jaksojen-kestot!" :jaksot [{:hankkimistapa_id 1} {:hankkimistapa_id 2} {:hankkimistapa_id 3}]} {:type "update-jakso" :jakso {:hankkimistapa_id 1} - :updates {:kesto [:n 0]}} + :updates {:kesto [:n 1]}} {:type "update-jakso" :jakso {:hankkimistapa_id 2} - :updates {:kesto [:n 0]}} + :updates {:kesto [:n 3]}} {:type "update-jakso" :jakso {:hankkimistapa_id 3} - :updates {:kesto [:n 1]}}] - updated-jaksot [{:hankkimistapa_id 1 :kesto 0} - {:hankkimistapa_id 2 :kesto 0} - {:hankkimistapa_id 3 :kesto 1}]] - (is (= (nh/retrieve-and-update-jaksot nippu) updated-jaksot)) + :updates {:kesto [:n 5]}}] + updated-jaksot [{:hankkimistapa_id 1 :kesto 1} + {:hankkimistapa_id 2 :kesto 3} + {:hankkimistapa_id 3 :kesto 5}]] + (is (= (nh/retrieve-and-update-jaksot! nippu) updated-jaksot)) (is (= @trauj-results results)))))) (def test-niputa-results (atom [])) @@ -573,11 +680,9 @@ oph.heratepalvelu.common/generate-uuid mock-generate-uuid oph.heratepalvelu.common/local-date-now (fn [] (LocalDate/of 2021 12 31)) oph.heratepalvelu.common/rand-str (fn [_] "abcdef") - oph.heratepalvelu.external.arvo/create-nippu-kyselylinkki - mock-create-nippu-kyselylinkki - oph.heratepalvelu.external.arvo/delete-nippukyselylinkki - mock-delete-nippukyselylinkki - oph.heratepalvelu.tep.niputusHandler/retrieve-and-update-jaksot + arvo/create-nippu-kyselylinkki mock-create-nippu-kyselylinkki + arvo/delete-nippukyselylinkki mock-delete-nippukyselylinkki + oph.heratepalvelu.tep.niputusHandler/retrieve-and-update-jaksot! mock-retrieve-and-update-jaksot oph.heratepalvelu.tep.tepCommon/update-nippu mock-update-nippu] (let [test-nippu-0 {:ohjaaja_ytunnus_kj_tutkinto "test-id-0" diff --git a/test/oph/heratepalvelu/util/date_test.clj b/test/oph/heratepalvelu/util/date_test.clj new file mode 100644 index 00000000..307bbe21 --- /dev/null +++ b/test/oph/heratepalvelu/util/date_test.clj @@ -0,0 +1,25 @@ +(ns oph.heratepalvelu.util.date-test + (:require + [clojure.test :refer [deftest is testing]] + [oph.heratepalvelu.util.date :as d]) + (:import java.time.LocalDate)) + +(def test-dates + (map #(apply (fn [^Integer y ^Integer m ^Integer d] + (LocalDate/of y m d)) %) + (partition 3 [2023 1 26 + 2023 1 27 + 2023 1 28 + 2023 1 29 + 2023 1 30 + 2023 1 31 + 2023 2 1 + 2023 2 2 + 2023 2 3 + 2023 2 4]))) + +(deftest test-range + (testing "`range` rakentaa onnistuneesti päivämääräsekvenssin, johon kuuluvat + sekä parametreina annetut alku- ja loppupäivämäärät." + (is (= (d/range (LocalDate/of 2023 1 26) (LocalDate/of 2023 2 04)) + test-dates))))