Skip to content

Completed (done) cards still flagged as overdue — getDueStatus() ignores done field #8001

@samsclub91

Description

@samsclub91

Bug: Completed (done) cards still flagged as overdue via API overdue field

Nextcloud Deck version: 1.17.1
Nextcloud version: 33.0.3

Description

When a card is marked as "done" (the done field set to a timestamp), the Nextcloud Deck API still returns overdue: 3 (the DUEDATE_OVERDUE constant) on that card if its original duedate is in the past. The overdue field computation does not check the done status of the card.

This causes third-party apps (e.g., Next Deck on iOS/Android) and API consumers to display completed tasks as overdue, even when they have a visible "done" checkmark.

Steps to Reproduce

  1. Create a card in Nextcloud Deck with a due date in the past (e.g., May 2)
  2. Mark the card as done (set the done checkbox)
  3. Query the card via the Deck API: GET /index.php/apps/deck/api/v1.0/boards/{id}/stacks

Expected Behavior

The overdue field on a done card should return 0 (DUEDATE_FUTURE) or a new value indicating "completed" — not 3 (DUEDATE_OVERDUE). A card that has been completed should never be flagged as overdue regardless of its original due date.

Actual Behavior

The API returns overdue: 3 for done cards with past due dates:

{
  "title": "Review ALL DNS configurations for jeepnet.tech",
  "done": "2026-05-31T12:50:09+00:00",
  "duedate": "2026-05-03T00:00:00+00:00",
  "overdue": 3
}

Root Cause

In lib/Model/CardDetails.php, the getDueStatus() method computes the overdue state based solely on getDaysUntilDue(), which only compares the duedate to the current date. It does not check $this->getDone():

private function getDueStatus(): int {
    $diffDays = $this->getDaysUntilDue();
    if ($diffDays === null || $diffDays > 1) {
        return static::DUEDATE_FUTURE;      // 0
    }
    if ($diffDays === 1) {
        return static::DUEDATE_NEXT;         // 1
    }
    if ($diffDays === 0) {
        return static::DUEDATE_NOW;           // 2
    }
    return static::DUEDATE_OVERDUE;          // 3 — reached even when done
}

And in lib/Db/Card.php, getDaysUntilDue() only checks duedate, not done:

public function getDaysUntilDue(): ?int {
    if ($this->getDuedate() === null) {
        return null;
    }
    // ... compares duedate to today, no done check
}

Notably, the database query layer in CardMapper.php does correctly exclude done cards from overdue queries (->andWhere($qb->expr()->isNull('done'))), but the per-card overdue field in API responses bypasses this.

Suggested Fix

Add a done check to getDueStatus():

private function getDueStatus(): int {
    if ($this->getDone() !== null) {
        return static::DUEDATE_FUTURE;  // or a new DUEDATE_COMPLETED constant
    }
    $diffDays = $this->getDaysUntilDue();
    // ... rest of existing logic
}

This would ensure that completed cards are never flagged as overdue in API responses, which would also fix the issue for all third-party apps consuming the API.

Impact

  • Third-party apps (Next Deck, etc.) that rely on the overdue field display completed tasks as overdue
  • Any API consumer filtering by overdue status gets false positives
  • The web UI may also be affected depending on which code paths it uses

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions