Pull request #83: status poll and rework of dossier-stats

Merge in RED/persistence-service from status-poll to master

* commit 'a973e0789b43fd8c92fe2a4043ea3c295960fff7':
  status poll and rework of dossier-stats
This commit is contained in:
Timo Bejan 2021-10-25 10:54:21 +02:00
commit f6755942d6
18 changed files with 169 additions and 71 deletions

View File

@ -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<Boolean> 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);

View File

@ -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<String, DossierStats> getDossierStats(@RequestBody Set<String> dossierIds);
@PostMapping(value = REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
List<DossierStats> getDossierStats(@RequestBody Set<String> dossierIds);
}

View File

@ -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<Boolean> 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);

View File

@ -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<FileModel> getAllStatuses();
@ResponseBody
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = STATUS_PATH+DOSSIER_ID_PATH_PARAM+CHANGES_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
JSONPrimitive<Boolean> 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)

View File

@ -33,6 +33,9 @@ public class DossierEntity {
@Column
private OffsetDateTime date;
@Column
private OffsetDateTime lastUpdated;
@Column(length = 4000)
private String description;

View File

@ -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<String> 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<DossierEntity> 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));
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -11,21 +11,24 @@ import java.time.OffsetDateTime;
public interface DossierRepository extends JpaRepository<DossierEntity, String> {
@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);
}

View File

@ -12,11 +12,25 @@ import java.util.List;
import javax.persistence.Column;
public interface FileRepository extends JpaRepository<FileEntity, String> {
boolean existsByDossierIdAndLastUpdatedIsAfter(String dossierId, OffsetDateTime since);
List<FileEntity> 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);
}

View File

@ -11,6 +11,8 @@ import java.util.Optional;
public interface NotificationRepository extends JpaRepository<NotificationEntity, Long> {
boolean existsByUserIdAndCreationDateIsAfter(String userId, OffsetDateTime since);
List<NotificationEntity> findByUserIdOrderByCreationDateDesc(String userId);
@Query("Select n from NotificationEntity n where n.softDeleted is null and n.userId = :userId order by n.creationDate desc")

View File

@ -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<Boolean> hasChangesSince(@RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since) {
return JSONPrimitive.of(dossierService.hasChangesSince(since));
}
@Override
@Transactional

View File

@ -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<String, DossierStats> getDossierStats(Set<String> dossierIds) {
return dossierIds.stream().collect(Collectors.toMap(Function.identity(), dossierStatsService::getDossierStats));
public List<DossierStats> getDossierStats(Set<String> dossierIds) {
return dossierIds.stream().map(dossierStatsService::getDossierStats).collect(Collectors.toList());
}
}

View File

@ -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<Boolean> hasChangesSince(@PathVariable(DOSSIER_ID_PARAM) String dossierId,
@RequestParam(SINCE_REQUEST_PARAM) OffsetDateTime since) {
return JSONPrimitive.of(fileStatusService.hasChangesSince(dossierId,since));
}
@Override
public List<FileModel> getDossierStatus(@PathVariable(DOSSIER_ID_PARAM) String dossierId) {

View File

@ -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<Boolean> 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<Long> notificationIds,
@RequestParam(SET_SEEN_PARAM) boolean setSeen) {

View File

@ -94,4 +94,7 @@ public class DossierService {
return dossierPersistenceService.findAllDossiers();
}
public boolean hasChangesSince(OffsetDateTime since) {
return dossierPersistenceService.hasChangesSince(since);
}
}

View File

@ -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);
}
}

View File

@ -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<String, DossierStats> dossierStatsMap = dossierStatsClient.getDossierStats(dossierIds);
List<DossierStats> 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);
}
}