Skip to content

Commit

Permalink
Merge pull request #4663 from navikt/chore/notify-sluttdato
Browse files Browse the repository at this point in the history
flytt logikk for avtale-notifikasjoner også
  • Loading branch information
sondrele authored Nov 21, 2024
2 parents d7f08f5 + 3cbece0 commit 4b5dab5
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import no.nav.mulighetsrommet.api.arrangor.model.ArrangorDto
import no.nav.mulighetsrommet.api.avtale.db.AvtaleDbo
import no.nav.mulighetsrommet.api.avtale.db.AvtaleRepository
import no.nav.mulighetsrommet.api.avtale.model.AvtaleDto
import no.nav.mulighetsrommet.api.avtale.model.AvtaleNotificationDto
import no.nav.mulighetsrommet.api.domain.dto.EndringshistorikkDto
import no.nav.mulighetsrommet.api.gjennomforing.db.TiltaksgjennomforingRepository
import no.nav.mulighetsrommet.api.responses.*
Expand Down Expand Up @@ -134,8 +133,6 @@ class AvtaleService(
return PaginatedResponse.of(pagination, totalCount, items)
}

fun getAllAvtalerSomNarmerSegSluttdato(): List<AvtaleNotificationDto> = avtaler.getAllAvtalerSomNarmerSegSluttdato()

