![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/ts.corals.io/corals-api/Corals/modules/Timesheet/Services/ |
<?php namespace Corals\Modules\Timesheet\Services; use Carbon\Carbon; use Corals\Modules\Timesheet\Facades\Timesheet; use Corals\Modules\Timesheet\Models\Client; use Corals\Modules\Timesheet\Models\Entry; use Corals\Modules\Timesheet\Transformers\API\EntryPresenter; use Corals\Settings\Facades\Settings; use Corals\User\Models\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Illuminate\Support\Str; class TimeSheetCalender { /** * @var User */ protected User $user; /** * @var array */ protected array $filters = []; /** * @param User|null $user * @return $this */ public function setUser(User $user = null) { if (is_null($user)) { $user = user(); } $this->user = $user; return $this; } /** * @param Request $request * @return $this */ public function setFilters(Request $request) { $this->filters = array_filter($request->only($this->filtersListKeys()), function ($filter) { return filled($filter) || strtolower($filter) !== 'null'; }); return $this; } /** * @param null $startPeriod * @return array */ public function getWeek($startPeriod = null) { $startPeriod = $this->getStartPeriod($startPeriod); $days = []; $endPeriod = $startPeriod->copy()->addDays(7); $weekDates = []; while ($startPeriod->lt($endPeriod)) { $days[] = $this->getDay($startPeriod); $weekDates[] = $startPeriod->toDateString(); $startPeriod->addDay(); } $weekDays = $this->getWeekDays($days, $weekDates); return [ 'weekDays' => $weekDays, 'days' => $days, 'week_total_time' => $this->getTotalSpentTimeForWeek($days), 'week_total_evaluation_time' => $this->getTotalSpentTimeForWeek($days, true), ]; } /** * @param $days * @return string */ protected function getTotalSpentTimeForWeek($days, $isBillable = false): string { $totalHours = 0; $totalMinutes = 0; foreach ($days as $day) { $timeKey = $isBillable ? 'total_evaluation_time' : 'total_time'; [$hours, $minutes] = explode(':', $day[$timeKey]); $totalHours += (int)$hours; $totalMinutes += (int)$minutes; } return Timesheet::formatHoursAndMinutes($totalHours, $totalMinutes); } /** * @param Carbon $date * @return array */ public function getDay(Carbon $date) { $dayDate = $date->toDateString(); $entries = $this->getEntries($dayDate); if (Timesheet::isTimesheetAdministration()) { $membersWithoutEntries = $this->membersWithoutEntriesForDate($dayDate); } else { $membersWithoutEntries = []; } return [ 'date' => $dayDate, 'prev_day' => $date->copy()->subDay()->toDateString(), 'next_day' => $date->copy()->addDay()->toDateString(), 'title' => $date->format('l, d M'), 'name' => $date->englishDayOfWeek, 'short_name' => $date->shortEnglishDayOfWeek, 'require_review' => data_get($entries, 'require_review', false), 'total_time' => data_get($entries, 'total_time'), 'total_evaluation_time' => data_get($entries, 'total_evaluation_time'), 'entries' => data_get($entries, 'data'), 'members_without_entries' => $membersWithoutEntries ]; } /** * @param string $dayDate * @return Builder[]|\Illuminate\Database\Eloquent\Collection */ protected function membersWithoutEntriesForDate(string $dayDate) { return User::query() ->whereHas('roles', function ($roles) { $roles->where('roles.name', 'member'); })->where('employee_type', '=', 'full_time') ->active() ->whereNotExists(function ($q) use ($dayDate) { $q->from('timesheet_entries') ->where('timesheet_entries.spent_at', $dayDate) ->whereColumn('timesheet_entries.user_id', 'users.id'); })->selectRaw("concat(users.name,' ',users.last_name,' - ',users.email) as name") ->pluck('name') ->toArray(); } /** * @param string $dayDate * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection */ protected function getEntries(string $dayDate) { $entries = Entry::query() ->with(['activity', 'project.client', 'invoice', 'user']) ->when(!Timesheet::isTimesheetAdministration(), function ($query) { $query->where('user_id', $this->user->id); })->when(Timesheet::isTimesheetAdministration(), function (Builder $query) { $this->applyFilters($query); })->where('spent_at', $dayDate) ->orderBy('has_reviewed') ->orderBy('user_id') ->orderBy('id', 'desc') ->get(); $data = []; $entries->each(function (Entry $entry) use (&$data) { $data[] = $entry->setPresenter(new EntryPresenter)->presenter(); }); return [ 'data' => $data, 'total_time' => $this->getTotalSpentTimeForEntries($entries), 'require_review' => $entries->where('has_reviewed', 0)->count() > 0, 'total_evaluation_time' => Timesheet::isTimesheetAdministration() ? $this->getTotalSpentTimeForEntries($entries, true) : '00:00', ]; } /** * @param Builder $builder */ protected function applyFilters(Builder $builder): void { if (!$this->filters || !Timesheet::isTimesheetAdministration()) { return; } foreach ($this->filters as $column => $value) { if (!$value) { continue; } $filterMethodHandler = sprintf("filterBy%s", Str::studly($column)); if (method_exists($this, $filterMethodHandler)) { $this->{$filterMethodHandler}($builder, $column, $value); } else { $builder->where($column, $value); } } $builder->select('timesheet_entries.*'); } /** * @param Builder $builder * @param $column * @param $value */ protected function filterByClientId(Builder $builder, $column, $value): void { $builder ->join('timesheet_projects', 'timesheet_entries.project_id', 'timesheet_projects.id') ->where($column, $value); } /** * @param $startPeriod * @return Carbon|\Illuminate\Support\Carbon */ protected function getStartPeriod($startPeriod) { if (is_null($startPeriod)) { $startPeriod = today(); } else { $startPeriod = Carbon::parse($startPeriod); } return $startPeriod->startOfWeek(Settings::get('timesheet_start_of_week', Carbon::MONDAY)); } /** * @param Collection $entries * @return string */ protected function getTotalSpentTimeForEntries(Collection $entries, $isBillable = false) { if ($isBillable) { $hours = $entries->sum('evaluation_hours'); $minutes = $entries->sum('evaluation_minutes'); } else { $hours = $entries->sum('hours'); $minutes = $entries->sum('minutes'); } return Timesheet::formatHoursAndMinutes($hours, $minutes); } /** * @return array */ public function getFiltersFormData() { $clients = Client::query()->pluck('name', 'id')->toArray(); return [ 'users' => Timesheet::getUsersFormData('member'), 'projects' => Timesheet::getProjectsFormData(), 'clients' => $clients ]; } /** * @return string[] */ protected function filtersListKeys() { return [ 'user_id', 'client_id', 'project_id' ]; } public function getWeekDays($days, $weekDates) { $allEntries = []; $weekRows = []; foreach ($days as $day) { foreach ($day['entries'] as $entry) { $allEntries[] = $entry; } } $result = collect($allEntries)->groupBy(['project_id', 'activity_id', 'user_id']); foreach ($result as $projectId => $projectObj) { foreach ($projectObj as $activityId => $activityObj) { foreach ($activityObj as $userId => $entries) { $weekRowEntries = []; $entries = collect($entries); foreach ($weekDates as $date) { $dayEntriesCollection = $entries->where('spent_at', $date); $dayEntriesFormatted = []; if ($dayEntriesCollection->isEmpty()) { $dayEntriesFormatted[] = [ 'entryId' => '', 'date' => $date, 'time' => [ 'HH' => '', 'mm' => '' ], 'description' => '', ]; } else { foreach ($dayEntriesCollection as $entry) { $dayEntriesFormatted[] = [ 'entryId' => $entry['id'], 'date' => $date, 'time' => [ 'HH' => Str::padLeft($entry['hours'], '2', '0'), 'mm' => Str::padLeft($entry['minutes'], '2', '0') ], 'description' => $entry['description']]; } } $weekRowEntries[$date] = $dayEntriesFormatted; } $weekRows[] = [ 'activity_id' => $activityId, 'activity' => $entries[0]['activity'], 'project_id' => $projectId, 'project' => $entries[0]['project'], 'client_name' => $entries[0]['client_name'], 'user_id' => $userId, 'user' => $entries[0]['user'], 'weekRowEntries' => $weekRowEntries ]; } } } return [ 'start_week' => date('D, d M', strtotime($weekDates[0])), 'end_week' => date('D, d M', strtotime($weekDates[count($weekDates) - 1])), 'prev_week' => date('Y-m-d', strtotime($weekDates[0] . ' -1 day')), 'next_week' => date('Y-m-d', strtotime($weekDates[count($weekDates) - 1] . ' +1 day')), 'week' => $weekRows, ]; } }