From f5f9247834eeaa5c94a9f18eabb4f9bdd6170676 Mon Sep 17 00:00:00 2001 From: yhampe Date: Wed, 23 Oct 2024 09:10:11 +0200 Subject: [PATCH 1/3] RED-9393: user stats endpoint added endpoint with discussed path --- .../impl/controller/UserStatsController.java | 54 +++++++++++++++++++ .../external/resource/UserStatsResource.java | 37 +++++++++++++ .../acl/custom/dossier/DossierACLService.java | 18 +++++++ .../v1/processor/roles/ActionRoles.java | 4 ++ .../FileStatusPersistenceService.java | 22 +++++--- .../repository/FileRepository.java | 11 ++-- .../v1/api/shared/model/UserStats.java | 18 +++++++ 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java create mode 100644 persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java new file mode 100644 index 000000000..9b801cb9b --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java @@ -0,0 +1,54 @@ +package com.iqser.red.persistence.service.v1.external.api.impl.controller; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService; +import com.iqser.red.service.persistence.management.v1.processor.service.DossierService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; +import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService; +import com.iqser.red.service.persistence.service.v1.api.external.resource.UserStatsResource; +import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class UserStatsController implements UserStatsResource { + + private final UserService userService; + private final DossierService dossierService; + private final FileStatusPersistenceService fileStatusPersistenceService; + private final DossierACLService dossierACLService; + + + @Override + public ResponseEntity getUserStats(String userId) { + + if (userService.getUserById(userId).isEmpty()) { + return new ResponseEntity(null, HttpStatus.NOT_FOUND); + } + List dossierMemberships = new ArrayList<>(); + List dossierOwnerships = new ArrayList<>(); + dossierService.getAllDossiers() + .stream() + .forEach(d -> { + if (dossierACLService.getMembers(d.getId()).contains(userId)) { + dossierMemberships.add(d.getId()); + } + if (dossierACLService.getOwners(d.getId()).contains(userId)) { + dossierOwnerships.add(d.getId()); + } + }); + + return new ResponseEntity<>(new UserStats(dossierMemberships.size(), dossierOwnerships.size(), this.fileStatusPersistenceService.getNumberOfAssignedFiles(userId)), + HttpStatus.OK); + } + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java new file mode 100644 index 000000000..86347d586 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java @@ -0,0 +1,37 @@ +package com.iqser.red.service.persistence.service.v1.api.external.resource; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@ApiResponses(value = {@ApiResponse(responseCode = "429", description = "Too many requests.")}) +public interface UserStatsResource { + + String USER_ID_PARAM = "userId"; + + String USER_ID_PATH_VARIABLE = "/{" + USER_ID_PARAM + "}"; + + String STATS_PATH = "/user-stats"; + + String PATH = ExternalApi.BASE_PATH + STATS_PATH; + + + @ResponseStatus(value = HttpStatus.OK) + @ResponseBody + @GetMapping(value = PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Gets user stats for user specified by id.", description = "") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")}) + ResponseEntity getUserStats(@Parameter(name = USER_ID_PARAM, description = "The unique identifier of the user whose statistics we want to retrieve.", required = true) @PathVariable(USER_ID_PARAM) String userId); + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java index 2777ef08e..894179b46 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java @@ -73,6 +73,24 @@ public class DossierACLService extends AbstractACLService { } + public Set getOwners(String dossierId) { + + ObjectIdentityImpl dossierIdentity = new ObjectIdentityImpl(getIdentifier(), dossierId); + var acl = mutableAclService.readAclById(dossierIdentity); + Set members = new HashSet<>(); + acl.getEntries() + .forEach(entry -> { + if (entry.getSid() instanceof PrincipalSid) { + var principal = ((PrincipalSid) entry.getSid()).getPrincipal(); + if (entry.getPermission().getMask() == RedPermission.OWNER.getMask()) { + members.add(principal); + } + } + }); + return members; + } + + @Override public String getIdentifier() { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java index 6c17e7741..1790b52b0 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java @@ -168,6 +168,10 @@ public final class ActionRoles { public static final String READ_APP_CONFIG = "red-read-app-configuration"; public static final String WRITE_APP_CONFIG = "red-write-app-configuration"; + // USER STATS + + public static final String READ_USER_STATS = "red-get-user-stats"; + // License Management public static final String UPDATE_LICENSE = "red-update-license"; public static final String READ_LICENSE = "red-read-license"; 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 fb0de27ee..b84fcfe20 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 @@ -10,7 +10,6 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -18,14 +17,15 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.dossier. import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntityComponentMappingVersionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection; import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.model.FileIdentifier; import com.iqser.red.service.persistence.management.v1.processor.model.OCRStatusUpdateResponse; import com.iqser.red.service.persistence.management.v1.processor.model.websocket.AnalyseStatus; -import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributesRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository; +import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute; import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentMappingMetadata; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo; @@ -429,6 +429,7 @@ public class FileStatusPersistenceService { .collect(Collectors.toList()); } + public List getFilesForDossierStats(String dossierId) { return fileRepository.findDossierStatsProjectionFileProjectionByDossierId(dossierId); @@ -489,12 +490,12 @@ public class FileStatusPersistenceService { fileAttributesRepository.deleteByFileIds(fileIds); } + public void hardDeleteFiles(List fileIds, OffsetDateTime hardDeleteTime) { fileRepository.hardDeleteFiles(fileIds, ProcessingStatus.PROCESSED, hardDeleteTime); fileAttributesRepository.deleteByFileIds(fileIds); - } @@ -562,7 +563,8 @@ public class FileStatusPersistenceService { uploader, ProcessingStatus.UNPROCESSED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), - OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis); + OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), + disableAutomaticAnalysis); } else { fileRepository.findById(fileId) @@ -574,7 +576,8 @@ public class FileStatusPersistenceService { ProcessingStatus.UNPROCESSED, WorkflowStatus.NEW, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), - OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis); + OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), + disableAutomaticAnalysis); deleteFileAttributes(fileId); } @@ -584,6 +587,13 @@ public class FileStatusPersistenceService { } + public int getNumberOfAssignedFiles(String userId) { + + List files = fileRepository.findFilesByAssignee(userId); + return files.size(); + } + + @Transactional public void deleteFileAttributes(String fileId) { @@ -702,6 +712,4 @@ public class FileStatusPersistenceService { fileRepository.setProtobufMigrationDone(fileIds); } - - } 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 b38b41d0c..9892caf29 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 @@ -48,6 +48,10 @@ public interface FileRepository extends JpaRepository { @Param("hasUpdates") boolean hasUpdates); + @Query("select f from FileEntity f where f.assignee = :assignee") + List findFilesByAssignee(@Param("assignee") String assignee); + + @Modifying @Query(""" update FileEntity f set f.numberOfPages = :numberOfPages, \ @@ -427,11 +431,10 @@ public interface FileRepository extends JpaRepository { @Query("SELECT f FROM FileEntity f WHERE f.protobufMigrationDone = false") List findByProtobufMigrationDoneFalse(Pageable pageable); - @Modifying - @Query("update FileEntity f set f.protobufMigrationDone = true " - + "where f.id in (:fileIds)") - void setProtobufMigrationDone(@Param("fileIds") List fileIds); + @Modifying + @Query("update FileEntity f set f.protobufMigrationDone = true " + "where f.id in (:fileIds)") + void setProtobufMigrationDone(@Param("fileIds") List fileIds); @Query("SELECT f FROM FileEntity f WHERE f.dossierId = :dossierId AND f.hardDeletedTime IS NULL AND f.deleted IS NULL") diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java new file mode 100644 index 000000000..5ce4f62dc --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java @@ -0,0 +1,18 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model; + +import lombok.Data; + +@Data +public class UserStats { + + private int numberOfDossierMemberships; + private int numberOfDossierOwnerships; + private int numberOfAssignedFiles; + public UserStats(int numberOfDossierMemberships, int numberOfDossierOwnerships, int numberOfAssignedFiles) { + + this.numberOfDossierMemberships = numberOfDossierMemberships; + this.numberOfDossierOwnerships = numberOfDossierOwnerships; + this.numberOfAssignedFiles = numberOfAssignedFiles; + } + +} \ No newline at end of file From c21a97420d11a0c46440b41ef662c37650ee6342 Mon Sep 17 00:00:00 2001 From: yhampe Date: Wed, 23 Oct 2024 09:10:11 +0200 Subject: [PATCH 2/3] RED-9393: user stats endpoint added endpoint with discussed path --- .../impl/controller/UserStatsController.java | 54 +++++++++++++++++++ .../external/resource/UserStatsResource.java | 37 +++++++++++++ .../acl/custom/dossier/DossierACLService.java | 18 +++++++ .../v1/processor/roles/ActionRoles.java | 4 ++ .../FileStatusPersistenceService.java | 9 ++++ .../repository/FileRepository.java | 4 ++ .../v1/api/shared/model/UserStats.java | 18 +++++++ 7 files changed, 144 insertions(+) create mode 100644 persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java create mode 100644 persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java new file mode 100644 index 000000000..9b801cb9b --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/UserStatsController.java @@ -0,0 +1,54 @@ +package com.iqser.red.persistence.service.v1.external.api.impl.controller; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService; +import com.iqser.red.service.persistence.management.v1.processor.service.DossierService; +import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService; +import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService; +import com.iqser.red.service.persistence.service.v1.api.external.resource.UserStatsResource; +import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +public class UserStatsController implements UserStatsResource { + + private final UserService userService; + private final DossierService dossierService; + private final FileStatusPersistenceService fileStatusPersistenceService; + private final DossierACLService dossierACLService; + + + @Override + public ResponseEntity getUserStats(String userId) { + + if (userService.getUserById(userId).isEmpty()) { + return new ResponseEntity(null, HttpStatus.NOT_FOUND); + } + List dossierMemberships = new ArrayList<>(); + List dossierOwnerships = new ArrayList<>(); + dossierService.getAllDossiers() + .stream() + .forEach(d -> { + if (dossierACLService.getMembers(d.getId()).contains(userId)) { + dossierMemberships.add(d.getId()); + } + if (dossierACLService.getOwners(d.getId()).contains(userId)) { + dossierOwnerships.add(d.getId()); + } + }); + + return new ResponseEntity<>(new UserStats(dossierMemberships.size(), dossierOwnerships.size(), this.fileStatusPersistenceService.getNumberOfAssignedFiles(userId)), + HttpStatus.OK); + } + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java new file mode 100644 index 000000000..86347d586 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/UserStatsResource.java @@ -0,0 +1,37 @@ +package com.iqser.red.service.persistence.service.v1.api.external.resource; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@ApiResponses(value = {@ApiResponse(responseCode = "429", description = "Too many requests.")}) +public interface UserStatsResource { + + String USER_ID_PARAM = "userId"; + + String USER_ID_PATH_VARIABLE = "/{" + USER_ID_PARAM + "}"; + + String STATS_PATH = "/user-stats"; + + String PATH = ExternalApi.BASE_PATH + STATS_PATH; + + + @ResponseStatus(value = HttpStatus.OK) + @ResponseBody + @GetMapping(value = PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Gets user stats for user specified by id.", description = "") + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")}) + ResponseEntity getUserStats(@Parameter(name = USER_ID_PARAM, description = "The unique identifier of the user whose statistics we want to retrieve.", required = true) @PathVariable(USER_ID_PARAM) String userId); + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java index 2777ef08e..894179b46 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/acl/custom/dossier/DossierACLService.java @@ -73,6 +73,24 @@ public class DossierACLService extends AbstractACLService { } + public Set getOwners(String dossierId) { + + ObjectIdentityImpl dossierIdentity = new ObjectIdentityImpl(getIdentifier(), dossierId); + var acl = mutableAclService.readAclById(dossierIdentity); + Set members = new HashSet<>(); + acl.getEntries() + .forEach(entry -> { + if (entry.getSid() instanceof PrincipalSid) { + var principal = ((PrincipalSid) entry.getSid()).getPrincipal(); + if (entry.getPermission().getMask() == RedPermission.OWNER.getMask()) { + members.add(principal); + } + } + }); + return members; + } + + @Override public String getIdentifier() { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java index 6c17e7741..1790b52b0 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/roles/ActionRoles.java @@ -168,6 +168,10 @@ public final class ActionRoles { public static final String READ_APP_CONFIG = "red-read-app-configuration"; public static final String WRITE_APP_CONFIG = "red-write-app-configuration"; + // USER STATS + + public static final String READ_USER_STATS = "red-get-user-stats"; + // License Management public static final String UPDATE_LICENSE = "red-update-license"; public static final String READ_LICENSE = "red-read-license"; 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 aad3cc332..3b69d7c72 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 @@ -18,6 +18,7 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.dossier. import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity; import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntityComponentMappingVersionEntity; +import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection; import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException; import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException; import com.iqser.red.service.persistence.management.v1.processor.model.FileIdentifier; @@ -26,6 +27,7 @@ import com.iqser.red.service.persistence.management.v1.processor.model.websocket import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributesRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository; +import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute; import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentMappingMetadata; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo; @@ -595,6 +597,13 @@ public class FileStatusPersistenceService { } + public int getNumberOfAssignedFiles(String userId) { + + List files = fileRepository.findFilesByAssignee(userId); + return files.size(); + } + + @Transactional public void deleteFileAttributes(String fileId) { 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 93cdfde12..6156dd593 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 @@ -49,6 +49,10 @@ public interface FileRepository extends JpaRepository { @Param("hasUpdates") boolean hasUpdates); + @Query("select f from FileEntity f where f.assignee = :assignee") + List findFilesByAssignee(@Param("assignee") String assignee); + + @Modifying @Query(""" update FileEntity f set f.numberOfPages = :numberOfPages, \ diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java new file mode 100644 index 000000000..5ce4f62dc --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/UserStats.java @@ -0,0 +1,18 @@ +package com.iqser.red.service.persistence.service.v1.api.shared.model; + +import lombok.Data; + +@Data +public class UserStats { + + private int numberOfDossierMemberships; + private int numberOfDossierOwnerships; + private int numberOfAssignedFiles; + public UserStats(int numberOfDossierMemberships, int numberOfDossierOwnerships, int numberOfAssignedFiles) { + + this.numberOfDossierMemberships = numberOfDossierMemberships; + this.numberOfDossierOwnerships = numberOfDossierOwnerships; + this.numberOfAssignedFiles = numberOfAssignedFiles; + } + +} \ No newline at end of file From 43d37b67b3022c1e2e6fb5d3853a3dd5e697f3e8 Mon Sep 17 00:00:00 2001 From: yhampe Date: Wed, 6 Nov 2024 09:48:50 +0100 Subject: [PATCH 3/3] RED-9393: user stats endpoint checkstyle --- .../FileStatusPersistenceService.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) 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 3b69d7c72..9174cf8e4 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 @@ -10,7 +10,6 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -24,7 +23,6 @@ import com.iqser.red.service.persistence.management.v1.processor.exception.NotFo import com.iqser.red.service.persistence.management.v1.processor.model.FileIdentifier; import com.iqser.red.service.persistence.management.v1.processor.model.OCRStatusUpdateResponse; import com.iqser.red.service.persistence.management.v1.processor.model.websocket.AnalyseStatus; -import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributesRepository; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository; import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService; @@ -417,6 +415,7 @@ public class FileStatusPersistenceService { .toList(); } + public List getActiveFilesForDossierTemplate(String dossierTemplateId) { return dossierService.findAllActiveDossiersForDossierTemplateId(dossierTemplateId) @@ -442,6 +441,7 @@ public class FileStatusPersistenceService { .collect(Collectors.toList()); } + public List getFilesForDossierStats(String dossierId) { return fileRepository.findDossierStatsProjectionFileProjectionByDossierId(dossierId); @@ -502,12 +502,12 @@ public class FileStatusPersistenceService { fileAttributesRepository.deleteByFileIds(fileIds); } + public void hardDeleteFiles(List fileIds, OffsetDateTime hardDeleteTime) { fileRepository.hardDeleteFiles(fileIds, ProcessingStatus.PROCESSED, hardDeleteTime); fileAttributesRepository.deleteByFileIds(fileIds); - } @@ -575,7 +575,8 @@ public class FileStatusPersistenceService { uploader, ProcessingStatus.UNPROCESSED, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), - OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis); + OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), + disableAutomaticAnalysis); } else { fileRepository.findById(fileId) @@ -587,7 +588,8 @@ public class FileStatusPersistenceService { ProcessingStatus.UNPROCESSED, WorkflowStatus.NEW, OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), - OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis); + OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), + disableAutomaticAnalysis); deleteFileAttributes(fileId); } @@ -656,11 +658,14 @@ public class FileStatusPersistenceService { fileRepository.updateFileModificationDate(fileId, fileManipulationDate); } + @Transactional - public void resetErrorCounter(String dossierTemplateId){ + public void resetErrorCounter(String dossierTemplateId) { + fileRepository.updateErrorCounter(dossierTemplateId, 0); } + @Transactional public void updateHasHighlights(String fileId, boolean hasHighlights) { @@ -735,7 +740,7 @@ public class FileStatusPersistenceService { public List findAllByDossierId(String dossierId, boolean includeDeleted) { - return fileRepository.findAllByDossierId(dossierId, includeDeleted); + return fileRepository.findAllByDossierId(dossierId, includeDeleted); } }