Skip to content
Snippets Groups Projects
Commit 4b9d13a6 authored by OZGCloud's avatar OZGCloud
Browse files

Merge branch 'master' into ozg-2956-mongodb-tls

parents 51f363c3 ba9fcb62
No related branches found
No related tags found
No related merge requests found
Showing
with 563 additions and 512 deletions
...@@ -27,42 +27,25 @@ pipeline { ...@@ -27,42 +27,25 @@ pipeline {
def rootVersion = getPomVersion('pom.xml') def rootVersion = getPomVersion('pom.xml')
def serverVersion = getPomVersion('vorgang-manager-server/pom.xml') def serverVersion = getPomVersion('vorgang-manager-server/pom.xml')
def interfaceVersion = getPomVersion('vorgang-manager-interface/pom.xml') def interfaceVersion = getPomVersion('vorgang-manager-interface/pom.xml')
def mailVersion = getPomVersion('nachrichten-manager/pom.xml')
if(isReleaseBranch()){ if(isReleaseBranch()){
if ( !(rootVersion ==~ RELEASE_REGEX) || !(serverVersion ==~ RELEASE_REGEX) || !(interfaceVersion ==~ RELEASE_REGEX) || !(mailVersion ==~ RELEASE_REGEX)) { if ( !(rootVersion ==~ RELEASE_REGEX) || !(serverVersion ==~ RELEASE_REGEX) || !(interfaceVersion ==~ RELEASE_REGEX) ) {
error("Keine Release Version für Branch ${env.BRANCH_NAME}.") error("Keine Release Version für Branch ${env.BRANCH_NAME}.")
} }
} else { } else {
if ( !(rootVersion ==~ SNAPSHOT_REGEX) || !(serverVersion ==~ SNAPSHOT_REGEX) || !(interfaceVersion ==~ SNAPSHOT_REGEX) || !(mailVersion ==~ SNAPSHOT_REGEX)) { if ( !(rootVersion ==~ SNAPSHOT_REGEX) || !(serverVersion ==~ SNAPSHOT_REGEX) || !(interfaceVersion ==~ SNAPSHOT_REGEX) ) {
error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.") error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.")
} }
} }
if( !(rootVersion == serverVersion && rootVersion == interfaceVersion && rootVersion == mailVersion)){ if( !(rootVersion == serverVersion && rootVersion == interfaceVersion )){
error("Versionen sind nicht identisch") error("Versionen sind nicht identisch")
} }
def bayernIdProxyParent = getPomVersion('nachrichten-bayernid-proxy/pom.xml')
def bayernIdProxyInterface = getPomVersion('nachrichten-bayernid-proxy/bayernid-proxy-interface/pom.xml')
if(isReleaseBranch()){
if ( !(bayernIdProxyParent ==~ RELEASE_REGEX) || !(bayernIdProxyInterface ==~ RELEASE_REGEX)) {
error("Keine Release Version für BayernIdProxy Branch ${env.BRANCH_NAME}.")
}
} else {
if ( !(bayernIdProxyParent ==~ SNAPSHOT_REGEX) || !(bayernIdProxyInterface ==~ SNAPSHOT_REGEX)) {
error("Keine Snapshot Version für BayernIdProxy Branch ${env.BRANCH_NAME}.")
}
}
if( !(bayernIdProxyParent == bayernIdProxyInterface)){
error("Versionen BayernIdProxy sind nicht identisch")
}
} }
} }
} }
stage('Build VorgangManager / NachrichtenManagner') { stage('Build VorgangManager') {
steps { steps {
script { script {
FAILED_STAGE=env.STAGE_NAME FAILED_STAGE=env.STAGE_NAME
...@@ -105,20 +88,6 @@ pipeline { ...@@ -105,20 +88,6 @@ pipeline {
} }
} }
stage('Build Docker image nachrichten-bayernid-proxy') {
steps {
script {
FAILED_STAGE=env.STAGE_NAME
}
configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
dir('nachrichten-bayernid-proxy/bayernid-proxy-impl') {
sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS spring-boot:build-image -DskipTests -Dmaven.wagon.http.retryHandler.count=3'
}
}
}
}
stage('Tag and Push Docker image vorgang-manager') { stage('Tag and Push Docker image vorgang-manager') {
steps { steps {
script { script {
...@@ -138,25 +107,6 @@ pipeline { ...@@ -138,25 +107,6 @@ pipeline {
} }
} }
stage('Tag and Push Docker image nachrichten-bayernid-proxy') {
steps {
script {
FAILED_STAGE=env.STAGE_NAME
IMAGE_TAG_BAYERN_ID_PROXY = generateImageTag('nachrichten-bayernid-proxy/pom.xml')
tagAndPushDockerImage('bayernid-proxy', IMAGE_TAG_BAYERN_ID_PROXY)
if (env.BRANCH_NAME == 'master') {
tagAndPushDockerImage('bayernid-proxy', 'snapshot-latest')
tagAndPushDockerImage('bayernid-proxy', 'e2e-test')
}
else if (env.BRANCH_NAME == 'release') {
tagAndPushDockerImage('bayernid-proxy', 'latest')
}
}
}
}
stage('Test, build and deploy Helm Chart vorgang-manager') { stage('Test, build and deploy Helm Chart vorgang-manager') {
steps { steps {
script { script {
...@@ -175,26 +125,6 @@ pipeline { ...@@ -175,26 +125,6 @@ pipeline {
} }
} }
stage('Test, build and deploy Helm Chart bayernid-proxy') {
steps {
script {
FAILED_STAGE=env.STAGE_NAME
HELM_CHART_VERSION_BAYERN_ID_PROXY = generateHelmChartVersion("nachrichten-bayernid-proxy/pom.xml")
dir('nachrichten-bayernid-proxy') {
sh "./run_helm_test.sh"
}
dir('nachrichten-bayernid-proxy/src/main/helm') {
sh "helm package --version=${HELM_CHART_VERSION_BAYERN_ID_PROXY} ."
deployHelmChart("bayernid-proxy", HELM_CHART_VERSION_BAYERN_ID_PROXY)
}
}
}
}
stage('Trigger Dev rollout') { stage('Trigger Dev rollout') {
when { when {
branch 'master' branch 'master'
...@@ -206,7 +136,6 @@ pipeline { ...@@ -206,7 +136,6 @@ pipeline {
cloneGitopsRepo() cloneGitopsRepo()
setNewVorgangManagerGitopsVersion("dev") setNewVorgangManagerGitopsVersion("dev")
setNewNachrichtenBayernIdProxyGitopsVersion("dev")
pushDevGitopsRepo() pushDevGitopsRepo()
} }
} }
...@@ -223,7 +152,6 @@ pipeline { ...@@ -223,7 +152,6 @@ pipeline {
cloneGitopsRepo() cloneGitopsRepo()
setNewVorgangManagerGitopsVersion("test") setNewVorgangManagerGitopsVersion("test")
setNewNachrichtenBayernIdProxyGitopsVersion("test")
pushTestGitopsRepo() pushTestGitopsRepo()
} }
...@@ -275,36 +203,6 @@ pipeline { ...@@ -275,36 +203,6 @@ pipeline {
unstable("SonarQube failed") unstable("SonarQube failed")
} }
} }
dir('nachrichten-manager') {
try {
withSonarQubeEnv('sonarqube-ozg-sh'){
sh 'mvn -s $MAVEN_SETTINGS sonar:sonar'
}
} catch (Exception e) {
unstable("SonarQube failed")
}
}
dir('notification-manager') {
try {
withSonarQubeEnv('sonarqube-ozg-sh'){
sh 'mvn -s $MAVEN_SETTINGS sonar:sonar'
}
} catch (Exception e) {
unstable("SonarQube failed")
}
}
dir('nachrichten-bayernid-proxy') {
try {
withSonarQubeEnv('sonarqube-ozg-sh'){
sh 'mvn -s $MAVEN_SETTINGS sonar:sonar'
}
} catch (Exception e) {
unstable("SonarQube BayernIdProxy failed")
}
}
} }
} }
} }
...@@ -414,18 +312,6 @@ Void setNewVorgangManagerGitopsVersion(String environment) { ...@@ -414,18 +312,6 @@ Void setNewVorgangManagerGitopsVersion(String environment) {
} }
} }
Void setNewNachrichtenBayernIdProxyGitopsVersion(String environment) {
dir("gitops") {
def envFile = "${environment}/application/values/bayernid-proxy-values.yaml"
def envVersions = readYaml file: envFile
envVersions.bayernid_proxy.image.tag = IMAGE_TAG_BAYERN_ID_PROXY
envVersions.bayernid_proxy.helm.version = HELM_CHART_VERSION_BAYERN_ID_PROXY
writeYaml file: envFile, data: envVersions, overwrite: true
}
}
Void pushDevGitopsRepo() { Void pushDevGitopsRepo() {
pushNewGitopsVersion('dev') pushNewGitopsVersion('dev')
} }
...@@ -443,7 +329,7 @@ Void pushNewGitopsVersion(String environment) { ...@@ -443,7 +329,7 @@ Void pushNewGitopsVersion(String environment) {
withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
sh "git add ${environment}/application/values/*-values.yaml" sh "git add ${environment}/application/values/*-values.yaml"
sh "git commit -m 'jenkins rollout ${environment} vorgang-manager version ${IMAGE_TAG} bayern-id version ${IMAGE_TAG_BAYERN_ID_PROXY}'" sh "git commit -m 'jenkins rollout ${environment} vorgang-manager version ${IMAGE_TAG}'"
sh 'git push https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git' sh 'git push https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git'
} }
} }
......
...@@ -5,18 +5,19 @@ ...@@ -5,18 +5,19 @@
<parent> <parent>
<groupId>de.ozgcloud.common</groupId> <groupId>de.ozgcloud.common</groupId>
<artifactId>ozgcloud-common-parent</artifactId> <artifactId>ozgcloud-common-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.1.0-SNAPSHOT</version>
<relativePath /> <relativePath />
</parent> </parent>
<groupId>de.ozgcloud.bescheid</groupId> <groupId>de.ozgcloud.bescheid</groupId>
<artifactId>bescheid-manager</artifactId> <artifactId>bescheid-manager</artifactId>
<name>OZG-Cloud Bescheid Manager</name> <name>OZG-Cloud Bescheid Manager</name>
<version>1.10.0-SNAPSHOT</version> <version>1.11.0-SNAPSHOT</version>
<properties> <properties>
<vorgang-manager.version>2.6.0-SNAPSHOT</vorgang-manager.version> <vorgang-manager.version>2.7.0-SNAPSHOT</vorgang-manager.version>
<api-lib.version>0.7.0-SNAPSHOT</api-lib.version> <nachrichten-manager.version>2.7.0-SNAPSHOT</nachrichten-manager.version>
<api-lib.version>0.8.0-SNAPSHOT</api-lib.version>
</properties> </properties>
<dependencies> <dependencies>
...@@ -26,6 +27,11 @@ ...@@ -26,6 +27,11 @@
<artifactId>vorgang-manager-interface</artifactId> <artifactId>vorgang-manager-interface</artifactId>
<version>${vorgang-manager.version}</version> <version>${vorgang-manager.version}</version>
</dependency> </dependency>
<dependency>
<groupId>de.ozgcloud.nachrichten</groupId>
<artifactId>nachrichten-manager-interface</artifactId>
<version>${nachrichten-manager.version}</version>
</dependency>
<dependency> <dependency>
<groupId>de.ozgcloud.command</groupId> <groupId>de.ozgcloud.command</groupId>
<artifactId>command-manager</artifactId> <artifactId>command-manager</artifactId>
......
...@@ -3,14 +3,11 @@ package de.ozgcloud.bescheid; ...@@ -3,14 +3,11 @@ package de.ozgcloud.bescheid;
import java.io.File; import java.io.File;
import java.util.Optional; import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import de.ozgcloud.bescheid.vorgang.Vorgang; import de.ozgcloud.bescheid.vorgang.Vorgang;
import de.ozgcloud.bescheid.vorgang.VorgangId; import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.common.binaryfile.FileId; import de.ozgcloud.common.binaryfile.FileId;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.With; import lombok.With;
@Builder(toBuilder = true) @Builder(toBuilder = true)
...@@ -46,29 +43,26 @@ public class Bescheid { ...@@ -46,29 +43,26 @@ public class Bescheid {
private Vorgang.ServiceKonto serviceKonto; private Vorgang.ServiceKonto serviceKonto;
public enum Status { public enum Status {
DRAFT, BESCHEID, SEND; DRAFT, SENT;
public boolean not(String value) { public boolean not(Object value) {
return !hasValue(value); return !hasValue(value);
} }
public boolean hasValue(String value) { public boolean hasValue(Object value) {
return this.name().equalsIgnoreCase(value); return this.name().equalsIgnoreCase(String.valueOf(value));
} }
} }
@RequiredArgsConstructor
public enum SendBy { public enum SendBy {
NACHRICHT("NACHRICHT"), MANUAL("MANUAL"); NACHRICHT, MANUAL;
private final String value;
public boolean notValue(Object sendByValue) { public boolean notValue(Object sendByValue) {
return !hasValue(sendByValue); return !hasValue(sendByValue);
} }
public boolean hasValue(Object sendByValue) { public boolean hasValue(Object sendByValue) {
return StringUtils.equalsIgnoreCase(value, String.valueOf(sendByValue)); return this.name().equalsIgnoreCase(String.valueOf(sendByValue));
} }
} }
......
...@@ -24,9 +24,11 @@ ...@@ -24,9 +24,11 @@
package de.ozgcloud.bescheid; package de.ozgcloud.bescheid;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
...@@ -34,6 +36,7 @@ import org.springframework.context.event.EventListener; ...@@ -34,6 +36,7 @@ import org.springframework.context.event.EventListener;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import de.ozgcloud.bescheid.Bescheid.SendBy;
import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService;
import de.ozgcloud.bescheid.binaryfile.BinaryFileService; import de.ozgcloud.bescheid.binaryfile.BinaryFileService;
import de.ozgcloud.bescheid.common.callcontext.CurrentUserService; import de.ozgcloud.bescheid.common.callcontext.CurrentUserService;
...@@ -43,6 +46,7 @@ import de.ozgcloud.bescheid.vorgang.VorgangId; ...@@ -43,6 +46,7 @@ import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.command.Command; import de.ozgcloud.command.Command;
import de.ozgcloud.command.CommandCreatedEvent; import de.ozgcloud.command.CommandCreatedEvent;
import de.ozgcloud.command.CommandFailedEvent; import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.document.BescheidDocumentCreatedEvent; import de.ozgcloud.document.BescheidDocumentCreatedEvent;
import de.ozgcloud.document.DocumentService; import de.ozgcloud.document.DocumentService;
import lombok.NonNull; import lombok.NonNull;
...@@ -59,7 +63,6 @@ class BescheidEventListener { ...@@ -59,7 +63,6 @@ class BescheidEventListener {
public static final String UPDATE_BESCHEID_ORDER = "UPDATE_BESCHEID"; public static final String UPDATE_BESCHEID_ORDER = "UPDATE_BESCHEID";
public static final String CREATE_BESCHEID_DOCUMENT_ORDER = "CREATE_BESCHEID_DOCUMENT"; public static final String CREATE_BESCHEID_DOCUMENT_ORDER = "CREATE_BESCHEID_DOCUMENT";
public static final String SEND_BESCHEID_ORDER = "SEND_BESCHEID"; public static final String SEND_BESCHEID_ORDER = "SEND_BESCHEID";
public static final String SEND_POSTFACH_MAIL_ORDER = "SEND_POSTFACH_MAIL";
public static final Predicate<Command> IS_CREATE_BESCHEID_COMMAND = command -> CREATE_BESCHEID_ORDER.equals(command.getOrder()); public static final Predicate<Command> IS_CREATE_BESCHEID_COMMAND = command -> CREATE_BESCHEID_ORDER.equals(command.getOrder());
private static final String IS_CREATE_BESCHEID = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_CREATE_BESCHEID_COMMAND.test(event.getSource())}"; private static final String IS_CREATE_BESCHEID = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_CREATE_BESCHEID_COMMAND.test(event.getSource())}";
...@@ -76,9 +79,6 @@ class BescheidEventListener { ...@@ -76,9 +79,6 @@ class BescheidEventListener {
public static final Predicate<Command> IS_SEND_BESCHEID_COMMAND = command -> SEND_BESCHEID_ORDER.equals(command.getOrder()); public static final Predicate<Command> IS_SEND_BESCHEID_COMMAND = command -> SEND_BESCHEID_ORDER.equals(command.getOrder());
private static final String IS_SEND_BESCHEID = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_SEND_BESCHEID_COMMAND.test(event.getSource())}"; private static final String IS_SEND_BESCHEID = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_SEND_BESCHEID_COMMAND.test(event.getSource())}";
public static final Predicate<Command> IS_SEND_POSTFACH_MAIL_COMMAND = command -> SEND_POSTFACH_MAIL_ORDER.equals(command.getOrder());
private static final String IS_SEND_POSTFACH_MAIL = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_SEND_POSTFACH_MAIL_COMMAND.test(event.getSource())}";
private static final String TEMPLATE_GROUP_KIEL = "Kiel"; private static final String TEMPLATE_GROUP_KIEL = "Kiel";
static final String VORGANG_ID_BODYKEY = "vorgangId"; static final String VORGANG_ID_BODYKEY = "vorgangId";
static final String BESCHEID_VOM_BODYKEY = "bescheidVom"; static final String BESCHEID_VOM_BODYKEY = "bescheidVom";
...@@ -160,17 +160,16 @@ class BescheidEventListener { ...@@ -160,17 +160,16 @@ class BescheidEventListener {
} }
void doSendBescheid(Command command) { void doSendBescheid(Command command) {
service.sendBescheidManually(command.getRelationId(), command.getRelationVersion()); var bescheidItem = attachedItemService.getItem(command.getRelationId());
eventPublisher.publishEvent(new BescheidSentEvent(command)); if (SendBy.MANUAL.hasValue(bescheidItem.getItem().get(Bescheid.FIELD_SEND_BY))) {
service.sendBescheidManually(bescheidItem, command.getRelationVersion());
} else if (SendBy.NACHRICHT.hasValue(bescheidItem.getItem().get(Bescheid.FIELD_SEND_BY))) {
service.sendBescheidPostfachMail(bescheidItem, command.getRelationVersion());
} else {
throw new TechnicalException("Bescheid has unexpected sendBy value: '%s'. Allowed values are %s."
.formatted(bescheidItem.getItem().get(Bescheid.FIELD_SEND_BY),
Arrays.stream(SendBy.values()).map(SendBy::name).collect(Collectors.joining(","))));
} }
@EventListener(condition = IS_SEND_POSTFACH_MAIL)
public void onSendPostfachMailCommand(CommandCreatedEvent event) {
runWithSecurityContext(event.getSource(), this::doSendPostfachMail);
}
void doSendPostfachMail(Command command) {
service.sendBescheidPostfachMail(command.getRelationId(), command.getRelationVersion());
eventPublisher.publishEvent(new BescheidSentEvent(command)); eventPublisher.publishEvent(new BescheidSentEvent(command));
} }
......
package de.ozgcloud.bescheid; package de.ozgcloud.bescheid;
import java.util.Collection;
import java.util.List;
import de.ozgcloud.bescheid.BescheidServiceGrpc.BescheidServiceImplBase; import de.ozgcloud.bescheid.BescheidServiceGrpc.BescheidServiceImplBase;
import de.ozgcloud.bescheid.attacheditem.AttachedItem;
import de.ozgcloud.bescheid.attacheditem.AttachedItemMapper;
import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService;
import de.ozgcloud.bescheid.attacheditem.BescheidItem; import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.bescheid.attacheditem.BescheidItemMapper;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.server.service.GrpcService; import net.devh.boot.grpc.server.service.GrpcService;
...@@ -13,12 +17,14 @@ import net.devh.boot.grpc.server.service.GrpcService; ...@@ -13,12 +17,14 @@ import net.devh.boot.grpc.server.service.GrpcService;
class BescheidGrpcService extends BescheidServiceImplBase { class BescheidGrpcService extends BescheidServiceImplBase {
private final AttachedItemService attachedItemService; private final AttachedItemService attachedItemService;
private final BescheidItemMapper bescheidMapper; private final AttachedItemMapper attachedItemMapper;
private final BescheidService bescheidService;
private final GrpcBescheidMapper grpcBescheidMapper;
@Override @Override
public void getBescheidDraft(GrpcGetBescheidDraftRequest request, StreamObserver<GrpcGetBescheidDraftResponse> responseObserver) { public void getBescheidDraft(GrpcGetBescheidDraftRequest request, StreamObserver<GrpcGetBescheidDraftResponse> responseObserver) {
var response = attachedItemService.findBescheidItem(request.getVorgangId()) var response = attachedItemService.findBescheidItem(request.getVorgangId())
.map(this::buildResponse) .map(this::buildGetBescheidDraftResponse)
.orElseGet(GrpcGetBescheidDraftResponse::getDefaultInstance); .orElseGet(GrpcGetBescheidDraftResponse::getDefaultInstance);
responseObserver.onNext(response); responseObserver.onNext(response);
...@@ -26,9 +32,29 @@ class BescheidGrpcService extends BescheidServiceImplBase { ...@@ -26,9 +32,29 @@ class BescheidGrpcService extends BescheidServiceImplBase {
} }
GrpcGetBescheidDraftResponse buildResponse(BescheidItem bescheidItem) { GrpcGetBescheidDraftResponse buildGetBescheidDraftResponse(AttachedItem bescheidItem) {
return GrpcGetBescheidDraftResponse.newBuilder() return GrpcGetBescheidDraftResponse.newBuilder()
.setBescheid(bescheidMapper.toBescheid(bescheidItem)) .setBescheid(attachedItemMapper.toBescheid(bescheidItem))
.build(); .build();
} }
@Override
public void getConfig(GrpcBescheidManagerConfigRequest request, StreamObserver<GrpcBescheidManagerConfigResponse> responseObserver) {
responseObserver.onNext(grpcBescheidMapper.fromBescheidManagerConfig(bescheidService.getConfig()));
responseObserver.onCompleted();
}
@Override
public void getAll(GrpcGetAllBescheidRequest request, StreamObserver<GrpcGetAllBescheidResponse> responseObserver) {
responseObserver.onNext(buildGetAllBescheidResponse(attachedItemService.findAllBescheid(VorgangId.from(request.getVorgangId()))));
responseObserver.onCompleted();
}
GrpcGetAllBescheidResponse buildGetAllBescheidResponse(Collection<AttachedItem> bescheidItems) {
return GrpcGetAllBescheidResponse.newBuilder().addAllBescheid(mapBescheid(bescheidItems)).build();
}
List<GrpcBescheid> mapBescheid(Collection<AttachedItem> bescheidItems) {
return bescheidItems.stream().map(attachedItemMapper::toBescheid).toList();
}
} }
...@@ -21,17 +21,23 @@ ...@@ -21,17 +21,23 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen * Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message; package de.ozgcloud.bescheid;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
@Builder @Builder
@Getter @Getter
public class BayernIdResponse { public class BescheidManagerConfig {
private boolean success; private String version;
private String status; private String javaVersion;
private String message; private Features features;
@Builder
@Getter
static class Features {
private boolean canCreateBescheidDocument;
}
} }
package de.ozgcloud.bescheid; package de.ozgcloud.bescheid;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.info.BuildProperties;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import de.ozgcloud.bescheid.attacheditem.AttachedItem; import de.ozgcloud.bescheid.attacheditem.AttachedItem;
...@@ -34,6 +34,7 @@ class BescheidService { ...@@ -34,6 +34,7 @@ class BescheidService {
private final NachrichtService nachrichtService; private final NachrichtService nachrichtService;
private final CurrentUserService currentUserService; private final CurrentUserService currentUserService;
private final ClientAttributeService bescheidClientAttributeService; private final ClientAttributeService bescheidClientAttributeService;
private final BuildProperties buildProperties;
private final Optional<BescheidRemoteService> remoteService; private final Optional<BescheidRemoteService> remoteService;
@PostConstruct @PostConstruct
...@@ -51,9 +52,13 @@ class BescheidService { ...@@ -51,9 +52,13 @@ class BescheidService {
private Bescheid doCreateBescheid(BescheidRequest request) { private Bescheid doCreateBescheid(BescheidRequest request) {
var vorgang = vorgangService.getById(request.getVorgangId()); var vorgang = vorgangService.getById(request.getVorgangId());
return remoteService.get().create(request, vorgang) return remoteService.map(service -> service.create(request, vorgang))
.toBuilder().vorgangId(vorgang.getId()).serviceKonto(vorgang.getServiceKonto()) .map(bescheid -> updateBescheid(bescheid, vorgang))
.build(); .orElseThrow(() -> new TechnicalException(ERROR_MESSAGE_NO_SERVICE));
}
private Bescheid updateBescheid(Bescheid bescheid, Vorgang vorgang) {
return bescheid.toBuilder().vorgangId(vorgang.getId()).serviceKonto(vorgang.getServiceKonto()).build();
} }
private void checkRemoteService() { private void checkRemoteService() {
...@@ -63,8 +68,7 @@ class BescheidService { ...@@ -63,8 +68,7 @@ class BescheidService {
} }
} }
public void sendBescheidManually(String id, long version) { public void sendBescheidManually(AttachedItem bescheidItem, long version) {
var bescheidItem = attachedItemService.getItem(id);
validateBescheidSendManually(bescheidItem, version); validateBescheidSendManually(bescheidItem, version);
sendBescheid(bescheidItem); sendBescheid(bescheidItem);
} }
...@@ -77,11 +81,10 @@ class BescheidService { ...@@ -77,11 +81,10 @@ class BescheidService {
} }
} }
public void sendBescheidPostfachMail(String id, long version) { public void sendBescheidPostfachMail(AttachedItem bescheidItem, long version) {
var bescheidItem = attachedItemService.getItem(id);
validateBescheidSendPostfach(bescheidItem, version); validateBescheidSendPostfach(bescheidItem, version);
var vorgang = vorgangService.getById(VorgangId.from(bescheidItem.getVorgangId())); var vorgang = vorgangService.getById(VorgangId.from(bescheidItem.getVorgangId()));
nachrichtService.createNachrichtDraft(buildBescheid(bescheidItem, vorgang.getServiceKonto())); nachrichtService.sendNachricht(buildBescheid(bescheidItem, vorgang.getServiceKonto()));
sendBescheid(bescheidItem); sendBescheid(bescheidItem);
} }
...@@ -133,12 +136,11 @@ class BescheidService { ...@@ -133,12 +136,11 @@ class BescheidService {
} }
void sendBescheid(AttachedItem bescheidItem) { void sendBescheid(AttachedItem bescheidItem) {
attachedItemService.patch(setBescheidSendStatus(bescheidItem)); attachedItemService.setBescheidStatus(bescheidItem.getId(), bescheidItem.getVersion(), Bescheid.Status.SENT);
try { try {
vorgangService.bescheiden(bescheidItem.getVorgangId()); vorgangService.bescheiden(bescheidItem.getVorgangId());
} catch (Exception e) { } catch (Exception e) {
var item = attachedItemService.getItem(bescheidItem.getId()); attachedItemService.setBescheidStatus(bescheidItem.getId(), bescheidItem.getVersion(), Bescheid.Status.DRAFT);
attachedItemService.patch(setBescheidDraftStatus(item));
throw e; throw e;
} }
bescheidClientAttributeService.setAntragResult(bescheidItem.getVorgangId(), getBewilligt(bescheidItem)); bescheidClientAttributeService.setAntragResult(bescheidItem.getVorgangId(), getBewilligt(bescheidItem));
...@@ -148,11 +150,21 @@ class BescheidService { ...@@ -148,11 +150,21 @@ class BescheidService {
return MapUtils.getBooleanValue(bescheidItem.getItem(), Bescheid.FIELD_BEWILLIGT, false); return MapUtils.getBooleanValue(bescheidItem.getItem(), Bescheid.FIELD_BEWILLIGT, false);
} }
AttachedItem setBescheidSendStatus(AttachedItem bescheidItem) { public BescheidManagerConfig getConfig() {
return bescheidItem.toBuilder().item(Map.of(Bescheid.FIELD_STATUS, Bescheid.Status.SEND.name())).build(); return BescheidManagerConfig.builder()
.version(buildProperties.getVersion())
.javaVersion(getJavaVersion())
.features(buildFeatures())
.build();
} }
AttachedItem setBescheidDraftStatus(AttachedItem bescheidItem) { String getJavaVersion() {
return bescheidItem.toBuilder().item(Map.of(Bescheid.FIELD_STATUS, Bescheid.Status.DRAFT.name())).build(); return System.getProperty("java.version");
}
BescheidManagerConfig.Features buildFeatures() {
return BescheidManagerConfig.Features.builder()
.canCreateBescheidDocument(remoteService.isPresent())
.build();
} }
} }
...@@ -33,4 +33,14 @@ public interface GrpcBescheidMapper { ...@@ -33,4 +33,14 @@ public interface GrpcBescheidMapper {
default String fromOptional(Optional<String> optionalString) { default String fromOptional(Optional<String> optionalString) {
return optionalString.orElse(StringUtils.EMPTY); return optionalString.orElse(StringUtils.EMPTY);
} }
@Mapping(target = "versionBytes", ignore = true)
@Mapping(target = "unknownFields", ignore = true)
@Mapping(target = "mergeUnknownFields", ignore = true)
@Mapping(target = "mergeFrom", ignore = true)
@Mapping(target = "mergeFeatures", ignore = true)
@Mapping(target = "javaVersionBytes", ignore = true)
@Mapping(target = "clearOneof", ignore = true)
@Mapping(target = "clearField", ignore = true)
GrpcBescheidManagerConfigResponse fromBescheidManagerConfig(BescheidManagerConfig bescheidManagerConfig);
} }
...@@ -23,14 +23,60 @@ ...@@ -23,14 +23,60 @@
*/ */
package de.ozgcloud.bescheid.attacheditem; package de.ozgcloud.bescheid.attacheditem;
import static java.util.Objects.*;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.GrpcBescheid;
import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper; import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem; import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
@Mapper(uses = { GrpcObjectMapper.class }) @Mapper(uses = { GrpcObjectMapper.class })
interface AttachedItemMapper { public interface AttachedItemMapper {
AttachedItem mapFromVorgangAttachedItem(GrpcVorgangAttachedItem item); AttachedItem mapFromVorgangAttachedItem(GrpcVorgangAttachedItem item);
default GrpcBescheid toBescheid(AttachedItem bescheidItem) {
var bescheidBuilder = GrpcBescheid.newBuilder().setVersion(bescheidItem.getVersion());
Optional.ofNullable(bescheidItem.getId()).ifPresent(bescheidBuilder::setId);
var bescheidData = bescheidItem.getItem();
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_BESCHIEDEN_AM)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setBeschiedenAm);
Optional.ofNullable(MapUtils.getBoolean(bescheidData, Bescheid.FIELD_BEWILLIGT)).ifPresent(bescheidBuilder::setBewilligt);
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_BESCHEID_DOCUMENT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setBescheidDocument);
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_SEND_BY)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setSendBy);
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_NACHRICHT_TEXT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setNachrichtText);
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_NACHRICHT_SUBJECT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setNachrichtSubject);
Optional.ofNullable(MapUtils.getString(bescheidData, Bescheid.FIELD_STATUS)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setStatus);
Optional.ofNullable(bescheidData.get(Bescheid.FIELD_ATTACHMENTS)).map(this::toAttachments).ifPresent(bescheidBuilder::addAllAttachments);
return bescheidBuilder.build();
}
@SuppressWarnings("unchecked")
default Collection<String> toAttachments(Object attachmentsObject) {
if (attachmentsObject instanceof Collection<?> attachments) {
return (Collection<String>) attachments;
}
if (attachmentsObject instanceof String attachment) {
attachment = StringUtils.trimToNull(attachment);
if (nonNull(attachment)) {
return List.of(attachment);
}
} else if (nonNull(attachmentsObject)) {
return List.of(String.valueOf(attachmentsObject));
}
return null; //NOSONAR
}
} }
...@@ -25,18 +25,24 @@ package de.ozgcloud.bescheid.attacheditem; ...@@ -25,18 +25,24 @@ package de.ozgcloud.bescheid.attacheditem;
import static java.util.Objects.*; import static java.util.Objects.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import de.ozgcloud.apilib.common.command.OzgCloudCommand; import de.ozgcloud.apilib.common.command.OzgCloudCommand;
import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
import de.ozgcloud.apilib.common.command.grpc.CommandMapper; import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor;
import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.command.Command; import de.ozgcloud.command.Command;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -53,17 +59,17 @@ public class AttachedItemService { ...@@ -53,17 +59,17 @@ public class AttachedItemService {
static final String DELETE_ATTACHED_ITEM = "DELETE_ATTACHED_ITEM"; static final String DELETE_ATTACHED_ITEM = "DELETE_ATTACHED_ITEM";
static final String PATCH_ATTACHED_ITEM = "PATCH_ATTACHED_ITEM"; static final String PATCH_ATTACHED_ITEM = "PATCH_ATTACHED_ITEM";
private static final Predicate<String> notExpectedSendByValue = sendBy -> !BescheidItem.ACCEPTED_SEND_BY_VALUES.contains(sendBy); private static final Predicate<String> notExpectedSendByValue = sendBy -> !ArrayUtils.contains(Bescheid.SendBy.values(), sendBy);
private final OzgCloudCommandService commandService; private final OzgCloudCommandService commandService;
private final VorgangAttachedItemRemoteService remoteService; private final VorgangAttachedItemRemoteService remoteService;
private final CommandMapper commandMapper; private final CommandMapper commandMapper;
public Optional<BescheidItem> findBescheidItem(String vorgangId) { public Optional<AttachedItem> findBescheidItem(String vorgangId) {
return remoteService.findBescheidDraft(vorgangId); return remoteService.findBescheidDraft(vorgangId);
} }
public BescheidItem getBescheidItem(String id) { public AttachedItem getBescheidItem(String id) {
return remoteService.getBescheid(id); return remoteService.getBescheid(id);
} }
...@@ -73,7 +79,7 @@ public class AttachedItemService { ...@@ -73,7 +79,7 @@ public class AttachedItemService {
.map(bescheid -> overrideAttachedItem(bescheid, command)).orElseGet(() -> createAttachedItem(command)); .map(bescheid -> overrideAttachedItem(bescheid, command)).orElseGet(() -> createAttachedItem(command));
} }
String overrideAttachedItem(BescheidItem bescheidItem, Command command) { String overrideAttachedItem(AttachedItem bescheidItem, Command command) {
var bodyObject = buildAttachedItemAsMap(command, buildItemMapWithAllBescheidFields(command)); var bodyObject = buildAttachedItemAsMap(command, buildItemMapWithAllBescheidFields(command));
var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildUpdateAttachedItemCommand(bescheidItem, bodyObject)); var finishedOzgCloudCommand = commandService.createAndWaitUntilDone(buildUpdateAttachedItemCommand(bescheidItem, bodyObject));
return finishedOzgCloudCommand.getCreatedResource(); return finishedOzgCloudCommand.getCreatedResource();
...@@ -81,13 +87,13 @@ public class AttachedItemService { ...@@ -81,13 +87,13 @@ public class AttachedItemService {
Map<String, Object> buildItemMapWithAllBescheidFields(Command command) { Map<String, Object> buildItemMapWithAllBescheidFields(Command command) {
var result = new HashMap<String, Object>(); var result = new HashMap<String, Object>();
result.put(BescheidItem.FIELD_BESCHIEDEN_AM, command.getBodyObject().get(BescheidItem.FIELD_BESCHIEDEN_AM)); result.put(Bescheid.FIELD_BESCHIEDEN_AM, command.getBodyObject().get(Bescheid.FIELD_BESCHIEDEN_AM));
result.put(BescheidItem.FIELD_BEWILLIGT, command.getBodyObject().get(BescheidItem.FIELD_BEWILLIGT)); result.put(Bescheid.FIELD_BEWILLIGT, command.getBodyObject().get(Bescheid.FIELD_BEWILLIGT));
result.put(BescheidItem.FIELD_BESCHEID_DOCUMENT, command.getBodyObject().get(BescheidItem.FIELD_BESCHEID_DOCUMENT)); result.put(Bescheid.FIELD_BESCHEID_DOCUMENT, command.getBodyObject().get(Bescheid.FIELD_BESCHEID_DOCUMENT));
result.put(BescheidItem.FIELD_SEND_BY, command.getBodyObject().get(BescheidItem.FIELD_SEND_BY)); result.put(Bescheid.FIELD_SEND_BY, command.getBodyObject().get(Bescheid.FIELD_SEND_BY));
result.put(BescheidItem.FIELD_NACHRICHT_TEXT, command.getBodyObject().get(BescheidItem.FIELD_NACHRICHT_TEXT)); result.put(Bescheid.FIELD_NACHRICHT_TEXT, command.getBodyObject().get(Bescheid.FIELD_NACHRICHT_TEXT));
result.put(BescheidItem.FIELD_NACHRICHT_SUBJECT, command.getBodyObject().get(BescheidItem.FIELD_NACHRICHT_SUBJECT)); result.put(Bescheid.FIELD_NACHRICHT_SUBJECT, command.getBodyObject().get(Bescheid.FIELD_NACHRICHT_SUBJECT));
result.put(BescheidItem.FIELD_ATTACHMENTS, command.getBodyObject().get(BescheidItem.FIELD_ATTACHMENTS)); result.put(Bescheid.FIELD_ATTACHMENTS, command.getBodyObject().get(Bescheid.FIELD_ATTACHMENTS));
return result; return result;
} }
...@@ -99,7 +105,7 @@ public class AttachedItemService { ...@@ -99,7 +105,7 @@ public class AttachedItemService {
commandService.createAndWaitUntilDone(buildUpdateAttachedItemCommand(bescheidItem, bodyObject)); commandService.createAndWaitUntilDone(buildUpdateAttachedItemCommand(bescheidItem, bodyObject));
} }
OzgCloudCommand buildUpdateAttachedItemCommand(BescheidItem bescheidItem, Map<String, Object> bodyObject) { OzgCloudCommand buildUpdateAttachedItemCommand(AttachedItem bescheidItem, Map<String, Object> bodyObject) {
return OzgCloudCommand.builder() return OzgCloudCommand.builder()
.vorgangId(commandMapper.toOzgCloudVorgangId(bescheidItem.getVorgangId())) .vorgangId(commandMapper.toOzgCloudVorgangId(bescheidItem.getVorgangId()))
.relationId(commandMapper.mapRelationId(bescheidItem.getId())) .relationId(commandMapper.mapRelationId(bescheidItem.getId()))
...@@ -124,23 +130,23 @@ public class AttachedItemService { ...@@ -124,23 +130,23 @@ public class AttachedItemService {
Map<String, Object> buildAttachedItemAsMap(Command command, Map<String, Object> itemmap) { Map<String, Object> buildAttachedItemAsMap(Command command, Map<String, Object> itemmap) {
var result = new HashMap<String, Object>(); var result = new HashMap<String, Object>();
result.put(BescheidItem.PROPERTY_VORGANG_ID, command.getVorgangId()); result.put(AttachedItem.PROPERTY_VORGANG_ID, command.getVorgangId());
result.put(BescheidItem.PROPERTY_CLIENT, BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME); result.put(AttachedItem.PROPERTY_CLIENT, BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME);
result.put(BescheidItem.PROPERTY_ITEM_NAME, BESCHEID_ITEM_NAME); result.put(AttachedItem.PROPERTY_ITEM_NAME, BESCHEID_ITEM_NAME);
result.put(BescheidItem.PROPERTY_ITEM, itemmap); result.put(AttachedItem.PROPERTY_ITEM, itemmap);
return result; return result;
} }
Map<String, Object> buildItemMapWithExistingBescheidFields(Command command) { Map<String, Object> buildItemMapWithExistingBescheidFields(Command command) {
var result = new HashMap<String, Object>(); var result = new HashMap<String, Object>();
result.put(BescheidItem.FIELD_STATUS, BescheidItem.Status.DRAFT.name()); result.put(Bescheid.FIELD_STATUS, Bescheid.Status.DRAFT.name());
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BESCHIEDEN_AM, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_BESCHIEDEN_AM, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BEWILLIGT, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_BEWILLIGT, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BESCHEID_DOCUMENT, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_BESCHEID_DOCUMENT, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_SEND_BY, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_SEND_BY, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_NACHRICHT_TEXT, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_TEXT, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_NACHRICHT_SUBJECT, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_NACHRICHT_SUBJECT, result);
addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_ATTACHMENTS, result); addValueFromMapIfExists(command.getBodyObject(), Bescheid.FIELD_ATTACHMENTS, result);
return result; return result;
} }
...@@ -151,16 +157,16 @@ public class AttachedItemService { ...@@ -151,16 +157,16 @@ public class AttachedItemService {
} }
void validateBescheidData(Map<String, Object> bodyObject) { void validateBescheidData(Map<String, Object> bodyObject) {
if (isNull(bodyObject.get(BescheidItem.FIELD_BESCHIEDEN_AM))) { if (isNull(bodyObject.get(Bescheid.FIELD_BESCHIEDEN_AM))) {
throw new TechnicalException("Fields '%s' is required for bescheid creation" .formatted(BescheidItem.FIELD_BESCHIEDEN_AM)); throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(Bescheid.FIELD_BESCHIEDEN_AM));
} }
if (isNull(bodyObject.get(BescheidItem.FIELD_BEWILLIGT))) { if (isNull(bodyObject.get(Bescheid.FIELD_BEWILLIGT))) {
throw new TechnicalException("Fields '%s' is required for bescheid creation" .formatted(BescheidItem.FIELD_BEWILLIGT)); throw new TechnicalException("Fields '%s' is required for bescheid creation".formatted(Bescheid.FIELD_BEWILLIGT));
} }
Optional.ofNullable(MapUtils.getString(bodyObject, BescheidItem.FIELD_SEND_BY)).filter(notExpectedSendByValue) Optional.ofNullable(MapUtils.getString(bodyObject, Bescheid.FIELD_SEND_BY)).filter(notExpectedSendByValue)
.ifPresent(sendBy -> .ifPresent(sendBy ->
LOG.warn("Unexpected value for field '%s': %s. Allowed are: %s" .formatted(BescheidItem.FIELD_SEND_BY, sendBy, LOG.warn("Unexpected value for field '%s': %s. Allowed are: %s".formatted(Bescheid.FIELD_SEND_BY, sendBy,
String.join(", ", BescheidItem.ACCEPTED_SEND_BY_VALUES))) Arrays.stream(Bescheid.SendBy.values()).map(Bescheid.SendBy::name).collect(Collectors.joining(","))))
); );
} }
...@@ -170,14 +176,14 @@ public class AttachedItemService { ...@@ -170,14 +176,14 @@ public class AttachedItemService {
commandService.createAndWaitUntilDone(buildDeleteItemCommand(command, bescheid)); commandService.createAndWaitUntilDone(buildDeleteItemCommand(command, bescheid));
} }
void validateBescheidStatus(BescheidItem bescheid) { void validateBescheidStatus(AttachedItem bescheid) {
var bescheidStatus = MapUtils.getString(bescheid.getBescheidData(), BescheidItem.FIELD_STATUS); var bescheidStatus = MapUtils.getString(bescheid.getItem(), Bescheid.FIELD_STATUS);
if (BescheidItem.Status.DRAFT.not(bescheidStatus)) { if (Bescheid.Status.DRAFT.not(bescheidStatus)) {
throw new TechnicalException("Bescheid draft with ID '%s' has an unexpected status: '%s'" .formatted(bescheid.getId(), bescheidStatus)); throw new TechnicalException("Bescheid draft with ID '%s' has an unexpected status: '%s'" .formatted(bescheid.getId(), bescheidStatus));
} }
} }
OzgCloudCommand buildDeleteItemCommand(Command command, BescheidItem bescheid) { OzgCloudCommand buildDeleteItemCommand(Command command, AttachedItem bescheid) {
return OzgCloudCommand.builder() return OzgCloudCommand.builder()
.vorgangId(commandMapper.toOzgCloudVorgangId(command.getVorgangId())) .vorgangId(commandMapper.toOzgCloudVorgangId(command.getVorgangId()))
.relationId(commandMapper.mapRelationId(bescheid.getId())) .relationId(commandMapper.mapRelationId(bescheid.getId()))
...@@ -190,28 +196,25 @@ public class AttachedItemService { ...@@ -190,28 +196,25 @@ public class AttachedItemService {
return remoteService.getItem(id); return remoteService.getItem(id);
} }
public void patch(AttachedItem item) { public void setBescheidStatus(String id, long version, Bescheid.Status status) {
commandService.createAndWaitUntilDone(buildPatchBescheidCommand(item)); commandService.createAndWaitUntilDone(buildPatchBescheidCommand(id, version, status));
} }
OzgCloudCommand buildPatchBescheidCommand(AttachedItem bescheidItem) { OzgCloudCommand buildPatchBescheidCommand(String bescheidId, long bescheidVersion, Bescheid.Status bescheidStatus) {
return OzgCloudCommand.builder() return OzgCloudCommand.builder()
.vorgangId(commandMapper.toOzgCloudVorgangId(bescheidItem.getVorgangId())) .relationId(commandMapper.mapRelationId(bescheidId))
.relationId(commandMapper.mapRelationId(bescheidItem.getId())) .relationVersion(bescheidVersion)
.relationVersion(bescheidItem.getVersion())
.order(PATCH_ATTACHED_ITEM) .order(PATCH_ATTACHED_ITEM)
.bodyObject(buildObjectMap(bescheidItem)) .bodyObject(buildObjectMap(bescheidId, bescheidStatus))
.build(); .build();
} }
Map<String, Object> buildObjectMap(AttachedItem bescheidItem) { Map<String, Object> buildObjectMap(String bescheidId, Bescheid.Status bescheidStatus) {
var bodyObject = new HashMap<String, Object>(); return Map.of(AttachedItem.PROPERTY_ID, bescheidId,
bodyObject.put(AttachedItem.PROPERTY_ID, bescheidItem.getId()); AttachedItem.PROPERTY_ITEM, Map.of(Bescheid.FIELD_STATUS, bescheidStatus.name()));
bodyObject.put(AttachedItem.PROPERTY_CLIENT, bescheidItem.getClient()); }
bodyObject.put(AttachedItem.PROPERTY_VORGANG_ID, bescheidItem.getVorgangId());
bodyObject.put(AttachedItem.PROPERTY_ITEM_NAME, bescheidItem.getItemName()); public Collection<AttachedItem> findAllBescheid(VorgangId vorgangId) {
bodyObject.put(AttachedItem.PROPERTY_VERSION, bescheidItem.getVersion()); return remoteService.findAllBescheid(vorgangId);
bodyObject.put(AttachedItem.PROPERTY_ITEM, bescheidItem.getItem());
return bodyObject;
} }
} }
/*
* 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.attacheditem;
import java.util.Map;
import java.util.Set;
import lombok.Builder;
import lombok.Getter;
@Builder(toBuilder = true)
@Getter
@Deprecated(since = "2.6.0")
public class BescheidItem {
static final Set<String> ACCEPTED_SEND_BY_VALUES = Set.of("POSTFACH", "MANUAL");
public static final String PROPERTY_ID = "id";
public static final String PROPERTY_CLIENT = "client";
public static final String PROPERTY_VORGANG_ID = "vorgangId";
public static final String PROPERTY_ITEM_NAME = "itemName";
public static final String PROPERTY_VERSION = "version";
public static final String PROPERTY_ITEM = "item";
public static final String FIELD_STATUS = "status";
public static final String FIELD_BESCHIEDEN_AM = "beschiedenAm";
public static final String FIELD_BEWILLIGT = "bewilligt";
public static final String FIELD_BESCHEID_DOCUMENT = "bescheidDocument";
public static final String FIELD_ATTACHMENTS = "attachments";
public static final String FIELD_SEND_BY = "sendBy";
public static final String FIELD_NACHRICHT_TEXT = "nachrichtText";
public static final String FIELD_NACHRICHT_SUBJECT = "nachrichtSubject";
private String id;
@Builder.Default
private long version = 0L;
private String client;
private String vorgangId;
private String itemName;
private Map<String, Object> bescheidData;
public enum Status {
DRAFT, BESCHEID, SEND;
public boolean not(String value) {
return !hasValue(value);
}
public boolean hasValue(String value) {
return this.name().equalsIgnoreCase(value);
}
}
}
/*
* 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.attacheditem;
import static java.util.Objects.*;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import de.ozgcloud.bescheid.GrpcBescheid;
import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
@Deprecated(since = "2.6.0")
public class BescheidItemMapper {
private final GrpcObjectMapper grpcObjectMapper;
public Stream<BescheidItem> fromFindVorgangAttachedItemResponse(GrpcFindVorgangAttachedItemResponse grpcResponse) {
return grpcResponse.getVorgangAttachedItemsList().stream()
.map(this::mapFromVorgangAttachedItem);
}
BescheidItem mapFromVorgangAttachedItem(GrpcVorgangAttachedItem item) {
return BescheidItem.builder()
.id(item.getId())
.version(item.getVersion())
.client(item.getClient())
.vorgangId(item.getVorgangId())
.itemName(item.getItemName())
.bescheidData(grpcObjectMapper.mapFromGrpc(item.getItem()))
.build();
}
public GrpcBescheid toBescheid(BescheidItem bescheid) {
var bescheidBuilder = GrpcBescheid.newBuilder().setVersion(bescheid.getVersion());
Optional.ofNullable(bescheid.getId()).ifPresent(bescheidBuilder::setId);
var bescheidData = bescheid.getBescheidData();
Optional.ofNullable(MapUtils.getString(bescheidData, BescheidItem.FIELD_BESCHIEDEN_AM)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setBeschiedenAm);
Optional.ofNullable(MapUtils.getBoolean(bescheidData, BescheidItem.FIELD_BEWILLIGT)).ifPresent(bescheidBuilder::setBewilligt);
Optional.ofNullable(MapUtils.getString(bescheidData, BescheidItem.FIELD_BESCHEID_DOCUMENT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setBescheidDocument);
Optional.ofNullable(MapUtils.getString(bescheidData, BescheidItem.FIELD_SEND_BY)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setSendBy);
Optional.ofNullable(MapUtils.getString(bescheidData, BescheidItem.FIELD_NACHRICHT_TEXT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setNachrichtText);
Optional.ofNullable(MapUtils.getString(bescheidData, BescheidItem.FIELD_NACHRICHT_SUBJECT)).map(StringUtils::trimToNull)
.ifPresent(bescheidBuilder::setNachrichtSubject);
Optional.ofNullable(bescheidData.get(BescheidItem.FIELD_ATTACHMENTS)).map(this::toAttachments).ifPresent(bescheidBuilder::addAllAttachments);
return bescheidBuilder.build();
}
@SuppressWarnings("unchecked")
Collection<String> toAttachments(Object attachmentsObject) {
if (attachmentsObject instanceof Collection<?> attachments) {
return (Collection<String>) attachments;
}
if (attachmentsObject instanceof String attachment) {
attachment = StringUtils.trimToNull(attachment);
if (nonNull(attachment)) {
return List.of(attachment);
}
} else if (nonNull(attachmentsObject)) {
return List.of(String.valueOf(attachmentsObject));
}
return null; //NOSONAR
}
}
...@@ -33,7 +33,7 @@ import lombok.NoArgsConstructor; ...@@ -33,7 +33,7 @@ import lombok.NoArgsConstructor;
class Utils { class Utils {
public static String extractClient(Command command) { public static String extractClient(Command command) {
return MapUtils.getString(command.getBodyObject(), BescheidItem.PROPERTY_CLIENT); return MapUtils.getString(command.getBodyObject(), AttachedItem.PROPERTY_CLIENT);
} }
} }
...@@ -27,13 +27,17 @@ import static de.ozgcloud.bescheid.attacheditem.AttachedItemService.*; ...@@ -27,13 +27,17 @@ import static de.ozgcloud.bescheid.attacheditem.AttachedItemService.*;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor;
import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest; import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest; import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
import de.ozgcloud.vorgang.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub; import de.ozgcloud.vorgang.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub;
...@@ -45,9 +49,9 @@ import net.devh.boot.grpc.client.inject.GrpcClient; ...@@ -45,9 +49,9 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
@Log4j2 @Log4j2
class VorgangAttachedItemRemoteService { class VorgangAttachedItemRemoteService {
private static final Comparator<BescheidItem> BY_BESCHIEDEN_AM_DESC = (bescheid1, bescheid2) -> { private static final Comparator<AttachedItem> BY_BESCHIEDEN_AM_DESC = (bescheid1, bescheid2) -> {
var beschiedenAm1 = LocalDate.parse(MapUtils.getString(bescheid1.getBescheidData(), BescheidItem.FIELD_BESCHIEDEN_AM)); var beschiedenAm1 = LocalDate.parse(MapUtils.getString(bescheid1.getItem(), Bescheid.FIELD_BESCHIEDEN_AM));
var beschiedenAm2 = LocalDate.parse(MapUtils.getString(bescheid2.getBescheidData(), BescheidItem.FIELD_BESCHIEDEN_AM)); var beschiedenAm2 = LocalDate.parse(MapUtils.getString(bescheid2.getItem(), Bescheid.FIELD_BESCHIEDEN_AM));
return beschiedenAm2.compareTo(beschiedenAm1); return beschiedenAm2.compareTo(beschiedenAm1);
}; };
...@@ -56,14 +60,16 @@ class VorgangAttachedItemRemoteService { ...@@ -56,14 +60,16 @@ class VorgangAttachedItemRemoteService {
@Autowired @Autowired
private ClientInterceptor bescheidCallContextInterceptor; private ClientInterceptor bescheidCallContextInterceptor;
@Autowired @Autowired
private BescheidItemMapper bescheidItemMapper;
@Autowired
private AttachedItemMapper attachedItemMapper; private AttachedItemMapper attachedItemMapper;
public Optional<BescheidItem> findBescheidDraft(String vorgangId) { public Optional<AttachedItem> findBescheidDraft(String vorgangId) {
return findBescheidDraft(buildFindRequest(vorgangId)); return findBescheidDraft(buildFindRequest(vorgangId));
} }
public List<AttachedItem> findAllBescheid(VorgangId vorgangId) {
return findAllBescheid(buildFindRequest(vorgangId.toString())).toList();
}
GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) { GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) {
return GrpcFindVorgangAttachedItemRequest.newBuilder() return GrpcFindVorgangAttachedItemRequest.newBuilder()
.setVorgangId(vorgangId) .setVorgangId(vorgangId)
...@@ -72,10 +78,8 @@ class VorgangAttachedItemRemoteService { ...@@ -72,10 +78,8 @@ class VorgangAttachedItemRemoteService {
.build(); .build();
} }
Optional<BescheidItem> findBescheidDraft(GrpcFindVorgangAttachedItemRequest request) { Optional<AttachedItem> findBescheidDraft(GrpcFindVorgangAttachedItemRequest request) {
var grpcResponse = getServiceStub().find(request); var bescheidItems = findAllBescheid(request).filter(this::hasStatusDraft).toList();
var bescheidItems = bescheidItemMapper.fromFindVorgangAttachedItemResponse(grpcResponse).filter(this::hasStatusDraft)
.sorted(BY_BESCHIEDEN_AM_DESC).toList();
if (bescheidItems.size() > 1) { if (bescheidItems.size() > 1) {
LOG.error("Found more than one ({}) draft bescheid for vorgangId: {}. Return one with last beschiedenAm date", bescheidItems.size(), LOG.error("Found more than one ({}) draft bescheid for vorgangId: {}. Return one with last beschiedenAm date", bescheidItems.size(),
bescheidItems.getFirst().getVorgangId()); bescheidItems.getFirst().getVorgangId());
...@@ -83,13 +87,19 @@ class VorgangAttachedItemRemoteService { ...@@ -83,13 +87,19 @@ class VorgangAttachedItemRemoteService {
return bescheidItems.isEmpty() ? Optional.empty() : Optional.of(bescheidItems.getFirst()); return bescheidItems.isEmpty() ? Optional.empty() : Optional.of(bescheidItems.getFirst());
} }
boolean hasStatusDraft(BescheidItem bescheidItem) { Stream<AttachedItem> findAllBescheid(GrpcFindVorgangAttachedItemRequest request) {
return BescheidItem.Status.DRAFT.hasValue(MapUtils.getString(bescheidItem.getBescheidData(), BescheidItem.FIELD_STATUS)); var grpcResponse = getServiceStub().find(request);
return grpcResponse.getVorgangAttachedItemsList().stream().map(attachedItemMapper::mapFromVorgangAttachedItem)
.sorted(BY_BESCHIEDEN_AM_DESC);
}
boolean hasStatusDraft(AttachedItem bescheidItem) {
return Bescheid.Status.DRAFT.hasValue(bescheidItem.getItem().get(Bescheid.FIELD_STATUS));
} }
public BescheidItem getBescheid(String bescheidId) { public AttachedItem getBescheid(String bescheidId) {
var grpcVorgangAttachedItemResponse = getServiceStub().getById(buildGetByIdRequest(bescheidId)); var grpcVorgangAttachedItemResponse = getServiceStub().getById(buildGetByIdRequest(bescheidId));
return bescheidItemMapper.mapFromVorgangAttachedItem(grpcVorgangAttachedItemResponse.getVorgangAttachedItem()); return attachedItemMapper.mapFromVorgangAttachedItem(grpcVorgangAttachedItemResponse.getVorgangAttachedItem());
} }
public AttachedItem getItem(String id) { public AttachedItem getItem(String id) {
......
...@@ -31,7 +31,7 @@ import lombok.RequiredArgsConstructor; ...@@ -31,7 +31,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ClientAttributeService { public class ClientAttributeService {
public static final String ATTRIBUTE_NAME_ANTRAG_BEWILLIGT = "ANTRAG_BEWILLIGT"; public static final String ATTRIBUTE_NAME_ANTRAG_BEWILLIGT = "antragBewilligt";
private final ClientAttributeRemoteService bescheidClientAttributeRemoteService; private final ClientAttributeRemoteService bescheidClientAttributeRemoteService;
......
...@@ -2,29 +2,43 @@ package de.ozgcloud.bescheid.nachricht; ...@@ -2,29 +2,43 @@ package de.ozgcloud.bescheid.nachricht;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
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.bescheid.Bescheid; import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.vorgang.Vorgang.PostfachAddress; import de.ozgcloud.bescheid.vorgang.Vorgang.PostfachAddress;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@Service @Service
@Log4j2 @Log4j2
@RequiredArgsConstructor
public class NachrichtService { public class NachrichtService {
@Autowired public static final String SEND_POSTFACH_NACHRICHT_ORDER = "SEND_POSTFACH_NACHRICHT";
private NachrichtRemoteService remoteService; public static final String FIELD_POSTFACH_ID = "postfachId";
static final String FIELD_REPLY_OPTION = "replyOption";
static final String REPLY_OPTION = "POSSIBLE";
static final String FIELD_SUBJECT = "subject";
static final String FIELD_MAIL_BODY = "mailBody";
static final String FIELD_ATTACHMENTS = "attachments";
@Autowired private final NachrichtRemoteService remoteService;
private Configuration freemarkerCfg; private final Configuration freemarkerCfg;
private final OzgCloudCommandService commandService;
private final CommandMapper commandMapper;
static final String SUBJECT = "Ihr Antrag"; static final String SUBJECT = "Ihr Antrag";
...@@ -45,14 +59,6 @@ public class NachrichtService { ...@@ -45,14 +59,6 @@ public class NachrichtService {
.build()); .build());
} }
Optional<PostfachAddress> getAddress(Bescheid bescheid) {
var serviceKonto = bescheid.getServiceKonto();
if (Objects.nonNull(serviceKonto)) {
return Optional.of(serviceKonto.getPostfachAddresses().get(0));
}
return Optional.empty();
}
String buildMessage(Bescheid bescheid) { String buildMessage(Bescheid bescheid) {
return bescheid.getNachrichtText() return bescheid.getNachrichtText()
.orElseGet(() -> fillTemplate(TEMPLATE_FILE, bescheid)); .orElseGet(() -> fillTemplate(TEMPLATE_FILE, bescheid));
...@@ -77,4 +83,46 @@ public class NachrichtService { ...@@ -77,4 +83,46 @@ public class NachrichtService {
throw new TechnicalException("Error loading mail template", e); throw new TechnicalException("Error loading mail template", e);
} }
} }
public void sendNachricht(Bescheid bescheid) {
var commandToCreate = buildSendBescheidCommand(bescheid);
commandService.createAndWaitUntilDone(commandToCreate);
}
OzgCloudCommand buildSendBescheidCommand(Bescheid bescheid) {
return OzgCloudCommand.builder()
.vorgangId(commandMapper.toOzgCloudVorgangId(bescheid.getVorgangId().toString()))
.relationId(commandMapper.mapRelationId(bescheid.getVorgangId().toString()))
.order(SEND_POSTFACH_NACHRICHT_ORDER)
.createdBy(commandMapper.toOzgCloudUserId(bescheid.getCreatedBy().toString()))
.bodyObject(buildSendNachrichtCommandBody(bescheid))
.build();
}
Map<String, Object> buildSendNachrichtCommandBody(Bescheid bescheid) {
return Map.of(FIELD_POSTFACH_ID, getPostfachId(bescheid),
FIELD_REPLY_OPTION, REPLY_OPTION,
FIELD_SUBJECT, bescheid.getNachrichtSubject().orElse(SUBJECT),
FIELD_MAIL_BODY, bescheid.getNachrichtText().orElse(StringUtils.EMPTY),
FIELD_ATTACHMENTS, bescheid.getBescheidFileId().toString()
);
}
String getPostfachId(Bescheid bescheid) {
return getAddress(bescheid)
.map(PostfachAddress::getIdentifier)
.map(identifier -> MapUtils.getString(identifier, FIELD_POSTFACH_ID))
.filter(StringUtils::isNotBlank)
.orElseThrow(() -> new TechnicalException("No PostfachId found for Bescheid (vorgangId: %s)".formatted(bescheid.getVorgangId())));
}
Optional<PostfachAddress> getAddress(Bescheid bescheid) {
var serviceKonto = bescheid.getServiceKonto();
if (Objects.nonNull(serviceKonto)) {
return Optional.of(serviceKonto.getPostfachAddresses().get(0));
}
return Optional.empty();
}
} }
...@@ -26,7 +26,7 @@ public class VorgangService { ...@@ -26,7 +26,7 @@ public class VorgangService {
bescheiden(getById(VorgangId.from(vorgangId))); bescheiden(getById(VorgangId.from(vorgangId)));
} }
public void bescheiden(Vorgang vorgang) { private void bescheiden(Vorgang vorgang) {
commandService.createAndWaitUntilDone(buildBescheidenCommand(vorgang)); commandService.createAndWaitUntilDone(buildBescheidenCommand(vorgang));
} }
...@@ -39,8 +39,4 @@ public class VorgangService { ...@@ -39,8 +39,4 @@ public class VorgangService {
.build(); .build();
} }
public Vorgang.ServiceKonto getServiceKonto(String vorgangId) {
var vorgang = getById(VorgangId.from(vorgangId));
return vorgang.getServiceKonto();
}
} }
...@@ -38,8 +38,8 @@ import de.ozgcloud.apilib.common.command.OzgCloudCommandService; ...@@ -38,8 +38,8 @@ import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
import de.ozgcloud.apilib.common.command.grpc.CommandMapper; import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
import de.ozgcloud.bescheid.Bescheid; import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor;
import de.ozgcloud.bescheid.attacheditem.AttachedItem;
import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService;
import de.ozgcloud.bescheid.attacheditem.BescheidItem;
import de.ozgcloud.command.Command; import de.ozgcloud.command.Command;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
...@@ -77,9 +77,9 @@ public class DocumentService { ...@@ -77,9 +77,9 @@ public class DocumentService {
} }
void validateBescheidItem(String bescheidId) { void validateBescheidItem(String bescheidId) {
var bescheidData = attachedItemService.getBescheidItem(bescheidId).getBescheidData(); var bescheidData = attachedItemService.getBescheidItem(bescheidId).getItem();
var status = MapUtils.getString(bescheidData, BescheidItem.FIELD_STATUS); var status = MapUtils.getString(bescheidData, Bescheid.FIELD_STATUS);
if (BescheidItem.Status.DRAFT.not(status)) { if (Bescheid.Status.DRAFT.not(status)) {
throw new TechnicalException("Bescheid is not in draft status"); throw new TechnicalException("Bescheid is not in draft status");
} }
} }
...@@ -95,10 +95,10 @@ public class DocumentService { ...@@ -95,10 +95,10 @@ public class DocumentService {
Map<String, Object> buildAttachedItem(Command command, Map<String, Object> itemMap) { Map<String, Object> buildAttachedItem(Command command, Map<String, Object> itemMap) {
var result = new HashMap<String, Object>(); var result = new HashMap<String, Object>();
result.put(BescheidItem.PROPERTY_VORGANG_ID, command.getVorgangId()); result.put(AttachedItem.PROPERTY_VORGANG_ID, command.getVorgangId());
result.put(BescheidItem.PROPERTY_CLIENT, BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME); result.put(AttachedItem.PROPERTY_CLIENT, BescheidCallContextAttachingInterceptor.BESCHEID_MANAGER_CLIENT_NAME);
result.put(BescheidItem.PROPERTY_ITEM_NAME, DOCUMENT_ITEM_NAME); result.put(AttachedItem.PROPERTY_ITEM_NAME, DOCUMENT_ITEM_NAME);
result.put(BescheidItem.PROPERTY_ITEM, itemMap); result.put(AttachedItem.PROPERTY_ITEM, itemMap);
return result; return result;
} }
......
...@@ -10,6 +10,7 @@ import java.util.Map; ...@@ -10,6 +10,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
...@@ -23,6 +24,7 @@ import org.springframework.context.ApplicationEventPublisher; ...@@ -23,6 +24,7 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import de.ozgcloud.bescheid.attacheditem.AttachedItem;
import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService;
import de.ozgcloud.bescheid.attacheditem.AttachedItemTestFactory; import de.ozgcloud.bescheid.attacheditem.AttachedItemTestFactory;
import de.ozgcloud.bescheid.binaryfile.BinaryFileService; import de.ozgcloud.bescheid.binaryfile.BinaryFileService;
...@@ -35,6 +37,7 @@ import de.ozgcloud.command.Command; ...@@ -35,6 +37,7 @@ import de.ozgcloud.command.Command;
import de.ozgcloud.command.CommandCreatedEventTestFactory; import de.ozgcloud.command.CommandCreatedEventTestFactory;
import de.ozgcloud.command.CommandFailedEvent; import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.command.CommandTestFactory; import de.ozgcloud.command.CommandTestFactory;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.document.BescheidDocumentCreatedEvent; import de.ozgcloud.document.BescheidDocumentCreatedEvent;
import de.ozgcloud.document.DocumentService; import de.ozgcloud.document.DocumentService;
...@@ -495,18 +498,40 @@ class BescheidEventListenerTest { ...@@ -495,18 +498,40 @@ class BescheidEventListenerTest {
@Nested @Nested
class TestDoSendBescheid { class TestDoSendBescheid {
private static final Command COMMAND = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID)
.relationVersion(AttachedItemTestFactory.VERSION).build();
@Captor @Captor
private ArgumentCaptor<BescheidSentEvent> bescheidSentEventCaptor; private ArgumentCaptor<BescheidSentEvent> bescheidSentEventCaptor;
@Test @Test
void shouldCallSendBescheid() { void shouldThrowExceptionIfUnkonwnSendBy() {
var item = AttachedItemTestFactory.createBescheidItem();
item.put(Bescheid.FIELD_SEND_BY, "unknown");
var bescheidItem = AttachedItemTestFactory.createBescheidBuilder().item(item).build();
when(attachedItemService.getItem(any())).thenReturn(bescheidItem);
var command = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID).build();
Assertions.assertThrows(TechnicalException.class, () -> listener.doSendBescheid(command));
}
@DisplayName("manually")
@Nested
class TestManually {
private static final Command COMMAND = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID)
.relationVersion(AttachedItemTestFactory.VERSION).bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
private final AttachedItem bescheidItem = AttachedItemTestFactory.createBescheid();
@BeforeEach
void init() {
when(attachedItemService.getItem(any())).thenReturn(bescheidItem);
}
@Test
void shouldCallSendBescheid() {
listener.doSendBescheid(COMMAND); listener.doSendBescheid(COMMAND);
verify(service).sendBescheidManually(AttachedItemTestFactory.ID, AttachedItemTestFactory.VERSION); verify(service).sendBescheidManually(bescheidItem, AttachedItemTestFactory.VERSION);
verify(service, never()).sendBescheidPostfachMail(any(), anyLong());
} }
@Test @Test
...@@ -518,51 +543,38 @@ class BescheidEventListenerTest { ...@@ -518,51 +543,38 @@ class BescheidEventListenerTest {
} }
} }
@DisplayName("per postfach mail")
@Nested @Nested
class TestOnSendPostfachMailCommand { class TestPostfachMail {
private final Command command = CommandTestFactory.create();
@Test private static final Command COMMAND = CommandTestFactory.createBuilder().relationId(AttachedItemTestFactory.ID)
void shouldCallRunWithSecurityContext() { .relationVersion(AttachedItemTestFactory.VERSION).bodyObject(AttachedItemTestFactory.createBescheidItem()).build();
listener.onSendPostfachMailCommand(CommandCreatedEventTestFactory.withCommand(command));
verify(listener).runWithSecurityContext(eq(command), any());
}
@Test private AttachedItem bescheidItem;
void shouldExecuteDoSendPostfachMail() {
listener.onSendPostfachMailCommand(CommandCreatedEventTestFactory.withCommand(command));
verify(listener).doSendPostfachMail(command); @BeforeEach
} void init() {
var item = AttachedItemTestFactory.createBescheidItem();
item.put(Bescheid.FIELD_SEND_BY, Bescheid.SendBy.NACHRICHT.name());
bescheidItem = AttachedItemTestFactory.createBescheidBuilder().item(item).build();
when(attachedItemService.getItem(any())).thenReturn(bescheidItem);
} }
@Nested
class TestDoSendPostfachMail {
@Captor
private ArgumentCaptor<BescheidSentEvent> bescheidSentEventCaptor;
@Test @Test
void shouldCallBescheidService() { void shouldCallBescheidService() {
var bescheidId = "bescheid-id"; listener.doSendBescheid(COMMAND);
var bescheidVersion = 1L;
var command = CommandTestFactory.createBuilder().relationId(bescheidId).relationVersion(bescheidVersion).build();
listener.doSendPostfachMail(command);
verify(service).sendBescheidPostfachMail(bescheidId, bescheidVersion); verify(service).sendBescheidPostfachMail(bescheidItem, AttachedItemTestFactory.VERSION);
verify(service, never()).sendBescheidManually(any(), anyLong());
} }
@Test @Test
void shouldPublishEvent() { void shouldPublishEvent() {
var command = CommandTestFactory.createBuilder().relationVersion(0L).build(); listener.doSendBescheid(COMMAND);
listener.doSendPostfachMail(command);
verify(eventPublisher).publishEvent(bescheidSentEventCaptor.capture()); verify(eventPublisher).publishEvent(bescheidSentEventCaptor.capture());
assertThat(bescheidSentEventCaptor.getValue().getCommand()).isEqualTo(command); assertThat(bescheidSentEventCaptor.getValue().getCommand()).isEqualTo(COMMAND);
}
} }
} }
......
...@@ -4,8 +4,11 @@ import static org.assertj.core.api.Assertions.*; ...@@ -4,8 +4,11 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.util.Collections;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
...@@ -14,9 +17,12 @@ import org.mockito.InjectMocks; ...@@ -14,9 +17,12 @@ import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy; import org.mockito.Spy;
import de.ozgcloud.bescheid.attacheditem.AttachedItem;
import de.ozgcloud.bescheid.attacheditem.AttachedItemMapper;
import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService;
import de.ozgcloud.bescheid.attacheditem.BescheidItemMapper; import de.ozgcloud.bescheid.attacheditem.AttachedItemTestFactory;
import de.ozgcloud.bescheid.attacheditem.BescheidItemTestFactory; import de.ozgcloud.bescheid.vorgang.VorgangId;
import de.ozgcloud.command.CommandTestFactory;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
class BescheidGrpcServiceTest { class BescheidGrpcServiceTest {
...@@ -28,7 +34,11 @@ class BescheidGrpcServiceTest { ...@@ -28,7 +34,11 @@ class BescheidGrpcServiceTest {
@Mock @Mock
private AttachedItemService attachedItemService; private AttachedItemService attachedItemService;
@Mock @Mock
private BescheidItemMapper mapper; private AttachedItemMapper attachedItemMapper;
@Mock
private BescheidService bescheidService;
@Mock
private GrpcBescheidMapper grpcBescheidMapper;
@Nested @Nested
class TestGetBescheidDraft { class TestGetBescheidDraft {
...@@ -44,19 +54,20 @@ class BescheidGrpcServiceTest { ...@@ -44,19 +54,20 @@ class BescheidGrpcServiceTest {
@Test @Test
void shouldBuildResponse() { void shouldBuildResponse() {
when(mapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create()); when(attachedItemMapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create());
when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); var bescheidItem = AttachedItemTestFactory.createBescheid();
when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(bescheidItem));
service.getBescheidDraft(request, responseObserver); service.getBescheidDraft(request, responseObserver);
verify(service).buildResponse(any()); verify(service).buildGetBescheidDraftResponse(bescheidItem);
} }
@Test @Test
void shouldCallNext() { void shouldCallNext() {
when(mapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create()); when(attachedItemMapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create());
when(service.buildResponse(any())).thenReturn(response); when(service.buildGetBescheidDraftResponse(any())).thenReturn(response);
when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(AttachedItemTestFactory.createBescheid()));
service.getBescheidDraft(request, responseObserver); service.getBescheidDraft(request, responseObserver);
...@@ -81,27 +92,189 @@ class BescheidGrpcServiceTest { ...@@ -81,27 +92,189 @@ class BescheidGrpcServiceTest {
} }
@Nested @Nested
class TestBuildResponse { class TestBuildGetBescheidDraftResponse {
@Test @Test
void shouldCallMapper() { void shouldCallMapper() {
when(mapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create()); when(attachedItemMapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create());
var bescheid = BescheidItemTestFactory.create(); var bescheid = AttachedItemTestFactory.createBescheid();
service.buildResponse(bescheid); service.buildGetBescheidDraftResponse(bescheid);
verify(mapper).toBescheid(bescheid); verify(attachedItemMapper).toBescheid(bescheid);
} }
@Test @Test
void shouldSetBescheid() { void shouldSetBescheid() {
var grpcBescheid = GrpcBescheidTestFactory.create(); var grpcBescheid = GrpcBescheidTestFactory.create();
when(mapper.toBescheid(any())).thenReturn(grpcBescheid); when(attachedItemMapper.toBescheid(any())).thenReturn(grpcBescheid);
var response = service.buildResponse(BescheidItemTestFactory.create()); var response = service.buildGetBescheidDraftResponse(AttachedItemTestFactory.createBescheid());
assertThat(response.getBescheid()).isEqualTo(grpcBescheid); assertThat(response.getBescheid()).isEqualTo(grpcBescheid);
} }
} }
@Nested
class TestGetConfig {
private static final GrpcBescheidManagerConfigResponse RESPONSE = GrpcBescheidManagerConfigResponse.newBuilder().build();
@Mock
private GrpcBescheidManagerConfigRequest request;
@Mock
private StreamObserver<GrpcBescheidManagerConfigResponse> responseObserver;
@Captor
private ArgumentCaptor<GrpcBescheidManagerConfigResponse> responseCaptor;
@Test
void shouldCallBescheidService() {
getConfig();
verify(bescheidService).getConfig();
}
@Test
void shouldCallGrpcBescheidMapper() {
var config = BescheidManagerConfigTestFactory.create();
when(bescheidService.getConfig()).thenReturn(config);
getConfig();
verify(grpcBescheidMapper).fromBescheidManagerConfig(config);
}
@Test
void shouldCallNext() {
when(grpcBescheidMapper.fromBescheidManagerConfig(any())).thenReturn(RESPONSE);
getConfig();
verify(responseObserver).onNext(RESPONSE);
}
@Test
void shouldCallCompleted() {
getConfig();
verify(responseObserver).onCompleted();
}
private void getConfig() {
service.getConfig(request, responseObserver);
}
}
@Nested
class TestGetAll {
private static final GrpcGetAllBescheidResponse RESPONSE = GrpcGetAllBescheidResponse.newBuilder().build();
@Mock
private GrpcGetAllBescheidRequest request;
@Mock
private StreamObserver<GrpcGetAllBescheidResponse> responseObserver;
@Captor
private ArgumentCaptor<GrpcGetAllBescheidResponse> responseCaptor;
@Captor
private ArgumentCaptor<VorgangId> vorgangIdCaptor;
@BeforeEach
void init() {
when(request.getVorgangId()).thenReturn(CommandTestFactory.VORGANG_ID);
doReturn(RESPONSE).when(service).buildGetAllBescheidResponse(anyCollection());
}
@Test
void shouldCallFindAllBescheid() {
service.getAll(request, responseObserver);
verify(attachedItemService).findAllBescheid(vorgangIdCaptor.capture());
assertThat(vorgangIdCaptor.getValue()).hasToString(CommandTestFactory.VORGANG_ID);
}
@Test
void shouldCallBuildResponse() {
var expectedBescheidItem = AttachedItemTestFactory.createBescheid();
when(attachedItemService.findAllBescheid(any())).thenReturn(List.of(expectedBescheidItem));
service.getAll(request, responseObserver);
verify(service).buildGetAllBescheidResponse(List.of(expectedBescheidItem));
}
@Test
void shouldCallOnNext() {
service.getAll(request, responseObserver);
verify(responseObserver).onNext(RESPONSE);
}
@Test
void shouldCallOnCompleted() {
service.getAll(request, responseObserver);
verify(responseObserver).onCompleted();
}
}
@Nested
class TestBuildResponseAllBescheid {
private static final GrpcBescheid GRPC_BESCHEID = GrpcBescheidTestFactory.create();
@Mock
private AttachedItem attachedItem;
@BeforeEach
void init() {
doReturn(Collections.singletonList(GRPC_BESCHEID)).when(service).mapBescheid(anyCollection());
}
@Test
void shouldCallMapBescheid() {
var bescheidItems = Collections.singleton(attachedItem);
service.buildGetAllBescheidResponse(bescheidItems);
verify(service).mapBescheid(bescheidItems);
}
@Test
void shouldReturnResponse() {
var bescheidItems = Collections.singleton(attachedItem);
var response = service.buildGetAllBescheidResponse(bescheidItems);
assertThat(response.getBescheidList()).containsExactly(GRPC_BESCHEID);
}
}
@Nested
class TestMapBescheid {
private static final GrpcBescheid GRPC_BESCHEID = GrpcBescheidTestFactory.create();
@Mock
private AttachedItem attachedItem;
@BeforeEach
void init() {
when(attachedItemMapper.toBescheid(attachedItem)).thenReturn(GRPC_BESCHEID);
}
@Test
void shouldCallMapper() {
service.mapBescheid(Collections.singleton(attachedItem));
verify(attachedItemMapper).toBescheid(attachedItem);
}
@Test
void shouldSetBescheid() {
var result = service.mapBescheid(Collections.singleton(attachedItem));
assertThat(result).containsExactly(GRPC_BESCHEID);
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment