diff --git a/domene/src/main/java/no/nav/foreldrepenger/los/avdelingsleder/AvdelingslederSaksbehandlerTjeneste.java b/domene/src/main/java/no/nav/foreldrepenger/los/avdelingsleder/AvdelingslederSaksbehandlerTjeneste.java index 906027e12..11bc945f4 100644 --- a/domene/src/main/java/no/nav/foreldrepenger/los/avdelingsleder/AvdelingslederSaksbehandlerTjeneste.java +++ b/domene/src/main/java/no/nav/foreldrepenger/los/avdelingsleder/AvdelingslederSaksbehandlerTjeneste.java @@ -10,6 +10,7 @@ import no.nav.foreldrepenger.los.organisasjon.Avdeling; import no.nav.foreldrepenger.los.organisasjon.OrganisasjonRepository; import no.nav.foreldrepenger.los.organisasjon.Saksbehandler; +import no.nav.foreldrepenger.los.organisasjon.SaksbehandlerGruppe; import no.nav.vedtak.exception.TekniskException; @ApplicationScoped @@ -37,7 +38,7 @@ public void leggSaksbehandlerTilAvdeling(String saksbehandlerIdent, String avdel .orElseGet(() -> opprettSaksbehandler(saksbehandlerIdent)); var avdeling = hentAvdeling(avdelingEnhet); saksbehandler.leggTilAvdeling(avdeling); - organisasjonRepository.lagre(saksbehandler); + organisasjonRepository.persistFlush(saksbehandler); organisasjonRepository.refresh(avdeling); } @@ -45,7 +46,7 @@ public void fjernSaksbehandlerFraAvdeling(String saksbehandlerIdent, String avde var saksbehandler = organisasjonRepository.hentSaksbehandlerHvisEksisterer(saksbehandlerIdent) .orElseThrow(() -> AvdelingSaksbehandlerTjenesteFeil.finnerIkkeSaksbehandler(saksbehandlerIdent)); saksbehandler.fjernAvdeling(organisasjonRepository.hentAvdelingFraEnhet(avdelingEnhet).orElseThrow()); - organisasjonRepository.lagre(saksbehandler); + organisasjonRepository.persistFlush(saksbehandler); var avdeling = hentAvdeling(avdelingEnhet); var oppgaveFiltreringList = avdeling.getOppgaveFiltrering(); @@ -62,11 +63,39 @@ private Avdeling hentAvdeling(String avdelingEnhet) { private Saksbehandler opprettSaksbehandler(String ident) { var saksbehandler = new Saksbehandler(ident.toUpperCase()); - organisasjonRepository.lagre(saksbehandler); + organisasjonRepository.persistFlush(saksbehandler); return organisasjonRepository.hentSaksbehandlerHvisEksisterer(ident) .orElseThrow(() -> AvdelingSaksbehandlerTjenesteFeil.finnerIkkeSaksbehandler(ident)); } + public List hentAvdelingensSaksbehandlereOgGrupper(String avdelingEnhet) { + return organisasjonRepository.hentSaksbehandlerGrupper(avdelingEnhet); + } + + public void leggSaksbehandlerTilGruppe(String saksbehandlerId, long gruppeId, String avdelingEnhet) { + organisasjonRepository.leggSaksbehandlerTilGruppe(saksbehandlerId, gruppeId, avdelingEnhet); + } + + public void fjernSaksbehandlerFraGruppe(String saksbehandlerId, long gruppeId, String avdelingEnhet) { + organisasjonRepository.fjernSaksbehandlerFraGruppe(saksbehandlerId, gruppeId, avdelingEnhet); + } + + public SaksbehandlerGruppe opprettSaksbehandlerGruppe(String avdelingEnhet) { + var gruppe = new SaksbehandlerGruppe("Ny saksbehandlergruppe"); + var avdeling = hentAvdeling(avdelingEnhet); + gruppe.setAvdeling(avdeling); + organisasjonRepository.persistFlush(gruppe); + return gruppe; + } + + public void endreSaksbehandlerGruppeNavn(long gruppeId, String gruppeNavn) { + organisasjonRepository.updateSaksbehandlerGruppeNavn(gruppeId, gruppeNavn); + } + + public void slettSaksbehandlerGruppe(long gruppeId, String avdelingEnhet) { + organisasjonRepository.slettSaksbehandlerGruppe(gruppeId, avdelingEnhet); + } + private static final class AvdelingSaksbehandlerTjenesteFeil { private static TekniskException finnerIkkeSaksbehandler(String ident) { return new TekniskException("Finner ikke saksbehandler med ident {}", ident); diff --git a/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/OrganisasjonRepository.java b/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/OrganisasjonRepository.java index b30a027dc..9804ea36d 100644 --- a/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/OrganisasjonRepository.java +++ b/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/OrganisasjonRepository.java @@ -10,6 +10,8 @@ import jakarta.inject.Inject; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; +import no.nav.foreldrepenger.los.felles.BaseEntitet; +import no.nav.vedtak.felles.jpa.TomtResultatException; @ApplicationScoped @@ -25,7 +27,7 @@ public OrganisasjonRepository(EntityManager entityManager) { OrganisasjonRepository() { } - public void lagre(Saksbehandler saksbehandler) { + public void persistFlush(T saksbehandler) { entityManager.persist(saksbehandler); entityManager.flush(); } @@ -59,4 +61,62 @@ public List hentAvdelinger() { var listeTypedQuery = entityManager.createQuery("FROM avdeling ", Avdeling.class); return listeTypedQuery.getResultList(); } + + public List hentSaksbehandlerGrupper(String avdelingEnhet) { + return entityManager.createQuery("FROM saksbehandlerGruppe g where g.avdeling.avdelingEnhet = :avdelingEnhet", SaksbehandlerGruppe.class) + .setParameter("avdelingEnhet", avdelingEnhet) + .getResultList(); + } + + public void leggSaksbehandlerTilGruppe(String saksbehandlerId, long gruppeId, String avdelingEnhet) { + var gruppe = entityManager.find(SaksbehandlerGruppe.class, gruppeId); + sjekkGruppeEnhetTilknytning(gruppeId, avdelingEnhet, gruppe); + var saksbehandler = hentSaksbehandlerHvisEksisterer(saksbehandlerId).filter(sb -> sb.getAvdelinger().contains(gruppe.getAvdeling())); + saksbehandler.ifPresentOrElse(sb -> { + gruppe.getSaksbehandlere().add(sb); + entityManager.persist(gruppe); + }, () -> { + throw fantIkkeSaksbehandlerException(saksbehandlerId, avdelingEnhet); + }); + } + + public void fjernSaksbehandlerFraGruppe(String saksbehandlerIdent, long gruppeId, String avdelingEnhet) { + var gruppe = entityManager.find(SaksbehandlerGruppe.class, gruppeId); + sjekkGruppeEnhetTilknytning(gruppeId, avdelingEnhet, gruppe); + gruppe.getSaksbehandlere().removeIf(s -> s.getSaksbehandlerIdent().equals(saksbehandlerIdent)); + entityManager.persist(gruppe); + } + + public void updateSaksbehandlerGruppeNavn(long gruppeId, String gruppeNavn) { + entityManager.createQuery("UPDATE saksbehandlerGruppe g SET g.gruppeNavn = :gruppeNavn WHERE g.id = :gruppeId") + .setParameter("gruppeNavn", gruppeNavn) + .setParameter("gruppeId", gruppeId) + .executeUpdate(); + } + + public void slettSaksbehandlerGruppe(long gruppeId, String avdelingEnhet) { + var gruppe = entityManager.find(SaksbehandlerGruppe.class, gruppeId); + sjekkGruppeEnhetTilknytning(gruppeId, avdelingEnhet, gruppe); + gruppe.getSaksbehandlere().clear(); + entityManager.merge(gruppe); + entityManager.remove(gruppe); + entityManager.flush(); + } + + private static void sjekkGruppeEnhetTilknytning(long gruppeId, String avdelingEnhet, SaksbehandlerGruppe gruppe) { + if (gruppe == null || !gruppe.getAvdeling().getAvdelingEnhet().equals(avdelingEnhet)) { + throw fantIkkeGruppeException(gruppeId, avdelingEnhet); + } + } + + private static TomtResultatException fantIkkeGruppeException(long gruppeId, String avdelingEnhet) { + return new TomtResultatException("FP-164688", String.format("Fant ikke gruppe %s for avdeling %s", gruppeId, avdelingEnhet)); + } + + private static TomtResultatException fantIkkeSaksbehandlerException(String saksbehandlerIdent, String avdelingEnhet) { + return new TomtResultatException("FP-164689", + String.format("Fant ikke saksbehandler %s tilknyttet avdeling %s", saksbehandlerIdent, avdelingEnhet)); + } + + } diff --git a/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/SaksbehandlerGruppe.java b/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/SaksbehandlerGruppe.java new file mode 100644 index 000000000..69f2981d9 --- /dev/null +++ b/domene/src/main/java/no/nav/foreldrepenger/los/organisasjon/SaksbehandlerGruppe.java @@ -0,0 +1,69 @@ +package no.nav.foreldrepenger.los.organisasjon; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import no.nav.foreldrepenger.los.felles.BaseEntitet; + +import java.util.HashSet; +import java.util.Set; + +@Entity(name = "saksbehandlerGruppe") +@Table(name = "SAKSBEHANDLER_GRUPPE") +public class SaksbehandlerGruppe extends BaseEntitet { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GRUPPE") + private Long id; + + @Column(name = "GRUPPE_NAVN") + private String gruppeNavn; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "AVDELING_ID", updatable = false) + private Avdeling avdeling; + + @ManyToMany + @JoinTable(name = "gruppe_tilknytning", joinColumns = @JoinColumn(name = "gruppe_id"), inverseJoinColumns = @JoinColumn(name = "saksbehandler_id")) + private Set saksbehandlere = new HashSet<>(); + + SaksbehandlerGruppe() { + // hibernate + } + + public SaksbehandlerGruppe(String gruppeNavn) { + this.gruppeNavn = gruppeNavn; + } + + public Long getId() { + return id; + } + + public Set getSaksbehandlere() { + return saksbehandlere; + } + + public Avdeling getAvdeling() { + return avdeling; + } + + public void setGruppeNavn(String gruppeNavn) { + this.gruppeNavn = gruppeNavn; + } + + public String getGruppeNavn() { + return gruppeNavn; + } + + public void setAvdeling(Avdeling avdeling) { + this.avdeling = avdeling; + } +} diff --git a/migreringer/src/main/resources/db/migration/defaultDS/2.2/V2.2_05__saksbehandlergrupper.sql b/migreringer/src/main/resources/db/migration/defaultDS/2.2/V2.2_05__saksbehandlergrupper.sql new file mode 100644 index 000000000..d05adde27 --- /dev/null +++ b/migreringer/src/main/resources/db/migration/defaultDS/2.2/V2.2_05__saksbehandlergrupper.sql @@ -0,0 +1,48 @@ +CREATE TABLE SAKSBEHANDLER_GRUPPE +( + ID NUMBER(19) NOT NULL + CONSTRAINT PK_SAKSBEHANDLER_GRUPPE PRIMARY KEY, + GRUPPE_NAVN VARCHAR2(255 char) NOT NULL, + AVDELING_ID NUMBER(19) NOT NULL + CONSTRAINT FK_SAKSBEHANDLER_GRUPPE_AVDELING_01 REFERENCES AVDELING (ID), + VERSJON NUMBER(19) default 0 not null, + OPPRETTET_AV VARCHAR2(20 char) default 'VL' not null, + OPPRETTET_TID TIMESTAMP(3) default systimestamp not null, + ENDRET_AV VARCHAR2(20 char), + ENDRET_TID TIMESTAMP(3) +); + +CREATE INDEX IDX_SAKSBEHANDLER_GRUPPE_1 + on SAKSBEHANDLER_GRUPPE (AVDELING_ID); + +COMMENT ON TABLE SAKSBEHANDLER_GRUPPE IS 'Tabell som holder informasjon om grupper'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.ID IS 'Gruppe ID'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.GRUPPE_NAVN IS 'Gruppenavn'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.AVDELING_ID IS 'Referanse til avdeling som gruppen tilhører'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.VERSJON IS 'angir versjon for optimistisk låsing hvor aktuelt'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.OPPRETTET_AV IS 'Bruker som opprettet raden'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.OPPRETTET_TID IS 'Tidspunkt for opprettelse'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.ENDRET_AV IS 'Endret av'; +COMMENT ON column SAKSBEHANDLER_GRUPPE.ENDRET_TID IS 'Timestamp endring'; + + +CREATE TABLE GRUPPE_TILKNYTNING +( + SAKSBEHANDLER_ID NUMBER(19) NOT NULL + CONSTRAINT FK_GRUPPE_TILKNYTNING_SAKSBEHANDLER_01 REFERENCES SAKSBEHANDLER (ID), + GRUPPE_ID NUMBER(19) NOT NULL + CONSTRAINT FK_GRUPPE_TILKNYTNING_SAKSBEHANDLER_GRUPPE_01 REFERENCES SAKSBEHANDLER_GRUPPE (ID), + CONSTRAINT PK_GRUPPE_TILKNYTNING PRIMARY KEY (SAKSBEHANDLER_ID, GRUPPE_ID) +); + +CREATE SEQUENCE SEQ_GRUPPE START WITH 1000 INCREMENT BY 50 NOCACHE; + +CREATE INDEX IDX_GRUPPE_TILKNYTNING_1 + on GRUPPE_TILKNYTNING (SAKSBEHANDLER_ID); + +CREATE INDEX IDX_GRUPPE_TILKNYTNING_2 + on GRUPPE_TILKNYTNING (GRUPPE_ID); + +COMMENT ON TABLE GRUPPE_TILKNYTNING IS 'Jointabell som holder koblinger mellom saksbehandlere og gruppe'; +COMMENT ON column GRUPPE_TILKNYTNING.SAKSBEHANDLER_ID IS 'Saksbehandler ID'; +COMMENT ON column GRUPPE_TILKNYTNING.GRUPPE_ID IS 'Gruppe ID'; diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/dto/SaksbehandlerOgGruppeDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/dto/SaksbehandlerOgGruppeDto.java new file mode 100644 index 000000000..b7719184e --- /dev/null +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/dto/SaksbehandlerOgGruppeDto.java @@ -0,0 +1,20 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksliste.FplosAbacAttributtType; +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerBrukerIdentDto; +import no.nav.vedtak.sikkerhet.abac.AbacDataAttributter; +import no.nav.vedtak.sikkerhet.abac.AbacDto; + +public record SaksbehandlerOgGruppeDto(@NotNull @Valid SaksbehandlerBrukerIdentDto brukerIdent, + @NotNull @Valid AvdelingEnhetDto avdelingEnhet, + @Min(1) @Max(Integer.MAX_VALUE) long gruppeId) implements AbacDto { + + @Override + public AbacDataAttributter abacAttributter() { + return AbacDataAttributter.opprett().leggTil(FplosAbacAttributtType.OPPGAVESTYRING_ENHET, avdelingEnhet.getAvdelingEnhet()); + } +} diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjeneste.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjeneste.java index d1ae165b0..49886f691 100644 --- a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjeneste.java +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjeneste.java @@ -20,6 +20,7 @@ import no.nav.foreldrepenger.los.avdelingsleder.AvdelingslederSaksbehandlerTjeneste; import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.AvdelingEnhetDto; import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.SaksbehandlerOgAvdelingDto; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.SaksbehandlerOgGruppeDto; import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerBrukerIdentDto; import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerDtoTjeneste; import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerMedAvdelingerDto; @@ -82,4 +83,60 @@ public void slettSaksbehandler(@NotNull @Parameter(description = "Brukeridentifi avdelingslederSaksbehandlerTjeneste.fjernSaksbehandlerFraAvdeling(saksbehandlerOgAvdeling.getBrukerIdent().getVerdi(), saksbehandlerOgAvdeling.getAvdelingEnhet().getAvdelingEnhet()); } + + @GET + @Path("/grupper") + @Operation(description = "Avdelingsliste saksbehandlere og grupper", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.READ, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET, sporingslogg = false) + public SaksbehandlereOgSaksbehandlerGrupper hentSaksbehandlerGrupper(@NotNull @QueryParam("avdelingEnhet") @Valid AvdelingEnhetDto avdelingEnhetDto) { + var avdelingensSaksbehandlere = avdelingslederSaksbehandlerTjeneste.hentAvdelingensSaksbehandlere(avdelingEnhetDto.getAvdelingEnhet()) + .stream() + .map(saksbehandlerDtoTjeneste::lagKjentOgUkjentSaksbehandlerMedAvdelingerDto) + .toList(); + // Litt dobbeltarbeid her i overgangsfase - vi henter saksbehandlere og mapper som før i tillegg til å gjøre samme med gruppene + var saksbehandlereGruppe = avdelingslederSaksbehandlerTjeneste.hentAvdelingensSaksbehandlereOgGrupper(avdelingEnhetDto.getAvdelingEnhet()) + .stream().map(g -> new SaksbehandlerGruppeDto(g.getId(), g.getGruppeNavn(), g.getSaksbehandlere().stream().map(saksbehandlerDtoTjeneste::lagKjentOgUkjentSaksbehandlerMedAvdelingerDto).toList())).toList(); + return new SaksbehandlereOgSaksbehandlerGrupper(avdelingensSaksbehandlere, saksbehandlereGruppe); + } + + @POST + @Path("/grupper/opprett-gruppe") + @Operation(description = "Oppretter gruppe", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.CREATE, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET) + public SaksbehandlerGruppeDto opprettSaksbehandlerGruppe(@Valid AvdelingEnhetDto dto) { + var sbg = avdelingslederSaksbehandlerTjeneste.opprettSaksbehandlerGruppe(dto.getAvdelingEnhet()); + return new SaksbehandlerGruppeDto(sbg.getId(), sbg.getGruppeNavn(), List.of()); + } + + @POST + @Path("/grupper/endre-gruppe") + @Operation(description = "Gir nytt navn til gruppe", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.UPDATE, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET) + public void endreSaksbehandlerGruppe(@Valid SaksbehandlerGruppeNavneEndringDto dto) { + avdelingslederSaksbehandlerTjeneste.endreSaksbehandlerGruppeNavn(dto.gruppeId(), dto.gruppeNavn()); + } + + @POST + @Path("/grupper/legg-til-saksbehandler") + @Operation(description = "Legger saksbehandler til gruppe", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.CREATE, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET) + public void leggSaksbehandlerTilGruppe(@Valid SaksbehandlerOgGruppeDto dto) { + avdelingslederSaksbehandlerTjeneste.leggSaksbehandlerTilGruppe(dto.brukerIdent().getVerdi(), dto.gruppeId(), dto.avdelingEnhet().getAvdelingEnhet()); + } + + @POST + @Path("/grupper/fjern-saksbehandler") + @Operation(description = "Fjerner saksbehandler fra gruppe", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.CREATE, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET) + public void fjernSaksbehandlerFraGruppe(@Valid SaksbehandlerOgGruppeDto dto) { + avdelingslederSaksbehandlerTjeneste.fjernSaksbehandlerFraGruppe(dto.brukerIdent().getVerdi(), dto.gruppeId(), dto.avdelingEnhet().getAvdelingEnhet()); + } + + @POST + @Path("/grupper/slett-saksbehandlergruppe") + @Operation(description = "Sletter saksbehandlergruppe", tags = "AvdelingslederSaksbehandlergrupper") + @BeskyttetRessurs(actionType = ActionType.DELETE, resourceType = ResourceType.OPPGAVESTYRING_AVDELINGENHET) + public void slettSaksbehandlerGruppe(@Valid SaksbehandlerGruppeSletteRequestDto dto) { + avdelingslederSaksbehandlerTjeneste.slettSaksbehandlerGruppe(dto.gruppeId(), dto.avdelingEnhet().getAvdelingEnhet()); + } } diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeDto.java new file mode 100644 index 000000000..2e1fe681c --- /dev/null +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeDto.java @@ -0,0 +1,7 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksbehandler; + +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerMedAvdelingerDto; +import java.util.List; + +public record SaksbehandlerGruppeDto(long gruppeId, String gruppeNavn, List saksbehandlere) { +} diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeNavneEndringDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeNavneEndringDto.java new file mode 100644 index 000000000..4e0e51ee4 --- /dev/null +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeNavneEndringDto.java @@ -0,0 +1,23 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksbehandler; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.AvdelingEnhetDto; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksliste.FplosAbacAttributtType; +import no.nav.vedtak.sikkerhet.abac.AbacDataAttributter; +import no.nav.vedtak.sikkerhet.abac.AbacDto; +import no.nav.vedtak.util.InputValideringRegex; + +public record SaksbehandlerGruppeNavneEndringDto(@Min(1) @Max(Integer.MAX_VALUE) long gruppeId, + @NotNull @Size(max = 500) @Pattern(regexp = InputValideringRegex.FRITEKST) String gruppeNavn, + @Valid AvdelingEnhetDto avdelingEnhet) implements AbacDto { + + @Override + public AbacDataAttributter abacAttributter() { + return AbacDataAttributter.opprett().leggTil(FplosAbacAttributtType.OPPGAVESTYRING_ENHET, avdelingEnhet.getAvdelingEnhet()); + } +} diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeSletteRequestDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeSletteRequestDto.java new file mode 100644 index 000000000..1a0ea7dd1 --- /dev/null +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlerGruppeSletteRequestDto.java @@ -0,0 +1,18 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksbehandler; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.AvdelingEnhetDto; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksliste.FplosAbacAttributtType; +import no.nav.vedtak.sikkerhet.abac.AbacDataAttributter; +import no.nav.vedtak.sikkerhet.abac.AbacDto; + +public record SaksbehandlerGruppeSletteRequestDto(@Min(1) @Max(Integer.MAX_VALUE) long gruppeId, + @Valid AvdelingEnhetDto avdelingEnhet) implements AbacDto { + + @Override + public AbacDataAttributter abacAttributter() { + return AbacDataAttributter.opprett().leggTil(FplosAbacAttributtType.OPPGAVESTYRING_ENHET, avdelingEnhet.getAvdelingEnhet()); + } +} diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlereOgSaksbehandlerGrupper.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlereOgSaksbehandlerGrupper.java new file mode 100644 index 000000000..9bc1409df --- /dev/null +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/SaksbehandlereOgSaksbehandlerGrupper.java @@ -0,0 +1,8 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksbehandler; + +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerMedAvdelingerDto; + +import java.util.List; + +public record SaksbehandlereOgSaksbehandlerGrupper(List saksbehandlere, List saksbehandlerGrupper) { +} diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerBrukerIdentDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerBrukerIdentDto.java index bd259191b..f70efe5e2 100644 --- a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerBrukerIdentDto.java +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerBrukerIdentDto.java @@ -19,10 +19,9 @@ public class SaksbehandlerBrukerIdentDto implements AbacDto { @NotNull @Size(max = 100) @Pattern(regexp = InputValideringRegex.FRITEKST) - private final String brukerIdent; + private String brukerIdent; public SaksbehandlerBrukerIdentDto() { - brukerIdent = null; // NOSONAR } public SaksbehandlerBrukerIdentDto(String brukerIdent) { diff --git a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerMedAvdelingerDto.java b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerMedAvdelingerDto.java index d4f5091cd..857f08b8f 100644 --- a/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerMedAvdelingerDto.java +++ b/web/src/main/java/no/nav/foreldrepenger/los/web/app/tjenester/felles/dto/SaksbehandlerMedAvdelingerDto.java @@ -9,7 +9,7 @@ public class SaksbehandlerMedAvdelingerDto { private SaksbehandlerDto saksbehandlerDto; private List avdelingsnavn; - SaksbehandlerMedAvdelingerDto(SaksbehandlerDto saksbehandlerDto, List avdelingsnavn) { + public SaksbehandlerMedAvdelingerDto(SaksbehandlerDto saksbehandlerDto, List avdelingsnavn) { this.saksbehandlerDto = saksbehandlerDto; this.avdelingsnavn = avdelingsnavn; } diff --git a/web/src/test/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjenesteTest.java b/web/src/test/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjenesteTest.java new file mode 100644 index 000000000..175dcf686 --- /dev/null +++ b/web/src/test/java/no/nav/foreldrepenger/los/web/app/tjenester/avdelingsleder/saksbehandler/AvdelingslederSaksbehandlerRestTjenesteTest.java @@ -0,0 +1,163 @@ +package no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.saksbehandler; + +import jakarta.persistence.EntityManager; +import no.nav.foreldrepenger.extensions.JpaExtension; + +import no.nav.foreldrepenger.los.avdelingsleder.AvdelingslederSaksbehandlerTjeneste; +import no.nav.foreldrepenger.los.oppgave.OppgaveRepository; +import no.nav.foreldrepenger.los.organisasjon.OrganisasjonRepository; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.AvdelingEnhetDto; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.SaksbehandlerOgAvdelingDto; +import no.nav.foreldrepenger.los.web.app.tjenester.avdelingsleder.dto.SaksbehandlerOgGruppeDto; +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerBrukerIdentDto; +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerDto; +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerDtoTjeneste; + +import no.nav.foreldrepenger.los.web.app.tjenester.felles.dto.SaksbehandlerMedAvdelingerDto; + +import no.nav.vedtak.felles.jpa.TomtResultatException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Objects; + +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +@ExtendWith(JpaExtension.class) +class AvdelingslederSaksbehandlerRestTjenesteTest { + + private static final AvdelingEnhetDto avdelingDto = new AvdelingEnhetDto("4817"); + private static final SaksbehandlerBrukerIdentDto brukerIdentDto = new SaksbehandlerBrukerIdentDto("Z999999"); + private static final SaksbehandlerDto saksbehandlerDto = new SaksbehandlerDto(brukerIdentDto, "Navn Navnesen"); + private AvdelingslederSaksbehandlerTjeneste avdelingslederSaksbehandlerTjeneste; + @Mock + private SaksbehandlerDtoTjeneste saksbehandlerDtoTjeneste; + + private AvdelingslederSaksbehandlerRestTjeneste restTjeneste; + + @Mock + private OppgaveRepository oppgaveRepository; + private EntityManager entityManager; + + @BeforeEach + public void setUp(EntityManager entityManager) { + this.entityManager = entityManager; + var organisasjonRepository = new OrganisasjonRepository(entityManager); + avdelingslederSaksbehandlerTjeneste = new AvdelingslederSaksbehandlerTjeneste(oppgaveRepository, organisasjonRepository); + restTjeneste = new AvdelingslederSaksbehandlerRestTjeneste(avdelingslederSaksbehandlerTjeneste, saksbehandlerDtoTjeneste); + } + + @Test + void kan_hente_lagrede_grupper() { + var nyGruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + var hentetGruppe = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + assertThat(nyGruppe).isNotNull().isInstanceOf(SaksbehandlerGruppeDto.class); + assertThat(hentetGruppe.saksbehandlerGrupper().get(0)).isEqualTo(nyGruppe); + } + + @Test + void kan_slette_gruppe() { + var gruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + restTjeneste.slettSaksbehandlerGruppe(new SaksbehandlerGruppeSletteRequestDto(gruppe.gruppeId(), avdelingDto)); + var etterSletting = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + assertThat(etterSletting.saksbehandlerGrupper()).isEmpty(); + } + + @Test + void kan_legge_saksbehandlere_til_gruppe() { + setupMockForMappingAvSaksbehandlerDto(); + + var gruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + restTjeneste.leggTilNySaksbehandler(new SaksbehandlerOgAvdelingDto(brukerIdentDto, avdelingDto)); + restTjeneste.leggSaksbehandlerTilGruppe(new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, (int) gruppe.gruppeId())); + var hentetGrupper = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + + assertThat(hentetGrupper.saksbehandlerGrupper()).hasSize(1); + var saksbehandlere = hentetGrupper.saksbehandlerGrupper().get(0).saksbehandlere(); + assertThat(saksbehandlere).hasSize(1); + assertThat(saksbehandlere.get(0).getBrukerIdent()).isEqualTo("Z999999"); + } + + @Test + void kan_fjerne_saksbehandlere_fra_gruppe() { + setupMockForMappingAvSaksbehandlerDto(); + var gruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + restTjeneste.leggTilNySaksbehandler(new SaksbehandlerOgAvdelingDto(brukerIdentDto, avdelingDto)); + restTjeneste.leggSaksbehandlerTilGruppe(new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, gruppe.gruppeId())); + var hentetGrupper = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + assertThat(hentetGrupper.saksbehandlerGrupper().get(0).saksbehandlere()).hasSize(1); + + restTjeneste.fjernSaksbehandlerFraGruppe(new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, gruppe.gruppeId())); + var etterSletting = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + assertThat(etterSletting.saksbehandlerGrupper().get(0).saksbehandlere()).isEmpty(); + } + + @Test + void kan_gi_grupper_nytt_navn() { + var gruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + assertThat(gruppe.gruppeNavn()).isNotEqualTo("Nytt navn"); + restTjeneste.endreSaksbehandlerGruppe(new SaksbehandlerGruppeNavneEndringDto(gruppe.gruppeId(), "Nytt navn", avdelingDto)); + entityManager.clear(); // glem eksisterende entiteter for å hente nytt fra databasen + var hentetGrupper = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + var oppdatertGruppe = hentetGrupper.saksbehandlerGrupper().get(0); + assertThat(oppdatertGruppe.gruppeNavn()).isEqualTo("Nytt navn"); + } + + @Test + void skal_gi_feilmelding_når_gruppe_ikke_finnes() { + var dto = new SaksbehandlerGruppeSletteRequestDto(1, avdelingDto); + assertThatThrownBy(() -> restTjeneste.slettSaksbehandlerGruppe(dto)).isInstanceOf(TomtResultatException.class) + .extracting(Throwable::getMessage) + .matches(s -> s.contains("Fant ikke gruppe " + dto.gruppeId() + " for avdeling " + avdelingDto.getAvdelingEnhet())); + } + + @Test + void skal_håndtere_at_saksbehandler_ikke_er_tilknyttet_gruppe() { + var gruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + var dto = new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, gruppe.gruppeId()); + assertThatNoException().isThrownBy(() -> restTjeneste.fjernSaksbehandlerFraGruppe(dto)); + } + + @Test + void skal_kunne_fjerne_saksbehandler_fra_individuelle_grupper() { + setupMockForMappingAvSaksbehandlerDto(); + var førsteGruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + restTjeneste.leggTilNySaksbehandler(new SaksbehandlerOgAvdelingDto(brukerIdentDto, avdelingDto)); + restTjeneste.leggSaksbehandlerTilGruppe(new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, førsteGruppe.gruppeId())); + var andreGruppe = restTjeneste.opprettSaksbehandlerGruppe(avdelingDto); + var saksbehandlerOgGruppeDto = new SaksbehandlerOgGruppeDto(brukerIdentDto, avdelingDto, andreGruppe.gruppeId()); + restTjeneste.leggSaksbehandlerTilGruppe(saksbehandlerOgGruppeDto); + restTjeneste.fjernSaksbehandlerFraGruppe(saksbehandlerOgGruppeDto); + + var hentetGrupper = restTjeneste.hentSaksbehandlerGrupper(avdelingDto); + var hentetGrupperListe = hentetGrupper.saksbehandlerGrupper(); + assertThat(hentetGrupperListe).hasSize(2); + for (var res : hentetGrupperListe) { + if (Objects.equals(res.gruppeId(), førsteGruppe.gruppeId())) { + assertThat(res.saksbehandlere()).hasSize(1); + } else if (Objects.equals(res.gruppeId(), andreGruppe.gruppeId())) { + assertThat(res.saksbehandlere()).isEmpty(); + } + else { + fail("Ukjent gruppe"); + } + } + } + + private void setupMockForMappingAvSaksbehandlerDto() { + when(saksbehandlerDtoTjeneste.lagKjentOgUkjentSaksbehandlerMedAvdelingerDto(argThat(sb -> sb.getSaksbehandlerIdent().equals("Z999999")))) + .thenReturn(new SaksbehandlerMedAvdelingerDto(saksbehandlerDto, singletonList(avdelingDto.getAvdelingEnhet()))); + } + +} diff --git a/web/src/test/resources/application-vtp.properties b/web/src/test/resources/application-vtp.properties index 3884bde2f..477b24300 100644 --- a/web/src/test/resources/application-vtp.properties +++ b/web/src/test/resources/application-vtp.properties @@ -30,7 +30,7 @@ systembruker.password=vtp ## Sikkerhet # Azure -azure.app.well.known.url=http://authserver:8086/azureAd/.well-known/openid-configuration +azure.app.well.known.url=http://authserver:8060/rest/azuread/.well-known/openid-configuration AZURE_APP_CLIENT_ID=vtp NAIS_CLUSTER_NAME=vtp