Skip to content

Commit

Permalink
Motta åpen IM og send til service som logger (#400)
Browse files Browse the repository at this point in the history
* Motta åpen IM og send til service som logger

* Revert publisering av data uten forespoerselId

* Liten forbedring på loggmelding

* Bruk melding beriket med Redis-data

* Spiss ansvaret til funksjon
  • Loading branch information
bjerga authored Jan 22, 2024
1 parent 9f86003 commit 44fd96a
Show file tree
Hide file tree
Showing 35 changed files with 924 additions and 82 deletions.
Empty file added aapenimservice/build.gradle.kts
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice

import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.JsonElement
import no.nav.helse.rapids_rivers.RapidsConnection
import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Avsender
import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding
import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Sykmeldt
import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding
import no.nav.helsearbeidsgiver.felles.BehovType
import no.nav.helsearbeidsgiver.felles.EventName
import no.nav.helsearbeidsgiver.felles.Key
import no.nav.helsearbeidsgiver.felles.PersonDato
import no.nav.helsearbeidsgiver.felles.json.les
import no.nav.helsearbeidsgiver.felles.json.lesOrNull
import no.nav.helsearbeidsgiver.felles.json.toJson
import no.nav.helsearbeidsgiver.felles.json.toMap
import no.nav.helsearbeidsgiver.felles.rapidsrivers.FailKanal
import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullDataKanal
import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullEventListener
import no.nav.helsearbeidsgiver.felles.rapidsrivers.composite.CompositeEventListener
import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail
import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore
import no.nav.helsearbeidsgiver.felles.utils.Log
import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer
import no.nav.helsearbeidsgiver.utils.json.toJson
import no.nav.helsearbeidsgiver.utils.json.toJsonStr
import no.nav.helsearbeidsgiver.utils.json.toPretty
import no.nav.helsearbeidsgiver.utils.log.MdcUtils
import no.nav.helsearbeidsgiver.utils.log.logger
import no.nav.helsearbeidsgiver.utils.log.sikkerLogger
import java.time.OffsetDateTime
import java.util.UUID

// TODO test
class AapenImService(
private val rapid: RapidsConnection,
override val redisStore: RedisStore
) : CompositeEventListener() {

private val logger = logger()
private val sikkerLogger = sikkerLogger()

override val event = EventName.AAPEN_IM_MOTTATT
override val startKeys = listOf(
Key.AAPEN_ID,
Key.SKJEMA_INNTEKTSMELDING,
Key.ARBEIDSGIVER_FNR
)
override val dataKeys = listOf(
Key.VIRKSOMHET,
Key.ARBEIDSTAKER_INFORMASJON,
Key.ARBEIDSGIVER_INFORMASJON,
Key.AAPEN_INNTEKTMELDING,
Key.ER_DUPLIKAT_IM
)

private val step1Data =
setOf(
Key.VIRKSOMHET,
Key.ARBEIDSTAKER_INFORMASJON,
Key.ARBEIDSGIVER_INFORMASJON
)

init {
StatefullEventListener(rapid, event, redisStore, startKeys, ::onPacket)
StatefullDataKanal(rapid, event, redisStore, dataKeys, ::onPacket)
FailKanal(rapid, event, ::onPacket)
}

override fun new(melding: Map<Key, JsonElement>) {
val transaksjonId = Key.UUID.les(UuidSerializer, melding)
val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding)
val skjema = Key.SKJEMA_INNTEKTSMELDING.les(SkjemaInntektsmelding.serializer(), melding)
val avsenderFnr = Key.ARBEIDSGIVER_FNR.les(String.serializer(), melding)

MdcUtils.withLogFields(
Log.klasse(this),
Log.event(event),
Log.transaksjonId(transaksjonId),
Log.aapenId(aapenId)
) {
rapid.publish(
Key.EVENT_NAME to event.toJson(),
Key.UUID to transaksjonId.toJson(),
Key.AAPEN_ID to aapenId.toJson(),
Key.BEHOV to BehovType.VIRKSOMHET.toJson(),
Key.ORGNRUNDERENHET to skjema.avsender.orgnr.toJson()
)

rapid.publish(
Key.EVENT_NAME to event.toJson(),
Key.UUID to transaksjonId.toJson(),
Key.AAPEN_ID to aapenId.toJson(),
Key.BEHOV to BehovType.FULLT_NAVN.toJson(),
Key.IDENTITETSNUMMER to skjema.sykmeldtFnr.toJson(),
Key.ARBEIDSGIVER_ID to avsenderFnr.toJson()
)
}
}

override fun inProgress(melding: Map<Key, JsonElement>) {
val transaksjonId = Key.UUID.les(UuidSerializer, melding)
val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding)

MdcUtils.withLogFields(
Log.klasse(this),
Log.event(event),
Log.transaksjonId(transaksjonId),
Log.aapenId(aapenId)
) {
if (step1Data.all { it in melding }) {
val skjema = Key.SKJEMA_INNTEKTSMELDING.les(SkjemaInntektsmelding.serializer(), melding)
val orgNavn = Key.VIRKSOMHET.les(String.serializer(), melding)
val sykmeldt = Key.ARBEIDSTAKER_INFORMASJON.les(PersonDato.serializer(), melding)
val avsender = Key.ARBEIDSGIVER_INFORMASJON.les(PersonDato.serializer(), melding)

val inntektsmelding = tilInntektsmelding(
aapenId = aapenId,
skjema = skjema,
orgNavn = orgNavn,
sykmeldt = sykmeldt,
avsender = avsender
)

logger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'")
sikkerLogger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'")
// rapid.publish(
// Key.EVENT_NAME to event.toJson(),
// Key.UUID to transaksjonId.toJson(),
// Key.AAPEN_ID to aapenId.toJson(),
// Key.BEHOV to BehovType.LAGRE_AAPEN_IM.toJson(),
// Key.AAPEN_INNTEKTMELDING to inntektsmelding.toJson(Inntektsmelding.serializer())
// )

// TODO Midlertidig sett svar til im-api
val clientId = redisStore.get(RedisKey.of(transaksjonId, event))!!.let(UUID::fromString)
redisStore.set(RedisKey.of(clientId), inntektsmelding.toJsonStr(Inntektsmelding.serializer()))
}
}
}

