Skip to content

Commit

Permalink
Merge pull request #2824 from Opetushallitus/tor-1947-valpas-kunnalle…
Browse files Browse the repository at this point in the history
…-ilmoitetut-muutos

TOR-1947: Valpas: kunnalle ilmotetut- listaukselle jätetään tehdyt ilmoitukset
  • Loading branch information
ilkkahanninen authored Jan 2, 2024
2 parents dfe740d + 81d57fc commit 3a05eaf
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import fi.oph.koski.henkilo.LaajatOppijaHenkilöTiedot
import fi.oph.koski.http.HttpStatus
import fi.oph.koski.log.Logging
import fi.oph.koski.organisaatio.Organisaatiotyyppi
import fi.oph.koski.raportit.AhvenanmaanKunnat
import fi.oph.koski.schema._
import fi.oph.koski.util.Timing
import fi.oph.koski.valpas.opiskeluoikeusrepository.{ValpasOppijaLaajatTiedot, ValpasOppilaitos, ValpasOppivelvollinenOppijaLaajatTiedot}
import fi.oph.koski.valpas.oppija.{OppijaHakutilanteillaLaajatTiedot, ValpasAccessResolver, ValpasErrorCategory}
import fi.oph.koski.valpas.oppija.{OppijaHakutilanteillaLaajatTiedot, ValpasAccessResolver, ValpasErrorCategory, ValpasOppijaLaajatTiedotService}
import fi.oph.koski.valpas.valpasrepository._
import fi.oph.koski.valpas.valpasuser.{ValpasRooli, ValpasSession}
import fi.oph.koski.valpas.yhteystiedot.{ValpasYhteystiedot, ValpasYhteystietoHakemukselta, ValpasYhteystietoOppijanumerorekisteristä}
Expand Down Expand Up @@ -100,6 +99,11 @@ class ValpasKuntailmoitusService(
)(
implicit session: ValpasSession
) : Either[HttpStatus, Seq[OppijaHakutilanteillaLaajatTiedot]] = {
val laajennettuRooli = ValpasOppijaLaajatTiedotService
.roolitJoilleHaetaanKaikistaOVLPiirinOppijoista
.find(accessResolver.accessToAnyOrg)
.getOrElse(rooli)

repository.queryByTekijäOrganisaatio(oppilaitosOid)
.map(ilmoitukset => {
// Tietokannassa ei voi olla kuntailmoituksia ilman oppijaOid:ia, joten oppijaOid:n olemassaoloa ei tässä
Expand All @@ -108,21 +112,31 @@ class ValpasKuntailmoitusService(
val oppijat = opiskeluoikeusDbService
.getOppijat(oppijaOids, rajaaOVKelpoisiinOpiskeluoikeuksiin = true, haeMyösOppivelvollisuudestaVapautetut = false)
.flatMap(oppijaLaajatTiedotService.asValpasOppijaLaajatTiedot()(_).toOption)
val oppijatJoihinKatseluoikeus = accessResolver
.filterByOppijaAccess(rooli, Some(oppilaitosOid))(oppijat)
.map(OppijaHakutilanteillaLaajatTiedot.apply)
val oppijatLisätiedoilla = lisätiedotRepository.readForOppijat(oppijatJoihinKatseluoikeus)
.filter(_.onOikeusValvoaKunnalla)

val (oppijatJoihinKatseluoikeus, oppijatJoihinEiKatseluoikeutta) = accessResolver
.separateByOppijaAccess(laajennettuRooli, Some(oppilaitosOid))(oppijat)
val oppijatLisätiedoilla = lisätiedotRepository.readForOppijat(oppijatJoihinKatseluoikeus.map(OppijaHakutilanteillaLaajatTiedot.apply))
val oppijatLaajatTiedot = oppijatLisätiedoilla.map(oppijaLisätiedotTuple =>
oppijaLisätiedotTuple._1.withLisätiedot(oppijaLisätiedotTuple._2)
)

// Lisää kuntailmoitukset oppijan tietoihin
oppijatLaajatTiedot.map(oppija => oppija.copy(
val oppijatKuntailmoituksilla = oppijatLaajatTiedot.map(oppija => oppija.copy(
kuntailmoitukset = ilmoitukset
// Tietokannassa ei voi olla kuntailmoituksia ilman oppijaOid:ia, joten oppijaOid:n olemassaoloa ei tässä
// erikseen tarkisteta, vaan keskeytys ja sen seurauksena tuleva 500-virhe on ok, jos oppijaOid on None.
.filter(ilmoitus => oppija.oppija.henkilö.kaikkiOidit.contains(ilmoitus.oppijaOid.get))
))

// Lisää oppijoille, joita ei voi muuten katsella, kuntailmoitukset ja poista ylimääräiset detaljit
val eiKatseltavatOppijatKuntailmoituksilla = oppijatJoihinEiKatseluoikeutta
.map(OppijaHakutilanteillaLaajatTiedot.apply)
.map(oppija => oppija.withEiKatseltavanMinimitiedot.copy(
kuntailmoitukset = ilmoitukset.filter(ilmoitus => oppija.oppija.henkilö.kaikkiOidit.contains(ilmoitus.oppijaOid.get))
))

oppijatKuntailmoituksilla ++ eiKatseltavatOppijatKuntailmoituksilla
})
}

Expand Down Expand Up @@ -537,3 +551,9 @@ object ValpasKuntailmoitusService {
"tuntematon"
).contains(opiskeluoikeudenTila.koodiarvo)
}

case class IlmoitettuOppijaJohonEiEnääKatseluoikeuksia(
etunimet: String,
sukunimi: String,
kuntailmoitukset: Seq[ValpasKuntailmoitusLaajatTiedot],
)
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ trait ValpasOppijaLaajatTiedot extends ValpasOppija {
// Importtaa sopiva monoidi kirjastosta fi.oph.koski.util.Monoid käyttääksesi tätä versiota
def mapOppivelvollinen[A](fn: ValpasOppivelvollinenOppijaLaajatTiedot => A)(implicit monoid: Monoid[A]): A =
ifOppivelvollinenOtherwise(monoid.empty)(fn)

def withEiKatseltavanMinimitiedot: ValpasOppijaLaajatTiedot
}

object ValpasOppivelvollinenOppijaLaajatTiedot {
Expand Down Expand Up @@ -92,7 +94,14 @@ case class ValpasOppivelvollinenOppijaLaajatTiedot(
onOikeusValvoaMaksuttomuutta: Boolean,
onOikeusValvoaKunnalla: Boolean,
override val oppivelvollisuudestaVapautus: Option[OppivelvollisuudestaVapautus] = None,
) extends ValpasOppijaLaajatTiedot
) extends ValpasOppijaLaajatTiedot {
override def withEiKatseltavanMinimitiedot: ValpasOppivelvollinenOppijaLaajatTiedot = copy(
henkilö = henkilö.withEiKatseltavanMinimitiedot,
hakeutumisvalvovatOppilaitokset = Set.empty,
suorittamisvalvovatOppilaitokset = Set.empty,
opiskeluoikeudet = Seq.empty,
)
}

object ValpasOppivelvollisuudestaVapautettuLaajatTiedot {
def apply(tiedot: ValpasOppivelvollinenOppijaLaajatTiedot, vapautus: OppivelvollisuudestaVapautus): ValpasOppivelvollisuudestaVapautettuLaajatTiedot =
Expand All @@ -117,6 +126,9 @@ case class ValpasOppivelvollisuudestaVapautettuLaajatTiedot(
def opiskeluoikeudet: Seq[ValpasOpiskeluoikeusLaajatTiedot] = List.empty
def hakeutumisvalvovatOppilaitokset: Set[Oid] = Set.empty
def suorittamisvalvovatOppilaitokset: Set[ValpasOppilaitos.Oid] = Set.empty

override def withEiKatseltavanMinimitiedot: ValpasOppivelvollisuudestaVapautettuLaajatTiedot =
copy(henkilö = henkilö.withEiKatseltavanMinimitiedot)
}

object ValpasHenkilö {
Expand Down Expand Up @@ -161,7 +173,16 @@ case class ValpasHenkilöLaajatTiedot(
turvakielto: Boolean,
äidinkieli: Option[String],
onTallennettuKoskeen: Boolean = true
) extends ValpasHenkilö
) extends ValpasHenkilö {
def withEiKatseltavanMinimitiedot: ValpasHenkilöLaajatTiedot = copy(
oid = "",
kaikkiOidit = Set.empty,
hetu = None,
syntymäaika = None,
kotikunta = None,
äidinkieli = None,
)
}

object ValpasOpiskeluoikeus {
type Oid = String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ case class OppijaHakutilanteillaLaajatTiedot(
))
)
}

def withEiKatseltavanMinimitiedot: OppijaHakutilanteillaLaajatTiedot = copy(
oppija = oppija.withEiKatseltavanMinimitiedot,
hakutilanteet = Seq.empty,
hakutilanneError = None,
yhteystiedot = Seq.empty,
kuntailmoitukset = Seq.empty,
oppivelvollisuudenKeskeytykset = Seq.empty,
onOikeusTehdäKuntailmoitus = Some(false),
onOikeusMitätöidäOppivelvollisuudestaVapautus = Some(false),
lisätiedot = Seq.empty,
)
}

