From acc705e190f105441fc4cc11f39f55dbfebda098 Mon Sep 17 00:00:00 2001 From: Mikael Bjerga Date: Mon, 23 Dec 2024 15:11:09 +0100 Subject: [PATCH] =?UTF-8?q?Returner=20kvittering=20basert=20p=C3=A5=20skje?= =?UTF-8?q?ma=20til=20frontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inntektsmelding/api/App.kt | 6 +- .../api/kvittering/KvitteringRoute.kt | 60 +++++- .../inntektsmelding/api/LocalApiApp.kt | 9 - .../api/kvittering/KvitteringRouteKtTest.kt | 62 ++---- .../db/InntektsmeldingRepository.kt | 14 +- .../db/river/HentLagretImRiver.kt | 44 +++- .../db/river/HentLagretImRiverTest.kt | 66 +++++- .../helsearbeidsgiver/felles/app/LocalApp.kt | 23 --- .../felles/domene/EksternInntektsmelding.kt | 7 - .../felles/domene/KvitteringResultat.kt | 16 ++ .../inntektsmelding/innsending/App.kt | 3 +- .../innsending/KvitteringService.kt | 188 ++++++++++++++---- .../KvitteringServiceTest.kt | 135 +++++++++---- .../integrasjonstest/KvitteringIT.kt | 41 +++- .../LagreSelvbestemtImService.kt | 1 - .../trengerservice/HentForespoerselService.kt | 3 - 16 files changed, 476 insertions(+), 202 deletions(-) delete mode 100644 apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/LocalApiApp.kt delete mode 100644 apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/app/LocalApp.kt create mode 100644 apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/KvitteringResultat.kt diff --git a/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt b/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt index bc8f833ef4..f50817a8e0 100644 --- a/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt +++ b/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt @@ -57,11 +57,7 @@ object Routes { } fun main() { - startServer() -} - -fun startServer(env: Map = System.getenv()) { - val rapid = RapidApplication.create(env) + val rapid = RapidApplication.create(System.getenv()) val redisConnection = RedisConnection(Env.Redis.url) embeddedServer( diff --git a/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt b/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt index 597d9ca5e2..c24a47c9f5 100644 --- a/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt +++ b/apps/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt @@ -4,16 +4,20 @@ import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection import io.ktor.server.application.call import io.ktor.server.routing.Route import io.ktor.server.routing.get +import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.builtins.serializer import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntekt import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding -import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Kvittering import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.KvitteringEkstern import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.KvitteringSimba +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Avsender +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Periode +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Sykmeldt +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.Tekst import no.nav.helsearbeidsgiver.felles.domene.EksternInntektsmelding -import no.nav.helsearbeidsgiver.felles.domene.InnsendtInntektsmelding +import no.nav.helsearbeidsgiver.felles.domene.KvitteringResultat import no.nav.helsearbeidsgiver.felles.metrics.Metrics import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisConnection import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisPrefix @@ -70,13 +74,13 @@ fun Route.kvittering( kvitteringProducer.publish(transaksjonId, forespoerselId) val resultatJson = redisPoller.hent(transaksjonId) - val resultat = resultatJson.success?.fromJson(InnsendtInntektsmelding.serializer()) + val resultat = resultatJson.success?.fromJson(KvitteringResultat.serializer()) if (resultat != null) { sikkerLogger.info("Hentet kvittering for '$forespoerselId'.\n${resultatJson.success?.toPretty()}") - if (resultat.dokument == null && resultat.eksternInntektsmelding == null) { + if (resultat.skjema == null && resultat.inntektsmelding == null && resultat.eksternInntektsmelding == null) { respondNotFound("Kvittering ikke funnet for forespørselId: $forespoerselId", String.serializer()) } else { - respondOk(resultat.tilKvittering(), Kvittering.serializer()) + respondOk(resultat.tilResponse(), KvitteringResponse.serializer()) } } else { val feilmelding = resultatJson.failure?.fromJson(String.serializer()) ?: Tekst.TEKNISK_FEIL_FORBIGAAENDE @@ -99,12 +103,52 @@ fun Route.kvittering( } } -private fun InnsendtInntektsmelding.tilKvittering(): Kvittering = - Kvittering( - kvitteringDokument = dokument?.tilKvitteringSimba(), +@Serializable +private data class KvitteringResponse( + val kvitteringNavNo: KvitteringNavNo?, + val kvitteringDokument: KvitteringSimba?, + val kvitteringEkstern: KvitteringEkstern?, +) + +@Serializable +private data class KvitteringNavNo( + val sykmeldt: Sykmeldt, + val avsender: Avsender, + val sykmeldingsperioder: List, + val skjema: SkjemaInntektsmelding, +) + +private fun KvitteringResultat.tilResponse(): KvitteringResponse = + KvitteringResponse( + kvitteringNavNo = tilKvitteringNavNo(), + kvitteringDokument = inntektsmelding?.tilKvitteringSimba(), kvitteringEkstern = eksternInntektsmelding?.tilKvitteringEkstern(), ) +private fun KvitteringResultat.tilKvitteringNavNo(): KvitteringNavNo? { + val skjemaKvittering = skjema + return if (skjemaKvittering != null) { + KvitteringNavNo( + sykmeldt = + Sykmeldt( + fnr = forespoersel.fnr, + navn = sykmeldtNavn, + ), + avsender = + Avsender( + orgnr = forespoersel.orgnr, + orgNavn = orgNavn, + navn = avsenderNavn, + tlf = skjemaKvittering.avsenderTlf, + ), + sykmeldingsperioder = forespoersel.sykmeldingsperioder, + skjema = skjemaKvittering, + ) + } else { + null + } +} + private fun Inntektsmelding.tilKvitteringSimba(): KvitteringSimba = KvitteringSimba( orgnrUnderenhet = orgnrUnderenhet, diff --git a/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/LocalApiApp.kt b/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/LocalApiApp.kt deleted file mode 100644 index 0930f59887..0000000000 --- a/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/LocalApiApp.kt +++ /dev/null @@ -1,9 +0,0 @@ -package no.nav.helsearbeidsgiver.inntektsmelding.api - -import no.nav.helsearbeidsgiver.felles.app.LocalApp - -fun main() { - val env = LocalApp().setupEnvironment("im-api", 8081) - - startServer(env) -} diff --git a/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRouteKtTest.kt b/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRouteKtTest.kt index 235aaf2248..56574f4cd3 100644 --- a/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRouteKtTest.kt +++ b/apps/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRouteKtTest.kt @@ -2,14 +2,17 @@ package no.nav.helsearbeidsgiver.inntektsmelding.api.kvittering import io.ktor.http.HttpStatusCode import io.mockk.coEvery +import no.nav.helsearbeidsgiver.felles.domene.KvitteringResultat import no.nav.helsearbeidsgiver.felles.domene.ResultJson import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.test.mock.mockEksternInntektsmelding +import no.nav.helsearbeidsgiver.felles.test.mock.mockForespoersel +import no.nav.helsearbeidsgiver.felles.test.mock.mockInntektsmelding +import no.nav.helsearbeidsgiver.felles.test.mock.mockSkjemaInntektsmelding import no.nav.helsearbeidsgiver.inntektsmelding.api.Routes import no.nav.helsearbeidsgiver.inntektsmelding.api.utils.ApiTest import no.nav.helsearbeidsgiver.inntektsmelding.api.utils.harTilgangResultat -import no.nav.helsearbeidsgiver.utils.json.parseJson import no.nav.helsearbeidsgiver.utils.json.toJson -import no.nav.helsearbeidsgiver.utils.test.json.removeJsonWhitespace import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import java.util.UUID @@ -38,7 +41,7 @@ class KvitteringRouteKtTest : ApiTest() { listOf( harTilgangResultat, ResultJson( - success = resultatMedInntektsmelding.parseJson(), + success = resultat.toJson(KvitteringResultat.serializer()), ).toJson() .toString(), ) @@ -49,46 +52,13 @@ class KvitteringRouteKtTest : ApiTest() { } } -private val resultatMedInntektsmelding = - """ - { - "dokument": { - "orgnrUnderenhet": "123456789", - "identitetsnummer": "12345678901", - "fulltNavn": "Ukjent", - "virksomhetNavn": "Ukjent", - "behandlingsdager": [], - "egenmeldingsperioder": [], - "bestemmendeFraværsdag": "2023-01-01", - "fraværsperioder": [ - { - "fom": "2023-01-01", - "tom": "2023-01-31" - } - ], - "arbeidsgiverperioder": [ - { - "fom": "2023-01-01", - "tom": "2023-01-16" - } - ], - "beregnetInntekt": 3000, - "fullLønnIArbeidsgiverPerioden": { - "utbetalerFullLønn": true, - "begrunnelse": null, - "utbetalt": null - }, - "refusjon": { - "utbetalerHeleEllerDeler": false, - "refusjonPrMnd": null, - "refusjonOpphører": null, - "refusjonEndringer": null - }, - "naturalytelser": null, - "tidspunkt": "2023-04-13T16:28:16.095083285+02:00", - "årsakInnsending": "NY", - "identitetsnummerInnsender": "" - }, - "eksternInntektsmelding": null - } - """.removeJsonWhitespace() +private val resultat = + KvitteringResultat( + forespoersel = mockForespoersel(), + sykmeldtNavn = "Syk Meldt", + avsenderNavn = "Avs Ender", + orgNavn = "Orga Nisasjon", + skjema = mockSkjemaInntektsmelding(), + inntektsmelding = mockInntektsmelding(), + eksternInntektsmelding = mockEksternInntektsmelding(), + ) diff --git a/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt b/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt index 3eeaa1623c..4967187e1f 100644 --- a/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt +++ b/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/InntektsmeldingRepository.kt @@ -25,21 +25,25 @@ class InntektsmeldingRepository( private val logger = logger() private val sikkerLogger = sikkerLogger() - fun hentNyesteEksternEllerInternInntektsmelding(forespoerselId: UUID): Pair = + fun hentNyesteEksternEllerInternInntektsmelding(forespoerselId: UUID): Triple = Metrics.dbInntektsmelding.recordTime(InntektsmeldingRepository::hentNyesteEksternEllerInternInntektsmelding) { transaction(db) { InntektsmeldingEntitet - .select(InntektsmeldingEntitet.dokument, InntektsmeldingEntitet.eksternInntektsmelding) - .where { InntektsmeldingEntitet.forespoerselId eq forespoerselId.toString() } + .select( + InntektsmeldingEntitet.skjema, + InntektsmeldingEntitet.dokument, + InntektsmeldingEntitet.eksternInntektsmelding, + ).where { InntektsmeldingEntitet.forespoerselId eq forespoerselId.toString() } .orderBy(InntektsmeldingEntitet.innsendt, SortOrder.DESC) .limit(1) .map { - Pair( + Triple( + it[InntektsmeldingEntitet.skjema], it[InntektsmeldingEntitet.dokument], it[InntektsmeldingEntitet.eksternInntektsmelding], ) }.firstOrNull() - }.orDefault(Pair(null, null)) + }.orDefault(Triple(null, null, null)) } fun oppdaterJournalpostId( diff --git a/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiver.kt b/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiver.kt index cad54ea16a..a9c62d76f6 100644 --- a/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiver.kt +++ b/apps/db/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiver.kt @@ -1,7 +1,11 @@ package no.nav.helsearbeidsgiver.inntektsmelding.db.river import kotlinx.serialization.json.JsonElement +import no.nav.helsearbeidsgiver.domene.inntektsmelding.Utils.convert +import no.nav.helsearbeidsgiver.domene.inntektsmelding.Utils.convertAgp +import no.nav.helsearbeidsgiver.domene.inntektsmelding.Utils.convertInntekt import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.BehovType import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key @@ -9,14 +13,17 @@ import no.nav.helsearbeidsgiver.felles.domene.EksternInntektsmelding import no.nav.helsearbeidsgiver.felles.domene.ResultJson import no.nav.helsearbeidsgiver.felles.json.krev import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.lesOrNull import no.nav.helsearbeidsgiver.felles.json.toJson import no.nav.helsearbeidsgiver.felles.json.toMap +import no.nav.helsearbeidsgiver.felles.rapidsrivers.KafkaKey import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail import no.nav.helsearbeidsgiver.felles.rapidsrivers.river.ObjectRiver import no.nav.helsearbeidsgiver.felles.utils.Log import no.nav.helsearbeidsgiver.inntektsmelding.db.InntektsmeldingRepository import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.json.toPretty import no.nav.helsearbeidsgiver.utils.log.logger import no.nav.helsearbeidsgiver.utils.log.sikkerLogger import java.util.UUID @@ -26,6 +33,7 @@ data class HentLagretImMelding( val behovType: BehovType, val transaksjonId: UUID, val data: Map, + val svarKafkaKey: KafkaKey?, val forespoerselId: UUID, ) @@ -46,15 +54,33 @@ class HentLagretImRiver( behovType = Key.BEHOV.krev(BehovType.HENT_LAGRET_IM, BehovType.serializer(), json), transaksjonId = Key.KONTEKST_ID.les(UuidSerializer, json), data = data, + svarKafkaKey = Key.SVAR_KAFKA_KEY.lesOrNull(KafkaKey.serializer(), data), forespoerselId = Key.FORESPOERSEL_ID.les(UuidSerializer, data), ) } override fun HentLagretImMelding.haandter(json: Map): Map { - val (inntektsmelding, eksternInntektsmelding) = + val ( + skjema, + inntektsmelding, + eksternInntektsmelding, + ) = imRepo .hentNyesteEksternEllerInternInntektsmelding(forespoerselId) - .tilPayloadPair() + .let { (skjema, inntektsmelding, eksternInntektsmelding) -> + val bakoverkompatibeltSkjema = + skjema ?: inntektsmelding?.let { + SkjemaInntektsmelding( + forespoerselId = forespoerselId, + avsenderTlf = it.telefonnummer.orEmpty(), + agp = it.convertAgp(), + inntekt = it.convertInntekt(), + refusjon = it.refusjon.convert(), + ) + } + + Triple(bakoverkompatibeltSkjema, inntektsmelding, eksternInntektsmelding) + }.tilPayloadTriple() loggHentet(inntektsmelding, eksternInntektsmelding) @@ -65,6 +91,7 @@ class HentLagretImRiver( data .plus( mapOf( + Key.SKJEMA_INNTEKTSMELDING to skjema.toJson(), Key.LAGRET_INNTEKTSMELDING to inntektsmelding.toJson(), Key.EKSTERN_INNTEKTSMELDING to eksternInntektsmelding.toJson(), ), @@ -109,7 +136,7 @@ class HentLagretImRiver( } } else { logger.info("Fant lagret inntektsmelding.") - sikkerLogger.info("Fant lagret inntektsmelding:\n${inntektsmelding.success}") + sikkerLogger.info("Fant lagret inntektsmelding.\n${inntektsmelding.success?.toPretty()}") } if (eksternInntektsmelding.success == null) { @@ -119,15 +146,16 @@ class HentLagretImRiver( } } else { logger.info("Fant lagret ekstern inntektsmelding.") - sikkerLogger.info("Fant lagret ekstern inntektsmelding:\n${eksternInntektsmelding.success}") + sikkerLogger.info("Fant lagret ekstern inntektsmelding.\n${eksternInntektsmelding.success?.toPretty()}") } } } -private fun Pair.tilPayloadPair(): Pair = - Pair( - first?.toJson(Inntektsmelding.serializer()).toSuccess(), - second?.toJson(EksternInntektsmelding.serializer()).toSuccess(), +private fun Triple.tilPayloadTriple(): Triple = + Triple( + first?.toJson(SkjemaInntektsmelding.serializer()).toSuccess(), + second?.toJson(Inntektsmelding.serializer()).toSuccess(), + third?.toJson(EksternInntektsmelding.serializer()).toSuccess(), ) private fun JsonElement?.toSuccess(): ResultJson = ResultJson(success = this) diff --git a/apps/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiverTest.kt b/apps/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiverTest.kt index b936fb2f45..f6c2b78db3 100644 --- a/apps/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiverTest.kt +++ b/apps/db/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/db/river/HentLagretImRiverTest.kt @@ -11,7 +11,9 @@ import io.mockk.mockk import io.mockk.verify import io.mockk.verifySequence import kotlinx.serialization.json.JsonElement +import no.nav.helsearbeidsgiver.domene.inntektsmelding.Utils.convert import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.BehovType import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key @@ -23,6 +25,8 @@ import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail import no.nav.helsearbeidsgiver.felles.test.mock.mockEksternInntektsmelding import no.nav.helsearbeidsgiver.felles.test.mock.mockFail import no.nav.helsearbeidsgiver.felles.test.mock.mockInntektsmelding +import no.nav.helsearbeidsgiver.felles.test.mock.mockInntektsmeldingV1 +import no.nav.helsearbeidsgiver.felles.test.mock.mockSkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.firstMessage import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.sendJson import no.nav.helsearbeidsgiver.inntektsmelding.db.InntektsmeldingRepository @@ -46,10 +50,11 @@ class HentLagretImRiverTest : context("henter inntektsmelding") { withData( mapOf( - "kun inntektsmelding" to Pair(mockInntektsmelding(), null), - "kun ekstern inntektsmelding" to Pair(null, mockEksternInntektsmelding()), - "ingen funnet" to Pair(null, null), - "begge typer funnet (skal ikke skje)" to Pair(mockInntektsmelding(), mockEksternInntektsmelding()), + "kun skjema og inntektsmelding" to Triple(mockSkjemaInntektsmelding(), mockInntektsmelding(), null), + "kun skjema" to Triple(mockSkjemaInntektsmelding(), null, null), + "kun ekstern inntektsmelding" to Triple(null, null, mockEksternInntektsmelding()), + "ingen funnet" to Triple(null, null, null), + "alle typer funnet (skal ikke skje)" to Triple(mockSkjemaInntektsmelding(), mockInntektsmelding(), mockEksternInntektsmelding()), ), ) { lagret -> every { @@ -72,13 +77,18 @@ class HentLagretImRiverTest : innkommendeMelding.data .plus( mapOf( - Key.LAGRET_INNTEKTSMELDING to + Key.SKJEMA_INNTEKTSMELDING to lagret.first + ?.toJson(SkjemaInntektsmelding.serializer()) + ?.toSuccessJson() + .orDefault(MockHentIm.tomResultJson()), + Key.LAGRET_INNTEKTSMELDING to + lagret.second ?.toJson(Inntektsmelding.serializer()) ?.toSuccessJson() .orDefault(MockHentIm.tomResultJson()), Key.EKSTERN_INNTEKTSMELDING to - lagret.second + lagret.third ?.toJson(EksternInntektsmelding.serializer()) ?.toSuccessJson() .orDefault(MockHentIm.tomResultJson()), @@ -92,6 +102,49 @@ class HentLagretImRiverTest : } } + test("konverterer inntektsmelding til skjema dersom skjema mangler") { + val innkommendeMelding = MockHentIm.innkommendeMelding() + val imV1 = mockInntektsmeldingV1() + val im = imV1.convert() + val skjema = + SkjemaInntektsmelding( + forespoerselId = innkommendeMelding.forespoerselId, + avsenderTlf = imV1.avsender.tlf, + agp = imV1.agp, + inntekt = imV1.inntekt, + refusjon = imV1.refusjon, + ) + + every { + mockImRepo.hentNyesteEksternEllerInternInntektsmelding(any()) + } returns Triple(null, im, null) + + testRapid.sendJson( + innkommendeMelding.toMap(), + ) + + testRapid.inspektør.size shouldBeExactly 1 + + testRapid.firstMessage().toMap() shouldContainExactly + mapOf( + Key.EVENT_NAME to innkommendeMelding.eventName.toJson(), + Key.KONTEKST_ID to innkommendeMelding.transaksjonId.toJson(), + Key.DATA to + innkommendeMelding.data + .plus( + mapOf( + Key.SKJEMA_INNTEKTSMELDING to skjema.toJson(SkjemaInntektsmelding.serializer()).toSuccessJson(), + Key.LAGRET_INNTEKTSMELDING to im.toJson(Inntektsmelding.serializer()).toSuccessJson(), + Key.EKSTERN_INNTEKTSMELDING to MockHentIm.tomResultJson(), + ), + ).toJson(), + ) + + verifySequence { + mockImRepo.hentNyesteEksternEllerInternInntektsmelding(innkommendeMelding.forespoerselId) + } + } + test("håndterer feil") { every { mockImRepo.hentNyesteEksternEllerInternInntektsmelding(any()) @@ -153,6 +206,7 @@ private object MockHentIm { mapOf( Key.FORESPOERSEL_ID to forespoerselId.toJson(), ), + svarKafkaKey = null, forespoerselId = forespoerselId, ) } diff --git a/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/app/LocalApp.kt b/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/app/LocalApp.kt deleted file mode 100644 index c2e93bc74e..0000000000 --- a/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/app/LocalApp.kt +++ /dev/null @@ -1,23 +0,0 @@ -package no.nav.helsearbeidsgiver.felles.app - -open class LocalApp { - open fun setupEnvironment( - memberId: String, - httpPort: Int, - ): Map { - val env = - mapOf( - "KAFKA_BOOTSTRAP_SERVERS" to "PLAINTEXT://localhost:9092", - "KAFKA_CONSUMER_GROUP_ID" to memberId, - "KAFKA_RAPID_TOPIC" to "helsearbeidsgiver.rapid", - "IDPORTEN_AUDIENCE" to "aud-localhost", - "IDPORTEN_WELL_KNOWN_URL" to "https://fakedings.intern.dev.nav.no/default/.well-known/openid-configuration", - "NAIS_APP_NAME" to "nimrod", - "REDIS_URL" to "redis://localhost:6379/0", - "REDIS_HOST" to "localhost", - "HTTP_PORT" to "" + httpPort, - ) - env.forEach { (k, v) -> System.setProperty(k, v) } - return env - } -} diff --git a/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/EksternInntektsmelding.kt b/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/EksternInntektsmelding.kt index e75697b84b..549c745108 100644 --- a/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/EksternInntektsmelding.kt +++ b/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/EksternInntektsmelding.kt @@ -4,7 +4,6 @@ package no.nav.helsearbeidsgiver.felles.domene import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding import no.nav.helsearbeidsgiver.utils.json.serializer.LocalDateTimeSerializer import java.time.LocalDateTime @@ -15,9 +14,3 @@ data class EksternInntektsmelding( val arkivreferanse: String, val tidspunkt: LocalDateTime, ) - -@Serializable -data class InnsendtInntektsmelding( - val dokument: Inntektsmelding?, - val eksternInntektsmelding: EksternInntektsmelding?, -) diff --git a/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/KvitteringResultat.kt b/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/KvitteringResultat.kt new file mode 100644 index 0000000000..0409720cd1 --- /dev/null +++ b/apps/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/domene/KvitteringResultat.kt @@ -0,0 +1,16 @@ +package no.nav.helsearbeidsgiver.felles.domene + +import kotlinx.serialization.Serializable +import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding + +@Serializable +data class KvitteringResultat( + val forespoersel: Forespoersel, + val sykmeldtNavn: String, + val avsenderNavn: String, + val orgNavn: String, + val skjema: SkjemaInntektsmelding?, + val inntektsmelding: Inntektsmelding?, + val eksternInntektsmelding: EksternInntektsmelding?, +) diff --git a/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/App.kt b/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/App.kt index 375d35eb83..1d4804f8fe 100644 --- a/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/App.kt +++ b/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/App.kt @@ -6,6 +6,7 @@ import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisConnection import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisPrefix import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore import no.nav.helsearbeidsgiver.felles.rapidsrivers.registerShutdownLifecycle +import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceRiverStateful import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceRiverStateless import no.nav.helsearbeidsgiver.utils.log.logger @@ -33,7 +34,7 @@ fun RapidsConnection.createInnsending(redisConnection: RedisConnection): RapidsC ).connect(this) logger.info("Starter ${KvitteringService::class.simpleName}...") - ServiceRiverStateless( + ServiceRiverStateful( KvitteringService( rapid = this, redisStore = RedisStore(redisConnection, RedisPrefix.Kvittering), diff --git a/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/KvitteringService.kt b/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/KvitteringService.kt index fb4c848cc3..04f0db9880 100644 --- a/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/KvitteringService.kt +++ b/apps/innsending/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/innsending/KvitteringService.kt @@ -3,18 +3,25 @@ package no.nav.helsearbeidsgiver.inntektsmelding.innsending import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection import kotlinx.serialization.json.JsonElement import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.BehovType import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key import no.nav.helsearbeidsgiver.felles.domene.EksternInntektsmelding -import no.nav.helsearbeidsgiver.felles.domene.InnsendtInntektsmelding +import no.nav.helsearbeidsgiver.felles.domene.Forespoersel +import no.nav.helsearbeidsgiver.felles.domene.KvitteringResultat +import no.nav.helsearbeidsgiver.felles.domene.Person import no.nav.helsearbeidsgiver.felles.domene.ResultJson import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.orgMapSerializer +import no.nav.helsearbeidsgiver.felles.json.personMapSerializer import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.rapidsrivers.KafkaKey import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore -import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceMed1Steg +import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.Service +import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceMed2Steg import no.nav.helsearbeidsgiver.felles.utils.Log import no.nav.helsearbeidsgiver.utils.json.fromJson import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer @@ -23,12 +30,18 @@ import no.nav.helsearbeidsgiver.utils.json.toPretty import no.nav.helsearbeidsgiver.utils.log.MdcUtils import no.nav.helsearbeidsgiver.utils.log.logger import no.nav.helsearbeidsgiver.utils.log.sikkerLogger +import no.nav.helsearbeidsgiver.utils.wrapper.Fnr +import no.nav.helsearbeidsgiver.utils.wrapper.Orgnr import java.util.UUID +private const val UKJENT_NAVN = "Ukjent navn" +private const val UKJENT_VIRKSOMHET = "Ukjent virksomhet" + class KvitteringService( private val rapid: RapidsConnection, - private val redisStore: RedisStore, -) : ServiceMed1Steg() { + override val redisStore: RedisStore, +) : ServiceMed2Steg(), + Service.MedRedis { override val logger = logger() override val sikkerLogger = sikkerLogger() @@ -40,10 +53,21 @@ class KvitteringService( ) data class Steg1( - val inntektsmeldingDokument: Inntektsmelding?, - val eksternInntektsmelding: EksternInntektsmelding?, + val forespoersel: Forespoersel, ) + sealed class Steg2 { + data class Komplett( + val orgnrMedNavn: Map, + val personer: Map, + val skjema: SkjemaInntektsmelding?, + val inntektsmelding: Inntektsmelding?, + val eksternInntektsmelding: EksternInntektsmelding?, + ) : Steg2() + + data object Delvis : Steg2() + } + override fun lesSteg0(melding: Map): Steg0 = Steg0( transaksjonId = Key.KONTEKST_ID.les(UuidSerializer, melding), @@ -52,43 +76,66 @@ class KvitteringService( override fun lesSteg1(melding: Map): Steg1 = Steg1( - inntektsmeldingDokument = + forespoersel = Key.FORESPOERSEL_SVAR.les(Forespoersel.serializer(), melding), + ) + + override fun lesSteg2(melding: Map): Steg2 { + val orgnrMedNavn = runCatching { Key.VIRKSOMHETER.les(orgMapSerializer, melding) } + val personer = runCatching { Key.PERSONER.les(personMapSerializer, melding) } + val skjema = + runCatching { + Key.SKJEMA_INNTEKTSMELDING + .les(ResultJson.serializer(), melding) + .success + ?.fromJson(SkjemaInntektsmelding.serializer()) + } + val inntektsmelding = + runCatching { Key.LAGRET_INNTEKTSMELDING .les(ResultJson.serializer(), melding) .success - ?.fromJson(Inntektsmelding.serializer()), - eksternInntektsmelding = + ?.fromJson(Inntektsmelding.serializer()) + } + val eksternInntektsmelding = + runCatching { Key.EKSTERN_INNTEKTSMELDING .les(ResultJson.serializer(), melding) .success - ?.fromJson(EksternInntektsmelding.serializer()), - ) + ?.fromJson(EksternInntektsmelding.serializer()) + } + + val results = listOf(orgnrMedNavn, personer, skjema, inntektsmelding, eksternInntektsmelding) + + return if (results.all { it.isSuccess }) { + Steg2.Komplett( + orgnrMedNavn = orgnrMedNavn.getOrThrow(), + personer = personer.getOrThrow(), + skjema = skjema.getOrThrow(), + inntektsmelding = inntektsmelding.getOrThrow(), + eksternInntektsmelding = eksternInntektsmelding.getOrThrow(), + ) + } else if (results.any { it.isSuccess }) { + Steg2.Delvis + } else { + throw results.firstNotNullOf { it.exceptionOrNull() } + } + } override fun utfoerSteg0( data: Map, steg0: Steg0, ) { - val publisert = - rapid.publish( + rapid + .publish( key = steg0.forespoerselId, Key.EVENT_NAME to eventName.toJson(), - Key.BEHOV to BehovType.HENT_LAGRET_IM.toJson(), + Key.BEHOV to BehovType.HENT_TRENGER_IM.toJson(), Key.KONTEKST_ID to steg0.transaksjonId.toJson(), Key.DATA to - data - .plus( - Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), - ).toJson(), - ) - - MdcUtils.withLogFields( - Log.behov(BehovType.HENT_LAGRET_IM), - ) { - "Publiserte melding med behov ${BehovType.HENT_LAGRET_IM}.".let { - logger.info(it) - sikkerLogger.info("$it\n${publisert.toPretty()}") - } - } + mapOf( + Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), + ).toJson(), + ).also { loggBehovPublisert(BehovType.HENT_TRENGER_IM, it) } } override fun utfoerSteg1( @@ -96,13 +143,72 @@ class KvitteringService( steg0: Steg0, steg1: Steg1, ) { - val resultJson = - ResultJson( - success = - InnsendtInntektsmelding(steg1.inntektsmeldingDokument, steg1.eksternInntektsmelding).toJson(InnsendtInntektsmelding.serializer()), - ) + rapid + .publish( + key = steg0.forespoerselId, + Key.EVENT_NAME to eventName.toJson(), + Key.BEHOV to BehovType.HENT_VIRKSOMHET_NAVN.toJson(), + Key.KONTEKST_ID to steg0.transaksjonId.toJson(), + Key.DATA to + mapOf( + Key.SVAR_KAFKA_KEY to KafkaKey(steg0.forespoerselId).toJson(), + Key.ORGNR_UNDERENHETER to setOf(steg1.forespoersel.orgnr).toJson(Orgnr.serializer()), + ).toJson(), + ).also { loggBehovPublisert(BehovType.HENT_VIRKSOMHET_NAVN, it) } + + rapid + .publish( + key = steg0.forespoerselId, + Key.EVENT_NAME to eventName.toJson(), + Key.BEHOV to BehovType.HENT_PERSONER.toJson(), + Key.KONTEKST_ID to steg0.transaksjonId.toJson(), + Key.DATA to + mapOf( + Key.SVAR_KAFKA_KEY to KafkaKey(steg0.forespoerselId).toJson(), + Key.FNR_LISTE to setOf(steg1.forespoersel.fnr).toJson(Fnr.serializer()), + ).toJson(), + ).also { loggBehovPublisert(BehovType.HENT_PERSONER, it) } - redisStore.skrivResultat(steg0.transaksjonId, resultJson) + rapid + .publish( + key = steg0.forespoerselId, + Key.EVENT_NAME to eventName.toJson(), + Key.BEHOV to BehovType.HENT_LAGRET_IM.toJson(), + Key.KONTEKST_ID to steg0.transaksjonId.toJson(), + Key.DATA to + mapOf( + Key.SVAR_KAFKA_KEY to KafkaKey(steg0.forespoerselId).toJson(), + Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), + ).toJson(), + ).also { loggBehovPublisert(BehovType.HENT_LAGRET_IM, it) } + } + + override fun utfoerSteg2( + data: Map, + steg0: Steg0, + steg1: Steg1, + steg2: Steg2, + ) { + if (steg2 is Steg2.Komplett) { + val sykmeldtNavn = steg2.personer[steg1.forespoersel.fnr]?.navn ?: UKJENT_NAVN + val orgNavn = steg2.orgnrMedNavn[steg1.forespoersel.orgnr] ?: UKJENT_VIRKSOMHET + + val resultJson = + ResultJson( + success = + KvitteringResultat( + forespoersel = steg1.forespoersel, + sykmeldtNavn = sykmeldtNavn, + avsenderNavn = steg2.inntektsmelding?.innsenderNavn ?: UKJENT_NAVN, + orgNavn = orgNavn, + skjema = steg2.skjema, + inntektsmelding = steg2.inntektsmelding, + eksternInntektsmelding = steg2.eksternInntektsmelding, + ).toJson(KvitteringResultat.serializer()), + ) + + redisStore.skrivResultat(steg0.transaksjonId, resultJson) + } } override fun onError( @@ -132,4 +238,18 @@ class KvitteringService( Log.transaksjonId(transaksjonId), Log.forespoerselId(forespoerselId), ) + + private fun loggBehovPublisert( + behovType: BehovType, + publisert: JsonElement, + ) { + MdcUtils.withLogFields( + Log.behov(behovType), + ) { + "Publiserte melding med behov $behovType.".let { + logger.info(it) + sikkerLogger.info("$it\n${publisert.toPretty()}") + } + } + } } diff --git a/apps/innsending/src/test/kotlin/no.nav.helsearbeidsgiver.inntektsmelding.innsending/KvitteringServiceTest.kt b/apps/innsending/src/test/kotlin/no.nav.helsearbeidsgiver.inntektsmelding.innsending/KvitteringServiceTest.kt index 06d4c81626..4204454fbd 100644 --- a/apps/innsending/src/test/kotlin/no.nav.helsearbeidsgiver.inntektsmelding.innsending/KvitteringServiceTest.kt +++ b/apps/innsending/src/test/kotlin/no.nav.helsearbeidsgiver.inntektsmelding.innsending/KvitteringServiceTest.kt @@ -7,75 +7,126 @@ import io.kotest.datatest.withData import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe import io.mockk.clearAllMocks -import io.mockk.mockk import io.mockk.verify import kotlinx.serialization.json.JsonElement import no.nav.helsearbeidsgiver.domene.inntektsmelding.deprecated.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.BehovType import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key import no.nav.helsearbeidsgiver.felles.domene.EksternInntektsmelding -import no.nav.helsearbeidsgiver.felles.domene.InnsendtInntektsmelding +import no.nav.helsearbeidsgiver.felles.domene.Forespoersel +import no.nav.helsearbeidsgiver.felles.domene.KvitteringResultat +import no.nav.helsearbeidsgiver.felles.domene.Person import no.nav.helsearbeidsgiver.felles.domene.ResultJson +import no.nav.helsearbeidsgiver.felles.json.orgMapSerializer +import no.nav.helsearbeidsgiver.felles.json.personMapSerializer import no.nav.helsearbeidsgiver.felles.json.toJson -import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore -import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceRiverStateless +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisPrefix +import no.nav.helsearbeidsgiver.felles.rapidsrivers.service.ServiceRiverStateful import no.nav.helsearbeidsgiver.felles.test.json.lesBehov +import no.nav.helsearbeidsgiver.felles.test.mock.MockRedis import no.nav.helsearbeidsgiver.felles.test.mock.mockEksternInntektsmelding import no.nav.helsearbeidsgiver.felles.test.mock.mockFail +import no.nav.helsearbeidsgiver.felles.test.mock.mockForespoersel import no.nav.helsearbeidsgiver.felles.test.mock.mockInntektsmelding +import no.nav.helsearbeidsgiver.felles.test.mock.mockSkjemaInntektsmelding import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.firstMessage +import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.message import no.nav.helsearbeidsgiver.felles.test.rapidsrivers.sendJson import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.pipe.orDefault +import no.nav.helsearbeidsgiver.utils.wrapper.Fnr +import no.nav.helsearbeidsgiver.utils.wrapper.Orgnr import java.util.UUID class KvitteringServiceTest : FunSpec({ val testRapid = TestRapid() - val mockRedisStore = mockk(relaxed = true) + val mockRedis = MockRedis(RedisPrefix.Kvittering) - ServiceRiverStateless( - KvitteringService(testRapid, mockRedisStore), + ServiceRiverStateful( + KvitteringService(testRapid, mockRedis.store), ).connect(testRapid) beforeTest { testRapid.reset() clearAllMocks() + mockRedis.setup() } context("kvittering hentes") { withData( mapOf( - "inntektsmelding hentes" to row(mockInntektsmelding(), null), - "ekstern inntektsmelding hentes" to row(null, mockEksternInntektsmelding()), - "ingen inntektsmelding funnet" to row(null, null), - "begge typer inntektsmelding funnet (skal ikke skje)" to row(mockInntektsmelding(), mockEksternInntektsmelding()), + "inntektsmelding hentes" to row(mockSkjemaInntektsmelding(), mockInntektsmelding(), null), + "ekstern inntektsmelding hentes" to row(null, null, mockEksternInntektsmelding()), + "ingen inntektsmelding funnet" to row(null, null, null), + "begge typer inntektsmelding funnet (skal ikke skje)" to + row(mockSkjemaInntektsmelding(), mockInntektsmelding(), mockEksternInntektsmelding()), ), - ) { (expectedInntektsmelding, expectedEksternInntektsmelding) -> + ) { (expectedSkjema, expectedInntektsmelding, expectedEksternInntektsmelding) -> val transaksjonId: UUID = UUID.randomUUID() - val expectedSuccess = MockKvittering.successResult(expectedInntektsmelding, expectedEksternInntektsmelding) + val avsenderNavn = "Barbie Roberts".takeUnless { expectedInntektsmelding == null }.orDefault("Ukjent navn") + val expectedResult = + KvitteringResultat( + forespoersel = mockForespoersel(), + sykmeldtNavn = "Kenneth Sean Carson", + avsenderNavn = avsenderNavn, + orgNavn = "Mattel", + skjema = expectedSkjema, + inntektsmelding = + expectedInntektsmelding?.copy( + innsenderNavn = avsenderNavn, + ), + eksternInntektsmelding = expectedEksternInntektsmelding, + ) + val sykmeldtFnr = expectedResult.forespoersel.fnr testRapid.sendJson( MockKvittering.steg0(transaksjonId), ) testRapid.inspektør.size shouldBeExactly 1 - testRapid.firstMessage().lesBehov() shouldBe BehovType.HENT_LAGRET_IM + testRapid.firstMessage().lesBehov() shouldBe BehovType.HENT_TRENGER_IM testRapid.sendJson( - MockKvittering.steg1(transaksjonId, expectedInntektsmelding, expectedEksternInntektsmelding), + MockKvittering.steg1(transaksjonId, expectedResult.forespoersel), ) - testRapid.inspektør.size shouldBeExactly 1 + testRapid.inspektør.size shouldBeExactly 4 + testRapid.message(1).lesBehov() shouldBe BehovType.HENT_VIRKSOMHET_NAVN + testRapid.message(2).lesBehov() shouldBe BehovType.HENT_PERSONER + testRapid.message(3).lesBehov() shouldBe BehovType.HENT_LAGRET_IM + + testRapid.sendJson( + MockKvittering.steg2( + transaksjonId, + mapOf(expectedResult.forespoersel.orgnr to expectedResult.orgNavn), + mapOf(sykmeldtFnr to Person(sykmeldtFnr, expectedResult.sykmeldtNavn)), + expectedResult.skjema, + expectedResult.inntektsmelding, + expectedResult.eksternInntektsmelding, + ), + ) + + testRapid.inspektør.size shouldBeExactly 4 verify { - mockRedisStore.skrivResultat(transaksjonId, expectedSuccess) + mockRedis.store.skrivResultat( + transaksjonId, + ResultJson( + success = expectedResult.toJson(KvitteringResultat.serializer()), + ), + ) } } } test("svarer med feilmelding dersom man ikke klarer å hente inntektsmelding") { - val expectedFailure = MockKvittering.failureResult() + val expectedFailure = + ResultJson( + failure = MockKvittering.fail.feilmelding.toJson(), + ) testRapid.sendJson( MockKvittering.steg0(MockKvittering.fail.kontekstId), @@ -88,26 +139,40 @@ class KvitteringServiceTest : testRapid.inspektør.size shouldBeExactly 1 verify { - mockRedisStore.skrivResultat(MockKvittering.fail.kontekstId, expectedFailure) + mockRedis.store.skrivResultat(MockKvittering.fail.kontekstId, expectedFailure) } } }) private object MockKvittering { - val foresporselId: UUID = UUID.randomUUID() - fun steg0(transaksjonId: UUID): Map = mapOf( Key.EVENT_NAME to EventName.KVITTERING_REQUESTED.toJson(), Key.KONTEKST_ID to transaksjonId.toJson(), Key.DATA to mapOf( - Key.FORESPOERSEL_ID to foresporselId.toJson(), + Key.FORESPOERSEL_ID to UUID.randomUUID().toJson(), ).toJson(), ) fun steg1( transaksjonId: UUID, + forespoersel: Forespoersel, + ): Map = + mapOf( + Key.EVENT_NAME to EventName.KVITTERING_REQUESTED.toJson(), + Key.KONTEKST_ID to transaksjonId.toJson(), + Key.DATA to + mapOf( + Key.FORESPOERSEL_SVAR to forespoersel.toJson(Forespoersel.serializer()), + ).toJson(), + ) + + fun steg2( + transaksjonId: UUID, + orgnrMedNavn: Map, + personer: Map, + skjema: SkjemaInntektsmelding?, inntektsmelding: Inntektsmelding?, eksternInntektsmelding: EksternInntektsmelding?, ): Map = @@ -116,32 +181,22 @@ private object MockKvittering { Key.KONTEKST_ID to transaksjonId.toJson(), Key.DATA to mapOf( - Key.FORESPOERSEL_ID to foresporselId.toJson(), + Key.VIRKSOMHETER to orgnrMedNavn.toJson(orgMapSerializer), + Key.PERSONER to personer.toJson(personMapSerializer), + Key.SKJEMA_INNTEKTSMELDING to + ResultJson( + success = skjema?.toJson(SkjemaInntektsmelding.serializer()), + ).toJson(), Key.LAGRET_INNTEKTSMELDING to ResultJson( - success = - inntektsmelding?.toJson(Inntektsmelding.serializer()), + success = inntektsmelding?.toJson(Inntektsmelding.serializer()), ).toJson(), Key.EKSTERN_INNTEKTSMELDING to ResultJson( - success = - eksternInntektsmelding?.toJson(EksternInntektsmelding.serializer()), + success = eksternInntektsmelding?.toJson(EksternInntektsmelding.serializer()), ).toJson(), ).toJson(), ) - fun successResult( - inntektsmelding: Inntektsmelding?, - eksternInntektsmelding: EksternInntektsmelding?, - ): ResultJson = - ResultJson( - success = InnsendtInntektsmelding(inntektsmelding, eksternInntektsmelding).toJson(InnsendtInntektsmelding.serializer()), - ) - - fun failureResult(): ResultJson = - ResultJson( - failure = fail.feilmelding.toJson(), - ) - val fail = mockFail("Fool of a Took!", EventName.KVITTERING_REQUESTED) } diff --git a/apps/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/KvitteringIT.kt b/apps/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/KvitteringIT.kt index 6c03b0cd76..e152c6cc8f 100644 --- a/apps/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/KvitteringIT.kt +++ b/apps/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/KvitteringIT.kt @@ -12,6 +12,7 @@ import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisPrefix import no.nav.helsearbeidsgiver.felles.test.mock.mockEksternInntektsmelding import no.nav.helsearbeidsgiver.felles.test.mock.mockInntektsmeldingGammeltFormat import no.nav.helsearbeidsgiver.felles.test.mock.mockSkjemaInntektsmelding +import no.nav.helsearbeidsgiver.inntektsmelding.integrasjonstest.mock.mockForespoerselSvarSuksess import no.nav.helsearbeidsgiver.inntektsmelding.integrasjonstest.utils.EndToEndTest import no.nav.helsearbeidsgiver.utils.json.toJson import no.nav.helsearbeidsgiver.utils.test.date.desember @@ -32,6 +33,14 @@ class KvitteringIT : EndToEndTest() { val transaksjonId = UUID.randomUUID() val skjema = mockSkjemaInntektsmelding() + mockForespoerselSvarFraHelsebro( + forespoerselId = skjema.forespoerselId, + forespoerselSvar = + mockForespoerselSvarSuksess().copy( + forespoerselId = skjema.forespoerselId, + ), + ) + val innsendingId = imRepository.lagreInntektsmeldingSkjema(skjema, 3.desember.atStartOfDay()) imRepository.oppdaterMedBeriketDokument(skjema.forespoerselId, innsendingId, mockInntektsmeldingGammeltFormat()) @@ -46,17 +55,15 @@ class KvitteringIT : EndToEndTest() { messages .filter(EventName.KVITTERING_REQUESTED) + .filter(Key.SKJEMA_INNTEKTSMELDING) .filter(Key.LAGRET_INNTEKTSMELDING) .filter(Key.EKSTERN_INNTEKTSMELDING) .firstAsMap() .also { val data = it[Key.DATA].shouldNotBeNull().toMap() - // Skal finne inntektsmeldingdokumentet - val imDokument = data[Key.LAGRET_INNTEKTSMELDING] - - imDokument.shouldNotBeNull() - imDokument shouldNotBe Mock.tomResultJson + data[Key.SKJEMA_INNTEKTSMELDING] shouldNotBe Mock.tomResultJson + data[Key.LAGRET_INNTEKTSMELDING] shouldNotBe Mock.tomResultJson data[Key.EKSTERN_INNTEKTSMELDING] shouldBe Mock.tomResultJson } @@ -69,6 +76,14 @@ class KvitteringIT : EndToEndTest() { val transaksjonId = UUID.randomUUID() val forespoerselId = UUID.randomUUID() + mockForespoerselSvarFraHelsebro( + forespoerselId = forespoerselId, + forespoerselSvar = + mockForespoerselSvarSuksess().copy( + forespoerselId = forespoerselId, + ), + ) + imRepository.lagreEksternInntektsmelding(forespoerselId, mockEksternInntektsmelding()) publish( @@ -82,13 +97,16 @@ class KvitteringIT : EndToEndTest() { messages .filter(EventName.KVITTERING_REQUESTED) + .filter(Key.SKJEMA_INNTEKTSMELDING) .filter(Key.LAGRET_INNTEKTSMELDING) .filter(Key.EKSTERN_INNTEKTSMELDING) .firstAsMap() .also { val data = it[Key.DATA].shouldNotBeNull().toMap() + data[Key.SKJEMA_INNTEKTSMELDING] shouldBe Mock.tomResultJson data[Key.LAGRET_INNTEKTSMELDING] shouldBe Mock.tomResultJson + val eIm = data[Key.EKSTERN_INNTEKTSMELDING] eIm.shouldNotBeNull() eIm shouldNotBe Mock.tomResultJson @@ -99,19 +117,29 @@ class KvitteringIT : EndToEndTest() { @Test fun `skal gi feilmelding når forespørsel ikke finnes`() { + val forespoerselId = UUID.randomUUID() val transaksjonId = UUID.randomUUID() + mockForespoerselSvarFraHelsebro( + forespoerselId = forespoerselId, + forespoerselSvar = + mockForespoerselSvarSuksess().copy( + forespoerselId = forespoerselId, + ), + ) + publish( Key.EVENT_NAME to EventName.KVITTERING_REQUESTED.toJson(), Key.KONTEKST_ID to transaksjonId.toJson(), Key.DATA to mapOf( - Key.FORESPOERSEL_ID to UUID.randomUUID().toJson(), + Key.FORESPOERSEL_ID to forespoerselId.toJson(), ).toJson(), ) messages .filter(EventName.KVITTERING_REQUESTED) + .filter(Key.SKJEMA_INNTEKTSMELDING) .filter(Key.LAGRET_INNTEKTSMELDING) .filter(Key.EKSTERN_INNTEKTSMELDING) .firstAsMap() @@ -119,6 +147,7 @@ class KvitteringIT : EndToEndTest() { val data = it[Key.DATA].shouldNotBeNull().toMap() // Skal ikke finne inntektsmeldingdokument + data[Key.SKJEMA_INNTEKTSMELDING] shouldBe Mock.tomResultJson data[Key.LAGRET_INNTEKTSMELDING] shouldBe Mock.tomResultJson data[Key.EKSTERN_INNTEKTSMELDING] shouldBe Mock.tomResultJson } diff --git a/apps/selvbestemt-lagre-im-service/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/selvbestemtlagreimservice/LagreSelvbestemtImService.kt b/apps/selvbestemt-lagre-im-service/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/selvbestemtlagreimservice/LagreSelvbestemtImService.kt index 6e8e6addec..a6dc004e8e 100644 --- a/apps/selvbestemt-lagre-im-service/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/selvbestemtlagreimservice/LagreSelvbestemtImService.kt +++ b/apps/selvbestemt-lagre-im-service/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/selvbestemtlagreimservice/LagreSelvbestemtImService.kt @@ -155,7 +155,6 @@ class LagreSelvbestemtImService( Key.DATA to mapOf( Key.SVAR_KAFKA_KEY to svarKafkaKey.toJson(), - Key.SELVBESTEMT_ID to steg0.skjema.selvbestemtId?.toJson(), Key.FNR_LISTE to setOf( steg0.skjema.sykmeldtFnr, diff --git a/apps/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/HentForespoerselService.kt b/apps/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/HentForespoerselService.kt index 49fd2ebe52..038c054d92 100644 --- a/apps/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/HentForespoerselService.kt +++ b/apps/trengerservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/trengerservice/HentForespoerselService.kt @@ -138,7 +138,6 @@ class HentForespoerselService( Key.DATA to mapOf( Key.SVAR_KAFKA_KEY to svarKafkaKey.toJson(), - Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), Key.ORGNR_UNDERENHETER to setOf(steg1.forespoersel.orgnr).toJson(Orgnr.serializer()), ).toJson(), ).also { loggBehovPublisert(BehovType.HENT_VIRKSOMHET_NAVN, it) } @@ -152,7 +151,6 @@ class HentForespoerselService( Key.DATA to mapOf( Key.SVAR_KAFKA_KEY to svarKafkaKey.toJson(), - Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), Key.FNR_LISTE to setOf( steg1.forespoersel.fnr, @@ -170,7 +168,6 @@ class HentForespoerselService( Key.DATA to mapOf( Key.SVAR_KAFKA_KEY to svarKafkaKey.toJson(), - Key.FORESPOERSEL_ID to steg0.forespoerselId.toJson(), Key.ORGNR_UNDERENHET to steg1.forespoersel.orgnr.toJson(), Key.FNR to steg1.forespoersel.fnr.toJson(), Key.INNTEKTSDATO to inntektsdato.toJson(),