Skip to content

Commit

Permalink
Merge pull request #693 from navikt/perioder-flere-fnr
Browse files Browse the repository at this point in the history
Håndter at personer kan ha flere identer når vi starter, avslutter og henter periode
  • Loading branch information
marenger committed Mar 9, 2023
2 parents 5826862 + 8bb0ad6 commit 6e71529
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ import java.time.LocalDateTime
interface ArbeidssokerperiodeRepository {
fun startPeriode(foedselsnummer: Foedselsnummer, fraDato: LocalDateTime)
fun avsluttPeriode(foedselsnummer: Foedselsnummer, tilDato: LocalDateTime)
fun avsluttPeriode(id: Int, tilDato: LocalDateTime)
fun hentPerioder(foedselsnummer: Foedselsnummer): List<ArbeidssokerperiodeDto>
fun hentPerioder(gjeldendeFoedselsnummer: Foedselsnummer, historiskeFoedselsnummer: List<Foedselsnummer>): List<ArbeidssokerperiodeDto>
}
Original file line number Diff line number Diff line change
@@ -1,45 +1,55 @@
package no.nav.fo.veilarbregistrering.arbeidssoker

import no.nav.fo.veilarbregistrering.arbeidssoker.formidlingsgruppe.FormidlingsgruppeEndretEvent
import no.nav.fo.veilarbregistrering.bruker.Foedselsnummer
import no.nav.fo.veilarbregistrering.bruker.Bruker
import no.nav.fo.veilarbregistrering.bruker.Periode
import no.nav.fo.veilarbregistrering.bruker.UserService
import no.nav.fo.veilarbregistrering.log.logger
import java.time.LocalDateTime

