mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-10-13 16:23:18 +01:00
move goal progress calculation out of the resources
This commit is contained in:
@@ -14,6 +14,7 @@ use App\Http\Resources\V1\Goal\GoalResource;
|
||||
use App\Models\Goal;
|
||||
use App\Models\Organization;
|
||||
use App\Service\BillingContract;
|
||||
use App\Service\GoalProgressService;
|
||||
use App\Service\GoalsContract;
|
||||
use App\Service\TimezoneService;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
@@ -73,7 +74,7 @@ class GoalController extends Controller
|
||||
*
|
||||
* @operationId getGoals
|
||||
*/
|
||||
public function index(Organization $organization, GoalIndexRequest $request, GoalsContract $access): GoalCollection
|
||||
public function index(Organization $organization, GoalIndexRequest $request, GoalsContract $access, GoalProgressService $progressService): GoalCollection
|
||||
{
|
||||
// An organization goal is visible to the member it is for, who does not hold the :organization-type permission.
|
||||
// Either permission is enough, the access contract decides which goals come back.
|
||||
@@ -96,8 +97,9 @@ class GoalController extends Controller
|
||||
}
|
||||
|
||||
$goals = $query->paginate(config('app.pagination_per_page_default'));
|
||||
$progressByGoalId = $progressService->getCurrentProgressForGoals($goals->getCollection(), Carbon::now());
|
||||
|
||||
return new GoalCollection($goals);
|
||||
return new GoalCollection($goals, $progressByGoalId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +109,7 @@ class GoalController extends Controller
|
||||
*
|
||||
* @operationId getGoal
|
||||
*/
|
||||
public function show(Organization $organization, Goal $goal, GoalsContract $access): GoalResource
|
||||
public function show(Organization $organization, Goal $goal, GoalsContract $access, GoalProgressService $progressService): GoalResource
|
||||
{
|
||||
// Either permission is enough, see index
|
||||
$this->checkAnyPermission($organization, ['goals:view:own', 'goals:view:organization-type']);
|
||||
@@ -118,7 +120,7 @@ class GoalController extends Controller
|
||||
}
|
||||
$goal->load('member.user');
|
||||
|
||||
return new GoalResource($goal);
|
||||
return new GoalResource($goal, $progressService->getCurrentProgress($goal, Carbon::now()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +130,7 @@ class GoalController extends Controller
|
||||
*
|
||||
* @operationId createGoal
|
||||
*/
|
||||
public function store(Organization $organization, GoalStoreRequest $request, GoalsContract $access): JsonResponse
|
||||
public function store(Organization $organization, GoalStoreRequest $request, GoalsContract $access, GoalProgressService $progressService): JsonResponse
|
||||
{
|
||||
if ($request->getType() === GoalType::Personal) {
|
||||
$this->checkPermission($organization, 'goals:create:own');
|
||||
@@ -159,7 +161,7 @@ class GoalController extends Controller
|
||||
$goal->save();
|
||||
$goal->load('member.user');
|
||||
|
||||
return (new GoalResource($goal))
|
||||
return (new GoalResource($goal, $progressService->getCurrentProgress($goal, Carbon::now())))
|
||||
->response()
|
||||
->setStatusCode(201);
|
||||
}
|
||||
@@ -173,7 +175,7 @@ class GoalController extends Controller
|
||||
*
|
||||
* @operationId updateGoal
|
||||
*/
|
||||
public function update(Organization $organization, Goal $goal, GoalUpdateRequest $request, GoalsContract $access): GoalResource
|
||||
public function update(Organization $organization, Goal $goal, GoalUpdateRequest $request, GoalsContract $access, GoalProgressService $progressService): GoalResource
|
||||
{
|
||||
if ($goal->type === GoalType::Personal) {
|
||||
$this->checkPermission($organization, 'goals:update:own', $goal);
|
||||
@@ -212,7 +214,7 @@ class GoalController extends Controller
|
||||
$goal->save();
|
||||
$goal->load('member.user');
|
||||
|
||||
return new GoalResource($goal);
|
||||
return new GoalResource($goal, $progressService->getCurrentProgress($goal, Carbon::now()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,14 +5,42 @@ declare(strict_types=1);
|
||||
namespace App\Http\Resources\V1\Goal;
|
||||
|
||||
use App\Http\Resources\PaginatedResourceCollection;
|
||||
use App\Models\Goal;
|
||||
use App\Service\Dto\GoalProgressDto;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class GoalCollection extends ResourceCollection implements PaginatedResourceCollection
|
||||
{
|
||||
/**
|
||||
* The resource that this resource collects.
|
||||
*
|
||||
* @var string
|
||||
* @var array<string, GoalProgressDto>
|
||||
*/
|
||||
public $collects = GoalResource::class;
|
||||
private array $progressByGoalId;
|
||||
|
||||
/**
|
||||
* @param array<string, GoalProgressDto> $progressByGoalId
|
||||
*/
|
||||
public function __construct($resource, array $progressByGoalId)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
$this->progressByGoalId = $progressByGoalId;
|
||||
}
|
||||
|
||||
protected function collects(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @return array<array<string, string|bool|int|null|array<string, string|bool|int|null|array<int, string>>>>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return $this->collection->map(function (Goal $goal) use ($request): array {
|
||||
return (new GoalResource($goal, $this->progressByGoalId[$goal->getKey()]))
|
||||
->toArray($request);
|
||||
})->all();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,23 @@ namespace App\Http\Resources\V1\Goal;
|
||||
|
||||
use App\Http\Resources\V1\BaseResource;
|
||||
use App\Models\Goal;
|
||||
use App\Service\GoalProgressService;
|
||||
use App\Service\Dto\GoalProgressDto;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* @property Goal $resource
|
||||
*/
|
||||
class GoalResource extends BaseResource
|
||||
{
|
||||
private GoalProgressDto $progress;
|
||||
|
||||
public function __construct(Goal $resource, GoalProgressDto $progress)
|
||||
{
|
||||
parent::__construct($resource);
|
||||
|
||||
$this->progress = $progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
@@ -22,11 +30,6 @@ class GoalResource extends BaseResource
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
$progressService = app(GoalProgressService::class);
|
||||
$now = Carbon::now();
|
||||
[$periodStart, $periodEnd] = $progressService->getPeriodBounds($this->resource, $now);
|
||||
$trackedSeconds = $progressService->getProgress($this->resource, $periodStart, $periodEnd);
|
||||
|
||||
return [
|
||||
/** @var string $id ID of the goal */
|
||||
'id' => $this->resource->id,
|
||||
@@ -70,13 +73,13 @@ class GoalResource extends BaseResource
|
||||
],
|
||||
'progress' => [
|
||||
/** @var string $period_start Start of the current period (inclusive) */
|
||||
'period_start' => $this->formatDateTime($periodStart),
|
||||
'period_start' => $this->formatDateTime($this->progress->periodStart),
|
||||
/** @var string $period_end End of the current period (exclusive) */
|
||||
'period_end' => $this->formatDateTime($periodEnd),
|
||||
'period_end' => $this->formatDateTime($this->progress->periodEnd),
|
||||
/** @var int $tracked_seconds Seconds tracked in the current period that match the filters, incl. the running time entry */
|
||||
'tracked_seconds' => $trackedSeconds,
|
||||
'tracked_seconds' => $this->progress->trackedSeconds,
|
||||
/** @var string $status Status in the current period (in_progress, achieved, on_track, exceeded) */
|
||||
'status' => $progressService->getStatus($this->resource, $trackedSeconds)->value,
|
||||
'status' => $this->progress->status->value,
|
||||
],
|
||||
/** @var string $created_at Date when the goal was created */
|
||||
'created_at' => $this->formatDateTime($this->resource->created_at),
|
||||
|
||||
Reference in New Issue
Block a user