diff --git a/app/Helpers/NotificationHelper.php b/app/Helpers/NotificationHelper.php index 7e541ce..f9c3ed6 100644 --- a/app/Helpers/NotificationHelper.php +++ b/app/Helpers/NotificationHelper.php @@ -6,7 +6,7 @@ use InvalidArgumentException; class NotificationHelper { - public static function newExpense($user_id, $expense_number, $receiver_ids = []) + public static function newExpense($expense_type, $expense_id, $user_id, $expense_number, $receiver_ids = []) { if (!is_array($receiver_ids) || empty($receiver_ids)) { throw new InvalidArgumentException('Receiver IDs must be a non-empty array.'); @@ -22,6 +22,8 @@ class NotificationHelper 'content' => 'You have new expense waiting for approval (' . $expense_number . ')', 'is_read' => 0, 'type' => 'new_expense', + 'expense_type' => $expense_type, + 'expense_id' => $expense_id, 'created_at' => now(), 'updated_at' => now(), ]; @@ -31,7 +33,7 @@ class NotificationHelper Notifications::insert($notifications); } - public static function approveExpense($user_id, $expense_number, $receiver_ids = []) + public static function approveExpense($expense_type, $expense_id, $user_id, $expense_number, $receiver_ids = []) { if (!is_array($receiver_ids) || empty($receiver_ids)) { throw new InvalidArgumentException('Receiver IDs must be a non-empty array.'); @@ -47,6 +49,8 @@ class NotificationHelper 'content' => 'You have new expense waiting for second approval (' . $expense_number . ')', 'is_read' => 0, 'type' => 'approve_expense', + 'expense_type' => $expense_type, + 'expense_id' => $expense_id, 'created_at' => now(), 'updated_at' => now(), ]; @@ -56,7 +60,7 @@ class NotificationHelper Notifications::insert($notifications); } - public static function approve2Expense($user_id, $expense_number, $receiver_ids = []) + public static function approve2Expense($expense_type, $expense_id, $user_id, $expense_number, $receiver_ids = []) { if (!is_array($receiver_ids) || empty($receiver_ids)) { throw new InvalidArgumentException('Receiver IDs must be a non-empty array.'); @@ -72,6 +76,8 @@ class NotificationHelper 'content' => 'You have new expense waiting for final approval (' . $expense_number . ')', 'is_read' => 0, 'type' => 'approve2_expense', + 'expense_type' => $expense_type, + 'expense_id' => $expense_id, 'created_at' => now(), 'updated_at' => now(), ]; diff --git a/app/Http/Controllers/Backend/AdminsController.php b/app/Http/Controllers/Backend/AdminsController.php index f178c3d..ce3b021 100644 --- a/app/Http/Controllers/Backend/AdminsController.php +++ b/app/Http/Controllers/Backend/AdminsController.php @@ -20,6 +20,7 @@ use App\Models\FormMeetingSeminar; use App\Models\UserHasCabang; use App\Models\Cabang; use App\Helpers\AuditTrailHelper; +use App\Models\Region; class AdminsController extends Controller { @@ -35,7 +36,7 @@ class AdminsController extends Controller 'path' => url()->current() ]; - $admins = Admin::with(['region', 'cabang', 'roles'])->get(); + $admins = Admin::with(['region', 'cabang', 'roles', 'getRayon', 'getRegion'])->get(); return view('backend.pages.admins.index', [ 'admins' => $admins, 'pageInfo' => $pageInfo, @@ -55,7 +56,7 @@ class AdminsController extends Controller return view('backend.pages.admins.create', [ 'roles' => Role::all(), 'pageInfo' => $pageInfo, - 'cabangs' => Cabang::all() + 'regions' => Region::all(), ]); } @@ -63,15 +64,16 @@ class AdminsController extends Controller { $this->checkAuthorization(auth()->user(), ['admin.create']); - $admin = new Admin(); - $admin->name = $request->name; - $admin->password = Hash::make($request->password); - $admin->username = $request->username; - $admin->email = $request->email; - $admin->phone = $request->phone; - $admin->save(); + $admin = Admin::create([ + 'name' => $request->name, + 'password' => Hash::make($request->password), + 'username' => $request->username, + 'email' => $request->email, + 'phone' => $request->phone, + 'region_id' => $request->region_id ? $request->region_id : null, + 'rayon_id' => $request->rayon_id ? $request->rayon_id : null, + ])->assignRole($request->roles); - // Assign the user to a cabang if($request->cabang_id) { UserHasCabang::create([ 'user_id' => $admin->id, @@ -79,21 +81,6 @@ class AdminsController extends Controller ]); } - if ($request->roles) { - $admin->assignRole($request->roles); - } - - // Create a folder in Nextcloud - // $response = NextcloudHelper::createUser(env('NEXT_CLOUD_URL'), env('NEXT_CLOUD_USERNAME'), env('NEXT_CLOUD_PASSWORD'), $request->username, $request->password, $request->name, $request->email); - - // if ($response['success']) { - // session()->flash('success', __('Admin has been created.')); - // return redirect()->route('admin.admins.index'); - // } else { - // session()->flash('error', $response['message']); - // return redirect()->route('admin.admins.index'); - // } - AuditTrailHelper::AddAuditTrail('Insert', 'Added New User (' . $request->email . ') to the User Table'); session()->flash('success', 'Admin has been created.'); return redirect()->back(); @@ -115,29 +102,33 @@ class AdminsController extends Controller 'admin' => $admin, 'roles' => Role::all(), 'pageInfo' => $pageInfo, - 'cabangs' => Cabang::all() + 'regions' => Region::all(), ]); } public function update(AdminRequest $request, int $id): RedirectResponse { $this->checkAuthorization(auth()->user(), ['admin.edit']); - $admin = Admin::findOrFail($id); - $admin->name = $request->name; - $admin->email = $request->email; - $admin->username = $request->username; - $admin->phone = $request->phone; - - if ($request->password) { - $admin->password = Hash::make($request->password); - } - $admin->save(); + $admin->update([ + 'name' => $request->name, + 'email' => $request->email, + 'username' => $request->username, + 'phone' => $request->phone, + 'region_id' => $request->region_id ? $request->region_id : null, + 'rayon_id' => $request->rayon_id ? $request->rayon_id : null, + ]); + $admin->roles()->detach(); if ($request->roles) { $admin->assignRole($request->roles); } + if ($request->password) { + $admin->password = Hash::make($request->password); + $admin->save(); + } + // Update the user's cabang if($request->cabang_id) { $userHasCabang = UserHasCabang::where('user_id', $admin->id)->first(); diff --git a/app/Http/Controllers/Backend/DashboardController.php b/app/Http/Controllers/Backend/DashboardController.php index 2ec0739..101c18b 100644 --- a/app/Http/Controllers/Backend/DashboardController.php +++ b/app/Http/Controllers/Backend/DashboardController.php @@ -22,36 +22,28 @@ class DashboardController extends Controller public function index() { $role = auth()->user()->getRoleNames()[0]; - $closing_date = env('CLOSING_DATE'); + $startDate = date('Y-m-' . env('STARTING_DATE')); // Starting date from .env for the current month + $closingDateNextMonth = date('Y-m-', strtotime('+1 month')) . env('CLOSING_DATE'); // Closing date for the next month + $forms = [ 'vehicle' => FormVehicleRunningCost::whereMonth('tanggal', date('m')) - ->whereYear('tanggal', date('Y')) - ->where('tanggal', '<=', date('Y-m-'.$closing_date)) - ->whereRaw('DAY(CURDATE()) <= '.$closing_date) + ->whereBetween('tanggal', [$startDate, $closingDateNextMonth]) ->orderBy('tanggal', 'desc') ->get(), 'upcountry' => FormUpCountry::whereMonth('tanggal', date('m')) - ->whereYear('tanggal', date('Y')) - ->where('tanggal', '<=', date('Y-m-'.$closing_date)) - ->whereRaw('DAY(CURDATE()) <= '.$closing_date) + ->whereBetween('tanggal', [$startDate, $closingDateNextMonth]) ->orderBy('tanggal', 'desc') ->get(), 'entertainment' => FormEntertaimentPresentation::whereMonth('tanggal', date('m')) - ->whereYear('tanggal', date('Y')) - ->where('tanggal', '<=', date('Y-m-'.$closing_date)) - ->whereRaw('DAY(CURDATE()) <= '.$closing_date) + ->whereBetween('tanggal', [$startDate, $closingDateNextMonth]) ->orderBy('tanggal', 'desc') ->get(), 'meeting' => FormMeetingSeminar::whereMonth('created_at', date('m')) - ->whereYear('created_at', date('Y')) - ->where('created_at', '<=', date('Y-m-'.$closing_date)) - ->whereRaw('DAY(CURDATE()) <= '.$closing_date) + ->whereBetween('created_at', [$startDate, $closingDateNextMonth]) ->orderBy('created_at', 'desc') ->get(), 'others' => FormOthers::whereMonth('tanggal', date('m')) - ->whereYear('tanggal', date('Y')) - ->where('tanggal', '<=', date('Y-m-'.$closing_date)) - ->whereRaw('DAY(CURDATE()) <= '.$closing_date) + ->whereBetween('tanggal', [$startDate, $closingDateNextMonth]) ->orderBy('tanggal', 'desc') ->get(), ]; @@ -117,14 +109,24 @@ class DashboardController extends Controller ]); } - public function mark_read() + public function mark_read($id) + { + $this->checkAuthorization(auth()->user(), ['notification.delete']); + $receiver_id = auth()->user()->id; + + Notifications::where('receiver_id', $receiver_id)->where('id', $id)->update(['is_read' => 1]); + + return response()->json(['message' => 'Notification marked as read.']); + } + + public function mark_all_read() { $this->checkAuthorization(auth()->user(), ['notification.delete']); $receiver_id = auth()->user()->id; Notifications::where('receiver_id', $receiver_id)->update(['is_read' => 1]); - session()->flash('success', 'Notifications marked as read.'); + session()->flash('success', 'All notifications marked as read.'); return redirect()->back(); } } diff --git a/app/Http/Controllers/Forms/FormEntertainmentPresentationController.php b/app/Http/Controllers/Forms/FormEntertainmentPresentationController.php index c0bb882..d5a2c6d 100644 --- a/app/Http/Controllers/Forms/FormEntertainmentPresentationController.php +++ b/app/Http/Controllers/Forms/FormEntertainmentPresentationController.php @@ -26,6 +26,7 @@ use App\Models\Admin; use App\Rules\FileType; use App\Helpers\BudgetHelper; use App\Helpers\NotificationHelper; +use Illuminate\Support\Facades\Log; class FormEntertainmentPresentationController extends Controller { @@ -220,15 +221,22 @@ class FormEntertainmentPresentationController extends Controller WhatsappHelper::newExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseCreated( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseCreated( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::newExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::newExpense('entertainment-presentation', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Insert', 'Insert New Expense at Form Entertainment Presentation (' . $expense_number . ')'); session()->flash('success', 'Form has been created.'); @@ -321,6 +329,7 @@ class FormEntertainmentPresentationController extends Controller 'approved_at' => now(), 'approved_by' => auth()->user()->id, 'status' => 'Approved 1', + 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -364,15 +373,22 @@ class FormEntertainmentPresentationController extends Controller WhatsappHelper::approveExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approveExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approveExpense('entertainment-presentation', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Entertainment (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); @@ -431,22 +447,29 @@ class FormEntertainmentPresentationController extends Controller WhatsappHelper::approve2Expense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved2( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved2( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approve2Expense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approve2Expense('entertainment-presentation', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Entertainment (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); return redirect()->back(); } - public function finalApprove(Request $request, $id) + public function finalApprove($id) { $this->checkAuthorization(auth()->user(), ['final_approval.approve']); @@ -458,8 +481,8 @@ class FormEntertainmentPresentationController extends Controller // Check if the total nominal exceeds the available budget $cabang_id = UserHasCabang::where('user_id', $form->user_id)->first()->cabang_id; - if($form->total > BudgetHelper::getAvailableBudget($cabang_id)) { - session()->flash('error', 'The total nominal exceeds the available budget.'); + if($form->approved_total > BudgetHelper::getAvailableBudget($cabang_id)) { + session()->flash('error', 'Budget cabang untuk periode ini tidak mencukupi, silahkan ajukan pada periode expense berikutnya'); return redirect()->back(); } @@ -467,7 +490,6 @@ class FormEntertainmentPresentationController extends Controller 'final_approved_at' => now(), 'final_approved_by' => auth()->user()->id, 'status' => 'Closed', - 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -506,13 +528,20 @@ class FormEntertainmentPresentationController extends Controller WhatsappHelper::finalApprove($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new FinalApprove( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new FinalApprove( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Final Approve', 'Final Approve Expense at Form Entertainment (' . $form->expense_number . ')'); session()->flash('success', 'Form has been final approved.'); @@ -557,13 +586,20 @@ class FormEntertainmentPresentationController extends Controller WhatsappHelper::rejectExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseRejected( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseRejected( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Reject', 'Reject Expense at Form Entertainment (' . $form->expense_number . ')'); session()->flash('success', 'Form has been rejected.'); diff --git a/app/Http/Controllers/Forms/FormMeetingSeminarController.php b/app/Http/Controllers/Forms/FormMeetingSeminarController.php index ebcf7d5..8b2a2d8 100644 --- a/app/Http/Controllers/Forms/FormMeetingSeminarController.php +++ b/app/Http/Controllers/Forms/FormMeetingSeminarController.php @@ -26,6 +26,7 @@ use App\Rules\FileType; use App\Models\Admin; use App\Helpers\BudgetHelper; use App\Helpers\NotificationHelper; +use Illuminate\Support\Facades\Log; class FormMeetingSeminarController extends Controller { @@ -254,15 +255,22 @@ class FormMeetingSeminarController extends Controller WhatsappHelper::newExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseCreated( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseCreated( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::newExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::newExpense('meeting-seminar', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Insert', 'Insert New Expense at Form Meeting Seminar (' . $expense_number . ')'); session()->flash('success', 'Form has been created.'); @@ -380,15 +388,26 @@ class FormMeetingSeminarController extends Controller return redirect()->back(); } - public function approve($id) + public function approve(Request $request, $id) { $this->checkAuthorization(auth()->user(), ['approval.approve']); $form = FormMeetingSeminar::findOrfail($id); + + $approved_data = [ + 'allowance' => $request->allowance ? $form->allowance : 0, + 'transport_ankot' => $request->transport_ankot ? $form->transport_ankot : 0, + 'hotel' => $request->hotel ? $form->hotel : 0, + ]; + $form->update([ 'approved_at' => now(), 'approved_by' => auth()->user()->id, 'status' => 'Approved 1', + 'approved_allowance' => $approved_data['allowance'], + 'approved_transport_ankot' => $approved_data['transport_ankot'], + 'approved_hotel' => $approved_data['hotel'], + 'approved_total' => array_sum($approved_data), ]); $name = $form->user->name; @@ -432,15 +451,22 @@ class FormMeetingSeminarController extends Controller WhatsappHelper::approveExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approveExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approveExpense('meeting-seminar', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Meeting Seminar (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); @@ -499,22 +525,29 @@ class FormMeetingSeminarController extends Controller WhatsappHelper::approve2Expense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved2( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved2( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approve2Expense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approve2Expense('meeting-seminar', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Meeting Seminar (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); return redirect()->back(); } - public function finalApprove(Request $request, $id) + public function finalApprove($id) { $this->checkAuthorization(auth()->user(), ['final_approval.approve']); @@ -524,16 +557,10 @@ class FormMeetingSeminarController extends Controller return redirect()->back(); } - $approved_data = [ - 'allowance' => $request->allowance ? $form->allowance : 0, - 'transport_ankot' => $request->transport_ankot ? $form->transport_ankot : 0, - 'hotel' => $request->hotel ? $form->hotel : 0, - ]; - // Check if the total nominal exceeds the available budget $cabang_id = UserHasCabang::where('user_id', $form->user_id)->first()->cabang_id; - if(array_sum($approved_data) > BudgetHelper::getAvailableBudget($cabang_id)) { - session()->flash('error', 'The total nominal exceeds the available budget.'); + if($form->approved_total > BudgetHelper::getAvailableBudget($cabang_id)) { + session()->flash('error', 'Budget cabang untuk periode ini tidak mencukupi, silahkan ajukan pada periode expense berikutnya'); return redirect()->back(); } @@ -541,10 +568,6 @@ class FormMeetingSeminarController extends Controller 'final_approved_at' => now(), 'final_approved_by' => auth()->user()->id, 'status' => 'Closed', - 'approved_allowance' => $approved_data['allowance'], - 'approved_transport_ankot' => $approved_data['transport_ankot'], - 'approved_hotel' => $approved_data['hotel'], - 'approved_total' => array_sum($approved_data), ]); $name = $form->user->name; @@ -583,13 +606,20 @@ class FormMeetingSeminarController extends Controller WhatsappHelper::finalApprove($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new FinalApprove( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new FinalApprove( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Final Approve', 'Final Approve Expense at Form Meeting Seminar (' . $form->expense_number . ')'); session()->flash('success', 'Form has been final approved.'); @@ -634,13 +664,20 @@ class FormMeetingSeminarController extends Controller WhatsappHelper::rejectExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseRejected( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseRejected( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Reject', 'Reject Expense at Form Meeting Seminar (' . $form->expense_number . ')'); session()->flash('success', 'Form has been rejected.'); diff --git a/app/Http/Controllers/Forms/FormOtherController.php b/app/Http/Controllers/Forms/FormOtherController.php index 53b8155..f39bcba 100644 --- a/app/Http/Controllers/Forms/FormOtherController.php +++ b/app/Http/Controllers/Forms/FormOtherController.php @@ -22,6 +22,7 @@ use App\Rules\FileType; use App\Models\Admin; use App\Helpers\BudgetHelper; use App\Helpers\NotificationHelper; +use Illuminate\Support\Facades\Log; class FormOtherController extends Controller { @@ -214,16 +215,23 @@ class FormOtherController extends Controller WhatsappHelper::newExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseCreated( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseCreated( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } // Send notification to the user - NotificationHelper::newExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::newExpense('other', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Insert', 'Insert New Expense at Form Other (' . $expense_number . ')'); session()->flash('success', 'Form has been created.'); @@ -311,6 +319,7 @@ class FormOtherController extends Controller 'approved_at' => now(), 'approved_by' => auth()->user()->id, 'status' => 'Approved 1', + 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -354,15 +363,22 @@ class FormOtherController extends Controller WhatsappHelper::approveExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approveExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approveExpense('other', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Other (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); @@ -421,22 +437,29 @@ class FormOtherController extends Controller WhatsappHelper::approve2Expense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved2( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved2( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approve2Expense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approve2Expense('other', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Other (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); return redirect()->back(); } - public function finalApprove(Request $request, $id) + public function finalApprove($id) { $this->checkAuthorization(auth()->user(), ['final_approval.approve']); @@ -448,8 +471,8 @@ class FormOtherController extends Controller // Check if the total nominal exceeds the available budget $cabang_id = UserHasCabang::where('user_id', $form->user_id)->first()->cabang_id; - if($form->total > BudgetHelper::getAvailableBudget($cabang_id)) { - session()->flash('error', 'The total nominal exceeds the available budget.'); + if($form->approved_total > BudgetHelper::getAvailableBudget($cabang_id)) { + session()->flash('error', 'Budget cabang untuk periode ini tidak mencukupi, silahkan ajukan pada periode expense berikutnya'); return redirect()->back(); } @@ -457,7 +480,6 @@ class FormOtherController extends Controller 'final_approved_at' => now(), 'final_approved_by' => auth()->user()->id, 'status' => 'Closed', - 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -496,13 +518,20 @@ class FormOtherController extends Controller WhatsappHelper::finalApprove($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new FinalApprove( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new FinalApprove( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Final Approve', 'Final Approve Expense at Form Other (' . $form->expense_number . ')'); session()->flash('success', 'Form has been final approved.'); @@ -547,13 +576,20 @@ class FormOtherController extends Controller WhatsappHelper::rejectExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseRejected( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseRejected( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Reject', 'Reject Expense at Form Other (' . $form->expense_number . ')'); session()->flash('success', 'Form has been rejected.'); diff --git a/app/Http/Controllers/Forms/FormUpCountryController.php b/app/Http/Controllers/Forms/FormUpCountryController.php index 277a24d..6ccb2e5 100644 --- a/app/Http/Controllers/Forms/FormUpCountryController.php +++ b/app/Http/Controllers/Forms/FormUpCountryController.php @@ -26,6 +26,7 @@ use App\Rules\FileType; use App\Models\Admin; use App\Helpers\BudgetHelper; use App\Helpers\NotificationHelper; +use Illuminate\Support\Facades\Log; class FormUpCountryController extends Controller { @@ -285,15 +286,22 @@ class FormUpCountryController extends Controller WhatsappHelper::newExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseCreated( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseCreated( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::newExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::newExpense('up-country', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Insert', 'Insert New Expense at Form Up Country (' . $expense_number . ')'); session()->flash('success', 'Form has been created.'); @@ -439,15 +447,29 @@ class FormUpCountryController extends Controller return redirect()->back(); } - public function approve($id) + public function approve(Request $request, $id) { $this->checkAuthorization(auth()->user(), ['approval.approve']); $form = FormUpCountry::findOrfail($id); + + $approved_data = [ + 'allowance' => $request->allowance ? $form->allowance : 0, + 'transport_dalkot' => $request->transport_dalkot ? $form->transport_dalkot : 0, + 'transport_ankot' => $request->transport_ankot ? $form->transport_ankot : 0, + 'hotel' => $request->hotel ? $form->hotel : 0, + ]; + $form->update([ 'approved_at' => now(), 'approved_by' => auth()->user()->id, 'status' => 'Approved 1', + + 'approved_allowance' => $approved_data['allowance'], + 'approved_transport_dalkot' => $approved_data['transport_dalkot'], + 'approved_transport_ankot' => $approved_data['transport_ankot'], + 'approved_hotel' => $approved_data['hotel'], + 'approved_total' => array_sum($approved_data), ]); $name = $form->user->name; @@ -490,16 +512,22 @@ class FormUpCountryController extends Controller $url = route('forms.up-country.view', $form->id); WhatsappHelper::approveExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); - // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approveExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approveExpense('up-country', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Up Country (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); @@ -557,22 +585,29 @@ class FormUpCountryController extends Controller WhatsappHelper::approve2Expense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved2( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved2( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approve2Expense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approve2Expense('up-country', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Up Country (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); return redirect()->back(); } - public function finalApprove(Request $request, $id) + public function finalApprove($id) { $this->checkAuthorization(auth()->user(), ['final_approval.approve']); @@ -582,17 +617,10 @@ class FormUpCountryController extends Controller return redirect()->back(); } - $approved_data = [ - 'allowance' => $request->allowance ? $form->allowance : 0, - 'transport_dalkot' => $request->transport_dalkot ? $form->transport_dalkot : 0, - 'transport_ankot' => $request->transport_ankot ? $form->transport_ankot : 0, - 'hotel' => $request->hotel ? $form->hotel : 0, - ]; - // Check if the total nominal exceeds the available budget $cabang_id = UserHasCabang::where('user_id', $form->user_id)->first()->cabang_id; - if(array_sum($approved_data) > BudgetHelper::getAvailableBudget($cabang_id)) { - session()->flash('error', 'The total nominal exceeds the available budget.'); + if($form->approved_total > BudgetHelper::getAvailableBudget($cabang_id)) { + session()->flash('error', 'Budget cabang untuk periode ini tidak mencukupi, silahkan ajukan pada periode expense berikutnya'); return redirect()->back(); } @@ -600,11 +628,6 @@ class FormUpCountryController extends Controller 'final_approved_at' => now(), 'final_approved_by' => auth()->user()->id, 'status' => 'Closed', - 'approved_allowance' => $approved_data['allowance'], - 'approved_transport_dalkot' => $approved_data['transport_dalkot'], - 'approved_transport_ankot' => $approved_data['transport_ankot'], - 'approved_hotel' => $approved_data['hotel'], - 'approved_total' => array_sum($approved_data), ]); $name = $form->user->name; @@ -643,13 +666,20 @@ class FormUpCountryController extends Controller WhatsappHelper::finalApprove($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new FinalApprove( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new FinalApprove( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Final Approve', 'Final Approve Expense at Form Up Country (' . $form->expense_number . ')'); session()->flash('success', 'Form has been final approved.'); @@ -694,13 +724,20 @@ class FormUpCountryController extends Controller WhatsappHelper::rejectExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseRejected( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseRejected( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Reject', 'Reject Expense at Form Up Country (' . $form->expense_number . ')'); session()->flash('success', 'Form has been rejected.'); diff --git a/app/Http/Controllers/Forms/FormVehicleController.php b/app/Http/Controllers/Forms/FormVehicleController.php index 7acea32..41568b8 100644 --- a/app/Http/Controllers/Forms/FormVehicleController.php +++ b/app/Http/Controllers/Forms/FormVehicleController.php @@ -26,6 +26,7 @@ use App\Rules\FileType; use App\Models\Admin; use App\Helpers\BudgetHelper; use App\Helpers\NotificationHelper; +use Illuminate\Support\Facades\Log; class FormVehicleController extends Controller { @@ -158,7 +159,6 @@ class FormVehicleController extends Controller $bukti_total->getContent(), $filename ); - } // Generate sequence number and expense number @@ -222,15 +222,22 @@ class FormVehicleController extends Controller WhatsappHelper::newExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseCreated( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseCreated( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::newExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::newExpense('vehicle-running-cost', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Insert', 'Insert New Expense at Form Vehicle Running Cost (' . $expense_number . ')'); session()->flash('success', 'Form has been created.'); @@ -324,6 +331,7 @@ class FormVehicleController extends Controller 'approved_at' => now(), 'approved_by' => auth()->user()->id, 'status' => 'Approved 1', + 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -367,15 +375,22 @@ class FormVehicleController extends Controller WhatsappHelper::approveExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approveExpense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approveExpense('vehicle-running-cost', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Vehicle Running Cost (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); @@ -434,22 +449,29 @@ class FormVehicleController extends Controller WhatsappHelper::approve2Expense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // // Send bulk email - Mail::to($recipients)->send(new ExpenseApproved2( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseApproved2( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } - NotificationHelper::approve2Expense($form->user_id, $expense_number, $receiver_ids); + NotificationHelper::approve2Expense('vehicle-running-cost', $form->id, $form->user_id, $expense_number, $receiver_ids); AuditTrailHelper::AddAuditTrail('Approve', 'Approve Expense at Form Vehicle Running Cost (' . $form->expense_number . ')'); session()->flash('success', 'Form has been approved.'); return redirect()->back(); } - public function finalApprove(Request $request, $id) + public function finalApprove($id) { $this->checkAuthorization(auth()->user(), ['final_approval.approve']); @@ -461,8 +483,8 @@ class FormVehicleController extends Controller // Check if the total nominal exceeds the available budget $cabang_id = UserHasCabang::where('user_id', $form->user_id)->first()->cabang_id; - if($form->total > BudgetHelper::getAvailableBudget($cabang_id)) { - session()->flash('error', 'The total nominal exceeds the available budget.'); + if($form->approved_total > BudgetHelper::getAvailableBudget($cabang_id)) { + session()->flash('error', 'Budget cabang untuk periode ini tidak mencukupi, silahkan ajukan pada periode expense berikutnya'); return redirect()->back(); } @@ -470,7 +492,6 @@ class FormVehicleController extends Controller 'final_approved_at' => now(), 'final_approved_by' => auth()->user()->id, 'status' => 'Closed', - 'approved_total' => $form->total, ]); $name = $form->user->name; @@ -509,13 +530,20 @@ class FormVehicleController extends Controller WhatsappHelper::finalApprove($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new FinalApprove( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new FinalApprove( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Final Approve', 'Final Approve Expense at Form Vehicle Running Cost (' . $form->expense_number . ')'); session()->flash('success', 'Form has been final approved.'); @@ -560,13 +588,20 @@ class FormVehicleController extends Controller WhatsappHelper::rejectExpense($phoneNumbers, $expense_number, $url, $tanggal, $total, $name); // Send bulk email - Mail::to($recipients)->send(new ExpenseRejected( - $name, - $expense_number, - $tanggal, - $total, - $url - )); + foreach ($recipients as $recipient) { + try { + Mail::to($recipient)->send(new ExpenseRejected( + $name, + $expense_number, + $tanggal, + $total, + $url + )); + } catch (\Exception $e) { + Log::error("Failed to send email to {$recipient}: " . $e->getMessage()); + continue; + } + } AuditTrailHelper::AddAuditTrail('Reject', 'Reject Expense at Form Vehicle Running Cost (' . $form->expense_number . ')'); session()->flash('success', 'Form has been rejected.'); diff --git a/app/Http/Controllers/Master/CabangController.php b/app/Http/Controllers/Master/CabangController.php index 09b4fe7..e4313d1 100644 --- a/app/Http/Controllers/Master/CabangController.php +++ b/app/Http/Controllers/Master/CabangController.php @@ -9,6 +9,7 @@ use App\Helpers\AuditTrailHelper; use App\Models\Admin; use App\Models\CostCentre; use App\Models\Region; +use App\Models\Rayon; class CabangController extends Controller { @@ -29,6 +30,25 @@ class CabangController extends Controller return response()->json($cabang); } + public function getRayonByCabang($cabangCode) + { + $cabang_id = Cabang::where('code', $cabangCode)->first()->id; + $rayon = Rayon::where('cabang_id', $cabang_id)->get(['code', 'name']); + return response()->json($rayon); + } + + public function getCabangByRegionId($regionId) + { + $cabang = Cabang::where('region_id', $regionId)->get(); + return response()->json($cabang); + } + + public function getRayonByCabangId($cabangId) + { + $rayon = Rayon::where('cabang_id', $cabangId)->get(); + return response()->json($rayon); + } + public function create() { $this->checkAuthorization(auth()->user(), ['cabang.create']); diff --git a/app/Models/Admin.php b/app/Models/Admin.php index 323b55a..f100981 100644 --- a/app/Models/Admin.php +++ b/app/Models/Admin.php @@ -29,7 +29,7 @@ class Admin extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', + 'username', 'name', 'email', 'password', 'region_id', 'rayon_id', 'phone' ]; /** @@ -163,6 +163,16 @@ class Admin extends Authenticatable return $this->hasOne(UserHasCabang::class, 'user_id')->with('cabang.region'); } + public function getRayon() + { + return $this->belongsTo(Rayon::class, 'rayon_id'); + } + + public function getRegion() + { + return $this->belongsTo(Region::class, 'region_id'); + } + public static function getUserByRoleName($roleName) { $role = Role::where('name', $roleName)->first(); diff --git a/app/Models/Notifications.php b/app/Models/Notifications.php index e98bfba..3b9ef1e 100644 --- a/app/Models/Notifications.php +++ b/app/Models/Notifications.php @@ -14,6 +14,8 @@ class Notifications extends Model 'content', 'is_read', 'type', + 'expense_type', + 'expense_id', 'created_at', 'updated_at' ]; diff --git a/config/mail.php b/config/mail.php index df13d3d..d196778 100644 --- a/config/mail.php +++ b/config/mail.php @@ -47,6 +47,7 @@ return [ 'password' => env('MAIL_PASSWORD'), 'timeout' => null, 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)), + 'throw' => false, ], 'ses' => [ diff --git a/database/migrations/2025_01_23_080737_add_region_id_and_rayon_id_to_admins_table.php b/database/migrations/2025_01_23_080737_add_region_id_and_rayon_id_to_admins_table.php new file mode 100644 index 0000000..693eb37 --- /dev/null +++ b/database/migrations/2025_01_23_080737_add_region_id_and_rayon_id_to_admins_table.php @@ -0,0 +1,30 @@ +foreignId('region_id')->nullable()->constrained('region')->after('id'); + $table->foreignId('rayon_id')->nullable()->constrained('rayon')->after('region_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('admins', function (Blueprint $table) { + $table->foreignId('region_id')->nullable()->constrained('region')->after('id'); + $table->foreignId('rayon_id')->nullable()->constrained('rayon')->after('region_id'); + }); + } +}; diff --git a/database/migrations/2025_01_23_092400_add_expense_type_and_expense_id_to_notifications_table.php b/database/migrations/2025_01_23_092400_add_expense_type_and_expense_id_to_notifications_table.php new file mode 100644 index 0000000..1939402 --- /dev/null +++ b/database/migrations/2025_01_23_092400_add_expense_type_and_expense_id_to_notifications_table.php @@ -0,0 +1,30 @@ +string('expense_type')->nullable()->after('type'); + $table->unsignedBigInteger('expense_id')->nullable()->after('expense_type'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('notifications', function (Blueprint $table) { + $table->dropColumn('expense_type'); + $table->dropColumn('expense_id'); + }); + } +}; diff --git a/resources/views/backend/pages/admins/create.blade.php b/resources/views/backend/pages/admins/create.blade.php index f39e539..e2b2b61 100644 --- a/resources/views/backend/pages/admins/create.blade.php +++ b/resources/views/backend/pages/admins/create.blade.php @@ -91,16 +91,28 @@