first change

This commit is contained in:
2025-07-27 17:40:56 +05:45
commit f8b9a6725b
3152 changed files with 229528 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\PMS\Exports;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Concerns\FromView;
use Modules\PMS\Repositories\TaskRepository;
class TaskExport implements FromView
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function view(): View
{
$filters = $this->request;
$tasks = (new TaskRepository())->findAll($filters);
return view('pms::export.tasks', [
'tasks' => $tasks,
]);
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class CommentController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('pms::index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('pms::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('pms::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('pms::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
}

View File

@@ -0,0 +1,187 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Modules\PMS\Models\KanbanColumn;
use Modules\PMS\Repositories\KanbanColumnInterface;
class KanbanColumnController extends Controller
{
/**
* Display a listing of the resource.
*/
private $kanbanColumn;
public function __construct(KanbanColumnInterface $kanbanColumn)
{
$this->kanbanColumn = $kanbanColumn;
}
public function index()
{
$data['editable'] = false;
$data['title'] = 'Kanban Column Lists';
$data['kanbanColumnLists'] = $this->kanbanColumn->findAll();
return view('pms::kanbanColumn.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'name' => 'required|unique:kanban_columns,name',
'category' => 'required|in:pending,backlog,in_progress,completed,on_hold,cancelled'
]);
$request->merge([
'position' => KanbanColumn::max('position') + 1 ?? 1,
]);
if ($validator->fails()) {
if ($request->ajax()) {
return response()->json([
'status' => false,
'msg' => $validator->errors(),
], 422);
}
$errors = implode(', ', $validator->errors()->all());
flash()->addError($errors);
return redirect()->back();
}
try {
$taskModel = $this->kanbanColumn->create($request->all());
if ($request->ajax()) {
return response()->json([
'status' => true,
'data' => $taskModel,
'msg' => 'Task Created Created',
]);
}
flash()->addSuccess('Kanban Column Created');
return redirect()->back();
} catch (\Throwable $th) {
if ($request->ajax()) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
]);
}
flash()->addError($th->getMessage());
return redirect()->back()->withError($th->getMessage());
}
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Kanban Column';
$data['kanbanColumn'] = $this->kanbanColumn->getKanbanColumnById($id);
return view('pms::kanbanColumn.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
if (request()->ajax()) {
$data['editable'] = true;
$data['kanbanColumn'] = $this->kanbanColumn->getKanbanColumnById($id);
return view('pms::kanbanColumn.partials.action', $data);
}
$data['editable'] = true;
$data['title'] = 'Kanban Column Lists';
$data['kanbanColumn'] = $this->kanbanColumn->getKanbanColumnById($id);
$data['kanbanColumnLists'] = $this->kanbanColumn->findAll();
return view('pms::kanbanColumn.index', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$request->validate([
'position' => 'required|integer',
'name' => 'required|unique:kanban_columns,name,' . $id,
'category' => 'required|in:pending,backlog,in_progress,completed,on_hold,cancelled'
]);
try {
$kanbanColumn = $this->kanbanColumn->getKanbanColumnById($id);
$items = KanbanColumn::whereNot('id', $kanbanColumn->id)->orderBy('position')->get();
DB::transaction(function () use ($kanbanColumn, $items, $request) {
$items->splice($request->position - 1, 0, [$kanbanColumn]);
$items = $items->values();
foreach ($items as $index => $item) {
$item->position = $index + 1;
$item->save();
}
$kanbanColumn->update($request->only(['name', 'color', 'category']));
});
flash()->success('Kanban Column Updated Successfully');
return redirect()->back();
} catch (\Throwable $th) {
flash()->error($th->getMessage());
return redirect()->back()->withInput();
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
DB::transaction(function () use ($id) {
$column = KanbanColumn::findOrFail($id);
$column->delete();
$items = KanbanColumn::where('position', '>', $column->position)
->orderBy('position')
->get();
foreach ($items as $item) {
$item->position = $item->position - 1;
$item->save();
}
});
flash()->success('Column has been deleted');
return redirect()->back();
} catch (\Throwable $th) {
flash()->error($th->getMessage());
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class PMSController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('pms::index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('pms::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('pms::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('pms::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Validator;
use Modules\PMS\Models\TaskCategory;
use Modules\PMS\Repositories\TaskCategoryInterface;
class TaskCategoryController extends Controller
{
/**
* Display a listing of the resource.
*/
private $taskCategory;
public function __construct(TaskCategoryInterface $taskCategory)
{
$this->taskCategory = $taskCategory;
}
public function index()
{
$data['title'] = 'Task Category Lists';
$data['taskCategoryLists'] = $this->taskCategory->findAll();
return view('pms::task-category.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Task Category';
$data['editable'] = false;
$data['status'] = TaskCategory::STATUS;
return view('pms::task-category.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required',
]);
if ($validator->fails()) {
if ($request->ajax()) {
return response()->json([
'status' => false,
'msg' => $validator->errors(),
], 422);
}
return to_route('taskCategory.create')->withError($validator->errors()->all());
}
try {
if (!$request->has('status')) {
$request->merge(['status' => 11]);
}
$taskModel = $this->taskCategory->create($request->all());
if ($request->ajax()) {
return response()->json([
'status' => true,
'data' => $taskModel,
'msg' => 'Task Created Created',
]);
}
return redirect()->route('task.index')->withSucess('Task Category Created');
} catch (\Throwable $th) {
if ($request->ajax()) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
]);
}
return redirect()->route('task.index')->withError($th->getMessage());
}
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Task Category';
$data['taskCategory'] = $this->taskCategory->getTaskCategoryById($id);
return view('pms::task-category.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
try {
$data['title'] = 'Edit Task Category';
$data['editable'] = true;
$data['status'] = TaskCategory::STATUS;
$data['taskCategory'] = $this->taskCategory->getTaskCategoryById($id);
} catch (\Throwable $th) {
flash()->error($th->getMessage());
}
return view('pms::task-category.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
try {
$this->taskCategory->update($id, $request->except(['_method', '_token']));
flash()->success('Task Category Updated Successfully');
} catch (\Throwable $th) {
flash()->error($th->getMessage());
}
return redirect()->route('task.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->taskCategory->delete($id);
flash()->success('Task Category Deleted Successfully');
} catch (\Throwable $th) {
flash()->error($th->getMessage());
}
}
}

View File

@@ -0,0 +1,627 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Employee\Models\Employee;
use Modules\Employee\Interfaces\EmployeeInterface;
use Modules\PMS\Exports\TaskExport;
use Modules\PMS\Models\KanbanColumn;
use Modules\PMS\Models\Task;
use Modules\PMS\Repositories\KanbanColumnInterface;
use Modules\PMS\Repositories\TaskCategoryInterface;
use Modules\PMS\Repositories\TaskInterface;
use Modules\Product\Interfaces\ProductInterface;
use Modules\Template\Emails\SendMail;
use Modules\Template\Repositories\TemplateInterface;
use Modules\Template\Repositories\TemplateRepository;
use Modules\User\Services\UserService;
class TaskController extends Controller
{
private $task;
private $project;
private $employee;
private $taskCategory;
private $product;
private $kanbanColumn;
private $template;
public function __construct(
TaskInterface $task,
EmployeeInterface $employee,
TaskCategoryInterface $taskCategory,
KanbanColumnInterface $kanbanColumn,
ProductInterface $product,
TemplateInterface $template,
) {
$this->task = $task;
$this->employee = $employee;
$this->taskCategory = $taskCategory;
$this->product = $product;
$this->kanbanColumn = $kanbanColumn;
$this->template = $template;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$filters = $request->all();
$data['title'] = 'Task List';
$data['editable'] = false;
$data['tasks'] = $this->task->findAll($filters);
$data['products'] = $this->product->findAll();
$data['taskCategories'] = $this->taskCategory->findAll();
$data['memberList'] = $this->employee->pluck();
$data['statusList'] = $this->kanbanColumn->pluck(function ($query) {
$query->orderBy('position');
});
return view('pms::task.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Task';
$data['editable'] = false;
$data['status'] = $this->kanbanColumn->pluck(function ($query) {
$query->orderBy('position');
});
$data['priority'] = Task::PRIORITY;
$data['product'] = $this->product->pluck();
$data['memberList'] = $this->employee->pluck();
$data['categoryList'] = $this->taskCategory->pluck();
return view('pms::task.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$validator = Validator::make($request->all(), [
'title' => 'required|string|max:255',
]);
if ($validator->fails()) {
return to_route('task.create')->withError($validator->errors()->all());
}
$inputData = $request->except(['_token', 'file']);
$task = $this->task->create($inputData);
$statusName = $this->task->getTaskById($task->id)->statusName['status'];
if ($request->hasFile('file')) {
$path = 'uploads/task';
$inputData['file'] = uploadImage($request->file, $path);
$task->documents()->updateOrCreate([
'documentable_id' => $task->id,
'documentable_type' => 'Modules\PMS\Models\Task',
], [
'document_name' => 'Task Files',
'document_path' => $inputData['file'],
]);
}
$createdBy = UserService::getUserById($task->createdby);
$user = $task->assignedUser;
if (config('app.send_mail')) {
$templateModel = (new TemplateRepository())->where(['alias' => 'task-assignee-template'])->first();
$message = $templateModel->message;
$message = str_replace('#image', asset('storage/' . setting('logo_pic')), $message);
$message = str_replace('#task_subject', $task->title, $message);
$message = str_replace('#assigned_by', $createdBy->name, $message);
$message = str_replace('#task_desc', $task->desc, $message);
$message = str_replace('#task_deadline', $task->due_date, $message);
$data = [
'subject' => 'New Task Created',
'body' => $message,
];
Mail::to($user)->send(new SendMail($data));
}
$priorityLabel = Task::PRIORITY[$inputData['priority']] ?? 'Unknown';
$this->product->getProductById($inputData['product_id'])->client->createLog([
'title' => 'Task Created',
'data' => "Task titled '{$inputData['title']}' with an status '{$statusName}' has been created.",
]);
foreach ($inputData['assigned_id'] as $employeeId) {
$employee = $this->employee->getEmployeeById($employeeId);
if (is_iterable($employee)) {
foreach ($employee as $emp) {
$emp->createLog([
'title' => 'Task Has Been Assigned',
'data' => "Task titled '{$inputData['title']}' with status '{$statusName}' and priority '{$priorityLabel}' has been created.",
]);
}
} else {
$employee->user->createLog([
'title' => 'Task Has Been Assigned',
'data' => "Task titled '{$inputData['title']}' with status '{$statusName}' and priority '{$priorityLabel}' has been created.",
]);
}
}
return redirect()->route('task.index')->withSucess('Task Created');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Task';
$data['task'] = $this->task->getTaskById($id);
$data['time'] = $data['task']->latest_task_time;
$data['clientName'] = $this->product->getProductById($data['task']->product_id)->client->name;
$data['status'] = $this->kanbanColumn->pluck(function ($query) {
$query->orderBy('position');
});
$data['template'] = $this->template->pluck();
return view('pms::task.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Task';
$data['editable'] = true;
$data['task'] = $this->task->getTaskById($id);
$data['status'] = $this->kanbanColumn->pluck(function ($query) {
$query->orderBy('position');
});
$data['priority'] = Task::PRIORITY;
$data['categoryList'] = $this->taskCategory->pluck();
$data['product'] = $this->product->pluck();
$data['memberList'] = $this->employee->pluck();
return view('pms::task.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$statusName = $this->task->getTaskById($id)->statusName['status'];
$allAssignedIds = $request->assigned_id['ids'] ?? [];
$currentAssignedIds = $this->task->getTaskById($id)->assigned_id['ids'] ?? [];
$newAssignedEmployees = array_diff($allAssignedIds, $currentAssignedIds);
$validator = Validator::make($request->all(), [
'title' => 'required|string|max:255',
]);
if ($validator->fails()) {
return to_route('task.create')->withError($validator->errors()->all());
}
$inputData = $request->except(['_method', '_token']);
try {
// Updating Task
$task = $this->task->update($id, $inputData);
// Handling File Upload
if ($request->hasFile('file')) {
$path = 'uploads/task';
$inputData['file'] = uploadImage($request->file, $path);
$task->documents()->updateOrCreate(
[
'documentable_id' => $task->id,
'documentable_type' => 'Modules\Invoice\Models\ReceivedInvoice',
],
[
'document_name' => 'Task Files',
'document_path' => $inputData['file'],
]
);
// Log for file upload
foreach ($currentAssignedIds as $empId) {
$employee = Employee::find($empId);
if ($employee) {
$employee->user->createLog([
'title' => 'Document Added',
'data' => "A new document has been added to the task titled '{$task->title}'.",
]);
} else {
flash()->addError("Employee with ID {$empId} not found while creating log for file upload.");
}
}
$client = $this->product->getProductById($inputData['product_id'])->client;
$client->createLog([
'title' => 'Document Added',
'data' => "A new document has been added to the task titled '{$task->title}'.",
]);
}
// Creating Logs for Client
$priority = Task::PRIORITY[$inputData['priority']] ?? 'Unknown';
$client = $this->product->getProductById($inputData['product_id'])->client;
if ($client) {
$client->createLog([
'title' => 'Task Updated',
'data' => "Task titled '{$inputData['title']}' with status '{$statusName}' and priority '{$priority}' has been created.",
]);
} else {
flash()->addError("Client not found for product ID {$inputData['product_id']}.");
}
// Creating Logs for New Employees
if ($newAssignedEmployees) {
foreach ($newAssignedEmployees as $empId) {
$employee = Employee::find($empId);
if ($employee) {
$employee->user->createLog([
'title' => 'Task Assigned',
'data' => "Task titled '{$inputData['title']}' with status '{$statusName}' and priority '{$priority}' has been created.",
]);
} else {
flash()->addError("Employee with ID {$empId} not found while creating assignment log.");
}
}
}
// Creating Logs for Current Employees
if ($currentAssignedIds) {
foreach ($currentAssignedIds as $empId) {
$employee = Employee::find($empId);
if ($employee) {
$employee->user->createLog([
'title' => 'Task Updated',
'data' => "Task titled '{$inputData['title']}' with status '{$statusName}' and priority '{$priority}' has been created.",
]);
} else {
flash()->addError("Employee with ID {$empId} not found while creating update log.");
}
}
}
return redirect()->route('task.index')->withSuccess('Task updated successfully.');
} catch (\Throwable $th) {
flash()->addError("Error while updating task: {$th->getMessage()}");
return redirect()->route('task.index')->withErrors('Something went wrong, please try again.');
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->task->delete($id);
flash()->success('Task Deleted Succesfully');
} catch (\Throwable $th) {
flash()->error($th->getMessage());
}
return response()->json(['status' => true, 'message' => 'Task Delete Succesfully']);
}
public function kanban(Request $request)
{
$data['title'] = 'Kanban Board';
$data['editable'] = false;
$data['statusList'] = $this->kanbanColumn->pluck(function ($query) {
$query->orderBy('position');
});
$data['memberList'] = $this->employee->pluck();
$data['columnsWithTasks'] = KanbanColumn::with([
'tasks' => function ($query) use ($request) {
$query->whereNull('parent_id');
if ($request->filled('search')) {
$search = $request->search;
$query->where('title', 'LIKE', "%$search%");
}
if ($request->filled('status')) {
$query->where('status', $request->status);
}
if ($request->filled('priority')) {
$query->where('priority', $request->priority);
}
if ($request->filled('date')) {
$dates = explode('to', $request->date);
$startDate = trim($dates[0]);
$endDate = isset($dates[1]) ? trim($dates[1]) : $startDate; // Handle single date or range
$query->whereBetween('start_date', [$startDate, $endDate]);
}
if ($request->filled('assigned_to')) {
$query->whereJsonContains("assigned_id->ids", (string) $request->assigned_to);
}
if (auth()->user()->hasRole('employee')) {
$assignedId = (string) auth()->user()->employee_id;
$query->whereJsonContains('assigned_id->ids', $assignedId);
}
$query->with('assignedUser:id,first_name,middle_name,last_name,profile_picture');
},
])
// ->withCount('tasks')
->orderBy('position')
->get();
// dd($data['columnsWithTasks']->toArray());
$data['columnLists'] = KanbanColumn::select(DB::raw("id, LOWER(REPLACE(name, ' ', '-')) as slug"))
->pluck('slug', 'id');
$data['taskCategories'] = $this->taskCategory->findAll();
return view('pms::task.kanban', $data);
}
public function changeStatus(Request $request)
{
try {
$taskModel = $this->task->getTaskById($request->id);
$prevTaskStatus = Task::findOrFail($request->id)->statusName['status'];
$client = $this->product->getProductById($taskModel->product_id)->client;
$taskModel->status = $request->changeStatus;
$taskModel->save();
$employeeIds = $taskModel->assigned_id['ids'];
// Creating logs for the client
$client->createLog([
'title' => 'Task Status Changed',
'data' => "Task Title: {$taskModel->title} | Status: From {$prevTaskStatus} to {$taskModel->statusName['status']}",
]);
// Creating logs for each employee assigned to the task
foreach ($employeeIds as $emp) {
$employee = Employee::findOrFail($emp);
$employee->user->createLog([
'title' => 'Task Status Changed',
'data' => "Task Title: {$taskModel->title} | Status: From {$prevTaskStatus} to {$taskModel->statusName['status']}",
]);
}
return response()->json([
'status' => true,
'msg' => 'Status Changed',
], 200);
} catch (\Throwable $th) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
], 400);
}
}
public function fetchComment($task_id)
{
$data['task'] = $this->task->getTaskById($task_id);
return view('pms::task.partials.comment', $data);
}
public function storeComment(Request $request)
{
$request->validate([
'content' => 'required',
]);
$task = $this->task->getTaskById($request->task_id);
$task->comments()->create(['content' => $request->content, 'comment_by' => Auth::id()]);
$user = $task->assignedUser;
if (config('app.send_mail')) {
$templateModel = (new TemplateRepository())->where(['alias' => 'comment-template'])->first();
$message = $templateModel->message;
$message = str_replace('#image', asset('storage/' . setting('logo_pic')), $message);
$message = str_replace('#content', $request->content, $message);
$data = [
'subject' => 'New Comment Added on Your Task',
'body' => $message,
];
Mail::to($user)->send(new SendMail($data));
}
// Creating Logs for Client and Employees
$employeeIds = $this->task->getTaskById($request->task_id)->assigned_id['ids'];
$commentPreview = substr($request->content, 0, 50);
if (strlen($request->content) > 50) {
$commentPreview .= '...';
}
$task->product->client->createLog([
'title' => 'Comment Added in Task: "' . $task->title . '"',
'data' => 'Comment: ' . $commentPreview,
]);
foreach ($employeeIds as $emp) {
$employee = Employee::findOrFail($emp);
$employee->user->createLog([
'title' => 'New Comment Added in Task: "' . $task->title . '"',
'data' => 'Comment: ' . $commentPreview,
]);
}
return response()->json([
'status' => true,
'msg' => 'Comment Store',
], 200);
}
public function uploadFile(Request $request)
{
$task = $this->task->getTaskById($request->task_id);
$client = $task->product->client;
if ($request->hasFile('file')) {
$path = 'uploads/task';
$fileName = $request->file->getClientOriginalName();
$filePath = uploadImage($request->file, $path);
$task->documents()->create(['document_name' => $fileName, 'document_path' => $filePath]);
}
// Storing Logs for Client and Employees
$client->createLog([
'title' => "Document Uploaded",
'data' => "For Task Title '{$task->title}'",
]);
foreach ($task->assignedUser as $employee) {
$employee->user->createLog([
'title' => "Document Uploaded",
'data' => "For Task Title '{$task->title}'",
]);
}
return response()->json([
'status' => true,
'msg' => 'File Upload',
], 200);
}
public function storeSubTask(Request $request)
{
try {
$request->merge(['status' => 10]);
$request->validate([
'title' => 'required',
'start_date' => 'required',
]);
$task = $this->task->create($request->all());
// Creating Logs for Client and Employees
$employeeIds = $this->task->getTaskById($request->parent_id)->assigned_id['ids'];
$taskTitle = $this->task->getTaskById($request->parent_id)->title;
$client = $this->product->getProductById($this->task->getTaskById($request->parent_id)->product_id)->Client;
$client->createLog([
'title' => "Sub-Task Added.",
'data' => "For Task Title '{$taskTitle}'",
]);
foreach ($employeeIds as $emp) {
$employee = Employee::findOrFail($emp);
$employee->user->createLog([
'title' => "Sub-Task Added.",
'data' => "For Task Title '{$taskTitle}'",
]);
}
return redirect()->back()->withSucess('Sub Task Created');
} catch (\Throwable $th) {
return redirect()->back()->withError($th->getMessage());
}
}
public function gantChart()
{
$data['title'] = 'Gantt Chart';
return view('pms::task.gantt.chart', $data);
}
public function getGantChartTask(Request $request)
{
// try {
$filters = $request->all();
$tasks = $this->task->getAllTasks($filters);
// dd($tasks->toArray());
$finalArr = [];
foreach ($tasks as $key => $task) {
$finalArr[] = [
'taskID' => (string) $task->id,
'taskName' => $task->title . ' (' . $task->project?->project_name . ')',
'resource' => $task->title,
'startDate' => $task->start_date,
'endDate' => $task->due_date,
'duration' => null,
'percentComplete' => null,
'dependencies' => null,
];
if (isset($task['subTask']) && !empty($task['subTask'])) {
foreach ($task['subTask'] as $sub_task) {
array_push($finalArr, [
'taskID' => (string) $sub_task->id,
'taskName' => $sub_task->title,
'resource' => $sub_task->title,
'startDate' => $sub_task->start_date,
'endDate' => $sub_task->due_date,
'duration' => null,
'percentComplete' => null,
'dependencies' => (string) $task->id,
]);
}
}
}
return response()->json([
'status' => true,
'data' => $finalArr,
'msg' => 'Data fetched',
], 200);
// } catch (\Throwable $th) {
// return response()->json([
// 'status' => false,
// 'msg' => $th->getMessage(),
// ], 400);
// }
}
public function export(Request $request)
{
return Excel::download(new TaskExport($request), 'tasks.xlsx');
}
public function sendMail(Request $request)
{
try {
$task = $this->task->getTaskById($request->task_id);
$message = $request->message;
// $message = str_replace('#name', $task->name, $message);
// $message = str_replace('#email', $task->email, $message);
$data = [
'subject' => $request->subject,
'body' => $message,
];
Mail::to($task->assignedUser)->send(new SendMail($data));
return response()->json([
'status' => true,
'msg' => 'Mail send successfully',
], 200);
} catch (\Throwable $th) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
], 500);
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\PMS\Repositories\TaskInterface;
use Modules\PMS\Repositories\TaskTimeInterface;
class TaskTimeController extends Controller
{
private $task;
private $tasktime;
public function __construct(
TaskInterface $task,
TaskTimeInterface $tasktime
) {
$this->task = $task;
$this->tasktime = $tasktime;
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
// $request->validate([
// 'start_time' => 'required',
// ]);
$taskModel = $this->task->getTaskById($request->task_id);
$taskTimeModel = $this->tasktime->getLatestTimeByTaskId($request->task_id);
$start_time = is_null($taskTimeModel) ? '00:00:00' : $taskTimeModel->end_time;
$taskModel->taskTime()->create(['start_time' => $start_time, 'end_time' => $request->time]);
return response()->json([
'status' => true,
'msg' => 'Time Store',
], 200);
} catch (\Throwable $th) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
], 400);
}
}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('pms::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('pms::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
}

