From 7e993a92492283779559318d04e2fbaabe7e7efa Mon Sep 17 00:00:00 2001 From: Gregor Vostrak Date: Thu, 25 Jun 2026 19:09:54 +0200 Subject: [PATCH] Fix not-contains tag filter dropping entries where tags is null --- app/Service/TimeEntryFilter.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/Service/TimeEntryFilter.php b/app/Service/TimeEntryFilter.php index 221d4b66..9faf53ac 100644 --- a/app/Service/TimeEntryFilter.php +++ b/app/Service/TimeEntryFilter.php @@ -210,6 +210,11 @@ class TimeEntryFilter } $includeNone = in_array(self::NONE_VALUE, $tagIds, true); $tagIds = array_values(array_filter($tagIds, fn (string $id): bool => $id !== self::NONE_VALUE)); + // An empty selection (no tag IDs and not filtering for "none") is no constraint, so apply nothing. + // This also prevents the not-contains branch from collapsing into "only entries with null tags". + if (count($tagIds) === 0 && ! $includeNone) { + return $this; + } $tagCondition = function (Builder $builder) use ($tagIds, $includeNone): void { foreach ($tagIds as $tagId) { @@ -223,7 +228,12 @@ class TimeEntryFilter }; if ($tagFilter === self::TAG_FILTER_NOT_CONTAINS) { - $this->builder->whereNot($tagCondition); + $this->builder->where(function (Builder $builder) use ($tagCondition, $includeNone): void { + $builder->whereNot($tagCondition); + if (! $includeNone) { + $builder->orWhereNull('tags'); + } + }); } else { $this->builder->where($tagCondition); }