You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

242 lines
10 KiB

<?php
namespace App\Http\Controllers;
use App\Models\Task;
use App\Models\Work;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\QueryBuilder;
class WorkController extends Controller
{
public function index($business, Request $request)
{
permit('businessAccess');
$per_page = $request->limit > 100 ? 10 : $request->limit;
$workQ = $this->indexFiltering($business)
->when($request->filled('group'), function ($q) use ($request) {
return $request->group == 'user' ? $q->report() : $q->reportByDate();
});
return $request->filled('group') ? $workQ->get() :
$workQ->defaultSort('-id')
->allowedSorts('id', 'started_at')->paginate($per_page);
}
public function indexFiltering($business)
{
$query = Work::where('works.business_id', $business);
$workQ = queryBuilder::for($query)
->join('tasks', 'tasks.id', 'works.task_id')
->select('works.*', 'tasks.title', 'tasks.sprint_id', 'tasks.system_id')
->allowedFilters([
AllowedFilter::exact('project_id'),
AllowedFilter::exact('tasks.sprint_id', null, false),
AllowedFilter::exact('tasks.system_id', null, false),
AllowedFilter::exact('user_id'),
AllowedFilter::scope('started_at_in'),
AllowedFilter::scope('started_at'),
AllowedFilter::scope('spent_time_from'),
AllowedFilter::scope('spent_time_to'),
]);
if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) {
$requested_projects = isset(\request('filter')['project_id']) ?
array_unique(explode(',',\request('filter')['project_id'] ?? null )) :
null;
$requested_projects = collect($requested_projects)->keyBy(null)->toArray();
$project_ids = $this->myStateProjects($requested_projects);
$workQ->where(function ($q) use ($project_ids) {
$q->whereIn('project_id', $project_ids['non_guest_ids'])
->orWhere(function ($q) use ($project_ids) {
$q->whereIn('project_id', $project_ids['guest_ids'])
->where('assignee_id', auth()->id());
});
});
}
return $workQ;
}
public function myStateProjects($requested_projects)
{
$non_guest_ids = [];
$guest_ids = [];
$is_empty = empty($requested_projects);
foreach (\request('_business_info')['info']['projects'] as $p_id => $p) {
$level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level'];
if (( $is_empty || isset($requested_projects[$p_id]))
&& $level > enum('levels.guest.id')) {
array_push($non_guest_ids, $p_id);
}
if (( $is_empty || isset($requested_projects[$p_id]))
&& $level == enum('levels.guest.id')) {
array_push($guest_ids, $p_id);
}
}
return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids];
}
public function show($business, $project, $task, $work)
{
permit('projectAccess', ['project_id' => $project]);
$work = Work::where([['project_id', $project ], ['task_id', $task], ['id', $work]])->firstOrFail();
if (can('isDefiniteGuestInProject', ['project_id' => $project])){ // is guest in project (only guest)
return $work->user_id == \auth()->id() ? $work : abort(Response::HTTP_FORBIDDEN); // not allowed
} else {
return $work;
}
}
/**
* Rule's:
* 1) only assignee_id can store work
* 2) started_at after task created_at
* 3) ended_at after started_at
* 4) not any work before in this work
*/
public function store($business, $project, $task, Request $request)
{
$taskModel = Task::findOrFail($task);
if ($taskModel->assignee_id != auth()->id()) {
abort(Response::HTTP_FORBIDDEN); // not allowed
}
$end = Carbon::createFromFormat('Y-m-d H:i', $request->ended_at);
$start = Carbon::createFromFormat('Y-m-d H:i', $request->started_at);
$diff_in_min = $end->diffInMinutes($start);
$work = Work::create($request->merge([
'business_id' => $business,
'project_id' => $project,
'task_id' => $task,
'user_id' => auth()->id(),
'minute_sum' => $diff_in_min,
'task' => [
'spent_time' => $taskModel->spent_time + $diff_in_min
]
])->except('_business_info'));
$taskModel->refresh();
// $taskModel->update([
// 'work_start' => Work::where('task_id', $taskModel->id)->orderBy('started_at')->first()->started_at ?? null,
// 'spent_time' => $taskModel->spent_time + $diff_in_min
// ]);
return $taskModel->load(['tagTask'=> fn($q) => $q->select('id', 'tag_id', 'task_id'), 'works', 'comments']);
}
public function storeValidation($request, $taskModel)
{
$this->validate($request, [
'message' => 'nullable|string|min:3|max:225',
'started_at' => 'required|date_format:Y-m-d H:i|after:'.$taskModel->created_at,
'ended_at' => 'required|date_format:Y-m-d H:i|after:started_at',
]);
$state = \request('_business_info')['workflows'][$taskModel->workflow_id]['statuses'][$taskModel->status_id]['state'] ?? null;
if ($state == enum('status.states.close.id') || $state == enum('status.states.done.id')) {
throw ValidationException::withMessages(['task' => 'The selected task is invalid.']);
}
$works = Work::where([
['ended_at', '>', $request->started_at],
['ended_at', '<', $request->ended_at],
])->orWhere([
['started_at', '>', $request->started_at],
['started_at', '<', $request->ended_at],
])->orWhere([
['started_at', '>=', $request->started_at],
['ended_at', '<=', $request->ended_at],
])->exists();
if ($works) {
throw ValidationException::withMessages(['work' => 'The selected work is invalid.']);
}
}
/**
* Rule's:
* 1) only assignee_id can store work
* 2) started_at after task created_at
* 3) ended_at after started_at
* 4) not any work before in this work
*/
public function update($business, $project, $task, $work, Request $request)
{
$taskModel = Task::findOrFail($task);
$workModel = Work::findOrFail($work);
if ($taskModel->assignee_id != auth()->id()) {
abort(Response::HTTP_FORBIDDEN); // not allowed
}
$end = Carbon::createFromFormat('Y-m-d H:i', $request->ended_at);
$start = Carbon::createFromFormat('Y-m-d H:i', $request->started_at);
$new_diff_in_min = $end->diffInMinutes($start);
$old_diff_in_min = $workModel->minute_sum;
$workModel->update($request->merge([
'business_id' => $business,
'project_id' => $project,
'task_id' => $task,
'user_id' => auth()->id(),
'minute_sum' => $new_diff_in_min,
'task' => [
'spent_time' => ($taskModel->spent_time - $old_diff_in_min) + $new_diff_in_min
]
])->except('_business_info'));
$taskModel->refresh();
// $taskModel->update([
// 'work_start' => Work::where('task_id', $taskModel->id)->orderBy('started_at')->first()->started_at ?? null,
// 'spent_time' => ($taskModel->spent_time - $old_diff_in_min) + $new_diff_in_min
// ]);
return $taskModel->load(['tagTask'=> fn($q) => $q->select('id', 'tag_id', 'task_id'), 'works', 'comments']);
}
public function updateValidation($request, $taskModel, $workModel)
{
$this->validate($request, [
'message' => 'nullable|string|min:3|max:225',
'started_at' => 'nullable|date_format:Y-m-d H:i|after:'.$taskModel->created_at,
'ended_at' => 'nullable|date_format:Y-m-d H:i|after:started_at',
]);
//ToDo: is needed to check status is active or idea??
$works = false;
if ($request->filled('started_at') || $request->filled('ended_at')) {
$started_at = $request->started_at ?? $workModel->started_at->format('Y-m-d H:i');
$ended_at = $request->ended_at ?? $workModel->ended_at->format('Y-m-d H:i');
if (strtotime($ended_at) <= strtotime($started_at)) {
throw ValidationException::withMessages(['ended_at' => 'The ended at must be a date after started at.']);
}
$works = Work::where([
['ended_at', '>', $started_at],
['ended_at', '<', $ended_at],
])->orWhere([
['started_at', '>', $started_at],
['started_at', '<', $ended_at],
])->orWhere([
['started_at', '>=', $started_at],
['ended_at', '<=', $ended_at],
])->where('id', '!=', $workModel->id)->exists();
$end = Carbon::createFromFormat('Y-m-d H:i', $ended_at);
$start = Carbon::createFromFormat('Y-m-d H:i', $started_at);
\request()->merge(['minute_sum' => $end->diffInMinutes($start)]);
}
if ($works) {
throw ValidationException::withMessages(['work' => 'The selected work is invalid.']);
}
}
public function destroy($business, $project, $task, $work)
{
$taskModel = Task::findOrFail($task);
$workModel = Work::findOrFail($work);
if ($taskModel->assignee_id != auth()->id()) {
abort(Response::HTTP_FORBIDDEN); // not allowed
}
$diff_in_min = $workModel->minute_sum;
$workModel->delete();
$taskModel->update([
'work_start' => Work::where('task_id', $taskModel->id)->orderBy('started_at')->first()->started_at ?? null,
'spent_time' => ($taskModel->spent_time - $diff_in_min)
]);
return $taskModel->load(['tagTask'=> fn($q) => $q->select('id', 'tag_id', 'task_id'), 'works','comments']);
}
}