View File

@@ -0,0 +1,171 @@
<?php
namespace Modules\PMS\Http\Controllers;
use App\Http\Controllers\Controller;
use Auth;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\PMS\Models\Ticket;
use Modules\PMS\Repositories\TicketInterface;
use Modules\Admin\Services\AdminService;
class TicketController extends Controller
{
private $ticketRepository;
private $adminService;
public function __construct(TicketInterface $ticketRepository, AdminService $adminService)
{
$this->adminService = $adminService;
$this->ticketRepository = $ticketRepository;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$data['title'] = 'Ticket List';
$data['tickets'] = $this->ticketRepository->findAll();
$data['statusList'] = Ticket::STATUS;
return view('pms::ticket.index', $data);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$data['title'] = 'Create Ticket';
$data['statusList'] = Ticket::STATUS;
$data['priority'] = Ticket::PRIORITY;
$data['ticketType'] = Ticket::TICKET_TYPE;
$data['departmentList'] = $this->adminService->pluckDepartments();
return view('pms::ticket.create', $data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$inputData = $request->all();
$ticket = $this->ticketRepository->create($inputData);
if ($request->hasFile('file')) {
$path = 'uploads/task';
$inputData['file'] = uploadImage($request->file, $path);
$ticket->documents()->updateOrCreate([
'documentable_id' => $ticket->id,
'documentable_type' => 'Modules\PMS\Models\Ticket',
], [
'document_name' => 'Ticket Files',
'document_path' => $inputData['file'],
]);
}
toastr()->success('Ticket Created Succesfully');
return redirect()->route('ticket.index');
}
/**
* Show the specified resource.
*/
public function show($id)
{
$data['title'] = 'View Ticket';
$data['tickets'] = $this->ticketRepository->getTicketById($id);
$data['status'] = Ticket::STATUS;
$data['priority'] = Ticket::PRIORITY;
$data['ticketType'] = Ticket::TICKET_TYPE;
return view('pms::ticket.show', $data);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$data['title'] = 'Edit Ticket';
$data['ticket'] = $this->ticketRepository->getTicketById($id);
return view('pms::ticket.edit', $data);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id): RedirectResponse
{
$inputData = $request->except(['_method', '_token']);
try {
$this->ticketRepository->update($id, $inputData);
toastr()->success('Ticket Update Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return redirect()->route('ticket.index');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->ticketRepository->delete($id);
toastr()->success('Ticket Deleted Succesfully');
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
}
public function storeComment(Request $request)
{
$request->validate([
'content' => 'required',
]);
$ticket = $this->ticketRepository->getTicketById($request->tickets_id);
$ticket->comments()->create(['content' => $request->content, 'comment_by' => Auth::id()]);
return redirect()->back();
}
public function uploadFile(Request $request)
{
$task = $this->ticketRepository->getTicketById($request->task_id);
if ($request->hasFile('file')) {
$path = 'uploads/ticket1';
$fileName = $request->file->getClientOriginalName();
$filePath = uploadImage($request->file, $path);
$task->documents()->create(['document_name' => $fileName, 'document_path' => $filePath]);
}
return response()->json([
'status' => true,
'msg' => 'File Upload',
], 200);
}
public function changeStatus(Request $request)
{
try {
$taskModel = $this->ticketRepository->getTicketById($request->id);
$taskModel->status = $request->changeStatus;
$taskModel->save();
return response()->json([
'status' => true,
'msg' => 'Status Changed',
], 200);
} catch (\Throwable $th) {
return response()->json([
'status' => false,
'msg' => $th->getMessage(),
], 400);
}
}
}

View File

View File

@@ -0,0 +1,26 @@
<?php
namespace Modules\PMS\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ClientRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
//
];
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
}

View File

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\PMS\Models;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* The attributes that are mass assignable.
*/
protected $fillable = ['content', 'comment_by'];
// protected $casts = [
// 'created_at' => 'datetime',
// ];
protected function createdAtFormatted(): Attribute
{
return Attribute::make(
get: fn($value, $attributes) => Carbon::parse($attributes['created_at'])->format('d, M Y H:i'),
);
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function user()
{
return $this->belongsTo(User::class, 'comment_by');
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Modules\PMS\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\PMS\Database\Factories\KanbanColumnFactory;
class KanbanColumn extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*/
protected $guarded = [];
public function tasks()
{
return $this->hasMany(Task::class,'status');
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\PMS\Models;
use App\Traits\CreatedUpdatedBy;
use App\Traits\StatusTrait;
use Illuminate\Database\Eloquent\Model;
use Modules\Admin\Models\Department;
use Modules\Employee\Models\Employee;
class Project extends Model
{
use StatusTrait, CreatedUpdatedBy;
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $table = 'tbl_projects';
protected $fillable = ['project_code', 'project_name', 'client_id', 'department_id', 'project_category_id', 'members_id', 'start_date', 'end_date', 'summary', 'key_notes', 'status', 'createdBy', 'updatedBy'];
protected $appends = ['status_name'];
protected $casts = [
'members_id' => 'json',
];
const CATEGORY = [
10 => 'Vue',
11 => 'Laravel',
];
public function client()
{
return $this->belongsTo(Client::class, 'client_id');
}
public function projectCategory()
{
return $this->belongsTo(ProjectCategory::class, 'project_category_id');
}
public function members()
{
return $this->belongsToJson(Employee::class, 'members_id->id');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Modules\PMS\Models;
use App\Traits\CreatedUpdatedBy;
use App\Traits\StatusTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectCategory extends Model
{
use HasFactory, StatusTrait, CreatedUpdatedBy;
public $appends = ['status_name'];
protected $table = 'tbl_project_categories';
protected $fillable = ['title', 'desc'];
}

View File

@@ -0,0 +1,117 @@
<?php
namespace Modules\PMS\Models;
use App\Models\Document;
use App\Traits\CreatedUpdatedBy;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Modules\Employee\Models\Employee;
use Modules\Product\Models\Product;
class Task extends Model
{
use CreatedUpdatedBy;
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $table = 'tbl_tasks';
protected $guarded = [];
protected $appends = ['status_name', 'priority_status'];
// const CATEGORY = [
// 10 => 'Vue',
// 11 => 'Laravel',
// ];
const PRIORITY = [
10 => 'High',
11 => 'Meduim',
12 => 'Low',
];
protected $casts = [
'assigned_id' => 'json',
];
protected function statusName(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
$kanbanColumn = KanbanColumn::where('id',$attributes['status'])->first();
return collect([
'status' => $kanbanColumn->name ?? 'N/A',
'color' => $kanbanColumn->name ?? '#808080'
]);
},
set: fn($value) => $value,
);
}
protected function priorityStatus(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['priority']) {
case '10':
return '<span class="badge bg-danger">' . self::PRIORITY[$attributes['priority']] . '</span>';
case '11':
return '<span class="badge bg-info">' . self::PRIORITY[$attributes['priority']] . '</span>';
case '12':
return '<span class="badge bg-primary">' . self::PRIORITY[$attributes['priority']] . '</span>';
default:
# code...
break;
}
},
set: fn($value) => $value,
);
}
public function product()
{
return $this->belongsTo(Product::class, 'product_id');
}
public function subTask()
{
return $this->hasMany(Task::class, 'parent_id');
}
public function taskTime()
{
return $this->hasMany(TaskTime::class, 'task_id');
}
public function latest_task_time()
{
return $this->hasOne(TaskTime::class, 'task_id')->latestOfMany();
}
public function assignedUser()
{
return $this->belongsToJson(Employee::class, 'assigned_id->ids');
}
public function taskCategory()
{
return $this->belongsTo(TaskCategory::class, 'task_category_id');
}
public function documents(): MorphMany
{
return $this->morphMany(Document::class, 'documentable');
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function column()
{
return $this->belongsTo(KanbanColumn::class, 'status');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\PMS\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\PMS\Database\Factories\TaskCategoryFactory;
use App\Traits\StatusTrait;
use App\Traits\CreatedUpdatedBy;
class TaskCategory extends Model
{
use HasFactory, StatusTrait, CreatedUpdatedBy;
public $appends = ['status_name'];
/**
* The attributes that are mass assignable.
*/
protected $table = 'tbl_task_categories';
protected $fillable = ['title', 'desc'];
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\PMS\Models;
use Illuminate\Database\Eloquent\Model;
class TaskTime extends Model
{
/**
* The attributes that are mass assignable.
*/
protected $table = 'tbl_task_times';
protected $fillable = ['task_id', 'start_time', 'end_time'];
public function task()
{
return $this->belongsTo(Task::class, 'task_id');
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Modules\PMS\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Document;
use Modules\Admin\Models\Department;
use Modules\Employee\Models\Employee;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Ticket extends Model
{
/**
* The attributes that are mass assignable.
*/
protected $table = 'tbl_tickets';
// protected $fillable = ['subject', 'employee_id', 'department_id', 'assign_group_id', 'project_id', 'desc', 'file', 'ticket_type', 'status', 'priority'];
protected $guarded = [];
protected $appends = ['status_name', 'priority_status', 'ticket_type'];
const STATUS = [
10 => 'Pending',
11 => 'Approved',
12 => 'Rejected',
];
const PRIORITY = [
10 => 'High',
11 => 'Meduim',
12 => 'Low',
];
const TICKET_TYPE = [
11 => 'Management',
12 => 'Boxes',
13 => 'Assets'
];
protected function statusName(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['status']) {
case '10':
$color = 'danger';
break;
case '11':
$color = 'info';
break;
case '12':
$color = 'primary';
break;
case '13':
$color = 'warning';
break;
case '14':
$color = 'success';
break;
default:
$color = 'light';
break;
}
return collect([
'status' => self::STATUS[$attributes['status']],
'color' => $color]);
},
set: fn($value) => $value,
);
}
protected function priorityStatus(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['priority']) {
case '10':
return '<span class="badge bg-danger">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
case '11':
return '<span class="badge bg-info">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
case '12':
return '<span class="badge bg-primary">' . self::PRIORITY[$attributes['priority']] . '</span>';
break;
default:
# code...
break;
}
},
set: fn($value) => $value,
);
}
protected function ticketType(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes) {
switch ($attributes['ticket_type']) {
case '11':
return '<span class="badge bg-info">' . self::TICKET_TYPE[$attributes['ticket_type']] . '</span>';
break;
case '12':
return '<span class="badge bg-info">' . self::TICKET_TYPE[$attributes['ticket_type']] . '</span>';
break;
case '13':
return '<span class="badge bg-info">' . self::TICKET_TYPE[$attributes['ticket_type']] . '</span>';
break;
default:
# code...
break;
}
},
set: fn($value) => $value,
);
}
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
public function employee()
{
return $this->belongsTo(Employee::class, 'employee_id');
}
public function department()
{
return $this->belongsTo(Department::class, 'department_id')->withDefault();
}
public function documents(): MorphMany
{
return $this->morphMany(Document::class, 'documentable');
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}

