Skip to content

Commit

Permalink
NAV-23449: Refaktorer logikk for hjemler til en egen pakke. Forenkler…
Browse files Browse the repository at this point in the history
… logikken og skriver enhetstester. (#4928)

### 💰 Hva skal gjøres, og hvorfor?
Favro:
https://favro.com/organization/98c34fb974ce445eac854de0/1844bbac3b6605eacc8f5543?card=NAV-23449

Forenkler logikken ved å trekke ut hjemler i en egen pakke. Fordeler
logikken ut over flere filer. Skriver enhetstester for den "nye"
logikken. Den "nye" logikken skal i teorien produsere samme resultat som
den forrige. Hensikten her er utelukkende å gjøre koden mer oversiktlig
og lettere å teste.

Toggle for å skru av/på refaktorert logikk slik at det kan merges uten å
testes først.

Toggle:
https://teamfamilie-unleash-web.iap.nav.cloud.nais.io/projects/default/features/familie-ba-sak.bruk_omskriving_av_hjemler_i_brev

Når toggle fjernes kan man fjerne mye "gammel" kode. 

### 🔎️ Er det noe spesielt du ønsker tilbakemelding om?
Nei

### ✅ Checklist
_Har du husket alle punktene i listen?_
- [ ] Jeg har testet mine endringer i henhold til akseptansekriteriene
🕵️
- [ ] Jeg har config- eller sql-endringer. I så fall, husk manuell
deploy til miljø for å verifisere endringene.
- [x] Jeg har skrevet tester. Hvis du ikke har skrevet tester, beskriv
hvorfor under 👇

### 💬 Ønsker du en muntlig gjennomgang?
- [ ] Ja
- [x] Nei
  • Loading branch information
thoalm authored Nov 28, 2024
1 parent 77e188c commit 1e3f687
Show file tree
Hide file tree
Showing 25 changed files with 2,581 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class FeatureToggleConfig {
// NAV-22995
const val SKAL_BRUKE_NY_KLASSEKODE_FOR_UTVIDET_BARNETRYGD = "familie-ba-sak.skal-bruke-ny-klassekode-for-utvidet-barnetrygd"

// NAV-23449 - Skrud av/på ny refaktorert logikk for hjemler i brev, skal i teorien produsere det samme resultatet
const val BRUK_OMSKRIVING_AV_HJEMLER_I_BREV = "familie-ba-sak.bruk_omskriving_av_hjemler_i_brev"

// satsendring
// Oppretter satsendring-tasker for de som ikke har fått ny task
const val SATSENDRING_ENABLET: String = "familie-ba-sak.satsendring-enablet"
Expand Down
29 changes: 21 additions & 8 deletions src/main/kotlin/no/nav/familie/ba/sak/kjerne/brev/BrevService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import no.nav.familie.ba.sak.common.Utils.storForbokstavIAlleNavn
import no.nav.familie.ba.sak.common.secureLogger
import no.nav.familie.ba.sak.common.tilDagMånedÅr
import no.nav.familie.ba.sak.common.toLocalDate
import no.nav.familie.ba.sak.config.FeatureToggleConfig
import no.nav.familie.ba.sak.integrasjoner.familieintegrasjoner.IntegrasjonClient
import no.nav.familie.ba.sak.integrasjoner.organisasjon.OrganisasjonService
import no.nav.familie.ba.sak.integrasjoner.sanity.SanityService
Expand Down Expand Up @@ -51,6 +52,7 @@ import no.nav.familie.ba.sak.kjerne.brev.domene.maler.VedtakFellesfelter
import no.nav.familie.ba.sak.kjerne.brev.domene.maler.VedtakFellesfelterSammensattKontrollsak
import no.nav.familie.ba.sak.kjerne.brev.domene.maler.Vedtaksbrev
import no.nav.familie.ba.sak.kjerne.brev.domene.maler.utbetalingEøs.UtbetalingMndEøs
import no.nav.familie.ba.sak.kjerne.brev.hjemler.HjemmeltekstUtleder
import no.nav.familie.ba.sak.kjerne.endretutbetaling.domene.EndretUtbetalingAndelRepository
import no.nav.familie.ba.sak.kjerne.eøs.kompetanse.KompetanseRepository
import no.nav.familie.ba.sak.kjerne.eøs.utenlandskperiodebeløp.UtenlandskPeriodebeløpRepository
Expand All @@ -73,6 +75,7 @@ import no.nav.familie.ba.sak.kjerne.vedtak.vedtaksperiode.VedtaksperiodeService
import no.nav.familie.ba.sak.kjerne.vedtak.vedtaksperiode.Vedtaksperiodetype
import no.nav.familie.ba.sak.kjerne.vilkårsvurdering.VilkårsvurderingService
import no.nav.familie.ba.sak.sikkerhet.SaksbehandlerContext
import no.nav.familie.unleash.UnleashService
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.time.LocalDate
Expand All @@ -99,6 +102,8 @@ class BrevService(
private val kompetanseRepository: KompetanseRepository,
private val valutakursRepository: ValutakursRepository,
private val endretUtbetalingAndelRepository: EndretUtbetalingAndelRepository,
private val hjemmeltekstUtleder: HjemmeltekstUtleder,
private val unleashService: UnleashService,
) {
fun hentVedtaksbrevData(vedtak: Vedtak): Vedtaksbrev {
val behandling = vedtak.behandling
Expand Down Expand Up @@ -468,14 +473,22 @@ class BrevService(
val refusjonEøs = refusjonEøsRepository.finnRefusjonEøsForBehandling(behandlingId)

val hjemler =
hentHjemler(
behandlingId = behandlingId,
erFritekstIBrev = sorterteVedtaksperioderMedBegrunnelser.any { it.fritekster.isNotEmpty() },
vedtaksperioder = sorterteVedtaksperioderMedBegrunnelser,
målform = personopplysningGrunnlag.søker.målform,
vedtakKorrigertHjemmelSkalMedIBrev = korrigertVedtak != null,
refusjonEøsHjemmelSkalMedIBrev = refusjonEøs.isNotEmpty(),
)
if (unleashService.isEnabled(FeatureToggleConfig.BRUK_OMSKRIVING_AV_HJEMLER_I_BREV, false)) {
hjemmeltekstUtleder.utledHjemmeltekst(
behandlingId = behandlingId,
vedtakKorrigertHjemmelSkalMedIBrev = korrigertVedtak != null,
sorterteVedtaksperioderMedBegrunnelser = sorterteVedtaksperioderMedBegrunnelser,
)
} else {
hentHjemler(
behandlingId = behandlingId,
erFritekstIBrev = sorterteVedtaksperioderMedBegrunnelser.any { it.fritekster.isNotEmpty() },
vedtaksperioder = sorterteVedtaksperioderMedBegrunnelser,
målform = personopplysningGrunnlag.søker.målform,
vedtakKorrigertHjemmelSkalMedIBrev = korrigertVedtak != null,
refusjonEøsHjemmelSkalMedIBrev = refusjonEøs.isNotEmpty(),
)
}

val organisasjonsnummer =
vedtak.behandling.fagsak.institusjon
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.kjerne.brev.domene.SanityEØSBegrunnelse

fun utledEØSForordningen883Hjemler(
sanityEøsBegrunnelser: List<SanityEØSBegrunnelse>,
) = sanityEøsBegrunnelser.flatMap { it.hjemlerEØSForordningen883 }.distinct()
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.kjerne.brev.domene.SanityEØSBegrunnelse

fun utledEØSForordningen987Hjemler(
sanityEøsBegrunnelser: List<SanityEØSBegrunnelse>,
refusjonEøsHjemmelSkalMedIBrev: Boolean,
): List<String> {
val hjemler = mutableListOf<String>()

hjemler.addAll(sanityEøsBegrunnelser.flatMap { it.hjemlerEØSForordningen987 })

if (refusjonEøsHjemmelSkalMedIBrev) {
hjemler.add("60")
}

return hjemler.distinct()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.kjerne.brev.domene.SanityBegrunnelse
import no.nav.familie.ba.sak.kjerne.brev.domene.SanityEØSBegrunnelse

fun utledFolketrygdlovenHjemler(
sanityBegrunnelser: List<SanityBegrunnelse>,
sanityEøsBegrunnelser: List<SanityEØSBegrunnelse>,
): List<String> {
val hjemlerFolketrygdloven = sanityBegrunnelser.flatMap { it.hjemlerFolketrygdloven }
val hjemlerFolketrygdlovenEøs = sanityEøsBegrunnelser.flatMap { it.hjemlerFolketrygdloven }
return (hjemlerFolketrygdloven + hjemlerFolketrygdlovenEøs).distinct()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

fun utledForvaltningsloverHjemler(vedtakKorrigertHjemmelSkalMedIBrev: Boolean): List<String> =
if (vedtakKorrigertHjemmelSkalMedIBrev) {
listOf("35")
} else {
emptyList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.common.Feil
import no.nav.familie.ba.sak.common.Utils
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.Målform

fun kombinerHjemler(
lform: Målform,
separasjonsavtaleStorbritanniaHjemler: List<String>,
ordinæreHjemler: List<String>,
folketrygdlovenHjemler: List<String>,
sForordningen883Hjemler: List<String>,
sForordningen987Hjemler: List<String>,
forvaltningslovenHjemler: List<String>,
): List<String> {
val alleHjemlerForBegrunnelser = mutableListOf<String>()

// Rekkefølgen her er viktig
if (separasjonsavtaleStorbritanniaHjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add(
"${
when (målform) {
Målform.NB -> "Separasjonsavtalen mellom Storbritannia og Norge artikkel"
Målform.NN -> "Separasjonsavtalen mellom Storbritannia og Noreg artikkel"
}
} ${
Utils.slåSammen(
separasjonsavtaleStorbritanniaHjemler,
)
}",
)
}

if (ordinæreHjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add(
"${
when (målform) {
Målform.NB -> "barnetrygdloven"
Målform.NN -> "barnetrygdlova"
}
} ${
hjemlerTilHjemmeltekst(
hjemler = ordinæreHjemler,
lovForHjemmel = "barnetrygdloven",
)
}",
)
}

if (folketrygdlovenHjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add(
"${
when (målform) {
Målform.NB -> "folketrygdloven"
Målform.NN -> "folketrygdlova"
}
} ${
hjemlerTilHjemmeltekst(
hjemler = folketrygdlovenHjemler,
lovForHjemmel = "folketrygdloven",
)
}",
)
}

if (eøsForordningen883Hjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add("EØS-forordning 883/2004 artikkel ${Utils.slåSammen(eøsForordningen883Hjemler)}")
}

if (eøsForordningen987Hjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add("EØS-forordning 987/2009 artikkel ${Utils.slåSammen(eøsForordningen987Hjemler)}")
}

if (forvaltningslovenHjemler.isNotEmpty()) {
alleHjemlerForBegrunnelser.add(
"${
when (målform) {
Målform.NB -> "forvaltningsloven"
Målform.NN -> "forvaltningslova"
}
} ${
hjemlerTilHjemmeltekst(
hjemler = forvaltningslovenHjemler,
lovForHjemmel = "forvaltningsloven",
)
}",
)
}

return alleHjemlerForBegrunnelser
}

private fun hjemlerTilHjemmeltekst(
hjemler: List<String>,
lovForHjemmel: String,
): String =
when (hjemler.size) {
0 -> throw Feil("Kan ikke lage hjemmeltekst for $lovForHjemmel når ingen begrunnelser har hjemler fra $lovForHjemmel knyttet til seg.")
1 -> "§ ${hjemler[0]}"
else -> "§§ ${Utils.slåSammen(hjemler)}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.common.FunksjonellFeil
import no.nav.familie.ba.sak.integrasjoner.sanity.SanityService
import no.nav.familie.ba.sak.kjerne.brev.slåSammen
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.PersongrunnlagService
import no.nav.familie.ba.sak.kjerne.vedtak.domene.VedtaksperiodeMedBegrunnelser
import no.nav.familie.ba.sak.kjerne.vedtak.refusjonEøs.RefusjonEøsService
import no.nav.familie.ba.sak.kjerne.vilkårsvurdering.VilkårsvurderingService
import org.springframework.stereotype.Component

@Component
class HjemmeltekstUtleder(
private val vilkårsvurderingService: VilkårsvurderingService,
private val sanityService: SanityService,
private val persongrunnlagService: PersongrunnlagService,
private val refusjonEøsService: RefusjonEøsService,
) {
fun utledHjemmeltekst(
behandlingId: Long,
vedtakKorrigertHjemmelSkalMedIBrev: Boolean,
sorterteVedtaksperioderMedBegrunnelser: List<VedtaksperiodeMedBegrunnelser>,
): String {
val vilkårsvurdering = vilkårsvurderingService.hentAktivForBehandling(behandlingId = behandlingId)
if (vilkårsvurdering == null) {
throw IllegalStateException("Finner ikke vilkårsvurdering ved begrunning av vedtak")
}

val begrunnelseTilSanityBegrunnelse = sanityService.hentSanityBegrunnelser()
val eøsBegrunnelseTilSanityEøsBegrunnelse = sanityService.hentSanityEØSBegrunnelser()

val sanitybegrunnelser =
sorterteVedtaksperioderMedBegrunnelser.flatMap { vedtaksperiode ->
vedtaksperiode.begrunnelser.mapNotNull { begrunnelse ->
begrunnelseTilSanityBegrunnelse[begrunnelse.standardbegrunnelse]
}
}

val sanityEøsBegrunnelser =
sorterteVedtaksperioderMedBegrunnelser.flatMap { vedtaksperiode ->
vedtaksperiode.eøsBegrunnelser.mapNotNull { eøsBegrunnelse ->
eøsBegrunnelseTilSanityEøsBegrunnelse[eøsBegrunnelse.begrunnelse]
}
}

val alleHjemlerForBegrunnelser =
kombinerHjemler(
målform = persongrunnlagService.hentSøkersMålform(behandlingId = behandlingId),
separasjonsavtaleStorbritanniaHjemler = utledSeprasjonsavtaleStorbritanniaHjemler(sanityEøsBegrunnelser = sanityEøsBegrunnelser),
ordinæreHjemler =
utledOrdinæreHjemler(
sanityBegrunnelser = sanitybegrunnelser,
sanityEøsBegrunnelser = sanityEøsBegrunnelser,
opplysningspliktHjemlerSkalMedIBrev = !vilkårsvurdering.erOpplysningspliktVilkårOppfylt(),
finnesVedtaksperiodeMedFritekst = sorterteVedtaksperioderMedBegrunnelser.any { it.fritekster.isNotEmpty() },
),
folketrygdlovenHjemler = utledFolketrygdlovenHjemler(sanityBegrunnelser = sanitybegrunnelser, sanityEøsBegrunnelser = sanityEøsBegrunnelser),
eøsForordningen883Hjemler = utledEØSForordningen883Hjemler(sanityEøsBegrunnelser = sanityEøsBegrunnelser),
eøsForordningen987Hjemler = utledEØSForordningen987Hjemler(sanityEøsBegrunnelser = sanityEøsBegrunnelser, refusjonEøsHjemmelSkalMedIBrev = refusjonEøsService.harRefusjonEøsPåBehandling(behandlingId)),
forvaltningslovenHjemler = utledForvaltningsloverHjemler(vedtakKorrigertHjemmelSkalMedIBrev = vedtakKorrigertHjemmelSkalMedIBrev),
)

return slåSammenHjemlerAvUlikeTyper(alleHjemlerForBegrunnelser)
}
}

private fun slåSammenHjemlerAvUlikeTyper(hjemler: List<String>) =
when (hjemler.size) {
0 -> throw FunksjonellFeil("Ingen hjemler var knyttet til begrunnelsen(e) som er valgt. Du må velge minst én begrunnelse som er knyttet til en hjemmel.")
1 -> hjemler.single()
else -> hjemler.slåSammen()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.kjerne.brev.domene.SanityBegrunnelse
import no.nav.familie.ba.sak.kjerne.brev.domene.SanityEØSBegrunnelse
import no.nav.familie.ba.sak.kjerne.vedtak.begrunnelser.hjemlerTilhørendeFritekst

fun utledOrdinæreHjemler(
sanityBegrunnelser: List<SanityBegrunnelse>,
sanityEøsBegrunnelser: List<SanityEØSBegrunnelse>,
opplysningspliktHjemlerSkalMedIBrev: Boolean,
finnesVedtaksperiodeMedFritekst: Boolean,
): List<String> {
val ordinæreHjemler = mutableSetOf<String>()
ordinæreHjemler.addAll(sanityBegrunnelser.flatMap { it.hjemler })
ordinæreHjemler.addAll(sanityEøsBegrunnelser.flatMap { it.hjemler })

if (opplysningspliktHjemlerSkalMedIBrev) {
val hjemlerNårOpplysningspliktIkkeOppfylt = listOf("17", "18")
ordinæreHjemler.addAll(hjemlerNårOpplysningspliktIkkeOppfylt)
}

if (finnesVedtaksperiodeMedFritekst) {
ordinæreHjemler.addAll(hjemlerTilhørendeFritekst.map { it.toString() })
}

return ordinæreHjemler
.map { it.toInt() }
.sorted()
.map { it.toString() }
.distinct()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.nav.familie.ba.sak.kjerne.brev.hjemler

import no.nav.familie.ba.sak.kjerne.brev.domene.SanityEØSBegrunnelse

fun utledSeprasjonsavtaleStorbritanniaHjemler(sanityEøsBegrunnelser: List<SanityEØSBegrunnelse>) =
sanityEøsBegrunnelser
.flatMap { it.hjemlerSeperasjonsavtalenStorbritannina }
.distinct()
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,6 @@ class RefusjonEøsService(
refusjonEøs.land = restRefusjonEøs.land
refusjonEøs.refusjonAvklart = restRefusjonEøs.refusjonAvklart
}

fun harRefusjonEøsPåBehandling(behandlingId: Long): Boolean = refusjonEøsRepository.finnRefusjonEøsForBehandling(behandlingId).isNotEmpty()
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import jakarta.persistence.OneToMany
import jakarta.persistence.SequenceGenerator
import jakarta.persistence.Table
import no.nav.familie.ba.sak.common.BaseEntitet
import no.nav.familie.ba.sak.kjerne.autovedtak.fødselshendelse.Resultat
import no.nav.familie.ba.sak.kjerne.behandling.domene.Behandling
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.PersonopplysningGrunnlag
import no.nav.familie.ba.sak.sikkerhet.RollestyringMotDatabase
Expand Down Expand Up @@ -84,6 +85,15 @@ data class Vilkårsvurdering(
.andreVurderinger
.singleOrNull { it.type == AnnenVurderingType.OPPLYSNINGSPLIKT }

fun erOpplysningspliktVilkårOppfylt(): Boolean {
val opplysningspliktVilkår =
personResultater
.single { it.erSøkersResultater() }
.andreVurderinger
.singleOrNull { it.type == AnnenVurderingType.OPPLYSNINGSPLIKT }
return opplysningspliktVilkår?.resultat == Resultat.OPPFYLT
}

fun hentPersonResultaterTil(aktørId: String): List<VilkårResultat> =
personResultater.find { it.aktør.aktørId == aktørId }?.vilkårResultater?.toList()
?: throw IllegalStateException("Fant ikke personresultat for $aktørId")
Expand Down
Loading

0 comments on commit 1e3f687

Please sign in to comment.