Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .nais/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ spec:
namespace: teamsykefravr
- application: logging
namespace: nais-system
- application: kodeverk-api
namespace: team-rocket
inbound:
rules:
- application: rpa-medlemskap-og-avgift
Expand Down
2 changes: 2 additions & 0 deletions .nais/prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ spec:
namespace: teamsykefravr
- application: logging
namespace: nais-system
- application: kodeverk-api
namespace: team-rocket
inbound:
rules:
- application: rpa-medlemskap-og-avgift
Expand Down
35 changes: 34 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ plugins {
id("org.jetbrains.kotlin.plugin.serialization") version "2.2.0"
id("com.gradleup.shadow") version "8.3.8"
id("com.expediagroup.graphql") version "8.8.1"
id("org.openapi.generator") version "7.15.0"
}

group = "no.nav"
Expand Down Expand Up @@ -161,8 +162,40 @@ val generatePDLClient by tasks.creating(GraphQLGenerateClientTask::class) {
dependsOn("downloadPDLSchema")
}

val generatedSourcesPath = "$buildDir/generated/source/openapi"

openApiGenerate {
inputSpec.set("${project.projectDir}/src/main/resources/kodeverk/openapi.json")
outputDir.set(generatedSourcesPath)
generatorName.set("kotlin")
packageName.set("no.nav.api.generated.kodeverk")
configOptions.set(
mapOf(
"library" to "jvm-ktor",
"serializationLibrary" to "kotlinx_serialization",
"dateLibrary" to "kotlinx-datetime",
),
)
}

tasks {
register("generateApi") {
group = "build"
description = "Generate API"
dependsOn("openApiGenerate")
}
processResources {
dependsOn("generatePDLClient")
dependsOn("generateApi", "generatePDLClient")
}
compileKotlin {
dependsOn("generateApi")
}
}

sourceSets {
main {
kotlin {
srcDir("$generatedSourcesPath/src/main/kotlin/")
}
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/no/nav/Consumers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package no.nav
import no.nav.api.dialog.saf.SafClient
import no.nav.api.dialog.sf.SFClient
import no.nav.api.digdir.DigdirClient
import no.nav.api.kodeverk.KodeverkClient
import no.nav.api.kontonummer.KontonummerRegister
import no.nav.api.oppfolging.Nom
import no.nav.api.oppfolging.OppfolgingClient
Expand All @@ -29,6 +30,7 @@ interface Consumers {
val kontonummerRegister: KontonummerRegister
val utbetalingerClient: UtbetalingerClient
val sfClient: SFClient
val kodeverkClient: KodeverkClient
}

class ConsumersImpl(
Expand All @@ -49,6 +51,7 @@ class ConsumersImpl(
override val oppfolgingClient: OppfolgingClient = OppfolgingClient(env.oppfolgingUrl, oboTokenClient.bindTo(env.oppfolgingScope))
override val syfoClient: SyfoClient = SyfoClient(env.syfoUrl, oboTokenClient.bindTo(env.syfoScope))
override val nom: NomClient = Nom(env.nomUrl, tokenclient.bindTo(env.nomScope)).client
override val kodeverkClient: KodeverkClient = KodeverkClient(env.kodeverkUrl, tokenclient.bindTo(env.kodeverkScope))
override val skrivestotteClient: SkrivestotteClient = SkrivestotteClient(env.skrivestotteUrl)
override val pdlClient: PdlClient = PdlClient(env.pdlUrl, oboTokenClient.bindTo(env.pdlScope))
override val safClient: SafClient = SafClient(env.safUrl, oboTokenClient.bindTo(env.safScope))
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/no/nav/Env.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ interface Env {
val skrivestotteUrl: String
val sfUrl: String
val sfScope: DownstreamApi
val kodeverkUrl: String
val kodeverkScope: DownstreamApi
val identAllowList: List<String>
}

Expand All @@ -53,6 +55,8 @@ class EnvImpl : Env {
override val skrivestotteUrl: String = getRequiredConfig("SKRIVESTOTTE_URL")
override val sfUrl: String = getRequiredConfig("SF_HENVENDELSE_URL")
override val sfScope: DownstreamApi = getRequiredConfig("SF_HENVENDELSE_SCOPE").toDownstreamApi()
override val kodeverkUrl: String = getRequiredConfig("KODEVERK_URL")
override val kodeverkScope: DownstreamApi = getRequiredConfig("KODEVERK_SCOPE").toDownstreamApi()
override val identAllowList: List<String> = getRequiredConfig("IDENT_ALLOW_LIST").uppercase().split(",")
}

Expand Down
5 changes: 4 additions & 1 deletion src/main/kotlin/no/nav/Services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import no.nav.api.dialog.DialogService
import no.nav.api.dialog.saf.SafService
import no.nav.api.dialog.sf.SFService
import no.nav.api.digdir.DigdirService
import no.nav.api.kodeverk.KodeverkService
import no.nav.api.oppfolging.OppfolgingService
import no.nav.api.pdl.PdlService
import no.nav.api.skrivestotte.SkrivestotteService
Expand All @@ -20,6 +21,7 @@ interface Services {
val sfService: SFService
val dialogService: DialogService
val utbetalingerService: UtbetalingerService
val kodeverkService: KodeverkService
}

class ServicesImpl(
Expand All @@ -33,7 +35,8 @@ class ServicesImpl(
override val syfoService = SyfoService(consumers.syfoClient, consumers.nom)
override val skrivestotteService = SkrivestotteService(consumers.skrivestotteClient)
override val digdirService = DigdirService(consumers.digdirClient)
override val pdlService = PdlService(consumers.pdlClient)
override val kodeverkService = KodeverkService(consumers.kodeverkClient)
override val pdlService = PdlService(consumers.pdlClient, kodeverkService)
override val safService = SafService(consumers.safClient)
override val sfService = SFService(consumers.sfClient)
override val dialogService = DialogService(safService, sfService, pdlService)
Expand Down
56 changes: 56 additions & 0 deletions src/main/kotlin/no/nav/api/kodeverk/KodeverkClient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

package no.nav.api.kodeverk
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.engine.okhttp.*
import no.nav.api.generated.kodeverk.apis.KodeverkApi
import no.nav.api.generated.kodeverk.models.GetKodeverkKoderBetydningerResponse
import no.nav.utils.*

class KodeverkClient(
kodeverkUrl: String,
private val tokenClient: BoundedMachineToMachineTokenClient,
httpEngine: HttpClientEngine =
OkHttp.create {
addInterceptor(XCorrelationIdInterceptor())
addInterceptor(
LoggingInterceptor(
name = "kodeverk",
callIdExtractor = { getCallId() },
),
)
addInterceptor(
HeadersInterceptor {
mapOf(
"Nav-Consumer-Id" to navConsumerId,
)
},
)
addInterceptor(
AuthorizationInterceptor {
tokenClient.createMachineToMachineToken()
},
)
},
) {
private val api =
KodeverkApi(kodeverkUrl, httpEngine) { config ->
config.installContentNegotiationAndIgnoreUnknownKeys()
}

suspend fun hentKodeverkRaw(navn: String): GetKodeverkKoderBetydningerResponse =
externalServiceCall {
val response =
api.betydningUsingGET(
navCallId = getCallId(),
navConsumerId = "modia-robot-api",
kodeverksnavn = navn,
spraak = listOf("nb"),
ekskluderUgyldige = null,
oppslagsdato = null,
)
when (response.success) {
true -> response.body()
else -> error("Feil ved henting av kodeverk: ${response.status}")
}
}
}
84 changes: 84 additions & 0 deletions src/main/kotlin/no/nav/api/kodeverk/KodeverkService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package no.nav.api.kodeverk

import kotlinx.coroutines.runBlocking
import no.nav.api.generated.kodeverk.models.GetKodeverkKoderBetydningerResponse
import no.nav.personoversikt.common.utils.Retry
import no.nav.personoversikt.common.utils.SelftestGenerator
import kotlin.collections.set
import kotlin.concurrent.fixedRateTimer
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds

enum class KodeverkNavn(
val kodeverkString: String,
) {
LAND("Landkoder"),
POSTNUMMER("Postnummer"),
}

class KodeverkService(
private val kodeverkClient: KodeverkClient,
) {
private var kodeverkCache: MutableMap<KodeverkNavn, Map<String, String>> = mutableMapOf()
private val emptyKodeverk: Map<String, String> = emptyMap()
private val reporter = SelftestGenerator.Reporter(name = "KodeverkService", critical = false)
private val retry =
Retry(
Retry.Config(
initDelay = 30.seconds,
growthFactor = 2.0,
delayLimit = 1.hours,
),
)

init {
fixedRateTimer(
name = "Prepopuler cache kodeverk",
daemon = true,
period = 1.hours.inWholeMilliseconds,
initialDelay = 0,
) {
runBlocking {
reporter.ping {
prepopulerCache()
}
}
}
}

private fun hentKodeverk(navn: KodeverkNavn): Map<String, String> = (kodeverkCache[navn] ?: emptyKodeverk)

internal fun parseTilKodeverk(respons: GetKodeverkKoderBetydningerResponse): Map<String, String> {
val res =
respons.betydninger.mapValues { entry ->
entry.value
.first()
.beskrivelser["nb"]
?.term ?: entry.key
}
return res
}

fun hentKodeBeskrivelse(
kodeverkNavn: KodeverkNavn,
kodeRef: String,
default: String,
): String {
val kodeverk = this.hentKodeverk(kodeverkNavn)
val beskrivelse = kodeverk[kodeRef]
if (beskrivelse == null) {
return default
}
return beskrivelse
}

internal fun prepopulerCache() {
KodeverkNavn.entries.forEach { navn ->
runBlocking {
retry.run {
kodeverkCache[navn] = parseTilKodeverk(kodeverkClient.hentKodeverkRaw(navn.kodeverkString))
}
}
}
}
}
3 changes: 2 additions & 1 deletion src/main/kotlin/no/nav/api/pdl/PdlRoutes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package no.nav.api.pdl
import io.bkbn.kompendium.core.metadata.PostInfo
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
import no.nav.api.CommonModels
import no.nav.api.generated.pdl.hentpersonalia.Navn
import no.nav.models.FnrRequest
import no.nav.models.deserializeFnr
import no.nav.utils.getJWT
Expand Down Expand Up @@ -77,6 +77,7 @@ data class AktorIdResponse(

@Serializable
data class PdlPersonalia(
val navn: Navn? = null,
val alder: Int? = null,
val bostedsAdresse: PdlAdresse? = null,
val kontaktAdresse: PdlAdresse? = null,
Expand Down
Loading