Skip to content

Commit

Permalink
Feature/user messages (#662)
Browse files Browse the repository at this point in the history
* Add create User-Message with test

* Add update User-Message with test

* Added delete/update/partialUpdate User-Message

* delete methode added else

* Added last methode to mark active messages as toDelete

* Update

* Update

* first Int Test

* add more int tests

---------

Co-authored-by: rabeaM <[email protected]>
  • Loading branch information
mafasva and ramueSVA authored Dec 9, 2024
1 parent 62b3a9f commit be9887d
Show file tree
Hide file tree
Showing 12 changed files with 708 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<mockserver-client.version>5.15.0</mockserver-client.version>
<ossindexAnalyzerEnabled>false</ossindexAnalyzerEnabled>
<spring.cloud-version>2023.0.3</spring.cloud-version>
<jsoup.version>1.18.3</jsoup.version>
</properties>

<repositories>
Expand Down Expand Up @@ -195,6 +196,11 @@
<artifactId>hapi-fhir-jaxrsserver-base</artifactId>
<version>${hapi.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/org/highmed/numportal/domain/dto/MessageDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.highmed.numportal.domain.dto;

import org.highmed.numportal.domain.model.MessageType;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@Schema
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MessageDto {

@Schema(accessMode = Schema.AccessMode.READ_ONLY)
Long id;

@NotNull
@NotEmpty
private String title;

private String text;

@NotNull
private LocalDateTime startDate;

@NotNull
private LocalDateTime endDate;

@NotNull
private MessageType type;

}
40 changes: 40 additions & 0 deletions src/main/java/org/highmed/numportal/domain/model/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.highmed.numportal.domain.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;

@Entity
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Message implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

private String text;

private LocalDateTime startDate;

private LocalDateTime endDate;

private MessageType type;

private boolean markAsDeleted;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.highmed.numportal.domain.model;

public enum MessageType {
INFO,
WARNING,
ERROR
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.highmed.numportal.domain.repository;

import org.highmed.numportal.domain.model.Message;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MessageRepository extends JpaRepository<Message, Long>, PagingAndSortingRepository<Message, Long> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class ExceptionsTemplate {
public static final String PROJECT_COHORT_CANNOT_BE_NULL = "Project: %s cohort cannot be null";
public static final String PROJECT_TEMPLATES_CANNOT_BE_NULL = "Project: %s templates cannot be null";
public static final String PROJECT_NOT_FOUND = "Project not found: %s";
public static final String MESSAGE_NOT_FOUND = "Message not found: %s";
public static final String CAN_T_FIND_THE_COHORT_BY_ID = "Can't find the cohort by id: %s";
public static final String AN_ISSUE_HAS_OCCURRED_CANNOT_EXECUTE_AQL = "An issue has occurred, cannot execute aql";
public static final String ERROR_WHILE_RETRIEVING_DATA = "Error while retrieving data: %s";
Expand All @@ -84,6 +85,9 @@ public class ExceptionsTemplate {
public static final String CANNOT_DELETE_PROJECT = "Cannot delete project: %s";
public static final String CANNOT_DELETE_PROJECT_INVALID_STATUS = "Cannot delete project: %s, invalid status: %s";
public static final String CANNOT_UPDATE_PROJECT_INVALID_PROJECT_STATUS = "Cannot update project: %s, invalid project status: %s";
public static final String CANNOT_UPDATE_MESSAGE_INVALID = "Cannot update message: %s, invalid: %s";
public static final String CANNOT_HANDLE_DATE = "Cannot handle date: %s";
public static final String CANNOT_DELETE_MESSAGE = "Cannot delete this message: %s";
public static final String NO_PERMISSIONS_TO_EDIT_THIS_PROJECT = "No permissions to edit this project";
public static final String CANNOT_ACCESS_THIS_RESOURCE_USER_IS_NOT_OWNER = "Cannot access this resource. User is not owner.";
public static final String DATA_EXPLORER_AVAILABLE_FOR_PUBLISHED_PROJECTS_ONLY = "Data explorer available for published projects only";
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/org/highmed/numportal/mapper/MessageMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.highmed.numportal.mapper;

import org.highmed.numportal.domain.dto.MessageDto;
import org.highmed.numportal.domain.model.Message;

import lombok.AllArgsConstructor;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
@AllArgsConstructor
public class MessageMapper {

private final ModelMapper modelMapper;

@PostConstruct
private void initialize() {
modelMapper.getConfiguration().setAmbiguityIgnored(true);
}

public MessageDto convertToDto(Message message) {
return modelMapper.map(message, MessageDto.class);

}

public Message convertToEntity(MessageDto messageDto) {
return modelMapper.map(messageDto, Message.class);
}
}
131 changes: 131 additions & 0 deletions src/main/java/org/highmed/numportal/service/MessageService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.highmed.numportal.service;

import org.highmed.numportal.domain.dto.MessageDto;
import org.highmed.numportal.domain.model.Message;
import org.highmed.numportal.domain.repository.MessageRepository;
import org.highmed.numportal.mapper.MessageMapper;
import org.highmed.numportal.service.exception.BadRequestException;
import org.highmed.numportal.service.exception.ResourceNotFound;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.safety.Safelist;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static org.highmed.numportal.domain.templates.ExceptionsTemplate.CANNOT_DELETE_MESSAGE;
import static org.highmed.numportal.domain.templates.ExceptionsTemplate.CANNOT_HANDLE_DATE;
import static org.highmed.numportal.domain.templates.ExceptionsTemplate.CANNOT_UPDATE_MESSAGE_INVALID;
import static org.highmed.numportal.domain.templates.ExceptionsTemplate.MESSAGE_NOT_FOUND;


@Slf4j
@Service
@AllArgsConstructor
public class MessageService {

private static final Safelist safeList = Safelist.simpleText().addTags("br");

private MessageMapper messageMapper;
private UserDetailsService userDetailsService;

private MessageRepository messageRepository;

public MessageDto createUserMessage(MessageDto messageDto, String userId) {
userDetailsService.checkIsUserApproved(userId);
Message message = messageMapper.convertToEntity(messageDto);
message.setText(Jsoup.clean(message.getText(), safeList));
validateDates(message.getStartDate(), message.getEndDate(), LocalDateTime.now().minusMinutes(5));

Message savedMessage = messageRepository.save(message);

return messageMapper.convertToDto(savedMessage);
}

public Page<MessageDto> getMessages(String userId, Pageable pageable) {
userDetailsService.checkIsUserApproved(userId);
Page<Message> messagePage = messageRepository.findAll(pageable);
return messagePage.map(message -> messageMapper.convertToDto(message));
}

public MessageDto updateUserMessage(Long id, MessageDto messageDto, String userId) {
userDetailsService.checkIsUserApproved(userId);
LocalDateTime now = LocalDateTime.now().minusMinutes(5);
Message messageToUpdate = messageRepository.findById(id)
.orElseThrow(() -> new ResourceNotFound(MessageService.class, MESSAGE_NOT_FOUND,
String.format(MESSAGE_NOT_FOUND, id)));

if (isInactiveMessage(messageToUpdate, now)) {
throw new BadRequestException(MessageService.class, CANNOT_UPDATE_MESSAGE_INVALID,
String.format(CANNOT_UPDATE_MESSAGE_INVALID, messageToUpdate.getId(), "message is not shown anymore"));
}
if (isActiveMessage(messageDto, messageToUpdate, now)) {
messageToUpdate.setEndDate(messageDto.getEndDate());
} else {
validateDates(messageDto.getStartDate(), messageDto.getEndDate(), now);

messageToUpdate.setTitle(messageDto.getTitle());
messageToUpdate.setText(Jsoup.clean(messageDto.getText(), safeList));
messageToUpdate.setStartDate(messageDto.getStartDate());
messageToUpdate.setEndDate(messageDto.getEndDate());
messageToUpdate.setType(messageDto.getType());

}
Message savedMessage = messageRepository.save(messageToUpdate);
return messageMapper.convertToDto(savedMessage);
}

public void deleteActiveUserMessage(Long id, String userId) {
LocalDateTime now = LocalDateTime.now().minusMinutes(5);
userDetailsService.checkIsUserApproved(userId);
Message messageToDelete = messageRepository.findById(id)
.orElseThrow(() -> new ResourceNotFound(MessageService.class, MESSAGE_NOT_FOUND,
String.format(MESSAGE_NOT_FOUND, id)));
// active messages should be marked as deleted
if (messageToDelete.getStartDate().isBefore(now) && messageToDelete.getEndDate().isAfter(now)) {
messageToDelete.setMarkAsDeleted(true);
messageRepository.save(messageToDelete);
} else {
throw new BadRequestException(MessageService.class, CANNOT_DELETE_MESSAGE,
String.format(CANNOT_DELETE_MESSAGE, messageToDelete.getId()));
}
}

public void deleteUserMessage(Long id, String userId) {
LocalDateTime now = LocalDateTime.now().minusMinutes(5);
userDetailsService.checkIsUserApproved(userId);
Message messageToDelete = messageRepository.findById(id)
.orElseThrow(() -> new ResourceNotFound(MessageService.class, MESSAGE_NOT_FOUND,
String.format(MESSAGE_NOT_FOUND, id)));
//just planned messages can be deleted
if (messageToDelete.getStartDate().isAfter(now)) {
messageRepository.deleteById(id);
} else {
throw new BadRequestException(MessageService.class, CANNOT_DELETE_MESSAGE,
String.format(CANNOT_DELETE_MESSAGE, messageToDelete.getId()));
}
}

private static boolean isInactiveMessage(Message messageToUpdate, LocalDateTime now) {
return messageToUpdate.getEndDate().isBefore(now);
}

private static boolean isActiveMessage(MessageDto messageDto, Message messageToUpdate, LocalDateTime now) {
return messageToUpdate.getStartDate().isBefore(now) && messageDto.getEndDate().isAfter(now);
}

private void validateDates(LocalDateTime startDate, LocalDateTime endDate, LocalDateTime now) {
if (startDate.isBefore(now)) {
throw new BadRequestException(MessageService.class, CANNOT_HANDLE_DATE,
String.format(CANNOT_HANDLE_DATE, startDate));
}
if (startDate.isAfter(endDate) || startDate.isEqual(endDate)) {
throw new BadRequestException(MessageService.class, CANNOT_HANDLE_DATE,
String.format(CANNOT_HANDLE_DATE, endDate));
}
}
}
Loading

0 comments on commit be9887d

Please sign in to comment.