File "HolidayController.php"

Full Path: /home/trinadezambia/public_html/admin_panel/app/Http/Controllers/HolidayController.php
File size: 10.81 KB
MIME-type: text/x-php
Charset: utf-8

<?php

namespace App\Http\Controllers;

use App\Repositories\Holiday\HolidayInterface;
use App\Repositories\SessionYear\SessionYearInterface;
use App\Services\BootstrapTableService;
use App\Services\ResponseService;
use App\Services\CachingService;
use App\Models\StaffAttendance;
use App\Models\Leave;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Throwable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class HolidayController extends Controller
{

    private HolidayInterface $holiday;
    private SessionYearInterface $sessionYear;
    private CachingService $cache;

    public function __construct(HolidayInterface $holiday, SessionYearInterface $sessionYear, CachingService $cache)
    {
        $this->holiday = $holiday;
        $this->sessionYear = $sessionYear;
        $this->cache = $cache;
    }

    public function index()
    {
        ResponseService::noFeatureThenRedirect('Holiday Management');
        ResponseService::noPermissionThenRedirect('holiday-list');
        $current_sessionYear = $this->cache->getSessionYear();
        $months = sessionYearWiseMonth();
        $schoolSettings = $this->cache->getSchoolSettings();
        return view('holiday.index', compact('months', 'current_sessionYear', 'schoolSettings'));
    }


    public function store(Request $request)
    {
        ResponseService::noFeatureThenRedirect('Holiday Management');
        ResponseService::noPermissionThenRedirect('holiday-create');

        $validator = Validator::make($request->all(), [
            'date' => 'required|date',
            'title' => 'required|string',
        ]);

        if ($validator->fails()) {
            ResponseService::errorResponse($validator->errors()->first());
        }

        try {
            DB::beginTransaction();

            $sessionYear = $this->cache->getSessionYear();
            $schoolSettings = $this->cache->getSchoolSettings();

            $holidayDate = Carbon::parse($request->date)->startOfDay();
            $holidayYmd = $holidayDate->format('Y-m-d');

            $sessionStart = Carbon::createFromFormat(
                $schoolSettings['date_format'] ?? 'Y-m-d',
                $sessionYear->start_date
            )->startOfDay();

            $sessionEnd = Carbon::createFromFormat(
                $schoolSettings['date_format'] ?? 'Y-m-d',
                $sessionYear->end_date
            )->endOfDay();

            // 🔒 Ensure holiday date is inside session year
            if ($holidayDate->lt($sessionStart) || $holidayDate->gt($sessionEnd)) {
                ResponseService::errorResponse(
                    'The selected date must fall within the current session year.'
                );
            }

            // 🚫 Do not allow holiday if staff attendance already exists
            $staffAttendanceExists = StaffAttendance::whereDate('date', $holidayYmd)->exists();
            if ($staffAttendanceExists) {
                ResponseService::errorResponse(
                    'Cannot add holiday on a date with existing staff attendance records.'
                );
            }

            // 🔍 Find approved leaves overlapping the holiday
            $leaves = Leave::where('status', 1) // approved
                ->where('from_date', '<=', $holidayYmd)
                ->where('to_date', '>=', $holidayYmd)
                ->get();

            $notifyUsers = [];

            if ($leaves->isNotEmpty()) {

                foreach ($leaves as $leave) {

                    // Delete the specific leave detail for this holiday date
                    $leave->leave_detail()->whereDate('date', $holidayYmd)->delete();

                    // Check if any details remain for this leave
                    if ($leave->leave_detail()->count() == 0) {
                        $notifyUsers[] = $leave->user_id;

                        // Delete associated files if any
                        foreach ($leave->file as $file) {
                            if (Storage::disk('public')->exists($file->getRawOriginal('file_url'))) {
                                Storage::disk('public')->delete($file->getRawOriginal('file_url'));
                            }
                        }
                        $leave->file()->delete();

                        // If no details left, delete the main leave record
                        $leave->delete();
                    }
                }
            }

            // ✅ Create holiday
            $holiday = $this->holiday->create($request->all());

            // 🔔 Notify affected users
            if (!empty($notifyUsers)) {
                send_notification(
                    $notifyUsers,
                    'Leave Rejected',
                    'Your leave request has been rejected because the selected date range includes a holiday on ' .
                        $holidayDate->format('Y-m-d') .
                        '. Please revise and resubmit your request.',
                    'holiday_leave_rejection'
                );
            }

            DB::commit();
            ResponseService::successResponse('Holiday added successfully');
        } catch (Throwable $e) {
            DB::rollBack();
            ResponseService::logErrorResponse($e, "Holiday Controller -> Store Method");
            ResponseService::errorResponse();
        }
    }

    public function update($id, Request $request)
    {
        ResponseService::noFeatureThenRedirect('Holiday Management');
        ResponseService::noPermissionThenSendJson('holiday-edit');
        $validator = Validator::make($request->all(), ['date' => 'required', 'title' => 'required',]);

        if ($validator->fails()) {
            ResponseService::errorResponse($validator->errors()->first());
        }
        try {
            $sessionYear = $this->cache->getSessionYear();
            $schoolSettings = $this->cache->getSchoolSettings();

            $holidayDate = Carbon::parse($request->date)->startOfDay();

            $sessionStart = Carbon::createFromFormat(
                $schoolSettings['date_format'],
                $sessionYear->start_date
            )->startOfDay();

            $sessionEnd = Carbon::createFromFormat(
                $schoolSettings['date_format'],
                $sessionYear->end_date
            )->endOfDay();

            // 🔒 Ensure holiday date is inside session year
            if ($holidayDate->lt($sessionStart) || $holidayDate->gt($sessionEnd)) {
                ResponseService::errorResponse(
                    'The selected date must fall within the current session year.'
                );
            }
            $this->holiday->update($id, $request->all());
            ResponseService::successResponse('Data Updated Successfully');
        } catch (Throwable $e) {
            ResponseService::logErrorResponse($e, "Holiday Controller -> Update Method");
            ResponseService::errorResponse();
        }
    }

    // TODO : Remove this if not necessary
    // public function holiday_view()
    // {
    //     return view('holiday.list');
    // }

    public function show(Request $request)
    {
        ResponseService::noFeatureThenRedirect('Holiday Management');
        ResponseService::noPermissionThenRedirect('holiday-list');
        $offset = request('offset', 0);
        $limit = request('limit', 10);
        $sort = request('sort', 'id');
        $order = request('order', 'DESC');
        $search = request('search');
        $session_year_id = $this->cache->getSessionYear()->id;
        $month = request('month');

        $sessionYear = $this->sessionYear->findById($session_year_id);
        $schoolSettings = $this->cache->getSchoolSettings();

        $sql = $this->holiday->builder()
            ->where(function ($query) use ($search) {
                $query->when($search, function ($query) use ($search) {
                    $query->where(function ($query) use ($search) {
                        $query->where('id', 'LIKE', "%$search%")->orwhere('title', 'LIKE', "%$search%")->orwhere('description', 'LIKE', "%$search%")->orwhere('date', 'LIKE', "%$search%");
                    });
                });
            })->when($session_year_id, function ($query) use ($sessionYear, $schoolSettings) {
                $query->whereDate('date', '>=', Carbon::createFromFormat($schoolSettings['date_format'], $sessionYear->start_date))
                    ->whereDate('date', '<=', Carbon::createFromFormat($schoolSettings['date_format'], $sessionYear->end_date));
            })->when($month, function ($query) use ($month) {
                $query->whereMonth('date', $month);
            });

        $total = $sql->count();
        if ($offset >= $total && $total > 0) {
            $lastPage = floor(($total - 1) / $limit) * $limit; // calculate last page offset
            $offset = $lastPage;
        }
        $sql->orderBy($sort, $order)->skip($offset)->take($limit);
        $res = $sql->get();

        $bulkData = array();
        $bulkData['total'] = $total;
        $rows = array();
        $no = 1;
        foreach ($res as $row) {
            $operate = BootstrapTableService::editButton(route('holiday.update', $row->id));
            $operate .= BootstrapTableService::deleteButton(route('holiday.destroy', $row->id));
            $tempRow = $row->toArray();
            $tempRow['no'] = $no++;
            // $tempRow['date'] = format_date($row->date);
            $tempRow['operate'] = $operate;
            $rows[] = $tempRow;
        }
        $bulkData['rows'] = $rows;
        return response()->json($bulkData);
    }

    public function destroy($id)
    {
        ResponseService::noFeatureThenRedirect('Holiday Management');
        ResponseService::noPermissionThenSendJson('holiday-delete');
        try {
            $this->holiday->deleteById($id);
            ResponseService::successResponse('Data Deleted Successfully');
        } catch (Throwable $e) {
            ResponseService::logErrorResponse($e, "Holiday Controller -> Delete Method");
            ResponseService::errorResponse();
        }
    }

    public function checkApprovedLeaves(Request $request)
    {
        try {
            $date = Carbon::parse($request->date)->format('Y-m-d');
            $approvedLeavesCount = Leave::whereIn('status',     [0, 1]) // Approved
                ->where('from_date', '<=', $date)
                ->where('to_date', '>=', $date)
                ->count();

            return response()->json([
                'error' => false,
                'count' => $approvedLeavesCount,
                'message' => $approvedLeavesCount > 0 ? "There are {$approvedLeavesCount} leaves on this date." : ''
            ]);
        } catch (Throwable $e) {
            ResponseService::logErrorResponse($e, "Holiday Controller -> Check Approved Leaves Method");
            return response()->json(['error' => true, 'message' => 'Something went wrong']);
        }
    }
}