object OppijaHakutilanteillaLaajatTiedot {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ class ValpasAccessResolver {
}
}

def separateByOppijaAccess[T <: ValpasOppijaLaajatTiedot](
rooli: ValpasRooli.Role,
oppilaitosOid: Option[ValpasOppilaitos.Oid] = None
)(
oppijat: Seq[T]
)(
implicit session: ValpasSession
): (Seq[T], Seq[T]) = {
val oppijatWithAccess = filterByOppijaAccess(rooli, oppilaitosOid)(oppijat)
(oppijatWithAccess, oppijat.diff(oppijatWithAccess))
}

def withOppijaAccessAsOrganisaatio[T <: ValpasOppijaLaajatTiedot]
(rooli: ValpasRooli.Role, organisaatioOid: Organisaatio.Oid)
(oppija: T)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ import fi.oph.koski.valpas.valpasrepository._
import fi.oph.koski.valpas.valpasuser.{ValpasRooli, ValpasSession}
import fi.oph.koski.valpas.yhteystiedot.ValpasYhteystiedot

object ValpasOppijaLaajatTiedotService {
val roolitJoilleHaetaanKaikistaOVLPiirinOppijoista: Seq[ValpasRooli.Role] = Seq(
ValpasRooli.OPPILAITOS_MAKSUTTOMUUS,
ValpasRooli.KUNTA,
)
}