override fun finalize(melding: Map<Key, JsonElement>) {
val transaksjonId = Key.UUID.les(UuidSerializer, melding)
val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding)
val erDuplikat = Key.ER_DUPLIKAT_IM.les(Boolean.serializer(), melding)
val inntektsmeldingJson = Key.AAPEN_INNTEKTMELDING.les(JsonElement.serializer(), melding)

MdcUtils.withLogFields(
Log.klasse(this),
Log.event(event),
Log.transaksjonId(transaksjonId),
Log.aapenId(aapenId)
) {
val clientId = redisStore.get(RedisKey.of(transaksjonId, event))?.let(UUID::fromString)

if (clientId == null) {
sikkerLogger.error("Forsøkte å fullføre, men clientId mangler i Redis.")
} else {
redisStore.set(RedisKey.of(clientId), inntektsmeldingJson.toString())
}

if (!erDuplikat) {
rapid.publish(
Key.EVENT_NAME to EventName.AAPEN_IM_LAGRET.toJson(),
Key.UUID to transaksjonId.toJson(),
Key.AAPEN_ID to aapenId.toJson(),
Key.AAPEN_INNTEKTMELDING to inntektsmeldingJson
)
.also {
MdcUtils.withLogFields(
Log.event(EventName.AAPEN_IM_LAGRET)
) {
logger.info("Publiserte melding.")
sikkerLogger.info("Publiserte melding:\n${it.toPretty()}")
}
}
}
}
}

override fun onError(melding: Map<Key, JsonElement>, fail: Fail) {
MdcUtils.withLogFields(
Log.klasse(this),
Log.event(EventName.AAPEN_IM_MOTTATT),
Log.transaksjonId(fail.transaksjonId)
) {
val utloesendeBehov = Key.BEHOV.lesOrNull(BehovType.serializer(), fail.utloesendeMelding.toMap())
val datafeil = when (utloesendeBehov) {
BehovType.VIRKSOMHET -> {
listOf(
Key.VIRKSOMHET to "Ukjent virksomhet".toJson()
)
}
BehovType.FULLT_NAVN -> {
val sykmeldtFnr = Key.IDENTITETSNUMMER.les(String.serializer(), melding)
val avsenderFnr = Key.ARBEIDSGIVER_ID.les(String.serializer(), melding)
listOf(
Key.ARBEIDSTAKER_INFORMASJON to tomPerson(sykmeldtFnr).toJson(PersonDato.serializer()),
Key.ARBEIDSGIVER_INFORMASJON to tomPerson(avsenderFnr).toJson(PersonDato.serializer())
)
}
else -> {
emptyList()
}
}

if (datafeil.isNotEmpty()) {
datafeil.forEach {
redisStore.set(RedisKey.of(fail.transaksjonId, it.first), it.second.toString())
}

val meldingMedDefault = datafeil.toMap() + melding

return inProgress(meldingMedDefault)
}

val clientId = redisStore.get(RedisKey.of(fail.transaksjonId, event))
?.let(UUID::fromString)

if (clientId == null) {
val aapenId = Key.AAPEN_ID.lesOrNull(UuidSerializer, fail.utloesendeMelding.toMap())
sikkerLogger.error("Forsøkte å terminere, men clientId mangler i Redis. aapenId=$aapenId")
} else {
redisStore.set(RedisKey.of(clientId), fail.feilmelding)
}
}
}
}

