3 Commits
Author SHA1 Message Date
Patrick Niebeling ce749e63a4 Fix overdue check to compare real timestamps, not whole calendar days
Build package / package (push) Successful in 57s
Build package / php-lint (8.4) (push) Successful in 44s
Build package / php-lint (8.5) (push) Successful in 35s
Build package / xml-lint (push) Successful in 11s
Build package / unit-tests (push) Successful in 37s
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.
2026-08-25 13:48:02 +02:00
Patrick Niebeling b203ba35f8 Align declared PHP compatibility with CI: require 8.4-8.5
Build package / php-lint (8.4) (push) Successful in 36s
Build package / php-lint (8.5) (push) Successful in 35s
Build package / xml-lint (push) Successful in 14s
Build package / unit-tests (push) Successful in 37s
Build package / package (push) Successful in 52s
Bump to 34.0.1.
2026-08-25 13:28:52 +02:00
Patrick Niebeling ef973af4b5 Drop PHP 8.2/8.3 from CI, test against 8.4/8.5 only
Build package / php-lint (8.4) (push) Successful in 36s
Build package / php-lint (8.5) (push) Successful in 33s
Build package / xml-lint (push) Successful in 11s
Build package / unit-tests (push) Successful in 39s
Build package / package (push) Successful in 52s
2026-08-25 13:14:02 +02:00
5 changed files with 38 additions and 13 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: gitea-runner-server03 runs-on: gitea-runner-server03
strategy: strategy:
matrix: matrix:
php-version: ['8.2', '8.3', '8.4', '8.5'] php-version: ['8.4', '8.5']
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
@@ -51,7 +51,7 @@ jobs:
- uses: shivammathur/setup-php@v2 - uses: shivammathur/setup-php@v2
with: with:
php-version: '8.3' php-version: '8.4'
extensions: sqlite, pdo_sqlite extensions: sqlite, pdo_sqlite
coverage: none coverage: none
+2 -2
View File
@@ -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). 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> ]]></description>
<version>34.0.0</version> <version>34.0.2</version>
<licence>agpl</licence> <licence>agpl</licence>
<author mail="patrick@niebel.ing">Patrick Niebeling</author> <author mail="patrick@niebel.ing">Patrick Niebeling</author>
<namespace>WorkflowDeckAutomation</namespace> <namespace>WorkflowDeckAutomation</namespace>
@@ -36,7 +36,7 @@ A background job periodically evaluates all enabled workflows and moves cards wh
<category>tools</category> <category>tools</category>
<bugs>https://github.com/pniebeling/workflow_deck_automation/issues</bugs> <bugs>https://github.com/pniebeling/workflow_deck_automation/issues</bugs>
<dependencies> <dependencies>
<php min-version="8.2" max-version="8.5"/> <php min-version="8.4" max-version="8.5"/>
<database min-version="9.4">pgsql</database> <database min-version="9.4">pgsql</database>
<database>sqlite</database> <database>sqlite</database>
<database min-version="8.0">mysql</database> <database min-version="8.0">mysql</database>
+15 -3
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace OCA\WorkflowDeckAutomation\Service; namespace OCA\WorkflowDeckAutomation\Service;
use DateTimeInterface;
use OCA\Deck\Db\Card; use OCA\Deck\Db\Card;
use OCA\WorkflowDeckAutomation\Db\Workflow; use OCA\WorkflowDeckAutomation\Db\Workflow;
use OCA\WorkflowDeckAutomation\Db\WorkflowMapper; use OCA\WorkflowDeckAutomation\Db\WorkflowMapper;
@@ -165,8 +166,10 @@ class WorkflowRunner {
// and the workflow wants a mail — this is decoration, not a check. // and the workflow wants a mail — this is decoration, not a check.
$targets = null; $targets = null;
$now = $this->timeFactory->getDateTime();
foreach ($cards as $card) { foreach ($cards as $card) {
if (!self::isOverdue($card->getDaysUntilDue())) { if (!self::isOverdue($card->getDuedate(), $now)) {
continue; 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
View File
@@ -1,6 +1,6 @@
{ {
"name": "workflow_deck_automation", "name": "workflow_deck_automation",
"version": "34.0.0", "version": "34.0.2",
"private": true, "private": true,
"type": "module", "type": "module",
"description": "Automates moving overdue Deck cards between stacks, configurable per user.", "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; namespace OCA\WorkflowDeckAutomation\Tests\Unit\Service;
use DateTimeImmutable;
use OCA\WorkflowDeckAutomation\Service\WorkflowRunner; use OCA\WorkflowDeckAutomation\Service\WorkflowRunner;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class WorkflowRunnerFilterTest extends TestCase { class WorkflowRunnerFilterTest extends TestCase {
public function testIsOverdueReturnsFalseWithoutDueDate(): void { 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 { public function testIsOverdueReturnsFalseForFutureDueDate(): void {
$this->assertFalse(WorkflowRunner::isOverdue(0)); $now = new DateTimeImmutable('2026-01-15 12:00:00');
$this->assertFalse(WorkflowRunner::isOverdue(3)); $this->assertFalse(WorkflowRunner::isOverdue($now->modify('+1 hour'), $now));
$this->assertFalse(WorkflowRunner::isOverdue($now->modify('+3 days'), $now));
} }
public function testIsOverdueReturnsTrueForPastDueDate(): void { public function testIsOverdueReturnsTrueForPastDueDate(): void {
$this->assertTrue(WorkflowRunner::isOverdue(-1)); $now = new DateTimeImmutable('2026-01-15 12:00:00');
$this->assertTrue(WorkflowRunner::isOverdue(-30)); $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 { public function testNoFiltersMatchesAnyCard(): void {