Skip to content

Commit

Permalink
Merge pull request #9 from Opetushallitus/OK-754-koulutustoimija-oppi…
Browse files Browse the repository at this point in the history
…laitos-toimipiste

Ok 754 koulutustoimija oppilaitos toimipiste
  • Loading branch information
heidilm authored Jan 23, 2025
2 parents 7ec025f + cf1bb55 commit 84504c4
Show file tree
Hide file tree
Showing 40 changed files with 4,884 additions and 383 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sealed trait Kieli extends EnumType with Product with Serializable

object Kieli extends Enum[Kieli] {
override def name: String = "kieli"
def values = List(Fi, Sv, En)
def values: List[Kieli] = List(Fi, Sv, En)
}

case object Fi extends Kieli { val name = "fi" }
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package fi.oph.ovara.backend.domain

sealed trait KoulutusToteutusHakukohde {
val hakukohdeNimi: Kielistetty
val hakukohdeOid: String
val koulutuksenTila: Option[String]
val toteutuksenTila: Option[String]
val hakukohteenTila: Option[String]
val aloituspaikat: Option[Int]
val onValintakoe: Option[Boolean]
val voiSuorittaaKaksoistutkinnon: Option[Boolean]
val jarjestaaUrheilijanAmmKoulutusta: Option[Boolean]
}

case class KoulutusToteutusHakukohdeResult(
hakukohdeNimi: Kielistetty,
hakukohdeOid: String,
koulutuksenTila: Option[String] = None,
toteutuksenTila: Option[String] = None,
hakukohteenTila: Option[String] = None,
aloituspaikat: Option[Int] = None,
onValintakoe: Option[Boolean] = None,
voiSuorittaaKaksoistutkinnon: Option[Boolean] = None,
jarjestaaUrheilijanAmmKoulutusta: Option[Boolean] = None
) extends KoulutusToteutusHakukohde

case class OrganisaationKoulutusToteutusHakukohde(
organisaatio_oid: Option[String],
koulutusToteutusHakukohde: KoulutusToteutusHakukohdeResult
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package fi.oph.ovara.backend.domain

case class Organisaatio(organisaatio_oid: String, organisaatio_nimi: Kielistetty, organisaatiotyypit: List[String])

case class OrganisaatioParentChild(parent_oid: String, child_oid: String, organisaatio: Organisaatio)

case class OrganisaatioHierarkia(
organisaatio_oid: String,
organisaatio_nimi: Kielistetty,
organisaatiotyypit: List[String],
oppilaitostyyppi: Option[String] = None,
tila: String,
parent_oids: List[String],
koulutustoimijaParent: Option[Organisaatio] = None,
children: List[OrganisaatioHierarkia]
)

case class OrganisaatioHierarkiaWithHakukohteet(
organisaatio_oid: String,
organisaatio_nimi: Kielistetty,
organisaatiotyypit: List[String],
parent_oids: List[String],
koulutustoimijaParent: Option[Organisaatio] = None,
children: List[OrganisaatioHierarkiaWithHakukohteet] = List(),
hakukohteet: List[OrganisaationKoulutusToteutusHakukohde]
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ package object domain {
"24", // Lukiokoulutus
"21", // Yhteishaun ulkopuolinen lukiokoulutus
)

val KOULUTUSTOIMIJAORGANISAATIOTYYPPI = "01"
val OPPILAITOSORGANISAATIOTYYPPI = "02"
val TOIMIPISTEORGANISAATIOTYYPPI = "03"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ package fi.oph.ovara.backend.raportointi

import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper, SerializationFeature}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import fi.oph.ovara.backend.domain.{User, UserResponse}
import fi.oph.ovara.backend.service.{CommonService, KoulutuksetToteutuksetHakukohteetService, OnrService}
import fi.oph.ovara.backend.utils.AuthoritiesUtil
import fi.oph.ovara.backend.domain.UserResponse
import fi.oph.ovara.backend.service.{CommonService, KoulutuksetToteutuksetHakukohteetService, UserService}
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.{Logger, LoggerFactory}
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.{HttpHeaders, MediaType}
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.http.HttpHeaders
import org.springframework.security.web.csrf.CsrfToken
import org.springframework.web.bind.annotation.{GetMapping, RequestMapping, RequestParam, RestController}
import org.springframework.web.servlet.view.RedirectView
Expand All @@ -23,9 +19,9 @@ import scala.jdk.CollectionConverters.*
@RestController
@RequestMapping(path = Array("api"))
class Controller(
onrService: OnrService,
commonService: CommonService,
koulutuksetToteutuksetHakukohteetService: KoulutuksetToteutuksetHakukohteetService
koulutuksetToteutuksetHakukohteetService: KoulutuksetToteutuksetHakukohteetService,
userService: UserService
) {
val LOG: Logger = LoggerFactory.getLogger(classOf[Controller]);

Expand All @@ -41,22 +37,15 @@ class Controller(
def healthcheck = "Ovara application is running!"

@GetMapping(path = Array("user"))
def user(@AuthenticationPrincipal userDetails: UserDetails): String = {
def user(): String = {
val enrichedUserDetails = userService.getEnrichedUserDetails
mapper.writeValueAsString(
UserResponse(
user =
if (userDetails == null)
if (enrichedUserDetails == null)
null
else
val asiointikieli = onrService.getAsiointikieli(userDetails.getUsername) match
case Left(e) => None
case Right(v) => Some(v)

User(
userOid = userDetails.getUsername,
authorities = AuthoritiesUtil.getRaportointiAuthorities(userDetails.getAuthorities),
asiointikieli = asiointikieli
)
enrichedUserDetails
)
)
}
Expand All @@ -73,24 +62,40 @@ class Controller(
@GetMapping(path = Array("haut"))
def haut: String = mapper.writeValueAsString(commonService.getHaut)

@GetMapping(path = Array("organisaatiot"))
def organisaatiot: String = mapper.writeValueAsString(commonService.getOrganisaatioHierarkiatWithUserRights)

// RAPORTIT

@GetMapping(path = Array("koulutukset-toteutukset-hakukohteet"))
def koulutukset_toteutukset_hakukohteet(
@RequestParam("alkamiskausi") alkamiskausi: java.util.Collection[String],
@RequestParam("haku") haku: java.util.Collection[String],
@RequestParam("koulutuksenTila", required = false) koulutuksenTila: String,
@RequestParam("toteutuksenTila", required = false) toteutuksenTila: String,
@RequestParam("hakukohteenTila", required = false) hakukohteenTila: String,
@RequestParam("valintakoe", required = false) valintakoe: Boolean,
@RequestParam("koulutustoimija", required = false) koulutustoimija: String,
@RequestParam("oppilaitos", required = false) oppilaitos: java.util.Collection[String],
@RequestParam("toimipiste", required = false) toimipiste: java.util.Collection[String],
@RequestParam("koulutuksen-tila", required = false) koulutuksenTila: String,
@RequestParam("toteutuksen-tila", required = false) toteutuksenTila: String,
@RequestParam("hakukohteen-tila", required = false) hakukohteenTila: String,
@RequestParam("valintakoe", required = false) valintakoe: String,
response: HttpServletResponse
): Unit = {
val maybeKoulutustoimija = Option(koulutustoimija)
val maybeKoulutuksenTila = Option(koulutuksenTila)
val maybeToteutuksenTila = Option(toteutuksenTila)
val maybeHakukohteenTila = Option(hakukohteenTila)
val maybeValintakoe = Option(valintakoe)
val wb = koulutuksetToteutuksetHakukohteetService.
get(
val maybeValintakoe = if (valintakoe == null) {
None
} else {
Option(valintakoe.toBoolean)
}

val wb = koulutuksetToteutuksetHakukohteetService.get(
alkamiskausi.asScala.toList,
haku.asScala.toList,
maybeKoulutustoimija,
if (oppilaitos == null) List() else oppilaitos.asScala.toList,
if (toimipiste == null) List() else toimipiste.asScala.toList,
maybeKoulutuksenTila,
maybeToteutuksenTila,
maybeHakukohteenTila,
Expand All @@ -99,10 +104,13 @@ class Controller(
try {
LOG.info(s"Sending excel in the response")
val date: LocalDateTime = LocalDateTime.now().withNano(0)
val dateTimeStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val out = response.getOutputStream
val dateTimeStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val out = response.getOutputStream
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, s"attachment; filename=\"koulutukset-toteutukset-hakukohteet-$dateTimeStr.xlsx\"")
response.setHeader(
HttpHeaders.CONTENT_DISPOSITION,
s"attachment; filename=\"koulutukset-toteutukset-hakukohteet-$dateTimeStr.xlsx\""
)
wb.write(out)
out.close()
wb.close()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package fi.oph.ovara.backend.raportointi

import io.swagger.v3.oas.models.{Components, OpenAPI}
import io.swagger.v3.oas.models.info.Info
import io.swagger.v3.oas.models.{Components, OpenAPI}
import org.springdoc.core.models.GroupedOpenApi
import org.springframework.context.annotation.{Bean, Configuration}

Expand All @@ -10,7 +10,8 @@ class SwaggerConfig {

@Bean
def publicApi(): GroupedOpenApi = {
GroupedOpenApi.builder()
GroupedOpenApi
.builder()
.group("ovara-apis")
.pathsToMatch("/**")
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,110 @@
package fi.oph.ovara.backend.repository

import fi.oph.ovara.backend.domain.{Haku, Kieli, Kielistetty, ammatillisetHakukohdekoodit}
import fi.oph.ovara.backend.domain.*
import org.springframework.stereotype.Component
import slick.jdbc.PostgresProfile.api.*
import slick.sql.SqlStreamingAction

@Component
class CommonRepository extends Extractors {
def selectDistinctAlkamisvuodet(): SqlStreamingAction[Vector[String], String, Effect] = {
sql"""select distinct koulutuksen_alkamisvuosi
from pub.pub_dim_toteutus pdt
where koulutuksen_alkamisvuosi is not null""".as[String]
sql"""SELECT DISTINCT koulutuksen_alkamisvuosi
FROM pub.pub_dim_toteutus pdt
WHERE koulutuksen_alkamisvuosi IS NOT NULL""".as[String]
}

def selectDistinctExistingHaut(): SqlStreamingAction[Vector[Haku], Haku, Effect] = {
val hakukohdekooditStr = ammatillisetHakukohdekoodit.map(s => s"'$s'").mkString(",")
sql"""select distinct haku_oid, haku_nimi
from pub.pub_dim_haku h
where kohdejoukko_koodi in (#$hakukohdekooditStr)
and h.tila != 'poistettu'""".as[Haku]
sql"""SELECT DISTINCT haku_oid, haku_nimi
FROM pub.pub_dim_haku h
WHERE kohdejoukko_koodi IN (#$hakukohdekooditStr)
AND h.tila != 'poistettu'""".as[Haku]
}

def selectDistinctOrganisaatiot(
organisaatiot: List[String]
): SqlStreamingAction[Vector[Organisaatio], Organisaatio, Effect] = {
val organisaatiotStr = organisaatiot.map(s => s"'$s'").mkString(",")
val optionalOrganisaatiotClause =
if (organisaatiotStr.isEmpty) "" else s"where org.organisaatio_oid in ($organisaatiotStr)"
sql"""SELECT DISTINCT *
FROM (SELECT organisaatio_oid, organisaatio_nimi, organisaatiotyypit
FROM pub.pub_dim_organisaatio o) AS org
#$optionalOrganisaatiotClause""".as[Organisaatio]
}

def selectDistinctKoulutustoimijat(
organisaatiot: List[String]
): SqlStreamingAction[Vector[Organisaatio], Organisaatio, Effect] = {
val organisaatiotStr = organisaatiot.map(s => s"'$s'").mkString(",")
val optionalOrganisaatiotClause =
if (organisaatiotStr.isEmpty) "" else s"where org.organisaatio_oid in ($organisaatiotStr)"
sql"""SELECT DISTINCT *
FROM (SELECT organisaatio_oid, organisaatio_nimi, organisaatiotyypit
FROM pub.pub_dim_organisaatio o
WHERE organisaatiotyypit ?? '01') AS org
#$optionalOrganisaatiotClause""".as[Organisaatio]
}

def selectChildOrganisaatiot(
organisaatiot: List[String]
): SqlStreamingAction[Vector[OrganisaatioParentChild], OrganisaatioParentChild, Effect] = {
val organisaatiotStr = organisaatiot.map(s => s"'$s'").mkString(",")

sql"""WITH RECURSIVE x AS (
SELECT parent_oid, child_oid
FROM pub.pub_dim_organisaatio_rakenne or1
WHERE parent_oid in (#$organisaatiotStr)
UNION
SELECT or2.parent_oid, or2.child_oid
FROM pub.pub_dim_organisaatio_rakenne or2
INNER JOIN x x1
ON or2.parent_oid = x1.child_oid
) SELECT parent_oid, child_oid, organisaatio_nimi, organisaatiotyypit
FROM x
inner join pub.pub_dim_organisaatio org
on org.organisaatio_oid = x.child_oid""".as[OrganisaatioParentChild]
}

val selectOrganisaatioHierarkiaSql =
"""SELECT organisaatio_oid,
organisaatio_nimi,
organisaatiotyypit,
oppilaitostyyppi,
tila,
parent_oids,
children"""

def selectKoulutustoimijaDescendants(
koulutustoimijaOids: List[String]
): SqlStreamingAction[Vector[OrganisaatioHierarkia], OrganisaatioHierarkia, Effect] = {
val organisaatiotStr = koulutustoimijaOids.map(s => s"'$s'").mkString(",")
sql"""#$selectOrganisaatioHierarkiaSql
FROM pub.pub_dim_koulutustoimija_ja_toimipisteet,
LATERAL jsonb_array_elements_text(parent_oids) AS parent_oid
WHERE parent_oid IN (#$organisaatiotStr)
""".as[OrganisaatioHierarkia]
}

def selectOppilaitosDescendants(
oids: List[String]
): SqlStreamingAction[Vector[OrganisaatioHierarkia], OrganisaatioHierarkia, Effect] = {
val organisaatiotStr = oids.map(s => s"'$s'").mkString(",")
sql"""#$selectOrganisaatioHierarkiaSql
FROM pub.pub_dim_oppilaitos_ja_toimipisteet,
LATERAL jsonb_array_elements_text(parent_oids) AS parent_oid
WHERE parent_oid IN (#$organisaatiotStr)
""".as[OrganisaatioHierarkia]
}

def selectToimipisteDescendants(
oids: List[String]
): SqlStreamingAction[Vector[OrganisaatioHierarkia], OrganisaatioHierarkia, Effect] = {
val organisaatiotStr = oids.map(s => s"'$s'").mkString(",")
sql"""#$selectOrganisaatioHierarkiaSql
FROM pub.pub_dim_toimipiste_ja_toimipisteet,
LATERAL jsonb_array_elements_text(parent_oids) AS parent_oid
WHERE parent_oid IN (#$organisaatiotStr)
""".as[OrganisaatioHierarkia]
}
}
Loading

0 comments on commit 84504c4

Please sign in to comment.