Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOR-2264 Skippaa validaatiot päätason suoritusta poistaessa #3256

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package fi.oph.koski.fixture

import fi.oph.koski.config.KoskiApplication
import fi.oph.koski.documentation.AmmatillinenExampleData.{ammatillinenTutkintoSuoritus, ammatillisetTutkinnonOsat, k3, pakollinenTutkinnonOsanSuoritus, puuteollisuudenPerustutkinnonSuoritus, puuteollisuudenPerustutkinto, stadinAmmattiopisto, stadinToimipiste, tietoJaViestintäTekniikanPerustutkinnonSuoritus}
import fi.oph.koski.documentation.ExampleData.{opiskeluoikeusMitätöity, suomenKieli}
import fi.oph.koski.documentation.ExampleData.{opiskeluoikeusLäsnä, opiskeluoikeusMitätöity, opiskeluoikeusValmistunut, suomenKieli}
import fi.oph.koski.documentation.ExamplesEsiopetus.{ostopalveluOpiskeluoikeus, peruskoulusuoritus, päiväkotisuoritus}
import fi.oph.koski.documentation.ExamplesPerusopetus.ysinOpiskeluoikeusKesken
import fi.oph.koski.documentation.VapaaSivistystyöExampleData.varsinaisSuomenKansanopisto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ object KoskiSpecificMockOppijat {
val vuonna2004SyntynytPeruskouluValmis2021EiKotikuntahistoriaa = koskiSpecificOppijat.oppija("Vuonna 2004 syntynyt (ei kotikuntahistoriaa)", "Peruskoulu suoritettu 2021", "010104A227T", syntymäaika = Some(LocalDate.of(2004, 1, 1)), kotikunta = Some("091"))
val vainMitätöityjäOpiskeluoikeuksia = koskiSpecificOppijat.oppija("Mitätön", "Minna", "010106A492V", syntymäaika = Some(LocalDate.of(2006, 1, 1)), kotikunta = Some("091"))
val lahdejarjestelmanPurku = koskiSpecificOppijat.oppija("Purettava", "Lasse", "010106A013D", syntymäaika = Some(LocalDate.of(2006, 1, 1)), kotikunta = Some("091"))
val rikkinäinenPerusopetus = koskiSpecificOppijat.oppija("Rikkinäinen", "Perusopetus", "311203A729Y", syntymäaika = Some(LocalDate.of(2003, 12, 31)))

//Jos luot uuden oppijan voi hetun generoida täältä: http://www.lintukoto.net/muut/henkilotunnus/index.php
//Huomaa, että hetun pitää olla oikean kaltainen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ class CompositeOpiskeluoikeusRepository(main: KoskiOpiskeluoikeusRepository, vir
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean = false,
skipValidations: Boolean = false,
)(
implicit user: KoskiSpecificSession
): Either[HttpStatus, CreateOrUpdateResult] =
withErrorLogging(() => main.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted))
withErrorLogging(() => main.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted, skipValidations))

def mapFailureToVirtaUnavailable(result: Try[Seq[Opiskeluoikeus]], oid: String): Try[WithWarnings[Seq[Opiskeluoikeus]]] = {
result match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ trait KoskiOpiskeluoikeusRepository {
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteComplete: Boolean = false,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): Either[HttpStatus, CreateOrUpdateResult]
def filterOppijat[A <: HenkilönTunnisteet](oppijat: List[A])(implicit user: KoskiSpecificSession): List[A]
def findByOppijaOids(oids: List[String])(implicit user: KoskiSpecificSession): Seq[Opiskeluoikeus]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ class PostgresKoskiOpiskeluoikeusRepository(
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean = false,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession): Either[HttpStatus, CreateOrUpdateResult] = {
actions.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted)
actions.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted, skipValidations)
}

