305 lines
11 KiB
PHP
305 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Modules\ManagementTools\Http\Controllers;
|
|
|
|
use App\User;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Modules\ManagementTools\Entities\MtScoreCard;
|
|
use Modules\ManagementTools\Entities\MtUserScore;
|
|
use Modules\ManagementTools\Entities\MtUserTask;
|
|
use Modules\ManagementTools\Entities\MtUserTimeLine;
|
|
use Modules\ManagementTools\Utils\ManagementToolsUtil;
|
|
use Modules\ManagementTools\Utils\TaskReportUtil;
|
|
|
|
class TaskReportController extends Controller
|
|
{
|
|
public function __construct(
|
|
protected ManagementToolsUtil $mtUtil,
|
|
protected TaskReportUtil $reportUtil
|
|
) {
|
|
}
|
|
|
|
protected function authorizeAccess(): void
|
|
{
|
|
if (! auth()->user()->can('managementtools.access') || ! auth()->user()->can('managementtools.task_report')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
}
|
|
|
|
protected function businessId(Request $request): int
|
|
{
|
|
return (int) $request->session()->get('user.business_id');
|
|
}
|
|
|
|
protected function adjacentUsers($users, $user_id): array
|
|
{
|
|
$ids = collect($users)->keys()->filter(fn ($id) => ! empty($id))->values();
|
|
|
|
if ($ids->isEmpty()) {
|
|
return [null, null];
|
|
}
|
|
|
|
if (empty($user_id)) {
|
|
$first = User::find($ids->first());
|
|
|
|
return [$first, $first];
|
|
}
|
|
|
|
$idx = $ids->search((int) $user_id);
|
|
if ($idx === false) {
|
|
$first = User::find($ids->first());
|
|
|
|
return [$first, $first];
|
|
}
|
|
|
|
$nextId = $idx < $ids->count() - 1 ? $ids[$idx + 1] : $ids->first();
|
|
$prevId = $idx > 0 ? $ids[$idx - 1] : $ids->last();
|
|
|
|
return [User::find($nextId), User::find($prevId)];
|
|
}
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId($request);
|
|
$users = User::forDropdown($business_id, false);
|
|
|
|
$user_id = $request->input('user_id');
|
|
$start_date_input = $request->input('start_date');
|
|
$end_date_input = $request->input('end_date');
|
|
$start_gregorian = $this->mtUtil->parseInputDate($start_date_input);
|
|
$end_gregorian = $this->mtUtil->parseInputDate($end_date_input);
|
|
|
|
$user_tasks = collect();
|
|
$week = [];
|
|
$last_week = [];
|
|
$calendar_tasks = collect();
|
|
$calendar_events = collect();
|
|
$grouped_tasks = collect();
|
|
$total_minutes = 0;
|
|
|
|
$day_tabs = $this->reportUtil->dayTabDates();
|
|
$dates = $day_tabs['future'];
|
|
$last_dates = $day_tabs['past'];
|
|
|
|
[$next_user, $previous_user] = $this->adjacentUsers($users, $user_id);
|
|
|
|
if ($user_id && $start_gregorian && $end_gregorian) {
|
|
$start = Carbon::parse($start_gregorian)->startOfDay();
|
|
$end = Carbon::parse($end_gregorian)->endOfDay();
|
|
|
|
$user_tasks = $this->reportUtil->tasksForUserInRange($business_id, (int) $user_id, $start, $end);
|
|
$total_minutes = $this->reportUtil->sumTasksWorkMinutes($user_tasks, (int) $user_id);
|
|
$grouped_tasks = $this->reportUtil->groupedTasksByTimelineDate($user_tasks, (int) $user_id);
|
|
|
|
foreach ($last_dates as $date) {
|
|
$last_week[] = $this->reportUtil->tasksForUserOnDate($business_id, (int) $user_id, $date);
|
|
}
|
|
|
|
foreach ($dates as $date) {
|
|
$week[] = $this->reportUtil->tasksForUserOnDate($business_id, (int) $user_id, $date);
|
|
}
|
|
|
|
$calendar_start = now()->subDays(6)->startOfDay();
|
|
$calendar_end = now()->addDays(6)->endOfDay();
|
|
$calendar_tasks = $this->reportUtil->calendarTasks($business_id, (int) $user_id, $calendar_start, $calendar_end);
|
|
}
|
|
|
|
$calendar_events = $calendar_tasks->map(fn ($task) => [
|
|
'title' => $task->title,
|
|
'start' => optional($task->created_at)->format('Y-m-d'),
|
|
'end' => optional($task->due_date)->format('Y-m-d'),
|
|
])->values();
|
|
|
|
return view('managementtools::task_report.index', [
|
|
'users' => $users,
|
|
'user_id' => $user_id,
|
|
'start_date' => $this->mtUtil->formatForInput($start_gregorian ?? $start_date_input),
|
|
'end_date' => $this->mtUtil->formatForInput($end_gregorian ?? $end_date_input),
|
|
'user_tasks' => $user_tasks,
|
|
'total_minutes' => $total_minutes,
|
|
'dates' => $dates,
|
|
'last_dates' => $last_dates,
|
|
'week' => $week,
|
|
'last_week' => $last_week,
|
|
'grouped_tasks' => $grouped_tasks,
|
|
'calendar_tasks' => $calendar_tasks,
|
|
'calendar_events' => $calendar_events,
|
|
'next_user' => $next_user,
|
|
'previous_user' => $previous_user,
|
|
'current_user_name' => ! empty($user_id) ? ($users[$user_id] ?? '—') : '—',
|
|
'can_manage_scores' => auth()->user()->can('managementtools.manage_scores'),
|
|
'can_manage_tasks' => auth()->user()->can('managementtools.manage_employee_tasks'),
|
|
'statuses' => MtUserTask::statusLabels(),
|
|
]);
|
|
}
|
|
|
|
public function userList()
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId(request());
|
|
$users = User::forDropdown($business_id, false);
|
|
$day_tabs = $this->reportUtil->dayTabDates();
|
|
|
|
return view('managementtools::task_report.modals.user_days', [
|
|
'users' => $users,
|
|
'dates' => $day_tabs['future'],
|
|
'business_id' => $business_id,
|
|
]);
|
|
}
|
|
|
|
public function changeTimeline($task_id, $user_id, $date = null)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId(request());
|
|
|
|
$task = MtUserTask::forBusiness($business_id)->findOrFail($task_id);
|
|
$timeline = $this->reportUtil->latestTimelineForTask($business_id, (int) $user_id, (int) $task_id, $date);
|
|
|
|
if (! $timeline) {
|
|
$timeline = MtUserTimeLine::create([
|
|
'business_id' => $business_id,
|
|
'user_id' => $user_id,
|
|
'user_task_id' => $task_id,
|
|
'starts_at' => $date ? Carbon::parse($date)->startOfDay()->addHours(9) : now(),
|
|
'ends_at' => $date ? Carbon::parse($date)->startOfDay()->addHours(10) : now()->addHour(),
|
|
]);
|
|
}
|
|
|
|
return view('managementtools::task_report.modals.change_timeline', compact('timeline', 'task', 'user_id'));
|
|
}
|
|
|
|
public function storeTimelineChange(Request $request)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId($request);
|
|
|
|
$request->validate([
|
|
'timeline_id' => 'required|integer|exists:mt_user_time_lines,id',
|
|
'starts_at' => 'required|string|max:30',
|
|
'ends_at' => 'required|string|max:30',
|
|
]);
|
|
|
|
$starts_at = $this->mtUtil->parseInputDateTime($request->starts_at);
|
|
$ends_at = $this->mtUtil->parseInputDateTime($request->ends_at);
|
|
|
|
if (! $starts_at || ! $ends_at || Carbon::parse($ends_at)->lte(Carbon::parse($starts_at))) {
|
|
return response()->json(['success' => false, 'msg' => __('managementtools::lang.something_went_wrong')]);
|
|
}
|
|
|
|
$timeline = MtUserTimeLine::forBusiness($business_id)->findOrFail($request->timeline_id);
|
|
$timeline->update([
|
|
'starts_at' => Carbon::parse($starts_at),
|
|
'ends_at' => Carbon::parse($ends_at),
|
|
]);
|
|
|
|
return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_updated')]);
|
|
}
|
|
|
|
public function taskScores($user_id, $task_id)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId(request());
|
|
|
|
$scores = MtUserScore::forBusiness($business_id)
|
|
->where('user_id', $user_id)
|
|
->where('task_id', $task_id)
|
|
->with(['scoreCard', 'user'])
|
|
->latest()
|
|
->get();
|
|
|
|
$cards = MtScoreCard::forBusiness($business_id)->active()->ordered()->get();
|
|
|
|
return view('managementtools::task_report.modals.task_scores', compact('scores', 'user_id', 'task_id', 'cards'));
|
|
}
|
|
|
|
public function storeTaskScore(Request $request, $user_id, $task_id)
|
|
{
|
|
if (! auth()->user()->can('managementtools.manage_scores')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = $this->businessId($request);
|
|
|
|
$request->validate([
|
|
'score_card_id' => 'required|integer|exists:mt_score_cards,id',
|
|
'description' => 'nullable|string|max:1000',
|
|
]);
|
|
|
|
$card = MtScoreCard::forBusiness($business_id)->findOrFail($request->score_card_id);
|
|
|
|
MtUserScore::create([
|
|
'business_id' => $business_id,
|
|
'user_id' => $user_id,
|
|
'score_card_id' => $card->id,
|
|
'score' => $card->points,
|
|
'type' => $card->points >= 0 ? '1' : '2',
|
|
'description' => $request->description,
|
|
'task_id' => $task_id,
|
|
'created_by' => auth()->id(),
|
|
]);
|
|
|
|
return response()->json(['success' => true, 'msg' => __('managementtools::lang.score_record_added')]);
|
|
}
|
|
|
|
public function destroyTaskScore($user_id, $score_id, $task_id)
|
|
{
|
|
if (! auth()->user()->can('managementtools.manage_scores')) {
|
|
abort(403, 'Unauthorized action.');
|
|
}
|
|
|
|
$business_id = $this->businessId(request());
|
|
$score = MtUserScore::forBusiness($business_id)
|
|
->where('user_id', $user_id)
|
|
->where('task_id', $task_id)
|
|
->findOrFail($score_id);
|
|
$score->delete();
|
|
|
|
return response()->json(['success' => true, 'msg' => __('managementtools::lang.score_record_deleted')]);
|
|
}
|
|
|
|
public function storeTimeLine(Request $request)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId($request);
|
|
|
|
$request->validate([
|
|
'user_id' => 'required|integer|exists:users,id',
|
|
'user_task_id' => 'nullable|integer|exists:mt_user_tasks,id',
|
|
'starts_at' => 'required|string|max:30',
|
|
'ends_at' => 'required|string|max:30',
|
|
'note' => 'nullable|string|max:500',
|
|
]);
|
|
|
|
$starts_at = $this->mtUtil->parseInputDateTime($request->starts_at);
|
|
$ends_at = $this->mtUtil->parseInputDateTime($request->ends_at);
|
|
|
|
if (! $starts_at || ! $ends_at || Carbon::parse($ends_at)->lte(Carbon::parse($starts_at))) {
|
|
return response()->json(['success' => false, 'msg' => __('managementtools::lang.something_went_wrong')]);
|
|
}
|
|
|
|
MtUserTimeLine::create([
|
|
'business_id' => $business_id,
|
|
'user_id' => $request->user_id,
|
|
'user_task_id' => $request->user_task_id ?: null,
|
|
'starts_at' => Carbon::parse($starts_at),
|
|
'ends_at' => Carbon::parse($ends_at),
|
|
'note' => $request->note,
|
|
]);
|
|
|
|
return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_added')]);
|
|
}
|
|
|
|
public function destroyTimeLine($id)
|
|
{
|
|
$this->authorizeAccess();
|
|
$business_id = $this->businessId(request());
|
|
$line = MtUserTimeLine::forBusiness($business_id)->findOrFail($id);
|
|
$line->delete();
|
|
|
|
return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_deleted')]);
|
|
}
|
|
}
|