Skip to content

Commit

Permalink
Merge pull request #790 from navikt/ny-mottaker
Browse files Browse the repository at this point in the history
Ny mottaker
  • Loading branch information
kenglxn authored Nov 19, 2024
2 parents 7c62a78 + 4f91ad3 commit 34aac08
Show file tree
Hide file tree
Showing 33 changed files with 1,916 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,15 @@ class BrukerRepositoryImpl(
altinnTilgang = "${mottaker.serviceCode}:${mottaker.serviceEdition}"
)
}

is HendelseModel.AltinnRessursMottaker -> {
storeAltinnMottaker(
notifikasjonId = notifikasjonId,
sakId = sakId,
orgNr = mottaker.virksomhetsnummer,
altinnTilgang = mottaker.ressursId
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,12 @@ object HendelseModel {
val virksomhetsnummer: String,
) : Mottaker()

@JsonTypeName("altinnRessurs")
data class AltinnRessursMottaker(
val virksomhetsnummer: String,
val ressursId: String,
) : Mottaker()

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
sealed class EksterntVarsel {
abstract val varselId: UUID
Expand Down Expand Up @@ -804,4 +810,5 @@ val HendelseModel.Mottaker.virksomhetsnummer: String
get() = when (this) {
is HendelseModel.NærmesteLederMottaker -> this.virksomhetsnummer
is HendelseModel.AltinnMottaker -> this.virksomhetsnummer
is HendelseModel.AltinnRessursMottaker -> this.virksomhetsnummer
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package no.nav.arbeidsgiver.notifikasjon.infrastruktur.produsenter

import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnRessursMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.Mottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.NærmesteLederMottaker
import no.nav.arbeidsgiver.notifikasjon.infrastruktur.azuread.AppName
Expand Down Expand Up @@ -51,6 +53,25 @@ data class ServicecodeDefinisjon(
override fun hashCode(): Int = Objects.hash(code, version)
}

data class RessursIdDefinisjon(
val ressursId: String,
) : MottakerDefinisjon() {
override fun akseptererMottaker(mottaker: Mottaker): Boolean =
when (mottaker) {
is AltinnRessursMottaker ->
mottaker.ressursId == ressursId
else -> false
}

override fun equals(other: Any?): Boolean = when {
this === other -> true
other is RessursIdDefinisjon -> this.ressursId == other.ressursId
else -> false
}

override fun hashCode(): Int = Objects.hash(ressursId)
}

object NærmesteLederDefinisjon : MottakerDefinisjon() {
override fun akseptererMottaker(mottaker: Mottaker): Boolean =
when (mottaker) {
Expand All @@ -65,10 +86,16 @@ object MottakerRegister {
return MOTTAKER_REGISTER.filterIsInstance<ServicecodeDefinisjon>()
}

val ressursIdDefinisjoner: List<RessursIdDefinisjon>
get() {
return MOTTAKER_REGISTER.filterIsInstance<RessursIdDefinisjon>()
}

fun erDefinert(mottakerDefinisjon: MottakerDefinisjon): Boolean =
when (mottakerDefinisjon) {
is ServicecodeDefinisjon -> servicecodeDefinisjoner.contains(mottakerDefinisjon)
is NærmesteLederDefinisjon -> true
is RessursIdDefinisjon -> ressursIdDefinisjoner.contains(mottakerDefinisjon)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ val FAGER_TESTPRODUSENT = Produsent(
"Inntektsmelding opplæringspenger",
),
tillatteMottakere = listOf(
RessursIdDefinisjon(ressursId = "test-fager"),
ServicecodeDefinisjon(code = "4936", version = "1"),
ServicecodeDefinisjon(code = "5516", version = "1", description = "Midlertidig lønnstilskudd"),
ServicecodeDefinisjon(code = "5516", version = "2", description = "Varig lønnstilskudd'"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
import no.nav.arbeidsgiver.notifikasjon.hendelse.HardDeletedRepository
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnRessursMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.BeskjedOpprettet
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.BrukerKlikket
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.EksterntVarselFeilet
Expand Down Expand Up @@ -234,6 +235,13 @@ class ProdusentRepositoryImpl(
where md.notifikasjon_id = valgt_notifikasjon.id
),
'[]'::jsonb)
|| coalesce(
(
select mar.mottakere::jsonb
from mottakere_altinn_ressurs_json mar
where mar.notifikasjon_id = valgt_notifikasjon.id
),
'[]'::jsonb)
) as mottakere
from valgt_notifikasjon
""",
Expand Down Expand Up @@ -855,6 +863,7 @@ class ProdusentRepositoryImpl(
when (mottaker) {
is NærmesteLederMottaker -> storeNærmesteLederMottaker(notifikasjonId, mottaker)
is AltinnMottaker -> storeAltinnMottaker(notifikasjonId, mottaker)
is AltinnRessursMottaker -> storeAltinnRessursMottaker(notifikasjonId, mottaker)
}
}

Expand Down Expand Up @@ -889,6 +898,21 @@ class ProdusentRepositoryImpl(
}
}

private fun Transaction.storeAltinnRessursMottaker(notifikasjonId: UUID, mottaker: AltinnRessursMottaker) {
executeUpdate(
"""
insert into mottaker_altinn_ressurs
(notifikasjon_id, virksomhet, ressursId)
values (?, ?, ?)
on conflict do nothing
"""
) {
uuid(notifikasjonId)
text(mottaker.virksomhetsnummer)
text(mottaker.ressursId)
}
}

private suspend fun oppdaterModellEtterKalenderavtaleOpprettet(hendelse: KalenderavtaleOpprettet) {
database.transaction {
executeUpdate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName
import graphql.schema.idl.RuntimeWiring
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnRessursMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.Mottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.NyStatusSak
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.NærmesteLederMottaker
Expand Down Expand Up @@ -227,6 +228,7 @@ private fun MottakerInput.sammeSom(mottaker: Mottaker): Boolean {
is NærmesteLederMottaker ->
mottaker.ansattFnr == this.naermesteLeder?.ansattFnr &&
mottaker.naermesteLederFnr == this.naermesteLeder.naermesteLederFnr
is AltinnRessursMottaker -> mottaker.ressursId == this.altinnRessurs?.ressursId
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package no.nav.arbeidsgiver.notifikasjon.produsent.api

import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinnRessursMottaker
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.AltinntjenesteVarselKontaktinfo
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.EksterntVarsel
import no.nav.arbeidsgiver.notifikasjon.hendelse.HendelseModel.EksterntVarselSendingsvindu
Expand Down Expand Up @@ -162,23 +163,35 @@ internal data class AltinnMottakerInput(
)
}

internal data class AltinnRessursMottakerInput(
val ressursId: String,
) {
fun tilDomene(virksomhetsnummer: String): Mottaker =
AltinnRessursMottaker(
ressursId = ressursId,
virksomhetsnummer = virksomhetsnummer
)
}

internal class UkjentRolleException(message: String) : RuntimeException(message)


internal data class MottakerInput(
val altinn: AltinnMottakerInput?,
val naermesteLeder: NaermesteLederMottakerInput?,
val altinnRessurs: AltinnRessursMottakerInput?
) {

fun tilHendelseModel(
virksomhetsnummer: String,
): Mottaker {
check(listOfNotNull(altinn, naermesteLeder).size == 1) {
check(listOfNotNull(altinn, naermesteLeder, altinnRessurs).size == 1) {
"Ugyldig mottaker"
}
return altinn?.tilDomene(virksomhetsnummer)
?: (naermesteLeder?.tilDomene(virksomhetsnummer)
?: throw IllegalArgumentException("Ugyldig mottaker"))
return altinnRessurs?.tilDomene(virksomhetsnummer)
?: altinn?.tilDomene(virksomhetsnummer)
?: naermesteLeder?.tilDomene(virksomhetsnummer)
?: throw IllegalArgumentException("Ugyldig mottaker")
}
}

Expand Down Expand Up @@ -213,7 +226,6 @@ internal fun EksterntVarselInput.SendetidspunktInput.somVinduOgTidspunkt(): Pair
}



internal data class PaaminnelseInput(
val tidspunkt: PaaminnelseTidspunktInput,
val eksterneVarsler: List<PaaminnelseEksterntVarselInput>,
Expand All @@ -223,7 +235,7 @@ internal data class PaaminnelseInput(
frist: LocalDate?,
startTidspunkt: LocalDateTime?,
virksomhetsnummer: String,
) : HendelseModel.Påminnelse = HendelseModel.Påminnelse(
): HendelseModel.Påminnelse = HendelseModel.Påminnelse(
tidspunkt = tidspunkt.tilDomene(notifikasjonOpprettetTidspunkt, frist, startTidspunkt),
eksterneVarsler = eksterneVarsler.map {
it.tilDomene(virksomhetsnummer)
Expand All @@ -248,22 +260,26 @@ data class PaaminnelseTidspunktInput(
frist,
startTidspunkt,
)

etterOpprettelse != null -> HendelseModel.PåminnelseTidspunkt.createAndValidateEtterOpprettelse(
etterOpprettelse,
notifikasjonOpprettetTidspunkt,
frist,
startTidspunkt
)

foerFrist != null -> HendelseModel.PåminnelseTidspunkt.createAndValidateFørFrist(
foerFrist,
notifikasjonOpprettetTidspunkt,
frist,
)

foerStartTidspunkt != null -> HendelseModel.PåminnelseTidspunkt.createAndValidateFørStartTidspunkt(
foerStartTidspunkt,
notifikasjonOpprettetTidspunkt,
startTidspunkt,
)

else -> throw RuntimeException("Feil format")
}
}
Expand Down Expand Up @@ -300,6 +316,7 @@ internal class PaaminnelseEksterntVarselInput(
throw RuntimeException("mottaker-felt mangler for sms")
}
}

class Epost(
val mottaker: EksterntVarselInput.Epost.Mottaker,
val epostTittel: String,
Expand All @@ -321,6 +338,7 @@ internal class PaaminnelseEksterntVarselInput(
throw RuntimeException("mottaker mangler for epost")
}
}

data class Altinntjeneste(
val mottaker: Mottaker,
val tittel: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ internal class QueryNotifikasjoner(
return when (domene) {
is HendelseModel.AltinnMottaker -> AltinnMottaker.fraDomene(domene)
is HendelseModel.NærmesteLederMottaker -> NærmesteLederMottaker.fraDomene(domene)
is HendelseModel.AltinnRessursMottaker -> AltinnRessursMottaker.fraDomene(domene)
}
}
}
Expand Down Expand Up @@ -305,6 +306,21 @@ internal class QueryNotifikasjoner(
}
}

@JsonTypeName("AltinnRessursMottaker")
data class AltinnRessursMottaker(
val ressursId: String,
val virksomhetsnummer: String
) : Mottaker(){
companion object {
fun fraDomene(domene: HendelseModel.AltinnRessursMottaker): AltinnRessursMottaker {
return AltinnRessursMottaker(
ressursId = domene.ressursId,
virksomhetsnummer = domene.virksomhetsnummer
)
}
}
}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "__typename")
sealed interface MineNotifikasjonerResultat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ fun List<Mottaker>.oppsummering(): String =
when (it) {
is NærmesteLederMottaker -> "NærmesteLeder"
is AltinnMottaker -> "Altinn:${it.serviceCode}:${it.serviceEdition}"
is HendelseModel.AltinnRessursMottaker -> "AltinnRessurs:${it.ressursId}"
}
}
.sorted()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
create table mottaker_altinn_ressurs
(
id bigserial primary key,
notifikasjon_id uuid not null references notifikasjon on delete cascade,
virksomhet text not null,
ressursId text not null
);

create index mottaker_altinn_ressurs_notifikasjon_id_idx
on mottaker_altinn_ressurs (notifikasjon_id);

create unique index mottaker_altinn_ressurs_unique
on mottaker_altinn_ressurs (notifikasjon_id, virksomhet, ressursId);

create view mottakere_altinn_ressurs_json as
select notifikasjon_id,
json_agg(
json_build_object(
'@type', 'altinnRessurs',
'virksomhetsnummer', virksomhet,
'ressursId', ressursId
)
) as mottakere
from mottaker_altinn_ressurs
group by notifikasjon_id;
29 changes: 26 additions & 3 deletions app/src/main/resources/produsent.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ type Kalenderavtale {
union Mottaker =
| AltinnMottaker
| NaermesteLederMottaker
| AltinnRessursMottaker

type AltinnMottaker {
serviceCode: String!
Expand All @@ -193,6 +194,11 @@ type NaermesteLederMottaker {
virksomhetsnummer: String!
}

type AltinnRessursMottaker {
virksomhetsnummer: String!
ressursId: String!
}

type OppgaveData {
tilstand: OppgaveTilstand

Expand Down Expand Up @@ -1691,22 +1697,39 @@ Vi har implementert det på denne måten fordi GraphQL ikke støtter union-typer
"""
input MottakerInput @ExactlyOneFieldGiven {
altinn: AltinnMottakerInput
altinnRessurs: AltinnRessursMottakerInput
naermesteLeder: NaermesteLederMottakerInput
}

"""
Spesifiser mottaker ved hjelp av tilganger i Altinn. Enhver som har den gitte tilgangen vil
Spesifiser mottaker ved hjelp av tilganger i Altinn 2. Enhver som har den gitte tilgangen vil
kunne se notifikasjone.
Tilgangssjekken utføres hver gang en bruker ser på notifikasjoner. Det betyr at hvis en
bruker mister en Altinn-tilgang, så vil de hverken se historiske eller nye notifikasjone knyttet til den Altinn-tilgangen.
Og motsatt, hvis en bruker får en Altinn-tilgang, vil de se tidligere notifikasjoner for den Altinn-tilgangen.
bruker mister en Altinn 2-tilgang, så vil de hverken se historiske eller nye notifikasjone knyttet til den Altinn 2-tilgangen.
Og motsatt, hvis en bruker får en Altinn 2-tilgang, vil de se tidligere notifikasjoner for den Altinn2-tilgangen.
Altinn 2 skal avvikles innen juni 2026, og denne mottakeren vil da også forsvinne. Vi anbefaler å migrere til Altinn 3, og ta i bruk
AltinnRessursMottakerInput. Når dere migrerer til Altinn3 kan vi sørge for at brukere fortsatt får tilgang til gamle saker og notifikasjoner, så lenge vi blir informert
om hvilke Altinn 3 ressurser som tilsvarer hvilke Altinn 2 tjenester. Ta gjerne kontakt med oss og gi beskjed.
"""
input AltinnMottakerInput {
serviceCode: String!
serviceEdition: String!
}

"""
Spesifiser mottaker ved hjelp av tilganger i Altinn 3. Enhver som har den gitte tilgangen vil
kunne se notifikasjone.
Tilgangssjekken utføres hver gang en bruker ser på notifikasjoner. Det betyr at hvis en
bruker mister en Altinn 3-tilgang, så vil de hverken se historiske eller nye notifikasjone knyttet til den Altinn 3-tilgangen.
Og motsatt, hvis en bruker får en Altinn 3-tilgang, vil de se tidligere notifikasjoner for den Altinn2-tilgangen.
"""
input AltinnRessursMottakerInput {
ressursId: String!
}

"""
Spesifiser mottaker ved hjelp av fødselsnummer. Fødselsnummeret er det til nærmeste leder. Det er kun denne personen
som potensielt kan se notifikasjonen. Det er videre en sjekk for å se om denne personen fortsatt er nærmeste leder
Expand Down
Loading

0 comments on commit 34aac08

Please sign in to comment.