ProjectGanttService.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. namespace App\Services\Project;
  3. use App\Http\Resources\API\ProjectGanttResource;
  4. use App\Http\Resources\API\ProjectGroupViewTaskResource;
  5. use App\Models\Enums\ProjectStatus;
  6. use App\Models\Project;
  7. use App\Models\Requirement;
  8. use App\Models\Task;
  9. use App\Models\User;
  10. use Carbon\Carbon;
  11. use Illuminate\Support\Collection;
  12. class ProjectGanttService
  13. {
  14. public function gantt(Project $project, string $group): array
  15. {
  16. $groupTasks = $this->getGroupTask($project, $group);
  17. $groups = $groupTasks->keys()->filter();
  18. $groupNamesKeyBy = $this->getGroupNamesKeyBy($groups, $group);
  19. $items = [];
  20. foreach(["", ...$groups] as $groupKey) {
  21. if (! isset($groupTasks[$groupKey])) {
  22. continue;
  23. }
  24. $treeTasks = make_tree($groupTasks[$groupKey]->toArray());
  25. $groupUniqueKey = uniqid();
  26. $items[] = $this->topGroupFormat(
  27. $groupUniqueKey,
  28. isset($groupNamesKeyBy[$groupKey]) ? $groupNamesKeyBy[$groupKey]['name'] : "Empty"
  29. );
  30. $tasks = $this->flattenTasks($treeTasks);
  31. foreach ($tasks as $task) {
  32. $items[] = $this->taskFormat($task, $groupUniqueKey);
  33. }
  34. }
  35. return $items;
  36. }
  37. protected function topGroupFormat(string $id, string $name)
  38. {
  39. return [
  40. 'id' => $id,
  41. 'text' => $name,
  42. 'parent' => 0,
  43. 'start_date' => null,
  44. 'end_date' => null,
  45. 'duration' => null,
  46. 'progress' => 0,
  47. 'assign_to' => null,
  48. 'open' => true,
  49. ];
  50. }
  51. protected function taskFormat(array $task, string $topId)
  52. {
  53. $progress = 0;
  54. $begin = $task['begin'] ? Carbon::parse($task['begin']) : Carbon::parse($task['created_at']);
  55. $end = $task['end'] ? Carbon::parse($task['end']) : $begin->copy()->addYears(2);
  56. $now = Carbon::now();
  57. if ($now->gt($end)) {
  58. $progress = 1;
  59. }
  60. if ($now->gt($begin) && $end->gt($now)) {
  61. $totalDay = $end->diffInDays($begin);
  62. $day = $now->diffInDays($begin);
  63. $progress = (float)number_format($day / $totalDay, 4);
  64. }
  65. return [
  66. 'id' => $task['id'],
  67. 'text' => $task['name'],
  68. 'parent' => $task['parent_id'] > 0 ? $task['parent_id'] : $topId ,
  69. 'start_date' => $task['begin'],
  70. 'end_date' => $task['end'],
  71. 'duration' => $end->diffInDays($begin),
  72. 'progress' => $progress,
  73. 'assign_to' =>$task['assign']?User::query()->where('id',$task['assign'])->first()->name:null,
  74. 'open' => true,
  75. ];
  76. }
  77. protected function flattenTasks($tasks) {
  78. $items = [];
  79. foreach ($tasks as $task) {
  80. $items[] = $task;
  81. if (!empty($task['children'])) {
  82. $items = array_merge($items, $this->flattenTasks($task['children']));
  83. }
  84. unset($task['children']);
  85. }
  86. return $items;
  87. }
  88. protected function getGroupNamesKeyBy(Collection $groups, string $group): array
  89. {
  90. $groupsFormat = $groups->map(fn($group) => ['id' => $group, 'name' => $group]);
  91. $groupNames = match ($group) {
  92. "requirement_id" => Requirement::query()->whereIn("id", $groups)->selectRaw("id,title as name")->get(),
  93. "task_type" => $groupsFormat,
  94. "assign" => User::query()->whereIn("id", $groups)->get(['id', 'name']),
  95. };
  96. return $groupNames->keyBy("id")->toArray();
  97. }
  98. protected function getGroupTask(
  99. Project $project,
  100. string $group,
  101. ): \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|array
  102. {
  103. return Task::query()
  104. ->with(['assignTo', 'finishedBy'])
  105. ->where("project_id", $project->id)
  106. ->get()
  107. ->groupBy($group);
  108. }
  109. }