fun avbrytAvtale(id: UUID, navIdent: NavIdent, aarsak: AvbruttAarsak?): StatusResponse<Unit> {
if (aarsak == null) {
return Either.Left(BadRequest(message = "Årsak mangler"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import no.nav.mulighetsrommet.api.arrangor.model.ArrangorKontaktperson
import no.nav.mulighetsrommet.api.avtale.Opsjonsmodell
import no.nav.mulighetsrommet.api.avtale.OpsjonsmodellData
import no.nav.mulighetsrommet.api.avtale.model.AvtaleDto
import no.nav.mulighetsrommet.api.avtale.model.AvtaleNotificationDto
import no.nav.mulighetsrommet.api.clients.norg2.Norg2Type
import no.nav.mulighetsrommet.api.domain.dto.*
import no.nav.mulighetsrommet.api.navenhet.db.ArenaNavEnhet
Expand Down Expand Up @@ -432,30 +431,6 @@ class AvtaleRepository(private val db: Database) {
}
}

fun getAllAvtalerSomNarmerSegSluttdato(currentDate: LocalDate = LocalDate.now()): List<AvtaleNotificationDto> {
val params = mapOf(
"currentDate" to currentDate,
)

@Language("PostgreSQL")
val query = """
select a.id::uuid, a.navn, a.start_dato, a.slutt_dato, array_agg(distinct aa.nav_ident) as administratorer
from avtale a
left join avtale_administrator aa on a.id = aa.avtale_id
where (:currentDate::timestamp + interval '8' month) = a.slutt_dato
or (:currentDate::timestamp + interval '6' month) = a.slutt_dato
or (:currentDate::timestamp + interval '3' month) = a.slutt_dato
or (:currentDate::timestamp + interval '14' day) = a.slutt_dato
or (:currentDate::timestamp + interval '7' day) = a.slutt_dato
group by a.id
""".trimIndent()

return queryOf(query, params)
.map { it.toAvtaleNotificationDto() }
.asList
.let { db.run(it) }
}

fun setOpphav(id: UUID, opphav: ArenaMigrering.Opphav) {
@Language("PostgreSQL")
val query = """
Expand Down Expand Up @@ -646,20 +621,6 @@ class AvtaleRepository(private val db: Database) {
)
}

private fun Row.toAvtaleNotificationDto(): AvtaleNotificationDto {
val administratorer = arrayOrNull<String?>("administratorer")?.asList()?.filterNotNull() ?: emptyList()
val startDato = localDate("start_dato")
val sluttDato = localDateOrNull("slutt_dato")

return AvtaleNotificationDto(
id = uuid("id"),
navn = string("navn"),
startDato = startDato,
sluttDato = sluttDato,
administratorer = administratorer.map { NavIdent(it) },
)
}

fun frikobleKontaktpersonFraAvtale(
kontaktpersonId: UUID,
avtaleId: UUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ data class AvtaleNotificationDto(
val id: UUID,
val navn: String,
@Serializable(with = LocalDateSerializer::class)
val startDato: LocalDate,
@Serializable(with = LocalDateSerializer::class)
val sluttDato: LocalDate? = null,
val sluttDato: LocalDate,
val administratorer: List<NavIdent>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import com.github.kagkarlsson.scheduler.task.helper.Tasks
import com.github.kagkarlsson.scheduler.task.schedule.DisabledSchedule
import com.github.kagkarlsson.scheduler.task.schedule.Schedule
import com.github.kagkarlsson.scheduler.task.schedule.Schedules
import no.nav.mulighetsrommet.api.avtale.AvtaleService
import kotliquery.Row
import kotliquery.queryOf
import no.nav.mulighetsrommet.api.avtale.model.AvtaleNotificationDto
import no.nav.mulighetsrommet.api.utils.DatoUtils.formaterDatoTilEuropeiskDatoformat
import no.nav.mulighetsrommet.database.Database
import no.nav.mulighetsrommet.domain.dto.NavIdent
import no.nav.mulighetsrommet.notifications.NotificationMetadata
import no.nav.mulighetsrommet.notifications.NotificationService
import no.nav.mulighetsrommet.notifications.NotificationType
import no.nav.mulighetsrommet.notifications.ScheduledNotification
import org.intellij.lang.annotations.Language
import java.time.Instant
import java.time.LocalDate

class NotifySluttdatoForAvtalerNarmerSeg(
config: Config,
notificationService: NotificationService,
avtaleService: AvtaleService,
private val db: Database,
private val notificationService: NotificationService,
) {
data class Config(
val disabled: Boolean = false,
Expand All @@ -35,24 +41,69 @@ class NotifySluttdatoForAvtalerNarmerSeg(
val task: RecurringTask<Void> = Tasks
.recurring(javaClass.simpleName, config.toSchedule())
.execute { _, _ ->
val avtaler = avtaleService.getAllAvtalerSomNarmerSegSluttdato()

avtaler.forEach {
it.administratorer.toNonEmptyListOrNull()?.let { administratorer ->
val notification = ScheduledNotification(
type = NotificationType.NOTIFICATION,
title = "Avtalen \"${it.navn}\" utløper ${
it.sluttDato?.formaterDatoTilEuropeiskDatoformat()
}",
targets = administratorer,
createdAt = Instant.now(),
metadata = NotificationMetadata(
linkText = "Gå til avtalen",
link = "/avtaler/${it.id}",
),
)
notificationService.scheduleNotification(notification)
}
notifySluttDatoNarmerSeg(LocalDate.now())
}

fun notifySluttDatoNarmerSeg(today: LocalDate) {
val avtaler = getAllAvtalerSomNarmerSegSluttdato(today)

avtaler.forEach { avtale ->
avtale.administratorer.toNonEmptyListOrNull()?.let { administratorer ->
val title = listOfNotNull(
"Avtalen",
"\"${avtale.navn}\"",
"utløper",
avtale.sluttDato.formaterDatoTilEuropeiskDatoformat(),
).joinToString(" ")

val notification = ScheduledNotification(
type = NotificationType.NOTIFICATION,
title = title,
targets = administratorer,
createdAt = Instant.now(),
metadata = NotificationMetadata(
linkText = "Gå til avtalen",
link = "/avtaler/${avtale.id}",
),
)

notificationService.scheduleNotification(notification)
}
}
}

fun getAllAvtalerSomNarmerSegSluttdato(
today: LocalDate,
): List<AvtaleNotificationDto> = db.useSession { session ->
@Language("PostgreSQL")
val query = """
select avtale.id::uuid,
avtale.navn,
avtale.slutt_dato,
array_agg(distinct nav_ident) as administratorer
from avtale
join avtale_administrator on avtale.id = avtale_id
where (:today::timestamp + interval '8' month) = avtale.slutt_dato
or (:today::timestamp + interval '6' month) = avtale.slutt_dato
or (:today::timestamp + interval '3' month) = avtale.slutt_dato
or (:today::timestamp + interval '14' day) = avtale.slutt_dato
or (:today::timestamp + interval '7' day) = avtale.slutt_dato
group by avtale.id
""".trimIndent()

queryOf(query, mapOf("today" to today))
.map { it.toAvtaleNotificationDto() }
.asList
.runWithSession(session)
}

private fun Row.toAvtaleNotificationDto(): AvtaleNotificationDto {
val administratorer = array<String>("administratorer").asList().map { NavIdent(it) }
return AvtaleNotificationDto(
id = uuid("id"),
navn = string("navn"),
sluttDato = localDate("slutt_dato"),
administratorer = administratorer,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ class NotifySluttdatoForGjennomforingerNarmerSeg(
fun notifySluttDatoNarmerSeg(today: LocalDate) {
val gjennomforinger = getAllGjennomforingerSomNarmerSegSluttdato(today)

gjennomforinger.forEach { dto ->
dto.administratorer.toNonEmptyListOrNull()?.also { administratorer ->
gjennomforinger.forEach { gjennomforing ->
gjennomforing.administratorer.toNonEmptyListOrNull()?.also { administratorer ->
val title = listOfNotNull(
"Gjennomføringen",
"\"${dto.navn}\"",
dto.tiltaksnummer?.let { "($it)" },
"\"${gjennomforing.navn}\"",
gjennomforing.tiltaksnummer?.let { "($it)" },
"utløper",
dto.sluttDato.formaterDatoTilEuropeiskDatoformat(),
gjennomforing.sluttDato.formaterDatoTilEuropeiskDatoformat(),
).joinToString(" ")

val notification = ScheduledNotification(
Expand All @@ -64,7 +64,7 @@ class NotifySluttdatoForGjennomforingerNarmerSeg(
createdAt = Instant.now(),
metadata = NotificationMetadata(
linkText = "Gå til gjennomføringen",
link = "/tiltaksgjennomforinger/${dto.id}",
link = "/tiltaksgjennomforinger/${gjennomforing.id}",
),
)

Expand All @@ -85,25 +85,20 @@ class NotifySluttdatoForGjennomforingerNarmerSeg(
gjennomforing.tiltaksnummer
from tiltaksgjennomforing gjennomforing
join tiltaksgjennomforing_administrator on tiltaksgjennomforing_id = gjennomforing.id
where (:current_date::timestamp + interval '14' day) = gjennomforing.slutt_dato
or (:current_date::timestamp + interval '7' day) = gjennomforing.slutt_dato
or (:current_date::timestamp + interval '1' day) = gjennomforing.slutt_dato
where (:today::timestamp + interval '14' day) = gjennomforing.slutt_dato
or (:today::timestamp + interval '7' day) = gjennomforing.slutt_dato
or (:today::timestamp + interval '1' day) = gjennomforing.slutt_dato
group by gjennomforing.id
""".trimIndent()

val params = mapOf("current_date" to today)

queryOf(query, params)
queryOf(query, mapOf("today" to today))
.map { it.toTiltaksgjennomforingNotificationDto() }
.asList
.runWithSession(session)
}

private fun Row.toTiltaksgjennomforingNotificationDto(): TiltaksgjennomforingNotificationDto {
val administratorer = array<String>("administratorer")
.asList()
.map { NavIdent(it) }

val administratorer = array<String>("administratorer").asList().map { NavIdent(it) }
return TiltaksgjennomforingNotificationDto(
id = uuid("id"),
navn = string("navn"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -846,60 +846,6 @@ class AvtaleRepositoryTest : FunSpec({
}
}

context("Notifikasjoner for avtaler") {
context("Avtaler nærmer seg sluttdato") {
val avtale6Mnd = AvtaleFixtures.oppfolging.copy(
id = UUID.randomUUID(),
startDato = LocalDate.of(2021, 1, 1),
sluttDato = LocalDate.of(2023, 11, 30),
)
val avtale3Mnd = AvtaleFixtures.oppfolging.copy(
id = UUID.randomUUID(),
startDato = LocalDate.of(2021, 1, 1),
sluttDato = LocalDate.of(2023, 8, 31),
)
val avtale14Dag = AvtaleFixtures.oppfolging.copy(
id = UUID.randomUUID(),
startDato = LocalDate.of(2021, 1, 1),
sluttDato = LocalDate.of(2023, 6, 14),
)
val avtale7Dag = AvtaleFixtures.oppfolging.copy(
id = UUID.randomUUID(),
startDato = LocalDate.of(2021, 1, 1),
sluttDato = LocalDate.of(2023, 6, 7),
)
val avtaleSomIkkeSkalMatche = AvtaleFixtures.oppfolging.copy(
id = UUID.randomUUID(),
startDato = LocalDate.of(2022, 6, 7),
sluttDato = LocalDate.of(2024, 1, 1),
)

val domain = MulighetsrommetTestDomain(
arrangorer = listOf(ArrangorFixtures.hovedenhet, ArrangorFixtures.underenhet1),
tiltakstyper = listOf(TiltakstypeFixtures.Oppfolging),
avtaler = listOf(avtale6Mnd, avtale3Mnd, avtale14Dag, avtale7Dag, avtaleSomIkkeSkalMatche),
)

domain.initialize(database.db)

val avtaler = AvtaleRepository(database.db)

test("Skal returnere avtaler som har sluttdato om 6 mnd, 3 mnd, 14 dager og 7 dager") {

val result = avtaler.getAllAvtalerSomNarmerSegSluttdato(
currentDate = LocalDate.of(2023, 5, 31),
)

result.map { it.id } shouldContainExactlyInAnyOrder listOf(
avtale6Mnd.id,
avtale3Mnd.id,
avtale14Dag.id,
avtale7Dag.id,
)
}
}
}

context("Status på avtale") {
val domain = MulighetsrommetTestDomain(
arrangorer = listOf(ArrangorFixtures.hovedenhet, ArrangorFixtures.underenhet1),
Expand Down
Loading

0 comments on commit 4b5dab5

Please sign in to comment.