View File

View File

View File

@@ -0,0 +1,129 @@
<?php
namespace Modules\PMS\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Modules\PMS\Repositories\KanbanColumnInterface;
use Modules\PMS\Repositories\KanbanColumnRepository;
use Modules\PMS\Repositories\TaskCategoryInterface;
use Modules\PMS\Repositories\TaskCategoryRepository;
use Modules\PMS\Repositories\TaskInterface;
use Modules\PMS\Repositories\TaskRepository;
use Modules\PMS\Repositories\TaskTimeInterface;
use Modules\PMS\Repositories\TaskTimeRepository;
use Modules\PMS\Repositories\TicketInterface;
use Modules\PMS\Repositories\TicketRepository;
class PMSServiceProvider extends ServiceProvider
{
protected string $moduleName = 'PMS';
protected string $moduleNameLower = 'pms';
/**
* Boot the application events.
*/
public function boot(): void
{
$this->registerCommands();
$this->registerCommandSchedules();
$this->registerTranslations();
$this->registerConfig();
$this->registerViews();
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->app->bind(KanbanColumnInterface::class, KanbanColumnRepository::class);
$this->app->bind(TaskCategoryInterface::class, TaskCategoryRepository::class);
$this->app->bind(TicketInterface::class, TicketRepository::class);
$this->app->bind(TaskInterface::class, TaskRepository::class);
$this->app->bind(TaskTimeInterface::class, TaskTimeRepository::class);
$this->app->register(RouteServiceProvider::class);
}
/**
* Register commands in the format of Command::class
*/
protected function registerCommands(): void
{
// $this->commands([]);
}
/**
* Register command Schedules.
*/
protected function registerCommandSchedules(): void
{
// $this->app->booted(function () {
// $schedule = $this->app->make(Schedule::class);
// $schedule->command('inspire')->hourly();
// });
}
/**
* Register translations.
*/
public function registerTranslations(): void
{
$langPath = resource_path('lang/modules/' . $this->moduleNameLower);
if (is_dir($langPath)) {
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
$this->loadJsonTranslationsFrom($langPath);
} else {
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
}
}
/**
* Register config.
*/
protected function registerConfig(): void
{
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower . '.php')], 'config');
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
}
/**
* Register views.
*/
public function registerViews(): void
{
$viewPath = resource_path('views/modules/' . $this->moduleNameLower);
$sourcePath = module_path($this->moduleName, 'resources/views');
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower . '-module-views']);
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
$componentNamespace = str_replace('/', '\\', config('modules.namespace') . '\\' . $this->moduleName . '\\' . ltrim(config('modules.paths.generator.component-class.path'), config('modules.paths.app_folder', '')));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [];
}
private function getPublishableViewPaths(): array
{
$paths = [];
foreach (config('view.paths') as $path) {
if (is_dir($path . '/modules/' . $this->moduleNameLower)) {
$paths[] = $path . '/modules/' . $this->moduleNameLower;
}
}
return $paths;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Modules\PMS\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*/
public function boot(): void
{
parent::boot();
}
/**
* Define the routes for the application.
*/
public function map(): void
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*/
protected function mapWebRoutes(): void
{
Route::middleware('web')->group(module_path('PMS', '/routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*/
protected function mapApiRoutes(): void
{
Route::middleware('api')->prefix('api')->name('api.')->group(module_path('PMS', '/routes/api.php'));
}
}

View File

View File

@@ -0,0 +1,14 @@
<?php
namespace Modules\PMS\Repositories;
interface KanbanColumnInterface
{
public function findAll();
public function getKanbanColumnById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck(callable $query = null);
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\PMS\Repositories;
use Modules\PMS\Models\KanbanColumn;
class KanbanColumnRepository implements KanbanColumnInterface
{
public function findAll()
{
return KanbanColumn::orderBy('position')->get();
}
public function getKanbanColumnById($TaskCategoryId)
{
return KanbanColumn::findOrFail($TaskCategoryId);
}
public function delete($TaskCategoryId)
{
KanbanColumn::destroy($TaskCategoryId);
}
public function create($TaskCategoryDetails)
{
return KanbanColumn::create($TaskCategoryDetails);
}
public function update($TaskCategoryId, array $newDetails)
{
return KanbanColumn::whereId($TaskCategoryId)->update($newDetails);
}
public function pluck(callable $query = null)
{
$baseQuery = KanbanColumn::query();
if (is_callable($query)) {
$query($baseQuery);
}
return $baseQuery->pluck('name', 'id')->all();
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Modules\PMS\Repositories;
interface TaskCategoryInterface
{
public function findAll();
public function getTaskCategoryById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Modules\PMS\Repositories;
use Modules\PMS\Models\TaskCategory;
class TaskCategoryRepository implements TaskCategoryInterface
{
public function findAll()
{
return TaskCategory::get();
}
public function getTaskCategoryById($TaskCategoryId)
{
return TaskCategory::findOrFail($TaskCategoryId);
}
public function delete($TaskCategoryId)
{
TaskCategory::destroy($TaskCategoryId);
}
public function create($TaskCategoryDetails)
{
return TaskCategory::create($TaskCategoryDetails);
}
public function update($TaskCategoryId, array $newDetails)
{
return TaskCategory::whereId($TaskCategoryId)->update($newDetails);
}
public function pluck()
{
return TaskCategory::pluck('title', 'id');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Modules\PMS\Repositories;
interface TaskInterface
{
public function findAll($filters = [], $limit = null, $offset = null);
public function getTaskById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
public function getAllTasks($filters = []);
public function findAllWithRelations(array $relations = [], $limit = null);
public function getTaskCountsByCategory($userId = null);
// public function getTaskbyMembers($employee_id);
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Modules\PMS\Repositories;
use Illuminate\Support\Facades\DB;
use Modules\PMS\Models\KanbanColumn;
use Modules\PMS\Models\Task;
class TaskRepository implements TaskInterface
{
public function findAll($filters = [], $limit = null, $offset = null)
{
return Task::when(true, function ($query) use ($filters) {
$query->whereNull("parent_id");
if (isset($filters["search"])) {
$search = $filters['search'];
$query->whereAny(['title'], 'LIKE', "%$search%");
}
if (isset($filters["status"])) {
$query->where("status", $filters["status"]);
}
if (isset($filters["priority"])) {
$query->where("priority", $filters["priority"]);
}
if (isset($filters["date"])) {
$explodeDate = explode("to", $filters['date']);
$query->whereBetween("start_date", [$explodeDate[0], preg_replace('/\s+/', '', $explodeDate[1])]);
}
if (isset($filters["assigned_to"])) {
$query->whereJsonContains("assigned_id->ids", (string) $filters['assigned_to']);
}
if (auth()->user()->hasRole('employee')) {
$assigned_id = auth()->user()->employee_id;
$query->whereJsonContains("assigned_id->ids", (string) $assigned_id);
}
})
->with('assignedUser:id,first_name,middle_name,last_name,profile_picture')
->latest()
->limit($limit)
->get();
}
public function getTaskById($TaskId)
{
return Task::findOrFail($TaskId);
}
public function delete($TaskId)
{
Task::destroy($TaskId);
}
public function create($TaskDetails)
{
return Task::create($TaskDetails);
}
public function update($TaskId, array $newDetails)
{
return Task::whereId($TaskId)->update($newDetails);
}
public function pluck()
{
return Task::pluck(DB::raw('CONCAT(first_name," ", middle_name , " ",last_name) AS full_name'), 'id');
}
public function getAllTasks($filters = [])
{
return Task::with('subTask')->when(true, function ($query) use ($filters) {
$query->whereNull("parent_id");
if (isset($filters["project_id"])) {
$query->where("project_id", $filters["project_id"]);
}
if (isset($filters["date"])) {
$explodeDate = explode("to", $filters['date']);
$query->whereBetween("start_date", [$explodeDate[0], preg_replace('/\s+/', '', $explodeDate[1])]);
}
})
// ->latest()
->get();
}
public function findAllWithRelations(array $relations = [], $limit = null)
{
$query = Task::with($relations);
if ($limit) {
$query->limit($limit);
}
return $query->get();
}
public function getTaskCountsByCategory($userId = null)
{
$query = KanbanColumn::select('category', DB::raw('COUNT(tbl_tasks.id) as task_count'))
->leftJoin('tbl_tasks', 'kanban_columns.id', '=', 'tbl_tasks.status');
// Filter by user ID if provided
if ($userId) {
$query->whereJsonContains('tbl_tasks.assigned_id->ids', (string) $userId);
}
return $query->groupBy('kanban_columns.category')->get();
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Modules\PMS\Repositories;
interface TaskTimeInterface
{
public function findAll($filters = [], $limit = null, $offset = null);
public function getTaskTimeById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
public function getLatestTimeByTaskId($TaskId);
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Modules\PMS\Repositories;
use Illuminate\Support\Facades\DB;
use Modules\PMS\Models\TaskTime;
class TaskTimeRepository implements TaskTimeInterface
{
public function findAll($filters = [], $limit = null, $offset = null)
{
return TaskTime::when(true, function ($query) use ($filters) {
$query->whereNull("parent_id");
if (isset($filters["search"])) {
$search = $filters['search'];
$query->whereAny(['title'], 'LIKE', "%$search%");
}
if (isset($filters["status"])) {
$query->where("status", $filters["status"]);
}
if (isset($filters["date"])) {
$explodeDate = explode("to", $filters['date']);
$query->whereBetween("start_date", [$explodeDate[0], preg_replace('/\s+/', '', $explodeDate[1])]);
}
})
->latest()
->limit(5)
->get();
}
public function getTaskTimeById($TaskId)
{
return TaskTime::findOrFail($TaskId);
}
public function delete($TaskId)
{
TaskTime::destroy($TaskId);
}
public function create($TaskDetails)
{
return TaskTime::create($TaskDetails);
}
public function update($TaskId, array $newDetails)
{
return TaskTime::whereId($TaskId)->update($newDetails);
}
public function pluck()
{
return TaskTime::pluck(DB::raw('CONCAT(first_name," ", middle_name , " ",last_name) AS full_name'), 'id');
}
public function getLatestTimeByTaskId($TaskId)
{
return TaskTime::where('task_id', $TaskId)->latest()->first();
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Modules\PMS\Repositories;
interface TicketInterface
{
public function findAll();
public function getTicketById($clientId);
public function delete($clientId);
public function create($clientDetails);
public function update($clientId, array $newDetails);
public function pluck();
public function count();
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\PMS\Repositories;
use Illuminate\Support\Facades\DB;
use Modules\PMS\Models\Ticket;
class TicketRepository implements TicketInterface
{
public function findAll()
{
return Ticket::paginate(20);
}
public function getTicketById($TicketId)
{
return Ticket::findOrFail($TicketId);
}
public function delete($TicketId)
{
Ticket::destroy($TicketId);
}
public function create($TicketDetails)
{
return Ticket::create($TicketDetails);
}
public function update($TicketId, array $newDetails)
{
return Ticket::whereId($TicketId)->update($newDetails);
}
public function pluck()
{
return Ticket::pluck('Ticket_name', 'id');
}
public function count()
{
return Ticket::count();
}
}