update handle calculate onleave ticket in next months
This commit is contained in:
parent
543b1af58c
commit
034b9eee2c
|
|
@ -51,7 +51,7 @@ class LeaveManagementController extends Controller
|
|||
)
|
||||
// ->where('notes.n_user_id', "1")
|
||||
->where('notes.n_year', $year)
|
||||
->whereIn('notes.n_reason', ['ONLEAVE', 'LEAVE_WITHOUT_PAY'])
|
||||
->whereIn('notes.n_reason', ['ONLEAVE', 'LEAVE_WITHOUT_PAY', 'TEMPORARY_ONLEAVE'])
|
||||
// ->groupBy("notes.n_user_id")
|
||||
->orderBy('notes.n_month')
|
||||
->orderBy('notes.n_day')
|
||||
|
|
@ -155,7 +155,7 @@ class LeaveManagementController extends Controller
|
|||
}
|
||||
|
||||
// Lọc chỉ lấy user có permission bao gồm staff
|
||||
$staffData = $leaveDays->filter(function($user) {
|
||||
$staffData = $leaveDays->filter(function ($user) {
|
||||
return isset($user['user']['permission']) && strpos($user['user']['permission'], 'staff') !== false;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -402,6 +402,10 @@ class TicketController extends Controller
|
|||
|
||||
$ticket->updated_by = $admin->name;
|
||||
$ticket->admin_note = $request->admin_note;
|
||||
|
||||
// Clear Timekeeping cache
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->start_date)->month, Carbon::parse($ticket->start_date)->year);
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->end_date)->month, Carbon::parse($ticket->end_date)->year);
|
||||
$ticket->save();
|
||||
|
||||
return AbstractController::ResultSuccess($ticket, "Ticket updated successfully!");
|
||||
|
|
@ -717,6 +721,7 @@ class TicketController extends Controller
|
|||
->first();
|
||||
|
||||
$totalAllocated = 0;
|
||||
// Xử lý gửi ticket sau tháng hiện tại
|
||||
if ($leaveDaysInfo && $user->is_permanent) {
|
||||
$currentMonth = Carbon::now()->month;
|
||||
$totalAllocated = $leaveDaysInfo->ld_day_total;
|
||||
|
|
@ -837,19 +842,21 @@ class TicketController extends Controller
|
|||
$dataMasterTypeNotes = CategoryController::getListMasterByType("REASON_NOTES");
|
||||
$onleave = null;
|
||||
$leaveWithoutPay = null;
|
||||
$temporaryOnleave = null;
|
||||
|
||||
if ($dataMasterTypeNotes) {
|
||||
// get nghỉ phép, nghỉ không phép
|
||||
$onleave = optional($dataMasterTypeNotes->where('c_code', 'ONLEAVE')->first())->c_code;
|
||||
$leaveWithoutPay = optional($dataMasterTypeNotes->where('c_code', 'LEAVE_WITHOUT_PAY')->first())->c_code;
|
||||
$temporaryOnleave = optional($dataMasterTypeNotes->where('c_code', 'TEMPORARY_ONLEAVE')->first())->c_code;
|
||||
}
|
||||
|
||||
if ($onleave == null || $leaveWithoutPay == null) {
|
||||
if ($onleave == null || $leaveWithoutPay == null || $temporaryOnleave == null) {
|
||||
return response()->json(['message' => "Data reason notes not found", 'status' => false]);
|
||||
}
|
||||
|
||||
if ($action == "confirm") {
|
||||
$this->handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay);
|
||||
$this->handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay, $temporaryOnleave);
|
||||
return response()->json(['message' => "confirmed", 'status' => true]);
|
||||
}
|
||||
|
||||
|
|
@ -887,20 +894,22 @@ class TicketController extends Controller
|
|||
$dataMasterTypeNotes = CategoryController::getListMasterByType("REASON_NOTES");
|
||||
$onleave = null;
|
||||
$leaveWithoutPay = null;
|
||||
$temporaryOnleave = null;
|
||||
|
||||
if ($dataMasterTypeNotes) {
|
||||
// Get nghỉ phép, nghỉ không phép
|
||||
$onleave = optional($dataMasterTypeNotes->where('c_code', 'ONLEAVE')->first())->c_code;
|
||||
$leaveWithoutPay = optional($dataMasterTypeNotes->where('c_code', 'LEAVE_WITHOUT_PAY')->first())->c_code;
|
||||
$temporaryOnleave = optional($dataMasterTypeNotes->where('c_code', 'TEMPORARY_ONLEAVE')->first())->c_code;
|
||||
}
|
||||
|
||||
// Không tìm được ngày phép, ko phép
|
||||
if ($onleave == null || $leaveWithoutPay == null) {
|
||||
if ($onleave == null || $leaveWithoutPay == null || $temporaryOnleave == null) {
|
||||
return redirect()->to(config('app.client_url') . '/404');
|
||||
}
|
||||
|
||||
if ($action == "confirm") {
|
||||
$this->handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay);
|
||||
$this->handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay, $temporaryOnleave);
|
||||
return redirect()->to(config('app.client_url') . '/tickets-management');
|
||||
}
|
||||
|
||||
|
|
@ -913,7 +922,7 @@ class TicketController extends Controller
|
|||
return redirect()->to(config('app.client_url') . '/tickets-management');
|
||||
}
|
||||
|
||||
private function handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay)
|
||||
private function handleConfirmTicket($ticket, $admin, $admin_note, $onleave, $leaveWithoutPay, $temporaryOnleave)
|
||||
{
|
||||
$startDate = $ticket->start_date; //Start day
|
||||
$startPeriod = $ticket->start_period; //The session begins
|
||||
|
|
@ -934,6 +943,7 @@ class TicketController extends Controller
|
|||
$dataListPeriod = $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
|
||||
$balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, null, true);
|
||||
// dd($balanceCheckResult, $dataListPeriod);
|
||||
$currentMonth = Carbon::now()->month;
|
||||
if ($balanceCheckResult['success'] == false) {
|
||||
if ($balanceCheckResult['months_info']) {
|
||||
foreach ($balanceCheckResult['months_info'] as $monthInfo) {
|
||||
|
|
@ -960,7 +970,7 @@ class TicketController extends Controller
|
|||
'n_month' => $month,
|
||||
'n_year' => $year,
|
||||
'n_time_type' => 'S',
|
||||
'n_reason' => $onleave,
|
||||
'n_reason' => $month > $currentMonth ? $temporaryOnleave : $onleave,
|
||||
'n_note' => $ticket->reason,
|
||||
'ticket_id' => $ticket->id
|
||||
]);
|
||||
|
|
@ -970,7 +980,7 @@ class TicketController extends Controller
|
|||
'n_month' => $month,
|
||||
'n_year' => $year,
|
||||
'n_time_type' => 'C',
|
||||
'n_reason' => $leaveWithoutPay,
|
||||
'n_reason' => $month > $currentMonth ? $temporaryOnleave : $leaveWithoutPay,
|
||||
'n_note' => $ticket->reason,
|
||||
'ticket_id' => $ticket->id
|
||||
]);
|
||||
|
|
@ -985,7 +995,7 @@ class TicketController extends Controller
|
|||
'n_month' => $month,
|
||||
'n_year' => $year,
|
||||
'n_time_type' => $period,
|
||||
'n_reason' => $onleave,
|
||||
'n_reason' => $month > $currentMonth ? $temporaryOnleave : $onleave,
|
||||
'n_note' => $ticket->reason,
|
||||
'ticket_id' => $ticket->id
|
||||
]);
|
||||
|
|
@ -999,7 +1009,7 @@ class TicketController extends Controller
|
|||
'n_month' => $month,
|
||||
'n_year' => $year,
|
||||
'n_time_type' => $period,
|
||||
'n_reason' => $leaveWithoutPay,
|
||||
'n_reason' => $month > $currentMonth ? $temporaryOnleave : $leaveWithoutPay,
|
||||
'n_note' => $ticket->reason,
|
||||
'ticket_id' => $ticket->id
|
||||
]);
|
||||
|
|
@ -1019,49 +1029,49 @@ class TicketController extends Controller
|
|||
'n_month' => $month,
|
||||
'n_year' => $year,
|
||||
'n_time_type' => $result['period'],
|
||||
'n_reason' => $onleave, // có phép
|
||||
'n_reason' => $month > $currentMonth ? $temporaryOnleave : $onleave,
|
||||
'n_note' => $ticket->reason,
|
||||
'ticket_id' => $ticket->id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$yearCheck = Carbon::parse($endDate)->year;
|
||||
// Check giá trị ld_day_total của bảng leave_days thuộc user id đó với giá trị của list item note trong bảng notes của user id đó
|
||||
$leaveDaysInfo = LeaveDays::where('ld_user_id', $ticket->user_id)
|
||||
->where('ld_year', $yearCheck)
|
||||
->first();
|
||||
if ($leaveDaysInfo) {
|
||||
// Tính tổng số ngày nghỉ có phép đã sử dụng trong năm
|
||||
$totalUsedLeaveDays = Notes::join('categories', function ($join) {
|
||||
$join->on('notes.n_time_type', '=', 'categories.c_code')
|
||||
->where('categories.c_type', 'TIME_TYPE');
|
||||
})
|
||||
->where('n_user_id', $ticket->user_id)
|
||||
->where('n_year', $yearCheck)
|
||||
->where('n_reason', 'ONLEAVE')
|
||||
->sum('categories.c_value');
|
||||
// $yearCheck = Carbon::parse($endDate)->year;
|
||||
// // Check giá trị ld_day_total của bảng leave_days thuộc user id đó với giá trị của list item note trong bảng notes của user id đó
|
||||
// $leaveDaysInfo = LeaveDays::where('ld_user_id', $ticket->user_id)
|
||||
// ->where('ld_year', $yearCheck)
|
||||
// ->first();
|
||||
// if ($leaveDaysInfo) {
|
||||
// // Tính tổng số ngày nghỉ có phép đã sử dụng trong năm
|
||||
// $totalUsedLeaveDays = Notes::join('categories', function ($join) {
|
||||
// $join->on('notes.n_time_type', '=', 'categories.c_code')
|
||||
// ->where('categories.c_type', 'TIME_TYPE');
|
||||
// })
|
||||
// ->where('n_user_id', $ticket->user_id)
|
||||
// ->where('n_year', $yearCheck)
|
||||
// ->where('n_reason', 'ONLEAVE')
|
||||
// ->sum('categories.c_value');
|
||||
|
||||
// Tính tổng số ngày phép được cấp
|
||||
$totalAllocatedDays = $leaveDaysInfo->ld_day_total +
|
||||
$leaveDaysInfo->ld_additional_day +
|
||||
$leaveDaysInfo->ld_special_leave_day;
|
||||
// // Tính tổng số ngày phép được cấp
|
||||
// $totalAllocatedDays = $leaveDaysInfo->ld_day_total +
|
||||
// $leaveDaysInfo->ld_additional_day +
|
||||
// $leaveDaysInfo->ld_special_leave_day;
|
||||
|
||||
// Tính số ngày vượt quá và làm tròn lên
|
||||
$excessDays = $totalUsedLeaveDays - $totalAllocatedDays;
|
||||
$roundedExcessDays = ceil($excessDays); // Làm tròn lên số nguyên gần nhất
|
||||
// // Tính số ngày vượt quá và làm tròn lên
|
||||
// $excessDays = $totalUsedLeaveDays - $totalAllocatedDays;
|
||||
// $roundedExcessDays = ceil($excessDays); // Làm tròn lên số nguyên gần nhất
|
||||
|
||||
// Kiểm tra nếu số ngày đã sử dụng vượt quá số ngày được cấp
|
||||
if ($roundedExcessDays > 0) {
|
||||
Log::warning("User ID: {$ticket->user_id} has used more leave days ({$totalUsedLeaveDays}) than allocated ({$totalAllocatedDays})");
|
||||
// // Kiểm tra nếu số ngày đã sử dụng vượt quá số ngày được cấp
|
||||
// if ($roundedExcessDays > 0) {
|
||||
// Log::warning("User ID: {$ticket->user_id} has used more leave days ({$totalUsedLeaveDays}) than allocated ({$totalAllocatedDays})");
|
||||
|
||||
// Cập nhật cột ld_day_total với số ngày đã làm tròn
|
||||
$leaveDaysInfo->ld_day_total += $roundedExcessDays;
|
||||
$leaveDaysInfo->save();
|
||||
// // Cập nhật cột ld_day_total với số ngày đã làm tròn
|
||||
// $leaveDaysInfo->ld_day_total += $roundedExcessDays;
|
||||
// $leaveDaysInfo->save();
|
||||
|
||||
Log::info("Updated leave days for User ID: {$ticket->user_id}. Added {$roundedExcessDays} days (rounded from {$excessDays})");
|
||||
}
|
||||
}
|
||||
// Log::info("Updated leave days for User ID: {$ticket->user_id}. Added {$roundedExcessDays} days (rounded from {$excessDays})");
|
||||
// }
|
||||
// }
|
||||
} else if ($ticket->type == "WFH") {
|
||||
$dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
|
||||
foreach ($dataListPeriod as $result) {
|
||||
|
|
@ -1117,7 +1127,8 @@ class TicketController extends Controller
|
|||
$ticket['status'] = 'CONFIRMED';
|
||||
$ticket->save();
|
||||
|
||||
$this->createOrUpdateRecordForCurrentMonth($month, $year);
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->start_date)->month, Carbon::parse($ticket->start_date)->year);
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->end_date)->month, Carbon::parse($ticket->end_date)->year);
|
||||
|
||||
// Send notification email to users
|
||||
$data = array(
|
||||
|
|
@ -1358,8 +1369,9 @@ class TicketController extends Controller
|
|||
$message = "";
|
||||
|
||||
if ($index === 0) {
|
||||
$showMonth = $monthData['month'] > Carbon::now()->month ? $monthData['month'] : Carbon::now()->month;
|
||||
$message .= "* Quy định: mỗi tháng được nghỉ tối đa {$max} ngày phép\n";
|
||||
$message .= "- Bạn đang có: {$totalLeave} ngày phép\n\n";
|
||||
$message .= "- Bạn có: {$totalLeave} ngày phép (Tính tới tháng {$showMonth})\n\n";
|
||||
}
|
||||
|
||||
// Hiển thị cộng phép nếu gửi ticket trong tương lai
|
||||
|
|
@ -1380,7 +1392,7 @@ class TicketController extends Controller
|
|||
}
|
||||
|
||||
if ($willUseLeave > 0 || $willUseNoPay > 0) {
|
||||
$message .= " - Bạn sẽ sử dụng: ";
|
||||
$message .= " - Dự kiến bạn sẽ sử dụng: ";
|
||||
$usedParts = [];
|
||||
if ($willUseLeave > 0) $usedParts[] = "{$willUseLeave} phép";
|
||||
if ($willUseNoPay > 0) $usedParts[] = "{$willUseNoPay} không phép";
|
||||
|
|
@ -1478,7 +1490,6 @@ class TicketController extends Controller
|
|||
for ($i = 1; $i <= $month; $i++) {
|
||||
// Giả lập cộng phép
|
||||
$onleaveDaysTotal++;
|
||||
$ld_note = $ld_note . "Cộng phép tháng " . $i . ".\n";
|
||||
// $tmpOnleaveDaysTotal = $onleaveDaysTotal;
|
||||
|
||||
$onleaveDaysInMonth = 0;
|
||||
|
|
|
|||
|
|
@ -171,12 +171,8 @@ class TimekeepingController extends Controller
|
|||
|
||||
// Validate the request
|
||||
$request->validate($rules);
|
||||
|
||||
$id = $request->input('id');
|
||||
|
||||
$month = $request->month;
|
||||
$year = $request->year;
|
||||
|
||||
$note = Notes::find($id);
|
||||
if (!$note) {
|
||||
return response()->json(['message' => 'Note not found', 'status' => false]);
|
||||
|
|
@ -193,77 +189,11 @@ class TimekeepingController extends Controller
|
|||
$ticket->save();
|
||||
|
||||
Notes::where('ticket_id', $ticket->id)->delete();
|
||||
$this->createOrUpdateRecordForCurrentMonth($month, $year);
|
||||
|
||||
// Clear Timekeeping cache
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->start_date)->month, Carbon::parse($ticket->start_date)->year);
|
||||
$this->createOrUpdateRecordForCurrentMonth(Carbon::parse($ticket->end_date)->month, Carbon::parse($ticket->end_date)->year);
|
||||
return response()->json(['message' => 'Delete success', 'status' => true]);
|
||||
|
||||
// $n_month = $note->n_month;
|
||||
// $n_year = $note->n_year;
|
||||
|
||||
// if ($note->n_reason == "ONLEAVE") {
|
||||
// // Get note reason ONLEAVE by $n_month, $n_year not include $note->id & include $note->n_user_id
|
||||
// // $onleave = Notes::getNotesByMonthAndYearAndUserId($n_month, $n_year, $note->n_user_id, $note->id);
|
||||
|
||||
// // Get note reason LEAVE_WITHOUT_PAY by $n_month, $n_year & include $note->n_user_id
|
||||
// $leaveWithoutPay = Notes::getNotesByMonthAndYearAndUserIdAndReason($n_month, $n_year, $note->n_user_id, 'LEAVE_WITHOUT_PAY');
|
||||
|
||||
// if (count($leaveWithoutPay) > 0) {
|
||||
// $deletedValue = ($note->n_time_type === 'ALL') ? 1.0 : 0.5;
|
||||
// $needUpdate = $deletedValue;
|
||||
// // dd($needUpdate, $leaveWithoutPay);
|
||||
// foreach ($leaveWithoutPay as $lwNote) {
|
||||
// if ($needUpdate <= 0) break;
|
||||
|
||||
// if ($lwNote->n_time_type === 'ALL') {
|
||||
// if ($needUpdate == 1.0) {
|
||||
// // Chuyển cả note ALL thành phép
|
||||
// $lwNote->update(['n_reason' => 'ONLEAVE']);
|
||||
// $needUpdate = 0;
|
||||
// break;
|
||||
// } else { // $needUpdate == 0.5
|
||||
// // Tách ALL thành 2 note S và C, chuyển S thành phép, C giữ không phép
|
||||
// Notes::create([
|
||||
// 'n_user_id' => $lwNote->n_user_id,
|
||||
// 'n_day' => $lwNote->n_day,
|
||||
// 'n_month' => $lwNote->n_month,
|
||||
// 'n_year' => $lwNote->n_year,
|
||||
// 'n_time_type' => 'S',
|
||||
// 'n_reason' => 'ONLEAVE',
|
||||
// 'n_note' => $lwNote->n_note
|
||||
// ]);
|
||||
// Notes::create([
|
||||
// 'n_user_id' => $lwNote->n_user_id,
|
||||
// 'n_day' => $lwNote->n_day,
|
||||
// 'n_month' => $lwNote->n_month,
|
||||
// 'n_year' => $lwNote->n_year,
|
||||
// 'n_time_type' => 'C',
|
||||
// 'n_reason' => 'LEAVE_WITHOUT_PAY',
|
||||
// 'n_note' => $lwNote->n_note
|
||||
// ]);
|
||||
// $lwNote->delete();
|
||||
// $needUpdate = 0;
|
||||
// break;
|
||||
// }
|
||||
// } else {
|
||||
// // Nếu $lwNote->n_time_type == 'S' hoặc 'C' => 0.5
|
||||
// if ($needUpdate == 1.0) {
|
||||
// // Chuyển cả note ALL thành phép
|
||||
// $lwNote->update(['n_reason' => 'ONLEAVE']);
|
||||
// $needUpdate -= 0.5;
|
||||
// } else { // $needUpdate == 0.5
|
||||
// // S hoặc C, chỉ cần chuyển đúng 0.5 ngày
|
||||
// $lwNote->update(['n_reason' => 'ONLEAVE']);
|
||||
// $needUpdate = 0;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // Khi note phép và k tồn tại nghỉ không phép => phép + dồn cho tháng sau
|
||||
// }
|
||||
// }
|
||||
// $note->delete();
|
||||
// $this->createOrUpdateRecordForCurrentMonth($month, $year);
|
||||
// return response()->json(['message' => 'Delete success', 'status' => true]);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
|
|
|
|||
|
|
@ -21,4 +21,4 @@ class AddMonthlyLeaveDaysCommand extends Command
|
|||
$year = $this->argument('year');
|
||||
AddMonthlyLeaveDays::dispatch($month, $year);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Jobs\UpdateTemporaryLeaveDays;
|
||||
|
||||
class UpdateTemporaryLeaveDaysCommand extends Command
|
||||
{
|
||||
protected $signature = 'update:temporary-leavedays {month?} {year?}';
|
||||
protected $description = 'Tính lại ngày phép cho các note tạm.';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$month = $this->argument('month');
|
||||
$year = $this->argument('year');
|
||||
UpdateTemporaryLeaveDays::dispatch($month, $year);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,8 +34,9 @@ class Kernel extends ConsoleKernel
|
|||
// Chạy buổi chiều lúc 17:30
|
||||
$schedule->command('attendance:check C')->dailyAt('17:30');
|
||||
|
||||
// Chạy vào 00:01 ngày đầu tiên của mỗi tháng
|
||||
// Chạy vào ngày đầu tiên của mỗi tháng
|
||||
$schedule->command('add:monthly-leavedays')->monthlyOn(1, '00:01');
|
||||
$schedule->command('update:temporary-leavedays')->monthlyOn(1, '00:05');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -65,16 +65,6 @@ class AddMonthlyLeaveDays implements ShouldQueue
|
|||
$permanentMonth = Carbon::parse($user->permanent_date)->month;
|
||||
if ($this->month > $leaveDay->ld_day_total - ($permanentDefault - $permanentMonth)) {
|
||||
$leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
|
||||
|
||||
// Xử lý ghi chú
|
||||
$newNote = "Cộng phép tháng " . $leaveDay->ld_day_total . ".\n";
|
||||
if (!empty($leaveDay->ld_note)) {
|
||||
// Nếu đã có ghi chú, thêm ghi chú mới vào và xuống dòng
|
||||
$leaveDay->ld_note = $leaveDay->ld_note . "\n" . $newNote;
|
||||
} else {
|
||||
// Nếu chưa có ghi chú, gán ghi chú mới
|
||||
$leaveDay->ld_note = $newNote;
|
||||
}
|
||||
$leaveDay->save();
|
||||
}
|
||||
}
|
||||
|
|
@ -84,16 +74,6 @@ class AddMonthlyLeaveDays implements ShouldQueue
|
|||
if ($leaveDay->ld_day_total < $this->month) {
|
||||
// Cộng mỗi tháng 1 ngày phép cho nhân viên
|
||||
$leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
|
||||
|
||||
// Xử lý ghi chú
|
||||
$newNote = "Cộng phép tháng " . $leaveDay->ld_day_total . ".\n";
|
||||
if (!empty($leaveDay->ld_note)) {
|
||||
// Nếu đã có ghi chú, thêm ghi chú mới vào và xuống dòng
|
||||
$leaveDay->ld_note = $leaveDay->ld_note . "\n" . $newNote;
|
||||
} else {
|
||||
// Nếu chưa có ghi chú, gán ghi chú mới
|
||||
$leaveDay->ld_note = $newNote;
|
||||
}
|
||||
$leaveDay->save();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,220 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\LeaveDays;
|
||||
use App\Models\Notes;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Admin\app\Models\Category;
|
||||
|
||||
class UpdateTemporaryLeaveDays implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
protected $month;
|
||||
protected $year;
|
||||
|
||||
public function __construct($month = null, $year = null)
|
||||
{
|
||||
$this->month = $month ?? Carbon::now()->month;
|
||||
$this->year = $year ?? Carbon::now()->year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$users = User::get();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$leaveDay = LeaveDays::where('ld_user_id', $user->id)
|
||||
->where('ld_year', $this->year)
|
||||
->first();
|
||||
|
||||
$notes = Notes::where('n_reason', 'TEMPORARY_ONLEAVE')
|
||||
->where('n_user_id', $user->id)
|
||||
->where('n_year', $this->year)
|
||||
->where('n_month', $this->month)
|
||||
->whereExists(function ($query) use ($user) {
|
||||
$query->select(DB::raw(1))
|
||||
->from('tickets')
|
||||
->where('tickets.user_id', $user->id)
|
||||
->where('tickets.status', 'CONFIRMED')
|
||||
->where('tickets.type', 'ONLEAVE');
|
||||
})
|
||||
->get();
|
||||
|
||||
$maxDaysPerMonth = $this->getMaxLeaveDaysPerMonth();
|
||||
|
||||
// Tổng ngày nghỉ sẽ dùng trong tháng
|
||||
$willUsedDaysInMonth = 0;
|
||||
foreach ($notes as $note) {
|
||||
$willUsedDaysInMonth += $note->n_time_type == 'ALL' ? 1.0 : 0.5;
|
||||
}
|
||||
|
||||
// Tổng phép đang có
|
||||
$onleaveDaysTotal = $leaveDay->ld_day_total + $leaveDay->ld_additional_day + $leaveDay->ld_special_leave_day;
|
||||
// Phép đã sử dụng tới tháng hiện tại
|
||||
$usedOnleaveDaysTotal = Notes::join('categories', function ($join) {
|
||||
$join->on('notes.n_time_type', '=', 'categories.c_code')
|
||||
->where('categories.c_type', 'TIME_TYPE');
|
||||
})
|
||||
->where('n_user_id', $user->id)
|
||||
->where('n_year', $this->year)
|
||||
->where('n_month', "<=", $this->month)
|
||||
->where('n_reason', 'ONLEAVE')
|
||||
->sum('categories.c_value');
|
||||
// Phép còn lại
|
||||
$remainingOnleaveDays = $onleaveDaysTotal - $usedOnleaveDaysTotal;
|
||||
|
||||
// Log::debug("User {$user->name}\n");
|
||||
// Log::debug(
|
||||
// "📊 Thống kê ngày phép:\n" .
|
||||
// " - Tháng: {$this->month}\n" .
|
||||
// " - Tổng ngày nghỉ sẽ dùng trong tháng: $willUsedDaysInMonth\n" .
|
||||
// " - Tổng ngày phép: $onleaveDaysTotal\n" .
|
||||
// " - Tổng ngày phép đã nghỉ: $usedOnleaveDaysTotal\n" .
|
||||
// " - Tổng ngày phép còn lại: $remainingOnleaveDays\n"
|
||||
// );
|
||||
|
||||
$onleave_days_will_use = 0; // Ngày phép sẽ dùng
|
||||
$nopay_days_will_use = 0; // Ngày ko phép sẽ dùng
|
||||
|
||||
// Ngày phép còn lại <= 0 (Hết phép)
|
||||
if ($remainingOnleaveDays <= 0) {
|
||||
$onleave_days_will_use = 0;
|
||||
$nopay_days_will_use = $willUsedDaysInMonth;
|
||||
|
||||
Log::debug("--- Hết phép trong tháng ---");
|
||||
}
|
||||
|
||||
// Ngày phép còn lại < ngày yêu cầu (Không đủ phép)
|
||||
else if ($remainingOnleaveDays < $willUsedDaysInMonth) {
|
||||
// Vượt limit
|
||||
if ($willUsedDaysInMonth > $maxDaysPerMonth) {
|
||||
// Phép còn lại > limit
|
||||
if ($remainingOnleaveDays > $maxDaysPerMonth) {
|
||||
$onleave_days_will_use = $maxDaysPerMonth;
|
||||
$nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth;
|
||||
}
|
||||
// Phép còn lại < limit
|
||||
else {
|
||||
$onleave_days_will_use = $remainingOnleaveDays;
|
||||
$nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays;
|
||||
}
|
||||
|
||||
Log::debug("--- Không đủ phép trong tháng, vượt quá limit ---",);
|
||||
}
|
||||
// Không vượt limit
|
||||
else {
|
||||
$onleave_days_will_use = $remainingOnleaveDays;
|
||||
$nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays;
|
||||
|
||||
Log::debug("--- Không đủ phép trong tháng, ko vượt limit ---");
|
||||
}
|
||||
}
|
||||
|
||||
// Ngày phép còn lại >= ngày yêu cầu (Đủ phép)
|
||||
else {
|
||||
// Vượt limit
|
||||
if ($willUsedDaysInMonth > $maxDaysPerMonth) {
|
||||
$onleave_days_will_use = $maxDaysPerMonth;
|
||||
$nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth;
|
||||
|
||||
Log::debug("--- Đủ phép, vượt limit ---");
|
||||
}
|
||||
// Không vượt limit
|
||||
else {
|
||||
$onleave_days_will_use = $willUsedDaysInMonth;
|
||||
$nopay_days_will_use = 0;
|
||||
|
||||
Log::debug("--- Đủ phép ---");
|
||||
}
|
||||
}
|
||||
|
||||
Log::debug("", [
|
||||
"Phep" => $onleave_days_will_use,
|
||||
"Khong Phep" => $nopay_days_will_use
|
||||
]);
|
||||
|
||||
// Có nghỉ không phép
|
||||
if ($nopay_days_will_use > 0) {
|
||||
foreach ($notes as $note) {
|
||||
$value = ($note->n_time_type === 'ALL') ? 1.0 : 0.5;
|
||||
|
||||
if ($note->n_time_type === 'ALL' && $onleave_days_will_use == 0.5) {
|
||||
// Chỉ còn 0.5 phép, chia thành 2 bản ghi: 1 phép, 1 không phép
|
||||
// Ưu tiên phép cho buổi sáng (S), không phép cho buổi chiều (C)
|
||||
|
||||
Notes::create([
|
||||
'n_user_id' => $user->id,
|
||||
'n_day' => $note->n_day,
|
||||
'n_month' => $note->n_month,
|
||||
'n_year' => $note->n_year,
|
||||
'n_time_type' => 'S',
|
||||
'n_reason' => 'ONLEAVE',
|
||||
'n_note' => $note->n_note,
|
||||
'ticket_id' => $note->ticket_id
|
||||
]);
|
||||
Notes::create([
|
||||
'n_user_id' => $user->id,
|
||||
'n_day' => $note->n_day,
|
||||
'n_month' => $note->n_month,
|
||||
'n_year' => $note->n_year,
|
||||
'n_time_type' => 'C',
|
||||
'n_reason' => 'LEAVE_WITHOUT_PAY',
|
||||
'n_note' => $note->n_note,
|
||||
'ticket_id' => $note->ticket_id
|
||||
]);
|
||||
|
||||
$note->delete();
|
||||
|
||||
$onleave_days_will_use = 0;
|
||||
$nopay_days_will_use -= 0.5;
|
||||
} elseif ($onleave_days_will_use > 0) {
|
||||
// Dùng ngày phép trước
|
||||
$use = min($onleave_days_will_use, $value);
|
||||
$note->update([
|
||||
'n_reason' => "ONLEAVE"
|
||||
]);
|
||||
$onleave_days_will_use -= $use;
|
||||
} elseif ($nopay_days_will_use > 0) {
|
||||
// Hết phép, chuyển sang không phép
|
||||
$use = min($nopay_days_will_use, $value);
|
||||
$note->update([
|
||||
'n_reason' => "LEAVE_WITHOUT_PAY"
|
||||
]);
|
||||
$nopay_days_will_use -= $use;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Đủ phép
|
||||
else {
|
||||
foreach ($notes as $note) {
|
||||
$note->update([
|
||||
'n_reason' => "ONLEAVE"
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getMaxLeaveDaysPerMonth(): int
|
||||
{
|
||||
$limitLeaveMonth = Category::where('c_type', 'LIMIT_LEAVE_MONTH')->where('c_code', "LIMIT")->first();
|
||||
if ($limitLeaveMonth) {
|
||||
$maxDaysPerMonth = (int)$limitLeaveMonth->c_value;
|
||||
} else {
|
||||
$maxDaysPerMonth = 3; // default nếu k có setting
|
||||
}
|
||||
return $maxDaysPerMonth;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('categories')->insert([
|
||||
[
|
||||
'c_code' => 'TEMPORARY_ONLEAVE',
|
||||
'c_name' => 'Nghỉ tạm trong tương lai',
|
||||
'c_type' => 'REASON_NOTES',
|
||||
'c_value' => "",
|
||||
'c_active' => 1,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('categories')->where('c_code', 'TEMPORARY_ONLEAVE')->delete();
|
||||
}
|
||||
};
|
||||
|
|
@ -21,7 +21,7 @@ import {
|
|||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { IconEdit, IconFileExcel } from '@tabler/icons-react'
|
||||
import { IconEdit, IconFileExcel, IconHelpCircle } from '@tabler/icons-react'
|
||||
import classes from './LeaveManagement.module.css'
|
||||
|
||||
import {
|
||||
|
|
@ -294,14 +294,17 @@ const LeaveManagement = () => {
|
|||
return monthInYear.map((d, i) => {
|
||||
let totalOnLeaveMonth = 0
|
||||
let totalLeaveWithoutPayMonth = 0
|
||||
let totalTempMonth = 0
|
||||
|
||||
monthlyLeaveDays
|
||||
.filter((item) => item.month === d.value)
|
||||
.map((item) => {
|
||||
if (item.reason_code === 'ONLEAVE') {
|
||||
totalOnLeaveMonth += Number(item.leave_days)
|
||||
} else {
|
||||
} else if (item.reason_code === 'LEAVE_WITHOUT_PAY') {
|
||||
totalLeaveWithoutPayMonth += Number(item.leave_days)
|
||||
} else {
|
||||
totalTempMonth += Number(item.leave_days)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -665,9 +668,11 @@ const LeaveManagement = () => {
|
|||
|
||||
let onleaveDaysInMonth: MonthlyLeaveDays[] = []
|
||||
let nopayDaysInMonth: MonthlyLeaveDays[] = []
|
||||
let tempDaysInMonth: MonthlyLeaveDays[] = []
|
||||
|
||||
let totalOnLeaveMonth = 0
|
||||
let totalLeaveWithoutPayMonth = 0
|
||||
let totalTempMonth = 0
|
||||
let usedAdditionalDay = 0
|
||||
|
||||
user.monthlyLeaveDays
|
||||
|
|
@ -676,9 +681,12 @@ const LeaveManagement = () => {
|
|||
if (item.reason_code === 'ONLEAVE') {
|
||||
totalOnLeaveMonth += Number(item.leave_days)
|
||||
onleaveDaysInMonth.push(item)
|
||||
} else {
|
||||
} else if (item.reason_code === 'LEAVE_WITHOUT_PAY') {
|
||||
totalLeaveWithoutPayMonth += Number(item.leave_days)
|
||||
nopayDaysInMonth.push(item)
|
||||
} else {
|
||||
totalTempMonth += Number(item.leave_days)
|
||||
tempDaysInMonth.push(item)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -703,6 +711,7 @@ const LeaveManagement = () => {
|
|||
return (
|
||||
<Table.Td
|
||||
bg={total > 0 ? '#ffb5b5' : ''}
|
||||
opacity={d.value > currentMonth ? 0.6 : 1}
|
||||
key={i}
|
||||
ta={'center'}
|
||||
>
|
||||
|
|
@ -757,10 +766,51 @@ const LeaveManagement = () => {
|
|||
</Stack>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{totalTempMonth > 0 && (
|
||||
<Box mt={6}>
|
||||
<Group align="center">
|
||||
<Text fw={500} c="blue" size="sm" mb={3}>
|
||||
Nghỉ dự kiến: {totalTempMonth}
|
||||
</Text>
|
||||
|
||||
<Tooltip
|
||||
multiline
|
||||
opened
|
||||
position="right"
|
||||
label={
|
||||
<Text size="xs">
|
||||
Ngày nghỉ đã được duyệt, sẽ tính phép
|
||||
khi đến tháng nghỉ.
|
||||
</Text>
|
||||
}
|
||||
offset={{ mainAxis: 15 }}
|
||||
>
|
||||
<Text fw={500} c="blue">
|
||||
<IconHelpCircle
|
||||
width={15}
|
||||
height={15}
|
||||
/>
|
||||
</Text>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<Stack gap={2} pl="md">
|
||||
{tempDaysInMonth?.map(
|
||||
(itemDay: any, indexDay: number) => (
|
||||
<Text size="xs" key={indexDay}>
|
||||
• {itemDay.time_type_name} (
|
||||
{itemDay.day}/{itemDay.month})
|
||||
</Text>
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<p>{total === 0 ? '' : total}</p>
|
||||
<Text size="sm">{total === 0 ? '' : total}</Text>
|
||||
</Tooltip>
|
||||
</Table.Td>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ const Tickets = () => {
|
|||
const [item, setItem] = useState({ id: 0 })
|
||||
const [activeBtn, setActiveBtn] = useState(false)
|
||||
const [disableBtn, setDisableBtn] = useState(false)
|
||||
const [isFetchData, setIsFetch] = useState(false)
|
||||
|
||||
const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
|
||||
const [dataReason, setDataReason] = useState<DataReason[]>([])
|
||||
|
|
@ -109,6 +110,8 @@ const Tickets = () => {
|
|||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setIsFetch(true)
|
||||
|
||||
const resultTimeType = await getListMasterByType('TIME_TYPE')
|
||||
setDataTimeType(
|
||||
resultTimeType.filter((item: DataTimeType) => item.c_code !== 'ALL'),
|
||||
|
|
@ -116,6 +119,8 @@ const Tickets = () => {
|
|||
|
||||
const resultReason = await getListMasterByType('REASON')
|
||||
setDataReason(resultReason)
|
||||
|
||||
setIsFetch(false)
|
||||
}
|
||||
|
||||
fetchData()
|
||||
|
|
@ -369,6 +374,7 @@ const Tickets = () => {
|
|||
setAction('add')
|
||||
form.reset()
|
||||
}}
|
||||
disabled={isFetchData}
|
||||
>
|
||||
+ Add
|
||||
</Button>
|
||||
|
|
@ -554,7 +560,8 @@ const Tickets = () => {
|
|||
if (confirmValues) {
|
||||
try {
|
||||
setConfirmLoading(true)
|
||||
action === 'add' && (await handleCreate(confirmValues, true))
|
||||
action === 'add' &&
|
||||
(await handleCreate(confirmValues, true))
|
||||
setConfirmLoading(false)
|
||||
setConfirmModal(false)
|
||||
} catch (error) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue