refactor(audit): extend activity feed row/DTO with count and happenedAtUntil (singletons default)

Prepares the activity feed data shape for session-style rollup (#285). Adds two
new fields that carry null-operation defaults for the existing hour-truncated
dedupe query:

- count: int (required) — always 1 for singleton rows
- happenedAtUntil: OffsetDateTime (nullable) — end-of-session timestamp for
  future rollup rows; null for singletons

No behavioral change yet — the rollup SQL rewrite lands in a follow-up commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-20 15:53:58 +02:00
parent 2873d8646b
commit 10f092c906
6 changed files with 18 additions and 3 deletions

View File

@@ -12,4 +12,6 @@ public interface ActivityFeedRow {
UUID getDocumentId();
Instant getHappenedAt();
boolean isYouMentioned();
int getCount();
Instant getHappenedAtUntil();
}

View File

@@ -39,7 +39,9 @@ public interface AuditLogQueryRepository extends JpaRepository<AuditLog, UUID> {
a.document_id AS documentId,
a.happened_at AS happened_at,
(a.kind = 'MENTION_CREATED'
AND a.payload->>'mentionedUserId' = :currentUserId) AS youMentioned
AND a.payload->>'mentionedUserId' = :currentUserId) AS youMentioned,
1 AS count,
CAST(NULL AS TIMESTAMPTZ) AS happenedAtUntil
FROM audit_log a
LEFT JOIN users u ON u.id = a.actor_id
WHERE a.kind IN ('TEXT_SAVED','FILE_UPLOADED','ANNOTATION_CREATED','COMMENT_ADDED','MENTION_CREATED')

View File

@@ -14,5 +14,7 @@ public record ActivityFeedItemDTO(
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) UUID documentId,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) String documentTitle,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) OffsetDateTime happenedAt,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) boolean youMentioned
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) boolean youMentioned,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) int count,
@Nullable OffsetDateTime happenedAtUntil
) {}

View File

@@ -130,13 +130,18 @@ public class DashboardService {
? new ActivityActorDTO(row.getActorInitials(), row.getActorColor(), row.getActorName())
: null;
String docTitle = titleCache.getOrDefault(row.getDocumentId(), "");
OffsetDateTime happenedAtUntil = row.getHappenedAtUntil() != null
? row.getHappenedAtUntil().atOffset(ZoneOffset.UTC)
: null;
return new ActivityFeedItemDTO(
org.raddatz.familienarchiv.audit.AuditKind.valueOf(row.getKind()),
actor,
row.getDocumentId(),
docTitle,
row.getHappenedAt().atOffset(ZoneOffset.UTC),
row.isYouMentioned()
row.isYouMentioned(),
row.getCount(),
happenedAtUntil
);
}).toList();
}

View File

@@ -56,6 +56,8 @@ class AuditLogQueryRepositoryIntegrationTest {
assertThat(rows.get(0).getKind()).isEqualTo("ANNOTATION_CREATED");
assertThat(rows.get(0).getDocumentId()).isEqualTo(DOC_ID);
assertThat(rows.get(0).getHappenedAt()).isNotNull();
assertThat(rows.get(0).getCount()).isEqualTo(1);
assertThat(rows.get(0).getHappenedAtUntil()).isNull();
}
@Test

View File

@@ -104,6 +104,8 @@ class DashboardServiceTest {
public UUID getDocumentId() { return docId; }
public Instant getHappenedAt() { return Instant.now(); }
public boolean isYouMentioned() { return false; }
public int getCount() { return 1; }
public Instant getHappenedAtUntil() { return null; }
};
}
}