class ArbeidssokerperiodeService(val repository: ArbeidssokerperiodeRepository) {
class ArbeidssokerperiodeService(
private val repository: ArbeidssokerperiodeRepository,
private val userService: UserService
) {

fun startPeriode(foedselsnummer: Foedselsnummer) {
if (harAktivPeriode(foedselsnummer)) {
fun startPeriode(bruker: Bruker) {
if (harAktivPeriode(bruker)) {
throw IllegalStateException("Bruker har allerede en aktiv periode")
}

repository.startPeriode(foedselsnummer, LocalDateTime.now())
repository.startPeriode(bruker.gjeldendeFoedselsnummer, LocalDateTime.now())
}

fun behandleFormidlingsgruppeEvent(formidlingsgruppeEndretEvent: FormidlingsgruppeEndretEvent) {
if (formidlingsgruppeEndretEvent.erArbeidssoker()) {
return
}

if (!harAktivPeriode(formidlingsgruppeEndretEvent.foedselsnummer)) {
return
val bruker = userService.finnBrukerGjennomPdlForSystemkontekst(formidlingsgruppeEndretEvent.foedselsnummer)
val aktivPeriode = hentAktivPeriode(bruker) ?: return

if (aktivPeriode.foedselsnummer != bruker.gjeldendeFoedselsnummer) {
// TODO skal vi i dette tilfellet oppdatere fødselsnummeret på perioden?
logger.warn("Avslutter periode for person som har et annet gjeldende fødselsnummer enn den aktive perioden")
}

repository.avsluttPeriode(foedselsnummer = formidlingsgruppeEndretEvent.foedselsnummer, LocalDateTime.now())
repository.avsluttPeriode(id = aktivPeriode.id, LocalDateTime.now())
}

fun hentPerioder(foedselsnummer: Foedselsnummer): List<Periode> {
return repository.hentPerioder(foedselsnummer).map { Periode(it.fra.toLocalDate(), it.til?.toLocalDate()) }
fun hentPerioder(bruker: Bruker): List<Periode> {
return repository.hentPerioder(bruker.gjeldendeFoedselsnummer, bruker.historiskeFoedselsnummer)
.map { Periode(it.fra.toLocalDate(), it.til?.toLocalDate()) }
}

private fun harAktivPeriode(foedselsnummer: Foedselsnummer): Boolean {
return harAktivPeriode(repository.hentPerioder(foedselsnummer))
private fun harAktivPeriode(bruker: Bruker): Boolean {
return hentAktivPeriode(bruker) != null
}

private fun harAktivPeriode(perioder: List<ArbeidssokerperiodeDto>): Boolean {
if (perioder.isEmpty()) {
return false
}
private fun hentAktivPeriode(bruker: Bruker): ArbeidssokerperiodeDto? {
val perioder = repository.hentPerioder(bruker.gjeldendeFoedselsnummer, bruker.historiskeFoedselsnummer)

if (perioder.isEmpty()) return null

return perioder.first().til == null
return perioder.find { it.til == null }
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package no.nav.fo.veilarbregistrering.arbeidssoker.formidlingsgruppe

import no.nav.common.featuretoggle.UnleashClient
import no.nav.fo.veilarbregistrering.aktorIdCache.AktorIdCacheService
import no.nav.fo.veilarbregistrering.arbeidssoker.ArbeidssokerperiodeService
import no.nav.fo.veilarbregistrering.arbeidssoker.Arbeidssoker
import no.nav.fo.veilarbregistrering.arbeidssoker.ArbeidssokerperiodeService
import no.nav.fo.veilarbregistrering.arbeidssoker.perioder.ArbeidssokerperiodeAvsluttetProducer
import no.nav.fo.veilarbregistrering.arbeidssoker.perioder.PopulerArbeidssokerperioderService
import no.nav.fo.veilarbregistrering.bruker.Foedselsnummer
Expand All @@ -18,7 +17,6 @@ class FormidlingsgruppeMottakService(
private val aktorIdCacheService: AktorIdCacheService,
private val populerArbeidssokerperioderService: PopulerArbeidssokerperioderService,
private val arbeidssokerperiodeAvsluttetProducer: ArbeidssokerperiodeAvsluttetProducer,
private val unleashClient: UnleashClient,
private val arbeidssokerperiodeService: ArbeidssokerperiodeService
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ArbeidssokerService(
) {

fun hentArbeidssokerperioder(bruker: Bruker, forespurtPeriode: Periode?): Arbeidssokerperioder {
val lagredePerioder = arbeidssokerperiodeService.hentPerioder(bruker.gjeldendeFoedselsnummer)
val lagredePerioder = arbeidssokerperiodeService.hentPerioder(bruker)

forespurtPeriode?.let {
return Arbeidssokerperioder.of(lagredePerioder.filter { it.overlapperMed(forespurtPeriode) }.map { Arbeidssokerperiode(it) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class UserService(
}
fun finnBrukerGjennomPdl(fnr: Foedselsnummer): Bruker = map(pdlOppslagGateway.hentIdenter(fnr))

fun finnBrukerGjennomPdlForSystemkontekst(fnr: Foedselsnummer): Bruker = map(pdlOppslagGateway.hentIdenter(fnr, true))

fun hentBruker(aktorId: AktorId): Bruker = map(pdlOppslagGateway.hentIdenter(aktorId))

fun getEnhetIdFromUrlOrThrow(): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,15 +329,13 @@ class ServiceBeansConfig {
aktorIdCacheService: AktorIdCacheService,
populerArbeidssokerperioderService: PopulerArbeidssokerperioderService,
arbeidssokerperiodeAvsluttetProducer: ArbeidssokerperiodeAvsluttetProducer,
unleashClient: UnleashClient,
arbeidssokerperiodeService: ArbeidssokerperiodeService
): FormidlingsgruppeMottakService {
return FormidlingsgruppeMottakService(
formidlingsgruppeRepository,
aktorIdCacheService,
populerArbeidssokerperioderService,
arbeidssokerperiodeAvsluttetProducer,
unleashClient,
arbeidssokerperiodeService
)
}
Expand Down Expand Up @@ -439,7 +437,10 @@ class ServiceBeansConfig {
}

@Bean
fun arbeidssokerperiodeService(arbeidssokerperiodeRepository: ArbeidssokerperiodeRepository): ArbeidssokerperiodeService {
return ArbeidssokerperiodeService(arbeidssokerperiodeRepository)
fun arbeidssokerperiodeService(
arbeidssokerperiodeRepository: ArbeidssokerperiodeRepository,
userService: UserService
): ArbeidssokerperiodeService {
return ArbeidssokerperiodeService(arbeidssokerperiodeRepository, userService)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,36 @@ class ArbeidssokerperiodeRepositoryImpl(private val db: NamedParameterJdbcTempla
}
}

override fun avsluttPeriode(id: Int, tilDato: LocalDateTime) {
val params = mapOf(
"id" to id,
"tilOgMed" to tilDato
)
val sql = "UPDATE $ARBEIDSSOKERPERIODE_TABELL SET til_og_med = :tilOgMed WHERE id = :id"

try {
db.update(sql, params)
} catch (e: DataIntegrityViolationException) {
throw DataIntegrityViolationException("Avslutning av arbeidssøkerperiode feilet", e)
}
}

override fun hentPerioder(foedselsnummer: Foedselsnummer): List<ArbeidssokerperiodeDto> {
val params = mapOf("foedselsnummer" to foedselsnummer.foedselsnummer)
val sql = "SELECT * FROM $ARBEIDSSOKERPERIODE_TABELL WHERE foedselsnummer = :foedselsnummer ORDER BY id DESC"
return db.query(sql, params, arbeidssokerperiodeMapper)
}

override fun hentPerioder(
gjeldendeFoedselsnummer: Foedselsnummer,
historiskeFoedselsnummer: List<Foedselsnummer>
): List<ArbeidssokerperiodeDto> {
val foedselsnummerList = historiskeFoedselsnummer + gjeldendeFoedselsnummer
val params = mapOf("foedselsnummerList" to foedselsnummerList.map(Foedselsnummer::stringValue))
val sql = "SELECT * FROM $ARBEIDSSOKERPERIODE_TABELL WHERE foedselsnummer IN (:foedselsnummerList)"
return db.query(sql, params, arbeidssokerperiodeMapper)
}

companion object {
const val ARBEIDSSOKERPERIODE_TABELL = "arbeidssokerperiode"
private val arbeidssokerperiodeMapper = RowMapper { rs, _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ open class BrukerRegistreringService(
}

try {
arbeidssokerperiodeService.startPeriode(bruker.gjeldendeFoedselsnummer)
arbeidssokerperiodeService.startPeriode(bruker)
} catch (e: RuntimeException) {
LOG.error("Feil ved starting av ny arbeidssøkerperiode", e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import no.nav.fo.veilarbregistrering.oppfolging.OppfolgingGateway
import no.nav.fo.veilarbregistrering.registrering.Tilstandsfeil
import no.nav.fo.veilarbregistrering.registrering.bruker.BrukerTilstandService
import no.nav.fo.veilarbregistrering.registrering.bruker.RegistreringType
import no.nav.fo.veilarbregistrering.registrering.ordinaer.BrukerRegistreringService
import org.springframework.transaction.annotation.Transactional

open class ReaktiveringBrukerService(
Expand Down Expand Up @@ -39,7 +38,7 @@ open class ReaktiveringBrukerService(
oppfolgingGateway.reaktiverBruker(bruker.gjeldendeFoedselsnummer)

try {
arbeidssokerperiodeService.startPeriode(bruker.gjeldendeFoedselsnummer)
arbeidssokerperiodeService.startPeriode(bruker)
} catch (e: RuntimeException) {
LOG.error("Feil ved starting av ny arbeidssøkerperiode", e)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package no.nav.fo.veilarbregistrering.arbeidssoker

import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import io.mockk.*
import no.nav.fo.veilarbregistrering.arbeidssoker.formidlingsgruppe.FormidlingsgruppeEndretEventTestdataBuilder.formidlingsgruppeEndret
import no.nav.fo.veilarbregistrering.bruker.AktorId
import no.nav.fo.veilarbregistrering.bruker.Bruker
import no.nav.fo.veilarbregistrering.bruker.Foedselsnummer
import no.nav.fo.veilarbregistrering.bruker.UserService
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand All @@ -13,59 +14,66 @@ import java.time.LocalDateTime
internal class ArbeidssokerperiodeServiceTest {
private lateinit var repository: ArbeidssokerperiodeRepository
private lateinit var service: ArbeidssokerperiodeService
private lateinit var userService: UserService

@BeforeEach
fun setUp () {
repository = mockk()
service = ArbeidssokerperiodeService(repository)
userService = mockk()
service = ArbeidssokerperiodeService(repository, userService)
}

@Test
fun `kaster exception hvis bruker har en aktiv periode`() {
val fnr = Foedselsnummer("42")
every { repository.hentPerioder(any()) } returns listOf(ArbeidssokerperiodeDto(1, fnr, LocalDateTime.now()))
every { repository.hentPerioder(any(), any()) } returns listOf(ArbeidssokerperiodeDto(1, fnr, LocalDateTime.now()))

assertThrows(IllegalStateException::class.java) {
service.startPeriode(fnr)
service.startPeriode(Bruker(fnr, AktorId("1234"), emptyList()))
}
}

@Test
fun `starter periode for bruker`() {
val fnr = Foedselsnummer("42")
every { repository.hentPerioder(any()) } returns emptyList()
every { repository.startPeriode(any(), any()) } returns Unit
val bruker = Bruker(Foedselsnummer("42"), AktorId("1234"), emptyList())
every { repository.hentPerioder(any(), any()) } returns emptyList()
every { repository.startPeriode(any(), any()) } just Runs

service.startPeriode(fnr)
service.startPeriode(bruker)

verify(exactly = 1) { repository.startPeriode(foedselsnummer = fnr, any())}
verify(exactly = 1) { repository.startPeriode(bruker.gjeldendeFoedselsnummer, any()) }
}

@Test
fun `gjør ingenting hvis ikke formidlingsgruppe er ISERV eller IARBS`() {
every { repository.avsluttPeriode(any(), any()) } returns Unit
every { repository.avsluttPeriode(any<Int>(), any()) } just Runs
service.behandleFormidlingsgruppeEvent(formidlingsgruppeEndretEvent = formidlingsgruppeEndret(LocalDateTime.now(), formidlingsgruppe = "ARBS"))
verify(exactly = 0) { repository.avsluttPeriode(any(), any()) }
verify(exactly = 0) { repository.avsluttPeriode(any<Int>(), any()) }
}

@Test
fun `gjør ingenting hvis ikke bruker har en aktiv periode` () {
every { repository.avsluttPeriode(any(), any()) } returns Unit
every { repository.hentPerioder(any())} returns emptyList()
every { userService.finnBrukerGjennomPdlForSystemkontekst(any()) } returns
Bruker(Foedselsnummer("12345678910"), AktorId("1234"), emptyList())
every { repository.avsluttPeriode(any<Int>(), any()) } just Runs
every { repository.hentPerioder(any(), any()) } returns emptyList()

service.behandleFormidlingsgruppeEvent(formidlingsgruppeEndretEvent = formidlingsgruppeEndret(LocalDateTime.now(), formidlingsgruppe = "ISERV"))

verify(exactly = 0) { repository.avsluttPeriode(any(), any()) }
verify(exactly = 0) { repository.avsluttPeriode(any<Int>(), any()) }
}

@Test
fun `avslutte periode for bruker`() {
every { repository.avsluttPeriode(any(), any()) } returns Unit
every { repository.hentPerioder(Foedselsnummer("12345678910"))} returns listOf(ArbeidssokerperiodeDto(1, Foedselsnummer("12345678910"), LocalDateTime.now()))
every { userService.finnBrukerGjennomPdlForSystemkontekst(any()) } returns
Bruker(Foedselsnummer("12345678910"), AktorId("1234"), emptyList())
every { repository.avsluttPeriode(any<Int>(), any()) } just Runs
every { repository.hentPerioder(Foedselsnummer("12345678910"), any()) } returns
listOf(ArbeidssokerperiodeDto(1, Foedselsnummer("12345678910"), LocalDateTime.now()))

service.behandleFormidlingsgruppeEvent(formidlingsgruppeEndretEvent = formidlingsgruppeEndret(LocalDateTime.now(), formidlingsgruppe = "ISERV"))

verify(exactly = 1) { repository.avsluttPeriode(Foedselsnummer("12345678910"), any()) }
verify(exactly = 1) { repository.avsluttPeriode(any<Int>(), any()) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class FormidlingsgruppeMottakServiceTest {
mockk(relaxed = true),
mockk(relaxed = true),
mockk(relaxed = true),
mockk(relaxed = true),
mockk(relaxed = true)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ArbeidssokerServiceHentArbeidssokerperioderTest {
arbeidssokerperiodeService
)

every { arbeidssokerperiodeService.hentPerioder(any()) } returns emptyList()
every { arbeidssokerperiodeService.hentPerioder(any<Bruker>()) } returns emptyList()
}

@Test
Expand All @@ -32,7 +32,7 @@ class ArbeidssokerServiceHentArbeidssokerperioderTest {
LocalDate.of(2020, 1, 2),
LocalDate.of(2020, 5, 1)
)
every { arbeidssokerperiodeService.hentPerioder(BRUKER_3.gjeldendeFoedselsnummer) } returns finnArbeissokerperioder(BRUKER_3.gjeldendeFoedselsnummer)
every { arbeidssokerperiodeService.hentPerioder(BRUKER_3) } returns finnArbeissokerperioder(BRUKER_3.gjeldendeFoedselsnummer)
val arbeidssokerperiodes = arbeidssokerService.hentArbeidssokerperioder(BRUKER_3, forespurtPeriode)
assertThat(arbeidssokerperiodes.eldsteFoerst()).containsExactly(
ARBEIDSSOKERPERIODE_1,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package no.nav.fo.veilarbregistrering.db.arbeidssoker

import no.nav.fo.veilarbregistrering.bruker.AktorId
import no.nav.fo.veilarbregistrering.bruker.Bruker
import no.nav.fo.veilarbregistrering.bruker.Foedselsnummer
import no.nav.fo.veilarbregistrering.bruker.FoedselsnummerTestdataBuilder.aremark
import no.nav.fo.veilarbregistrering.config.db.DatabaseConfig
import no.nav.fo.veilarbregistrering.config.db.RepositoryConfig
Expand All @@ -10,8 +13,9 @@ import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabas
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest
import org.springframework.test.context.ContextConfiguration
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull

@JdbcTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
Expand All @@ -34,6 +38,39 @@ internal class ArbeidssokerperiodeRepositoryImplTest(@Autowired private val arbe
arbeidssokerperiodeRepositoryImpl.startPeriode(aremark(), LocalDateTime.now())
arbeidssokerperiodeRepositoryImpl.avsluttPeriode(aremark(), LocalDateTime.now())
val arbeidssokerperioder = arbeidssokerperiodeRepositoryImpl.hentPerioder(aremark())
assertNotEquals(null, arbeidssokerperioder.first().til)
assertNotNull(arbeidssokerperioder.first().til)
}

@Test
fun `skal avslutte periode for id`() {
val gjeldendeFnr = aremark()
val start = LocalDateTime.now().minusYears(3)
val slutt = LocalDateTime.now()
arbeidssokerperiodeRepositoryImpl.startPeriode(gjeldendeFnr, start)
val aktivPeriode = arbeidssokerperiodeRepositoryImpl.hentPerioder(gjeldendeFnr, emptyList())
arbeidssokerperiodeRepositoryImpl.avsluttPeriode(aktivPeriode.first().id, slutt)
val arbeidssokerperioder = arbeidssokerperiodeRepositoryImpl.hentPerioder(gjeldendeFnr, emptyList())

assertEquals(1, arbeidssokerperioder.size)
assertEquals(start.truncatedTo(ChronoUnit.MILLIS), arbeidssokerperioder.first().fra.truncatedTo(ChronoUnit.MILLIS))
assertEquals(slutt.truncatedTo(ChronoUnit.MILLIS), arbeidssokerperioder.first().til?.truncatedTo(ChronoUnit.MILLIS))
}

@Test
fun `skal hente alle perioder for en person med historiske og gjeldende fødselsnummer`() {
val historiskeFoedselsnummer = listOf(Foedselsnummer("12345678911"), Foedselsnummer("12345678910"))
val bruker = Bruker(aremark(), AktorId("1234"), historiskeFoedselsnummer)
arbeidssokerperiodeRepositoryImpl.startPeriode(historiskeFoedselsnummer.first(), LocalDateTime.now().minusYears(5))
arbeidssokerperiodeRepositoryImpl.avsluttPeriode(historiskeFoedselsnummer.first(), LocalDateTime.now().minusYears(5).plusMonths(7))

arbeidssokerperiodeRepositoryImpl.startPeriode(historiskeFoedselsnummer.last(), LocalDateTime.now().minusYears(3))
arbeidssokerperiodeRepositoryImpl.avsluttPeriode(historiskeFoedselsnummer.last(), LocalDateTime.now().minusYears(3).plusMonths(7))

arbeidssokerperiodeRepositoryImpl.startPeriode(aremark(), LocalDateTime.now().minusDays(21))

val arbeidssokerperioder = arbeidssokerperiodeRepositoryImpl.hentPerioder(bruker.gjeldendeFoedselsnummer, bruker.historiskeFoedselsnummer)

assertEquals(3, arbeidssokerperioder.size)

}
}

0 comments on commit 6e71529

Please sign in to comment.