def merkitseSuoritusjakoTehdyksiIlmanKäyttöoikeudenTarkastusta(oid: String): HttpStatus = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class PostgresKoskiOpiskeluoikeusRepositoryActions(
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional] = {
val identifier = OpiskeluoikeusIdentifier(oppijaOid.oppijaOid, opiskeluoikeus)

Expand All @@ -88,7 +89,7 @@ class PostgresKoskiOpiskeluoikeusRepositoryActions(
case Right(_) if !validationConfig.tarkastaOpiskeluoikeuksienDuplikaatit =>
createAction(oppijaOid, opiskeluoikeus)
case Right(aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet) if allowUpdate =>
updateIfUnambiguousAiempiOpiskeluoikeusAction(oppijaOid, opiskeluoikeus, identifier, aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet, allowDeleteCompleted)
updateIfUnambiguousAiempiOpiskeluoikeusAction(oppijaOid, opiskeluoikeus, identifier, aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet, allowDeleteCompleted, skipValidations)
case Right(aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet) if vastaavanRinnakkaisenOpiskeluoikeudenLisääminenSallittu(opiskeluoikeus, aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet) =>
createAction(oppijaOid, opiskeluoikeus)
case Right(_) =>
Expand All @@ -103,15 +104,16 @@ class PostgresKoskiOpiskeluoikeusRepositoryActions(
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
identifier: OpiskeluoikeusIdentifier,
aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet: List[KoskiOpiskeluoikeusRow],
allowDeleteCompleted: Boolean
allowDeleteCompleted: Boolean,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional] = {
(identifier, aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet) match {
case (id: OppijaOidOrganisaatioJaTyyppi, _) =>
DBIOAction.successful(Left(KoskiErrorCategory.conflict.exists("" +
s"Olemassaolevan opiskeluoikeuden päivitystä ilman tunnistetta ei tueta. Päivitettävä opiskeluoikeus-oid: ${aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet.map(_.oid).mkString(", ")}. Päivittävä tunniste: ${id.copy(oppijaOid = "****")}"
)))
case (_, List(aiempiSamaksiJonkinIdnPerusteellaTunnistettuOpiskeluoikeus)) =>
updateIfSameOppijaAction(oppijaOid, aiempiSamaksiJonkinIdnPerusteellaTunnistettuOpiskeluoikeus, opiskeluoikeus, allowDeleteCompleted)
updateIfSameOppijaAction(oppijaOid, aiempiSamaksiJonkinIdnPerusteellaTunnistettuOpiskeluoikeus, opiskeluoikeus, allowDeleteCompleted, skipValidations)
case _ =>
DBIO.successful(Left(KoskiErrorCategory.conflict.löytyiEnemmänKuinYksiRivi(s"Löytyi enemmän kuin yksi rivi päivitettäväksi (${aiemmatSamaksiJonkinIdnPerusteellaTunnistetutOpiskeluoikeudet.map(_.oid)})")))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ trait PostgresOpiskeluoikeusRepositoryActions[OOROW <: OpiskeluoikeusRow, OOTABL
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): Either[HttpStatus, CreateOrUpdateResult] = {
def createOrUpdateWithRetry: Either[HttpStatus, CreateOrUpdateResult] = {
val result = try {
runDbSync {
(for {
result <- createOrUpdateAction(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted)
result <- createOrUpdateAction(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted, skipValidations)
syncAction <- syncAction(oppijaOid, opiskeluoikeus, result)
} yield result).transactionally
}
Expand Down Expand Up @@ -115,6 +116,7 @@ trait PostgresOpiskeluoikeusRepositoryActions[OOROW <: OpiskeluoikeusRow, OOTABL
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean = false,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession): dbio.DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional]

protected def findByIdentifierAction(identifier: OpiskeluoikeusIdentifier)(implicit user: KoskiSpecificSession): dbio.DBIOAction[Either[HttpStatus, List[OOROW]], NoStream, Read] = {
Expand Down Expand Up @@ -203,10 +205,11 @@ trait PostgresOpiskeluoikeusRepositoryActions[OOROW <: OpiskeluoikeusRow, OOTABL
oppijaOid: PossiblyUnverifiedHenkilöOid,
oldRow: OOROW,
uusiOpiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowDeleteCompletedSuoritukset: Boolean
allowDeleteCompletedSuoritukset: Boolean,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional] = {
if (oppijaOid.oppijaOid == oldRow.oppijaOid) {
updateAction(oldRow, uusiOpiskeluoikeus, allowDeleteCompletedSuoritukset)
updateAction(oldRow, uusiOpiskeluoikeus, allowDeleteCompletedSuoritukset, skipValidations)
} else { // Check if oppija oid belongs to master of slave oppija oids
oppijaOidsByOppijaOid(oldRow.oppijaOid).flatMap { oids =>
if (oids.contains(oppijaOid.oppijaOid)) {
Expand All @@ -221,7 +224,8 @@ trait PostgresOpiskeluoikeusRepositoryActions[OOROW <: OpiskeluoikeusRow, OOTABL
private def updateAction[A <: PäätasonSuoritus](
oldRow: OOROW,
uusiOpiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowDeleteCompletedSuoritukset: Boolean
allowDeleteCompletedSuoritukset: Boolean,
skipValidations: Boolean = false
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Write with Transactional with Read] = {
val (id, oid, versionumero) = (oldRow.id, oldRow.oid, oldRow.versionumero)
val nextVersionumero = versionumero + 1
Expand All @@ -239,7 +243,7 @@ trait PostgresOpiskeluoikeusRepositoryActions[OOROW <: OpiskeluoikeusRow, OOTABL
val onVstOsaamismerkinSuoritus = tallennettavaOpiskeluoikeus.suoritukset.exists(_.tyyppi.koodiarvo == "vstosaamismerkki")
val onMitätöitävissä = OpiskeluoikeusAccessChecker.isInvalidatable(tallennettavaOpiskeluoikeus, user)

val ohitaValidaatiovirheeet = config.getStringList("validaatiot.ohitaValidaatiovirheetKäyttäjällä").contains(user.user.username)
val ohitaValidaatiovirheeet = config.getStringList("validaatiot.ohitaValidaatiovirheetKäyttäjällä").contains(user.user.username) || skipValidations

validator.validateOpiskeluoikeusChange(vanhaOpiskeluoikeus, tallennettavaOpiskeluoikeus) match {
case HttpStatus.ok if tallennettavaOpiskeluoikeus.mitätöity && onTaiteenPerusopetusOpiskeluoikeus && !onMitätöitävissä =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class PostgresYtrOpiskeluoikeusRepositoryActions(
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional] = {
val identifier = OpiskeluoikeusIdentifier(oppijaOid.oppijaOid, opiskeluoikeus)

Expand All @@ -56,7 +57,7 @@ class PostgresYtrOpiskeluoikeusRepositoryActions(
case Right(Nil) =>
createAction(oppijaOid, opiskeluoikeus)
case Right(aiemmatOpiskeluoikeudet) if allowUpdate =>
updateIfUnambiguousAiempiOpiskeluoikeusAction(oppijaOid, opiskeluoikeus, aiemmatOpiskeluoikeudet, allowDeleteCompleted)
updateIfUnambiguousAiempiOpiskeluoikeusAction(oppijaOid, opiskeluoikeus, aiemmatOpiskeluoikeudet, allowDeleteCompleted, skipValidations)
case Right(_) =>
DBIO.successful(Left(KoskiErrorCategory.conflict.exists())) // Ei tehdä uutta, koska vastaava vanha YO-opiskeluoikeus on olemassa
case Left(err) =>
Expand All @@ -68,11 +69,12 @@ class PostgresYtrOpiskeluoikeusRepositoryActions(
oppijaOid: PossiblyUnverifiedHenkilöOid,
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
aiemmatOpiskeluoikeudet: List[YtrOpiskeluoikeusRow],
allowDeleteCompleted: Boolean
allowDeleteCompleted: Boolean,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession): DBIOAction[Either[HttpStatus, CreateOrUpdateResult], NoStream, Read with Write with Transactional] = {
aiemmatOpiskeluoikeudet match {
case List(vanhaOpiskeluoikeus) =>
updateIfSameOppijaAction(oppijaOid, vanhaOpiskeluoikeus, opiskeluoikeus, allowDeleteCompleted)
updateIfSameOppijaAction(oppijaOid, vanhaOpiskeluoikeus, opiskeluoikeus, allowDeleteCompleted, skipValidations)
case _ =>
DBIO.successful(Left(KoskiErrorCategory.conflict.löytyiEnemmänKuinYksiRivi(s"Löytyi enemmän kuin yksi rivi päivitettäväksi (${aiemmatOpiskeluoikeudet.map(_.oid)})")))
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/scala/fi/oph/koski/oppija/KoskiOppijaFacade.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class KoskiOppijaFacade(
allowUpdate: Boolean,
allowDeleteCompleted: Boolean = false,
skipGlobaaliValidation: Boolean = false,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession): Either[HttpStatus, HenkilönOpiskeluoikeusVersiot] = {
val timedBlockname = s"createOrUpdate ${oppija.opiskeluoikeudet.map(_.tyyppi.koodiarvo).mkString(",")}"
timed(timedBlockname) {
Expand Down Expand Up @@ -221,7 +222,7 @@ class KoskiOppijaFacade(
Left(KoskiErrorCategory.forbidden.omienTietojenMuokkaus())
} else {
val opiskeluoikeusCreationResults: Seq[Either[HttpStatus, OpiskeluoikeusVersio]] = opiskeluoikeudet.map { opiskeluoikeus =>
createOrUpdateOpiskeluoikeus(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted)
createOrUpdateOpiskeluoikeus(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted, skipValidations)
}

opiskeluoikeusCreationResults.find(_.isLeft) match {
Expand Down Expand Up @@ -272,14 +273,15 @@ class KoskiOppijaFacade(
invalidate(
opiskeluoikeusOid,
cancelPäätasonSuoritus(opiskeluoikeusOid, päätasonSuoritus, versionumero),
oppija => createOrUpdate(oppija, allowUpdate = true, allowDeleteCompleted = true, skipGlobaaliValidation = true)
oppija => createOrUpdate(oppija, allowUpdate = true, allowDeleteCompleted = true, skipGlobaaliValidation = true, skipValidations = true)
)

private def createOrUpdateOpiskeluoikeus(
oppijaOid: PossiblyUnverifiedHenkilöOid,
opiskeluoikeus: KoskeenTallennettavaOpiskeluoikeus,
allowUpdate: Boolean,
allowDeleteCompleted: Boolean = false
allowDeleteCompleted: Boolean = false,
skipValidations: Boolean = false,
)(implicit user: KoskiSpecificSession)
: Either[HttpStatus, OpiskeluoikeusVersio] = {
if (oppijaOid.oppijaOid == user.oid) {
Expand All @@ -289,7 +291,7 @@ class KoskiOppijaFacade(
case ytrOo: YlioppilastutkinnonOpiskeluoikeus =>
ytrDownloadedOpiskeluoikeusRepository.createOrUpdate(oppijaOid, ytrOo)
case _ =>
opiskeluoikeusRepository.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted)
opiskeluoikeusRepository.createOrUpdate(oppijaOid, opiskeluoikeus, allowUpdate, allowDeleteCompleted, skipValidations)
}
result.right.map { (result: CreateOrUpdateResult) =>
applicationLog(oppijaOid, opiskeluoikeus, result)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package fi.oph.koski.api.misc

import fi.oph.koski.KoskiHttpSpec
import fi.oph.koski.documentation.ExampleData.{opiskeluoikeusLäsnä, opiskeluoikeusValmistunut}
import fi.oph.koski.documentation.PerusopetusExampleData
import fi.oph.koski.henkilo.KoskiSpecificMockOppijat
import fi.oph.koski.http.{ErrorMatcher, KoskiErrorCategory}
import fi.oph.koski.schema.{PerusopetuksenOpiskeluoikeus, PerusopetuksenVuosiluokanSuoritus}
import fi.oph.koski.schema.{NuortenPerusopetuksenOpiskeluoikeudenTila, NuortenPerusopetuksenOpiskeluoikeusjakso, PerusopetuksenOpiskeluoikeus, PerusopetuksenVuosiluokanSuoritus}
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.should.Matchers

class PaatasonSuoritusInvalidateSpec extends AnyFreeSpec with Matchers with KoskiHttpSpec with PaatasonSuoritusTestMethods {
import java.time.LocalDate.{of => date}

class PaatasonSuoritusInvalidateSpec extends AnyFreeSpec with Matchers with KoskiHttpSpec with PaatasonSuoritusTestMethods with OpiskeluoikeusTestMethodsPerusopetus {

"Päätason suorituksen poistaminen" - {
"onnistuu" - {
Expand Down Expand Up @@ -93,6 +97,36 @@ class PaatasonSuoritusInvalidateSpec extends AnyFreeSpec with Matchers with Kosk
.filter(_.luokka == "8C")
assert(jäljelläOlevaVuosiluokanSuoritus.length == 1)
}

"kun opiskeluoikeus on rikkinäinen" in {

defaultKoskiApplication.validationContext.runWithoutValidations {
createOrUpdate(KoskiSpecificMockOppijat.rikkinäinenPerusopetus, PerusopetusExampleData.päättötodistusOpiskeluoikeus()
.withTila(NuortenPerusopetuksenOpiskeluoikeudenTila(
List(NuortenPerusopetuksenOpiskeluoikeusjakso(date(2016, 6, 1), opiskeluoikeusLäsnä)) ++ Some(date(2016, 6, 4)).toList.map(päivä => NuortenPerusopetuksenOpiskeluoikeusjakso(päivä, opiskeluoikeusValmistunut)))))
}


val oo = oppija(KoskiSpecificMockOppijat.rikkinäinenPerusopetus.oid).tallennettavatOpiskeluoikeudet.find(_.tyyppi.koodiarvo == "perusopetus").get
val suoritus = oo.suoritukset
.collect { case s: PerusopetuksenVuosiluokanSuoritus => s }
.find(_.luokka == "9C")
.get

deletePäätasonSuoritus(oo.oid.get, 1, suoritus) {
verifyResponseStatusOk()
}

val updated = getOpiskeluoikeus(KoskiSpecificMockOppijat.rikkinäinenPerusopetus.oid, "perusopetus")

val poistettuVuosiluokanSuoritus = updated.suoritukset
.collect { case s: PerusopetuksenVuosiluokanSuoritus => s }
.filter(_.luokka == "9C")

poistettuVuosiluokanSuoritus shouldBe empty

updated.suoritukset.length should equal(3)
}
}

"epäonnistuu" - {
Expand Down
Loading