From 371645d0928f8df0ec23cd04506a0b7b19013730 Mon Sep 17 00:00:00 2001 From: Sondre Lefsaker Date: Tue, 26 Nov 2024 15:51:40 +0100 Subject: [PATCH 1/2] endre fra avbrutt_tidspunkt til avsluttet_tidspunkt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dette fører til av vi lagrer når en gjennomføring blir avsluttet, som igjen trigger at alle endringer på status blir replikert til bigquery. - Status GJENNOMFORES blir utledet i stedet for PLANLAGT --- .../TiltaksgjennomforingRoutes.kt | 3 +- .../TiltaksgjennomforingService.kt | 20 +- .../TiltaksgjennomforingValidator.kt | 2 +- .../db/TiltaksgjennomforingRepository.kt | 78 ++--- .../task/UpdateTiltaksgjennomforingStatus.kt | 80 +++-- .../R__tiltaksgjennomforing_admin_view.sql | 32 +- .../R__veilederflate_tiltak_view.sql | 16 +- .../migration/V208__gjennomforing_status.sql | 29 ++ .../arenaadapter/ArenaAdapterServiceTest.kt | 12 +- .../TiltaksgjennomforingRoutesTest.kt | 2 +- .../TiltaksgjennomforingServiceTest.kt | 7 +- .../TiltaksgjennomforingValidatorTest.kt | 11 +- .../db/TiltaksgjennomforingRepositoryTest.kt | 25 +- .../UpdateTiltaksgjennomforingStatusTest.kt | 319 +++++++++++------- 14 files changed, 376 insertions(+), 260 deletions(-) create mode 100644 mulighetsrommet-api/src/main/resources/db/migration/V208__gjennomforing_status.sql diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutes.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutes.kt index c9ae8e19ca..dfd1da28f5 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutes.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutes.kt @@ -30,6 +30,7 @@ import no.nav.mulighetsrommet.domain.serializers.UUIDSerializer import no.nav.mulighetsrommet.utdanning.db.UtdanningslopDbo import org.koin.ktor.ext.inject import java.time.LocalDate +import java.time.LocalDateTime import java.util.* fun Route.tiltaksgjennomforingRoutes() { @@ -118,7 +119,7 @@ fun Route.tiltaksgjennomforingRoutes() { ) } - service.avbryt(id, aarsak, navIdent) + service.setAvsluttet(id, LocalDateTime.now(), aarsak, EndretAv.NavAnsatt(navIdent)) call.respond(HttpStatusCode.OK) } diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingService.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingService.kt index 289289d8cd..ee2f012773 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingService.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingService.kt @@ -23,6 +23,7 @@ import no.nav.mulighetsrommet.domain.constants.ArenaMigrering.Tiltaksgjennomfori import no.nav.mulighetsrommet.domain.dto.AvbruttAarsak import no.nav.mulighetsrommet.domain.dto.NavIdent import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingEksternV1Dto +import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatus import no.nav.mulighetsrommet.notifications.NotificationRepository import no.nav.mulighetsrommet.notifications.NotificationType import no.nav.mulighetsrommet.notifications.ScheduledNotification @@ -157,10 +158,23 @@ class TiltaksgjennomforingService( logEndring("Endret avtale", dto, EndretAv.NavAnsatt(navIdent), tx) } - fun avbryt(id: UUID, aarsak: AvbruttAarsak, navIdent: NavIdent) = db.transaction { tx -> - tiltaksgjennomforinger.avbryt(tx, id, LocalDateTime.now(), aarsak) + fun setAvsluttet( + id: UUID, + avsluttetTidspunkt: LocalDateTime, + avsluttetAarsak: AvbruttAarsak?, + endretAv: EndretAv, + ): Unit = db.transaction { tx -> + tiltaksgjennomforinger.setAvsluttet(tx, id, avsluttetTidspunkt, avsluttetAarsak) + val dto = getOrError(id, tx) - logEndring("Gjennomføring ble avbrutt", dto, EndretAv.NavAnsatt(navIdent), tx) + val operation = when (dto.status.status) { + TiltaksgjennomforingStatus.AVSLUTTET -> "Gjennomføringen ble avsluttet" + TiltaksgjennomforingStatus.AVBRUTT -> "Gjennomføringen ble avbrutt" + TiltaksgjennomforingStatus.AVLYST -> "Gjennomføringen ble avlyst" + else -> throw IllegalStateException("Gjennomføringen ble nettopp avsluttet, men status ${dto.status.status} indikerer noe annet") + } + logEndring(operation, dto, endretAv, tx) + tiltaksgjennomforingKafkaProducer.publish(dto.toTiltaksgjennomforingV1Dto()) } diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidator.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidator.kt index efaa9238e5..ef8bfcd13e 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidator.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidator.kt @@ -291,7 +291,7 @@ class TiltaksgjennomforingValidator( add( ValidationError.of( TiltaksgjennomforingDbo::navn, - "Du kan ikke gjøre endringer på en gjennomføring som ikke er aktiv", + "Du kan ikke gjøre endringer på en gjennomføring som er ${previous.status.status.name.lowercase()}", ), ) } diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepository.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepository.kt index 827c5cd7d7..2bb3ec880c 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepository.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepository.kt @@ -415,7 +415,7 @@ class TiltaksgjennomforingRepository(private val db: Database) { where (start_dato <= :periode_slutt) and (slutt_dato >= :periode_start or slutt_dato is null) and - (avbrutt_tidspunkt > :periode_start or avbrutt_tidspunkt is null) and + (avsluttet_tidspunkt > :periode_start or avsluttet_tidspunkt is null) and not exists ( select 1 from refusjonskrav @@ -431,36 +431,6 @@ class TiltaksgjennomforingRepository(private val db: Database) { .let { db.run(it) } } - fun getAllByDateIntervalAndNotAvbrutt( - dateIntervalStart: LocalDate, - dateIntervalEnd: LocalDate, - pagination: Pagination, - ): List { - logger.info("Henter alle tiltaksgjennomføringer med start- eller sluttdato mellom $dateIntervalStart og $dateIntervalEnd, og ikke avbrutt") - - @Language("PostgreSQL") - val query = """ - select g.id::uuid - from tiltaksgjennomforing g join tiltakstype t on g.tiltakstype_id = t.id - where t.tiltakskode is not null and g.avbrutt_tidspunkt is null and ( - (g.start_dato > :date_interval_start and g.start_dato <= :date_interval_end) or - (g.slutt_dato >= :date_interval_start and g.slutt_dato < :date_interval_end)) - order by g.id - limit :limit offset :offset - """.trimIndent() - - return queryOf( - query, - mapOf( - "date_interval_start" to dateIntervalStart, - "date_interval_end" to dateIntervalEnd, - ) + pagination.parameters, - ) - .map { it.uuid("id") } - .asList - .let { db.run(it) } - } - fun delete(id: UUID): Int = db.useSession { delete(id, it) } @@ -546,21 +516,24 @@ class TiltaksgjennomforingRepository(private val db: Database) { return queryOf(query, avtaleId, gjennomforingId).asUpdate.let { tx.run(it) } } - fun avbryt(id: UUID, tidspunkt: LocalDateTime, aarsak: AvbruttAarsak): Int = db.transaction { - avbryt(it, id, tidspunkt, aarsak) + fun setAvsluttet(id: UUID, tidspunkt: LocalDateTime, aarsak: AvbruttAarsak?): Int = db.transaction { + setAvsluttet(it, id, tidspunkt, aarsak) } - fun avbryt(tx: Session, id: UUID, tidspunkt: LocalDateTime, aarsak: AvbruttAarsak): Int { + fun setAvsluttet(tx: Session, id: UUID, tidspunkt: LocalDateTime, aarsak: AvbruttAarsak?): Int { @Language("PostgreSQL") val query = """ - update tiltaksgjennomforing set - avbrutt_tidspunkt = :tidspunkt, + update tiltaksgjennomforing + set avsluttet_tidspunkt = :tidspunkt, avbrutt_aarsak = :aarsak, - publisert = false + publisert = false, + apent_for_pamelding = false where id = :id::uuid """.trimIndent() - return tx.run(queryOf(query, mapOf("id" to id, "tidspunkt" to tidspunkt, "aarsak" to aarsak.name)).asUpdate) + val params = mapOf("id" to id, "tidspunkt" to tidspunkt, "aarsak" to aarsak?.name) + + return queryOf(query, params).asUpdate.runWithSession(tx) } fun frikobleKontaktpersonFraGjennomforing( @@ -615,30 +588,31 @@ class TiltaksgjennomforingRepository(private val db: Database) { val startDato = localDate("start_dato") val sluttDato = localDateOrNull("slutt_dato") - val avbruttTidspunkt = localDateTimeOrNull("avbrutt_tidspunkt") - val avbruttAarsak = stringOrNull("avbrutt_aarsak")?.let { AvbruttAarsak.fromString(it) } - val utdanningslop = stringOrNull("utdanningslop_json")?.let { Json.decodeFromString(it) } + val status = TiltaksgjennomforingStatus.valueOf(string("status")) + val avbrutt = when (status) { + TiltaksgjennomforingStatus.AVBRUTT, TiltaksgjennomforingStatus.AVLYST -> { + val aarsak = AvbruttAarsak.fromString(string("avbrutt_aarsak")) + AvbruttDto( + tidspunkt = localDateTime("avsluttet_tidspunkt"), + aarsak = aarsak, + beskrivelse = aarsak.beskrivelse, + ) + } + + else -> null + } + return TiltaksgjennomforingDto( id = uuid("id"), navn = string("navn"), tiltaksnummer = stringOrNull("tiltaksnummer"), startDato = startDato, sluttDato = sluttDato, - status = TiltaksgjennomforingStatusDto( - TiltaksgjennomforingStatus.valueOf(string("status")), - avbruttTidspunkt?.let { - requireNotNull(avbruttAarsak) - AvbruttDto( - tidspunkt = avbruttTidspunkt, - aarsak = avbruttAarsak, - beskrivelse = avbruttAarsak.beskrivelse, - ) - }, - ), + status = TiltaksgjennomforingStatusDto(status, avbrutt), apentForPamelding = boolean("apent_for_pamelding"), antallPlasser = intOrNull("antall_plasser"), avtaleId = uuidOrNull("avtale_id"), diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatus.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatus.kt index 52e1d19e1d..83686ca9b0 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatus.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatus.kt @@ -3,51 +3,71 @@ package no.nav.mulighetsrommet.api.gjennomforing.task import com.github.kagkarlsson.scheduler.task.helper.RecurringTask import com.github.kagkarlsson.scheduler.task.helper.Tasks import com.github.kagkarlsson.scheduler.task.schedule.Daily -import no.nav.mulighetsrommet.api.gjennomforing.db.TiltaksgjennomforingRepository -import no.nav.mulighetsrommet.api.gjennomforing.kafka.SisteTiltaksgjennomforingerV1KafkaProducer -import no.nav.mulighetsrommet.database.utils.DatabaseUtils -import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatus +import kotliquery.queryOf +import no.nav.mulighetsrommet.api.gjennomforing.TiltaksgjennomforingService +import no.nav.mulighetsrommet.api.services.EndretAv +import no.nav.mulighetsrommet.database.Database +import org.intellij.lang.annotations.Language import org.slf4j.LoggerFactory import java.time.LocalDate import java.time.LocalTime -import java.time.ZoneId +import java.util.* class UpdateTiltaksgjennomforingStatus( - private val tiltaksgjennomforingRepository: TiltaksgjennomforingRepository, - private val tiltaksgjennomforingKafkaProducer: SisteTiltaksgjennomforingerV1KafkaProducer, + private val db: Database, + private val gjennomforingService: TiltaksgjennomforingService, ) { private val logger = LoggerFactory.getLogger(javaClass) val task: RecurringTask = Tasks .recurring(javaClass.simpleName, Daily(LocalTime.MIDNIGHT)) - .execute { _, context -> - val lastSuccessDate = context.execution.lastSuccess - ?.let { LocalDate.ofInstant(it, ZoneId.systemDefault()) } - ?: LocalDate.now() - - oppdaterTiltaksgjennomforingStatus(LocalDate.now(), lastSuccessDate) + .execute { _, _ -> + oppdaterTiltaksgjennomforingStatus(LocalDate.now()) } - fun oppdaterTiltaksgjennomforingStatus(today: LocalDate, lastSuccessDate: LocalDate) { - logger.info("Oppdaterer statuser for gjennomføringer med start eller sluttdato mellom $lastSuccessDate og $today") + fun oppdaterTiltaksgjennomforingStatus(today: LocalDate) { + logger.info("Oppdaterer status på gjennomføringer som skal avsluttes fra og med dato $today") + + val gjennomforinger = getGjennomforingerSomSkalAvsluttes( + sluttDatoLessThan = today, + ) - val numberOfUpdates = DatabaseUtils.paginate(pageSize = 1000) { pagination -> - val tiltaksgjennomforinger = tiltaksgjennomforingRepository.getAllByDateIntervalAndNotAvbrutt( - dateIntervalStart = lastSuccessDate, - dateIntervalEnd = today, - pagination = pagination, + gjennomforinger.forEach { id -> + logger.info("Avslutter gjennomføring id=$id") + gjennomforingService.setAvsluttet( + id = id, + avsluttetTidspunkt = today.atStartOfDay(), + avsluttetAarsak = null, + endretAv = EndretAv.System, ) + } - tiltaksgjennomforinger.forEach { id -> - val gjennomforing = requireNotNull(tiltaksgjennomforingRepository.get(id)) - tiltaksgjennomforingKafkaProducer.publish(gjennomforing.toTiltaksgjennomforingV1Dto()) - if (gjennomforing.status.status == TiltaksgjennomforingStatus.AVSLUTTET) { - tiltaksgjennomforingRepository.setPublisert(gjennomforing.id, false) - } - } + logger.info("Oppdaterte status for ${gjennomforinger.size} gjennomføringer") + } - tiltaksgjennomforinger - } - logger.info("Oppdaterte status for $numberOfUpdates tiltaksgjennomføringer") + private fun getGjennomforingerSomSkalAvsluttes( + sluttDatoLessThan: LocalDate, + ): List = db.useSession { tx -> + @Language("PostgreSQL") + val query = """ + select gjennomforing.id, + gjennomforing.slutt_dato, + tiltaksgjennomforing_status(gjennomforing.start_dato, gjennomforing.slutt_dato, gjennomforing.avsluttet_tidspunkt) as current_status + from tiltaksgjennomforing gjennomforing + join tiltakstype on gjennomforing.tiltakstype_id = tiltakstype.id + where gjennomforing.avsluttet_tidspunkt is null + and gjennomforing.slutt_dato < :slutt_dato_lt + order by gjennomforing.id + limit :limit offset :offset + """.trimIndent() + + val params = mapOf( + "slutt_dato_lt" to sluttDatoLessThan, + ) + + queryOf(query, params) + .map { it.uuid("id") } + .asList + .runWithSession(tx) } } diff --git a/mulighetsrommet-api/src/main/resources/db/migration/R__tiltaksgjennomforing_admin_view.sql b/mulighetsrommet-api/src/main/resources/db/migration/R__tiltaksgjennomforing_admin_view.sql index c3aeac8eb0..0275c692fd 100644 --- a/mulighetsrommet-api/src/main/resources/db/migration/R__tiltaksgjennomforing_admin_view.sql +++ b/mulighetsrommet-api/src/main/resources/db/migration/R__tiltaksgjennomforing_admin_view.sql @@ -20,30 +20,30 @@ select gjennomforing.id, gjennomforing.estimert_ventetid_enhet, gjennomforing.sted_for_gjennomforing, gjennomforing.publisert, - gjennomforing.nav_region as nav_region_enhetsnummer, - nav_region.navn as nav_region_navn, - nav_region.type as nav_region_type, - nav_region.overordnet_enhet as nav_region_overordnet_enhet, - nav_region.status as nav_region_status, - gjennomforing.arena_ansvarlig_enhet as arena_nav_enhet_enhetsnummer, - arena_nav_enhet.navn as arena_nav_enhet_navn, - gjennomforing.avbrutt_tidspunkt, + gjennomforing.nav_region as nav_region_enhetsnummer, + nav_region.navn as nav_region_navn, + nav_region.type as nav_region_type, + nav_region.overordnet_enhet as nav_region_overordnet_enhet, + nav_region.status as nav_region_status, + gjennomforing.arena_ansvarlig_enhet as arena_nav_enhet_enhetsnummer, + arena_nav_enhet.navn as arena_nav_enhet_navn, + gjennomforing.avsluttet_tidspunkt, gjennomforing.avbrutt_aarsak, gjennomforing.tilgjengelig_for_arrangor_fra_og_med_dato, tiltaksgjennomforing_status(gjennomforing.start_dato, gjennomforing.slutt_dato, - gjennomforing.avbrutt_tidspunkt) as status, + gjennomforing.avsluttet_tidspunkt) as status, nav_kontaktpersoner_json, administratorer_json, nav_enheter_json, amo_kategorisering_json, - tiltakstype.id as tiltakstype_id, - tiltakstype.navn as tiltakstype_navn, - tiltakstype.tiltakskode as tiltakstype_tiltakskode, - arrangor.id as arrangor_id, - arrangor.organisasjonsnummer as arrangor_organisasjonsnummer, - arrangor.navn as arrangor_navn, - arrangor.slettet_dato is not null as arrangor_slettet, + tiltakstype.id as tiltakstype_id, + tiltakstype.navn as tiltakstype_navn, + tiltakstype.tiltakskode as tiltakstype_tiltakskode, + arrangor.id as arrangor_id, + arrangor.organisasjonsnummer as arrangor_organisasjonsnummer, + arrangor.navn as arrangor_navn, + arrangor.slettet_dato is not null as arrangor_slettet, arrangor_kontaktpersoner_json, utdanningslop_json from tiltaksgjennomforing gjennomforing diff --git a/mulighetsrommet-api/src/main/resources/db/migration/R__veilederflate_tiltak_view.sql b/mulighetsrommet-api/src/main/resources/db/migration/R__veilederflate_tiltak_view.sql index dfbb456652..011a59d929 100644 --- a/mulighetsrommet-api/src/main/resources/db/migration/R__veilederflate_tiltak_view.sql +++ b/mulighetsrommet-api/src/main/resources/db/migration/R__veilederflate_tiltak_view.sql @@ -18,18 +18,18 @@ select gjennomforing.id, gjennomforing.publisert, tiltaksgjennomforing_status(gjennomforing.start_dato, gjennomforing.slutt_dato, - gjennomforing.avbrutt_tidspunkt) as status, - tiltakstype.sanity_id as tiltakstype_sanity_id, - tiltakstype.navn as tiltakstype_navn, - tiltakstype.tiltakskode as tiltakstype_tiltakskode, - tiltakstype.innsatsgrupper as tiltakstype_innsatsgrupper, + gjennomforing.avsluttet_tidspunkt) as status, + tiltakstype.sanity_id as tiltakstype_sanity_id, + tiltakstype.navn as tiltakstype_navn, + tiltakstype.tiltakskode as tiltakstype_tiltakskode, + tiltakstype.innsatsgrupper as tiltakstype_innsatsgrupper, avtale.personvern_bekreftet, personopplysninger_som_kan_behandles, nav_enheter, nav_kontaktpersoner_json, - arrangor.id as arrangor_id, - arrangor.organisasjonsnummer as arrangor_organisasjonsnummer, - arrangor.navn as arrangor_navn, + arrangor.id as arrangor_id, + arrangor.organisasjonsnummer as arrangor_organisasjonsnummer, + arrangor.navn as arrangor_navn, arrangor_kontaktpersoner_json from tiltaksgjennomforing gjennomforing join tiltakstype on gjennomforing.tiltakstype_id = tiltakstype.id diff --git a/mulighetsrommet-api/src/main/resources/db/migration/V208__gjennomforing_status.sql b/mulighetsrommet-api/src/main/resources/db/migration/V208__gjennomforing_status.sql new file mode 100644 index 0000000000..12052d8992 --- /dev/null +++ b/mulighetsrommet-api/src/main/resources/db/migration/V208__gjennomforing_status.sql @@ -0,0 +1,29 @@ +alter table tiltaksgjennomforing + rename column avbrutt_tidspunkt to avsluttet_tidspunkt; + +alter table tiltaksgjennomforing + drop constraint ck_avbrutttidspunktaarsak; + +update tiltaksgjennomforing +set avsluttet_tidspunkt = slutt_dato + interval '1' day +where avsluttet_tidspunkt is null + and (slutt_dato + interval '1' day) < now(); + +create or replace function tiltaksgjennomforing_status( + start_dato date, + slutt_dato date, + avbrutt_tidspunkt timestamp +) + returns varchar + language plpgsql +as +$$ +begin + return case + when avbrutt_tidspunkt is null then 'GJENNOMFORES' + when avbrutt_tidspunkt < start_dato then 'AVLYST' + when slutt_dato is null or avbrutt_tidspunkt < slutt_dato + interval '1' day then 'AVBRUTT' + else 'AVSLUTTET' + end; +end; +$$; diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/arenaadapter/ArenaAdapterServiceTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/arenaadapter/ArenaAdapterServiceTest.kt index 989d70c936..db632bbc49 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/arenaadapter/ArenaAdapterServiceTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/arenaadapter/ArenaAdapterServiceTest.kt @@ -270,7 +270,7 @@ class ArenaAdapterServiceTest : } } - test("skal ikke overskrive avbrutt_tidspunkt") { + test("skal ikke overskrive avsluttet_tidspunkt") { val gjennomforing1 = TiltaksgjennomforingFixtures.Oppfolging1.copy( startDato = LocalDate.now(), sluttDato = LocalDate.now().plusDays(1), @@ -292,7 +292,7 @@ class ArenaAdapterServiceTest : // Setter den til custom avbrutt tidspunkt for å sjekke at den ikke overskrives med en "fake" en val jan2023 = LocalDateTime.of(2023, 1, 1, 0, 0, 0) - gjennomforinger.avbryt(gjennomforing1.id, jan2023, AvbruttAarsak.EndringHosArrangor) + gjennomforinger.setAvsluttet(gjennomforing1.id, jan2023, AvbruttAarsak.EndringHosArrangor) val arenaDbo = ArenaTiltaksgjennomforingDbo( id = gjennomforing1.id, @@ -315,13 +315,13 @@ class ArenaAdapterServiceTest : service.upsertTiltaksgjennomforing(arenaDbo) - val avbruttTidspunkt = - Query("select avbrutt_tidspunkt, avbrutt_aarsak from tiltaksgjennomforing where id = '${gjennomforing1.id}'") - .map { it.localDateTime("avbrutt_tidspunkt") to it.string("avbrutt_aarsak") } + val avbrutt = + Query("select avsluttet_tidspunkt, avbrutt_aarsak from tiltaksgjennomforing where id = '${gjennomforing1.id}'") + .map { it.localDateTime("avsluttet_tidspunkt") to it.string("avbrutt_aarsak") } .asSingle .let { database.db.run(it) } - avbruttTidspunkt shouldBe (jan2023 to "ENDRING_HOS_ARRANGOR") + avbrutt shouldBe (jan2023 to "ENDRING_HOS_ARRANGOR") } test("skal publisere til kafka når det er endringer fra Arena") { diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutesTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutesTest.kt index 4b579e8b35..6e81d7dd8e 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutesTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingRoutesTest.kt @@ -267,7 +267,7 @@ class TiltaksgjennomforingRoutesTest : FunSpec({ domain.initialize(database.db) - gjennomforinger.avbryt( + gjennomforinger.setAvsluttet( domain.gjennomforinger[1].id, LocalDateTime.now(), AvbruttAarsak.Feilregistrering, diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingServiceTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingServiceTest.kt index 902c419054..9242398f33 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingServiceTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingServiceTest.kt @@ -21,6 +21,7 @@ import no.nav.mulighetsrommet.api.gjennomforing.kafka.SisteTiltaksgjennomforinge import no.nav.mulighetsrommet.api.navansatt.db.NavAnsattDbo import no.nav.mulighetsrommet.api.navansatt.db.NavAnsattRepository import no.nav.mulighetsrommet.api.responses.ValidationError +import no.nav.mulighetsrommet.api.services.EndretAv import no.nav.mulighetsrommet.api.services.EndringshistorikkService import no.nav.mulighetsrommet.database.kotest.extensions.FlywayDatabaseTestListener import no.nav.mulighetsrommet.database.kotest.extensions.truncateAll @@ -29,6 +30,7 @@ import no.nav.mulighetsrommet.domain.dto.NavIdent import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatus import no.nav.mulighetsrommet.notifications.NotificationRepository import java.time.LocalDate +import java.time.LocalDateTime import java.util.* class TiltaksgjennomforingServiceTest : FunSpec({ @@ -233,10 +235,11 @@ class TiltaksgjennomforingServiceTest : FunSpec({ every { tiltaksgjennomforingKafkaProducer.publish(any()) } throws Exception() shouldThrow { - tiltaksgjennomforingService.avbryt( + tiltaksgjennomforingService.setAvsluttet( gjennomforing.id, + LocalDateTime.now(), AvbruttAarsak.Feilregistrering, - bertilNavIdent, + EndretAv.NavAnsatt(bertilNavIdent), ) } diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidatorTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidatorTest.kt index 54a5f0e3f7..316345c08e 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidatorTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/TiltaksgjennomforingValidatorTest.kt @@ -438,24 +438,29 @@ class TiltaksgjennomforingValidatorTest : FunSpec({ } test("should fail when is avbrutt") { - tiltaksgjennomforinger.avbryt(gjennomforing.id, LocalDateTime.now(), AvbruttAarsak.Feilregistrering) + tiltaksgjennomforinger.setAvsluttet( + gjennomforing.id, + LocalDateTime.now(), + AvbruttAarsak.Feilregistrering, + ) val validator = TiltaksgjennomforingValidator(tiltakstyper, avtaler, arrangorer, unleash) val previous = tiltaksgjennomforinger.get(gjennomforing.id) validator.validate(gjennomforing, previous).shouldBeLeft().shouldContainExactlyInAnyOrder( - ValidationError("navn", "Du kan ikke gjøre endringer på en gjennomføring som ikke er aktiv"), + ValidationError("navn", "Du kan ikke gjøre endringer på en gjennomføring som er avbrutt"), ) } test("should fail when is avsluttet") { tiltaksgjennomforinger.upsert(gjennomforing.copy(sluttDato = LocalDate.now().minusDays(2))) + tiltaksgjennomforinger.setAvsluttet(gjennomforing.id, LocalDateTime.now(), null) val validator = TiltaksgjennomforingValidator(tiltakstyper, avtaler, arrangorer, unleash) val previous = tiltaksgjennomforinger.get(gjennomforing.id) validator.validate(gjennomforing, previous).shouldBeLeft().shouldContainExactlyInAnyOrder( - ValidationError("navn", "Du kan ikke gjøre endringer på en gjennomføring som ikke er aktiv"), + ValidationError("navn", "Du kan ikke gjøre endringer på en gjennomføring som er avsluttet"), ) } } diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepositoryTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepositoryTest.kt index ebe5928092..1203a66e42 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepositoryTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/db/TiltaksgjennomforingRepositoryTest.kt @@ -101,7 +101,7 @@ class TiltaksgjennomforingRepositoryTest : FunSpec({ it.startDato shouldBe Oppfolging1.startDato it.sluttDato shouldBe Oppfolging1.sluttDato it.arenaAnsvarligEnhet shouldBe null - it.status.status shouldBe TiltaksgjennomforingStatus.AVSLUTTET + it.status.status shouldBe TiltaksgjennomforingStatus.GJENNOMFORES it.apentForPamelding shouldBe true it.antallPlasser shouldBe 12 it.avtaleId shouldBe Oppfolging1.avtaleId @@ -355,7 +355,7 @@ class TiltaksgjennomforingRepositoryTest : FunSpec({ tiltaksgjennomforinger.get(gjennomforing.id)?.publisert shouldBe false tiltaksgjennomforinger.setPublisert(gjennomforing.id, true) - tiltaksgjennomforinger.avbryt(gjennomforing.id, LocalDateTime.now(), AvbruttAarsak.Feilregistrering) + tiltaksgjennomforinger.setAvsluttet(gjennomforing.id, LocalDateTime.now(), AvbruttAarsak.Feilregistrering) tiltaksgjennomforinger.get(gjennomforing.id)?.publisert shouldBe false } @@ -713,23 +713,27 @@ class TiltaksgjennomforingRepositoryTest : FunSpec({ context("tiltaksgjennomforingstatus") { val tiltaksgjennomforinger = TiltaksgjennomforingRepository(database.db) - val dagensDato = LocalDate.now() + val dagensDato = LocalDate.of(2024, 6, 1) val enManedFrem = dagensDato.plusMonths(1) val enManedTilbake = dagensDato.minusMonths(1) val toManederFrem = dagensDato.plusMonths(2) val toManederTilbake = dagensDato.minusMonths(2) - test("status AVLYST og AVBRUTT utledes fra avbrutt-tidspunkt") { + test("status AVLYST, AVBRUTT, AVSLUTTET utledes fra avsluttet-tidspunkt") { forAll( row(enManedTilbake, enManedFrem, enManedTilbake.minusDays(1), TiltaksgjennomforingStatus.AVLYST), + row(enManedTilbake, null, enManedTilbake.minusDays(1), TiltaksgjennomforingStatus.AVLYST), row(enManedFrem, toManederFrem, dagensDato, TiltaksgjennomforingStatus.AVLYST), row(dagensDato, toManederFrem, dagensDato, TiltaksgjennomforingStatus.AVBRUTT), row(enManedTilbake, enManedFrem, enManedTilbake.plusDays(3), TiltaksgjennomforingStatus.AVBRUTT), - row(enManedFrem, toManederFrem, enManedFrem.plusMonths(2), TiltaksgjennomforingStatus.AVBRUTT), + row(enManedTilbake, enManedFrem, enManedFrem, TiltaksgjennomforingStatus.AVBRUTT), + row(enManedTilbake, null, enManedFrem, TiltaksgjennomforingStatus.AVBRUTT), + row(enManedFrem, toManederFrem, enManedFrem.plusMonths(2), TiltaksgjennomforingStatus.AVSLUTTET), + row(enManedTilbake, enManedFrem, enManedFrem.plusDays(1), TiltaksgjennomforingStatus.AVSLUTTET), ) { startDato, sluttDato, avbruttDato, expectedStatus -> tiltaksgjennomforinger.upsert(AFT1.copy(startDato = startDato, sluttDato = sluttDato)) - tiltaksgjennomforinger.avbryt( + tiltaksgjennomforinger.setAvsluttet( AFT1.id, avbruttDato.atStartOfDay(), AvbruttAarsak.Feilregistrering, @@ -739,14 +743,13 @@ class TiltaksgjennomforingRepositoryTest : FunSpec({ } } - test("hvis ikke avbrutt så blir status utledet basert på dagens dato") { + test("hvis ikke avsluttet så blir status GJENNOMFORES") { forAll( - row(toManederTilbake, enManedTilbake, TiltaksgjennomforingStatus.AVSLUTTET), - row(enManedTilbake, enManedFrem, TiltaksgjennomforingStatus.GJENNOMFORES), + row(toManederTilbake, enManedTilbake, TiltaksgjennomforingStatus.GJENNOMFORES), row(enManedTilbake, null, TiltaksgjennomforingStatus.GJENNOMFORES), row(dagensDato, dagensDato, TiltaksgjennomforingStatus.GJENNOMFORES), - row(enManedFrem, toManederFrem, TiltaksgjennomforingStatus.PLANLAGT), - row(enManedFrem, null, TiltaksgjennomforingStatus.PLANLAGT), + row(enManedFrem, toManederFrem, TiltaksgjennomforingStatus.GJENNOMFORES), + row(enManedFrem, null, TiltaksgjennomforingStatus.GJENNOMFORES), ) { startDato, sluttDato, status -> tiltaksgjennomforinger.upsert(AFT1.copy(startDato = startDato, sluttDato = sluttDato)) diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatusTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatusTest.kt index a2cba652fd..2a905b65ba 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatusTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/gjennomforing/task/UpdateTiltaksgjennomforingStatusTest.kt @@ -1,172 +1,239 @@ package no.nav.mulighetsrommet.api.gjennomforing.task import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.mockk.mockk import io.mockk.verify import io.mockk.verifyAll import no.nav.mulighetsrommet.api.databaseConfig -import no.nav.mulighetsrommet.api.fixtures.* -import no.nav.mulighetsrommet.api.gjennomforing.db.TiltaksgjennomforingDbo +import no.nav.mulighetsrommet.api.fixtures.AvtaleFixtures +import no.nav.mulighetsrommet.api.fixtures.MulighetsrommetTestDomain +import no.nav.mulighetsrommet.api.fixtures.TiltaksgjennomforingFixtures +import no.nav.mulighetsrommet.api.fixtures.TiltakstypeFixtures +import no.nav.mulighetsrommet.api.gjennomforing.TiltaksgjennomforingService import no.nav.mulighetsrommet.api.gjennomforing.db.TiltaksgjennomforingRepository import no.nav.mulighetsrommet.api.gjennomforing.kafka.SisteTiltaksgjennomforingerV1KafkaProducer import no.nav.mulighetsrommet.database.kotest.extensions.FlywayDatabaseTestListener import no.nav.mulighetsrommet.database.kotest.extensions.truncateAll import no.nav.mulighetsrommet.domain.dto.AvbruttAarsak -import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingEksternV1Dto -import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatus +import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatus.* +import no.nav.mulighetsrommet.domain.dto.TiltaksgjennomforingStatusDto +import no.nav.mulighetsrommet.notifications.NotificationRepository import java.time.LocalDate -import java.time.LocalDateTime import java.util.* -class UpdateTiltaksgjennomforingStatusTest : - FunSpec({ +class UpdateTiltaksgjennomforingStatusTest : FunSpec({ + val database = extension(FlywayDatabaseTestListener(databaseConfig)) + + fun createTask( + tiltaksgjennomforingKafkaProducer: SisteTiltaksgjennomforingerV1KafkaProducer, + ) = UpdateTiltaksgjennomforingStatus( + database.db, + TiltaksgjennomforingService( + db = database.db, + tiltaksgjennomforinger = TiltaksgjennomforingRepository(database.db), + tiltaksgjennomforingKafkaProducer = tiltaksgjennomforingKafkaProducer, + notificationRepository = NotificationRepository(database.db), + validator = mockk(relaxed = true), + documentHistoryService = mockk(relaxed = true), + navAnsattService = mockk(relaxed = true), + ), + ) + + context("oppdater statuser på tiltaksgjennomføringer") { + val gjennomforing1 = TiltaksgjennomforingFixtures.Oppfolging1.copy( + id = UUID.randomUUID(), + startDato = LocalDate.of(2023, 1, 1), + sluttDato = LocalDate.of(2023, 12, 31), + ) + val gjennomforing2 = TiltaksgjennomforingFixtures.Oppfolging1.copy( + id = UUID.randomUUID(), + startDato = LocalDate.of(2023, 1, 1), + sluttDato = LocalDate.of(2023, 1, 31), + ) + val gjennomforing3 = TiltaksgjennomforingFixtures.Oppfolging1.copy( + id = UUID.randomUUID(), + startDato = LocalDate.of(2023, 1, 1), + sluttDato = LocalDate.of(2023, 1, 31), + ) + val domain = MulighetsrommetTestDomain( + tiltakstyper = listOf(TiltakstypeFixtures.Oppfolging), + avtaler = listOf(AvtaleFixtures.oppfolging), + gjennomforinger = listOf( + gjennomforing1, + gjennomforing2, + gjennomforing3, + ), + ) + + val gjennomforinger = TiltaksgjennomforingRepository(database.db) + + beforeEach { + domain.initialize(database.db) + } - val database = extension(FlywayDatabaseTestListener(databaseConfig)) + afterEach { + database.db.truncateAll() + } - val lastSuccessDate = LocalDate.of(2023, 2, 14) - val today = LocalDate.of(2023, 2, 16) + test("forsøker ikke å avslutte gjennomføringer før sluttDato er passert") { + val producer = mockk(relaxed = true) + val task = createTask(producer) - context("oppdater statuser på tiltaksgjennomføringer") { - val tiltaksgjennomforingKafkaProducer = mockk(relaxed = true) - val task = UpdateTiltaksgjennomforingStatus( - TiltaksgjennomforingRepository(database.db), - tiltaksgjennomforingKafkaProducer, - ) + task.oppdaterTiltaksgjennomforingStatus(today = LocalDate.of(2023, 1, 31)) - fun TiltaksgjennomforingDbo.toDto(status: TiltaksgjennomforingStatus) = TiltaksgjennomforingEksternV1Dto( - id = id, - tiltakstype = TiltakstypeFixtures.Oppfolging.run { - TiltaksgjennomforingEksternV1Dto.Tiltakstype( - id = id, - navn = navn, - arenaKode = arenaKode, - tiltakskode = tiltakskode!!, - ) - }, - navn = navn, - virksomhetsnummer = ArrangorFixtures.underenhet1.organisasjonsnummer.value, - startDato = startDato, - sluttDato = sluttDato, - status = status, - oppstart = oppstart, - tilgjengeligForArrangorFraOgMedDato = null, - apentForPamelding = true, - ) + gjennomforinger.get(gjennomforing1.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(GJENNOMFORES, avbrutt = null)) + } + gjennomforinger.get(gjennomforing2.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(GJENNOMFORES, avbrutt = null)) + } + gjennomforinger.get(gjennomforing3.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(GJENNOMFORES, avbrutt = null)) + } - val startdatoInnenforMenAvsluttetStatus = TiltaksgjennomforingFixtures.Oppfolging1.copy( - id = UUID.randomUUID(), - startDato = LocalDate.of(2023, 2, 15), - sluttDato = LocalDate.now().plusYears(1), - ) - val startdatoInnenfor = TiltaksgjennomforingFixtures.Oppfolging1.copy( - id = UUID.randomUUID(), - startDato = LocalDate.of(2023, 2, 15), - sluttDato = LocalDate.now().plusYears(1), - ) - val sluttdatoInnenforMenAvbruttStatus = TiltaksgjennomforingFixtures.Oppfolging1.copy( - id = UUID.randomUUID(), - startDato = lastSuccessDate, - sluttDato = lastSuccessDate, - ) - val sluttdatoInnenfor = TiltaksgjennomforingFixtures.Oppfolging1.copy( - id = UUID.randomUUID(), - startDato = lastSuccessDate, - sluttDato = lastSuccessDate, - ) - val datoerUtenfor = TiltaksgjennomforingFixtures.Oppfolging1.copy( - id = UUID.randomUUID(), - startDato = lastSuccessDate, - sluttDato = LocalDate.now().plusYears(1), - ) - val domain = MulighetsrommetTestDomain( - tiltakstyper = listOf(TiltakstypeFixtures.Oppfolging), - avtaler = listOf(AvtaleFixtures.oppfolging), - gjennomforinger = listOf( - startdatoInnenforMenAvsluttetStatus, - startdatoInnenfor, - sluttdatoInnenforMenAvbruttStatus, - sluttdatoInnenfor, - datoerUtenfor, - ), - ) + verify(exactly = 0) { producer.publish(any()) } + } + + test("avslutter gjennomføringer når sluttDato er passert") { + val producer = mockk(relaxed = true) + val task = createTask(producer) - val gjennomforinger = TiltaksgjennomforingRepository(database.db) + task.oppdaterTiltaksgjennomforingStatus(today = LocalDate.of(2023, 2, 1)) - beforeEach { - domain.initialize(database.db) - gjennomforinger.avbryt( - startdatoInnenforMenAvsluttetStatus.id, - LocalDateTime.now(), - AvbruttAarsak.Feilregistrering, + gjennomforinger.get(gjennomforing1.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(GJENNOMFORES, avbrutt = null)) + } + gjennomforinger.get(gjennomforing2.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) + } + gjennomforinger.get(gjennomforing3.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) + } + + verifyAll { + producer.publish( + match { + it.id == gjennomforing2.id && it.status == AVSLUTTET + }, ) - gjennomforinger.avbryt( - sluttdatoInnenforMenAvbruttStatus.id, - LocalDateTime.now(), - AvbruttAarsak.Feilregistrering, + producer.publish( + match { + it.id == gjennomforing3.id && it.status == AVSLUTTET + }, ) } + } - afterEach { - database.db.truncateAll() - } + test("avslutter gjennomføringer når sluttDato er passert (sluttDato passert med flere dager)") { + val producer = mockk(relaxed = true) + val task = createTask(producer) - test("oppdater statuser på kafka på relevante tiltaksgjennomføringer") { - task.oppdaterTiltaksgjennomforingStatus(today, lastSuccessDate) + task.oppdaterTiltaksgjennomforingStatus(today = LocalDate.of(2023, 3, 1)) - verifyAll { - tiltaksgjennomforingKafkaProducer.publish(startdatoInnenfor.toDto(TiltaksgjennomforingStatus.GJENNOMFORES)) - tiltaksgjennomforingKafkaProducer.publish(sluttdatoInnenfor.toDto(TiltaksgjennomforingStatus.AVSLUTTET)) - } + gjennomforinger.get(gjennomforing1.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(GJENNOMFORES, avbrutt = null)) + } + gjennomforinger.get(gjennomforing2.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) + } + gjennomforinger.get(gjennomforing3.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) } - test("avpubliserer når tiltak blir avsluttet på relevante tiltaksgjennomføringer") { - gjennomforinger.setPublisert(startdatoInnenfor.id, true) - gjennomforinger.setPublisert(sluttdatoInnenfor.id, true) - task.oppdaterTiltaksgjennomforingStatus(today, lastSuccessDate) - - verifyAll { - tiltaksgjennomforingKafkaProducer.publish(startdatoInnenfor.toDto(TiltaksgjennomforingStatus.GJENNOMFORES)) - tiltaksgjennomforingKafkaProducer.publish(sluttdatoInnenfor.toDto(TiltaksgjennomforingStatus.AVSLUTTET)) - } - gjennomforinger.get(startdatoInnenfor.id)?.publisert shouldBe true - gjennomforinger.get(sluttdatoInnenfor.id)?.publisert shouldBe false + verifyAll { + producer.publish( + match { + it.id == gjennomforing2.id && it.status == AVSLUTTET + }, + ) + producer.publish( + match { + it.id == gjennomforing3.id && it.status == AVSLUTTET + }, + ) } } - context("tiltak i egen regi") { - val tiltaksgjennomforingKafkaProducer = mockk(relaxed = true) - val task = UpdateTiltaksgjennomforingStatus( - TiltaksgjennomforingRepository(database.db), - tiltaksgjennomforingKafkaProducer, + test("forsøker ikke å avslutte gjennomføringer som allerede er avsluttet, avlyst eller avbrutt") { + val producer = mockk(relaxed = true) + val task = createTask(producer) + + gjennomforinger.setAvsluttet( + gjennomforing1.id, + LocalDate.of(2024, 1, 1).atStartOfDay(), + AvbruttAarsak.Feilregistrering, ) - val startdatoInnenfor = TiltaksgjennomforingFixtures.IPS1.copy( - id = UUID.randomUUID(), - startDato = LocalDate.of(2023, 2, 15), - sluttDato = LocalDate.now().plusYears(1), + gjennomforinger.setAvsluttet( + gjennomforing2.id, + LocalDate.of(2022, 12, 31).atStartOfDay(), + AvbruttAarsak.Feilregistrering, ) - val domain = MulighetsrommetTestDomain( - tiltakstyper = listOf(TiltakstypeFixtures.IPS), - avtaler = listOf(AvtaleFixtures.IPS), - gjennomforinger = listOf(startdatoInnenfor), + gjennomforinger.setAvsluttet( + gjennomforing3.id, + LocalDate.of(2023, 1, 1).atStartOfDay(), + AvbruttAarsak.Feilregistrering, ) - beforeEach { - domain.initialize(database.db) - } + task.oppdaterTiltaksgjennomforingStatus(today = LocalDate.of(2024, 1, 2)) - afterEach { - database.db.truncateAll() + gjennomforinger.get(gjennomforing1.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) + } + gjennomforinger.get(gjennomforing2.id).shouldNotBeNull().should { + it.status.status.shouldBe(AVLYST) + it.status.avbrutt.shouldNotBeNull().aarsak.shouldBe(AvbruttAarsak.Feilregistrering) } + gjennomforinger.get(gjennomforing3.id).shouldNotBeNull().should { + it.status.status.shouldBe(AVBRUTT) + it.status.avbrutt.shouldNotBeNull().aarsak.shouldBe(AvbruttAarsak.Feilregistrering) + } + + verify(exactly = 0) { producer.publish(any()) } + } + } + + context("når gjennomføring blir avsluttet") { + val gjennomforing = TiltaksgjennomforingFixtures.Oppfolging1.copy( + id = UUID.randomUUID(), + startDato = LocalDate.of(2023, 1, 1), + sluttDato = LocalDate.of(2023, 1, 31), + ) + + val domain = MulighetsrommetTestDomain( + tiltakstyper = listOf(TiltakstypeFixtures.Oppfolging), + avtaler = listOf(AvtaleFixtures.oppfolging), + gjennomforinger = listOf(gjennomforing), + ) + + val gjennomforinger = TiltaksgjennomforingRepository(database.db) + + beforeEach { + domain.initialize(database.db) + } + + afterEach { + database.db.truncateAll() + } + + test("avpubliserer og stenger gjennomføring for påmelding") { + val producer = mockk(relaxed = true) + val task = createTask(producer) + + gjennomforinger.setPublisert(gjennomforing.id, true) + gjennomforinger.setApentForPamelding(gjennomforing.id, true) - test("oppdaterer ikke status på kafka") { - task.oppdaterTiltaksgjennomforingStatus(today, lastSuccessDate) + task.oppdaterTiltaksgjennomforingStatus(today = LocalDate.of(2023, 2, 1)) - verify(exactly = 0) { - tiltaksgjennomforingKafkaProducer.publish(any()) - } + gjennomforinger.get(gjennomforing.id).shouldNotBeNull().should { + it.status.shouldBe(TiltaksgjennomforingStatusDto(AVSLUTTET, avbrutt = null)) + it.publisert.shouldBe(false) + it.apentForPamelding.shouldBe(false) } } - }) + } +}) From 66586ce11aa477c54e89b4c1a96aa2eb4b04af01 Mon Sep 17 00:00:00 2001 From: Sondre Lefsaker Date: Wed, 27 Nov 2024 08:42:13 +0100 Subject: [PATCH 2/2] forenkle avtalevalidering --- .../api/avtale/AvtaleService.kt | 32 ++++++------------- .../api/avtale/AvtaleServiceTest.kt | 31 ++---------------- 2 files changed, 12 insertions(+), 51 deletions(-) diff --git a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleService.kt b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleService.kt index 7aaabfffd2..5d22ccf405 100644 --- a/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleService.kt +++ b/mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleService.kt @@ -159,29 +159,15 @@ class AvtaleService( ), ) - val (antallAktiveGjennomforinger, antallPlanlagteGjennomforinger) = gjennomforinger.partition { it.status.status == TiltaksgjennomforingStatus.GJENNOMFORES } - if (antallAktiveGjennomforinger.isNotEmpty()) { - return Either.Left( - BadRequest( - message = "Avtalen har ${antallAktiveGjennomforinger.size} ${ - if (antallAktiveGjennomforinger.size > 1) "aktive tiltaksgjennomføringer" else "aktiv tiltaksgjennomføring" - } koblet til seg. Du må frikoble ${ - if (antallAktiveGjennomforinger.size > 1) "gjennomføringene" else "gjennomføringen" - } før du kan avbryte avtalen.", - ), - ) - } - - if (antallPlanlagteGjennomforinger.isNotEmpty()) { - return Either.Left( - BadRequest( - message = "Avtalen har ${antallPlanlagteGjennomforinger.size} ${ - if (antallPlanlagteGjennomforinger.size > 1) "planlagte tiltaksgjennomføringer" else "planlagt tiltaksgjennomføring" - } koblet til seg. Du må flytte eller avslutte ${ - if (antallPlanlagteGjennomforinger.size > 1) "gjennomføringene" else "gjennomføringen" - } før du kan avbryte avtalen.", - ), - ) + if (gjennomforinger.isNotEmpty()) { + val plural = gjennomforinger.size > 1 + val message = listOf( + "Avtalen har", + gjennomforinger.size, + if (plural) "aktive gjennomføringer" else "aktiv gjennomføring", + "og kan derfor ikke avbrytes.", + ).joinToString(" ") + return Either.Left(BadRequest(message)) } db.transaction { tx -> diff --git a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleServiceTest.kt b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleServiceTest.kt index cc558adcd2..6fb026ab84 100644 --- a/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleServiceTest.kt +++ b/mulighetsrommet-api/src/test/kotlin/no/nav/mulighetsrommet/api/avtale/AvtaleServiceTest.kt @@ -34,6 +34,7 @@ import no.nav.mulighetsrommet.domain.dto.Organisasjonsnummer import no.nav.mulighetsrommet.notifications.NotificationRepository import no.nav.mulighetsrommet.utils.toUUID import java.time.LocalDate +import java.time.LocalDateTime import java.util.* class AvtaleServiceTest : FunSpec({ @@ -183,34 +184,7 @@ class AvtaleServiceTest : FunSpec({ tiltaksgjennomforinger.upsert(oppfolging2) avtaleService.avbrytAvtale(avtale.id, bertilNavIdent, AvbruttAarsak.Feilregistrering).shouldBeLeft( - BadRequest("Avtalen har 2 aktive tiltaksgjennomføringer koblet til seg. Du må frikoble gjennomføringene før du kan avbryte avtalen."), - ) - } - - test("Man skal ikke få avbryte, men få en melding dersom det finnes planlagte gjennomføringer koblet til avtalen") { - val avtale = AvtaleFixtures.oppfolging.copy( - id = UUID.randomUUID(), - navn = "Avtale som eksisterer", - startDato = LocalDate.now(), - sluttDato = LocalDate.now().plusMonths(1), - ) - avtaleRepository.upsert(avtale) - val oppfolging1 = TiltaksgjennomforingFixtures.Oppfolging1.copy( - avtaleId = avtale.id, - startDato = LocalDate.now().plusDays(1), - sluttDato = null, - ) - val oppfolging2 = TiltaksgjennomforingFixtures.Oppfolging2.copy( - avtaleId = avtale.id, - startDato = LocalDate.now().plusDays(1), - sluttDato = null, - ) - - tiltaksgjennomforinger.upsert(oppfolging1) - tiltaksgjennomforinger.upsert(oppfolging2) - - avtaleService.avbrytAvtale(avtale.id, bertilNavIdent, AvbruttAarsak.Feilregistrering).shouldBeLeft( - BadRequest("Avtalen har 2 planlagte tiltaksgjennomføringer koblet til seg. Du må flytte eller avslutte gjennomføringene før du kan avbryte avtalen."), + BadRequest("Avtalen har 2 aktive gjennomføringer og kan derfor ikke avbrytes."), ) } @@ -228,6 +202,7 @@ class AvtaleServiceTest : FunSpec({ sluttDato = LocalDate.now().minusDays(1), ) tiltaksgjennomforinger.upsert(oppfolging1) + tiltaksgjennomforinger.setAvsluttet(oppfolging1.id, LocalDateTime.now(), null) avtaleService.avbrytAvtale(avtale.id, bertilNavIdent, AvbruttAarsak.Feilregistrering).shouldBeRight() }