From ea58883616ef57c234ef84168238ad2f5c29501f Mon Sep 17 00:00:00 2001 From: "Anders.Vik.Lysne" Date: Thu, 2 Jan 2025 16:05:59 +0100 Subject: [PATCH 1/2] SoftDelete hendelse sletter notifikasjon og sak fra produsent databasen --- .../produsent/ProdusentRepository.kt | 78 ++++++------------- .../api/SoftDeleteNotifikasjonTests.kt | 26 +++---- .../produsent/api/SoftDeleteSakTests.kt | 23 +++--- 3 files changed, 45 insertions(+), 82 deletions(-) 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 8835c59bb..1104ca25c 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 @@ -43,6 +43,7 @@ interface ProdusentRepository { SAK, BESKJED, OPPGAVE, + KALENDERAVTALE } suspend fun hentNotifikasjon(id: UUID): ProdusentModel.Notifikasjon? @@ -324,8 +325,8 @@ class ProdusentRepositoryImpl( is OppgaveUtgått -> oppdaterModellEtterOppgaveUtgått(hendelse) is PåminnelseOpprettet -> /* Ignorer */ Unit is BrukerKlikket -> /* Ignorer */ Unit - is SoftDelete -> oppdaterModellEtterSoftDelete(hendelse) - is HardDelete -> oppdaterModellEtterHardDelete(hendelse) + is SoftDelete -> oppdaterModellEtterDelete(aggregateId = hendelse.aggregateId, merkelapp = hendelse.merkelapp, grupperingsid = hendelse.grupperingsid) + is HardDelete -> oppdaterModellEtterDelete(aggregateId = hendelse.aggregateId, merkelapp = hendelse.merkelapp, grupperingsid = hendelse.grupperingsid) is EksterntVarselVellykket -> oppdaterModellEtterEksterntVarselVellykket(hendelse) is EksterntVarselFeilet -> oppdaterModellEtterEksterntVarselFeilet(hendelse) is EksterntVarselKansellert -> oppdaterModellEtterEksterntVarselKansellert(hendelse) @@ -460,7 +461,7 @@ class ProdusentRepositoryImpl( } } - private suspend fun oppdaterModellEtterNesteStegSak(nesteStegSak: HendelseModel.NesteStegSak) { + private suspend fun oppdaterModellEtterNesteStegSak(nesteStegSak: NesteStegSak) { database.transaction { executeUpdate( """ @@ -491,9 +492,9 @@ class ProdusentRepositoryImpl( } } - private suspend fun oppdaterModellEtterHardDelete(hardDelete: HardDelete) { + private suspend fun oppdaterModellEtterDelete(aggregateId: UUID, merkelapp: String?, grupperingsid: String?) { database.transaction { - registrerDelete(this, hardDelete.aggregateId) + registrerDelete(this, aggregateId) executeQuery(""" select aggregate_type from ( select 'SAK' as aggregate_type from sak where id = ? @@ -501,11 +502,14 @@ class ProdusentRepositoryImpl( select 'BESKJED' as aggregate_type from notifikasjon where id = ? union select 'OPPGAVE' as aggregate_type from notifikasjon where id = ? + union + select 'KALENDERAVTALE' as aggregate_type from notifikasjon where id = ? ) as aggregate_type """, setup = { - uuid(hardDelete.aggregateId) - uuid(hardDelete.aggregateId) - uuid(hardDelete.aggregateId) + uuid(aggregateId) + uuid(aggregateId) + uuid(aggregateId) + uuid(aggregateId) }, transform = { AggregateType.valueOf(getString("aggregate_type")) }).firstOrNull()?.let { @@ -517,18 +521,18 @@ class ProdusentRepositoryImpl( values (?, ?, ?, ?); """ ) { - uuid(hardDelete.aggregateId) + uuid(aggregateId) text(it.name) - nullableText(hardDelete.merkelapp) - nullableText(hardDelete.grupperingsid) + nullableText(merkelapp) + nullableText(grupperingsid) } } - if (hardDelete.grupperingsid != null && hardDelete.merkelapp != null) { + if (grupperingsid != null && merkelapp != null) { // cascade hard delete av sak med grupperingsid og merkelapp executeUpdate("""delete from notifikasjon n where n.grupperingsid = ? and merkelapp = ?;""") { - text(hardDelete.grupperingsid) - text(hardDelete.merkelapp) + text(grupperingsid) + text(merkelapp) } } executeUpdate( @@ -537,7 +541,7 @@ class ProdusentRepositoryImpl( where id = ? """ ) { - uuid(hardDelete.aggregateId) + uuid(aggregateId) } executeUpdate( """ @@ -545,7 +549,7 @@ class ProdusentRepositoryImpl( where id = ? """ ) { - uuid(hardDelete.aggregateId) + uuid(aggregateId) } executeUpdate( """ @@ -553,7 +557,7 @@ class ProdusentRepositoryImpl( where notifikasjon_id = ? """ ) { - uuid(hardDelete.aggregateId) + uuid(aggregateId) } executeUpdate( """ @@ -561,45 +565,7 @@ class ProdusentRepositoryImpl( where notifikasjon_id = ? """ ) { - uuid(hardDelete.aggregateId) - } - } - } - - private suspend fun oppdaterModellEtterSoftDelete(softDelete: SoftDelete) { - database.transaction { - executeUpdate( - """ - UPDATE notifikasjon - SET deleted_at = ? - WHERE id = ? - """ - ) { - timestamp_with_timezone(softDelete.deletedAt) - uuid(softDelete.aggregateId) - } - if (softDelete.grupperingsid !== null && softDelete.merkelapp !== null) { - executeUpdate( - """ - update notifikasjon - SET deleted_at = ? - WHERE grupperingsid = ? AND merkelapp = ? - """.trimIndent() - ) { - timestamp_with_timezone(softDelete.deletedAt) - text(softDelete.grupperingsid) - text(softDelete.merkelapp) - } - } - executeUpdate( - """ - UPDATE sak - SET deleted_at = ? - WHERE id = ? - """ - ) { - timestamp_with_timezone(softDelete.deletedAt) - uuid(softDelete.aggregateId) + uuid(aggregateId) } } } diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteNotifikasjonTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteNotifikasjonTests.kt index 6ac5863d2..ed1eb8e4b 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteNotifikasjonTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteNotifikasjonTests.kt @@ -4,7 +4,6 @@ package no.nav.arbeidsgiver.notifikasjon.produsent.api import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe -import io.kotest.matchers.shouldNotBe import io.kotest.matchers.types.instanceOf import io.ktor.server.testing.* import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker @@ -63,7 +62,7 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ describe("SoftDelete-oppførsel") { - context("Eksisterende oppgave blir markert som slettet") { + context("Eksisterende oppgave blir slettet") { val (produsentModel, kafkaProducer, engine) = setupEngine() @@ -98,9 +97,9 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ } } - it("har slettet-status i modellen") { - val notifikasjon = produsentModel.hentNotifikasjon(uuid)!! - notifikasjon.deletedAt shouldNotBe null + it("har blitt slettet i modellen") { + val notifikasjon = produsentModel.hentNotifikasjon(uuid) + notifikasjon shouldBe null } it("notifikasjon2 har ikke slettet-status i modellen") { val notifikasjon = produsentModel.hentNotifikasjon(uuid2)!! @@ -108,7 +107,7 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ } - it("mineNotifikasjoner rapporterer som softDeleted") { + it("mineNotifikasjoner rapporterer ikke lenger notifikasjon") { val response = engine.produsentApi( """ query { @@ -226,10 +225,9 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ response.getTypedContent("mineNotifikasjoner") .edges .map { it.node } - .find { it.id == uuid }!! + .find { it.id == uuid } - slettetNotifikasjon.metadata.softDeleted shouldBe true - slettetNotifikasjon.metadata.softDeletedAt shouldNotBe null + slettetNotifikasjon shouldBe null } } @@ -287,7 +285,7 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ val response = engine.produsentApi( """ mutation { - softDeleteNotifikasjonByEksternId(eksternId: "$eksternId", merkelapp: "$merkelapp") { + softDeleteNotifikasjonByEksternId_V2(eksternId: "$eksternId", merkelapp: "$merkelapp") { __typename ... on SoftDeleteNotifikasjonVellykket { id @@ -302,7 +300,7 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ it("returnerer tilbake id-en") { val vellykket = - response.getTypedContent("softDeleteNotifikasjonByEksternId") + response.getTypedContent("softDeleteNotifikasjonByEksternId_V2") vellykket.id shouldBe uuid } @@ -312,9 +310,9 @@ class SoftDeleteNotifikasjonTests : DescribeSpec({ } } - it("har fått slettet tidspunkt") { - val notifikasjon = produsentModel.hentNotifikasjon(uuid)!! - notifikasjon.deletedAt shouldNotBe null + it("har blitt slettet i modellen") { + val notifikasjon = produsentModel.hentNotifikasjon(uuid) + notifikasjon shouldBe null } it("oppgave 2 har ikke fått slettet tidspunkt") { val notifikasjon = produsentModel.hentNotifikasjon(uuid2)!! diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteSakTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteSakTests.kt index a31fbadfd..703fb58e7 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteSakTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/SoftDeleteSakTests.kt @@ -2,7 +2,6 @@ package no.nav.arbeidsgiver.notifikasjon.produsent.api import io.kotest.core.spec.style.DescribeSpec import io.kotest.matchers.shouldBe -import io.kotest.matchers.shouldNotBe import io.kotest.matchers.types.instanceOf import io.ktor.server.testing.* import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel @@ -140,9 +139,9 @@ class SoftDeleteSakTests : DescribeSpec({ } } - it("har slettet-status i modellen") { - val notifikasjon = produsentModel.hentSak(uuid)!! - notifikasjon.deletedAt shouldNotBe null + it("har blitt slettet i modellen") { + val notifikasjon = produsentModel.hentSak(uuid) + notifikasjon shouldBe null } it("notifikasjon2 har ikke slettet-status i modellen") { val notifikasjon = produsentModel.hentSak(uuid2)!! @@ -193,7 +192,7 @@ class SoftDeleteSakTests : DescribeSpec({ } context("SoftDelete cascader fra sak til notifikasjoner"){ - val (produsentModel, kafkaProducer, engine) = setupEngine() + val (produsentModel, _, engine) = setupEngine() produsentModel.oppdaterModellEtterHendelse(sakOpprettet) produsentModel.oppdaterModellEtterHendelse(sakOpprettet2) produsentModel.oppdaterModellEtterHendelse(oppgaveOpprettet) @@ -224,8 +223,8 @@ class SoftDeleteSakTests : DescribeSpec({ } it ("oppgave er slettet") { - val notifikasjon = produsentModel.hentNotifikasjon(uuid3)!! - notifikasjon.deletedAt shouldNotBe null + val notifikasjon = produsentModel.hentNotifikasjon(uuid3) + notifikasjon shouldBe null } it ("oppgave 2 er ikke slettet") { @@ -234,8 +233,8 @@ class SoftDeleteSakTests : DescribeSpec({ } it ("beskjed er slettet") { - val notifikasjon = produsentModel.hentNotifikasjon(uuid5)!! - notifikasjon.deletedAt shouldNotBe null + val notifikasjon = produsentModel.hentNotifikasjon(uuid5) + notifikasjon shouldBe null } } } @@ -276,9 +275,9 @@ class SoftDeleteSakTests : DescribeSpec({ } } - it("har fått slettet tidspunkt") { - val notifikasjon = produsentModel.hentSak(uuid)!! - notifikasjon.deletedAt shouldNotBe null + it("har blitt slettet i modellen") { + val notifikasjon = produsentModel.hentSak(uuid) + notifikasjon shouldBe null } it("oppgave 2 har ikke fått slettet tidspunkt") { val notifikasjon = produsentModel.hentSak(uuid2)!! From 677d262f17072d17eaaeb77e4228fa02a0f8a546 Mon Sep 17 00:00:00 2001 From: "Anders.Vik.Lysne" Date: Fri, 3 Jan 2025 12:08:03 +0100 Subject: [PATCH 2/2] Legg til adhoc mutation, siden adhoc kun fungerer for gql queries --- test-produsent/src/Komponenter/AdHoc.tsx | 60 ++++++++++++++++++- .../src/Komponenter/Komponenter.tsx | 5 +- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/test-produsent/src/Komponenter/AdHoc.tsx b/test-produsent/src/Komponenter/AdHoc.tsx index 977a962ff..9eb5d66ec 100644 --- a/test-produsent/src/Komponenter/AdHoc.tsx +++ b/test-produsent/src/Komponenter/AdHoc.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Button, Textarea } from "@navikt/ds-react"; -import {gql, useLazyQuery} from "@apollo/client"; +import { gql, useLazyQuery, useMutation } from '@apollo/client'; const defaultQueryString = `query init {whoami}` const initQuery = gql`${defaultQueryString}` -export const AdHoc: React.FunctionComponent = () => { +export const AdHocQuery: React.FunctionComponent = () => { const [executeQuery, { loading, error: apolloError, data }] = useLazyQuery(initQuery); const [variables, setVariables] = React.useState(""); @@ -23,7 +23,7 @@ export const AdHoc: React.FunctionComponent = () => { }); setError(null) } catch (error) { - setError(`Feilet parsing. Skriv i JSON-format {"{\"key\":\"value\"}"} ${error}`) + setError(`Feilet parsing. Skriv i JSON-format {"key":"value"} ${error}`) } }; @@ -57,4 +57,58 @@ export const AdHoc: React.FunctionComponent = () => { ); +}; + +export const AdHocMutation: React.FunctionComponent = () => { + const [executeMutation, { loading, error: apolloError, data }] = useMutation(gql("mutation {whoami}")); + + const [variables, setVariables] = React.useState(""); + const [mutation, setMutation] = React.useState(""); + const [error, setError] = React.useState(null); + const handleRunMutation = async () => { + try { + const parsedVariables = variables !== "" ? JSON.parse(variables) : {}; + if (mutation === "") { + setError("Skriv inn en mutation ") + } + await executeMutation({ + variables: parsedVariables, + mutation: gql`${mutation}`, + }); + setError(null) + } catch (error) { + setError(`Feilet parsing. Skriv i JSON-format {"key":"value"} ${error}`) + } + }; + + return ( + <> +
+