diff --git a/src/main/kotlin/no/nav/syfo/database/SykmeldingFieldsRepository.kt b/src/main/kotlin/no/nav/syfo/database/SykmeldingFieldsRepository.kt new file mode 100644 index 00000000..fdd7f7b3 --- /dev/null +++ b/src/main/kotlin/no/nav/syfo/database/SykmeldingFieldsRepository.kt @@ -0,0 +1,71 @@ +package no.nav.syfo.database + +import no.nav.syfo.domain.PersonIdent +import java.sql.Connection +import java.sql.SQLException +import java.time.OffsetDateTime +import java.util.UUID + +class SykmeldingFieldsRepository() { + + fun createPersonoppgaveSykmeldingFields( + referanseUUID: UUID, + personident: PersonIdent, + tiltakNav: String?, + tiltakAndre: String?, + bistand: String?, + connection: Connection, + ) { + val idList = connection.prepareStatement(CREATE_SYKMELDING_FIELDS).use { + it.setString(1, referanseUUID.toString()) + it.setObject(2, OffsetDateTime.now()) + it.setString(3, personident.value) + it.setString(4, tiltakNav ?: "") + it.setString(5, tiltakAndre ?: "") + it.setString(6, bistand ?: "") + it.executeQuery().toList { getInt("id") } + } + + if (idList.size != 1) { + throw SQLException("Creating sykmelding failed, no rows affected.") + } + } + + fun findExistingPersonoppgaveFromSykmeldingFields( + personident: PersonIdent, + tiltakNav: String?, + tiltakAndre: String?, + bistand: String?, + connection: Connection, + ) = connection.prepareStatement(FIND_EXISTING_FROM_SYKMELDING_FIELDS).use { + it.setString(1, personident.value) + it.setString(2, tiltakNav ?: "") + it.setString(3, tiltakAndre ?: "") + it.setString(4, bistand ?: "") + it.executeQuery().toList { getInt("id") }.isNotEmpty() + } + + companion object { + private const val CREATE_SYKMELDING_FIELDS = + """ + INSERT INTO SYKMELDING ( + id, + referanse_uuid, + created_at, + personident, + tiltak_nav, + tiltak_andre, + bistand) + VALUES (DEFAULT, ?, ?, ?, ?, ?, ?) RETURNING id + """ + + private const val FIND_EXISTING_FROM_SYKMELDING_FIELDS = + """ + SELECT id FROM SYKMELDING WHERE + personident = ? AND + tiltak_nav = ? AND + tiltak_andre = ? AND + bistand = ? + """ + } +} diff --git a/src/main/kotlin/no/nav/syfo/sykmelding/KafkaSykmeldingConsumer.kt b/src/main/kotlin/no/nav/syfo/sykmelding/KafkaSykmeldingConsumer.kt index 02fbe927..b2483f15 100644 --- a/src/main/kotlin/no/nav/syfo/sykmelding/KafkaSykmeldingConsumer.kt +++ b/src/main/kotlin/no/nav/syfo/sykmelding/KafkaSykmeldingConsumer.kt @@ -4,6 +4,7 @@ import no.nav.syfo.ApplicationState import no.nav.syfo.Environment import no.nav.syfo.database.DatabaseInterface import no.nav.syfo.database.PersonOppgaveRepository +import no.nav.syfo.database.SykmeldingFieldsRepository import no.nav.syfo.domain.* import no.nav.syfo.kafka.KafkaConsumerService import no.nav.syfo.kafka.kafkaAivenConsumerConfig @@ -37,7 +38,7 @@ fun launchKafkaTaskSykmelding( applicationState = applicationState, kafkaConsumerService = KafkaSykmeldingConsumer( database = database, - personOppgaveRepository = personOppgaveRepository + personOppgaveRepository = personOppgaveRepository, ), consumerProperties = consumerProperties, topics = listOf(SYKMELDING_TOPIC, MANUELL_SYKMELDING_TOPIC), @@ -50,6 +51,7 @@ class KafkaSykmeldingConsumer( ) : KafkaConsumerService { override val pollDurationInMillis: Long = 1000 + private val sykmeldingFieldsRepository = SykmeldingFieldsRepository() override fun pollAndProcessRecords( kafkaConsumer: KafkaConsumer, @@ -115,7 +117,14 @@ class KafkaSykmeldingConsumer( val arbeidstakerPersonident = PersonIdent(receivedSykmeldingDTO.personNrPasient) val hasExistingUbehandlet = connection.getPersonOppgaverByReferanseUuid(referanseUuid) .any { it.behandletTidspunkt == null } - if (!hasExistingUbehandlet) { + val hasExistingDuplicate = sykmeldingFieldsRepository.findExistingPersonoppgaveFromSykmeldingFields( + personident = arbeidstakerPersonident, + tiltakNav = receivedSykmeldingDTO.sykmelding.tiltakNAV, + tiltakAndre = receivedSykmeldingDTO.sykmelding.andreTiltak, + bistand = receivedSykmeldingDTO.sykmelding.meldingTilNAV?.beskrivBistand, + connection = connection, + ) + if (!hasExistingUbehandlet && !hasExistingDuplicate) { val personOppgave = PersonOppgave( referanseUuid = referanseUuid, personIdent = arbeidstakerPersonident, @@ -126,10 +135,17 @@ class KafkaSykmeldingConsumer( personOppgave = personOppgave, connection = connection ) - val tiltakNav = !receivedSykmeldingDTO.sykmelding.tiltakNAV.isNullOrEmpty() - val tiltakAndre = !receivedSykmeldingDTO.sykmelding.andreTiltak.isNullOrEmpty() - log.info("Created personoppgave ${personOppgave.uuid} from sykmelding with tiltakNav=$tiltakNav and tiltakAndre=$tiltakAndre") + sykmeldingFieldsRepository.createPersonoppgaveSykmeldingFields( + referanseUUID = referanseUuid, + personident = arbeidstakerPersonident, + tiltakNav = receivedSykmeldingDTO.sykmelding.tiltakNAV, + tiltakAndre = receivedSykmeldingDTO.sykmelding.andreTiltak, + bistand = receivedSykmeldingDTO.sykmelding.meldingTilNAV?.beskrivBistand, + connection = connection, + ) COUNT_MOTTATT_SYKMELDING_SUCCESS.increment() + } else if (hasExistingDuplicate) { + COUNT_MOTTATT_SYKMELDING_DUPLICATE.increment() } } diff --git a/src/main/kotlin/no/nav/syfo/sykmelding/SykmeldingMetrics.kt b/src/main/kotlin/no/nav/syfo/sykmelding/SykmeldingMetrics.kt index 7b38781c..9d4c11f1 100644 --- a/src/main/kotlin/no/nav/syfo/sykmelding/SykmeldingMetrics.kt +++ b/src/main/kotlin/no/nav/syfo/sykmelding/SykmeldingMetrics.kt @@ -5,6 +5,7 @@ import no.nav.syfo.metric.* const val MOTTATT_SYKMELDING = "${METRICS_NS}_mottatt_sykmelding_count" const val MOTTATT_SYKMELDING_CREATED_PERSONOPPGAVE = "${METRICS_NS}_mottatt_sykmelding_personoppgave_count" +const val MOTTATT_SYKMELDING_DUPLICATE = "${METRICS_NS}_mottatt_sykmelding_duplikat_count" const val MOTTATT_SYKMELDING_BESKRIV_BISTAND_NAV_IRRELEVANT = "${METRICS_NS}_mottatt_sykmelding_beskriv_bistand_nav_irrelevant_count" const val MOTTATT_SYKMELDING_TILTAK_NAV_IRRELEVANT = "${METRICS_NS}_mottatt_sykmelding_tiltak_nav_irrelevant_count" const val MOTTATT_SYKMELDING_ANDRE_TILTAK_IRRELEVANT = "${METRICS_NS}_mottatt_sykmelding_andre_tiltak_irrelevant_count" @@ -19,6 +20,11 @@ val COUNT_MOTTATT_SYKMELDING_SUCCESS: Counter = Counter .description("Counts the number of received sykmelding that created personoppgave") .register(METRICS_REGISTRY) +val COUNT_MOTTATT_SYKMELDING_DUPLICATE: Counter = Counter + .builder(MOTTATT_SYKMELDING_DUPLICATE) + .description("Counts the number of received sykmelding that had duplicate fields") + .register(METRICS_REGISTRY) + val COUNT_MOTTATT_SYKMELDING_BESKRIV_BISTAND_NAV_IRRELEVANT: Counter = Counter .builder(MOTTATT_SYKMELDING_BESKRIV_BISTAND_NAV_IRRELEVANT) .description("Counts the number of received sykmelding with beskriv bistand Nav that is irrelevant for oppgave") diff --git a/src/main/resources/db/migration/V5_9__create_table_sykmelding.sql b/src/main/resources/db/migration/V5_9__create_table_sykmelding.sql new file mode 100644 index 00000000..0aae2b7c --- /dev/null +++ b/src/main/resources/db/migration/V5_9__create_table_sykmelding.sql @@ -0,0 +1,11 @@ +CREATE TABLE sykmelding ( + id SERIAL PRIMARY KEY, + created_at TIMESTAMPTZ NOT NULL, + referanse_uuid CHAR(36) NOT NULL, + personident VARCHAR(11) NOT NULL, + tiltak_nav TEXT NOT NULL, + tiltak_andre TEXT NOT NULL, + bistand TEXT NOT NULL +); + +CREATE INDEX ix_sykmelding_personident ON sykmelding(personident); diff --git a/src/test/kotlin/no/nav/syfo/sykmelding/SykmeldingConsumerSpek.kt b/src/test/kotlin/no/nav/syfo/sykmelding/SykmeldingConsumerSpek.kt index 23eb870b..02855f7d 100644 --- a/src/test/kotlin/no/nav/syfo/sykmelding/SykmeldingConsumerSpek.kt +++ b/src/test/kotlin/no/nav/syfo/sykmelding/SykmeldingConsumerSpek.kt @@ -130,6 +130,38 @@ class SykmeldingConsumerSpek : Spek({ personOppgave.behandletTidspunkt shouldBe null personOppgave.referanseUuid shouldBeEqualTo sykmeldingId } + it("Does not creates oppgave if andreTiltak has text but duplicate from previous sykmelding") { + val sykmelding = generateKafkaSykmelding( + sykmeldingId = UUID.randomUUID(), + meldingTilNAV = null, + andreTiltak = "Jeg synes NAV skal gjøre dette", + ) + kafkaConsumer.mockPollConsumerRecords( + recordValue = sykmelding, + topic = topic, + ) + kafkaSykmeldingConsumer.pollAndProcessRecords( + kafkaConsumer = kafkaConsumer, + ) + database.getPersonOppgaver( + personIdent = PersonIdent(sykmelding.personNrPasient), + ).size shouldBeEqualTo 1 + val sykmeldingNext = generateKafkaSykmelding( + sykmeldingId = UUID.randomUUID(), + meldingTilNAV = null, + andreTiltak = "Jeg synes NAV skal gjøre dette", + ) + kafkaConsumer.mockPollConsumerRecords( + recordValue = sykmeldingNext, + topic = topic, + ) + kafkaSykmeldingConsumer.pollAndProcessRecords( + kafkaConsumer = kafkaConsumer, + ) + database.getPersonOppgaver( + personIdent = PersonIdent(sykmelding.personNrPasient), + ).size shouldBeEqualTo 1 + } it("Does not create oppgave if meldingTilNAV, tiltakNAV, and andreTiltak is null") { val sykmeldingId = UUID.randomUUID() val sykmelding = generateKafkaSykmelding( diff --git a/src/test/kotlin/no/nav/syfo/testutil/TestDB.kt b/src/test/kotlin/no/nav/syfo/testutil/TestDB.kt index 7580574d..4916e309 100644 --- a/src/test/kotlin/no/nav/syfo/testutil/TestDB.kt +++ b/src/test/kotlin/no/nav/syfo/testutil/TestDB.kt @@ -59,6 +59,9 @@ fun DatabaseInterface.dropData() { """ DELETE FROM DIALOGMOTE_STATUSENDRING """.trimIndent(), + """ + DELETE FROM SYKMELDING + """.trimIndent(), ) this.connection.use { connection -> queryList.forEach { query ->