ultimatepos/Modules/ProfessionalProject/Http/Controllers/ProjectController.php

357 lines
14 KiB
PHP

<?php
namespace Modules\ProfessionalProject\Http\Controllers;
use App\Contact;
use App\User;
use App\Utils\ModuleUtil;
use App\Utils\Util;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ProfessionalProject\Entities\PpMilestone;
use Modules\ProfessionalProject\Entities\PpProject;
use Modules\ProfessionalProject\Entities\PpProjectCategory;
use Modules\ProfessionalProject\Entities\PpTask;
use Modules\ProfessionalProject\Entities\PpTaskStatus;
use Modules\ProfessionalProject\Utils\ProfessionalProjectUtil;
class ProjectController extends Controller
{
protected $commonUtil;
protected $ppUtil;
protected $moduleUtil;
public function __construct(Util $commonUtil, ProfessionalProjectUtil $ppUtil, ModuleUtil $moduleUtil)
{
$this->commonUtil = $commonUtil;
$this->ppUtil = $ppUtil;
$this->moduleUtil = $moduleUtil;
}
protected function authorizeModule()
{
$business_id = request()->session()->get('user.business_id');
if (! (auth()->user()->can('superadmin')
|| $this->moduleUtil->hasThePermissionInSubscription($business_id, 'professional_project_module'))) {
abort(403, 'Unauthorized action.');
}
if (! auth()->user()->can('professionalproject.access')) {
abort(403, 'Unauthorized action.');
}
}
public function index()
{
$this->authorizeModule();
$business_id = request()->session()->get('user.business_id');
$is_admin = $this->commonUtil->is_admin(auth()->user(), $business_id);
$user_id = auth()->user()->id;
$statuses = PpProject::statusDropdown();
$view = request()->get('view', 'list');
if (request()->ajax()) {
$query = PpProject::with(['customer', 'members', 'lead'])
->where('business_id', $business_id)
->where('is_archived', false);
if (! $is_admin) {
$query->where(function ($q) use ($user_id) {
$q->where('lead_id', $user_id)
->orWhereHas('members', fn ($m) => $m->where('user_id', $user_id));
});
}
if (request()->filled('status')) {
$query->where('status', request()->get('status'));
}
if (request()->filled('filter_category')) {
$filter = request()->get('filter_category');
if ($filter === 'uncategorized') {
$query->uncategorized();
} elseif ($filter !== 'all' && is_numeric($filter)) {
$query->inCategory((int) $filter);
}
}
if (request()->filled('filter_category') && is_numeric(request()->get('filter_category'))) {
$cat_id = (int) request()->get('filter_category');
if (PpProjectCategory::forBusiness($business_id)->where('parent_id', $cat_id)->exists()) {
$bridge = app(\Modules\ManagementTools\Utils\ProfessionalProjectBridge::class);
$browse = $bridge->getCategoryBrowseData($business_id, $cat_id, $user_id, $is_admin, $view);
$browse['link_mode'] = 'pp';
return view('professionalproject::category.partials.subcategories_browser', $browse)->render();
}
}
if ($view === 'kanban') {
$projects = $query->get()->groupBy('status');
$sorted = [];
foreach ($statuses as $key => $label) {
$sorted[$key] = $projects->get($key, collect());
}
return view('professionalproject::project.partials.kanban')
->with(compact('sorted', 'statuses', 'is_admin'))
->render();
}
$projects = $query->latest()->paginate(15);
return view('professionalproject::project.partials.list')
->with(compact('projects', 'is_admin'))
->render();
}
return view('professionalproject::project.index')
->with(compact('statuses', 'view'))
->with([
'filter_category' => request()->get('filter_category'),
'root_categories' => PpProjectCategory::forBusiness($business_id)->roots()->orderBy('position')->orderBy('name')->get(),
'active_category' => request()->filled('filter_category') && is_numeric(request()->get('filter_category'))
? PpProjectCategory::forBusiness($business_id)->find(request()->get('filter_category'))
: null,
'category_breadcrumb' => request()->filled('filter_category') && is_numeric(request()->get('filter_category'))
? PpProjectCategory::breadcrumb($business_id, (int) request()->get('filter_category'))
: collect(),
]);
}
protected function formData($business_id, $project = null)
{
$exclude_id = $project ? $project->id : null;
$projects = PpProject::projectDropdown($business_id);
if ($exclude_id) {
$projects = $projects->except($exclude_id);
}
return [
'users' => User::forDropdown($business_id, false),
'customers' => Contact::customersDropdown($business_id, false),
'statuses' => PpProject::statusDropdown(),
'projects' => $projects,
'categories' => PpProjectCategory::dropdown($business_id),
'categories_with_members' => PpProjectCategory::forBusiness($business_id)
->with('members')
->orderBy('position')
->orderBy('name')
->get(),
'project' => $project,
];
}
protected function syncProjectRelations(PpProject $project, Request $request)
{
$members = array_filter((array) $request->input('user_id', []));
$manager_id = $request->input('manager_id') ?: $request->input('lead_id');
if (empty($members)) {
$members = [auth()->id()];
}
if ($manager_id && ! in_array($manager_id, $members)) {
$members[] = $manager_id;
}
$project->members()->sync($members);
$project->categories()->sync($request->input('category_id', []));
$project->supervisors()->sync($request->input('supervisor_id', []));
$parent_ids = array_filter((array) $request->input('parent_id', []));
$project->parents()->sync($parent_ids);
$project->update(['parent_id' => ! empty($parent_ids) ? (int) reset($parent_ids) : null]);
}
public function create()
{
$this->authorizeModule();
if (! auth()->user()->can('professionalproject.create_project')) {
abort(403, 'Unauthorized action.');
}
$business_id = request()->session()->get('user.business_id');
return view('professionalproject::project.create')
->with($this->formData($business_id));
}
public function store(Request $request)
{
$this->authorizeModule();
if (! auth()->user()->can('professionalproject.create_project')) {
abort(403, 'Unauthorized action.');
}
try {
$business_id = $request->session()->get('user.business_id');
$manager_id = $request->input('manager_id') ?: auth()->user()->id;
$input = $request->only(['name', 'description', 'contact_id', 'status', 'difficulty']);
$input['business_id'] = $business_id;
$input['created_by'] = auth()->user()->id;
$input['manager_id'] = $manager_id;
$input['lead_id'] = $manager_id;
$input['start_date'] = $this->commonUtil->uf_date($request->input('start_date'), true);
$input['end_date'] = $this->commonUtil->uf_date($request->input('end_date'), true);
$input['progress_manual'] = ! empty($request->input('progress_manual'));
$input['progress'] = $request->input('progress', 0);
$input['is_locked'] = ! empty($request->input('is_locked'));
$project = PpProject::create($input);
$this->syncProjectRelations($project, $request);
$this->ppUtil->ensureUncategorisedMilestone($business_id, $project->id, auth()->user()->id);
$this->ppUtil->ensureTaskStatuses($business_id, auth()->user()->id);
$output = ['success' => true, 'msg' => __('lang_v1.success')];
} catch (\Exception $e) {
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
$output = ['success' => false, 'msg' => __('messages.something_went_wrong')];
}
return redirect()->action([self::class, 'show'], $project->id)->with('status', $output);
}
public function show($id)
{
$this->authorizeModule();
$business_id = request()->session()->get('user.business_id');
$project = PpProject::with(['customer', 'members', 'lead', 'milestones', 'tasks.status', 'tasks.assignees'])
->where('business_id', $business_id)
->findOrFail($id);
if (! $this->ppUtil->canAccessProject(auth()->user(), $business_id, $id)) {
abort(403, 'Unauthorized action.');
}
$tab = request()->get('tab', 'overview');
$can_manage = $this->ppUtil->canManageProject(auth()->user(), $business_id, $id);
$statuses = PpProject::statusDropdown();
$task_statuses = PpTaskStatus::where('business_id', $business_id)->orderBy('position')->get();
$milestones = PpMilestone::withCount('tasks')->where('project_id', $id)->orderBy('position')->get();
$users = User::forDropdown($business_id, false);
return view('professionalproject::project.show')
->with(compact('project', 'tab', 'can_manage', 'statuses', 'task_statuses', 'milestones', 'users'));
}
public function edit($id)
{
$this->authorizeModule();
if (! auth()->user()->can('professionalproject.edit_project')) {
abort(403, 'Unauthorized action.');
}
$business_id = request()->session()->get('user.business_id');
$project = PpProject::with(['categories', 'members', 'supervisors', 'parents'])
->where('business_id', $business_id)
->findOrFail($id);
if (! $this->ppUtil->canManageProject(auth()->user(), $business_id, $id)) {
abort(403, 'Unauthorized action.');
}
return view('professionalproject::project.edit')
->with($this->formData($business_id, $project));
}
public function update(Request $request, $id)
{
$this->authorizeModule();
if (! auth()->user()->can('professionalproject.edit_project')) {
abort(403, 'Unauthorized action.');
}
$business_id = $request->session()->get('user.business_id');
$project = PpProject::where('business_id', $business_id)->findOrFail($id);
if (! $this->ppUtil->canManageProject(auth()->user(), $business_id, $id)) {
abort(403, 'Unauthorized action.');
}
try {
$manager_id = $request->input('manager_id') ?: $project->lead_id;
$input = $request->only(['name', 'description', 'contact_id', 'status', 'difficulty', 'progress']);
$input['manager_id'] = $manager_id;
$input['lead_id'] = $manager_id;
$input['start_date'] = $this->commonUtil->uf_date($request->input('start_date'), true);
$input['end_date'] = $this->commonUtil->uf_date($request->input('end_date'), true);
$input['progress_manual'] = ! empty($request->input('progress_manual'));
$input['is_locked'] = ! empty($request->input('is_locked'));
$project->update($input);
$this->syncProjectRelations($project, $request);
if (! $project->progress_manual) {
$project->recalculateProgress();
}
$output = ['success' => true, 'msg' => __('lang_v1.success')];
} catch (\Exception $e) {
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
$output = ['success' => false, 'msg' => __('messages.something_went_wrong')];
}
if ($request->ajax()) {
return $output;
}
return redirect()->action([self::class, 'show'], $id)->with('status', $output);
}
public function destroy($id)
{
$this->authorizeModule();
if (! auth()->user()->can('professionalproject.delete_project')) {
abort(403, 'Unauthorized action.');
}
$business_id = request()->session()->get('user.business_id');
$project = PpProject::where('business_id', $business_id)->findOrFail($id);
try {
$project->delete();
$output = ['success' => true, 'msg' => __('lang_v1.success')];
} catch (\Exception $e) {
$output = ['success' => false, 'msg' => __('messages.something_went_wrong')];
}
return $output;
}
public function postStatus(Request $request, $id)
{
$this->authorizeModule();
$business_id = $request->session()->get('user.business_id');
$project = PpProject::where('business_id', $business_id)->findOrFail($id);
if (! $this->ppUtil->canManageProject(auth()->user(), $business_id, $id)) {
abort(403, 'Unauthorized action.');
}
$project->update(['status' => $request->input('status')]);
return ['success' => true, 'msg' => __('lang_v1.success')];
}
public function archive($id)
{
$this->authorizeModule();
$business_id = request()->session()->get('user.business_id');
$project = PpProject::where('business_id', $business_id)->findOrFail($id);
if (! $this->ppUtil->canManageProject(auth()->user(), $business_id, $id)) {
abort(403, 'Unauthorized action.');
}
$project->update(['is_archived' => true]);
return ['success' => true, 'msg' => __('professionalproject::lang.project_archived')];
}
}