Files
GSB-Construction/Modules/TimelineScheduling/app/Services/GanttDataTransformer.php

69 lines
2.2 KiB
PHP

<?php
namespace Modules\TimelineScheduling\Services;
use Illuminate\Support\Collection;
use Modules\ProjectManagement\Models\Task;
use Modules\TimelineScheduling\Models\TaskDependency;
class GanttDataTransformer
{
/**
* Transform project tasks + dependencies into Gantt-chart-ready JSON.
* Compatible with Frappe Gantt / similar chart libraries.
*/
public function transform(int $projectId): array
{
$tasks = Task::where('project_id', $projectId)
->select('id', 'ulid', 'name', 'status', 'start_date', 'end_date', 'priority')
->orderBy('start_date')
->get();
$dependencies = TaskDependency::whereIn('task_id', $tasks->pluck('id'))
->get()
->groupBy('task_id');
$ganttTasks = $tasks->map(function (Task $task) use ($dependencies) {
$deps = $dependencies->get($task->id, collect());
$depStrings = $deps->map(fn($d) => "task-{$d->predecessor_id}")->implode(', ');
return [
'id' => "task-{$task->id}",
'name' => $task->name,
'start' => $task->start_date?->format('Y-m-d') ?? now()->format('Y-m-d'),
'end' => $task->end_date?->format('Y-m-d') ?? now()->addDays(7)->format('Y-m-d'),
'progress' => $this->statusToProgress($task->status),
'dependencies' => $depStrings ?: null,
'custom_class' => $this->statusToClass($task->status),
'meta' => [
'task_id' => $task->id,
'status' => $task->status,
'priority' => $task->priority,
],
];
});
return $ganttTasks->values()->toArray();
}
private function statusToProgress(string $status): int
{
return match ($status) {
'completed' => 100,
'in_progress' => 50,
'on_hold' => 25,
default => 0,
};
}
private function statusToClass(string $status): string
{
return match ($status) {
'completed' => 'bar-completed',
'in_progress' => 'bar-in-progress',
'on_hold' => 'bar-on-hold',
default => 'bar-pending',
};
}
}