get("https://graph.microsoft.com/v1.0/groups/$groupId/events"); return $response->json()['value']; } public static function getAccessToken() { $tenantId = env('MICROSOFT_TENANT_ID'); $clientId = env('MICROSOFT_CLIENT_ID'); $clientSecret = env('MICROSOFT_CLIENT_SECRET'); $username = env('MICROSOFT_USERNAME'); $password = env('MICROSOFT_PASSWORD'); $response = Http::asForm()->post("https://login.microsoftonline.com/{$tenantId}/oauth2/v2.0/token", [ 'grant_type' => 'password', 'client_id' => $clientId, 'client_secret' => $clientSecret, 'username' => $username, 'password' => $password, 'scope' => 'https://graph.microsoft.com/.default', ]); if ($response->failed()) { dd($response->body()); throw new \Exception('Failed to obtain access token: ' . $response->body()); } return $response->json()['access_token']; } public static function addBlockers(mixed $blockers) { foreach ($blockers as $blocker) { self::addBlocker($blocker); } } private static function addBlocker(mixed $blocker) { $attendees = $blocker['attendees']; // pre kazdeho cloveka z eventu, ktory je zaroven userom v TM vytvorime blocker foreach ($attendees as $attendee) { $user = User::where('email', $attendee['emailAddress']['address'])->first(); if ( ! $user) { continue; } $blockerToInsert = []; $blockerToInsert['office365_id'] = $blocker['id']; $blockerToInsert['office365_change_key'] = $blocker['changeKey']; $blockerToInsert['user_id'] = $user->id; $blockerToInsert['name'] = $blocker['subject']; $blockerToInsert['type'] = "office365_blocker"; $blockerToInsert['start'] = $blocker['start']['dateTime']; $blockerToInsert['end'] = $blocker['end']['dateTime']; $blockerToInsert['approved'] = 1; $blockerToInsert['created_at'] = Carbon::now()->toDateTimeString(); $blockerToInsert['updated_at'] = Carbon::now()->toDateTimeString(); Blocker::insert($blockerToInsert); } } public static function editBlockers(mixed $editedBlockers) { foreach ($editedBlockers as $editedBlocker) { self::editBlocker($editedBlocker); } } private static function editBlocker(mixed $editedBlocker) { $attendees = $editedBlocker['attendees']; // pre kazdeho cloveka z eventu, ktory je zaroven userom v TM updatneme blocker foreach ($attendees as $attendee) { $user = User::where('email', $attendee['emailAddress']['address'])->first(); if ( ! $user) { continue; } $blocker = Blocker::where('office365_id', $editedBlocker['id'])->where('user_id', $user->id)->first(); $blocker->update([ 'office365_change_key' => $editedBlocker['changeKey'], 'name' => $editedBlocker['subject'], 'start' => $editedBlocker['start']['dateTime'], 'end' => $editedBlocker['end']['dateTime'], 'updated_at' => Carbon::now()->toDateTimeString(), ]); } } public static function addSubtasks(mixed $newSubtasks) { foreach ($newSubtasks as $newSubtask) { $project = Project::where('code', explode(' ', $newSubtask['subject'])[0])->first(); // ak existuje viac master taskov, pouzijeme posledny $mastertask = MasterTask::where('project_id', $project->id)->latest()->first(); // ak neexistuje master task k danemu projektu, tak sa subtask neprida if ( ! $mastertask) { continue; } self::addSubtaskToAllInvited($newSubtask, $mastertask); } } private static function addSubtaskToAllInvited(mixed $newSubtask, mixed $mastertask) { $attendees = $newSubtask['attendees']; $subtasksToInsert = []; $i = 0; // pre kazdeho cloveka z eventu, ktory je zaroven userom v TM vytvorime subtask foreach ($attendees as $attendee) { $user = User::where('email', $attendee['emailAddress']['address'])->first(); $creator = User::where('email', $newSubtask['organizer']['emailAddress']['address'])->first(); if ( ! $user || ! $creator) { continue; } $subtasksToInsert[$i]['user_id'] = $user->id; // vymazem prve slovo z title, ktore je project code $subtasksToInsert[$i]['title'] = substr($newSubtask['subject'], strpos($newSubtask['subject'], ' ') + 1); // estimated_time je rozdiel medzi end.dateTime a start.dateTime zakhruhleny na najblizsiu 0.5 hodinu $subtasksToInsert[$i]['estimated_time'] = round((strtotime($newSubtask['end']['dateTime']) - strtotime($newSubtask['start']['dateTime'])) / 3600, 1); $subtasksToInsert[$i]['tracked_time'] = 0; $subtasksToInsert[$i]['created_by'] = $creator->id; $subtasksToInsert[$i]['office365_id'] = $newSubtask['id']; $subtasksToInsert[$i]['office365_change_key'] = $newSubtask['changeKey']; $subtasksToInsert[$i]['type'] = 'office365'; $subtasksToInsert[$i]['description'] = $newSubtask['body']['content']; $subtasksToInsert[$i]['deadline'] = $newSubtask['end']['dateTime']; $subtasksToInsert[$i]['office365_location'] = $newSubtask['location']['displayName']; $subtasksToInsert[$i]['is_finished'] = 0; } $subtasks = $mastertask->subtasks()->createMany($subtasksToInsert); // vytvorenie timeblocks foreach ($subtasks as $subtask) { $subtask->syncTimeblocks([ [ 'sub_task_id' => $subtask->id, 'start' => $newSubtask['start']['dateTime'], 'end' => $newSubtask['end']['dateTime'], 'is_finished' => 0, ] ]); } // manualne musim trigernut tuto operaciu, lebo cez Observer sa to nespusti - ten je nastaveny len na update subtasku $mastertask->recalculateEstimatedTime(); } public static function finishSubtasks(mixed $subtasks) { foreach ($subtasks as $subtask) { // ukoncenie timeblocks foreach ($subtask->timeblocks as $timeblock) { $timeblock->update([ 'is_finished' => 1, ]); } // pridanie odtrackovaneho casu $subtask->syncTimesheets([ [ 'sub_task_id' => $subtask->id, 'employee_id' => $subtask->user_id, 'time' => $subtask->estimated_time, ], ]); $subtask->update([ 'is_finished' => 1, ]); } // manualne musim trignernut tuto operaciu, lebo cez Observer sa to nespusti - ten je nastaveny len na update subtasku $subtasks->first()->mastertask->recalculateTrackedTime(); } public static function editSubtasks(mixed $editedSubtasks) { foreach ($editedSubtasks as $editedSubtask) { self::editSubtask($editedSubtask); } } private static function editSubtask(mixed $editedSubtask) { $attendees = $editedSubtask['attendees']; // vrati subtasky pre userov, ktori sa uz nenachadzaju v evente, ale v nasej databaze tento subtask maju. ale iba v pripade, ak ich subtasky este nie su ukoncene (is_finished != 1) // TODO - zvlast do funkcie $subtasksToDelete = SubTask::where('is_finished', 0)->where('office365_id', $editedSubtask['id'])->get()->filter(function ($subtask) use ( $attendees ) { $event = collect($attendees)->firstWhere('emailAddress.address', $subtask->user->email); return ! $event; }); foreach ($subtasksToDelete as $subtaskToDelete) { // vymazanie timeblockov foreach ($subtaskToDelete->timeblocks as $timeblock) { $timeblock->delete(); } // vymazanie timesheetov foreach ($subtaskToDelete->timesheets as $timesheet) { $timesheet->delete(); } $subtaskToDelete->delete(); } // novym ucastnikom sa klasicky vytvori subtask ako v pripade noveho subtasku. pre 1 subtask existuje iba 1 user. // TODO - zvlast do funkcie $newAttendees = array_filter($attendees, function ($attendee) use ($editedSubtask) { $idsOfAttendees = SubTask::where('office365_id', $editedSubtask['id'])->get()->pluck('user_id')->toArray(); $idOfUserFromOffice365 = User::where('email', $attendee['emailAddress']['address'])->first(); // if user doesnt exist in our database, we skip it if ( ! $idOfUserFromOffice365) { return false; } return ! in_array($idOfUserFromOffice365->id, $idsOfAttendees); }); // nakopiruj subtask tak, ze bude obsahovat iba newAttendees $editedSubtaskWithOnlyNewAttendees = $editedSubtask; $editedSubtaskWithOnlyNewAttendees['attendees'] = $newAttendees; $project = Project::where('code', explode(' ', $editedSubtask['subject'])[0])->first(); // ak existuje viac master taskov, pouzijeme posledny $mastertask = MasterTask::where('project_id', $project->id)->latest()->first(); self::addSubtaskToAllInvited($editedSubtaskWithOnlyNewAttendees, $mastertask); // existujucim ucastnikom sa updatne subtask foreach ($attendees as $attendee) { $idOfUserFromOffice365 = User::where('email', $attendee['emailAddress']['address'])->first(); // if user doesnt exist in our database, we skip it if ( ! $idOfUserFromOffice365) { continue; } $subtask = SubTask::where('office365_id', $editedSubtask['id'])->where('user_id', $idOfUserFromOffice365->id)->first(); if ( ! $subtask) { continue; } $subtask->update([ 'office365_change_key' => $editedSubtask['changeKey'], 'title' => substr($editedSubtask['subject'], strpos($editedSubtask['subject'], ' ') + 1), 'estimated_time' => round((strtotime($editedSubtask['end']['dateTime']) - strtotime($editedSubtask['start']['dateTime'])) / 3600, 1), 'description' => $editedSubtask['body']['content'], 'deadline' => $editedSubtask['end']['dateTime'], 'office365_location' => $editedSubtask['location']['displayName'], ]); $oldTimeblock = $subtask->timeblocks->first(); // ak sa zmenilo trvanie alebo casy subtasku, tak sa updatne aj timeblock if ($oldTimeblock['start'] != $editedSubtask['start']['dateTime'] || $oldTimeblock['end'] != $editedSubtask['end']['dateTime']) { $subtask->syncTimeblocks([ [ 'sub_task_id' => $subtask->id, 'start' => $editedSubtask['start']['dateTime'], 'end' => $editedSubtask['end']['dateTime'], 'is_finished' => 0, ] ]); } } // manualne musim trignernut tuto operaciu, lebo cez Observer sa to nespusti - ten je nastaveny len na update subtasku Subtask::where('office365_id', $editedSubtask['id'])->first()->mastertask->recalculateEstimatedTime(); } }