diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierResource.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierResource.java index 6f7f51508..b8ed39205 100644 --- a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierResource.java +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierResource.java @@ -1,11 +1,13 @@ package com.iqser.red.service.persistence.service.v1.api.resources; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.time.OffsetDateTime; import java.util.List; import java.util.Set; @@ -22,6 +24,15 @@ public interface DossierResource { String INCLUDE_DELETED_PARAM = "includeDeleted"; + String SINCE_REQUEST_PARAM="since"; + + String CHANGES_PATH = "/has-changes"; + + @ResponseBody + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = REST_PATH+CHANGES_PATH, produces = MediaType.APPLICATION_JSON_VALUE) + JSONPrimitive hasChangesSince(@RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since); + @PostMapping(value = REST_PATH, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) Dossier addDossier(@RequestBody CreateOrUpdateDossierRequest dossierRequest); diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierStatsResource.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierStatsResource.java index 57ec5f47a..ab5a53e67 100644 --- a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierStatsResource.java +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/DossierStatsResource.java @@ -4,8 +4,10 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.do import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import java.util.List; import java.util.Map; import java.util.Set; @@ -19,6 +21,6 @@ public interface DossierStatsResource { @GetMapping(value = REST_PATH + DOSSIER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE) DossierStats getDossierStats(@PathVariable(DOSSIER_ID_PARAM) String dossierId); - @GetMapping(value = REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE) - Map getDossierStats(@RequestBody Set dossierIds); + @PostMapping(value = REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE) + List getDossierStats(@RequestBody Set dossierIds); } diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationResource.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationResource.java index 23dcdb924..a83e081e6 100644 --- a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationResource.java +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/NotificationResource.java @@ -1,11 +1,13 @@ package com.iqser.red.service.persistence.service.v1.api.resources; import com.iqser.red.service.persistence.service.v1.api.model.audit.AddNotificationRequest; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.notification.Notification; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.time.OffsetDateTime; import java.util.List; @ResponseStatus(value = HttpStatus.OK) @@ -14,6 +16,7 @@ public interface NotificationResource { String NOTIFICATION_PATH = "/notification"; String TOGGLE_SEEN_PATH = "/toggle-seen"; String TOGGLE_READ_PATH = "/toggle-read"; + String CHANGES_PATH = "/has-changes"; String USER_ID_PARAM = "userId"; String USER_ID_PATH_PARAM = "/{" + USER_ID_PARAM + "}"; @@ -21,7 +24,13 @@ public interface NotificationResource { String INCLUDE_SEEN_PARAM = "includeSeen"; String SET_SEEN_PARAM = "setSeen"; String SET_READ_PARAM = "setRead"; + String SINCE_REQUEST_PARAM = "since"; + @ResponseBody + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = NOTIFICATION_PATH + CHANGES_PATH + USER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE) + JSONPrimitive hasNewNotificationsSince(@PathVariable(USER_ID_PARAM) String userId, + @RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since); @PostMapping(value = NOTIFICATION_PATH, consumes = MediaType.APPLICATION_JSON_VALUE) void addNotification(@RequestBody AddNotificationRequest addNotificationRequest); diff --git a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/StatusResource.java b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/StatusResource.java index d2499bd12..c14be1f06 100644 --- a/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/StatusResource.java +++ b/persistence-service-v1/persistence-service-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/resources/StatusResource.java @@ -6,6 +6,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.time.OffsetDateTime; import java.util.List; import java.util.Set; @@ -19,16 +20,26 @@ public interface StatusResource { String FILE_ID = "fileId"; String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}"; + String CHANGES_PATH = "/has-changes"; + String EXCLUDED_STATUS_PARAM = "excluded"; String APPROVER_ID_REQUEST_PARAM = "approverId"; String REVIEWER_ID_REQUEST_PARAM = "reviewerId"; + String SINCE_REQUEST_PARAM="since"; + + @ResponseBody @ResponseStatus(value = HttpStatus.OK) @GetMapping(value = STATUS_PATH, produces = MediaType.APPLICATION_JSON_VALUE) List getAllStatuses(); + @ResponseBody + @ResponseStatus(value = HttpStatus.OK) + @GetMapping(value = STATUS_PATH+DOSSIER_ID_PATH_PARAM+CHANGES_PATH, produces = MediaType.APPLICATION_JSON_VALUE) + JSONPrimitive hasChangesSince(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since); + @ResponseBody @ResponseStatus(value = HttpStatus.OK) @GetMapping(value = STATUS_PATH + DOSSIER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/dossier/DossierEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/dossier/DossierEntity.java index 673ebf04e..c1995b577 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/dossier/DossierEntity.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/dossier/DossierEntity.java @@ -33,6 +33,9 @@ public class DossierEntity { @Column private OffsetDateTime date; + @Column + private OffsetDateTime lastUpdated; + @Column(length = 4000) private String description; diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/DossierPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/DossierPersistenceService.java index a8ea15eae..42664303f 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/DossierPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/DossierPersistenceService.java @@ -7,7 +7,6 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.ReportTemplateRepository; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest; -import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; @@ -17,9 +16,7 @@ import javax.transaction.Transactional; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; import java.util.List; -import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; import static com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException.DOSSIER_NOT_FOUND_MESSAGE; @@ -32,6 +29,7 @@ public class DossierPersistenceService { private final DossierTemplateRepository dossierTemplateRepository; private final ReportTemplateRepository reportTemplateRepository; + public DossierEntity insert(CreateOrUpdateDossierRequest createOrUpdateDossierRequest) { DossierEntity dossier = new DossierEntity(); @@ -39,7 +37,7 @@ public class DossierPersistenceService { dossier.setId(UUID.randomUUID().toString()); dossier.setStatus(DossierStatus.ACTIVE); dossier.setDate(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); - + dossier.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); dossier.setDossierTemplate(dossierTemplateRepository.getOne(createOrUpdateDossierRequest.getDossierTemplateId())); var reportTemplates = reportTemplateRepository.findAllById(createOrUpdateDossierRequest.getReportTemplateIds()); reportTemplates.forEach(r -> r.getDossiers().add(dossier)); @@ -57,6 +55,7 @@ public class DossierPersistenceService { dossierRepository.findById(dossierId).ifPresent(dossier -> { BeanUtils.copyProperties(createOrUpdateDossierRequest, dossier); dossier.setDossierTemplate(dossierTemplateRepository.getOne(createOrUpdateDossierRequest.getDossierTemplateId())); + dossier.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); var reportTemplates = reportTemplateRepository.findAllById(createOrUpdateDossierRequest.getReportTemplateIds()); reportTemplates.forEach(r -> r.getDossiers().add(dossier)); dossier.setReportTemplates(reportTemplates); @@ -65,14 +64,6 @@ public class DossierPersistenceService { } - @Transactional - public void updateReportTemplateIds(String dossierId, Set reportTemplateIds) { - dossierRepository.findById(dossierId).ifPresent(dossier -> { - dossier.setReportTemplates(reportTemplateRepository.findAllById(reportTemplateIds)); - }); - } - - public DossierEntity getAndValidateDossier(String dossierId) { // check whether the dossierId exists and is not deleted var dossier = findByDossierId(dossierId); @@ -94,22 +85,15 @@ public class DossierPersistenceService { } - public List findSoftDeletedDossiers() { - - return findAllDossiers().stream().filter(d -> d.getSoftDeletedTime() != null).collect(Collectors.toList()); - - } - - @Transactional public void hardDelete(String dossierId) { - dossierRepository.hardDelete(dossierId, DossierStatus.DELETED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + dossierRepository.hardDelete(dossierId, DossierStatus.DELETED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); } @Transactional public void undelete(String dossierId) { - int updateCount = dossierRepository.undelete(dossierId, DossierStatus.ACTIVE); + int updateCount = dossierRepository.undelete(dossierId, DossierStatus.ACTIVE, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); if (updateCount == 0) { throw new BadRequestException("Cannot undelete a hard-deleted dossier!"); } @@ -118,7 +102,10 @@ public class DossierPersistenceService { @Transactional public void markDossierAsDeleted(String dossierId, OffsetDateTime softDeletedTime) { - dossierRepository.markDossierAsDeleted(dossierId, DossierStatus.DELETED, softDeletedTime); + dossierRepository.markDossierAsDeleted(dossierId, DossierStatus.DELETED, softDeletedTime, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); } + public boolean hasChangesSince(OffsetDateTime since) { + return dossierRepository.existsByLastUpdatedIsAfter(since.truncatedTo(ChronoUnit.MILLIS)); + } } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java index c99247f3d..f0f961bb1 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/FileStatusPersistenceService.java @@ -1,17 +1,5 @@ package com.iqser.red.service.persistence.management.v1.processor.service.persistence; -import java.time.OffsetDateTime; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -import javax.transaction.Transactional; - -import org.springframework.stereotype.Service; - import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeConfigEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; @@ -22,8 +10,17 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus; - import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -48,7 +45,7 @@ public class FileStatusPersistenceService { file.setAdded(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setUploader(uploader); file.setLastUploaded(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); - + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); fileRepository.save(file); } @@ -87,7 +84,7 @@ public class FileStatusPersistenceService { if (isFileDeleted(fileId)) { return; } - fileRepository.updateFlags(fileId, hasRedactions, hasHints, hasImages, hasSuggestions, hasComments, hasUpdates); + fileRepository.updateFlags(fileId, OffsetDateTime.now(), hasRedactions, hasHints, hasImages, hasSuggestions, hasComments, hasUpdates); } @@ -131,6 +128,7 @@ public class FileStatusPersistenceService { return; } file.setProcessingStatus(ProcessingStatus.PROCESSED); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setLastIndexed(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -146,6 +144,7 @@ public class FileStatusPersistenceService { if (isFileDeleted(file)) { return; } + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setLastOCRTime(time); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -161,6 +160,7 @@ public class FileStatusPersistenceService { if (isFileDeleted(file)) { return; } + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setHasAnnotationComments(hasComments); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -175,6 +175,7 @@ public class FileStatusPersistenceService { if (isFileDeleted(file)) { return; } + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setLastManualRedaction(date); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -191,6 +192,7 @@ public class FileStatusPersistenceService { if (isFileDeleted(file)) { return; } + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setLastManualRedaction(date); file.setHasSuggestions(hasSuggestions); }, () -> { @@ -211,6 +213,7 @@ public class FileStatusPersistenceService { } var fileAttributeEntities = convertFileAttributes(dossierId, file, fileAttributes); file.setLastFileAttributeChange(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setFileAttributes(fileAttributeEntities); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -227,6 +230,7 @@ public class FileStatusPersistenceService { return; } file.setLastManualRedaction(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setExcludedPages(excludedPages); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -259,6 +263,7 @@ public class FileStatusPersistenceService { fileRepository.findById(fileId).ifPresentOrElse((file) -> { file.setProcessingStatus(ProcessingStatus.DELETED); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setDeleted(softDeletedTime); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -274,6 +279,8 @@ public class FileStatusPersistenceService { file.setProcessingStatus(ProcessingStatus.DELETED); file.setDeleted(file.getDeleted() == null ? OffsetDateTime.now() .truncatedTo(ChronoUnit.MILLIS) : file.getDeleted()); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + file.setDeleted(file.getDeleted() == null ? OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS) : file.getDeleted()); file.setHardDeletedTime(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); fileAttributesRepository.deleteByFileId(fileId); @@ -291,6 +298,7 @@ public class FileStatusPersistenceService { if (file.getHardDeletedTime() != null) { throw new BadRequestException("Cannot undelete a hard-deleted dossier file!"); } + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setProcessingStatus(ProcessingStatus.PROCESSED); file.setDeleted(null); }, () -> { @@ -308,6 +316,8 @@ public class FileStatusPersistenceService { } file.setCurrentReviewer(currentReviewer); file.setLastReviewer(lastReviewer); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); + file.setWorkflowStatus(currentReviewer == null ? WorkflowStatus.UNASSIGNED : WorkflowStatus.UNDER_REVIEW); file.setWorkflowStatus(currentReviewer == null ? WorkflowStatus.UNASSIGNED : WorkflowStatus.UNDER_REVIEW); }, () -> { throw new NotFoundException("Unknown file=" + fileId); @@ -324,6 +334,7 @@ public class FileStatusPersistenceService { return; } file.setExcluded(excluded); + file.setLastUpdated(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)); file.setLastProcessed(null); file.setLastReviewer(null); file.setCurrentReviewer(null); @@ -418,4 +429,7 @@ public class FileStatusPersistenceService { return isFileDeleted.get(); } + public boolean hasChangesSince(String dossierId, OffsetDateTime since) { + return fileRepository.existsByDossierIdAndLastUpdatedIsAfter(dossierId, since); + } } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPersistenceService.java index 5ae791ad7..775071347 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPersistenceService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/NotificationPersistenceService.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; import java.util.List; @Service @@ -20,6 +21,9 @@ public class NotificationPersistenceService { private final NotificationRepository notificationRepository; + public boolean hasNewNotificationsSince(String userId, OffsetDateTime since) { + return notificationRepository.existsByUserIdAndCreationDateIsAfter(userId, since.truncatedTo(ChronoUnit.MILLIS)); + } @SneakyThrows public void insertNotification(AddNotificationRequest addNotificationRequest) { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/DossierRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/DossierRepository.java index ab08c987f..d0da0ce50 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/DossierRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/DossierRepository.java @@ -11,21 +11,24 @@ import java.time.OffsetDateTime; public interface DossierRepository extends JpaRepository { @Modifying - @Query("update DossierEntity d set d.status = :dossierStatus, d.hardDeletedTime = :hardDeletedTime," + + @Query("update DossierEntity d set d.status = :dossierStatus, d.hardDeletedTime = :hardDeletedTime, d.lastUpdated = :lastUpdated," + " d.softDeletedTime = " + "case " + "when d.softDeletedTime is null then :hardDeletedTime " + "when d.softDeletedTime is not null then d.softDeletedTime " + "end " + "where d.id = :dossierId") - void hardDelete(String dossierId, DossierStatus dossierStatus, OffsetDateTime hardDeletedTime); + void hardDelete(String dossierId, DossierStatus dossierStatus, OffsetDateTime hardDeletedTime, OffsetDateTime lastUpdated); @Modifying - @Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = null where d.id = :dossierId" + + @Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = null, d.lastUpdated = :lastUpdated where d.id = :dossierId" + " and d.hardDeletedTime is null") - int undelete(String dossierId, DossierStatus dossierStatus); + int undelete(String dossierId, DossierStatus dossierStatus, OffsetDateTime lastUpdated); @Modifying - @Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = :softDeletedTime where d.id = :dossierId") - void markDossierAsDeleted(String dossierId, DossierStatus dossierStatus, OffsetDateTime softDeletedTime); + @Query("update DossierEntity d set d.status = :dossierStatus, d.softDeletedTime = :softDeletedTime, d.lastUpdated = :lastUpdated where d.id = :dossierId") + void markDossierAsDeleted(String dossierId, DossierStatus dossierStatus, OffsetDateTime softDeletedTime, OffsetDateTime lastUpdated); + + boolean existsByLastUpdatedIsAfter(OffsetDateTime since); + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FileRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FileRepository.java index 3ca4423c0..06fc6f518 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FileRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/FileRepository.java @@ -12,11 +12,25 @@ import java.util.List; import javax.persistence.Column; public interface FileRepository extends JpaRepository { + + boolean existsByDossierIdAndLastUpdatedIsAfter(String dossierId, OffsetDateTime since); + List findByDossierId(String dossierId); @Modifying - @Query("update FileEntity e set e.hasRedactions = :hasRedactions , e.hasHints = :hasHints, e.hasSuggestions = :hasSuggestions, e.hasImages = :hasImages, e.hasUpdates = :hasUpdates, e.hasAnnotationComments = :hasComments where e.id =:fileId") - void updateFlags(String fileId, boolean hasRedactions, boolean hasHints, boolean hasImages, boolean hasSuggestions, boolean hasComments, boolean hasUpdates); + @Query("update FileEntity e set e.hasRedactions = :hasRedactions ," + + " e.hasHints = :hasHints, e.hasSuggestions = :hasSuggestions," + + " e.hasImages = :hasImages, e.hasUpdates = :hasUpdates, e.hasAnnotationComments = :hasComments, " + + " e.lastUpdated = :lastUpdated " + + " where e.id =:fileId") + void updateFlags(String fileId, + OffsetDateTime lastUpdated, + boolean hasRedactions, + boolean hasHints, + boolean hasImages, + boolean hasSuggestions, + boolean hasComments, + boolean hasUpdates); } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationRepository.java index da08ba3d3..750f6a7fe 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/NotificationRepository.java @@ -11,6 +11,8 @@ import java.util.Optional; public interface NotificationRepository extends JpaRepository { + boolean existsByUserIdAndCreationDateIsAfter(String userId, OffsetDateTime since); + List findByUserIdOrderByCreationDateDesc(String userId); @Query("Select n from NotificationEntity n where n.softDeleted is null and n.userId = :userId order by n.creationDate desc") diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierController.java index 041d51b8c..ff15f8e61 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierController.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierController.java @@ -7,6 +7,7 @@ import com.iqser.red.service.peristence.v1.server.utils.DossierMapper; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStatus; @@ -35,6 +36,12 @@ public class DossierController implements DossierResource { private final FileStatusService fileStatusService; private final FileService fileService; + @Override + public JSONPrimitive hasChangesSince(@RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since) { + + return JSONPrimitive.of(dossierService.hasChangesSince(since)); + } + @Override @Transactional diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierStatsController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierStatsController.java index 827793b41..e100fd59e 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierStatsController.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/DossierStatsController.java @@ -6,6 +6,7 @@ import com.iqser.red.service.persistence.service.v1.api.resources.DossierStatsRe import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.RestController; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -23,7 +24,7 @@ public class DossierStatsController implements DossierStatsResource { } @Override - public Map getDossierStats(Set dossierIds) { - return dossierIds.stream().collect(Collectors.toMap(Function.identity(), dossierStatsService::getDossierStats)); + public List getDossierStats(Set dossierIds) { + return dossierIds.stream().map(dossierStatsService::getDossierStats).collect(Collectors.toList()); } } diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/FileStatusController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/FileStatusController.java index 9707c9637..a3b90f1ae 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/FileStatusController.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/FileStatusController.java @@ -3,6 +3,7 @@ package com.iqser.red.service.peristence.v1.server.controller; import com.iqser.red.service.peristence.v1.server.service.*; import com.iqser.red.service.peristence.v1.server.utils.FileModelMapper; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus; @@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.time.OffsetDateTime; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -38,6 +40,14 @@ public class FileStatusController implements StatusResource { } + @Override + public JSONPrimitive hasChangesSince(@PathVariable(DOSSIER_ID_PARAM) String dossierId, + @RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since) { + + return JSONPrimitive.of(fileStatusService.hasChangesSince(dossierId,since)); + } + + @Override public List getDossierStatus(@PathVariable(DOSSIER_ID_PARAM) String dossierId) { diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationController.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationController.java index 1d250ff74..86295f103 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationController.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/controller/NotificationController.java @@ -1,7 +1,10 @@ package com.iqser.red.service.peristence.v1.server.controller; +import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.NotificationPersistenceService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.NotificationPreferencesPersistenceService; import com.iqser.red.service.persistence.service.v1.api.model.audit.AddNotificationRequest; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.notification.Notification; import com.iqser.red.service.persistence.service.v1.api.resources.NotificationResource; import lombok.RequiredArgsConstructor; @@ -21,12 +24,25 @@ public class NotificationController implements NotificationResource { private final NotificationPersistenceService notificationPersistenceService; + private final NotificationPreferencesPersistenceService notificationPreferencesPersistenceService; - public void addNotification(@RequestBody AddNotificationRequest addNotificationRequest) { - - notificationPersistenceService.insertNotification(addNotificationRequest); + @Override + public JSONPrimitive hasNewNotificationsSince(String userId, OffsetDateTime since) { + return JSONPrimitive.of(notificationPersistenceService.hasNewNotificationsSince(userId, since)); } + public void addNotification(@RequestBody AddNotificationRequest addNotificationRequest) { + try { + var userPreferences = notificationPreferencesPersistenceService.getNotificationPreferences(addNotificationRequest.getUserId()); + if (userPreferences.getInAppNotifications().contains(addNotificationRequest.getNotificationType()) + || userPreferences.getEmailNotifications().contains(addNotificationRequest.getNotificationType())) { + notificationPersistenceService.insertNotification(addNotificationRequest); + } + } catch (NotFoundException e) { + notificationPersistenceService.insertNotification(addNotificationRequest); + } + + } public void toggleSeen(@PathVariable(USER_ID_PARAM) String userId, @RequestBody List notificationIds, @RequestParam(SET_SEEN_PARAM) boolean setSeen) { diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/DossierService.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/DossierService.java index 8f96c1ed0..8b8f18b9f 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/DossierService.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/DossierService.java @@ -94,4 +94,7 @@ public class DossierService { return dossierPersistenceService.findAllDossiers(); } + public boolean hasChangesSince(OffsetDateTime since) { + return dossierPersistenceService.hasChangesSince(since); + } } diff --git a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/FileStatusService.java b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/FileStatusService.java index ef551e8da..54e8931b3 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/FileStatusService.java +++ b/persistence-service-v1/persistence-service-server-v1/src/main/java/com/iqser/red/service/peristence/v1/server/service/FileStatusService.java @@ -10,6 +10,7 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.dossier. import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; import com.iqser.red.service.persistence.management.v1.processor.exception.UserNotFoundException; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.*; +import com.iqser.red.service.persistence.service.v1.api.model.common.JSONPrimitive; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileType; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus; @@ -344,4 +345,7 @@ public class FileStatusService { return fileAttributeList; } + public boolean hasChangesSince(String dossierId, OffsetDateTime since) { + return fileStatusPersistenceService.hasChangesSince(dossierId,since); + } } diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierStatsTest.java b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierStatsTest.java index af597611a..9713fa4c2 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierStatsTest.java +++ b/persistence-service-v1/persistence-service-server-v1/src/test/java/com/iqser/red/service/peristence/v1/server/integration/tests/DossierStatsTest.java @@ -10,15 +10,12 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.do import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierStats; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.ProcessingStatus; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.WorkflowStatus; - -import org.hibernate.jdbc.Work; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; - import java.util.HashSet; -import java.util.Map; +import java.util.List; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -57,7 +54,7 @@ public class DossierStatsTest extends AbstractPersistenceServerServiceTest { // alter file 1 var loadedFile1 = fileClient.getFileStatus(dossier1.getId(), file1.getId()); assertThat(loadedFile1.isHasRedactions()).isFalse(); - fileRepository.findById(file1.getId()).ifPresent((file)->{ + fileRepository.findById(file1.getId()).ifPresent((file) -> { file.setNumberOfAnalyses(NUMBER_PAGES_ANALYZED); file.setHasRedactions(true); file.setHasHints(true); @@ -68,18 +65,18 @@ public class DossierStatsTest extends AbstractPersistenceServerServiceTest { assertThat(loadedFile1.isHasRedactions()).isTrue(); // alter file 2 - fileRepository.findById(file2.getId()).ifPresent((file)->{ + fileRepository.findById(file2.getId()).ifPresent((file) -> { file.setHasSuggestions(true); fileRepository.save(file); }); // second dossier - dossier2 = dossierTesterAndProvider.provideTestDossier(dossierTemplate,"Dossier2"); + dossier2 = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier2"); var file3 = fileTesterAndProvider.testAndProvideFile(dossier2, "file3"); var file4 = fileTesterAndProvider.testAndProvideFile(dossier2, "file4"); //alter file 4 - fileRepository.findById(file4.getId()).ifPresent((file)->{ + fileRepository.findById(file4.getId()).ifPresent((file) -> { file.setHasHints(true); file.setWorkflowStatus(WorkflowStatus.APPROVED); fileRepository.save(file); @@ -106,18 +103,18 @@ public class DossierStatsTest extends AbstractPersistenceServerServiceTest { dossierIds.add(dossier1.getId()); dossierIds.add(dossier2.getId()); - Map dossierStatsMap = dossierStatsClient.getDossierStats(dossierIds); + List dossierStatsList = dossierStatsClient.getDossierStats(dossierIds); // get the result for dossier2 - DossierStats dossierStats2 = dossierStatsMap.get(dossier2.getId()); - assertThat(dossierStats2.getNumberOfFiles()).isEqualTo(2); - assertThat(dossierStats2.getNumberOfAnalysedPages()).isEqualTo(0); - assertThat(dossierStats2.isHasRedactionsFilePresent()).isFalse(); - assertThat(dossierStats2.isHasHintsNoRedactionsFilePresent()).isTrue(); - assertThat(dossierStats2.isHasSuggestionsFilePresent()).isFalse(); - assertThat(dossierStats2.isHasUpdatesFilePresent()).isFalse(); - assertThat(dossierStats2.isHasNoFlagsFilePresent()).isTrue(); - assertThat(dossierStats2.getFileCountPerWorkflowStatus().get(WorkflowStatus.UNASSIGNED)).isEqualTo(1); - assertThat(dossierStats2.getFileCountPerWorkflowStatus().get(WorkflowStatus.APPROVED)).isEqualTo(1); + DossierStats dossierStats = dossierStatsList.stream().filter(d -> d.getDossierId().equals(dossier2.getId())).findAny().get(); + assertThat(dossierStats.getNumberOfFiles()).isEqualTo(2); + assertThat(dossierStats.getNumberOfAnalysedPages()).isEqualTo(0); + assertThat(dossierStats.isHasRedactionsFilePresent()).isFalse(); + assertThat(dossierStats.isHasHintsNoRedactionsFilePresent()).isTrue(); + assertThat(dossierStats.isHasSuggestionsFilePresent()).isFalse(); + assertThat(dossierStats.isHasUpdatesFilePresent()).isFalse(); + assertThat(dossierStats.isHasNoFlagsFilePresent()).isTrue(); + assertThat(dossierStats.getFileCountPerWorkflowStatus().get(WorkflowStatus.UNASSIGNED)).isEqualTo(1); + assertThat(dossierStats.getFileCountPerWorkflowStatus().get(WorkflowStatus.APPROVED)).isEqualTo(1); } }