Skip to content

Commit

Permalink
Merge pull request #956 from navikt/ef-sak-controller
Browse files Browse the repository at this point in the history
Stønadsperioder fra EF-Sak
  • Loading branch information
charliemidtlyng authored Feb 13, 2024
2 parents d3d33c9 + d1d12f1 commit 8de75ce
Show file tree
Hide file tree
Showing 17 changed files with 564 additions and 1 deletion.
1 change: 1 addition & 0 deletions .deploy/nais-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ spec:
outbound:
rules:
- application: familie-ef-mottak
- application: familie-ef-sak
- application: "safselvbetjening-q2"
namespace: "teamdokumenthandtering"
cluster: "dev-fss"
Expand Down
1 change: 1 addition & 0 deletions .deploy/nais-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ spec:
outbound:
rules:
- application: familie-ef-mottak
- application: familie-ef-sak
- application: "safselvbetjening"
namespace: "teamdokumenthandtering"
cluster: "prod-fss"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package no.nav.familie.ef.søknad.infrastruktur.config

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.web.util.UriComponentsBuilder
import java.net.URI

@ConfigurationProperties("familie.ef.saksbehandling")
data class SaksbehandlingConfig(val uri: URI) {

internal val hentStønadsperioderUri = byggUri(PATH_HENT_STØNADSPERIODER)
internal val pingUri = byggUri(PATH_PING)

private fun byggUri(path: String) = UriComponentsBuilder.fromUri(uri).path(path).build().toUri()

companion object {

private const val PATH_HENT_STØNADSPERIODER = "/ekstern/minside/stonadsperioder"
private const val PATH_PING = "ping"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SafClient(
@Qualifier("tokenExchange") restOperations: RestOperations,
) : AbstractPingableRestClient(restOperations, "saf.dokument") {

fun hentDokument(journalpostId: String, dokumentInfoId: String, dokumentVariantformat: Variantformat): ByteArray =
fun hentDokument(journalpostId: String, dokumentInfoId: String, dokumentVariantformat: Variantformat) =
getForEntity<ByteArray>(
UriComponentsBuilder.fromUriString("${safConfig.safRestUri}/hentdokument/" + "$journalpostId/$dokumentInfoId/$dokumentVariantformat")
.build().toUri(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package no.nav.familie.ef.søknad.minside

import no.nav.familie.ef.søknad.infrastruktur.config.SaksbehandlingConfig
import no.nav.familie.ef.søknad.minside.dto.StønadsperioderDto
import no.nav.familie.http.client.AbstractPingableRestClient
import no.nav.familie.kontrakter.felles.Ressurs
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import org.springframework.web.client.RestOperations
import org.springframework.web.util.UriComponentsBuilder
import java.net.URI
import no.nav.familie.kontrakter.felles.getDataOrThrow

@Service
class SaksbehandlingClient(
private val config: SaksbehandlingConfig,
@Qualifier("tokenExchange") operations: RestOperations,
) :
AbstractPingableRestClient(operations, "saksbehandling") {

override val pingUri: URI = config.pingUri

fun hentStønadsperioderForBruker() = getForEntity<Ressurs<StønadsperioderDto>>(
UriComponentsBuilder.fromUriString("${config.hentStønadsperioderUri}").build().toUri(),
).getDataOrThrow()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.nav.familie.ef.søknad.minside

import no.nav.familie.sikkerhet.EksternBrukerUtils
import no.nav.security.token.support.core.api.ProtectedWithClaims
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDate

@RestController
@RequestMapping("/api/saksbehandling")
@ProtectedWithClaims(issuer = EksternBrukerUtils.ISSUER_TOKENX, claimMap = ["acr=Level4"])
class SaksbehandlingController(private val saksbehandlingService: SaksbehandlingService) {

@GetMapping("/stonadsperioder")
fun hentStønadsperioderForBruker() = saksbehandlingService.hentStønadsperioderForBruker()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package no.nav.familie.ef.søknad.minside

import no.nav.familie.ef.søknad.minside.dto.MineStønaderDto
import no.nav.familie.ef.søknad.minside.dto.PeriodeStatus
import no.nav.familie.ef.søknad.minside.dto.Stønad
import no.nav.familie.ef.søknad.minside.dto.StønadsperiodeDto
import no.nav.familie.kontrakter.felles.Datoperiode
import no.nav.familie.kontrakter.felles.erSammenhengende
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import no.nav.familie.ef.søknad.minside.dto.PeriodeStatus.FREMTIDIG_UTEN_OPPHOLD
import no.nav.familie.ef.søknad.minside.dto.PeriodeStatus.INGEN
import no.nav.familie.ef.søknad.minside.dto.PeriodeStatus.LØPENDE_UTEN_OPPHOLD
import no.nav.familie.ef.søknad.minside.dto.PeriodeStatus.TIDLIGERE_ELLER_OPPHOLD
import no.nav.familie.ef.søknad.utils.DatoUtil.dagensDato

@Service
class SaksbehandlingService(private val saksbehandlingClient: SaksbehandlingClient) {

private val logger = LoggerFactory.getLogger(javaClass)
private val secureLogger = LoggerFactory.getLogger("secureLogger")

fun hentStønadsperioderForBruker(): MineStønaderDto {
val stønadsperioder = saksbehandlingClient.hentStønadsperioderForBruker()

val mineStønaderDto = MineStønaderDto(
overgangsstønad = utledStønad(stønadsperioder.overgangsstønad),
barnetilsyn = utledStønad(stønadsperioder.barnetilsyn),
skolepenger = utledStønad(stønadsperioder.skolepenger),
)

return mineStønaderDto
}

private fun utledStønad(stønader: List<StønadsperiodeDto>): Stønad {
val perioderSortertPåDato = stønader.sortedBy { it.fraDato }

val (periodeStatus, relevantePerioder) = utledPeriodeStatusMedPerioder(perioderSortertPåDato)
val startDato = utledStartDato(periodeStatus, relevantePerioder)
val sluttDato = utledTilDato(periodeStatus, relevantePerioder)

return Stønad(
periodeStatus = periodeStatus,
startDato = startDato,
sluttDato = sluttDato,
perioder = perioderSortertPåDato,
)
}

private fun utledTilDato(
periodeStatus: PeriodeStatus,
relevantePerioder: List<StønadsperiodeDto>,
) =
if (periodeStatus === FREMTIDIG_UTEN_OPPHOLD || periodeStatus === LØPENDE_UTEN_OPPHOLD) relevantePerioder.last().tilDato else null

private fun utledStartDato(
periodeStatus: PeriodeStatus,
relevantePerioder: List<StønadsperiodeDto>,
) = if (periodeStatus === FREMTIDIG_UTEN_OPPHOLD) relevantePerioder.first().fraDato else null

private fun utledPeriodeStatusMedPerioder(perioder: List<StønadsperiodeDto>): Pair<PeriodeStatus, List<StønadsperiodeDto>> {
if (perioder.isEmpty()) {
return Pair(INGEN, emptyList())
}

val perioderMedFremtidigSluttdato = perioder.filter { it.tilDato >= dagensDato() }
val datoPerioderMedFremtidigSluttdato =
perioderMedFremtidigSluttdato.map { Datoperiode(fom = it.fraDato, tom = it.tilDato) }

val periodeStatus = utledPeriodeStatus(datoPerioderMedFremtidigSluttdato)

return when (periodeStatus) {
INGEN, TIDLIGERE_ELLER_OPPHOLD -> Pair(periodeStatus, emptyList())
LØPENDE_UTEN_OPPHOLD, FREMTIDIG_UTEN_OPPHOLD -> Pair(periodeStatus, perioderMedFremtidigSluttdato)
}
}

private fun utledPeriodeStatus(datoPerioderMedFremtidigSluttdato: List<Datoperiode>): PeriodeStatus {
val harFremtidigePerioderOgErSammenhengende =
datoPerioderMedFremtidigSluttdato.erSammenhengende() && datoPerioderMedFremtidigSluttdato.isNotEmpty()
val inneholderDagensDato = datoPerioderMedFremtidigSluttdato.any { it.inneholder(dagensDato()) }
return if (harFremtidigePerioderOgErSammenhengende && inneholderDagensDato) {
LØPENDE_UTEN_OPPHOLD
} else if (harFremtidigePerioderOgErSammenhengende) {
FREMTIDIG_UTEN_OPPHOLD
} else {
TIDLIGERE_ELLER_OPPHOLD
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package no.nav.familie.ef.søknad.minside.dto

import java.time.LocalDate

data class StønadsperioderDto(
val overgangsstønad: List<StønadsperiodeDto>,
val barnetilsyn: List<StønadsperiodeDto>,
val skolepenger: List<StønadsperiodeDto>,
)
data class StønadsperiodeDto(
val fraDato: LocalDate,
val tilDato: LocalDate,
val beløp: Int,
)

data class MineStønaderDto(
val overgangsstønad: Stønad,
val barnetilsyn: Stønad,
val skolepenger: Stønad,
)

data class Stønad(
val periodeStatus: PeriodeStatus,
val startDato: LocalDate?, // Startdato settes der hvor vi har fremtidige perioder uten opphold
val sluttDato: LocalDate?, // Sluttdato settes der hvor vi har fremtidige eller løpende perioder uten opphold
val perioder: List<StønadsperiodeDto>,
)

enum class PeriodeStatus {
LØPENDE_UTEN_OPPHOLD,
FREMTIDIG_UTEN_OPPHOLD,
TIDLIGERE_ELLER_OPPHOLD,
INGEN,
}
7 changes: 7 additions & 0 deletions src/main/kotlin/no/nav/familie/ef/søknad/utils/DatoUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package no.nav.familie.ef.søknad.utils

import java.time.LocalDate

object DatoUtil {
fun dagensDato(): LocalDate = LocalDate.now()
}
3 changes: 3 additions & 0 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ familie:
mottak:
uri: http://familie-ef-mottak/api
audience: dev-gcp:teamfamilie:familie-ef-mottak
saksbehandling:
uri: http://familie-ef-sak/api
audience: dev-gcp:teamfamilie:familie-ef-sak
integrasjoner:
uri: https://familie-integrasjoner.dev-fss-pub.nais.io/api
scope: api://dev-fss.teamfamilie.familie-integrasjoner/.default
Expand Down
13 changes: 13 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ familie:
mottak:
uri: http://familie-ef-mottak/api
audience: prod-gcp:teamfamilie:familie-ef-mottak
saksbehandling:
uri: http://familie-ef-sak/api
audience: prod-gcp:teamfamilie:familie-ef-sak
integrasjoner:
uri: https://familie-integrasjoner.prod-fss-pub.nais.io/api
scope: ${FAMILIE_INTEGRASJONER_SCOPE}
Expand Down Expand Up @@ -72,6 +75,16 @@ no.nav.security.jwt:
client-id: ${TOKEN_X_CLIENT_ID}
client-auth-method: private_key_jwt
client-jwk: ${TOKEN_X_PRIVATE_JWK}
saksbehandling:
resource-url: ${familie.ef.saksbehandling.uri}
well-known-url: ${TOKEN_X_WELL_KNOWN_URL}
grant-type: urn:ietf:params:oauth:grant-type:token-exchange
token-exchange:
audience: ${familie.ef.saksbehandling.audience}
authentication:
client-id: ${TOKEN_X_CLIENT_ID}
client-auth-method: private_key_jwt
client-jwk: ${TOKEN_X_PRIVATE_JWK}
pdl:
resource-url: ${PDL_URL}
well-known-url: ${TOKEN_X_WELL_KNOWN_URL}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ fun main(args: Array<String>) {
"mock-mottak",
"mock-integrasjoner",
"mock-saf",
"mock-saksbehandling",
)
.properties(mapOf("mock-oauth2-server.port" to mockOauth2ServerPort))
.run(*args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import java.util.UUID
"mock-mottak",
"kodeverk-cache-test",
"mock-saf",
"mock-saksbehandling",
)
@EnableMockOAuth2Server
abstract class OppslagSpringRunnerTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package no.nav.familie.ef.søknad.minside

import io.mockk.every
import io.mockk.mockk
import no.nav.familie.ef.søknad.minside.dto.StønadsperiodeDto
import no.nav.familie.ef.søknad.minside.dto.StønadsperioderDto
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.context.annotation.Profile
import java.time.LocalDate

@Configuration
@Profile("mock-saksbehandling")
class SaksbehandlingClientMock {

@Bean
@Primary
fun saksbehandlingClient(): SaksbehandlingClient {
val saksbehandlingCLient: SaksbehandlingClient = mockk()

val stønadsperioderDto = StønadsperioderDto(
overgangsstønad = stønadsperioderOvergangsstønad,
barnetilsyn = stønadsperioderBarnetilsyn,
skolepenger = stønadsperioderSkolepenger,
)

every { saksbehandlingCLient.hentStønadsperioderForBruker() } returns stønadsperioderDto

return saksbehandlingCLient
}

private val stønadsperioderOvergangsstønad: List<StønadsperiodeDto> = listOf(
StønadsperiodeDto(
fraDato = LocalDate.of(2024, 1, 1),
tilDato = LocalDate.of(2025, 9, 30),
beløp = 19065,
),
StønadsperiodeDto(
fraDato = LocalDate.of(2023, 12, 1),
tilDato = LocalDate.of(2023, 12, 31),
beløp = 4215,
),
StønadsperiodeDto(
fraDato = LocalDate.of(2023, 11, 1),
tilDato = LocalDate.of(2023, 11, 30),
beløp = 13665,
),
)

private val stønadsperioderBarnetilsyn: List<StønadsperiodeDto> = listOf(
StønadsperiodeDto(
fraDato = LocalDate.of(2022, 1, 1),
tilDato = LocalDate.of(2023, 9, 30),
beløp = 19065,
),
StønadsperiodeDto(
fraDato = LocalDate.of(2021, 12, 1),
tilDato = LocalDate.of(2021, 12, 31),
beløp = 4215,
),
StønadsperiodeDto(
fraDato = LocalDate.of(2021, 11, 1),
tilDato = LocalDate.of(2021, 11, 30),
beløp = 13665,
),
)

private val stønadsperioderSkolepenger: List<StønadsperiodeDto> = listOf(
StønadsperiodeDto(
fraDato = LocalDate.of(2024, 3, 1),
tilDato = LocalDate.of(2027, 1, 31),
beløp = 19065,
),
)
}
Loading

0 comments on commit 8de75ce

Please sign in to comment.