Skip to content

Commit

Permalink
EY-4661 10mnd brev aktivitetsplikt (#6174)
Browse files Browse the repository at this point in the history
* EY-4661 10mnd brev aktivitetsplikt

* Rydd opp etter rebase mot main

* Reminder

* Flytt skalopprettebrev ting inn i ifen så det ikke gjøres ellers

* Legg til noen tester for opprett brev

* EY-4661 Hent utlandstilknytning på saken

* EY-4661 Alltid returnere en brevid ellers kaste exception
  • Loading branch information
sebassonav authored Nov 1, 2024
1 parent e708fbe commit bac7472
Show file tree
Hide file tree
Showing 32 changed files with 582 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package no.nav.etterlatte.behandling.aktivitetsplikt

import no.nav.etterlatte.behandling.hendelse.getUUID
import no.nav.etterlatte.behandling.hendelse.setLong
import no.nav.etterlatte.brev.model.BrevID
import no.nav.etterlatte.common.ConnectionAutoclosing
import no.nav.etterlatte.libs.common.sak.SakId
import no.nav.etterlatte.libs.database.singleOrNull
Expand All @@ -15,7 +17,7 @@ class AktivitetspliktBrevDao(
val stmt =
prepareStatement(
"""
SELECT oppgave_id, sak_id, utbetaling, redusert_etter_inntekt, skal_sende_brev from aktivitetsplikt_brevdata
SELECT oppgave_id, sak_id, utbetaling, redusert_etter_inntekt, skal_sende_brev, brev_id from aktivitetsplikt_brevdata
WHERE oppgave_id = ?
""".trimIndent(),
)
Expand All @@ -24,8 +26,16 @@ class AktivitetspliktBrevDao(
AktivitetspliktInformasjonBrevdata(
oppgaveId = getUUID("oppgave_id"),
sakid = SakId(getLong("sak_id")),
utbetaling = getBoolean("utbetaling"),
redusertEtterInntekt = getBoolean("redusert_etter_inntekt"),
brevId = if (getObject("brev_id") == null) null else getLong("brev_id"),
utbetaling = if (getObject("utbetaling") == null) null else getBoolean("utbetaling"),
redusertEtterInntekt =
if (getObject("redusert_etter_inntekt") ==
null
) {
null
} else {
getBoolean("redusert_etter_inntekt")
},
skalSendeBrev = getBoolean("skal_sende_brev"),
)
}
Expand All @@ -52,4 +62,23 @@ class AktivitetspliktBrevDao(
stmt.executeUpdate()
}
}

fun lagreBrevId(
oppgaveId: UUID,
brevId: BrevID,
) = connectionAutoclosing.hentConnection { connection ->
with(connection) {
val stmt =
prepareStatement(
"""
UPDATE aktivitetsplikt_brevdata SET brev_id = ?
WHERE oppgave_id = ?
""".trimIndent(),
)
stmt.setLong(1, brevId)
stmt.setObject(2, oppgaveId)
stmt.executeUpdate()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
package no.nav.etterlatte.behandling.aktivitetsplikt

import kotlinx.coroutines.runBlocking
import no.nav.etterlatte.behandling.BehandlingService
import no.nav.etterlatte.behandling.aktivitetsplikt.vurdering.AktivitetspliktAktivitetsgradType
import no.nav.etterlatte.behandling.klienter.BrevApiKlient
import no.nav.etterlatte.brev.BrevParametre
import no.nav.etterlatte.brev.model.BrevID
import no.nav.etterlatte.brev.model.oms.Aktivitetsgrad
import no.nav.etterlatte.brev.model.oms.NasjonalEllerUtland
import no.nav.etterlatte.libs.common.behandling.UtlandstilknytningType
import no.nav.etterlatte.libs.common.feilhaandtering.GenerellIkkeFunnetException
import no.nav.etterlatte.libs.common.feilhaandtering.UgyldigForespoerselException
import no.nav.etterlatte.libs.common.oppgave.OppgaveIntern
import no.nav.etterlatte.libs.common.oppgave.OppgaveType
import no.nav.etterlatte.libs.common.sak.Sak
import no.nav.etterlatte.libs.common.sak.SakId
import no.nav.etterlatte.libs.common.toJson
import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo
import no.nav.etterlatte.oppgave.OppgaveService
import no.nav.etterlatte.sak.SakService
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.util.UUID

class AktivitetspliktOppgaveService(
private val aktivitetspliktService: AktivitetspliktService,
private val oppgaveService: OppgaveService,
private val sakService: SakService,
private val aktivitetspliktBrevDao: AktivitetspliktBrevDao,
private val brevApiKlient: BrevApiKlient,
private val behandlingService: BehandlingService,
) {
private val logger: Logger = LoggerFactory.getLogger(this.javaClass.name)

fun hentVurderingForOppgave(oppgaveId: UUID): AktivitetspliktOppgaveVurdering {
val oppgave = oppgaveService.hentOppgave(oppgaveId)
val vurderingType =
Expand Down Expand Up @@ -58,17 +75,101 @@ class AktivitetspliktOppgaveService(
): AktivitetspliktInformasjonBrevdata? {
val oppgave = oppgaveService.hentOppgave(oppgaveId)
val sak = sakService.finnSak(oppgave.sakId) ?: throw GenerellIkkeFunnetException()
aktivitetspliktBrevDao.lagreBrevdata(data.toDaoObjekt(oppgaveId, sakid = sak.id))
aktivitetspliktBrevDao.lagreBrevdata(data.toDaoObjektBrevutfall(oppgaveId, sakid = sak.id))
return aktivitetspliktBrevDao.hentBrevdata(oppgaveId)
}

private fun mapAktivitetsgradstypeTilAktivtetsgrad(aktivitetsgrad: AktivitetspliktAktivitetsgradType): Aktivitetsgrad =
when (aktivitetsgrad) {
AktivitetspliktAktivitetsgradType.AKTIVITET_UNDER_50 -> Aktivitetsgrad.UNDER_50_PROSENT
AktivitetspliktAktivitetsgradType.AKTIVITET_OVER_50 -> Aktivitetsgrad.OVER_50_PROSENT
AktivitetspliktAktivitetsgradType.AKTIVITET_100 -> Aktivitetsgrad.AKKURAT_100_PROSENT
}

private fun mapNasjonalEllerUtland(utland: UtlandstilknytningType): NasjonalEllerUtland =
when (utland) {
UtlandstilknytningType.NASJONAL -> NasjonalEllerUtland.NASJONAL
UtlandstilknytningType.UTLANDSTILSNITT -> NasjonalEllerUtland.UTLAND
UtlandstilknytningType.BOSATT_UTLAND -> NasjonalEllerUtland.UTLAND
}

fun opprettBrevHvisKraveneErOppfyltOgDetIkkeFinnes(
oppgaveId: UUID,
brukerTokenInfo: BrukerTokenInfo,
): BrevID {
val oppgave = oppgaveService.hentOppgave(oppgaveId)
val brevData = aktivitetspliktBrevDao.hentBrevdata(oppgaveId) ?: throw GenerellIkkeFunnetException()
if (brevData.brevId != null) {
return brevData.brevId
}
val skalOppretteBrev = skalOppretteBrev(brevData)
if (skalOppretteBrev) {
val vurderingForOppgave = aktivitetspliktService.hentVurderingForOppgave(oppgaveId) ?: throw GenerellIkkeFunnetException()
val sisteAktivtetsgrad = vurderingForOppgave.aktivitet.maxBy { it.fom }
val nasjonalEllerUtland = behandlingService.hentUtlandstilknytningForSak(oppgave.sakId) ?: throw GenerellIkkeFunnetException()
val brevParametreAktivitetsplikt10mnd =
BrevParametre.AktivitetspliktInformasjon10Mnd(
aktivitetsgrad = mapAktivitetsgradstypeTilAktivtetsgrad(sisteAktivtetsgrad.aktivitetsgrad),
utbetaling = brevData.utbetaling!!,
redusertEtterInntekt = brevData.redusertEtterInntekt!!,
nasjonalEllerUtland = mapNasjonalEllerUtland(nasjonalEllerUtland.type),
)
val opprettetBrev =
runBlocking {
brevApiKlient.opprettSpesifiktBrev(
oppgave.sakId,
brevParametreAktivitetsplikt10mnd,
brukerTokenInfo = brukerTokenInfo,
)
}
aktivitetspliktBrevDao.lagreBrevId(oppgaveId, opprettetBrev.id)
return opprettetBrev.id
} else {
throw BrevFeil("Kunne ikke opprette brev for $oppgaveId se data: ${brevData.toJson()}")
}
}

private fun skalOppretteBrev(brevdata: AktivitetspliktInformasjonBrevdata): Boolean {
if (brevdata.skalSendeBrev) {
if (brevdata.brevId == null) {
val harUtbetaling = brevdata.utbetaling != null
val harReduserEtterInntekt = brevdata.redusertEtterInntekt != null
if (!harUtbetaling || !harReduserEtterInntekt) {
logger.info("Mangler brevdatainformasjon for oppgaveid ${brevdata.oppgaveId}")
throw ManglerBrevdata("Mangler brevdatainformasjon for oppgaveid ${brevdata.oppgaveId}")
}
return true
} else {
logger.info("Oppretter ikke brev for oppgaveid ${brevdata.oppgaveId} brevid finnes allerede, id: ${brevdata.brevId}")
return false
}
} else {
logger.info("Oppretter ikke brev for oppgaveid ${brevdata.oppgaveId} har ikke valgt å sende brev for oppgave")
return false
}
}
}

class BrevFeil(
msg: String,
) : UgyldigForespoerselException(
code = "FEIL_I_BREV_FORESPØRSEL",
detail = msg,
)

class ManglerBrevdata(
msg: String,
) : UgyldigForespoerselException(
code = "MANGLER_BREVDATA",
detail = msg,
)

data class AktivitetspliktInformasjonBrevdataRequest(
val skalSendeBrev: Boolean,
val utbetaling: Boolean? = null,
val redusertEtterInntekt: Boolean? = null,
) {
fun toDaoObjekt(
fun toDaoObjektBrevutfall(
oppgaveId: UUID,
sakid: SakId,
): AktivitetspliktInformasjonBrevdata =
Expand All @@ -84,6 +185,7 @@ data class AktivitetspliktInformasjonBrevdataRequest(
data class AktivitetspliktInformasjonBrevdata(
val oppgaveId: UUID,
val sakid: SakId,
val brevId: Long? = null,
val skalSendeBrev: Boolean,
val utbetaling: Boolean? = null,
val redusertEtterInntekt: Boolean? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import kotlinx.coroutines.runBlocking
import no.nav.etterlatte.behandling.aktivitetsplikt.vurdering.LagreAktivitetspliktAktivitetsgrad
import no.nav.etterlatte.behandling.aktivitetsplikt.vurdering.LagreAktivitetspliktUnntak
import no.nav.etterlatte.behandling.domain.TilstandException
import no.nav.etterlatte.brev.model.BrevID
import no.nav.etterlatte.inTransaction
import no.nav.etterlatte.libs.common.behandling.OpprettAktivitetspliktOppfolging
import no.nav.etterlatte.libs.common.behandling.OpprettOppgaveForAktivitetspliktVarigUnntakDto
Expand Down Expand Up @@ -238,6 +239,13 @@ internal fun Route.aktivitetspliktRoutes(
inTransaction { aktivitetspliktOppgaveService.lagreBrevdata(oppgaveId, brevdata) }
call.respond(HttpStatusCode.OK)
}
post("opprettbrev") {
val brevId =
inTransaction {
aktivitetspliktOppgaveService.opprettBrevHvisKraveneErOppfyltOgDetIkkeFinnes(oppgaveId = oppgaveId, brukerTokenInfo)
}
call.respond(BrevIdDto(brevId))
}
}

route("/api/sak/{$SAKID_CALL_PARAMETER}/oppgave/{$OPPGAVEID_CALL_PARAMETER}/aktivitetsplikt/vurdering") {
Expand Down Expand Up @@ -341,6 +349,10 @@ internal fun Route.aktivitetspliktRoutes(
}
}

data class BrevIdDto(
val brevId: BrevID? = null,
)

class VurderingIkkeFunnetException(
sakId: SakId,
referanse: UUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,5 @@ fun PreparedStatement.setLong(

fun ResultSet.getUUID(name: String) = getObject(name) as UUID

// TODO: denne går på resultsettet ikke kolonnen og vil mappe feil om spørringen har treff på andre kolonner i selecten
fun ResultSet.getLongOrNull(name: String) = getLong(name).takeUnless { wasNull() }
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.github.michaelbull.result.mapError
import com.typesafe.config.Config
import io.ktor.client.HttpClient
import no.nav.etterlatte.behandling.objectMapper
import no.nav.etterlatte.brev.BrevParametre
import no.nav.etterlatte.brev.model.Brev
import no.nav.etterlatte.libs.common.behandling.Klage
import no.nav.etterlatte.libs.common.brev.BestillingsIdDto
Expand All @@ -21,6 +22,12 @@ import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo
import java.util.UUID

interface BrevApiKlient {
suspend fun opprettSpesifiktBrev(
sakId: SakId,
brevParametre: BrevParametre,
brukerTokenInfo: BrukerTokenInfo,
): Brev

suspend fun opprettKlageOversendelsesbrevISak(
klageId: UUID,
brukerTokenInfo: BrukerTokenInfo,
Expand Down Expand Up @@ -104,6 +111,21 @@ class BrevApiKlientObo(
private val clientId = config.getString("brev-api.client.id")
private val resourceUrl = config.getString("brev-api.resource.url")

override suspend fun opprettSpesifiktBrev(
sakId: SakId,
brevParametre: BrevParametre,
brukerTokenInfo: BrukerTokenInfo,
): Brev =
post(
url = "$resourceUrl/api/brev/sak/$sakId/spesifikk",
onSuccess = { resource ->
resource.response?.let { objectMapper.readValue(it.toJson()) }
?: throw RuntimeException("Fikk ikke en riktig respons fra oppretting av brev")
},
brukerTokenInfo = brukerTokenInfo,
postBody = brevParametre.toJson(),
)

override suspend fun opprettKlageOversendelsesbrevISak(
klageId: UUID,
brukerTokenInfo: BrukerTokenInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,5 @@ fun PreparedStatement.setInt(
value: Int?,
) = if (value == null) setNull(index, Types.BIGINT) else setInt(index, value)

// TODO: denne går på resultsettet ikke kolonnen og vil mappe feil om spørringen har treff på andre kolonner i selecten
fun ResultSet.getIntOrNull(name: String) = getInt(name).takeUnless { wasNull() }
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ internal class ApplicationContext(
oppgaveService = oppgaveService,
sakService = sakService,
aktivitetspliktBrevDao = aktivitetspliktBrevDao,
brevApiKlient = brevApiKlient,
behandlingService = behandlingService,
)

// Jobs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE aktivitetsplikt_brevdata ADD COLUMN brev_id BIGINT;
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,45 @@ class AktivitetspliktBrevDaoTest(

dao.hentBrevdata(UUID.randomUUID()) shouldBe null
}

@Test
fun `Kan lagre hente og sette brevid`() {
val sak = sakSkrivDao.opprettSak("person", SakType.OMSTILLINGSSTOENAD, Enheter.defaultEnhet.enhetNr)
val oppgave = lagNyOppgave(sak).also { oppgaveDao.opprettOppgave(it) }

val brevdata =
AktivitetspliktInformasjonBrevdata(
sakid = sak.id,
oppgaveId = oppgave.id,
skalSendeBrev = true,
utbetaling = false,
redusertEtterInntekt = false,
)

dao.lagreBrevdata(brevdata)
val lagretBrevdata = dao.hentBrevdata(oppgave.id)
lagretBrevdata shouldBe brevdata

val brevId = 1L
dao.lagreBrevId(oppgave.id, brevId)
val brevdataMedBrevId = dao.hentBrevdata(oppgave.id)
brevdataMedBrevId?.brevId shouldBe brevId
}

@Test
fun `Skal fungere med nullable for booleans`() {
val sak = sakSkrivDao.opprettSak("person", SakType.OMSTILLINGSSTOENAD, Enheter.defaultEnhet.enhetNr)
val oppgave = lagNyOppgave(sak).also { oppgaveDao.opprettOppgave(it) }

val brevdata =
AktivitetspliktInformasjonBrevdata(
sakid = sak.id,
oppgaveId = oppgave.id,
skalSendeBrev = false,
)

dao.lagreBrevdata(brevdata)
val lagretBrevdata = dao.hentBrevdata(oppgave.id)
lagretBrevdata shouldBe brevdata
}
}
Loading

0 comments on commit bac7472

Please sign in to comment.