From 8072db88266a1323c3f5dd43b491b5a84f50ebb3 Mon Sep 17 00:00:00 2001 From: Ugur Alpay Cenar Date: Mon, 11 Dec 2023 14:56:32 +0100 Subject: [PATCH] =?UTF-8?q?Ny=20endepunkt=20for=20=C3=A5=20hente=20notat?= =?UTF-8?q?=20opplysninger=20og=20ainntekt=20lenke=20(#105)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pr.yaml | 2 - .nais/feature.yaml | 4 +- .nais/main.yaml | 4 +- .nais/prod.yaml | 4 +- pom.xml | 6 +- .../consumer/BidragPersonConsumer.kt | 4 +- .../DeprecatedOpplysningerController.kt | 9 +- .../v1/ArbeidOgInntektController.kt | 65 +++++ .../v1/NotatOpplysningerController.kt | 18 ++ .../controller/v1/OpplysningerController.kt | 9 +- .../database/datamodell/Sivilstand.kt | 4 +- .../repository/OpplysningerRepository.kt | 3 +- .../dto/husstandsbarn/HusstandsbarnDto.kt | 1 + .../bidrag/behandling/dto/notat/NotatDto.kt | 124 +++++++++ .../behandling/service/ForskuddService.kt | 20 +- .../service/NotatOpplysningerService.kt | 256 ++++++++++++++++++ .../behandling/service/OpplysningerService.kt | 20 +- .../behandling/service/PersonService.kt | 16 ++ .../behandling/transformers/DtoExtensions.kt | 6 +- .../transformers/Forskuddsmapping.kt | 11 +- .../controller/InntekterControllerTest.kt | 113 ++------ .../controller/KontrollerTestRunner.kt | 4 + .../NotatOpplysningerControllerTest.kt | 89 ++++++ .../behandling/service/CommonTestRunner.kt | 8 +- .../service/OpplysningerServiceTest.kt | 12 +- .../nav/bidrag/behandling/utils/StubUtils.kt | 24 +- .../nav/bidrag/behandling/utils/Testdata.kt | 170 +++++++++++- .../behandling/utils/TestdataManager.kt | 53 ++++ src/test/resources/application-test.yaml | 1 + 29 files changed, 912 insertions(+), 148 deletions(-) create mode 100644 src/main/kotlin/no/nav/bidrag/behandling/controller/v1/ArbeidOgInntektController.kt create mode 100644 src/main/kotlin/no/nav/bidrag/behandling/controller/v1/NotatOpplysningerController.kt create mode 100644 src/main/kotlin/no/nav/bidrag/behandling/dto/notat/NotatDto.kt create mode 100644 src/main/kotlin/no/nav/bidrag/behandling/service/NotatOpplysningerService.kt create mode 100644 src/main/kotlin/no/nav/bidrag/behandling/service/PersonService.kt create mode 100644 src/test/kotlin/no/nav/bidrag/behandling/controller/NotatOpplysningerControllerTest.kt create mode 100644 src/test/kotlin/no/nav/bidrag/behandling/utils/TestdataManager.kt diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index a4d7ef289..b499100b8 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -15,5 +15,3 @@ jobs: with: nais_variabler_filnavn: main.yaml maven_options: -B -q -fae -Pit - - diff --git a/.nais/feature.yaml b/.nais/feature.yaml index 4e6d8817a..6cc59a6ae 100644 --- a/.nais/feature.yaml +++ b/.nais/feature.yaml @@ -15,6 +15,7 @@ env: TOPIC_VEDTAK: bidrag.vedtak-feature BIDRAG_ORGANISASJON_SCOPE: dev-fss.bidrag.bidrag-organisasjon BIDRAG_ORGANISASJON_URL: https://bidrag-organisasjon-feature.dev-fss-pub.nais.io/bidrag-organisasjon + ARBEID_OG_INNTEKT_URL: https://arbeid-og-inntekt-q1.dev-fss-pub.nais.io/api/v2 JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 kafka: pool: nav-dev @@ -42,4 +43,5 @@ outbound-access-apps: - bidrag-tilgangskontroll-feature outbound-access-hosts: - bidrag-person-feature.dev-fss-pub.nais.io - - bidrag-organisasjon-feature.dev-fss-pub.nais.io \ No newline at end of file + - bidrag-organisasjon-feature.dev-fss-pub.nais.io + - arbeid-og-inntekt-q1.dev-fss-pub.nais.io \ No newline at end of file diff --git a/.nais/main.yaml b/.nais/main.yaml index 2e090e5cc..af2406e83 100644 --- a/.nais/main.yaml +++ b/.nais/main.yaml @@ -15,6 +15,7 @@ env: BIDRAG_ORGANISASJON_SCOPE: dev-fss.bidrag.bidrag-organisasjon BIDRAG_ORGANISASJON_URL: https://bidrag-organisasjon.dev-fss-pub.nais.io/bidrag-organisasjon TOPIC_VEDTAK: bidrag.vedtak-syntetisk + ARBEID_OG_INNTEKT_URL: https://arbeid-og-inntekt.dev-fss-pub.nais.io/api/v2 JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 kafka: pool: nav-dev @@ -42,4 +43,5 @@ outbound-access-apps: - bidrag-tilgangskontroll outbound-access-hosts: - bidrag-person.dev-fss-pub.nais.io - - bidrag-organisasjon.dev-fss-pub.nais.io \ No newline at end of file + - bidrag-organisasjon.dev-fss-pub.nais.io + - arbeid-og-inntekt.dev-fss-pub.nais.io \ No newline at end of file diff --git a/.nais/prod.yaml b/.nais/prod.yaml index b056ba87d..b27799957 100644 --- a/.nais/prod.yaml +++ b/.nais/prod.yaml @@ -14,6 +14,7 @@ env: BIDRAG_TILGANGGSKONTROLL_SCOPE: prod-gcp.bidrag.bidrag-tilgangskontroll BIDRAG_ORGANISASJON_SCOPE: prod-fss.bidrag.bidrag-organisasjon BIDRAG_ORGANISASJON_URL: https://bidrag-organisasjon.prod-fss-pub.nais.io/bidrag-organisasjon + ARBEID_OG_INNTEKT_URL: https://arbeid-og-inntekt.prod-fss-pub.nais.io/api/v2 TOPIC_VEDTAK: bidrag.vedtak kafka: pool: nav-prod @@ -41,4 +42,5 @@ outbound-access-apps: - bidrag-tilgangskontroll outbound-access-hosts: - bidrag-person.prod-fss-pub.nais.io - - bidrag-organisasjon.prod-fss-pub.nais.io \ No newline at end of file + - bidrag-organisasjon.prod-fss-pub.nais.io + - arbeid-og-inntekt.prod-fss-pub.nais.io \ No newline at end of file diff --git a/pom.xml b/pom.xml index 976f5bb5e..5b4745171 100644 --- a/pom.xml +++ b/pom.xml @@ -190,7 +190,11 @@ jackson-module-kotlin ${jackson.version} - + + com.fasterxml.jackson.module + jackson-module-kotlin + ${jackson.version} + diff --git a/src/main/kotlin/no/nav/bidrag/behandling/consumer/BidragPersonConsumer.kt b/src/main/kotlin/no/nav/bidrag/behandling/consumer/BidragPersonConsumer.kt index cf9da69b2..3082e45c7 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/consumer/BidragPersonConsumer.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/consumer/BidragPersonConsumer.kt @@ -2,9 +2,9 @@ package no.nav.bidrag.behandling.consumer import no.nav.bidrag.behandling.config.CacheConfig.Companion.PERSON_CACHE import no.nav.bidrag.behandling.dto.HentPersonRequest -import no.nav.bidrag.behandling.dto.HentPersonResponse import no.nav.bidrag.commons.cache.BrukerCacheable import no.nav.bidrag.commons.web.client.AbstractRestClient +import no.nav.bidrag.transport.person.PersonDto import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service @@ -21,7 +21,7 @@ class BidragPersonConsumer( UriComponentsBuilder.fromUri(bidragPersonUrl).pathSegment("informasjon").build().toUri() @BrukerCacheable(PERSON_CACHE) - fun hentPerson(ident: String): HentPersonResponse { + fun hentPerson(ident: String): PersonDto { return postForNonNullEntity(hentPersonUri, HentPersonRequest(ident)) } } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/controller/deprecated/DeprecatedOpplysningerController.kt b/src/main/kotlin/no/nav/bidrag/behandling/controller/deprecated/DeprecatedOpplysningerController.kt index 79fd1c651..4efa5bb4d 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/controller/deprecated/DeprecatedOpplysningerController.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/controller/deprecated/DeprecatedOpplysningerController.kt @@ -41,7 +41,12 @@ class DeprecatedOpplysningerController(val opplysningerService: OpplysningerServ @RequestBody(required = true) addOpplysningerRequest: AddOpplysningerRequest, ): OpplysningerDto { val (_, _, opplysningerType, data, hentetDato) = addOpplysningerRequest - return opplysningerService.opprett(behandlingId, opplysningerType, data, hentetDato.toDate()) + return opplysningerService.opprett( + behandlingId, + opplysningerType, + data, + hentetDato.toDate(), + ) .toDto() } @@ -69,6 +74,6 @@ class DeprecatedOpplysningerController(val opplysningerService: OpplysningerServ return opplysningerService.hentSistAktiv( behandlingId, opplysningerType, - ).orElseThrow { behandlingNotFoundException(behandlingId) }.toDto() + )?.toDto() ?: behandlingNotFoundException(behandlingId) } } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/ArbeidOgInntektController.kt b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/ArbeidOgInntektController.kt new file mode 100644 index 000000000..dcdcbbcd7 --- /dev/null +++ b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/ArbeidOgInntektController.kt @@ -0,0 +1,65 @@ +package no.nav.bidrag.behandling.controller.v1 + +import mu.KotlinLogging +import no.nav.bidrag.behandling.database.datamodell.Behandlingstype +import no.nav.bidrag.behandling.service.BehandlingService +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.client.RestTemplate +import org.springframework.web.client.getForEntity + +private val log = KotlinLogging.logger {} + +data class ArbeidOgInntektLenkeRequest( + val behandlingId: Long, + val ident: String, +) + +@BehandlingRestControllerV1 +class ArbeidOgInntektController( + @Value("\${ARBEID_OG_INNTEKT_URL}") private val ainntektUrl: String, + private val behandlingService: BehandlingService, +) { + @PostMapping("/arbeidOgInntekt/ainntekt") + fun ainntektLenke( + @RequestBody request: ArbeidOgInntektLenkeRequest, + ): String { + return hentAinntektLenke(request) + } + + @PostMapping("/arbeidOgInntekt/arbeidsforhold") + fun arbeidsforholdLenke( + @RequestBody request: ArbeidOgInntektLenkeRequest, + ): String { + return hentArbeidsforholdLenke(request) + } + + private fun hentAinntektLenke(request: ArbeidOgInntektLenkeRequest): String { + val behandling = behandlingService.hentBehandlingById(request.behandlingId) + val kodeverkContext = + "$ainntektUrl/redirect/sok/a-inntekt" + val restTemplate: RestTemplate = + RestTemplateBuilder() + .defaultHeader( + "Nav-A-inntekt-Filter", + if (behandling.behandlingstype == Behandlingstype.FORSKUDD) "BidragsforskuddA-Inntekt" else "BidragA-Inntekt", + ) + .defaultHeader("Nav-Enhet", behandling.behandlerEnhet) + .defaultHeader("Nav-FagsakId", behandling.saksnummer) + .defaultHeader("Nav-Personident", request.ident) + .build() + return restTemplate.getForEntity(kodeverkContext).body!! + } + + private fun hentArbeidsforholdLenke(request: ArbeidOgInntektLenkeRequest): String { + val kodeverkContext = + "$ainntektUrl/redirect/sok/arbeidstaker" + val restTemplate: RestTemplate = + RestTemplateBuilder() + .defaultHeader("Nav-Personident", request.ident) + .build() + return restTemplate.getForEntity(kodeverkContext).body!! + } +} diff --git a/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/NotatOpplysningerController.kt b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/NotatOpplysningerController.kt new file mode 100644 index 000000000..8835a12a7 --- /dev/null +++ b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/NotatOpplysningerController.kt @@ -0,0 +1,18 @@ +package no.nav.bidrag.behandling.controller.v1 + +import no.nav.bidrag.behandling.dto.notat.NotatDto +import no.nav.bidrag.behandling.service.NotatOpplysningerService +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable + +@BehandlingRestControllerV1 +class NotatOpplysningerController( + private val notatOpplysningerService: NotatOpplysningerService, +) { + @GetMapping("/notat/{behandlingId}") + fun hentNotatOpplysninger( + @PathVariable behandlingId: Long, + ): NotatDto { + return notatOpplysningerService.hentNotatOpplysninger(behandlingId) + } +} diff --git a/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/OpplysningerController.kt b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/OpplysningerController.kt index 9070e05ff..edd7e1935 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/OpplysningerController.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/controller/v1/OpplysningerController.kt @@ -40,7 +40,12 @@ class OpplysningerController(val opplysningerService: OpplysningerService) { @RequestBody(required = true) addOpplysningerRequest: AddOpplysningerRequest, ): OpplysningerDto { val (_, _, opplysningerType, data, hentetDato) = addOpplysningerRequest - return opplysningerService.opprett(behandlingId, opplysningerType, data, hentetDato.toDate()) + return opplysningerService.opprett( + behandlingId, + opplysningerType, + data, + hentetDato.toDate(), + ) .toDto() } @@ -68,6 +73,6 @@ class OpplysningerController(val opplysningerService: OpplysningerService) { return opplysningerService.hentSistAktiv( behandlingId, opplysningerType, - ).orElseThrow { behandlingNotFoundException(behandlingId) }.toDto() + )?.toDto() ?: behandlingNotFoundException(behandlingId) } } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/database/datamodell/Sivilstand.kt b/src/main/kotlin/no/nav/bidrag/behandling/database/datamodell/Sivilstand.kt index d0a14cd62..0a52868eb 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/database/datamodell/Sivilstand.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/database/datamodell/Sivilstand.kt @@ -9,6 +9,7 @@ import jakarta.persistence.GenerationType import jakarta.persistence.Id import jakarta.persistence.JoinColumn import jakarta.persistence.ManyToOne +import no.nav.bidrag.domene.enums.person.Sivilstandskode import java.time.LocalDate // TODO: koble sammen med rolletabellen @@ -19,7 +20,8 @@ class Sivilstand( val behandling: Behandling, val datoFom: LocalDate? = null, val datoTom: LocalDate? = null, - val sivilstand: String, + @Enumerated(EnumType.STRING) + val sivilstand: Sivilstandskode, @Enumerated(EnumType.STRING) val kilde: Kilde, @Id diff --git a/src/main/kotlin/no/nav/bidrag/behandling/database/repository/OpplysningerRepository.kt b/src/main/kotlin/no/nav/bidrag/behandling/database/repository/OpplysningerRepository.kt index 9d5910ee4..69fa9644e 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/database/repository/OpplysningerRepository.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/database/repository/OpplysningerRepository.kt @@ -3,11 +3,10 @@ package no.nav.bidrag.behandling.database.repository import no.nav.bidrag.behandling.database.datamodell.Opplysninger import no.nav.bidrag.behandling.database.datamodell.OpplysningerType import org.springframework.data.repository.CrudRepository -import java.util.Optional interface OpplysningerRepository : CrudRepository { fun findTopByBehandlingIdAndOpplysningerTypeOrderByTsDescIdDesc( behandlingId: Long, opplysningerType: OpplysningerType, - ): Optional + ): Opplysninger? } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/dto/husstandsbarn/HusstandsbarnDto.kt b/src/main/kotlin/no/nav/bidrag/behandling/dto/husstandsbarn/HusstandsbarnDto.kt index b3b1ac3b7..8966a962b 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/dto/husstandsbarn/HusstandsbarnDto.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/dto/husstandsbarn/HusstandsbarnDto.kt @@ -15,4 +15,5 @@ data class HusstandsbarnDto( @Schema(type = "string", format = "date", example = "2025-01-25") @JsonFormat(pattern = "yyyy-MM-dd") val fødselsdato: LocalDate, + val foedselsdato: LocalDate = fødselsdato, ) diff --git a/src/main/kotlin/no/nav/bidrag/behandling/dto/notat/NotatDto.kt b/src/main/kotlin/no/nav/bidrag/behandling/dto/notat/NotatDto.kt new file mode 100644 index 000000000..64d2f71e3 --- /dev/null +++ b/src/main/kotlin/no/nav/bidrag/behandling/dto/notat/NotatDto.kt @@ -0,0 +1,124 @@ +package no.nav.bidrag.behandling.dto.notat + +import no.nav.bidrag.domene.enums.inntekt.Inntektsrapportering +import no.nav.bidrag.domene.enums.person.Bostatuskode +import no.nav.bidrag.domene.enums.person.Sivilstandskode +import no.nav.bidrag.domene.enums.rolle.Rolletype +import no.nav.bidrag.domene.enums.rolle.SøktAvType +import no.nav.bidrag.domene.ident.Personident +import no.nav.bidrag.domene.tid.ÅrMånedsperiode +import java.math.BigDecimal +import java.time.LocalDate +import java.time.YearMonth + +data class NotatDto( + val saksnummer: String, + val saksbehandlerNavn: String?, + val virkningstidspunkt: Virkningstidspunkt, + val boforhold: Boforhold, + val parterISøknad: List, + val inntekter: Inntekter, + val vedtak: List, +) + +data class Virkningstidspunkt( + val søknadstype: String?, + val søktAv: SøktAvType?, + val mottattDato: YearMonth?, + val søktFraDato: YearMonth?, + val virkningstidspunkt: LocalDate?, + val notat: Notat, +) + +data class Notat( + val medIVedtaket: String?, + val intern: String?, +) + +data class Boforhold( + val barn: List = emptyList(), + val sivilstand: SivilstandNotat, + val notat: Notat, +) + +data class SivilstandNotat( + val opplysningerFraFolkeregisteret: List> = emptyList(), + val opplysningerBruktTilBeregning: List> = emptyList(), +) + +data class BoforholdBarn( + val navn: String, + val fødselsdato: LocalDate?, + val opplysningerFraFolkeregisteret: List> = emptyList(), + val opplysningerBruktTilBeregning: List> = emptyList(), +) + +data class OpplysningerFraFolkeregisteret( + val periode: ÅrMånedsperiode, + val status: T?, +) + +data class OpplysningerBruktTilBeregning( + val periode: ÅrMånedsperiode, + val status: T, + val kilde: String, +) + +data class ParterISøknad( + val rolle: Rolletype, + val navn: String?, + val fødselsdato: LocalDate?, + val personident: Personident?, +) + +data class Inntekter( + val inntekterPerRolle: List, + val notat: Notat, +) + +data class InntekterPerRolle( + val rolle: Rolletype, + val arbeidsforhold: List, + val inntekterSomLeggesTilGrunn: List, + val barnetillegg: List, + val utvidetBarnetrygd: List, +) + +data class Arbeidsforhold( + val periode: ÅrMånedsperiode, + val arbeidsgiver: String, + val stillingProsent: String?, + val lønnsendringDato: LocalDate?, +) + +data class InntekterSomLeggesTilGrunn( + val inntektType: Inntektsrapportering?, + val beskrivelse: String?, + val periode: ÅrMånedsperiode?, + val beløp: BigDecimal, +) + +data class Barnetillegg( + val periode: ÅrMånedsperiode, + val beløp: BigDecimal, +) + +data class UtvidetBarnetrygd( + val periode: ÅrMånedsperiode, + val beløp: BigDecimal, +) + +data class Vedtak( + val navn: String, + val fødselsdato: LocalDate, + val resultat: List, +) + +data class Resultat( + val type: String, + val periode: ÅrMånedsperiode, + val inntekt: BigDecimal, + val sivilstand: String, + val antallBarn: Int, + val resultat: String, +) diff --git a/src/main/kotlin/no/nav/bidrag/behandling/service/ForskuddService.kt b/src/main/kotlin/no/nav/bidrag/behandling/service/ForskuddService.kt index 93038b515..5144e4894 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/service/ForskuddService.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/service/ForskuddService.kt @@ -20,7 +20,6 @@ import no.nav.bidrag.transport.behandling.felles.grunnlag.Person import org.springframework.stereotype.Service import org.springframework.web.client.HttpClientErrorException import java.time.LocalDate -import java.time.format.DateTimeFormatter private val LOGGER = KotlinLogging.logger {} @@ -33,7 +32,8 @@ class ForskuddService( fun beregneForskudd(behandlingsid: Long): Forskuddsberegningrespons { val respons = either { - val behandling = behandlingService.hentBehandlingById(behandlingsid).validere().bind() + val behandling = + behandlingService.hentBehandlingById(behandlingsid).validere().bind() val resultat = behandling.getSøknadsbarn().mapOrAccumulate { val fødselsdato = finneFødselsdato(it.ident, it.foedselsdato) @@ -43,7 +43,9 @@ class ForskuddService( fantIkkeFødselsdatoTilSøknadsbarn(behandlingsid) } - val rolleBm = behandling.roller.filter { r -> r.rolletype == Rolletype.BIDRAGSMOTTAKER }.first() + val rolleBm = + behandling.roller.filter { r -> r.rolletype == Rolletype.BIDRAGSMOTTAKER } + .first() val bm = lagePersonobjekt( rolleBm.ident, @@ -51,9 +53,12 @@ class ForskuddService( rolleBm.foedselsdato, "bidragsmottaker", ) - val søknadsbarn = lagePersonobjekt(it.ident, it.navn, fødselsdato, "søknadsbarn-${it.id}") - val øvrigeBarnIHusstand = oppretteGrunnlagForHusstandsbarn(behandling, it.ident!!) - var beregnForskudd = behandling.tilBeregnGrunnlag(bm, søknadsbarn, øvrigeBarnIHusstand) + val søknadsbarn = + lagePersonobjekt(it.ident, it.navn, fødselsdato, "søknadsbarn-${it.id}") + val øvrigeBarnIHusstand = + oppretteGrunnlagForHusstandsbarn(behandling, it.ident!!) + var beregnForskudd = + behandling.tilBeregnGrunnlag(bm, søknadsbarn, øvrigeBarnIHusstand) try { bidragBeregnForskuddConsumer.beregnForskudd(beregnForskudd) @@ -125,8 +130,7 @@ class ForskuddService( fødselsdato: LocalDate?, ): LocalDate? { return if (fødselsdato == null && ident != null) { - val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy") - LocalDate.parse(bidragPersonConsumer.hentPerson(ident).fødselsdato, formatter) + hentPersonFødselsdato(ident) } else { fødselsdato } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/service/NotatOpplysningerService.kt b/src/main/kotlin/no/nav/bidrag/behandling/service/NotatOpplysningerService.kt new file mode 100644 index 000000000..f8371f725 --- /dev/null +++ b/src/main/kotlin/no/nav/bidrag/behandling/service/NotatOpplysningerService.kt @@ -0,0 +1,256 @@ +package no.nav.bidrag.behandling.service + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.fasterxml.jackson.module.kotlin.registerKotlinModule +import no.nav.bidrag.behandling.database.datamodell.Behandling +import no.nav.bidrag.behandling.database.datamodell.Husstandsbarn +import no.nav.bidrag.behandling.database.datamodell.OpplysningerType +import no.nav.bidrag.behandling.database.datamodell.Rolle +import no.nav.bidrag.behandling.database.datamodell.Sivilstand +import no.nav.bidrag.behandling.dto.notat.Arbeidsforhold +import no.nav.bidrag.behandling.dto.notat.Barnetillegg +import no.nav.bidrag.behandling.dto.notat.Boforhold +import no.nav.bidrag.behandling.dto.notat.BoforholdBarn +import no.nav.bidrag.behandling.dto.notat.Inntekter +import no.nav.bidrag.behandling.dto.notat.InntekterPerRolle +import no.nav.bidrag.behandling.dto.notat.InntekterSomLeggesTilGrunn +import no.nav.bidrag.behandling.dto.notat.Notat +import no.nav.bidrag.behandling.dto.notat.NotatDto +import no.nav.bidrag.behandling.dto.notat.OpplysningerBruktTilBeregning +import no.nav.bidrag.behandling.dto.notat.OpplysningerFraFolkeregisteret +import no.nav.bidrag.behandling.dto.notat.ParterISøknad +import no.nav.bidrag.behandling.dto.notat.SivilstandNotat +import no.nav.bidrag.behandling.dto.notat.UtvidetBarnetrygd +import no.nav.bidrag.behandling.dto.notat.Virkningstidspunkt +import no.nav.bidrag.behandling.transformers.toLocalDate +import no.nav.bidrag.commons.security.utils.TokenUtils +import no.nav.bidrag.commons.service.organisasjon.SaksbehandlernavnProvider +import no.nav.bidrag.domene.enums.person.Bostatuskode +import no.nav.bidrag.domene.enums.person.Sivilstandskode +import no.nav.bidrag.domene.enums.rolle.Rolletype +import no.nav.bidrag.domene.ident.Personident +import no.nav.bidrag.domene.tid.ÅrMånedsperiode +import no.nav.bidrag.transport.behandling.grunnlag.response.ArbeidsforholdDto +import org.springframework.stereotype.Service +import java.time.LocalDate +import java.time.YearMonth + +private val objectmapper = ObjectMapper().findAndRegisterModules().registerKotlinModule() + +@Service +class NotatOpplysningerService( + private val behandlingService: BehandlingService, + private val opplysningerService: OpplysningerService, +) { + fun hentNotatOpplysninger(behandlingId: Long): NotatDto { + val behandling = behandlingService.hentBehandlingById(behandlingId) + val opplysningerBoforholdJson = + opplysningerService.hentSistAktiv(behandlingId, OpplysningerType.BOFORHOLD) + ?.let { objectmapper.readTree(it.data) } + val husstandGrunnlag = opplysningerBoforholdJson?.get("husstand")?.toList() ?: emptyList() + val sivilstandGrunnlag = + opplysningerBoforholdJson?.get("sivilstand")?.toList() ?: emptyList() + + val opplysningerInntektJson = + opplysningerService.hentSistAktiv(behandlingId, OpplysningerType.INNTEKTSOPPLYSNINGER) + ?.let { objectmapper.readTree(it.data) } + val arbeidsforhold: List = + opplysningerInntektJson?.get("arbeidsforhold")?.toString() + ?.let { objectmapper.readValue(it) } ?: emptyList() + return NotatDto( + saksnummer = behandling.saksnummer, + saksbehandlerNavn = + TokenUtils.hentSaksbehandlerIdent() + ?.let { SaksbehandlernavnProvider.hentSaksbehandlernavn(it) }, + virkningstidspunkt = behandling.tilVirkningstidspunkt(), + boforhold = + Boforhold( + notat = behandling.tilNotatBoforhold(), + sivilstand = behandling.tilSivilstand(sivilstandGrunnlag), + barn = + behandling.husstandsbarn.sortedBy { it.ident } + .map { it.tilBoforholdBarn(husstandGrunnlag) }, + ), + parterISøknad = behandling.roller.map(Rolle::tilPartISøknad), + inntekter = + Inntekter( + notat = behandling.tilNotatInntekt(), + inntekterPerRolle = + behandling.roller.map { + behandling.hentInntekterForIdent(it.ident!!, it.rolletype, arbeidsforhold) + }, + ), + vedtak = emptyList(), + ) + } +} + +private fun Behandling.tilNotatBoforhold() = + Notat( + medIVedtaket = boforholdsbegrunnelseIVedtakOgNotat, + intern = boforholdsbegrunnelseKunINotat, + ) + +private fun Behandling.tilNotatVirkningstidspunkt() = + Notat( + medIVedtaket = virkningstidspunktsbegrunnelseIVedtakOgNotat, + intern = virkningstidspunktbegrunnelseKunINotat, + ) + +private fun Behandling.tilNotatInntekt() = + Notat( + medIVedtaket = inntektsbegrunnelseIVedtakOgNotat, + intern = inntektsbegrunnelseKunINotat, + ) + +private fun Behandling.tilSivilstand(sivilstandGrunnlag: List) = + SivilstandNotat( + opplysningerBruktTilBeregning = + sivilstand.sortedBy { it.datoFom } + .map(Sivilstand::tilSivilstandsperiode), + opplysningerFraFolkeregisteret = + sivilstandGrunnlag.map { periode -> + OpplysningerFraFolkeregisteret( + periode = + ÅrMånedsperiode( + periode.get("datoFom").asText().takeIf { date -> date != "null" } + ?.let { date -> LocalDate.parse(date) } ?: LocalDate.now(), + periode.get("datoTom").asText().takeIf { date -> date != "null" } + ?.let { date -> LocalDate.parse(date) }, + ), + status = + periode.get("sivilstand")?.asText() + ?.let { it1 -> Sivilstandskode.valueOf(it1) }, + ) + }.sortedBy { it.periode?.fom }, + ) + +private fun Sivilstand.tilSivilstandsperiode() = + OpplysningerBruktTilBeregning( + periode = + ÅrMånedsperiode( + datoFom!!, + datoTom, + ), + status = sivilstand, + kilde = kilde.name, + ) + +private fun Behandling.tilVirkningstidspunkt() = + Virkningstidspunkt( + søknadstype = soknadstype.name, + søktAv = soknadFra, + mottattDato = YearMonth.from(mottattdato), + søktFraDato = YearMonth.from(datoFom), + virkningstidspunkt = virkningsdato, + notat = tilNotatVirkningstidspunkt(), + ) + +private fun Husstandsbarn.tilBoforholdBarn(husstandGrunnlag: List) = + BoforholdBarn( + navn = navn!!, + fødselsdato = + foedselsdato + ?: hentPersonFødselsdato(ident), + opplysningerFraFolkeregisteret = + husstandGrunnlag.filter { + it.get("ident").textValue() == this.ident + }.flatMap { + it.get("perioder")?.toList()?.map { periode -> + OpplysningerFraFolkeregisteret( + periode = + ÅrMånedsperiode( + LocalDate.parse(periode.get("fraDato").asText().split("T")[0]), + periode.get("tilDato").asText().takeIf { date -> date != "null" } + ?.let { date -> LocalDate.parse(date.split("T")[0]) }, + ), + status = + periode.get("bostatus")?.asText() + ?.let { it1 -> Bostatuskode.valueOf(it1) }, + ) + } ?: emptyList() + }, + opplysningerBruktTilBeregning = + perioder.sortedBy { it.datoFom }.map { periode -> + OpplysningerBruktTilBeregning( + periode = + ÅrMånedsperiode( + periode.datoFom!!, + periode.datoTom, + ), + status = periode.bostatus, + kilde = periode.kilde.name, + ) + }, + ) + +private fun Rolle.tilPartISøknad() = + ParterISøknad( + rolle = rolletype, + navn = hentPersonVisningsnavn(ident), + fødselsdato = foedselsdato ?: hentPersonFødselsdato(ident), + personident = ident?.let { Personident(it) }, + ) + +private fun Behandling.hentInntekterForIdent( + ident: String, + rolle: Rolletype, + arbeidsforhold: List, +) = InntekterPerRolle( + rolle = rolle, + inntekterSomLeggesTilGrunn = + inntekter.sortedBy { it.datoFom } + .filter { it.ident == ident && it.taMed } + .map { + InntekterSomLeggesTilGrunn( + beløp = it.belop, + periode = ÅrMånedsperiode(it.datoFom, it.datoTom), + beskrivelse = it.inntektstype.name, + inntektType = it.inntektstype, + ) + }, + barnetillegg = + if (rolle == Rolletype.BIDRAGSMOTTAKER) { + barnetillegg.sortedBy { it.datoFom } + .map { + Barnetillegg( + periode = + ÅrMånedsperiode( + it.datoFom!!.toLocalDate(), + it.datoTom?.toLocalDate(), + ), + beløp = it.barnetillegg, + ) + } + } else { + emptyList() + }, + utvidetBarnetrygd = + if (rolle == Rolletype.BIDRAGSMOTTAKER) { + utvidetBarnetrygd.sortedBy { it.datoFom } + .map { + UtvidetBarnetrygd( + periode = + ÅrMånedsperiode( + it.datoFom!!, + it.datoTom, + ), + beløp = it.belop, + ) + } + } else { + emptyList() + }, + arbeidsforhold = + arbeidsforhold.filter { it.partPersonId == ident } + .map { + Arbeidsforhold( + periode = ÅrMånedsperiode(it.startdato!!, it.sluttdato), + arbeidsgiver = it.arbeidsgiverNavn ?: "-", + stillingProsent = it.ansettelsesdetaljer?.firstOrNull()?.avtaltStillingsprosent?.toString(), + lønnsendringDato = it.ansettelsesdetaljer?.firstOrNull()?.sisteLønnsendringDato, + ) + }, +) diff --git a/src/main/kotlin/no/nav/bidrag/behandling/service/OpplysningerService.kt b/src/main/kotlin/no/nav/bidrag/behandling/service/OpplysningerService.kt index 18ad8e28d..29d250cb6 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/service/OpplysningerService.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/service/OpplysningerService.kt @@ -8,7 +8,6 @@ import no.nav.bidrag.behandling.database.repository.OpplysningerRepository import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.util.Date -import java.util.Optional @Service class OpplysningerService( @@ -23,15 +22,26 @@ class OpplysningerService( hentetDato: Date, ): Opplysninger { behandlingRepository - .findBehandlingById(behandlingId).orElseThrow { behandlingNotFoundException(behandlingId) } + .findBehandlingById(behandlingId) + .orElseThrow { behandlingNotFoundException(behandlingId) } .let { - return opplysningerRepository.save(Opplysninger(it, opplysningerType, data, hentetDato)) + return opplysningerRepository.save( + Opplysninger( + it, + opplysningerType, + data, + hentetDato, + ), + ) } } fun hentSistAktiv( behandlingId: Long, opplysningerType: OpplysningerType, - ): Optional = - opplysningerRepository.findTopByBehandlingIdAndOpplysningerTypeOrderByTsDescIdDesc(behandlingId, opplysningerType) + ): Opplysninger? = + opplysningerRepository.findTopByBehandlingIdAndOpplysningerTypeOrderByTsDescIdDesc( + behandlingId, + opplysningerType, + ) } diff --git a/src/main/kotlin/no/nav/bidrag/behandling/service/PersonService.kt b/src/main/kotlin/no/nav/bidrag/behandling/service/PersonService.kt new file mode 100644 index 000000000..561632fb3 --- /dev/null +++ b/src/main/kotlin/no/nav/bidrag/behandling/service/PersonService.kt @@ -0,0 +1,16 @@ +package no.nav.bidrag.behandling.service + +import no.nav.bidrag.behandling.consumer.BidragPersonConsumer +import no.nav.bidrag.commons.service.AppContext +import no.nav.bidrag.transport.person.PersonDto + +fun hentPerson(ident: String?): PersonDto? = + try { + ident?.let { AppContext.getBean(BidragPersonConsumer::class.java).hentPerson(ident) } + } catch (e: Exception) { + null + } + +fun hentPersonFødselsdato(ident: String?) = hentPerson(ident)?.fødselsdato + +fun hentPersonVisningsnavn(ident: String?) = hentPerson(ident)?.visningsnavn diff --git a/src/main/kotlin/no/nav/bidrag/behandling/transformers/DtoExtensions.kt b/src/main/kotlin/no/nav/bidrag/behandling/transformers/DtoExtensions.kt index 71b536d8c..739bbf727 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/transformers/DtoExtensions.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/transformers/DtoExtensions.kt @@ -31,14 +31,14 @@ fun Set.toSivilstandDto() = it.id, it.datoFom, it.datoTom, - it.sivilstand.tilSivilstandskodeForBeregning(), + it.sivilstand, it.kilde, ) }.toSet() fun Set.toSivilstandDomain(behandling: Behandling) = this.map { - Sivilstand(behandling, it.datoFom, it.datoTom, it.sivilstand.name, it.kilde, it.id) + Sivilstand(behandling, it.datoFom, it.datoTom, it.sivilstand, it.kilde, it.id) }.toMutableSet() fun Set.toBarnetilleggDto() = @@ -103,7 +103,7 @@ fun Set.toDomain(husstandsBarn: Husstandsbarn) = husstandsBarn, it.datoFom, it.datoTom, - it.bostatus, + it.bostatus!!, it.kilde, ) }.toSet() diff --git a/src/main/kotlin/no/nav/bidrag/behandling/transformers/Forskuddsmapping.kt b/src/main/kotlin/no/nav/bidrag/behandling/transformers/Forskuddsmapping.kt index e5b156414..5fcb3cb76 100644 --- a/src/main/kotlin/no/nav/bidrag/behandling/transformers/Forskuddsmapping.kt +++ b/src/main/kotlin/no/nav/bidrag/behandling/transformers/Forskuddsmapping.kt @@ -45,7 +45,7 @@ fun Behandling.tilGrunnlagSivilstand(bm: Grunnlag): Set { innhold = POJONode( SivilstandPeriode( - sivilstand = it.sivilstand.tilSivilstandskodeForBeregning(), + sivilstand = it.sivilstand, periode = ÅrMånedsperiode(it.datoFom!!, it.datoTom), ), ), @@ -58,8 +58,13 @@ fun Behandling.tilGrunnlagBostatus(grunnlagBarn: Set): Set { val mapper = jacksonObjectMapper() grunnlagBarn.forEach { val barn = mapper.treeToValue(it.innhold, Person::class.java) - val bostatusperioderForBarn = this.husstandsbarn.filter { hb -> hb.ident == barn.ident.verdi }.first() - bostatusperiodegrunnlag + oppretteGrunnlagForBostatusperioder(it.referanse!!, bostatusperioderForBarn.perioder) + val bostatusperioderForBarn = + this.husstandsbarn.filter { hb -> hb.ident == barn.ident.verdi }.first() + bostatusperiodegrunnlag + + oppretteGrunnlagForBostatusperioder( + it.referanse!!, + bostatusperioderForBarn.perioder, + ) } return bostatusperiodegrunnlag } diff --git a/src/test/kotlin/no/nav/bidrag/behandling/controller/InntekterControllerTest.kt b/src/test/kotlin/no/nav/bidrag/behandling/controller/InntekterControllerTest.kt index e6e73568c..159efc0f9 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/controller/InntekterControllerTest.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/controller/InntekterControllerTest.kt @@ -4,20 +4,13 @@ import io.kotest.assertions.assertSoftly import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import jakarta.persistence.EntityManager -import no.nav.bidrag.behandling.database.datamodell.Behandling -import no.nav.bidrag.behandling.database.datamodell.Inntekt -import no.nav.bidrag.behandling.database.datamodell.Inntektspost import no.nav.bidrag.behandling.database.repository.BehandlingRepository import no.nav.bidrag.behandling.dto.inntekt.InntektDto import no.nav.bidrag.behandling.dto.inntekt.InntekterResponse import no.nav.bidrag.behandling.dto.inntekt.OppdatereInntekterRequest import no.nav.bidrag.behandling.service.BehandlingService -import no.nav.bidrag.behandling.utils.oppretteBehandling import no.nav.bidrag.domene.enums.inntekt.Inntektsrapportering import no.nav.bidrag.transport.behandling.inntekt.response.InntektPost -import org.hibernate.engine.spi.SessionImplementor -import org.hibernate.resource.transaction.spi.TransactionStatus import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested @@ -39,9 +32,6 @@ class InntekterControllerTest : KontrollerTestRunner() { @Autowired lateinit var behandlingService: BehandlingService - @Autowired - lateinit var entityManager: EntityManager - @BeforeEach fun oppsett() { behandlingRepository.deleteAll() @@ -53,19 +43,12 @@ class InntekterControllerTest : KontrollerTestRunner() { @Test fun `skal hente inntekter for behandling`() { // given - var behandling = behandlingRepository.save(behandling()) - - var inntekt = inntekt(behandling) - inntekt.inntektsposter = inntektsposter(inntekt) - behandling.inntekter = setOf(inntekt).toMutableSet() - behandlingRepository.save(behandling) - - var lagretBehandlingMedInntekter = behandlingRepository.findAll().iterator().next() + val behandling = testdataManager.opprettBehandling() // when val r1 = httpHeaderTestRestTemplate.exchange( - "${rootUri()}/behandling/${lagretBehandlingMedInntekter.id}/inntekter", + "${rootUri()}/behandling/${behandling.id}/inntekter", HttpMethod.GET, HttpEntity.EMPTY, InntekterResponse::class.java, @@ -76,23 +59,19 @@ class InntekterControllerTest : KontrollerTestRunner() { r1 shouldNotBe null r1.statusCode shouldBe HttpStatus.OK r1.body shouldNotBe null - r1.body!!.inntekter.size shouldBeExactly 1 + r1.body!!.inntekter.size shouldBeExactly 3 } } @Test fun `skal returnere tom liste av inntekter for behandling som mangler inntekter`() { // given - var behandling = behandling() - - behandlingRepository.save(behandling) - - var lagretBehandlingUtenInntekter = behandlingRepository.findAll().iterator().next() + val behandling = testdataManager.opprettBehandling(false) // when val r1 = httpHeaderTestRestTemplate.exchange( - "${rootUri()}/behandling/${lagretBehandlingUtenInntekter.id}/inntekter", + "${rootUri()}/behandling/${behandling.id}/inntekter", HttpMethod.GET, HttpEntity.EMPTY, InntekterResponse::class.java, @@ -115,17 +94,16 @@ class InntekterControllerTest : KontrollerTestRunner() { @Transactional open fun `skal opprette inntekter`() { // given - lagreBehandlingIEgenTransaksjon(false) - var lagretBehandlingUtenInntekter = behandlingRepository.findAll().iterator().next() + val behandling = testdataManager.opprettBehandling(false) - assert(lagretBehandlingUtenInntekter.inntekter.size == 0) + assert(behandling.inntekter.size == 0) val inn = testInntektDto() // when val r = httpHeaderTestRestTemplate.exchange( - "${rootUri()}/behandling/${lagretBehandlingUtenInntekter.id}/inntekter", + "${rootUri()}/behandling/${behandling.id}/inntekter", HttpMethod.PUT, HttpEntity(OppdatereInntekterRequest(setOf(inn), emptySet(), emptySet())), InntekterResponse::class.java, @@ -140,10 +118,9 @@ class InntekterControllerTest : KontrollerTestRunner() { @Transactional open fun `skal oppdatere eksisterende inntekter`() { // given - lagreBehandlingIEgenTransaksjon(true) - var lagretBehandlingMedInntekter = behandlingRepository.findAll().iterator().next() + val behandling = testdataManager.opprettBehandling(true) - assert(lagretBehandlingMedInntekter.inntekter.size > 0) + assert(behandling.inntekter.size > 0) // when val inntekt1 = @@ -164,9 +141,15 @@ class InntekterControllerTest : KontrollerTestRunner() { val r1 = httpHeaderTestRestTemplate.exchange( - "${rootUri()}/behandling/${lagretBehandlingMedInntekter.id}/inntekter", + "${rootUri()}/behandling/${behandling.id}/inntekter", HttpMethod.PUT, - HttpEntity(OppdatereInntekterRequest(setOf(inntekt1, inntekt2), setOf(), setOf())), + HttpEntity( + OppdatereInntekterRequest( + setOf(inntekt1, inntekt2), + setOf(), + setOf(), + ), + ), InntekterResponse::class.java, ) @@ -186,15 +169,14 @@ class InntekterControllerTest : KontrollerTestRunner() { @Transactional open fun `skal slette inntekter`() { // given - lagreBehandlingIEgenTransaksjon(true) - var lagretBehandlingMedInntekter = behandlingRepository.findAll().iterator().next() + val behandling = testdataManager.opprettBehandling(true) - assert(lagretBehandlingMedInntekter.inntekter.size > 0) + assert(behandling.inntekter.size > 0) // when val r = httpHeaderTestRestTemplate.exchange( - "${rootUri()}/behandling/${lagretBehandlingMedInntekter.id}/inntekter", + "${rootUri()}/behandling/${behandling.id}/inntekter", HttpMethod.PUT, HttpEntity(OppdatereInntekterRequest(emptySet(), emptySet(), emptySet())), InntekterResponse::class.java, @@ -206,49 +188,6 @@ class InntekterControllerTest : KontrollerTestRunner() { } } - private fun lagreBehandlingIEgenTransaksjon(inkludereInntekter: Boolean) { - val sessionImplementor = entityManager.delegate as SessionImplementor - var transaction = sessionImplementor.transaction - - var transactionStatus = transaction.status - if (TransactionStatus.NOT_ACTIVE == transactionStatus) { - transaction.begin() - } - - var behandling = behandling() - - if (inkludereInntekter) { - var inntekt = inntekt(behandling) - inntekt.inntektsposter = inntektsposter(inntekt) - behandling.inntekter = setOf(inntekt).toMutableSet() - } - - entityManager?.persist(behandling) - transaction.commit() - } - - private fun inntekt(behandling: Behandling) = - Inntekt( - Inntektsrapportering.INNTEKTSOPPLYSNINGER_ARBEIDSGIVER, - BigDecimal.valueOf(45000), - LocalDate.now().minusYears(1).withDayOfYear(1), - LocalDate.now().minusYears(1).withMonth(12).withDayOfMonth(31), - "1234", - true, - true, - behandling = behandling, - ) - - private fun inntektsposter(inntekt: Inntekt): MutableSet = - setOf( - Inntektspost( - BigDecimal.valueOf(400000), - "lønnFraFluefiske", - "Lønn fra fluefiske", - inntekt = inntekt, - ), - ).toMutableSet() - private fun testInntektDto() = InntektDto( null, @@ -261,14 +200,4 @@ class InntekterControllerTest : KontrollerTestRunner() { true, setOf(InntektPost("ABC", "ABC", BigDecimal.TEN)), ) - - private fun behandling(): Behandling { - val behandling: Behandling = - behandlingRepository.save( - oppretteBehandling(), - ) - return behandling - } - - fun createBehandling(): Behandling = behandlingService.createBehandling(behandling()) } diff --git a/src/test/kotlin/no/nav/bidrag/behandling/controller/KontrollerTestRunner.kt b/src/test/kotlin/no/nav/bidrag/behandling/controller/KontrollerTestRunner.kt index 0f43fea2a..c4c39ca3e 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/controller/KontrollerTestRunner.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/controller/KontrollerTestRunner.kt @@ -3,6 +3,7 @@ package no.nav.bidrag.behandling.controller import StubUtils import com.github.tomakehurst.wiremock.client.WireMock import no.nav.bidrag.behandling.service.CommonTestRunner +import no.nav.bidrag.behandling.utils.TestdataManager import no.nav.bidrag.commons.web.test.HttpHeaderTestRestTemplate import org.junit.jupiter.api.BeforeEach import org.springframework.beans.factory.annotation.Autowired @@ -15,6 +16,9 @@ abstract class KontrollerTestRunner : CommonTestRunner() { @Autowired lateinit var httpHeaderTestRestTemplate: HttpHeaderTestRestTemplate + @Autowired + lateinit var testdataManager: TestdataManager + val stubUtils: StubUtils = StubUtils() protected fun rootUri(): String { diff --git a/src/test/kotlin/no/nav/bidrag/behandling/controller/NotatOpplysningerControllerTest.kt b/src/test/kotlin/no/nav/bidrag/behandling/controller/NotatOpplysningerControllerTest.kt new file mode 100644 index 000000000..63165010f --- /dev/null +++ b/src/test/kotlin/no/nav/bidrag/behandling/controller/NotatOpplysningerControllerTest.kt @@ -0,0 +1,89 @@ +package no.nav.bidrag.behandling.controller + +import io.kotest.assertions.assertSoftly +import io.kotest.matchers.collections.shouldBeIn +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.shouldBe +import no.nav.bidrag.behandling.database.datamodell.Rolle +import no.nav.bidrag.behandling.dto.notat.NotatDto +import no.nav.bidrag.behandling.utils.SAKSNUMMER +import no.nav.bidrag.behandling.utils.testdataBM +import no.nav.bidrag.behandling.utils.testdataBarn1 +import no.nav.bidrag.behandling.utils.testdataBarn2 +import no.nav.bidrag.domene.enums.rolle.Rolletype +import no.nav.bidrag.domene.enums.rolle.SøktAvType +import org.junit.jupiter.api.Test +import org.springframework.http.HttpEntity +import org.springframework.http.HttpMethod +import org.springframework.http.HttpStatus +import java.time.LocalDate +import java.time.YearMonth + +class NotatOpplysningerControllerTest : KontrollerTestRunner() { + @Test + fun `skal hente opplysninger for notat`() { + val behandling = testdataManager.opprettBehandling() + stubUtils.stubHentePersoninfo( + personident = testdataBM[Rolle::ident.name] as String, + navn = testdataBM[Rolle::navn.name] as String, + shouldContaintPersonIdent = true, + ) + stubUtils.stubHentePersoninfo( + personident = testdataBarn1[Rolle::ident.name] as String, + navn = testdataBarn1[Rolle::navn.name] as String, + shouldContaintPersonIdent = true, + ) + stubUtils.stubHentePersoninfo( + personident = testdataBarn2[Rolle::ident.name] as String, + navn = testdataBarn2[Rolle::navn.name] as String, + shouldContaintPersonIdent = true, + ) + val r1 = + httpHeaderTestRestTemplate.exchange( + "${rootUri()}/notat/${behandling.id}", + HttpMethod.GET, + HttpEntity.EMPTY, + NotatDto::class.java, + ) + + r1.statusCode shouldBe HttpStatus.OK + + val notatResponse = r1.body!! + + assertSoftly { + notatResponse.saksnummer shouldBe SAKSNUMMER + notatResponse.saksbehandlerNavn shouldBe "Fornavn Etternavn" + notatResponse.virkningstidspunkt.søktAv shouldBe SøktAvType.BIDRAGSMOTTAKER + notatResponse.virkningstidspunkt.virkningstidspunkt shouldBe LocalDate.parse("2023-02-01") + notatResponse.virkningstidspunkt.søktFraDato shouldBe YearMonth.parse("2022-08") + notatResponse.virkningstidspunkt.mottattDato shouldBe YearMonth.parse("2023-03") + notatResponse.virkningstidspunkt.notat.medIVedtaket shouldBe "notat virkning med i vedtak" + notatResponse.virkningstidspunkt.notat.intern shouldBe "notat virkning" + + notatResponse.inntekter.inntekterPerRolle shouldHaveSize 3 + notatResponse.boforhold.barn shouldHaveSize 2 + notatResponse.boforhold.sivilstand.opplysningerBruktTilBeregning shouldHaveSize 2 + + val barn1 = + notatResponse.parterISøknad.find { it.personident?.verdi == testdataBarn1[Rolle::ident.name] as String }!! + barn1.navn shouldBe testdataBarn1[Rolle::navn.name] as String + barn1.rolle shouldBe Rolletype.BARN + barn1.fødselsdato shouldBe testdataBarn1[Rolle::foedselsdato.name] + + val inntekterBM = + notatResponse.inntekter.inntekterPerRolle.find { it.rolle == Rolletype.BIDRAGSMOTTAKER }!! + inntekterBM.inntekterSomLeggesTilGrunn shouldHaveSize 3 + + notatResponse.boforhold.barn[0].navn shouldBeIn + listOf( + testdataBarn1[Rolle::navn.name] as String, + testdataBarn2[Rolle::navn.name] as String, + ) + notatResponse.boforhold.barn[1].navn shouldBeIn + listOf( + testdataBarn1[Rolle::navn.name] as String, + testdataBarn2[Rolle::navn.name] as String, + ) + } + } +} diff --git a/src/test/kotlin/no/nav/bidrag/behandling/service/CommonTestRunner.kt b/src/test/kotlin/no/nav/bidrag/behandling/service/CommonTestRunner.kt index e0c89da88..9e880dde9 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/service/CommonTestRunner.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/service/CommonTestRunner.kt @@ -1,13 +1,19 @@ package no.nav.bidrag.behandling.service import no.nav.bidrag.behandling.BehandlingAppTest +import no.nav.bidrag.commons.service.AppContext import no.nav.security.token.support.spring.test.EnableMockOAuth2Server import org.springframework.boot.test.context.SpringBootTest import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock +import org.springframework.context.annotation.Import import org.springframework.test.context.ActiveProfiles @ActiveProfiles("test") -@SpringBootTest(classes = [BehandlingAppTest::class], webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest( + classes = [BehandlingAppTest::class], + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, +) @AutoConfigureWireMock(port = 0) @EnableMockOAuth2Server +@Import(AppContext::class) abstract class CommonTestRunner diff --git a/src/test/kotlin/no/nav/bidrag/behandling/service/OpplysningerServiceTest.kt b/src/test/kotlin/no/nav/bidrag/behandling/service/OpplysningerServiceTest.kt index 73d643213..5c7fcd816 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/service/OpplysningerServiceTest.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/service/OpplysningerServiceTest.kt @@ -7,13 +7,13 @@ import no.nav.bidrag.behandling.database.datamodell.OpplysningerType import no.nav.bidrag.behandling.database.datamodell.Soknadstype import no.nav.bidrag.domene.enums.rolle.SøktAvType import no.nav.bidrag.domene.enums.vedtak.Engangsbeløptype -import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import java.time.LocalDate import java.util.Date import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.assertNotNull +import kotlin.test.assertNull class OpplysningerServiceTest : TestContainerRunner() { @Autowired @@ -25,7 +25,7 @@ class OpplysningerServiceTest : TestContainerRunner() { @Test fun `hente opplysninger`() { val res = opplysningerService.hentSistAktiv(1, OpplysningerType.BOFORHOLD) - assertFalse(res.isPresent) + assertNull(res) } @Test @@ -52,9 +52,9 @@ class OpplysningerServiceTest : TestContainerRunner() { ) val opp4 = opplysningerService.opprett(b.id!!, OpplysningerType.BOFORHOLD, "data", Date(1)) - val option = opplysningerService.hentSistAktiv(b.id!!, OpplysningerType.BOFORHOLD) + val opplysninger = opplysningerService.hentSistAktiv(b.id!!, OpplysningerType.BOFORHOLD) - assertTrue(option.isPresent) - assertEquals(opp4.id, option.get().id) + assertNotNull(opplysninger) + assertEquals(opp4.id, opplysninger.id) } } diff --git a/src/test/kotlin/no/nav/bidrag/behandling/utils/StubUtils.kt b/src/test/kotlin/no/nav/bidrag/behandling/utils/StubUtils.kt index b42566c4c..7a2e48c49 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/utils/StubUtils.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/utils/StubUtils.kt @@ -1,6 +1,5 @@ import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.databind.ObjectMapper -import com.github.tomakehurst.wiremock.WireMockServer import com.github.tomakehurst.wiremock.client.CountMatchingStrategy import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder import com.github.tomakehurst.wiremock.client.WireMock @@ -9,14 +8,14 @@ import com.github.tomakehurst.wiremock.matching.ContainsPattern import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder import no.nav.bidrag.behandling.consumer.ForsendelseResponsTo import no.nav.bidrag.behandling.consumer.OpprettForsendelseRespons -import no.nav.bidrag.behandling.dto.HentPersonResponse import no.nav.bidrag.behandling.utils.opprettForsendelseResponsUnderOpprettelse -import no.nav.bidrag.commons.service.AppContext import no.nav.bidrag.commons.service.organisasjon.SaksbehandlerInfoResponse import no.nav.bidrag.domene.enums.grunnlag.Grunnlagstype +import no.nav.bidrag.domene.ident.Personident import no.nav.bidrag.domene.tid.ÅrMånedsperiode import no.nav.bidrag.transport.behandling.beregning.felles.BeregnGrunnlag import no.nav.bidrag.transport.behandling.beregning.felles.Grunnlag +import no.nav.bidrag.transport.person.PersonDto import org.junit.Assert import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus @@ -93,17 +92,26 @@ class StubUtils { fun stubHentePersoninfo( status: HttpStatus = HttpStatus.OK, personident: String, + navn: String = "Navn Navnesen", + shouldContaintPersonIdent: Boolean = false, ) { + var postRequest = WireMock.post(WireMock.urlMatching("/bidrag-person/informasjon")) + + if (shouldContaintPersonIdent) { + postRequest = postRequest.withRequestBody(ContainsPattern(personident)) + } + WireMock.stubFor( - WireMock.post(WireMock.urlMatching("/bidrag-person/informasjon")) + postRequest .willReturn( aClosedJsonResponse() .withStatus(status.value()) .withBody( toJsonString( - HentPersonResponse( - personident, - fødselsdato = LocalDate.now().minusMonths(500).toString(), + PersonDto( + ident = Personident(personident), + fødselsdato = LocalDate.now().minusMonths(500), + visningsnavn = navn, ), ), ), @@ -155,7 +163,7 @@ class StubUtils { } fun stubHentSaksbehandler() { - AppContext.getBean(WireMockServer::class.java).stubFor( + WireMock.stubFor( WireMock.get(WireMock.urlMatching("/organisasjon/saksbehandler/info/(.*)")).willReturn( aResponse() .withHeader(HttpHeaders.CONNECTION, "close") diff --git a/src/test/kotlin/no/nav/bidrag/behandling/utils/Testdata.kt b/src/test/kotlin/no/nav/bidrag/behandling/utils/Testdata.kt index 8afc2856f..36b5020be 100644 --- a/src/test/kotlin/no/nav/bidrag/behandling/utils/Testdata.kt +++ b/src/test/kotlin/no/nav/bidrag/behandling/utils/Testdata.kt @@ -6,12 +6,23 @@ import no.nav.bidrag.behandling.consumer.ForsendelseStatusTo import no.nav.bidrag.behandling.consumer.ForsendelseTypeTo import no.nav.bidrag.behandling.database.datamodell.Behandling import no.nav.bidrag.behandling.database.datamodell.Behandlingstype +import no.nav.bidrag.behandling.database.datamodell.Husstandsbarn +import no.nav.bidrag.behandling.database.datamodell.Husstandsbarnperiode +import no.nav.bidrag.behandling.database.datamodell.Inntekt +import no.nav.bidrag.behandling.database.datamodell.Inntektspost +import no.nav.bidrag.behandling.database.datamodell.Kilde import no.nav.bidrag.behandling.database.datamodell.Rolle +import no.nav.bidrag.behandling.database.datamodell.Sivilstand import no.nav.bidrag.behandling.database.datamodell.Soknadstype import no.nav.bidrag.behandling.dto.forsendelse.ForsendelseRolleDto +import no.nav.bidrag.domene.enums.inntekt.Inntektsrapportering +import no.nav.bidrag.domene.enums.person.Bostatuskode +import no.nav.bidrag.domene.enums.person.Sivilstandskode import no.nav.bidrag.domene.enums.rolle.Rolletype import no.nav.bidrag.domene.enums.rolle.SøktAvType +import no.nav.bidrag.domene.enums.vedtak.Stønadstype import no.nav.bidrag.domene.ident.Personident +import java.math.BigDecimal import java.time.LocalDate import java.time.YearMonth @@ -21,6 +32,30 @@ val ROLLE_BM = ForsendelseRolleDto(Personident("313213213"), type = Rolletype.BI val ROLLE_BA_1 = ForsendelseRolleDto(Personident("1344124"), type = Rolletype.BARN) val ROLLE_BP = ForsendelseRolleDto(Personident("213244124"), type = Rolletype.BIDRAGSPLIKTIG) +val testdataBM = + mapOf( + Rolle::navn.name to "Oran Mappe", + Rolle::ident.name to "1232134544", + Rolle::rolletype.name to Rolletype.BIDRAGSMOTTAKER, + Rolle::foedselsdato.name to LocalDate.parse("2020-03-01"), + ) + +val testdataBarn1 = + mapOf( + Rolle::navn.name to "Kran Mappe", + Rolle::ident.name to "6216464366", + Rolle::rolletype.name to Rolletype.BARN, + Rolle::foedselsdato.name to LocalDate.parse("2020-03-01"), + ) + +val testdataBarn2 = + mapOf( + Rolle::navn.name to "Gran Mappe", + Rolle::ident.name to "123312312", + Rolle::rolletype.name to Rolletype.BARN, + Rolle::foedselsdato.name to LocalDate.parse("2018-05-09"), + ) + fun opprettForsendelseResponsUnderOpprettelse(forsendelseId: Long = 1) = ForsendelseResponsTo( forsendelseId = forsendelseId, @@ -38,23 +73,144 @@ fun oppretteBehandling(): Behandling { return Behandling( Behandlingstype.FORSKUDD, Soknadstype.FASTSETTELSE, - datoFom = YearMonth.now().atDay(1).minusMonths(16), + datoFom = YearMonth.parse("2022-08").atEndOfMonth(), datoTom = YearMonth.now().plusMonths(10).atEndOfMonth(), - mottattdato = LocalDate.now(), - "1900000", - 123, + mottattdato = LocalDate.parse("2023-03-15"), + SAKSNUMMER, + SOKNAD_ID, null, - "ENH", + "4806", "Z9999", "Navn Navnesen", "bisys", SøktAvType.BIDRAGSMOTTAKER, + Stønadstype.FORSKUDD, null, - null, - virkningsdato = LocalDate.now(), + virkningsdato = LocalDate.parse("2023-02-01"), + ) +} + +fun opprettInntekt( + behandling: Behandling, + data: Map, +) = Inntekt( + Inntektsrapportering.AINNTEKT_BEREGNET_12MND, + BigDecimal.valueOf(45000), + LocalDate.now().minusYears(1).withDayOfYear(1), + LocalDate.now().minusYears(1).withMonth(12).withDayOfMonth(31), + data[Rolle::ident.name] as String, + true, + true, + behandling = behandling, +) + +fun opprettInntekter( + behandling: Behandling, + data: Map, +) = mutableSetOf( + Inntekt( + Inntektsrapportering.AINNTEKT_BEREGNET_12MND, + BigDecimal.valueOf(45000), + LocalDate.parse("2023-01-01"), + LocalDate.parse("2023-12-31"), + data[Rolle::ident.name] as String, + true, + true, + behandling = behandling, + ), + Inntekt( + Inntektsrapportering.LIGNINGSINNTEKT, + BigDecimal.valueOf(33000), + LocalDate.parse("2023-01-01"), + LocalDate.parse("2023-12-31"), + data[Rolle::ident.name] as String, + true, + true, + behandling = behandling, + ), + Inntekt( + Inntektsrapportering.SAKSBEHANDLER_BEREGNET_INNTEKT, + BigDecimal.valueOf(55000), + LocalDate.parse("2022-01-01"), + LocalDate.parse("2022-12-31"), + data[Rolle::ident.name] as String, + false, + true, + behandling = behandling, + ), +) + +fun opprettInntektsposter(inntekt: Inntekt): MutableSet = + setOf( + Inntektspost( + BigDecimal.valueOf(400000), + "lønnFraFluefiske", + "Lønn fra fluefiske", + inntekt = inntekt, + ), + ).toMutableSet() + +fun opprettSivilstand( + behandling: Behandling, + datoFom: LocalDate = LocalDate.parse("2023-01-01"), + datoTom: LocalDate? = null, + sivilstand: Sivilstandskode = Sivilstandskode.BOR_ALENE_MED_BARN, +): Sivilstand { + return Sivilstand( + behandling = behandling, + datoFom = datoFom, + datoTom = datoTom, + sivilstand = sivilstand, + kilde = Kilde.OFFENTLIG, + ) +} + +fun opprettRolle( + behandling: Behandling, + data: Map, +): Rolle { + return Rolle( + navn = data[Rolle::navn.name] as String, + ident = data[Rolle::ident.name] as String, + rolletype = data[Rolle::rolletype.name] as Rolletype, + behandling = behandling, + foedselsdato = data[Rolle::foedselsdato.name] as LocalDate, + opprettetDato = LocalDate.now(), ) } +fun opprettHusstandsbarn( + behandling: Behandling, + data: Map, +): Husstandsbarn { + val husstandsbarn = + Husstandsbarn( + navn = data[Rolle::navn.name] as String, + ident = data[Rolle::ident.name] as String, + medISaken = true, + behandling = behandling, + foedselsdato = data[Rolle::foedselsdato.name] as LocalDate, + ) + husstandsbarn.perioder = + mutableSetOf( + Husstandsbarnperiode( + datoFom = LocalDate.parse("2023-01-01"), + datoTom = LocalDate.parse("2023-05-31"), + bostatus = Bostatuskode.MED_FORELDER, + kilde = Kilde.OFFENTLIG, + husstandsbarn = husstandsbarn, + ), + Husstandsbarnperiode( + datoFom = LocalDate.parse("2023-05-31"), + datoTom = null, + bostatus = Bostatuskode.IKKE_MED_FORELDER, + kilde = Kilde.OFFENTLIG, + husstandsbarn = husstandsbarn, + ), + ) + return husstandsbarn +} + fun oppretteBehandlingRoller(behandling: Behandling) = mutableSetOf( Rolle( diff --git a/src/test/kotlin/no/nav/bidrag/behandling/utils/TestdataManager.kt b/src/test/kotlin/no/nav/bidrag/behandling/utils/TestdataManager.kt new file mode 100644 index 000000000..00e73905a --- /dev/null +++ b/src/test/kotlin/no/nav/bidrag/behandling/utils/TestdataManager.kt @@ -0,0 +1,53 @@ +package no.nav.bidrag.behandling.utils + +import jakarta.transaction.Transactional +import no.nav.bidrag.behandling.database.datamodell.Behandling +import no.nav.bidrag.behandling.database.repository.BehandlingRepository +import no.nav.bidrag.domene.enums.person.Sivilstandskode +import org.springframework.stereotype.Component +import java.time.LocalDate + +@Component +class TestdataManager(private val behandlingRepository: BehandlingRepository) { + @Transactional(Transactional.TxType.REQUIRES_NEW) + fun opprettBehandling(inkluderInntekter: Boolean = true): Behandling { + val behandling = oppretteBehandling() + behandling.virkningstidspunktsbegrunnelseIVedtakOgNotat = "notat virkning med i vedtak" + behandling.virkningstidspunktbegrunnelseKunINotat = "notat virkning" + behandling.husstandsbarn = + mutableSetOf( + opprettHusstandsbarn(behandling, testdataBarn1), + opprettHusstandsbarn(behandling, testdataBarn2), + ) + behandling.roller = + mutableSetOf( + opprettRolle(behandling, testdataBarn1), + opprettRolle(behandling, testdataBarn2), + opprettRolle(behandling, testdataBM), + ) + behandling.sivilstand = + mutableSetOf( + opprettSivilstand( + behandling, + LocalDate.parse("2023-01-01"), + LocalDate.parse("2023-05-31"), + Sivilstandskode.BOR_ALENE_MED_BARN, + ), + opprettSivilstand( + behandling, + LocalDate.parse("2023-06-01"), + null, + Sivilstandskode.BOR_ALENE_MED_BARN, + ), + ) + + if (inkluderInntekter) { + behandling.inntekter = opprettInntekter(behandling, testdataBM) + behandling.inntekter.forEach { + it.inntektsposter = opprettInntektsposter(it) + } + } + + return behandlingRepository.save(behandling) + } +} diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index 2d11b66f4..19790f9d6 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -4,6 +4,7 @@ BIDRAG_GRUNNLAG_URL: http://localhost:${wiremock.server.port}/grunnlag BIDRAG_FORSENDELSE_URL: http://localhost:${wiremock.server.port}/forsendelse BIDRAG_TILGANGSKONTROLL_URL: http://localhost:${wiremock.server.port}/tilgangskontroll BIDRAG_ORGANISASJON_URL: http://localhost:${wiremock.server.port}/organisasjon +ARBEID_OG_INNTEKT_URL: http://localhost:${wiremock.server.port}/ainntekt AZURE_OPENID_CONFIG_ISSUER: http://localhost:${mock-oauth2-server.port}/aad AZURE_APP_TENANT_ID: 12321321-123213-3213123 AZURE_APP_CLIENT_ID: asdasd-sadas-ddas-qwe