Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions app/Domain/Tickets/Services/Tickets.php
Original file line number Diff line number Diff line change
Expand Up @@ -2418,12 +2418,43 @@ public function getAllDoneUserTickets(?int $userId = null, ?int $project = null)
* then re-completed the same day is included once. Built on the general
* getStatusChangeEvents primitive, so throughput/burndown and strategy
* reporting can reuse the same query.
*
* Thin wrapper over {@see getMyClosedTicketsForRange} with from == to.
*/
Comment on lines +2421 to 2423
#[RequiresPermission(TicketsPermissions::VIEW)]
public function getMyClosedTicketsForDate(?int $userId = null, ?string $date = null): array
{
$date = $date ?: date('Y-m-d');

return $this->getMyClosedTicketsForRange($userId, $date, $date);
}

/**
* @api
*
* Range form of {@see getMyClosedTicketsForDate}: the user's tasks marked
* DONE anywhere within [$from, $to] (inclusive, dates 'Y-m-d'), each
* annotated with `dateClosed` (the completion timestamp). Powers the mobile
* Progress "Closed this week / this month" sections — completed arcs are
* keyed on close-date within the period, independent of how recently the
* project was otherwise touched, so finished work never disappears.
*
* Same "closed" definition as the single-date form: the ticket is currently
* DONE and its status was changed to that DONE status within the range. A
* ticket completed more than once in the range is included once, keyed to
* its latest completion (events are newest-first). Defaults to today when
* either bound is omitted.
*/
#[RequiresPermission(TicketsPermissions::VIEW)]
public function getMyClosedTicketsForRange(?int $userId = null, ?string $from = null, ?string $to = null): array
{
$from = $from ?: date('Y-m-d');
$to = $to ?: date('Y-m-d');
// Tolerate a reversed range rather than returning nothing.
if ($from > $to) {
[$from, $to] = [$to, $from];
}
Comment on lines +2456 to +2475
Comment on lines +2468 to +2475

// Candidates: the user's currently-DONE tickets (statusType resolved).
$doneTickets = $this->getAllDoneUserTickets($userId);
if (empty($doneTickets)) {
Expand All @@ -2435,7 +2466,7 @@ public function getMyClosedTicketsForDate(?int $userId = null, ?string $date = n
$byId[$ticket['id']] = $ticket;
}

$events = $this->ticketRepository->getStatusChangeEvents(array_keys($byId), $date, $date);
$events = $this->ticketRepository->getStatusChangeEvents(array_keys($byId), $from, $to);

$closed = [];
foreach ($events as $event) {
Expand All @@ -2446,8 +2477,8 @@ public function getMyClosedTicketsForDate(?int $userId = null, ?string $date = n
}

// Only count changes INTO the ticket's current (DONE) status — it
// was actually marked done that day, not merely touched. Events are
// newest-first, so the first match keeps the latest completion time.
// was actually marked done in the range, not merely touched. Events
// are newest-first, so the first match keeps the latest completion.
if ((string) $event['changeValue'] === (string) $ticket['status']) {
$ticket['dateClosed'] = $event['dateModified'];
$closed[$ticketId] = $ticket;
Expand Down
Loading