ultimatepos/Modules/ManagementTools/Http/Controllers/TaskReportController.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')]);
}
}