diff --git a/appinfo/info.xml b/appinfo/info.xml
index 5c4db0c..959f224 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -28,7 +28,7 @@ This app lets every user configure their own Deck automation workflows from Pers
A background job periodically evaluates all enabled workflows and moves cards whose due date has passed, using Deck's own internal PHP classes only (no HTTP/OCS calls).
]]>
- 34.0.1
+ 34.0.2
agpl
Patrick Niebeling
WorkflowDeckAutomation
diff --git a/lib/Service/WorkflowRunner.php b/lib/Service/WorkflowRunner.php
index d40bd61..2808ada 100644
--- a/lib/Service/WorkflowRunner.php
+++ b/lib/Service/WorkflowRunner.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace OCA\WorkflowDeckAutomation\Service;
+use DateTimeInterface;
use OCA\Deck\Db\Card;
use OCA\WorkflowDeckAutomation\Db\Workflow;
use OCA\WorkflowDeckAutomation\Db\WorkflowMapper;
@@ -165,8 +166,10 @@ class WorkflowRunner {
// and the workflow wants a mail — this is decoration, not a check.
$targets = null;
+ $now = $this->timeFactory->getDateTime();
+
foreach ($cards as $card) {
- if (!self::isOverdue($card->getDaysUntilDue())) {
+ if (!self::isOverdue($card->getDuedate(), $now)) {
continue;
}
@@ -319,8 +322,17 @@ class WorkflowRunner {
}
}
- public static function isOverdue(?int $daysUntilDue): bool {
- return $daysUntilDue !== null && $daysUntilDue < 0;
+ /**
+ * Compares the card's actual due timestamp against $now instead of Deck's own
+ * Card::getDaysUntilDue(), which truncates both sides to midnight before diffing
+ * (DateInterval's %a is a whole-day count) and therefore reports 0 - not overdue -
+ * for any card whose due time has already passed today. That silently held back
+ * every card for up to 24h after it actually fell due; comparing the raw datetime
+ * instead matches what Deck's own UI shows (e.g. "vor 2 Stunden") and has no
+ * day-rounding step to get wrong.
+ */
+ public static function isOverdue(?DateTimeInterface $duedate, DateTimeInterface $now): bool {
+ return $duedate !== null && $duedate < $now;
}
/**
diff --git a/package.json b/package.json
index 16a3a1e..de0f383 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "workflow_deck_automation",
- "version": "34.0.1",
+ "version": "34.0.2",
"private": true,
"type": "module",
"description": "Automates moving overdue Deck cards between stacks, configurable per user.",
diff --git a/tests/Unit/Service/WorkflowRunnerFilterTest.php b/tests/Unit/Service/WorkflowRunnerFilterTest.php
index e9d553b..93b01b3 100644
--- a/tests/Unit/Service/WorkflowRunnerFilterTest.php
+++ b/tests/Unit/Service/WorkflowRunnerFilterTest.php
@@ -4,22 +4,35 @@ declare(strict_types=1);
namespace OCA\WorkflowDeckAutomation\Tests\Unit\Service;
+use DateTimeImmutable;
use OCA\WorkflowDeckAutomation\Service\WorkflowRunner;
use PHPUnit\Framework\TestCase;
class WorkflowRunnerFilterTest extends TestCase {
public function testIsOverdueReturnsFalseWithoutDueDate(): void {
- $this->assertFalse(WorkflowRunner::isOverdue(null));
+ $this->assertFalse(WorkflowRunner::isOverdue(null, new DateTimeImmutable('2026-01-15 12:00:00')));
}
public function testIsOverdueReturnsFalseForFutureDueDate(): void {
- $this->assertFalse(WorkflowRunner::isOverdue(0));
- $this->assertFalse(WorkflowRunner::isOverdue(3));
+ $now = new DateTimeImmutable('2026-01-15 12:00:00');
+ $this->assertFalse(WorkflowRunner::isOverdue($now->modify('+1 hour'), $now));
+ $this->assertFalse(WorkflowRunner::isOverdue($now->modify('+3 days'), $now));
}
public function testIsOverdueReturnsTrueForPastDueDate(): void {
- $this->assertTrue(WorkflowRunner::isOverdue(-1));
- $this->assertTrue(WorkflowRunner::isOverdue(-30));
+ $now = new DateTimeImmutable('2026-01-15 12:00:00');
+ $this->assertTrue(WorkflowRunner::isOverdue($now->modify('-1 hour'), $now));
+ $this->assertTrue(WorkflowRunner::isOverdue($now->modify('-30 days'), $now));
+ }
+
+ public function testIsOverdueReturnsTrueForADueTimeEarlierTheSameDay(): void {
+ // Regression: comparing whole calendar days (as Deck's own
+ // Card::getDaysUntilDue() does) reports a card due earlier today as
+ // "0 days until due", not overdue, until the calendar date rolls
+ // over - holding every card back for up to 24h after it actually
+ // fell due. isOverdue() must compare the real timestamps instead.
+ $now = new DateTimeImmutable('2026-01-15 12:00:00');
+ $this->assertTrue(WorkflowRunner::isOverdue(new DateTimeImmutable('2026-01-15 06:00:00'), $now));
}
public function testNoFiltersMatchesAnyCard(): void {