Skip to content

Commit

Permalink
NAV-22311: Sørger for at BehandleSak-oppgave opprettes med korrekt ko…
Browse files Browse the repository at this point in the history
…mbinasjon av saksbehandler og enhet (#4760)

Favro:
[NAV-22311](https://favro.com/organization/98c34fb974ce445eac854de0/1844bbac3b6605eacc8f5543?card=NAV-22311)
### 💰 Hva skal gjøres, og hvorfor?
Som en følge av kommende endring i `OppgaveSystemet` (OS), er vi nødt
til å sikre at kombinasjonen av saksbehandler (tilordnetRessurs) og
enhet (tildeltEnhetsnr) er korrekt. Altså at saksbehandler som settes
som ansvarlig på en oppgave har tilgang til å behandle barnetrygd-saker
på vegne av enheten som settes. Denne valideringen i OS har ikke
eksistert tidligere, men skapte en del feil for oss da den ble rullet
ut. Endringen i OS er rullet tilbake i påvente av at vi gjør nødvendige
justeringer på vår side.

For å løse dette har vi laget servicen `NavIdentOgEnhetService` som
henter saksbehandlers enhets-tilganger (Axsys) og sjekker disse opp mot
den geografiske behandlende enheten arbeidsfordelings-tjenesten (NORG2)
mener at skal stå som behandlende enhet. Resultatet er en gyldig
kombinasjon av saksbehandler/nav-ident og enhetsnummer.
* Enheter som 2103 (Vikafossen) og 4863 (Midlertidig enhet) håndteres
etter "spesial"-regler (se Favro)
* Øvrige enheter håndteres likt (se Favro)

Fordi vi potensielt overstyrer enheten arbeidsfordelings-tjenesten
(NORG2) har satt, sørger vi for å oppdatere
`arbeidsfordelingPåBehandling` ved endringer.

Når saksbehandler manuelt endrer behandlende enhet, sørger vi også for
at saksbehandler på oppgave blir nullstilt.

### ✅ Checklist
- [x] Jeg har testet mine endringer i henhold til akseptansekriteriene
🕵️
- [ ] Jeg har config- eller sql-endringer.
- [ ] Jeg har skrevet tester.

### 💬 Ønsker du en muntlig gjennomgang?
- [ ] Ja
- [x] Nei, endringene er utviklet i gruppe på 3.

---------

Co-authored-by: thoalm <[email protected]>
  • Loading branch information
bragejahren and thoalm authored Sep 27, 2024
1 parent a30f6ff commit ff51522
Show file tree
Hide file tree
Showing 15 changed files with 1,052 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class FeatureToggleConfig {
// NAV-21071 lagt bak toggle og kan evt fjernes på sikt hvis man ikke har trengt å skru den på igjen
const val SKAL_OPPRETTE_FREMLEGGSOPPGAVE_EØS_MEDLEM = "familie-ba-sak.skalOpprettFremleggsoppgaveDersomEOSMedlem"

// NAV-22311
const val OPPRETT_SAK_PÅ_RIKTIG_ENHET_OG_SAKSBEHANDLER = "familie-ba-ks-sak.opprett-sak-paa-riktig-enhet-og-saksbehandler"

// 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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import no.nav.familie.ba.sak.task.DistribuerDokumentDTO
import no.nav.familie.ba.sak.task.OpprettTaskService.Companion.RETRY_BACKOFF_5000MS
import no.nav.familie.http.client.AbstractRestClient
import no.nav.familie.kontrakter.felles.Fagsystem
import no.nav.familie.kontrakter.felles.NavIdent
import no.nav.familie.kontrakter.felles.PersonIdent
import no.nav.familie.kontrakter.felles.Ressurs
import no.nav.familie.kontrakter.felles.Tema
Expand All @@ -28,6 +29,8 @@ import no.nav.familie.kontrakter.felles.dokdist.Distribusjonstidspunkt
import no.nav.familie.kontrakter.felles.dokdist.ManuellAdresse
import no.nav.familie.kontrakter.felles.dokdistkanal.Distribusjonskanal
import no.nav.familie.kontrakter.felles.dokdistkanal.DokdistkanalRequest
import no.nav.familie.kontrakter.felles.enhet.Enhet
import no.nav.familie.kontrakter.felles.enhet.HentEnheterNavIdentHarTilgangTilRequest
import no.nav.familie.kontrakter.felles.journalpost.Journalpost
import no.nav.familie.kontrakter.felles.journalpost.JournalposterForBrukerRequest
import no.nav.familie.kontrakter.felles.kodeverk.KodeverkDto
Expand All @@ -38,7 +41,6 @@ import no.nav.familie.kontrakter.felles.oppgave.Oppgave
import no.nav.familie.kontrakter.felles.oppgave.OppgaveResponse
import no.nav.familie.kontrakter.felles.oppgave.OpprettOppgaveRequest
import no.nav.familie.kontrakter.felles.organisasjon.Organisasjon
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.annotation.Cacheable
Expand Down Expand Up @@ -233,6 +235,17 @@ class IntegrasjonClient(
}
}

fun hentEnheterSomNavIdentHarTilgangTil(navIdent: NavIdent): List<Enhet> {
val uri = URI.create("$integrasjonUri/enhetstilganger")
return kallEksternTjenesteRessurs(
tjeneste = "enhetstilganger",
uri = uri,
formål = "Hent enheter en NAV-ident har tilgang til",
) {
postForEntity(uri, HentEnheterNavIdentHarTilgangTilRequest(navIdent, Tema.BAR))
}
}

fun opprettOppgave(opprettOppgave: OpprettOppgaveRequest): OppgaveResponse {
val uri = URI.create("$integrasjonUri/oppgave/opprett")

Expand Down Expand Up @@ -519,7 +532,6 @@ class IntegrasjonClient(
}

companion object {
private val logger = LoggerFactory.getLogger(IntegrasjonClient::class.java)
const val VEDTAK_VEDLEGG_FILNAVN = "NAV_33-0005bm-10.2016.pdf"
const val VEDTAK_VEDLEGG_TITTEL = "Stønadsmottakerens rettigheter og plikter (Barnetrygd)"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package no.nav.familie.ba.sak.integrasjoner.oppgave

import no.nav.familie.ba.sak.common.Feil
import no.nav.familie.ba.sak.integrasjoner.familieintegrasjoner.IntegrasjonClient
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.BarnetrygdEnhet
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.BarnetrygdEnhet.Companion.erGyldigBehandlendeBarnetrygdEnhet
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.ArbeidsfordelingPåBehandling
import no.nav.familie.kontrakter.felles.NavIdent
import org.springframework.stereotype.Service

@Service
class OppgaveArbeidsfordelingService(
private val integrasjonClient: IntegrasjonClient,
) {
fun finnArbeidsfordelingForOppgave(
arbeidsfordelingPåBehandling: ArbeidsfordelingPåBehandling,
navIdent: NavIdent?,
): OppgaveArbeidsfordeling =
when (arbeidsfordelingPåBehandling.behandlendeEnhetId) {
BarnetrygdEnhet.MIDLERTIDIG_ENHET.enhetsnummer -> håndterMidlertidigEnhet4863(navIdent)
BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer -> håndterVikafossenEnhet2103(navIdent)
else -> håndterAndreEnheter(navIdent, arbeidsfordelingPåBehandling)
}

private fun håndterMidlertidigEnhet4863(
navIdent: NavIdent?,
): OppgaveArbeidsfordeling {
if (navIdent == null) {
throw Feil("Kan ikke sette ${BarnetrygdEnhet.MIDLERTIDIG_ENHET} om man mangler NAV-ident")
}
val enheterNavIdentHarTilgangTil =
integrasjonClient
.hentEnheterSomNavIdentHarTilgangTil(navIdent)
.filter { erGyldigBehandlendeBarnetrygdEnhet(it.enhetsnummer) }
.filter { it.enhetsnummer != BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer }
if (enheterNavIdentHarTilgangTil.isEmpty()) {
throw Feil("Fant ingen passende enhetsnummer for nav-ident $navIdent")
}
// Velger bare det første enhetsnummeret i tilfeller hvor man har flere, avklart med fag
val nyBehandlendeEnhet = enheterNavIdentHarTilgangTil.first()
return OppgaveArbeidsfordeling(
navIdent,
nyBehandlendeEnhet.enhetsnummer,
nyBehandlendeEnhet.enhetsnavn,
)
}

private fun håndterVikafossenEnhet2103(
navIdent: NavIdent?,
): OppgaveArbeidsfordeling {
if (navIdent == null) {
throw Feil("Kan ikke sette ${BarnetrygdEnhet.VIKAFOSSEN} om man mangler NAV-ident")
}
val harTilgangTilVikafossenEnhet2103 =
integrasjonClient
.hentEnheterSomNavIdentHarTilgangTil(navIdent)
.filter { erGyldigBehandlendeBarnetrygdEnhet(it.enhetsnummer) }
.any { it.enhetsnummer == BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer }
if (!harTilgangTilVikafossenEnhet2103) {
return OppgaveArbeidsfordeling(
null,
BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer,
BarnetrygdEnhet.VIKAFOSSEN.enhetsnavn,
)
}
return OppgaveArbeidsfordeling(
navIdent,
BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer,
BarnetrygdEnhet.VIKAFOSSEN.enhetsnavn,
)
}

private fun håndterAndreEnheter(
navIdent: NavIdent?,
arbeidsfordelingPåBehandling: ArbeidsfordelingPåBehandling,
): OppgaveArbeidsfordeling {
if (navIdent == null) {
// navIdent er null ved automatisk journalføring
return OppgaveArbeidsfordeling(
null,
arbeidsfordelingPåBehandling.behandlendeEnhetId,
arbeidsfordelingPåBehandling.behandlendeEnhetNavn,
)
}
val enheterNavIdentHarTilgangTil =
integrasjonClient
.hentEnheterSomNavIdentHarTilgangTil(navIdent)
.filter { erGyldigBehandlendeBarnetrygdEnhet(it.enhetsnummer) }
.filter { it.enhetsnummer != BarnetrygdEnhet.VIKAFOSSEN.enhetsnummer }
if (enheterNavIdentHarTilgangTil.isEmpty()) {
throw Feil("Fant ingen passende enhetsnummer for NAV-ident $navIdent")
}
val harTilgangTilBehandledeEnhet =
enheterNavIdentHarTilgangTil.any {
it.enhetsnummer == arbeidsfordelingPåBehandling.behandlendeEnhetId
}
if (!harTilgangTilBehandledeEnhet) {
// Velger bare det første enhetsnummeret i tilfeller hvor man har flere, avklart med fag
val nyBehandlendeEnhet = enheterNavIdentHarTilgangTil.first()
return OppgaveArbeidsfordeling(
navIdent,
nyBehandlendeEnhet.enhetsnummer,
nyBehandlendeEnhet.enhetsnavn,
)
}
return OppgaveArbeidsfordeling(
navIdent,
arbeidsfordelingPåBehandling.behandlendeEnhetId,
arbeidsfordelingPåBehandling.behandlendeEnhetNavn,
)
}
}

data class OppgaveArbeidsfordeling(
val navIdent: NavIdent?,
val enhetsnummer: String,
val enhetsnavn: String,
) {
init {
require(enhetsnummer.length == 4) { "Enhetsnummer må være 4 siffer" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import io.micrometer.core.instrument.Metrics
import no.nav.familie.ba.sak.common.Feil
import no.nav.familie.ba.sak.common.FunksjonellFeil
import no.nav.familie.ba.sak.common.secureLogger
import no.nav.familie.ba.sak.config.FeatureToggleConfig
import no.nav.familie.ba.sak.integrasjoner.familieintegrasjoner.IntegrasjonClient
import no.nav.familie.ba.sak.integrasjoner.oppgave.domene.DbOppgave
import no.nav.familie.ba.sak.integrasjoner.oppgave.domene.OppgaveRepository
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.ArbeidsfordelingPåBehandlingRepository
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.hentArbeidsfordelingPåBehandling
import no.nav.familie.ba.sak.kjerne.behandling.BehandlingHentOgPersisterService
import no.nav.familie.ba.sak.kjerne.behandling.domene.Behandling
import no.nav.familie.ba.sak.kjerne.behandling.domene.BehandlingRepository
import no.nav.familie.ba.sak.kjerne.logg.LoggService
import no.nav.familie.ba.sak.task.OpprettTaskService
import no.nav.familie.ba.sak.task.dto.ManuellOppgaveType
import no.nav.familie.kontrakter.felles.NavIdent
import no.nav.familie.kontrakter.felles.Tema
import no.nav.familie.kontrakter.felles.oppgave.FinnOppgaveRequest
import no.nav.familie.kontrakter.felles.oppgave.FinnOppgaveResponseDto
Expand All @@ -26,6 +29,7 @@ import no.nav.familie.kontrakter.felles.oppgave.Oppgavetype
import no.nav.familie.kontrakter.felles.oppgave.OpprettOppgaveRequest
import no.nav.familie.kontrakter.felles.oppgave.StatusEnum.FEILREGISTRERT
import no.nav.familie.kontrakter.felles.oppgave.StatusEnum.FERDIGSTILT
import no.nav.familie.unleash.UnleashService
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.time.LocalDate
Expand All @@ -38,10 +42,12 @@ class OppgaveService(
private val integrasjonClient: IntegrasjonClient,
private val behandlingRepository: BehandlingRepository,
private val oppgaveRepository: OppgaveRepository,
private val arbeidsfordelingPåBehandlingRepository: ArbeidsfordelingPåBehandlingRepository,
private val opprettTaskService: OpprettTaskService,
private val loggService: LoggService,
private val behandlingHentOgPersisterService: BehandlingHentOgPersisterService,
private val oppgaveArbeidsfordelingService: OppgaveArbeidsfordelingService,
private val arbeidsfordelingPåBehandlingRepository: ArbeidsfordelingPåBehandlingRepository,
private val unleashService: UnleashService,
) {
private val antallOppgaveTyper: MutableMap<Oppgavetype, Counter> = mutableMapOf()

Expand All @@ -68,15 +74,17 @@ class OppgaveService(

eksisterendeOppgave.gsakId
} else {
val arbeidsfordelingsenhet =
arbeidsfordelingPåBehandlingRepository.finnArbeidsfordelingPåBehandling(behandling.id)

if (arbeidsfordelingsenhet == null) {
logger.warn(
"Fant ikke behandlende enhet på behandling ${behandling.id} " +
"ved opprettelse av $oppgavetype-oppgave.",
val arbeidsfordelingPåBehandling =
arbeidsfordelingPåBehandlingRepository
.hentArbeidsfordelingPåBehandling(behandlingId)

val oppgaveArbeidsfordeling =
oppgaveArbeidsfordelingService.finnArbeidsfordelingForOppgave(
arbeidsfordelingPåBehandling = arbeidsfordelingPåBehandling,
navIdent = tilordnetNavIdent?.let { NavIdent(it) },
)
}

val opprettSakPåRiktigEnhetOgSaksbehandlerToggleErPå = unleashService.isEnabled(FeatureToggleConfig.OPPRETT_SAK_PÅ_RIKTIG_ENHET_OG_SAKSBEHANDLER, false)

val opprettOppgave =
OpprettOppgaveRequest(
Expand All @@ -86,10 +94,10 @@ class OppgaveService(
oppgavetype = oppgavetype,
fristFerdigstillelse = fristForFerdigstillelse,
beskrivelse = lagOppgaveTekst(fagsakId, beskrivelse),
enhetsnummer = arbeidsfordelingsenhet?.behandlendeEnhetId,
enhetsnummer = if (opprettSakPåRiktigEnhetOgSaksbehandlerToggleErPå) oppgaveArbeidsfordeling.enhetsnummer else arbeidsfordelingPåBehandling.behandlendeEnhetId,
behandlingstema = behandling.tilOppgaveBehandlingTema().value,
behandlingstype = behandling.kategori.tilOppgavebehandlingType().value,
tilordnetRessurs = tilordnetNavIdent,
tilordnetRessurs = if (opprettSakPåRiktigEnhetOgSaksbehandlerToggleErPå) oppgaveArbeidsfordeling.navIdent?.ident else tilordnetNavIdent,
behandlesAvApplikasjon =
when {
oppgavetyperSomBehandlesAvBaSak.contains(oppgavetype) -> "familie-ba-sak"
Expand All @@ -104,6 +112,20 @@ class OppgaveService(

økTellerForAntallOppgaveTyper(oppgavetype)

if (opprettSakPåRiktigEnhetOgSaksbehandlerToggleErPå) {
val erEnhetsnummerEndret = arbeidsfordelingPåBehandling.behandlendeEnhetId != oppgaveArbeidsfordeling.enhetsnummer

if (erEnhetsnummerEndret) {
arbeidsfordelingPåBehandlingRepository.save(
arbeidsfordelingPåBehandling.copy(
behandlendeEnhetId = oppgaveArbeidsfordeling.enhetsnummer,
behandlendeEnhetNavn = oppgaveArbeidsfordeling.enhetsnavn,
manueltOverstyrt = false,
),
)
}
}

opprettetOppgaveId
}
}
Expand Down Expand Up @@ -192,7 +214,8 @@ class OppgaveService(
if (oppgave.status == FERDIGSTILT && oppgave.oppgavetype == Oppgavetype.VurderLivshendelse.value) {
dbOppgave.erFerdigstilt = true
} else {
integrasjonClient.tilordneEnhetForOppgave(oppgaveId = oppgave.id!!, nyEnhet = nyEnhet)
val oppgaveOppdatering = Oppgave(id = oppgave.id, tildeltEnhetsnr = nyEnhet, tilordnetRessurs = null, mappeId = null)
patchOppgave(oppgaveOppdatering)
}
}
}
Expand Down Expand Up @@ -286,6 +309,7 @@ class OppgaveService(
oppgaveErAvsluttet -> {
logger.info("Oppgave ${dbOppgave.gsakId} er allerede avsluttet")
}

else -> {
val nyFrist = LocalDate.parse(gammelOppgave.fristFerdigstillelse!!).plus(forlengelse)
val nyOppgave = gammelOppgave.copy(fristFerdigstillelse = nyFrist.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import no.nav.familie.ba.sak.integrasjoner.oppgave.OppgaveService
import no.nav.familie.ba.sak.integrasjoner.pdl.PersonopplysningerService
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.ArbeidsfordelingPåBehandling
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.ArbeidsfordelingPåBehandlingRepository
import no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene.hentArbeidsfordelingPåBehandling
import no.nav.familie.ba.sak.kjerne.behandling.domene.Behandling
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.PersonopplysningGrunnlagRepository
import no.nav.familie.ba.sak.kjerne.grunnlag.personopplysninger.barn
Expand Down Expand Up @@ -38,8 +39,7 @@ class ArbeidsfordelingService(
endreBehandlendeEnhet: RestEndreBehandlendeEnhet,
) {
val aktivArbeidsfordelingPåBehandling =
arbeidsfordelingPåBehandlingRepository.finnArbeidsfordelingPåBehandling(behandling.id)
?: throw Feil("Finner ikke tilknyttet arbeidsfordelingsenhet på behandling ${behandling.id}")
arbeidsfordelingPåBehandlingRepository.hentArbeidsfordelingPåBehandling(behandling.id)

val forrigeArbeidsfordelingsenhet =
Arbeidsfordelingsenhet(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package no.nav.familie.ba.sak.kjerne.arbeidsfordeling

enum class BarnetrygdEnhet(
val enhetsnummer: String,
val enhetsnavn: String,
) {
VIKAFOSSEN("2103", "NAV Vikafossen"),
DRAMMEN("4806", "NAV Familie- og pensjonsytelser Drammen"),
VADSØ("4820", "NAV Familie- og pensjonsytelser Vadsø"),
OSLO("4833", "NAV Familie- og pensjonsytelser Oslo 1"),
STORD("4842", "NAV Familie- og pensjonsytelser Stord"),
STEINKJER("4817", "NAV Familie- og pensjonsytelser Steinkjer"),
MIDLERTIDIG_ENHET("4863", "Midlertidig enhet"),
;

override fun toString(): String = "$enhetsnavn ($enhetsnummer)"

companion object {
private val GYLDIGE_BEHANDLENDE_BARNETRYGD_ENHETER: List<BarnetrygdEnhet> =
listOf(
VIKAFOSSEN,
DRAMMEN,
VADSØ,
OSLO,
STORD,
STEINKJER,
)

fun erGyldigBehandlendeBarnetrygdEnhet(enhetsnummer: String): Boolean =
GYLDIGE_BEHANDLENDE_BARNETRYGD_ENHETER.any { it.enhetsnummer == enhetsnummer }
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package no.nav.familie.ba.sak.kjerne.arbeidsfordeling.domene

import no.nav.familie.ba.sak.common.Feil
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query

interface ArbeidsfordelingPåBehandlingRepository : JpaRepository<ArbeidsfordelingPåBehandling, Long> {
@Query(value = "SELECT apb FROM ArbeidsfordelingPåBehandling apb WHERE apb.behandlingId = :behandlingId")
fun finnArbeidsfordelingPåBehandling(behandlingId: Long): ArbeidsfordelingPåBehandling?
}

// Extension-function fordi default methods for JPA ikke er støttet uten @JvmDefaultWithCompatibility
fun ArbeidsfordelingPåBehandlingRepository.hentArbeidsfordelingPåBehandling(behandlingId: Long): ArbeidsfordelingPåBehandling =
finnArbeidsfordelingPåBehandling(behandlingId) ?: throw Feil("Finner ikke tilknyttet arbeidsfordelingsenhet på behandling $behandlingId")
Loading

0 comments on commit ff51522

Please sign in to comment.