ManagementSystem/BACKEND/app/Jobs/CheckUserAttendanceJob.php

198 lines
9.3 KiB
PHP

<?php
namespace App\Jobs;
use App\Mail\TicketMail;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use Modules\Admin\app\Http\Controllers\CategoryController;
use Modules\Admin\app\Models\Admin;
use Modules\Admin\app\Models\Ticket;
use Modules\Admin\app\Models\Tracking;
class CheckUserAttendanceJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $period;
/**
* Create a new job instance.
* @param string|null $period
*/
public function __construct($period = null)
{
$this->period = $period;
}
/**
* Execute the job.
*/
public function handle()
{
// Lấy tất cả người dùng
$users = User::where('permission', 'not like', '%admin%')
->where('permission', 'not like', '%accountant%')->get();
foreach ($users as $key => $user) {
// if ($user->id != 4) {
// continue;
// }
// Kiểm tra dựa trên period (Sáng 'S' hoặc Chiều 'C')
if ($this->period === 'S') {
$this->checkMorning($user);
} elseif ($this->period === 'C') {
$this->checkAfternoon($user);
} else {
if ($this->period == null) {
// Nếu không có period, kiểm tra cả sáng và chiều
$this->checkMorning($user);
$this->checkAfternoon($user);
}
}
}
}
private function checkAttendance($user, $periodCode, $startTime, $endTime)
{
$today = Carbon::today();
$userId = $user->id;
// Lấy tất cả tracking của user trong khoảng thời gian được chỉ định
$records = Tracking::where('user_id', $userId)
->whereBetween('time_string', [$startTime, $endTime])
->get();
$hasCheckIn = $records->where('status', 'check in')->isNotEmpty();
$hasCheckOut = $records->where('status', 'check out')->isNotEmpty();
// Kiểm tra nếu đã có ticket chờ xử lý hoặc đã được xác nhận, cho cả sáng và chiều
$existingTicket = Ticket::where('user_id', $userId)
->where(function ($query) use ($today, $periodCode) {
// Check for tickets that exactly cover the current day and period
$query->where(function ($subQuery) use ($today, $periodCode) {
$subQuery->where('start_date', $today->format('Y-m-d'))
->where('end_date', $today->format('Y-m-d'))
->where(function ($periodQuery) use ($periodCode) {
// Check if the ticket covers the current period
$periodQuery->where('start_period', $periodCode)
->orWhere(function ($query) {
// Check for a full-day ticket (S -> C)
$query->where('start_period', 'S')
->where('end_period', 'C');
});
});
})
// Check for tickets that span multiple days
->orWhere(function ($subQuery) use ($today, $periodCode) {
$subQuery->where('start_date', '<=', $today->format('Y-m-d'))
->where('end_date', '>=', $today->format('Y-m-d'))
->where(function ($periodQuery) use ($periodCode, $today) {
$periodQuery->where(function ($query) use ($today) {
$query->where('start_date', '<', $today->format('Y-m-d'))
->where('end_date', '>', $today->format('Y-m-d'));
})
->orWhere(function ($query) use ($today, $periodCode) {
$query->where(function ($queryDateStart) use ($today, $periodCode) {
$queryDateStart->where('start_date', '=', $today->format('Y-m-d'))
->where('end_date', '>', $today->format('Y-m-d'))
->where(function ($queryDateStartChild) use ($periodCode) {
$queryDateStartChild->where('start_period', $periodCode)
->orWhere(function ($query) {
$query->where('start_period', 'S');
});
});
})
->orWhere(function ($queryDateEnd) use ($today, $periodCode) {
$queryDateEnd->where('end_date', '=', $today->format('Y-m-d'))
->where('start_date', '<', $today->format('Y-m-d'))
->where(function ($queryDateStartChild) use ($periodCode) {
$queryDateStartChild->where('end_period', $periodCode)
->orWhere(function ($query) {
$query->where('end_period', 'C');
});
});
});
});
});
});
})
->whereIn('status', ['WAITING', 'CONFIRMED'])
->first();
$type = 'ONLEAVE';
$reason = 'KHONG PHEP';
//Check ngày hợp lệ nếu có check và check out của user khác
$dateNow = Tracking::whereBetween('time_string', [$startTime, $endTime])
->get();
$hasCheckIndateNow = $dateNow->where('status', 'check in')->isNotEmpty();
$hasCheckOutdateNow = $dateNow->where('status', 'check out')->isNotEmpty();
// Nếu không có check-in hoặc check-out, và chưa có ticket, tạo ticket mới
if (($hasCheckIndateNow && $hasCheckOutdateNow) && !$hasCheckIn && !$hasCheckOut && !$existingTicket) {
Ticket::create([
'user_id' => $userId,
'start_date' => $today->format('Y-m-d'),
'start_period' => $periodCode,
'end_date' => $today->format('Y-m-d'),
'end_period' => $periodCode,
'type' => $type,
'reason' => $reason,
'status' => 'WAITING',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
//Send mail
$dataMasterStartPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $periodCode);
$dataMasterEndPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $periodCode);
$dataMasterType = CategoryController::getListMasterByCodeAndType("REASON", $type);
$formattedStartDate = $today->format('d/m/Y');
$formattedEndDate = $today->format('d/m/Y');
$admins = Admin::where('permission', 'like', '%admin%')->get();
foreach ($admins as $key => $value) {
$data = array(
"email_template" => "email.notification_tickets",
"email" => $user->email,
"name" => $user->name,
"date" => $dataMasterStartPeriod->c_name . " (" . $formattedStartDate . ") - " . $dataMasterEndPeriod->c_name . " (" . $formattedEndDate . ")",
"type" => $dataMasterType->c_name,
"note" => $reason,
"link" => "/tickets-management", //link đến page admin
"subject" => "[Ticket request] Ticket From " . $user->name
);
Mail::to($value->email)->send(new TicketMail($data));
}
}
}
/**
* Kiểm tra check-in/check-out buổi sáng và tạo ticket nếu thiếu.
* @param int $userId
*/
public function checkMorning($user)
{
$startTime = Carbon::today()->setTime(6, 0); // Thời gian bắt đầu buổi sáng
$endTime = Carbon::createFromTime(12, 0); // Thời gian kết thúc buổi sáng
$this->checkAttendance($user, 'S', $startTime, $endTime);
}
/**
* Kiểm tra check-in/check-out buổi chiều và tạo ticket nếu thiếu.
* @param int $userId
*/
public function checkAfternoon($user)
{
$startTime = Carbon::today()->setTime(12, 0); // Thời gian bắt đầu buổi chiều
$endTime = Carbon::createFromTime(17, 30); // Thời gian kết thúc buổi chiều
$this->checkAttendance($user, 'C', $startTime, $endTime);
}
}