A project management app derived from Mind-Vision-Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 line
4.9KB

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Repositories;
  4. use Core\Database;
  5. class TaskRepository
  6. {
  7. public function __construct(protected ?Database $database = null)
  8. {
  9. $this->database ??= database();
  10. }
  11. public function create(int $projectId, array $data): int
  12. {
  13. $position = (int) ($this->database->first(
  14. 'SELECT COALESCE(MAX(position), 0) + 1 AS next_position FROM tasks WHERE project_id = :project_id AND status = :status',
  15. [
  16. 'project_id' => $projectId,
  17. 'status' => $data['status'] ?? 'backlog',
  18. ]
  19. )['next_position'] ?? 1);
  20. $this->database->execute(
  21. 'INSERT INTO tasks (
  22. project_id, title, description, status, priority, assignee, estimate_hours, due_date, position, completed_at
  23. ) VALUES (
  24. :project_id, :title, :description, :status, :priority, :assignee, :estimate_hours, :due_date, :position, :completed_at
  25. )',
  26. [
  27. 'project_id' => $projectId,
  28. 'title' => $data['title'],
  29. 'description' => $data['description'] ?? '',
  30. 'status' => $data['status'] ?? 'backlog',
  31. 'priority' => $data['priority'] ?? 'normal',
  32. 'assignee' => $data['assignee'] ?? '',
  33. 'estimate_hours' => $data['estimate_hours'] ?? null,
  34. 'due_date' => $data['due_date'] ?? null,
  35. 'position' => $position,
  36. 'completed_at' => ($data['status'] ?? 'backlog') === 'done' ? date('Y-m-d H:i:s') : null,
  37. ]
  38. );
  39. return (int) $this->database->pdo()->lastInsertId();
  40. }
  41. public function updateStatus(int $taskId, string $status): ?int
  42. {
  43. $task = $this->database->first('SELECT id, project_id, title, status FROM tasks WHERE id = :id', ['id' => $taskId]);
  44. if ($task === null) {
  45. return null;
  46. }
  47. $completedAt = $status === 'done' ? date('Y-m-d H:i:s') : null;
  48. $this->database->execute(
  49. 'UPDATE tasks
  50. SET status = :status,
  51. completed_at = :completed_at,
  52. updated_at = CURRENT_TIMESTAMP
  53. WHERE id = :id',
  54. [
  55. 'status' => $status,
  56. 'completed_at' => $completedAt,
  57. 'id' => $taskId,
  58. ]
  59. );
  60. return (int) $task['project_id'];
  61. }
  62. public function dueSoon(int $limit = 6): array
  63. {
  64. $limit = max(1, min(25, $limit));
  65. return $this->database->query(
  66. 'SELECT t.*, p.name AS project_name, p.code AS project_code
  67. FROM tasks t
  68. INNER JOIN projects p ON p.id = t.project_id
  69. WHERE t.status != "done"
  70. AND t.due_date IS NOT NULL
  71. AND date(t.due_date) BETWEEN date("now") AND date("now", "+7 day")
  72. ORDER BY date(t.due_date) ASC, CASE t.priority WHEN "urgent" THEN 0 WHEN "high" THEN 1 WHEN "normal" THEN 2 ELSE 3 END, t.id DESC
  73. LIMIT ' . $limit
  74. );
  75. }
  76. public function overdue(int $limit = 6): array
  77. {
  78. $limit = max(1, min(25, $limit));
  79. return $this->database->query(
  80. 'SELECT t.*, p.name AS project_name, p.code AS project_code
  81. FROM tasks t
  82. INNER JOIN projects p ON p.id = t.project_id
  83. WHERE t.status != "done"
  84. AND t.due_date IS NOT NULL
  85. AND date(t.due_date) < date("now")
  86. ORDER BY date(t.due_date) ASC, t.id DESC
  87. LIMIT ' . $limit
  88. );
  89. }
  90. public function countsByStatus(int $projectId): array
  91. {
  92. $rows = $this->database->query(
  93. 'SELECT status, COUNT(*) AS total
  94. FROM tasks
  95. WHERE project_id = :project_id
  96. GROUP BY status',
  97. ['project_id' => $projectId]
  98. );
  99. $counts = [];
  100. foreach ($rows as $row) {
  101. $counts[$row['status']] = (int) $row['total'];
  102. }
  103. return $counts;
  104. }
  105. public function forProject(int $projectId): array
  106. {
  107. return $this->database->query(
  108. 'SELECT *
  109. FROM tasks
  110. WHERE project_id = :project_id
  111. ORDER BY
  112. CASE status
  113. WHEN "backlog" THEN 0
  114. WHEN "in-progress" THEN 1
  115. WHEN "review" THEN 2
  116. WHEN "blocked" THEN 3
  117. WHEN "done" THEN 4
  118. ELSE 5
  119. END,
  120. CASE priority
  121. WHEN "urgent" THEN 0
  122. WHEN "high" THEN 1
  123. WHEN "normal" THEN 2
  124. ELSE 3
  125. END,
  126. due_date IS NULL,
  127. due_date ASC,
  128. position ASC,
  129. id ASC',
  130. ['project_id' => $projectId]
  131. );
  132. }
  133. }

Powered by TurnKey Linux.