diff --git a/build.gradle.kts b/build.gradle.kts index 94829f5..5a44a58 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,9 @@ plugins { dependencies { implementation("com.github.navikt:rapids-and-rivers:$rapidsAndRiversVersion") + implementation("com.github.navikt.tbd-libs:azure-token-client-default:$tbdLibsVersion") + implementation("com.github.navikt.tbd-libs:retry:$tbdLibsVersion") + implementation("com.github.navikt.tbd-libs:speed-client:$tbdLibsVersion") implementation("io.ktor:ktor-client-apache:$ktorVersion") implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") diff --git a/deploy/dev.yml b/deploy/dev.yml index 048d78a..9e8d5c1 100644 --- a/deploy/dev.yml +++ b/deploy/dev.yml @@ -40,6 +40,14 @@ spec: databases: - name: sporbar envVarPrefix: DATABASE + accessPolicy: + outbound: + rules: + - application: speed-api + azure: + application: + enabled: true + tenant: trygdeetaten.no env: - name: KAFKA_RAPID_TOPIC value: tbd.rapid.v1 diff --git a/deploy/prod.yml b/deploy/prod.yml index 12804cd..c03c5d2 100644 --- a/deploy/prod.yml +++ b/deploy/prod.yml @@ -43,6 +43,14 @@ spec: databases: - name: sporbar envVarPrefix: DATABASE + accessPolicy: + outbound: + rules: + - application: speed-api + azure: + application: + enabled: true + tenant: nav.no env: - name: KAFKA_RAPID_TOPIC value: tbd.rapid.v1 diff --git a/src/main/kotlin/no/nav/helse/sporbar/AnnulleringRiver.kt b/src/main/kotlin/no/nav/helse/sporbar/AnnulleringRiver.kt index 60a03f0..8dee85c 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/AnnulleringRiver.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/AnnulleringRiver.kt @@ -6,16 +6,19 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.River import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.isMissingOrNull +import com.github.navikt.tbd_libs.rapids_and_rivers.withMDC import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageProblems import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection +import com.github.navikt.tbd_libs.result_object.getOrThrow +import com.github.navikt.tbd_libs.retry.retryBlocking +import com.github.navikt.tbd_libs.speed.SpeedClient import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.time.LocalDate -import java.time.LocalDateTime import java.util.UUID +import no.nav.helse.sporbar.dto.AnnulleringDto private val log: Logger = LoggerFactory.getLogger("sporbar") private val sikkerLog: Logger = LoggerFactory.getLogger("tjenestekall") @@ -23,6 +26,7 @@ private val sikkerLog: Logger = LoggerFactory.getLogger("tjenestekall") class AnnulleringRiver( rapidsConnection: RapidsConnection, private val aivenProducer: KafkaProducer, + private val speedClient: SpeedClient ): River.PacketListener { init { @@ -30,6 +34,7 @@ class AnnulleringRiver( validate { it.demandValue("@event_name", "utbetaling_annullert") it.requireKey( + "@id", "fødselsnummer", "organisasjonsnummer", "tidspunkt", @@ -48,10 +53,19 @@ class AnnulleringRiver( } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val fødselsnummer = packet["fødselsnummer"].asText() + val callId = packet["@id"].asText() + withMDC("callId" to callId) { + håndterAnnullering(packet, callId) + } + } + + private fun håndterAnnullering(packet: JsonMessage, callId: String) { + val ident = packet["fødselsnummer"].asText() + val identer = retryBlocking { speedClient.hentFødselsnummerOgAktørId(ident, callId).getOrThrow() } + val annulleringDto = AnnulleringDto( organisasjonsnummer = packet["organisasjonsnummer"].asText(), - fødselsnummer = fødselsnummer, + fødselsnummer = identer.fødselsnummer, tidsstempel = packet["tidspunkt"].asLocalDateTime(), fom = packet["fom"].asLocalDate(), tom = packet["tom"].asLocalDate(), @@ -60,32 +74,9 @@ class AnnulleringRiver( arbeidsgiverFagsystemId = packet["arbeidsgiverFagsystemId"].takeUnless { it.isMissingOrNull() }?.asText(), personFagsystemId = packet["personFagsystemId"].takeUnless { it.isMissingOrNull() }?.asText() ) - val annulleringJson = objectMapper.valueToTree(annulleringDto) - aivenProducer.send( - ProducerRecord( - "tbd.utbetaling", - null, - fødselsnummer, - annulleringJson.toString(), - listOf(Meldingstype.Annullering.header()) - ) - ) + val annulleringJson = objectMapper.writeValueAsString(annulleringDto) + aivenProducer.send(ProducerRecord("tbd.utbetaling", null, identer.fødselsnummer, annulleringJson, listOf(Meldingstype.Annullering.header()))) log.info("Publiserte annullering") sikkerLog.info("Publiserte annullering $annulleringJson") } - - data class AnnulleringDto( - val utbetalingId: UUID, - val korrelasjonsId: UUID, - val organisasjonsnummer: String, - val tidsstempel: LocalDateTime, - val fødselsnummer: String, - val fom: LocalDate, - val tom: LocalDate, - val arbeidsgiverFagsystemId: String?, - val personFagsystemId: String?) { - val event = "utbetaling_annullert" - @Deprecated("trengs så lenge vi produserer til on-prem") - val orgnummer: String = organisasjonsnummer - } } diff --git a/src/main/kotlin/no/nav/helse/sporbar/App.kt b/src/main/kotlin/no/nav/helse/sporbar/App.kt index 5374050..509ad63 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/App.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/App.kt @@ -4,20 +4,18 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.github.navikt.tbd_libs.azure.createAzureTokenClientFromEnvironment +import com.github.navikt.tbd_libs.kafka.AivenConfig +import com.github.navikt.tbd_libs.kafka.ConsumerProducerFactory import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection -import java.util.Properties +import com.github.navikt.tbd_libs.speed.SpeedClient +import java.net.http.HttpClient import no.nav.helse.rapids_rivers.RapidApplication import no.nav.helse.sporbar.sis.BehandlingForkastetRiver import no.nav.helse.sporbar.sis.BehandlingLukketRiver import no.nav.helse.sporbar.sis.BehandlingOpprettetRiver import no.nav.helse.sporbar.sis.KafkaSisPublisher import no.nav.helse.sporbar.sis.VedtaksperiodeVenterRiver -import org.apache.kafka.clients.CommonClientConfigs -import org.apache.kafka.clients.producer.KafkaProducer -import org.apache.kafka.clients.producer.ProducerConfig -import org.apache.kafka.common.config.SslConfigs -import org.apache.kafka.common.security.auth.SecurityProtocol -import org.apache.kafka.common.serialization.StringSerializer import org.slf4j.LoggerFactory val objectMapper: ObjectMapper = jacksonObjectMapper() @@ -35,7 +33,8 @@ fun main() { } fun launchApplication(env: Map) { - RapidApplication.create(env).apply { + val factory = ConsumerProducerFactory(AivenConfig.default) + RapidApplication.create(env, factory).apply { val dataSourceBuilder = DataSourceBuilder() register(object : RapidsConnection.StatusListener { override fun onStartup(rapidsConnection: RapidsConnection) { @@ -43,23 +42,28 @@ fun launchApplication(env: Map) { } }) + val azureClient = createAzureTokenClientFromEnvironment(env) + val speedClient = SpeedClient( + httpClient = HttpClient.newHttpClient(), + objectMapper = objectMapper, + tokenProvider = azureClient + ) + val dokumentDao = DokumentDao(dataSourceBuilder::dataSource) - val aivenProducer = createAivenProducer(env) + val aivenProducer = factory.createProducer() val vedtakFattetMediator = VedtakFattetMediator( dokumentDao = dokumentDao, producer = aivenProducer ) - val utbetalingMediator = UtbetalingMediator( - producer = aivenProducer - ) + val utbetalingMediator = UtbetalingMediator(aivenProducer) NyttDokumentRiver(this, dokumentDao) - VedtakFattetRiver(this, vedtakFattetMediator) - VedtaksperiodeAnnullertRiver(this, aivenProducer) - UtbetalingUtbetaltRiver(this, utbetalingMediator) - UtbetalingUtenUtbetalingRiver(this, utbetalingMediator) - AnnulleringRiver(this, aivenProducer) + VedtakFattetRiver(this, vedtakFattetMediator, speedClient) + VedtaksperiodeAnnullertRiver(this, aivenProducer, speedClient) + UtbetalingUtbetaltRiver(this, utbetalingMediator, speedClient) + UtbetalingUtenUtbetalingRiver(this, utbetalingMediator, speedClient) + AnnulleringRiver(this, aivenProducer, speedClient) val sisPublisher = KafkaSisPublisher(aivenProducer) BehandlingOpprettetRiver(this, dokumentDao, sisPublisher) @@ -69,22 +73,3 @@ fun launchApplication(env: Map) { }.start() } - -private fun createAivenProducer(env: Map): KafkaProducer { - val properties = Properties().apply { - put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, env.getValue("KAFKA_BROKERS")) - put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, SecurityProtocol.SSL.name) - put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "") - put(SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG, "jks") - put(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG, "PKCS12") - put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, env.getValue("KAFKA_TRUSTSTORE_PATH")) - put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, env.getValue("KAFKA_CREDSTORE_PASSWORD")) - put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG, env.getValue("KAFKA_KEYSTORE_PATH")) - put(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG, env.getValue("KAFKA_CREDSTORE_PASSWORD")) - - put(ProducerConfig.ACKS_CONFIG, "1") - put(ProducerConfig.LINGER_MS_CONFIG, "0") - put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "1") - } - return KafkaProducer(properties, StringSerializer(), StringSerializer()) -} diff --git a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingMediator.kt b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingMediator.kt index d2f1a41..ff61622 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingMediator.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingMediator.kt @@ -1,8 +1,9 @@ package no.nav.helse.sporbar -import com.fasterxml.jackson.databind.JsonNode -import org.apache.kafka.clients.producer.ProducerRecord +import no.nav.helse.sporbar.dto.UtbetalingUtbetaltDto +import no.nav.helse.sporbar.dto.UtbetalingUtenUtbetalingDto import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerRecord import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -11,24 +12,16 @@ private val sikkerLogg: Logger = LoggerFactory.getLogger("tjenestekall") internal class UtbetalingMediator( private val producer: KafkaProducer ) { - internal fun utbetalingUtbetalt(utbetalingUtbetalt: UtbetalingUtbetalt) = - send(utbetalingUtbetalt, Meldingstype.Utbetaling) + internal fun utbetalingUtbetalt(utbetalingUtbetalt: UtbetalingUtbetaltDto) = + send(utbetalingUtbetalt.fødselsnummer, utbetalingUtbetalt, Meldingstype.Utbetaling) - internal fun utbetalingUtenUtbetaling(utbetalingUtbetalt: UtbetalingUtbetalt) = - send(utbetalingUtbetalt, Meldingstype.UtenUtbetaling) + internal fun utbetalingUtenUtbetaling(utbetalingUtbetalt: UtbetalingUtenUtbetalingDto) = + send(utbetalingUtbetalt.fødselsnummer, utbetalingUtbetalt, Meldingstype.UtenUtbetaling) - private fun send(utbetalingUtbetalt: UtbetalingUtbetalt, meldingstype: Meldingstype) { - val utbetalingJson = objectMapper.valueToTree(utbetalingUtbetalt) - producer.send( - ProducerRecord( - "tbd.utbetaling", - null, - utbetalingUtbetalt.fødselsnummer, - utbetalingJson.toString(), - listOf(meldingstype.header()) - ) - ) - sikkerLogg.info("Publiserer ${utbetalingUtbetalt.event}: {}", utbetalingJson) + private fun send(key: String, utbetalingUtbetalt: T, meldingstype: Meldingstype) { + val utbetalingJson = objectMapper.writeValueAsString(utbetalingUtbetalt) + producer.send(ProducerRecord("tbd.utbetaling", null, key, utbetalingJson, listOf(meldingstype.header()))) + sikkerLogg.info("Publiserer ${meldingstype}: {}", utbetalingJson) } } diff --git a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtbetaltRiver.kt b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtbetaltRiver.kt index f588248..04ff618 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtbetaltRiver.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtbetaltRiver.kt @@ -6,24 +6,30 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.River import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.isMissingOrNull +import com.github.navikt.tbd_libs.rapids_and_rivers.withMDC import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageProblems import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection -import no.nav.helse.sporbar.UtbetalingUtbetalt.OppdragDto.Companion.parseOppdrag -import no.nav.helse.sporbar.UtbetalingUtbetalt.OppdragDto.UtbetalingslinjeDto.Companion.parseLinje +import com.github.navikt.tbd_libs.result_object.getOrThrow +import com.github.navikt.tbd_libs.retry.retryBlocking +import com.github.navikt.tbd_libs.speed.SpeedClient import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.time.LocalDate import java.util.UUID +import no.nav.helse.sporbar.dto.BegrunnelseDto +import no.nav.helse.sporbar.dto.OppdragDto.Companion.parseOppdrag +import no.nav.helse.sporbar.dto.UtbetalingUtbetaltDto +import no.nav.helse.sporbar.dto.UtbetalingdagDto private val log: Logger = LoggerFactory.getLogger("sporbar") private val sikkerLog = LoggerFactory.getLogger("tjenestekall") -private val NULLE_UT_TOMME_OPPDRAG = System.getenv("NULLE_UT_TOMME_OPPDRAG")?.toBoolean() ?: false +val NULLE_UT_TOMME_OPPDRAG = System.getenv("NULLE_UT_TOMME_OPPDRAG")?.toBoolean() ?: false internal class UtbetalingUtbetaltRiver( rapidsConnection: RapidsConnection, - private val utbetalingMediator: UtbetalingMediator + private val utbetalingMediator: UtbetalingMediator, + private val speedClient: SpeedClient ) : River.PacketListener { init { @@ -31,7 +37,6 @@ internal class UtbetalingUtbetaltRiver( validate { it.demandValue("@event_name", "utbetaling_utbetalt") it.requireKey( - "aktørId", "fødselsnummer", "@id", "organisasjonsnummer", @@ -79,8 +84,16 @@ internal class UtbetalingUtbetaltRiver( } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val fødselsnummer = packet["fødselsnummer"].asText() - val aktørId = packet["aktørId"].asText() + val callId = packet["@id"].asText() + withMDC("callId" to callId) { + håndterUtbetalingUtbetalt(packet, callId) + } + } + + private fun håndterUtbetalingUtbetalt(packet: JsonMessage, callId: String) { + val ident = packet["fødselsnummer"].asText() + val identer = retryBlocking { speedClient.hentFødselsnummerOgAktørId(ident, callId).getOrThrow() } + val organisasjonsnummer = packet["organisasjonsnummer"].asText() val fom = packet["fom"].asLocalDate() val tom = packet["tom"].asLocalDate() @@ -93,7 +106,7 @@ internal class UtbetalingUtbetaltRiver( val automatiskBehandling = packet["automatiskBehandling"].asBoolean() val type = packet["type"].asText() val utbetalingsdager = packet["utbetalingsdager"].toList().map { dag -> - UtbetalingUtbetalt.UtbetalingdagDto( + UtbetalingdagDto( dato = dag["dato"].asLocalDate(), type = dag["type"].dagtype, begrunnelser = dag.path("begrunnelser").takeUnless(JsonNode::isMissingOrNull) @@ -104,14 +117,12 @@ internal class UtbetalingUtbetaltRiver( val arbeidsgiverOppdrag = parseOppdrag(packet["arbeidsgiverOppdrag"]) val personOppdrag = parseOppdrag(packet["personOppdrag"]) - utbetalingMediator.utbetalingUtbetalt( - UtbetalingUtbetalt( - event = "utbetaling_utbetalt", + UtbetalingUtbetaltDto( utbetalingId = utbetalingId, korrelasjonsId = korrelasjonsId, - fødselsnummer = fødselsnummer, - aktørId = aktørId, + fødselsnummer = identer.fødselsnummer, + aktørId = identer.aktørId, organisasjonsnummer = organisasjonsnummer, fom = fom, tom = tom, @@ -132,124 +143,27 @@ internal class UtbetalingUtbetaltRiver( } } -data class UtbetalingUtbetalt( - val event: String, - val utbetalingId: UUID, - val korrelasjonsId: UUID, - val fødselsnummer: String, - val aktørId: String, - val organisasjonsnummer: String, - val fom: LocalDate, - val tom: LocalDate, - val forbrukteSykedager: Int, - val gjenståendeSykedager: Int, - val stønadsdager: Int, - val automatiskBehandling: Boolean, - val arbeidsgiverOppdrag: OppdragDto?, - val personOppdrag: OppdragDto?, - val type: String, - val utbetalingsdager: List, - val antallVedtak: Int?, - val foreløpigBeregnetSluttPåSykepenger: LocalDate -) { - enum class Begrunnelse { - AndreYtelserAap, - AndreYtelserDagpenger, - AndreYtelserForeldrepenger, - AndreYtelserOmsorgspenger, - AndreYtelserOpplaringspenger, - AndreYtelserPleiepenger, - AndreYtelserSvangerskapspenger, - SykepengedagerOppbrukt, - SykepengedagerOppbruktOver67, - MinimumInntekt, - EgenmeldingUtenforArbeidsgiverperiode, - MinimumSykdomsgrad, - ManglerOpptjening, - ManglerMedlemskap, - EtterDødsdato, - Over70, - MinimumInntektOver67, - NyVilkårsprøvingNødvendig, - UKJENT - } - - data class OppdragDto( - val mottaker: String, - val fagområde: String, - val fagsystemId: String, - val nettoBeløp: Int, - val stønadsdager: Int, - val fom: LocalDate, - val tom: LocalDate, - val utbetalingslinjer: List - ) { - companion object { - fun parseOppdrag(oppdrag: JsonNode) = - OppdragDto( - mottaker = oppdrag["mottaker"].asText(), - fagområde = oppdrag["fagområde"].asText(), - fagsystemId = oppdrag["fagsystemId"].asText(), - nettoBeløp = oppdrag["nettoBeløp"].asInt(), - stønadsdager = oppdrag["stønadsdager"].asInt(), - fom = oppdrag["fom"].asLocalDate(), - tom = oppdrag["tom"].asLocalDate(), - utbetalingslinjer = oppdrag["linjer"].map { linje -> parseLinje(linje) } - ).takeUnless { NULLE_UT_TOMME_OPPDRAG && it.utbetalingslinjer.isEmpty() } - } - - data class UtbetalingslinjeDto( - val fom: LocalDate, - val tom: LocalDate, - val dagsats: Int, - val totalbeløp: Int, - val grad: Double, - val stønadsdager: Int - ) { - companion object { - fun parseLinje(linje: JsonNode) = - UtbetalingslinjeDto( - fom = linje["fom"].asLocalDate(), - tom = linje["tom"].asLocalDate(), - dagsats = linje["sats"].asInt(), - totalbeløp = linje["totalbeløp"].asInt(), - grad = linje["grad"].asDouble(), - stønadsdager = linje["stønadsdager"].asInt() - ) - } - } - } - data class UtbetalingdagDto( - val dato: LocalDate, - val type: String, - val begrunnelser: List - ) -} - -internal fun mapBegrunnelser(begrunnelser: List): List = begrunnelser.map { +internal fun mapBegrunnelser(begrunnelser: List): List = begrunnelser.map { when (it.asText()) { - "SykepengedagerOppbrukt" -> UtbetalingUtbetalt.Begrunnelse.SykepengedagerOppbrukt - "SykepengedagerOppbruktOver67" -> UtbetalingUtbetalt.Begrunnelse.SykepengedagerOppbruktOver67 - "MinimumInntekt" -> UtbetalingUtbetalt.Begrunnelse.MinimumInntekt - "MinimumInntektOver67" -> UtbetalingUtbetalt.Begrunnelse.MinimumInntektOver67 - "EgenmeldingUtenforArbeidsgiverperiode" -> UtbetalingUtbetalt.Begrunnelse.EgenmeldingUtenforArbeidsgiverperiode - "AndreYtelserAap" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserAap - "AndreYtelserDagpenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserDagpenger - "AndreYtelserForeldrepenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserForeldrepenger - "AndreYtelserOmsorgspenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserOmsorgspenger - "AndreYtelserOpplaringspenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserOpplaringspenger - "AndreYtelserPleiepenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserPleiepenger - "AndreYtelserSvangerskapspenger" -> UtbetalingUtbetalt.Begrunnelse.AndreYtelserSvangerskapspenger - "MinimumSykdomsgrad" -> UtbetalingUtbetalt.Begrunnelse.MinimumSykdomsgrad - "ManglerOpptjening" -> UtbetalingUtbetalt.Begrunnelse.ManglerOpptjening - "ManglerMedlemskap" -> UtbetalingUtbetalt.Begrunnelse.ManglerMedlemskap - "EtterDødsdato" -> UtbetalingUtbetalt.Begrunnelse.EtterDødsdato - "Over70" -> UtbetalingUtbetalt.Begrunnelse.Over70 - "NyVilkårsprøvingNødvendig" -> UtbetalingUtbetalt.Begrunnelse.NyVilkårsprøvingNødvendig - else -> { - log.error("Ukjent begrunnelse $it") - UtbetalingUtbetalt.Begrunnelse.UKJENT - } + "SykepengedagerOppbrukt" -> BegrunnelseDto.SykepengedagerOppbrukt + "SykepengedagerOppbruktOver67" -> BegrunnelseDto.SykepengedagerOppbruktOver67 + "MinimumInntekt" -> BegrunnelseDto.MinimumInntekt + "MinimumInntektOver67" -> BegrunnelseDto.MinimumInntektOver67 + "EgenmeldingUtenforArbeidsgiverperiode" -> BegrunnelseDto.EgenmeldingUtenforArbeidsgiverperiode + "AndreYtelserAap" -> BegrunnelseDto.AndreYtelserAap + "AndreYtelserDagpenger" -> BegrunnelseDto.AndreYtelserDagpenger + "AndreYtelserForeldrepenger" -> BegrunnelseDto.AndreYtelserForeldrepenger + "AndreYtelserOmsorgspenger" -> BegrunnelseDto.AndreYtelserOmsorgspenger + "AndreYtelserOpplaringspenger" -> BegrunnelseDto.AndreYtelserOpplaringspenger + "AndreYtelserPleiepenger" -> BegrunnelseDto.AndreYtelserPleiepenger + "AndreYtelserSvangerskapspenger" -> BegrunnelseDto.AndreYtelserSvangerskapspenger + "MinimumSykdomsgrad" -> BegrunnelseDto.MinimumSykdomsgrad + "ManglerOpptjening" -> BegrunnelseDto.ManglerOpptjening + "ManglerMedlemskap" -> BegrunnelseDto.ManglerMedlemskap + "EtterDødsdato" -> BegrunnelseDto.EtterDødsdato + "Over70" -> BegrunnelseDto.Over70 + "NyVilkårsprøvingNødvendig" -> BegrunnelseDto.NyVilkårsprøvingNødvendig + else -> error("Ukjent begrunnelse $it") } } diff --git a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtenUtbetalingRiver.kt b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtenUtbetalingRiver.kt index 342f12f..494f675 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtenUtbetalingRiver.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/UtbetalingUtenUtbetalingRiver.kt @@ -6,20 +6,27 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.River import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.isMissingOrNull +import com.github.navikt.tbd_libs.rapids_and_rivers.withMDC import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageProblems import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection -import no.nav.helse.sporbar.UtbetalingUtbetalt.OppdragDto.Companion.parseOppdrag +import com.github.navikt.tbd_libs.result_object.getOrThrow +import com.github.navikt.tbd_libs.retry.retryBlocking +import com.github.navikt.tbd_libs.speed.SpeedClient import org.slf4j.Logger import org.slf4j.LoggerFactory import java.util.UUID +import no.nav.helse.sporbar.dto.OppdragDto.Companion.parseOppdrag +import no.nav.helse.sporbar.dto.UtbetalingUtenUtbetalingDto +import no.nav.helse.sporbar.dto.UtbetalingdagDto private val log: Logger = LoggerFactory.getLogger("sporbar") private val sikkerLog = LoggerFactory.getLogger("tjenestekall") internal class UtbetalingUtenUtbetalingRiver( rapidsConnection: RapidsConnection, - private val utbetalingMediator: UtbetalingMediator + private val utbetalingMediator: UtbetalingMediator, + private val speedClient: SpeedClient ) : River.PacketListener { init { @@ -27,7 +34,6 @@ internal class UtbetalingUtenUtbetalingRiver( validate { it.demandValue("@event_name", "utbetaling_uten_utbetaling") it.requireKey( - "aktørId", "fødselsnummer", "@id", "organisasjonsnummer", @@ -75,8 +81,16 @@ internal class UtbetalingUtenUtbetalingRiver( } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val fødselsnummer = packet["fødselsnummer"].asText() - val aktørId = packet["aktørId"].asText() + val callId = packet["@id"].asText() + withMDC("callId" to callId) { + håndterUtbetalingUtenUtbetaling(packet, callId) + } + } + + private fun håndterUtbetalingUtenUtbetaling(packet: JsonMessage, callId: String) { + val ident = packet["fødselsnummer"].asText() + val identer = retryBlocking { speedClient.hentFødselsnummerOgAktørId(ident, callId).getOrThrow() } + val organisasjonsnummer = packet["organisasjonsnummer"].asText() val fom = packet["fom"].asLocalDate() val tom = packet["tom"].asLocalDate() @@ -88,8 +102,8 @@ internal class UtbetalingUtenUtbetalingRiver( val stønadsdager = packet["stønadsdager"].asInt() val type = packet["type"].asText() val automatiskBehandling = packet["automatiskBehandling"].asBoolean() - val utbetalingsdager = packet["utbetalingsdager"].toList().map{ dag -> - UtbetalingUtbetalt.UtbetalingdagDto( + val utbetalingsdager = packet["utbetalingsdager"].toList().map { dag -> + UtbetalingdagDto( dato = dag["dato"].asLocalDate(), type = dag["type"].dagtype, begrunnelser = dag.path("begrunnelser").takeUnless(JsonNode::isMissingOrNull) @@ -101,12 +115,11 @@ internal class UtbetalingUtenUtbetalingRiver( val personOppdrag = parseOppdrag(packet["personOppdrag"]) utbetalingMediator.utbetalingUtenUtbetaling( - UtbetalingUtbetalt( - event = "utbetaling_uten_utbetaling", + UtbetalingUtenUtbetalingDto( utbetalingId = utbetalingId, korrelasjonsId = korrelasjonsId, - fødselsnummer = fødselsnummer, - aktørId = aktørId, + fødselsnummer = identer.fødselsnummer, + aktørId = identer.aktørId, organisasjonsnummer = organisasjonsnummer, fom = fom, tom = tom, diff --git a/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetMediator.kt b/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetMediator.kt index c4cc588..7c0b5db 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetMediator.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetMediator.kt @@ -1,9 +1,12 @@ package no.nav.helse.sporbar -import com.fasterxml.jackson.databind.node.ObjectNode -import java.time.LocalDate -import java.time.LocalDateTime -import java.util.UUID +import no.nav.helse.sporbar.dto.BegrunnelseForEksternDto +import no.nav.helse.sporbar.dto.DokumentForEkstern +import no.nav.helse.sporbar.dto.FastsattEtterHovedregelForEksternDto +import no.nav.helse.sporbar.dto.FastsattEtterSkjønnForEksternDto +import no.nav.helse.sporbar.dto.FastsattIInfotrygdForEksternDto +import no.nav.helse.sporbar.dto.PeriodeForEksternDto +import no.nav.helse.sporbar.dto.VedtakFattetForEksternDto import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import org.slf4j.Logger @@ -17,18 +20,10 @@ internal class VedtakFattetMediator( private val producer: KafkaProducer ) { internal fun vedtakFattet(vedtakFattet: VedtakFattet) { - val dokumenter: List = dokumentDao.finn(vedtakFattet.hendelseIder) - val meldingForEkstern = objectMapper.valueToTree(oversett(vedtakFattet, dokumenter)) - producer.send( - ProducerRecord( - "tbd.vedtak", - null, - vedtakFattet.fødselsnummer, - meldingForEkstern.toString(), - listOf(Meldingstype.VedtakFattet.header()) - ) - ) + val eksternDto = oversett(vedtakFattet, dokumenter) + val meldingForEkstern = objectMapper.writeValueAsString(eksternDto) + producer.send(ProducerRecord("tbd.vedtak", null, vedtakFattet.fødselsnummer, meldingForEkstern, listOf(Meldingstype.VedtakFattet.header()))) sikkerLogg.info("Publiserer vedtakFattet {}", meldingForEkstern) log.info("Publiserte vedtakFattet for {}", dokumenter.map { it.dokumentId }) } @@ -46,7 +41,13 @@ internal class VedtakFattetMediator( grunnlagForSykepengegrunnlag = vedtakFattet.grunnlagForSykepengegrunnlag, grunnlagForSykepengegrunnlagPerArbeidsgiver = vedtakFattet.grunnlagForSykepengegrunnlagPerArbeidsgiver, begrensning = vedtakFattet.begrensning, - dokumenter = dokumenter, + dokumenter = dokumenter.map { + DokumentForEkstern(it.dokumentId, when (it.type) { + Dokument.Type.Sykmelding -> DokumentForEkstern.Type.Sykmelding + Dokument.Type.Søknad -> DokumentForEkstern.Type.Søknad + Dokument.Type.Inntektsmelding -> DokumentForEkstern.Type.Inntektsmelding + }) + }, utbetalingId = vedtakFattet.utbetalingId, vedtakFattetTidspunkt = vedtakFattet.vedtakFattetTidspunkt, sykepengegrunnlagsfakta = vedtakFattet.sykepengegrunnlagsfakta?.let { oversett(it) }, @@ -59,8 +60,7 @@ internal class VedtakFattetMediator( } ) }, - tags = vedtakFattet.tags, - versjon = "1.2.0" + tags = vedtakFattet.tags ) } @@ -91,69 +91,4 @@ internal class VedtakFattetMediator( } } -data class BegrunnelseForEksternDto( - val type: String, - val begrunnelse: String, - val perioder: List -) - -data class PeriodeForEksternDto( - val fom: LocalDate, - val tom: LocalDate -) - -data class VedtakFattetForEksternDto( - val fødselsnummer: String, - val aktørId: String, - val organisasjonsnummer: String, - val fom: LocalDate, - val tom: LocalDate, - val skjæringstidspunkt: LocalDate, - val dokumenter: List, - val inntekt: Double, - val sykepengegrunnlag: Double, - val grunnlagForSykepengegrunnlag: Double, - val grunnlagForSykepengegrunnlagPerArbeidsgiver: Map, - val begrensning: String, - val utbetalingId: UUID?, - val vedtakFattetTidspunkt: LocalDateTime, - val sykepengegrunnlagsfakta: SykepengegrunnlagsfaktaForEksternDto?, - val begrunnelser: List, - val versjon: String, - val tags: Set -) - -sealed class SykepengegrunnlagsfaktaForEksternDto - -data class FastsattEtterHovedregelForEksternDto( - val fastsatt: String, - val omregnetÅrsinntekt: Double, - val innrapportertÅrsinntekt: Double, - val avviksprosent: Double, - val `6G`: Double, - val tags: Set, - val arbeidsgivere: List -): SykepengegrunnlagsfaktaForEksternDto() { - data class Arbeidsgiver(val arbeidsgiver: String, val omregnetÅrsinntekt: Double) -} - -data class FastsattEtterSkjønnForEksternDto( - val fastsatt: String, - val omregnetÅrsinntekt: Double, - val innrapportertÅrsinntekt: Double, - val skjønnsfastsatt: Double, - val avviksprosent: Double, - val `6G`: Double, - val tags: Set, - val arbeidsgivere: List -): SykepengegrunnlagsfaktaForEksternDto() { - data class Arbeidsgiver(val arbeidsgiver: String, val omregnetÅrsinntekt: Double, val skjønnsfastsatt: Double) -} - -data class FastsattIInfotrygdForEksternDto( - val fastsatt: String, - val omregnetÅrsinntekt: Double, -) : SykepengegrunnlagsfaktaForEksternDto() - - diff --git a/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetRiver.kt b/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetRiver.kt index 0abae52..e273a2b 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetRiver.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/VedtakFattetRiver.kt @@ -7,9 +7,13 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.River import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.isMissingOrNull +import com.github.navikt.tbd_libs.rapids_and_rivers.withMDC import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageProblems import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection +import com.github.navikt.tbd_libs.result_object.getOrThrow +import com.github.navikt.tbd_libs.retry.retryBlocking +import com.github.navikt.tbd_libs.speed.SpeedClient import java.time.LocalDate import java.time.LocalDateTime import java.util.UUID @@ -22,7 +26,8 @@ private val sikkerLog = LoggerFactory.getLogger("tjenestekall") internal class VedtakFattetRiver( rapidsConnection: RapidsConnection, - private val vedtakFattetMediator: VedtakFattetMediator + private val vedtakFattetMediator: VedtakFattetMediator, + private val speedClient: SpeedClient ) : River.PacketListener { init { @@ -30,7 +35,6 @@ internal class VedtakFattetRiver( validate { it.demandValue("@event_name", "vedtak_fattet") it.requireKey( - "aktørId", "fødselsnummer", "@id", "vedtaksperiodeId", @@ -61,8 +65,16 @@ internal class VedtakFattetRiver( } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val fødselsnummer = packet["fødselsnummer"].asText() - val aktørId = packet["aktørId"].asText() + val callId = packet["@id"].asText() + withMDC("callId" to callId) { + håndterVedtakFattet(packet, callId) + } + } + + private fun håndterVedtakFattet(packet: JsonMessage, callId: String) { + val ident = packet["fødselsnummer"].asText() + val identer = retryBlocking { speedClient.hentFødselsnummerOgAktørId(ident, callId).getOrThrow() } + val organisasjonsnummer = packet["organisasjonsnummer"].asText() val fom = packet["fom"].asLocalDate() val tom = packet["tom"].asLocalDate() @@ -94,8 +106,8 @@ internal class VedtakFattetRiver( vedtakFattetMediator.vedtakFattet( VedtakFattet( - fødselsnummer = fødselsnummer, - aktørId = aktørId, + fødselsnummer = identer.fødselsnummer, + aktørId = identer.aktørId, organisasjonsnummer = organisasjonsnummer, fom = fom, tom = tom, diff --git a/src/main/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiver.kt b/src/main/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiver.kt index ac11d79..ab00143 100644 --- a/src/main/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiver.kt +++ b/src/main/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiver.kt @@ -4,11 +4,15 @@ import com.fasterxml.jackson.databind.JsonNode import com.github.navikt.tbd_libs.rapids_and_rivers.JsonMessage import com.github.navikt.tbd_libs.rapids_and_rivers.River import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate +import com.github.navikt.tbd_libs.rapids_and_rivers.withMDC import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageContext import com.github.navikt.tbd_libs.rapids_and_rivers_api.MessageProblems import com.github.navikt.tbd_libs.rapids_and_rivers_api.RapidsConnection -import java.time.LocalDate +import com.github.navikt.tbd_libs.result_object.getOrThrow +import com.github.navikt.tbd_libs.retry.retryBlocking +import com.github.navikt.tbd_libs.speed.SpeedClient import java.util.UUID +import no.nav.helse.sporbar.dto.VedtakAnnullertDto import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import org.slf4j.Logger @@ -19,7 +23,8 @@ private val sikkerLog = LoggerFactory.getLogger("tjenestekall") internal class VedtaksperiodeAnnullertRiver( rapidsConnection: RapidsConnection, - private val aivenProducer: KafkaProducer + private val aivenProducer: KafkaProducer, + private val speedClient: SpeedClient ) : River.PacketListener { init { @@ -27,7 +32,6 @@ internal class VedtaksperiodeAnnullertRiver( validate { it.demandValue("@event_name", "vedtaksperiode_annullert") it.requireKey( - "aktørId", "fødselsnummer", "@id", "organisasjonsnummer", @@ -45,38 +49,27 @@ internal class VedtaksperiodeAnnullertRiver( } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val fødselsnummer = packet["fødselsnummer"].asText() + val callId = packet["@id"].asText() + withMDC("callId" to callId) { + håndterAnnullering(packet, callId) + } + } + private fun håndterAnnullering(packet: JsonMessage, callId: String) { + val ident = packet["fødselsnummer"].asText() + val identer = retryBlocking { speedClient.hentFødselsnummerOgAktørId(ident, callId).getOrThrow() } + val vedtakAnnullertDto = VedtakAnnullertDto( - fødselsnummer = fødselsnummer, - aktørId = packet["aktørId"].asText(), + fødselsnummer = identer.fødselsnummer, + aktørId = identer.aktørId, organisasjonsnummer = packet["organisasjonsnummer"].asText(), vedtaksperiodeId = UUID.fromString(packet["vedtaksperiodeId"].asText()), fom = packet["fom"].asLocalDate(), tom = packet["tom"].asLocalDate() ) - val vedtakAnnullertJson = objectMapper.valueToTree(vedtakAnnullertDto) - aivenProducer.send( - ProducerRecord( - "tbd.vedtak", - null, - fødselsnummer, - vedtakAnnullertJson.toString(), - listOf(Meldingstype.VedtakAnnullert.header()) - ) - ) + val vedtakAnnullertJson = objectMapper.writeValueAsString(vedtakAnnullertDto) + aivenProducer.send(ProducerRecord("tbd.vedtak", null, identer.fødselsnummer, vedtakAnnullertJson, listOf(Meldingstype.VedtakAnnullert.header()))) - log.info("Sender vedtakAnnullert: ${packet["@id"].asText()}") + log.info("Sender vedtakAnnullert: $callId") sikkerLog.info("Sender vedtakAnnullert: $vedtakAnnullertJson") } - - data class VedtakAnnullertDto( - val fødselsnummer: String, - val aktørId: String, - val organisasjonsnummer: String, - val vedtaksperiodeId: UUID, - val fom: LocalDate, - val tom: LocalDate, - val event: String = "vedtak_annullert", - val versjon: String = "1.0.0" - ) } \ No newline at end of file diff --git a/src/main/kotlin/no/nav/helse/sporbar/dto/AnnulleringDto.kt b/src/main/kotlin/no/nav/helse/sporbar/dto/AnnulleringDto.kt new file mode 100644 index 0000000..8ea636f --- /dev/null +++ b/src/main/kotlin/no/nav/helse/sporbar/dto/AnnulleringDto.kt @@ -0,0 +1,20 @@ +package no.nav.helse.sporbar.dto + +import java.time.LocalDate +import java.time.LocalDateTime +import java.util.UUID + +data class AnnulleringDto( + val utbetalingId: UUID, + val korrelasjonsId: UUID, + val organisasjonsnummer: String, + val tidsstempel: LocalDateTime, + val fødselsnummer: String, + val fom: LocalDate, + val tom: LocalDate, + val arbeidsgiverFagsystemId: String?, + val personFagsystemId: String?) { + val event = "utbetaling_annullert" + @Deprecated("trengs så lenge vi produserer til on-prem") + val orgnummer: String = organisasjonsnummer +} \ No newline at end of file diff --git a/src/main/kotlin/no/nav/helse/sporbar/dto/UtbetalingUtbetaltDto.kt b/src/main/kotlin/no/nav/helse/sporbar/dto/UtbetalingUtbetaltDto.kt new file mode 100644 index 0000000..d3e4acc --- /dev/null +++ b/src/main/kotlin/no/nav/helse/sporbar/dto/UtbetalingUtbetaltDto.kt @@ -0,0 +1,126 @@ +package no.nav.helse.sporbar.dto + +import com.fasterxml.jackson.databind.JsonNode +import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate +import java.time.LocalDate +import java.util.UUID +import no.nav.helse.sporbar.NULLE_UT_TOMME_OPPDRAG +import no.nav.helse.sporbar.dto.OppdragDto.UtbetalingslinjeDto.Companion.parseLinje +import kotlin.collections.map + +data class UtbetalingUtbetaltDto( + val utbetalingId: UUID, + val korrelasjonsId: UUID, + val fødselsnummer: String, + val aktørId: String, + val organisasjonsnummer: String, + val fom: LocalDate, + val tom: LocalDate, + val forbrukteSykedager: Int, + val gjenståendeSykedager: Int, + val stønadsdager: Int, + val automatiskBehandling: Boolean, + val arbeidsgiverOppdrag: OppdragDto?, + val personOppdrag: OppdragDto?, + val type: String, + val utbetalingsdager: List, + val antallVedtak: Int?, + val foreløpigBeregnetSluttPåSykepenger: LocalDate +) { + val event = "utbetaling_utbetalt" +} + +data class UtbetalingUtenUtbetalingDto( + val utbetalingId: UUID, + val korrelasjonsId: UUID, + val fødselsnummer: String, + val aktørId: String, + val organisasjonsnummer: String, + val fom: LocalDate, + val tom: LocalDate, + val forbrukteSykedager: Int, + val gjenståendeSykedager: Int, + val stønadsdager: Int, + val automatiskBehandling: Boolean, + val arbeidsgiverOppdrag: OppdragDto?, + val personOppdrag: OppdragDto?, + val type: String, + val utbetalingsdager: List, + val antallVedtak: Int?, + val foreløpigBeregnetSluttPåSykepenger: LocalDate +) { + val event = "utbetaling_uten_utbetaling" +} + +enum class BegrunnelseDto { + AndreYtelserAap, + AndreYtelserDagpenger, + AndreYtelserForeldrepenger, + AndreYtelserOmsorgspenger, + AndreYtelserOpplaringspenger, + AndreYtelserPleiepenger, + AndreYtelserSvangerskapspenger, + SykepengedagerOppbrukt, + SykepengedagerOppbruktOver67, + MinimumInntekt, + EgenmeldingUtenforArbeidsgiverperiode, + MinimumSykdomsgrad, + ManglerOpptjening, + ManglerMedlemskap, + EtterDødsdato, + Over70, + MinimumInntektOver67, + NyVilkårsprøvingNødvendig, + UKJENT +} + +data class OppdragDto( + val mottaker: String, + val fagområde: String, + val fagsystemId: String, + val nettoBeløp: Int, + val stønadsdager: Int, + val fom: LocalDate, + val tom: LocalDate, + val utbetalingslinjer: List +) { + companion object { + fun parseOppdrag(oppdrag: JsonNode) = + OppdragDto( + mottaker = oppdrag["mottaker"].asText(), + fagområde = oppdrag["fagområde"].asText(), + fagsystemId = oppdrag["fagsystemId"].asText(), + nettoBeløp = oppdrag["nettoBeløp"].asInt(), + stønadsdager = oppdrag["stønadsdager"].asInt(), + fom = oppdrag["fom"].asLocalDate(), + tom = oppdrag["tom"].asLocalDate(), + utbetalingslinjer = oppdrag["linjer"].map { linje -> parseLinje(linje) } + ).takeUnless { NULLE_UT_TOMME_OPPDRAG && it.utbetalingslinjer.isEmpty() } + } + + data class UtbetalingslinjeDto( + val fom: LocalDate, + val tom: LocalDate, + val dagsats: Int, + val totalbeløp: Int, + val grad: Double, + val stønadsdager: Int + ) { + companion object { + fun parseLinje(linje: JsonNode) = + UtbetalingslinjeDto( + fom = linje["fom"].asLocalDate(), + tom = linje["tom"].asLocalDate(), + dagsats = linje["sats"].asInt(), + totalbeløp = linje["totalbeløp"].asInt(), + grad = linje["grad"].asDouble(), + stønadsdager = linje["stønadsdager"].asInt() + ) + } + } +} +data class UtbetalingdagDto( + val dato: LocalDate, + val type: String, + val begrunnelser: List +) \ No newline at end of file diff --git a/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakAnnullertDto.kt b/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakAnnullertDto.kt new file mode 100644 index 0000000..f0f7072 --- /dev/null +++ b/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakAnnullertDto.kt @@ -0,0 +1,16 @@ +package no.nav.helse.sporbar.dto + +import java.time.LocalDate +import java.util.UUID + +data class VedtakAnnullertDto( + val fødselsnummer: String, + val aktørId: String, + val organisasjonsnummer: String, + val vedtaksperiodeId: UUID, + val fom: LocalDate, + val tom: LocalDate +) { + val event: String = "vedtak_annullert" + val versjon: String = "1.0.0" +} \ No newline at end of file diff --git a/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakFattetForEksternDto.kt b/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakFattetForEksternDto.kt new file mode 100644 index 0000000..3ccc078 --- /dev/null +++ b/src/main/kotlin/no/nav/helse/sporbar/dto/VedtakFattetForEksternDto.kt @@ -0,0 +1,78 @@ +package no.nav.helse.sporbar.dto + +import java.time.LocalDate +import java.time.LocalDateTime +import java.util.UUID + +data class VedtakFattetForEksternDto( + val fødselsnummer: String, + val aktørId: String, + val organisasjonsnummer: String, + val fom: LocalDate, + val tom: LocalDate, + val skjæringstidspunkt: LocalDate, + val dokumenter: List, + val inntekt: Double, + val sykepengegrunnlag: Double, + val grunnlagForSykepengegrunnlag: Double, + val grunnlagForSykepengegrunnlagPerArbeidsgiver: Map, + val begrensning: String, + val utbetalingId: UUID?, + val vedtakFattetTidspunkt: LocalDateTime, + val sykepengegrunnlagsfakta: SykepengegrunnlagsfaktaForEksternDto?, + val begrunnelser: List, + val tags: Set +) { + val versjon: String = "1.2.0" +} + +class DokumentForEkstern(val dokumentId: UUID, val type: Type) { + enum class Type { + Sykmelding, Søknad, Inntektsmelding + } +} + +data class BegrunnelseForEksternDto( + val type: String, + val begrunnelse: String, + val perioder: List +) + +data class PeriodeForEksternDto( + val fom: LocalDate, + val tom: LocalDate +) + +sealed class SykepengegrunnlagsfaktaForEksternDto + +data class FastsattEtterHovedregelForEksternDto( + val fastsatt: String, + val omregnetÅrsinntekt: Double, + val innrapportertÅrsinntekt: Double, + val avviksprosent: Double, + val `6G`: Double, + val tags: Set, + val arbeidsgivere: List +): SykepengegrunnlagsfaktaForEksternDto() { + data class Arbeidsgiver(val arbeidsgiver: String, val omregnetÅrsinntekt: Double) +} + +data class FastsattEtterSkjønnForEksternDto( + val fastsatt: String, + val omregnetÅrsinntekt: Double, + val innrapportertÅrsinntekt: Double, + val skjønnsfastsatt: Double, + val avviksprosent: Double, + val `6G`: Double, + val tags: Set, + val arbeidsgivere: List +): SykepengegrunnlagsfaktaForEksternDto() { + data class Arbeidsgiver(val arbeidsgiver: String, val omregnetÅrsinntekt: Double, val skjønnsfastsatt: Double) +} + +data class FastsattIInfotrygdForEksternDto( + val fastsatt: String, + val omregnetÅrsinntekt: Double, +) : SykepengegrunnlagsfaktaForEksternDto() + + diff --git a/src/test/kotlin/no/nav/helse/sporbar/AnnulleringRiverTest.kt b/src/test/kotlin/no/nav/helse/sporbar/AnnulleringRiverTest.kt index 3640609..26b4b49 100644 --- a/src/test/kotlin/no/nav/helse/sporbar/AnnulleringRiverTest.kt +++ b/src/test/kotlin/no/nav/helse/sporbar/AnnulleringRiverTest.kt @@ -4,7 +4,11 @@ import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.isMissingOrNull import com.github.navikt.tbd_libs.rapids_and_rivers.test_support.TestRapid +import com.github.navikt.tbd_libs.result_object.ok +import com.github.navikt.tbd_libs.speed.IdentResponse +import com.github.navikt.tbd_libs.speed.SpeedClient import io.mockk.CapturingSlot +import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.apache.kafka.clients.producer.KafkaProducer @@ -34,9 +38,16 @@ class AnnulleringRiverTest { private val testRapid = TestRapid() private val aivenProducerMock = mockk>(relaxed = true) - + private val speedClient = mockk { + every { hentFødselsnummerOgAktørId(any(), any()) } returns IdentResponse( + fødselsnummer = fødselsnummer, + aktørId = "aktørId", + npid = null, + kilde = IdentResponse.KildeResponse.PDL + ).ok() + } init { - AnnulleringRiver(testRapid, aivenProducerMock) + AnnulleringRiver(testRapid, aivenProducerMock, speedClient) } @Test @@ -121,7 +132,6 @@ class AnnulleringRiverTest { ) = """ { "fødselsnummer": "$fødselsnummer", - "aktørId": "1427484794278", "organisasjonsnummer": "$organisasjonsnummer", "tidspunkt": "$tidsstempel", "fom": "$fom", diff --git a/src/test/kotlin/no/nav/helse/sporbar/UtbetalingTest.kt b/src/test/kotlin/no/nav/helse/sporbar/UtbetalingTest.kt index 8f29e10..3f43ef2 100644 --- a/src/test/kotlin/no/nav/helse/sporbar/UtbetalingTest.kt +++ b/src/test/kotlin/no/nav/helse/sporbar/UtbetalingTest.kt @@ -2,7 +2,11 @@ package no.nav.helse.sporbar import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.test_support.TestRapid +import com.github.navikt.tbd_libs.result_object.ok +import com.github.navikt.tbd_libs.speed.IdentResponse +import com.github.navikt.tbd_libs.speed.SpeedClient import io.mockk.clearAllMocks +import io.mockk.every import io.mockk.mockk import io.mockk.verify import java.time.LocalDate @@ -12,6 +16,7 @@ import no.nav.helse.sporbar.JsonSchemaValidator.validertJson import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import org.intellij.lang.annotations.Language +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach @@ -55,16 +60,27 @@ internal class UtbetalingTest { private val utbetalingMediator = UtbetalingMediator( producer = producerMock ) + private val speedClient = mockk() init { NyttDokumentRiver(testRapid, dokumentDao) - VedtakFattetRiver(testRapid, vedtakFattetMediator) - UtbetalingUtbetaltRiver(testRapid, utbetalingMediator) - UtbetalingUtenUtbetalingRiver(testRapid, utbetalingMediator) + VedtakFattetRiver(testRapid, vedtakFattetMediator, speedClient) + UtbetalingUtbetaltRiver(testRapid, utbetalingMediator, speedClient) + UtbetalingUtenUtbetalingRiver(testRapid, utbetalingMediator, speedClient) } @BeforeEach fun setup() { + every { speedClient.hentFødselsnummerOgAktørId(any(), any()) } returns IdentResponse( + fødselsnummer = FØDSELSNUMMER, + aktørId = AKTØRID, + npid = null, + kilde = IdentResponse.KildeResponse.PDL + ).ok() + } + + @AfterEach + fun after() { testRapid.reset() clearAllMocks() } @@ -323,7 +339,6 @@ internal class UtbetalingTest { "@event_name": "vedtak_fattet", "@id": "1826ead5-4e9e-4670-892d-ea4ec2ffec04", "@opprettet": "$TIDSSTEMPEL", - "aktørId": "$AKTØRID", "fødselsnummer": "$FØDSELSNUMMER", "organisasjonsnummer": "$ORGNUMMER", "tags": [], @@ -441,7 +456,6 @@ internal class UtbetalingTest { ], "@id": "1826ead5-4e9e-4670-892d-ea4ec2ffec01", "@opprettet": "$TIDSSTEMPEL", - "aktørId": "$AKTØRID", "fødselsnummer": "$FØDSELSNUMMER", "organisasjonsnummer": "$ORGNUMMER" } @@ -563,7 +577,6 @@ internal class UtbetalingTest { } ], "@opprettet": "${LocalDateTime.now()}", - "aktørId": "123", "organisasjonsnummer": "123456789" } """ @@ -639,7 +652,6 @@ internal class UtbetalingTest { } ], "@opprettet": "${LocalDateTime.now()}", - "aktørId": "123", "organisasjonsnummer": "123456789" } """ @@ -704,7 +716,6 @@ internal class UtbetalingTest { } ], "@opprettet": "${LocalDateTime.now()}", - "aktørId": "123", "organisasjonsnummer": "123456789" } """ @@ -771,7 +782,6 @@ internal class UtbetalingTest { } ], "@opprettet": "${LocalDateTime.now()}", - "aktørId": "123", "organisasjonsnummer": "123456789" } """ @@ -845,7 +855,6 @@ internal class UtbetalingTest { "id": "75be4efa-fa13-44a9-afc2-6583dd87d626", "opprettet": "2020-06-12T09:20:31.985479" }, - "aktørId": "42", "fødselsnummer": "$FØDSELSNUMMER" } """ diff --git a/src/test/kotlin/no/nav/helse/sporbar/VedtakFattetRiverTest.kt b/src/test/kotlin/no/nav/helse/sporbar/VedtakFattetRiverTest.kt index edcc27a..f0f1b7f 100644 --- a/src/test/kotlin/no/nav/helse/sporbar/VedtakFattetRiverTest.kt +++ b/src/test/kotlin/no/nav/helse/sporbar/VedtakFattetRiverTest.kt @@ -3,7 +3,11 @@ package no.nav.helse.sporbar import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDateTime import com.github.navikt.tbd_libs.rapids_and_rivers.test_support.TestRapid +import com.github.navikt.tbd_libs.result_object.ok +import com.github.navikt.tbd_libs.speed.IdentResponse +import com.github.navikt.tbd_libs.speed.SpeedClient import io.mockk.clearAllMocks +import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.apache.kafka.clients.producer.KafkaProducer @@ -18,6 +22,7 @@ import java.time.LocalDate import java.time.LocalDateTime import java.util.* import no.nav.helse.sporbar.JsonSchemaValidator.validertJson +import org.junit.jupiter.api.AfterEach @TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class VedtakFattetRiverTest { @@ -49,15 +54,26 @@ internal class VedtakFattetRiverTest { private val utbetalingMediator = UtbetalingMediator( producer = producerMock ) + private val speedClient = mockk() init { NyttDokumentRiver(testRapid, dokumentDao) - VedtakFattetRiver(testRapid, vedtakFattetMediator) - UtbetalingUtbetaltRiver(testRapid, utbetalingMediator) + VedtakFattetRiver(testRapid, vedtakFattetMediator, speedClient) + UtbetalingUtbetaltRiver(testRapid, utbetalingMediator, speedClient) } @BeforeEach fun setup() { + every { speedClient.hentFødselsnummerOgAktørId(any(), any()) } returns IdentResponse( + fødselsnummer = FØDSELSNUMMER, + aktørId = AKTØRID, + npid = null, + kilde = IdentResponse.KildeResponse.PDL + ).ok() + } + + @AfterEach + fun after() { testRapid.reset() clearAllMocks() } @@ -304,7 +320,6 @@ internal class VedtakFattetRiverTest { "@event_name": "vedtak_fattet", "@id": "1826ead5-4e9e-4670-892d-ea4ec2ffec04", "@opprettet": "$TIDSSTEMPEL", - "aktørId": "$AKTØRID", "fødselsnummer": "$FØDSELSNUMMER", "organisasjonsnummer": "$ORGNUMMER", "vedtakFattetTidspunkt": "$VEDTAK_FATTET_TIDSPUNKT", @@ -342,7 +357,6 @@ internal class VedtakFattetRiverTest { "@event_name": "vedtak_fattet", "@id": "1826ead5-4e9e-4670-892d-ea4ec2ffec04", "@opprettet": "$TIDSSTEMPEL", - "aktørId": "$AKTØRID", "fødselsnummer": "$FØDSELSNUMMER", "organisasjonsnummer": "$ORGNUMMER", "vedtakFattetTidspunkt": "$VEDTAK_FATTET_TIDSPUNKT", @@ -437,7 +451,6 @@ internal class VedtakFattetRiverTest { "id": "75be4efa-fa13-44a9-afc2-6583dd87d626", "opprettet": "2020-06-12T09:20:31.985479" }, - "aktørId": "42", "fødselsnummer": "$FØDSELSNUMMER" } """ diff --git a/src/test/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiverTest.kt b/src/test/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiverTest.kt index ab6b899..d08ac49 100644 --- a/src/test/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiverTest.kt +++ b/src/test/kotlin/no/nav/helse/sporbar/VedtaksperiodeAnnullertRiverTest.kt @@ -2,7 +2,11 @@ package no.nav.helse.sporbar import com.github.navikt.tbd_libs.rapids_and_rivers.asLocalDate import com.github.navikt.tbd_libs.rapids_and_rivers.test_support.TestRapid +import com.github.navikt.tbd_libs.result_object.ok +import com.github.navikt.tbd_libs.speed.IdentResponse +import com.github.navikt.tbd_libs.speed.SpeedClient import io.mockk.CapturingSlot +import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.apache.kafka.clients.producer.KafkaProducer @@ -26,9 +30,17 @@ class VedtaksperiodeAnnullertRiverTest { private val testRapid = TestRapid() private val aivenProducerMock = mockk>(relaxed = true) + private val speedClient = mockk { + every { hentFødselsnummerOgAktørId(any(), any()) } returns IdentResponse( + fødselsnummer = fødselsnummer, + aktørId = aktørId, + npid = null, + kilde = IdentResponse.KildeResponse.PDL + ).ok() + } init { - VedtaksperiodeAnnullertRiver(testRapid, aivenProducerMock) + VedtaksperiodeAnnullertRiver(testRapid, aivenProducerMock, speedClient) } @Test @@ -53,7 +65,6 @@ class VedtaksperiodeAnnullertRiverTest { ) = """ { "fødselsnummer": "$fødselsnummer", - "aktørId": "1427484794278", "organisasjonsnummer": "$organisasjonsnummer", "vedtaksperiodeId": "${UUID.randomUUID()}", "fom": "$fom",