diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/InntektApi.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/InntektApi.kt index 81aa9942..4b65d5ba 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/InntektApi.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/InntektApi.kt @@ -32,6 +32,11 @@ import io.micrometer.prometheusmetrics.PrometheusConfig import io.micrometer.prometheusmetrics.PrometheusMeterRegistry import io.prometheus.metrics.model.registry.PrometheusRegistry import mu.KotlinLogging +import no.nav.dagpenger.inntekt.api.v1.enhetsregisteret +import no.nav.dagpenger.inntekt.api.v1.inntekt +import no.nav.dagpenger.inntekt.api.v1.opptjeningsperiodeApi +import no.nav.dagpenger.inntekt.api.v1.uklassifisertInntekt +import no.nav.dagpenger.inntekt.api.v3.inntektV3 import no.nav.dagpenger.inntekt.db.IllegalInntektIdException import no.nav.dagpenger.inntekt.db.InntektNotFoundException import no.nav.dagpenger.inntekt.db.InntektStore @@ -41,10 +46,6 @@ import no.nav.dagpenger.inntekt.oppslag.PersonNotFoundException import no.nav.dagpenger.inntekt.oppslag.PersonOppslag import no.nav.dagpenger.inntekt.oppslag.enhetsregister.EnhetsregisterClient import no.nav.dagpenger.inntekt.serder.jacksonObjectMapper -import no.nav.dagpenger.inntekt.v1.enhetsregisteret -import no.nav.dagpenger.inntekt.v1.inntekt -import no.nav.dagpenger.inntekt.v1.opptjeningsperiodeApi -import no.nav.dagpenger.inntekt.v1.uklassifisertInntekt import org.slf4j.event.Level import java.net.URI @@ -60,7 +61,12 @@ internal fun Application.inntektApi( enhetsregisterClient: EnhetsregisterClient, healthChecks: List, collectorRegistry: PrometheusRegistry = PrometheusRegistry.defaultRegistry, - meterRegistry: PrometheusMeterRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT, collectorRegistry, Clock.SYSTEM), + meterRegistry: PrometheusMeterRegistry = + PrometheusMeterRegistry( + PrometheusConfig.DEFAULT, + collectorRegistry, + Clock.SYSTEM, + ), ) { install(DefaultHeaders) install(MicrometerMetrics) { @@ -232,6 +238,11 @@ internal fun Application.inntektApi( } } } + authenticate("azure") { + route("/v3/inntekt") { + inntektV3(behandlingsInntektsGetter, personOppslag, inntektStore) + } + } naischecks(healthChecks, meterRegistry) } } diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRoute.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRoute.kt similarity index 95% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRoute.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRoute.kt index d7563a6e..2f865f06 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRoute.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRoute.kt @@ -1,10 +1,9 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import io.ktor.client.plugins.ClientRequestException import io.ktor.http.CacheControl import io.ktor.http.ContentType import io.ktor.http.HttpStatusCode -import io.ktor.server.application.call import io.ktor.server.plugins.BadRequestException import io.ktor.server.response.cacheControl import io.ktor.server.response.respondText diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntektRoute.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRoute.kt similarity index 97% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntektRoute.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRoute.kt index 35a4de9c..8d2bc363 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntektRoute.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRoute.kt @@ -1,7 +1,6 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import io.ktor.http.HttpStatusCode -import io.ktor.server.application.call import io.ktor.server.plugins.MissingRequestParameterException import io.ktor.server.plugins.callid.callId import io.ktor.server.request.receive diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntjeningsperiodeRoute.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntjeningsperiodeRoute.kt similarity index 85% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntjeningsperiodeRoute.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntjeningsperiodeRoute.kt index e3e6fe31..d786b108 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/InntjeningsperiodeRoute.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/InntjeningsperiodeRoute.kt @@ -1,7 +1,6 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import io.ktor.http.HttpStatusCode -import io.ktor.server.application.call import io.ktor.server.request.receive import io.ktor.server.response.respond import io.ktor.server.routing.Route @@ -9,11 +8,11 @@ import io.ktor.server.routing.post import io.ktor.server.routing.route import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import no.nav.dagpenger.inntekt.api.v1.models.InntjeningsperiodeParametre +import no.nav.dagpenger.inntekt.api.v1.models.InntjeningsperiodeResultat import no.nav.dagpenger.inntekt.db.InntektId import no.nav.dagpenger.inntekt.db.InntektStore import no.nav.dagpenger.inntekt.opptjeningsperiode.Opptjeningsperiode -import no.nav.dagpenger.inntekt.v1.models.InntjeningsperiodeParametre -import no.nav.dagpenger.inntekt.v1.models.InntjeningsperiodeResultat import java.time.LocalDate fun Route.opptjeningsperiodeApi(inntektStore: InntektStore) { diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRoute.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRoute.kt similarity index 91% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRoute.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRoute.kt index 8982ab00..4582cf88 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRoute.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRoute.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import com.auth0.jwt.exceptions.JWTDecodeException import io.ktor.http.HttpStatusCode @@ -18,6 +18,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import mu.KotlinLogging import mu.withLoggingContext +import no.nav.dagpenger.inntekt.api.v1.models.InntekterDto +import no.nav.dagpenger.inntekt.api.v1.models.mapToStoredInntekt import no.nav.dagpenger.inntekt.db.InntektId import no.nav.dagpenger.inntekt.db.InntektNotFoundException import no.nav.dagpenger.inntekt.db.InntektStore @@ -40,8 +42,6 @@ import no.nav.dagpenger.inntekt.oppslag.Person import no.nav.dagpenger.inntekt.oppslag.PersonOppslag import no.nav.dagpenger.inntekt.oppslag.enhetsregister.EnhetsregisterClient import no.nav.dagpenger.inntekt.opptjeningsperiode.Opptjeningsperiode -import no.nav.dagpenger.inntekt.v1.models.InntekterDto -import no.nav.dagpenger.inntekt.v1.models.mapToStoredInntekt import java.time.LocalDate import kotlin.coroutines.CoroutineContext @@ -146,14 +146,14 @@ fun Route.uklassifisertInntekt( withContext(coroutineContext) { val inntektId = InntektId(call.parameters["inntektId"]!!) inntektStore - .getInntektMedPersonFnr(inntektId) - .let { - val person = personOppslag.hentPerson(it.fødselsnummer) - val inntektsmottaker = Inntektsmottaker(it.fødselsnummer, person.sammensattNavn()) + .getStoredInntektMedMetadata(inntektId) + .let { storedInntektMedMetadata -> + val person = personOppslag.hentPerson(storedInntektMedMetadata.fødselsnummer) + val inntektsmottaker = Inntektsmottaker(storedInntektMedMetadata.fødselsnummer, person.sammensattNavn()) val organisasjoner = hentOrganisasjoner( enhetsregisterClient, - it.inntekt.arbeidsInntektMaaned + storedInntektMedMetadata.inntekt.arbeidsInntektMaaned ?.flatMap { it.arbeidsInntektInformasjon?.inntektListe.orEmpty() } ?.filter { inntekt -> inntekt.virksomhet?.aktoerType == AktoerType.ORGANISASJON && @@ -162,7 +162,11 @@ fun Route.uklassifisertInntekt( ?.toTypedArray() ?.toList() ?: emptyList(), ) - it.inntekt.mapToFrontend(inntektsmottaker, organisasjoner) + storedInntektMedMetadata.inntekt.mapToFrontend( + person = inntektsmottaker, + organisasjoner = organisasjoner, + storedInntektMedMetadata, + ) }.let { call.respond(HttpStatusCode.OK, it) } @@ -171,8 +175,8 @@ fun Route.uklassifisertInntekt( post { withContext(coroutineContext) { val inntektId = call.parameters["inntektId"]!! - call - .receive() + val inntekterDto = call.receive() + inntekterDto .mapToStoredInntekt( inntektId = inntektId, ).let { @@ -189,12 +193,16 @@ fun Route.uklassifisertInntekt( inntektPersonMapping.kontekstType, ), beregningsdato = inntektPersonMapping.beregningsdato, - ), + ).apply { + this.opptjeningsperiode.førsteMåned = inntekterDto.periode.fraOgMed + this.opptjeningsperiode.sisteAvsluttendeKalenderMåned = inntekterDto.periode.tilOgMed + }, inntekt = it.inntekt, manueltRedigert = ManueltRedigert.from( - true, - call.getSubject(), + bool = true, + redigertAv = call.getSubject(), + begrunnelse = inntekterDto.begrunnelse, ), ), ) diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDto.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDto.kt similarity index 94% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDto.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDto.kt index 01357aac..77d2566b 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDto.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDto.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1.models +package no.nav.dagpenger.inntekt.api.v1.models import no.nav.dagpenger.inntekt.db.InntektId import no.nav.dagpenger.inntekt.db.StoredInntekt @@ -17,6 +17,13 @@ import java.time.YearMonth data class InntekterDto( val virksomheter: List, val mottaker: Inntektsmottaker, + val periode: PeriodeDto, + val begrunnelse: String? = null, +) + +data class PeriodeDto( + val fraOgMed: YearMonth, + val tilOgMed: YearMonth, ) fun InntekterDto.mapToStoredInntekt(inntektId: String): StoredInntekt = diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeParametre.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeParametre.kt similarity index 68% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeParametre.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeParametre.kt index a2b5f250..01d7b155 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeParametre.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeParametre.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1.models +package no.nav.dagpenger.inntekt.api.v1.models data class InntjeningsperiodeParametre( val beregningsdato: String, diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeResultat.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeResultat.kt similarity index 62% rename from dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeResultat.kt rename to dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeResultat.kt index a35b8dc9..d2fbea3b 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/v1/models/InntjeningsperiodeResultat.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntjeningsperiodeResultat.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1.models +package no.nav.dagpenger.inntekt.api.v1.models class InntjeningsperiodeResultat( val sammeInntjeningsPeriode: Boolean, diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3.kt new file mode 100644 index 00000000..9a8aa339 --- /dev/null +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3.kt @@ -0,0 +1,86 @@ +package no.nav.dagpenger.inntekt.api.v3 + +import io.ktor.http.HttpStatusCode +import io.ktor.server.plugins.callid.callId +import io.ktor.server.request.receive +import io.ktor.server.response.respond +import io.ktor.server.routing.Route +import io.ktor.server.routing.post +import io.ktor.server.routing.route +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.withContext +import no.nav.dagpenger.inntekt.BehandlingsInntektsGetter +import no.nav.dagpenger.inntekt.db.InntektId +import no.nav.dagpenger.inntekt.db.InntektStore +import no.nav.dagpenger.inntekt.db.Inntektparametre +import no.nav.dagpenger.inntekt.db.ManueltRedigert +import no.nav.dagpenger.inntekt.db.RegelKontekst +import no.nav.dagpenger.inntekt.oppslag.PersonOppslag +import no.nav.dagpenger.inntekt.v1.Inntekt +import no.nav.dagpenger.inntekt.v1.KlassifisertInntektMåned +import java.time.LocalDate +import java.time.YearMonth + +fun Route.inntektV3( + behandlingsInntektsGetter: BehandlingsInntektsGetter, + personOppslag: PersonOppslag, + inntektStore: InntektStore, +) { + route("/klassifisert") { + post { + withContext(IO) { + val klassifisertInntektRequestDto = call.receive() + val person = personOppslag.hentPerson(klassifisertInntektRequestDto.personIdentifikator) + val inntektparametre = + Inntektparametre( + aktørId = person.aktørId, + fødselsnummer = person.fødselsnummer, + regelkontekst = klassifisertInntektRequestDto.regelkontekst, + beregningsdato = klassifisertInntektRequestDto.beregningsDato, + ).apply { + opptjeningsperiode.førsteMåned = klassifisertInntektRequestDto.periodeFraOgMed + opptjeningsperiode.sisteAvsluttendeKalenderMåned = klassifisertInntektRequestDto.periodeTilOgMed + } + val klassifisertInntekt = + behandlingsInntektsGetter.getKlassifisertInntekt( + inntektparametre, + call.callId, + ) + val manueltRedigert = inntektStore.getManueltRedigert(InntektId(klassifisertInntekt.inntektsId)) + + call.respond( + HttpStatusCode.OK, + mapToKlassifisertInntektResponseDto(klassifisertInntekt, manueltRedigert), + ) + } + } + } +} + +data class KlassifisertInntektRequestDto( + val personIdentifikator: String, + val regelkontekst: RegelKontekst, + val beregningsDato: LocalDate, + val periodeFraOgMed: YearMonth, + val periodeTilOgMed: YearMonth, +) + +data class KlassifisertInntektResponseDto( + val inntektsId: String, + val inntektsListe: List, + val manueltRedigert: Boolean? = false, + val begrunnelseManueltRedigert: String? = null, + val sisteAvsluttendeKalenderMåned: YearMonth, +) + +private fun mapToKlassifisertInntektResponseDto( + inntekt: Inntekt, + manueltRedigert: ManueltRedigert?, +): KlassifisertInntektResponseDto = + KlassifisertInntektResponseDto( + inntektsId = inntekt.inntektsId, + inntektsListe = inntekt.inntektsListe, + manueltRedigert = inntekt.manueltRedigert, + begrunnelseManueltRedigert = manueltRedigert?.begrunnelse, + sisteAvsluttendeKalenderMåned = inntekt.sisteAvsluttendeKalenderMåned, + ) diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/InntektStore.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/InntektStore.kt index 37ce03b8..08ffa5d9 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/InntektStore.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/InntektStore.kt @@ -6,6 +6,7 @@ import no.nav.dagpenger.inntekt.opptjeningsperiode.Opptjeningsperiode import no.nav.dagpenger.inntekt.v1.SpesifisertInntekt import java.time.LocalDate import java.time.LocalDateTime +import java.time.YearMonth import java.time.ZoneOffset import java.time.ZonedDateTime @@ -29,7 +30,7 @@ interface InntektStore { fun markerInntektBrukt(inntektId: InntektId): Int - fun getInntektMedPersonFnr(inntektId: InntektId): StoredInntektMedFnr + fun getStoredInntektMedMetadata(inntektId: InntektId): StoredInntektMedMetadata } data class Inntektparametre( @@ -66,13 +67,15 @@ data class InntektPersonMapping( data class ManueltRedigert( val redigertAv: String, + val begrunnelse: String? = null, ) { companion object { fun from( bool: Boolean, redigertAv: String, + begrunnelse: String? = null, ) = when (bool) { - true -> ManueltRedigert(redigertAv) + true -> ManueltRedigert(redigertAv, begrunnelse) false -> null } } @@ -102,12 +105,20 @@ data class InntektId( } } -data class StoredInntektMedFnr( +data class StoredInntektMedMetadata( val inntektId: InntektId, val inntekt: InntektkomponentResponse, val manueltRedigert: Boolean, val timestamp: LocalDateTime? = null, val fødselsnummer: String, + val beregningsdato: LocalDate, + val storedInntektPeriode: StoredInntektPeriode?, + val begrunnelse: String? = null, +) + +data class StoredInntektPeriode( + val fraOgMed: YearMonth?, + val tilOgMed: YearMonth?, ) class InntektNotFoundException( diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/PostgresInntektStore.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/PostgresInntektStore.kt index b501c22f..deb592da 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/PostgresInntektStore.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/db/PostgresInntektStore.kt @@ -18,6 +18,7 @@ import org.intellij.lang.annotations.Language import org.postgresql.util.PGobject import org.postgresql.util.PSQLException import java.time.LocalDate +import java.time.YearMonth import java.time.ZonedDateTime import javax.sql.DataSource @@ -41,7 +42,7 @@ internal class PostgresInntektStore( @Language("sql") val statement = """ - SELECT redigert_av + SELECT redigert_av, begrunnelse FROM inntekt_V1_manuelt_redigert WHERE inntekt_id = ? """.trimMargin() @@ -50,7 +51,7 @@ internal class PostgresInntektStore( session.run( queryOf(statement, inntektId.id) .map { row -> - ManueltRedigert(row.string(1)) + ManueltRedigert(row.string("redigert_av"), row.string("begrunnelse")) }.asSingle, ) } @@ -187,27 +188,34 @@ internal class PostgresInntektStore( return mapToSpesifisertInntekt(stored.first, Opptjeningsperiode(stored.second).sisteAvsluttendeKalenderMåned) } - override fun getInntektMedPersonFnr(inntektId: InntektId): StoredInntektMedFnr { + override fun getStoredInntektMedMetadata(inntektId: InntektId): StoredInntektMedMetadata { @Language("sql") val statement = """ - SELECT inntekt.id, inntekt.inntekt, inntekt.manuelt_redigert, inntekt.timestamp, mapping.fnr - from inntekt_V1 inntekt - inner join inntekt_V1_person_mapping mapping on inntekt.id = mapping.inntektid - where inntekt.id = ? - + SELECT inntekt.id, inntekt.inntekt, inntekt.manuelt_redigert, inntekt.timestamp, mapping.fnr, mapping.beregningsdato, mapping.periodeFraOgMed, mapping.periodeTilOgMed, manuelt_redigert.begrunnelse + FROM inntekt_V1 inntekt + INNER JOIN inntekt_V1_person_mapping mapping ON inntekt.id = mapping.inntektid + LEFT JOIN inntekt_V1_manuelt_redigert manuelt_redigert ON inntekt.id = manuelt_redigert.inntekt_id + WHERE inntekt.id = ? """.trimIndent() return using(sessionOf(dataSource)) { session -> session.run( queryOf(statement, inntektId.id) .map { - StoredInntektMedFnr( + StoredInntektMedMetadata( inntektId = InntektId(it.string("id")), inntekt = it.binaryStream("inntekt").use { jacksonObjectMapper.readValue(it) }, manueltRedigert = it.boolean("manuelt_redigert"), timestamp = it.zonedDateTime("timestamp").toLocalDateTime(), fødselsnummer = it.string("fnr"), + beregningsdato = it.localDate("beregningsdato"), + storedInntektPeriode = + StoredInntektPeriode( + fraOgMed = it.localDateOrNull("periodeFraOgMed")?.let { localDate -> YearMonth.from(localDate) }, + tilOgMed = it.localDateOrNull("periodeTilOgMed")?.let { localDate -> YearMonth.from(localDate) }, + ), + begrunnelse = it.stringOrNull("begrunnelse"), ) }.asSingle, ) ?: throw InntektNotFoundException("Inntekt with id $inntektId not found.") @@ -242,7 +250,10 @@ internal class PostgresInntektStore( ) tx.run( queryOf( - "INSERT INTO inntekt_V1_person_mapping(inntektId, aktørId, fnr, kontekstId, beregningsdato, kontekstType) VALUES (:inntektId, :aktorId, :fnr, :kontekstId, :beregningsdato, :kontekstType::kontekstTypeNavn)", + """ + INSERT INTO inntekt_V1_person_mapping(inntektId, aktørId, fnr, kontekstId, beregningsdato, kontekstType, periodeFraOgMed, periodeTilOgMed) + VALUES (:inntektId, :aktorId, :fnr, :kontekstId, :beregningsdato, :kontekstType::kontekstTypeNavn, :periodeFraOgMed, :periodeTilOgMed) + """.trimIndent(), mapOf( "inntektId" to inntektId.id, "aktorId" to command.inntektparametre.aktørId, @@ -250,17 +261,30 @@ internal class PostgresInntektStore( "kontekstId" to command.inntektparametre.regelkontekst.id, "kontekstType" to command.inntektparametre.regelkontekst.type, "beregningsdato" to command.inntektparametre.beregningsdato, + "periodeFraOgMed" to + command.inntektparametre.opptjeningsperiode.førsteMåned.let { + LocalDate.of(it.year, it.month, 1) + }, + "periodeTilOgMed" to + command.inntektparametre.opptjeningsperiode.sisteAvsluttendeKalenderMåned.let { + LocalDate.of(it.year, it.month, 1) + }, ), ).asUpdate, ) command.manueltRedigert?.let { + it.begrunnelse?.length?.let { lengde -> + require(lengde <= 1024) { "Begrunnelsen kan ikke være lengre enn 1024 tegn." } + } + tx.run( queryOf( - "INSERT INTO inntekt_V1_manuelt_redigert VALUES(:id,:redigert)", + "INSERT INTO inntekt_V1_manuelt_redigert (inntekt_id, redigert_av, begrunnelse) VALUES(:id, :redigert, :begrunnelse)", mapOf( "id" to inntektId.id, "redigert" to it.redigertAv, + "begrunnelse" to it.begrunnelse, ), ).asUpdate, ) diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontend.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontend.kt index d88af12a..32841733 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontend.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontend.kt @@ -1,5 +1,8 @@ package no.nav.dagpenger.inntekt.mapping +import no.nav.dagpenger.inntekt.api.v1.models.InntekterDto +import no.nav.dagpenger.inntekt.api.v1.models.PeriodeDto +import no.nav.dagpenger.inntekt.db.StoredInntektMedMetadata import no.nav.dagpenger.inntekt.inntektskomponenten.v1.Aktoer import no.nav.dagpenger.inntekt.inntektskomponenten.v1.Avvik import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektBeskrivelse @@ -7,13 +10,14 @@ import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektType import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektkomponentResponse import no.nav.dagpenger.inntekt.inntektskomponenten.v1.Periode import no.nav.dagpenger.inntekt.inntektskomponenten.v1.TilleggInformasjon -import no.nav.dagpenger.inntekt.v1.models.InntekterDto +import no.nav.dagpenger.inntekt.opptjeningsperiode.Opptjeningsperiode import java.math.BigDecimal import java.time.YearMonth fun InntektkomponentResponse.mapToFrontend( person: Inntektsmottaker, organisasjoner: List, + storedInntektMedMetadata: StoredInntektMedMetadata, ): InntekterDto { val inntekt = arbeidsInntektMaaned val virksomheter: MutableList = mutableListOf() @@ -55,8 +59,8 @@ fun InntektkomponentResponse.mapToFrontend( eksisterendeVirksomhet.inntekter?.addAll(inntekter) eksisterendeVirksomhet.periode = InntektPeriode( - fra = eksisterendeVirksomhet.inntekter!!.minOf { it.aarMaaned }, - til = eksisterendeVirksomhet.inntekter.maxOf { it.aarMaaned }, + fraOgMed = eksisterendeVirksomhet.inntekter!!.minOf { it.aarMaaned }, + tilOgMed = eksisterendeVirksomhet.inntekter.maxOf { it.aarMaaned }, ) eksisterendeVirksomhet.totalBelop = eksisterendeVirksomhet.inntekter.sumOf { it.belop } } else { @@ -66,8 +70,8 @@ fun InntektkomponentResponse.mapToFrontend( virksomhetsnavn = virksomhetNavn, periode = InntektPeriode( - fra = arbeidsInntektMaaned.aarMaaned, - til = arbeidsInntektMaaned.aarMaaned, + fraOgMed = arbeidsInntektMaaned.aarMaaned, + tilOgMed = arbeidsInntektMaaned.aarMaaned, ), inntekter = inntekter, avvikListe = mutableListOf(), @@ -97,6 +101,16 @@ fun InntektkomponentResponse.mapToFrontend( return InntekterDto( virksomheter = virksomheter, mottaker = person, + periode = getPeriode(storedInntektMedMetadata), + begrunnelse = storedInntektMedMetadata.begrunnelse, + ) +} + +private fun getPeriode(storedInntektMedMetadata: StoredInntektMedMetadata): PeriodeDto { + val opptjeningsperiode = Opptjeningsperiode(beregningsdato = storedInntektMedMetadata.beregningsdato) + return PeriodeDto( + fraOgMed = storedInntektMedMetadata.storedInntektPeriode?.fraOgMed ?: opptjeningsperiode.førsteMåned, + tilOgMed = storedInntektMedMetadata.storedInntektPeriode?.tilOgMed ?: opptjeningsperiode.sisteAvsluttendeKalenderMåned, ) } @@ -110,8 +124,8 @@ data class Virksomhet( ) data class InntektPeriode( - val fra: YearMonth, - val til: YearMonth, + val fraOgMed: YearMonth, + val tilOgMed: YearMonth, ) data class InntektMaaned( diff --git a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/opptjeningsperiode/Opptjeningsperiode.kt b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/opptjeningsperiode/Opptjeningsperiode.kt index 9c5b071a..d1c465c7 100644 --- a/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/opptjeningsperiode/Opptjeningsperiode.kt +++ b/dp-inntekt-api/src/main/kotlin/no/nav/dagpenger/inntekt/opptjeningsperiode/Opptjeningsperiode.kt @@ -6,7 +6,9 @@ import java.time.YearMonth import java.time.ZoneId import java.util.Date -data class Opptjeningsperiode(val beregningsdato: LocalDate) { +data class Opptjeningsperiode( + val beregningsdato: LocalDate, +) { private val antattRapporteringsFrist = LocalDate.of(beregningsdato.year, beregningsdato.month, 5) private val reellRapporteringsFrist: LocalDate = finnFørsteArbeidsdagEtterRapporterteringsFrist(antattRapporteringsFrist) @@ -16,21 +18,20 @@ data class Opptjeningsperiode(val beregningsdato: LocalDate) { else -> 1 } - val sisteAvsluttendeKalenderMåned: YearMonth = beregningsdato.minusMonths(månedSubtraksjon).toYearMonth() - val førsteMåned: YearMonth = sisteAvsluttendeKalenderMåned.minusMonths(35) + var sisteAvsluttendeKalenderMåned: YearMonth = beregningsdato.minusMonths(månedSubtraksjon).toYearMonth() + var førsteMåned: YearMonth = sisteAvsluttendeKalenderMåned.minusMonths(35) fun sammeOpptjeningsPeriode(other: Opptjeningsperiode): Boolean = this.sisteAvsluttendeKalenderMåned == other.sisteAvsluttendeKalenderMåned - private tailrec fun finnFørsteArbeidsdagEtterRapporterteringsFrist(rapporteringsFrist: LocalDate): LocalDate { - return if (rapporteringsFrist.erArbeidsdag()) { + private tailrec fun finnFørsteArbeidsdagEtterRapporterteringsFrist(rapporteringsFrist: LocalDate): LocalDate = + if (rapporteringsFrist.erArbeidsdag()) { rapporteringsFrist } else { finnFørsteArbeidsdagEtterRapporterteringsFrist( rapporteringsFrist.plusDays(1), ) } - } private fun LocalDate.erArbeidsdag(): Boolean = NorwegianDateUtil.isWorkingDay(Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())) diff --git a/dp-inntekt-api/src/main/resources/db/migration/V12_1__Inntekt_person_mapping_add_periodeFraOgMed_og_periodeTilOgMed.sql b/dp-inntekt-api/src/main/resources/db/migration/V12_1__Inntekt_person_mapping_add_periodeFraOgMed_og_periodeTilOgMed.sql new file mode 100644 index 00000000..ee7a1056 --- /dev/null +++ b/dp-inntekt-api/src/main/resources/db/migration/V12_1__Inntekt_person_mapping_add_periodeFraOgMed_og_periodeTilOgMed.sql @@ -0,0 +1,3 @@ +ALTER TABLE inntekt_v1_person_mapping + ADD COLUMN periodeFraOgMed DATE, + ADD COLUMN periodeTilOgMed DATE; diff --git a/dp-inntekt-api/src/main/resources/db/migration/V13_1__inntekt_manuelt_redigert_add_begrunnelse.sql b/dp-inntekt-api/src/main/resources/db/migration/V13_1__inntekt_manuelt_redigert_add_begrunnelse.sql new file mode 100644 index 00000000..b58035aa --- /dev/null +++ b/dp-inntekt-api/src/main/resources/db/migration/V13_1__inntekt_manuelt_redigert_add_begrunnelse.sql @@ -0,0 +1,2 @@ +ALTER TABLE inntekt_v1_manuelt_redigert + ADD COLUMN begrunnelse VARCHAR(1024); \ No newline at end of file diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/NaisChecksTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/NaisChecksTest.kt index 8128e7d1..6d1dbe3d 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/NaisChecksTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/NaisChecksTest.kt @@ -4,11 +4,11 @@ import io.ktor.client.request.get import io.ktor.http.HttpStatusCode import io.mockk.every import io.mockk.mockk +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication import no.nav.dagpenger.inntekt.db.InntektStore import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektskomponentClient import no.nav.dagpenger.inntekt.oppslag.PersonOppslag -import no.nav.dagpenger.inntekt.v1.TestApplication.mockInntektApi -import no.nav.dagpenger.inntekt.v1.TestApplication.withMockAuthServerAndTestApplication import org.junit.jupiter.api.Test import kotlin.test.assertEquals diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRouteTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRouteTest.kt similarity index 87% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRouteTest.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRouteTest.kt index 74000984..be18ddef 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/EnhetsregistrerRouteTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/EnhetsregistrerRouteTest.kt @@ -1,13 +1,13 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import io.kotest.matchers.shouldBe import io.ktor.client.request.get import io.ktor.http.HttpStatusCode import io.mockk.coEvery import io.mockk.mockk +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication import no.nav.dagpenger.inntekt.oppslag.enhetsregister.EnhetsregisterClient -import no.nav.dagpenger.inntekt.v1.TestApplication.mockInntektApi -import no.nav.dagpenger.inntekt.v1.TestApplication.withMockAuthServerAndTestApplication import org.junit.jupiter.api.Test internal class EnhetsregistrerRouteTest { diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRequestTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRequestTest.kt similarity index 95% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRequestTest.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRequestTest.kt index 64c13ce5..a835739c 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRequestTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRequestTest.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import no.nav.dagpenger.inntekt.oppslag.Person import no.nav.dagpenger.inntekt.opptjeningsperiode.Opptjeningsperiode diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRouteSpec.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRouteSpec.kt similarity index 94% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRouteSpec.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRouteSpec.kt index ef7196a6..4a3cf625 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/InntektRouteSpec.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/InntektRouteSpec.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import de.huxhorn.sulky.ulid.ULID import io.kotest.assertions.assertSoftly @@ -18,6 +18,10 @@ import io.mockk.mockk import io.mockk.spyk import no.bekk.bekkopen.person.FodselsnummerCalculator.getFodselsnummerForDate import no.nav.dagpenger.inntekt.BehandlingsInntektsGetter +import no.nav.dagpenger.inntekt.api.v1.TestApplication.autentisert +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.testOAuthToken +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication import no.nav.dagpenger.inntekt.db.InntektId import no.nav.dagpenger.inntekt.db.InntektNotFoundException import no.nav.dagpenger.inntekt.db.Inntektparametre @@ -30,10 +34,10 @@ import no.nav.dagpenger.inntekt.oppslag.Person import no.nav.dagpenger.inntekt.oppslag.PersonNotFoundException import no.nav.dagpenger.inntekt.oppslag.PersonOppslag import no.nav.dagpenger.inntekt.serder.jacksonObjectMapper -import no.nav.dagpenger.inntekt.v1.TestApplication.autentisert -import no.nav.dagpenger.inntekt.v1.TestApplication.mockInntektApi -import no.nav.dagpenger.inntekt.v1.TestApplication.testOAuthToken -import no.nav.dagpenger.inntekt.v1.TestApplication.withMockAuthServerAndTestApplication +import no.nav.dagpenger.inntekt.v1.Inntekt +import no.nav.dagpenger.inntekt.v1.InntektKlasse +import no.nav.dagpenger.inntekt.v1.KlassifisertInntekt +import no.nav.dagpenger.inntekt.v1.KlassifisertInntektMåned import org.junit.jupiter.api.Test import java.time.LocalDate import java.time.YearMonth @@ -45,7 +49,11 @@ internal class InntektRouteSpec { private val fnr = getFodselsnummerForDate( Date.from( - LocalDate.now().minusYears(20).atStartOfDay(ZoneId.systemDefault()).toInstant(), + LocalDate + .now() + .minusYears(20) + .atStartOfDay(ZoneId.systemDefault()) + .toInstant(), ), ).personnummer private val ulid = ULID().nextULID() diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/OpptjeningsperiodeRouteSpec.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/OpptjeningsperiodeRouteSpec.kt similarity index 84% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/OpptjeningsperiodeRouteSpec.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/OpptjeningsperiodeRouteSpec.kt index fe57117c..0f22a056 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/OpptjeningsperiodeRouteSpec.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/OpptjeningsperiodeRouteSpec.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import io.ktor.client.statement.bodyAsText import io.ktor.http.HttpMethod @@ -6,10 +6,10 @@ import io.ktor.http.HttpStatusCode import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.runBlocking +import no.nav.dagpenger.inntekt.api.v1.TestApplication.autentisert +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication import no.nav.dagpenger.inntekt.db.InntektStore -import no.nav.dagpenger.inntekt.v1.TestApplication.autentisert -import no.nav.dagpenger.inntekt.v1.TestApplication.mockInntektApi -import no.nav.dagpenger.inntekt.v1.TestApplication.withMockAuthServerAndTestApplication import org.junit.jupiter.api.Test import java.time.LocalDate import kotlin.test.assertEquals diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/TestApplication.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/TestApplication.kt similarity index 91% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/TestApplication.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/TestApplication.kt index b0c6a89e..58e2d650 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/TestApplication.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/TestApplication.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import com.natpryce.konfig.Configuration import com.natpryce.konfig.ConfigurationMap @@ -37,14 +37,15 @@ internal object TestApplication { } } val testOAuthToken: String by lazy { - mockOAuth2Server.issueToken( - issuerId = ISSUER_ID, - subject = TEST_OAUTH_USER, - ).serialize() + mockOAuth2Server + .issueToken( + issuerId = ISSUER_ID, + subject = TEST_OAUTH_USER, + ).serialize() } - private fun config(): Configuration { - return Config.config overriding + private fun config(): Configuration = + Config.config overriding ConfigurationMap( mapOf( "AZURE_OPENID_CONFIG_JWKS_URI" to mockOAuth2Server.jwksUrl(ISSUER_ID).toString(), @@ -52,7 +53,6 @@ internal object TestApplication { "AZURE_APP_CLIENT_ID" to ISSUER_ID, ), ) - } internal fun mockInntektApi( inntektskomponentClient: InntektskomponentClient = mockk(), @@ -78,11 +78,9 @@ internal object TestApplication { internal fun withMockAuthServerAndTestApplication( moduleFunction: Application.() -> Unit = mockInntektApi(), test: suspend ApplicationTestBuilder.() -> Unit, - ) { - return testApplication { - application(moduleFunction) - test() - } + ) = testApplication { + application(moduleFunction) + test() } internal suspend fun ApplicationTestBuilder.autentisert( diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRouteTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRouteTest.kt similarity index 93% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRouteTest.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRouteTest.kt index 25634e43..ae814619 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/UklassifisertInntektRouteTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/UklassifisertInntektRouteTest.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1 +package no.nav.dagpenger.inntekt.api.v1 import com.fasterxml.jackson.module.kotlin.readValue import de.huxhorn.sulky.ulid.ULID @@ -18,6 +18,11 @@ import io.mockk.slot import io.mockk.verify import kotlinx.coroutines.runBlocking import no.nav.dagpenger.inntekt.Problem +import no.nav.dagpenger.inntekt.api.v1.TestApplication.TEST_OAUTH_USER +import no.nav.dagpenger.inntekt.api.v1.TestApplication.autentisert +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication +import no.nav.dagpenger.inntekt.api.v1.models.InntekterDto import no.nav.dagpenger.inntekt.db.DetachedInntekt import no.nav.dagpenger.inntekt.db.InntektId import no.nav.dagpenger.inntekt.db.InntektPersonMapping @@ -27,7 +32,8 @@ import no.nav.dagpenger.inntekt.db.ManueltRedigert import no.nav.dagpenger.inntekt.db.RegelKontekst import no.nav.dagpenger.inntekt.db.StoreInntektCommand import no.nav.dagpenger.inntekt.db.StoredInntekt -import no.nav.dagpenger.inntekt.db.StoredInntektMedFnr +import no.nav.dagpenger.inntekt.db.StoredInntektMedMetadata +import no.nav.dagpenger.inntekt.db.StoredInntektPeriode import no.nav.dagpenger.inntekt.inntektskomponenten.v1.Aktoer import no.nav.dagpenger.inntekt.inntektskomponenten.v1.AktoerType import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektBeskrivelse @@ -44,14 +50,10 @@ import no.nav.dagpenger.inntekt.oppslag.Person import no.nav.dagpenger.inntekt.oppslag.PersonOppslag import no.nav.dagpenger.inntekt.oppslag.enhetsregister.EnhetsregisterClient import no.nav.dagpenger.inntekt.serder.jacksonObjectMapper -import no.nav.dagpenger.inntekt.v1.TestApplication.TEST_OAUTH_USER -import no.nav.dagpenger.inntekt.v1.TestApplication.autentisert -import no.nav.dagpenger.inntekt.v1.TestApplication.mockInntektApi -import no.nav.dagpenger.inntekt.v1.TestApplication.withMockAuthServerAndTestApplication -import no.nav.dagpenger.inntekt.v1.models.InntekterDto import org.junit.jupiter.api.Test import java.math.BigDecimal import java.time.LocalDate +import java.time.LocalDate.now import java.time.LocalDateTime import java.time.YearMonth import kotlin.test.assertEquals @@ -495,15 +497,20 @@ internal class UklassifisertInntektRouteTest { .getResource("/test-data/example-inntekt-med-inntektId-payload.json") ?.readText() every { - inntektStoreMock.getInntektMedPersonFnr(inntektId) + inntektStoreMock.getStoredInntektMedMetadata(inntektId) } returns - StoredInntektMedFnr( + StoredInntektMedMetadata( inntektId, - inntekt = - jacksonObjectMapper.readValue(body!!), + inntekt = jacksonObjectMapper.readValue(body!!), manueltRedigert = false, timestamp = LocalDateTime.now(), fødselsnummer = fødselsnummer, + beregningsdato = now(), + storedInntektPeriode = + StoredInntektPeriode( + fraOgMed = YearMonth.of(2023, 1), + tilOgMed = YearMonth.of(2025, 5), + ), ) val response = @@ -514,6 +521,8 @@ internal class UklassifisertInntektRouteTest { response.status shouldBe OK val storedInntekt = jacksonObjectMapper.readValue(response.bodyAsText()) + storedInntekt.periode.fraOgMed shouldBe YearMonth.of(2023, 1) + storedInntekt.periode.tilOgMed shouldBe YearMonth.of(2025, 5) storedInntekt.virksomheter shouldHaveSize 2 storedInntekt.virksomheter[0].inntekter?.shouldHaveSize(4) storedInntekt.virksomheter.first().virksomhetsnummer shouldBe "1111111" @@ -544,7 +553,7 @@ internal class UklassifisertInntektRouteTest { aktørId = "123456789", fnr = null, kontekstId = "kontekstId", - beregningsdato = LocalDate.now(), + beregningsdato = now(), timestamp = LocalDateTime.now(), kontekstType = "kontekstType", ) @@ -567,7 +576,11 @@ internal class UklassifisertInntektRouteTest { storeInntektCommandSlot.captured.inntektparametre.regelkontekst.id shouldBe inntektPersonMapping.kontekstId storeInntektCommandSlot.captured.inntektparametre.regelkontekst.type shouldBe inntektPersonMapping.kontekstType storeInntektCommandSlot.captured.inntektparametre.beregningsdato shouldBe inntektPersonMapping.beregningsdato + storeInntektCommandSlot.captured.inntektparametre.opptjeningsperiode.førsteMåned shouldBe YearMonth.of(2000, 12) + storeInntektCommandSlot.captured.inntektparametre.opptjeningsperiode.sisteAvsluttendeKalenderMåned shouldBe + YearMonth.of(2025, 4) storeInntektCommandSlot.captured.manueltRedigert.shouldNotBeNull() storeInntektCommandSlot.captured.manueltRedigert!!.redigertAv shouldBe TEST_OAUTH_USER + storeInntektCommandSlot.captured.manueltRedigert!!.begrunnelse shouldBe "Dette er en begrunnelse." } } diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDtoTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDtoTest.kt similarity index 99% rename from dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDtoTest.kt rename to dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDtoTest.kt index 77ebcda5..42bce877 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/v1/models/InntekterDtoTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v1/models/InntekterDtoTest.kt @@ -1,4 +1,4 @@ -package no.nav.dagpenger.inntekt.v1.models +package no.nav.dagpenger.inntekt.api.v1.models import com.fasterxml.jackson.module.kotlin.readValue import de.huxhorn.sulky.ulid.ULID diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3Test.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3Test.kt new file mode 100644 index 00000000..ca8d2018 --- /dev/null +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/api/v3/KlassifisertInntektRouteV3Test.kt @@ -0,0 +1,197 @@ +package no.nav.dagpenger.inntekt.api.v3 + +import com.fasterxml.jackson.module.kotlin.readValue +import de.huxhorn.sulky.ulid.ULID +import io.kotest.matchers.collections.shouldNotBeEmpty +import io.kotest.matchers.shouldBe +import io.ktor.client.statement.bodyAsText +import io.ktor.http.HttpMethod +import io.ktor.http.HttpStatusCode.Companion.OK +import io.mockk.coEvery +import io.mockk.every +import io.mockk.mockk +import no.nav.dagpenger.inntekt.BehandlingsInntektsGetter +import no.nav.dagpenger.inntekt.api.v1.TestApplication.autentisert +import no.nav.dagpenger.inntekt.api.v1.TestApplication.mockInntektApi +import no.nav.dagpenger.inntekt.api.v1.TestApplication.withMockAuthServerAndTestApplication +import no.nav.dagpenger.inntekt.db.InntektStore +import no.nav.dagpenger.inntekt.db.Inntektparametre +import no.nav.dagpenger.inntekt.db.ManueltRedigert +import no.nav.dagpenger.inntekt.db.RegelKontekst +import no.nav.dagpenger.inntekt.oppslag.Person +import no.nav.dagpenger.inntekt.oppslag.PersonOppslag +import no.nav.dagpenger.inntekt.serder.jacksonObjectMapper +import no.nav.dagpenger.inntekt.v1.Inntekt +import no.nav.dagpenger.inntekt.v1.KlassifisertInntektMåned +import java.time.LocalDate +import java.time.YearMonth +import java.time.YearMonth.now +import kotlin.test.Test + +class KlassifisertInntektRouteV3Test { + private val fødselsnummer = "12345678901" + private val aktørId = "12345" + private val personOppslagMock: PersonOppslag = mockk() + private val behandlingsInntektsGetterMock: BehandlingsInntektsGetter = mockk() + private val inntektParametreCapture = mutableListOf() + private val inntektStoreMock: InntektStore = mockk() + private val regelkontekst = RegelKontekst("id", "type") + private val beregningsDato = LocalDate.of(2018, 5, 27)!! + private val periodeFraOgMed = YearMonth.of(2017, 1)!! + private val periodeTilOgMed = YearMonth.of(2018, 12)!! + private val inntektsId = ULID().nextULID() + private val sisteAvsluttendeKalenderMåned = now() + + init { + coEvery { + personOppslagMock.hentPerson(any()) + } returns + Person( + fødselsnummer, + aktørId, + "Navn", + null, + "Navnesen", + ) + + coEvery { + behandlingsInntektsGetterMock.getKlassifisertInntekt( + capture(inntektParametreCapture), + any(), + ) + } returns createInntekt(true) + + every { inntektStoreMock.getManueltRedigert(any()) } returns mockk(relaxed = true) + } + + @Test + fun `Inntektparametre opprettes med forventede verdier`() { + withMockAuthServerAndTestApplication( + mockInntektApi( + personOppslag = personOppslagMock, + behandlingsInntektsGetter = behandlingsInntektsGetterMock, + inntektStore = inntektStoreMock, + ), + ) { + val response = + autentisert( + httpMethod = HttpMethod.Post, + endepunkt = "/v3/inntekt/klassifisert", + body = + jacksonObjectMapper.writeValueAsString( + KlassifisertInntektRequestDto( + fødselsnummer, + regelkontekst, + beregningsDato, + periodeFraOgMed, + periodeTilOgMed, + ), + ), + ) + + response.status shouldBe OK + val inntektparametre = inntektParametreCapture.first() + inntektparametre.aktørId shouldBe aktørId + inntektparametre.fødselsnummer shouldBe fødselsnummer + inntektparametre.regelkontekst shouldBe regelkontekst + inntektparametre.beregningsdato shouldBe beregningsDato + inntektparametre.opptjeningsperiode.førsteMåned shouldBe periodeFraOgMed + inntektparametre.opptjeningsperiode.sisteAvsluttendeKalenderMåned shouldBe periodeTilOgMed + } + } + + @Test + fun `Klassifisert-endepunktet returnerer forventet respons når inntekten er manuelt redigert`() { + every { inntektStoreMock.getManueltRedigert(any()) } returns + ManueltRedigert( + "N313373", + "Dette er en begrunnelse.", + ) + + withMockAuthServerAndTestApplication( + mockInntektApi( + personOppslag = personOppslagMock, + behandlingsInntektsGetter = behandlingsInntektsGetterMock, + inntektStore = inntektStoreMock, + ), + ) { + val response = + autentisert( + httpMethod = HttpMethod.Post, + endepunkt = "/v3/inntekt/klassifisert", + body = + jacksonObjectMapper.writeValueAsString( + KlassifisertInntektRequestDto( + fødselsnummer, + regelkontekst, + beregningsDato, + periodeFraOgMed, + periodeTilOgMed, + ), + ), + ) + + response.status shouldBe OK + val klassifisertInntektResponseDto = + jacksonObjectMapper.readValue(response.bodyAsText()) + klassifisertInntektResponseDto.inntektsId shouldBe inntektsId + klassifisertInntektResponseDto.inntektsListe.shouldNotBeEmpty() + klassifisertInntektResponseDto.manueltRedigert shouldBe true + klassifisertInntektResponseDto.begrunnelseManueltRedigert shouldBe "Dette er en begrunnelse." + klassifisertInntektResponseDto.sisteAvsluttendeKalenderMåned shouldBe sisteAvsluttendeKalenderMåned + } + } + + @Test + fun `Klassifisert-endepunktet returnerer forventet respons når inntekten ikke er manuelt redigert`() { + every { inntektStoreMock.getManueltRedigert(any()) } returns null + + coEvery { + behandlingsInntektsGetterMock.getKlassifisertInntekt( + capture(inntektParametreCapture), + any(), + ) + } returns createInntekt(false) + + withMockAuthServerAndTestApplication( + mockInntektApi( + personOppslag = personOppslagMock, + behandlingsInntektsGetter = behandlingsInntektsGetterMock, + inntektStore = inntektStoreMock, + ), + ) { + val response = + autentisert( + httpMethod = HttpMethod.Post, + endepunkt = "/v3/inntekt/klassifisert", + body = + jacksonObjectMapper.writeValueAsString( + KlassifisertInntektRequestDto( + fødselsnummer, + regelkontekst, + beregningsDato, + periodeFraOgMed, + periodeTilOgMed, + ), + ), + ) + + response.status shouldBe OK + val klassifisertInntektResponseDto = + jacksonObjectMapper.readValue(response.bodyAsText()) + klassifisertInntektResponseDto.inntektsId shouldBe inntektsId + klassifisertInntektResponseDto.inntektsListe.shouldNotBeEmpty() + klassifisertInntektResponseDto.manueltRedigert shouldBe false + klassifisertInntektResponseDto.begrunnelseManueltRedigert shouldBe null + klassifisertInntektResponseDto.sisteAvsluttendeKalenderMåned shouldBe sisteAvsluttendeKalenderMåned + } + } + + private fun createInntekt(manueltRedigert: Boolean): Inntekt = + Inntekt( + inntektsId, + listOf(KlassifisertInntektMåned(now(), listOf())), + manueltRedigert, + now(), + ) +} diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/db/PostgresTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/db/PostgresTest.kt index a14e5471..d7661853 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/db/PostgresTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/db/PostgresTest.kt @@ -1,9 +1,11 @@ package no.nav.dagpenger.inntekt.db import io.kotest.assertions.assertSoftly +import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe +import io.kotest.matchers.throwable.shouldHaveMessage import io.kotest.property.Arb import io.kotest.property.arbitrary.arbitrary import io.kotest.property.arbitrary.localDateTime @@ -29,7 +31,7 @@ internal class PostgresTest { fun `Migration scripts are applied successfully`() { withCleanDb { val migrations = PostgresDataSourceBuilder.runMigration() - assertEquals(16, migrations, "Wrong number of migrations") + assertEquals(18, migrations, "Wrong number of migrations") } } @@ -45,7 +47,7 @@ internal class PostgresTest { fun `Migration of testdata `() { withCleanDb { val migrations = PostgresDataSourceBuilder.runMigration(locations = listOf("db/migration", "db/testdata")) - assertEquals(21, migrations, "Wrong number of migrations") + assertEquals(23, migrations, "Wrong number of migrations") } } } @@ -209,7 +211,7 @@ internal class PostgresInntektStoreTest { emptyList(), Aktoer(AktoerType.AKTOER_ID, "1234"), ) - val manueltRedigert = ManueltRedigert("user") + val manueltRedigert = ManueltRedigert("user", "Dette er en begrunnelse.") val storedInntekt = storeInntekt( @@ -219,14 +221,82 @@ internal class PostgresInntektStoreTest { manueltRedigert = manueltRedigert, ), ) - assertTrue(storedInntekt.manueltRedigert) - val storedInntektByRequest = getInntekt(storedInntekt.inntektId) - assertTrue(storedInntektByRequest.manueltRedigert) - val storedManueltRedigert = getManueltRedigert(storedInntekt.inntektId) - assertNotNull(storedManueltRedigert) - assertEquals(manueltRedigert, storedManueltRedigert) + storedManueltRedigert shouldNotBe null + storedManueltRedigert shouldBe manueltRedigert + storedInntekt.manueltRedigert shouldBe true + storedInntektByRequest.manueltRedigert shouldBe true + } + } + } + + @Test + fun `Lagring av inntekt skal kaste IllegalArgumentException når begrunnelse er lengre enn 1024 tegn`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val parameters = Inntektparametre("1234", "1234", LocalDate.now(), RegelKontekst("1234", "vedtak")) + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + val manueltRedigert = ManueltRedigert("user", "A".repeat(1025)) + + val exception = + shouldThrow { + storeInntekt( + StoreInntektCommand( + inntektparametre = parameters, + inntekt = hentInntektListeResponse, + manueltRedigert = manueltRedigert, + ), + ) + } + exception shouldHaveMessage "Begrunnelsen kan ikke være lengre enn 1024 tegn." + } + } + } + + @Test + fun `getStoredInntektMedMetadata returnerer forventet resultat når inntekten ikke er manuelt redigert`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val parameters = Inntektparametre("1234", "1234", LocalDate.now(), RegelKontekst("1234", "vedtak")) + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + storeInntekt( + StoreInntektCommand( + inntektparametre = parameters, + inntekt = hentInntektListeResponse, + manueltRedigert = null, + ), + ) + } + } + } + + @Test + fun `getStoredInntektMedMetadata returnerer forventet resultat når inntekten er manuelt redigert`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val parameters = Inntektparametre("1234", "1234", LocalDate.now(), RegelKontekst("1234", "vedtak")) + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + val manueltRedigert = ManueltRedigert("user", "Dette er en begrunnelse.") + storeInntekt( + StoreInntektCommand( + inntektparametre = parameters, + inntekt = hentInntektListeResponse, + manueltRedigert = manueltRedigert, + ), + ) } } } @@ -440,6 +510,108 @@ internal class PostgresInntektStoreTest { } } } + + @Test + fun `Hent inntekt_person_mapping`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + val inntektparametre = + Inntektparametre( + aktørId = "12345", + fødselsnummer = "0987654321", + beregningsdato = LocalDate.now(), + regelkontekst = RegelKontekst("432", "vedtak"), + ) + val storedInntekt = + storeInntekt( + StoreInntektCommand( + inntektparametre = inntektparametre, + inntekt = hentInntektListeResponse, + ), + ) + + val inntektPersonMapping = getInntektPersonMapping(storedInntekt.inntektId.id) + + inntektPersonMapping.inntektId.id shouldBe storedInntekt.inntektId.id + inntektPersonMapping.aktørId shouldBe inntektparametre.aktørId + inntektPersonMapping.fnr shouldBe inntektparametre.fødselsnummer + inntektPersonMapping.kontekstId shouldBe inntektparametre.regelkontekst.id + inntektPersonMapping.beregningsdato shouldBe inntektparametre.beregningsdato + inntektPersonMapping.timestamp shouldNotBe null + inntektPersonMapping.kontekstType shouldBe inntektparametre.regelkontekst.type + } + } + } + + @Test + fun `getStoredInntektMedMetadata returnerer forventet respons`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + val inntektparametre = Inntektparametre("1234", "1234", LocalDate.now(), RegelKontekst("12345", "vedtak")) + val storedInntekt = + storeInntekt( + StoreInntektCommand( + inntektparametre = inntektparametre, + inntekt = hentInntektListeResponse, + ), + ) + + val storedInntektMedMetadata = getStoredInntektMedMetadata(storedInntekt.inntektId) + + storedInntektMedMetadata.inntektId shouldBe storedInntekt.inntektId + storedInntektMedMetadata.inntekt shouldBe hentInntektListeResponse + storedInntektMedMetadata.manueltRedigert shouldBe false + storedInntektMedMetadata.fødselsnummer shouldBe "1234" + storedInntektMedMetadata.timestamp shouldNotBe null + storedInntektMedMetadata.begrunnelse shouldBe null + } + } + } + + @Test + fun `getStoredInntektMedMetadata inkluderer begrunnelse når det finnes`() { + withMigratedDb { + with(PostgresInntektStore(PostgresDataSourceBuilder.dataSource)) { + val hentInntektListeResponse = + InntektkomponentResponse( + emptyList(), + Aktoer(AktoerType.AKTOER_ID, "1234"), + ) + val inntektparametre = Inntektparametre("1234", "1234", LocalDate.now(), RegelKontekst("12345", "vedtak")) + val storedInntekt = + storeInntekt( + StoreInntektCommand( + inntektparametre = inntektparametre, + inntekt = hentInntektListeResponse, + manueltRedigert = + ManueltRedigert( + redigertAv = "user", + begrunnelse = "Dette er en begrunnelse.", + ), + ), + ) + + val storedInntektMedMetadata = getStoredInntektMedMetadata(storedInntekt.inntektId) + + storedInntektMedMetadata.inntektId shouldBe storedInntekt.inntektId + storedInntektMedMetadata.inntekt shouldBe hentInntektListeResponse + storedInntektMedMetadata.manueltRedigert shouldBe true + storedInntektMedMetadata.fødselsnummer shouldBe "1234" + storedInntektMedMetadata.timestamp shouldNotBe null + storedInntektMedMetadata.begrunnelse shouldBe "Dette er en begrunnelse." + } + } + } } internal class InntektsStorePropertyTest : StringSpec() { @@ -474,7 +646,9 @@ internal class InntektsStorePropertyTest : StringSpec() { regelkontekst = RegelKontekst(kontekstId.next(it), "vedtak"), fødselsnummer = aktørId.next(it), beregningsdato = - Arb.localDateTime(minYear = 2010, maxYear = LocalDate.now().year).next(it) + Arb + .localDateTime(minYear = 2010, maxYear = LocalDate.now().year) + .next(it) .toLocalDate(), ), inntekt = diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontendTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontendTest.kt index ed8bf6a3..7947ecd0 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontendTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/mapping/MapToInntektFrontendTest.kt @@ -1,5 +1,10 @@ package no.nav.dagpenger.inntekt.mapping +import de.huxhorn.sulky.ulid.ULID +import io.kotest.matchers.shouldBe +import no.nav.dagpenger.inntekt.db.InntektId +import no.nav.dagpenger.inntekt.db.StoredInntektMedMetadata +import no.nav.dagpenger.inntekt.db.StoredInntektPeriode import no.nav.dagpenger.inntekt.inntektskomponenten.v1.Aktoer import no.nav.dagpenger.inntekt.inntektskomponenten.v1.AktoerType import no.nav.dagpenger.inntekt.inntektskomponenten.v1.ArbeidsInntektInformasjon @@ -12,6 +17,8 @@ import no.nav.dagpenger.inntekt.inntektskomponenten.v1.TilleggInformasjon import no.nav.dagpenger.inntekt.serder.jacksonObjectMapper import org.junit.jupiter.api.Test import java.math.BigDecimal +import java.time.LocalDate.now +import java.time.LocalDateTime import java.time.YearMonth import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -187,10 +194,21 @@ class MapToInntektFrontendTest { fun `Map inntekt til InntektForVirksomhetMedPersonInformasjon`() { val mappedToInntektFrontend = inntektkomponentResponse.mapToFrontend( - mottaker, - organisasjoner, + person = mottaker, + organisasjoner = organisasjoner, + StoredInntektMedMetadata( + InntektId(ULID().nextULID().toString()), + inntektkomponentResponse, + true, + LocalDateTime.now(), + "01234567890", + now(), + StoredInntektPeriode(YearMonth.now(), YearMonth.now()), + "Dette er en begrunnelse.", + ), ) + mappedToInntektFrontend.begrunnelse shouldBe "Dette er en begrunnelse." assertEquals(2, mappedToInntektFrontend.virksomheter.size) assertEquals(mottaker, mappedToInntektFrontend.mottaker) @@ -331,7 +349,20 @@ class MapToInntektFrontendTest { ) val mapTilFrontendMedNullVirksomhet = - inntektkomponentResponseMedTomVirksomhet.mapToFrontend(mottaker, organisasjoner) + inntektkomponentResponseMedTomVirksomhet.mapToFrontend( + mottaker, + organisasjoner, + StoredInntektMedMetadata( + InntektId(ULID().nextULID().toString()), + inntektkomponentResponse, + true, + LocalDateTime.now(), + "01234567890", + now(), + StoredInntektPeriode(YearMonth.now(), YearMonth.now()), + "Dette er en begrunnelse.", + ), + ) assertEquals(3, mapTilFrontendMedNullVirksomhet.virksomheter.size) assertEquals(2, mapTilFrontendMedNullVirksomhet.virksomheter.filter { it.virksomhetsnummer == "" }.size) assertEquals(1, mapTilFrontendMedNullVirksomhet.virksomheter.filter { it.virksomhetsnummer == "896929120" }.size) diff --git a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/subsumsjonbrukt/VaktmesterTest.kt b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/subsumsjonbrukt/VaktmesterTest.kt index 0f64ea7c..db680cd8 100644 --- a/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/subsumsjonbrukt/VaktmesterTest.kt +++ b/dp-inntekt-api/src/test/kotlin/no/nav/dagpenger/inntekt/subsumsjonbrukt/VaktmesterTest.kt @@ -16,12 +16,14 @@ import no.nav.dagpenger.inntekt.inntektskomponenten.v1.AktoerType import no.nav.dagpenger.inntekt.inntektskomponenten.v1.ArbeidsInntektInformasjon import no.nav.dagpenger.inntekt.inntektskomponenten.v1.ArbeidsInntektMaaned import no.nav.dagpenger.inntekt.inntektskomponenten.v1.InntektkomponentResponse +import org.junit.jupiter.api.Order import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import java.time.LocalDate import java.time.YearMonth import java.time.ZonedDateTime +@Order(0) internal class VaktmesterTest { private val parameters = Inntektparametre( @@ -121,7 +123,9 @@ internal class VaktmesterTest { assertThrows { inntektStore.getInntekt(ubruktEldreEnn180Dager.inntektId) } inntektStore.getInntekt(ubruktYngreEnn180Dager.inntektId) shouldBe ubruktYngreEnn180Dager } - PrometheusRegistry.defaultRegistry.scrape().find { it.metadata.name == "inntekt_slettet" } + PrometheusRegistry.defaultRegistry + .scrape() + .find { it.metadata.name == "inntekt_slettet" } ?.let { metric -> metric.dataPoints[0].labels shouldNotBe null metric.dataPoints[0].scrapeTimestampMillis shouldNotBe null diff --git a/dp-inntekt-api/src/test/resources/junit-platform.properties b/dp-inntekt-api/src/test/resources/junit-platform.properties new file mode 100644 index 00000000..23acd63a --- /dev/null +++ b/dp-inntekt-api/src/test/resources/junit-platform.properties @@ -0,0 +1 @@ +junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation \ No newline at end of file diff --git a/dp-inntekt-api/src/test/resources/test-data/expected-uklassifisert-post-body.json b/dp-inntekt-api/src/test/resources/test-data/expected-uklassifisert-post-body.json index fd0272bb..43942cea 100644 --- a/dp-inntekt-api/src/test/resources/test-data/expected-uklassifisert-post-body.json +++ b/dp-inntekt-api/src/test/resources/test-data/expected-uklassifisert-post-body.json @@ -4,8 +4,8 @@ "virksomhetsnummer": "123456789", "virksomhetsnavn": "Test Virksomhet", "periode": { - "fra": "2023-01", - "til": "2024-12" + "fraOgMed": "2023-01", + "tilOgMed": "2024-12" }, "inntekter": [ { @@ -131,8 +131,8 @@ "virksomhetsnummer": "987654321", "virksomhetsnavn": "Virksomheten Test", "periode": { - "fra": "2024-01", - "til": "2025-03" + "fraOgMed": "2024-01", + "tilOgMed": "2025-03" }, "inntekter": [ { @@ -271,8 +271,8 @@ "virksomhetsnummer": "550475189", "virksomhetsnavn": "Virksomheten Test", "periode": { - "fra": "2000-12", - "til": "2000-12" + "fraOgMed": "2000-12", + "tilOgMed": "2000-12" }, "inntekter": [], "totalBelop": 0, @@ -299,5 +299,10 @@ "mottaker": { "pnr": "19876543210", "navn": "Navn Navnesen" - } + }, + "periode": { + "fraOgMed": "2000-12", + "tilOgMed": "2025-04" + }, + "begrunnelse": "Dette er en begrunnelse." } \ No newline at end of file diff --git a/nais/dev/nais.yaml b/nais/dev/nais.yaml index c86c4b54..766a552e 100644 --- a/nais/dev/nais.yaml +++ b/nais/dev/nais.yaml @@ -33,7 +33,7 @@ spec: memory: 512Mi requests: cpu: 100m - memory: 256Mi + memory: 512Mi observability: logging: destinations: @@ -78,7 +78,7 @@ spec: - collation: nb_NO.UTF8 databases: - envVarPrefix: DB - name: inntekt-gjustering6 + name: inntekt diskAutoresize: true diskType: SSD highAvailability: false diff --git a/nais/prod/nais.yaml b/nais/prod/nais.yaml index 2767c379..6cb49969 100644 --- a/nais/prod/nais.yaml +++ b/nais/prod/nais.yaml @@ -25,7 +25,7 @@ spec: max: 6 resources: limits: - memory: 1024Mi + memory: 768Mi requests: cpu: 30m memory: 512Mi