feat(search): add searchDocumentsByPersonId with Specification-based sender/receiver query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-06 16:04:54 +02:00
parent 70e8a6e6ad
commit 79e4a3f9db
3 changed files with 104 additions and 1 deletions

View File

@@ -57,6 +57,7 @@ public interface DocumentRepository extends JpaRepository<Document, UUID>, JpaSp
@EntityGraph("Document.full")
List<Document> findByReceiversId(UUID receiverId);
// Callers access only doc.getTags() to mutate the set — receivers/sender not touched; no graph needed.
List<Document> findByTags_Id(UUID tagId);

View File

@@ -1034,7 +1034,25 @@ public class DocumentService {
}
public DocumentSearchResult searchDocumentsByPersonId(UUID personId, LocalDate from, LocalDate to, Pageable pageable) {
throw new UnsupportedOperationException("Implemented in Task 12 — findBySenderOrReceiver JPQL");
Person person = personService.getById(personId);
Specification<Document> spec = buildPersonSpec(person, from, to);
Page<Document> page = documentRepository.findAll(spec, pageable);
List<DocumentListItem> items = enrichItems(page.getContent(), null);
return DocumentSearchResult.paged(items, pageable, page.getTotalElements());
}
private Specification<Document> buildPersonSpec(Person person, LocalDate from, LocalDate to) {
return (root, query, cb) -> {
if (query != null) query.distinct(true);
var receiversJoin = root.join("receivers", jakarta.persistence.criteria.JoinType.LEFT);
var senderPredicate = cb.equal(root.get("sender"), person);
var receiverPredicate = cb.equal(receiversJoin, person);
var personPredicate = cb.or(senderPredicate, receiverPredicate);
var predicates = new java.util.ArrayList<>(java.util.List.of(personPredicate));
if (from != null) predicates.add(cb.greaterThanOrEqualTo(root.get("documentDate"), from));
if (to != null) predicates.add(cb.lessThanOrEqualTo(root.get("documentDate"), to));
return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
};
}
public long getIncompleteCount() {