From 95e03cd2df09489cf96669d2d176e6b9134ad53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Golberg?= Date: Wed, 13 Nov 2024 09:53:00 +0100 Subject: [PATCH] =?UTF-8?q?Brevh=C3=A5ndtering=20for=20omregning=20(#6275)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feil key for brevkode i river * Egne endepunkter og metoder for brev for omregning * Omregningsriver for vedtak ordner brev hvis relevant før vedtakshendelse sendes ut * config * Fikse tester * Gjenbruker eksisterende endepunkt for opprett, journalfør og distribuer * Feil config enum navn * Dropper å avbryte hvis behandlingstatus ikke tillater det under omregning * mer config * Endre rekkefølge i opprett og ferdigstill brev og bruker eksisterende metode for ferdigstill/distribuer * Endrer til å bruke vedtaksbrev route * Legger til brevutfall etter opprettet behandling --- .../kotlin/behandling/BehandlingService.kt | 6 +- .../behandlinginfo/BehandlingInfoService.kt | 16 +++- .../behandling/omregning/OmregningService.kt | 4 +- apps/etterlatte-brev-api/.nais/dev.yaml | 1 + apps/etterlatte-brev-api/.nais/prod.yaml | 1 + .../no/nav/etterlatte/brev/BrevRoute.kt | 3 +- .../no/nav/etterlatte/brev/BrevService.kt | 13 ++- .../brev/vedtaksbrev/VedtaksbrevRoute.kt | 33 ++++++- .../brev/vedtaksbrev/VedtaksbrevService.kt | 17 +++- .../OmregningsHendelserBehandlingRiver.kt | 22 +++++ .../kotlin/regulering/VedtakAttestertRiver.kt | 21 ++--- .../.nais/dev.yaml | 5 ++ .../.nais/prod.yaml | 5 ++ .../build.gradle.kts | 1 + .../src/main/kotlin/Application.kt | 9 +- .../no/nav/etterlatte/klienter/BrevKlient.kt | 68 ++++++++++++++ .../nav/etterlatte/regulering/AppBuilder.kt | 17 ++++ .../OpprettVedtakforespoerselRiver.kt | 89 ++++++++++++++++--- .../OpprettVedtakforespoerselRiverTest.kt | 58 +++++++++++- .../kotlin/no/nav/etterlatte/brev/Brev.kt | 5 ++ .../src/main/kotlin/EnvKey.kt | 1 + 21 files changed, 353 insertions(+), 42 deletions(-) create mode 100644 apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/klienter/BrevKlient.kt diff --git a/apps/etterlatte-behandling/src/main/kotlin/behandling/BehandlingService.kt b/apps/etterlatte-behandling/src/main/kotlin/behandling/BehandlingService.kt index 1c175c6bd77..a0fccedbf00 100644 --- a/apps/etterlatte-behandling/src/main/kotlin/behandling/BehandlingService.kt +++ b/apps/etterlatte-behandling/src/main/kotlin/behandling/BehandlingService.kt @@ -258,7 +258,7 @@ interface BehandlingService { opphoerFraOgMed: YearMonth, ) - fun hentAapenOmregning(sakId: SakId): UUID? + fun hentAapenOmregning(sakId: SakId): Revurdering? fun oppdaterTidligereFamiliepleier( behandlingId: UUID, @@ -863,7 +863,7 @@ internal class BehandlingServiceImpl( } } - override fun hentAapenOmregning(sakId: SakId): UUID? = + override fun hentAapenOmregning(sakId: SakId): Revurdering? = behandlingDao .hentAlleRevurderingerISakMedAarsak( sakId, @@ -874,7 +874,7 @@ internal class BehandlingServiceImpl( ), ).singleOrNull { it.status != BehandlingStatus.AVBRUTT && it.status != BehandlingStatus.IVERKSATT - }?.id + } override fun oppdaterTidligereFamiliepleier( behandlingId: UUID, diff --git a/apps/etterlatte-behandling/src/main/kotlin/behandling/behandlinginfo/BehandlingInfoService.kt b/apps/etterlatte-behandling/src/main/kotlin/behandling/behandlinginfo/BehandlingInfoService.kt index 0a635f7770f..7c74e0a4682 100644 --- a/apps/etterlatte-behandling/src/main/kotlin/behandling/behandlinginfo/BehandlingInfoService.kt +++ b/apps/etterlatte-behandling/src/main/kotlin/behandling/behandlinginfo/BehandlingInfoService.kt @@ -7,9 +7,11 @@ import no.nav.etterlatte.behandling.utland.SluttbehandlingUtlandBehandlinginfo import no.nav.etterlatte.libs.common.behandling.BehandlingStatus import no.nav.etterlatte.libs.common.behandling.BehandlingType import no.nav.etterlatte.libs.common.behandling.Brevutfall +import no.nav.etterlatte.libs.common.behandling.Revurderingaarsak import no.nav.etterlatte.libs.common.behandling.SakType import no.nav.etterlatte.libs.common.feilhaandtering.GenerellIkkeFunnetException import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo +import org.slf4j.LoggerFactory import java.util.UUID class BehandlingInfoService( @@ -17,6 +19,8 @@ class BehandlingInfoService( private val behandlingService: BehandlingService, private val behandlingsstatusService: BehandlingStatusService, ) { + private val logger = LoggerFactory.getLogger(BehandlingInfoService::class.java) + fun lagreBrevutfallOgEtterbetaling( behandlingId: UUID, brukerTokenInfo: BrukerTokenInfo, @@ -28,7 +32,10 @@ class BehandlingInfoService( behandlingService.hentBehandling(behandlingId) ?: throw GenerellIkkeFunnetException() - sjekkBehandlingKanEndres(behandling, opphoer) + logger.info("Behandling $behandlingId årsak ${behandling.revurderingsaarsak()}") + if (behandling.revurderingsaarsak()?.name != Revurderingaarsak.AARLIG_INNTEKTSJUSTERING.name) { + sjekkBehandlingKanEndres(behandling, opphoer) + } val lagretBrevutfall = lagreBrevutfall(behandling, brevutfall) val lagretEtterbetaling = lagreEtterbetaling(behandling, etterbetaling) @@ -168,7 +175,12 @@ class BehandlingInfoService( } else { when (behandling.sak.sakType) { SakType.BARNEPENSJON -> behandlingsstatusService.settBeregnet(behandling.id, brukerTokenInfo, false) - SakType.OMSTILLINGSSTOENAD -> behandlingsstatusService.settAvkortet(behandling.id, brukerTokenInfo, false) + SakType.OMSTILLINGSSTOENAD -> + behandlingsstatusService.settAvkortet( + behandling.id, + brukerTokenInfo, + false, + ) } } } diff --git a/apps/etterlatte-behandling/src/main/kotlin/behandling/omregning/OmregningService.kt b/apps/etterlatte-behandling/src/main/kotlin/behandling/omregning/OmregningService.kt index 354e57acd19..4b5e0700ea1 100644 --- a/apps/etterlatte-behandling/src/main/kotlin/behandling/omregning/OmregningService.kt +++ b/apps/etterlatte-behandling/src/main/kotlin/behandling/omregning/OmregningService.kt @@ -26,7 +26,9 @@ class OmregningService( ) { if (request.status == KjoeringStatus.FEILA) { behandlingService.hentAapenOmregning(request.sakId)?.let { - behandlingService.avbrytBehandling(it, bruker) + if (it.status.kanAvbrytes()) { + behandlingService.avbrytBehandling(it.id, bruker) + } } } omregningDao.oppdaterKjoering(request) diff --git a/apps/etterlatte-brev-api/.nais/dev.yaml b/apps/etterlatte-brev-api/.nais/dev.yaml index f3420d37657..266f06ba25a 100644 --- a/apps/etterlatte-brev-api/.nais/dev.yaml +++ b/apps/etterlatte-brev-api/.nais/dev.yaml @@ -152,6 +152,7 @@ spec: - application: etterlatte-behandling - application: etterlatte-testdata-behandler - application: etterlatte-brev-kafka + - application: etterlatte-vedtaksvurdering-kafka - application: azure-token-generator # https://docs.nais.io/auth/entra-id/how-to/generate/?h=token+azure namespace: aura cluster: dev-gcp diff --git a/apps/etterlatte-brev-api/.nais/prod.yaml b/apps/etterlatte-brev-api/.nais/prod.yaml index 6fe25174ed6..b7c4349174c 100644 --- a/apps/etterlatte-brev-api/.nais/prod.yaml +++ b/apps/etterlatte-brev-api/.nais/prod.yaml @@ -159,3 +159,4 @@ spec: - application: etterlatte-saksbehandling-ui - application: etterlatte-behandling - application: etterlatte-brev-kafka + - application: etterlatte-vedtaksvurdering-kafka diff --git a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevRoute.kt b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevRoute.kt index 60deb2b1b1a..44b3462e5cb 100644 --- a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevRoute.kt +++ b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevRoute.kt @@ -295,7 +295,8 @@ fun Route.brevRoute( post("pdf") { withSakId(tilgangssjekker, skrivetilgang = true) { sakId -> try { - val brev = pdfService.lagreOpplastaPDF(sakId, call.receiveMultipart().readAllParts(), brukerTokenInfo) + val brev = + pdfService.lagreOpplastaPDF(sakId, call.receiveMultipart().readAllParts(), brukerTokenInfo) brev.onSuccess { call.respond(brev) } diff --git a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevService.kt b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevService.kt index af2d14aa1a5..562e21345a1 100644 --- a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevService.kt +++ b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/BrevService.kt @@ -43,6 +43,9 @@ class BrevService( private val logger = LoggerFactory.getLogger(this::class.java) private val sikkerlogger = sikkerlogger() + /* + * Brev uten behandling (dødshendelse, etc) + */ suspend fun opprettJournalfoerOgDistribuerRiver( bruker: BrukerTokenInfo, req: OpprettJournalfoerOgDistribuerRequest, @@ -82,7 +85,10 @@ class BrevService( return BrevDistribusjonResponse(brevId, true) } catch (e: Exception) { val oppdatertBrev = db.hentBrev(brevId) - logger.error("Feil opp sto under ferdigstill/journalfør/distribuer av brevID=$brevId, status: ${oppdatertBrev.status}", e) + logger.error( + "Feil opp sto under ferdigstill/journalfør/distribuer av brevID=$brevId, status: ${oppdatertBrev.status}", + e, + ) oppgaveService.opprettOppgaveForFeiletBrev(req.sakId, brevId, bruker) return BrevDistribusjonResponse(brevId, false) } @@ -127,7 +133,10 @@ class BrevService( return BrevStatusResponse(brevId, oppdatertBrev.status) } catch (e: Exception) { val oppdatertBrev = db.hentBrev(brevId) - logger.error("Feil opp sto under ferdigstill/journalfør/distribuer av brevID=$brevId, status: ${oppdatertBrev.status}", e) + logger.error( + "Feil opp sto under ferdigstill/journalfør/distribuer av brevID=$brevId, status: ${oppdatertBrev.status}", + e, + ) return BrevStatusResponse(brevId, oppdatertBrev.status) } diff --git a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevRoute.kt b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevRoute.kt index 0f7cf71e992..baf6945df28 100644 --- a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevRoute.kt +++ b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevRoute.kt @@ -13,6 +13,7 @@ import io.ktor.server.routing.route import no.nav.etterlatte.brev.Brevtype import no.nav.etterlatte.brev.JournalfoerBrevService import no.nav.etterlatte.brev.VedtakTilJournalfoering +import no.nav.etterlatte.brev.model.GenererOgFerdigstillVedtaksbrev import no.nav.etterlatte.libs.common.sak.SakId import no.nav.etterlatte.libs.ktor.route.BEHANDLINGID_CALL_PARAMETER import no.nav.etterlatte.libs.ktor.route.Tilgangssjekker @@ -93,6 +94,28 @@ fun Route.vedtaksbrevRoute( } } + post("vedtak/generer-pdf-og-ferdigstill") { + kunSystembruker { systembruker -> + val behandlingId = behandlingId + val request = call.receive() + logger.info("Generere og ferdigstille vedtaksbrev for behandling (behandlingId=$behandlingId)") + + measureTimedValue { + service.genererPdfOgFerdigstill(request.behandlingId, request.brevId, systembruker) + }.also { (_, varighet) -> + logger.info( + "Generere og ferdigstilling av vedtaksbrev tok ${ + varighet.toString( + DurationUnit.SECONDS, + 2, + ) + }", + ) + call.respond(HttpStatusCode.OK) + } + } + } + post("vedtak/ferdigstill") { withBehandlingId(tilgangssjekker, skrivetilgang = true) { behandlingId -> logger.info("Ferdigstiller vedtaksbrev for behandling (id=$behandlingId)") @@ -118,10 +141,12 @@ fun Route.vedtaksbrevRoute( service.hentNyttInnhold(sakId, brevId, behandlingId, brukerTokenInfo, body.brevtype) }.let { (brevPayload, varighet) -> logger.info( - "Oppretting av nytt innhold til brev (id=$brevId) tok ${varighet.toString( - DurationUnit.SECONDS, - 2, - )}", + "Oppretting av nytt innhold til brev (id=$brevId) tok ${ + varighet.toString( + DurationUnit.SECONDS, + 2, + ) + }", ) call.respond(brevPayload) } diff --git a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevService.kt b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevService.kt index 1057268b89f..2b7f59f0dda 100644 --- a/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevService.kt +++ b/apps/etterlatte-brev-api/src/main/kotlin/no/nav/etterlatte/brev/vedtaksbrev/VedtaksbrevService.kt @@ -90,7 +90,13 @@ class VedtaksbrevService( pdfGenerator.genererPdf( id = id, bruker = bruker, - avsenderRequest = { brukerToken, vedtak, enhet -> opprettAvsenderRequest(brukerToken, vedtak, enhet) }, + avsenderRequest = { brukerToken, vedtak, enhet -> + opprettAvsenderRequest( + brukerToken, + vedtak, + enhet, + ) + }, brevKodeMapping = { brevKodeMappingVedtak.brevKode(it) }, brevDataMapping = { brevDataMapperFerdigstilling.brevDataFerdigstilling(it) }, ) @@ -113,6 +119,15 @@ class VedtaksbrevService( return pdf } + suspend fun genererPdfOgFerdigstill( + behandlingId: UUID, + brevId: BrevID, + brukerTokenInfo: BrukerTokenInfo, + ) { + genererPdf(brevId, brukerTokenInfo) + ferdigstillVedtaksbrev(behandlingId, brukerTokenInfo) + } + suspend fun ferdigstillVedtaksbrev( behandlingId: UUID, brukerTokenInfo: BrukerTokenInfo, diff --git a/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/OmregningsHendelserBehandlingRiver.kt b/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/OmregningsHendelserBehandlingRiver.kt index 2f34cc8bcad..8c016042484 100644 --- a/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/OmregningsHendelserBehandlingRiver.kt +++ b/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/OmregningsHendelserBehandlingRiver.kt @@ -1,7 +1,11 @@ package no.nav.etterlatte.regulering import no.nav.etterlatte.BehandlingService +import no.nav.etterlatte.libs.common.behandling.Aldersgruppe +import no.nav.etterlatte.libs.common.behandling.BrevutfallDto +import no.nav.etterlatte.libs.common.behandling.BrevutfallOgEtterbetalingDto import no.nav.etterlatte.libs.common.behandling.Revurderingaarsak +import no.nav.etterlatte.libs.common.grunnlag.Grunnlagsopplysning import no.nav.etterlatte.libs.common.rapidsandrivers.setEventNameForHendelseType import no.nav.etterlatte.libs.common.revurdering.AutomatiskRevurderingRequest import no.nav.etterlatte.libs.common.sak.KjoeringStatus @@ -53,6 +57,24 @@ internal class OmregningsHendelserBehandlingRiver( ), ) + if (omregningData.revurderingaarsak == Revurderingaarsak.AARLIG_INNTEKTSJUSTERING) { + behandlinger.leggInnBrevutfall( + BrevutfallOgEtterbetalingDto( + behandlingId = behandlingId, + opphoer = false, // TODO opphørfom?a + etterbetaling = null, + brevutfall = + BrevutfallDto( + behandlingId = behandlingId, + aldersgruppe = Aldersgruppe.OVER_18, // eller null siden oms? + feilutbetaling = null, + frivilligSkattetrekk = false, + kilde = Grunnlagsopplysning.automatiskSaksbehandler, + ), + ), + ) + } + omregningData.endreSakType(sakType) omregningData.endreBehandlingId(behandlingId) omregningData.endreForrigeBehandlingid(forrigeBehandlingId) diff --git a/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/VedtakAttestertRiver.kt b/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/VedtakAttestertRiver.kt index cf14ce6bcab..63f2f7e05d9 100644 --- a/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/VedtakAttestertRiver.kt +++ b/apps/etterlatte-oppdater-behandling/src/main/kotlin/regulering/VedtakAttestertRiver.kt @@ -1,10 +1,6 @@ package no.nav.etterlatte.regulering import no.nav.etterlatte.BehandlingService -import no.nav.etterlatte.brev.BrevRequestHendelseType -import no.nav.etterlatte.brev.Brevkoder -import no.nav.etterlatte.libs.common.behandling.Revurderingaarsak -import no.nav.etterlatte.libs.common.rapidsandrivers.setEventNameForHendelseType import no.nav.etterlatte.libs.common.sak.KjoeringStatus import no.nav.etterlatte.libs.common.sak.LagreKjoeringRequest import no.nav.etterlatte.libs.common.vedtak.VedtakKafkaHendelseHendelseType @@ -19,9 +15,7 @@ import no.nav.etterlatte.rapidsandrivers.ReguleringEvents.BEREGNING_BRUKT_OMREGN import no.nav.etterlatte.rapidsandrivers.ReguleringEvents.BEREGNING_G_ETTER import no.nav.etterlatte.rapidsandrivers.ReguleringEvents.BEREGNING_G_FOER import no.nav.etterlatte.rapidsandrivers.ReguleringEvents.VEDTAK_BELOEP -import no.nav.etterlatte.rapidsandrivers.brevKode import no.nav.etterlatte.rapidsandrivers.omregningData -import no.nav.etterlatte.rapidsandrivers.sakId import no.nav.helse.rapids_rivers.JsonMessage import no.nav.helse.rapids_rivers.MessageContext import no.nav.helse.rapids_rivers.RapidsConnection @@ -36,6 +30,7 @@ internal class VedtakAttestertRiver( init { initialiserRiver(rapidsConnection, VedtakKafkaHendelseHendelseType.ATTESTERT) { + // TODO lytt på noe annet? eksplisitt klar for ferdigstil elns? validate { it.requireKey(OmregningDataPacket.KEY) } validate { it.requireKey(OmregningDataPacket.SAK_ID) } validate { it.requireKey(OmregningDataPacket.KJOERING) } @@ -75,16 +70,10 @@ internal class VedtakAttestertRiver( vedtakBeloep = bigDecimal(packet, VEDTAK_BELOEP), ) - // Årlig inntektsjustering jobb skal sende ut varsel og vedtak etter at sak er ferdig omregnet - if (packet.omregningData.revurderingaarsak == Revurderingaarsak.AARLIG_INNTEKTSJUSTERING) { - packet.setEventNameForHendelseType(BrevRequestHendelseType.OPPRETT_JOURNALFOER_OG_DISTRIBUER) - packet.brevKode = Brevkoder.OMS_INNTEKTSJUSTERING_VARSEL.name - packet.sakId = packet.omregningData.sakId - context.publish(packet.toJson()) - } else { - behandlingService.lagreFullfoertKjoering(request) - logger.info("Sak $sakId er ferdig omregnet, status oppdatert til: ${request.status}") - } + // TODO Burde ikke ferdigstille kun basert på attestert men også om brev er ordentlig distribuert osv. Bør gjøre en sanity check er først? + + behandlingService.lagreFullfoertKjoering(request) + logger.info("Sak $sakId er ferdig omregnet, status oppdatert til: ${request.status}") } private fun bigDecimal( diff --git a/apps/etterlatte-vedtaksvurdering-kafka/.nais/dev.yaml b/apps/etterlatte-vedtaksvurdering-kafka/.nais/dev.yaml index 462bb08540f..414c8284609 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/.nais/dev.yaml +++ b/apps/etterlatte-vedtaksvurdering-kafka/.nais/dev.yaml @@ -52,6 +52,10 @@ spec: value: api://dev-gcp.etterlatte.etterlatte-utbetaling/.default - name: ETTERLATTE_UTBETALING_URL value: http://etterlatte-utbetaling + - name: BREV_AZURE_SCOPE + value: api://dev-gcp.etterlatte.etterlatte-brev-api/.default + - name: ETTERLATTE_BREV_API_URL + value: http://etterlatte-brev-api envFrom: - secret: my-application-unleash-api-token accessPolicy: @@ -59,5 +63,6 @@ spec: rules: - application: etterlatte-vedtaksvurdering - application: etterlatte-utbetaling + - application: etterlatte-brev-api external: - host: etterlatte-unleash-api.nav.cloud.nais.io diff --git a/apps/etterlatte-vedtaksvurdering-kafka/.nais/prod.yaml b/apps/etterlatte-vedtaksvurdering-kafka/.nais/prod.yaml index 5d0cec8fc6a..6051c15fe50 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/.nais/prod.yaml +++ b/apps/etterlatte-vedtaksvurdering-kafka/.nais/prod.yaml @@ -52,6 +52,10 @@ spec: value: api://prod-gcp.etterlatte.etterlatte-utbetaling/.default - name: ETTERLATTE_UTBETALING_URL value: http://etterlatte-utbetaling + - name: BREV_AZURE_SCOPE + value: api://prod-gcp.etterlatte.etterlatte-brev-api/.default + - name: ETTERLATTE_BREV_API_URL + value: http://etterlatte-brev-api envFrom: - secret: my-application-unleash-api-token accessPolicy: @@ -59,5 +63,6 @@ spec: rules: - application: etterlatte-vedtaksvurdering - application: etterlatte-utbetaling + - application: etterlatte-brev-api external: - host: etterlatte-unleash-api.nav.cloud.nais.io diff --git a/apps/etterlatte-vedtaksvurdering-kafka/build.gradle.kts b/apps/etterlatte-vedtaksvurdering-kafka/build.gradle.kts index 609b7528343..10fe1332a11 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/build.gradle.kts +++ b/apps/etterlatte-vedtaksvurdering-kafka/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { implementation(project(":libs:etterlatte-behandling-model")) implementation(project(":libs:etterlatte-utbetaling-model")) implementation(project(":libs:etterlatte-vedtaksvurdering-model")) + implementation(project(":libs:etterlatte-brev-model")) implementation(project(":libs:etterlatte-migrering-model")) implementation(project(":libs:etterlatte-oppgave-model")) implementation(project(":libs:etterlatte-funksjonsbrytere")) diff --git a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/Application.kt b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/Application.kt index e2f250e83b6..84d8716ce7d 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/Application.kt +++ b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/Application.kt @@ -15,8 +15,15 @@ fun main() { val appBuilder = AppBuilder(rapidEnv) val vedtakKlient = appBuilder.lagVedtakKlient() val utbetalingKlient = appBuilder.lagUtbetalingKlient() + val brevKlient = appBuilder.lagBrevKlient() LoependeYtelserforespoerselRiver(rapidsConnection, vedtakKlient) - OpprettVedtakforespoerselRiver(rapidsConnection, vedtakKlient, utbetalingKlient, appBuilder.lagFeatureToggleService()) + OpprettVedtakforespoerselRiver( + rapidsConnection, + vedtakKlient, + utbetalingKlient, + brevKlient, + appBuilder.lagFeatureToggleService(), + ) LagreIverksattVedtakRiver(rapidsConnection, vedtakKlient) AttestertVedtakRiver(rapidsConnection, vedtakKlient) SamordningMottattRiver(rapidsConnection, vedtakKlient) diff --git a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/klienter/BrevKlient.kt b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/klienter/BrevKlient.kt new file mode 100644 index 00000000000..5b069edf8ee --- /dev/null +++ b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/klienter/BrevKlient.kt @@ -0,0 +1,68 @@ +package no.nav.etterlatte.no.nav.etterlatte.klienter + +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.plugins.ResponseException +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.http.ContentType +import io.ktor.http.contentType +import kotlinx.coroutines.runBlocking +import no.nav.etterlatte.brev.model.Brev +import no.nav.etterlatte.brev.model.GenererOgFerdigstillVedtaksbrev +import no.nav.etterlatte.libs.common.feilhaandtering.InternfeilException +import no.nav.etterlatte.libs.common.retryOgPakkUt +import no.nav.etterlatte.libs.common.sak.SakId +import no.nav.etterlatte.libs.common.toJson +import org.slf4j.LoggerFactory +import java.time.Duration +import java.util.UUID + +class BrevKlient( + private val httpClient: HttpClient, + private val url: String, +) { + private val logger = LoggerFactory.getLogger(this::class.java) + + internal fun opprettBrev( + behandlingId: UUID, + sakId: SakId, + ): Brev = + runBlocking { + try { + logger.info("Ber brev-api om å opprette vedtaksbrev for behandling id=$behandlingId") + retryOgPakkUt(times = 5, vent = { timesleft -> Thread.sleep(Duration.ofSeconds(1L * timesleft)) }) { + httpClient + .post("$url/api/brev/behandling/$behandlingId/vedtak?sakId=${sakId.sakId}") { + contentType(ContentType.Application.Json) + // setBody(opprett.toJson()) + }.body() + } + } catch (e: ResponseException) { + logger.error("Opprettelse av brev feilet for behandling med id=$behandlingId", e) + throw InternfeilException("Opprettelse av brev feilet for behandling med id=$behandlingId") + } + } + + internal fun genererPdfOgFerdigstillVedtaksbrev( + behandlingId: UUID, + request: GenererOgFerdigstillVedtaksbrev, + ) = runBlocking { + try { + logger.info("Kaller brev-api for å generere og ferdigstille vedtaksbrev for $behandlingId") + retryOgPakkUt(times = 5, vent = { timesleft -> Thread.sleep(Duration.ofSeconds(1L * timesleft)) }) { + httpClient + .post("$url/api/brev/behandling/$behandlingId/vedtak/generer-pdf-og-ferdigstill") { + contentType(ContentType.Application.Json) + setBody(request.toJson()) + } + } + } catch (e: ResponseException) { + logger.error( + "Forsøk på å generere pdf og ferdigstille vedtaksbrev feilet for behandling med id=$behandlingId", + e, + ) + throw InternfeilException("Forsøk på å generere pdf og ferdigstille vedtaksbrev feilet for behandling med id=$behandlingId") + } + } +} diff --git a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/AppBuilder.kt b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/AppBuilder.kt index ced186433dc..f48c0e6b8f3 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/AppBuilder.kt +++ b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/AppBuilder.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import io.ktor.client.HttpClient +import no.nav.etterlatte.EnvKey import no.nav.etterlatte.EnvKey.UTBETALING_AZURE_SCOPE import no.nav.etterlatte.EnvKey.VEDTAK_AZURE_SCOPE import no.nav.etterlatte.VedtakServiceImpl @@ -15,8 +16,10 @@ import no.nav.etterlatte.libs.ktor.AzureEnums.AZURE_APP_CLIENT_ID import no.nav.etterlatte.libs.ktor.AzureEnums.AZURE_APP_JWK import no.nav.etterlatte.libs.ktor.AzureEnums.AZURE_APP_WELL_KNOWN_URL import no.nav.etterlatte.libs.ktor.httpClientClientCredentials +import no.nav.etterlatte.no.nav.etterlatte.klienter.BrevKlient import no.nav.etterlatte.no.nav.etterlatte.klienter.UtbetalingKlient import no.nav.etterlatte.no.nav.etterlatte.klienter.UtbetalingKlientImpl +import no.nav.etterlatte.regulering.VedtakKafkaKey.ETTERLATTE_BREV_API_URL import no.nav.etterlatte.regulering.VedtakKafkaKey.ETTERLATTE_UTBETALING_URL import no.nav.etterlatte.regulering.VedtakKafkaKey.ETTERLATTE_VEDTAK_URL @@ -25,12 +28,15 @@ class AppBuilder( ) { private val vedtakUrl = requireNotNull(props[ETTERLATTE_VEDTAK_URL]) { "Mangler vedtak url " } private val utbetalingUrl = requireNotNull(props[ETTERLATTE_UTBETALING_URL]) { "Mangler utbetaling url " } + private val brevUrl = requireNotNull(props[ETTERLATTE_BREV_API_URL]) { "Mangler brev-api url " } private val env = Miljoevariabler.systemEnv() fun lagVedtakKlient(): VedtakServiceImpl = VedtakServiceImpl(vedtakHttpKlient, vedtakUrl) fun lagUtbetalingKlient(): UtbetalingKlient = UtbetalingKlientImpl(utbetalingHttpKlient, utbetalingUrl) + fun lagBrevKlient(): BrevKlient = BrevKlient(brevHttpKlient, brevUrl) + fun lagFeatureToggleService(): FeatureToggleService = FeatureToggleService.initialiser(featureToggleProperties) private val vedtakHttpKlient: HttpClient by lazy { @@ -53,6 +59,16 @@ class AppBuilder( ) } + private val brevHttpKlient: HttpClient by lazy { + httpClientClientCredentials( + azureAppClientId = props.requireEnvValue(AZURE_APP_CLIENT_ID), + azureAppJwk = env.requireEnvValue(AZURE_APP_JWK), + azureAppWellKnownUrl = env.requireEnvValue(AZURE_APP_WELL_KNOWN_URL), + azureAppScope = env.requireEnvValue(EnvKey.BREV_AZURE_SCOPE), + ekstraJacksoninnstillinger = { it.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) }, + ) + } + private val featureToggleProperties: FeatureToggleProperties by lazy { featureToggleProperties(ConfigFactory.load()) } @@ -68,6 +84,7 @@ private fun featureToggleProperties(config: Config) = enum class VedtakKafkaKey : EnvEnum { ETTERLATTE_VEDTAK_URL, ETTERLATTE_UTBETALING_URL, + ETTERLATTE_BREV_API_URL, ; override fun key() = name diff --git a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiver.kt b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiver.kt index a6a0d6be50a..c5dfa90aea4 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiver.kt +++ b/apps/etterlatte-vedtaksvurdering-kafka/src/main/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiver.kt @@ -1,8 +1,15 @@ package no.nav.etterlatte.regulering import no.nav.etterlatte.VedtakService +import no.nav.etterlatte.brev.model.Brev +import no.nav.etterlatte.brev.model.BrevID +import no.nav.etterlatte.brev.model.GenererOgFerdigstillVedtaksbrev import no.nav.etterlatte.funksjonsbrytere.FeatureToggleService +import no.nav.etterlatte.libs.common.behandling.Revurderingaarsak +import no.nav.etterlatte.libs.common.feilhaandtering.InternfeilException +import no.nav.etterlatte.libs.common.sak.SakId import no.nav.etterlatte.libs.common.vedtak.VedtakInnholdDto +import no.nav.etterlatte.no.nav.etterlatte.klienter.BrevKlient import no.nav.etterlatte.no.nav.etterlatte.klienter.UtbetalingKlient import no.nav.etterlatte.no.nav.etterlatte.regulering.ReguleringFeatureToggle import no.nav.etterlatte.rapidsandrivers.HENDELSE_DATA_KEY @@ -29,6 +36,7 @@ internal class OpprettVedtakforespoerselRiver( rapidsConnection: RapidsConnection, private val vedtak: VedtakService, private val utbetalingKlient: UtbetalingKlient, + private val brevKlient: BrevKlient, private val featureToggleService: FeatureToggleService, ) : ListenerMedLoggingOgFeilhaandtering() { private val logger = LoggerFactory.getLogger(this::class.java) @@ -39,6 +47,7 @@ internal class OpprettVedtakforespoerselRiver( validate { it.requireKey(OmregningDataPacket.SAK_ID) } validate { it.requireKey(OmregningDataPacket.BEHANDLING_ID) } validate { it.requireKey(OmregningDataPacket.FRA_DATO) } + validate { it.requireKey(OmregningDataPacket.REV_AARSAK) } } } @@ -53,23 +62,37 @@ internal class OpprettVedtakforespoerselRiver( logger.info("Leser opprett-vedtak forespoersel for sak $sakId") val behandlingId = omregningData.hentBehandlingId() val dato = omregningData.hentFraDato() + val revurderingaarsak = omregningData.revurderingaarsak + + val skalSendeBrev = + when (omregningData.revurderingaarsak) { + Revurderingaarsak.AARLIG_INNTEKTSJUSTERING -> true + else -> false + } val respons = if (featureToggleService.isEnabled(ReguleringFeatureToggle.SkalStoppeEtterFattetVedtak, false)) { + opprettBrev(behandlingId, sakId, revurderingaarsak) vedtak.opprettVedtakOgFatt(sakId, behandlingId) } else { when (omregningData.utbetalingVerifikasjon) { - UtbetalingVerifikasjon.INGEN -> vedtak.opprettVedtakFattOgAttester(sakId, behandlingId) - UtbetalingVerifikasjon.SIMULERING -> { - vedtak.opprettVedtakOgFatt(sakId, behandlingId) - verifiserUendretUtbetaling(behandlingId, skalAvbryte = false) - vedtak.attesterVedtak(sakId, behandlingId) - } - UtbetalingVerifikasjon.SIMULERING_AVBRYT_ETTERBETALING_ELLER_TILBAKEKREVING -> { - vedtak.opprettVedtakOgFatt(sakId, behandlingId) - verifiserUendretUtbetaling(behandlingId, skalAvbryte = true) - vedtak.attesterVedtak(sakId, behandlingId) + UtbetalingVerifikasjon.INGEN -> { + if (skalSendeBrev) { + vedtakOgBrev(sakId, behandlingId, revurderingaarsak) + } else { + vedtak.opprettVedtakFattOgAttester(sakId, behandlingId) + } } + + UtbetalingVerifikasjon.SIMULERING -> vedtakOgBrev(sakId, behandlingId, revurderingaarsak, false) + + UtbetalingVerifikasjon.SIMULERING_AVBRYT_ETTERBETALING_ELLER_TILBAKEKREVING -> + vedtakOgBrev( + sakId, + behandlingId, + revurderingaarsak, + true, + ) } } @@ -113,6 +136,52 @@ internal class OpprettVedtakforespoerselRiver( } } + private fun vedtakOgBrev( + sakId: SakId, + behandlingId: UUID, + revurderingaarsak: Revurderingaarsak, + skalAvbryteUtbetaling: Boolean? = null, + ): VedtakOgRapid { + vedtak.opprettVedtakOgFatt(sakId, behandlingId) + val brev = opprettBrev(behandlingId, sakId, revurderingaarsak) + + if (skalAvbryteUtbetaling != null) { + verifiserUendretUtbetaling(behandlingId, skalAvbryte = skalAvbryteUtbetaling) + } + + if (brev != null) { + ferdigstillBrev(behandlingId, brev.id, revurderingaarsak) + } + + return vedtak.attesterVedtak(sakId, behandlingId) + } + + private fun opprettBrev( + behandlingId: UUID, + sakId: SakId, + revurderingaarsak: Revurderingaarsak, + ): Brev? = + when (revurderingaarsak) { + Revurderingaarsak.AARLIG_INNTEKTSJUSTERING -> brevKlient.opprettBrev(behandlingId, sakId) + else -> null + } + + private fun ferdigstillBrev( + behandlingId: UUID, + brevId: BrevID, + revurderingaarsak: Revurderingaarsak, + ) { + when (revurderingaarsak) { + Revurderingaarsak.AARLIG_INNTEKTSJUSTERING -> + brevKlient.genererPdfOgFerdigstillVedtaksbrev( + behandlingId, + GenererOgFerdigstillVedtaksbrev(behandlingId, brevId), + ) + + else -> throw InternfeilException("Støtter ikke brev under automatisk omregning for $revurderingaarsak") + } + } + private fun hentBeloep( respons: VedtakOgRapid, dato: LocalDate, diff --git a/apps/etterlatte-vedtaksvurdering-kafka/src/test/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiverTest.kt b/apps/etterlatte-vedtaksvurdering-kafka/src/test/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiverTest.kt index 96a8ba7001f..81890301976 100644 --- a/apps/etterlatte-vedtaksvurdering-kafka/src/test/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiverTest.kt +++ b/apps/etterlatte-vedtaksvurdering-kafka/src/test/kotlin/no/nav/etterlatte/regulering/OpprettVedtakforespoerselRiverTest.kt @@ -10,6 +10,7 @@ import no.nav.etterlatte.funksjonsbrytere.DummyFeatureToggleService import no.nav.etterlatte.libs.common.behandling.Revurderingaarsak import no.nav.etterlatte.libs.common.rapidsandrivers.EVENT_NAME_KEY import no.nav.etterlatte.libs.common.rapidsandrivers.lagParMedEventNameKey +import no.nav.etterlatte.no.nav.etterlatte.klienter.BrevKlient import no.nav.etterlatte.no.nav.etterlatte.klienter.UtbetalingKlient import no.nav.etterlatte.no.nav.etterlatte.regulering.ReguleringFeatureToggle import no.nav.etterlatte.rapidsandrivers.EventNames @@ -53,12 +54,15 @@ internal class OpprettVedtakforespoerselRiverTest { val melding = genererOpprettVedtakforespoersel(behandlingId) val vedtakServiceMock = mockk(relaxed = true) val utbetalingKlientMock = mockk(relaxed = true) + val brevKlientMock = mockk(relaxed = true) + val inspector = TestRapid().apply { OpprettVedtakforespoerselRiver( this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, DummyFeatureToggleService(), ) } @@ -74,6 +78,7 @@ internal class OpprettVedtakforespoerselRiverTest { val melding = genererOpprettVedtakforespoersel(behandlingId) val vedtakServiceMock = mockk(relaxed = true) val utbetalingKlientMock = mockk(relaxed = true) + val brevKlientMock = mockk(relaxed = true) val featureToggleService = DummyFeatureToggleService() featureToggleService.settBryter(ReguleringFeatureToggle.SkalStoppeEtterFattetVedtak, true) @@ -83,6 +88,7 @@ internal class OpprettVedtakforespoerselRiverTest { this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, featureToggleService, ) } @@ -98,6 +104,7 @@ internal class OpprettVedtakforespoerselRiverTest { val melding = genererOpprettVedtakforespoersel(behandlingId) val vedtakServiceMock = mockk(relaxed = true) val utbetalingKlientMock = mockk(relaxed = true) + val brevKlientMock = mockk(relaxed = true) val featureToggleService = DummyFeatureToggleService() featureToggleService.settBryter(ReguleringFeatureToggle.SkalStoppeEtterFattetVedtak, false) @@ -107,6 +114,7 @@ internal class OpprettVedtakforespoerselRiverTest { this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, featureToggleService, ) } @@ -142,12 +150,15 @@ internal class OpprettVedtakforespoerselRiverTest { ) } } + val brevKlientMock = mockk(relaxed = true) + val inspector = TestRapid().apply { OpprettVedtakforespoerselRiver( this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, DummyFeatureToggleService(), ) } @@ -173,16 +184,27 @@ internal class OpprettVedtakforespoerselRiverTest { mockk { every { simuler(any()) } returns mockk { - every { etterbetaling } returns listOf(mockk(relaxed = true) { every { beloep } returns BigDecimal.valueOf(100) }) + every { etterbetaling } returns + listOf( + mockk(relaxed = true) { + every { beloep } returns + BigDecimal.valueOf( + 100, + ) + }, + ) every { tilbakekreving } returns listOf(mockk(relaxed = true)) } } + val brevKlientMock = mockk(relaxed = true) + val inspector = TestRapid().apply { OpprettVedtakforespoerselRiver( this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, DummyFeatureToggleService(), ) } @@ -216,12 +238,15 @@ internal class OpprettVedtakforespoerselRiverTest { listOf(mockk(relaxed = true) { every { beloep } returns BigDecimal.valueOf(100) }) } } + val brevKlientMock = mockk(relaxed = true) + val inspector = TestRapid().apply { OpprettVedtakforespoerselRiver( this, vedtakServiceMock, utbetalingKlientMock, + brevKlientMock, DummyFeatureToggleService(), ) } @@ -235,4 +260,35 @@ internal class OpprettVedtakforespoerselRiverTest { verify { utbetalingKlientMock.simuler(behandlingId) } verify(exactly = 0) { vedtakServiceMock.attesterVedtak(sakId, behandlingId) } } + + @Test + fun `Aarlig inntektsjustering skal opprette og distribuere brev`() { + val behandlingId = UUID.randomUUID() + val melding = + genererOpprettVedtakforespoersel( + behandlingId, + revurderingaarsak = Revurderingaarsak.AARLIG_INNTEKTSJUSTERING, + ) + val vedtakServiceMock = mockk(relaxed = true) + val utbetalingKlientMock = mockk(relaxed = true) + val brevKlientMock = mockk(relaxed = true) + + val inspector = + TestRapid().apply { + OpprettVedtakforespoerselRiver( + this, + vedtakServiceMock, + utbetalingKlientMock, + brevKlientMock, + DummyFeatureToggleService(), + ) + } + + inspector.sendTestMessage(melding.toJson()) + + verify { vedtakServiceMock.opprettVedtakOgFatt(sakId, behandlingId) } + verify { vedtakServiceMock.attesterVedtak(sakId, behandlingId) } + verify { brevKlientMock.opprettBrev(behandlingId, sakId) } + verify { brevKlientMock.genererPdfOgFerdigstillVedtaksbrev(behandlingId, any()) } + } } diff --git a/libs/etterlatte-brev-model/src/main/kotlin/no/nav/etterlatte/brev/Brev.kt b/libs/etterlatte-brev-model/src/main/kotlin/no/nav/etterlatte/brev/Brev.kt index 1c9c14e1ca5..ce180cbf0fc 100644 --- a/libs/etterlatte-brev-model/src/main/kotlin/no/nav/etterlatte/brev/Brev.kt +++ b/libs/etterlatte-brev-model/src/main/kotlin/no/nav/etterlatte/brev/Brev.kt @@ -125,6 +125,11 @@ data class OpprettJournalfoerOgDistribuerRequest( val sakId: SakId, ) +data class GenererOgFerdigstillVedtaksbrev( + val behandlingId: UUID, + val brevId: BrevID, +) + data class FerdigstillJournalFoerOgDistribuerOpprettetBrev( val brevId: BrevID, val sakId: SakId, diff --git a/libs/saksbehandling-common/src/main/kotlin/EnvKey.kt b/libs/saksbehandling-common/src/main/kotlin/EnvKey.kt index 033033f04f7..88551e3cbb9 100644 --- a/libs/saksbehandling-common/src/main/kotlin/EnvKey.kt +++ b/libs/saksbehandling-common/src/main/kotlin/EnvKey.kt @@ -18,6 +18,7 @@ enum class EnvKey : EnvEnum { TRYGDETID_AZURE_SCOPE, VEDTAK_AZURE_SCOPE, UTBETALING_AZURE_SCOPE, + BREV_AZURE_SCOPE, ETTERLATTE_KLAGE_API_URL, ETTERLATTE_TILBAKEKREVING_URL, ETTERLATTE_MIGRERING_URL,