ManagementSystem/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php

423 lines
16 KiB
PHP

<?php
namespace Modules\Admin\app\Http\Controllers;
use App\Helper\Cache\CurrentMonthTimekeeping;
use App\Http\Controllers\Controller;
use App\Models\Notes;
use App\Traits\AnalyzeData;
use App\Traits\HasFilterRequest;
use App\Traits\HasOrderByRequest;
use App\Traits\HasSearchRequest;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Admin\app\Models\Category;
use Modules\Admin\app\Models\Ticket;
class TicketController extends Controller
{
use HasOrderByRequest;
use HasFilterRequest;
use HasSearchRequest;
use AnalyzeData;
public function getByUserId(Request $request)
{
$tickets = new Ticket;
// Order by
$this->orderByRequest($tickets, $request);
// Filter
$this->filterRequest(
builder: $tickets,
request: $request,
filterKeys: [
'type' => self::F_TEXT,
'reason' => self::F_TEXT,
'updated_by' => self::F_TEXT,
'start_date' => [
'type' => self::F_THAN_EQ_DATETIME,
'column' => 'tickets.start_date'
],
'end_date' => [
'type' => self::F_THAN_EQ_DATETIME,
'column' => 'tickets.end_date'
],
]
);
$this->searchRequest(
builder: $tickets,
value: $request->get('search'),
fields: [
'users.name',
"start_date",
"startPeriod.c_name",
"end_date",
"endPeriod.c_name",
"typeReason.c_name",
'status',
"reason",
]
);
$responseData = array_merge(
$tickets
->join('users', 'tickets.user_id', '=', 'users.id')
->leftJoin("categories as startPeriod", function ($join) {
$join->on('start_period', '=', 'startPeriod.c_code');
$join->on('startPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as endPeriod", function ($join) {
$join->on('end_period', '=', 'endPeriod.c_code');
$join->on('endPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as typeReason", function ($join) {
$join->on('type', '=', 'typeReason.c_code');
$join->on('typeReason.c_type', DB::raw("CONCAT('REASON')"));
})
->leftJoin("categories as statusTickets", function ($join) {
$join->on('status', '=', 'statusTickets.c_code');
$join->on('statusTickets.c_type', DB::raw("CONCAT('STATUS_TICKETS')"));
})
->where('user_id', auth('admins')->user()->id)->orderBy('tickets.created_at', 'desc')
->select(
'users.name as user_name',
'users.email',
'tickets.*',
'startPeriod.c_name as startPeriodName',
'endPeriod.c_name as endPeriodName',
'typeReason.c_name as typeReasonName',
'statusTickets.c_name as statusTicketsName',
)
->paginate($request->get('per_page'))->toArray(),
['status' => true]
);
return response()->json($responseData);
}
public function getAll(Request $request)
{
$tickets = new Ticket;
// Order by
$this->orderByRequest($tickets, $request);
// Filter
$this->filterRequest(
builder: $tickets,
request: $request,
filterKeys: [
'type' => self::F_TEXT,
'reason' => self::F_TEXT,
'updated_by' => self::F_TEXT,
'start_date' => [
'type' => self::F_THAN_EQ_DATETIME,
'column' => 'tickets.start_date'
],
'end_date' => [
'type' => self::F_THAN_EQ_DATETIME,
'column' => 'tickets.end_date'
],
]
);
$this->searchRequest(
builder: $tickets,
value: $request->get('search'),
fields: [
'users.name',
"start_date",
"startPeriod.c_name",
"end_date",
"endPeriod.c_name",
"typeReason.c_name",
'status',
"reason",
"admin_note"
]
);
if ($request->typeReason != '') {
$tickets = $tickets->where('tickets.type', '=', $request->typeReason);
}
if ($request->statusFilter != '') {
$tickets = $tickets->where('tickets.status', '=', $request->statusFilter);
}
$responseData = array_merge(
$tickets
->join('users', 'tickets.user_id', '=', 'users.id')
->leftJoin("categories as startPeriod", function ($join) {
$join->on('start_period', '=', 'startPeriod.c_code');
$join->on('startPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as endPeriod", function ($join) {
$join->on('end_period', '=', 'endPeriod.c_code');
$join->on('endPeriod.c_type', DB::raw("CONCAT('TIME_TYPE')"));
})
->leftJoin("categories as typeReason", function ($join) {
$join->on('type', '=', 'typeReason.c_code');
$join->on('typeReason.c_type', DB::raw("CONCAT('REASON')"));
})
->leftJoin("categories as statusTickets", function ($join) {
$join->on('status', '=', 'statusTickets.c_code');
$join->on('statusTickets.c_type', DB::raw("CONCAT('STATUS_TICKETS')"));
})
->select(
'users.name as user_name',
'users.email',
'tickets.*',
'startPeriod.c_name as startPeriodName',
'endPeriod.c_name as endPeriodName',
'typeReason.c_name as typeReasonName',
'statusTickets.c_name as statusTicketsName',
)
->orderBy('tickets.created_at', 'desc')->paginate($request->get('per_page'))->toArray(),
['status' => true]
);
return response()->json($responseData);
}
public function createTicket(Request $request)
{
// Define validation rules
$rules = [
'start_date' => 'required|date',
'start_period' => 'required|string',
'end_date' => 'required|date|after_or_equal:start_date',
'end_period' => 'required|string',
'type' => 'required|string',
];
// Validate the request
$request->validate($rules);
// return $request;
//Get data from request
$startDate = $request->input('start_date'); //Start day
$startPeriod = $request->input('start_period'); //The session begins
$endDate = $request->input('end_date'); //End date
$endPeriod = $request->input('end_period'); //Session ends
$type = $request->input('type');
$reason = $request->input('reason');
$user = auth('admins')->user(); // user create ticket
// return $user;
$ticket = Ticket::create([
'start_date' => Carbon::create($startDate)->setTimezone(env('TIME_ZONE')),
'start_period' => $startPeriod,
'end_date' => Carbon::create($endDate)->setTimezone(env('TIME_ZONE')),
'end_period' => $endPeriod,
'type' => $type,
'status' => 'WAITING',
'reason' => $reason,
'user_id' => $user->id
]);
// Send notification email to admin (list)
return response()->json(['data' => $ticket, 'status' => true]);
}
public function deleteTicket(Request $request)
{
$rules = [
'ticket_id' => 'required'
];
// Validate the request
$request->validate($rules);
$user = auth('admins')->user();
$ticket_id = $request->input('ticket_id');
$ticket = Ticket::find($ticket_id);
if ($ticket) {
// $user->id == user_id of ticket ---> delete
if ($ticket->user_id == $user->id) {
$ticket->delete();
return response()->json(['message' => 'delete success', 'status' => true]);
} else {
return response()->json(['message' => 'You are committing an act of vandalism', 'status' => false]);
}
}
return response()->json(['message' => 'Delete fail', 'status' => false]);
}
public function handleTicket(Request $request)
{
$rules = [
'ticket_id' => 'required',
'action' => 'required',
'admin_note' => 'required'
];
// Validate the request
$request->validate($rules);
$ticket_id = $request->input('ticket_id');
$admin_note = $request->input('admin_note');
$action = $request->input('action'); // 'confirm' or 'refuse'
$admin = auth('admins')->user();
$ticket = Ticket::find($ticket_id);
if (!$ticket || $ticket->status !== "WAITING") {
return response()->json(['message' => "Ticket not found", 'status' => false]);
}
$results = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
// $admin->id != user_id of ticket ---> continue
// Confirm
// Add records to the notes table like function Timekeeping.addNoteForUser() based on the $results array
// Update updated_by and admin_note in tickets table
// Send notification email to users
// Refuse
// Update updated_by and admin_note in tickets table
// Send notification email to users
if ($action == "confirm") {
// dd($results);
foreach ($results as $result) {
list($year, $month, $day) = explode('-', $result['date']);
Notes::create([
'n_user_id' => $ticket->user_id,
'n_day' => $day,
'n_month' => $month,
'n_year' => $year,
'n_time_type' => $result['period'],
'n_reason' => $ticket->type,
'n_note' => $ticket->reason
]);
if($ticket->type == "WFH"){
// $user_ids = $request->users;
// $year = $request->year;
// $month = $request->month;
// $day = $request->day;
// $type = $request->type;
// foreach ($user_ids as $id) {
// $user = Admin::find($id);
// $date = Carbon::create($year, $month, $day)->setTimezone(env('TIME_ZONE'));
// $start = $date->copy()->setTime(7, 31, 11);
// $end = $type == 'half' ? $date->copy()->setTime(11, 31, 11) : $date->copy()->setTime(17, 1, 11);
// Tracking::insert([
// [
// 'name' => $user->name,
// 'user_id' => $user->id,
// 'status' => 'check in',
// 'time_string' => $start->format('Y-m-d H:i:s'),
// 'created_at' => $start->setTimezone('UTC')
// ],
// [
// 'name' => $user->name,
// 'user_id' => $user->id,
// 'status' => 'check out',
// 'time_string' => $end->format('Y-m-d H:i:s'),
// 'created_at' => $end->setTimezone('UTC')
// ]
// ]);
// }
// $this->createOrUpdateRecordForCurrentMonth($month, $year);
}
}
$ticket['updated_by'] = $admin->name;
$ticket['admin_note'] = $admin_note;
$ticket['status'] = 'CONFIRMED';
$ticket->save();
$this->createOrUpdateRecordForCurrentMonth($month, $year);
return response()->json(['message' => "confirmed", 'status' => true]);
}
if ($action == "refuse") {
$ticket['updated_by'] = $admin->name;
$ticket['admin_note'] = $admin_note;
$ticket['status'] = 'REFUSED';
$ticket->save();
return response()->json(['message' => "refused", 'status' => true]);
}
return response()->json(['message' => "failed", 'status' => false]);
}
private function getAllPeriod($startDate, $startPeriod, $endDate, $endPeriod)
{
//Create an array to contain the results
$results = [];
//Use CarbonPeriod to create a period from the start date to the end date
$period = CarbonPeriod::create($startDate, $endDate);
$time_type = Category::where('c_type', 'TIME_TYPE')->get();
$morning = null;
$afternoon = null;
$all_day = null;
foreach ($time_type as $item) {
switch ($item->c_code) {
case 'S':
$morning = $item;
break;
case 'C':
$afternoon = $item;
break;
case 'ALL':
$all_day = $item;
break;
}
}
foreach ($period as $date) {
//If it is the start date
if ($date->isSameDay($startDate)) {
//Add start session
//If the start date is morning, add afternoon
if ($startDate == $endDate) {
if ($startPeriod == $endPeriod) {
$results[] = ['date' => $date->toDateString(), 'period' => $startPeriod];
} else {
$results[] = ['date' => $date->toDateString(), 'period' => $all_day->c_code];
}
} else {
if ($startPeriod == $morning->c_code) {
$results[] = ['date' => $date->toDateString(), 'period' => $all_day->c_code];
} else {
$results[] = ['date' => $date->toDateString(), 'period' => $startPeriod];
}
}
} elseif ($date->isSameDay($endDate)) {
//If it is the end date
//If the end session is afternoon, add morning first
if ($endPeriod == $afternoon->c_code) {
$results[] = ['date' => $date->toDateString(), 'period' => $all_day->c_code];
} else {
$results[] = ['date' => $date->toDateString(), 'period' => $endPeriod];
}
} else {
//Add both sessions for days between intervals
$results[] = ['date' => $date->toDateString(), 'period' => $all_day->c_code];
// $results[] = ['date' => $date->toDateString(), 'period' => 'afternoon'];
}
}
//Returns results
return $results;
}
}