Skip to content

Commit

Permalink
IS-2727: Use sen fase bulk endpoint (#439)
Browse files Browse the repository at this point in the history
  • Loading branch information
andersrognstad authored Oct 16, 2024
1 parent 2ca06f6 commit 776aa69
Show file tree
Hide file tree
Showing 19 changed files with 255 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .nais/naiserator-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ spec:
- application: ismanglendemedvirkning
- application: istilgangskontroll
- application: ishuskelapp
- application: ismeroppfolging
azure:
application:
allowAllUsers: true
Expand Down Expand Up @@ -107,6 +108,10 @@ spec:
value: "dev-gcp.teamsykefravr.ismanglendemedvirkning"
- name: MANGLENDEMEDVIRKNING_URL
value: "http://ismanglendemedvirkning"
- name: ISMEROPPFOLGING_CLIENT_ID
value: "dev-gcp.teamsykefravr.ismeroppfolging"
- name: ISMEROPPFOLGING_URL
value: "http://ismeroppfolging"
- name: ISTILGANGSKONTROLL_CLIENT_ID
value: "dev-gcp.teamsykefravr.istilgangskontroll"
- name: ISTILGANGSKONTROLL_HOST
Expand Down
5 changes: 5 additions & 0 deletions .nais/naiserator-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ spec:
- application: ismanglendemedvirkning
- application: istilgangskontroll
- application: ishuskelapp
- application: ismeroppfolging
azure:
application:
allowAllUsers: true
Expand Down Expand Up @@ -108,6 +109,10 @@ spec:
value: "prod-gcp.teamsykefravr.ismanglendemedvirkning"
- name: MANGLENDEMEDVIRKNING_URL
value: "http://ismanglendemedvirkning"
- name: ISMEROPPFOLGING_CLIENT_ID
value: "prod-gcp.teamsykefravr.ismeroppfolging"
- name: ISMEROPPFOLGING_URL
value: "http://ismeroppfolging"
- name: ISTILGANGSKONTROLL_CLIENT_ID
value: "prod-gcp.teamsykefravr.istilgangskontroll"
- name: ISTILGANGSKONTROLL_HOST
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/no/nav/syfo/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import no.nav.syfo.personstatus.infrastructure.clients.arbeidsuforhet.Arbeidsufo
import no.nav.syfo.personstatus.infrastructure.clients.manglendemedvirkning.ManglendeMedvirkningClient
import no.nav.syfo.personstatus.infrastructure.clients.azuread.AzureAdClient
import no.nav.syfo.personstatus.infrastructure.clients.behandlendeenhet.BehandlendeEnhetClient
import no.nav.syfo.personstatus.infrastructure.clients.meroppfolging.MerOppfolgingClient
import no.nav.syfo.personstatus.infrastructure.clients.oppfolgingsoppgave.OppfolgingsoppgaveClient
import no.nav.syfo.personstatus.infrastructure.clients.pdl.PdlClient
import no.nav.syfo.personstatus.infrastructure.clients.veiledertilgang.VeilederTilgangskontrollClient
Expand Down Expand Up @@ -72,6 +73,10 @@ fun main() {
azureAdClient = azureAdClient,
clientEnvironment = environment.clients.manglendeMedvirkning,
)
val merOppfolgingClient = MerOppfolgingClient(
azureAdClient = azureAdClient,
clientEnvironment = environment.clients.ismeroppfolging,
)
val veilederTilgangskontrollClient = VeilederTilgangskontrollClient(
azureAdClient = azureAdClient,
istilgangskontrollEnv = environment.clients.istilgangskontroll,
Expand Down Expand Up @@ -114,6 +119,7 @@ fun main() {
aktivitetskravClient = aktivitetskravClient,
manglendeMedvirkningClient = manglendeMedvirkningClient,
arbeidsuforhetvurderingClient = arbeidsuforhetvurderingClient,
merOppfolgingClient = merOppfolgingClient,
),
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/no/nav/syfo/ApplicationEnvironment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ data class Environment(
baseUrl = getEnvVar("MANGLENDEMEDVIRKNING_URL"),
clientId = getEnvVar("MANGLENDEMEDVIRKNING_CLIENT_ID"),
),
ismeroppfolging = ClientEnvironment(
baseUrl = getEnvVar("ISMEROPPFOLGING_URL"),
clientId = getEnvVar("ISMEROPPFOLGING_CLIENT_ID"),
),
istilgangskontroll = ClientEnvironment(
baseUrl = getEnvVar("ISTILGANGSKONTROLL_HOST"),
clientId = getEnvVar("ISTILGANGSKONTROLL_CLIENT_ID"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import no.nav.syfo.personstatus.application.arbeidsuforhet.Arbeidsuforhetvurderi
import no.nav.syfo.personstatus.application.arbeidsuforhet.IArbeidsuforhetvurderingClient
import no.nav.syfo.personstatus.application.manglendemedvirkning.IManglendeMedvirkningClient
import no.nav.syfo.personstatus.application.manglendemedvirkning.ManglendeMedvirkningResponseDTO
import no.nav.syfo.personstatus.application.meroppfolging.IMeroppfolgingClient
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidaterResponseDTO
import no.nav.syfo.personstatus.application.oppfolgingsoppgave.IOppfolgingsoppgaveClient
import no.nav.syfo.personstatus.application.oppfolgingsoppgave.OppfolgingsoppgaverResponseDTO
import no.nav.syfo.personstatus.domain.PersonIdent
Expand All @@ -22,6 +24,7 @@ class PersonoversiktOppgaverService(
private val manglendeMedvirkningClient: IManglendeMedvirkningClient,
private val aktivitetskravClient: IAktivitetskravClient,
private val oppfolgingsoppgaveClient: IOppfolgingsoppgaveClient,
private val merOppfolgingClient: IMeroppfolgingClient,
) {
private val log = LoggerFactory.getLogger(this::class.java)

Expand Down Expand Up @@ -50,6 +53,11 @@ class PersonoversiktOppgaverService(
token = token,
personStatuser = personer,
)
val senOppfolgingKandidater = getSenOppfolgingKandidaterForPersons(
callId = callId,
token = token,
personStatuser = personer,
)

return personer.associate {
it.fnr to PersonoversiktAktiveOppgaver(
Expand All @@ -65,6 +73,9 @@ class PersonoversiktOppgaverService(
manglendeMedvirkning = manglendeMedvirkning.await()
?.vurderinger
?.get(it.fnr),
senOppfolgingKandidat = senOppfolgingKandidater.await()
?.kandidater
?.get(it.fnr),
)
}
}
Expand Down Expand Up @@ -152,4 +163,24 @@ class PersonoversiktOppgaverService(
null
}
}

private fun getSenOppfolgingKandidaterForPersons(
callId: String,
token: String,
personStatuser: List<PersonOversiktStatus>,
): Deferred<SenOppfolgingKandidaterResponseDTO?> =
CoroutineScope(Dispatchers.IO).async {
val personidenterWithActiveSenOppfolgingKandidat = personStatuser
.filter { it.isAktivSenOppfolgingKandidat }
.map { PersonIdent(it.fnr) }
if (personidenterWithActiveSenOppfolgingKandidat.isNotEmpty()) {
merOppfolgingClient.getSenOppfolgingKandidater(
callId = callId,
token = token,
personidenter = personidenterWithActiveSenOppfolgingKandidat,
)
} else {
null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ fun Route.registerPersonoversiktApiV2(
oppfolgingsoppgave = aktiveOppgaver?.oppfolgingsoppgave,
aktivitetskravvurdering = aktiveOppgaver?.aktivitetskrav,
manglendeMedvirkning = aktiveOppgaver?.manglendeMedvirkning,
senOppfolgingKandidat = aktiveOppgaver?.senOppfolgingKandidat,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package no.nav.syfo.personstatus.api.v2.model
import no.nav.syfo.personstatus.application.aktivitetskrav.AktivitetskravDTO
import no.nav.syfo.personstatus.application.arbeidsuforhet.ArbeidsuforhetvurderingDTO
import no.nav.syfo.personstatus.application.manglendemedvirkning.ManglendeMedvirkningDTO
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidatDTO
import no.nav.syfo.personstatus.application.oppfolgingsoppgave.OppfolgingsoppgaveDTO
import java.time.LocalDate

Expand All @@ -22,7 +23,8 @@ data class PersonOversiktStatusDTO(
val arbeidsuforhetvurdering: ArbeidsuforhetvurderingDTO?,
val friskmeldingTilArbeidsformidlingFom: LocalDate?,
val oppfolgingsoppgave: OppfolgingsoppgaveDTO?,
val isAktivSenOppfolgingKandidat: Boolean,
val isAktivSenOppfolgingKandidat: Boolean, // TODO: Denne kan fjernes når frontend bruker senOppfolgingKandidat
val senOppfolgingKandidat: SenOppfolgingKandidatDTO?,
val aktivitetskravvurdering: AktivitetskravDTO?,
val manglendeMedvirkning: ManglendeMedvirkningDTO?,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package no.nav.syfo.personstatus.application
import no.nav.syfo.personstatus.application.aktivitetskrav.AktivitetskravDTO
import no.nav.syfo.personstatus.application.arbeidsuforhet.ArbeidsuforhetvurderingDTO
import no.nav.syfo.personstatus.application.manglendemedvirkning.ManglendeMedvirkningDTO
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidatDTO
import no.nav.syfo.personstatus.application.oppfolgingsoppgave.OppfolgingsoppgaveDTO

data class PersonoversiktAktiveOppgaver(
val arbeidsuforhet: ArbeidsuforhetvurderingDTO?,
val oppfolgingsoppgave: OppfolgingsoppgaveDTO?,
val aktivitetskrav: AktivitetskravDTO?,
val manglendeMedvirkning: ManglendeMedvirkningDTO?,
val senOppfolgingKandidat: SenOppfolgingKandidatDTO?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package no.nav.syfo.personstatus.application.meroppfolging

import no.nav.syfo.personstatus.domain.PersonIdent

interface IMeroppfolgingClient {
suspend fun getSenOppfolgingKandidater(
callId: String,
token: String,
personidenter: List<PersonIdent>,
): SenOppfolgingKandidaterResponseDTO?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package no.nav.syfo.personstatus.application.meroppfolging

import java.time.LocalDateTime
import java.util.*

data class SenOppfolgingKandidaterRequestDTO(
val personidenter: List<String>
)

data class SenOppfolgingKandidaterResponseDTO(
val kandidater: Map<String, SenOppfolgingKandidatDTO>
)

data class SenOppfolgingKandidatDTO(
val uuid: UUID,
val personident: String,
val varselAt: LocalDateTime?,
val svar: SvarResponseDTO?,
)

data class SvarResponseDTO(
val svarAt: LocalDateTime,
val onskerOppfolging: OnskerOppfolging,
)

enum class OnskerOppfolging {
JA,
NEI,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import no.nav.syfo.personstatus.api.v2.model.PersonOversiktStatusDTO
import no.nav.syfo.personstatus.application.aktivitetskrav.AktivitetskravDTO
import no.nav.syfo.personstatus.application.arbeidsuforhet.ArbeidsuforhetvurderingDTO
import no.nav.syfo.personstatus.application.manglendemedvirkning.ManglendeMedvirkningDTO
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidatDTO
import no.nav.syfo.personstatus.application.oppfolgingsoppgave.OppfolgingsoppgaveDTO
import no.nav.syfo.util.isBeforeOrEqual
import no.nav.syfo.util.toLocalDateOslo
Expand Down Expand Up @@ -91,6 +92,7 @@ fun PersonOversiktStatus.toPersonOversiktStatusDTO(
oppfolgingsoppgave: OppfolgingsoppgaveDTO?,
aktivitetskravvurdering: AktivitetskravDTO?,
manglendeMedvirkning: ManglendeMedvirkningDTO?,
senOppfolgingKandidat: SenOppfolgingKandidatDTO?,
) =
PersonOversiktStatusDTO(
veilederIdent = veilederIdent,
Expand All @@ -111,6 +113,7 @@ fun PersonOversiktStatus.toPersonOversiktStatusDTO(
isAktivSenOppfolgingKandidat = isAktivSenOppfolgingKandidat,
aktivitetskravvurdering = aktivitetskravvurdering,
manglendeMedvirkning = manglendeMedvirkning,
senOppfolgingKandidat = senOppfolgingKandidat,
)

fun PersonOversiktStatus.hasActiveBehandlerdialogOppgave(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ data class ClientsEnvironment(
val aktivitetskrav: ClientEnvironment,
val istilgangskontroll: ClientEnvironment,
val ishuskelapp: ClientEnvironment,
val ismeroppfolging: ClientEnvironment,
)

data class ClientEnvironment(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package no.nav.syfo.personstatus.infrastructure.clients.meroppfolging

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.micrometer.core.instrument.Counter
import net.logstash.logback.argument.StructuredArguments
import no.nav.syfo.personstatus.application.meroppfolging.IMeroppfolgingClient
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidaterRequestDTO
import no.nav.syfo.personstatus.application.meroppfolging.SenOppfolgingKandidaterResponseDTO
import no.nav.syfo.personstatus.domain.PersonIdent
import no.nav.syfo.personstatus.infrastructure.METRICS_NS
import no.nav.syfo.personstatus.infrastructure.METRICS_REGISTRY
import no.nav.syfo.personstatus.infrastructure.clients.ClientEnvironment
import no.nav.syfo.personstatus.infrastructure.clients.azuread.AzureAdClient
import no.nav.syfo.personstatus.infrastructure.clients.httpClientDefault
import no.nav.syfo.util.NAV_CALL_ID_HEADER
import no.nav.syfo.util.bearerHeader
import no.nav.syfo.util.callIdArgument
import org.slf4j.LoggerFactory

class MerOppfolgingClient(
private val azureAdClient: AzureAdClient,
private val clientEnvironment: ClientEnvironment,
private val httpClient: HttpClient = httpClientDefault(),
) : IMeroppfolgingClient {

override suspend fun getSenOppfolgingKandidater(
callId: String,
token: String,
personidenter: List<PersonIdent>
): SenOppfolgingKandidaterResponseDTO? {
val oboToken = azureAdClient.getOnBehalfOfToken(
scopeClientId = clientEnvironment.clientId,
token,
)?.accessToken ?: throw RuntimeException("Failed to get OBO-token for sen oppfolging kandidater")
val requestDTO = SenOppfolgingKandidaterRequestDTO(personidenter.map { it.value })

return try {
val response = httpClient.post("${clientEnvironment.baseUrl}$MEROPPFOLGING_SENOPPFOLGING_KANDIDATER_API_PATH") {
header(HttpHeaders.Authorization, bearerHeader(oboToken))
header(NAV_CALL_ID_HEADER, callId)
accept(ContentType.Application.Json)
contentType(ContentType.Application.Json)
setBody(requestDTO)
}
when (response.status) {
HttpStatusCode.OK -> {
COUNT_CALL_MEROPPFOLGING_SUCCESS.increment()
response.body<SenOppfolgingKandidaterResponseDTO>()
}
HttpStatusCode.NotFound -> {
log.error("Resource not found")
COUNT_CALL_MEROPPFOLGING_FAIL.increment()
null
}
else -> {
log.error("Unhandled status code: ${response.status}")
COUNT_CALL_MEROPPFOLGING_FAIL.increment()
null
}
}
} catch (e: ClientRequestException) {
handleUnexpectedResponseException(e.response, callId)
throw e
} catch (e: ServerResponseException) {
handleUnexpectedResponseException(e.response, callId)
throw e
}
}

private fun handleUnexpectedResponseException(
response: HttpResponse,
callId: String,
) {
log.error(
"Error while requesting from ismeroppfolging with {}, {}",
StructuredArguments.keyValue("statusCode", response.status.value.toString()),
callIdArgument(callId)
)
COUNT_CALL_MEROPPFOLGING_FAIL.increment()
}

companion object {
const val MEROPPFOLGING_SENOPPFOLGING_KANDIDATER_API_PATH = "/api/internad/v1/senoppfolging/get-kandidater"
private val log = LoggerFactory.getLogger(this::class.java)

private const val CALL_MEROPPFOLGING_BASE = "${METRICS_NS}_call_ismeroppfolging"
private const val CALL_MEROPPFOLGING_SUCCESS = "${CALL_MEROPPFOLGING_BASE}_success_count"
private const val CALL_MEROPPFOLGING_FAIL = "${CALL_MEROPPFOLGING_BASE}_fail_count"

val COUNT_CALL_MEROPPFOLGING_SUCCESS: Counter = Counter
.builder(CALL_MEROPPFOLGING_SUCCESS)
.description("Counts the number of successful calls to ismeroppfolging")
.register(METRICS_REGISTRY)
val COUNT_CALL_MEROPPFOLGING_FAIL: Counter = Counter
.builder(CALL_MEROPPFOLGING_FAIL)
.description("Counts the number of failed calls to ismeroppfolging")
.register(METRICS_REGISTRY)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ object PersonoversiktStatusApiV2Spek : Spek({
personOversiktStatus.fnr shouldBeEqualTo personident
personOversiktStatus.enhet shouldBeEqualTo NAV_ENHET
personOversiktStatus.isAktivSenOppfolgingKandidat shouldBeEqualTo true
personOversiktStatus.senOppfolgingKandidat shouldNotBe null
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import no.nav.syfo.personstatus.infrastructure.clients.aktivitetskrav.Aktivitets
import no.nav.syfo.personstatus.infrastructure.clients.arbeidsuforhet.ArbeidsuforhetvurderingClient
import no.nav.syfo.personstatus.infrastructure.clients.manglendemedvirkning.ManglendeMedvirkningClient
import no.nav.syfo.personstatus.infrastructure.clients.azuread.AzureAdClient
import no.nav.syfo.personstatus.infrastructure.clients.meroppfolging.MerOppfolgingClient
import no.nav.syfo.personstatus.infrastructure.clients.oppfolgingsoppgave.OppfolgingsoppgaveClient
import no.nav.syfo.personstatus.infrastructure.database.repository.PersonOversiktStatusRepository

Expand Down Expand Up @@ -59,6 +60,11 @@ class InternalMockEnvironment private constructor() {
clientEnvironment = environment.clients.aktivitetskrav,
httpClient = externalMockEnvironment.mockHttpClient
)
private val merOppfolgingClient = MerOppfolgingClient(
azureAdClient = azureAdClient,
clientEnvironment = environment.clients.ismeroppfolging,
httpClient = externalMockEnvironment.mockHttpClient
)
private val eregClient = EregClient(
clientEnvironment = environment.clients.ereg,
redisStore = redisStore,
Expand Down
Loading

0 comments on commit 776aa69

Please sign in to comment.