PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.12
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.12
2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 1.41 1.45 All 41 releases
fluent-boards / app / Services / BoardService.php

BoardService.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.12, at app/Services/BoardService.php

803 lines 26.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\App\Services;
4
5 use FluentBoards\App\Models\Activity;
6 use FluentBoards\App\Models\Stage;
7 use FluentBoards\App\Models\User;
8 use FluentBoards\App\Models\Board;
9 use FluentBoards\App\Models\Relation;
10 use FluentBoards\App\Models\Task;
11 use FluentBoards\App\Models\Meta;
12 use FluentBoards\App\Models\TaskMeta;
13 use FluentBoards\Framework\Support\Arr;
14
15 class BoardService
16 {
17 public function getBoardsByType($type)
18 {
19 return Board::where('type', $type)->whereNull('archived_at')->orderBy('created_at', 'ASC')->get();
20 }
21
22 public function deleteBoard($boardId)
23 {
24 $board = Board::findOrFail($boardId);
25
26 $options = null;
27 //if we need to do something before a board is deleted
28 do_action('fluent_boards/before_board_deleted', $board, $options);
29
30 //related task delete, task related relations delete
31 $allTaskIdsInBoard = $board->tasks->pluck('id');
32 $taskRelatedRelations = Relation::whereIn('object_id', $allTaskIdsInBoard);
33 $taskRelatedRelations->delete();
34 TaskMeta::whereIn('task_id', $allTaskIdsInBoard)->delete();
35
36
37 Task::whereIn('id', $allTaskIdsInBoard)->delete();
38
39 //removing all Board Settings
40 $board->boardUserEmailNotificationSettings()->detach();
41 $board->boardUserNotificationSettings()->detach();
42 //removing all Board users
43 $board->users()->detach();
44
45 //removing add board stages
46 $board->stages()->delete();
47
48 //removing add board labels
49 $board->labels()->delete();
50
51 //removing add board comment
52 $board->comments()->delete();
53
54 foreach ($board->notifications as $notification) {
55 $notification->users()->detach();
56 }
57 $board->notifications()->delete();
58
59 //delete board related meta
60 $this->deleteBoardMeta($boardId);
61
62 $board->delete();
63 // do_action('fluent_boards/board_deleted', $board);
64 }
65
66 public function fetchBoardMeta($boardId)
67 {
68 $boardMeta = Meta::where('object_id', $boardId)
69 ->where('object_type', 'board')
70 ->where('key', 'is_auth_require')
71 ->orderBy('id', 'desc')->first();
72
73 if ($boardMeta) {
74 $boardMeta->value = maybe_unserialize($boardMeta->value);
75 return $boardMeta;
76 } else {
77 $meta = new Meta();
78 $settingData = array(
79 'is_auth_require_idea_submit' => '',
80 'is_auth_require_voting_commenting' => '',
81 'is_auth_require_reaction' => '',
82 'is_allow_email_along_with_auth' => '',
83 'is_allow_unauthentication_reaction_along_with_auth' => ''
84 );
85 $meta->object_id = $boardId;
86 $meta->object_type = 'board';
87 $meta->key = 'is_auth_require';
88 $meta->value = \maybe_serialize($settingData);
89 $meta->save();
90 $meta->value = $settingData;
91 return $meta;
92 }
93 }
94
95 public function modifyAuthenticationPermission($data, $boardId)
96 {
97 $boardMeta = Meta::where('object_id', $boardId)
98 ->where('object_type', 'board')
99 ->where('key', 'is_auth_require')
100 ->orderBy('id', 'desc')->first();
101
102 if ($boardMeta) {
103 $settings = array(
104 'is_auth_require_idea_submit' => $data['is_auth_require_idea_submit'],
105 'is_auth_require_voting_commenting' => $data['is_auth_require_voting_commenting'],
106 'is_auth_require_reaction' => $data['is_auth_require_reaction'],
107 'is_allow_email_along_with_auth' => $data['is_allow_email_along_with_auth'],
108 'is_allow_unauthentication_reaction_along_with_auth' => $data['is_allow_unauthentication_reaction_along_with_auth']
109 );
110 $boardMeta->value = \maybe_serialize($settings);
111 $boardMeta->save();
112 }
113 return $boardMeta;
114 }
115
116 public function createBoard($boardData)
117 {
118 $boardData = [
119 'title' => $boardData['title'],
120 'type' => $boardData['type'] ? $boardData['type'] : 'todo',
121 'description' => $boardData['description'],
122 'currency' => isset($boardData['currency']) ? $boardData['currency'] : 'USD',
123 'background' => isset($boardData['background']) ? $boardData['background'] : '',
124 ];
125
126 $boardData = apply_filters('fluent_boards/before_create_board', $boardData);
127
128 $board = Board::create($boardData);
129
130 $this->setCurrentUserPreferencesOnBoardCreate($board);
131
132 return $board;
133 }
134
135 private function setCurrentUserPreferencesOnBoardCreate($board)
136 {
137 $board->users()->attach(
138 get_current_user_id(),
139 [
140 'object_type' => Constant::OBJECT_TYPE_BOARD_USER,
141 'settings' => maybe_serialize([
142 Constant::IS_BOARD_ADMIN => true
143 ]),
144 'preferences' => maybe_serialize(Constant::BOARD_NOTIFICATION_TYPES)
145 ]
146 );
147 }
148
149 public function removeUserFromBoard($boardId, $userId)
150 {
151
152 $board = Board::findOrFail($boardId);
153 $user = User::findOrFail($userId);
154
155 $board->users()->detach($userId);
156 $board->boardUserNotificationSettings()->detach($userId); //removing notification settings of user in that board
157 $board->boardUserEmailNotificationSettings()->detach($userId); //removing email notification settings of user in that board
158
159 //detacing all tasks of this board from user
160 $taskIdsToDetach = $user->tasks()->where('board_id', $boardId)->get()->pluck('id');
161
162 $user->tasks()->detach($taskIdsToDetach);
163 $user->watchingTasks()->detach($taskIdsToDetach);
164
165 // do_action('fluent_boards/board_member_removed', $boardId, $user->display_name);
166 }
167
168 public function removeFromRecentlyOpened($boardId, $userId)
169 {
170 $recentlyOpened = Meta::where('object_id', $userId)
171 ->where('object_type', Constant::OBJECT_TYPE_USER)
172 ->where('key', Constant::USER_RECENT_BOARDS)
173 ->first();
174 if ($recentlyOpened) {
175 $recentBoardIds = $recentlyOpened->value;
176
177 $index = array_search($boardId, $recentBoardIds);
178 array_splice($recentBoardIds, $index, 1);
179
180 $recentlyOpened->value = $recentBoardIds;
181 $recentlyOpened->save();
182 }
183
184 }
185
186 public function updateBoard($board, $data)
187 {
188 if ($data['title']) {
189 $data['title'] = $data['title'];
190 } else {
191 throw new \Exception('Title cannot be empty');
192 }
193 if (isset($data['description'])) {
194 $data['description'] = $data['description'];
195 }
196 $board->fill($data);
197 $board->save();
198 // do_action('fluent_boards/board_updated', $board);
199 return $board;
200 }
201
202 public function defaultStages()
203 {
204 $stages = [
205 (object)[
206 'group' => 'open',
207 'label' => 'Open',
208 ],
209 (object)[
210 'group' => 'in_progress',
211 'label' => 'In Progress',
212 ],
213 (object)[
214 'group' => 'completed',
215 'label' => 'Completed',
216 ],
217 ];
218
219 return serialize($this->processStages($stages));
220 }
221
222 public function changePositionOfStage($boardId, $changeData)
223 {
224 $allStages = Stage::where('board_id', $boardId)
225 ->where('is_archived', 0)
226 ->where('type', 'stage')
227 ->orderBy('position', 'asc')
228 ->get();
229
230 $changedStage = null;
231
232 foreach ($allStages as $stage) {
233 if ($changeData['fromPosition'] < $changeData['toPosition']) {
234 if ($stage['position'] == $changeData['fromPosition']) {
235 $stage['position'] = (int)$changeData['toPosition'];
236 $stage->save();
237 $changedStage = $stage;
238 } elseif (
239 $stage['position'] > $changeData['fromPosition'] &&
240 $stage['position'] <= $changeData['toPosition']
241 ) {
242 $stage['position'] = $stage->position - 1;
243 $stage->save();
244 }
245 } else {
246 if (
247 $stage['position'] >= $changeData['toPosition'] &&
248 $stage['position'] < $changeData['fromPosition']
249 ) {
250 $stage['position'] = $stage->position + 1;
251 $stage->save();
252 } elseif ($stage['position'] == $changeData['fromPosition']) {
253 $stage['position'] = (int)$changeData['toPosition'];
254 $stage->save();
255 $changedStage = $stage;
256 }
257 }
258 }
259
260 do_action('fluent_boards/board_stage_dragged', $changedStage);
261 }
262
263 public function rePositionStages($boardId, $incomingList)
264 {
265 $oldList = Stage::where('board_id', $boardId)->where('type', 'stage')->whereNull('archived_at')->orderBy('position')->pluck('id');
266
267 foreach ($incomingList as $key => $stage_id) {
268 $stage = Stage::findOrFail($stage_id);
269 $stage->moveToNewPosition($key + 1);
270 }
271 do_action('fluent_boards/board_stages_reordered', $boardId, $oldList);
272 }
273
274 public function processStages($stages)
275 {
276 $processedStages = [];
277 foreach ($stages as $stage) {
278 if (is_object($stage)) {
279 $processedStages[] = (object)[
280 'group' => Helper::snake_case($stage->slug),
281 'label' => sanitize_text_field($stage->label)
282 ];
283 } else {
284 $processedStages[] = (object)[
285 'group' => Helper::snake_case($stage['group']),
286 'label' => sanitize_text_field($stage['label'])
287 ];
288 }
289 }
290 return $processedStages;
291 }
292
293 public function archiveStage($id, $stage)
294 {
295 $stage->archived_at = current_time('mysql');
296 $stage->position = 0;
297 $stage->save();
298
299 do_action('fluent_boards/board_stage_archived', $id, $stage->title);
300 return $stage;
301 }
302
303 public function restoreStage($id, $stage)
304 {
305 $stageService = new StageService();
306 $lastStagePosition = $stageService->getLastPositionOfStagesOfBoard($stage->board_id);
307 $stage->archived_at = null;
308 $stage->position = $lastStagePosition ? $lastStagePosition->position + 1 : 1;
309 $stage->save();
310 do_action('fluent_boards/board_stage_restored', $id, $stage->title);
311 return $stage;
312 }
313
314 public function getActivities($id, $data)
315 {
316 $per_page = isset($data['per_page']) ? $data['per_page'] : 40;
317 $page = isset($data['page']) ? $data['page'] : 1;
318 return Activity::where('object_id', $id)->where('object_type', Constant::ACTIVITY_BOARD)->with(['user'])
319 ->orderBy('id', 'DESC')
320 ->paginate($per_page, ['*'], 'page', $page);
321 }
322
323 public function isAlreadyMember($boardId, $memberId)
324 {
325 $isAlreadyMember = Relation::where('object_id', $boardId)
326 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
327 ->where('foreign_id', $memberId)->first();
328
329 return $isAlreadyMember ?? false;
330 }
331
332 public function addMembersInBoard($boardId, $memberId)
333 {
334 $board = Board::find($boardId);
335
336 if (!$board) {
337 return false;
338 }
339
340 $board->users()->attach(
341 $memberId,
342 [
343 'object_type' => Constant::OBJECT_TYPE_BOARD_USER,
344 'settings' => maybe_serialize(Constant::BOARD_USER_SETTINGS),
345 'preferences' => maybe_serialize(Constant::BOARD_NOTIFICATION_TYPES)
346 ]
347 );
348 $boardMember = User::find($memberId);
349 do_action('fluent_boards/board_member_added', $boardId, $boardMember->display_name);
350 return $boardMember;
351 }
352
353 public function makeAdminOfBoard($boardId, $userId)
354 {
355 $boardUser = Relation::where('object_id', $boardId)
356 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
357 ->where('foreign_id', $userId)->first();
358 $boardUser->settings = [
359 'is_admin' => true
360 ];
361 $boardUser->save();
362
363 $user = User::findOrFail($userId);
364 do_action('fluent_boards/board_admin_added', $boardId, $userId);
365 $user['is_admin'] = true;
366 $user['is_board_admin'] = true;
367 return $user;
368 }
369
370 public function removeAdminFromBoard($boardId, $userId)
371 {
372 $boardUser = Relation::where('object_id', $boardId)
373 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
374 ->where('foreign_id', $userId)->first();
375
376 $boardUser->settings = [
377 'is_admin' => false
378 ];
379
380 $boardUser->save();
381 $user = User::findOrFail($userId);
382 do_action('fluent_boards/board_admin_removed', $boardId, $userId);
383 $user['is_admin'] = false;
384 $user['is_board_admin'] = false;
385 return $user;
386 }
387
388 public function getUsersOfBoards()
389 {
390 $userBoards = Relation::whereNotNull('board_id')
391 ->where('user_id', get_current_user_id())
392 ->where('status', 'ACTIVE')->get();
393
394 return $userBoards;
395 }
396
397 /**
398 * change board background
399 * @param mixed $backgroundData
400 * @return string
401 */
402
403 public function setBoardBackground($backgroundData, $board_id)
404 {
405 $board = Board::find($board_id);
406 $background = $board->background;
407
408 // if board background has color
409 if (isset($backgroundData['color'])) {
410 $background['color'] = $backgroundData['color'];
411 $background['image_url'] = null;
412 $background['is_image'] = false;
413 }
414
415 // if board background has image
416 if (isset($backgroundData['image_url'])) {
417 $background['image_url'] = $backgroundData['image_url'];
418 $background['is_image'] = true;
419 $background['color'] = null;
420 }
421 $background['id'] = $backgroundData['id'];
422
423 $board->background = $background;
424 $board->save();
425
426 return $board->background;
427 }
428
429
430 /**
431 * Summary of getStageTaskAvailablePositions
432 * @param mixed $board_id
433 * @param mixed $stage_slug
434 * @return array of available positions of the stage with one increased value because if the stage has 10 tasks than it will have 10 position and +1 as last position of the stage
435 */
436 public function getStageTaskAvailablePositions($board_id, $stage_id)
437 {
438 $availablePositions = Task::query()
439 ->where('board_id', $board_id)
440 ->where('parent_id', null)
441 ->where('stage_id', $stage_id)
442 ->whereNull('archived_at')
443 ->orderBy('position', 'asc')
444 ->get()
445 ->pluck('position')->toArray();
446
447 $totalPosition = count($availablePositions);
448 $availablePositions[$totalPosition] = $totalPosition + 1;
449
450 return $availablePositions;
451 }
452
453 public function getAssigneesByBoard($board_id, $search = '')
454 {
455 $assignees = [];
456 $boardUsers = [];
457 $board = Board::with('users')->find($board_id);
458
459 if ($board) {
460 if ($search) {
461 $boardUsers = $board->users->filter(
462 function ($user) use ($search) {
463 return strpos($user->display_name, $search) !== false || strpos($user->user_email, $search) !== false;
464 }
465 );
466 } else {
467 $boardUsers = $board->users;
468 }
469 };
470 foreach ($boardUsers as $user) {
471 $taskAssignee = Relation::where('foreign_id', $user->ID)->where('object_type', 'task_assignee')->exists();
472 if ($taskAssignee) {
473 $assignees[] = $user;
474 }
475 }
476 return $assignees;
477 }
478
479 public function updateRecentOpenedBoards($boardId)
480 {
481 $userId = get_current_user_id();
482
483 $recentlyOpened = Meta::where('object_id', $userId)
484 ->where('object_type', Constant::OBJECT_TYPE_USER)
485 ->where('key', Constant::USER_RECENT_BOARDS)
486 ->first();
487
488 if (!$recentlyOpened) {
489 $openedBoards = [$boardId];
490 $userMeta = new Meta();
491 $userMeta->object_id = $userId;
492 $userMeta->object_type = Constant::OBJECT_TYPE_USER;
493 $userMeta->key = Constant::USER_RECENT_BOARDS;
494 $userMeta->value = $openedBoards;
495 $userMeta->save();
496 } else {
497 $boards = $recentlyOpened->value;
498 if (in_array($boardId, $boards)) {
499 $index = array_search($boardId, $boards);
500 if ($index == 1) {
501 $boards[1] = $boards[0];
502 $boards[0] = $boardId;
503 } elseif ($index == 2) {
504 $boards[2] = $boards[1];
505 $boards[1] = $boards[0];
506 $boards[0] = $boardId;
507 }
508 $recentlyOpened->value = $boards;
509 $recentlyOpened->save();
510 } else {
511 $boards[2] = $boards[1];
512 $boards[1] = $boards[0];
513 $boards[0] = $boardId;
514 $recentlyOpened->value = $boards;
515 $recentlyOpened->save();
516 }
517 }
518 }
519
520 public function getRecentBoards()
521 {
522 $userId = get_current_user_id();
523
524 $recentBoardIds = Meta::query()->where('object_id', $userId)
525 ->where('object_type', Constant::OBJECT_TYPE_USER)
526 ->where('key', Constant::USER_RECENT_BOARDS)
527 ->value('value');
528
529 if (!$recentBoardIds) {
530 return [];
531 }
532
533 $currentUser = User::find($userId);
534
535 if (!PermissionManager::isAdmin($userId)){
536 $recentBoardIds = array_intersect($recentBoardIds, $currentUser->whichBoards->pluck('id')->toArray());
537 }
538
539 return Board::whereIn('id', $recentBoardIds)->withCount('completedTasks')->with(['stages', 'users'])->get();
540 }
541
542 public function updateAssociateMember($contactId, $boardId)
543 {
544 $contactOfBoard = $this->getAssociateMember($boardId, true);
545
546 if ($contactOfBoard) {
547 $contactOfBoard->value = $contactId;
548 $contactOfBoard->save();
549 } else {
550 $contactOfBoard = new Meta();
551 $contactOfBoard->object_id = $boardId;
552 $contactOfBoard->object_type = Constant::OBJECT_TYPE_BOARD;
553 $contactOfBoard->key = Constant::BOARD_ASSOCIATED_CRM_CONTACT;
554 $contactOfBoard->value = $contactId;
555 $contactOfBoard->save();
556 }
557
558 $board = Board::findOrFail($boardId);
559 do_action('fluent_boards/contact_added_to_board', $board, $contactId);
560
561 }
562
563 public function getAssociateMember($boardId, $fromUpdateMethod = false)
564 {
565
566 $contactOfBoard = Meta::query()->where('object_id', $boardId)
567 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
568 ->where('key', Constant::BOARD_ASSOCIATED_CRM_CONTACT)
569 ->first();
570
571 if ($fromUpdateMethod) {
572 return $contactOfBoard;
573 }
574
575 if (!$contactOfBoard) {
576 return null;
577 }
578
579 return Helper::crm_contact($contactOfBoard->value);
580
581 // return \FluentCrm\App\Models\Subscriber::find($contactOfBoard->value);
582 }
583
584 public function deleteAssociateMember($boardId, $contact_id)
585 {
586 $contactOfBoard = Meta::query()->where('object_id', $boardId)
587 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
588 ->where('key', Constant::BOARD_ASSOCIATED_CRM_CONTACT)
589 ->where('value', $contact_id)
590 ->first();
591
592 $contactOfBoard->delete();
593 }
594
595 public function sendInvitationToBoard($boardId, $email)
596 {
597 $user = User::query()->where('user_email', $email)->first();
598
599 if ($user) {
600 return $user;
601 }
602
603 do_action('fluent_boards_pro/send_invitation', $boardId, $email);
604
605 return;
606
607 }
608
609 public function getInvitations($boardId)
610 {
611 return Meta::query()->where('object_id', $boardId)
612 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
613 ->where('key', Constant::BOARD_INVITATION)
614 ->get();
615 }
616
617 public function deleteInvitation($invitationId)
618 {
619 Meta::findOrFail($invitationId)->delete();
620 }
621
622 public function hasDataChanged($boardId)
623 {
624 $stages = [];
625 $labels = [];
626 $tasks = [];
627 $labels = [];
628 $taskDeleted = false;
629 $stageDeleted = false;
630 $labelDeleted = false;
631 $oneMinuteAgoTimestamp = current_time('timestamp') - 60; // Get the current timestamp and subtract 60 seconds
632 $oneMinuteAgo = date_i18n('Y-m-d H:i:s', $oneMinuteAgoTimestamp); // Format the timestamp into the desired format in GMT
633
634 $board = Board::find($boardId);
635 if (!$board) {
636 throw new \Exception("Board doesn't exists");
637 }
638 // if stage in this board has been deleted
639 $stageDeleted = Activity::where('object_id', $boardId)->where('updated_at', '>=', $oneMinuteAgo)->where('action', 'deleted')->where('column', 'stage')->exists();
640
641 if ($stageDeleted) {
642 $stages = $board->stages;
643 } else {
644 $stages = (new StageService())->getLastOneMinuteUpdatedStages($boardId);
645 }
646
647 $labelDeleted = Activity::where('object_id', $boardId)->where('updated_at', '>=', $oneMinuteAgo)->where('action', 'deleted')->where('column', 'label')->exists();
648 if ($labelDeleted) {
649 $labels = $board->labels;
650 } else {
651 $labels = (new LabelService())->getLastOneMinuteUpdatedLabels($boardId);
652 }
653
654 // if task in this board has been deleted
655 $taskDeletedOrMovedFormBoard = Activity::where('object_id', $boardId)->where('updated_at', '>=', $oneMinuteAgo)->where('action', 'deleted')->orWhere('action', 'moved')->where('column', 'task')->exists();
656
657 if ($taskDeletedOrMovedFormBoard) {
658 $tasks = Task::query()
659 ->where([
660 'board_id' => $boardId,
661 'parent_id' => null,
662 'archived_at' => null
663 ])
664 ->with(['assignees', 'labels'])
665 ->orderBy('due_at', 'ASC')
666 ->get();
667 } else {
668 $tasks = (new TaskService())->getLastOneMinuteUpdatedTasks($boardId);
669 }
670
671 foreach ($tasks as $task) {
672 $task->isOverdue = $task->isOverdue();
673 $task->isUpcoming = $task->upcoming();
674 }
675
676 if ($board->updated_at >= $oneMinuteAgo) {
677 $board->background = \maybe_unserialize($board->background);
678 } else {
679 $board = [];
680 }
681
682 return [
683 'board' => $board,
684 'stages' => $stages,
685 'labels' => $labels,
686 'tasks' => $tasks,
687 'taskDeleted' => $taskDeletedOrMovedFormBoard,
688 'stageDeleted' => $stageDeleted,
689 ];
690 }
691
692 public function getAssociatedBoards($associatedId)
693 {
694
695 $boardIds = Meta::query()->where('value', $associatedId)
696 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
697 ->where('key', Constant::BOARD_ASSOCIATED_CRM_CONTACT)
698 ->pluck('object_id');
699
700 return Board::query()->whereIn('id', $boardIds)->with('stages', 'users')->get();
701 }
702
703 private function deleteBoardMeta($boardId)
704 {
705 Meta::where('object_id', $boardId)
706 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
707 ->delete();
708 }
709
710 public function copyBoard($boardData)
711 {
712 $boardData = apply_filters('fluent_boards/before_create_board', $boardData);
713
714 $board = Board::create($boardData);
715
716 $this->setCurrentUserPreferencesOnBoardCreate($board);
717
718 return $board;
719 }
720
721 public function getBoardReports($board_id)
722 {
723 $completedTaskCount = Task::where('board_id', $board_id)
724 ->where('status', 'closed')
725 ->whereNull('parent_id')
726 ->whereNull('archived_at')
727 ->count();
728
729 $openTaskCount = Task::where('board_id', $board_id)
730 // ->whereNull('due_at')
731 ->whereNull('parent_id')
732 ->whereNull('archived_at')
733 ->where('status', 'open')
734 ->count();
735
736 $overDue = Task::where('board_id', $board_id)
737 // ->whereNotNull('due_at')
738 // ->where('status', 'open')
739 ->whereNull('parent_id')
740 ->whereNull('archived_at')
741 ->overdue(true)
742 ->count();
743
744 $totalTasks = Task::where('board_id', $board_id)
745 ->whereNull('parent_id')
746 ->whereNull('archived_at')
747 ->count();
748
749 $high = Task::where('board_id', $board_id)->where('status', 'open')->where('priority', 'high')->count();
750 $medium = Task::where('board_id', $board_id)->where('status', 'open')->where('priority', 'medium')->count();
751 $low = Task::where('board_id', $board_id)->where('status', 'open')->where('priority', 'low')->count();
752
753 $reportData = [
754 'completion' => [
755 'completed' => $completedTaskCount,
756 'incomplete' => $openTaskCount,
757 'overdue' => $overDue,
758 'total' => $totalTasks
759 ],
760 'priority' => [
761 'high' => $high,
762 'medium' => $medium,
763 'low' => $low
764 ]
765
766 ];
767 return $reportData;
768 }
769
770 public function getStageWiseBoardReports($board_id)
771 {
772 $stages = Stage::where('board_id', $board_id)
773 ->where('type', 'stage')
774 ->whereNull('archived_at')
775 ->get();
776
777 foreach ($stages as $stage) {
778 $completedTaskCount = Task::where('stage_id', $stage->id)
779 ->where('status', 'closed')
780 ->count();
781
782 $openTaskCount = Task::where('stage_id', $stage->id)
783 ->whereNull('due_at')
784 ->where('status', 'open')
785 ->count();
786
787 $overDue = Task::where('stage_id', $stage->id)
788 ->whereNotNull('due_at')
789 ->where('status', 'open')
790 ->overdue(true)
791 ->count();
792
793 $stage->report = [
794 'completed' => $completedTaskCount,
795 'incomplete' => $openTaskCount,
796 'overdue' => $overDue
797 ];
798 }
799
800 return $stages;
801 }
802 }
803