Skip to content
Snippets Groups Projects
Commit 8bcee4d1 authored by OZGCloud's avatar OZGCloud
Browse files

Merge branch 'master' of git@git.ozg-sh.de:mgm/pluto.git

parents 320b496c bdaf3937
Branches
Tags
No related merge requests found
Showing
with 273 additions and 54 deletions
......@@ -24,4 +24,7 @@ service CommandService {
rpc GetPendingCommands(GrpcGetPendingCommandsRequest) returns (GrpcGetPendingCommandsResponse){
}
rpc FindCommands(GrpcFindCommandsRequest) returns (GrpcCommandsResponse) {
}
}
\ No newline at end of file
......@@ -12,16 +12,17 @@ option java_outer_classname = "CommandModelProto";
enum GrpcOrder {
VORGANG_ANNEHMEN = 0;
VORGANG_VERWERFEN = 1;
VORGANG_ZURUECKHOLEN = 2;
VORGANG_BEARBEITEN = 3;
VORGANG_BESCHEIDEN = 4;
VORGANG_ZURUECKSTELLEN = 5;
VORGANG_ABSCHLIESSEN = 6;
VORGANG_WIEDEREROEFFNEN = 7;
REDIRECT_VORGANG = 8;
UNDEFINED = 0;
VORGANG_ANNEHMEN = 1;
VORGANG_VERWERFEN = 2;
VORGANG_ZURUECKHOLEN = 3;
VORGANG_BEARBEITEN = 4;
VORGANG_BESCHEIDEN = 5;
VORGANG_ZURUECKSTELLEN = 6;
VORGANG_ABSCHLIESSEN = 7;
VORGANG_WIEDEREROEFFNEN = 8;
REDIRECT_VORGANG = 9;
CREATE_WIEDERVORLAGE = 15;
EDIT_WIEDERVORLAGE = 16;
......@@ -68,10 +69,13 @@ message GrpcGetCommandRequest {
message GrpcCommand {
string id = 1;
string createdAt = 2;
string createdBy = 3;
string status = 4;
string relationId = 5;
GrpcOrder order = 6;
string finishedAt = 3;
string createdBy = 10;
string createdByName = 11;
string status = 12;
string relationId = 13;
GrpcOrder order = 15;
GrpcRedirectRequest redirectRequest = 16;
}
message GrpcExistsPendingCommandsRequest {
......@@ -88,11 +92,23 @@ message GrpcRedirectRequest {
string password = 2;
}
message GrpcGetPendingCommandsRequest {
de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
string vorgangId = 2;
}
message GrpcFindCommandsRequest {
de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
string vorgangId = 2;
repeated string status = 3;
GrpcOrder order = 4;
}
message GrpcGetPendingCommandsResponse {
repeated GrpcCommand command = 1;
}
message GrpcCommandsResponse {
repeated GrpcCommand command = 1;
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ public class Command {
private String id;
private ZonedDateTime createdAt;
private ZonedDateTime finishedAt;
private String createdBy;
private String createdByName;
......
......@@ -3,6 +3,8 @@ package de.itvsh.ozg.pluto.command;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
......@@ -17,9 +19,11 @@ import org.springframework.stereotype.Repository;
class CommandRepository {
private static final String MONGODB_ID = "id";
private static final String MONDODB_STATUS = "status";
private static final String MONDODB_RELATION_ID = "relationId";
private static final String MONDODB_RELATION_VERSION = "relationVersion";
private static final String MONGODB_STATUS = "status";
private static final String MONGODB_FINISHED_AT = "finishedAt";
private static final String MONGODB_RELATION_ID = "relationId";
private static final String MONGODB_RELATION_VERSION = "relationVersion";
private static final String MONGODB_ORDER = "order";
@Autowired
private MongoOperations mongoOperations;
......@@ -28,11 +32,17 @@ class CommandRepository {
return mongoOperations.save(command);
}
void finishCommand(String commandId) {
mongoOperations.updateFirst(
query(where(MONGODB_ID).is(commandId)),
new Update().set(MONGODB_STATUS, CommandStatus.FINISHED).set(MONGODB_FINISHED_AT, ZonedDateTime.now()),
Command.class);
}
void updateCommandStatus(String commandId, CommandStatus status) {
mongoOperations.updateFirst(
query(where(MONGODB_ID).is(commandId)),
new Update()
.set(MONDODB_STATUS, status),
new Update().set(MONGODB_STATUS, status),
Command.class);
}
......@@ -40,8 +50,8 @@ class CommandRepository {
mongoOperations.updateFirst(
query(where(MONGODB_ID).is(commandId)),
new Update()
.set(MONDODB_STATUS, status)
.set(MONDODB_RELATION_VERSION, relationVersion),
.set(MONGODB_STATUS, status)
.set(MONGODB_RELATION_VERSION, relationVersion),
Command.class);
}
......@@ -60,7 +70,22 @@ class CommandRepository {
private Query buildPendingCommandQuery(String relationId) {
return query(new Criteria().andOperator(
where(MONDODB_RELATION_ID).is(relationId),
where(MONDODB_STATUS).in(CommandStatus.PENDING.name(), CommandStatus.REVOKE_PENDING.name())));
where(MONGODB_RELATION_ID).is(relationId),
where(MONGODB_STATUS).in(CommandStatus.PENDING.name(), CommandStatus.REVOKE_PENDING.name())));
}
List<Command> findCommands(String relationId, Collection<CommandStatus> status, Optional<Order> order) {
return mongoOperations.find(buildCommandsQuery(relationId, status, order), Command.class);
}
private Query buildCommandsQuery(String relationId, Collection<CommandStatus> status, Optional<Order> commandOrder) {
var result = query(new Criteria().andOperator(
where(MONGODB_RELATION_ID).is(relationId)));
if (!status.isEmpty())
result.addCriteria(new Criteria(MONGODB_STATUS).in(status));
commandOrder.map(Order::name).ifPresent(order -> result.addCriteria(new Criteria(MONGODB_ORDER).is(order)));
return result;
}
}
package de.itvsh.ozg.pluto.command;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -37,6 +39,7 @@ public class CommandService {
.relationId(request.getRelationId())
.relationVersion(request.getRelationVersion())
.previousStatus(actualStatus)
.redirectRequest(request.getRedirectRequest())
.wiedervorlage(request.getWiedervorlage())
.kommentar(request.getKommentar())
.build();
......@@ -57,7 +60,7 @@ public class CommandService {
}
public void setCommandFinished(String commandId) {
updateCommandStatus(commandId, CommandStatus.FINISHED);
repository.finishCommand(commandId);
}
public void setCommandRevoked(String commandId) {
......@@ -79,4 +82,8 @@ public class CommandService {
public List<Command> getPendingCommands(String relationId) {
return repository.getPendingCommands(relationId);
}
public Stream<Command> findCommands(String relationId, Collection<CommandStatus> status, Optional<Order> order) {
return repository.findCommands(relationId, status, order).stream();
}
}
\ No newline at end of file
......@@ -28,6 +28,7 @@ public interface GrpcCreateCommandRequestMapper {
CreateCommandRequest fromGrpc(GrpcCreateCommandRequest grpcRequest);
@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
@ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL)
Order map(GrpcOrder grpcOrder);
CallContext fromGrpc(GrpcCallContext callContext);
......
......@@ -6,7 +6,6 @@ import org.mapstruct.CollectionMappingStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.NullValueCheckStrategy;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
import de.itvsh.ozg.pluto.command.Kommentar;
import de.itvsh.ozg.pluto.kommentar.GrpcFindKommentarsByVorgangIdResponse;
......@@ -18,8 +17,6 @@ import de.itvsh.ozg.pluto.kommentar.GrpcKommentar;
collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
interface GrpcKommentarMapper {
GrpcKommentarMapper INSTANCE = Mappers.getMapper(GrpcKommentarMapper.class);
GrpcKommentar map(Kommentar kommentar);
default GrpcGetKommentarResponse toGrpc(Kommentar kommentar) {
......
package de.itvsh.ozg.pluto.command.status;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -9,19 +11,24 @@ import de.itvsh.ozg.pluto.command.Command;
import de.itvsh.ozg.pluto.command.CommandResponse;
import de.itvsh.ozg.pluto.command.CommandResponse.ResponseCode;
import de.itvsh.ozg.pluto.command.CommandService;
import de.itvsh.ozg.pluto.command.CommandStatus;
import de.itvsh.ozg.pluto.command.CreateCommandRequest;
import de.itvsh.ozg.pluto.command.GrpcCommandResponseMapper;
import de.itvsh.ozg.pluto.command.GrpcCreateCommandRequestMapper;
import de.itvsh.ozg.pluto.command.Order;
import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceImplBase;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcFindCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
import de.itvsh.ozg.pluto.grpc.command.GrpcRevokeCommandRequest;
import de.itvsh.ozg.pluto.vorgang.Vorgang;
import de.itvsh.ozg.pluto.vorgang.VorgangService;
......@@ -126,4 +133,21 @@ class GrpcVorgangCommandService extends CommandServiceImplBase {
.collect(Collectors.toList()))
.build();
}
@Override
public void findCommands(GrpcFindCommandsRequest request, StreamObserver<GrpcCommandsResponse> responseObserver) {
var statusList = request.getStatusList().stream().map(CommandStatus::valueOf).collect(Collectors.toList());
var order = Optional.of(request.getOrder()).filter(grpcOrder -> grpcOrder != GrpcOrder.UNDEFINED)
.map(grpcOrder -> Order.valueOf(grpcOrder.name()));
Stream<Command> commands = commandService.findCommands(request.getVorgangId(), statusList, order);
responseObserver.onNext(buildCommandsResponse(commands));
responseObserver.onCompleted();
}
private GrpcCommandsResponse buildCommandsResponse(Stream<Command> commands) {
return GrpcCommandsResponse.newBuilder().addAllCommand(commands.map(grpcCommandMapper::toGrpc).collect(Collectors.toList())).build();
}
}
......@@ -22,7 +22,7 @@ public class Vorgang {
static final String MONGODB_FIELDNAME_STATUS = "status";
public enum Status {
NEU, ANGENOMMEN, VERWORFEN, IN_BEARBEITUNG, BESCHIEDEN, ABGESCHLOSSEN, REDIRECT;
NEU, ANGENOMMEN, VERWORFEN, IN_BEARBEITUNG, BESCHIEDEN, ABGESCHLOSSEN, REDIRECT, WEITERGELEITET;
}
@Id
......
package de.itvsh.ozg.pluto.vorgang;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import de.itvsh.ozg.pluto.vorgang.redirect.VorgangRedirectedEvent;
@Component
public class VorgangEventListener {
@Autowired
private VorgangService service;
@EventListener
public void updateStatus(VorgangRedirectedEvent event) {
service.setStatusToWeitergeleitet(event.getSource());
}
}
package de.itvsh.ozg.pluto.vorgang;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.Optional;
......@@ -46,4 +46,13 @@ class VorgangRepository {
.set(Vorgang.MONGODB_FIELDNAME_STATUS, status),
Vorgang.class);
}
void updateStatusWithoutVersionCheck(String vorgangId, Status status) {
mongoOperations.updateFirst(
query(where(Vorgang.MONGODB_FIELDNAME_ID).is(vorgangId)),
new Update()
.inc(Vorgang.MONGODB_FIELDNAME_VERSION, 1)
.set(Vorgang.MONGODB_FIELDNAME_STATUS, status),
Vorgang.class);
}
}
......@@ -7,6 +7,7 @@ import org.springframework.stereotype.Service;
import de.itvsh.ozg.pluto.command.Command;
import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
import de.itvsh.ozg.pluto.vorgang.redirect.RedirectService;
@Service
public class VorgangService {
......@@ -14,6 +15,8 @@ public class VorgangService {
@Autowired
private VorgangRepository repository;
@Autowired
private RedirectService redirectService;
@Autowired
private ApplicationEventPublisher publisher;
public void createVorgang(Eingang eingang) {
......@@ -52,7 +55,16 @@ public class VorgangService {
}
public Vorgang redirect(Command command) {
return doUpdateStatus(command.getRelationId(), command.getRelationVersion(), Status.REDIRECT);
var vorgang = doUpdateStatus(command.getRelationId(), command.getRelationVersion(), Status.REDIRECT);
redirectService.redirectVorgang(vorgang, command);
return vorgang;
}
public Vorgang setStatusToWeitergeleitet(Command command) {
repository.updateStatusWithoutVersionCheck(command.getRelationId(), Status.WEITERGELEITET);
return getById(command.getRelationId());
}
public Vorgang revokeStatusChange(Command command) {
......
......@@ -47,9 +47,11 @@ public class RedirectService {
MailSendRequest createRedirectMail(Vorgang vorgang, Command command) {
// TODO add attachments
// TODO set subject
return MailSendRequest.builder()
.fromAddress(mailFrom)
.toAddress(command.getRedirectRequest().getEmail())
.subject("Wdgl Vorgang.")
.body(fillMailTemplate(vorgang))
.requestReference(command)
.build();
......
pluto:
redirect:
mail-from: ea@ozg-sh.de
\ No newline at end of file
......@@ -12,3 +12,7 @@ spring:
prefer-ip: true
url: http://localhost:8090
pluto:
redirect:
mail-from: ea@ozg-sh.de
logging:
level:
ROOT: WARN
'[de.itvsh]': INFO
'[de.itvsh]': INFO,
spring:
application:
......@@ -11,6 +11,12 @@ spring:
authentication-database: admin
freemarker:
cache: true
mail:
username: ea@ozg-sh.de
password: 8oD%jo!uxbrq
host: smtp.dd24.net
port: 587
properties.mail.smtp.starttls.enable: true
pluto:
redirect:
......
Sehr geehrte Damen und Herren,
#############################################################################
# TESTMAIL
#
# Diese Mail wurde von einem Test-System verschickt. Sollte Sie diese
# irrtümlich erhalten haben, löschen Sie sie bitte wieder.
# Vielen Dank
#
# TESTMAIL
#############################################################################
Sehr geehrte Damen und Herren,
anliegend übersende ich Ihnen zuständigkeitshalber einen Antrag ${antragsName} mit der Bitte um weitere Veranlassung.
Das Aktenzeichen lautet: ${eingangsKennzeichen}
......@@ -14,11 +23,11 @@
Antragsmanagement
[cid:${CONTENT_ID_1}]
[cid:]
einheitlicher ansprechpartner schleswig-holstein
im
[cid:${CONTENT_ID_2}]
[cid:]
IT Verbund Schleswig-Holstein
Anstalt öffentlichen Rechts
......
package de.itvsh.ozg.pluto.command.kommentar;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import java.util.UUID;
......@@ -8,6 +8,7 @@ import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import de.itvsh.ozg.pluto.command.KommentarTestFactory;
import de.itvsh.ozg.pluto.kommentar.GrpcFindKommentarsByVorgangIdResponse;
......@@ -15,7 +16,7 @@ import de.itvsh.ozg.pluto.kommentar.GrpcGetKommentarResponse;
class GrpcKommentarMapperTest {
private GrpcKommentarMapper mapper = GrpcKommentarMapper.INSTANCE;
private GrpcKommentarMapper mapper = Mappers.getMapper(GrpcKommentarMapper.class);
@Nested
class TestKommentarToGrpcResponse {
......
......@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
......@@ -19,20 +20,25 @@ import org.mockito.Spy;
import de.itvsh.ozg.pluto.command.Command;
import de.itvsh.ozg.pluto.command.CommandResponse;
import de.itvsh.ozg.pluto.command.CommandService;
import de.itvsh.ozg.pluto.command.CommandStatus;
import de.itvsh.ozg.pluto.command.CommandTestFactory;
import de.itvsh.ozg.pluto.command.CreateCommandRequest;
import de.itvsh.ozg.pluto.command.CreateCommandRequestTestFactory;
import de.itvsh.ozg.pluto.command.GrpcCommandResponseMapper;
import de.itvsh.ozg.pluto.command.GrpcCreateCommandRequestMapper;
import de.itvsh.ozg.pluto.command.Order;
import de.itvsh.ozg.pluto.common.grpc.StreamRecorder;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcFindCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsResponse;
import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
import de.itvsh.ozg.pluto.grpc.command.GrpcRevokeCommandRequest;
import de.itvsh.ozg.pluto.vorgang.Vorgang;
import de.itvsh.ozg.pluto.vorgang.VorgangService;
......@@ -311,4 +317,45 @@ class GrpcVorgangCommandServiceTest {
}
}
}
@Nested
class TestFindCommands {
private final GrpcFindCommandsRequest.Builder requestBuilder = GrpcFindCommandsRequest.newBuilder().setVorgangId(VorgangTestFactory.ID);
private final StreamRecorder<GrpcCommandsResponse> responseObserver = StreamRecorder.create();
@Test
void shouldCallService() {
callFindCommands(requestBuilder.build());
verify(commandService).findCommands(VorgangTestFactory.ID, Collections.emptyList(), Optional.empty());
}
@Test
void shouldCallServiceWithStatus() {
callFindCommands(requestBuilder.addStatus(CommandStatus.FINISHED.name()).build());
verify(commandService).findCommands(VorgangTestFactory.ID, Collections.singletonList(CommandStatus.FINISHED), Optional.empty());
}
@Test
void shouldCallServiceWithOrder() {
callFindCommands(requestBuilder.setOrder(GrpcOrder.VORGANG_ABSCHLIESSEN).build());
verify(commandService).findCommands(VorgangTestFactory.ID, Collections.emptyList(), Optional.of(Order.VORGANG_ABSCHLIESSEN));
}
private void callFindCommands(GrpcFindCommandsRequest request) {
service.findCommands(request, responseObserver);
try {
if (!responseObserver.awaitCompletion(5, TimeUnit.SECONDS)) {
fail("The call did not terminate in time(5 seconds)");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
\ No newline at end of file
package de.itvsh.ozg.pluto.vorgang;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import de.itvsh.ozg.pluto.vorgang.redirect.VorgangRedirectedEventTestFactory;
class VorgangEventListenerTest {
@InjectMocks // NOSONAR
private VorgangEventListener listener;
@Mock
private VorgangService service;
@Nested
class OnVorgangRedirectedEvent {
@Test
void shouldSetStatus() {
listener.updateStatus(VorgangRedirectedEventTestFactory.create());
verify(service).setStatusToWeitergeleitet(VorgangRedirectedEventTestFactory.SOURCE);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment