From 2035f4ff17bbeb2df410cc3b063141d80fabf9c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 21:37:34 +0000 Subject: [PATCH 1/6] Bump nanoid from 3.3.7 to 3.3.8 in /widget/demo Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8. - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8) --- updated-dependencies: - dependency-name: nanoid dependency-type: indirect ... Signed-off-by: dependabot[bot] --- widget/demo/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/widget/demo/package-lock.json b/widget/demo/package-lock.json index 8c9bff1e9..cf63c35e6 100644 --- a/widget/demo/package-lock.json +++ b/widget/demo/package-lock.json @@ -2966,9 +2966,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -5810,9 +5810,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" }, "negotiator": { "version": "0.6.3", From 983b2b879b7aa9b265014d0e6633c0834af46865 Mon Sep 17 00:00:00 2001 From: Ken Gullaksen Date: Tue, 17 Dec 2024 16:58:26 +0100 Subject: [PATCH 2/6] =?UTF-8?q?hopp=20over=20status=20etter=20soft=20delet?= =?UTF-8?q?e=20inntil=20proper=20fix=20er=20p=C3=A5=20plass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastruktur/kafka/Hendelsesstr\303\270mKafkaImpl.kt" | 4 ++++ 1 file changed, 4 insertions(+) diff --git "a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/kafka/Hendelsesstr\303\270mKafkaImpl.kt" "b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/kafka/Hendelsesstr\303\270mKafkaImpl.kt" index b92d6054e..8b7b2badf 100644 --- "a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/kafka/Hendelsesstr\303\270mKafkaImpl.kt" +++ "b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/kafka/Hendelsesstr\303\270mKafkaImpl.kt" @@ -35,6 +35,10 @@ class HendelsesstrømKafkaImpl( */ private val brokenHendelseId: Set = setOf( UUID.fromString("75977ac3-5ccd-42d2-ada0-93482462b8a9"), + + // soft delete rett etter opprettelse gjør at partisjon er stuck i prod. + // se også https://github.com/navikt/arbeidsgiver-notifikasjon-produsent-api/pull/800 + UUID.fromString("34a375aa-d967-4327-911b-177afcce9d6e"), ) override suspend fun forEach( From c1461eccdad29374759c69e189cf19f49eaf3d71 Mon Sep 17 00:00:00 2001 From: Ken Gullaksen Date: Tue, 17 Dec 2024 21:37:23 +0100 Subject: [PATCH 3/6] =?UTF-8?q?Relax=20ISO8601DateTime=20skalar=20ved=20?= =?UTF-8?q?=C3=A5=20st=C3=B8tte=20flere=20formater?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Endringer oppsummert: * ISO8601DateTime skalar i produsent api støtter nå input både med og uten offset * uten offset antas oslo lokal tid * Input typen til kalenderavtale startTidspunkt og sluttTidspunkt i mutations endres til å bruke ISO8601DateTime i stedet for ISO8601LocalDateTime * Bakgrunn for dette er å gjøre det lettere å bruke nySak og nyKalenderavtale sammen. Slippe å forholde seg til to formater på tidspunkt. Detaljer: Under panseret brukte denne skalaren ISO_OFFSET_DATE_TIME som parser. Som medførte at input som hadde denne skalaren som type alltid måtte ha med offset. Her endres skalaren til å bruke ISO_DATE_TIME som parser samt at den parsede verdien konverteres til en OffsetDateTime i UTC tid. Dersom input kommer uten offset så antas input å representere oslo lokal tid. Dette er reflektert i API dokumentasjonen. Typen til kalenderavtale starttidspunkt og slutttidspunkt endres fra ISO8601LocalDateTime til ISO8601DateTime. Hovedmotivasjonen her er at det er dårlig DX å tvinges til å forholde seg til to formater på tidspunkt i mutations man må gjøre sammen. E.g. nySak & nyKalenderavtale. Denne endringen endrer kun skalarens oppførsel på en bakoverkompatibel måte. Det er derimot en breaking change for brukere av kalenderavtale mutations, men dette er ikke tatt i bruk i prod enda. Vurderer det som verdt å endre kontrakten nå, før det er i bruk i prod. Utrulling av endring blir koordinert med teamet som holder på å ta dette i bruk i dev. --- .../notifikasjon/infrastruktur/Database.kt | 1 - .../infrastruktur/graphql/Scalars.kt | 13 ++++- .../produsent/api/MutationKalenderavtale.kt | 48 +++++++++---------- .../SkedulertP\303\245minnelseRepository.kt" | 1 + app/src/main/resources/produsent.graphql | 13 +++-- .../infrastruktur/graphql/ScalarsTest.kt | 32 +++++++++++++ ...nsOppf\303\270rselForProdusentApiTests.kt" | 4 +- .../src/Komponenter/KalenderAvtale.tsx | 4 +- 8 files changed, 78 insertions(+), 38 deletions(-) create mode 100644 app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/ScalarsTest.kt diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/Database.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/Database.kt index e39220ec4..51d9d06fa 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/Database.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/Database.kt @@ -2,7 +2,6 @@ package no.nav.arbeidsgiver.notifikasjon.infrastruktur import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource -import com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory import kotlinx.coroutines.* import no.nav.arbeidsgiver.notifikasjon.infrastruktur.json.laxObjectMapper import no.nav.arbeidsgiver.notifikasjon.infrastruktur.json.writeValueAsStringSupportingTypeInfoInCollections diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/Scalars.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/Scalars.kt index 5b5d9a1b1..ffefc0b65 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/Scalars.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/Scalars.kt @@ -3,10 +3,13 @@ package no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql import graphql.language.StringValue import graphql.schema.* import no.nav.arbeidsgiver.notifikasjon.infrastruktur.ISO8601Period +import no.nav.arbeidsgiver.notifikasjon.tid.atOsloAsOffsetDateTime import java.time.LocalDate import java.time.LocalDateTime import java.time.OffsetDateTime +import java.time.ZoneOffset import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoField import java.time.temporal.TemporalAccessor import java.time.temporal.TemporalQuery @@ -64,8 +67,14 @@ object Scalars { val ISO8601DateTime: GraphQLScalarType = dateTimeScalar( name = "ISO8601DateTime", - dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME, - temporalQuery = OffsetDateTime::from + dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME, + temporalQuery = { + if (it.isSupported(ChronoField.OFFSET_SECONDS)) { + OffsetDateTime.from(it).withOffsetSameInstant(ZoneOffset.UTC) + } else { + LocalDateTime.from(it).atOsloAsOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC) + } + } ) val ISO8601LocalDateTime: GraphQLScalarType = diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationKalenderavtale.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationKalenderavtale.kt index 202220bad..3d0de1000 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationKalenderavtale.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationKalenderavtale.kt @@ -13,8 +13,8 @@ import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentRepository import no.nav.arbeidsgiver.notifikasjon.produsent.api.MutationKalenderavtale.KalenderavtaleTilstand.AVLYST import no.nav.arbeidsgiver.notifikasjon.produsent.api.MutationKalenderavtale.KalenderavtaleTilstand.VENTER_SVAR_FRA_ARBEIDSGIVER import no.nav.arbeidsgiver.notifikasjon.produsent.tilProdusentModel +import no.nav.arbeidsgiver.notifikasjon.tid.inOsloLocalDateTime import java.time.Instant -import java.time.LocalDateTime import java.time.OffsetDateTime import java.util.* @@ -40,10 +40,10 @@ internal class MutationKalenderavtale( tekst = env.getTypedArgument("tekst"), lenke = env.getTypedArgument("lenke"), mottakere = env.getTypedArgument>("mottakere"), - startTidspunkt = env.getTypedArgument("startTidspunkt"), - sluttTidspunkt = env.getTypedArgumentOrNull("sluttTidspunkt"), + startTidspunkt = env.getTypedArgument("startTidspunkt"), + sluttTidspunkt = env.getTypedArgumentOrNull("sluttTidspunkt"), lokasjon = env.getTypedArgumentOrNull("lokasjon"), - erDigitalt = env.getTypedArgumentOrNull("erDigitalt") ?: false, + erDigitalt = env.getTypedArgumentOrNull("erDigitalt") == true, tilstand = env.getTypedArgumentOrDefault("tilstand") { VENTER_SVAR_FRA_ARBEIDSGIVER }, eksterneVarsler = env.getTypedArgumentOrDefault>("eksterneVarsler") { emptyList() }, paaminnelse = env.getTypedArgumentOrNull("paaminnelse"), @@ -60,8 +60,8 @@ internal class MutationKalenderavtale( nyTilstand = env.getTypedArgumentOrNull("nyTilstand"), nyTekst = env.getTypedArgumentOrNull("nyTekst"), nyLenke = env.getTypedArgumentOrNull("nyLenke"), - nyttStartTidspunkt = env.getTypedArgumentOrNull("nyttStartTidspunkt"), - nyttSluttTidspunkt = env.getTypedArgumentOrNull("nyttSluttTidspunkt"), + nyttStartTidspunkt = env.getTypedArgumentOrNull("nyttStartTidspunkt"), + nyttSluttTidspunkt = env.getTypedArgumentOrNull("nyttSluttTidspunkt"), nyLokasjon = env.getTypedArgumentOrNull("nyLokasjon"), nyErDigitalt = env.getTypedArgumentOrNull("nyErDigitalt"), eksterneVarsler = env.getTypedArgumentOrDefault>("eksterneVarsler") { emptyList() }.ifEmpty { null }, @@ -81,8 +81,8 @@ internal class MutationKalenderavtale( nyTilstand = env.getTypedArgumentOrNull("nyTilstand"), nyTekst = env.getTypedArgumentOrNull("nyTekst"), nyLenke = env.getTypedArgumentOrNull("nyLenke"), - nyttStartTidspunkt = env.getTypedArgumentOrNull("nyttStartTidspunkt"), - nyttSluttTidspunkt = env.getTypedArgumentOrNull("nyttSluttTidspunkt"), + nyttStartTidspunkt = env.getTypedArgumentOrNull("nyttStartTidspunkt"), + nyttSluttTidspunkt = env.getTypedArgumentOrNull("nyttSluttTidspunkt"), nyLokasjon = env.getTypedArgumentOrNull("nyLokasjon"), nyErDigitalt = env.getTypedArgumentOrNull("nyErDigitalt"), eksterneVarsler = env.getTypedArgumentOrDefault>("eksterneVarsler") { emptyList() }.ifEmpty { null }, @@ -120,8 +120,8 @@ internal class MutationKalenderavtale( val tekst: String, val lenke: String, val mottakere: List, - val startTidspunkt: LocalDateTime, - val sluttTidspunkt: LocalDateTime?, + val startTidspunkt: OffsetDateTime, + val sluttTidspunkt: OffsetDateTime?, val lokasjon: LokasjonInput?, val erDigitalt: Boolean, val tilstand: KalenderavtaleTilstand, @@ -157,8 +157,8 @@ internal class MutationKalenderavtale( virksomhetsnummer = virksomhetsnummer, produsentId = produsentId, kildeAppNavn = kildeAppNavn, - startTidspunkt = startTidspunkt, - sluttTidspunkt = sluttTidspunkt, + startTidspunkt = startTidspunkt.inOsloLocalDateTime(), + sluttTidspunkt = sluttTidspunkt?.inOsloLocalDateTime(), tilstand = tilstand.tilHendelseModel(), lokasjon = lokasjon?.tilHendelseModel(), erDigitalt = erDigitalt, @@ -168,7 +168,7 @@ internal class MutationKalenderavtale( påminnelse = paaminnelse?.tilDomene( notifikasjonOpprettetTidspunkt = opprettetTidspunkt, frist = null, - startTidspunkt = startTidspunkt, + startTidspunkt = startTidspunkt.inOsloLocalDateTime(), virksomhetsnummer = virksomhetsnummer, ), ) @@ -286,14 +286,14 @@ internal class MutationKalenderavtale( ) } else if ( nyttStartTidspunkt != null && - nyttStartTidspunkt!!.isAfter(eksisterende.sluttTidspunkt) + nyttStartTidspunkt!!.inOsloLocalDateTime().isAfter(eksisterende.sluttTidspunkt) ) { onValidationError( Error.UgyldigKalenderavtale("startTidspunkt må være før sluttTidspunkt") ) } else if ( nyttSluttTidspunkt != null - && nyttSluttTidspunkt!!.isBefore(eksisterende.startTidspunkt) + && nyttSluttTidspunkt!!.inOsloLocalDateTime().isBefore(eksisterende.startTidspunkt) ) { onValidationError( Error.UgyldigKalenderavtale("startTidspunkt må være før sluttTidspunkt") @@ -310,8 +310,8 @@ internal class MutationKalenderavtale( tilstand = nyTilstand?.tilHendelseModel(), lenke = nyLenke, tekst = nyTekst, - startTidspunkt = nyttStartTidspunkt, - sluttTidspunkt = nyttSluttTidspunkt, + startTidspunkt = nyttStartTidspunkt?.inOsloLocalDateTime(), + sluttTidspunkt = nyttSluttTidspunkt?.inOsloLocalDateTime(), lokasjon = nyLokasjon?.tilHendelseModel(), erDigitalt = nyErDigitalt, hardDelete = hardDelete?.tilHendelseModel(), @@ -319,7 +319,7 @@ internal class MutationKalenderavtale( påminnelse = if (nyTilstand == AVLYST) null else paaminnelse?.tilDomene( notifikasjonOpprettetTidspunkt = eksisterende.opprettetTidspunkt, frist = null, - startTidspunkt = nyttStartTidspunkt ?: eksisterende.startTidspunkt, + startTidspunkt = (nyttStartTidspunkt?.inOsloLocalDateTime() ?: eksisterende.startTidspunkt), virksomhetsnummer = eksisterende.virksomhetsnummer, ), idempotenceKey = idempotenceKey, @@ -332,8 +332,8 @@ internal class MutationKalenderavtale( abstract val nyTilstand: KalenderavtaleTilstand? abstract val nyTekst: String? abstract val nyLenke: String? - abstract val nyttStartTidspunkt: LocalDateTime? - abstract val nyttSluttTidspunkt: LocalDateTime? + abstract val nyttStartTidspunkt: OffsetDateTime? + abstract val nyttSluttTidspunkt: OffsetDateTime? abstract val nyLokasjon: NyKalenderavtaleInput.LokasjonInput? abstract val nyErDigitalt: Boolean? abstract val hardDelete: HardDeleteUpdateInput? @@ -365,8 +365,8 @@ internal class MutationKalenderavtale( override val nyTilstand: KalenderavtaleTilstand?, override val nyTekst: String?, override val nyLenke: String?, - override val nyttStartTidspunkt: LocalDateTime?, - override val nyttSluttTidspunkt: LocalDateTime?, + override val nyttStartTidspunkt: OffsetDateTime?, + override val nyttSluttTidspunkt: OffsetDateTime?, override val nyLokasjon: NyKalenderavtaleInput.LokasjonInput?, override val nyErDigitalt: Boolean?, override val eksterneVarsler: List?, @@ -381,8 +381,8 @@ internal class MutationKalenderavtale( override val nyTilstand: KalenderavtaleTilstand?, override val nyTekst: String?, override val nyLenke: String?, - override val nyttStartTidspunkt: LocalDateTime?, - override val nyttSluttTidspunkt: LocalDateTime?, + override val nyttStartTidspunkt: OffsetDateTime?, + override val nyttSluttTidspunkt: OffsetDateTime?, override val nyLokasjon: NyKalenderavtaleInput.LokasjonInput?, override val nyErDigitalt: Boolean?, override val eksterneVarsler: List?, diff --git "a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/skedulert_p\303\245minnelse/SkedulertP\303\245minnelseRepository.kt" "b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/skedulert_p\303\245minnelse/SkedulertP\303\245minnelseRepository.kt" index c5b6acd15..e58cb0091 100644 --- "a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/skedulert_p\303\245minnelse/SkedulertP\303\245minnelseRepository.kt" +++ "b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/skedulert_p\303\245minnelse/SkedulertP\303\245minnelseRepository.kt" @@ -4,6 +4,7 @@ import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.KalenderavtaleTilstand import no.nav.arbeidsgiver.notifikasjon.infrastruktur.local_database.* import no.nav.arbeidsgiver.notifikasjon.skedulert_påminnelse.Notifikasjontilstand.* +import no.nav.arbeidsgiver.notifikasjon.tid.inOsloLocalDateTime import java.sql.Connection import java.time.Instant import java.time.LocalDate diff --git a/app/src/main/resources/produsent.graphql b/app/src/main/resources/produsent.graphql index 1cae72d47..4c047c792 100644 --- a/app/src/main/resources/produsent.graphql +++ b/app/src/main/resources/produsent.graphql @@ -10,9 +10,8 @@ directive @MaxValue(upToIncluding: Int) on ARGUMENT_DEFINITION directive @NorwegianMobilePhoneNumber on INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION """ -DateTime med offset etter ISO8601-standaren. F.eks. '2011-12-03T10:15:30+01:00'. - -Er representert som String. +DateTime etter ISO8601-standaren. F.eks. '2011-12-03T10:15:30+01:00'. +Dersom tidssone/offset ikke er oppgitt, så antar vi at tidspunktet er Oslo-tid ('Europe/Oslo'). """ scalar ISO8601DateTime @@ -254,12 +253,12 @@ type KalenderavtaleData { """ Når avtalen starter. """ - startTidspunkt: ISO8601LocalDateTime! + startTidspunkt: ISO8601DateTime! """ Når avtalen slutter. """ - sluttTidspunkt: ISO8601LocalDateTime + sluttTidspunkt: ISO8601DateTime """ Her kan dere oppgi en fysisk adresse som brukeren kan møte opp på dersom dere har det. @@ -449,12 +448,12 @@ type Mutation { """ Når avtalen starter. """ - startTidspunkt: ISO8601LocalDateTime! + startTidspunkt: ISO8601DateTime! """ Når avtalen slutter. """ - sluttTidspunkt: ISO8601LocalDateTime + sluttTidspunkt: ISO8601DateTime """ Her kan dere oppgi en fysisk adresse som brukeren kan møte opp på dersom dere har det. diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/ScalarsTest.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/ScalarsTest.kt new file mode 100644 index 000000000..3e5ca6b6a --- /dev/null +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/infrastruktur/graphql/ScalarsTest.kt @@ -0,0 +1,32 @@ +package no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.datatest.withData +import io.kotest.matchers.equals.shouldBeEqual +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.instanceOf +import no.nav.arbeidsgiver.notifikasjon.infrastruktur.kafka.kafkaObjectMapper +import java.time.OffsetDateTime + +class ScalarsTest : DescribeSpec({ + describe("ISO8601DateTime") { + withData( + "2020-01-01T00:01Z" to "2020-01-01T00:01:00Z", // 00:01 UTC == 01:01 Oslo + "2020-01-01T01:01+01:00" to "2020-01-01T00:01:00Z", // 01:01 +1 == 01:01 Oslo + "2020-01-01T01:01+01:00[Europe/Oslo]" to "2020-01-01T00:01:00Z", // == 01:01 Oslo + "2020-01-01T01:01" to "2020-01-01T00:01:00Z", // 01:01 Oslo + "2020-01-01T01:01:00.00" to "2020-01-01T00:01:00Z", // 01:01 Oslo + "2024-03-31T01:59:00" to "2024-03-31T00:59:00Z", // 01:59 Oslo (rett før sommertid 0200) + "2024-03-31T02:01:00" to "2024-03-31T01:01:00Z", // 02:01 Oslo (rett etter sommertid, aldri på klokka) + "2024-03-31T02:59:00" to "2024-03-31T01:59:00Z", // 02:59 Oslo (var aldri på klokka) + "2024-03-31T03:01:00" to "2024-03-31T01:01:00Z", // 03:01 Oslo (rett etter sommertid 0200) + ) { (ts, expected) -> + Scalars.ISO8601DateTime.coercing.parseValue(ts).let { + it shouldBe instanceOf() + it!! shouldBeEqual OffsetDateTime.parse(expected) + + kafkaObjectMapper.writeValueAsString(it) shouldBe "\"$expected\"" + } + } + } +}) diff --git "a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/IdempotensOppf\303\270rselForProdusentApiTests.kt" "b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/IdempotensOppf\303\270rselForProdusentApiTests.kt" index da6c5c433..3935bad18 100644 --- "a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/IdempotensOppf\303\270rselForProdusentApiTests.kt" +++ "b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/IdempotensOppf\303\270rselForProdusentApiTests.kt" @@ -86,8 +86,8 @@ class IdempotensOppførselForProdusentApiTests : DescribeSpec({ // language=GraphQL return """ mutation NyKalenderavtale( - ${'$'}startTidspunkt: ISO8601LocalDateTime! = "2024-10-12T07:00:00.00" - ${'$'}sluttTidspunkt: ISO8601LocalDateTime + ${'$'}startTidspunkt: ISO8601DateTime! = "2024-10-12T07:00:00.00" + ${'$'}sluttTidspunkt: ISO8601DateTime ${'$'}lokasjon: LokasjonInput ${'$'}erDigitalt: Boolean ${'$'}tilstand: KalenderavtaleTilstand diff --git a/test-produsent/src/Komponenter/KalenderAvtale.tsx b/test-produsent/src/Komponenter/KalenderAvtale.tsx index 3668f65c5..126e0f6e4 100644 --- a/test-produsent/src/Komponenter/KalenderAvtale.tsx +++ b/test-produsent/src/Komponenter/KalenderAvtale.tsx @@ -36,8 +36,8 @@ const NY_KALENDERAVTALE = gql` $eksternId: String! $lenke: String! $tekst: String! - $startTidspunkt: ISO8601LocalDateTime! - $sluttTidspunkt: ISO8601LocalDateTime + $startTidspunkt: ISO8601DateTime! + $sluttTidspunkt: ISO8601DateTime $eksterneVarsler: [EksterntVarselInput!]! $paaminnelse: PaaminnelseInput $lokasjon: LokasjonInput From 5be6a6794c82d1070fba363f8865f01c0264c9b7 Mon Sep 17 00:00:00 2001 From: "Anders.Vik.Lysne" Date: Wed, 18 Dec 2024 11:37:09 +0100 Subject: [PATCH 4/6] =?UTF-8?q?Legg=20til=20soft=20delete=20aggregater=20i?= =?UTF-8?q?=20deleted=20aggregates.=20lett=20refaktorering=20for=20=C3=A5?= =?UTF-8?q?=20tilpasse=20dette?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notifikasjon/bruker/BrukerRepository.kt | 14 +++----------- .../notifikasjon/dataprodukt/DataproduktModel.kt | 2 +- .../notifikasjon/hendelse/HardDeletedRepository.kt | 8 ++------ .../notifikasjon/produsent/ProdusentRepository.kt | 2 +- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerRepository.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerRepository.kt index 0f4b6bd91..4d81a5924 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerRepository.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerRepository.kt @@ -706,14 +706,7 @@ class BrukerRepositoryImpl( is OppgaveUtført -> oppdaterModellEtterOppgaveUtført(hendelse, metadata) is OppgaveUtgått -> oppdaterModellEtterOppgaveUtgått(hendelse) is SoftDelete -> oppdaterModellEtterDelete(hendelse.aggregateId, hendelse.grupperingsid, hendelse.merkelapp) - is HardDelete -> oppdaterModellEtterDelete( - hendelse.aggregateId, - hendelse.grupperingsid, - hendelse.merkelapp - ) { tx -> - registrerHardDelete(tx, hendelse) - } - + is HardDelete -> oppdaterModellEtterDelete(hendelse.aggregateId,hendelse.grupperingsid,hendelse.merkelapp) is EksterntVarselFeilet -> Unit is EksterntVarselVellykket -> Unit is EksterntVarselKansellert -> Unit @@ -834,8 +827,7 @@ class BrukerRepositoryImpl( private suspend fun oppdaterModellEtterDelete( aggregateId: UUID, grupperingsid: String?, - merkelapp: String?, - callback: (tx: Transaction) -> Unit = {} + merkelapp: String? ) { database.transaction({ throw RuntimeException("Delete", it) @@ -859,7 +851,7 @@ class BrukerRepositoryImpl( uuid(aggregateId) } - callback(this) + registrerDelete(this, aggregateId) } } diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/dataprodukt/DataproduktModel.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/dataprodukt/DataproduktModel.kt index 98b2417cb..e259d3dde 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/dataprodukt/DataproduktModel.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/dataprodukt/DataproduktModel.kt @@ -425,7 +425,7 @@ class DataproduktModel( ) { uuid(hendelse.aggregateId) } - registrerHardDelete(this, hendelse) + registrerDelete(this, hendelse.aggregateId) } } diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/hendelse/HardDeletedRepository.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/hendelse/HardDeletedRepository.kt index 39d147e28..7d00bd3b0 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/hendelse/HardDeletedRepository.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/hendelse/HardDeletedRepository.kt @@ -40,16 +40,12 @@ open class HardDeletedRepository(private val database: Database) { } - fun registrerHardDelete(tx: Transaction, hendelse: HendelseModel.Hendelse) { - if (hendelse !is HendelseModel.HardDelete) { - return - } - + fun registrerDelete(tx: Transaction, aggregateId: UUID) { tx.executeUpdate(""" insert into hard_deleted_aggregates(aggregate_id) values (?) on conflict do nothing """) { - uuid(hendelse.aggregateId) + uuid(aggregateId) } } } \ No newline at end of file diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/ProdusentRepository.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/ProdusentRepository.kt index 069262043..8835c59bb 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/ProdusentRepository.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/ProdusentRepository.kt @@ -493,7 +493,7 @@ class ProdusentRepositoryImpl( private suspend fun oppdaterModellEtterHardDelete(hardDelete: HardDelete) { database.transaction { - registrerHardDelete(this, hardDelete) + registrerDelete(this, hardDelete.aggregateId) executeQuery(""" select aggregate_type from ( select 'SAK' as aggregate_type from sak where id = ? From 60338aa1f9aba12595590ce1b0d70295a36113bc Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 18 Dec 2024 11:12:01 +0000 Subject: [PATCH 5/6] Autoupdate docs --- docs/api.html | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/docs/api.html b/docs/api.html index a90314c3b..19fc0f8ac 100644 --- a/docs/api.html +++ b/docs/api.html @@ -6,7 +6,7 @@ API-dokumentasjon | Notifikasjoner for arbeidsgivere - +
@@ -1698,13 +1698,13 @@
Arguments
- startTidspunkt - ISO8601LocalDateTime! + startTidspunkt - ISO8601DateTime! Når avtalen starter. - sluttTidspunkt - ISO8601LocalDateTime + sluttTidspunkt - ISO8601DateTime Når avtalen slutter. @@ -1762,8 +1762,8 @@
Query
$tekst: String!, $lenke: String!, $mottakere: [MottakerInput!]!, - $startTidspunkt: ISO8601LocalDateTime!, - $sluttTidspunkt: ISO8601LocalDateTime, + $startTidspunkt: ISO8601DateTime!, + $sluttTidspunkt: ISO8601DateTime, $lokasjon: LokasjonInput, $erDigitalt: Boolean, $tilstand: KalenderavtaleTilstand, @@ -1836,8 +1836,8 @@
Variables
"tekst": "foo123", "lenke": "foo123", "mottakere": [MottakerInput], - "startTidspunkt": ISO8601LocalDateTime, - "sluttTidspunkt": ISO8601LocalDateTime, + "startTidspunkt": ISO8601DateTime, + "sluttTidspunkt": ISO8601DateTime, "lokasjon": LokasjonInput, "erDigitalt": true, "tilstand": "VENTER_SVAR_FRA_ARBEIDSGIVER", @@ -6476,8 +6476,7 @@

ISO8601DateTime

Description
-

DateTime med offset etter ISO8601-standaren. F.eks. '2011-12-03T10:15:30+01:00'.

-

Er representert som String.

+

DateTime etter ISO8601-standaren. F.eks. '2011-12-03T10:15:30+01:00'. Dersom tidssone/offset ikke er oppgitt, så antar vi at tidspunktet er Oslo-tid ('Europe/Oslo').

@@ -6665,12 +6664,12 @@
Fields
Lenken som brukeren føres til hvis de klikker på kalenderavtalen. - startTidspunkt - ISO8601LocalDateTime! + startTidspunkt - ISO8601DateTime! Når avtalen starter. - sluttTidspunkt - ISO8601LocalDateTime + sluttTidspunkt - ISO8601DateTime Når avtalen slutter. @@ -6702,8 +6701,8 @@
Example
"merkelapp": "foo123", "tekst": "foo123", "lenke": "foo123", - "startTidspunkt": ISO8601LocalDateTime, - "sluttTidspunkt": ISO8601LocalDateTime, + "startTidspunkt": ISO8601DateTime, + "sluttTidspunkt": ISO8601DateTime, "lokasjon": Lokasjon, "digitalt": true, "tilstand": "VENTER_SVAR_FRA_ARBEIDSGIVER" From ac4ebc5ad04aeaa176922ed223ce528e2bb5c4fa Mon Sep 17 00:00:00 2001 From: "Anders.Vik.Lysne" Date: Wed, 18 Dec 2024 14:11:25 +0100 Subject: [PATCH 6/6] lag test --- .../bruker/BrukerModelIdempotensTests.kt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerModelIdempotensTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerModelIdempotensTests.kt index fee9b65d5..d4798cba7 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerModelIdempotensTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/bruker/BrukerModelIdempotensTests.kt @@ -106,8 +106,57 @@ class BrukerModelIdempotensTests : DescribeSpec({ } assertDeleted(database, sakId, notifikasjonId, grupperingsid, merkelapp) + } + + describe("soft delete på sak sletter alt og kan replayes uten sakOpprettet") { + val database = testDatabase(Bruker.databaseConfig) + val brukerRepository = BrukerRepositoryImpl(database) + val merkelapp = "idempotenstest" + val grupperingsid = "gr-42" + val sakId = uuid("42") + val notifikasjonId = uuid("314") + + val sakOpprettet = brukerRepository.sakOpprettet( + sakId = sakId, + virksomhetsnummer = TEST_VIRKSOMHET_1, + merkelapp = merkelapp, + grupperingsid = grupperingsid, + mottakere = listOf(TEST_MOTTAKER_1, TEST_MOTTAKER_2), + ) + val hendelsesforløp = listOf( + sakOpprettet, + brukerRepository.nyStatusSak(sakOpprettet, idempotensKey = "idempotensKey"), + brukerRepository . beskjedOpprettet ( + sakId = sakId, + notifikasjonId = notifikasjonId, + virksomhetsnummer = TEST_VIRKSOMHET_1, + merkelapp = merkelapp, + grupperingsid = grupperingsid, + mottakere = listOf(TEST_MOTTAKER_1, TEST_MOTTAKER_2), + ), + HendelseModel.SoftDelete( + hendelseId = UUID.randomUUID(), + virksomhetsnummer = TEST_VIRKSOMHET_1, + aggregateId = sakId, + produsentId = "", + kildeAppNavn = "", + deletedAt = OffsetDateTime.now(), + grupperingsid = grupperingsid, + merkelapp = merkelapp, + ).also { + brukerRepository.oppdaterModellEtterHendelse(it) + } + ) + assertDeleted(database, sakId, notifikasjonId, grupperingsid, merkelapp) + + // replay events utenom sakOpprettet + hendelsesforløp.drop(1).forEach { + brukerRepository.oppdaterModellEtterHendelse(it) + } + + assertDeleted(database, sakId, notifikasjonId, grupperingsid, merkelapp) } }) @@ -157,4 +206,13 @@ private suspend fun DescribeSpecContainerScope.assertDeleted( asMap() }.size shouldBe 0 } + it("sak_status is deleted"){ + database.nonTransactionalExecuteQuery( + """ + select * from sak_status where sak_id = '${notifikasjonId}' + """ + ) { + asMap() + }.size shouldBe 0 + } } \ No newline at end of file