Skip to content

Commit

Permalink
fix: ignore medewerker rol without medewerker (#2284)
Browse files Browse the repository at this point in the history
Ignore medewerker rol without medewerker because this is possible in the
ZGW APIs and it does occur in certain scenarios.

Solves PZ-4904

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
edgarvonk and github-actions[bot] authored Dec 20, 2024
1 parent 9053457 commit 8884ea7
Show file tree
Hide file tree
Showing 20 changed files with 382 additions and 147 deletions.
3 changes: 0 additions & 3 deletions src/main/java/net/atos/client/zgw/zrc/ZrcClientService.java
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,8 @@ public void updateRol(final Zaak zaak, final Rol<?> rol, final String toelichtin

public void deleteRol(final Zaak zaak, final BetrokkeneType betrokkeneType, final String toelichting) {
final List<Rol<?>> rollen = listRollen(zaak);

final Optional<Rol<?>> rolMedewerker = rollen.stream().filter(rol -> rol.getBetrokkeneType() == betrokkeneType).findFirst();

rolMedewerker.ifPresent(betrokkene -> rollen.removeIf(rol -> rol.equalBetrokkeneRol(betrokkene)));

updateRollen(zaak, rollen, toelichting);
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/net/atos/client/zgw/zrc/model/Rol.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.Objects;
import java.util.UUID;

import javax.annotation.Nullable;

import jakarta.json.bind.annotation.JsonbDateFormat;
import jakarta.json.bind.annotation.JsonbTypeDeserializer;

Expand Down Expand Up @@ -172,6 +174,12 @@ public void setIndicatieMachtiging(final IndicatieMachtiging indicatieMachtiging
this.indicatieMachtiging = indicatieMachtiging;
}

/**
* Can be null according to the ZGW API and this does occur in practice in certain circumstances.
*
* @return the betrokkene identificatie; or null if there is none
*/
@Nullable
public T getBetrokkeneIdentificatie() {
return betrokkeneIdentificatie;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.net.URI;
import java.util.Objects;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;

import net.atos.client.zgw.ztc.model.generated.RolType;
Expand All @@ -23,7 +25,9 @@ public RolMedewerker(
final URI zaak,
final RolType roltype,
final String roltoelichting,
final Medewerker betrokkeneIdentificatie
// it is possible in the ZGW API to have a RolMedewerker without a Medewerker
// and this does occur in practice in certain circumstances
@Nullable final Medewerker betrokkeneIdentificatie
) {
super(zaak, roltype, BetrokkeneType.MEDEWERKER, betrokkeneIdentificatie, roltoelichting);
}
Expand Down Expand Up @@ -72,6 +76,9 @@ public String getIdentificatienummer() {

@Override
protected int hashCodeBetrokkeneIdentificatie() {
if (getBetrokkeneIdentificatie() == null) {
return -1;
}
return Objects.hash(getBetrokkeneIdentificatie().getIdentificatie());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -201,13 +202,13 @@ private String resolveDefaultValue(final String defaultValue, final ResolveDefau
}

private String getGroepForZaakDefaultValue(final Zaak zaak) {
return zgwApiService.findGroepForZaak(zaak)
return Optional.ofNullable(zgwApiService.findGroepForZaak(zaak))
.map(groep -> identityService.readGroup(groep.getBetrokkeneIdentificatie().getIdentificatie()).getName())
.orElse(null);
}

private String getBehandelaarForZaakDefaultValue(final Zaak zaak) {
return zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak)
return Optional.ofNullable(zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak))
.map(behandelaar -> identityService.readUser(behandelaar.getIdentificatienummer()).getFullName())
.orElse(null);
}
Expand Down
31 changes: 20 additions & 11 deletions src/main/java/net/atos/zac/mailtemplates/MailTemplateHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ public String resolveVariabelen(final String tekst, final Zaak zaak) {
zaak.getUiterlijkeEinddatumAfdoening().format(DATE_FORMATTER));

if (resolvedTekst.contains(ZAAK_STATUS.getVariabele())) {
resolvedTekst = replaceVariabele(resolvedTekst, ZAAK_STATUS,
resolvedTekst = replaceVariabele(
resolvedTekst,
ZAAK_STATUS,
Optional.of(zaak.getStatus())
.map(zrcClientService::readStatus)
.map(Status::getStatustype)
Expand All @@ -163,20 +165,24 @@ public String resolveVariabelen(final String tekst, final Zaak zaak) {

if (resolvedTekst.contains(ZAAK_INITIATOR.getVariabele()) ||
resolvedTekst.contains(ZAAK_INITIATOR_ADRES.getVariabele())) {
resolvedTekst = replaceInitiatorVariabelen(resolvedTekst,
zgwApiService.findInitiatorRoleForZaak(zaak));
resolvedTekst = replaceInitiatorVariabelen(
resolvedTekst,
Optional.ofNullable(zgwApiService.findInitiatorRoleForZaak(zaak))
);
}

if (resolvedTekst.contains(ZAAK_BEHANDELAAR_GROEP.getVariabele())) {
resolvedTekst = replaceVariabele(resolvedTekst, ZAAK_BEHANDELAAR_GROEP,
zgwApiService.findGroepForZaak(zaak)
.map(RolOrganisatorischeEenheid::getNaam));
String groupName = Optional.ofNullable(zgwApiService.findGroepForZaak(zaak))
.map(RolOrganisatorischeEenheid::getNaam)
.orElse(null);
resolvedTekst = replaceVariabele(resolvedTekst, ZAAK_BEHANDELAAR_GROEP, groupName);
}

if (resolvedTekst.contains(ZAAK_BEHANDELAAR_MEDEWERKER.getVariabele())) {
resolvedTekst = replaceVariabele(resolvedTekst, ZAAK_BEHANDELAAR_MEDEWERKER,
zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak)
.map(RolMedewerker::getNaam));
String medewerkerName = Optional.ofNullable(zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak))
.map(RolMedewerker::getNaam)
.orElse(null);
resolvedTekst = replaceVariabele(resolvedTekst, ZAAK_BEHANDELAAR_MEDEWERKER, medewerkerName);
}
}
return resolvedTekst;
Expand Down Expand Up @@ -240,9 +246,12 @@ public static String stripParagraphTags(final String onderwerp) {

private MailLink createMailLinkFromZaak(final Zaak zaak) {
final ZaakType zaaktype = ztcClientService.readZaaktype(zaak.getZaaktype());
return new MailLink(zaak.getIdentificatie(),
return new MailLink(
zaak.getIdentificatie(),
configuratieService.zaakTonenUrl(zaak.getIdentificatie()),
"de zaak", "(%s)".formatted(zaaktype.getOmschrijving()));
"de zaak",
"(%s)".formatted(zaaktype.getOmschrijving())
);
}

private MailLink createMailLinkFromTask(final TaskInfo taskInfo) {
Expand Down
42 changes: 23 additions & 19 deletions src/main/kotlin/net/atos/client/zgw/shared/ZGWApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ import java.net.URI
import java.time.LocalDate
import java.time.Period
import java.time.ZonedDateTime
import java.util.Optional
import java.util.UUID
import java.util.logging.Logger
import kotlin.jvm.optionals.getOrNull

/**
* Service class for ZGW API's.
Expand All @@ -57,6 +57,7 @@ class ZGWApiService @Inject constructor(

// Page numbering in ZGW APIs starts with 1
const val FIRST_PAGE_NUMBER_ZGW_APIS: Int = 1
const val ZAAK_OBJECT_DELETION_PREFIX = "Verwijderd"
}

/**
Expand Down Expand Up @@ -236,7 +237,7 @@ class ZGWApiService @Inject constructor(
// delete the relationship of the EnkelvoudigInformatieobject with the zaak.
zaakInformatieobjecten
.filter { it.zaakUUID == zaakUUID }
.forEach { zrcClientService.deleteZaakInformatieobject(it.uuid, toelichting, "Verwijderd") }
.forEach { zrcClientService.deleteZaakInformatieobject(it.uuid, toelichting, ZAAK_OBJECT_DELETION_PREFIX) }

// if the EnkelvoudigInformatieobject has no relationship(s) with other zaken it can be deleted.
if (zaakInformatieobjecten.all { it.zaakUUID == zaakUUID }) {
Expand All @@ -250,36 +251,39 @@ class ZGWApiService @Inject constructor(
* @param zaak [Zaak]
* @return [RolOrganisatorischeEenheid] or 'null'.
*/
fun findGroepForZaak(zaak: Zaak): Optional<RolOrganisatorischeEenheid> =
findBehandelaarRoleForZaak(zaak, BetrokkeneType.ORGANISATORISCHE_EENHEID)
.map { RolOrganisatorischeEenheid::class.java.cast(it) }
fun findGroepForZaak(zaak: Zaak): RolOrganisatorischeEenheid? =
findBehandelaarRoleForZaak(zaak, BetrokkeneType.ORGANISATORISCHE_EENHEID)?.let {
it as RolOrganisatorischeEenheid
}

/**
* Find [RolMedewerker] for [Zaak] with behandelaar [OmschrijvingGeneriekEnum].
*
* @param zaak [Zaak]
* @return [RolMedewerker] or 'null'.
* @return [RolMedewerker] or 'null' if the rol medewerker could not be found.
*/
fun findBehandelaarMedewerkerRoleForZaak(zaak: Zaak): Optional<RolMedewerker> =
findBehandelaarRoleForZaak(zaak, BetrokkeneType.MEDEWERKER)
.map { RolMedewerker::class.java.cast(it) }
fun findBehandelaarMedewerkerRoleForZaak(zaak: Zaak): RolMedewerker? =
findBehandelaarRoleForZaak(zaak, BetrokkeneType.MEDEWERKER)?.let {
it as RolMedewerker
}

fun findInitiatorRoleForZaak(zaak: Zaak): Optional<Rol<*>> =
fun findInitiatorRoleForZaak(zaak: Zaak): Rol<*>? =
ztcClientService.findRoltypen(zaak.zaaktype, OmschrijvingGeneriekEnum.INITIATOR)
// there should be only one initiator role type but in case there are multiple, we take the first one
// there should be only one initiator role type,
// but in case there are multiple, we take the first one
.firstOrNull()?.let {
zrcClientService.listRollen(RolListParameters(zaak.url, it.url)).getSingleResult()
} ?: Optional.empty()
zrcClientService.listRollen(RolListParameters(zaak.url, it.url)).getSingleResult().getOrNull()
}

private fun findBehandelaarRoleForZaak(
zaak: Zaak,
betrokkeneType: BetrokkeneType
): Optional<Rol<*>> =
ztcClientService.findRoltypen(zaak.zaaktype, OmschrijvingGeneriekEnum.BEHANDELAAR)
// there should be only one behandelaar role type but in case there are multiple, we take the first one
.firstOrNull()?.let {
zrcClientService.listRollen(RolListParameters(zaak.url, it.url, betrokkeneType)).getSingleResult()
} ?: Optional.empty()
): Rol<*>? = ztcClientService.findRoltypen(zaak.zaaktype, OmschrijvingGeneriekEnum.BEHANDELAAR)
// there should be one and only one 'behandelaar' role type
// but in case there are multiple, we take the first one
.firstOrNull()?.let {
zrcClientService.listRollen(RolListParameters(zaak.url, it.url, betrokkeneType)).singleResult.getOrNull()
}

private fun createStatusForZaak(zaakURI: URI, statustypeURI: URI, toelichting: String?): Status {
val status = Status(zaakURI, statustypeURI, ZonedDateTime.now())
Expand Down
24 changes: 11 additions & 13 deletions src/main/kotlin/net/atos/zac/app/zaak/ZaakRestService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ class ZaakRestService @Inject constructor(
@Path("initiator")
fun updateInitiator(gegevens: RESTZaakBetrokkeneGegevens): RestZaak {
val zaak = zrcClientService.readZaak(gegevens.zaakUUID)
zgwApiService.findInitiatorRoleForZaak(zaak)
.ifPresent { removeInitiator(zaak, it, ROL_VERWIJDER_REDEN) }
zgwApiService.findInitiatorRoleForZaak(zaak)?.also {
removeInitiator(zaak, it, ROL_VERWIJDER_REDEN)
}
addInitiator(gegevens.betrokkeneIdentificatieType, gegevens.betrokkeneIdentificatie, zaak)
return restZaakConverter.toRestZaak(zaak)
}
Expand All @@ -213,8 +214,9 @@ class ZaakRestService @Inject constructor(
@Path("{uuid}/initiator")
fun deleteInitiator(@PathParam("uuid") zaakUUID: UUID, reden: RESTReden): RestZaak {
val zaak = zrcClientService.readZaak(zaakUUID)
zgwApiService.findInitiatorRoleForZaak(zaak)
.ifPresent { removeInitiator(zaak, it, reden.reden) }
zgwApiService.findInitiatorRoleForZaak(zaak)?.also {
removeInitiator(zaak, it, reden.reden)
}
return restZaakConverter.toRestZaak(zaak)
}

Expand Down Expand Up @@ -520,22 +522,18 @@ class ZaakRestService @Inject constructor(
assertPolicy(policyService.readZaakRechten(it).toekennen)
}
val behandelaar = zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak)
.map { it.betrokkeneIdentificatie.identificatie }
.orElse(null)
?.betrokkeneIdentificatie?.identificatie
val isUpdated = AtomicBoolean(false)
if (behandelaar != toekennenGegevens.assigneeUserName) {
toekennenGegevens.assigneeUserName?.takeIf { it.isNotEmpty() }?.let {
val user = identityService.readUser(it)
zrcClientService.updateRol(zaak, zaakService.bepaalRolMedewerker(user, zaak), toekennenGegevens.reason)
}
// no, or an empty behandelaarGebruikersnaam means the zaak should be unassigned
?: zrcClientService.deleteRol(zaak, BetrokkeneType.MEDEWERKER, toekennenGegevens.reason)
} ?: zrcClientService.deleteRol(zaak, BetrokkeneType.MEDEWERKER, toekennenGegevens.reason)
isUpdated.set(true)
}
zgwApiService.findGroepForZaak(zaak).ifPresent {
val groupId = toekennenGegevens.groupId
if (it.betrokkeneIdentificatie.identificatie != groupId) {
val group = identityService.readGroup(groupId)
zgwApiService.findGroepForZaak(zaak)?.betrokkeneIdentificatie?.identificatie?.let { currentGroupId ->
if (currentGroupId != toekennenGegevens.groupId) {
val group = identityService.readGroup(toekennenGegevens.groupId)
val role = zaakService.bepaalRolGroep(group, zaak)
zrcClientService.updateRol(zaak, role, toekennenGegevens.reason)
isUpdated.set(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import java.time.Period
import java.util.EnumSet
import java.util.UUID
import java.util.logging.Logger
import kotlin.jvm.optionals.getOrNull

@Suppress("LongParameterList")
class RestZaakConverter @Inject constructor(
Expand Down Expand Up @@ -71,14 +70,16 @@ class RestZaakConverter @Inject constructor(
@Suppress("LongMethod", "CyclomaticComplexMethod")
fun toRestZaak(zaak: Zaak, status: Status?, statustype: StatusType?): RestZaak {
val zaaktype = ztcClientService.readZaaktype(zaak.zaaktype)
val groep = zgwApiService.findGroepForZaak(zaak)
.map { restGroupConverter.convertGroupId(it.betrokkeneIdentificatie.identificatie) }
.orElse(null)
val groep = zgwApiService.findGroepForZaak(zaak)?.let { rolOrganisatorischeEenheid ->
rolOrganisatorischeEenheid.betrokkeneIdentificatie?.let {
restGroupConverter.convertGroupId(it.identificatie)
}
}
val besluiten = brcClientService.listBesluiten(zaak)
.map { restDecisionConverter.convertToRestDecision(it) }
val behandelaar = zgwApiService.findBehandelaarMedewerkerRoleForZaak(zaak)
.map { restUserConverter.convertUserId(it.betrokkeneIdentificatie.identificatie) }
.orElse(null)
?.betrokkeneIdentificatie
?.let { restUserConverter.convertUserId(it.identificatie) }
val initiator = zgwApiService.findInitiatorRoleForZaak(zaak)
return RestZaak(
identificatie = zaak.identificatie,
Expand Down Expand Up @@ -112,8 +113,8 @@ class RestZaakConverter @Inject constructor(
vertrouwelijkheidaanduiding = zaak.vertrouwelijkheidaanduiding.name,
groep = groep,
behandelaar = behandelaar,
initiatorIdentificatie = initiator.getOrNull()?.identificatienummer,
initiatorIdentificatieType = when (val betrokkeneType = initiator.getOrNull()?.betrokkeneType) {
initiatorIdentificatie = initiator?.identificatienummer,
initiatorIdentificatieType = when (val betrokkeneType = initiator?.betrokkeneType) {
BetrokkeneType.NATUURLIJK_PERSOON -> IdentificatieType.BSN
BetrokkeneType.VESTIGING -> IdentificatieType.VN
BetrokkeneType.NIET_NATUURLIJK_PERSOON -> IdentificatieType.RSIN
Expand Down
Loading

0 comments on commit 8884ea7

Please sign in to comment.