diff --git a/common/pom.xml b/common/pom.xml index 54c68693..d881db63 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/interfaces/pom.xml b/interfaces/pom.xml index ecd30f0e..7509e140 100644 --- a/interfaces/pom.xml +++ b/interfaces/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/AbstractConnectorMagdaClient.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/AbstractConnectorMagdaClient.java new file mode 100644 index 00000000..3fdb4f59 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/AbstractConnectorMagdaClient.java @@ -0,0 +1,36 @@ +package be.vlaanderen.vip.magda.client; + +import be.vlaanderen.vip.magda.exception.ServerException; + +import java.util.UUID; + +public abstract class AbstractConnectorMagdaClient implements MagdaClient { + + private final MagdaConnector connector; + + protected AbstractConnectorMagdaClient( + MagdaConnector connector) { + this.connector = connector; + } + + @Override + public MagdaResponseWrapper send(MagdaRequest request) throws MagdaClientException { + return send(request, UUID.randomUUID()); + } + + @Override + public MagdaResponseWrapper send(MagdaRequest request, UUID requestId) throws MagdaClientException { + try { + var response = connector.send(request, requestId); + + validateMagdaResponse(response, request); + + return new MagdaResponseWrapper(response); + } + catch (ServerException e) { + throw new MagdaClientException("Error occurred while sending magda request", e); + } + } + + protected abstract void validateMagdaResponse(MagdaResponse response, MagdaRequest request) throws MagdaClientException; +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/ConnectorMagdaClient.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/ConnectorMagdaClient.java index 8a8442cc..13460c90 100644 --- a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/ConnectorMagdaClient.java +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/ConnectorMagdaClient.java @@ -1,41 +1,23 @@ package be.vlaanderen.vip.magda.client; -import be.vlaanderen.vip.magda.exception.ServerException; import be.vlaanderen.vip.magda.exception.UitzonderingenSectionInResponseException; import be.vlaanderen.vip.magda.legallogging.model.UitzonderingEntry; import be.vlaanderen.vip.magda.legallogging.model.UitzonderingType; import java.util.List; -import java.util.UUID; -public class ConnectorMagdaClient implements MagdaClient { - private MagdaConnector connector; - - public ConnectorMagdaClient( - MagdaConnector connector) { - this.connector = connector; - } +/** + * A MagdaConnector-based client which handles both level 2 and level 3 uitzondingen in the response. + * Level 3 uitzondingen are handled in an opinionated manner whereby an exception is thrown if at least one of them is of type "FOUT". + */ +public class ConnectorMagdaClient extends AbstractConnectorMagdaClient { - @Override - public MagdaResponseWrapper send(MagdaRequest request) throws MagdaClientException { - return send(request, UUID.randomUUID()); + public ConnectorMagdaClient(MagdaConnector connector) { + super(connector); } @Override - public MagdaResponseWrapper send(MagdaRequest request, UUID requestId) throws MagdaClientException { - try { - var response = connector.send(request, requestId); - - validateMagdaResponse(response, request); - - return new MagdaResponseWrapper(response); - } - catch (ServerException e) { - throw new MagdaClientException("Error occurred while sending magda request", e); - } - } - - private void validateMagdaResponse(MagdaResponse response, MagdaRequest request) throws MagdaClientException { + protected void validateMagdaResponse(MagdaResponse response, MagdaRequest request) throws MagdaClientException { if(!response.getUitzonderingEntries().isEmpty()) { throw new MagdaClientException("Level 2 exception occurred while calling magda service", new UitzonderingenSectionInResponseException(request.getSubject(), response.getUitzonderingEntries(), request.getCorrelationId(), response.getRequestId())); } @@ -47,5 +29,4 @@ private void validateMagdaResponse(MagdaResponse response, MagdaRequest request) private boolean haveAtLeastOneFout(List entries) { return entries.stream().anyMatch(uitzonderingEntry -> uitzonderingEntry.getUitzonderingType().equals(UitzonderingType.FOUT)); } - } diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClient.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClient.java new file mode 100644 index 00000000..8d6ac450 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClient.java @@ -0,0 +1,20 @@ +package be.vlaanderen.vip.magda.client; + +import be.vlaanderen.vip.magda.exception.UitzonderingenSectionInResponseException; + +/** + * A MagdaConnector-based client which handles level 2 uitzondingen in the response. + */ +public class LenientConnectorMagdaClient extends AbstractConnectorMagdaClient { + + public LenientConnectorMagdaClient(MagdaConnector connector) { + super(connector); + } + + @Override + protected void validateMagdaResponse(MagdaResponse response, MagdaRequest request) throws MagdaClientException { + if(!response.getUitzonderingEntries().isEmpty()) { + throw new MagdaClientException("Level 2 exception occurred while calling magda service", new UitzonderingenSectionInResponseException(request.getSubject(), response.getUitzonderingEntries(), request.getCorrelationId(), response.getRequestId())); + } + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/EducationEnrollmentSource.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/EducationEnrollmentSource.java new file mode 100644 index 00000000..4d5ecb94 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/EducationEnrollmentSource.java @@ -0,0 +1,17 @@ +package be.vlaanderen.vip.magda.client.diensten; + +import lombok.Getter; + +@Getter +public enum EducationEnrollmentSource { + HO("HO"), + INT("INT"), + LP("LP"), + VWO("VWO"); + + private final String value; + + EducationEnrollmentSource(String value) { + this.value = value; + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequest.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequest.java new file mode 100644 index 00000000..d05422c2 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequest.java @@ -0,0 +1,115 @@ +package be.vlaanderen.vip.magda.client.diensten; + +import be.vlaanderen.vip.magda.client.MagdaDocument; +import be.vlaanderen.vip.magda.client.MagdaServiceIdentification; +import be.vlaanderen.vip.magda.client.diensten.subject.INSZNumber; +import be.vlaanderen.vip.magda.client.domeinservice.MagdaRegistrationInfo; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.time.LocalDate; +import java.util.Set; +import java.util.UUID; + +import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE; + +/** + * A request to the "Onderwijs.GeefHistoriekInschrijving" MAGDA service, which provides education enrollment histories for a person. + * Adds the following fields to the {@link PersonMagdaRequest}: + * + * + * @see XML template for this request type + */ +@Getter +@ToString +@EqualsAndHashCode(callSuper = true) +public class GeefHistoriekInschrijvingRequest extends PersonMagdaRequest { + + public static class Builder extends PersonMagdaRequest.Builder { + + @Getter(AccessLevel.PROTECTED) + private LocalDate startDate; + @Getter(AccessLevel.PROTECTED) + private LocalDate endDate; + @Getter(AccessLevel.PROTECTED) + private Set sources; + + public Builder startDate(LocalDate startDate) { + this.startDate = startDate; + return this; + } + + public Builder endDate(LocalDate endDate) { + this.endDate = endDate; + return this; + } + + public Builder sources(Set sources) { + this.sources = sources; + return this; + } + + public GeefHistoriekInschrijvingRequest build() { + if(getInsz() == null) { throw new IllegalStateException("INSZ number must be given"); } + if(getStartDate() == null) { throw new IllegalStateException("Start date must be given"); } + if(getEndDate() == null) { throw new IllegalStateException("End date must be given"); } + + return new GeefHistoriekInschrijvingRequest( + getInsz(), + getRegistration(), + getStartDate(), + getEndDate(), + getSources() + ); + } + } + + public static Builder builder() { + return new Builder(); + } + + @NotNull + private final LocalDate startDate; + @NotNull + private final LocalDate endDate; + @Nullable + private final Set sources; + + private GeefHistoriekInschrijvingRequest( + @NotNull INSZNumber insz, + @NotNull String registratie, + @NotNull LocalDate startDate, + @NotNull LocalDate endDate, + @Nullable Set sources) { + super(insz, registratie); + this.startDate = startDate; + this.endDate = endDate; + this.sources = sources; + } + + @Override + public MagdaServiceIdentification magdaServiceIdentification() { + return new MagdaServiceIdentification("Onderwijs.GeefHistoriekInschrijving", "02.01.0000"); + } + + @Override + protected void fillIn(MagdaDocument request, UUID requestId, MagdaRegistrationInfo magdaRegistrationInfo) { + fillInCommonFields(request, requestId, magdaRegistrationInfo); + + request.setValue("//Criteria/Periode/Begin", startDate.format(ISO_LOCAL_DATE)); + request.setValue("//Criteria/Periode/Einde", endDate.format(ISO_LOCAL_DATE)); + if(sources != null) { + sources.forEach(source -> request.createTextNode("//Criteria/Bronnen", "Bron", source.getValue())); + } else { + request.removeNode("//Criteria/Bronnen"); + } + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistory.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistory.java new file mode 100644 index 00000000..a5a7e8a5 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistory.java @@ -0,0 +1,305 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.MagdaDocument; +import be.vlaanderen.vip.magda.client.MagdaResponse; +import be.vlaanderen.vip.magda.client.MagdaResponseWrapper; +import be.vlaanderen.vip.magda.client.diensten.EducationEnrollmentSource; +import jakarta.annotation.Nullable; + +import java.time.LocalDate; +import java.time.Year; +import java.util.List; + +/** + * Information on a citizen's history of enrollment in education. + */ +public interface EnrollmentHistory { + + static EnrollmentHistory ofMagdaDocument(MagdaDocument magdaDocument) throws MagdaClientException { + return MagdaResponseEnrollmentHistoryAdapterJaxbImpl.getInstance().adapt(new MagdaResponseWrapper(MagdaResponse.builder() + .document(magdaDocument) + .build())); + } + + List enrollments(); + + interface Enrollment { + + EducationEnrollmentSource source(); + + String reference(); + + Institution institution(); + + @Nullable + EducationLocation educationLocation(); + + @Nullable + HigherEducation higherEducation(); + + @Nullable + CompulsoryEducation compulsoryEducation(); + } + + interface Institution { + + String institutionNumber(); + + String officialName(); + + @Nullable + String agency(); + + @Nullable + Address address(); + + @Nullable + ContactInfo contactInfo(); + } + + interface EducationLocation { + + Integer number(); + + @Nullable + String description(); + + @Nullable + Address address(); + + @Nullable + ContactInfo contactInfo(); + } + + interface HigherEducation { + + Year academyYear(); + + CodeAndDescription status(); + + LocalDate dateOfEnrollment(); + + @Nullable + LocalDate dateOfDisenrollment(); + + @Nullable + Training training(); + + CodeAndDescription contractType(); + + CreditPoints creditPoints(); + + @Nullable + Integer studyLoad(); + + Boolean isAdequateStudyLoad(); + + Boolean isStudyCertificateAchievable(); + + @Nullable + List studyCertificates(); + + @Nullable + Training nextTraining(); + + @Nullable + Training previousTraining(); + } + + interface CompulsoryEducation { + + CodeAndDescription programType(); + + @Nullable + LocalDate dateOfEnrollment(); + + @Nullable + LocalDate dateOfFirstClass(); + + Year schoolYear(); + + @Nullable + AdministrativeGroupRegistration administrativeGroupRegistration(); + } + + interface Training { + + String code(); + + String fullName(); + + NameElements nameElements(); + + CodeAndDescription type(); + } + + interface NameElements { + + @Nullable + String degreePrefix(); + + @Nullable + String degree(); + + @Nullable + String degreeSpecification(); + + @Nullable + String qualificationPrefix(); + + String qualification(); + } + + interface CreditPoints { + + Integer amountTaken(); + + Integer amountAcquired(); + + Integer amountDeliberated(); + + Integer amountNoResult(); + + @Nullable + Integer amountNotParticipated(); + + @Nullable + Integer amountNotSucceeded(); + + Integer amountNotAcquired(); + + Integer amountExempted(); + + Integer amountOptedOut(); + } + + interface StudyCertificate { + + String reference(); + + @Nullable + String ledReference(); + } + + interface AdministrativeGroupRegistration { + + @Nullable + String reference(); + + Period period(); + + AdministrativeGroup administrativeGroup(); + + @Nullable + CodeAndDescription specialNeedsType(); + + @Nullable + Disenrollment disenrollment(); + + @Nullable + Boolean isForeignLanguageNewcomer(); + + @Nullable + Boolean isFormerForeignLanguageNewcomer(); + } + + interface AdministrativeGroup { + + String number(); + + @Nullable + String name(); + + CodeAndDescription level(); + + CodeAndDescription educationType(); + + @Nullable + DualCurriculum dualCurriculum(); + } + + interface DualCurriculum { + + CodeAndDescription learningPathway(); + } + + interface Disenrollment { + + CodeAndDescription reason(); + + CodeAndDescription situationAfter(); + } + + interface Address { + + @Nullable + Street street(); + + @Nullable + String houseNumber(); + + @Nullable + String postalBoxNumber(); + + @Nullable + Municipality municipality(); + + @Nullable + Country country(); + } + + interface Street { + + @Nullable + String name(); + } + + interface Municipality { + + @Nullable + String nisCode(); + + @Nullable + String postalCode(); + + @Nullable + String name(); + } + + interface Country { + + @Nullable + String isoCode(); + + @Nullable + String name(); + } + + interface ContactInfo { + + @Nullable + String phoneNumber(); + + @Nullable + String emailAddress(); + + @Nullable + String website(); + } + + interface Period { + + LocalDate startDate(); + + LocalDate endDate(); + } + + interface CodeAndDescription { + + String codeValue(); + + @Nullable + String codeDescription(); + } +} \ No newline at end of file diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistoryJaxb.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistoryJaxb.java new file mode 100644 index 00000000..c16c2ad2 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/EnrollmentHistoryJaxb.java @@ -0,0 +1,503 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.diensten.EducationEnrollmentSource; +import be.vlaanderen.vip.magda.client.domain.model.shared.LocalDateXmlAdapter; +import be.vlaanderen.vip.magda.client.domain.model.shared.YearXmlAdapter; +import jakarta.annotation.Nullable; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.Year; +import java.util.ArrayList; +import java.util.List; + +@XmlRootElement(name = "Inhoud") +@Accessors(fluent = true) +public class EnrollmentHistoryJaxb implements EnrollmentHistory, Serializable { + + @Serial + private static final long serialVersionUID = 7417543781799245182L; + + @XmlElementWrapper(name = "Inschrijvingen") + @XmlElement(name = "Inschrijving") + ArrayList enrollments; + + @Override + public List enrollments() { + return enrollments.stream() + .map(x -> (Enrollment) x) + .toList(); + } + + @Getter + private static class EnrollmentJaxb implements Enrollment, Serializable { + + @Serial + private static final long serialVersionUID = 2123983013630220684L; + + @XmlElement(name = "Bron") + EducationEnrollmentSource source; + + @XmlElement(name = "Referte") + String reference; + + @XmlElement(name = "Instelling") + InstitutionJaxb institution; + + @XmlElement(name = "OnderwijsLocatie") + @Nullable + EducationLocationJaxb educationLocation; + + @XmlElement(name = "HogerOnderwijs") + @Nullable + HigherEducationJaxb higherEducation; + + @XmlElement(name = "LeerplichtOnderwijs") + @Nullable + CompulsoryEducationJaxb compulsoryEducation; + } + + @Getter + private static class InstitutionJaxb implements Institution, Serializable { + + @Serial + private static final long serialVersionUID = -1510011456863582497L; + + @XmlElement(name = "Instellingsnummer") + String institutionNumber; + + @XmlElement(name = "OfficieleNaam") + String officialName; + + @XmlElement(name = "Instantie") + @Nullable + String agency; + + @XmlElement(name = "Adres") + @Nullable + AddressJaxb address; + + @XmlElement(name = "Contactgegevens") + @Nullable + ContactInfoJaxb contactInfo; + } + + @Getter + private static class EducationLocationJaxb implements EducationLocation, Serializable { + + @Serial + private static final long serialVersionUID = -6414697292027312262L; + + @XmlElement(name = "Nummer") + Integer number; + + @XmlElement(name = "Omschrijving") + @Nullable + String description; + + @XmlElement(name = "Adres") + @Nullable + AddressJaxb address; + + @XmlElement(name = "Contactgegevens") + @Nullable + ContactInfoJaxb contactInfo; + } + + @Getter + private static class HigherEducationJaxb implements HigherEducation, Serializable { + + @Serial + private static final long serialVersionUID = -344798218191945921L; + + @XmlElement(name = "Academiejaar") + @XmlJavaTypeAdapter(YearXmlAdapter.class) + Year academyYear; + + @XmlElement(name = "Status") + CodeAndDescriptionJaxb status; + + @XmlElement(name = "DatumInschrijving") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + LocalDate dateOfEnrollment; + + @XmlElement(name = "DatumUitschrijving") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + @Nullable + LocalDate dateOfDisenrollment; + + @XmlElement(name = "Opleiding") + @Nullable + TrainingJaxb training; + + @XmlElement(name = "SoortContract") + CodeAndDescriptionJaxb contractType; + + @XmlElement(name = "Studiepunten") + CreditPointsJaxb creditPoints; + + @XmlElement(name = "Studieomvang") + @Nullable + Integer studyLoad; + + @XmlElement(name = "ToereikendeStudieomvang") + Boolean isAdequateStudyLoad; + + @XmlElement(name = "StudiebewijsHaalbaar") + Boolean isStudyCertificateAchievable; + + @XmlElementWrapper(name = "Studiebewijzen") + @XmlElement(name = "Studiebewijs") + @Nullable + ArrayList studyCertificates; + + @Override + public List studyCertificates() { + if(studyCertificates == null) { + return null; + } + + return studyCertificates.stream() + .map(x -> (StudyCertificate) x) + .toList(); + } + + @XmlElement(name = "VolgendeOpleiding") + @Nullable + TrainingJaxb nextTraining; + + @XmlElement(name = "VorigeOpleiding") + @Nullable + TrainingJaxb previousTraining; + } + + @Getter + private static class CompulsoryEducationJaxb implements CompulsoryEducation, Serializable { + + @Serial + private static final long serialVersionUID = 394155513929130862L; + + @XmlElement(name = "SoortProgramma") + CodeAndDescriptionJaxb programType; + + @XmlElement(name = "DatumInschrijving") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + @Nullable + LocalDate dateOfEnrollment; + + @XmlElement(name = "DatumEersteLes") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + @Nullable + LocalDate dateOfFirstClass; + + @XmlElement(name = "Schooljaar") + @XmlJavaTypeAdapter(YearXmlAdapter.class) + Year schoolYear; + + @XmlElement(name = "InschrijvingAdministratieveGroep") + @Nullable + AdministrativeGroupRegistrationJaxb administrativeGroupRegistration; + } + + @Getter + private static class TrainingJaxb implements Training, Serializable { + + @Serial + private static final long serialVersionUID = 3947632101949342933L; + + @XmlElement(name = "Code") + String code; + + @XmlElement(name = "VolledigeNaam") + String fullName; + + @XmlElement(name = "NaamElementen") + NameElementsJaxb nameElements; + + @XmlElement(name = "Soort") + CodeAndDescriptionJaxb type; + } + + @Getter + private static class NameElementsJaxb implements NameElements, Serializable { + + @Serial + private static final long serialVersionUID = -7146590833317862189L; + + @XmlElement(name = "PrefixGraad") + @Nullable + String degreePrefix; + + @XmlElement(name = "Graad") + @Nullable + String degree; + + @XmlElement(name = "SpecificatieGraad") + @Nullable + String degreeSpecification; + + @XmlElement(name = "PrefixKwalificatie") + @Nullable + String qualificationPrefix; + + @XmlElement(name = "Kwalificatie") + String qualification; + } + + @Getter + private static class CreditPointsJaxb implements CreditPoints, Serializable { + + @Serial + private static final long serialVersionUID = 4288678212016253460L; + + @XmlElement(name = "Opgenomen") + Integer amountTaken; + + @XmlElement(name = "Verworven") + Integer amountAcquired; + + @XmlElement(name = "Gedelibereerd") + Integer amountDeliberated; + + @XmlElement(name = "GeenResultaat") + Integer amountNoResult; + + @XmlElement(name = "NietDeelgenomen") + @Nullable + Integer amountNotParticipated; + + @XmlElement(name = "NietGeslaagd") + @Nullable + Integer amountNotSucceeded; + + @XmlElement(name = "NietVerworven") + Integer amountNotAcquired; + + @XmlElement(name = "Vrijgesteld") + Integer amountExempted; + + @XmlElement(name = "Uitgeschreven") + Integer amountOptedOut; + } + + @Getter + private static class StudyCertificateJaxb implements StudyCertificate, Serializable { + + @Serial + private static final long serialVersionUID = -7569422110911431585L; + + @XmlElement(name = "Referte") + String reference; + + @XmlElement(name = "LEDReferte") + @Nullable + String ledReference; + } + + @Getter + private static class AdministrativeGroupRegistrationJaxb implements AdministrativeGroupRegistration, Serializable { + + @Serial + private static final long serialVersionUID = -4857829255909214297L; + + @XmlElement(name = "Referte") + @Nullable + String reference; + + @XmlElement(name = "Periode") + PeriodJaxb period; + + @XmlElement(name = "AdministratieveGroep") + AdministrativeGroupJaxb administrativeGroup; + + @XmlElement(name = "TypeBuitengewoon") + @Nullable + CodeAndDescriptionJaxb specialNeedsType; + + @XmlElement(name = "Uitschrijving") + @Nullable + DisenrollmentJaxb disenrollment; + + @XmlElement(name = "AnderstaligeNieuwkomer") + @Nullable + Boolean isForeignLanguageNewcomer; + + @XmlElement(name = "GewezenAnderstaligeNieuwkomer") + @Nullable + Boolean isFormerForeignLanguageNewcomer; + } + + @Getter + private static class AdministrativeGroupJaxb implements AdministrativeGroup, Serializable { + + @Serial + private static final long serialVersionUID = -2950123647627117385L; + + @XmlElement(name = "Nummer") + String number; + + @XmlElement(name = "Naam") + @Nullable + String name; + + @XmlElement(name = "Niveau") + CodeAndDescriptionJaxb level; + + @XmlElement(name = "SoortOnderwijs") + CodeAndDescriptionJaxb educationType; + + @XmlElement(name = "DuaalLeren") + @Nullable + DualCurriculumJaxb dualCurriculum; + } + + @Getter + private static class DualCurriculumJaxb implements DualCurriculum, Serializable { + + @Serial + private static final long serialVersionUID = -4011341482386475604L; + + @XmlElement(name = "Leerweg") + CodeAndDescriptionJaxb learningPathway; + } + + @Getter + private static class DisenrollmentJaxb implements Disenrollment, Serializable { + + @Serial + private static final long serialVersionUID = -990045071616004454L; + + @XmlElement(name = "Aanleiding") + CodeAndDescriptionJaxb reason; + + @XmlElement(name = "SituatieNa") + CodeAndDescriptionJaxb situationAfter; + } + + @Getter + private static class AddressJaxb implements Address, Serializable { + + @Serial + private static final long serialVersionUID = -2602789444589500341L; + + @XmlElement(name = "Straat") + @Nullable + StreetJaxb street; + + @XmlElement(name = "Huisnummer") + @Nullable + String houseNumber; + + @XmlElement(name = "Busnummer") + @Nullable + String postalBoxNumber; + + @XmlElement(name = "Gemeente") + @Nullable + MunicipalityJaxb municipality; + + @XmlElement(name = "Land") + @Nullable + CountryJaxb country; + } + + @Getter + private static class StreetJaxb implements Street, Serializable { + + @Serial + private static final long serialVersionUID = -8500375798881388985L; + + @XmlElement(name = "Naam") + @Nullable + String name; + } + + @Getter + private static class MunicipalityJaxb implements Municipality, Serializable { + + @Serial + private static final long serialVersionUID = -5732523182095981641L; + + @XmlElement(name = "NISCode") + @Nullable + String nisCode; + + @XmlElement(name = "PostCode") + @Nullable + String postalCode; + + @XmlElement(name = "Naam") + @Nullable + String name; + } + + @Getter + private static class CountryJaxb implements Country, Serializable { + + @Serial + private static final long serialVersionUID = 3027740616814131639L; + + @XmlElement(name = "ISOCode") + @Nullable + String isoCode; + + @XmlElement(name = "Naam") + @Nullable + String name; + } + + @Getter + private static class ContactInfoJaxb implements ContactInfo, Serializable { + + @Serial + private static final long serialVersionUID = 4043991542075763020L; + + @XmlElement(name = "Telefoonnummer") + @Nullable + String phoneNumber; + + @XmlElement(name = "Email") + @Nullable + String emailAddress; + + @XmlElement(name = "Website") + @Nullable + String website; + } + + @Getter + private static class PeriodJaxb implements Period, Serializable { + + @Serial + private static final long serialVersionUID = -7829462301916655547L; + + @XmlElement(name = "Begin") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + LocalDate startDate; + + @XmlElement(name = "Einde") + @XmlJavaTypeAdapter(LocalDateXmlAdapter.class) + LocalDate endDate; + } + + @Getter + private static class CodeAndDescriptionJaxb implements CodeAndDescription, Serializable { + + @Serial + private static final long serialVersionUID = -5682187439322660274L; + + @XmlElement(name = "Code") + String codeValue; + + @XmlElement(name = "Omschrijving") + @Nullable + String codeDescription; + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/GiveEnrollmentHistoryService.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/GiveEnrollmentHistoryService.java new file mode 100644 index 00000000..c822eb8c --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/GiveEnrollmentHistoryService.java @@ -0,0 +1,18 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.diensten.GeefHistoriekInschrijvingRequest; + +/** + * A service for interfacing with MAGDA's "Onderwijs.GeefHistoriekInschrijving" services for retrieving information on a person's education enrollment history. + */ +public interface GiveEnrollmentHistoryService { + + /** + * Retrieves education enrollment history information from a GeefHistoriekInschrijvingRequest request. + * + * @see EnrollmentHistory + * @see GeefHistoriekInschrijvingRequest + */ + EnrollmentHistory getEnrollmentHistory(GeefHistoriekInschrijvingRequest request) throws MagdaClientException; +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryService.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryService.java new file mode 100644 index 00000000..d28f7f30 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryService.java @@ -0,0 +1,43 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClient; +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.MagdaResponse; +import be.vlaanderen.vip.magda.client.diensten.GeefHistoriekInschrijvingRequest; +import be.vlaanderen.vip.magda.exception.UitzonderingenSectionInResponseException; +import be.vlaanderen.vip.magda.legallogging.model.UitzonderingType; + +public class MagdaClientGiveEnrollmentHistoryService implements GiveEnrollmentHistoryService { + + private final MagdaClient client; + private final MagdaResponseEnrollmentHistoryAdapter adapter; + + public MagdaClientGiveEnrollmentHistoryService( + MagdaClient client, + MagdaResponseEnrollmentHistoryAdapter adapter) { + this.client = client; + this.adapter = adapter; + } + + public MagdaClientGiveEnrollmentHistoryService( + MagdaClient service) { + this(service, MagdaResponseEnrollmentHistoryAdapterJaxbImpl.getInstance()); + } + + @Override + public EnrollmentHistory getEnrollmentHistory(GeefHistoriekInschrijvingRequest request) throws MagdaClientException { + var responseWrapper = client.send(request); + + validateResponse(responseWrapper.getResponse(), request); // XXX test + + return adapter.adapt(responseWrapper); + } + + private void validateResponse(MagdaResponse response, GeefHistoriekInschrijvingRequest request) throws MagdaClientException { + if(response.getResponseUitzonderingEntries().stream().anyMatch(x -> + x.getUitzonderingType().equals(UitzonderingType.FOUT) && + !"30101".equals(x.getIdentification()))) { + throw new MagdaClientException("Level 3 exception occurred while calling magda service", new UitzonderingenSectionInResponseException(request.getSubject(), response.getResponseUitzonderingEntries(), request.getCorrelationId(), response.getRequestId())); + } + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapter.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapter.java new file mode 100644 index 00000000..c1d018bd --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapter.java @@ -0,0 +1,9 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.MagdaResponseWrapper; + +public interface MagdaResponseEnrollmentHistoryAdapter { + + EnrollmentHistory adapt(MagdaResponseWrapper wrapper) throws MagdaClientException; +} \ No newline at end of file diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapterJaxbImpl.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapterJaxbImpl.java new file mode 100644 index 00000000..c8d5bd7c --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaResponseEnrollmentHistoryAdapterJaxbImpl.java @@ -0,0 +1,45 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.MagdaResponseWrapper; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import lombok.SneakyThrows; + +import java.util.NoSuchElementException; +import java.util.Optional; + +public class MagdaResponseEnrollmentHistoryAdapterJaxbImpl implements MagdaResponseEnrollmentHistoryAdapter { + + private static MagdaResponseEnrollmentHistoryAdapterJaxbImpl instance; + + public static MagdaResponseEnrollmentHistoryAdapterJaxbImpl getInstance() { + if(instance == null) { + instance = new MagdaResponseEnrollmentHistoryAdapterJaxbImpl(); + } + + return instance; + } + + private final JAXBContext context; + + @SneakyThrows + private MagdaResponseEnrollmentHistoryAdapterJaxbImpl() { + context = JAXBContext.newInstance(EnrollmentHistoryJaxb.class); + } + + @Override + public EnrollmentHistory adapt(MagdaResponseWrapper wrapper) throws MagdaClientException { + try { + var node = Optional.ofNullable(wrapper + .getResponse() + .getDocument() + .xpath("//Inhoud") + .item(0)); + return (EnrollmentHistory) context.createUnmarshaller() + .unmarshal(node.orElseThrow()); + } catch (NoSuchElementException | JAXBException e) { + throw new MagdaClientException("Could not parse magda response", e); + } + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapter.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapter.java new file mode 100644 index 00000000..4d9479f4 --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapter.java @@ -0,0 +1,23 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import jakarta.xml.bind.annotation.adapters.XmlAdapter; + +import java.time.LocalDate; +import java.util.Optional; + +public class LocalDateXmlAdapter extends XmlAdapter { + + @Override + public LocalDate unmarshal(String stringValue) { + return Optional.ofNullable(stringValue) + .map(LocalDate::parse) + .orElse(null); + } + + @Override + public String marshal(LocalDate localDate) { + return Optional.ofNullable(localDate) + .map(LocalDate::toString) + .orElse(null); + } +} diff --git a/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapter.java b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapter.java new file mode 100644 index 00000000..faeb374e --- /dev/null +++ b/interfaces/src/main/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapter.java @@ -0,0 +1,23 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import jakarta.xml.bind.annotation.adapters.XmlAdapter; + +import java.time.Year; +import java.util.Optional; + +public class YearXmlAdapter extends XmlAdapter { + + @Override + public Year unmarshal(String stringValue) { + return Optional.ofNullable(stringValue) + .map(Year::parse) + .orElse(null); + } + + @Override + public String marshal(Year year) { + return Optional.ofNullable(year) + .map(Year::toString) + .orElse(null); + } +} diff --git a/interfaces/src/main/resources/templates/Onderwijs.GeefHistoriekInschrijving/02.01.0000/template.xml b/interfaces/src/main/resources/templates/Onderwijs.GeefHistoriekInschrijving/02.01.0000/template.xml new file mode 100644 index 00000000..5b63520f --- /dev/null +++ b/interfaces/src/main/resources/templates/Onderwijs.GeefHistoriekInschrijving/02.01.0000/template.xml @@ -0,0 +1,42 @@ + + + + + + + GeefHistoriekInschrijving + 02.01.0000 + + VRAAG + + Datum + Tijd + + + Identificatie + Referte + Hoedanigheid + + + + + + a + + + 00000000000 + + 2015-01-01 + 2016-06-30 + + + + + + + + + + + \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClientTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClientTest.java new file mode 100644 index 00000000..47889d8d --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/LenientConnectorMagdaClientTest.java @@ -0,0 +1,84 @@ +package be.vlaanderen.vip.magda.client; + +import be.vlaanderen.vip.magda.exception.ServerException; +import be.vlaanderen.vip.magda.legallogging.model.UitzonderingEntry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class LenientConnectorMagdaClientTest { + @Mock private MagdaConnector connector; + + @InjectMocks + private LenientConnectorMagdaClient service; + + @Nested + class Send { + private static final UUID REQUEST_ID = UUID.fromString("64fb1939-0ca7-432b-b7f4-3b53f7fc3789"); + + @Mock private MagdaRequest request; + + @Mock private MagdaResponse response; + + private final List level2errors = new ArrayList<>(); + private final List level3errors = new ArrayList<>(); + + @BeforeEach + void setup() { + lenient().when(response.getUitzonderingEntries()).thenReturn(level2errors); + lenient().when(response.getResponseUitzonderingEntries()).thenReturn(level3errors); + lenient().when(response.getRequestId()).thenReturn(REQUEST_ID); + } + + @Test + void returnsMagdaResponse_whenResponseContainsNoErrors() throws MagdaClientException { + when(connector.send(request, REQUEST_ID)).thenReturn(response); + + var result = service.send(request, REQUEST_ID); + + assertThat(result.getResponse(), is(equalTo(response))); + } + + @Test + void returnsMagdaResponse_whenResponseContainsLevel3Errors() throws MagdaClientException { + when(connector.send(request, REQUEST_ID)).thenReturn(response); + level3errors.add(mock(UitzonderingEntry.class)); + + var result = service.send(request, REQUEST_ID); + + assertThat(result.getResponse(), is(equalTo(response))); + } + + @Test + void throwsException_whenSendFails() { + when(connector.send(request, REQUEST_ID)).thenThrow(ServerException.class); + + assertThrows(MagdaClientException.class, + () -> service.send(request, REQUEST_ID)); + } + + @Test + void throwsException_whenResponseContainsLevel2Errors() { + when(connector.send(request, REQUEST_ID)).thenReturn(response); + level2errors.add(mock(UitzonderingEntry.class)); + + assertThrows(MagdaClientException.class, + () -> service.send(request, REQUEST_ID)); + } + } +} diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequestTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequestTest.java new file mode 100644 index 00000000..b591ff27 --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/diensten/GeefHistoriekInschrijvingRequestTest.java @@ -0,0 +1,123 @@ +package be.vlaanderen.vip.magda.client.diensten; + +import be.vlaanderen.vip.magda.client.diensten.subject.INSZNumber; +import be.vlaanderen.vip.magda.client.domeinservice.MagdaRegistrationInfo; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.Set; +import java.util.UUID; + +import static be.vlaanderen.vip.magda.client.diensten.EducationEnrollmentSource.*; +import static be.vlaanderen.vip.magda.client.diensten.TestBase.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.jupiter.api.Assertions.*; + +class GeefHistoriekInschrijvingRequestTest { + + @Nested + class Builder { + + private GeefHistoriekInschrijvingRequest.Builder builder; + + @BeforeEach + void setup() { + builder = GeefHistoriekInschrijvingRequest.builder() + .startDate(LocalDate.of(2024, 1, 1)) + .endDate(LocalDate.of(2024, 12, 31)) + .sources(Set.of(LP, VWO)); + } + + @Test + void buildsRequest() { + builder.insz(TEST_INSZ); + var request = builder.build(); + + assertNotNull(request); + assertEquals(INSZNumber.of(TEST_INSZ), request.getInsz()); + assertEquals(LocalDate.of(2024, 1, 1), request.getStartDate()); + assertEquals(LocalDate.of(2024, 12, 31), request.getEndDate()); + assertEquals(Set.of(LP, VWO), request.getSources()); + } + + @Test + void whenInszIsNull_throwsException() { + assertThrows(IllegalStateException.class, () -> builder.build()); + } + + @Test + void whenStartDateIsNull_throwsException() { + builder.insz(TEST_INSZ) + .startDate(null); + + assertThrows(IllegalStateException.class, () -> builder.build()); + } + + @Test + void whenEndDateIsNull_throwsException() { + builder.insz(TEST_INSZ) + .endDate(null); + + assertThrows(IllegalStateException.class, () -> builder.build()); + } + + @Test + void sourcesIsOptional() { + builder.insz(TEST_INSZ) + .sources(null); + + var request = builder.build(); + + assertNotNull(request); + assertNull(request.getSources()); + } + } + + @Nested + class ToMagdaDocument { + private static final UUID REQUEST_ID = UUID.fromString("64fb1939-0ca7-432b-b7f4-3b53f7fc3789"); + + private MagdaRegistrationInfo magdaRegistrationInfo; + private GeefHistoriekInschrijvingRequest.Builder builder; + + @BeforeEach + void setup() { + magdaRegistrationInfo = MagdaRegistrationInfo.builder() + .identification("identification") + .hoedanigheidscode("hoedanigheidscode") + .build(); + + builder = GeefHistoriekInschrijvingRequest.builder() + .insz(TEST_INSZ) + .startDate(LocalDate.of(2024, 1, 1)) + .endDate(LocalDate.of(2024, 12, 31)) + .sources(Set.of(LP, VWO)); + } + + @Test + void fillsInValues() { + var document = builder.build() + .toMagdaDocument(REQUEST_ID, magdaRegistrationInfo); + + assertNotNull(document); + assertEquals(TEST_INSZ, document.getValue("//Vraag/Inhoud/Criteria/INSZ")); + assertEquals("2024-01-01", document.getValue("//Vraag/Inhoud/Criteria/Periode/Begin")); + assertEquals("2024-12-31", document.getValue("//Vraag/Inhoud/Criteria/Periode/Einde")); + assertThat(document.getValues("//Vraag/Inhoud/Criteria/Bronnen/Bron"), containsInAnyOrder("LP", "VWO")); + } + + @Test + void whenSourcesAreNotGiven_documentDoesNotIncludeThem() { + var document = builder + .sources(null) + .build() + .toMagdaDocument(REQUEST_ID, magdaRegistrationInfo); + + assertNotNull(document); + assertNull(document.getValue("//Vraag/Inhoud/Criteria/Bronnen")); + } + } +} \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryServiceTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryServiceTest.java new file mode 100644 index 00000000..9f91f3f8 --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/giveenrollmenthistory/MagdaClientGiveEnrollmentHistoryServiceTest.java @@ -0,0 +1,106 @@ +package be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClient; +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.MagdaResponse; +import be.vlaanderen.vip.magda.client.MagdaResponseWrapper; +import be.vlaanderen.vip.magda.client.diensten.GeefHistoriekInschrijvingRequest; +import be.vlaanderen.vip.magda.legallogging.model.UitzonderingEntry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static be.vlaanderen.vip.magda.client.diensten.EducationEnrollmentSource.HO; +import static be.vlaanderen.vip.magda.client.diensten.EducationEnrollmentSource.INT; +import static be.vlaanderen.vip.magda.legallogging.model.UitzonderingType.FOUT; +import static be.vlaanderen.vip.magda.legallogging.model.UitzonderingType.WAARSCHUWING; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MagdaClientGiveEnrollmentHistoryServiceTest { + + @Mock + private MagdaClient magdaClient; + @Mock + private MagdaResponseEnrollmentHistoryAdapter adapter; + + @InjectMocks + private MagdaClientGiveEnrollmentHistoryService service; + + @Nested + class GetEnrollmentHistory { + + private GeefHistoriekInschrijvingRequest request; + + @BeforeEach + void setup() { + request = GeefHistoriekInschrijvingRequest.builder() + .insz("insz") + .startDate(LocalDate.of(2024, 1, 1)) + .endDate(LocalDate.of(2025, 1, 1)) + .sources(Set.of(HO, INT)) + .build(); + + request.setCorrelationId(UUID.fromString("6469cd5e-e8ed-43f7-a91e-48fdfbb76e0f")); + } + + @Test + void callsMagdaService() throws MagdaClientException { + when(magdaClient.send(request)).thenReturn(new MagdaResponseWrapper(MagdaResponse.builder() + .responseUitzonderingEntries(List.of()) + .build())); + + service.getEnrollmentHistory(request); + + verify(magdaClient).send(request); + } + + @Test + void throwsNoException_ifContainsAnyNonErrorLevel3Uitzondering() throws MagdaClientException { + when(magdaClient.send(request)).thenReturn(new MagdaResponseWrapper(MagdaResponse.builder() + .responseUitzonderingEntries(List.of(UitzonderingEntry.builder() + .identification("30101") + .uitzonderingType(WAARSCHUWING) + .build())) + .build())); + + assertDoesNotThrow(() -> service.getEnrollmentHistory(request)); + } + + @Test + void throwsNoException_ifContainsLevel3Error30101() throws MagdaClientException { + when(magdaClient.send(request)).thenReturn(new MagdaResponseWrapper(MagdaResponse.builder() + .responseUitzonderingEntries(List.of(UitzonderingEntry.builder() + .identification("30101") + .uitzonderingType(FOUT) + .build())) + .build())); + + assertDoesNotThrow(() -> service.getEnrollmentHistory(request)); + } + + @Test + void throwsException_ifContainsOtherLevel3Error() throws MagdaClientException { + when(magdaClient.send(request)).thenReturn(new MagdaResponseWrapper(MagdaResponse.builder() + .responseUitzonderingEntries(List.of(UitzonderingEntry.builder() + .identification("12345") + .uitzonderingType(FOUT) + .build())) + .build())); + + assertThrows(MagdaClientException.class, () -> service.getEnrollmentHistory(request)); + } + } +} \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapterTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapterTest.java new file mode 100644 index 00000000..8f96181f --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/LocalDateXmlAdapterTest.java @@ -0,0 +1,36 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class LocalDateXmlAdapterTest { + + private static final LocalDate LOCAL_DATE = LocalDate.of(2024, 1, 2); + private static final String LOCAL_DATE_STRING = "2024-01-02"; + + private final LocalDateXmlAdapter adapter = new LocalDateXmlAdapter(); + + @Test + void unmarshal_parsesValue() { + assertEquals(LOCAL_DATE, adapter.unmarshal(LOCAL_DATE_STRING)); + } + + @Test + void unmarshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.unmarshal(null)); + } + + @Test + void marshal_formatsValue() { + assertEquals(LOCAL_DATE_STRING, adapter.marshal(LOCAL_DATE)); + } + + @Test + void marshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.marshal(null)); + } +} \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateTimeXmlAdapterTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateTimeXmlAdapterTest.java new file mode 100644 index 00000000..395304f5 --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateTimeXmlAdapterTest.java @@ -0,0 +1,37 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import org.junit.jupiter.api.Test; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class OffsetDateTimeXmlAdapterTest { + + private static final OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2024, 1, 2, 3, 4, 5, 0, ZoneOffset.UTC); + private static final String OFFSET_DATE_TIME_STRING = "2024-01-02T03:04:05.000"; + + private final OffsetDateTimeXmlAdapter adapter = new OffsetDateTimeXmlAdapter(); + + @Test + void unmarshal_parsesValue() { + assertEquals(OFFSET_DATE_TIME, adapter.unmarshal(OFFSET_DATE_TIME_STRING)); + } + + @Test + void unmarshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.unmarshal(null)); + } + + @Test + void marshal_formatsValue() { + assertEquals(OFFSET_DATE_TIME_STRING, adapter.marshal(OFFSET_DATE_TIME)); + } + + @Test + void marshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.marshal(null)); + } +} \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateXmlAdapterTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateXmlAdapterTest.java new file mode 100644 index 00000000..fefd8b12 --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/OffsetDateXmlAdapterTest.java @@ -0,0 +1,37 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import org.junit.jupiter.api.Test; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class OffsetDateXmlAdapterTest { + + private static final OffsetDateTime OFFSET_DATE = OffsetDateTime.of(2024, 1, 2, 0, 0, 0, 0, ZoneOffset.UTC); + private static final String OFFSET_DATE_STRING = "2024-01-02"; + + private final OffsetDateXmlAdapter adapter = new OffsetDateXmlAdapter(); + + @Test + void unmarshal_parsesValue() { + assertEquals(OFFSET_DATE, adapter.unmarshal(OFFSET_DATE_STRING)); + } + + @Test + void unmarshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.unmarshal(null)); + } + + @Test + void marshal_formatsValue() { + assertEquals(OFFSET_DATE_STRING, adapter.marshal(OFFSET_DATE)); + } + + @Test + void marshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.marshal(null)); + } +} \ No newline at end of file diff --git a/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapterTest.java b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapterTest.java new file mode 100644 index 00000000..2fd778ee --- /dev/null +++ b/interfaces/src/test/java/be/vlaanderen/vip/magda/client/domain/model/shared/YearXmlAdapterTest.java @@ -0,0 +1,36 @@ +package be.vlaanderen.vip.magda.client.domain.model.shared; + +import org.junit.jupiter.api.Test; + +import java.time.Year; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class YearXmlAdapterTest { + + private static final Year YEAR = Year.of(2024); + private static final String YEAR_STRING = "2024"; + + private final YearXmlAdapter adapter = new YearXmlAdapter(); + + @Test + void unmarshal_parsesValue() { + assertEquals(YEAR, adapter.unmarshal(YEAR_STRING)); + } + + @Test + void unmarshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.unmarshal(null)); + } + + @Test + void marshal_formatsValue() { + assertEquals(YEAR_STRING, adapter.marshal(YEAR)); + } + + @Test + void marshal_yieldsNullWhenValueIsNull() { + assertNull(adapter.marshal(null)); + } +} \ No newline at end of file diff --git a/magdaconnector/pom.xml b/magdaconnector/pom.xml index 6b29a8d1..c16e9d99 100644 --- a/magdaconnector/pom.xml +++ b/magdaconnector/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/magdamock-starter/pom.xml b/magdamock-starter/pom.xml index 9eb1a313..d6ec08a9 100644 --- a/magdamock-starter/pom.xml +++ b/magdamock-starter/pom.xml @@ -8,7 +8,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 magdamock-starter diff --git a/magdamock/pom.xml b/magdamock/pom.xml index 4efd9fe7..839123d8 100644 --- a/magdamock/pom.xml +++ b/magdamock/pom.xml @@ -3,7 +3,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/magdamock/src/test/java/be/vlaanderen/vip/mock/magda/client/domain/giveenrollmenthistory/MagdaResponseGiveEnrollmentHistoryIntegrationTest.java b/magdamock/src/test/java/be/vlaanderen/vip/mock/magda/client/domain/giveenrollmenthistory/MagdaResponseGiveEnrollmentHistoryIntegrationTest.java new file mode 100644 index 00000000..b04d936d --- /dev/null +++ b/magdamock/src/test/java/be/vlaanderen/vip/mock/magda/client/domain/giveenrollmenthistory/MagdaResponseGiveEnrollmentHistoryIntegrationTest.java @@ -0,0 +1,40 @@ +package be.vlaanderen.vip.mock.magda.client.domain.giveenrollmenthistory; + +import be.vlaanderen.vip.magda.client.MagdaClientException; +import be.vlaanderen.vip.magda.client.diensten.GeefHistoriekInschrijvingRequest; +import be.vlaanderen.vip.magda.client.domain.giveenrollmenthistory.EnrollmentHistory; +import be.vlaanderen.vip.mock.magda.client.domain.MagdaMock; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class MagdaResponseGiveEnrollmentHistoryIntegrationTest { + + private EnrollmentHistory enrollmentHistory; + + @BeforeEach + void setup() throws MagdaClientException { + enrollmentHistory = enrollmentHistory("88611099807"); + } + + @Test + void dataIsBoundToResponseDocument() { + var enrollments = enrollmentHistory.enrollments(); + assertNotNull(enrollments); + assertEquals(6, enrollments.size()); + } + + private EnrollmentHistory enrollmentHistory(String insz) throws MagdaClientException { + var response = MagdaMock.getInstance().send(GeefHistoriekInschrijvingRequest.builder() + .insz(insz) + .startDate(LocalDate.of(2024, 1, 1)) + .endDate(LocalDate.of(2025, 1, 1)) + .build()); + + return EnrollmentHistory.ofMagdaDocument(response.getDocument()); + } +} \ No newline at end of file diff --git a/magdaservice/pom.xml b/magdaservice/pom.xml index 48413acf..7e1cc262 100644 --- a/magdaservice/pom.xml +++ b/magdaservice/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/pom.xml b/pom.xml index f1c62b59..e32ca392 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ be.vlaanderen.vip.mock magda - 2.35.0 + 2.36.0 magdaservice MAGDA diensten Mock voor afnemers diff --git a/signing/pom.xml b/signing/pom.xml index 94484765..6682179c 100644 --- a/signing/pom.xml +++ b/signing/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0 diff --git a/tester/pom.xml b/tester/pom.xml index 5afd1235..b2957335 100644 --- a/tester/pom.xml +++ b/tester/pom.xml @@ -5,7 +5,7 @@ magda be.vlaanderen.vip.mock - 2.35.0 + 2.36.0 4.0.0