| 1 | package com.edtech.service; | |
| 2 | ||
| 3 | import com.edtech.dto.DocumentResponseDto; | |
| 4 | import com.edtech.model.AcaoAuditoria; | |
| 5 | import com.edtech.model.Document; | |
| 6 | import com.edtech.model.DocumentStatus; | |
| 7 | import com.edtech.model.Project; | |
| 8 | import com.edtech.model.ProjectMember; | |
| 9 | import com.edtech.model.ProjectRole; | |
| 10 | import com.edtech.model.User; | |
| 11 | import com.edtech.repository.DocumentCommentRepository; | |
| 12 | import com.edtech.repository.DocumentRepository; | |
| 13 | import com.edtech.repository.ProjectMemberRepository; | |
| 14 | import com.edtech.repository.ProjectRepository; | |
| 15 | import com.edtech.repository.UserRepository; | |
| 16 | import com.fasterxml.jackson.databind.ObjectMapper; | |
| 17 | import java.io.IOException; | |
| 18 | import java.util.Locale; | |
| 19 | import java.util.Map; | |
| 20 | import java.util.Set; | |
| 21 | import java.util.UUID; | |
| 22 | import org.apache.tika.Tika; | |
| 23 | import org.springframework.data.domain.Page; | |
| 24 | import org.springframework.data.domain.Pageable; | |
| 25 | import org.springframework.stereotype.Service; | |
| 26 | import org.springframework.transaction.annotation.Transactional; | |
| 27 | import org.springframework.web.multipart.MultipartFile; | |
| 28 | ||
| 29 | /** Documentacao para DocumentService. */ | |
| 30 | @Service | |
| 31 | public class DocumentService { | |
| 32 | ||
| 33 | private static final String MIME_PDF = "application/pdf"; | |
| 34 | private static final String MIME_CSV = "text/csv"; | |
| 35 | private static final String MIME_JSON = "application/json"; | |
| 36 | private static final Map<String, String> ALLOWED_MIME_BY_EXTENSION = | |
| 37 | Map.of(".pdf", MIME_PDF, ".csv", MIME_CSV, ".json", MIME_JSON); | |
| 38 | private static final Set<String> CSV_COMPATIBLE_DETECTED_TYPES = | |
| 39 | Set.of(MIME_CSV, "text/plain", "application/csv", "application/vnd.ms-excel"); | |
| 40 | private static final Set<String> JSON_COMPATIBLE_DETECTED_TYPES = Set.of(MIME_JSON, "text/plain"); | |
| 41 | ||
| 42 | private final DocumentRepository documentRepository; | |
| 43 | private final ProjectRepository projectRepository; | |
| 44 | private final UserRepository userRepository; | |
| 45 | private final ProjectMemberRepository projectMemberRepository; | |
| 46 | private final DocumentCommentRepository documentCommentRepository; | |
| 47 | private final AuditLogService auditLogService; | |
| 48 | private final StorageService storageService; | |
| 49 | private final NotificationService notificationService; | |
| 50 | private final Tika tika = new Tika(); | |
| 51 | private final ObjectMapper objectMapper = new ObjectMapper(); | |
| 52 | ||
| 53 | /** Documentacao. */ | |
| 54 | public DocumentService( | |
| 55 | DocumentRepository documentRepository, | |
| 56 | ProjectRepository projectRepository, | |
| 57 | UserRepository userRepository, | |
| 58 | ProjectMemberRepository projectMemberRepository, | |
| 59 | DocumentCommentRepository documentCommentRepository, | |
| 60 | AuditLogService auditLogService, | |
| 61 | StorageService storageService, | |
| 62 | NotificationService notificationService) { | |
| 63 | this.documentRepository = documentRepository; | |
| 64 | this.projectRepository = projectRepository; | |
| 65 | this.userRepository = userRepository; | |
| 66 | this.projectMemberRepository = projectMemberRepository; | |
| 67 | this.documentCommentRepository = documentCommentRepository; | |
| 68 | this.auditLogService = auditLogService; | |
| 69 | this.storageService = storageService; | |
| 70 | this.notificationService = notificationService; | |
| 71 | } | |
| 72 | ||
| 73 | /** Documentacao. */ | |
| 74 | @Transactional | |
| 75 | public DocumentResponseDto uploadDocument( | |
| 76 | MultipartFile file, String title, UUID projectId, UUID authorId) { | |
| 77 | User author = | |
| 78 | userRepository | |
| 79 | .findById(authorId) | |
| 80 |
1
1. lambda$uploadDocument$0 : replaced return value with null for com/edtech/service/DocumentService::lambda$uploadDocument$0 → KILLED |
.orElseThrow(() -> new RuntimeException("Author not found")); |
| 81 | Project project = | |
| 82 | projectRepository | |
| 83 | .findById(projectId) | |
| 84 |
1
1. lambda$uploadDocument$1 : replaced return value with null for com/edtech/service/DocumentService::lambda$uploadDocument$1 → KILLED |
.orElseThrow(() -> new RuntimeException("Project not found")); |
| 85 | ||
| 86 | projectMemberRepository | |
| 87 | .findByProjectIdAndUserId(projectId, authorId) | |
| 88 |
1
1. lambda$uploadDocument$2 : replaced return value with null for com/edtech/service/DocumentService::lambda$uploadDocument$2 → KILLED |
.orElseThrow(() -> new RuntimeException("Author is not a member of the project")); |
| 89 | ||
| 90 | try { | |
| 91 | String originalFilename = file.getOriginalFilename(); | |
| 92 |
1
1. uploadDocument : negated conditional → KILLED |
if (originalFilename == null) { |
| 93 | throw new IllegalArgumentException("Filename cannot be null"); | |
| 94 | } | |
| 95 | ||
| 96 | String contentType = validateAllowedFile(file, originalFilename); | |
| 97 | String fileKey = UUID.randomUUID() + "_" + originalFilename; | |
| 98 | ||
| 99 |
1
1. uploadDocument : removed call to com/edtech/service/StorageService::uploadFile → KILLED |
storageService.uploadFile(file, fileKey, contentType); |
| 100 | ||
| 101 | Document document = new Document(); | |
| 102 |
1
1. uploadDocument : removed call to com/edtech/model/Document::setTitle → KILLED |
document.setTitle(title); |
| 103 |
1
1. uploadDocument : removed call to com/edtech/model/Document::setFileUrl → KILLED |
document.setFileUrl(fileKey); |
| 104 |
1
1. uploadDocument : removed call to com/edtech/model/Document::setStatus → SURVIVED |
document.setStatus(DocumentStatus.DRAFT); |
| 105 |
1
1. uploadDocument : removed call to com/edtech/model/Document::setAuthor → KILLED |
document.setAuthor(author); |
| 106 |
1
1. uploadDocument : removed call to com/edtech/model/Document::setProject → KILLED |
document.setProject(project); |
| 107 | ||
| 108 | document = documentRepository.save(document); | |
| 109 | ||
| 110 | auditLogService.logDocumentAction( | |
| 111 | authorId, | |
| 112 | AcaoAuditoria.UPLOAD_SUCCESS, | |
| 113 | document.getId(), | |
| 114 | "Documento anexado no Cloud Storage: " + title); | |
| 115 | ||
| 116 | DocumentResponseDto responseDto = mapToDto(document); | |
| 117 |
1
1. uploadDocument : removed call to com/edtech/service/NotificationService::sendToTopic → SURVIVED |
notificationService.sendToTopic( |
| 118 | "/topic/projects/" + projectId, | |
| 119 | Map.of("type", "DOCUMENT_UPLOADED", "document", responseDto)); | |
| 120 | ||
| 121 |
1
1. uploadDocument : replaced return value with null for com/edtech/service/DocumentService::uploadDocument → KILLED |
return responseDto; |
| 122 | } catch (IOException e) { | |
| 123 | throw new RuntimeException("Falha ao analisar o conteudo do arquivo", e); | |
| 124 | } catch (IllegalArgumentException e) { | |
| 125 | throw e; | |
| 126 | } catch (Exception e) { | |
| 127 | throw new RuntimeException("Failed to upload file to Cloud Storage: " + e.getMessage()); | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | /** Documentacao para o metodo getPresignedUrl. */ | |
| 132 | public String getPresignedUrl(UUID documentId, UUID userId) { | |
| 133 | Document document = | |
| 134 | documentRepository | |
| 135 | .findById(documentId) | |
| 136 |
1
1. lambda$getPresignedUrl$3 : replaced return value with null for com/edtech/service/DocumentService::lambda$getPresignedUrl$3 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 137 | ||
| 138 | projectMemberRepository | |
| 139 | .findByProjectIdAndUserId(document.getProject().getId(), userId) | |
| 140 | .orElseThrow( | |
| 141 |
1
1. lambda$getPresignedUrl$4 : replaced return value with null for com/edtech/service/DocumentService::lambda$getPresignedUrl$4 → KILLED |
() -> new RuntimeException("Access denied: You are not a member of this project")); |
| 142 | ||
| 143 | String presignedUrl; | |
| 144 | try { | |
| 145 | presignedUrl = storageService.getPresignedUrl(document.getFileUrl()); | |
| 146 | } catch (Exception e) { | |
| 147 | throw new RuntimeException("Failed to generate presigned URL", e); | |
| 148 | } | |
| 149 | ||
| 150 | auditLogService.logDocumentAction( | |
| 151 | userId, | |
| 152 | AcaoAuditoria.DOWNLOAD, | |
| 153 | documentId, | |
| 154 | "Gerada URL presigned para download: " + document.getTitle()); | |
| 155 |
1
1. getPresignedUrl : replaced return value with "" for com/edtech/service/DocumentService::getPresignedUrl → KILLED |
return presignedUrl; |
| 156 | } | |
| 157 | ||
| 158 | /** Documentacao. */ | |
| 159 | public Page<DocumentResponseDto> listDocumentsByUser( | |
| 160 | UUID userId, UUID projectId, String title, DocumentStatus status, Pageable pageable) { | |
| 161 |
1
1. listDocumentsByUser : replaced return value with null for com/edtech/service/DocumentService::listDocumentsByUser → KILLED |
return documentRepository |
| 162 | .findDocumentsByUserIdAndFilters(userId, projectId, title, status, pageable) | |
| 163 | .map(this::mapToDto); | |
| 164 | } | |
| 165 | ||
| 166 | /** Documentacao. */ | |
| 167 | @Transactional | |
| 168 | public void deleteDocument(UUID documentId, UUID userId) { | |
| 169 | Document document = | |
| 170 | documentRepository | |
| 171 | .findById(documentId) | |
| 172 |
1
1. lambda$deleteDocument$5 : replaced return value with null for com/edtech/service/DocumentService::lambda$deleteDocument$5 → KILLED |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 173 | ||
| 174 |
1
1. deleteDocument : negated conditional → KILLED |
if (!document.getAuthor().getId().equals(userId)) { |
| 175 | throw new RuntimeException("Only the author can delete this document"); | |
| 176 | } | |
| 177 |
1
1. deleteDocument : negated conditional → KILLED |
if (document.getStatus() != DocumentStatus.DRAFT) { |
| 178 | throw new RuntimeException("Only DRAFT documents can be deleted"); | |
| 179 | } | |
| 180 | ||
| 181 | try { | |
| 182 |
1
1. deleteDocument : removed call to com/edtech/service/StorageService::deleteFile → KILLED |
storageService.deleteFile(document.getFileUrl()); |
| 183 | } catch (Exception e) { | |
| 184 | throw new RuntimeException("Erro ao excluir arquivo fisico: " + e.getMessage()); | |
| 185 | } | |
| 186 | ||
| 187 |
1
1. deleteDocument : removed call to com/edtech/repository/DocumentRepository::delete → KILLED |
documentRepository.delete(document); |
| 188 | auditLogService.logDocumentAction( | |
| 189 | userId, | |
| 190 | AcaoAuditoria.DELETE_DOCUMENT, | |
| 191 | documentId, | |
| 192 | "Documento excluido: " + document.getTitle()); | |
| 193 | } | |
| 194 | ||
| 195 | private String validateAllowedFile(MultipartFile file, String originalFilename) | |
| 196 | throws IOException { | |
| 197 | String extension = extractExtension(originalFilename); | |
| 198 | String expectedMimeType = ALLOWED_MIME_BY_EXTENSION.get(extension); | |
| 199 |
1
1. validateAllowedFile : negated conditional → KILLED |
if (expectedMimeType == null) { |
| 200 | throw new IllegalArgumentException( | |
| 201 | "Tipo de arquivo nao permitido. Formatos aceitos: PDF, CSV e JSON."); | |
| 202 | } | |
| 203 | ||
| 204 | String declaredType = normalizeMimeType(file.getContentType()); | |
| 205 |
1
1. validateAllowedFile : negated conditional → KILLED |
if (!expectedMimeType.equals(declaredType)) { |
| 206 | throw new IllegalArgumentException( | |
| 207 | "Content-Type nao permitido para " | |
| 208 | + extension | |
| 209 | + ". Esperado: " | |
| 210 | + expectedMimeType | |
| 211 | + ". Recebido: " | |
| 212 | + declaredType); | |
| 213 | } | |
| 214 | ||
| 215 | String detectedType = normalizeMimeType(tika.detect(file.getInputStream(), originalFilename)); | |
| 216 |
1
1. validateAllowedFile : negated conditional → KILLED |
if (!isDetectedTypeCompatible(expectedMimeType, detectedType)) { |
| 217 | throw new IllegalArgumentException( | |
| 218 | "Conteudo do arquivo nao corresponde ao tipo permitido. Tipo detectado: " + detectedType); | |
| 219 | } | |
| 220 | ||
| 221 |
1
1. validateAllowedFile : negated conditional → KILLED |
if (MIME_JSON.equals(expectedMimeType)) { |
| 222 |
1
1. validateAllowedFile : removed call to com/edtech/service/DocumentService::validateJsonContent → SURVIVED |
validateJsonContent(file); |
| 223 | } | |
| 224 | ||
| 225 |
1
1. validateAllowedFile : replaced return value with "" for com/edtech/service/DocumentService::validateAllowedFile → KILLED |
return expectedMimeType; |
| 226 | } | |
| 227 | ||
| 228 | private String extractExtension(String filename) { | |
| 229 | int lastDotIndex = filename.lastIndexOf('.'); | |
| 230 |
4
1. extractExtension : Replaced integer subtraction with addition → SURVIVED 2. extractExtension : changed conditional boundary → SURVIVED 3. extractExtension : negated conditional → KILLED 4. extractExtension : negated conditional → KILLED |
if (lastDotIndex < 0 || lastDotIndex == filename.length() - 1) { |
| 231 | return ""; | |
| 232 | } | |
| 233 |
1
1. extractExtension : replaced return value with "" for com/edtech/service/DocumentService::extractExtension → KILLED |
return filename.substring(lastDotIndex).toLowerCase(Locale.ROOT); |
| 234 | } | |
| 235 | ||
| 236 | private boolean isDetectedTypeCompatible(String expectedMimeType, String detectedType) { | |
| 237 |
1
1. isDetectedTypeCompatible : negated conditional → KILLED |
if (MIME_CSV.equals(expectedMimeType)) { |
| 238 |
2
1. isDetectedTypeCompatible : replaced boolean return with true for com/edtech/service/DocumentService::isDetectedTypeCompatible → SURVIVED 2. isDetectedTypeCompatible : replaced boolean return with false for com/edtech/service/DocumentService::isDetectedTypeCompatible → KILLED |
return CSV_COMPATIBLE_DETECTED_TYPES.contains(detectedType); |
| 239 | } | |
| 240 |
1
1. isDetectedTypeCompatible : negated conditional → KILLED |
if (MIME_JSON.equals(expectedMimeType)) { |
| 241 |
2
1. isDetectedTypeCompatible : replaced boolean return with true for com/edtech/service/DocumentService::isDetectedTypeCompatible → SURVIVED 2. isDetectedTypeCompatible : replaced boolean return with false for com/edtech/service/DocumentService::isDetectedTypeCompatible → KILLED |
return JSON_COMPATIBLE_DETECTED_TYPES.contains(detectedType); |
| 242 | } | |
| 243 |
2
1. isDetectedTypeCompatible : replaced boolean return with true for com/edtech/service/DocumentService::isDetectedTypeCompatible → SURVIVED 2. isDetectedTypeCompatible : replaced boolean return with false for com/edtech/service/DocumentService::isDetectedTypeCompatible → KILLED |
return expectedMimeType.equals(detectedType); |
| 244 | } | |
| 245 | ||
| 246 | private String normalizeMimeType(String mimeType) { | |
| 247 |
2
1. normalizeMimeType : negated conditional → KILLED 2. normalizeMimeType : negated conditional → KILLED |
if (mimeType == null || mimeType.isBlank()) { |
| 248 | return ""; | |
| 249 | } | |
| 250 |
1
1. normalizeMimeType : replaced return value with "" for com/edtech/service/DocumentService::normalizeMimeType → KILLED |
return mimeType.split(";")[0].trim().toLowerCase(Locale.ROOT); |
| 251 | } | |
| 252 | ||
| 253 | private void validateJsonContent(MultipartFile file) throws IOException { | |
| 254 | objectMapper.readTree(file.getInputStream()); | |
| 255 | } | |
| 256 | ||
| 257 | private DocumentResponseDto mapToDto(Document document) { | |
| 258 | DocumentResponseDto dto = new DocumentResponseDto(); | |
| 259 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setId → KILLED |
dto.setId(document.getId()); |
| 260 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setTitle → KILLED |
dto.setTitle(document.getTitle()); |
| 261 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setFileUrl → KILLED |
dto.setFileUrl(document.getFileUrl()); |
| 262 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setStatus → KILLED |
dto.setStatus(document.getStatus()); |
| 263 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setAuthorId → KILLED |
dto.setAuthorId(document.getAuthor().getId()); |
| 264 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setProjectId → KILLED |
dto.setProjectId(document.getProject().getId()); |
| 265 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setCreatedAt → SURVIVED |
dto.setCreatedAt(document.getCreatedAt()); |
| 266 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setFeedback → KILLED |
dto.setFeedback(document.getFeedback()); |
| 267 |
1
1. mapToDto : removed call to com/edtech/dto/DocumentResponseDto::setStarred → KILLED |
dto.setStarred(document.isStarred()); |
| 268 |
1
1. mapToDto : replaced return value with null for com/edtech/service/DocumentService::mapToDto → KILLED |
return dto; |
| 269 | } | |
| 270 | ||
| 271 | /** Javadoc. */ | |
| 272 | @Transactional(readOnly = true) | |
| 273 | public java.util.List<com.edtech.dto.CommentResponseDto> getComments( | |
| 274 | UUID documentId, UUID userId) { | |
| 275 | Document document = | |
| 276 | documentRepository | |
| 277 | .findById(documentId) | |
| 278 |
1
1. lambda$getComments$6 : replaced return value with null for com/edtech/service/DocumentService::lambda$getComments$6 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 279 | projectMemberRepository | |
| 280 | .findByProjectIdAndUserId(document.getProject().getId(), userId) | |
| 281 |
1
1. lambda$getComments$7 : replaced return value with null for com/edtech/service/DocumentService::lambda$getComments$7 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Access denied")); |
| 282 | ||
| 283 |
1
1. getComments : replaced return value with Collections.emptyList for com/edtech/service/DocumentService::getComments → KILLED |
return documentCommentRepository.findByDocumentIdOrderByCreatedAtAsc(documentId).stream() |
| 284 | .map( | |
| 285 | c -> { | |
| 286 | com.edtech.dto.CommentResponseDto dto = new com.edtech.dto.CommentResponseDto(); | |
| 287 |
1
1. lambda$getComments$8 : removed call to com/edtech/dto/CommentResponseDto::setId → KILLED |
dto.setId(c.getId()); |
| 288 |
1
1. lambda$getComments$8 : removed call to com/edtech/dto/CommentResponseDto::setContent → KILLED |
dto.setContent(c.getContent()); |
| 289 |
1
1. lambda$getComments$8 : removed call to com/edtech/dto/CommentResponseDto::setCreatedAt → SURVIVED |
dto.setCreatedAt(c.getCreatedAt()); |
| 290 |
1
1. lambda$getComments$8 : removed call to com/edtech/dto/CommentResponseDto::setAuthorId → KILLED |
dto.setAuthorId(c.getAuthor().getId()); |
| 291 |
1
1. lambda$getComments$8 : removed call to com/edtech/dto/CommentResponseDto::setAuthorName → KILLED |
dto.setAuthorName(c.getAuthor().getName()); |
| 292 |
1
1. lambda$getComments$8 : replaced return value with null for com/edtech/service/DocumentService::lambda$getComments$8 → KILLED |
return dto; |
| 293 | }) | |
| 294 | .collect(java.util.stream.Collectors.toList()); | |
| 295 | } | |
| 296 | ||
| 297 | /** Javadoc. */ | |
| 298 | @Transactional | |
| 299 | public com.edtech.dto.CommentResponseDto addComment( | |
| 300 | UUID documentId, UUID userId, String content) { | |
| 301 | Document document = | |
| 302 | documentRepository | |
| 303 | .findById(documentId) | |
| 304 |
1
1. lambda$addComment$9 : replaced return value with null for com/edtech/service/DocumentService::lambda$addComment$9 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 305 | User user = | |
| 306 |
1
1. lambda$addComment$10 : replaced return value with null for com/edtech/service/DocumentService::lambda$addComment$10 → NO_COVERAGE |
userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found")); |
| 307 | projectMemberRepository | |
| 308 | .findByProjectIdAndUserId(document.getProject().getId(), userId) | |
| 309 |
1
1. lambda$addComment$11 : replaced return value with null for com/edtech/service/DocumentService::lambda$addComment$11 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Access denied")); |
| 310 | ||
| 311 | com.edtech.model.DocumentComment comment = new com.edtech.model.DocumentComment(); | |
| 312 |
1
1. addComment : removed call to com/edtech/model/DocumentComment::setDocument → SURVIVED |
comment.setDocument(document); |
| 313 |
1
1. addComment : removed call to com/edtech/model/DocumentComment::setAuthor → KILLED |
comment.setAuthor(user); |
| 314 |
1
1. addComment : removed call to com/edtech/model/DocumentComment::setContent → KILLED |
comment.setContent(content); |
| 315 | ||
| 316 | comment = documentCommentRepository.save(comment); | |
| 317 | ||
| 318 | auditLogService.logDocumentAction( | |
| 319 | userId, AcaoAuditoria.REVIEW_DOCUMENT, documentId, "Adicionou um comentário ao documento."); | |
| 320 | ||
| 321 | com.edtech.dto.CommentResponseDto dto = new com.edtech.dto.CommentResponseDto(); | |
| 322 |
1
1. addComment : removed call to com/edtech/dto/CommentResponseDto::setId → KILLED |
dto.setId(comment.getId()); |
| 323 |
1
1. addComment : removed call to com/edtech/dto/CommentResponseDto::setContent → KILLED |
dto.setContent(comment.getContent()); |
| 324 |
1
1. addComment : removed call to com/edtech/dto/CommentResponseDto::setCreatedAt → KILLED |
dto.setCreatedAt(comment.getCreatedAt()); |
| 325 |
1
1. addComment : removed call to com/edtech/dto/CommentResponseDto::setAuthorId → KILLED |
dto.setAuthorId(comment.getAuthor().getId()); |
| 326 |
1
1. addComment : removed call to com/edtech/dto/CommentResponseDto::setAuthorName → KILLED |
dto.setAuthorName(comment.getAuthor().getName()); |
| 327 | ||
| 328 |
1
1. addComment : removed call to com/edtech/service/NotificationService::sendToTopic → KILLED |
notificationService.sendToTopic( |
| 329 | "/topic/projects/" + document.getProject().getId(), | |
| 330 | Map.of("type", "NEW_COMMENT", "documentId", documentId, "comment", dto)); | |
| 331 | ||
| 332 |
1
1. addComment : replaced return value with null for com/edtech/service/DocumentService::addComment → KILLED |
return dto; |
| 333 | } | |
| 334 | ||
| 335 | /** Documentacao. */ | |
| 336 | @Transactional | |
| 337 | public DocumentResponseDto reviewDocument( | |
| 338 | UUID documentId, UUID reviewerId, DocumentStatus newStatus, String feedback) { | |
| 339 |
2
1. reviewDocument : negated conditional → KILLED 2. reviewDocument : negated conditional → KILLED |
if (newStatus != DocumentStatus.APPROVED && newStatus != DocumentStatus.REJECTED) { |
| 340 | throw new IllegalArgumentException( | |
| 341 | "Status invalido. Apenas APPROVED ou REJECTED sao permitidos na revisao."); | |
| 342 | } | |
| 343 | Document document = | |
| 344 | documentRepository | |
| 345 | .findById(documentId) | |
| 346 |
1
1. lambda$reviewDocument$12 : replaced return value with null for com/edtech/service/DocumentService::lambda$reviewDocument$12 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 347 | ProjectMember member = | |
| 348 | projectMemberRepository | |
| 349 | .findByProjectIdAndUserId(document.getProject().getId(), reviewerId) | |
| 350 | .orElseThrow( | |
| 351 |
1
1. lambda$reviewDocument$13 : replaced return value with null for com/edtech/service/DocumentService::lambda$reviewDocument$13 → KILLED |
() -> new RuntimeException("Acess denied: You are not a member of this project")); |
| 352 |
1
1. reviewDocument : negated conditional → KILLED |
if (member.getRole() != ProjectRole.ADVISOR) { |
| 353 | throw new RuntimeException("Acess denied: Only an ADVISOR can review documents"); | |
| 354 | } | |
| 355 |
1
1. reviewDocument : negated conditional → KILLED |
if (document.getStatus() != DocumentStatus.PENDING_REVIEW) { |
| 356 | throw new RuntimeException("Document is not pending review"); | |
| 357 | } | |
| 358 |
1
1. reviewDocument : removed call to com/edtech/model/Document::setStatus → KILLED |
document.setStatus(newStatus); |
| 359 |
1
1. reviewDocument : removed call to com/edtech/model/Document::setFeedback → KILLED |
document.setFeedback(feedback); |
| 360 | Document savedDocument = documentRepository.save(document); | |
| 361 | AcaoAuditoria acao = | |
| 362 |
1
1. reviewDocument : negated conditional → KILLED |
(newStatus == DocumentStatus.APPROVED) |
| 363 | ? AcaoAuditoria.DOCUMENT_APPROVED | |
| 364 | : AcaoAuditoria.DOCUMENT_REJECTED; | |
| 365 | String details = | |
| 366 | "Status alterado para " | |
| 367 | + newStatus | |
| 368 | + ".Feedback: " | |
| 369 |
2
1. reviewDocument : negated conditional → SURVIVED 2. reviewDocument : negated conditional → KILLED |
+ (feedback != null && !feedback.trim().isEmpty() ? feedback : "Sem feedback"); |
| 370 | auditLogService.logDocumentAction(reviewerId, acao, documentId, details); | |
| 371 | ||
| 372 | DocumentResponseDto responseDto = mapToDto(savedDocument); | |
| 373 |
1
1. reviewDocument : removed call to com/edtech/service/NotificationService::sendToTopic → SURVIVED |
notificationService.sendToTopic( |
| 374 | "/topic/projects/" + document.getProject().getId(), | |
| 375 | Map.of("type", "DOCUMENT_REVIEWED", "document", responseDto)); | |
| 376 | ||
| 377 |
1
1. reviewDocument : replaced return value with null for com/edtech/service/DocumentService::reviewDocument → KILLED |
return responseDto; |
| 378 | } | |
| 379 | ||
| 380 | /** Javadoc. */ | |
| 381 | @Transactional | |
| 382 | public DocumentResponseDto toggleStar(UUID documentId, UUID userId) { | |
| 383 | Document document = | |
| 384 | documentRepository | |
| 385 | .findById(documentId) | |
| 386 |
1
1. lambda$toggleStar$14 : replaced return value with null for com/edtech/service/DocumentService::lambda$toggleStar$14 → NO_COVERAGE |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 387 | ||
| 388 | projectMemberRepository | |
| 389 | .findByProjectIdAndUserId(document.getProject().getId(), userId) | |
| 390 | .orElseThrow( | |
| 391 |
1
1. lambda$toggleStar$15 : replaced return value with null for com/edtech/service/DocumentService::lambda$toggleStar$15 → NO_COVERAGE |
() -> new RuntimeException("Access denied: You are not a member of this project")); |
| 392 | ||
| 393 |
2
1. toggleStar : negated conditional → KILLED 2. toggleStar : removed call to com/edtech/model/Document::setStarred → KILLED |
document.setStarred(!document.isStarred()); |
| 394 | Document savedDocument = documentRepository.save(document); | |
| 395 | ||
| 396 |
1
1. toggleStar : replaced return value with null for com/edtech/service/DocumentService::toggleStar → KILLED |
return mapToDto(savedDocument); |
| 397 | } | |
| 398 | } | |
Mutations | ||
| 80 |
1.1 |
|
| 84 |
1.1 |
|
| 88 |
1.1 |
|
| 92 |
1.1 |
|
| 99 |
1.1 |
|
| 102 |
1.1 |
|
| 103 |
1.1 |
|
| 104 |
1.1 |
|
| 105 |
1.1 |
|
| 106 |
1.1 |
|
| 117 |
1.1 |
|
| 121 |
1.1 |
|
| 136 |
1.1 |
|
| 141 |
1.1 |
|
| 155 |
1.1 |
|
| 161 |
1.1 |
|
| 172 |
1.1 |
|
| 174 |
1.1 |
|
| 177 |
1.1 |
|
| 182 |
1.1 |
|
| 187 |
1.1 |
|
| 199 |
1.1 |
|
| 205 |
1.1 |
|
| 216 |
1.1 |
|
| 221 |
1.1 |
|
| 222 |
1.1 |
|
| 225 |
1.1 |
|
| 230 |
1.1 2.2 3.3 4.4 |
|
| 233 |
1.1 |
|
| 237 |
1.1 |
|
| 238 |
1.1 2.2 |
|
| 240 |
1.1 |
|
| 241 |
1.1 2.2 |
|
| 243 |
1.1 2.2 |
|
| 247 |
1.1 2.2 |
|
| 250 |
1.1 |
|
| 259 |
1.1 |
|
| 260 |
1.1 |
|
| 261 |
1.1 |
|
| 262 |
1.1 |
|
| 263 |
1.1 |
|
| 264 |
1.1 |
|
| 265 |
1.1 |
|
| 266 |
1.1 |
|
| 267 |
1.1 |
|
| 268 |
1.1 |
|
| 278 |
1.1 |
|
| 281 |
1.1 |
|
| 283 |
1.1 |
|
| 287 |
1.1 |
|
| 288 |
1.1 |
|
| 289 |
1.1 |
|
| 290 |
1.1 |
|
| 291 |
1.1 |
|
| 292 |
1.1 |
|
| 304 |
1.1 |
|
| 306 |
1.1 |
|
| 309 |
1.1 |
|
| 312 |
1.1 |
|
| 313 |
1.1 |
|
| 314 |
1.1 |
|
| 322 |
1.1 |
|
| 323 |
1.1 |
|
| 324 |
1.1 |
|
| 325 |
1.1 |
|
| 326 |
1.1 |
|
| 328 |
1.1 |
|
| 332 |
1.1 |
|
| 339 |
1.1 2.2 |
|
| 346 |
1.1 |
|
| 351 |
1.1 |
|
| 352 |
1.1 |
|
| 355 |
1.1 |
|
| 358 |
1.1 |
|
| 359 |
1.1 |
|
| 362 |
1.1 |
|
| 369 |
1.1 2.2 |
|
| 373 |
1.1 |
|
| 377 |
1.1 |
|
| 386 |
1.1 |
|
| 391 |
1.1 |
|
| 393 |
1.1 2.2 |
|
| 396 |
1.1 |