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

    No labels
    No 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