diff --git a/.nais/nais.yml b/.nais/nais.yml index 736d405fe9..cdc3bb685c 100644 --- a/.nais/nais.yml +++ b/.nais/nais.yml @@ -56,12 +56,13 @@ spec: outbound: rules: - application: tiltakspenger-tiltak - - application: tiltakspenger-dokument - application: utsjekk namespace: helved external: - host: {{ urlPdl }} - host: {{ urlSkjerming }} + - host: {{ urlJoark }} + - host: {{ urlDokdist }} inbound: rules: - application: tiltakspenger-saksbehandler @@ -79,12 +80,6 @@ spec: permissions: roles: - "lage_hendelser" - - application: tiltakspenger-vedtak-rivers - namespace: tpts - cluster: {{ cluster }} - permissions: - roles: - - "lage_hendelser" env: {{#each azure.groups}} - name: {{this.name}} diff --git a/.nais/vars/dev.yml b/.nais/vars/dev.yml index 710ccd82ba..86d146dc8d 100644 --- a/.nais/vars/dev.yml +++ b/.nais/vars/dev.yml @@ -8,6 +8,8 @@ cluster: dev-gcp tenant: trygdeetaten.no urlPdl: pdl-api.dev-fss-pub.nais.io urlSkjerming: skjermede-personer-pip.intern.dev.nav.no +urlJoark: dokarkiv.dev-fss-pub.nais.io +urlDokdist: dokdistfordeling.dev-fss-pub.nais.io azure: groups: - name: ROLE_SAKSBEHANDLER diff --git a/.nais/vars/prod.yml b/.nais/vars/prod.yml index b136c17620..3366a05906 100644 --- a/.nais/vars/prod.yml +++ b/.nais/vars/prod.yml @@ -8,6 +8,8 @@ cluster: prod-gcp tenant: nav.no urlPdl: pdl-api.prod-fss-pub.nais.io urlSkjerming: skjermede-personer-pip.intern.nav.no +urlJoark: dokarkiv.prod-fss-pub.nais.io +urlDokdist: dokdistfordeling.prod-fss-pub.nais.io azure: groups: - name: ROLE_SAKSBEHANDLER diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 75a0c79114..0fb8a502d4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -83,7 +83,11 @@ dependencies { // Helved/Utsjekk/Utbetaling implementation("no.nav.utsjekk.kontrakter:iverksett:$iverksettVersjon") - // DIV + // TODO post-mvp jah: Fjern denne når meldekort er over på pdfgen + implementation("org.apache.pdfbox:pdfbox:2.0.28") + + + // Arrow implementation("io.arrow-kt:arrow-core:1.2.4") testImplementation(platform("org.junit:junit-bom:5.11.1")) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/App.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/App.kt index 9d46658929..b6fbd9c60b 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/App.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/App.kt @@ -18,6 +18,8 @@ import no.nav.tiltakspenger.vedtak.db.DataSourceSetup import no.nav.tiltakspenger.vedtak.jobber.TaskExecutor import no.nav.tiltakspenger.vedtak.routes.vedtakApi import no.nav.tiltakspenger.vedtak.tilgang.JWTInnloggetSaksbehandlerProvider +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds fun main() { System.setProperty("logback.configurationFile", Configuration.logbackConfigurationFile()) @@ -49,17 +51,23 @@ fun main() { RunCheckFactory( leaderPodLookup = object : LeaderPodLookup { - override fun amITheLeader(localHostName: String): Either = true.right() + override fun amITheLeader(localHostName: String): Either = + true.right() }, ) } val stoppableTasks = TaskExecutor.startJob( + initialDelay = if (Configuration.isNais()) 1.minutes else 1.seconds, runCheckFactory = runCheckFactory, tasks = - listOf { _ -> + listOf { correlationId -> applicationContext.utbetalingContext.opprettUtbetalingsvedtakService.opprettUtbetalingsvedtak() + // applicationContext.utbetalingContext.sendUtbetalingerService.send(correlationId) + // applicationContext.utbetalingContext.journalførUtbetalingsvedtakService.journalfør(correlationId) + applicationContext.førstegangsbehandlingContext.journalførVedtaksbrevService.journalfør(correlationId) + applicationContext.førstegangsbehandlingContext.distribuerVedtaksbrevService.distribuer(correlationId) }, ) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/Configuration.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/Configuration.kt index 10feecb41e..c0b181b2b3 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/Configuration.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/Configuration.kt @@ -56,7 +56,7 @@ object Configuration { "ROLE_STRENGT_FORTROLIG" to "5ef775f2-61f8-4283-bf3d-8d03f428aa14", "ROLE_SKJERMING" to "dbe4ad45-320b-4e9a-aaa1-73cca4ee124d", "ROLE_DRIFT" to "c511113e-5b22-49e7-b9c4-eeb23b01f518", - "PDL_SCOPE" to "api://localhost:8091/.default", + "PDL_SCOPE" to "localhost", "PDL_ENDPOINT_URL" to "https://localhost:8091/graphql", "SKJERMING_SCOPE" to "localhost", "SKJERMING_URL" to "http://host.docker.internal:8091", @@ -64,12 +64,16 @@ object Configuration { "TILTAK_URL" to "http://host.docker.internal:8091", "UTBETALING_SCOPE" to "localhost", "UTBETALING_URL" to "http://localhost:8091", - "DOKUMENT_SCOPE" to "localhost", - "DOKUMENT_URL" to "http://localhost:8091", + "JOARK_SCOPE" to "localhost", + "JOARK_URL" to "http://localhost:8091", + "DOKDIST_SCOPE" to "localhost", + "DOKDIST_URL" to "http://localhost:8091", + "PDFGEN_SCOPE" to "localhost", + "PDFGEN_URL" to "http://localhost:8091", "NAIS_APP_IMAGE" to "http://localhost8080:githubhash", "AZURE_APP_CLIENT_ID" to "tiltakspenger-vedtak", "AZURE_APP_CLIENT_SECRET" to "secret", - "AZURE_APP_WELL_KNOWN_URL" to "http://localhost:2222", + "AZURE_APP_WELL_KNOWN_URL" to "http://host.docker.internal:6969/azure/.well-known/openid-configuration", "AZURE_OPENID_CONFIG_ISSUER" to "http://host.docker.internal:6969/azure", "AZURE_OPENID_CONFIG_JWKS_URI" to "http://host.docker.internal:6969/azure/jwks", "DB_USERNAME" to "postgres", @@ -92,8 +96,12 @@ object Configuration { "TILTAK_URL" to "http://tiltakspenger-tiltak", "UTBETALING_SCOPE" to "api://dev-gcp.helved.utsjekk/.default", "UTBETALING_URL" to "http://utsjekk.helved", - "DOKUMENT_SCOPE" to "api://dev-gcp.tpts.tiltakspenger-dokument/.default", - "DOKUMENT_URL" to "http://tiltakspenger-dokument", + "JOARK_SCOPE" to "api://dev-fss.teamdokumenthandtering.dokarkiv-q1/.default", + "JOARK_URL" to "https://dokarkiv.dev-fss-pub.nais.io", + "DOKDIST_SCOPE" to "api://dev-fss.teamdokumenthandtering.saf-q1/.default", + "DOKDIST_URL" to "https://dokdistfordeling-q1.dev-fss-pub.nais.io", + "PDFGEN_SCOPE" to "api://dev-gcp.tpts.tiltakspenger-pdfgen/.default", + "PDFGEN_URL" to "http://tiltakspenger-pdfgen", ), ) private val prodProperties = @@ -108,8 +116,12 @@ object Configuration { "TILTAK_URL" to "http://tiltakspenger-tiltak", "UTBETALING_SCOPE" to "api://prod-gcp.helved.utsjekk/.default", "UTBETALING_URL" to "http://utsjekk.helved", - "DOKUMENT_SCOPE" to "api://prod-gcp.tpts.tiltakspenger-dokument/.default", - "DOKUMENT_URL" to "http://tiltakspenger-dokument", + "JOARK_SCOPE" to "api://prod-fss.teamdokumenthandtering.dokarkiv/.default", + "JOARK_URL" to "https://dokarkiv.prod-fss-pub.nais.io", + "DOKDIST_SCOPE" to "api://prod-fss.teamdokumenthandtering.saf/.default", + "DOKDIST_URL" to "https://dokdistfordeling.prod-fss-pub.nais.io", + "PDFGEN_SCOPE" to "api://prod-gcp.tpts.tiltakspenger-pdfgen/.default", + "PDFGEN_URL" to "http://tiltakspenger-pdfgen", ), ) @@ -198,8 +210,20 @@ object Configuration { wellknownUrl = wellknownUrl, ) - fun oauthConfigDokument( - scope: String = config()[Key("DOKUMENT_SCOPE", stringType)], + fun oauthConfigJoark( + scope: String = config()[Key("JOARK_SCOPE", stringType)], + clientId: String = config()[Key("AZURE_APP_CLIENT_ID", stringType)], + clientSecret: String = config()[Key("AZURE_APP_CLIENT_SECRET", stringType)], + wellknownUrl: String = config()[Key("AZURE_APP_WELL_KNOWN_URL", stringType)], + ) = AzureTokenProvider.OauthConfig( + scope = scope, + clientId = clientId, + clientSecret = clientSecret, + wellknownUrl = wellknownUrl, + ) + + fun oauthConfigDokdist( + scope: String = config()[Key("DOKDIST_SCOPE", stringType)], clientId: String = config()[Key("AZURE_APP_CLIENT_ID", stringType)], clientSecret: String = config()[Key("AZURE_APP_CLIENT_SECRET", stringType)], wellknownUrl: String = config()[Key("AZURE_APP_WELL_KNOWN_URL", stringType)], @@ -228,8 +252,9 @@ object Configuration { fun tiltakClientConfig(baseUrl: String = config()[Key("TILTAK_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) - fun dokumentClientConfig(baseUrl: String = config()[Key("DOKUMENT_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) - + fun joarkClientConfig(baseUrl: String = config()[Key("JOARK_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) + fun dokdistClientConfig(baseUrl: String = config()[Key("DOKDIST_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) + fun pdfgenClientConfig(baseUrl: String = config()[Key("PDFGEN_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) fun utbetalingClientConfig(baseUrl: String = config()[Key("UTBETALING_URL", stringType)]) = ClientConfig(baseUrl = baseUrl) fun isNais() = applicationProfile() != Profile.LOCAL diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/brevpublisher/VedtaksbrevMapper.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/brevpublisher/VedtaksbrevMapper.kt deleted file mode 100644 index e746a77a1c..0000000000 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/brevpublisher/VedtaksbrevMapper.kt +++ /dev/null @@ -1,62 +0,0 @@ -package no.nav.tiltakspenger.vedtak.clients.brevpublisher - -import no.nav.tiltakspenger.libs.dokument.BrevDTO -import no.nav.tiltakspenger.libs.dokument.PersonaliaDTO -import no.nav.tiltakspenger.libs.dokument.TiltaksinfoDTO -import no.nav.tiltakspenger.saksbehandling.domene.personopplysninger.PersonopplysningerSøker -import no.nav.tiltakspenger.saksbehandling.domene.sak.Saksnummer -import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak -import java.time.LocalDate -import java.time.format.DateTimeFormatter -import java.util.Locale - -val norskDatoFormatter: DateTimeFormatter = - DateTimeFormatter.ofPattern( - "d. MMMM yyyy", - Locale - .Builder() - .setLanguage("no") - .setRegion("NO") - .build(), - ) - -object VedtaksbrevMapper { - fun mapVedtaksBrevDTO( - saksnummer: Saksnummer, - vedtak: Rammevedtak, - personopplysninger: PersonopplysningerSøker, - ) = BrevDTO( - personalia = mapPersonaliaDTO(vedtak, personopplysninger), - tiltaksinfo = - TiltaksinfoDTO( - // TODO pre-mvp KEBH: Denne må fikses, men ikke nå. Tar en runde på brev - tiltak = "MåkK", - tiltaksnavn = "mÅKk", - tiltaksnummer = "MÅkk", - arrangør = "måKK", - ), - fraDato = vedtak.periode.fraOgMed.format(norskDatoFormatter), - tilDato = vedtak.periode.tilOgMed.format(norskDatoFormatter), - saksnummer = saksnummer.verdi, - // TODO pre-mvp jah: Er det vits at denne er her før vi implementerer barnetillegg? - barnetillegg = false, - saksbehandler = vedtak.saksbehandler, - beslutter = vedtak.beslutter, - // TODO pre-mvp jah: Dersom vi sender fra oss satser til bruker i rammevedtaksbrevet, bør vi lagre dette og heller hente det fra vedtaket. - sats = 285, - satsBarn = 53, - kontor = "måkk", - datoForUtsending = LocalDate.now().format(norskDatoFormatter), - ) - - private fun mapPersonaliaDTO( - vedtak: Rammevedtak, - personopplysninger: PersonopplysningerSøker, - ) = PersonaliaDTO( - ident = personopplysninger.fnr.verdi, - fornavn = personopplysninger.fornavn, - etternavn = personopplysninger.etternavn, - // TODO pre-mvp jah: Ikke vits å ha denne her før vi har implementert barnetillegg - antallBarn = 0, - ) -} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistHttpClient.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistHttpClient.kt new file mode 100644 index 0000000000..661075c9d1 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistHttpClient.kt @@ -0,0 +1,75 @@ +package no.nav.tiltakspenger.vedtak.clients.dokdist + +import arrow.core.Either +import arrow.core.flatten +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.future.await +import kotlinx.coroutines.withContext +import mu.KotlinLogging +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.ports.DokdistGateway +import no.nav.tiltakspenger.distribusjon.ports.KunneIkkeDistribuereDokument +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.sikkerlogg +import no.nav.tiltakspenger.libs.common.AccessToken +import no.nav.tiltakspenger.libs.common.CorrelationId +import java.net.URI +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.toJavaDuration + +class DokdistHttpClient( + baseUrl: String, + private val getToken: suspend () -> AccessToken, + connectTimeout: Duration = 1.seconds, + private val timeout: Duration = 1.seconds, +) : DokdistGateway { + + private val log = KotlinLogging.logger {} + + private val client = + java.net.http.HttpClient + .newBuilder() + .connectTimeout(connectTimeout.toJavaDuration()) + .followRedirects(java.net.http.HttpClient.Redirect.NEVER) + .build() + + private val uri = URI.create("$baseUrl/rest/v1/distribuerjournalpost") + + override suspend fun distribuerDokument( + journalpostId: JournalpostId, + correlationId: CorrelationId, + ): Either { + return withContext(Dispatchers.IO) { + val jsonPayload = journalpostId.toDokdistRequest() + Either + .catch { + val request = createRequest(jsonPayload, correlationId) + val httpResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).await() + httpResponse.body().dokdistResponseToDomain(log) + }.mapLeft { + // Either.catch slipper igjennom CancellationException som er ønskelig. + log.error(it) { "Feil ved kall til dokdist. journalpostId: $journalpostId. Se sikkerlogg for detaljer." } + sikkerlogg.error(it) { "Feil ved kall til dokdist. journalpostId: $journalpostId. . jsonPayload: $jsonPayload, uri: $uri" } + KunneIkkeDistribuereDokument + }.flatten() + } + } + + private suspend fun createRequest( + jsonPayload: String, + correlationId: CorrelationId, + ): HttpRequest? = + HttpRequest + .newBuilder() + .uri(uri) + .timeout(timeout.toJavaDuration()) + .header("Accept", "application/json") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer ${getToken().value}") + .header("Nav-CallId", correlationId.value) + .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) + .build() +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistRequest.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistRequest.kt new file mode 100644 index 0000000000..8a153c27f1 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistRequest.kt @@ -0,0 +1,31 @@ +package no.nav.tiltakspenger.vedtak.clients.dokdist + +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.vedtak.routes.serialize + +private data class DokdistRequest( + val journalpostId: String, + val bestillendeFagsystem: String = "IND", + val dokumentProdApp: String = "Tiltakspenger", + val distribusjonstype: DistribusjonsType = DistribusjonsType.VEDTAK, + val distribusjonstidspunkt: Distribusjonstidspunkt = Distribusjonstidspunkt.KJERNETID, +) { + enum class DistribusjonsType { + VEDTAK, + VIKTIG, + ANNET, + } + + enum class Distribusjonstidspunkt { + UMIDDELBART, + KJERNETID, + } +} + +fun JournalpostId.toDokdistRequest(): String { + return DokdistRequest( + journalpostId = this.toString(), + ).let { + serialize(it) + } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistResponse.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistResponse.kt new file mode 100644 index 0000000000..4f641dc07a --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokdist/DokdistResponse.kt @@ -0,0 +1,19 @@ +package no.nav.tiltakspenger.vedtak.clients.dokdist + +import arrow.core.Either +import mu.KLogger +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.ports.KunneIkkeDistribuereDokument +import no.nav.tiltakspenger.vedtak.db.deserialize + +private data class DokdistResponse( + val bestillingsId: String, +) + +internal fun String.dokdistResponseToDomain(log: KLogger): Either { + return Either.catch { DistribusjonId(deserialize(this).bestillingsId) } + .mapLeft { + log.error(it) { "Kunne ikke deserialisere respons fra dokdist. forventet 'bestillingsId'. jsonResponse: $this" } + KunneIkkeDistribuereDokument + } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentDTO.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentDTO.kt deleted file mode 100644 index b41dadd1e7..0000000000 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentDTO.kt +++ /dev/null @@ -1,85 +0,0 @@ -package no.nav.tiltakspenger.vedtak.clients.dokument - -import no.nav.tiltakspenger.libs.tiltak.TiltakstypeSomGirRett -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Deltatt.DeltattMedLønnITiltaket -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Deltatt.DeltattUtenLønnITiltaket -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Fravær.Syk.SykBruker -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Fravær.Syk.SyktBarn -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Fravær.Velferd.VelferdGodkjentAvNav -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Fravær.Velferd.VelferdIkkeGodkjentAvNav -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.IkkeDeltatt -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Sperret -import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.DELTATT_MED_LØNN_I_TILTAKET -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.DELTATT_UTEN_LØNN_I_TILTAKET -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.FRAVÆR_SYK -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.FRAVÆR_SYKT_BARN -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.FRAVÆR_VELFERD_GODKJENT_AV_NAV -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.FRAVÆR_VELFERD_IKKE_GODKJENT_AV_NAV -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.IKKE_DELTATT -import no.nav.tiltakspenger.vedtak.clients.dokument.MeldekortDagStatusTilDokumentDTO.SPERRET -import java.time.LocalDate -import java.time.LocalDateTime - -internal data class DokumentMeldekortDTO( - val meldekortId: String, - val sakId: String, - val meldekortPeriode: PeriodeDTO, - val saksbehandler: String, - val meldekortDager: List, - val innsendingTidspunkt: LocalDateTime, - val fnr: String, -) - -// TODO jah: Ikke viktig, men denne kan flyttes til en felles plass i libs også kan vi slette kopiene overalt. Da kan den og ha tilDomene() eller tilPeriode() -internal data class PeriodeDTO( - val fraOgMed: LocalDate, - val tilOgMed: LocalDate, -) - -internal data class MeldekortDagDTO( - val dato: LocalDate, - val tiltakType: TiltakstypeSomGirRett?, - val status: MeldekortDagStatusTilDokumentDTO, -) - -internal enum class MeldekortDagStatusTilDokumentDTO { - SPERRET, - DELTATT_UTEN_LØNN_I_TILTAKET, - DELTATT_MED_LØNN_I_TILTAKET, - IKKE_DELTATT, - FRAVÆR_SYK, - FRAVÆR_SYKT_BARN, - FRAVÆR_VELFERD_GODKJENT_AV_NAV, - FRAVÆR_VELFERD_IKKE_GODKJENT_AV_NAV, -} - -internal fun mapMeldekortDTOTilDokumentDTO( - vedtak: Utbetalingsvedtak, -): DokumentMeldekortDTO = - DokumentMeldekortDTO( - meldekortId = vedtak.meldekortId.toString(), - meldekortPeriode = PeriodeDTO(vedtak.periode.fraOgMed, vedtak.periode.tilOgMed), - sakId = vedtak.sakId.toString(), - saksbehandler = vedtak.saksbehandler, - meldekortDager = - vedtak.meldekortperiode.verdi.map { dag -> - MeldekortDagDTO( - dato = dag.dato, - tiltakType = dag.tiltakstype, - status = - when (dag) { - is DeltattMedLønnITiltaket -> DELTATT_MED_LØNN_I_TILTAKET - is DeltattUtenLønnITiltaket -> DELTATT_UTEN_LØNN_I_TILTAKET - is SykBruker -> FRAVÆR_SYK - is SyktBarn -> FRAVÆR_SYKT_BARN - is VelferdGodkjentAvNav -> FRAVÆR_VELFERD_GODKJENT_AV_NAV - is VelferdIkkeGodkjentAvNav -> FRAVÆR_VELFERD_IKKE_GODKJENT_AV_NAV - is IkkeDeltatt -> IKKE_DELTATT - is Sperret -> SPERRET - }, - ) - }, - innsendingTidspunkt = vedtak.vedtakstidspunkt, - fnr = vedtak.fnr.verdi, - ) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentHttpClient.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentHttpClient.kt deleted file mode 100644 index 49f50be640..0000000000 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/dokument/DokumentHttpClient.kt +++ /dev/null @@ -1,61 +0,0 @@ -package no.nav.tiltakspenger.vedtak.clients.dokument - -import io.ktor.client.HttpClient -import io.ktor.client.call.body -import io.ktor.client.engine.HttpClientEngine -import io.ktor.client.request.accept -import io.ktor.client.request.bearerAuth -import io.ktor.client.request.header -import io.ktor.client.request.post -import io.ktor.client.request.setBody -import io.ktor.http.ContentType -import io.ktor.http.HttpStatusCode -import io.ktor.http.contentType -import mu.KotlinLogging -import no.nav.tiltakspenger.libs.common.AccessToken -import no.nav.tiltakspenger.libs.common.CorrelationId -import no.nav.tiltakspenger.meldekort.ports.DokumentGateway -import no.nav.tiltakspenger.meldekort.ports.JoarkResponse -import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak -import no.nav.tiltakspenger.vedtak.clients.defaultHttpClient -import no.nav.tiltakspenger.vedtak.db.objectMapper - -private val LOG = KotlinLogging.logger {} - -class DokumentHttpClient( - private val baseUrl: String, - private val getToken: suspend () -> AccessToken, - engine: HttpClientEngine? = null, - private val httpClient: HttpClient = - defaultHttpClient( - objectMapper = objectMapper, - engine = engine, - ), -) : DokumentGateway { - companion object { - const val NAV_CALL_ID_HEADER = "Nav-Call-Id" - } - - override suspend fun journalførMeldekort( - vedtak: Utbetalingsvedtak, - correlationId: CorrelationId, - ): JoarkResponse { - LOG.info { "Request motatt for å sende meldekort til tiltakspenger-dokument på $baseUrl/meldekort/arkivmeldekort" } - - val httpResponse = - httpClient.post("$baseUrl/meldekort/arkivmeldekort") { - header(NAV_CALL_ID_HEADER, correlationId) - bearerAuth(getToken().value) - accept(ContentType.Application.Json) - contentType(ContentType.Application.Json) - setBody( - mapMeldekortDTOTilDokumentDTO(vedtak), - ) - } - - return when (httpResponse.status) { - HttpStatusCode.OK -> httpResponse.call.response.body() - else -> throw RuntimeException("error (responseCode=${httpResponse.status.value}) fra Dokument") - } - } -} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkHttpClient.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkHttpClient.kt new file mode 100644 index 0000000000..8a94da8a2c --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkHttpClient.kt @@ -0,0 +1,127 @@ +package no.nav.tiltakspenger.vedtak.clients.joark + +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.plugins.ClientRequestException +import io.ktor.client.request.accept +import io.ktor.client.request.bearerAuth +import io.ktor.client.request.header +import io.ktor.client.request.parameter +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.http.ContentType +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import mu.KotlinLogging +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.common.AccessToken +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.meldekort.ports.JournalførMeldekortGateway +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.saksbehandling.ports.JournalførVedtaksbrevGateway +import no.nav.tiltakspenger.vedtak.clients.httpClientWithRetry + +internal const val JOARK_PATH = "rest/journalpostapi/v1/journalpost" + +/** + * https://confluence.adeo.no/display/BOA/opprettJournalpost + * swagger: https://dokarkiv-q2.dev.intern.nav.no/swagger-ui/index.html#/ + */ +internal class JoarkHttpClient( + private val baseUrl: String, + private val client: HttpClient = httpClientWithRetry(timeout = 30L), + private val getAccessToken: suspend () -> AccessToken, +) : JournalførVedtaksbrevGateway, JournalførMeldekortGateway { + + private val log = KotlinLogging.logger {} + + override suspend fun journalførVedtaksbrev( + vedtak: Rammevedtak, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId { + val jsonBody = vedtak.toJournalpostRequest(pdfOgJson) + return opprettJournalpost(jsonBody, correlationId) + } + + override suspend fun journalførMeldekort( + meldekort: Meldekort, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId { + val jsonBody = meldekort.toJournalpostRequest(pdfOgJson) + return opprettJournalpost(jsonBody, correlationId) + } + + private suspend fun opprettJournalpost( + jsonBody: String, + correlationId: CorrelationId, + ): JournalpostId { + try { + log.info("Starter journalføring av dokument") + val token = getAccessToken() + val res = client.post("$baseUrl/$JOARK_PATH") { + accept(ContentType.Application.Json) + header("X-Correlation-ID", correlationId.value) + header("Nav-Callid", correlationId.value) + parameter("forsoekFerdigstill", true) + bearerAuth(token.value) + contentType(ContentType.Application.Json) + setBody(jsonBody) + } + + when (res.status) { + HttpStatusCode.Created -> { + val response = res.call.body() + log.info(response.toString()) + + val journalpostId = if (response.journalpostId.isNullOrEmpty()) { + log.error("Kallet til Joark gikk ok, men vi fikk ingen journalpostId fra Joark") + throw IllegalStateException("Kallet til Joark gikk ok, men vi fikk ingen journalpostId fra Joark") + } else { + response.journalpostId + } + + // if ((response.journalpostferdigstilt == null) || (response.journalpostferdigstilt == false)) { + // log.error("Kunne ikke ferdigstille journalføring for journalpostId: $journalpostId. response=$response") + // throw IllegalStateException("Kunne ikke ferdigstille journalføring for journalpostId: $journalpostId. response=$response") + // } + + log.info("Vi har opprettet journalpost med id : $journalpostId") + return JournalpostId(journalpostId) + } + + else -> { + log.error("Kallet til joark feilet ${res.status} ${res.status.description}") + throw RuntimeException("Feil i kallet til joark") + } + } + } catch (throwable: Throwable) { + if (throwable is ClientRequestException && throwable.response.status == HttpStatusCode.Conflict) { + log.warn("Har allerede blitt journalført (409 Conflict)") + val response = throwable.response.call.body() + return JournalpostId(response.journalpostId.orEmpty()) + } + if (throwable is IllegalStateException) { + throw throwable + } else { + log.error(throwable) { "Kallet til joark feilet $throwable" } + throw RuntimeException("Feil i kallet til joark $throwable") + } + } + } + + data class JoarkResponse( + val journalpostId: String?, + val journalpostferdigstilt: Boolean?, + val melding: String?, + val dokumenter: List?, + ) + + data class Dokumenter( + val dokumentInfoId: String?, + val tittel: String?, + ) +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkRequest.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkRequest.kt new file mode 100644 index 0000000000..cab19efca6 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/JoarkRequest.kt @@ -0,0 +1,82 @@ +@file:Suppress("unused") + +package no.nav.tiltakspenger.vedtak.clients.joark + +/** + * @param eksternReferanseId Brukes som dedup-nøkkel. + */ +internal data class JoarkRequest( + val tittel: String, + val journalpostType: JournalPostType, + val tema: String = "IND", + val kanal: String?, + val journalfoerendeEnhet: String = "9999", + val avsenderMottaker: AvsenderMottaker, + val bruker: Bruker, + val sak: Sak?, + val dokumenter: List, + val eksternReferanseId: String, +) { + enum class JournalPostType { + INNGAAENDE, + UTGAAENDE, + NOTAT, + } + + data class AvsenderMottaker( + val id: String, + val idType: String = "FNR", + ) + + sealed class Sak { + data class Fagsak( + val fagsakId: String, + val fagsaksystem: String = "TILTAKSPENGER", + val sakstype: String = "FAGSAK", + ) : Sak() + } + + data class Bruker( + val id: String, + val idType: String = "FNR", + ) + + data class JournalpostDokument( + val tittel: String, + val brevkode: String, + val dokumentvarianter: List, + ) { + sealed class DokumentVariant { + abstract val filtype: String + abstract val fysiskDokument: String + abstract val variantformat: String + abstract val filnavn: String + + data class ArkivPDF( + override val fysiskDokument: String, + val tittel: String, + ) : DokumentVariant() { + override val filtype: String = "PDFA" + override val variantformat: String = "ARKIV" + override val filnavn: String = "$tittel.pdf" + } + + data class VedleggPDF( + override val fysiskDokument: String, + override val filnavn: String, + ) : DokumentVariant() { + override val filtype: String = "PDFA" + override val variantformat: String = "ARKIV" + } + + data class OriginalJson( + override val fysiskDokument: String, + val tittel: String, + ) : DokumentVariant() { + override val filtype: String = "JSON" + override val variantformat: String = "ORIGINAL" + override val filnavn: String = "$tittel.json" + } + } + } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/MeldekortToJournalpostMapper.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/MeldekortToJournalpostMapper.kt new file mode 100644 index 0000000000..ba63d830b6 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/MeldekortToJournalpostMapper.kt @@ -0,0 +1,50 @@ +package no.nav.tiltakspenger.vedtak.clients.joark + +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.periodisering.Periode +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.vedtak.clients.joark.JoarkRequest.JournalpostDokument.DokumentVariant.ArkivPDF +import no.nav.tiltakspenger.vedtak.clients.joark.JoarkRequest.JournalpostDokument.DokumentVariant.OriginalJson +import no.nav.tiltakspenger.vedtak.routes.objectMapper +import java.time.format.DateTimeFormatter +import java.time.temporal.WeekFields + +internal fun Meldekort.toJournalpostRequest( + pdfOgJson: PdfOgJson, +): String { + val tittel = lagMeldekortTittel(this.periode) + return JoarkRequest( + tittel = tittel, + journalpostType = JoarkRequest.JournalPostType.NOTAT, + // I følge doccen, skal denne være null for NOTAT. + kanal = null, + avsenderMottaker = JoarkRequest.AvsenderMottaker(this.fnr.verdi), + bruker = JoarkRequest.Bruker(this.fnr.verdi), + sak = JoarkRequest.Sak.Fagsak(this.sakId.toString()), + dokumenter = listOf( + JoarkRequest.JournalpostDokument( + tittel = tittel, + brevkode = "MELDEKORT-TILTAKSPENGER", + dokumentvarianter = listOf( + ArkivPDF( + fysiskDokument = pdfOgJson.pdfAsBase64(), + tittel = tittel, + ), + OriginalJson( + fysiskDokument = pdfOgJson.jsonAsBase64(), + tittel = tittel, + ), + ), + ), + ), + eksternReferanseId = this.id.toString(), + ).let { objectMapper.writeValueAsString(it) } +} + +private fun lagMeldekortTittel(periode: Periode): String { + // Meldekort for uke 5 - 6 (29.01.2024 - 11.02.2024) + val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy") + return "Meldekort for uke ${periode.fraOgMed.get(WeekFields.ISO.weekOfWeekBasedYear())}" + + " - ${periode.tilOgMed.get(WeekFields.ISO.weekOfWeekBasedYear())}" + + " (${periode.fraOgMed.format(formatter)} - ${periode.tilOgMed.format(formatter)})" +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/RammevedtakToJournalpostMapper.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/RammevedtakToJournalpostMapper.kt new file mode 100644 index 0000000000..40a5f207e3 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/joark/RammevedtakToJournalpostMapper.kt @@ -0,0 +1,39 @@ +package no.nav.tiltakspenger.vedtak.clients.joark + +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.vedtak.clients.joark.JoarkRequest.JournalpostDokument.DokumentVariant.ArkivPDF +import no.nav.tiltakspenger.vedtak.clients.joark.JoarkRequest.JournalpostDokument.DokumentVariant.OriginalJson +import no.nav.tiltakspenger.vedtak.routes.objectMapper + +internal fun Rammevedtak.toJournalpostRequest( + pdfOgJson: PdfOgJson, +): String { + val tittel = "Vedtak om tiltakspenger" + return JoarkRequest( + tittel = tittel, + journalpostType = JoarkRequest.JournalPostType.UTGAAENDE, + // Utsendingskanal. Forsendelsen er distribuert digitalt til brukers meldingsboks i nav.no. + kanal = "NAV_NO", + avsenderMottaker = JoarkRequest.AvsenderMottaker(this.fnr.verdi), + bruker = JoarkRequest.Bruker(this.fnr.verdi), + sak = JoarkRequest.Sak.Fagsak(this.sakId.toString()), + dokumenter = listOf( + JoarkRequest.JournalpostDokument( + tittel = tittel, + brevkode = "MELDEKORT-TILTAKSPENGER", + dokumentvarianter = listOf( + ArkivPDF( + fysiskDokument = pdfOgJson.pdfAsBase64(), + tittel = tittel, + ), + OriginalJson( + fysiskDokument = pdfOgJson.jsonAsBase64(), + tittel = tittel, + ), + ), + ), + ), + eksternReferanseId = this.id.toString(), + ).let { objectMapper.writeValueAsString(it) } +} diff --git "a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevF\303\270rstegangsvedtakInnvilgelseDTO.kt" "b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevF\303\270rstegangsvedtakInnvilgelseDTO.kt" new file mode 100644 index 0000000000..8fa15f5ce2 --- /dev/null +++ "b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevF\303\270rstegangsvedtakInnvilgelseDTO.kt" @@ -0,0 +1,51 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen + +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.vedtak.clients.pdfgen.formattering.norskDatoFormatter +import no.nav.tiltakspenger.vedtak.db.serialize +import java.time.LocalDate + +@Suppress("unused") +private class BrevFørstegangsvedtakInnvilgelseDTO( + val personalia: BrevPersonaliaDTO, + val tiltaksinfo: BrevTiltaksinfoDTO, + val fraDato: String, + val tilDato: String, + val saksnummer: String, + val barnetillegg: Boolean, + val saksbehandler: String, + val beslutter: String, + val kontor: String, + val datoForUtsending: String, + val sats: Int, + val satsBarn: Int, +) + +internal fun Rammevedtak.tobrevDTO(): String { + return BrevFørstegangsvedtakInnvilgelseDTO( + personalia = BrevPersonaliaDTO( + ident = this.fnr.verdi, + fornavn = "TODO pre-mvp jah: Hent fra PDL", + etternavn = "TODO pre-mvp", + antallBarn = 0, + ), + tiltaksinfo = BrevTiltaksinfoDTO( + tiltak = "TODO pre-mvp jah: Disse bør være lagret på behandlingen. Enten på vilkåret eller rett på behandlingen.", + tiltaksnavn = "TODO pre-mvp", + tiltaksnummer = "TODO pre-mvp", + arrangør = "TODO pre-mvp", + ), + fraDato = periode.fraOgMed.format(norskDatoFormatter), + tilDato = periode.tilOgMed.format(norskDatoFormatter), + saksnummer = saksnummer.verdi, + barnetillegg = false, + saksbehandler = saksbehandler, + beslutter = beslutter, + kontor = "TODO pre-mvp: Dette bør ligge på behandlingen. Se NORG-oppgave i trello.", + // Dette er vår dato, det brukes typisk når bruker klager på vedtaksbrev på dato ... + datoForUtsending = LocalDate.now().format(norskDatoFormatter), + // TODO pre-mvp jah: Dette må ligge i behandlingen. Men dette vil kunne være en periodisering. Si f.eks. vedtaket går fra slutten av desember. + sats = 285, + satsBarn = 53, + ).let { serialize(it) } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevPersonaliaDTO.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevPersonaliaDTO.kt new file mode 100644 index 0000000000..59413c8ddc --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevPersonaliaDTO.kt @@ -0,0 +1,8 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen + +internal data class BrevPersonaliaDTO( + val ident: String, + val fornavn: String, + val etternavn: String, + val antallBarn: Int, +) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevTiltaksinfoDTO.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevTiltaksinfoDTO.kt new file mode 100644 index 0000000000..e9959e3846 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/BrevTiltaksinfoDTO.kt @@ -0,0 +1,8 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen + +internal data class BrevTiltaksinfoDTO( + val tiltak: String, + val tiltaksnavn: String, + val tiltaksnummer: String, + val arrangør: String, +) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/DokumentMeldekortDTO.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/DokumentMeldekortDTO.kt new file mode 100644 index 0000000000..091a713810 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/DokumentMeldekortDTO.kt @@ -0,0 +1,92 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen + +import com.fasterxml.jackson.databind.JsonNode +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.meldekort.domene.Meldekortdag +import no.nav.tiltakspenger.meldekort.domene.ReduksjonAvYtelsePåGrunnAvFravær +import no.nav.tiltakspenger.vedtak.routes.objectMapper + +private data class DokumentMeldekortDTO( + val meldekortId: String, + val sakId: String, + val meldekortPeriode: PeriodeDTO, + val saksbehandler: String, + val meldekortDager: List, + val tiltakstype: String, + val iverksattTidspunkt: String, + val personopplysninger: PersonopplysningerDTO, +) { + + data class PersonopplysningerDTO( + val fornavn: String, + val etternavn: String, + val ident: String, + ) + + data class PeriodeDTO( + val fom: String, + val tom: String, + ) + + data class MeldekortDagDTO( + val dato: String, + val tiltakType: String, + val status: String, + val beløp: Int, + val prosent: Int, + val reduksjon: String?, + ) +} + +fun Meldekort.UtfyltMeldekort.toPdf(): JsonNode { + return DokumentMeldekortDTO( + meldekortId = id.toString(), + sakId = sakId.toString(), + meldekortPeriode = DokumentMeldekortDTO.PeriodeDTO( + fom = periode.fraOgMed.toString(), + tom = periode.tilOgMed.toString(), + ), + saksbehandler = saksbehandler, + meldekortDager = this.meldekortperiode.verdi.map { dag -> + DokumentMeldekortDTO.MeldekortDagDTO( + dato = dag.dato.toString(), + tiltakType = dag.tiltakstype.toString(), + status = dag.toStatus(), + beløp = dag.beløp, + prosent = dag.prosent, + reduksjon = dag.toReduksjon(), + ) + }, + // TODO pre-mvp jah: Holder det med tiltakstype? Hva bør vi mappe den til? + tiltakstype = tiltakstype.toString(), + iverksattTidspunkt = this.iverksattTidspunkt.toString(), + personopplysninger = DokumentMeldekortDTO.PersonopplysningerDTO( + fornavn = "TODO pre-mvp jah: Hent fra PDL", + etternavn = "TODO pre-mvp", + ident = fnr.verdi, + ), + ).let { objectMapper.valueToTree(it) } +} + +private fun Meldekortdag.toStatus(): String { + return when (this) { + is Meldekortdag.IkkeUtfylt -> "IkkeUtfylt" + is Meldekortdag.Utfylt.Deltatt.DeltattMedLønnITiltaket -> "DeltattMedLønnITiltaket" + is Meldekortdag.Utfylt.Deltatt.DeltattUtenLønnITiltaket -> "DeltattUtenLønnITiltaket" + is Meldekortdag.Utfylt.Fravær.Syk.SykBruker -> "SykBruker" + is Meldekortdag.Utfylt.Fravær.Syk.SyktBarn -> "SyktBarn" + is Meldekortdag.Utfylt.Fravær.Velferd.VelferdGodkjentAvNav -> "VelferdGodkjentAvNav" + is Meldekortdag.Utfylt.Fravær.Velferd.VelferdIkkeGodkjentAvNav -> "VelferdIkkeGodkjentAvNav" + is Meldekortdag.Utfylt.IkkeDeltatt -> "IkkeDeltatt" + is Meldekortdag.Utfylt.Sperret -> "Sperret" + } +} + +private fun Meldekortdag.toReduksjon(): String? { + return when (reduksjon) { + ReduksjonAvYtelsePåGrunnAvFravær.IngenReduksjon -> "IngenReduksjon" + ReduksjonAvYtelsePåGrunnAvFravær.Reduksjon -> "Reduksjon" + ReduksjonAvYtelsePåGrunnAvFravær.YtelsenFallerBort -> "YtelsenFallerBort" + null -> null + } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/PdfgenHttpClient.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/PdfgenHttpClient.kt new file mode 100644 index 0000000000..ee1467efad --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/PdfgenHttpClient.kt @@ -0,0 +1,115 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen + +import arrow.core.Either +import com.fasterxml.jackson.databind.JsonNode +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.future.await +import kotlinx.coroutines.withContext +import mu.KotlinLogging +import no.nav.tiltakspenger.felles.PdfA +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.felles.sikkerlogg +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.meldekort.ports.GenererMeldekortPdfGateway +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.saksbehandling.ports.GenererVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.KunneIkkeGenererePdf +import org.apache.pdfbox.pdmodel.PDDocument +import org.apache.pdfbox.pdmodel.PDPage +import org.apache.pdfbox.pdmodel.PDPageContentStream +import org.apache.pdfbox.pdmodel.font.PDType1Font +import java.io.ByteArrayOutputStream +import java.net.URI +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.toJavaDuration + +/** + * Har ansvar for å konvertere domene til JSON som sendes til https://github.com/navikt/tiltakspenger-pdfgen for å generere PDF. + */ +internal class PdfgenHttpClient( + baseUrl: String, + connectTimeout: Duration = 1.seconds, + private val timeout: Duration = 1.seconds, +) : GenererVedtaksbrevGateway, GenererMeldekortPdfGateway { + + private val log = KotlinLogging.logger {} + + private val client = + java.net.http.HttpClient + .newBuilder() + .connectTimeout(connectTimeout.toJavaDuration()) + .followRedirects(java.net.http.HttpClient.Redirect.NEVER) + .build() + + private val vedtakInnvilgelseUri = URI.create("$baseUrl/api/v1/genpdf/tpts/vedtakInnvilgelse") + + override suspend fun genererVedtaksbrev(vedtak: Rammevedtak): Either { + return withContext(Dispatchers.IO) { + val jsonPayload = vedtak.tobrevDTO() + Either + .catch { + val request = createPdfgenRequest(jsonPayload, vedtakInnvilgelseUri) + val httpResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).await() + val body = httpResponse.body() + PdfOgJson(PdfA(body), jsonPayload) + }.mapLeft { + // Either.catch slipper igjennom CancellationException som er ønskelig. + log.error(it) { "Feil ved kall til pdfgen. Vedtak ${vedtak.id}, saksnummer ${vedtak.saksnummer}, sakId: ${vedtak.sakId}. Se sikkerlogg for detaljer." } + sikkerlogg.error(it) { "Feil ved kall til pdfgen. Vedtak ${vedtak.id}, saksnummer ${vedtak.saksnummer}, sakId: ${vedtak.sakId}. jsonPayload: $jsonPayload, uri: $vedtakInnvilgelseUri" } + KunneIkkeGenererePdf + } + } + } + + override fun genererMeldekortPdf(meldekort: Meldekort.UtfyltMeldekort): PdfOgJson { + val data = meldekort.toPdf() + return genererPdfFraJson(data) + } + + private fun createPdfgenRequest( + jsonPayload: String, + uri: URI, + ): HttpRequest? = + HttpRequest + .newBuilder() + .uri(uri) + .timeout(timeout.toJavaDuration()) + .header("Accept", "application/pdf") + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) + .build() +} + +// TODO post-mvp jah: Skal bruke pdfgen-core for å generere PDF-er +private fun genererPdfFraJson(jsonNode: JsonNode): PdfOgJson { + PDDocument().use { document -> + val margin = 50f + val linjeAvstand = 15f + val sideStørrelse = PDPage().mediaBox.height - margin * 3f + val linjerPerSide = (sideStørrelse / linjeAvstand).toInt() + val peneLinjer = jsonNode.toPrettyString().split("\n") + peneLinjer.chunked(linjerPerSide).forEach { linjer -> + val side = PDPage() + document.addPage(side) + PDPageContentStream(document, side).use { contentStream -> + contentStream.setFont(PDType1Font.HELVETICA, 12f) + contentStream.beginText() + contentStream.newLineAtOffset(margin, 700f) + linjer.forEach { linje -> + contentStream.showText(linje) + contentStream.newLineAtOffset(0f, -linjeAvstand) + } + contentStream.endText() + } + } + + val byteArray: ByteArray = ByteArrayOutputStream().use { byteArrayOutputStream -> + document.save(byteArrayOutputStream) + byteArrayOutputStream.toByteArray() + } + return PdfOgJson(PdfA(byteArray), jsonNode.toString()) + } +} diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/formattering/Datoformattering.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/formattering/Datoformattering.kt new file mode 100644 index 0000000000..23fef68ad7 --- /dev/null +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/pdfgen/formattering/Datoformattering.kt @@ -0,0 +1,14 @@ +package no.nav.tiltakspenger.vedtak.clients.pdfgen.formattering + +import java.time.format.DateTimeFormatter +import java.util.Locale + +val norskDatoFormatter: DateTimeFormatter = + DateTimeFormatter.ofPattern( + "d. MMMM yyyy", + Locale + .Builder() + .setLanguage("no") + .setRegion("NO") + .build(), + ) diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/utbetaling/UtbetalingHttpClient.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/utbetaling/UtbetalingHttpClient.kt index c929c090f5..66addb44fc 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/utbetaling/UtbetalingHttpClient.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/clients/utbetaling/UtbetalingHttpClient.kt @@ -28,11 +28,12 @@ private val log = KotlinLogging.logger {} * https://navikt.github.io/utsjekk-docs/ */ class UtbetalingHttpClient( - endepunkt: String, + baseUrl: String, private val getToken: suspend () -> AccessToken, connectTimeout: Duration = 1.seconds, private val timeout: Duration = 1.seconds, ) : UtbetalingGateway { + private val client = java.net.http.HttpClient .newBuilder() @@ -40,7 +41,7 @@ class UtbetalingHttpClient( .followRedirects(java.net.http.HttpClient.Redirect.NEVER) .build() - private val uri = URI.create("$endepunkt/api/iverksetting/v2") + private val uri = URI.create("$baseUrl/api/iverksetting/v2") override suspend fun iverksett( vedtak: Utbetalingsvedtak, @@ -74,7 +75,7 @@ class UtbetalingHttpClient( .newBuilder() .uri(uri) .timeout(timeout.toJavaDuration()) - .header("Authorization", "Bearer ${getToken()}") + .header("Authorization", "Bearer ${getToken().value}") .header("Accept", "application/json") .header("Content-Type", "application/json") // Dette er kun for vår del, open telemetry vil kunne være et alternativ. Slack tråd: https://nav-it.slack.com/archives/C06SJTR2X3L/p1724072054018589 diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/ApplicationContext.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/ApplicationContext.kt index 9696572f7d..0e146096c3 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/ApplicationContext.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/ApplicationContext.kt @@ -44,6 +44,9 @@ open class ApplicationContext( statistikkSakRepo = statistikkContext.statistikkSakRepo, statistikkStønadRepo = statistikkContext.statistikkStønadRepo, gitHash = gitHash, + journalførVedtaksbrevGateway = dokumentContext.journalførVedtaksbrevGateway, + genererVedtaksbrevGateway = dokumentContext.genererVedtaksbrevGateway, + dokdistGateway = dokumentContext.dokdistGateway, ) } open val utbetalingContext by lazy { @@ -51,7 +54,8 @@ open class ApplicationContext( sessionFactory = sessionFactory, rammevedtakRepo = førstegangsbehandlingContext.rammevedtakRepo, statistikkStønadRepo = statistikkContext.statistikkStønadRepo, - dokumentGateway = dokumentContext.dokumentGateway, + genererMeldekortPdfGateway = dokumentContext.genererMeldekortPdfGateway, + journalførMeldekortGateway = dokumentContext.journalførMeldekortGateway, ) } } diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/DokumentContext.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/DokumentContext.kt index c1983c6bb9..4f524e2066 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/DokumentContext.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/DokumentContext.kt @@ -1,17 +1,39 @@ package no.nav.tiltakspenger.vedtak.context -import no.nav.tiltakspenger.meldekort.ports.DokumentGateway +import no.nav.tiltakspenger.distribusjon.ports.DokdistGateway +import no.nav.tiltakspenger.meldekort.ports.GenererMeldekortPdfGateway +import no.nav.tiltakspenger.meldekort.ports.JournalførMeldekortGateway +import no.nav.tiltakspenger.saksbehandling.ports.GenererVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.JournalførVedtaksbrevGateway import no.nav.tiltakspenger.vedtak.Configuration import no.nav.tiltakspenger.vedtak.auth.AzureTokenProvider -import no.nav.tiltakspenger.vedtak.clients.dokument.DokumentHttpClient +import no.nav.tiltakspenger.vedtak.clients.dokdist.DokdistHttpClient +import no.nav.tiltakspenger.vedtak.clients.joark.JoarkHttpClient +import no.nav.tiltakspenger.vedtak.clients.pdfgen.PdfgenHttpClient @Suppress("unused") open class DokumentContext { - private val tokenProviderDokument by lazy { AzureTokenProvider(config = Configuration.oauthConfigDokument()) } - open val dokumentGateway: DokumentGateway by lazy { - DokumentHttpClient( - baseUrl = Configuration.dokumentClientConfig().baseUrl, - getToken = tokenProviderDokument::getToken, + private val tokenProviderDokdist by lazy { AzureTokenProvider(config = Configuration.oauthConfigDokdist()) } + private val joarkClient by lazy { + JoarkHttpClient( + baseUrl = Configuration.joarkClientConfig().baseUrl, + getAccessToken = AzureTokenProvider(config = Configuration.oauthConfigJoark())::getToken, ) } + open val dokdistGateway: DokdistGateway by lazy { + DokdistHttpClient( + baseUrl = Configuration.dokdistClientConfig().baseUrl, + getToken = tokenProviderDokdist::getToken, + ) + } + open val journalførMeldekortGateway: JournalførMeldekortGateway by lazy { joarkClient } + open val journalførVedtaksbrevGateway: JournalførVedtaksbrevGateway by lazy { joarkClient } + + private val pdfgen by lazy { + PdfgenHttpClient( + baseUrl = Configuration.pdfgenClientConfig().baseUrl, + ) + } + open val genererMeldekortPdfGateway: GenererMeldekortPdfGateway by lazy { pdfgen } + open val genererVedtaksbrevGateway: GenererVedtaksbrevGateway by lazy { pdfgen } } diff --git "a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/F\303\270rstegangsbehandlingContext.kt" "b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/F\303\270rstegangsbehandlingContext.kt" index 0f6dcc9083..28edcb74ea 100644 --- "a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/F\303\270rstegangsbehandlingContext.kt" +++ "b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/F\303\270rstegangsbehandlingContext.kt" @@ -1,9 +1,12 @@ package no.nav.tiltakspenger.vedtak.context +import no.nav.tiltakspenger.distribusjon.ports.DokdistGateway import no.nav.tiltakspenger.libs.persistering.domene.SessionFactory import no.nav.tiltakspenger.libs.persistering.infrastruktur.PostgresSessionFactory import no.nav.tiltakspenger.meldekort.ports.MeldekortRepo import no.nav.tiltakspenger.saksbehandling.ports.BehandlingRepo +import no.nav.tiltakspenger.saksbehandling.ports.GenererVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.JournalførVedtaksbrevGateway import no.nav.tiltakspenger.saksbehandling.ports.PersonopplysningerRepo import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo import no.nav.tiltakspenger.saksbehandling.ports.SakRepo @@ -15,6 +18,8 @@ import no.nav.tiltakspenger.saksbehandling.service.behandling.vilkår.kvp.KvpVil import no.nav.tiltakspenger.saksbehandling.service.behandling.vilkår.kvp.KvpVilkårServiceImpl import no.nav.tiltakspenger.saksbehandling.service.behandling.vilkår.livsopphold.LivsoppholdVilkårService import no.nav.tiltakspenger.saksbehandling.service.behandling.vilkår.livsopphold.LivsoppholdVilkårServiceImpl +import no.nav.tiltakspenger.saksbehandling.service.distribuering.DistribuerVedtaksbrevService +import no.nav.tiltakspenger.saksbehandling.service.journalføring.JournalførVedtaksbrevService import no.nav.tiltakspenger.saksbehandling.service.vedtak.RammevedtakService import no.nav.tiltakspenger.saksbehandling.service.vedtak.RammevedtakServiceImpl import no.nav.tiltakspenger.vedtak.repository.behandling.BehandlingPostgresRepo @@ -28,6 +33,9 @@ open class FørstegangsbehandlingContext( statistikkSakRepo: StatistikkSakRepo, statistikkStønadRepo: StatistikkStønadRepo, gitHash: String, + journalførVedtaksbrevGateway: JournalførVedtaksbrevGateway, + genererVedtaksbrevGateway: GenererVedtaksbrevGateway, + dokdistGateway: DokdistGateway, ) { open val rammevedtakRepo: RammevedtakRepo by lazy { RammevedtakPostgresRepo(sessionFactory as PostgresSessionFactory) } open val behandlingRepo: BehandlingRepo by lazy { BehandlingPostgresRepo(sessionFactory as PostgresSessionFactory) } @@ -57,4 +65,19 @@ open class FørstegangsbehandlingContext( ) } val rammevedtakService: RammevedtakService by lazy { RammevedtakServiceImpl(rammevedtakRepo) } + + val journalførVedtaksbrevService by lazy { + JournalførVedtaksbrevService( + journalførVedtaksbrevGateway = journalførVedtaksbrevGateway, + rammevedtakRepo = rammevedtakRepo, + genererVedtaksbrevGateway = genererVedtaksbrevGateway, + ) + } + + val distribuerVedtaksbrevService by lazy { + DistribuerVedtaksbrevService( + dokdistGateway = dokdistGateway, + rammevedtakRepo = rammevedtakRepo, + ) + } } diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/UtbetalingContext.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/UtbetalingContext.kt index 9ef81ad456..e648eeb316 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/UtbetalingContext.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/context/UtbetalingContext.kt @@ -2,7 +2,8 @@ package no.nav.tiltakspenger.vedtak.context import no.nav.tiltakspenger.libs.persistering.domene.SessionFactory import no.nav.tiltakspenger.libs.persistering.infrastruktur.PostgresSessionFactory -import no.nav.tiltakspenger.meldekort.ports.DokumentGateway +import no.nav.tiltakspenger.meldekort.ports.GenererMeldekortPdfGateway +import no.nav.tiltakspenger.meldekort.ports.JournalførMeldekortGateway import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo import no.nav.tiltakspenger.saksbehandling.ports.StatistikkStønadRepo import no.nav.tiltakspenger.saksbehandling.ports.UtbetalingGateway @@ -21,12 +22,13 @@ open class UtbetalingContext( sessionFactory: SessionFactory, rammevedtakRepo: RammevedtakRepo, statistikkStønadRepo: StatistikkStønadRepo, - dokumentGateway: DokumentGateway, + genererMeldekortPdfGateway: GenererMeldekortPdfGateway, + journalførMeldekortGateway: JournalførMeldekortGateway, ) { private val tokenProviderUtbetaling = AzureTokenProvider(config = Configuration.oauthConfigUtbetaling()) open val utbetalingGateway: UtbetalingGateway by lazy { UtbetalingHttpClient( - endepunkt = Configuration.utbetalingClientConfig().baseUrl, + baseUrl = Configuration.utbetalingClientConfig().baseUrl, getToken = tokenProviderUtbetaling::getToken, ) } @@ -55,7 +57,8 @@ open class UtbetalingContext( val journalførUtbetalingsvedtakService by lazy { JournalførUtbetalingsvedtakService( utbetalingsvedtakRepo = utbetalingsvedtakRepo, - dokumentGateway = dokumentGateway, + journalførMeldekortGateway = journalførMeldekortGateway, + genererMeldekortPdfGateway = genererMeldekortPdfGateway, ) } } diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/meldekort/MeldekortPostgresRepo.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/meldekort/MeldekortPostgresRepo.kt index c71b02fe75..fde4e1a21c 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/meldekort/MeldekortPostgresRepo.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/meldekort/MeldekortPostgresRepo.kt @@ -204,6 +204,7 @@ class MeldekortPostgresRepo( forrigeMeldekortId = row.stringOrNull("forrigeMeldekortId")?.let { MeldekortId.fromString(it) }, tiltakstype = meldekortperiode.tiltakstype, status = row.string("status").toMeldekortStatus(), + iverksattTidspunkt = row.localDateTimeOrNull("iverksatt_tidspunkt"), ) } "KLAR_TIL_UTFYLLING" -> { diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakPostgresRepo.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakPostgresRepo.kt index 2ff82de077..38acf2aa1a 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakPostgresRepo.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakPostgresRepo.kt @@ -3,6 +3,7 @@ package no.nav.tiltakspenger.vedtak.repository.utbetaling import kotliquery.Row import kotliquery.Session import kotliquery.queryOf +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.Fnr import no.nav.tiltakspenger.libs.common.MeldekortId @@ -18,6 +19,7 @@ import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo import no.nav.tiltakspenger.vedtak.repository.meldekort.MeldekortPostgresRepo import no.nav.tiltakspenger.vedtak.repository.meldekort.toMeldekortStatus +import java.time.LocalDateTime internal class UtbetalingsvedtakPostgresRepo( private val sessionFactory: PostgresSessionFactory, @@ -70,14 +72,21 @@ internal class UtbetalingsvedtakPostgresRepo( override fun markerSendtTilUtbetaling( vedtakId: VedtakId, + tidspunkt: LocalDateTime, utbetalingsrespons: SendtUtbetaling, ) { sessionFactory.withSession { session -> session.run( queryOf( - "update utbetalingsvedtak set sendt_til_utbetaling = true, utbetaling_metadata = to_jsonb(:metadata::jsonb) where id = :id", + """ + update utbetalingsvedtak + set sendt_til_utbetaling_tidspunkt = :tidspunkt, + utbetaling_metadata = to_jsonb(:metadata::jsonb) + where id = :id + """.trimIndent(), mapOf( "id" to vedtakId.toString(), + "tidspunkt" to tidspunkt, "metadata" to """{"request": "${utbetalingsrespons.request}", "response": "${utbetalingsrespons.response}"}""", ), ).asUpdate, @@ -85,12 +94,25 @@ internal class UtbetalingsvedtakPostgresRepo( } } - override fun markerSendtTilDokument(vedtakId: VedtakId) { + override fun markerJournalført( + vedtakId: VedtakId, + journalpostId: JournalpostId, + tidspunkt: LocalDateTime, + ) { sessionFactory.withSession { session -> session.run( queryOf( - "update utbetalingsvedtak set sendt_til_dokument = true where id = :id", - mapOf("id" to vedtakId.toString()), + """ + update utbetalingsvedtak + set journalpost_id = :journalpostId, + journalføringstidspunkt = :tidspunkt + where id = :id + """.trimIndent(), + mapOf( + "id" to vedtakId.toString(), + "journalpostId" to journalpostId.toString(), + "tidspunkt" to tidspunkt.toString(), + ), ).asUpdate, ) } @@ -170,6 +192,7 @@ internal class UtbetalingsvedtakPostgresRepo( forrigeMeldekortId = row.stringOrNull("forrigeMeldekortId")?.let { MeldekortId.fromString(it) }, tiltakstype = meldekortperiode.tiltakstype, status = row.string("status").toMeldekortStatus(), + iverksattTidspunkt = row.localDateTimeOrNull("iverksatt_tidspunkt"), ) }.asList, ) @@ -183,7 +206,7 @@ internal class UtbetalingsvedtakPostgresRepo( select u.*,s.ident as fnr,s.saksnummer from utbetalingsvedtak u join sak s on s.id = u.sakid - where u.sendt_til_utbetaling = false + where u.sendt_til_utbetaling_tidspunkt is null limit :limit """.trimIndent(), mapOf("limit" to limit), @@ -193,7 +216,7 @@ internal class UtbetalingsvedtakPostgresRepo( ) } - override fun hentUtbetalingsvedtakForDokument(limit: Int): List = + override fun hentDeSomSkalJournalføres(limit: Int): List = sessionFactory.withSession { session -> session.run( queryOf( @@ -201,7 +224,7 @@ internal class UtbetalingsvedtakPostgresRepo( select u.*,s.ident as fnr,s.saksnummer from utbetalingsvedtak u join sak s on s.id = u.sakid - where u.sendt_til_dokument = false + where u.journalpost_id is null limit :limit """.trimIndent(), mapOf("limit" to limit), @@ -225,15 +248,15 @@ internal class UtbetalingsvedtakPostgresRepo( beslutter = string("beslutter"), utbetalingsperiode = string("utbetalingsperiode").toUtbetalingsperiode(), forrigeUtbetalingsvedtak = stringOrNull("forrigeVedtakId")?.let { VedtakId.fromString(it) }, - meldekortperiode = + meldekort = MeldekortPostgresRepo .hentForMeldekortId( MeldekortId.fromString(string("meldekortId")), session, - )!! - .meldekortperiode as Meldeperiode.UtfyltMeldeperiode, - sendtTilUtbetaling = boolean("sendt_til_utbetaling"), - sendtTilDokument = boolean("sendt_til_dokument"), + )!! as UtfyltMeldekort, + sendtTilUtbetaling = localDateTimeOrNull("sendt_til_utbetaling_tidspunkt"), + journalpostId = stringOrNull("journalpost_id")?.let { JournalpostId(it) }, + journalføringstidspunkt = localDateTimeOrNull("journalføringstidspunkt"), ) } } diff --git a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/vedtak/RammevedtakPostgresRepo.kt b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/vedtak/RammevedtakPostgresRepo.kt index 4437713bc3..0b6dcdfd0c 100644 --- a/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/vedtak/RammevedtakPostgresRepo.kt +++ b/app/src/main/kotlin/no/nav/tiltakspenger/vedtak/repository/vedtak/RammevedtakPostgresRepo.kt @@ -3,6 +3,9 @@ package no.nav.tiltakspenger.vedtak.repository.vedtak import kotliquery.Row import kotliquery.Session import kotliquery.queryOf +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.domene.VedtakSomSkalDistribueres +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.felles.sikkerlogg import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.Fnr @@ -15,7 +18,7 @@ import no.nav.tiltakspenger.libs.persistering.infrastruktur.PostgresSessionConte import no.nav.tiltakspenger.libs.persistering.infrastruktur.PostgresSessionFactory import no.nav.tiltakspenger.saksbehandling.domene.sak.Saksnummer import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak -import no.nav.tiltakspenger.saksbehandling.domene.vedtak.VedtaksType +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Vedtakstype import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo import no.nav.tiltakspenger.vedtak.repository.behandling.BehandlingPostgresRepo import java.time.LocalDateTime @@ -61,6 +64,96 @@ class RammevedtakPostgresRepo( sikkerlogg.info { "Hentet ${it.size} vedtak for ident $fnr" } } + override fun hentRammevedtakSomSkalJournalføres( + limit: Int, + ): List { + return sessionFactory.withSession { session -> + session.run( + queryOf( + """ + select v.*, s.saksnummer + from rammevedtak v + join sak s + on s.id = v.sak_id + where v.journalpost_id is null + limit :limit + """.trimIndent(), + mapOf( + "limit" to limit, + ), + ).map { row -> + row.toVedtak(session) + }.asList, + ) + } + } + + override fun hentRammevedtakSomSkalDistribueres(limit: Int): List { + return sessionFactory.withSession { session -> + session.run( + queryOf( + """ + select v.id,v.journalpost_id + from rammevedtak v + where v.journalpost_id is not null + and v.journalføringstidspunkt is not null + and v.distribusjonstidspunkt is null + and v.distribusjon_id is null + limit :limit + """.trimIndent(), + mapOf( + "limit" to limit, + ), + ).map { row -> + VedtakSomSkalDistribueres( + id = VedtakId.fromString(row.string("id")), + journalpostId = JournalpostId(row.string("journalpost_id")), + ) + }.asList, + ) + } + } + + override fun markerJournalført(id: VedtakId, journalpostId: JournalpostId, tidspunkt: LocalDateTime) { + sessionFactory.withSession { session -> + session.run( + queryOf( + """ + update rammevedtak + set journalpost_id = :journalpostId, + journalføringstidspunkt = :tidspunkt + where id = :id + """.trimIndent(), + mapOf( + "id" to id.toString(), + "journalpostId" to journalpostId.toString(), + "tidspunkt" to tidspunkt, + ), + ).asUpdate, + ) + } + } + + override fun markerDistribuert(id: VedtakId, distribusjonId: DistribusjonId, tidspunkt: LocalDateTime) { + sessionFactory.withSession { session -> + session.run( + queryOf( + """ + update rammevedtak + set distribusjon_id = :distribusjonId, + distribusjonstidspunkt = :tidspunkt + where id = :id + """.trimIndent(), + mapOf( + "id" to id.toString(), + "distribusjonId" to distribusjonId.toString(), + "tidspunkt" to tidspunkt, + ), + ).asUpdate, + ) + } + } + override fun lagre( vedtak: Rammevedtak, context: TransactionContext?, @@ -147,10 +240,12 @@ class RammevedtakPostgresRepo( session, )!!, vedtaksdato = localDateTime("vedtaksdato"), - vedtaksType = VedtaksType.valueOf(string("vedtakstype")), + vedtaksType = Vedtakstype.valueOf(string("vedtakstype")), periode = Periode(fraOgMed = localDate("fom"), tilOgMed = localDate("tom")), saksbehandler = string("saksbehandler"), beslutter = string("beslutter"), + journalpostId = stringOrNull("journalpost_id")?.let { JournalpostId(it) }, + journalføringstidstpunkt = localDateTimeOrNull("journalføringstidspunkt"), ) } } diff --git a/app/src/main/resources/db/local-migration/V1005__behandling.sql b/app/src/main/resources/db/local-migration/V1005__behandling.sql index b189fcdc35..db80a3b765 100644 --- a/app/src/main/resources/db/local-migration/V1005__behandling.sql +++ b/app/src/main/resources/db/local-migration/V1005__behandling.sql @@ -1,4 +1,4 @@ -INSERT INTO public.behandling (id,sakid,fom,tom,status,saksbehandler,beslutter,iverksatttidspunkt,sist_endret,opprettet,vilkårssett,stønadsdager,attesteringer) VALUES +INSERT INTO public.behandling (id,sakid,fom,tom,status,saksbehandler,beslutter,iverksatt_tidspunkt,sist_endret,opprettet,vilkårssett,stønadsdager,attesteringer) VALUES ('beh_01HSTQVPVR7GB9TBC8V5HMSJ5Z','sak_01HSTQVPVRW3R23Z1XVA6WX7ZT','2024-01-12','2025-01-01','KLAR_TIL_BEHANDLING',NULL,NULL,NULL,'2024-03-25 13:02:50.39473+01','2024-03-25 13:02:46.290095+01', '{"livsoppholdVilkår": {"vurderingsperiode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"saksbehandlerSaksopplysning": null,"søknadSaksopplysning": {"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"tidsstempel": "2024-07-12T13:15:54.746779","saksbehandler": null,"årsakTilEndring": null,"harLivsoppholdYtelser": false},"avklartSaksopplysning": null, "utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "UAVKLART"}]}, "kvpVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]}, "introVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]},"institusjonsoppholdVilkår": {"søknadSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]},"alderVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"kravfristVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "søknadSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"tiltakDeltagelseVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"},"avklartSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"}}}','{"vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i", "antallDager": "5", "deltagelseprosent": "100", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "kilde": "Komet"}}','{"attesteringer": []}'), ('beh_01HSTRQBRYNAV2ZZDWZFGTH86C','sak_01HSTRQBRYJJXXHSVK4NGAM2RT','2024-01-12','2025-01-01','KLAR_TIL_BESLUTNING','Z123450',NULL,NULL,'2024-03-26 14:25:57.992043+01','2024-03-25 13:17:52.431892+01', '{"livsoppholdVilkår": {"vurderingsperiode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"saksbehandlerSaksopplysning": {"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"tidsstempel": "2024-07-12T13:15:54.746779","saksbehandler": {"navIdent": "Z123450", "brukernavn": "Z123450","epost": "Z123450@nav.no", "roller": ["BESLUTTER"]},"årsakTilEndring": null,"harLivsoppholdYtelser": false},"søknadSaksopplysning": {"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"tidsstempel": "2024-07-12T13:15:54.746779","saksbehandler": null,"årsakTilEndring": null,"harLivsoppholdYtelser": false},"avklartSaksopplysning": {"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"tidsstempel": "2024-07-12T13:15:54.746779","saksbehandler": {"navIdent": "Z123450", "brukernavn": "Z123450","epost": "Z123450@nav.no", "roller": ["BESLUTTER"]},"årsakTilEndring": null,"harLivsoppholdYtelser": false}, "utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]}, "kvpVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]}, "introVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]},"institusjonsoppholdVilkår": {"søknadSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"},"utfall": "OPPFYLT"}]},"alderVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"kravfristVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "søknadSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"tiltakDeltagelseVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"},"avklartSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"}}}','{"vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i", "antallDager": "5", "deltagelseprosent": "100", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "kilde": "Komet"}}','{"attesteringer": []}'), ('beh_01HSTSPGMGVJKA29DHDS3APXTE','sak_01HSTSPGMGXKVTC89MCRT62QES','2024-01-12','2024-06-07','UNDER_BEHANDLING','Z123450',NULL,NULL,'2024-03-26 14:25:41.349507+01','2024-03-25 13:34:53.221716+01', '{"livsoppholdVilkår": {"vurderingsperiode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"saksbehandlerSaksopplysning": null,"søknadSaksopplysning": {"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"tidsstempel": "2024-07-12T13:15:54.746779","saksbehandler": null,"årsakTilEndring": null,"harLivsoppholdYtelser": false},"avklartSaksopplysning": null, "utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"utfall": "UAVKLART"}]}, "kvpVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"utfall": "OPPFYLT"}]}, "introVilkår": {"søknadSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"deltakelseForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"deltar": "DELTAR_IKKE"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"utfall": "OPPFYLT"}]},"institusjonsoppholdVilkår": {"søknadSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"avklartSaksopplysning": {"oppholdForPeriode": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"opphold": "IKKE_OPPHOLD"}],"årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"utfallsperioder": [{"periode": {"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"},"utfall": "OPPFYLT"}]},"alderVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}, "registerSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"fødselsdato": "2000-01-01","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"kravfristVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}, "søknadSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"},"saksbehandlerSaksopplysning": null,"avklartSaksopplysning": {"kravdato": "2024-01-12T13:15:54.746779","årsakTilEndring": null,"saksbehandler": null,"tidsstempel": "2024-06-25T14:39:07.002156"}},"tiltakDeltagelseVilkår": { "utfallsperioder": [{"utfall": "OPPFYLT", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}}], "vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"},"avklartSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i","girRett": true, "deltagelsePeriode":{"fraOgMed": "2024-01-12","tilOgMed": "2024-06-07"}, "tidsstempel": "2024-06-25T14:39:07.002156", "status": "Deltar", "kilde": "Komet"}}}', '{"vurderingsperiode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "registerSaksopplysning": {"tiltakstype":"GRUPPE_AMO", "tiltakNavn": "Supertiltaket alle er glad i", "antallDager": "5", "deltagelseprosent": "100", "periode":{"fraOgMed": "2024-01-12","tilOgMed": "2025-01-01"}, "tidsstempel": "2024-06-25T14:39:07.002156", "kilde": "Komet"}}','{"attesteringer": []}'), diff --git a/app/src/main/resources/db/migration/V1__Tabeller.sql b/app/src/main/resources/db/migration/V1__Tabeller.sql index 0e6272be13..6c36628dc3 100644 --- a/app/src/main/resources/db/migration/V1__Tabeller.sql +++ b/app/src/main/resources/db/migration/V1__Tabeller.sql @@ -22,8 +22,8 @@ create TABLE sak id VARCHAR PRIMARY KEY, ident VARCHAR NOT NULL, saksnummer VARCHAR NOT NULL UNIQUE, - sist_endret TIMESTAMP WITH TIME ZONE NOT NULL, - opprettet TIMESTAMP WITH TIME ZONE NOT NULL + sist_endret TIMESTAMPTZ NOT NULL, + opprettet TIMESTAMPTZ NOT NULL ); CREATE TABLE behandling @@ -35,9 +35,9 @@ CREATE TABLE behandling status VARCHAR NOT NULL, saksbehandler VARCHAR NULL, beslutter VARCHAR NULL, - iverksattTidspunkt TIMESTAMP WITH TIME ZONE NULL, - sist_endret TIMESTAMP WITH TIME ZONE NOT NULL, - opprettet TIMESTAMP WITH TIME ZONE NOT NULL, + iverksatt_tidspunkt TIMESTAMPTZ NULL, + sist_endret TIMESTAMPTZ NOT NULL, + opprettet TIMESTAMPTZ NOT NULL, vilkårssett JSONB NOT NULL, stønadsdager JSONB NOT NULL, attesteringer JSONB NULL @@ -49,17 +49,21 @@ CREATE TABLE rammevedtak sak_id VARCHAR NULL REFERENCES sak (id), behandling_id VARCHAR NULL REFERENCES behandling (id), vedtakstype VARCHAR NOT NULL, - vedtaksdato TIMESTAMP WITH TIME ZONE NOT NULL, + vedtaksdato TIMESTAMPTZ NOT NULL, fom DATE NOT NULL, tom DATE NOT NULL, saksbehandler VARCHAR NOT NULL, beslutter VARCHAR NOT NULL, - opprettet TIMESTAMP WITH TIME ZONE NOT NULL + opprettet TIMESTAMPTZ NOT NULL, + journalpost_id VARCHAR NULL, + journalføringstidspunkt TIMESTAMPTZ NULL, + distribusjon_id VARCHAR NULL, + distribusjonstidspunkt TIMESTAMPTZ NULL ); CREATE TABLE sak_personopplysninger_søker ( - id VARCHAR PRIMARY KEY, + id VARCHAR PRIMARY KEY, sakId VARCHAR NOT NULL REFERENCES sak (id), ident VARCHAR NOT NULL, fødselsdato DATE NOT NULL, @@ -72,7 +76,7 @@ CREATE TABLE sak_personopplysninger_søker skjermet BOOLEAN NULL, kommune VARCHAR NULL, bydel VARCHAR NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL ); CREATE TABLE sak_personopplysninger_barn_med_ident @@ -89,7 +93,7 @@ CREATE TABLE sak_personopplysninger_barn_med_ident strengt_fortrolig_utland BOOLEAN NOT NULL, oppholdsland VARCHAR NULL, skjermet BOOLEAN NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL ); CREATE TABLE sak_personopplysninger_barn_uten_ident @@ -100,7 +104,7 @@ CREATE TABLE sak_personopplysninger_barn_uten_ident fornavn VARCHAR NULL, mellomnavn VARCHAR NULL, etternavn VARCHAR NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL ); CREATE TABLE søknad @@ -113,8 +117,8 @@ CREATE TABLE søknad fornavn VARCHAR NOT NULL, etternavn VARCHAR NOT NULL, journalpost_id VARCHAR NOT NULL, - opprettet TIMESTAMP WITH TIME ZONE NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL, + opprettet TIMESTAMPTZ NULL, + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL, kvp_type VARCHAR NOT NULL, kvp_ja BOOLEAN NULL, kvp_fom DATE NULL, @@ -197,22 +201,22 @@ CREATE TABLE tiltak deltakelse_prosent FLOAT NULL, deltakelse_status VARCHAR NOT NULL, kilde VARCHAR NOT NULL, - tidsstempel_kilde TIMESTAMP WITH TIME ZONE NOT NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL + tidsstempel_kilde TIMESTAMPTZ NOT NULL, + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL ); CREATE TABLE stønadsdager_tiltak ( - id VARCHAR PRIMARY KEY, + id VARCHAR PRIMARY KEY, antall_dager NUMERIC NOT NULL, fom DATE NOT NULL, tom DATE NOT NULL, datakilde VARCHAR NOT NULL, - tidsstempel_kilde TIMESTAMP WITH TIME ZONE NOT NULL, - tidsstempel_hos_oss TIMESTAMP WITH TIME ZONE NOT NULL, + tidsstempel_kilde TIMESTAMPTZ NOT NULL, + tidsstempel_hos_oss TIMESTAMPTZ NOT NULL, tiltak_id VARCHAR NOT NULL REFERENCES tiltak (id), behandling_id VARCHAR NOT NULL REFERENCES behandling (id), - avklart_tidspunkt TIMESTAMP WITH TIME ZONE NULL, + avklart_tidspunkt TIMESTAMPTZ NULL, saksbehandler VARCHAR NULL ); @@ -227,7 +231,8 @@ create table meldekort meldekortdager jsonb not null, saksbehandler varchar null, beslutter varchar null, - status varchar not null + status varchar not null, + iverksatt_tidspunkt timestamptz null ); create table utbetalingsvedtak @@ -236,14 +241,15 @@ create table utbetalingsvedtak sakId varchar not null references sak(id), rammevedtakId varchar not null references rammevedtak(id), brukerNavkontor varchar not null, - vedtakstidspunkt timestamp not null, + vedtakstidspunkt timestamptz not null, saksbehandler varchar not null, beslutter varchar not null, forrigeVedtakId varchar null references utbetalingsvedtak(id), meldekortId varchar not null references meldekort(id), utbetalingsperiode jsonb not null, - sendt_til_utbetaling boolean not null default false, - sendt_til_dokument boolean not null default false, + sendt_til_utbetaling_tidspunkt timestamptz null, + journalpost_id varchar null, + journalføringstidspunkt timestamptz null, utbetaling_metadata jsonb null ); @@ -301,8 +307,8 @@ create table statistikk_stønad tiltak_dato date null, gyldig_fra_dato_tiltak date null, gyldig_til_dato_tiltak date null, - sist_endret timestamp with time zone null, - opprettet timestamp with time zone null + sist_endret timestamptz null, + opprettet timestamptz null ); create table statistikk_sak @@ -313,15 +319,15 @@ create table statistikk_sak behandlingid varchar null, relatertbehandlingid varchar null, ident varchar null, - mottatt_tidspunkt timestamp with time zone null, - registrerttidspunkt timestamp with time zone null, - ferdigbehandlettidspunkt timestamp with time zone null, - vedtaktidspunkt timestamp with time zone null, - utbetalttidspunkt timestamp with time zone null, - endrettidspunkt timestamp with time zone null, + mottatt_tidspunkt timestamptz null, + registrerttidspunkt timestamptz null, + ferdigbehandlettidspunkt timestamptz null, + vedtaktidspunkt timestamptz null, + utbetalttidspunkt timestamptz null, + endrettidspunkt timestamptz null, søknadsformat varchar null, - forventetoppstarttidspunkt timestamp with time zone null, - teknisktidspunkt timestamp with time zone null, + forventetoppstarttidspunkt timestamptz null, + teknisktidspunkt timestamptz null, sakytelse varchar null, sakutland boolean null, behandlingtype varchar null, diff --git a/app/src/main/resources/logback.local.xml b/app/src/main/resources/logback.local.xml index 7654820afe..ab5bc76180 100644 --- a/app/src/main/resources/logback.local.xml +++ b/app/src/main/resources/logback.local.xml @@ -11,8 +11,8 @@ - - + + diff --git a/app/src/test/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakRepoImplTest.kt b/app/src/test/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakRepoImplTest.kt index c1f91cec72..87c286bfef 100644 --- a/app/src/test/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakRepoImplTest.kt +++ b/app/src/test/kotlin/no/nav/tiltakspenger/vedtak/repository/utbetaling/UtbetalingsvedtakRepoImplTest.kt @@ -6,6 +6,7 @@ import no.nav.tiltakspenger.utbetaling.domene.tilUtbetalingsperiode import no.nav.tiltakspenger.vedtak.db.persisterRammevedtakMedUtfyltMeldekort import no.nav.tiltakspenger.vedtak.db.withMigratedDb import org.junit.jupiter.api.Test +import java.time.LocalDateTime class UtbetalingsvedtakRepoImplTest { @Test @@ -26,7 +27,11 @@ class UtbetalingsvedtakRepoImplTest { utbetalingsvedtakRepo.hentGodkjenteMeldekortUtenUtbetalingsvedtak() shouldBe emptyList() utbetalingsvedtakRepo.hentUtbetalingsvedtakForUtsjekk() shouldBe listOf(utbetalingsvedtak) - utbetalingsvedtakRepo.markerSendtTilUtbetaling(utbetalingsvedtak.id, SendtUtbetaling("", "")) + utbetalingsvedtakRepo.markerSendtTilUtbetaling( + vedtakId = utbetalingsvedtak.id, + tidspunkt = LocalDateTime.now(), + utbetalingsrespons = SendtUtbetaling("", ""), + ) utbetalingsvedtakRepo.hentUtbetalingsvedtakForUtsjekk() shouldBe emptyList() } } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/DistribusjonId.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/DistribusjonId.kt new file mode 100644 index 0000000000..4fe3f1f740 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/DistribusjonId.kt @@ -0,0 +1,8 @@ +package no.nav.tiltakspenger.distribusjon.domene + +@JvmInline +value class DistribusjonId( + private val value: String, +) { + override fun toString() = value +} diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/VedtakSomSkalDistribueres.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/VedtakSomSkalDistribueres.kt new file mode 100644 index 0000000000..94af08d512 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/domene/VedtakSomSkalDistribueres.kt @@ -0,0 +1,9 @@ +package no.nav.tiltakspenger.distribusjon.domene + +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.libs.common.VedtakId + +data class VedtakSomSkalDistribueres( + val id: VedtakId, + val journalpostId: JournalpostId, +) diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/ports/DokdistGateway.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/ports/DokdistGateway.kt new file mode 100644 index 0000000000..6e969ceae5 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/distribusjon/ports/DokdistGateway.kt @@ -0,0 +1,15 @@ +package no.nav.tiltakspenger.distribusjon.ports + +import arrow.core.Either +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.libs.common.CorrelationId + +interface DokdistGateway { + suspend fun distribuerDokument( + journalpostId: JournalpostId, + correlationId: CorrelationId, + ): Either +} + +object KunneIkkeDistribuereDokument diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/felles/PdfA.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/PdfA.kt new file mode 100644 index 0000000000..d03e0a8802 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/PdfA.kt @@ -0,0 +1,28 @@ +package no.nav.tiltakspenger.felles + +import java.util.Base64 + +class PdfA(private val content: ByteArray) { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as PdfA + + return content.contentEquals(other.content) + } + + /** + * Tar kun med de 20 første tegnene i toString for å unngå å logge unødvendig mye binærdata. + */ + override fun toString(): String { + val tjueFørsteTegn = content.copyOfRange(0, if (content.size > 20) 20 else content.size) + return "$tjueFørsteTegn - size ${content.size}" + } + + override fun hashCode(): Int = content.contentHashCode() + fun getContent(): ByteArray = content.clone() + + fun toBase64(): String = Base64.getEncoder().encodeToString(getContent()) +} diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/JournalpostId.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/JournalpostId.kt" new file mode 100644 index 0000000000..9ed50d1df7 --- /dev/null +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/JournalpostId.kt" @@ -0,0 +1,8 @@ +package no.nav.tiltakspenger.felles.journalføring + +@JvmInline +value class JournalpostId( + private val value: String, +) { + override fun toString() = value +} diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/PdfOgJson.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/PdfOgJson.kt" new file mode 100644 index 0000000000..a21d54f0c5 --- /dev/null +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/felles/journalf\303\270ring/PdfOgJson.kt" @@ -0,0 +1,12 @@ +package no.nav.tiltakspenger.felles.journalføring + +import no.nav.tiltakspenger.felles.PdfA +import java.util.Base64 + +data class PdfOgJson( + val pdf: PdfA, + val json: String, +) { + fun pdfAsBase64(): String = pdf.toBase64() + fun jsonAsBase64(): String = Base64.getEncoder().encodeToString(json.toByteArray()) +} diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekort.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekort.kt index d8dd190e0d..5553f4200c 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekort.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekort.kt @@ -15,6 +15,7 @@ import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak import no.nav.tiltakspenger.saksbehandling.domene.vilkår.AvklartUtfallForPeriode import java.time.DayOfWeek import java.time.LocalDate +import java.time.LocalDateTime import java.time.temporal.TemporalAdjusters sealed interface Meldekort { @@ -39,8 +40,7 @@ sealed interface Meldekort { * * @param saksbehandler: Obligatorisk dersom meldekortet er utfylt av saksbehandler. * @param beslutter: Obligatorisk dersom meldekortet er godkjent av beslutter. - * - * TODO pre-mvp jah: Verifiser at saksbehandler og beslutter ikke er den samme. + * @param forrigeMeldekortId kan være null dersom det er første meldekort. */ data class UtfyltMeldekort( override val id: MeldekortId, @@ -53,6 +53,7 @@ sealed interface Meldekort { override val saksbehandler: String, override val beslutter: String?, override val status: MeldekortStatus, + val iverksattTidspunkt: LocalDateTime?, ) : Meldekort { init { require(status in listOf(MeldekortStatus.GODKJENT, MeldekortStatus.KLAR_TIL_BESLUTNING)) @@ -60,7 +61,7 @@ sealed interface Meldekort { /** * TODO post-mvp jah: Ved revurderinger av rammevedtaket, så må vi basere oss på både forrige meldekort og revurderingsvedtaket. Dette løser vi å flytte mer logikk til Sak.kt. - * TODO post-mvp jah: Når vi implementerer delvis innvilgelse vil hele meldekortperioder bli SPERRET. + * TODO post-mvp jah: Når vi implementerer delvis innvilgelse vil hele meldekortperioder kunne bli SPERRET. */ fun opprettNesteMeldekort( utfallsperioder: Periodisering, @@ -106,6 +107,7 @@ sealed interface Meldekort { saksbehandler = this.saksbehandler, beslutter = beslutter.navIdent, status = MeldekortStatus.GODKJENT, + iverksattTidspunkt = LocalDateTime.now(), ).right() } @@ -146,6 +148,7 @@ sealed interface Meldekort { saksbehandler = saksbehandler.navIdent, beslutter = this.beslutter, status = MeldekortStatus.KLAR_TIL_BESLUTNING, + iverksattTidspunkt = null, ).right() } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekortdag.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekortdag.kt index e6aa6433df..107d9e65d8 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekortdag.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/domene/Meldekortdag.kt @@ -2,8 +2,6 @@ package no.nav.tiltakspenger.meldekort.domene import no.nav.tiltakspenger.libs.common.MeldekortId import no.nav.tiltakspenger.libs.tiltak.TiltakstypeSomGirRett -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Deltatt.DeltattUtenLønnITiltaket -import no.nav.tiltakspenger.meldekort.domene.Meldekortdag.Utfylt.Fravær.Velferd.VelferdIkkeGodkjentAvNav import no.nav.tiltakspenger.meldekort.domene.ReduksjonAvYtelsePåGrunnAvFravær.IngenReduksjon import no.nav.tiltakspenger.meldekort.domene.ReduksjonAvYtelsePåGrunnAvFravær.YtelsenFallerBort import java.time.LocalDate @@ -20,6 +18,9 @@ sealed interface Meldekortdag { val tiltakstype: TiltakstypeSomGirRett val beregningsdag: Beregningsdag? + val beløp: Int get() = beregningsdag?.beløp ?: 0 + val prosent: Int get() = beregningsdag?.prosent ?: 0 + data class IkkeUtfylt( override val meldekortId: MeldekortId, override val dato: LocalDate, diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/DokumentGateway.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/DokumentGateway.kt deleted file mode 100644 index e622e18098..0000000000 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/DokumentGateway.kt +++ /dev/null @@ -1,18 +0,0 @@ -package no.nav.tiltakspenger.meldekort.ports - -import no.nav.tiltakspenger.libs.common.CorrelationId -import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak -import java.time.LocalDateTime - -interface DokumentGateway { - // TODO jah: Denne bør være mer generisk. - suspend fun journalførMeldekort( - vedtak: Utbetalingsvedtak, - correlationId: CorrelationId, - ): JoarkResponse -} - -data class JoarkResponse( - val journalpostId: String, - val innsendingTidspunkt: LocalDateTime, -) diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/GenererMeldekortPdfGateway.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/GenererMeldekortPdfGateway.kt new file mode 100644 index 0000000000..910df6a765 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/GenererMeldekortPdfGateway.kt @@ -0,0 +1,8 @@ +package no.nav.tiltakspenger.meldekort.ports + +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.meldekort.domene.Meldekort + +interface GenererMeldekortPdfGateway { + fun genererMeldekortPdf(meldekort: Meldekort.UtfyltMeldekort): PdfOgJson +} diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/Journalf\303\270rMeldekortGateway.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/Journalf\303\270rMeldekortGateway.kt" new file mode 100644 index 0000000000..2e3f004a33 --- /dev/null +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/meldekort/ports/Journalf\303\270rMeldekortGateway.kt" @@ -0,0 +1,14 @@ +package no.nav.tiltakspenger.meldekort.ports + +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.meldekort.domene.Meldekort + +interface JournalførMeldekortGateway { + suspend fun journalførMeldekort( + meldekort: Meldekort, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId +} diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/domene/vedtak/Rammevedtak.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/domene/vedtak/Rammevedtak.kt index 4998810e07..00b043f854 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/domene/vedtak/Rammevedtak.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/domene/vedtak/Rammevedtak.kt @@ -1,10 +1,11 @@ package no.nav.tiltakspenger.saksbehandling.domene.vedtak +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.SakId import no.nav.tiltakspenger.libs.common.VedtakId import no.nav.tiltakspenger.libs.periodisering.Periode import no.nav.tiltakspenger.libs.periodisering.Periodisering -import no.nav.tiltakspenger.saksbehandling.domene.behandling.Behandling import no.nav.tiltakspenger.saksbehandling.domene.behandling.Behandlingsstatus import no.nav.tiltakspenger.saksbehandling.domene.behandling.Førstegangsbehandling import no.nav.tiltakspenger.saksbehandling.domene.sak.Saksnummer @@ -15,25 +16,28 @@ data class Rammevedtak( val id: VedtakId = VedtakId.random(), val sakId: SakId, val saksnummer: Saksnummer, - val behandling: Behandling, + val behandling: Førstegangsbehandling, val vedtaksdato: LocalDateTime, - val vedtaksType: VedtaksType, + val vedtaksType: Vedtakstype, val periode: Periode, val saksbehandler: String, val beslutter: String, + val journalpostId: JournalpostId?, + val journalføringstidstpunkt: LocalDateTime?, + val distribusjonId: DistribusjonId? = null, + val distribusjonstidspunkt: LocalDateTime? = null, ) { val fnr = behandling.fnr val utfallsperioder: Periodisering get() = behandling.avklarteUtfallsperioder } -enum class VedtaksType( +enum class Vedtakstype( val navn: String, - val skalSendeBrev: Boolean, ) { - AVSLAG("Avslag", true), - INNVILGELSE("Innvilgelse", true), - STANS("Stans", true), - FORLENGELSE("Forlengelse", true), + AVSLAG("Avslag"), + INNVILGELSE("Innvilgelse"), + STANS("Stans"), + FORLENGELSE("Forlengelse"), } fun Førstegangsbehandling.opprettVedtak(): Rammevedtak { @@ -44,9 +48,11 @@ fun Førstegangsbehandling.opprettVedtak(): Rammevedtak { saksnummer = this.saksnummer, behandling = this, vedtaksdato = LocalDateTime.now(), - vedtaksType = VedtaksType.INNVILGELSE, + vedtaksType = Vedtakstype.INNVILGELSE, periode = this.vurderingsperiode, saksbehandler = this.saksbehandler!!, beslutter = this.beslutter!!, + journalpostId = null, + journalføringstidstpunkt = null, ) } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/GenererVedtaksbrevGateway.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/GenererVedtaksbrevGateway.kt new file mode 100644 index 0000000000..991b66c77c --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/GenererVedtaksbrevGateway.kt @@ -0,0 +1,11 @@ +package no.nav.tiltakspenger.saksbehandling.ports + +import arrow.core.Either +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak + +interface GenererVedtaksbrevGateway { + suspend fun genererVedtaksbrev(vedtak: Rammevedtak): Either +} + +object KunneIkkeGenererePdf diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/Journalf\303\270rVedtaksbrevGateway.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/Journalf\303\270rVedtaksbrevGateway.kt" new file mode 100644 index 0000000000..4898ac3fb7 --- /dev/null +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/Journalf\303\270rVedtaksbrevGateway.kt" @@ -0,0 +1,14 @@ +package no.nav.tiltakspenger.saksbehandling.ports + +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak + +interface JournalførVedtaksbrevGateway { + suspend fun journalførVedtaksbrev( + vedtak: Rammevedtak, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId +} diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/RammevedtakRepo.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/RammevedtakRepo.kt index bb10bdd25f..74454422b8 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/RammevedtakRepo.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/ports/RammevedtakRepo.kt @@ -1,9 +1,13 @@ package no.nav.tiltakspenger.saksbehandling.ports +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.domene.VedtakSomSkalDistribueres +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.Fnr import no.nav.tiltakspenger.libs.common.VedtakId import no.nav.tiltakspenger.libs.persistering.domene.TransactionContext import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import java.time.LocalDateTime interface RammevedtakRepo { fun hentForVedtakId(vedtakId: VedtakId): Rammevedtak? @@ -14,4 +18,12 @@ interface RammevedtakRepo { ) fun hentForFnr(fnr: Fnr): List + + fun hentRammevedtakSomSkalJournalføres(limit: Int = 10): List + + fun hentRammevedtakSomSkalDistribueres(limit: Int = 10): List + + fun markerJournalført(id: VedtakId, journalpostId: JournalpostId, tidspunkt: LocalDateTime) + + fun markerDistribuert(id: VedtakId, distribusjonId: DistribusjonId, tidspunkt: LocalDateTime) } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/distribuering/DistribuerVedtaksbrevService.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/distribuering/DistribuerVedtaksbrevService.kt new file mode 100644 index 0000000000..08ff7a6799 --- /dev/null +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/distribuering/DistribuerVedtaksbrevService.kt @@ -0,0 +1,38 @@ +package no.nav.tiltakspenger.saksbehandling.service.distribuering + +import arrow.core.Either +import arrow.core.getOrElse +import mu.KotlinLogging +import no.nav.tiltakspenger.distribusjon.ports.DokdistGateway +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo +import java.time.LocalDateTime + +class DistribuerVedtaksbrevService( + private val dokdistGateway: DokdistGateway, + private val rammevedtakRepo: RammevedtakRepo, +) { + private val log = KotlinLogging.logger {} + + /** Ment å kalles fra en jobb - journalfører alle rammevedtak som skal sende brev. */ + suspend fun distribuer( + correlationId: CorrelationId, + ) { + rammevedtakRepo.hentRammevedtakSomSkalDistribueres().forEach { vedtakSomSkalDistribueres -> + log.info { "Prøver å distribuere journalpost for rammevedtak. $vedtakSomSkalDistribueres" } + Either.catch { + val distribusjonId = + dokdistGateway.distribuerDokument(vedtakSomSkalDistribueres.journalpostId, correlationId) + .getOrElse { + log.error { "Kunne ikke distribuere vedtaksbrev. $vedtakSomSkalDistribueres" } + return@forEach + } + log.info { "Vedtaksbrev distribuert. $vedtakSomSkalDistribueres" } + rammevedtakRepo.markerDistribuert(vedtakSomSkalDistribueres.id, distribusjonId, LocalDateTime.now()) + log.info { "Vedtaksbrev markert som distribuert. distribusjonId: $distribusjonId, $vedtakSomSkalDistribueres" } + }.onLeft { + log.error(it) { "Feil ved journalføring av vedtaksbrev. $vedtakSomSkalDistribueres" } + } + } + } +} diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/journalf\303\270ring/Journalf\303\270rVedtaksbrevService.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/journalf\303\270ring/Journalf\303\270rVedtaksbrevService.kt" new file mode 100644 index 0000000000..ce66eeba77 --- /dev/null +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/journalf\303\270ring/Journalf\303\270rVedtaksbrevService.kt" @@ -0,0 +1,37 @@ +package no.nav.tiltakspenger.saksbehandling.service.journalføring + +import arrow.core.Either +import arrow.core.getOrElse +import mu.KotlinLogging +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.saksbehandling.ports.GenererVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.JournalførVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo +import java.time.LocalDateTime + +class JournalførVedtaksbrevService( + private val journalførVedtaksbrevGateway: JournalførVedtaksbrevGateway, + private val rammevedtakRepo: RammevedtakRepo, + private val genererVedtaksbrevGateway: GenererVedtaksbrevGateway, +) { + private val log = KotlinLogging.logger {} + + /** Ment å kalles fra en jobb - journalfører alle rammevedtak som skal sende brev. */ + suspend fun journalfør( + correlationId: CorrelationId, + ) { + rammevedtakRepo.hentRammevedtakSomSkalJournalføres().forEach { vedtak -> + log.info { "Journalfører vedtaksbrev for vedtak ${vedtak.id}" } + Either.catch { + val pdfOgJson = genererVedtaksbrevGateway.genererVedtaksbrev(vedtak).getOrElse { return@forEach } + log.info { "Vedtaksbrev generert for vedtak ${vedtak.id}" } + val journalpostId = journalførVedtaksbrevGateway.journalførVedtaksbrev(vedtak, pdfOgJson, correlationId) + log.info { "Vedtaksbrev journalført for vedtak ${vedtak.id}" } + rammevedtakRepo.markerJournalført(vedtak.id, journalpostId, LocalDateTime.now()) + log.info { "Vedtaksbrev markert som journalført for vedtak ${vedtak.id}" } + }.onLeft { + log.error(it) { "Feil ved journalføring av vedtaksbrev for vedtak ${vedtak.id}" } + } + } + } +} diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/statistikk/sak/StatistikkSakMapper.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/statistikk/sak/StatistikkSakMapper.kt index 01f052ed5a..6618d480b0 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/statistikk/sak/StatistikkSakMapper.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/statistikk/sak/StatistikkSakMapper.kt @@ -4,7 +4,7 @@ import no.nav.tiltakspenger.felles.nå import no.nav.tiltakspenger.saksbehandling.domene.behandling.Behandling import no.nav.tiltakspenger.saksbehandling.domene.sak.SakDetaljer import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak -import no.nav.tiltakspenger.saksbehandling.domene.vedtak.VedtaksType +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Vedtakstype import no.nav.tiltakspenger.saksbehandling.domene.vilkår.UtfallForPeriode import no.nav.tiltakspenger.saksbehandling.domene.vilkår.Vilkårssett @@ -68,10 +68,10 @@ fun iverksettBehandlingMapper(sak: SakDetaljer, behandling: Behandling, vedtak: behandlingType = BehandlingType.FØRSTEGANGSBEHANDLING, behandlingStatus = BehandlingStatus.FERDIG_BEHANDLET, behandlingResultat = when (vedtak.vedtaksType) { - VedtaksType.AVSLAG -> BehandlingResultat.AVSLAG - VedtaksType.INNVILGELSE -> BehandlingResultat.INNVILGET - VedtaksType.STANS -> BehandlingResultat.STANS - VedtaksType.FORLENGELSE -> BehandlingResultat.FORLENGELSE + Vedtakstype.AVSLAG -> BehandlingResultat.AVSLAG + Vedtakstype.INNVILGELSE -> BehandlingResultat.INNVILGET + Vedtakstype.STANS -> BehandlingResultat.STANS + Vedtakstype.FORLENGELSE -> BehandlingResultat.FORLENGELSE }, resultatBegrunnelse = null, behandlingMetode = BehandlingMetode.MANUELL.name, diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/vedtak/RammevedtakServiceImpl.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/vedtak/RammevedtakServiceImpl.kt index 965b6560fa..9d253603a8 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/vedtak/RammevedtakServiceImpl.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/saksbehandling/service/vedtak/RammevedtakServiceImpl.kt @@ -10,14 +10,15 @@ import java.time.LocalDate class RammevedtakServiceImpl( private val vedtakRepo: RammevedtakRepo, ) : RammevedtakService { + override fun hentVedtak(vedtakId: VedtakId): Rammevedtak? = vedtakRepo.hentForVedtakId(vedtakId) override fun hentVedtakForIdent( ident: Fnr, fom: LocalDate, tom: LocalDate, - ): List = - vedtakRepo + ): List { + return vedtakRepo .hentForFnr(ident) .filter { vedtak -> vedtak.periode.overlapperMed( @@ -27,4 +28,5 @@ class RammevedtakServiceImpl( ), ) } + } } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/domene/Utbetalingsvedtak.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/domene/Utbetalingsvedtak.kt index f14a73147e..83ce2bdd75 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/domene/Utbetalingsvedtak.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/domene/Utbetalingsvedtak.kt @@ -1,11 +1,11 @@ package no.nav.tiltakspenger.utbetaling.domene +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.felles.nå import no.nav.tiltakspenger.libs.common.Fnr import no.nav.tiltakspenger.libs.common.SakId import no.nav.tiltakspenger.libs.common.VedtakId import no.nav.tiltakspenger.meldekort.domene.Meldekort -import no.nav.tiltakspenger.meldekort.domene.Meldeperiode import no.nav.tiltakspenger.saksbehandling.domene.sak.Saksnummer import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak import no.nav.tiltakspenger.saksbehandling.service.statistikk.stønad.StatistikkUtbetalingDTO @@ -25,11 +25,12 @@ data class Utbetalingsvedtak( val brukerNavkontor: String, val saksbehandler: String, val beslutter: String, - val meldekortperiode: Meldeperiode.UtfyltMeldeperiode, + val meldekort: Meldekort.UtfyltMeldekort, val utbetalingsperiode: UtbetalingsperioderGruppertPåMeldekortperiode, val forrigeUtbetalingsvedtak: VedtakId?, - val sendtTilUtbetaling: Boolean, - val sendtTilDokument: Boolean, + val sendtTilUtbetaling: LocalDateTime?, + val journalpostId: JournalpostId?, + val journalføringstidspunkt: LocalDateTime?, ) { val periode = utbetalingsperiode.periode val beløp = utbetalingsperiode.beløp @@ -45,23 +46,6 @@ data class Utbetalingsvedtak( } } -/** - * @property meldekortperiode Vi tar bare inn en periode her i MVP, siden vi ikke har støtte for korrigering av tidligere meldekort. - */ -fun Utbetalingsvedtak.nyttUtbetalingVedtak( - saksbehandler: String, - meldekortperiode: Meldeperiode.UtfyltMeldeperiode, -): Utbetalingsvedtak = - this.copy( - id = VedtakId.random(), - vedtakstidspunkt = LocalDateTime.now(), - saksbehandler = saksbehandler, - beslutter = saksbehandler, - utbetalingsperiode = meldekortperiode.genererUtbetalingsperioderGruppertPåMeldekortperiode(), - meldekortperiode = meldekortperiode, - forrigeUtbetalingsvedtak = this.id, - ) - fun Meldekort.UtfyltMeldekort.tilUtbetalingsperiode( rammevedtak: Rammevedtak, forrigeUtbetalingsvedtak: VedtakId?, @@ -77,11 +61,12 @@ fun Meldekort.UtfyltMeldekort.tilUtbetalingsperiode( brukerNavkontor = "0220", saksbehandler = this.saksbehandler, beslutter = this.beslutter!!, - meldekortperiode = this.meldekortperiode, + meldekort = this, utbetalingsperiode = this.meldekortperiode.genererUtbetalingsperioderGruppertPåMeldekortperiode(), forrigeUtbetalingsvedtak = forrigeUtbetalingsvedtak, - sendtTilUtbetaling = false, - sendtTilDokument = false, + sendtTilUtbetaling = null, + journalpostId = null, + journalføringstidspunkt = null, ) fun Utbetalingsvedtak.tilStatistikk(): StatistikkUtbetalingDTO = diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/ports/UtbetalingsvedtakRepo.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/ports/UtbetalingsvedtakRepo.kt index 8430d7fd8a..5856d21b9a 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/ports/UtbetalingsvedtakRepo.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/ports/UtbetalingsvedtakRepo.kt @@ -1,5 +1,6 @@ package no.nav.tiltakspenger.utbetaling.ports +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.SakId import no.nav.tiltakspenger.libs.common.VedtakId @@ -7,16 +8,22 @@ import no.nav.tiltakspenger.libs.persistering.domene.TransactionContext import no.nav.tiltakspenger.meldekort.domene.Meldekort import no.nav.tiltakspenger.saksbehandling.ports.SendtUtbetaling import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak +import java.time.LocalDateTime interface UtbetalingsvedtakRepo { fun lagre(vedtak: Utbetalingsvedtak, context: TransactionContext? = null) fun markerSendtTilUtbetaling( vedtakId: VedtakId, + tidspunkt: LocalDateTime, utbetalingsrespons: SendtUtbetaling, ) - fun markerSendtTilDokument(vedtakId: VedtakId) + fun markerJournalført( + vedtakId: VedtakId, + journalpostId: JournalpostId, + tidspunkt: LocalDateTime, + ) fun hentForVedtakId(vedtakId: VedtakId): Utbetalingsvedtak? @@ -28,5 +35,5 @@ interface UtbetalingsvedtakRepo { fun hentUtbetalingsvedtakForUtsjekk(limit: Int = 10): List - fun hentUtbetalingsvedtakForDokument(limit: Int = 10): List + fun hentDeSomSkalJournalføres(limit: Int = 10): List } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/HentUtbetalingsvedtakService.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/HentUtbetalingsvedtakService.kt index a53e70dddb..8faf6899d7 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/HentUtbetalingsvedtakService.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/HentUtbetalingsvedtakService.kt @@ -1,6 +1,5 @@ package no.nav.tiltakspenger.utbetaling.service -import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.VedtakId import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo @@ -8,9 +7,5 @@ import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo class HentUtbetalingsvedtakService( private val utbetalingsvedtakRepo: UtbetalingsvedtakRepo, ) { - fun hentForBehandlingId(behandlingId: BehandlingId): List { - return utbetalingsvedtakRepo.hentForFørstegangsbehandlingId(behandlingId) - } - fun hentForVedtakId(vedtakId: VedtakId): Utbetalingsvedtak? = utbetalingsvedtakRepo.hentForVedtakId(vedtakId) } diff --git "a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/Journalf\303\270rUtbetalingsvedtakService.kt" "b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/Journalf\303\270rUtbetalingsvedtakService.kt" index bf31ebcf5f..4db6886b29 100644 --- "a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/Journalf\303\270rUtbetalingsvedtakService.kt" +++ "b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/Journalf\303\270rUtbetalingsvedtakService.kt" @@ -3,29 +3,38 @@ package no.nav.tiltakspenger.utbetaling.service import arrow.core.Either import mu.KotlinLogging import no.nav.tiltakspenger.libs.common.CorrelationId -import no.nav.tiltakspenger.meldekort.ports.DokumentGateway +import no.nav.tiltakspenger.meldekort.ports.GenererMeldekortPdfGateway +import no.nav.tiltakspenger.meldekort.ports.JournalførMeldekortGateway import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo +import java.time.LocalDateTime /** - * Har ansvar for å sende utbetalingsvedtak/meldekort til tiltakspenger-dokument. + * Har ansvar for å generere pdf og sende utbetalingsvedtak til journalføring. * Denne er kun ment og kalles fra en jobb. */ class JournalførUtbetalingsvedtakService( + private val journalførMeldekortGateway: JournalførMeldekortGateway, private val utbetalingsvedtakRepo: UtbetalingsvedtakRepo, - private val dokumentGateway: DokumentGateway, + private val genererMeldekortPdfGateway: GenererMeldekortPdfGateway, ) { - private val logger = KotlinLogging.logger { } + private val log = KotlinLogging.logger { } - suspend fun send(correlationId: CorrelationId) { - utbetalingsvedtakRepo.hentUtbetalingsvedtakForDokument().forEach { utbetalingsvedtak -> + suspend fun journalfør(correlationId: CorrelationId) { + utbetalingsvedtakRepo.hentDeSomSkalJournalføres().forEach { utbetalingsvedtak -> + log.info { "Journalfører utbetalingsvedtak. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}" } Either.catch { - // TODO pre-mvp jah: Diskuter med teamet om vi trenger en egen pod for å journalføre? Den er jo uansett synkron så vedtak vil ta seg av retries. Kunne det vært et lib istedenfor? - val response = dokumentGateway.journalførMeldekort(utbetalingsvedtak, correlationId) - logger.info { "Utbetalingsvedtak journalført. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}. Response: $response" } - utbetalingsvedtakRepo.markerSendtTilDokument(utbetalingsvedtak.id) - logger.info { "Utbetalingsvedtak markert som sendt til dokument. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}. Response: $response" } + val pdfOgJson = genererMeldekortPdfGateway.genererMeldekortPdf(utbetalingsvedtak.meldekort) + log.info { "Pdf generert for utbetalingsvedtak. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}" } + val journalpostId = journalførMeldekortGateway.journalførMeldekort( + meldekort = utbetalingsvedtak.meldekort, + pdfOgJson = pdfOgJson, + correlationId = correlationId, + ) + log.info { "utbetalingsvedtak journalført. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}. JournalpostId: $journalpostId" } + utbetalingsvedtakRepo.markerJournalført(utbetalingsvedtak.id, journalpostId, LocalDateTime.now()) + log.info { "Utbetalingsvedtak markert som journalført. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}. JournalpostId: $journalpostId" } }.onLeft { - logger.error(it) { "Ukjent feil skjedde under journalføring av utbetaling. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}" } + log.error(it) { "Ukjent feil skjedde under generering av brev og journalføring av utbetalingsvedtak. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}" } } } } diff --git a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/SendUtbetalingerService.kt b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/SendUtbetalingerService.kt index b48f17789a..3bf848b147 100644 --- a/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/SendUtbetalingerService.kt +++ b/domene/src/main/kotlin/no/nav/tiltakspenger/utbetaling/service/SendUtbetalingerService.kt @@ -5,6 +5,7 @@ import mu.KotlinLogging import no.nav.tiltakspenger.libs.common.CorrelationId import no.nav.tiltakspenger.saksbehandling.ports.UtbetalingGateway import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo +import java.time.LocalDateTime /** * Har ansvar for å sende klare utbetalingsvedtak til helved utsjekk. @@ -20,7 +21,7 @@ class SendUtbetalingerService( Either.catch { utbetalingsklient.iverksett(utbetalingsvedtak, correlationId).onRight { logger.info { "Utbetaling iverksatt for vedtak ${utbetalingsvedtak.id}" } - utbetalingsvedtakRepo.markerSendtTilUtbetaling(utbetalingsvedtak.id, it) + utbetalingsvedtakRepo.markerSendtTilUtbetaling(utbetalingsvedtak.id, LocalDateTime.now(), it) logger.info { "Utbetaling markert som utbetalt for vedtak ${utbetalingsvedtak.id}" } }.onLeft { logger.error { "Utbetaling kunne ikke iverksettes. Saksnummer: ${utbetalingsvedtak.saksnummer}, sakId: ${utbetalingsvedtak.sakId}, utbetalingsvedtakId: ${utbetalingsvedtak.id}" } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/common/DistribusjonIdGenerator.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/DistribusjonIdGenerator.kt new file mode 100644 index 0000000000..04b94673c8 --- /dev/null +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/DistribusjonIdGenerator.kt @@ -0,0 +1,15 @@ +package no.nav.tiltakspenger.common + +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import java.util.concurrent.atomic.AtomicLong + +/** + * Trådsikker. Dersom tester deler database, bør de bruke en felles statisk versjon av denne. + */ +class DistribusjonIdGenerator( + første: Long = 1, +) { + private val neste = AtomicLong(første) + + fun neste(): DistribusjonId = DistribusjonId(neste.getAndIncrement().toString()) +} diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/common/JournalpostIdGenerator.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/JournalpostIdGenerator.kt index 15efb3ee5f..7057db4c0d 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/common/JournalpostIdGenerator.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/JournalpostIdGenerator.kt @@ -1,5 +1,6 @@ package no.nav.tiltakspenger.common +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import java.util.concurrent.atomic.AtomicLong /** @@ -10,5 +11,5 @@ class JournalpostIdGenerator( ) { private val neste = AtomicLong(første) - fun neste(): String = neste.getAndIncrement().toString() + fun neste(): JournalpostId = JournalpostId(neste.getAndIncrement().toString()) } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/common/TestApplicationContext.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/TestApplicationContext.kt index f44673ac98..91234d2087 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/common/TestApplicationContext.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/common/TestApplicationContext.kt @@ -1,8 +1,12 @@ package no.nav.tiltakspenger.common -import no.nav.tiltakspenger.fakes.clients.DokumentFakeGateway +import no.nav.tiltakspenger.fakes.clients.DokdistFakeGateway import no.nav.tiltakspenger.fakes.clients.FellesFakeAdressebeskyttelseKlient import no.nav.tiltakspenger.fakes.clients.FellesFakeSkjermingsklient +import no.nav.tiltakspenger.fakes.clients.GenererFakeMeldekortPdfGateway +import no.nav.tiltakspenger.fakes.clients.GenererFakeVedtaksbrevGateway +import no.nav.tiltakspenger.fakes.clients.JournalførFakeMeldekortGateway +import no.nav.tiltakspenger.fakes.clients.JournalførFakeVedtaksbrevGateway import no.nav.tiltakspenger.fakes.clients.PersonFakeGateway import no.nav.tiltakspenger.fakes.clients.SkjermingFakeGateway import no.nav.tiltakspenger.fakes.clients.TiltakFakeGateway @@ -43,11 +47,11 @@ import no.nav.tiltakspenger.vedtak.context.UtbetalingContext */ class TestApplicationContext : ApplicationContext(TestSessionFactory(), "fake-git-hash") { val journalpostIdGenerator = JournalpostIdGenerator() + val distribusjonIdGenerator = DistribusjonIdGenerator() private val rammevedtakFakeRepo = RammevedtakFakeRepo() private val statistikkStønadFakeRepo = StatistikkStønadFakeRepo() private val statistikkSakFakeRepo = StatistikkSakFakeRepo() - private val dokumentGatewayFake = DokumentFakeGateway(journalpostIdGenerator) private val utbetalingGatewayFake = UtbetalingFakeGateway() private val meldekortFakeRepo = MeldekortFakeRepo() private val utbetalingsvedtakFakeRepo = UtbetalingsvedtakFakeRepo(rammevedtakFakeRepo, meldekortFakeRepo) @@ -59,6 +63,11 @@ class TestApplicationContext : ApplicationContext(TestSessionFactory(), "fake-gi private val personGatewayFake = PersonFakeGateway() private val fellesPersonTilgangsstyringsklient = FellesFakeAdressebeskyttelseKlient() private val fellesFakeSkjermingsklient = FellesFakeSkjermingsklient() + private val genererFakeMeldekortPdfGateway = GenererFakeMeldekortPdfGateway() + private val genererFakeVedtaksbrevGateway = GenererFakeVedtaksbrevGateway() + private val journalførFakeMeldekortGateway = JournalførFakeMeldekortGateway(journalpostIdGenerator) + private val journalførFakeVedtaksbrevGateway = JournalførFakeVedtaksbrevGateway(journalpostIdGenerator) + private val dokdistFakeGateway = DokdistFakeGateway(distribusjonIdGenerator) fun leggTilPerson( fnr: Fnr, @@ -95,7 +104,10 @@ class TestApplicationContext : ApplicationContext(TestSessionFactory(), "fake-gi } override val dokumentContext by lazy { object : DokumentContext() { - override val dokumentGateway = dokumentGatewayFake + override val journalførMeldekortGateway = journalførFakeMeldekortGateway + override val journalførVedtaksbrevGateway = journalførFakeVedtaksbrevGateway + override val genererMeldekortPdfGateway = genererFakeMeldekortPdfGateway + override val genererVedtaksbrevGateway = genererFakeVedtaksbrevGateway } } @@ -157,6 +169,9 @@ class TestApplicationContext : ApplicationContext(TestSessionFactory(), "fake-gi statistikkSakRepo = statistikkSakFakeRepo, statistikkStønadRepo = statistikkStønadFakeRepo, gitHash = "fake-git-hash", + journalførVedtaksbrevGateway = dokumentContext.journalførVedtaksbrevGateway, + genererVedtaksbrevGateway = dokumentContext.genererVedtaksbrevGateway, + dokdistGateway = dokumentContext.dokdistGateway, ) { override val rammevedtakRepo = rammevedtakFakeRepo override val behandlingRepo = behandlingFakeRepo @@ -164,7 +179,13 @@ class TestApplicationContext : ApplicationContext(TestSessionFactory(), "fake-gi } override val utbetalingContext by lazy { - object : UtbetalingContext(sessionFactory, rammevedtakFakeRepo, statistikkStønadFakeRepo, dokumentGatewayFake) { + object : UtbetalingContext( + sessionFactory = sessionFactory, + rammevedtakRepo = rammevedtakFakeRepo, + statistikkStønadRepo = statistikkStønadFakeRepo, + genererMeldekortPdfGateway = genererFakeMeldekortPdfGateway, + journalførMeldekortGateway = journalførFakeMeldekortGateway, + ) { override val utbetalingGateway = utbetalingGatewayFake override val utbetalingsvedtakRepo = utbetalingsvedtakFakeRepo } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokdistFakeGateway.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokdistFakeGateway.kt new file mode 100644 index 0000000000..ef0c31c862 --- /dev/null +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokdistFakeGateway.kt @@ -0,0 +1,25 @@ +package no.nav.tiltakspenger.fakes.clients + +import arrow.core.Either +import arrow.core.right +import no.nav.tiltakspenger.common.DistribusjonIdGenerator +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.ports.DokdistGateway +import no.nav.tiltakspenger.distribusjon.ports.KunneIkkeDistribuereDokument +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.libs.common.CorrelationId +import java.util.concurrent.ConcurrentHashMap + +class DokdistFakeGateway( + private val distribusjonIdGenerator: DistribusjonIdGenerator, +) : DokdistGateway { + + private val data = ConcurrentHashMap() + + override suspend fun distribuerDokument( + journalpostId: JournalpostId, + correlationId: CorrelationId, + ): Either { + return data.computeIfAbsent(journalpostId) { distribusjonIdGenerator.neste() }.right() + } +} diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokumentFakeGateway.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokumentFakeGateway.kt deleted file mode 100644 index 78ffa8b3be..0000000000 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/DokumentFakeGateway.kt +++ /dev/null @@ -1,45 +0,0 @@ -package no.nav.tiltakspenger.fakes.clients - -import arrow.atomic.Atomic -import no.nav.tiltakspenger.common.JournalpostIdGenerator -import no.nav.tiltakspenger.libs.common.CorrelationId -import no.nav.tiltakspenger.libs.common.SakId -import no.nav.tiltakspenger.meldekort.ports.DokumentGateway -import no.nav.tiltakspenger.meldekort.ports.JoarkResponse -import no.nav.tiltakspenger.saksbehandling.domene.sak.Saksnummer -import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak -import java.time.LocalDateTime - -class DokumentFakeGateway( - private val journalpostIdGenerator: JournalpostIdGenerator, -) : DokumentGateway { - private val brevSendt: Atomic> = Atomic(mutableMapOf()) - val antallBrevSendt: Int get() = brevSendt.get().size - - override suspend fun journalførMeldekort( - vedtak: Utbetalingsvedtak, - correlationId: CorrelationId, - ): JoarkResponse { - val response = JoarkResponse(journalpostIdGenerator.neste(), LocalDateTime.now()) - brevSendt.get().plus( - vedtak.sakId to - BrevSendt( - vedtak, - correlationId, - response, - ), - ) - return response - } - - fun hentBrevSendt(sakId: SakId): BrevSendt? = brevSendt.get()[sakId] - - /** Hent på sakId er raskere. */ - fun hentBrevSendt(saksnummer: Saksnummer): BrevSendt? = brevSendt.get().values.find { it.vedtak.saksnummer == saksnummer } - - data class BrevSendt( - val vedtak: Utbetalingsvedtak, - val correlationId: CorrelationId, - val response: JoarkResponse, - ) -} diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeMeldekortPdfGateway.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeMeldekortPdfGateway.kt new file mode 100644 index 0000000000..bc522d395f --- /dev/null +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeMeldekortPdfGateway.kt @@ -0,0 +1,13 @@ +package no.nav.tiltakspenger.fakes.clients + +import no.nav.tiltakspenger.felles.PdfA +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.meldekort.ports.GenererMeldekortPdfGateway + +class GenererFakeMeldekortPdfGateway : GenererMeldekortPdfGateway { + private val response by lazy { PdfOgJson(PdfA("pdf".toByteArray()), "json") } + override fun genererMeldekortPdf(meldekort: Meldekort.UtfyltMeldekort): PdfOgJson { + return response + } +} diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeVedtaksbrevGateway.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeVedtaksbrevGateway.kt new file mode 100644 index 0000000000..62c5654d66 --- /dev/null +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/GenererFakeVedtaksbrevGateway.kt @@ -0,0 +1,16 @@ +package no.nav.tiltakspenger.fakes.clients + +import arrow.core.Either +import arrow.core.right +import no.nav.tiltakspenger.felles.PdfA +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.saksbehandling.ports.GenererVedtaksbrevGateway +import no.nav.tiltakspenger.saksbehandling.ports.KunneIkkeGenererePdf + +class GenererFakeVedtaksbrevGateway : GenererVedtaksbrevGateway { + private val response by lazy { PdfOgJson(PdfA("pdf".toByteArray()), "json").right() } + override suspend fun genererVedtaksbrev(vedtak: Rammevedtak): Either { + return response + } +} diff --git "a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeMeldekortGateway.kt" "b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeMeldekortGateway.kt" new file mode 100644 index 0000000000..3e2253b360 --- /dev/null +++ "b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeMeldekortGateway.kt" @@ -0,0 +1,27 @@ +package no.nav.tiltakspenger.fakes.clients + +import arrow.atomic.Atomic +import no.nav.tiltakspenger.common.JournalpostIdGenerator +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.libs.common.MeldekortId +import no.nav.tiltakspenger.meldekort.domene.Meldekort +import no.nav.tiltakspenger.meldekort.ports.JournalførMeldekortGateway + +class JournalførFakeMeldekortGateway( + private val journalpostIdGenerator: JournalpostIdGenerator, +) : JournalførMeldekortGateway { + + private val data = Atomic(mutableMapOf()) + + override suspend fun journalførMeldekort( + meldekort: Meldekort, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId { + return data.get()[meldekort.id] ?: journalpostIdGenerator.neste().also { + data.get().putIfAbsent(meldekort.id, it) + } + } +} diff --git "a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeVedtaksbrevGateway.kt" "b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeVedtaksbrevGateway.kt" new file mode 100644 index 0000000000..297abf82a0 --- /dev/null +++ "b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/clients/Journalf\303\270rFakeVedtaksbrevGateway.kt" @@ -0,0 +1,27 @@ +package no.nav.tiltakspenger.fakes.clients + +import arrow.atomic.Atomic +import no.nav.tiltakspenger.common.JournalpostIdGenerator +import no.nav.tiltakspenger.felles.journalføring.JournalpostId +import no.nav.tiltakspenger.felles.journalføring.PdfOgJson +import no.nav.tiltakspenger.libs.common.CorrelationId +import no.nav.tiltakspenger.libs.common.VedtakId +import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak +import no.nav.tiltakspenger.saksbehandling.ports.JournalførVedtaksbrevGateway + +class JournalførFakeVedtaksbrevGateway( + private val journalpostIdGenerator: JournalpostIdGenerator, +) : JournalførVedtaksbrevGateway { + + private val data = Atomic(mutableMapOf()) + + override suspend fun journalførVedtaksbrev( + vedtak: Rammevedtak, + pdfOgJson: PdfOgJson, + correlationId: CorrelationId, + ): JournalpostId { + return data.get()[vedtak.id] ?: journalpostIdGenerator.neste().also { + data.get().putIfAbsent(vedtak.id, it) + } + } +} diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/RammevedtakFakeRepo.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/RammevedtakFakeRepo.kt index ae9f31bb5e..133cd375a1 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/RammevedtakFakeRepo.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/RammevedtakFakeRepo.kt @@ -1,6 +1,9 @@ package no.nav.tiltakspenger.fakes.repos import arrow.atomic.Atomic +import no.nav.tiltakspenger.distribusjon.domene.DistribusjonId +import no.nav.tiltakspenger.distribusjon.domene.VedtakSomSkalDistribueres +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.Fnr import no.nav.tiltakspenger.libs.common.SakId @@ -8,8 +11,10 @@ import no.nav.tiltakspenger.libs.common.VedtakId import no.nav.tiltakspenger.libs.persistering.domene.TransactionContext import no.nav.tiltakspenger.saksbehandling.domene.vedtak.Rammevedtak import no.nav.tiltakspenger.saksbehandling.ports.RammevedtakRepo +import java.time.LocalDateTime class RammevedtakFakeRepo : RammevedtakRepo { + private val data = Atomic(mutableMapOf()) override fun hentForVedtakId(vedtakId: VedtakId): Rammevedtak? = data.get()[vedtakId] @@ -23,7 +28,26 @@ class RammevedtakFakeRepo : RammevedtakRepo { override fun hentForFnr(fnr: Fnr): List = data.get().values.filter { it.behandling.fnr == fnr } + override fun hentRammevedtakSomSkalJournalføres(limit: Int): List { + return data.get().values.filter { it.journalpostId == null }.take(limit) + } + + override fun markerJournalført(id: VedtakId, journalpostId: JournalpostId, tidspunkt: LocalDateTime) { + data.get()[id] = data.get()[id]!!.copy(journalpostId = journalpostId, journalføringstidstpunkt = tidspunkt) + } + + override fun hentRammevedtakSomSkalDistribueres(limit: Int): List { + return data.get().values.filter { it.distribusjonId == null }.map { + VedtakSomSkalDistribueres(it.id, it.journalpostId!!) + }.take(limit) + } + + override fun markerDistribuert(id: VedtakId, distribusjonId: DistribusjonId, tidspunkt: LocalDateTime) { + data.get()[id] = data.get()[id]!!.copy(distribusjonId = distribusjonId, distribusjonstidspunkt = tidspunkt) + } + fun hentForSakId(sakId: SakId): Rammevedtak? = data.get().values.find { it.behandling.sakId == sakId } - fun hentForBehandlingId(behandlingId: BehandlingId): Rammevedtak? = data.get().values.find { it.behandling.id == behandlingId } + fun hentForBehandlingId(behandlingId: BehandlingId): Rammevedtak? = + data.get().values.find { it.behandling.id == behandlingId } } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/UtbetalingsvedtakFakeRepo.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/UtbetalingsvedtakFakeRepo.kt index 91e9877c86..7d87120ca1 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/UtbetalingsvedtakFakeRepo.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/fakes/repos/UtbetalingsvedtakFakeRepo.kt @@ -1,6 +1,7 @@ package no.nav.tiltakspenger.fakes.repos import arrow.atomic.Atomic +import no.nav.tiltakspenger.felles.journalføring.JournalpostId import no.nav.tiltakspenger.libs.common.BehandlingId import no.nav.tiltakspenger.libs.common.SakId import no.nav.tiltakspenger.libs.common.VedtakId @@ -9,6 +10,7 @@ import no.nav.tiltakspenger.meldekort.domene.Meldekort.UtfyltMeldekort import no.nav.tiltakspenger.saksbehandling.ports.SendtUtbetaling import no.nav.tiltakspenger.utbetaling.domene.Utbetalingsvedtak import no.nav.tiltakspenger.utbetaling.ports.UtbetalingsvedtakRepo +import java.time.LocalDateTime class UtbetalingsvedtakFakeRepo( private val rammevedtakFakeRepo: RammevedtakFakeRepo, @@ -22,13 +24,19 @@ class UtbetalingsvedtakFakeRepo( override fun markerSendtTilUtbetaling( vedtakId: VedtakId, + tidspunkt: LocalDateTime, utbetalingsrespons: SendtUtbetaling, ) { - data.get()[vedtakId] = data.get()[vedtakId]!!.copy(sendtTilUtbetaling = true) + data.get()[vedtakId] = data.get()[vedtakId]!!.copy(sendtTilUtbetaling = tidspunkt) } - override fun markerSendtTilDokument(vedtakId: VedtakId) { - data.get()[vedtakId] = data.get()[vedtakId]!!.copy(sendtTilDokument = true) + override fun markerJournalført( + vedtakId: VedtakId, + journalpostId: JournalpostId, + tidspunkt: LocalDateTime, + ) { + data.get()[vedtakId] = + data.get()[vedtakId]!!.copy(journalpostId = journalpostId, journalføringstidspunkt = tidspunkt) } override fun hentForVedtakId(vedtakId: VedtakId): Utbetalingsvedtak? = data.get()[vedtakId] @@ -42,12 +50,12 @@ class UtbetalingsvedtakFakeRepo( override fun hentGodkjenteMeldekortUtenUtbetalingsvedtak(limit: Int): List = meldekortFakeRepo.hentAlle().filter { - data.get().values.none { utbetalingsvedtak -> utbetalingsvedtak.meldekortperiode.meldekortId == it.id } + data.get().values.none { utbetalingsvedtak -> utbetalingsvedtak.meldekort.id == it.id } } override fun hentUtbetalingsvedtakForUtsjekk(limit: Int): List = - data.get().values.filter { it.sendtTilUtbetaling } + data.get().values.filter { it.sendtTilUtbetaling == null }.take(limit) - override fun hentUtbetalingsvedtakForDokument(limit: Int): List = - data.get().values.filter { it.sendtTilDokument } + override fun hentDeSomSkalJournalføres(limit: Int): List = + data.get().values.filter { it.journalpostId == null }.take(limit) } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/MeldekortMother.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/MeldekortMother.kt index 61ab359d42..a8e91b5d9e 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/MeldekortMother.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/MeldekortMother.kt @@ -21,6 +21,7 @@ import no.nav.tiltakspenger.meldekort.domene.Meldeperioder import no.nav.tiltakspenger.meldekort.domene.SendMeldekortTilBeslutterKommando import no.nav.tiltakspenger.saksbehandling.domene.vilkår.AvklartUtfallForPeriode import java.time.LocalDate +import java.time.LocalDateTime interface MeldekortMother { @@ -39,6 +40,7 @@ interface MeldekortMother { forrigeMeldekortId: MeldekortId? = null, tiltakstype: TiltakstypeSomGirRett = TiltakstypeSomGirRett.GRUPPE_AMO, status: MeldekortStatus = MeldekortStatus.GODKJENT, + iverksattTidspunkt: LocalDateTime? = null, ) = Meldekort.UtfyltMeldekort( id = id, sakId = sakId, @@ -50,6 +52,7 @@ interface MeldekortMother { forrigeMeldekortId = forrigeMeldekortId, tiltakstype = tiltakstype, status = status, + iverksattTidspunkt = iverksattTidspunkt, ) /** @@ -135,7 +138,15 @@ interface MeldekortMother { ) } return kommandoer.drop(1).fold( - førsteBeregnetMeldekort(tiltakstype, kommandoer.first().meldekortId, sakId, fnr, rammevedtakId, kommandoer.first(), utfallsperioder).first, + førsteBeregnetMeldekort( + tiltakstype, + kommandoer.first().meldekortId, + sakId, + fnr, + rammevedtakId, + kommandoer.first(), + utfallsperioder, + ).first, ) { meldekortperioder, kommando -> meldekortperioder.beregnNesteMeldekort(kommando, fnr) } diff --git a/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/SakMother.kt b/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/SakMother.kt index a06cc4c49f..2cc959ce43 100644 --- a/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/SakMother.kt +++ b/test-common/src/main/kotlin/no/nav/tiltakspenger/objectmothers/SakMother.kt @@ -133,7 +133,7 @@ interface SakMother { løpenummer: Int = 1001, saksnummer: Saksnummer = Saksnummer(iDag, løpenummer), saksbehandler: Saksbehandler = saksbehandler(), - beslutter: Saksbehandler = saksbehandler(), + beslutter: Saksbehandler = beslutter(), ): Sak { return sakTilBeslutter( sakId = sakId, @@ -141,9 +141,10 @@ interface SakMother { saksbehandler = saksbehandler, ).let { require(it.behandlinger.size == 1) + val iverksattBehandling = it.førstegangsbehandling.iverksett(beslutter, godkjentAttestering()) it.copy( - behandlinger = nonEmptyListOf(it.førstegangsbehandling.iverksett(beslutter, godkjentAttestering())), - vedtak = listOf(it.førstegangsbehandling.opprettVedtak()), + behandlinger = nonEmptyListOf(iverksattBehandling), + vedtak = listOf(iverksattBehandling.opprettVedtak()), ) } }