Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IS-1646: Consume huskelapp-status in personoversiktstatus #316

Merged
merged 4 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .nais/naiserator-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@ spec:
# Bruk samme dato i enhetens-oversikt-query og index
- name: ARENA_CUTOFF
value: "2023-03-10"
- name: IS_HUSKELAPP_CONSUMER_ENABLED
value: "true"
2 changes: 2 additions & 0 deletions .nais/naiserator-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ spec:
# Bruk samme dato i enhetens-oversikt-query og index
- name: ARENA_CUTOFF
value: "2023-03-10"
- name: IS_HUSKELAPP_CONSUMER_ENABLED
value: "false"
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ data class Environment(
port = getEnvVar("REDIS_PORT", "6379").toInt(),
secret = getEnvVar("REDIS_PASSWORD"),
),

val isHuskelappConsumerEnabled: Boolean = getEnvVar("IS_HUSKELAPP_CONSUMER_ENABLED").toBoolean()
)

fun getEnvVar(varName: String, defaultValue: String? = null) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const val queryGetPersonerWithOppgaveAndOldEnhet =
OR behandlerdialog_ubesvart_ubehandlet = 't'
OR behandlerdialog_avvist_ubehandlet = 't'
OR aktivitetskrav_vurder_stans_ubehandlet = 't'
OR huskelapp_active = 't'
)
AND (tildelt_enhet_updated_at IS NULL OR tildelt_enhet_updated_at <= NOW() - INTERVAL '24 HOURS')
ORDER BY tildelt_enhet_updated_at ASC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const val queryPersonOppfolgingstilfelleVirksomhetNoVirksomhetsnavnList =
OR behandlerdialog_ubesvart_ubehandlet = 't'
OR behandlerdialog_avvist_ubehandlet = 't'
OR aktivitetskrav_vurder_stans_ubehandlet = 't'
OR huskelapp_active = 't'
)
ORDER BY PERSON_OPPFOLGINGSTILFELLE_VIRKSOMHET.created_at ASC
LIMIT 1000
Expand Down
45 changes: 45 additions & 0 deletions src/main/kotlin/no/nav/syfo/huskelapp/HuskelappService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package no.nav.syfo.huskelapp

import no.nav.syfo.application.database.DatabaseInterface
import no.nav.syfo.huskelapp.domain.Huskelapp
import no.nav.syfo.huskelapp.kafka.COUNT_KAFKA_CONSUMER_HUSKELAPP_READ
import no.nav.syfo.personstatus.db.createPersonOversiktStatus
import no.nav.syfo.personstatus.db.getPersonOversiktStatusList
import no.nav.syfo.personstatus.db.updateHuskelappActive
import org.slf4j.Logger
import org.slf4j.LoggerFactory

