diff --git a/bescheid-manager/pom.xml b/bescheid-manager/pom.xml index 7e5356426db314f5fa3b38c0cc08d9954fe27ce6..0919d7e470b7f729376b616fdfdd54caf2dc3d3f 100644 --- a/bescheid-manager/pom.xml +++ b/bescheid-manager/pom.xml @@ -18,6 +18,7 @@ <vorgang-manager.version>2.13.0</vorgang-manager.version> <nachrichten-manager.version>2.9.0</nachrichten-manager.version> <api-lib.version>0.12.0</api-lib.version> + <spring-cloud-config-client.version>4.1.3</spring-cloud-config-client.version> </properties> <dependencies> @@ -96,6 +97,11 @@ <optional>true</optional> </dependency> + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-config</artifactId> + <version>${spring-cloud-config-client.version}</version> + </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java index d181389e9cba0ebc0b7fa4f0ae3eecf9a1df3e3b..63f65d84733dae7ab98e63095234692c04f09dc7 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java @@ -10,7 +10,7 @@ import lombok.Builder; import lombok.Getter; import lombok.Singular; -@Builder +@Builder(toBuilder = true) @Getter public class Bescheid { diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java index 6e6cdaf0d38f5e31d8ec32b6e6353ceb23b357ee..3beaadf3f4fd167bba8a29b34c613afe2348604c 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java @@ -106,7 +106,7 @@ class BescheidEventListener { } void doCreateBescheid(Command command) { - var createdItemId = attachedItemService.createBescheidDraft(command); + var createdItemId = service.createBescheidDraft(command); eventPublisher.publishEvent(new BescheidCreatedEvent(command, createdItemId)); } diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java index 8abe425a3a1187b737bb41c851c1578a8db3e12c..28d4be14a789e33ff2b5b301c70341ad80f0b560 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidMapper.java @@ -1,9 +1,11 @@ package de.ozgcloud.bescheid; +import static de.ozgcloud.bescheid.Bescheid.*; + import java.time.LocalDate; -import java.time.ZonedDateTime; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -17,20 +19,27 @@ import org.mapstruct.Mapping; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.NullValuePropertyMappingStrategy; import org.mapstruct.ReportingPolicy; +import org.springframework.beans.factory.annotation.Autowired; -import de.ozgcloud.bescheid.Bescheid.SendBy; -import de.ozgcloud.bescheid.Bescheid.Status; import de.ozgcloud.bescheid.vorgang.VorgangId; +import de.ozgcloud.command.Command; import de.ozgcloud.common.attached_item.AttachedItem; +import de.ozgcloud.common.attached_item.AttachedItemService; import de.ozgcloud.common.binaryfile.FileId; +import de.ozgcloud.common.datatype.StringBasedValue; @Mapper(uses = { SentInfoMapper.class }, // unmappedTargetPolicy = ReportingPolicy.WARN, // collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, // nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) // -public interface BescheidMapper { +public abstract class BescheidMapper { + + @Autowired + private SentInfoMapper sentInfoMapper; + @Mapping(target = "sentInfoOrBuilder", ignore = true) + @Mapping(target = "defaultInstanceForType", ignore = true) @Mapping(target = "mergeFrom", ignore = true) @Mapping(target = "clearField", ignore = true) @Mapping(target = "clearOneof", ignore = true) @@ -49,50 +58,118 @@ public interface BescheidMapper { @Mapping(target = "nachrichtText", expression = "java(fromOptional(bescheid.getNachrichtText()))") @Mapping(target = "nachrichtSubject", expression = "java(fromOptional(bescheid.getNachrichtSubject()))") @Mapping(target = "attachmentsList", source = "attachments") - GrpcBescheid toBescheid(Bescheid bescheid); + abstract GrpcBescheid toBescheid(Bescheid bescheid); - default String toString(FileId fileId) { + String toString(FileId fileId) { return fileId.toString(); } - default String toString(BescheidId bescheidId) { + String toString(BescheidId bescheidId) { return bescheidId.toString(); } - default String fromOptional(Optional<String> optionalString) { + String fromOptional(Optional<String> optionalString) { return optionalString.orElse(StringUtils.EMPTY); } - default Bescheid mapFromAttachedItem(AttachedItem item) { - var itemMap = item.getItem(); - var builder = Bescheid.builder() + @Mapping(target = "featuresOrBuilder", ignore = true) + @Mapping(target = "defaultInstanceForType", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFeatures", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "javaVersionBytes", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "versionBytes", ignore = true) + @Mapping(target = "allFields", ignore = true) + abstract GrpcBescheidManagerConfigResponse fromBescheidManagerConfig(BescheidManagerConfig bescheidManagerConfig); + + @Mapping(target = "defaultInstanceForType", ignore = true) + @Mapping(target = "bescheidOrBuilder", ignore = true) + @Mapping(target = "bescheid", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeBescheid", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + abstract GrpcGetBescheidResponse toGetBescheidResponse(Bescheid bescheid); + + @Mapping(target = "defaultInstanceForType", ignore = true) + @Mapping(target = "bescheidOrBuilder", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeBescheid", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + abstract GrpcGetBescheidDraftResponse toGetBescheidDraftResponse(Bescheid bescheid); + + Bescheid mapFromAttachedItem(AttachedItem item) { + return buildBescheidBuilder(item.getItem()) .id(BescheidId.from(item.getId())) .version(item.getVersion()) .vorgangId(VorgangId.from(item.getVorgangId())) - .createdBy(UserId.from(MapUtils.getString(itemMap, Bescheid.FIELD_CREATED_BY))) - .bewilligt(MapUtils.getBoolean(itemMap, Bescheid.FIELD_BEWILLIGT)) - .nachrichtText(Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_NACHRICHT_TEXT))) - .nachrichtSubject(Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_NACHRICHT_SUBJECT))) - .status(Status.valueOf(MapUtils.getString(itemMap, Bescheid.FIELD_STATUS))) - .beschiedenAm(LocalDate.parse(MapUtils.getString(itemMap, Bescheid.FIELD_BESCHIEDEN_AM))); + .build(); + } - getBescheidDocument(itemMap).ifPresent(builder::bescheidDocument); - getAttachments(itemMap).ifPresent(builder::attachments); - getSendBy(itemMap).ifPresent(builder::sendBy); - getSentInfo(itemMap).ifPresent(builder::sentInfo); + Bescheid mapFromCommand(Command command) { + return buildBescheidBuilder(command.getBodyObject()) + .vorgangId(VorgangId.from(command.getVorgangId())) + .build(); + } + + private Bescheid.BescheidBuilder buildBescheidBuilder(Map<String, Object> bescheidMap) { + var bescheidBuilder = Bescheid.builder(); + Optional.ofNullable(MapUtils.getBoolean(bescheidMap, Bescheid.FIELD_BEWILLIGT)).ifPresent(bescheidBuilder::bewilligt); + getBeschiedenAm(bescheidMap).ifPresent(bescheidBuilder::beschiedenAm); + getStatus(bescheidMap).ifPresent(bescheidBuilder::status); + getCreatedBy(bescheidMap).ifPresent(bescheidBuilder::createdBy); + getBescheidDocument(bescheidMap).ifPresent(bescheidBuilder::bescheidDocument); + bescheidBuilder.nachrichtSubject(getNachrichtSubject(bescheidMap)); + bescheidBuilder.nachrichtText(getNachrichtText(bescheidMap)); + getSendBy(bescheidMap).ifPresent(bescheidBuilder::sendBy); + mapToAttachments(bescheidMap.get(Bescheid.FIELD_ATTACHMENTS)).ifPresent(bescheidBuilder::attachments); + getSentInfo(bescheidMap).ifPresent(bescheidBuilder::sentInfo); + return bescheidBuilder; + } + + Optional<LocalDate> getBeschiedenAm(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_BESCHIEDEN_AM).map(LocalDate::parse); + } + + Optional<Bescheid.Status> getStatus(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_STATUS).map(Bescheid.Status::valueOf); + } + + Optional<UserId> getCreatedBy(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_CREATED_BY).map(UserId::from); + } - return builder.build(); + Optional<SendBy> getSendBy(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_SEND_BY).map(SendBy::valueOf); } - default Optional<FileId> getBescheidDocument(Map<String, Object> itemMap) { - return Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_BESCHEID_DOCUMENT)).map(FileId::from); + Optional<FileId> getBescheidDocument(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_BESCHEID_DOCUMENT).map(FileId::from); } - default Optional<List<FileId>> getAttachments(Map<String, Object> itemMap) { - return mapToAttachments(MapUtils.getObject(itemMap, Bescheid.FIELD_ATTACHMENTS)); + private Optional<String> getNachrichtSubject(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_NACHRICHT_SUBJECT); } - default Optional<List<FileId>> mapToAttachments(Object attachments) { + private Optional<String> getNachrichtText(Map<String, Object> bescheidMap) { + return getStringValue(bescheidMap, Bescheid.FIELD_NACHRICHT_TEXT); + } + + private Optional<String> getStringValue(Map<String, Object> srcMap, String field) { + return Optional.ofNullable(MapUtils.getString(srcMap, field)).map(StringUtils::trimToNull); + } + + Optional<List<FileId>> mapToAttachments(Object attachments) { if (Objects.isNull(attachments) || StringUtils.isEmpty(String.valueOf(attachments))) { return Optional.empty(); } @@ -102,47 +179,55 @@ public interface BescheidMapper { return Optional.of(Collections.singletonList(FileId.from((String) attachments))); } - default Optional<SendBy> getSendBy(Map<String, Object> itemMap) { - return Optional.ofNullable(MapUtils.getString(itemMap, Bescheid.FIELD_SEND_BY)).map(SendBy::valueOf); + private Optional<SentInfo> getSentInfo(Map<String, Object> itemMap) { + return Optional.ofNullable(MapUtils.getMap(itemMap, Bescheid.FIELD_SENT_INFO)).map(sentInfoMapper::toSentInfo); } - default Optional<SentInfo> getSentInfo(Map<String, Object> itemMap) { - return Optional.ofNullable(MapUtils.getMap(itemMap, Bescheid.FIELD_SENT_INFO)).map(this::toSentInfo); + @Mapping(target = "client", constant = BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME) + @Mapping(target = "itemName", constant = AttachedItemService.BESCHEID_ITEM_NAME) + @Mapping(target = "item", expression = "java(mapToItem(bescheid))") + public abstract AttachedItem mapFromBescheid(Bescheid bescheid); + + String mapToString(StringBasedValue value) { + return value.toString(); } - default SentInfo toSentInfo(Map<String, Object> sentInfoMap) { - return SentInfo.builder() - .sentBy(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_BY)) - .sentAt(ZonedDateTime.parse(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_AT))) - .build(); + public Map<String, Object> mapToItem(Bescheid bescheid) { + var result = new HashMap<String, Object>(); + result.put(Bescheid.FIELD_BEWILLIGT, bescheid.isBewilligt()); + mapBeschiedenAm(bescheid).ifPresent(beschiedenAm -> result.put(Bescheid.FIELD_BESCHIEDEN_AM, beschiedenAm)); + mapStatus(bescheid).ifPresent(status -> result.put(Bescheid.FIELD_STATUS, status)); + mapBescheidDocument(bescheid).ifPresent(bescheidDocumentId -> result.put(Bescheid.FIELD_BESCHEID_DOCUMENT, bescheidDocumentId)); + mapSendBy(bescheid).ifPresent(sendBy -> result.put(Bescheid.FIELD_SEND_BY, sendBy)); + bescheid.getNachrichtSubject().ifPresent(subject -> result.put(Bescheid.FIELD_NACHRICHT_SUBJECT, subject)); + bescheid.getNachrichtText().ifPresent(text -> result.put(Bescheid.FIELD_NACHRICHT_TEXT, text)); + mapSentInfo(bescheid).ifPresent(sentInfo -> result.put(FIELD_SENT_INFO, sentInfo)); + mapAttachmentIds(bescheid.getAttachments()).ifPresent(attachmentIds -> result.put(FIELD_ATTACHMENTS, attachmentIds)); + return Collections.unmodifiableMap(result); } - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFeatures", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "javaVersionBytes", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "versionBytes", ignore = true) - @Mapping(target = "allFields", ignore = true) - GrpcBescheidManagerConfigResponse fromBescheidManagerConfig(BescheidManagerConfig bescheidManagerConfig); + private Optional<String> mapBeschiedenAm(Bescheid bescheid) { + return Optional.ofNullable(bescheid.getBeschiedenAm()).map(LocalDate::toString); + } - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeBescheid", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - GrpcGetBescheidResponse toGetBescheidResponse(Bescheid bescheid); + private Optional<String> mapStatus(Bescheid bescheid) { + return Optional.ofNullable(bescheid.getStatus()).map(Bescheid.Status::name); + } + + private Optional<String> mapBescheidDocument(Bescheid bescheid) { + return Optional.ofNullable(bescheid.getBescheidDocument()).map(FileId::toString); + } + + private Optional<String> mapSendBy(Bescheid bescheid) { + return Optional.ofNullable(bescheid.getSendBy()).map(Bescheid.SendBy::name); + } + + public Optional<Map<String, Object>> mapSentInfo(Bescheid bescheid) { + return Optional.ofNullable(bescheid.getSentInfo()).map(sentInfoMapper::toMap); + } + + Optional<List<String>> mapAttachmentIds(List<FileId> attachments) { + return attachments.isEmpty() ? Optional.empty() : Optional.of(attachments.stream().map(FileId::toString).toList()); + } - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeBescheid", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - GrpcGetBescheidDraftResponse toGetBescheidDraftResponse(Bescheid bescheid); } \ No newline at end of file diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java index 372e07eb95400196f7cb1d540716314f5994ef44..cd1d2fc2ccb45a29beedfc74b4d90b7ecc8d559f 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java @@ -1,13 +1,17 @@ package de.ozgcloud.bescheid; +import static java.util.Objects.*; + import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.Stream; import jakarta.annotation.PostConstruct; @@ -22,7 +26,9 @@ import de.ozgcloud.apilib.common.command.OzgCloudCommand; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.common.command.OzgCloudCreateSubCommandsRequest; import de.ozgcloud.apilib.common.command.grpc.CommandMapper; +import de.ozgcloud.bescheid.administration.AdministrationService; import de.ozgcloud.bescheid.attributes.ClientAttributeService; +import de.ozgcloud.bescheid.common.freemarker.TemplateHandler; import de.ozgcloud.bescheid.common.user.UserProfileService; import de.ozgcloud.bescheid.vorgang.Vorgang; import de.ozgcloud.bescheid.vorgang.VorgangId; @@ -39,7 +45,11 @@ import lombok.extern.log4j.Log4j2; @Service @Log4j2 @RequiredArgsConstructor -class BescheidService { +public class BescheidService { + + static final String DEFAULT_NACHRICHT_SUBJECT = "Ihr Bescheid zum Antrag"; + public static final String DEFAULT_NACHRICHT_TEMPLATE_FILE = "bescheid.nachrichtTemplate.txt.ftlh"; + public static final String KEY_TEMPLATE_SIGNATURE = "signature"; private static final String ERROR_MESSAGE_NO_SERVICE = "No Bescheid Endpoint is configured."; @@ -60,12 +70,16 @@ class BescheidService { private final UserProfileService userProfileService; @Qualifier(BescheidManagerConfiguration.COMMAND_SERVICE_NAME) private final OzgCloudCommandService commandService; + private final AdministrationService administrationService; + private final CommandMapper commandMapper; private final ClientAttributeService bescheidClientAttributeService; private final BuildProperties buildProperties; private final Optional<BescheidRemoteService> remoteService; private final BescheidMapper mapper; + private final TemplateHandler templateHandler; + @PostConstruct void logStatus() { remoteService.ifPresentOrElse( @@ -74,13 +88,65 @@ class BescheidService { } public Optional<Bescheid> findDraft(String vorgangId) { - return attachedItemService.findBescheidItem(vorgangId).map(mapper::mapFromAttachedItem); + return attachedItemService.findBescheidItem(VorgangId.from(vorgangId)).map(mapper::mapFromAttachedItem); } public Stream<Bescheid> findAll(VorgangId vorgangId) { return attachedItemService.findAllBescheid(vorgangId).stream().map(mapper::mapFromAttachedItem); } + public String createBescheidDraft(Command createBescheidDraftCommand) { + validateBescheidData(createBescheidDraftCommand.getBodyObject()); + return attachedItemService.createBescheidDraft(buildBescheidDraft(createBescheidDraftCommand)); + } + + void validateBescheidData(Map<String, Object> bodyObject) { + validateBescheidField(bodyObject, Bescheid.FIELD_BESCHIEDEN_AM); + validateBescheidField(bodyObject, Bescheid.FIELD_BEWILLIGT); + validateSendBy(MapUtils.getString(bodyObject, Bescheid.FIELD_SEND_BY)); + } + + void validateBescheidField(Map<String, Object> bescheid, String field) { + if (isNull(bescheid.get(field))) { + throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(field)); + } + } + + void validateSendBy(String sendBy) { + if (isUnknownSendByValue(sendBy)) { + var possibleSendByValues = Arrays.stream(Bescheid.SendBy.values()).map(Bescheid.SendBy::name) + .collect(Collectors.joining(",")); + var message = String.format("Unexpected value for field '%s': %s. Allowed are: %s", Bescheid.FIELD_SEND_BY, sendBy, + possibleSendByValues); + throw new TechnicalException(message); + } + } + + private boolean isUnknownSendByValue(String sendByValue) { + return Arrays.stream(Bescheid.SendBy.values()).noneMatch(sendBy -> sendBy.hasValue(sendByValue)); + } + + Bescheid buildBescheidDraft(Command command) { + var bescheid = mapper.mapFromCommand(command); + var resultBuilder = bescheid.toBuilder().id(null).version(0).status(Bescheid.Status.DRAFT); + if (bescheid.getNachrichtSubject().isEmpty()) { + resultBuilder.nachrichtSubject(Optional.of(DEFAULT_NACHRICHT_SUBJECT)); + } + if (bescheid.getNachrichtText().isEmpty()) { + resultBuilder.nachrichtText(Optional.of(createNachrichtText())); + } + return resultBuilder.build(); + } + + String createNachrichtText() { + return templateHandler.fillTemplate(DEFAULT_NACHRICHT_TEMPLATE_FILE, getTemplateParameters()); + } + + Map<String, Object> getTemplateParameters() { + return administrationService.getNachrichtSignature().map(signature -> Map.<String, Object>of(KEY_TEMPLATE_SIGNATURE, signature)) + .orElseGet(Collections::emptyMap); + } + public BescheidResponse createBescheid(BescheidRequest request) { checkRemoteService(); diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java index a16e4a4aa3a7717c0c74905602962de176537df4..95c5b586e88adc7881815f3331ad7213f5bcb530 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/SentInfoMapper.java @@ -1,5 +1,12 @@ package de.ozgcloud.bescheid; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -8,6 +15,9 @@ import org.mapstruct.ReportingPolicy; @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) public interface SentInfoMapper { + String GRPC_DATE_TIME_FORMATTER = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + + @Mapping(target = "defaultInstanceForType", ignore = true) @Mapping(target = "mergeFrom", ignore = true) @Mapping(target = "clearField", ignore = true) @Mapping(target = "clearOneof", ignore = true) @@ -16,6 +26,20 @@ public interface SentInfoMapper { @Mapping(target = "sentByBytes", ignore = true) @Mapping(target = "unknownFields", ignore = true) @Mapping(target = "allFields", ignore = true) - @Mapping(target = "sentAt", source = "sentAt", dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'") + @Mapping(target = "sentAt", source = "sentAt", dateFormat = GRPC_DATE_TIME_FORMATTER) GrpcSentInfo mapTo(SentInfo sentInfo); + + default SentInfo toSentInfo(Map<String, Object> sentInfoMap) { + return SentInfo.builder() + .sentBy(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_BY)) + .sentAt(ZonedDateTime.parse(MapUtils.getString(sentInfoMap, SentInfo.FIELD_SENT_AT), DateTimeFormatter.ISO_DATE_TIME)) + .build(); + } + + default Map<String, Object> toMap(SentInfo sentInfo) { + var result = new HashMap<String, Object>(); + result.put(SentInfo.FIELD_SENT_BY, sentInfo.getSentBy()); + result.put(SentInfo.FIELD_SENT_AT, sentInfo.getSentAt().format(DateTimeFormatter.ISO_DATE_TIME)); + return Collections.unmodifiableMap(result); + } } diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..59f93a0239f649eb4156fb5512494e06749066d9 --- /dev/null +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationProperties.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.bescheid.administration; + +import java.util.Optional; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@RefreshScope +@Configuration +@ConfigurationProperties(prefix = "ozgcloud.postfach") +public class AdministrationProperties { + + private Optional<String> signatur = Optional.empty(); + +} diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java new file mode 100644 index 0000000000000000000000000000000000000000..920c5ea67d8285d1646b7840bf6c5fd91fb8c1ab --- /dev/null +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationService.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.bescheid.administration; + +import java.util.Optional; + +import org.springframework.cloud.endpoint.RefreshEndpoint; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class AdministrationService { + + private final AdministrationProperties administrationProperties; + private final RefreshEndpoint refreshEndpoint; + + public Optional<String> getNachrichtSignature() { + return administrationProperties.getSignatur(); + } + + public void refreshConfig() { + refreshEndpoint.refresh(); + } +} diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..41fde870cc01fe94e9d2089742e77ffffd6a3f4a --- /dev/null +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/administration/AdministrationSyncScheduler.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.bescheid.administration; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; + +@Component +@ConditionalOnProperty(value = "ozgcloud.administration.sync.enabled", havingValue = "true", matchIfMissing = true) +@RequiredArgsConstructor +public class AdministrationSyncScheduler { + + private final AdministrationService service; + + @Scheduled(initialDelayString = "${ozgcloud.administration.sync.delay}", fixedDelayString = "${ozgcloud.administration.sync.delay}") + public void sync() { + service.refreshConfig(); + } +} diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java index 73d20952c8b05bf3fa0dd93c8d284c7583c319a5..c3431d175ebf43e14f6a7fd15baf34cb7b81a5f6 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemMapper.java @@ -23,13 +23,25 @@ */ package de.ozgcloud.common.attached_item; +import java.util.Map; + import org.mapstruct.Mapper; +import org.mapstruct.NullValueCheckStrategy; import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper; import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem; -@Mapper(uses = { GrpcObjectMapper.class }) +@Mapper(uses = { GrpcObjectMapper.class }, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) public interface AttachedItemMapper { AttachedItem mapFromVorgangAttachedItem(GrpcVorgangAttachedItem item); + + default Map<String, Object> toMap(AttachedItem attachedItem) { + return Map.of( + AttachedItem.PROPERTY_VORGANG_ID, attachedItem.getVorgangId(), + AttachedItem.PROPERTY_CLIENT, attachedItem.getClient(), + AttachedItem.PROPERTY_ITEM_NAME, attachedItem.getItemName(), + AttachedItem.PROPERTY_ITEM, attachedItem.getItem()); + } + } \ No newline at end of file diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java index 551279332894c5c12395a7a43a2a93de52c180dc..d0ad2ed4e32a2eb9fe424440629f23e0e50e9331 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/AttachedItemService.java @@ -23,15 +23,11 @@ */ package de.ozgcloud.common.attached_item; -import static java.util.Objects.*; - -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.function.Function; -import java.util.stream.Collectors; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -45,7 +41,7 @@ import de.ozgcloud.bescheid.Bescheid; import de.ozgcloud.bescheid.Bescheid.Status; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; import de.ozgcloud.bescheid.BescheidManagerConfiguration; -import de.ozgcloud.bescheid.common.freemarker.TemplateHandler; +import de.ozgcloud.bescheid.BescheidMapper; import de.ozgcloud.bescheid.vorgang.VorgangId; import de.ozgcloud.command.Command; import de.ozgcloud.common.errorhandling.TechnicalException; @@ -62,16 +58,15 @@ public class AttachedItemService { static final String UPDATE_ATTACHED_ITEM_ORDER = "UPDATE_ATTACHED_ITEM"; static final String DELETE_ATTACHED_ITEM = "DELETE_ATTACHED_ITEM"; - static final String DEFAULT_SUBJECT = "Ihr Bescheid zum Antrag"; - static final String DEFAULT_TEMPLATE_FILE = "bescheid.nachrichtTemplate.txt.ftlh"; - @Qualifier(BescheidManagerConfiguration.COMMAND_SERVICE_NAME) private final OzgCloudCommandService commandService; private final VorgangAttachedItemRemoteService remoteService; + private final CommandMapper commandMapper; - private final TemplateHandler templateHandler; + private final AttachedItemMapper attachedItemMapper; + private final BescheidMapper bescheidMapper; - public Optional<AttachedItem> findBescheidItem(String vorgangId) { + public Optional<AttachedItem> findBescheidItem(VorgangId vorgangId) { return remoteService.findBescheidDraft(vorgangId); } @@ -79,41 +74,20 @@ public class AttachedItemService { return remoteService.getItem(id); } - public String createBescheidDraft(Command command) { - validateBescheidData(command.getBodyObject()); - return remoteService.findBescheidDraft(command.getVorgangId()) - .map(bescheid -> overrideAttachedItem(bescheid, command)).orElseGet(() -> createAttachedItem(command)); - } - - void validateBescheidData(Map<String, Object> bodyObject) { - validateBescheidField(bodyObject, Bescheid.FIELD_BESCHIEDEN_AM); - validateBescheidField(bodyObject, Bescheid.FIELD_BEWILLIGT); - validateSendBy(getSendBy(bodyObject)); - } - - void validateBescheidField(Map<String, Object> bescheid, String field) { - if (isNull(bescheid.get(field))) { - throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(field)); - } - } - - void validateSendBy(String sendBy) { - if (isUnknownSendByValue(sendBy)) { - var possibleSendByValues = Arrays.stream(Bescheid.SendBy.values()).map(Bescheid.SendBy::name) - .collect(Collectors.joining(",")); - var message = String.format("Unexpected value for field '%s': %s. Allowed are: %s", Bescheid.FIELD_SEND_BY, sendBy, - possibleSendByValues); - throw new TechnicalException(message); - } + public String createBescheidDraft(Bescheid bescheidDraft) { + return remoteService.findBescheidDraft(bescheidDraft.getVorgangId()) + .map(bescheidItem -> overrideAttachedItem(mergeBescheidDrafts(bescheidItem, bescheidDraft))) + .orElseGet(() -> createAttachedItem(bescheidDraft)); } - private boolean isUnknownSendByValue(String sendByValue) { - return Arrays.stream(Bescheid.SendBy.values()).noneMatch(sendBy -> sendBy.hasValue(sendByValue)); + AttachedItem mergeBescheidDrafts(AttachedItem existingBescheidItem, Bescheid newBescheidDraft) { + return existingBescheidItem.toBuilder() + .item(bescheidMapper.mapToItem(newBescheidDraft)) + .build(); } - String overrideAttachedItem(AttachedItem bescheidItem, Command command) { - var attachedItem = buildAttachedItemAsMap(command, buildItemMapWithAllBescheidFields(command)); - var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildPatchAttachedItemCommand(bescheidItem, attachedItem)); + String overrideAttachedItem(AttachedItem bescheidItem) { + var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildPatchAttachedItemCommand(bescheidItem, bescheidItem.getItem())); return finishedOzgCloudCommand.getCreatedResource(); } @@ -178,16 +152,17 @@ public class AttachedItemService { .build(); } - String createAttachedItem(Command command) { - return commandService.createAndWaitUntilDone(buildCreateAttachedItemCommand(command)).getCreatedResource(); + String createAttachedItem(Bescheid bescheidDraft) { + var bescheidItem = bescheidMapper.mapFromBescheid(bescheidDraft); + return commandService.createAndWaitUntilDone(buildCreateAttachedItemCommand(bescheidItem)).getCreatedResource(); } - OzgCloudCommand buildCreateAttachedItemCommand(Command command) { + OzgCloudCommand buildCreateAttachedItemCommand(AttachedItem bescheidItem) { return OzgCloudCommand.builder() - .vorgangId(commandMapper.toOzgCloudVorgangId(command.getVorgangId())) - .relationId(commandMapper.mapRelationId(command.getRelationId())) + .vorgangId(commandMapper.toOzgCloudVorgangId(bescheidItem.getVorgangId())) + .relationId(commandMapper.mapRelationId(bescheidItem.getVorgangId())) .order(CREATE_ATTACHED_ITEM_ORDER) - .bodyObject(buildAttachedItemAsMap(command, buildCreateBescheidItemMap(command))).build(); + .bodyObject(attachedItemMapper.toMap(bescheidItem)).build(); } Map<String, Object> buildAttachedItemAsMap(Command command, Map<String, Object> itemMap) { @@ -199,17 +174,6 @@ public class AttachedItemService { return result; } - Map<String, Object> buildCreateBescheidItemMap(Command command) { - var result = buildItemMapWithExistingBescheidFields(command); - if (StringUtils.isEmpty(getNachrichtSubject(command))) { - result.put(Bescheid.FIELD_NACHRICHT_SUBJECT, DEFAULT_SUBJECT); - } - if (StringUtils.isEmpty(getNachrichtText(command))) { - result.put(Bescheid.FIELD_NACHRICHT_TEXT, templateHandler.getRawTemplate(DEFAULT_TEMPLATE_FILE)); - } - return result; - } - Map<String, Object> buildItemMapWithExistingBescheidFields(Command command) { var result = buildItemMap(Bescheid.Status.DRAFT); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_BESCHIEDEN_AM, result); @@ -222,14 +186,6 @@ public class AttachedItemService { return result; } - private String getNachrichtSubject(Command command) { - return MapUtils.getString(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_SUBJECT); - } - - private String getNachrichtText(Command command) { - return MapUtils.getString(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_TEXT); - } - void addValueFromMapIfExists(Map<String, Object> sourceMap, String key, Map<String, Object> targetMap) { if (sourceMap.containsKey(key)) { targetMap.put(key, sourceMap.get(key)); diff --git a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java index 6bc59454c9bd380608d7594e82a4df4f48174101..1d8756a0c968d0463e6f94391afb91fad9143c04 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteService.java @@ -62,8 +62,8 @@ class VorgangAttachedItemRemoteService { @Autowired private AttachedItemMapper attachedItemMapper; - public Optional<AttachedItem> findBescheidDraft(String vorgangId) { - return findBescheidDraft(buildFindRequest(vorgangId)); + public Optional<AttachedItem> findBescheidDraft(VorgangId vorgangId) { + return findBescheidDraft(buildFindRequest(vorgangId.toString())); } public List<AttachedItem> findAllBescheid(VorgangId vorgangId) { diff --git a/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh index 368804ed6ea51f622c32a2e90a21d5f1dd00763f..a16717f3fed5f7943af7f6cb701e085bdebeebb9 100644 --- a/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh +++ b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh @@ -2,6 +2,6 @@ Sehr geehrte/r Antragsteller/in, im Folgenden erhalten Sie Ihren Bescheid. -Mit freundlichen Grüßen +${(signature)!"Mit freundlichen Grüßen -Ihre Verwaltung \ No newline at end of file +Ihre Verwaltung"} \ No newline at end of file diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java index 2700586f2f8dd27bd9940ad790f6d2cc395370df..66403e2e7b83b2ac4ce30cb2b532cbdca881da64 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java @@ -64,7 +64,7 @@ class BescheidEventListenerITCase { void shouldCallService() { publisher.publishEvent(CommandCreatedEventTestFactory.withCommand(command)); - verify(attachedItemService).createBescheidDraft(command); + verify(service).createBescheidDraft(command); } @Test diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java index 5d2d0689225962c1127644fe1f38063cb1e13c01..a3734e17d99a07d77410d213ebbe30415424cb1f 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java @@ -106,14 +106,14 @@ class BescheidEventListenerTest { void shouldCallCreateBescheidDraft() { listener.doCreateBescheid(COMMAND); - verify(attachedItemService).createBescheidDraft(COMMAND); + verify(service).createBescheidDraft(COMMAND); } @Test @DisplayName("should publish BescheidCreatedEvent after creating BescheidDraft") void shouldPublishBescheidCreatedEventWithCommand() { var createdResource = "item-id"; - when(attachedItemService.createBescheidDraft(any())).thenReturn(createdResource); + when(service.createBescheidDraft(any())).thenReturn(createdResource); listener.doCreateBescheid(COMMAND); @@ -125,7 +125,7 @@ class BescheidEventListenerTest { @DisplayName("should publish BescheidCreatedEvent with created resource") void shouldPublishBescheidCreatedEventWithCreatedResource() { var createdResource = "item-id"; - when(attachedItemService.createBescheidDraft(any())).thenReturn(createdResource); + when(service.createBescheidDraft(any())).thenReturn(createdResource); listener.doCreateBescheid(COMMAND); @@ -497,7 +497,7 @@ class BescheidEventListenerTest { private static final Command COMMAND = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID) .relationVersion(AttachedItemTestFactory.VERSION).bodyObject(AttachedItemTestFactory.createBescheidItem()).build(); - private AttachedItem bescheidItem = createManuallyBescheidItem(); + private final AttachedItem bescheidItem = createManuallyBescheidItem(); private AttachedItem createManuallyBescheidItem() { var attachedItem = AttachedItemTestFactory.createBescheid(); diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java index 8feda3dfe1ac673133247f758d71d3a413fa4a52..4e867c490dcc6bdcecd99e3b26cbc221caf686be 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidMapperTest.java @@ -6,6 +6,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; @@ -17,10 +18,14 @@ import org.mockito.InjectMocks; import org.mockito.Spy; import de.ozgcloud.bescheid.vorgang.VorgangTestFactory; +import de.ozgcloud.command.CommandTestFactory; +import de.ozgcloud.common.attached_item.AttachedItemService; import de.ozgcloud.common.attached_item.AttachedItemTestFactory; +import de.ozgcloud.document.DocumentTestFactory; class BescheidMapperTest { + @Spy @InjectMocks private final BescheidMapper mapper = Mappers.getMapper(BescheidMapper.class); @Spy @@ -45,9 +50,7 @@ class BescheidMapperTest { void shouldMapAllFields() { var result = mapper.toBescheid(BescheidTestFactory.create()); - assertThat(result).usingRecursiveComparison() - .ignoringFields("memoizedHashCode", "sentInfo_") - .isEqualTo(GrpcBescheidWithoutDocumentTestFactory.create()); + assertThat(result).usingRecursiveComparison().isEqualTo(GrpcBescheidWithoutDocumentTestFactory.create()); } } @@ -120,4 +123,139 @@ class BescheidMapperTest { assertThat(response).usingRecursiveComparison().isEqualTo(GrpcGetBescheidDraftResponseTestFactory.create()); } } + + @DisplayName("Map from command") + @Nested + class TestMapFromCommand { + + @Test + void shouldMap() { + var command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem()) + .vorgangId(VorgangTestFactory.ID_STR).build(); + + var result = mapper.mapFromCommand(command); + + assertThat(result).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(BescheidTestFactory.create()); + } + } + + @Nested + class TestMapFromBescheid { + + @Test + void shouldSetClient() { + var result = mapper.mapFromBescheid(BescheidTestFactory.create()); + + assertThat(result.getClient()).isEqualTo(BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME); + } + + @Test + void shouldSetItemName() { + var result = mapper.mapFromBescheid(BescheidTestFactory.create()); + + assertThat(result.getItemName()).isEqualTo(AttachedItemService.BESCHEID_ITEM_NAME); + } + + @Test + void shouldCallMapBescheidToItem() { + var bescheid = BescheidTestFactory.create(); + + mapper.mapFromBescheid(bescheid); + + verify(mapper).mapToItem(bescheid); + } + + @Test + void shouldSetItem() { + var itemMap = Map.<String, Object>of("key", "value"); + doReturn(itemMap).when(mapper).mapToItem(any()); + + var result = mapper.mapFromBescheid(BescheidTestFactory.create()); + + assertThat(result.getItem()).isEqualTo(itemMap); + } + } + + @Nested + class TestMapBescheidToItem { + + @Test + void shouldSetBewilligt() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_BEWILLIGT, BescheidTestFactory.BEWILLIGT); + } + + @Test + void shouldSetBeschiedenAm() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_BESCHIEDEN_AM, BescheidTestFactory.BESCHIEDEN_AM_STR); + } + + @Test + void shouldSetStatus() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_STATUS, BescheidTestFactory.STATUS.name()); + } + + @Test + void shouldSetBescheidDocument() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result.get(Bescheid.FIELD_BESCHEID_DOCUMENT)).hasToString(DocumentTestFactory.ID); + } + + @Test + void shouldSetSendBy() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_SEND_BY, BescheidTestFactory.SEND_BY.name()); + } + + @Test + void shouldSetNachrichtSubject() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, BescheidTestFactory.NACHRICHT_SUBJECT); + } + + @Test + void shouldSetNachrichtText() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, BescheidTestFactory.NACHRICHT_TEXT); + } + + @Test + void shouldCallSentInfoMapper() { + mapper.mapToItem(BescheidTestFactory.create()); + + verify(sentInfoMapper).toMap(BescheidTestFactory.SENT_INFO); + } + + @Test + void shouldSetSentInfo() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_SENT_INFO, SentInfoTestFactory.asMap()); + } + + @Test + void shouldSetAttachments() { + var result = mapper.mapToItem(BescheidTestFactory.create()); + + assertThat(result).containsEntry(Bescheid.FIELD_ATTACHMENTS, + List.of(BescheidTestFactory.ATTACHMENT_STR, BescheidTestFactory.ATTACHMENT_STR)); + } + + @Test + void shouldNotAddEmptyEntries() { + var result = mapper.mapToItem(Bescheid.builder().build()); + + assertThat(result).containsOnlyKeys(Bescheid.FIELD_BEWILLIGT); + } + } + } \ No newline at end of file diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java index 1bfa29f025365178aa5a66816db937b5670b2536..e593e429c550d90454013369ab01640091b5afef 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java @@ -1,7 +1,6 @@ package de.ozgcloud.bescheid; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.InstanceOfAssertFactories.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -41,7 +40,9 @@ import de.ozgcloud.apilib.common.datatypes.GenericId; import de.ozgcloud.apilib.user.OzgCloudUserId; import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId; import de.ozgcloud.bescheid.Bescheid.SendBy; +import de.ozgcloud.bescheid.administration.AdministrationService; import de.ozgcloud.bescheid.attributes.ClientAttributeService; +import de.ozgcloud.bescheid.common.freemarker.TemplateHandler; import de.ozgcloud.bescheid.common.user.UserProfile; import de.ozgcloud.bescheid.common.user.UserProfileService; import de.ozgcloud.bescheid.common.user.UserProfileTestFactory; @@ -85,6 +86,10 @@ class BescheidServiceTest { private BescheidRemoteService remoteService; @Mock private BescheidMapper mapper; + @Mock + private AdministrationService administrationService; + @Mock + private TemplateHandler templateHandler; @BeforeEach void init() { @@ -108,7 +113,7 @@ class BescheidServiceTest { void shouldCallVorgangAttachedItemRemoteService() { service.findDraft(VorgangTestFactory.ID_STR); - verify(attachedItemService).findBescheidItem(VorgangTestFactory.ID_STR); + verify(attachedItemService).findBescheidItem(VorgangTestFactory.ID); } @Test @@ -165,6 +170,254 @@ class BescheidServiceTest { } } + @Nested + class TestCreateBescheidDraft { + + private static final Map<String, Object> COMMAND_BODY = Map.of("key", "value"); + private static final Command COMMAND = CommandTestFactory.createBuilder().bodyObject(COMMAND_BODY).build(); + private static final Bescheid BESCHEID_DRAFT = BescheidTestFactory.create(); + + @BeforeEach + void init() { + doNothing().when(service).validateBescheidData(any()); + doReturn(BESCHEID_DRAFT).when(service).buildBescheidDraft(any()); + } + + @Test + void shouldCallValidateBescheidData() { + service.createBescheidDraft(COMMAND); + + verify(service).validateBescheidData(COMMAND_BODY); + } + + @Test + void shouldCallAttachedItemService() { + service.createBescheidDraft(COMMAND); + + verify(attachedItemService).createBescheidDraft(BESCHEID_DRAFT); + } + + @Test + void shouldReturnResult() { + var createdBescheidId = "created-bescheid-id"; + when(attachedItemService.createBescheidDraft(any(Bescheid.class))).thenReturn(createdBescheidId); + + var result = service.createBescheidDraft(COMMAND); + + assertThat(result).isEqualTo(createdBescheidId); + } + } + + @Nested + class TestValidateBescheidData { + + private static final Command CREATE_BESCHEID_DRAFT_COMMAND = CommandTestFactory.createBuilder() + .bodyObject(AttachedItemTestFactory.createBescheidItem()).build(); + + @Test + void shouldValidate() { + assertDoesNotThrow(() -> service.validateBescheidData(CREATE_BESCHEID_DRAFT_COMMAND.getBodyObject())); + } + + @DisplayName("should fail if bescheidAm is missing") + @Test + void shouldThrowExceptionByBescheidAm() { + var map = Map.<String, Object>of(Bescheid.FIELD_BEWILLIGT, true); + + assertThrows(TechnicalException.class, () -> service.validateBescheidData(map)); + } + + @DisplayName("should fail if bewilligt is missing") + @Test + void shouldThrowExceptionByBewilligt() { + var map = Map.<String, Object>of(Bescheid.FIELD_BESCHIEDEN_AM, "2021-01-01"); + + assertThrows(TechnicalException.class, () -> service.validateBescheidData(map)); + } + + @Test + void shouldValidateSendBy() { + var bodyObject = Map.<String, Object>of(Bescheid.FIELD_SEND_BY, SendBy.MANUAL.name()); + doNothing().when(service).validateBescheidField(any(), any()); + + service.validateBescheidData(bodyObject); + + verify(service).validateSendBy(SendBy.MANUAL.name()); + } + + @DisplayName("validate sendBy") + @Nested + class TestValidateSendBy { + + @ValueSource(strings = { "not-exist", "" }) + @ParameterizedTest + void shouldThrowExceptionOnNonExistingSendByValue(String sendBy) { + assertThrows(TechnicalException.class, () -> service.validateSendBy(sendBy)); + } + + @EnumSource(names = { "NACHRICHT", "MANUAL" }) + @ParameterizedTest + void shouldNotThrowAnyExceptionOnExistingSendByValue(SendBy sendBy) { + assertDoesNotThrow(() -> service.validateSendBy(sendBy.name())); + } + } + } + + @Nested + class TestBuildBescheidDraft { + + private static final Command CREATE_BESCHEID_DRAFT_COMMAND = CommandTestFactory.createBuilder() + .bodyObject(AttachedItemTestFactory.createBescheidItem()).build(); + + private final Bescheid bescheid = BescheidTestFactory.createBuilder().status(Bescheid.Status.SENT).build(); + + @BeforeEach + void init() { + when(mapper.mapFromCommand(any())).thenReturn(bescheid); + } + + @Test + void shouldCallMapFromCommand() { + buildBescheidDraft(); + + verify(mapper).mapFromCommand(CREATE_BESCHEID_DRAFT_COMMAND); + } + + @Test + void shouldResetId() { + var result = buildBescheidDraft(); + + assertThat(result.getId()).isNull(); + } + + @Test + void shouldResetVersion() { + var result = buildBescheidDraft(); + + assertThat(result.getVersion()).isZero(); + } + + @Test + void shouldSetStatus() { + var result = buildBescheidDraft(); + + assertThat(result.getStatus()).isEqualTo(Bescheid.Status.DRAFT); + } + + @Test + void shouldNotOverrideNachrichtSubject() { + var result = buildBescheidDraft(); + + assertThat(result.getNachrichtSubject()).contains(BescheidTestFactory.NACHRICHT_SUBJECT); + } + + @Test + void shouldSetNachrichtSubject() { + var bescheid = BescheidTestFactory.createBuilder().nachrichtSubject(Optional.empty()).build(); + when(mapper.mapFromCommand(any())).thenReturn(bescheid); + + var result = buildBescheidDraft(); + + assertThat(result.getNachrichtSubject()).contains(BescheidService.SUBJECT); + } + + @Test + void shouldNotOverrideNachrichtText() { + var result = buildBescheidDraft(); + + assertThat(result.getNachrichtText()).contains(BescheidTestFactory.NACHRICHT_TEXT); + } + + @Test + void shouldCallCreateNachrichtText() { + var createdText = "created text"; + doReturn(createdText).when(service).createNachrichtText(); + var bescheid = BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build(); + when(mapper.mapFromCommand(any())).thenReturn(bescheid); + + buildBescheidDraft(); + + verify(service).createNachrichtText(); + } + + @Test + void shouldSetNachrichtText() { + var createdText = "created text"; + doReturn(createdText).when(service).createNachrichtText(); + var bescheid = BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build(); + when(mapper.mapFromCommand(any())).thenReturn(bescheid); + + var result = buildBescheidDraft(); + + assertThat(result.getNachrichtText()).contains(createdText); + } + + private Bescheid buildBescheidDraft() { + return service.buildBescheidDraft(CREATE_BESCHEID_DRAFT_COMMAND); + } + } + + @Nested + class TestCreateNachrichtText { + + @Captor + private ArgumentCaptor<Map<String, Object>> signatureCaptor; + + @Test + void shouldCallGetTemplateParameters() { + service.createNachrichtText(); + + verify(service).getTemplateParameters(); + } + + @Test + void shouldCallFillTemplate() { + var parameterMap = Map.<String, Object>of("key", "value"); + doReturn(parameterMap).when(service).getTemplateParameters(); + + service.createNachrichtText(); + + verify(templateHandler).fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE, parameterMap); + } + + @Test + void shouldReturnNachricht() { + when(templateHandler.fillTemplate(any(), any())).thenReturn(BescheidTestFactory.NACHRICHT_TEXT); + + var result = service.createNachrichtText(); + + assertThat(result).isEqualTo(BescheidTestFactory.NACHRICHT_TEXT); + } + } + + @Nested + class TestGetTemplateParameters { + + @Test + void shouldCallAdministrationService() { + service.createNachrichtText(); + + verify(administrationService).getNachrichtSignature(); + } + + @Test + void shouldReturnParameters() { + var signature = "signature"; + when(administrationService.getNachrichtSignature()).thenReturn(Optional.of(signature)); + + var result = service.getTemplateParameters(); + + assertThat(result).containsEntry(BescheidService.KEY_TEMPLATE_SIGNATURE, signature); + } + + @Test + void shouldReturnEmptyMap() { + var result = service.getTemplateParameters(); + + assertThat(result).isEmpty(); + } + } + @Nested class TestCreateBescheid { diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java index 9bbaa5728dc689fe6d70fe510af8ae909b65ae7f..b04cada3828d9fae6a85c5217c97df420972f353 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java @@ -3,6 +3,7 @@ package de.ozgcloud.bescheid; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.info.BuildProperties; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.endpoint.RefreshEndpoint; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.security.authentication.AuthenticationTrustResolver; @@ -14,6 +15,8 @@ public class BescheidTestApplication { @MockBean private BuildProperties buildProperties; + @MockBean + private RefreshEndpoint refreshEndpoint; @Bean AuthenticationTrustResolver trustResolver() { diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java index 326882334bbe54cd6987bf3eb812f1e086639642..7b90a2215cbddb56900ea293d7bbfd5cb9f44363 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java @@ -19,6 +19,7 @@ public class BescheidTestFactory { public final static boolean BEWILLIGT = true; + public final static BescheidId ID = BescheidId.from(AttachedItemTestFactory.ID); public final static Status STATUS = Status.DRAFT; public final static String BESCHIEDEN_AM_STR = "2021-01-10"; public final static LocalDate BESCHIEDEN_AM = LocalDate.parse(BESCHIEDEN_AM_STR); @@ -39,7 +40,7 @@ public class BescheidTestFactory { public static Bescheid.BescheidBuilder createBuilder() { return Bescheid.builder() - .id(BescheidId.from(AttachedItemTestFactory.ID)) + .id(ID) .version(AttachedItemTestFactory.VERSION) .vorgangId(VorgangTestFactory.ID) .createdBy(UserProfileTestFactory.ID) diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java index 2fa8f14b830b3c980e207d41ef1af3cafe69d00b..c3f9eea19a4f802f8214371b024f5bc3b7e08453 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/SentInfoMapperTest.java @@ -9,7 +9,7 @@ import org.mapstruct.factory.Mappers; class SentInfoMapperTest { - private SentInfoMapper mapper = Mappers.getMapper(SentInfoMapper.class); + private final SentInfoMapper mapper = Mappers.getMapper(SentInfoMapper.class); @DisplayName("Map to") @Nested @@ -22,4 +22,28 @@ class SentInfoMapperTest { assertThat(mappedSentInfo).usingRecursiveComparison().isEqualTo(GrpcSentInfoTestFactory.create()); } } + + @DisplayName("Map to SentInfo") + @Nested + class TestToSentInfo { + + @Test + void shouldMap() { + var mappedSentInfo = mapper.toSentInfo(SentInfoTestFactory.asMap()); + + assertThat(mappedSentInfo).usingRecursiveComparison().isEqualTo(SentInfoTestFactory.create()); + } + } + + @DisplayName("As map") + @Nested + class TestAsMap { + + @Test + void shouldMap() { + var mappedSentInfo = mapper.toMap(SentInfoTestFactory.create()); + + assertThat(mappedSentInfo).isEqualTo(SentInfoTestFactory.asMap()); + } + } } diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..13e64879f85860b95b1e2a71154e56dced290343 --- /dev/null +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/administration/AdministrationServiceTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.bescheid.administration; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.cloud.endpoint.RefreshEndpoint; + +class AdministrationServiceTest { + + @InjectMocks + private AdministrationService service; + + @Mock + private AdministrationProperties properties; + @Mock + private RefreshEndpoint refreshEndpoint; + + @Nested + class GetNachrichtSignature { + + @Test + void shouldCallGetSignature() { + service.getNachrichtSignature(); + + verify(properties).getSignatur(); + } + + @Test + void shouldReturnSignature() { + var signature = "signature"; + when(properties.getSignatur()).thenReturn(Optional.of(signature)); + + var result = service.getNachrichtSignature(); + + assertThat(result).contains(signature); + } + } + + @Nested + class TestRefreshConfig { + + @Test + void shouldCallRefresh() { + service.refreshConfig(); + + verify(refreshEndpoint).refresh(); + } + } +} \ No newline at end of file diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java index 071cb7d7ee00b57de1a217ccef7e4522df18a4c9..eeca8c0c770782be6364a6f9ae130e440a1168d7 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/freemarker/TemplateHandlerITCase.java @@ -2,6 +2,9 @@ package de.ozgcloud.bescheid.common.freemarker; import static org.assertj.core.api.Assertions.*; +import java.util.Collections; +import java.util.Map; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -10,6 +13,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.common.command.grpc.CommandMapper; +import de.ozgcloud.bescheid.BescheidService; import de.ozgcloud.common.test.ITCase; @ITCase @@ -39,4 +43,32 @@ class TemplateHandlerITCase { .contains("Mit freundlichen Grüßen"); } } + + @DisplayName("Fill template") + @Nested + class TestFillTemplate { + + @Test + void shouldReturnFilledTemplate() { + var signatur = "ganz andere Signatur"; + var content = handler.fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE, + Map.of(BescheidService.KEY_TEMPLATE_SIGNATURE, signatur)); + + assertThat(content) + .contains("Sehr geehrte/r Antragsteller/in") + .contains("im Folgenden erhalten Sie Ihren Bescheid.") + .contains(signatur); + } + + @Test + void shouldReturnWithDefaultValue() { + var content = handler.fillTemplate(BescheidService.DEFAULT_NACHRICHT_TEMPLATE_FILE, Collections.emptyMap()); + + assertThat(content) + .contains("Sehr geehrte/r Antragsteller/in") + .contains("im Folgenden erhalten Sie Ihren Bescheid.") + .contains("Mit freundlichen Grüßen") + .contains("Ihre Verwaltung"); + } + } } diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java index 986f208f2f4ab75effbf1a4c42744624a2f8f202..25998524cc118900d7f705f2ff8c7268e2007b7b 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemMapperTest.java @@ -27,6 +27,8 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.Map; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -35,6 +37,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import de.ozgcloud.bescheid.SentInfoMapper; +import de.ozgcloud.command.CommandTestFactory; import de.ozgcloud.document.DocumentService; import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper; @@ -46,6 +50,8 @@ class AttachedItemMapperTest { @Mock private GrpcObjectMapper grpcObjectMapper; + @Mock + private SentInfoMapper sentInfoMapper; @Nested class TestMapFromVorgangAttachedItem { @@ -64,4 +70,39 @@ class AttachedItemMapperTest { assertThat(result).usingRecursiveComparison().isEqualTo(AttachedItemTestFactory.createDocument()); } } + + @Nested + class TestAsMap { + + @Test + void shouldSetVorgangId() { + var result = mapper.toMap(AttachedItemTestFactory.createBescheid()); + + assertThat(result).containsEntry(AttachedItem.PROPERTY_VORGANG_ID, CommandTestFactory.VORGANG_ID); + } + + @Test + void shouldSetClient() { + var result = mapper.toMap(AttachedItemTestFactory.createBescheid()); + + assertThat(result).containsEntry(AttachedItem.PROPERTY_CLIENT, AttachedItemTestFactory.CLIENT); + } + + @Test + void shouldSetItemName() { + var result = mapper.toMap(AttachedItemTestFactory.createBescheid()); + + assertThat(result).containsEntry(AttachedItem.PROPERTY_ITEM_NAME, AttachedItemService.BESCHEID_ITEM_NAME); + } + + @Test + void shouldSetItem() { + var item = Map.<String, Object>of("key", "value"); + var attachedItem = AttachedItemTestFactory.createBescheidBuilder().clearItem().item(item).build(); + + var result = mapper.toMap(attachedItem); + + assertThat(result).containsEntry(AttachedItem.PROPERTY_ITEM, item); + } + } } \ No newline at end of file diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java index 1c2e8557104da84c83ebc6d37565bc357c5461e9..aaa9b15a805e2c989b97f0d77577c2499ec18a56 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemServiceTest.java @@ -34,32 +34,23 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; -import com.thedeanda.lorem.LoremIpsum; - import de.ozgcloud.apilib.common.command.OzgCloudCommand; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.common.command.grpc.CommandMapper; import de.ozgcloud.apilib.common.datatypes.GenericId; import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId; import de.ozgcloud.bescheid.Bescheid; -import de.ozgcloud.bescheid.Bescheid.SendBy; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; +import de.ozgcloud.bescheid.BescheidMapper; import de.ozgcloud.bescheid.BescheidTestFactory; -import de.ozgcloud.bescheid.common.freemarker.TemplateHandler; import de.ozgcloud.bescheid.vorgang.VorgangId; import de.ozgcloud.bescheid.vorgang.VorgangTestFactory; import de.ozgcloud.command.Command; @@ -84,25 +75,24 @@ class AttachedItemServiceTest { @Mock private CommandMapper commandMapper; @Mock - - private TemplateHandler templateHandler; + private BescheidMapper bescheidMapper; @Nested class TestFindBescheidItem { @Test void shouldCallGetBescheidDraft() { - service.findBescheidItem(CommandTestFactory.VORGANG_ID); + service.findBescheidItem(VorgangTestFactory.ID); - verify(remoteService).findBescheidDraft(CommandTestFactory.VORGANG_ID); + verify(remoteService).findBescheidDraft(VorgangTestFactory.ID); } @Test void shouldReturnBescheidItem() { var expected = AttachedItemTestFactory.createBescheid(); - when(remoteService.findBescheidDraft(anyString())).thenReturn(Optional.of(expected)); + when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(expected)); - var actual = service.findBescheidItem(CommandTestFactory.VORGANG_ID); + var actual = service.findBescheidItem(VorgangTestFactory.ID); assertThat(actual).contains(expected); } @@ -112,286 +102,170 @@ class AttachedItemServiceTest { class TestCreateBescheidDraft { private static final String CREATED_ATTACHED_ITEM_ID = "attached-item-id"; + private static final Bescheid BESCHEID = BescheidTestFactory.create(); private final AttachedItem bescheidItem = AttachedItemTestFactory.createBescheid(); - private Command command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem()).build(); @Mock - private OzgCloudCommand ozgCloudCommand; - @Captor - private ArgumentCaptor<AttachedItem> bescheidItemCaptor; + private AttachedItem updatedBescheidItem; @Test - void shouldCallValidateData() { + void shouldCallGetBescheidDraft() { doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any()); - service.createBescheidDraft(command); + service.createBescheidDraft(BESCHEID); - verify(service).validateBescheidData(command.getBodyObject()); + verify(remoteService).findBescheidDraft(VorgangTestFactory.ID); } @Test - void shouldCallGetBescheidDraft() { - doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any()); + void shouldCallMergeBescheidDrafts() { + doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any()); + when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(bescheidItem)); - service.createBescheidDraft(command); + service.createBescheidDraft(BESCHEID); - verify(remoteService).findBescheidDraft(CommandTestFactory.VORGANG_ID); + verify(service).mergeBescheidDrafts(bescheidItem, BESCHEID); } @Test - void shouldCallUpdateBescheidDraft() { - doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any(), any()); - when(remoteService.findBescheidDraft(anyString())).thenReturn(Optional.of(bescheidItem)); + void shouldCallOverrideAttachedItem() { + doReturn(CREATED_ATTACHED_ITEM_ID).when(service).overrideAttachedItem(any()); + when(remoteService.findBescheidDraft(any(VorgangId.class))).thenReturn(Optional.of(bescheidItem)); + doReturn(updatedBescheidItem).when(service).mergeBescheidDrafts(any(), any()); - service.createBescheidDraft(command); + service.createBescheidDraft(BESCHEID); - verify(service).overrideAttachedItem(bescheidItemCaptor.capture(), eq(command)); - assertThat(bescheidItemCaptor.getValue()).isEqualTo(bescheidItem); + verify(service).overrideAttachedItem(updatedBescheidItem); } @Test void shouldCallCreateBescheidDraft() { doReturn(CREATED_ATTACHED_ITEM_ID).when(service).createAttachedItem(any()); - service.createBescheidDraft(command); + service.createBescheidDraft(BESCHEID); - verify(service).createBescheidDraft(command); + verify(service).createBescheidDraft(BESCHEID); } - @Nested - class TestCreateAttachedItem { - - @Mock - private OzgCloudCommand createAttachedItemCommand; - - @BeforeEach - void init() { - when(commandService.createAndWaitUntilDone(any())).thenReturn(ozgCloudCommand); - } - - @Test - void shouldCallBuildCreateAttachedItemCommand() { - createAttachedItem(); - - verify(service).buildCreateAttachedItemCommand(command); - } + } - @Test - void shouldCallCommandService() { - doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any()); + @Nested + class TestCreateAttachedItem { - createAttachedItem(); + private static final Bescheid BESCHEID = BescheidTestFactory.create(); + private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid(); - verify(commandService).createAndWaitUntilDone(createAttachedItemCommand); - } + @Mock + private OzgCloudCommand createAttachedItemCommand; + @Mock + private OzgCloudCommand finishedOzgCloudCommand; - private void createAttachedItem() { - service.createAttachedItem(command); - } + @BeforeEach + void init() { + when(commandService.createAndWaitUntilDone(any())).thenReturn(finishedOzgCloudCommand); + when(finishedOzgCloudCommand.getCreatedResource()).thenReturn(AttachedItemTestFactory.ID); + when(bescheidMapper.mapFromBescheid(any())).thenReturn(BESCHEID_ITEM); } - @Nested - class TestBuildCreateAttachedItemCommand { - - @Test - void shouldCallVorgangIdMapper() { - service.buildCreateAttachedItemCommand(command); - - verify(commandMapper).toOzgCloudVorgangId(CommandTestFactory.VORGANG_ID); - } - - @Test - void shouldSetVorgangId() { - var expectedVorgangId = OzgCloudVorgangId.from(CommandTestFactory.VORGANG_ID); - when(commandMapper.toOzgCloudVorgangId(any())).thenReturn(expectedVorgangId); - - var result = service.buildCreateAttachedItemCommand(command); - - assertThat(result.getVorgangId()).isEqualTo(expectedVorgangId); - } - - @Test - void shouldCallRelationIdMapper() { - var expectedRelationId = "relationId"; - command = CommandTestFactory.createBuilder().relationId(expectedRelationId).build(); - when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(command.getRelationId())); - - service.buildCreateAttachedItemCommand(command); - - verify(commandMapper).mapRelationId(expectedRelationId); - } - - @Test - void shouldSetRelationId() { - var expectedRelationId = "relationId"; - command = CommandTestFactory.createBuilder().relationId(expectedRelationId).build(); - when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(command.getRelationId())); - - var result = service.buildCreateAttachedItemCommand(command); - - assertThat(result.getRelationId()).hasToString(command.getRelationId()); - } - - @Test - void shouldCallBuildAttachedItemAsMap() { - var expectedItemMap = Map.<String, Object>of("key", "value"); - doReturn(expectedItemMap).when(service).buildCreateBescheidItemMap(any()); - - service.buildCreateAttachedItemCommand(command); - - verify(service).buildAttachedItemAsMap(command, expectedItemMap); - } - - @Test - void shouldSetBodyObject() { - var expectedBodyObject = Map.<String, Object>of("key", "value"); - doReturn(expectedBodyObject).when(service).buildAttachedItemAsMap(any(), any()); - - var result = service.buildCreateAttachedItemCommand(command); - - assertThat(result.getBodyObject()).containsAllEntriesOf(expectedBodyObject); - } - - @Test - void shouldSetOrder() { - var result = service.buildCreateAttachedItemCommand(command); + @Test + void shouldCallMapFromBescheid() { + createAttachedItem(); - assertThat(result.getOrder()).isEqualTo(AttachedItemService.CREATE_ATTACHED_ITEM_ORDER); - } + verify(bescheidMapper).mapFromBescheid(BESCHEID); } - @DisplayName("Build create bescheid itemMap") - @Nested - class TestBuildCreateBescheidItemMap { - - private static final String TEMPLATE_CONTENT_AS_STRING = LoremIpsum.getInstance().getParagraphs(5, 20); - - @DisplayName("on empty nachricht") - @Nested - class TestOnEmptyNachricht { - - @Test - void shouldHaveDefaultNachrichtSubjectInBodyIfMissing() { - var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); - - assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, AttachedItemService.DEFAULT_SUBJECT); - } - - @Test - void shouldCallTemplateHandler() { - when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING); - - service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); + @Test + void shouldCallBuildCreateAttachedItemCommand() { + doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any()); - verify(templateHandler).getRawTemplate(AttachedItemService.DEFAULT_TEMPLATE_FILE); - } + createAttachedItem(); - @Test - void shouldHaveDefaultNachrichtTextInBodyIfMissing() { - when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING); + verify(service).buildCreateAttachedItemCommand(BESCHEID_ITEM); + } - var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); + @Test + void shouldCallCommandService() { + doReturn(createAttachedItemCommand).when(service).buildCreateAttachedItemCommand(any()); - assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, TEMPLATE_CONTENT_AS_STRING); - } + createAttachedItem(); - private Command createCommandWithoutNachricht() { - var bescheidItemMap = AttachedItemTestFactory.createBescheidItem(); - bescheidItemMap.put(Bescheid.FIELD_NACHRICHT_SUBJECT, StringUtils.EMPTY); - bescheidItemMap.put(Bescheid.FIELD_NACHRICHT_TEXT, StringUtils.EMPTY); - return CommandTestFactory.createBuilder().bodyObject(bescheidItemMap).build(); - } - } + verify(commandService).createAndWaitUntilDone(createAttachedItemCommand); + } - @DisplayName("on non existing nachricht") - @Nested - class TestNonExistingNachricht { + @Test + void shouldReturnCreatedResource() { + var result = createAttachedItem(); - @Test - void shouldHaveDefaultNachrichtSubjectInBodyIfMissing() { - var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); + assertThat(result).isEqualTo(AttachedItemTestFactory.ID); + } - assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_SUBJECT, AttachedItemService.DEFAULT_SUBJECT); - } + private String createAttachedItem() { + return service.createAttachedItem(BESCHEID); + } + } - @Test - void shouldCallTemplateHandler() { - when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING); + @Nested + class TestBuildCreateAttachedItemCommand { - service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); + private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid(); - verify(templateHandler).getRawTemplate(AttachedItemService.DEFAULT_TEMPLATE_FILE); - } + @Test + void shouldCallVorgangIdMapper() { + service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - @Test - void shouldHaveDefaultNachrichtTextInBodyIfMissing() { - when(templateHandler.getRawTemplate(any())).thenReturn(TEMPLATE_CONTENT_AS_STRING); + verify(commandMapper).toOzgCloudVorgangId(CommandTestFactory.VORGANG_ID); + } - var bodyObject = service.buildCreateBescheidItemMap(createCommandWithoutNachricht()); + @Test + void shouldSetVorgangId() { + var expectedVorgangId = OzgCloudVorgangId.from(CommandTestFactory.VORGANG_ID); + when(commandMapper.toOzgCloudVorgangId(any())).thenReturn(expectedVorgangId); - assertThat(bodyObject).containsEntry(Bescheid.FIELD_NACHRICHT_TEXT, TEMPLATE_CONTENT_AS_STRING); - } + var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - private Command createCommandWithoutNachricht() { - var bescheidItemMap = AttachedItemTestFactory.createBescheidItem(); - bescheidItemMap.remove(Bescheid.FIELD_NACHRICHT_SUBJECT); - bescheidItemMap.remove(Bescheid.FIELD_NACHRICHT_TEXT); - return CommandTestFactory.createBuilder().bodyObject(bescheidItemMap).build(); - } - } + assertThat(result.getVorgangId()).isEqualTo(expectedVorgangId); } - @Nested - class TestValidateBescheidData { + @Test + void shouldCallRelationIdMapper() { + service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - @Test - void shouldValidate() { - assertDoesNotThrow(() -> service.validateBescheidData(command.getBodyObject())); - } + verify(commandMapper).mapRelationId(CommandTestFactory.VORGANG_ID); + } - @DisplayName(value = "should fail if bescheidAm is missing") - @Test - void shouldThrowExceptionByBescheidAm() { - var map = Map.<String, Object>of(Bescheid.FIELD_BEWILLIGT, true); + @Test + void shouldSetRelationId() { + var expectedRelationId = "relationId"; + when(commandMapper.mapRelationId(any())).thenReturn(GenericId.from(expectedRelationId)); - assertThrows(TechnicalException.class, () -> service.validateBescheidData(map)); - } + var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - @DisplayName(value = "should fail if bewilligt is missing") - @Test - void shouldThrowExceptionByBewilligt() { - var map = Map.<String, Object>of(Bescheid.FIELD_BESCHIEDEN_AM, "2021-01-01"); + assertThat(result.getRelationId()).hasToString(expectedRelationId); + } - assertThrows(TechnicalException.class, () -> service.validateBescheidData(map)); - } + @Test + void shouldSetOrder() { + var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - @Test - void shouldValidateSendBy() { - var bodyObject = Map.<String, Object>of(Bescheid.FIELD_SEND_BY, SendBy.MANUAL.name()); - doNothing().when(service).validateBescheidField(any(), any()); + assertThat(result.getOrder()).isEqualTo(AttachedItemService.CREATE_ATTACHED_ITEM_ORDER); + } - service.validateBescheidData(bodyObject); + @Test + void shouldCallAttachedItemMapper() { + service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - verify(service).validateSendBy(SendBy.MANUAL.name()); - } + verify(mapper).toMap(BESCHEID_ITEM); + } - @DisplayName("validate sendBy") - @Nested - class TestValidateSendBy { + @Test + void shouldSetBodyObject() { + var itemMap = Map.<String, Object>of("key", "value"); + when(mapper.toMap(any())).thenReturn(itemMap); - @ValueSource(strings = { "not-exist", "" }) - @ParameterizedTest - void shouldThrowExceptionOnNonExistingSendByValue(String sendBy) { - assertThrows(TechnicalException.class, () -> service.validateSendBy(sendBy)); - } + var result = service.buildCreateAttachedItemCommand(BESCHEID_ITEM); - @EnumSource(names = { "NACHRICHT", "MANUAL" }) - @ParameterizedTest - void shouldNotThrowAnyExceptionOnExistingSendByValue(SendBy sendBy) { - assertDoesNotThrow(() -> service.validateSendBy(sendBy.name())); - } - } + assertThat(result.getBodyObject()).containsAllEntriesOf(itemMap); } } @@ -633,41 +507,22 @@ class AttachedItemServiceTest { class TestOverrideAttachedItem { private static final String CREATED_RESOURCE = "created-resource"; + @Mock private OzgCloudCommand updateItemCommand; - private final Command command = CommandTestFactory.createBuilder().bodyObject(AttachedItemTestFactory.createBescheidItem()).build(); - @BeforeEach void init() { when(commandService.createAndWaitUntilDone(any())).thenReturn(updateItemCommand); when(updateItemCommand.getCreatedResource()).thenReturn(CREATED_RESOURCE); } - @Test - void shouldCallBuildItemMapWithAllBescheidFields() { - service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command); - - verify(service).buildItemMapWithAllBescheidFields(command); - } - - @Test - void shouldCallBuildAttachedItemAsMap() { - var itemMap = Map.<String, Object>of("key", "value"); - doReturn(itemMap).when(service).buildItemMapWithAllBescheidFields(any()); - - service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command); - - verify(service).buildAttachedItemAsMap(command, itemMap); - } - @Test void shouldCallBuildUpdateAttachedItemCommand() { var bodyObject = Map.<String, Object>of("key", "value"); - doReturn(bodyObject).when(service).buildAttachedItemAsMap(any(), any()); - var bescheidItem = AttachedItemTestFactory.createBescheid(); + var bescheidItem = AttachedItemTestFactory.createBescheidBuilder().clearItem().item(bodyObject).build(); - service.overrideAttachedItem(bescheidItem, command); + service.overrideAttachedItem(bescheidItem); verify(service).buildPatchAttachedItemCommand(bescheidItem, bodyObject); } @@ -676,14 +531,14 @@ class AttachedItemServiceTest { void shouldCallCommandService() { doReturn(updateItemCommand).when(service).buildPatchAttachedItemCommand(any(), any()); - service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command); + service.overrideAttachedItem(AttachedItemTestFactory.createBescheid()); verify(commandService).createAndWaitUntilDone(updateItemCommand); } @Test void shouldReturnCreatedResource() { - var result = service.overrideAttachedItem(AttachedItemTestFactory.createBescheid(), command); + var result = service.overrideAttachedItem(AttachedItemTestFactory.createBescheid()); assertThat(result).isEqualTo(CREATED_RESOURCE); } diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java index 6f95bc5930e980d4818394d9cf83cafcae4ab65f..9b3ac12ebfa3c1f1385bedaab9d8383c25c750a8 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/AttachedItemTestFactory.java @@ -33,6 +33,7 @@ import java.util.Map; import de.ozgcloud.bescheid.Bescheid; import de.ozgcloud.bescheid.BescheidTestFactory; import de.ozgcloud.bescheid.SentInfo; +import de.ozgcloud.bescheid.SentInfoTestFactory; import de.ozgcloud.bescheid.common.user.UserProfileTestFactory; import de.ozgcloud.bescheid.vorgang.VorgangTestFactory; import de.ozgcloud.command.CommandTestFactory; @@ -47,6 +48,7 @@ public class AttachedItemTestFactory { public static final String ID = "bescheid-item-id"; public static final long VERSION = 10L; public static final String CLIENT = "client"; + public static final Map<String, Object> SENT_INFO = SentInfoTestFactory.asMap(); public static AttachedItem create() { return createBuilder().build(); @@ -64,7 +66,6 @@ public class AttachedItemTestFactory { public static Map<String, Object> createBescheidItem() { var item = new HashMap<String, Object>(); - item.put(AttachedItem.PROPERTY_VORGANG_ID, VorgangTestFactory.ID); item.put(Bescheid.FIELD_STATUS, BescheidTestFactory.STATUS.name()); item.put(Bescheid.FIELD_BESCHIEDEN_AM, BescheidTestFactory.BESCHIEDEN_AM_STR); item.put(Bescheid.FIELD_BEWILLIGT, BescheidTestFactory.BEWILLIGT); @@ -73,9 +74,8 @@ public class AttachedItemTestFactory { item.put(Bescheid.FIELD_SEND_BY, BescheidTestFactory.SEND_BY.name()); item.put(Bescheid.FIELD_NACHRICHT_TEXT, BescheidTestFactory.NACHRICHT_TEXT); item.put(Bescheid.FIELD_NACHRICHT_SUBJECT, BescheidTestFactory.NACHRICHT_SUBJECT); - item.put(Bescheid.FIELD_SENT_INFO, Map.of( - SentInfo.FIELD_SENT_BY, SENT_BY, - SentInfo.FIELD_SENT_AT, SENT_AT_STR)); + item.put(Bescheid.FIELD_CREATED_BY, UserProfileTestFactory.ID_STR); + item.put(Bescheid.FIELD_SENT_INFO, SENT_INFO); return item; } diff --git a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java index 7e1a5140b048e87f07aa2c005f6595234a5ea669..104ace168b6b7486c39adf39df9657a825b8d577 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/common/attached_item/VorgangAttachedItemRemoteServiceTest.java @@ -58,8 +58,6 @@ import io.grpc.ClientInterceptor; class VorgangAttachedItemRemoteServiceTest { - private static final String VORGANG_ID = "vorgang-id"; - @Spy @InjectMocks private VorgangAttachedItemRemoteService service; @@ -78,8 +76,7 @@ class VorgangAttachedItemRemoteServiceTest { private GrpcFindVorgangAttachedItemRequest request; @Nested - @DisplayName("by vorgangId") - class TestGetByVorgangId { + class TestFindByVorgangId { private static final AttachedItem BESCHEID_ITEM = AttachedItemTestFactory.createBescheid(); @@ -91,21 +88,21 @@ class VorgangAttachedItemRemoteServiceTest { @Test void shouldCallCreateFindRequestBuilder() { - service.findBescheidDraft(VORGANG_ID); + service.findBescheidDraft(VorgangTestFactory.ID); - verify(service).buildFindRequest(VORGANG_ID); + verify(service).buildFindRequest(VorgangTestFactory.ID_STR); } @Test void shouldCallGetBescheidDraft() { - service.findBescheidDraft(VORGANG_ID); + service.findBescheidDraft(VorgangTestFactory.ID); verify(service).findBescheidDraft(request); } @Test void shouldReturnResult() { - var result = service.findBescheidDraft(VORGANG_ID); + var result = service.findBescheidDraft(VorgangTestFactory.ID); assertThat(result).contains(BESCHEID_ITEM); } diff --git a/bescheid-manager/src/test/resources/application-itcase.yml b/bescheid-manager/src/test/resources/application-itcase.yml index 8157581c058ea205d2708730f584327d24121e24..72e5c1342fce4a554381a3cc7d09cd4a09af48f7 100644 --- a/bescheid-manager/src/test/resources/application-itcase.yml +++ b/bescheid-manager/src/test/resources/application-itcase.yml @@ -6,6 +6,9 @@ logging: config: classpath:log4j2-local.xml ozgcloud: + admin: + sync: + enabled: false bescheid: smart-documents: url: https://demo-de.smartdocuments.com/wsxmldeposit/deposit/unattended @@ -14,3 +17,7 @@ ozgcloud: password: MGM templateGroup: Kiel template: Halteverbot +spring: + cloud: + config: + enabled: false diff --git a/pom.xml b/pom.xml index 243bcdbe0d07aaefaf96bce4c9dab285b63c5f74..f27c49331eda7a4c8073d28ce417fb5b8ad22162 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager</artifactId> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <name>OZG-Cloud Vorgang Manager</name> <packaging>pom</packaging> diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl index 1317f415cf1502d9f897172dfcfcfdf2b1c3a2ef..d3319d470a404cdc82ea1f46d66de742c7b4662b 100644 --- a/src/main/helm/templates/_helpers.tpl +++ b/src/main/helm/templates/_helpers.tpl @@ -62,7 +62,7 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{- end -}} {{- define "app.grpc_client_user-manager_address" -}} -{{ printf "%s.%s:9000" .Values.usermanagerName .Release.Namespace }} +{{ printf "dns:///%s.%s:9000" .Values.usermanagerName .Release.Namespace }} {{- end -}} {{- define "app.ozgcloud_migration_user-manager_address" -}} @@ -70,7 +70,11 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{- end -}} {{- define "app.ozgcloud_vorgangmanager_address" -}} -{{ printf "%s.%s:9090" .Values.vorgangmanagerName .Release.Namespace }} +{{ printf "dns:///%s.%s:9090" .Values.vorgangmanagerName .Release.Namespace }} +{{- end -}} + +{{- define "app.ozgcloud_administration_address" -}} +{{ printf "http://%s.%s:8080" .Values.administrationName .Release.Namespace }} {{- end -}} {{- define "app.databaseSecretName" -}} diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml index 329fb56867a302145ce93e6d1d11e8384d795713..ba379a93e17e623cf46bbc3f6e05aa8750eacff8 100644 --- a/src/main/helm/templates/deployment.yaml +++ b/src/main/helm/templates/deployment.yaml @@ -63,6 +63,8 @@ spec: value: "/bindings" - name: spring_profiles_active value: {{ include "app.envSpringProfiles" . }} + - name: ozgcloud_application_address + value: {{ include "app.ozgcloud_vorgangmanager_address" . }} - name: ozgcloud_nachrichten-manager_address value: {{ include "app.ozgcloud_vorgangmanager_address" . }} {{- if .Values.env.ozgcloudAktenzeichen.enabled }} @@ -154,7 +156,11 @@ spec: - name: ozgcloud_user-manager_url value: {{ include "app.ozgcloud_migration_user-manager_address" . }} - name: ozgcloud_zufi-manager_address - value: {{ .Values.zufiManager.address }} + value: {{ (.Values.zufiManager).address }} + - name: grpc_client_zufi-manager_address + value: {{ (.Values.zufiManager).address }} + - name: grpc_client_zufi-manager_negotiationType + value: {{ (.Values.zufiManager).grpcClientNegotiationType }} {{- if not (.Values.database).useExternal }} - name: spring_data_mongodb_uri valueFrom: @@ -203,8 +209,9 @@ spec: key: login optional: false {{- end }} - + - name: ozgcloud_administration_address + value: {{ include "app.ozgcloud_administration_address" . }} {{- if ((.Values.ozgcloud).antragraum).enabled }} @@ -229,6 +236,10 @@ spec: - name: ozgcloud_feature_bescheid_kielHackathonRoute value: {{ quote (((.Values.ozgcloud).feature).bescheid).kielHackathonRoute }} {{- end }} + {{- if (((.Values.ozgcloud).notification).eingangsbestaetigung).replyAllowed }} + - name: ozgcloud_notification_eingangsbestaetigung_replyAllowed + value: {{ quote (((.Values.ozgcloud).notification).eingangsbestaetigung).replyAllowed }} + {{- end }} {{- if (.Values.ozgcloud).processors}} {{- range $processor_index, $processor := (.Values.ozgcloud).processors }} diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml index e3e934bcf2512f810ac66837eeb74669a843aa7e..e5b2c533cc56546800a78f562d1d17fefe4403f9 100644 --- a/src/main/helm/templates/network_policy.yaml +++ b/src/main/helm/templates/network_policy.yaml @@ -127,7 +127,7 @@ spec: - to: - namespaceSelector: matchLabels: - kubernetes.io/metadata.name: {{((.Values.ozgcloud).antragraum).namespace | default "antragraum"}} + kubernetes.io/metadata.name: {{((.Values.ozgcloud).infoManager).namespace | default "info-manager"}} podSelector: matchLabels: component: info-manager diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml index 30fe6d16e7959cfd36ad808debca0000f7ea0419..6a380e033dcf8986792b1e8b8ca9f92a4ab81a0c 100644 --- a/src/main/helm/values.yaml +++ b/src/main/helm/values.yaml @@ -57,8 +57,10 @@ vorgangmanagerName: vorgang-manager usermanagerName: user-manager +administrationName: administration + zufiManager: - address: dns://zufi-manager.zufi:9090 + address: dns:///zufi-server.zufi:9090 elasticsearch: certificateSecretName: elasticsearch-certificate diff --git a/src/test/helm/deployment_administration_address_env_test.yaml b/src/test/helm/deployment_administration_address_env_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b2bf2db3eed725512711a2f11cf87727c94e78bd --- /dev/null +++ b/src/test/helm/deployment_administration_address_env_test.yaml @@ -0,0 +1,44 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment administration address env +release: + name: vorgang-manager + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + ozgcloud: + environment: dev + imagePullSecret: image-pull-secret +tests: + - it: should have set administration server address + set: + administrationName: custom_admin_name + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_administration_address + value: http://custom_admin_name.by-helm-test:8080 diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml index 573afcbdd936a8c2721f1706297fa5fca68f5d16..4d71e36a71fcb5da19e5c6b55afd44ad528bcbd8 100644 --- a/src/test/helm/deployment_env_test.yaml +++ b/src/test/helm/deployment_env_test.yaml @@ -140,4 +140,16 @@ tests: path: spec.template.spec.containers[0].env content: name: ozgcloud_processors_1_forms_0_formEngineName - value: FormSolutions \ No newline at end of file + value: FormSolutions + - it: should have notification properties + set: + ozgcloud: + notification: + eingangsbestaetigung: + replyAllowed: true + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_notification_eingangsbestaetigung_replyAllowed + value: "true" \ No newline at end of file diff --git a/src/test/helm/deployment_grpc_user_manager_address_test.yaml b/src/test/helm/deployment_grpc_user_manager_address_test.yaml index 1e31f050c93476fd389121baed48304cd9b58747..a26e7cb0ceed7622dd361937c32f5074b6e60567 100644 --- a/src/test/helm/deployment_grpc_user_manager_address_test.yaml +++ b/src/test/helm/deployment_grpc_user_manager_address_test.yaml @@ -39,7 +39,7 @@ tests: path: spec.template.spec.containers[0].env content: name: grpc_client_user-manager_address - value: user-manager.sh-helm-test:9000 + value: dns:///user-manager.sh-helm-test:9000 - it: should contain default user-manager grpc negotiationType tls asserts: - contains: diff --git a/src/test/helm/deployment_nachrichten_manager_address_test.yaml b/src/test/helm/deployment_nachrichten_manager_address_test.yaml index b91b3cc5fe1d814a525fc99464add26e746aa617..67887800a93d5637f079a8aaed0ffa08e588a8af 100644 --- a/src/test/helm/deployment_nachrichten_manager_address_test.yaml +++ b/src/test/helm/deployment_nachrichten_manager_address_test.yaml @@ -39,4 +39,4 @@ tests: path: spec.template.spec.containers[0].env content: name: ozgcloud_nachrichten-manager_address - value: vorgang-manager.sh-helm-test:9090 + value: dns:///vorgang-manager.sh-helm-test:9090 diff --git a/src/test/helm/deployment_vorgang_manager_env_test.yaml b/src/test/helm/deployment_vorgang_manager_env_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4626fa9296378d85086ac3e15513241aa785e23d --- /dev/null +++ b/src/test/helm/deployment_vorgang_manager_env_test.yaml @@ -0,0 +1,42 @@ +# +# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment vorgang manager environment +release: + name: vorgang-manager + namespace: by-helm-test +templates: + - templates/deployment.yaml +set: + ozgcloud: + environment: dev + imagePullSecret: test-image-pull-secret +tests: + - it: check if application address is set + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_application_address + value: dns:///vorgang-manager.by-helm-test:9090 \ No newline at end of file diff --git a/src/test/helm/deployment_zufimanager_address_env_test.yaml b/src/test/helm/deployment_zufimanager_address_env_test.yaml index 8a16fc9df3dd161711d0a6803f2383106222cba8..d73c2e5b39e192cfe0f30908ccaa4c2d5d22fe1c 100644 --- a/src/test/helm/deployment_zufimanager_address_env_test.yaml +++ b/src/test/helm/deployment_zufimanager_address_env_test.yaml @@ -22,10 +22,10 @@ # unter der Lizenz sind dem Lizenztext zu entnehmen. # -suite: test environments +suite: deployment zufi-manager address environment release: name: vorgang-manager - namespace: sh-helm-test + namespace: by-helm-test templates: - templates/deployment.yaml set: @@ -33,10 +33,51 @@ set: environment: dev imagePullSecret: test-image-pull-secret tests: - - it: check if zufi-manager address is correct + - it: check default zufi-manager address asserts: - contains: path: spec.template.spec.containers[0].env content: name: ozgcloud_zufi-manager_address - value: dns://zufi-manager.zufi:9090 + value: dns:///zufi-server.zufi:9090 + + - it: should set custom zufi-manager address + set: + zufiManager: + address: dns://other.zufi:9090 + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_zufi-manager_address + value: dns://other.zufi:9090 + + - it: check default zufi-manager grpc client address + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: grpc_client_zufi-manager_address + value: dns:///zufi-server.zufi:9090 + + - it: should set custom zufi-manager grpc client address + set: + zufiManager: + address: dns://other.zufi:9090 + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: grpc_client_zufi-manager_address + value: dns://other.zufi:9090 + + - it: check if zufi-manager negotiationType is set + set: + zufiManager: + grpcClientNegotiationType: NOT_DEFAULT + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: grpc_client_zufi-manager_negotiationType + value: NOT_DEFAULT diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml index b7e9d4650328f3c91c39415893510530a27162b6..8c72186be1545a2ce6c85d8df72f4d8d1e73838a 100644 --- a/src/test/helm/network_policy_test.yaml +++ b/src/test/helm/network_policy_test.yaml @@ -389,7 +389,7 @@ tests: to: - namespaceSelector: matchLabels: - kubernetes.io/metadata.name: antragraum + kubernetes.io/metadata.name: info-manager podSelector: matchLabels: component: info-manager @@ -401,7 +401,8 @@ tests: ozgcloud: antragraum: enabled: true - namespace: antragraum2 + infoManager: + namespace: info-manager2 asserts: - contains: path: spec.egress @@ -409,7 +410,7 @@ tests: to: - namespaceSelector: matchLabels: - kubernetes.io/metadata.name: antragraum2 + kubernetes.io/metadata.name: info-manager2 podSelector: matchLabels: component: info-manager @@ -428,7 +429,7 @@ tests: to: - namespaceSelector: matchLabels: - kubernetes.io/metadata.name: antragraum02 + kubernetes.io/metadata.name: info-manager podSelector: matchLabels: component: info-manager diff --git a/vorgang-manager-base/pom.xml b/vorgang-manager-base/pom.xml index 3923414abfe3ef269b65c880d6351c7e71e2aea9..3330f384b382b6d0c1d4570dc8503d1ba745363c 100644 --- a/vorgang-manager-base/pom.xml +++ b/vorgang-manager-base/pom.xml @@ -12,7 +12,7 @@ <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-base</artifactId> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <name>OZG-Cloud Vorgang Manager Base</name> diff --git a/vorgang-manager-command/pom.xml b/vorgang-manager-command/pom.xml index fc5073e4fc4aea732ef106c2cd2e49ea2c55e3d7..90c93b9f28cbac4fc1a4b84c72ee49b9e56c99b1 100644 --- a/vorgang-manager-command/pom.xml +++ b/vorgang-manager-command/pom.xml @@ -10,7 +10,7 @@ <groupId>de.ozgcloud.command</groupId> <artifactId>command-manager</artifactId> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <name>OZG-Cloud Command Manager</name> <properties> diff --git a/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..3ed40fd7a5f9a371792f4971920a78e183211f53 --- /dev/null +++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/PostfachNachrichtReceivedEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.command; + +import java.io.Serial; + +import org.springframework.context.ApplicationEvent; + +import lombok.Getter; + +@Getter +public class PostfachNachrichtReceivedEvent extends ApplicationEvent { + + @Serial + private static final long serialVersionUID = 1L; + + private final String nachrichtId; + + public PostfachNachrichtReceivedEvent(Command command, String nachrichtId) { + super(command); + this.nachrichtId = nachrichtId; + } + + @Override + public Command getSource() { + return (Command) super.getSource(); + } + +} diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java similarity index 74% rename from vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java index 7847c2522279ff910b9d0f0aec2c3e3d79eaa1b6..7515a5e69b0002b4c8ef91bcd0eb7c653ca6499d 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java +++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAssignedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,20 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.vorgang.vorgang; +package de.ozgcloud.command; -import de.ozgcloud.command.Command; -import de.ozgcloud.command.CommandExecutedEvent; -import lombok.Getter; - -@Getter public class VorgangAssignedEvent extends CommandExecutedEvent { - private transient Command command; private static final long serialVersionUID = 1L; - protected VorgangAssignedEvent(Command command) { - super(command.getId()); - this.command = command; + public VorgangAssignedEvent(Command command) { + super(command); } } diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java similarity index 78% rename from vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java index baa5b5817df7e9130c043f8344d455e2f32fccb4..6ffbefae323b3cf0a6b9d3342a03a1ca6488eb00 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java +++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangAttachedItemCreatedEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung @@ -21,16 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -package de.ozgcloud.vorgang.attached_item; - -import de.ozgcloud.command.CommandExecutedEvent; +package de.ozgcloud.command; public class VorgangAttachedItemCreatedEvent extends CommandExecutedEvent { private static final long serialVersionUID = 1L; - protected VorgangAttachedItemCreatedEvent(String commandId, String createdResource) { - super(commandId, createdResource); + public VorgangAttachedItemCreatedEvent(Command command, String createdResource) { + super(command, createdResource); } - } diff --git a/vorgang-manager-interface/pom.xml b/vorgang-manager-interface/pom.xml index 10ab7eba451eab9ea09c595cb14a125eb255b6e4..2057978d5dba01316f9982e85efd173257f477b2 100644 --- a/vorgang-manager-interface/pom.xml +++ b/vorgang-manager-interface/pom.xml @@ -36,7 +36,7 @@ <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-interface</artifactId> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <name>OZG-Cloud Vorgang Manager gRPC Interface</name> <description>Interface (gRPC) for Vorgang Manager Server</description> diff --git a/vorgang-manager-server/pom.xml b/vorgang-manager-server/pom.xml index ed8f383c0cc12d942e6c55167227b69a55abfe9d..93cea504a132e6aa3f6a317ebcc93d6723ac7f5a 100644 --- a/vorgang-manager-server/pom.xml +++ b/vorgang-manager-server/pom.xml @@ -38,7 +38,7 @@ <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-server</artifactId> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <name>OZG-Cloud Vorgang Manager Server</name> <description>Server Implementierung des VorgangManagers</description> @@ -50,15 +50,15 @@ <spring-boot.build-image.imageName>docker.ozg-sh.de/vorgang-manager:build-latest</spring-boot.build-image.imageName> <ozgcloud.license.version>1.3.0</ozgcloud.license.version> - <zufi-manager-interface.version>1.0.0</zufi-manager-interface.version> + <zufi-manager-interface.version>1.4.0-SNAPSHOT</zufi-manager-interface.version> <user-manager-interface.version>2.1.0</user-manager-interface.version> <bescheid-manager.version>1.18.0-SNAPSHOT</bescheid-manager.version> <processor-manager.version>0.4.1</processor-manager.version> - <nachrichten-manager.version>2.11.0</nachrichten-manager.version> + <nachrichten-manager.version>2.12.0-SNAPSHOT</nachrichten-manager.version> <ozgcloud-starter.version>0.12.0</ozgcloud-starter.version> - <notification-manager.version>2.10.0</notification-manager.version> - <collaboration-manager.version>0.3.0-PR-5-SNAPSHOT</collaboration-manager.version> + <notification-manager.version>2.11.0-SNAPSHOT</notification-manager.version> + <collaboration-manager.version>0.3.0-SNAPSHOT</collaboration-manager.version> <zip.version>2.11.1</zip.version> <jsoup.version>1.15.3</jsoup.version> diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..a17f844828bc8983610fab48bced19bbe373363d --- /dev/null +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerProperties.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang; + +import jakarta.validation.constraints.NotBlank; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Validated +@Configuration +@ConfigurationProperties(prefix = "ozgcloud.application") +public class VorgangManagerProperties { + + @NotBlank + private String address; + +} diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java index cf991372cac1e53ef918bf360128a4939f9ccb6c..cc8905ccdc227a1c78533d54c0b26dea0fa71022 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java @@ -75,7 +75,7 @@ class VorgangAttachedItemEventListener { validateCreateCommand(command); var item = mapper.fill(command.getBodyObject()).toBuilder().id(null).version(0).build(); - service.create(command.getId(), item); + service.create(command, item); } void validateCreateCommand(Command command) { diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java index 1b5a7e177d280d25fef6e40d3eb61ee2b180fa38..ef0d12da9202197c9c16570fe7005f8052f7a178 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; import jakarta.validation.Valid; +import org.apache.commons.collections.MapUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -38,6 +39,9 @@ import org.springframework.validation.annotation.Validated; import de.ozgcloud.command.Command; import de.ozgcloud.command.CommandRevokeFailedEvent; import de.ozgcloud.command.CommandRevokedEvent; +import de.ozgcloud.command.VorgangAttachedItemCreatedEvent; +import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import de.ozgcloud.vorgang.command.PersistedCommand; import de.ozgcloud.vorgang.common.errorhandling.NotFoundException; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -54,10 +58,10 @@ public class VorgangAttachedItemService { private final VorgangAttachedItemRepository repository; private final ApplicationEventPublisher publisher; - public VorgangAttachedItem create(@NonNull String commandId, @Valid VorgangAttachedItem item) { + public VorgangAttachedItem create(@NonNull Command command, @Valid VorgangAttachedItem item) { var saved = repository.save(prepareForCreation(item)); - publisher.publishEvent(new VorgangAttachedItemCreatedEvent(commandId, saved.getId())); + publisher.publishEvent(new VorgangAttachedItemCreatedEvent(buildExecutedCommand(command, saved), saved.getId())); return saved; } @@ -71,11 +75,34 @@ public class VorgangAttachedItemService { } private Map<String, Object> removeId(@NonNull Map<String, Object> item) { - var map = new HashMap<String, Object>(item); + var map = new HashMap<>(item); map.remove(VorgangAttachedItem.FIELDNAME_ID); return Collections.unmodifiableMap(map); } + Command buildExecutedCommand(Command command, VorgangAttachedItem item) { + return PersistedCommand.builder() + .id(command.getId()) + .vorgangId(command.getVorgangId()) + .relationId(command.getRelationId()) + .relationVersion(command.getRelationVersion()) + .order(command.getOrder()) + .createdAt(command.getCreatedAt()) + .createdBy(command.getCreatedBy()) + .status(command.getStatus()) + .createdResource(item.getId()) + .bodyObject(buildBodyObject(item)) + .build(); + } + + Map<String, Object> buildBodyObject(VorgangAttachedItem item) { + var map = new HashMap<String, Object>(); + map.put(VorgangAttachedItem.FIELDNAME_ITEM_NAME, item.getItemName()); + Optional.ofNullable(MapUtils.getString(item.getItem(), PostfachNachricht.FIELD_DIRECTION)) + .ifPresent(direction -> map.put(PostfachNachricht.FIELD_DIRECTION, direction)); + return Collections.unmodifiableMap(map); + } + public void update(String commandId, VorgangAttachedItem item) { doUpdate(item.getId(), item.getVersion(), item.getItem()); diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java index 9a6ebc1d3d61375724355556991d5af587a2d09b..5a4671ad54436d0e9657a7c62b323dbcaa25d0df 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java @@ -31,8 +31,10 @@ import de.ozgcloud.command.CommandExecutedEvent; import de.ozgcloud.command.CommandFailedEvent; import de.ozgcloud.command.CommandRevokeFailedEvent; import de.ozgcloud.command.CommandRevokedEvent; +import lombok.extern.log4j.Log4j2; @Component +@Log4j2 public class CommandEventListener { @Autowired diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java new file mode 100644 index 0000000000000000000000000000000000000000..2b89cdfa416e725bbe8f5539579a05dfe3adab70 --- /dev/null +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachType.java @@ -0,0 +1,50 @@ +package de.ozgcloud.vorgang.common.migration; + +import java.util.Set; + +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "2024-09-14 15:00:00 OZG-6641", order = "M012", author = "ebardin", runAlways = true) +public class M012_UpdateBayernIdPostfachType { // NOSONAR + + static final String KEY_HEADER_SERVICE_KONTO_TYPE = "header.serviceKonto.type"; + static final String KEY_EINGANG_SERVICE_KONTO_TYPE = "eingangs." + KEY_HEADER_SERVICE_KONTO_TYPE; + static final Set<String> POSSIBLE_BAYERN_ID_TYPE = Set.of("BayernId", "BayernID"); + static final String BAYERN_ID_TYPE_NEW = "BAYERN_ID"; + private static final String VORGANG_COLLECTION = "vorgang"; + + @Execution + public void doMigration(MongoTemplate template) { + updateVorgangHeader(template); + updateEingangsHeader(template); + } + + private void updateVorgangHeader(MongoTemplate template) { + template.updateMulti(createFilterQuery(KEY_HEADER_SERVICE_KONTO_TYPE), createUpdate(KEY_HEADER_SERVICE_KONTO_TYPE), VORGANG_COLLECTION); + } + + private void updateEingangsHeader(MongoTemplate template) { + template.updateMulti(createFilterQuery(KEY_EINGANG_SERVICE_KONTO_TYPE), createUpdate("eingangs.$[]." + KEY_HEADER_SERVICE_KONTO_TYPE), + VORGANG_COLLECTION); + } + + private Query createFilterQuery(String key) { + return new Query(Criteria.where(key).in(POSSIBLE_BAYERN_ID_TYPE)); + } + + private Update createUpdate(String key) { + return new Update().set(key, BAYERN_ID_TYPE_NEW); + } + + @RollbackExecution + public void rollback() { + // kein rollback implementiert + } +} \ No newline at end of file diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java index c844c3f36cc550abab150590103780d6b28bdc84..3e15c4de420cec0b23cf9338e795816acd9fc705 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java @@ -24,8 +24,6 @@ package de.ozgcloud.vorgang.common.search; import java.text.MessageFormat; -import java.util.Collections; -import java.util.HashMap; import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -34,11 +32,11 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import de.ozgcloud.command.Command; +import de.ozgcloud.command.VorgangAssignedEvent; import de.ozgcloud.command.VorgangCreatedEvent; import de.ozgcloud.vorgang.command.CommandService; import de.ozgcloud.vorgang.status.StatusChangedEvent; import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent; -import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent; import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent; import de.ozgcloud.vorgang.vorgang.VorgangService; import lombok.extern.log4j.Log4j2; diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java index b7e0a3b89913ecac2c47e1a9cc9e20649743b46a..8a32bc95d96fa69088182ce7e9627059d3609767 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java @@ -2,11 +2,15 @@ package de.ozgcloud.vorgang.common.userconfig; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor public class UserConfigService { - @Autowired - private UserConfigRemoteService userConfigRemoteService; + + private final UserConfigRemoteService userConfigRemoteService; public List<String> getSupportedOrganisationsEinheiten() { return userConfigRemoteService.getSupportedOrganisationsEinheiten(); diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java index 171439dbfbd3f234b2b5801b322cb963379f7972..778f33bf0339e0bf0e0d08b9a2c5806498a37e33 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java @@ -25,29 +25,34 @@ package de.ozgcloud.vorgang.registry; import java.util.concurrent.TimeUnit; -import org.springframework.beans.factory.annotation.Autowired; +import jakarta.annotation.PostConstruct; + import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import de.ozgcloud.vorgang.common.userconfig.UserConfigService; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; -@Profile("!itcase") @Component -@ConditionalOnProperty(prefix = "ozgcloud.vorgang-manager", name = { "address" }) +@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" }) @Log4j2 +@RequiredArgsConstructor class RegistryScheduler { - @Autowired - private RegistryService registryService; - @Autowired - private UserConfigService userConfigService; + private final RegistryService registryService; + + private final UserConfigService userConfigService; + + @PostConstruct + void logInitialization() { + LOG.info("Starting ZuFi registry scheduler"); + } - @Scheduled(fixedDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.fixedDelay:5}", // - initialDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.initialDelay:5}", // + @Scheduled(fixedDelayString = "${ozgcloud.registry.scheduler.fixedDelayMinutes}", + initialDelayString = "${ozgcloud.registry.scheduler.initialDelayMinutes}", timeUnit = TimeUnit.MINUTES) @SchedulerLock(name = "RegistryScheduler") void register() { diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java index e2e8475bf30d833e339a9f688503611b2569ff98..028946325fe06593c20f604a94abc1679a2a8d66 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java @@ -1,43 +1,28 @@ package de.ozgcloud.vorgang.registry; import java.util.List; -import java.util.Optional; -import org.apache.commons.collections4.CollectionUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import de.ozgcloud.vorgang.VorgangManagerProperties; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @Service @Log4j2 +@RequiredArgsConstructor +@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" }) class RegistryService { - @Value(value = "${ozgcloud.vorgang-manager.address:#{null}}") - private Optional<String> vorgangManagerAddress; - @Autowired - private ZufiRemoteService zufiRemoteService; + private final VorgangManagerProperties vorgangManagerProperties; + private final ZufiRemoteService zufiRemoteService; public void registerVorgangManager(List<String> supportedOrganisationsEinheiten) { - try { - register(supportedOrganisationsEinheiten); - } catch (Exception e) { - LOG.error("Error registering this VorgangsManager.", e); + if (supportedOrganisationsEinheiten.isEmpty()) { + LOG.warn("Missing organisationseinheitenIds. Skipping registration."); + return; } - } - - private void register(List<String> supportedOrganisationsEinheiten) { - if (CollectionUtils.isNotEmpty(supportedOrganisationsEinheiten)) { - registerAddress(supportedOrganisationsEinheiten, vorgangManagerAddress); - } else { - LOG.warn("No OrganistationsEinheitenIds provided. Not registering this VorgangsManager"); - } - } - - void registerAddress(List<String> supportedOrganisationsEinheiten, Optional<String> vorgangManagerAddress) { - vorgangManagerAddress.ifPresentOrElse(address -> { - zufiRemoteService.registerVorgangManager(supportedOrganisationsEinheiten, address); - }, () -> LOG.error("Property ozgcloud.vorgang-manager.address not set. Not registering this VorgangsManager")); + zufiRemoteService.registerVorgangManager(supportedOrganisationsEinheiten, vorgangManagerProperties.getAddress()); } } diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java index bc436dedd25d7bd9ee4ef1ad95f7cfffb1612e8b..aab5f17c1c67ebe61d6122fb13a3da561628ed6b 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java @@ -2,25 +2,29 @@ package de.ozgcloud.vorgang.registry; import java.util.List; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor; -import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest; -import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationRequest; +import de.ozgcloud.zufi.grpc.organisationseinheit.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub; import lombok.NonNull; import lombok.extern.log4j.Log4j2; import net.devh.boot.grpc.client.inject.GrpcClient; @Log4j2 @Service +@ConditionalOnProperty(prefix = "ozgcloud.zufi-manager", name = { "address" }) class ZufiRemoteService { + @GrpcClient("zufi-manager") private VorgangManagerRegistrationServiceBlockingStub serviceStub; public void registerVorgangManager(@NonNull List<String> organistationsEinheitenIds, String vorgangManagerAddress) { - boolean success = getServiceStub() - .register(buildRequest(organistationsEinheitenIds, vorgangManagerAddress)).getSuccess(); - LOG.info("Register success: " + success); + var result = getServiceStub().register(buildRequest(organistationsEinheitenIds, vorgangManagerAddress)); + if (!result.getSuccess()) { + LOG.warn("Registration failed: {}", result.getMessage()); + } } private VorgangManagerRegistrationServiceBlockingStub getServiceStub() { diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java index 51e2ba9baad098db8ba6c73cd84f6ee75ddd8d1a..67678fb2648931db32733b0f3c113d43e0d87bc5 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java @@ -42,6 +42,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import de.ozgcloud.command.Command; +import de.ozgcloud.command.VorgangAssignedEvent; import de.ozgcloud.command.VorgangCreatedEvent; import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap; import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted; diff --git a/vorgang-manager-server/src/main/resources/application-local.yml b/vorgang-manager-server/src/main/resources/application-local.yml index 3c001700cf121f982f772d96606412189ad50db3..f6a467f4938cfac669d42e0bbf2c81cfd10d9eb4 100644 --- a/vorgang-manager-server/src/main/resources/application-local.yml +++ b/vorgang-manager-server/src/main/resources/application-local.yml @@ -43,6 +43,9 @@ grpc: enabled: false spring: + cloud: + config: + enabled: false data: mongodb: database: vorgang-manager-local @@ -55,7 +58,12 @@ spring: '[mail.smtp.starttls.enable]': true ozgcloud: + administration: + sync: + enabled: false aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA + application: + address: http://localhost:9090 notification: mail-from: ea@ozg-sh.de redirect: @@ -64,7 +72,7 @@ ozgcloud: url: http://localhost:9092/migration/user user: cleanup: - cron: 0 */5 * * * * + cron: "-" feature: bescheid: enable-dummy-document-processor: true diff --git a/vorgang-manager-server/src/main/resources/application.yml b/vorgang-manager-server/src/main/resources/application.yml index 6784f1d84c27c3a9745a4eb3f978d175cb440eeb..14efedc146c86e36e8dff4ebdf7c3f66ea544275 100644 --- a/vorgang-manager-server/src/main/resources/application.yml +++ b/vorgang-manager-server/src/main/resources/application.yml @@ -11,6 +11,8 @@ mongock: transactionEnabled: false spring: + config: + import: optional:configserver:${ozgcloud_administration_address}/configserver/ application: name: OzgCloud_VorgangManager data: @@ -40,6 +42,8 @@ grpc: command-manager: address: self:self negotiationType: PLAINTEXT + zufi-manager: + negotiationType: TLS server: security: @@ -68,10 +72,17 @@ management: endpoints: web: exposure: - include: health,prometheus + include: health,prometheus,refresh ozgcloud: + administration: + sync: + delay: 900_000 production: false + registry: + scheduler: + fixedDelayMinutes: 5 + initialDelayMinutes: 5 osi: postfach: scheduler: diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java index 61fc27b309e3d269706f3a8bd3c1fd74da19ff6e..1488e8f8dd4f1baef4b2831081ccd6a078a6ef36 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumITCase.java @@ -181,7 +181,7 @@ class AntragraumITCase { grpcService.findRueckfragen( GrpcFindRueckfrageRequestTestFactory.createBuilder().setSamlToken(TestUtils.loadTextFile("SamlResponse.xml")).build(), responseObserver); - verify(responseObserver).onNext(captor.capture()); + verify(responseObserver, timeout(30000)).onNext(captor.capture()); return captor.getValue().getRueckfrageHeadList(); } } @@ -189,12 +189,13 @@ class AntragraumITCase { private Vorgang createVorgang(TrustLevel trustLevel) { return VorgangTestFactory.createBuilder() .id(null) + .version(0) .header(VorgangHeadTestFactory.createBuilder().serviceKonto(createBayernIdServiceKonto(trustLevel)).build()) .build(); } private ServiceKonto createBayernIdServiceKonto(TrustLevel trustLevel) { - return ServiceKontoTestFactory.createBuilder().type("BayernID").trustLevel(trustLevel.getValue()).build(); + return ServiceKontoTestFactory.createBuilder().type("BAYERN_ID").trustLevel(trustLevel.getValue()).build(); } private VorgangAttachedItem createPostfachNachrichtVorgangAttachedItem(String vorgangId) { @@ -219,7 +220,7 @@ class AntragraumITCase { PostfachAddress.VERSION_FIELD, 1, PostfachAddress.IDENTIFIER_FIELD, Map.of(PostfachNachricht.FIELD_POSTFACH_ID, PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE), - PostfachAddress.SERVICEKONTO_TYPE_FIELD, "BayernID")); + PostfachAddress.SERVICEKONTO_TYPE_FIELD, "BAYERN_ID")); return nachrichtItem; } } \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java index 516b1ea807fd936a7d7c91b034f8bba505c02017..566a427a59914c63bce1077851710e205be84baa 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java @@ -23,14 +23,20 @@ */ package de.ozgcloud.nachrichten.postfach; +import static org.awaitility.Awaitility.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -40,10 +46,13 @@ import org.springframework.context.ApplicationEventPublisher; import de.ozgcloud.command.Command; import de.ozgcloud.command.CommandCreatedEvent; +import de.ozgcloud.command.VorgangAttachedItemCreatedEvent; import de.ozgcloud.common.test.ITCase; import de.ozgcloud.vorgang.VorgangManagerServerApplication; +import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem; import de.ozgcloud.vorgang.command.CommandService; import de.ozgcloud.vorgang.command.CommandTestFactory; +import de.ozgcloud.vorgang.command.Order; import de.ozgcloud.vorgang.vorgang.VorgangService; @ITCase @@ -89,4 +98,54 @@ class PostfachEventListenerITCase { } } + @Nested + class TestOnIncomingPostfachNachrichtItemCreated { + + private static final Command COMMAND = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name()) + .bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, AttachedItemRemoteService.ITEM_NAME, + PostfachNachricht.FIELD_DIRECTION, "IN")).build(); + + @Test + void shouldCallListener() { + var event = new VorgangAttachedItemCreatedEvent(COMMAND, CommandTestFactory.CREATED_RESOURCE); + + publisher.publishEvent(event); + + await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).onIncomingPostfachNachrichtItemCreated(event)); + } + + @DisplayName("should not call listener") + @ParameterizedTest(name = "on order {0}") + @EnumSource(value = Order.class, names = { "CREATE_ATTACHED_ITEM" }, mode = EnumSource.Mode.EXCLUDE) + void shouldNotCallListenerOnWrongOrder(Order order) { + var command = CommandTestFactory.createBuilder().order(order.name()).build(); + + publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE)); + + await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any())); + } + + @DisplayName("should not call listener when not postfach mail item") + @Test + void shouldNotCallListenerOnWrongItem() { + var command = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name()) + .bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, "not-postfach-mail-item")).build(); + + publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE)); + + await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any())); + } + + @DisplayName("should not call listener when not incoming item") + @Test + void shouldNotCallListenerOnWrongDirection() { + var command = CommandTestFactory.createBuilder().order(Order.CREATE_ATTACHED_ITEM.name()) + .bodyObject(Map.of(VorgangAttachedItem.FIELDNAME_ITEM_NAME, AttachedItemRemoteService.ITEM_NAME, + PostfachNachricht.FIELD_DIRECTION, "OUT")).build(); + + publisher.publishEvent(new VorgangAttachedItemCreatedEvent(command, CommandTestFactory.CREATED_RESOURCE)); + + await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener, never()).onIncomingPostfachNachrichtItemCreated(any())); + } + } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java index 1ef45402d363fe6e8a0a695dd349c88383f31773..fbae6587b954a7ec5313c997719bb4ceb03d97b2 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java @@ -164,4 +164,5 @@ class VorgangAttachedItemEventListenerITCase { await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(service).revokeDelete(command)); } } + } \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java index 28611d93e880d5012906f5dc8da81aea4c5a2846..26b2c4ba13544fdaf44d06f89a12a5308a2b676a 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java @@ -51,6 +51,7 @@ import org.springframework.context.ApplicationEventPublisher; import de.ozgcloud.command.Command; import de.ozgcloud.command.RevokeCommandEvent; +import de.ozgcloud.command.VorgangAttachedItemCreatedEvent; import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory; import de.ozgcloud.vorgang.command.CommandService; import de.ozgcloud.vorgang.command.CommandTestFactory; @@ -98,7 +99,7 @@ class VorgangAttachedItemEventListenerTest { void withItem() { listener.createItem(CommandCreatedEventTestFactory.create(command)); - verify(service).create(eq(CommandTestFactory.ID), itemCaptor.capture()); + verify(service).create(eq(command), itemCaptor.capture()); assertThat(itemCaptor.getValue()).usingRecursiveComparison() .ignoringFields(VorgangAttachedItem.FIELDNAME_ID, VorgangAttachedItem.FIELDNAME_VERSION) .isEqualTo(VorgangAttachedItemTestFactory.create()); @@ -108,7 +109,7 @@ class VorgangAttachedItemEventListenerTest { void withIdAndVersionAsNull() { listener.createItem(CommandCreatedEventTestFactory.create(command)); - verify(service).create(eq(CommandTestFactory.ID), itemCaptor.capture()); + verify(service).create(eq(command), itemCaptor.capture()); var item = itemCaptor.getValue(); assertThat(item.getId()).isNull(); @@ -496,4 +497,5 @@ class VorgangAttachedItemEventListenerTest { verify(service).revokePatch(command, CommandTestFactory.PREVIOUS_STATE); } } + } \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java index 6bafdceabe71af6f52b99993f7a89d309f612924..ca9b0e78ab82bf475d52383be1dbae940bb6e3fb 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java @@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.ApplicationEventPublisher; +import de.ozgcloud.command.Command; import de.ozgcloud.common.test.ITCase; import de.ozgcloud.vorgang.command.CommandTestFactory; @@ -27,25 +28,28 @@ class VorgangAttachedItemServiceITCase { @Nested class TestCreate { + + private static final Command COMMAND = CommandTestFactory.create(); + @Test void shouldDenyMissingClientName() { var item = VorgangAttachedItemTestFactory.createBuilder().client(StringUtils.EMPTY).build(); - assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class); + assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class); } @Test void shouldDenyMissingVorgangId() { var item = VorgangAttachedItemTestFactory.createBuilder().vorgangId(StringUtils.EMPTY).build(); - assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class); + assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class); } @Test void shouldDenyMissingItemName() { var item = VorgangAttachedItemTestFactory.createBuilder().itemName(StringUtils.EMPTY).build(); - assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item)).isInstanceOf(ConstraintViolationException.class); + assertThatThrownBy(() -> service.create(COMMAND, item)).isInstanceOf(ConstraintViolationException.class); } } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java index 1d2933edd7aedfb0a91ecf9554cccd43be3b7f48..7447aa18488ebd0ed7406989214afbda377580da 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java @@ -33,6 +33,7 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -46,6 +47,8 @@ import org.springframework.context.ApplicationEventPublisher; import de.ozgcloud.command.Command; import de.ozgcloud.command.CommandRevokeFailedEvent; import de.ozgcloud.command.CommandRevokedEvent; +import de.ozgcloud.command.VorgangAttachedItemCreatedEvent; +import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; import de.ozgcloud.vorgang.command.CommandTestFactory; import de.ozgcloud.vorgang.common.errorhandling.NotFoundException; @@ -64,53 +67,205 @@ class VorgangAttachedItemServiceTest { @Nested class TestCreateItem { + private static final VorgangAttachedItem PREPARED_ITEM = VorgangAttachedItemTestFactory.create(); + private static final VorgangAttachedItem PERSISTED_ITEM = VorgangAttachedItemTestFactory.createBuilder() + .id(CommandTestFactory.CREATED_RESOURCE).build(); + + @Captor + private ArgumentCaptor<VorgangAttachedItemCreatedEvent> eventCaptor; + + @BeforeEach + void init() { + when(repository.save(any())).thenReturn(PERSISTED_ITEM); + doReturn(PREPARED_ITEM).when(service).prepareForCreation(any()); + } + + @Test + void shouldCallPrepareForCreation() { + var item = VorgangAttachedItemTestFactory.create(); + + service.create(CommandTestFactory.create(), item); + + verify(service).prepareForCreation(item); + } + @Test void shouldCallRepository() { - when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create()); + service.create(CommandTestFactory.create(), VorgangAttachedItemTestFactory.create()); - service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create()); + verify(repository).save(PREPARED_ITEM); + } - verify(repository).save(any()); + @Test + void shouldCallBuildExecutedCommand() { + var command = CommandTestFactory.create(); + + service.create(command, VorgangAttachedItemTestFactory.create()); + + verify(service).buildExecutedCommand(command, PERSISTED_ITEM); } @Test void shouldPublishEvent() { - when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create()); + var executedCommand = CommandTestFactory.create(); + doReturn(executedCommand).when(service).buildExecutedCommand(any(), any()); + + service.create(CommandTestFactory.create(), VorgangAttachedItemTestFactory.create()); + + verify(publisher).publishEvent(eventCaptor.capture()); + assertThat(eventCaptor.getValue()).satisfies(event -> { + assertThat(event.getCommand()).isSameAs(executedCommand); + assertThat(event.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE); + }); + } + } + + @Nested + class TestPrepareForCreation { + @Test + void shouldRemoveId() { + var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + + assertThat(prepared.getId()).isNull(); + } + + @Test + void shouldSetVersionToZero() { + var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + + assertThat(prepared.getVersion()).isZero(); + } + + @Test + void shouldRemoveIdFromItem() { + var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + + assertThat(prepared.getItem()).doesNotContainKey(VorgangAttachedItem.FIELDNAME_ID); + } + + @Test + void shouldSetIsDeletedToFalse() { + var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + + assertThat(prepared.isDeleted()).isFalse(); + } + } + + @Nested + class TestBuildExecutedCommand { + + private static final VorgangAttachedItem ITEM = VorgangAttachedItemTestFactory.create(); + + @Test + void shouldSetId() { + var result = buildExecutedCommand(); + + assertThat(result.getId()).isEqualTo(CommandTestFactory.ID); + } + + @Test + void shouldSetVorgangId() { + var result = buildExecutedCommand(); + + assertThat(result.getVorgangId()).isEqualTo(VorgangTestFactory.ID); + } + + @Test + void shouldSetRelationId() { + var result = buildExecutedCommand(); + + assertThat(result.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID); + } + + @Test + void shouldSetRelationVersion() { + var result = buildExecutedCommand(); + + assertThat(result.getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION); + } + + @Test + void shouldSetOrder() { + var result = buildExecutedCommand(); + + assertThat(result.getOrder()).isEqualTo(CommandTestFactory.ORDER.name()); + } + + @Test + void shouldSetCreatedAt() { + var result = buildExecutedCommand(); + + assertThat(result.getCreatedAt()).isEqualTo(CommandTestFactory.CREATED_AT); + } + + @Test + void shouldSetCreatedBy() { + var result = buildExecutedCommand(); + + assertThat(result.getCreatedBy()).isEqualTo(CommandTestFactory.CREATED_BY); + } - service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create()); + @Test + void shouldSetStatus() { + var result = buildExecutedCommand(); + + assertThat(result.getStatus()).isEqualTo(CommandTestFactory.STATUS); + } - verify(publisher).publishEvent(any(VorgangAttachedItemCreatedEvent.class)); + @Test + void shouldSetCreatedResource() { + var result = buildExecutedCommand(); + + assertThat(result.getCreatedResource()).isEqualTo(VorgangAttachedItemTestFactory.ID); } - @Nested - class TestPrepareForCreation { - @Test - void shouldRemoveId() { - var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + @Test + void shouldCallBuildBodyObject() { + buildExecutedCommand(); - assertThat(prepared.getId()).isNull(); - } + verify(service).buildBodyObject(ITEM); + } - @Test - void shouldSetVersionToZero() { - var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + @Test + void shouldSetBodyObject() { + var bodyObject = Map.<String, Object>of("key", "value"); + doReturn(bodyObject).when(service).buildBodyObject(any()); - assertThat(prepared.getVersion()).isZero(); - } + var result = buildExecutedCommand(); - @Test - void shouldRemoveIdFromItem() { - var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + assertThat(result.getBodyObject()).isEqualTo(bodyObject); + } - assertThat(prepared.getItem()).doesNotContainKey(VorgangAttachedItem.FIELDNAME_ID); - } + private Command buildExecutedCommand() { + return service.buildExecutedCommand(CommandTestFactory.create(), ITEM); + } + } - @Test - void shouldSetIsDeletedToFalse() { - var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create()); + @Nested + class TestBuildBodyObject { + + @Test + void shouldSetItemName() { + var result = service.buildBodyObject(VorgangAttachedItemTestFactory.create()); + + assertThat(result).containsEntry(VorgangAttachedItem.FIELDNAME_ITEM_NAME, ITEM_NAME); + } + + @Test + void shouldSetMailDirection() { + var item = VorgangAttachedItemTestFactory.createBuilder() + .item(Map.of(PostfachNachricht.FIELD_DIRECTION, PostfachNachricht.Direction.IN.name())).build(); + + var result = service.buildBodyObject(item); + + assertThat(result).containsEntry(PostfachNachricht.FIELD_DIRECTION, PostfachNachricht.Direction.IN.name()); + } + + @Test + void shouldHandleMissingDirection() { + var result = service.buildBodyObject(VorgangAttachedItemTestFactory.create()); - assertThat(prepared.isDeleted()).isFalse(); - } + assertThat(result).doesNotContainKey(PostfachNachricht.FIELD_DIRECTION); } } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..546eb8da689160432261bef9bb4a08f4d7f577d8 --- /dev/null +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M012_UpdateBayernIdPostfachTypeITCase.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.vorgang.common.migration; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; +import java.util.Map; + +import org.bson.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Query; + +import de.ozgcloud.common.test.DataITCase; + +@DataITCase +class M012_UpdateBayernIdPostfachTypeITCase { + + private static final String FIELD_HEADER = "header"; + private static final String FIELD_SERVICE_KONTO = "serviceKonto"; + private static final String FIELD_TYPE = "type"; + private static final String FIELD_EINGANG = "eingangs"; + + private final M012_UpdateBayernIdPostfachType migration = new M012_UpdateBayernIdPostfachType(); + + @Autowired + private MigrationDbTestUtils dbTestUtils; + @Autowired + private MongoTemplate template; + + @BeforeEach + void init() { + dbTestUtils.dropVorgangCollection(); + } + + @DisplayName("should migrate when") + @ParameterizedTest(name = "header's serviceKonto type is \"{0}\"") + @ValueSource(strings = { "BayernId", "BayernID" }) + void shouldMitgrateHeader(String type) { + saveVorgangWithHeaderServiceKonto(createServiceKonto(type)); + + migration.doMigration(template); + + assertThat(loadHeaderServiceKonto()).containsEntry(FIELD_TYPE, M012_UpdateBayernIdPostfachType.BAYERN_ID_TYPE_NEW); + } + + @DisplayName("should migrate when") + @ParameterizedTest(name = "eingang's serviceKonto type is \"{0}\"") + @ValueSource(strings = { "BayernId", "BayernID" }) + void shouldMigrateEingang(String type) { + saveVorgangWithEingangServiceKonto(createServiceKonto(type)); + + migration.doMigration(template); + + assertThat(loadEingangServiceKonto()).containsEntry(FIELD_TYPE, M012_UpdateBayernIdPostfachType.BAYERN_ID_TYPE_NEW); + } + + @DisplayName("should skip when") + @ParameterizedTest(name = "header's serviceKonto type is \"{0}\"") + @NullAndEmptySource + @ValueSource(strings = { "another", "OSI" }) + void shouldSkipWhenServiceKontoMissingInHeader(String type) { + saveVorgangWithHeaderServiceKonto(createServiceKonto(type)); + + migration.doMigration(template); + + assertThat(loadHeaderServiceKonto()).containsEntry(FIELD_TYPE, type); + } + + @DisplayName("should skip when") + @ParameterizedTest(name = "eingang's serviceKonto type is \"{0}\"") + @NullAndEmptySource + @ValueSource(strings = { "another", "OSI" }) + void shouldSkipWhenServiceKontoMissingInEingang(String type) { + saveVorgangWithEingangServiceKonto(createServiceKonto(type)); + + migration.doMigration(template); + + assertThat(loadEingangServiceKonto()).containsEntry(FIELD_TYPE, type); + } + + private Document createServiceKonto(String type) { + var serviceKonto = new Document(); + serviceKonto.put(FIELD_TYPE, type); + return serviceKonto; + } + + private void saveVorgangWithHeaderServiceKonto(Document serviceKonto) { + dbTestUtils.saveVorgang(new Document(Map.of(FIELD_HEADER, Map.of(FIELD_SERVICE_KONTO, serviceKonto)))); + } + + private void saveVorgangWithEingangServiceKonto(Document serviceKonto) { + var eingang = new Document(Map.of(FIELD_HEADER, Map.of(FIELD_SERVICE_KONTO, serviceKonto))); + dbTestUtils.saveVorgang(new Document(Map.of(FIELD_EINGANG, List.of(eingang)))); + } + + private Document loadHeaderServiceKonto() { + var vorgangs = dbTestUtils.findVorgang(new Query()); + return getServiceKonto(vorgangs.getFirst()); + } + + private Document loadEingangServiceKonto() { + var vorgangs = dbTestUtils.findVorgang(new Query()); + return getServiceKonto(vorgangs.getFirst().getList(FIELD_EINGANG, Document.class).getFirst()); + } + + private Document getServiceKonto(Document vorgang) { + return vorgang.get(FIELD_HEADER, Document.class).get(FIELD_SERVICE_KONTO, Document.class); + } +} \ No newline at end of file diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java index 359c21709666e3ec0f2c5c8e07d5317ba351dc79..22d8cf0cbc1376ac758021b083685c7ac518efdb 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java @@ -37,13 +37,13 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import de.ozgcloud.command.Command; +import de.ozgcloud.command.VorgangAssignedEvent; import de.ozgcloud.command.VorgangCreatedEvent; import de.ozgcloud.vorgang.command.CommandService; import de.ozgcloud.vorgang.command.CommandTestFactory; import de.ozgcloud.vorgang.status.StatusChangedEvent; import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent; import de.ozgcloud.vorgang.vorgang.Vorgang; -import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent; import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent; import de.ozgcloud.vorgang.vorgang.VorgangDeletedEventTestFactory; import de.ozgcloud.vorgang.vorgang.VorgangService; @@ -127,7 +127,7 @@ class SearchEventListenerTest { @Nested class TestOnDeletedVorgang { - private VorgangDeletedEvent event = VorgangDeletedEventTestFactory.create(); + private final VorgangDeletedEvent event = VorgangDeletedEventTestFactory.create(); @Test void shouldCallService() { diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java index 7bf1b282a7708c1e16fab1f6f6a71873b5f245bf..831f430ef392061414267c8478689cbe90f1a712 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java @@ -1,6 +1,6 @@ package de.ozgcloud.vorgang.registry; -import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationResponse; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationResponse; public class GrpcRegistrationResponseTestFactory { public static GrpcVorgangManagerRegistrationResponse create() { diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java index 7f5f58b5e47dd5ecb7cf48219f092d42fc1134ad..aaf11c29d09a7e063e209f2b97b070bd7880a303 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java @@ -1,25 +1,24 @@ package de.ozgcloud.vorgang.registry; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.Spy; -import org.springframework.test.util.ReflectionTestUtils; + +import de.ozgcloud.vorgang.VorgangManagerProperties; class RegistryServiceTest { + private static final String ORGANISATION_EINHEITEN_ID = "123456"; private static final List<String> ORGANISATION_EINHEITEN_IDS = List.of(ORGANISATION_EINHEITEN_ID); - private static final Optional<String> VORGANG_MANAGER_ADDRESS = Optional.of("address"); + private static final String VORGANG_MANAGER_ADDRESS = "vorgang-manager-address"; @Spy @InjectMocks @@ -27,34 +26,24 @@ class RegistryServiceTest { @Mock private ZufiRemoteService zufiRemoteService; + @Mock + private VorgangManagerProperties vorgangManagerProperties; - @DisplayName("Test registering the VorgangManager") - @Nested - class TestRegistryVorgangManager { - @BeforeEach - void initVorgangManagerAddress() { - ReflectionTestUtils.setField(registryService, "vorgangManagerAddress", VORGANG_MANAGER_ADDRESS); - } - - @Test - void shouldCallZuFiRemoteService() { - registryService.registerVorgangManager(ORGANISATION_EINHEITEN_IDS); - - verify(zufiRemoteService).registerVorgangManager(anyList(), any()); - } + @Test + void shouldCallZuFiRemoteService() { + when(vorgangManagerProperties.getAddress()).thenReturn(VORGANG_MANAGER_ADDRESS); - @Test - void shouldNotCallZuFiRemoteServiceOnEmptyOrganisationsEinheitenIds() { - registryService.registerVorgangManager(Collections.emptyList()); + registryService.registerVorgangManager(ORGANISATION_EINHEITEN_IDS); - verify(zufiRemoteService, never()).registerVorgangManager(anyList(), any()); - } + verify(zufiRemoteService).registerVorgangManager(ORGANISATION_EINHEITEN_IDS, VORGANG_MANAGER_ADDRESS); + } - @Test - void shouldNotCallServiceStub() { - registryService.registerAddress(ORGANISATION_EINHEITEN_IDS, Optional.empty()); + @DisplayName("should not call zufi remote service when organisationseinheitenIds is empty") + @Test + void shouldNotCallRegisterAddress() { + registryService.registerVorgangManager(Collections.emptyList()); - verify(zufiRemoteService, never()).registerVorgangManager(any(), any()); - } + Mockito.verifyNoInteractions(zufiRemoteService); } + } diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java index 384ca37218780385c58092d40024998380a4e4c2..a09030f20ec00b66f0edb7d1823874c5a0f41101 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java @@ -14,8 +14,8 @@ import org.mockito.Mock; import org.mockito.Spy; import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor; -import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest; -import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcVorgangManagerRegistrationRequest; +import de.ozgcloud.zufi.grpc.organisationseinheit.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub; class ZufiRemoteServiceTest { private static final String ORGANISATIONS_EINHEITEN_ID = "123456"; diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java index fb8085fe48a868c0c40ff629bf19ae4ec4dcea32..c6a8daf26e2d1696cad785c5cb1c66cf1d73f33a 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java @@ -47,6 +47,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.access.AccessDeniedException; import de.ozgcloud.command.Command; +import de.ozgcloud.command.VorgangAssignedEvent; import de.ozgcloud.command.VorgangCreatedEvent; import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted; import de.ozgcloud.vorgang.command.CommandTestFactory; diff --git a/vorgang-manager-server/src/test/resources/application-itcase.yml b/vorgang-manager-server/src/test/resources/application-itcase.yml index 96b714f6f813bab2e43f054df6147c89749a6dbf..a9ac195ac3ed2a031ad421adb61d574b2504519c 100644 --- a/vorgang-manager-server/src/test/resources/application-itcase.yml +++ b/vorgang-manager-server/src/test/resources/application-itcase.yml @@ -11,7 +11,16 @@ grpc: port: -1 ozgcloud: + administration: + sync: + enabled: false + application: + address: localhost aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA mongock: enabled: false +spring: + cloud: + config: + enabled: false diff --git a/vorgang-manager-utils/pom.xml b/vorgang-manager-utils/pom.xml index 9e92999a5f1b5093a63fc6f0b563ab7e72aa5d11..0d232ba161371a55bbf231ffac22faaab225a57d 100644 --- a/vorgang-manager-utils/pom.xml +++ b/vorgang-manager-utils/pom.xml @@ -37,7 +37,7 @@ <groupId>de.ozgcloud.vorgang</groupId> <artifactId>vorgang-manager-utils</artifactId> <name>OZG-Cloud Vorgang Manager Utils</name> - <version>2.14.0-SNAPSHOT</version> + <version>2.15.0-SNAPSHOT</version> <properties> <maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>