Fix overdue check to compare real timestamps, not whole calendar days
WorkflowRunner::isOverdue() took Card::getDaysUntilDue(), which Deck computes by truncating both "now" and the due date to midnight before diffing. A card due earlier today therefore reported 0 days until due - not overdue - until the calendar date rolled over to the next day, so a card due "this morning" sat unmoved for up to 24h while one due "yesterday morning" moved immediately. isOverdue() now takes the due date and $now directly and compares them as real timestamps, matching what Deck's own UI shows. Bump to 34.0.2.
This commit is contained in:
+1
-1
@@ -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).
|
||||
]]></description>
|
||||
<version>34.0.1</version>
|
||||
<version>34.0.2</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="patrick@niebel.ing">Patrick Niebeling</author>
|
||||
<namespace>WorkflowDeckAutomation</namespace>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -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.",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user