class HuskelappService(
private val database: DatabaseInterface,
) {
fun processHuskelapp(records: List<Huskelapp>) {
database.connection.use { connection ->
records.forEach { huskelapp ->
val existingPersonOversiktStatus = connection.getPersonOversiktStatusList(
fnr = huskelapp.personIdent.value,
).firstOrNull()

if (existingPersonOversiktStatus == null) {
val personoversiktStatus = huskelapp.toPersonoversiktStatus()
connection.createPersonOversiktStatus(
commit = false,
personOversiktStatus = personoversiktStatus,
)
} else {
connection.updateHuskelappActive(
isHuskelappActive = huskelapp.isActive,
personIdent = huskelapp.personIdent,
)
}

log.info("Received huskelapp with uuid=${huskelapp.uuid}")
COUNT_KAFKA_CONSUMER_HUSKELAPP_READ.increment()
}
connection.commit()
}
}

companion object {
val log: Logger = LoggerFactory.getLogger(this::class.java)
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/no/nav/syfo/huskelapp/domain/Huskelapp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package no.nav.syfo.huskelapp.domain

import no.nav.syfo.domain.PersonIdent
import no.nav.syfo.personstatus.domain.PersonOversiktStatus
import java.util.UUID

data class Huskelapp(
val uuid: UUID,
val personIdent: PersonIdent,
val isActive: Boolean,
) {
fun toPersonoversiktStatus() = PersonOversiktStatus(
fnr = personIdent.value,
).copy(
huskelappActive = isActive,
)
Comment on lines +12 to +16
Copy link
Contributor Author

@eirikdahlen eirikdahlen Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gjorde sånn i stedet for å "fylle ut" det store objektet, nå som vi har default-values.
Hadde det vært penere med en .create()-metode? I så fall burde man kanskje lage flere, for aktivitetskrav, huskelapp, dialogmøtestatusendring etc etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Hadde nok vært fint og ryddet litt opp i det ja, men får ta det i en egen PR.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package no.nav.syfo.huskelapp.kafka

import no.nav.syfo.huskelapp.HuskelappService
import no.nav.syfo.kafka.KafkaConsumerService
import org.apache.kafka.clients.consumer.ConsumerRecords
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.slf4j.LoggerFactory
import java.time.Duration

class HuskelappConsumer(
private val huskelappService: HuskelappService
) : KafkaConsumerService<KafkaHuskelapp> {

override val pollDurationInMillis: Long = 1000

override fun pollAndProcessRecords(kafkaConsumer: KafkaConsumer<String, KafkaHuskelapp>) {
val records = kafkaConsumer.poll(Duration.ofMillis(pollDurationInMillis))
if (records.count() > 0) {
processRecords(records)
kafkaConsumer.commitSync()
}
}

private fun processRecords(
consumerRecords: ConsumerRecords<String, KafkaHuskelapp>,
) {
val validRecords = consumerRecords.requireNoNulls()
huskelappService.processHuskelapp(
records = validRecords.map { it.value().toHuskelapp() }
)
}

companion object {
private val log = LoggerFactory.getLogger(HuskelappConsumer::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package no.nav.syfo.huskelapp.kafka

import io.micrometer.core.instrument.Counter
import no.nav.syfo.metric.METRICS_NS
import no.nav.syfo.metric.METRICS_REGISTRY

const val KAFKA_CONSUMER_HUSKELAPP_BASE = "${METRICS_NS}_kafka_consumer_huskelapp"
const val KAFKA_CONSUMER_HUSKELAPP_READ = "${KAFKA_CONSUMER_HUSKELAPP_BASE}_read"

val COUNT_KAFKA_CONSUMER_HUSKELAPP_READ: Counter = Counter.builder(KAFKA_CONSUMER_HUSKELAPP_READ)
.description("Counts the number of reads from topic - huskelapp")
.register(METRICS_REGISTRY)
44 changes: 44 additions & 0 deletions src/main/kotlin/no/nav/syfo/huskelapp/kafka/HuskelappTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package no.nav.syfo.huskelapp.kafka

import no.nav.syfo.application.ApplicationState
import no.nav.syfo.application.database.database
import no.nav.syfo.application.kafka.KafkaEnvironment
import no.nav.syfo.application.kafka.kafkaAivenConsumerConfig
import no.nav.syfo.huskelapp.HuskelappService
import no.nav.syfo.kafka.launchKafkaTask
import no.nav.syfo.util.configuredJacksonMapper
import org.apache.kafka.clients.consumer.ConsumerConfig
import org.apache.kafka.common.serialization.Deserializer
import java.util.*

const val HUSKELAPP_TOPIC =
"teamsykefravr.huskelapp"

fun launchHuskelappConsumer(
applicationState: ApplicationState,
kafkaEnvironment: KafkaEnvironment,
) {
val huskelappService = HuskelappService(
database = database
)
val huskelappConsumer = HuskelappConsumer(
huskelappService = huskelappService,
)
val consumerProperties = Properties().apply {
putAll(kafkaAivenConsumerConfig(kafkaEnvironment = kafkaEnvironment))
this[ConsumerConfig.MAX_POLL_RECORDS_CONFIG] = "10"
this[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = KafkaHuskelappDeserializer::class.java.canonicalName
}
launchKafkaTask(
applicationState = applicationState,
topic = HUSKELAPP_TOPIC,
consumerProperties = consumerProperties,
kafkaConsumerService = huskelappConsumer
)
}

class KafkaHuskelappDeserializer : Deserializer<KafkaHuskelapp> {
private val mapper = configuredJacksonMapper()
override fun deserialize(topic: String, data: ByteArray): KafkaHuskelapp =
mapper.readValue(data, KafkaHuskelapp::class.java)
}
22 changes: 22 additions & 0 deletions src/main/kotlin/no/nav/syfo/huskelapp/kafka/KafkaHuskelapp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package no.nav.syfo.huskelapp.kafka

import no.nav.syfo.domain.PersonIdent
import no.nav.syfo.huskelapp.domain.Huskelapp
import java.time.OffsetDateTime
import java.util.UUID

data class KafkaHuskelapp(
val uuid: UUID,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Så at det var UUID i ishuskelapp. Deserialisereren fikser det, eller?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tror det skal gå bra, men vi får teste i dev 💥

val personIdent: String,
val veilederIdent: String,
val tekst: String,
val isActive: Boolean,
val createdAt: OffsetDateTime,
val updatedAt: OffsetDateTime,
) {
fun toHuskelapp() = Huskelapp(
uuid = uuid,
personIdent = PersonIdent(personIdent),
isActive = isActive,
)
}
8 changes: 8 additions & 0 deletions src/main/kotlin/no/nav/syfo/kafka/KafkaModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import no.nav.syfo.application.Environment
import no.nav.syfo.client.azuread.AzureAdClient
import no.nav.syfo.dialogmotekandidat.kafka.launchKafkaTaskDialogmotekandidatEndring
import no.nav.syfo.dialogmotestatusendring.kafka.launchKafkaTaskDialogmoteStatusendring
import no.nav.syfo.huskelapp.kafka.launchHuskelappConsumer
import no.nav.syfo.identhendelse.kafka.launchKafkaTaskIdenthendelse
import no.nav.syfo.oppfolgingstilfelle.kafka.launchKafkaTaskOppfolgingstilfellePerson
import no.nav.syfo.pdlpersonhendelse.kafka.launchKafkaTaskPersonhendelse
Expand Down Expand Up @@ -51,4 +52,11 @@ fun launchKafkaModule(
applicationState = applicationState,
environment = environment,
)

if (environment.isHuskelappConsumerEnabled) {
launchHuskelappConsumer(
applicationState = applicationState,
kafkaEnvironment = environment.kafka,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ data class PersonOversiktStatusDTO(
val aktivitetskravVurderingFrist: LocalDate?,
val behandlerdialogUbehandlet: Boolean,
val aktivitetskravVurderStansUbehandlet: Boolean,
val huskelappActive: Boolean,
)

data class PersonOppfolgingstilfelleDTO(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,22 @@ fun Connection.updateAktivitetskravVurderStans(
it.execute()
}
}

const val queryUpdatePersonOversiktStatusHuskelappActive =
"""
UPDATE PERSON_OVERSIKT_STATUS
SET huskelapp_active = ?, sist_endret = ?
WHERE fnr = ?
"""

fun Connection.updateHuskelappActive(
isHuskelappActive: Boolean,
personIdent: PersonIdent,
) {
this.prepareStatement(queryUpdatePersonOversiktStatusHuskelappActive).use {
it.setBoolean(1, isHuskelappActive)
it.setObject(2, Timestamp.from(Instant.now()))
it.setString(3, personIdent.value)
it.execute()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ const val queryCreatePersonOversiktStatus =
behandlerdialog_svar_ubehandlet,
behandlerdialog_ubesvart_ubehandlet,
behandlerdialog_avvist_ubehandlet,
aktivitetskrav_vurder_stans_ubehandlet
) VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
aktivitetskrav_vurder_stans_ubehandlet,
huskelapp_active
) VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id
"""

Expand Down Expand Up @@ -107,6 +108,7 @@ fun Connection.createPersonOversiktStatus(
it.setBoolean(28, personOversiktStatus.behandlerdialogUbesvartUbehandlet)
it.setBoolean(29, personOversiktStatus.behandlerdialogAvvistUbehandlet)
it.setBoolean(30, personOversiktStatus.aktivitetskravVurderStansUbehandlet)
it.setBoolean(31, personOversiktStatus.huskelappActive)
it.executeQuery().toList { getInt("id") }.firstOrNull()
} ?: throw SQLException("Creating PersonOversikStatus failed, no rows affected.")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const val queryHentUbehandledePersonerTilknyttetEnhet = """
OR behandlerdialog_ubesvart_ubehandlet = 't'
OR behandlerdialog_avvist_ubehandlet = 't'
OR aktivitetskrav_vurder_stans_ubehandlet = 't'
OR huskelapp_active = 't'
)
);
"""
Expand Down Expand Up @@ -115,6 +116,7 @@ fun ResultSet.toPPersonOversiktStatus(): PPersonOversiktStatus =
behandlerdialogUbesvartUbehandlet = getObject("behandlerdialog_ubesvart_ubehandlet") as Boolean,
behandlerdialogAvvistUbehandlet = getObject("behandlerdialog_avvist_ubehandlet") as Boolean,
aktivitetskravVurderStansUbehandlet = getObject("aktivitetskrav_vurder_stans_ubehandlet") as Boolean,
huskelappActive = getObject("huskelapp_active") as Boolean,
)

fun ResultSet.toVeilederBrukerKnytning(): VeilederBrukerKnytning =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,35 @@ data class PPersonOversiktStatus(
val behandlerdialogUbesvartUbehandlet: Boolean,
val behandlerdialogAvvistUbehandlet: Boolean,
val aktivitetskravVurderStansUbehandlet: Boolean,
val huskelappActive: Boolean,
)

fun PPersonOversiktStatus.toPersonOversiktStatus(
personOppfolgingstilfelleVirksomhetList: List<PersonOppfolgingstilfelleVirksomhet>,
) = PersonOversiktStatus(
fnr = this.fnr,
navn = this.navn,
enhet = this.enhet,
veilederIdent = this.veilederIdent,
motebehovUbehandlet = this.motebehovUbehandlet,
oppfolgingsplanLPSBistandUbehandlet = this.oppfolgingsplanLPSBistandUbehandlet,
dialogmotesvarUbehandlet = this.dialogmotesvarUbehandlet,
dialogmotekandidat = this.dialogmotekandidat,
dialogmotekandidatGeneratedAt = this.dialogmotekandidatGeneratedAt,
motestatus = this.motestatus,
motestatusGeneratedAt = this.motestatusGeneratedAt,
latestOppfolgingstilfelle = this.toPersonOppfolgingstilfelle(
fnr = fnr,
navn = navn,
enhet = enhet,
veilederIdent = veilederIdent,
motebehovUbehandlet = motebehovUbehandlet,
oppfolgingsplanLPSBistandUbehandlet = oppfolgingsplanLPSBistandUbehandlet,
dialogmotesvarUbehandlet = dialogmotesvarUbehandlet,
dialogmotekandidat = dialogmotekandidat,
dialogmotekandidatGeneratedAt = dialogmotekandidatGeneratedAt,
motestatus = motestatus,
motestatusGeneratedAt = motestatusGeneratedAt,
latestOppfolgingstilfelle = toPersonOppfolgingstilfelle(
personOppfolgingstilfelleVirksomhetList = personOppfolgingstilfelleVirksomhetList,
),
aktivitetskrav = this.aktivitetskrav?.let { AktivitetskravStatus.valueOf(this.aktivitetskrav) },
aktivitetskravStoppunkt = this.aktivitetskravStoppunkt,
aktivitetskravSistVurdert = this.aktivitetskravUpdatedAt,
aktivitetskravVurderingFrist = this.aktivitetskravVurderingFrist,
behandlerdialogSvarUbehandlet = this.behandlerdialogSvarUbehandlet,
behandlerdialogUbesvartUbehandlet = this.behandlerdialogUbesvartUbehandlet,
behandlerdialogAvvistUbehandlet = this.behandlerdialogAvvistUbehandlet,
aktivitetskravVurderStansUbehandlet = this.aktivitetskravVurderStansUbehandlet,
aktivitetskrav = aktivitetskrav?.let { AktivitetskravStatus.valueOf(aktivitetskrav) },
aktivitetskravStoppunkt = aktivitetskravStoppunkt,
aktivitetskravSistVurdert = aktivitetskravUpdatedAt,
aktivitetskravVurderingFrist = aktivitetskravVurderingFrist,
behandlerdialogSvarUbehandlet = behandlerdialogSvarUbehandlet,
behandlerdialogUbesvartUbehandlet = behandlerdialogUbesvartUbehandlet,
behandlerdialogAvvistUbehandlet = behandlerdialogAvvistUbehandlet,
aktivitetskravVurderStansUbehandlet = aktivitetskravVurderStansUbehandlet,
huskelappActive = huskelappActive,
)

fun PPersonOversiktStatus.toPersonOppfolgingstilfelle(
Expand Down
Loading