feat(#145): add status filter to GET /api/documents/search

Dashboard "Recently Added" widget calls ?status=REVIEWED&size=5.
Null status is a no-op — existing callers without the param are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-29 00:21:48 +01:00
parent 968993c48e
commit 147d1f2de5
6 changed files with 77 additions and 5 deletions

View File

@@ -17,6 +17,7 @@ import org.raddatz.familienarchiv.dto.IncompleteDocumentDTO;
import org.raddatz.familienarchiv.exception.DomainException;
import org.raddatz.familienarchiv.exception.ErrorCode;
import org.raddatz.familienarchiv.model.Document;
import org.raddatz.familienarchiv.model.DocumentStatus;
import org.raddatz.familienarchiv.model.DocumentVersion;
import org.raddatz.familienarchiv.security.Permission;
import org.raddatz.familienarchiv.security.RequirePermission;
@@ -184,8 +185,9 @@ public class DocumentController {
@RequestParam(required = false) LocalDate to,
@RequestParam(required = false) UUID senderId,
@RequestParam(required = false) UUID receiverId,
@RequestParam(required = false, name = "tag") List<String> tags) {
return ResponseEntity.ok(documentService.searchDocuments(q, from, to, senderId, receiverId, tags));
@RequestParam(required = false, name = "tag") List<String> tags,
@RequestParam(required = false) DocumentStatus status) {
return ResponseEntity.ok(documentService.searchDocuments(q, from, to, senderId, receiverId, tags, status));
}
// --- VERSIONS ---

View File

@@ -7,6 +7,7 @@ import java.util.List;
import java.util.UUID;
import org.raddatz.familienarchiv.model.Document;
import org.raddatz.familienarchiv.model.DocumentStatus;
import org.raddatz.familienarchiv.model.Tag;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
@@ -55,6 +56,11 @@ public class DocumentSpecifications {
};
}
// Filtert nach Status
public static Specification<Document> hasStatus(DocumentStatus status) {
return (root, query, cb) -> status == null ? null : cb.equal(root.get("status"), status);
}
// Filtert nach Schlagworten (UND-Verknüpfung)
public static Specification<Document> hasTags(List<String> tags) {
return (root, query, cb) -> {

View File

@@ -261,12 +261,13 @@ public class DocumentService {
}
// 1. Allgemeine Suche (für das Suchfeld im Frontend)
public List<Document> searchDocuments(String text, LocalDate from, LocalDate to, UUID sender, UUID receiver, List<String> tags) {
public List<Document> searchDocuments(String text, LocalDate from, LocalDate to, UUID sender, UUID receiver, List<String> tags, DocumentStatus status) {
Specification<Document> spec = Specification.where(hasText(text))
.and(isBetween(from, to))
.and(hasSender(sender))
.and(hasReceiver(receiver))
.and(hasTags(tags));
.and(hasTags(tags))
.and(hasStatus(status));
// Neueste zuerst (nach Erstellungsdatum)
return documentRepository.findAll(spec, Sort.by(Sort.Direction.DESC, "createdAt"));