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 = ? 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 3d0de1000..c33211365 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 @@ -9,6 +9,7 @@ import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.KalenderavtaleOpp import no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql.* import no.nav.arbeidsgiver.notifikasjon.infrastruktur.logger import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel +import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel.Sak 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 @@ -209,12 +210,12 @@ internal class MutationKalenderavtale( nyKalenderavtale: NyKalenderavtaleInput, ): NyKalenderavtaleResultat { val produsent = hentProdusent(context) { error -> return error } - val sakId: UUID = nyKalenderavtale.grupperingsid.let { grupperingsid -> + val sak: Sak = nyKalenderavtale.grupperingsid.let { grupperingsid -> hentSak( produsentRepository = produsentRepository, grupperingsid = grupperingsid, merkelapp = nyKalenderavtale.merkelapp - ) { error -> return error }.id + ) { error -> return error } } val id = UUID.randomUUID() @@ -222,7 +223,7 @@ internal class MutationKalenderavtale( id = id, produsentId = produsent.id, kildeAppNavn = context.appName, - sakId = sakId, + sakId = sak.id, ) { error -> return error } tilgangsstyrNyNotifikasjon( @@ -231,6 +232,10 @@ internal class MutationKalenderavtale( nyKalenderavtale.merkelapp ) { error -> return error } + validerMottakereMotSak(sak, nyKalenderavtale.virksomhetsnummer, nyKalenderavtale.mottakere) { error -> + return error + } + val eksisterende = produsentRepository.hentNotifikasjon( eksternId = nyKalenderavtaleHendelse.eksternId, merkelapp = nyKalenderavtaleHendelse.merkelapp diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyBeskjed.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyBeskjed.kt index d79c242ba..054b25b24 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyBeskjed.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyBeskjed.kt @@ -6,6 +6,7 @@ import graphql.schema.idl.RuntimeWiring import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.BeskjedOpprettet import no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql.* import no.nav.arbeidsgiver.notifikasjon.infrastruktur.logger +import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel.Sak import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentRepository import no.nav.arbeidsgiver.notifikasjon.produsent.tilProdusentModel import java.util.* @@ -79,11 +80,11 @@ internal class MutationNyBeskjed( nyBeskjed: NyBeskjedInput, ): NyBeskjedResultat { val produsent = hentProdusent(context) { error -> return error } - val sakId : UUID? = nyBeskjed.metadata.grupperingsid?.let { grupperingsid -> + val sak : Sak? = nyBeskjed.metadata.grupperingsid?.let { grupperingsid -> runCatching { hentSak(produsentRepository, grupperingsid, nyBeskjed.notifikasjon.merkelapp) { TODO("make sak required by returning this error") - }.id + } }.getOrNull() } val id = UUID.randomUUID() @@ -92,7 +93,7 @@ internal class MutationNyBeskjed( id = id, produsentId = produsent.id, kildeAppNavn = context.appName, - sakId = sakId, + sakId = sak?.id, ) } catch (e: UkjentRolleException) { return Error.UkjentRolle(e.message!!) @@ -106,6 +107,10 @@ internal class MutationNyBeskjed( return error } + validerMottakereMotSak(sak, nyBeskjed.metadata.virksomhetsnummer, nyBeskjed.mottakere) { error -> + return error + } + val eksisterende = produsentRepository.hentNotifikasjon( eksternId = domeneNyBeskjed.eksternId, merkelapp = domeneNyBeskjed.merkelapp diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyOppgave.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyOppgave.kt index e63f48522..6a90934a6 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyOppgave.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/MutationNyOppgave.kt @@ -7,6 +7,7 @@ import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.OppgaveOpprettet import no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql.* import no.nav.arbeidsgiver.notifikasjon.infrastruktur.logger import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel +import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel.Sak import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentRepository import no.nav.arbeidsgiver.notifikasjon.produsent.tilProdusentModel import java.time.LocalDate @@ -96,11 +97,11 @@ internal class MutationNyOppgave( nyOppgave: NyOppgaveInput, ): NyOppgaveResultat { val produsent = hentProdusent(context) { error -> return error } - val sakId : UUID? = nyOppgave.metadata.grupperingsid?.let { grupperingsid -> + val sak : Sak? = nyOppgave.metadata.grupperingsid?.let { grupperingsid -> runCatching { hentSak(produsentRepository, grupperingsid, nyOppgave.notifikasjon.merkelapp) { TODO("make sak required by returning this error") - }.id + } }.getOrNull() } val id = UUID.randomUUID() @@ -109,7 +110,7 @@ internal class MutationNyOppgave( id = id, produsentId = produsent.id, kildeAppNavn = context.appName, - sakId = sakId, + sakId = sak?.id, ) } catch (e: UkjentRolleException){ return Error.UkjentRolle(e.message!!) @@ -123,6 +124,10 @@ internal class MutationNyOppgave( nyOppgave.notifikasjon.merkelapp, ) { error -> return error } + validerMottakereMotSak(sak, nyOppgave.metadata.virksomhetsnummer, nyOppgave.mottakere) { error -> + return error + } + val eksisterende = produsentRepository.hentNotifikasjon( eksternId = domeneNyOppgave.eksternId, merkelapp = domeneNyOppgave.merkelapp, diff --git a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Util.kt b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Util.kt index efce34deb..378e06912 100644 --- a/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Util.kt +++ b/app/src/main/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Util.kt @@ -133,6 +133,37 @@ internal inline fun tilgangsstyrProdusent( return produsent } +private inline fun validerMottakerMotSak( + sak: ProdusentModel.Sak, + virksomhetsnummer: String, + mottakerInput: MottakerInput, + onError: (Error.UgyldigMottaker) -> Nothing +) { + var mottaker = mottakerInput.tilHendelseModel(virksomhetsnummer) + if (mottaker !in sak.mottakere) { + onError( + Error.UgyldigMottaker( + """ + | Ugyldig mottaker '${mottakerInput}'. + | Mottaker må finnes på sak. + """.trimMargin() + ) + ) + } +} + +internal inline fun validerMottakereMotSak( + sak: ProdusentModel.Sak?, + virksomhetsnummer: String, + mottakere: List, + onError: (Error.UgyldigMottaker) -> Nothing +) { + if (sak == null) return + for (mottaker in mottakere) { + validerMottakerMotSak(sak, virksomhetsnummer, mottaker, onError) + } +} + fun String.ensurePrefix(prefix: String) = prefix + removePrefix(prefix) 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 diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Common.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Common.kt index 86e591f6a..7fb570e69 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Common.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/Common.kt @@ -35,6 +35,7 @@ val stubProdusentRegister: ProdusentRegister = object : ProdusentRegister { tillatteMerkelapper = listOf("tag", "tag2"), tillatteMottakere = listOf( ServicecodeDefinisjon(code = "5441", version = "1"), + ServicecodeDefinisjon(code = "1", version = "1"), RessursIdDefinisjon(ressursId = "test-fager"), NærmesteLederDefinisjon, ) diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/EksternVarselApiTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/EksternVarselApiTests.kt index 88cecc378..e423827fa 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/EksternVarselApiTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/EksternVarselApiTests.kt @@ -7,6 +7,7 @@ import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe import io.ktor.server.testing.* +import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.EksterntVarselFeilet import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.EksterntVarselVellykket import no.nav.arbeidsgiver.notifikasjon.infrastruktur.graphql.GraphQLRequest @@ -94,7 +95,7 @@ class EksternVarselApiTests: DescribeSpec({ } mottaker: { altinn: { - serviceCode: "5441" + serviceCode: "1" serviceEdition: "1" } } @@ -124,7 +125,7 @@ class EksternVarselApiTests: DescribeSpec({ nyNotifikasjon: nyKalenderavtale( mottakere: { altinn: { - serviceCode: "5441" + serviceCode: "1" serviceEdition: "1" } } @@ -364,7 +365,14 @@ class EksternVarselApiTests: DescribeSpec({ produsentModel.oppdaterModellEtterHendelse(EksempelHendelse.SakOpprettet.copy( virksomhetsnummer = "0", merkelapp = "tag", - grupperingsid = "0" + grupperingsid = "0", + mottakere = listOf( + AltinnMottaker( + virksomhetsnummer = "0", + serviceCode = "1", + serviceEdition = "1" + ), + ) )) val nyNotifikasjonResult = engine.produsentApi(GraphQLRequest( query = nyNotifikasjonMutation(nyKalenderavtale), 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 3935bad18..93a09dd9f 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" @@ -21,8 +21,8 @@ import java.util.* class IdempotensOppførselForProdusentApiTests : DescribeSpec({ - val virksomhetsnummer = "1234" - val mottaker = AltinnMottaker(serviceCode = "5441", serviceEdition = "1", virksomhetsnummer = virksomhetsnummer) + val virksomhetsnummer = "1" + val mottaker = AltinnMottaker(serviceCode = "1", serviceEdition = "1", virksomhetsnummer = virksomhetsnummer) val eksternId = "42" val grupperingsid = "42" diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/KalenderavtaleTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/KalenderavtaleTests.kt index 697e4df5a..5f8513fa1 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/KalenderavtaleTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/KalenderavtaleTests.kt @@ -1,6 +1,7 @@ package no.nav.arbeidsgiver.notifikasjon.produsent.api import io.kotest.core.spec.style.DescribeSpec +import io.kotest.core.spec.style.scopes.DescribeSpecContainerScope import io.kotest.matchers.collections.beEmpty import io.kotest.matchers.nulls.beNull import io.kotest.matchers.should @@ -11,12 +12,12 @@ import io.kotest.matchers.types.instanceOf import io.ktor.http.* import io.ktor.server.testing.* import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel +import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.NærmesteLederMottaker import no.nav.arbeidsgiver.notifikasjon.produsent.Produsent import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentModel import no.nav.arbeidsgiver.notifikasjon.produsent.ProdusentRepositoryImpl import no.nav.arbeidsgiver.notifikasjon.produsent.api.MutationKalenderavtale.KalenderavtaleTilstand.* import no.nav.arbeidsgiver.notifikasjon.util.* -import org.joda.time.LocalDate import java.time.LocalDateTime import java.time.OffsetDateTime import java.util.* @@ -30,7 +31,7 @@ class KalenderavtaleTests : DescribeSpec({ describe("Kalenderavtale mutations") { val (produsentRepository, kafkaProducer, engine) = setupEngine() val sakOpprettet = HendelseModel.SakOpprettet( - virksomhetsnummer = "1", + virksomhetsnummer = "42", merkelapp = "tag", grupperingsid = grupperingsid, mottakere = listOf( @@ -311,6 +312,65 @@ class KalenderavtaleTests : DescribeSpec({ } } } + context("Validering av mottaker mot sak") { + val (produsentRepository, kafkaProducer, engine) = setupEngine() + val sakOpprettet = HendelseModel.SakOpprettet( + virksomhetsnummer = "42", + merkelapp = "tag", + grupperingsid = "g42", + mottakere = listOf( + NærmesteLederMottaker( + naermesteLederFnr = "12345678910", + ansattFnr = "321", + virksomhetsnummer = "42" + ) + ), + hendelseId = uuid("11"), + sakId = uuid("11"), + tittel = "test", + lenke = "https://nav.no", + oppgittTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + mottattTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + kildeAppNavn = "", + produsentId = "", + nesteSteg = null, + hardDelete = null, + tilleggsinformasjon = null + ).also { + produsentRepository.oppdaterModellEtterHendelse(it) + } + + val nyKalenderavtale = opprettKalenderavtaleMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "41", + eksternId = "1", + mottaker = + """naermesteLeder: { + naermesteLederFnr: "12345678910", + ansattFnr: "321" + }""" + ) + it("Kalenderavtale har feil virksomhetsnummer") { + nyKalenderavtale shouldBe instanceOf() + } + + val nyKalenderavtale2 = opprettKalenderavtaleMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "42", + eksternId = "2", + mottaker = + """altinn: { + serviceCode: "1", + serviceEdition: "1" + }""" + ) + + it("Kalenderavtale har feil mottakerType") { + nyKalenderavtale2 shouldBe instanceOf() + } + } } }) @@ -539,3 +599,72 @@ private fun TestApplicationEngine.oppdaterKalenderavtaleByEksternId( } """.trimIndent() ) + +private fun DescribeSpecContainerScope.opprettKalenderavtaleMedMottaker( + engine: TestApplicationEngine, + grupperingsId: String, + eksternId: String, + mottaker: String, + virksomhetsnummer: String, + startTidspunkt: String = "2024-10-12T07:20:50.52", + sluttTidspunkt: String = "2024-10-12T08:20:50.52", +): MutationKalenderavtale.NyKalenderavtaleResultat { + val mutation = + """ + mutation { + nyKalenderavtale( + mottakere: [{ + $mottaker + } + ] + + lenke: "https://foo.bar" + tekst: "hello world" + merkelapp: "tag" + grupperingsid: "$grupperingsId" + eksternId: "$eksternId" + startTidspunkt: "$startTidspunkt" + sluttTidspunkt: "$sluttTidspunkt" + lokasjon: { + postnummer: "1234" + poststed: "Kneika" + adresse: "rundt svingen og borti høgget" + } + erDigitalt: true + virksomhetsnummer: "$virksomhetsnummer" + eksterneVarsler: [{ + altinntjeneste: { + sendetidspunkt: { + sendevindu: LOEPENDE + } + mottaker: { + serviceCode: "5441" + serviceEdition: "1" + } + innhold: "foo" + tittel: "bar" + } + }] + hardDelete: { + den: "2019-10-13T07:20:50.52" + } + ) { + __typename + ... on NyKalenderavtaleVellykket { + id + eksterneVarsler { + id + } + } + ... on Error { + feilmelding + } + } + } + """.trimIndent() + + val response = engine.produsentApi(mutation) + response.status() shouldBe HttpStatusCode.OK + response.getGraphqlErrors() should beEmpty() + return response.getTypedContent("nyKalenderavtale") +} \ No newline at end of file diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyBeskjedTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyBeskjedTests.kt index 524423a02..993fd5ecd 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyBeskjedTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyBeskjedTests.kt @@ -103,6 +103,82 @@ class NyBeskjedTests : DescribeSpec({ produsentRepository.hentNotifikasjon(id) shouldNot beNull() } } + + describe("Validering av mottaker mot sak") { + val (produsentRepository, _, engine) = setupEngine() + val sakOpprettet = HendelseModel.SakOpprettet( + virksomhetsnummer = "42", + merkelapp = "tag", + grupperingsid = "g42", + mottakere = listOf( + NærmesteLederMottaker( + naermesteLederFnr = "12345678910", + ansattFnr = "321", + virksomhetsnummer = "42" + ) + ), + hendelseId = uuid("11"), + sakId = uuid("11"), + tittel = "test", + lenke = "https://nav.no", + oppgittTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + mottattTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + kildeAppNavn = "", + produsentId = "", + nesteSteg = null, + hardDelete = null, + tilleggsinformasjon = null + ).also { + produsentRepository.oppdaterModellEtterHendelse(it) + } + + val nyBeskjed = opprettBeskjedMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "41", + eksternId = "1", + mottaker = + """naermesteLeder: { + naermesteLederFnr: "12345678910", + ansattFnr: "321" + }""" + ) + it("Beskjed har feil virksomhetsnummer") { + nyBeskjed shouldBe instanceOf() + } + + val nyBeskjed2 = opprettBeskjedMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "42", + eksternId = "2", + mottaker = + """altinn: { + serviceCode: "1", + serviceEdition: "1" + }""" + ) + + it("Beskjed har feil mottakerType") { + nyBeskjed2 shouldBe instanceOf() + } + + val nyBeskjed3 = opprettBeskjedMedMottaker( + engine, + grupperingsId = "g41", + virksomhetsnummer = "41", + eksternId = "3", + mottaker = + """altinn: { + serviceCode: "1", + serviceEdition: "1" + }""" + ) + + it("Beskjed har ikke grupperingsid, og er ikke koblet til sak") { + nyBeskjed3 shouldBe instanceOf() + } + } }) private fun DescribeSpec.setupEngine(): Triple { @@ -173,3 +249,54 @@ private suspend inline fun DescribeSpecContainerScope.opprettOgTestNyBeskjed( return nyBeskjed as MutationNyBeskjed.NyBeskjedVellykket } + +private fun DescribeSpecContainerScope.opprettBeskjedMedMottaker( + engine: TestApplicationEngine, + grupperingsId: String, + eksternId: String, + mottaker: String, + virksomhetsnummer: String, +): MutationNyBeskjed.NyBeskjedResultat { + val mutation = + """ + mutation { + nyBeskjed(nyBeskjed: { + mottakere: [{ + $mottaker + } + ] + + notifikasjon: { + lenke: "https://foo.bar", + tekst: "hello world", + merkelapp: "tag", + } + metadata: { + eksternId: "$eksternId", + opprettetTidspunkt: "2019-10-12T07:20:50.52Z" + virksomhetsnummer: "$virksomhetsnummer" + hardDelete: { + den: "2019-10-13T07:20:50.52" + } + grupperingsid: "$grupperingsId", + } + }) { + __typename + ... on NyBeskjedVellykket { + id + eksterneVarsler { + id + } + } + ... on Error { + feilmelding + } + } + } + """.trimIndent() + + val response = engine.produsentApi(mutation) + response.status() shouldBe HttpStatusCode.OK + response.getGraphqlErrors() should beEmpty() + return response.getTypedContent("nyBeskjed") +} \ No newline at end of file diff --git a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyOppgaveTests.kt b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyOppgaveTests.kt index 81ce45882..7975c612f 100644 --- a/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyOppgaveTests.kt +++ b/app/src/test/kotlin/no/nav/arbeidsgiver/notifikasjon/produsent/api/NyOppgaveTests.kt @@ -58,7 +58,8 @@ class NyOppgaveTests : DescribeSpec({ describe("produsent-api happy path med frist") { val (produsentRepository, kafkaProducer, engine) = setupEngine() - val nyOppgave = opprettOgTestNyOppgave(engine, frist = """frist: "2020-01-02" """) + val nyOppgave = + opprettOgTestNyOppgave(engine, frist = """frist: "2020-01-02" """) it("sends message to kafka") { kafkaProducer.hendelser.removeLast().also { @@ -84,7 +85,8 @@ class NyOppgaveTests : DescribeSpec({ produsentRepository.hentNotifikasjon(id) shouldNot beNull() } - val nyOppgave2 = opprettOgTestNyOppgave(engine, frist = """frist: "2020-01-02" """) + val nyOppgave2 = + opprettOgTestNyOppgave(engine, frist = """frist: "2020-01-02" """) it("idempotent oppførsel ved opprettelse av identisk sak") { nyOppgave2.id shouldBe nyOppgave.id } @@ -149,6 +151,82 @@ class NyOppgaveTests : DescribeSpec({ produsentRepository.hentNotifikasjon(id) shouldNot beNull() } } + + describe("Validering av mottaker mot sak") { + val (produsentRepository, kafkaProducer, engine) = setupEngine() + val sakOpprettet = HendelseModel.SakOpprettet( + virksomhetsnummer = "42", + merkelapp = "tag", + grupperingsid = "g42", + mottakere = listOf( + NærmesteLederMottaker( + naermesteLederFnr = "12345678910", + ansattFnr = "321", + virksomhetsnummer = "42" + ) + ), + hendelseId = uuid("11"), + sakId = uuid("11"), + tittel = "test", + lenke = "https://nav.no", + oppgittTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + mottattTidspunkt = OffsetDateTime.parse("2020-01-01T01:01Z"), + kildeAppNavn = "", + produsentId = "", + nesteSteg = null, + hardDelete = null, + tilleggsinformasjon = null + ).also { + produsentRepository.oppdaterModellEtterHendelse(it) + } + + val nyOppgave = opprettOppgaveMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "41", + eksternId = "1", + mottaker = + """naermesteLeder: { + naermesteLederFnr: "12345678910", + ansattFnr: "321" + }""" + ) + it("Oppgave har feil virksomhetsnummer") { + nyOppgave shouldBe instanceOf() + } + + val nyOppgave2 = opprettOppgaveMedMottaker( + engine, + grupperingsId = "g42", + virksomhetsnummer = "42", + eksternId = "2", + mottaker = + """altinn: { + serviceCode: "1", + serviceEdition: "1" + }""" + ) + + it("Oppgave har feil mottakerType") { + nyOppgave2 shouldBe instanceOf() + } + + val nyOppgave3 = opprettOppgaveMedMottaker( + engine, + grupperingsId = "g41", + virksomhetsnummer = "41", + eksternId = "3", + mottaker = + """altinn: { + serviceCode: "1", + serviceEdition: "1" + }""" + ) + + it("Oppgave har ikke grupperingsid, og er ikke koblet til sak") { + nyOppgave3 shouldBe instanceOf() + } + } }) private fun DescribeSpec.setupEngine(): Triple { @@ -162,11 +240,12 @@ private fun DescribeSpec.setupEngine(): Triple DescribeSpecContainerScope.opprettOgTestNyOppgave( +private suspend inline fun DescribeSpecContainerScope.opprettOgTestNyOppgave( engine: TestApplicationEngine, frist: String = "", grupperingsid: String = "", -): T { + + ): T { val response = engine.produsentApi( """ mutation { @@ -204,7 +283,7 @@ private suspend inline fun Desc feilmelding idTilEksisterende } - ... on Error { + ... on UgyldigMottaker { feilmelding } } @@ -227,3 +306,53 @@ private suspend inline fun Desc return nyOppgave as T } +private fun DescribeSpecContainerScope.opprettOppgaveMedMottaker( + engine: TestApplicationEngine, + grupperingsId: String, + eksternId: String, + mottaker: String, + virksomhetsnummer: String, +): MutationNyOppgave.NyOppgaveResultat { + val mutation = + """ + mutation { + nyOppgave(nyOppgave: { + mottakere: [{ + $mottaker + } + ] + + notifikasjon: { + lenke: "https://foo.bar", + tekst: "hello world", + merkelapp: "tag", + } + metadata: { + eksternId: "$eksternId", + opprettetTidspunkt: "2019-10-12T07:20:50.52Z" + virksomhetsnummer: "$virksomhetsnummer" + hardDelete: { + den: "2019-10-13T07:20:50.52" + } + grupperingsid: "$grupperingsId", + } + }) { + __typename + ... on NyOppgaveVellykket { + id + eksterneVarsler { + id + } + } + ... on Error { + feilmelding + } + } + } + """.trimIndent() + + val response = engine.produsentApi(mutation) + response.status() shouldBe HttpStatusCode.OK + response.getGraphqlErrors() should beEmpty() + return response.getTypedContent("nyOppgave") +} \ No newline at end of file