class ValpasOppijaLaajatTiedotService(
application: KoskiApplication
) extends Logging with Timing {
Expand All @@ -33,11 +40,6 @@ class ValpasOppijaLaajatTiedotService(

private val validatingAndResolvingExtractor = application.validatingAndResolvingExtractor

private val roolitJoilleHaetaanKaikistaOVLPiirinOppijoista: Seq[ValpasRooli.Role] = Seq(
ValpasRooli.OPPILAITOS_MAKSUTTOMUUS,
ValpasRooli.KUNTA,
)

def getOppijaLaajatTiedot
(
rooli: ValpasRooli.Role,
Expand All @@ -47,7 +49,7 @@ class ValpasOppijaLaajatTiedotService(
)
(implicit session: ValpasSession)
: Either[HttpStatus, ValpasOppijaLaajatTiedot] = {
val rajaaOVKelpoisiinOpiskeluoikeuksiin = !roolitJoilleHaetaanKaikistaOVLPiirinOppijoista.contains(rooli)
val rajaaOVKelpoisiinOpiskeluoikeuksiin = !ValpasOppijaLaajatTiedotService.roolitJoilleHaetaanKaikistaOVLPiirinOppijoista.contains(rooli)

opiskeluoikeusDbService.getOppija(oppijaOid, rajaaOVKelpoisiinOpiskeluoikeuksiin, haeMyösOppivelvollisuudestaVapautettu = true) match {
case Some(oppijaRow) =>
Expand Down Expand Up @@ -80,7 +82,7 @@ class ValpasOppijaLaajatTiedotService(
// rajaaOVKelposillaOppivelvollisuuksilla-lippu. Naiivimpi vaihtoehto olisi hakea kaikilla rooleilla ja tarkastaa mitkä kyselyt onnistuivat.
// Jos granulariteettia jatkossa kasvatetaan, tämä funktio pitää toteuttaa myös eri tavalla.

val laajimmatRoolit = roolit.intersect(roolitJoilleHaetaanKaikistaOVLPiirinOppijoista)
val laajimmatRoolit = roolit.intersect(ValpasOppijaLaajatTiedotService.roolitJoilleHaetaanKaikistaOVLPiirinOppijoista)
if (roolit.isEmpty) {
Left(ValpasErrorCategory.forbidden.oppija())
} else if (laajimmatRoolit.nonEmpty) {
Expand Down Expand Up @@ -128,7 +130,7 @@ class ValpasOppijaLaajatTiedotService(
accessResolver.accessToAnyOrg(ValpasRooli.OPPILAITOS_MAKSUTTOMUUS)
val palautaLukionAineopinnotJaYOTutkinnotJosMyösAmmatillisiaOpintoja = true

val rooli = roolitJoilleHaetaanKaikistaOVLPiirinOppijoista.find(accessResolver.accessToAnyOrg)
val rooli = ValpasOppijaLaajatTiedotService.roolitJoilleHaetaanKaikistaOVLPiirinOppijoista.find(accessResolver.accessToAnyOrg)

getOppijaLaajatTiedotHakuJaYhteystiedoilla(
oppijaOid,
Expand Down Expand Up @@ -334,6 +336,7 @@ class ValpasOppijaLaajatTiedotService(
// Tällä säännöllä napataan kiinni tilanteet, joissa Valppaan ja Kosken tiedot opiskeluoikeuden voimassaolosta eivät ole
// synkassa tai oppijasta on tehty ilmoitus, mutta oppijan eroamisen merkitseminen on jäänyt tekemättä
// ja sen takia olisi vaara että kuntailmoitus hautautuisi käyttöliittymässä.
// TODO TOR-1947: Tähän pitää varmaan lisätä extralogiikkaa pitämään keväällä tehdyt ilmoitukset aktiivisena 1.9. asti?
else if (!rajapäivätService.tarkastelupäivä.isAfter(ilmoituksentekopäivä.plusMonths(rajapäivätService.kuntailmoitusAktiivisuusKuukausina))) {
true
}
Expand Down
12 changes: 6 additions & 6 deletions valpas-web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,17 @@ const oppijanNimi = (
backRefName: keyof OppijaViewBackNavProps
): Value => {
const value = `${oppija.oppija.henkilö.sukunimi} ${oppija.oppija.henkilö.etunimet}`
const linkTo = oppijaPath.href(basePath, {
oppijaOid: oppija.oppija.henkilö.oid,
[backRefName]: organisaatioOid,
})
const linkTo =
oppija.oppija.henkilö.oid !== ""
? oppijaPath.href(basePath, {
oppijaOid: oppija.oppija.henkilö.oid,
[backRefName]: organisaatioOid,
})
: undefined

return {
value,
display: <Link to={linkTo}>{value}</Link>,
display: linkTo && <Link to={linkTo}>{value}</Link>,
}
}

Expand Down
37 changes: 37 additions & 0 deletions valpas-web/test/integrationtests/kuntailmoitus.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,47 @@
import { hakeutumisvalvonnanKunnalleIlmoitetutPathWithoutOrg } from "../../src/state/paths"
import { dataTableEventuallyEquals } from "../integrationtests-env/browser/datatable"
import { loginAs } from "../integrationtests-env/browser/reset"
import {
opo,
teeKuntailmoitusHakutilannenäkymästä,
} from "./kuntailmoitus.shared"

const ilmoitusPath =
hakeutumisvalvonnanKunnalleIlmoitetutPathWithoutOrg.href("/virkailija")

describe("Kuntailmoituksen tekeminen 1/7", () => {
it("happy path hakeutumisen valvojana", async () => {
await teeKuntailmoitusHakutilannenäkymästä("valpas-jkl-normaali", opo)
})

it("Kaikki hakeutumisvalvojana tehdyt ilmoitukset näytetään, vaikka oppijan tietoja ei enää olisikaan mahdollista tarkastella", async () => {
await loginAs(
ilmoitusPath,
"valpas-jkl-normaali-perus",
false,
"2021-12-05"
)

await dataTableEventuallyEquals(
".kuntailmoitukset",
`
Ilmoituksen-lisätiedot–poistettu Valpas | 19.5.2005 | 1.2.246.562.10.69417312936 | 5.12.2021 | –
Kahdella-oppija-oidilla-ilmo Valpas | – | Pyhtään kunta | 5.12.2021 | Ei
Kahdella-oppija-oidilla-ilmo-2 Valpas | – | Pyhtään kunta | 5.12.2021 | Ei
KahdenKoulunYsi-ilmo Valpas | – | Pyhtään kunta | 5.12.2021 | Ei
KasiinAstiToisessaKoulussaOllut-ilmo Valpas | 2.5.2005 | Pyhtään kunta | 5.12.2021 | Ei
LukionAloittanut-ilmo Valpas | – | Pyhtään kunta | 15.6.2021 | Ei
LukionAloittanutJaLopettanut-ilmo Valpas | – | Helsingin kaupunki | 30.11.2021 | Ei
LukionAloittanutJaLopettanut-ilmo Valpas | – | Pyhtään kunta | 20.9.2021 | Ei
LukionAloittanutJaLopettanut-ilmo Valpas | – | Helsingin kaupunki | 15.9.2021 | Ei
LukionAloittanutJaLopettanut-ilmo Valpas | – | Pyhtään kunta | 15.6.2021 | Ei
Oppivelvollisuus-keskeytetty-ei-opiskele Valpas | – | Pyhtään kunta | 20.5.2021 | Ei
Oppivelvollisuus-keskeytetty-ei-opiskele Valpas | – | Helsingin kaupunki | 19.5.2021 | Ei
Turvakielto Valpas | 29.9.2004 | Pyhtään kunta | 5.12.2021 | Ei
Ysiluokka-valmis-ja-ilmoitettu-ja-uusi-nivelvaihe Valpas | – | Pyhtään kunta | 27.6.2021 | Ei
Ysiluokka-valmis-keväällä-2021-ilmo Valpas | – | Pyhtään kunta | 5.12.2021 | Ei
`,
"|"
)
})
})
18 changes: 0 additions & 18 deletions valpas-web/test/integrationtests/suorittaminen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
reset,
resetMockData,
} from "../integrationtests-env/browser/reset"
import { sleep } from "../integrationtests-env/browser/utils"
import { hakutilannePath } from "../integrationtests/hakutilanne.shared"
import {
Oppija,
Expand Down Expand Up @@ -376,23 +375,6 @@ describe("Suorittamisen valvonta -näkymä", () => {
await expectElementEventuallyNotVisible(oppijaRowSelector)
})

it("Kuntailmoituksen näkyminen oppijasta, joka on eri oppilaitoksen suorittamisen valvottava ja käyttäjällä on riittävät oikeudet molempiin oppilaitoksiin", async () => {
// Ysiluokka-valmis-ja-ilmoitettu-ja-uusi-nivelvaihe Valpas (240706A3571)
const oppijaOid = "1.2.246.562.24.00000000166"
const oppijaRowSelector = `.table__row[data-row*="${oppijaOid}"]`

await reset(suorittaminenListaJklPath, true)
await loginAs(suorittaminenListaJklPath, "valpas-monta")
await waitTableLoadingHasFinished(".suorittaminen")
await sleep(500)
await expectElementEventuallyNotVisible(oppijaRowSelector)

await goToLocation(suorittaminenKuntailmoitusListaJklPath)
await waitTableLoadingHasFinished(".kuntailmoitukset")
await sleep(500)
await expectElementEventuallyNotVisible(oppijaRowSelector)
})

it("Suorittamisen valvonta ei näytä oppijaa, joka on valmistunut amiksesta, mutta on alle 18v", async () => {
// Amis-valmistunut-eronnut-valmasta Valpas (180605A313U) ei näy listalla
await loginAs(
Expand Down

0 comments on commit 3a05eaf

Please sign in to comment.