private fun tilInntektsmelding(
aapenId: UUID,
skjema: SkjemaInntektsmelding,
orgNavn: String,
sykmeldt: PersonDato,
avsender: PersonDato
): Inntektsmelding =
Inntektsmelding(
id = aapenId,
sykmeldt = Sykmeldt(
fnr = sykmeldt.ident,
navn = sykmeldt.navn
),
avsender = Avsender(
orgnr = skjema.avsender.orgnr,
orgNavn = orgNavn,
fnr = avsender.ident,
navn = avsender.navn,
tlf = skjema.avsender.tlf
),
sykmeldingsperioder = skjema.sykmeldingsperioder,
agp = skjema.agp,
inntekt = skjema.inntekt,
refusjon = skjema.refusjon,
aarsakInnsending = skjema.aarsakInnsending,
mottatt = OffsetDateTime.now()
)

private fun tomPerson(fnr: String): PersonDato =
PersonDato(
navn = "",
fødselsdato = null,
ident = fnr
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice

import no.nav.helse.rapids_rivers.RapidApplication
import no.nav.helse.rapids_rivers.RapidsConnection
import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore
import no.nav.helsearbeidsgiver.utils.log.logger

private val logger = "im-aapenimservice".logger()

fun main() {
val redisStore = RedisStore(Env.redisUrl)

RapidApplication
.create(System.getenv())
.createAapenImService(redisStore)
.start()
}

fun RapidsConnection.createAapenImService(redisStore: RedisStore): RapidsConnection =
also {
logger.info("Starter ${AapenImService::class.simpleName}...")
AapenImService(this, redisStore)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice

import no.nav.helsearbeidsgiver.felles.fromEnv

object Env {
val redisUrl = "REDIS_URL".fromEnv()
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import no.nav.helsearbeidsgiver.utils.json.toJson
import no.nav.helsearbeidsgiver.utils.log.MdcUtils
import java.util.UUID

// TODO test
class TilgangLoeser(
rapidsConnection: RapidsConnection,
private val altinnClient: AltinnClient
Expand All @@ -40,8 +41,7 @@ class TilgangLoeser(
it.interestedIn(
Key.UUID,
Key.ORGNRUNDERENHET,
Key.FNR,
Key.FORESPOERSEL_ID
Key.FNR
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import no.nav.helse.rapids_rivers.RapidApplication
import no.nav.helse.rapids_rivers.RapidsConnection
import no.nav.helsearbeidsgiver.inntektsmelding.api.aapeninntektmelding.aapenInntektmeldingRoute
import no.nav.helsearbeidsgiver.inntektsmelding.api.aktiveorgnr.aktiveOrgnrRoute
import no.nav.helsearbeidsgiver.inntektsmelding.api.auth.Tilgangskontroll
import no.nav.helsearbeidsgiver.inntektsmelding.api.innsending.innsendingRoute
Expand All @@ -38,6 +39,7 @@ object Routes {
const val TRENGER = "/trenger"
const val INNTEKT = "/inntekt"
const val INNSENDING = "/inntektsmelding"
const val AAPEN_INNTEKTMELDING = "/aapen-inntektsmelding"
const val KVITTERING = "/kvittering"
const val AKTIVEORGNR = "/aktiveorgnr"
}
Expand Down Expand Up @@ -100,6 +102,7 @@ fun Application.apiModule(rapid: RapidsConnection) {
trengerRoute(rapid, tilgangskontroll, redisPoller)
inntektRoute(rapid, tilgangskontroll, redisPoller)
innsendingRoute(rapid, tilgangskontroll, redisPoller)
aapenInntektmeldingRoute(rapid, tilgangskontroll, redisPoller)
kvitteringRoute(rapid, tilgangskontroll, redisPoller)
aktiveOrgnrRoute(rapid, redisPoller)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class RedisPoller {
json.parseJson()
} catch (e: Exception) {
"JSON-parsing feilet.".let {
sikkerLogger.error("$it key=$key json=$json")
throw RedisPollerJsonParseException("$it Se sikker logg for mer info. key='$key'", e)
sikkerLogger.error("$it key=$key json=$json", e)
throw RedisPollerJsonParseException("$it key='$key'", e)
}
}
}
Expand Down
Loading

0 comments on commit 44fd96a

Please sign in to comment.