ok
Direktori : /home2/selectio/www/fms-worksuite/app/Http/Controllers/ |
Current File : /home2/selectio/www/fms-worksuite/app/Http/Controllers/ProjectController.php |
<?php namespace App\Http\Controllers; use Carbon\Carbon; use App\Models\Role; use App\Models\Task; use App\Models\Team; use App\Models\User; use App\Helper\Files; use App\Helper\Reply; use App\Models\Module; use App\Models\Pinned; use App\Models\Expense; use App\Models\Invoice; use App\Models\Payment; use App\Models\Project; use App\Models\SubTask; use App\Models\Currency; use App\Models\TaskFile; use App\Models\TaskUser; use App\Models\Discussion; use App\Models\Permission; use App\Models\BankAccount; use App\Models\MentionUser; use App\Models\ProjectFile; use App\Models\ProjectNote; use App\Models\SubTaskFile; use App\Scopes\ActiveScope; use App\Traits\ImportExcel; use Illuminate\Http\Request; use App\Models\ProjectMember; use App\Imports\ProjectImport; use App\Jobs\ImportProjectJob; use App\Models\MessageSetting; use App\Models\PermissionRole; use App\Models\PermissionType; use App\Models\ProjectSetting; use App\Models\ProjectTimeLog; use App\Models\UserPermission; use App\Models\DiscussionReply; use App\Models\ProjectActivity; use App\Models\ProjectCategory; use App\Models\ProjectTemplate; use App\Models\TaskboardColumn; use App\Traits\ProjectProgress; use App\Models\ProjectMilestone; use App\DataTables\TasksDataTable; use App\Models\DiscussionCategory; use Illuminate\Support\Facades\DB; use App\Models\ProjectTimeLogBreak; use Illuminate\Support\Facades\Bus; use App\Models\ProjectStatusSetting; use Maatwebsite\Excel\Facades\Excel; use App\DataTables\ExpensesDataTable; use App\DataTables\InvoicesDataTable; use App\DataTables\PaymentsDataTable; use App\DataTables\ProjectsDataTable; use App\DataTables\TimeLogsDataTable; use App\DataTables\DiscussionDataTable; use Illuminate\Support\Facades\Artisan; use Maatwebsite\Excel\HeadingRowImport; use App\DataTables\ArchiveTasksDataTable; use App\DataTables\ProjectNotesDataTable; use App\Http\Requests\Project\StoreProject; use App\DataTables\ArchiveProjectsDataTable; use App\Http\Requests\Project\UpdateProject; use Maatwebsite\Excel\Imports\HeadingRowFormatter; use App\Http\Requests\Admin\Employee\ImportRequest; use App\Http\Requests\Admin\Employee\ImportProcessRequest; use Symfony\Component\Mailer\Exception\TransportException; class ProjectController extends AccountBaseController { use ProjectProgress, ImportExcel; public function __construct() { parent::__construct(); $this->pageTitle = 'app.menu.projects'; $this->middleware(function ($request, $next) { abort_403(!in_array('projects', $this->user->modules)); return $next($request); }); } /** * XXXXXXXXXXX * * @return \Illuminate\Http\Response */ public function index(ProjectsDataTable $dataTable) { $viewPermission = user()->permission('view_projects'); abort_403((!in_array($viewPermission, ['all', 'added', 'owned', 'both']))); if (!request()->ajax()) { if (in_array('client', user_roles())) { $this->clients = User::client(); } else { $this->clients = User::allClients(); $this->allEmployees = User::allEmployees(null, true, ($viewPermission == 'all' ? 'all' : null)); } $this->categories = ProjectCategory::all(); $this->departments = Team::all(); $this->projectStatus = ProjectStatusSetting::where('status', 'active')->get(); } return $dataTable->render('projects.index', $this->data); } /** * XXXXXXXXXXX * * @return array */ public function applyQuickAction(Request $request) { switch ($request->action_type) { case 'delete': $this->deleteRecords($request); return Reply::success(__('messages.deleteSuccess')); case 'archive': $this->archiveRecords($request); return Reply::success(__('messages.projectArchiveSuccessfully')); case 'change-status': $this->changeStatus($request); return Reply::success(__('messages.updateSuccess')); default: return Reply::error(__('messages.selectAction')); } } protected function deleteRecords($request) { abort_403(user()->permission('delete_projects') != 'all'); Project::withTrashed()->whereIn('id', explode(',', $request->row_ids))->forceDelete(); $items = explode(',', $request->row_ids); foreach ($items as $item) { // Delete project files Files::deleteDirectory(ProjectFile::FILE_PATH . '/' . $item); } } protected function archiveRecords($request) { abort_403(user()->permission('edit_projects') != 'all'); Project::whereIn('id', explode(',', $request->row_ids))->delete(); } public function archiveDestroy($id) { Project::destroy($id); return Reply::success(__('messages.projectArchiveSuccessfully')); } protected function changeStatus($request) { abort_403(user()->permission('edit_projects') != 'all'); Project::whereIn('id', explode(',', $request->row_ids))->update(['status' => $request->status]); } public function updateStatus(Request $request, $id) { Project::findOrFail($id) ->update([ 'status' => $request->status, ]); return Reply::success(__('messages.updateSuccess')); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { $project = Project::withTrashed()->findOrFail($id); $this->deletePermission = user()->permission('delete_projects'); abort_403(!($this->deletePermission == 'all' || ($this->deletePermission == 'added' && $project->added_by == user()->id))); // Delete project files Files::deleteDirectory(ProjectFile::FILE_PATH . '/' . $id); $project->forceDelete(); return Reply::success(__('messages.deleteSuccess')); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { $this->addPermission = user()->permission('add_projects'); abort_403(!in_array($this->addPermission, ['all', 'added'])); $this->pageTitle = __('app.addProject'); $this->clients = User::allClients(null, true, ($this->addPermission == 'all' ? 'all' : null)); $this->categories = ProjectCategory::all(); $this->templates = ProjectTemplate::all(); $this->currencies = Currency::all(); $this->teams = Team::all(); $this->employees = User::allEmployees(null, true, ($this->addPermission == 'all' ? 'all' : null)); $this->redirectUrl = request()->redirectUrl; $this->project = (request()['duplicate_project']) ? Project::with('client', 'members', 'members.user', 'members.user.session', 'members.user.employeeDetail.designation', 'milestones', 'milestones.currency')->withTrashed()->findOrFail(request()['duplicate_project'])->withCustomFields() : null; if ($this->project) { $this->projectMembers = $this->project->members ? $this->project->members->pluck('user_id')->toArray() : null; } $this->projectTemplate = request('template') ? ProjectTemplate::with('projectMembers')->findOrFail(request('template')) : null; if ($this->projectTemplate) { $this->projectTemplateMembers = $this->projectTemplate->projectMembers ? $this->projectTemplate->projectMembers->pluck('id')->toArray() : null; } $project = new Project(); if ($project->getCustomFieldGroupsWithFields()) { $this->fields = $project->getCustomFieldGroupsWithFields()->fields; } if (in_array('client', user_roles())) { $this->client = User::withoutGlobalScope(ActiveScope::class)->findOrFail(user()->id); } else { $this->client = isset(request()->default_client) ? User::withoutGlobalScope(ActiveScope::class)->findOrFail(request()->default_client) : null; } $userData = []; $usersData = $this->employees; foreach ($usersData as $user) { $url = route('employees.show', [$user->id]); $userData[] = ['id' => $user->id, 'value' => $user->name, 'image' => $user->image_url, 'link' => $url]; } $this->userData = $userData; if (request()->ajax()) { $html = view('projects.ajax.create', $this->data)->render(); return Reply::dataOnly(['status' => 'success', 'html' => $html, 'title' => $this->pageTitle]); } $this->view = 'projects.ajax.create'; return view('projects.create', $this->data); } /** * @param StoreProject $request * @return array|mixed * @throws \Throwable */ public function store(StoreProject $request) { $this->addPermission = user()->permission('add_projects'); abort_403(!in_array($this->addPermission, ['all', 'added'])); DB::beginTransaction(); try { $startDate = Carbon::createFromFormat($this->company->date_format, $request->start_date)->format('Y-m-d'); $deadline = !$request->has('without_deadline') ? Carbon::createFromFormat($this->company->date_format, $request->deadline)->format('Y-m-d') : null; $project = new Project(); $project->project_name = $request->project_name; $project->project_short_code = $request->project_code; $project->start_date = $startDate; $project->deadline = $deadline; $project->client_id = $request->client_id; if (!is_null($request->duplicateProjectID)) { $duplicateProject = Project::findOrFail($request->duplicateProjectID); $project->project_summary = trim_editor($duplicateProject->project_summary); $project->category_id = $duplicateProject->category_id; $project->client_view_task = $duplicateProject->client_view_task; $project->allow_client_notification = $duplicateProject->allow_client_notification; $project->manual_timelog = $duplicateProject->manual_timelog; $project->team_id = $duplicateProject->team_id; $project->status = 'not started'; $project->project_budget = $duplicateProject->project_budget; $project->currency_id = $duplicateProject->currency_id; $project->hours_allocated = $duplicateProject->hours_allocated; $project->notes = trim_editor($duplicateProject->notes); } else { $project->project_summary = trim_editor($request->project_summary); if ($request->category_id != '') { $project->category_id = $request->category_id; } $request->client_view_task = $request->client_view_task ? 'enable' : 'disable'; $project->allow_client_notification = ($request->client_view_task) && ($request->client_task_notification) ? 'enable' : 'disable'; $request->manual_timelog = $request->manual_timelog ? 'enable' : 'disable'; if ($request->team_id > 0) { $project->team_id = $request->team_id; } $project->project_budget = $request->project_budget; $project->currency_id = $request->currency_id != '' ? $request->currency_id : company()->currency_id; $project->hours_allocated = $request->hours_allocated; $defaultsStatus = ProjectStatusSetting::where('default_status', 1)->get(); foreach ($defaultsStatus as $default) { $project->status = $default->status_name; } $project->miro_board_id = $request->miro_board_id; $project->client_access = $request->has('client_access') && $request->client_access ? 1 : 0; $project->enable_miroboard = $request->has('miroboard_checkbox') && $request->miroboard_checkbox ? 1 : 0; $project->notes = trim_editor($request->notes); } if ($request->public) { $project->public = $request->public ? 1 : 0; } $project->save(); if (trim_editor($request->notes) != '') { $project->notes()->create([ 'title' => 'Note', 'details' => $request->notes, 'client_id' => $request->client_id, ]); } $this->logSearchEntry($project->id, $project->project_name, 'projects.show', 'project'); $this->logProjectActivity($project->id, 'messages.addedAsNewProject'); if ($request->template_id) { $template = ProjectTemplate::with('projectMembers')->findOrFail($request->template_id); foreach ($template->tasks as $task) { $projectTask = new Task(); $projectTask->project_id = $project->id; $projectTask->heading = $task->heading; $projectTask->task_category_id = $task->project_template_task_category_id; $projectTask->description = trim_editor($task->description); $projectTask->start_date = $startDate; $projectTask->due_date = $deadline; $projectTask->is_private = 0; $projectTask->save(); foreach ($task->usersMany as $value) { TaskUser::create( [ 'user_id' => $value->id, 'task_id' => $projectTask->id ] ); } foreach ($task->subtasks as $value) { $projectTask->subtasks()->create(['title' => $value->title]); } } } if (!is_null($request->duplicateProjectID)) { $this->storeDuplicateProject($request, $project); } // To add custom fields data if ($request->custom_fields_data) { $project->updateCustomFieldData($request->custom_fields_data); } // Commit Transaction DB::commit(); if($request->has('type') && $request->type == 'duplicateProject'){ return Reply::success(__('messages.projectCopiedSuccessfully')); } else { $redirectUrl = urldecode($request->redirect_url); if ($redirectUrl == '') { $redirectUrl = route('projects.index'); } return Reply::dataOnly(['projectID' => $project->id, 'redirectUrl' => $redirectUrl]); } } catch (TransportException $e) { // Rollback Transaction DB::rollback(); return Reply::error('Please configure SMTP details to add project. Visit Settings -> notification setting to set smtp ' . $e->getMessage(), 'smtp_error'); } catch (\Exception $e) { // Rollback Transaction DB::rollback(); return Reply::error('Some error occurred when inserting the data. Please try again or contact support ' . $e->getMessage()); } } public function edit($id) { $this->project = Project::with('client', 'members', 'members.user', 'members.user.session', 'members.user.employeeDetail.designation', 'milestones', 'milestones.currency') ->withTrashed() ->findOrFail($id) ->withCustomFields(); $memberIds = $this->project->members->pluck('user_id')->toArray(); $this->editPermission = user()->permission('edit_projects'); $this->editProjectMembersPermission = user()->permission('edit_project_members'); abort_403(!( $this->editPermission == 'all' || ($this->editPermission == 'added' && user()->id == $this->project->added_by) || ($this->editPermission == 'owned' && user()->id == $this->project->client_id && in_array('client', user_roles())) || ($this->editPermission == 'owned' && in_array(user()->id, $memberIds) && in_array('employee', user_roles())) || ($this->editPermission == 'both' && (user()->id == $this->project->client_id || user()->id == $this->project->added_by)) || ($this->editPermission == 'both' && in_array(user()->id, $memberIds) && in_array('employee', user_roles())) )); $this->pageTitle = __('app.update') . ' ' . __('app.project'); if ($this->project->getCustomFieldGroupsWithFields()) { $this->fields = $this->project->getCustomFieldGroupsWithFields()->fields; } $this->clients = User::allClients(null, true, ($this->editPermission == 'all' ? 'all' : null)); $this->categories = ProjectCategory::all(); $this->currencies = Currency::all(); $this->teams = Team::all(); $this->projectStatus = ProjectStatusSetting::where('status', 'active')->get(); $this->employees = ''; if ($this->editPermission == 'all' || $this->editProjectMembersPermission == 'all') { $this->employees = User::allEmployees(null, null, ($this->editPermission == 'all' ? 'all' : null)); } $userData = []; $usersData = $this->employees; foreach ($usersData as $user) { $url = route('employees.show', [$user->id]); $userData[] = ['id' => $user->id, 'value' => $user->name, 'image' => $user->image_url, 'link' => $url]; } $this->userData = $userData; if (request()->ajax()) { $html = view('projects.ajax.edit', $this->data)->render(); return Reply::dataOnly(['status' => 'success', 'html' => $html, 'title' => $this->pageTitle]); } abort_403(user()->permission('edit_projects') == 'added' && $this->project->added_by != user()->id); $this->view = 'projects.ajax.edit'; return view('projects.create', $this->data); } /** * @param UpdateProject $request * @param int $id * @return array * @throws \Froiden\RestAPI\Exceptions\RelatedResourceNotFoundException */ public function update(UpdateProject $request, $id) { $project = Project::findOrFail($id); $project->project_name = $request->project_name; $project->project_short_code = $request->project_code; $project->project_summary = trim_editor($request->project_summary); $project->start_date = Carbon::createFromFormat($this->company->date_format, $request->start_date)->format('Y-m-d'); if (!$request->has('without_deadline')) { $project->deadline = Carbon::createFromFormat($this->company->date_format, $request->deadline)->format('Y-m-d'); } else { $project->deadline = null; } if ($request->notes != '') { $project->notes = trim_editor($request->notes); } if ($request->category_id != '') { $project->category_id = $request->category_id; } if ($request->client_view_task) { $project->client_view_task = 'enable'; } else { $project->client_view_task = 'disable'; } if ($request->client_task_notification) { $project->allow_client_notification = 'enable'; } else { $project->allow_client_notification = 'disable'; } if ($request->manual_timelog) { $project->manual_timelog = 'enable'; } else { $project->manual_timelog = 'disable'; } $project->team_id = null; if ($request->team_id > 0) { $project->team_id = $request->team_id; } $project->client_id = ($request->client_id == 'null' || $request->client_id == '') ? null : $request->client_id; if ($request->calculate_task_progress) { $project->calculate_task_progress = 'true'; $project->completion_percent = $this->calculateProjectProgress($id, 'true'); } else { $project->calculate_task_progress = 'false'; $project->completion_percent = $request->completion_percent; } $project->project_budget = $request->project_budget; $project->currency_id = $request->currency_id != '' ? $request->currency_id : company()->currency_id; $project->hours_allocated = $request->hours_allocated; $project->status = $request->status; $project->miro_board_id = $request->miro_board_id; if ($request->has('miroboard_checkbox')) { $project->client_access = $request->has('client_access') && $request->client_access ? 1 : 0; } else { $project->client_access = 0; } $project->enable_miroboard = $request->has('miroboard_checkbox') && $request->miroboard_checkbox ? 1 : 0; if ($request->public) { $project->public = 1; } if ($request->private) { $project->public = 0; } if (!$request->private && !$request->public && $request->member_id) { $project->projectMembers()->sync($request->member_id); } $project->save(); // To add custom fields data if ($request->custom_fields_data) { $project->updateCustomFieldData($request->custom_fields_data); } $this->logProjectActivity($project->id, 'messages.updateSuccess'); $redirectUrl = urldecode($request->redirect_url); if ($redirectUrl == '') { $redirectUrl = route('projects.index'); } return Reply::successWithData(__('messages.updateSuccess'), ['projectID' => $project->id, 'redirectUrl' => $redirectUrl]); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { $this->viewPermission = user()->permission('view_projects'); $viewFilePermission = user()->permission('view_project_files'); $this->viewMiroboardPermission = user()->permission('view_miroboard'); $viewMilestonePermission = user()->permission('view_project_milestones'); $this->viewPaymentPermission = user()->permission('view_project_payments'); $this->viewProjectTimelogPermission = user()->permission('view_project_timelogs'); $this->viewExpensePermission = user()->permission('view_project_expenses'); $this->viewRatingPermission = user()->permission('view_project_rating'); $this->viewBurndownChartPermission = user()->permission('view_project_burndown_chart'); $this->viewProjectMemberPermission = user()->permission('view_project_members'); $this->project = Project::with(['client', 'members', 'members.user','mentionProject', 'members.user.session', 'members.user.employeeDetail.designation', 'milestones' => function ($q) use ($viewMilestonePermission) { if ($viewMilestonePermission == 'added') { $q->where('added_by', user()->id); } }, 'milestones.currency', 'files' => function ($q) use ($viewFilePermission) { if ($viewFilePermission == 'added') { $q->where('added_by', user()->id); } }]) ->withTrashed() ->findOrFail($id) ->withCustomFields(); $this->projectStatusColor = ProjectStatusSetting::where('status_name', $this->project->status)->first(); $memberIds = $this->project->members->pluck('user_id')->toArray(); $mentionIds = $this->project->mentionProject->pluck('user_id')->toArray(); abort_403(!( $this->viewPermission == 'all' || $this->project->public || ($this->viewPermission == 'added' && user()->id == $this->project->added_by) || ($this->viewPermission == 'owned' && user()->id == $this->project->client_id && in_array('client', user_roles())) || ($this->viewPermission == 'owned' && in_array(user()->id, $memberIds) && in_array('employee', user_roles())) || ($this->viewPermission == 'both' && (user()->id == $this->project->client_id || user()->id == $this->project->added_by)) || ($this->viewPermission == 'both' && (in_array(user()->id, $memberIds) || user()->id == $this->project->added_by) && in_array('employee', user_roles())) || (($this->viewPermission == 'none') || (!is_null(($this->project->mentionProject))) && in_array(user()->id, $mentionIds)) )); $this->pageTitle = ucfirst($this->project->project_name); if ($this->project->getCustomFieldGroupsWithFields()) { $this->fields = $this->project->getCustomFieldGroupsWithFields()->fields; } $this->messageSetting = MessageSetting::first(); $this->projectStatus = ProjectStatusSetting::where('status', 'active')->get(); $tab = request('tab'); switch ($tab) { case 'members': abort_403(!( $this->viewProjectMemberPermission == 'all' )); $this->view = 'projects.ajax.members'; break; case 'milestones': $this->view = 'projects.ajax.milestones'; break; case 'taskboard': session()->forget('pusher_settings'); $this->view = 'projects.ajax.taskboard'; break; case 'tasks': $this->taskBoardStatus = TaskboardColumn::all(); return (!$this->project->trashed()) ? $this->tasks($this->project->project_admin == user()->id) : $this->archivedTasks($this->project->project_admin == user()->id); case 'gantt': $this->taskBoardStatus = TaskboardColumn::all(); $this->view = 'projects.ajax.gantt'; break; case 'invoices': return $this->invoices(); case 'files': $this->view = 'projects.ajax.files'; break; case 'timelogs': return $this->timelogs($this->project->project_admin == user()->id); case 'expenses': return $this->expenses(); case 'miroboard'; abort_403(!in_array($this->viewMiroboardPermission, ['all']) || !$this->project->enable_miroboard && ((!in_array('client', user_roles()) && !$this->project->client_access && $this->project->client_id != user()->id))); $this->view = 'projects.ajax.miroboard'; break; case 'payments': return $this->payments(); case 'discussion': $this->discussionCategories = DiscussionCategory::orderBy('order', 'asc')->get(); return $this->discussions($this->project->project_admin == user()->id); case 'notes': return $this->notes($this->project->project_admin == user()->id); case 'rating': return $this->rating($this->project->project_admin == user()->id); case 'burndown-chart': $this->fromDate = now($this->company->timezone)->startOfMonth(); $this->toDate = now($this->company->timezone); return $this->burndownChart($this->project); case 'activity': $this->activities = ProjectActivity::getProjectActivities($id, 10); $this->view = 'projects.ajax.activity'; break; default: $this->taskChart = $this->taskChartData($id); $hoursLogged = $this->project->times()->sum('total_minutes'); $breakMinutes = ProjectTimeLogBreak::projectBreakMinutes($id); $this->hoursBudgetChart = $this->hoursBudgetChartData($this->project, $hoursLogged, $breakMinutes); $this->amountBudgetChart = $this->amountBudgetChartData($this->project); $this->taskBoardStatus = TaskboardColumn::all(); $this->earnings = Payment::where('status', 'complete') ->where('project_id', $id) ->sum('amount'); $this->hoursLogged = intdiv($hoursLogged - $breakMinutes, 60); $this->expenses = Expense::where(['project_id' => $id, 'status' => 'approved'])->sum('price'); $this->view = 'projects.ajax.overview'; break; } if (request()->ajax()) { $html = view($this->view, $this->data)->render(); return Reply::dataOnly(['status' => 'success', 'html' => $html, 'title' => $this->pageTitle]); } $this->activeTab = $tab ?: 'overview'; return view('projects.show', $this->data); } /** * XXXXXXXXXXX * * @return array */ public function taskChartData($id) { $taskStatus = TaskboardColumn::all(); $data['labels'] = $taskStatus->pluck('column_name'); $data['colors'] = $taskStatus->pluck('label_color'); $data['values'] = []; foreach ($taskStatus as $label) { $data['values'][] = Task::where('project_id', $id)->where('tasks.board_column_id', $label->id)->count(); } return $data; } /** * XXXXXXXXXXX * * @return array */ public function hoursBudgetChartData($project, $hoursLogged, $breakMinutes) { $hoursBudget = $project->hours_allocated ? $project->hours_allocated : 0; $hoursLogged = intdiv($hoursLogged - $breakMinutes, 60); $overRun = $hoursLogged - $hoursBudget; $overRun = $overRun < 0 ? 0 : $overRun; $hoursLogged = ($hoursLogged > $hoursBudget) ? $hoursBudget : $hoursLogged; $data['labels'] = [__('app.planned'), __('app.actual')]; $data['colors'] = ['#2cb100', '#d30000']; $data['threshold'] = $hoursBudget; $dataset = [ [ 'name' => __('app.planned'), 'values' => [$hoursBudget, $hoursLogged], ], [ 'name' => __('app.overrun'), 'values' => [0, $overRun], ], ]; $data['datasets'] = $dataset; return $data; } /** * XXXXXXXXXXX * * @return \Illuminate\Http\Response */ public function amountBudgetChartData($project) { $amountBudget = $project->project_budget ?: 0; $earnings = Payment::where('status', 'complete') ->where('project_id', $project->id) ->sum('amount'); $plannedOverun = $earnings < $amountBudget ? $earnings : $amountBudget; $overRun = $earnings - $amountBudget; $overRun = $overRun < 0 ? 0 : $overRun; $data['labels'] = [__('app.planned'), __('app.actual')]; $data['colors'] = ['#2cb100', '#d30000']; $data['threshold'] = $amountBudget; $dataset = [ [ 'name' => __('app.planned'), 'values' => [$amountBudget, $plannedOverun], ], [ 'name' => __('app.overrun'), 'values' => [0, $overRun], ], ]; $data['datasets'] = $dataset; return $data; } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return array */ public function storePin(Request $request) { $pinned = new Pinned(); $pinned->task_id = $request->task_id; $pinned->project_id = $request->project_id; $pinned->save(); return Reply::success(__('messages.pinnedSuccess')); } /** * Remove the specified resource from storage. * * @param int $id * @return array */ public function destroyPin(Request $request, $id) { Pinned::where('project_id', $id)->where('user_id', user()->id)->delete(); return Reply::success(__('messages.deleteSuccess')); } public function assignProjectAdmin(Request $request) { $userId = $request->userId; $projectId = $request->projectId; $project = Project::findOrFail($projectId); $project->project_admin = $userId; $project->save(); return Reply::success(__('messages.roleAssigned')); } public function tasks($projectAdmin = false) { $dataTable = new TasksDataTable(); if (!$projectAdmin) { $viewPermission = user()->permission('view_project_tasks'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); $viewPermission = user()->permission('view_tasks'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned', 'both'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.tasks'; return $dataTable->render('projects.show', $this->data); } public function archivedTasks($projectAdmin = false) { $dataTable = new ArchiveTasksDataTable(); if (!$projectAdmin) { $viewPermission = user()->permission('view_project_tasks'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); $viewPermission = user()->permission('view_tasks'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned', 'both'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.tasks'; return $dataTable->render('projects.show', $this->data); } public function ganttData() { $id = request('projectID'); $assignedTo = request('assignedTo'); $projectTask = request('projectTask'); $taskStatus = request('taskStatus'); $milestones = request('milestones'); $withoutDueDate = false; if ($assignedTo != 'all') { $tasks = Task::projectTasks($id, $assignedTo, null, $withoutDueDate); } else { $tasks = Task::projectTasks($id, null, null, $withoutDueDate); } if ($projectTask) { $tasks = $tasks->whereIn('id', explode(',', $projectTask)); } if ($taskStatus) { $tasks = $tasks->whereIn('board_column_id', explode(',', $taskStatus)); } if ($milestones != '') { $tasks = $tasks->whereIn('milestone_id', explode(',', $milestones)); } $data = array(); $count = 0; foreach ($tasks as $task) { $data[$count] = [ 'id' => 'task-' . $task->id, 'name' => ucfirst($task->heading), 'start' => ((!is_null($task->start_date)) ? $task->start_date->format('Y-m-d') : ((!is_null($task->due_date)) ? $task->due_date->format('Y-m-d') : null)), 'end' => (!is_null($task->due_date)) ? $task->due_date->format('Y-m-d') : $task->start_date->format('Y-m-d'), 'progress' => 0, 'bg_color' => $task->boardColumn->label_color, 'taskid' => $task->id, 'draggable' => true ]; if (!is_null($task->dependent_task_id)) { $data[$count]['dependencies'] = 'task-' . $task->dependent_task_id; } $count++; } return response()->json($data); } public function invoices() { $dataTable = new InvoicesDataTable; $viewPermission = user()->permission('view_project_invoices'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.invoices'; return $dataTable->render('projects.show', $this->data); } /** * XXXXXXXXXXX * * @return \Illuminate\Http\Response */ public function invoiceList(Request $request, $id) { $options = '<option value="">--</option>'; $viewPermission = user()->permission('view_invoices'); if (($viewPermission == 'all' || $viewPermission == 'added')) { if ($id != 0) { $invoices = Invoice::with('payment', 'currency')->where('project_id', $id)->where('send_status', 1)->pending()->get(); } else { $invoices = Invoice::with('payment')->where('send_status', 1) ->where(function ($q) { $q->where('status', 'unpaid') ->orWhere('status', 'partial'); })->get(); } foreach ($invoices as $item) { $paidAmount = $item->amountPaid(); $options .= '<option data-currency-code="'.$item->currency->currency_code.'" data-currency-id="' . $item->currency_id . '" data-content="' . $item->invoice_number . ' - ' . __('app.total') . ': <span class=\'text-dark f-w-500 mr-2\'>' . currency_format($item->total, $item->currency->id) . ' </span>' . __('modules.invoices.due') . ': <span class=\'text-red\'>' . currency_format(max(($item->total - $paidAmount), 0), $item->currency->id) . '</span>" value="' . $item->id . '"> ' . $item->invoice_number . ' </option>'; } } $bankData = '<option value="">--</option>'; $this->viewBankAccountPermission = user()->permission('view_bankaccount'); $bankDetails = BankAccount::where('status', 1)->where('currency_id', $request->currencyId); if($this->viewBankAccountPermission == 'added'){ $bankDetails = $bankDetails->where('added_by', user()->id); } $bankDetails = $bankDetails->get(); foreach ($bankDetails as $bankDetail) { $bankName = ''; if($bankDetail->type == 'bank') { $bankName = $bankDetail->bank_name.' |'; } $bankData .= '<option value="' . $bankDetail->id . '">'.$bankName .' '.mb_ucwords($bankDetail->account_name). '</option>'; } $exchangeRate = Currency::where('id', $request->currencyId)->pluck('exchange_rate')->toArray(); return Reply::dataOnly(['status' => 'success', 'data' => $options, 'account' => $bankData, 'exchangeRate' => $exchangeRate]); } /** * XXXXXXXXXXX * * @return \Illuminate\Http\Response */ public function members($id) { $options = ''; $userData = []; $project = Project::select('id', 'public')->find($id); $checkPublic = ($project) ? $project->public : 0; if ($id == 0 || $checkPublic == 1) { $members = User::allEmployees(null, true); foreach ($members as $item) { $self_select = (user() && user()->id == $item->id) ? '<span class=\'ml-2 badge badge-secondary\'>' . __('app.itsYou') . '</span>' : ''; $options .= '<option data-content="<span class=\'badge badge-pill badge-light border\'><div class=\'d-inline-block mr-1\'><img class=\'taskEmployeeImg rounded-circle\' src=' . $item->image_url . ' ></div> ' . $item->name . '' . $self_select . '</span>" value="' . $item->id . '"> ' . $item->name . '</option>'; } $projectShortCode = '--'; } else { $members = ProjectMember::with('user')->where('project_id', $id)->get(); foreach ($members as $item) { $self_select = (user() && user()->id == $item->user->id) ? '<span class=\'ml-2 badge badge-secondary\'>' . __('app.itsYou') . '</span>' : ''; $options .= '<option data-content="<span class=\'badge badge-pill badge-light border\'><div class=\'d-inline-block mr-1\'><img class=\'taskEmployeeImg rounded-circle\' src=' . $item->user->image_url . ' ></div> ' . $item->user->name . '' . $self_select . '</span>" value="' . $item->user->id . '"> ' . $item->user->name . ' </option>'; $url = route('employees.show', [$item->user->id]); $userData[] = ['id' => $item->user->id, 'value' => $item->user->name, 'image' => $item->user->image_url, 'link' => $url]; } $project = Project::findOrFail($id); $projectShortCode = $project->project_short_code; } return Reply::dataOnly(['status' => 'success', 'unique_id' => $projectShortCode, 'data' => $options, 'userData' => $userData]); } public function timelogs($projectAdmin = false) { $dataTable = new TimeLogsDataTable(); if (!$projectAdmin) { $viewPermission = user()->permission('view_project_timelogs'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.timelogs'; return $dataTable->render('projects.show', $this->data); } public function expenses() { $dataTable = new ExpensesDataTable(); $viewPermission = user()->permission('view_project_expenses'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.expenses'; return $dataTable->render('projects.show', $this->data); } public function payments() { $dataTable = new PaymentsDataTable(); $viewPermission = user()->permission('view_project_payments'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned'])); $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.payments'; return $dataTable->render('projects.show', $this->data); } public function discussions($projectAdmin = false) { $dataTable = new DiscussionDataTable(); if (!$projectAdmin) { $viewPermission = user()->permission('view_project_discussions'); abort_403(!in_array($viewPermission, ['all', 'added'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'overview'; $this->view = 'projects.ajax.discussion'; return $dataTable->render('projects.show', $this->data); } public function burndown(Request $request, $id) { $this->project = Project::with(['tasks' => function ($query) use ($request) { if ($request->startDate !== null && $request->startDate != 'null' && $request->startDate != '') { $query->where(DB::raw('DATE(`start_date`)'), '>=', Carbon::createFromFormat($this->company->date_format, $request->startDate)); } if ($request->endDate !== null && $request->endDate != 'null' && $request->endDate != '') { $query->where(DB::raw('DATE(`due_date`)'), '<=', Carbon::createFromFormat($this->company->date_format, $request->endDate)); } $query->whereNotNull('due_date'); }])->withTrashed()->findOrFail($id); $this->totalTask = $this->project->tasks->count(); $datesArray = []; $startDate = $request->startDate ? Carbon::createFromFormat($this->company->date_format, $request->startDate) : Carbon::parse($this->project->start_date); if ($this->project->deadline) { $endDate = $request->endDate ? Carbon::createFromFormat($this->company->date_format, $request->endDate) : Carbon::parse($this->project->deadline); } else { $endDate = $request->endDate ? Carbon::createFromFormat($this->company->date_format, $request->endDate) : now(); } for ($startDate; $startDate <= $endDate; $startDate->addDay()) { $datesArray[] = $startDate->format($this->company->date_format); } $uncompletedTasks = []; $createdTasks = []; $deadlineTasks = []; $deadlineTasksCount = []; $this->datesArray = json_encode($datesArray); foreach ($datesArray as $key => $value) { if (Carbon::createFromFormat($this->company->date_format, $value)->lessThanOrEqualTo(now())) { $uncompletedTasks[$key] = $this->project->tasks->filter(function ($task) use ($value) { if (is_null($task->completed_on)) { return true; } return $task->completed_on ? $task->completed_on->greaterThanOrEqualTo(Carbon::createFromFormat($this->company->date_format, $value)) : false; })->count(); $createdTasks[$key] = $this->project->tasks->filter(function ($task) use ($value) { return Carbon::createFromFormat($this->company->date_format, $value)->startOfDay()->equalTo($task->created_at->startOfDay()); })->count(); if ($key > 0) { $uncompletedTasks[$key] += $createdTasks[$key]; } } $deadlineTasksCount[] = $this->project->tasks->filter(function ($task) use ($value) { return Carbon::createFromFormat($this->company->date_format, $value)->startOfDay()->equalTo($task->due_date->startOfDay()); })->count(); if ($key == 0) { $deadlineTasks[$key] = $this->totalTask - $deadlineTasksCount[$key]; } else { $newKey = $key - 1; $deadlineTasks[$key] = $deadlineTasks[$newKey] - $deadlineTasksCount[$key]; } } $this->uncompletedTasks = json_encode($uncompletedTasks); $this->deadlineTasks = json_encode($deadlineTasks); if ($request->ajax()) { return $this->data; } $this->startDate = $request->startDate ? Carbon::parse($request->startDate)->format($this->company->date_format) : Carbon::parse($this->project->start_date)->format($this->company->date_format); $this->endDate = $endDate->format($this->company->date_format); return view('projects.ajax.burndown', $this->data); } public function notes($projectAdmin = false) { $dataTable = new ProjectNotesDataTable(); if (!$projectAdmin) { $viewPermission = user()->permission('view_project_note'); abort_403(!in_array($viewPermission, ['all', 'added', 'owned', 'both'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'profile'; $this->view = 'projects.ajax.notes'; return $dataTable->render('projects.show', $this->data); } public function burndownChart($project) { $viewPermission = user()->permission('view_project_burndown_chart'); abort_403(!(in_array($viewPermission, ['all']) || $project->project_admin == user()->id)); $tab = request('tab'); $this->activeTab = $tab ?: 'burndown-chart'; $this->view = 'projects.ajax.burndown'; return view('projects.show', $this->data); } public function rating($projectAdmin) { if (!$projectAdmin) { $viewPermission = user()->permission('view_project_rating'); abort_403(!in_array($viewPermission, ['all', 'added'])); } $tab = request('tab'); $this->activeTab = $tab ?: 'rating'; $this->view = 'projects.ajax.rating'; return view('projects.show', $this->data); } /** * XXXXXXXXXXX * * @return \Illuminate\Http\Response */ public function archive(ArchiveProjectsDataTable $dataTable) { $viewPermission = user()->permission('view_projects'); abort_403($viewPermission == 'none'); if (!request()->ajax()) { if (in_array('client', user_roles())) { $this->clients = User::client(); } else { $this->clients = User::allClients(); $this->allEmployees = User::allEmployees(); } $this->categories = ProjectCategory::all(); $this->departments = Team::all(); } return $dataTable->render('projects.archive', $this->data); } public function archiveRestore($id) { $project = Project::withTrashed()->findOrFail($id); $project->restore(); return Reply::success(__('messages.projectRevertSuccessfully')); } public function importProject() { $this->pageTitle = __('app.importExcel') . ' ' . __('app.menu.projects'); $this->addPermission = user()->permission('add_projects'); abort_403(!in_array($this->addPermission, ['all', 'added'])); if (request()->ajax()) { $html = view('projects.ajax.import', $this->data)->render(); return Reply::dataOnly(['status' => 'success', 'html' => $html, 'title' => $this->pageTitle]); } $this->view = 'projects.ajax.import'; return view('projects.create', $this->data); } public function importStore(ImportRequest $request) { $this->importFileProcess($request, ProjectImport::class); $view = view('projects.ajax.import_progress', $this->data)->render(); return Reply::successWithData(__('messages.importUploadSuccess'), ['view' => $view]); } public function importProcess(ImportProcessRequest $request) { $batch = $this->importJobProcess($request, ProjectImport::class, ImportProjectJob::class); return Reply::successWithData(__('messages.importProcessStart'), ['batch' => $batch]); } public function changeProjectStatus(Request $request) { $projectId = $request->projectId; $statusID = $request->statusId; $project = Project::with('members')->findOrFail($projectId); $projectUsers = $project->members->pluck('user_id')->toArray(); $this->editProjectPermission = user()->permission('edit_projects'); abort_403(!( $this->editProjectPermission == 'all' || ($this->editProjectPermission == 'added' && user()->id == $project->added_by) || ($this->editProjectPermission == 'owned' && user()->id == $project->client_id && in_array('client', user_roles())) || ($this->editProjectPermission == 'owned' && in_array(user()->id, $projectUsers) && in_array('employee', user_roles())) || ($this->editProjectPermission == 'both' && (user()->id == $project->client_id || user()->id == $project->added_by)) || ($this->editProjectPermission == 'both' && in_array(user()->id, $projectUsers) && in_array('employee', user_roles()) ))); $projectStatus = ProjectStatusSetting::where('status_name', $statusID)->first(); $project->status = $projectStatus->status_name; $project->save(); return Reply::success(__('messages.updateSuccess')); } public function pendingTasks($id) { if ($id != 0) { $tasks = Task::join('task_users', 'task_users.task_id', '=', 'tasks.id') ->with('project') ->pending() ->where('task_users.user_id', '=', $this->user->id) ->where('tasks.project_id', '=', $id) ->select('tasks.*') ->get(); } else { $tasks = Task::join('task_users', 'task_users.task_id', '=', 'tasks.id') ->with('project') ->pending() ->where('task_users.user_id', '=', $this->user->id) ->select('tasks.*') ->get(); } $options = '<option value="">--</option>'; foreach ($tasks as $item) { $name = ''; if (!is_null($item->project_id)) { $name .= "<h5 class='f-12 text-darkest-grey'>" . ucfirst($item->heading) . "</h5><div class='text-muted f-11'>" . $item->project->project_name . '</div>'; } else { $name .= "<span class='text-dark-grey f-11'>" . ucfirst($item->heading) . '</span>'; } $options .= '<option data-content="' . $name . '" value="' . $item->id . '">' . $item->heading . '</option>'; } return Reply::dataOnly(['status' => 'success', 'data' => $options]); } public function ajaxLoadProject(Request $request) { $search = $request->search; $response = []; if ($search) { $lists = Project::allProjects($search); foreach ($lists as $list) { $response[] = [ 'id' => $list->id, 'text' => $list->project_name, ]; } } return response()->json($response); } public function duplicateProject($id) { $this->projectId = $id; $this->project = Project::findOrFail($id); $this->taskboardColumns = TaskboardColumn::orderBy('priority', 'asc')->get(); $addPermission = user()->permission('add_projects'); $this->memberIds = $this->project->members->pluck('user_id')->toArray(); $this->employees = User::allEmployees(null, true, ($addPermission == 'all' ? 'all' : null)); $this->clients = User::allClients(null, true, ($addPermission == 'all' ? 'all' : null)); if (in_array('client', user_roles())) { $this->client = User::withoutGlobalScope(ActiveScope::class)->findOrFail(user()->id); } else { $this->client = isset(request()->default_client) ? User::withoutGlobalScope(ActiveScope::class)->findOrFail(request()->default_client) : null; } return view('projects.duplicate-project', $this->data); } public function storeDuplicateProject($request, $project) { // For duplicate project if($request->has('file')){ $projectExists = ProjectFile::where('project_id', $request->duplicateProjectID)->get(); if ($projectExists) { foreach ($projectExists as $projectExist) { $file = new ProjectFile(); $file->user_id = $projectExist->user_id; $file->project_id = $project->id; $fileName = Files::generateNewFileName($projectExist->filename); Files::copy(ProjectFile::FILE_PATH . '/' . $projectExist->project_id . '/' . $projectExist->hashname, ProjectFile::FILE_PATH . '/' . $project->id . '/' . $fileName); $file->filename = $projectExist->filename; $file->hashname = $fileName; $file->size = $projectExist->size; $file->save(); $this->logProjectActivity($project->id, $this->user->id, 'fileActivity', $project->board_column_id); /* @phpstan-ignore-line */ } } } if($request->has('milestone')){ $projectMilestoneExists = ProjectMilestone::where('project_id', $request->duplicateProjectID)->get(); if ($projectMilestoneExists) { foreach ($projectMilestoneExists as $projectMilestoneExist) { $milestone = new ProjectMilestone(); $milestone->project_id = $project->id; $milestone->milestone_title = $projectMilestoneExist->milestone_title; $milestone->summary = $projectMilestoneExist->summary; $milestone->cost = $projectMilestoneExist->cost; $milestone->currency_id = $projectMilestoneExist->currency_id; $milestone->status = $projectMilestoneExist->status; $milestone->start_date = $projectMilestoneExist->start_date; $milestone->end_date = $projectMilestoneExist->end_date; $milestone->save(); $this->logProjectActivity($milestone->project_id, 'messages.milestoneUpdated'); } } } if($request->has('time_sheet')){ $projectTimeLogExists = ProjectTimeLog::where('project_id', $request->duplicateProjectID)->get(); if ($projectTimeLogExists) { foreach ($projectTimeLogExists as $projectTimeLogExist) { $projectTimeLog = new ProjectTimeLog(); $projectTimeLog->project_id = $project->id; $projectTimeLog->task_id = $projectTimeLogExist->task_id; $projectTimeLog->user_id = $projectTimeLogExist->user_id; $projectTimeLog->start_time = $projectTimeLogExist->start_time; $projectTimeLog->end_time = $projectTimeLogExist->end_time; $projectTimeLog->total_hours = $projectTimeLogExist->total_hours; $projectTimeLog->total_minutes = $projectTimeLogExist->total_minutes; $projectTimeLog->hourly_rate = $projectTimeLogExist->hourly_rate; $projectTimeLog->memo = $projectTimeLogExist->memo; $projectTimeLog->edited_by_user = user()->id; $projectTimeLog->save(); } } } if($request->has('note')){ $projectNoteExists = ProjectNote::where('project_id', $request->duplicateProjectID)->get(); if ($projectNoteExists) { foreach ($projectNoteExists as $projectNoteExist) { $projectNote = new ProjectNote(); $projectNote->project_id = $project->id; $projectNote->title = $projectNoteExist->title; $projectNote->details = $projectNoteExist->details; $projectNote->type = $projectNoteExist->type; $projectNote->client_id = $projectNoteExist->client_id; $projectNote->is_client_show = $projectNoteExist->is_client_show; $projectNote->ask_password = $projectNoteExist->ask_password; $projectNote->save(); } } } if($request->has('task')){ $projectTasks = Task::with('labels', 'taskUsers'); if($request->task_status){ $projectTasks->whereIn('board_column_id', $request->task_status); } $projectTasks = $projectTasks->where('project_id', $request->duplicateProjectID)->get(); $taskBoard = TaskboardColumn::where('slug', 'incomplete')->first(); if ($projectTasks) { foreach ($projectTasks as $projectTask) { $task = new Task(); $task->company_id = company()->id; $task->project_id = $project->id; $task->heading = $projectTask->heading; $task->description = trim_editor($projectTask->description); $task->start_date = $projectTask->start_date; $task->due_date = $projectTask->due_date; $task->task_category_id = $projectTask->category_id; /* @phpstan-ignore-line */ $task->priority = $projectTask->priority; $task->board_column_id = $taskBoard->id; $task->dependent_task_id = $projectTask->dependent_task_id; $task->is_private = $projectTask->is_private; $task->billable = $projectTask->billable; $task->estimate_hours = $projectTask->estimate_hours; $task->estimate_minutes = $projectTask->estimate_minutes; $task->milestone_id = $projectTask->milestone_id; $task->repeat = $projectTask->repeat; $task->hash = md5(microtime()); if ($projectTask->repeat) { $task->repeat_count = $projectTask->repeat_count; $task->repeat_type = $projectTask->repeat_type; $task->repeat_cycles = $projectTask->repeat_cycles; } if ($project) { $projectLastTaskCount = Task::projectTaskCount($project->id); $task->task_short_code = ($project) ? $project->project_short_code . '-' . ((int)$projectLastTaskCount + 1) : null; } $task->saveQuietly(); $this->saveSubTask($projectTask, $task, $request); } } } } public function saveSubTask($projectTask, $task, $request) { if($request->has('same_assignee')){ foreach($projectTask->taskUsers as $taskUsers){ $taskUser = new TaskUser(); $taskUser->task_id = $task->id; $taskUser->user_id = $taskUsers->user_id; $taskUser->save(); } } if (!is_null($projectTask->id) && $request->has('sub_task')) { $subTasks = SubTask::with(['files'])->where('task_id', $projectTask->id)->get(); if ($subTasks) { foreach ($subTasks as $subTask) { $subTaskData = new SubTask(); $subTaskData->title = $subTask->title; $subTaskData->task_id = $task->id; $subTaskData->description = trim_editor($subTask->description); if ($subTask->start_date != '' && $subTask->due_date != '') { $subTaskData->start_date = $subTask->start_date; $subTaskData->due_date = $subTask->due_date; } $subTaskData->assigned_to = $subTask->assigned_to; $subTaskData->save(); if ($subTask->files) { foreach ($subTask->files as $fileData) { $file = new SubTaskFile(); $file->user_id = $fileData->user_id; $file->sub_task_id = $subTaskData->id; $fileName = Files::generateNewFileName($fileData->filename); Files::copy(SubTaskFile::FILE_PATH . '/' . $fileData->sub_task_id . '/' . $fileData->hashname, SubTaskFile::FILE_PATH . '/' . $subTaskData->id . '/' . $fileName); $file->filename = $fileData->filename; $file->hashname = $fileName; $file->size = $fileData->size; $file->save(); } } } } } } }