From 4c6a6d8ceadc42f471b7c86e095fb64554051e19 Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Sat, 17 May 2025 11:34:12 +0700 Subject: [PATCH] feat(holidaycalendar): implement full feature set for holiday calendar management - Mengganti namespace model `HolidayCalendar` dari `Entities` ke `Models`. - Menambahkan validasi izin untuk semua aksi CRUD dan ekspor pada `HolidayCalendarController`. - Mengintegrasikan fitur izin pada tombol aksi (create, update, delete, export) di view `index.blade.php`. - Mengupdate logika form view `create.blade.php` untuk mendukung pengelolaan izin dan action dinamis. - Menambahkan class test `HolidayCalendarControllerTest` dengan pengujian lengkap mencakup: - Hak akses untuk membaca, membuat, memperbarui, menghapus, dan mengekspor data. - Validasi data saat penyimpanan/pembaruan. - Validasi respon HTTP untuk setiap aksi berdasarkan izin. - Memastikan user tanpa izin akan menerima pesan atau pembatasan akses yang relevan (HTTP 403). - Fitur ekspor CSV hanya dapat diakses oleh user dengan izin `basic-data.export`. - Memperbaiki rendering tindakan pada data tabel di `index.blade.php` agar responsif terhadap izin user. Signed-off-by: Daeng Deni Mardaeni --- app/Exports/HolidayCalendarExport.php | 2 +- .../Controllers/HolidayCalendarController.php | 66 +++- .../views/holidaycalendar/create.blade.php | 134 ++++---- .../views/holidaycalendar/index.blade.php | 26 +- .../Feature/HolidayCalendarControllerTest.php | 285 ++++++++++++++++++ 5 files changed, 439 insertions(+), 74 deletions(-) create mode 100644 tests/Feature/HolidayCalendarControllerTest.php diff --git a/app/Exports/HolidayCalendarExport.php b/app/Exports/HolidayCalendarExport.php index dc850af..9e842ab 100644 --- a/app/Exports/HolidayCalendarExport.php +++ b/app/Exports/HolidayCalendarExport.php @@ -6,7 +6,7 @@ use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithColumnFormatting; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Concerns\WithMapping; -use Modules\Basicdata\Entities\HolidayCalendar; +use Modules\Basicdata\Models\HolidayCalendar; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; class HolidayCalendarExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping diff --git a/app/Http/Controllers/HolidayCalendarController.php b/app/Http/Controllers/HolidayCalendarController.php index 9e8ea75..f7a1af8 100644 --- a/app/Http/Controllers/HolidayCalendarController.php +++ b/app/Http/Controllers/HolidayCalendarController.php @@ -12,15 +12,35 @@ class HolidayCalendarController extends Controller { - public $user; + /** + * Get the authenticated user. + * + * @return \Illuminate\Contracts\Auth\Authenticatable|null + */ + protected function getUser() + { + return \Illuminate\Support\Facades\Auth::guard('web')->user(); + } public function index() { + // Check if the authenticated user has the required permission to view holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.read')) { + abort(403, 'Sorry! You are not allowed to view holiday calendars.'); + } + return view('basicdata::holidaycalendar.index'); } public function store(HolidayCalendarRequest $request) { + // Check if the authenticated user has the required permission to create holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.create')) { + abort(403, 'Sorry! You are not allowed to create holiday calendars.'); + } + $validate = $request->validated(); if ($validate) { @@ -40,17 +60,35 @@ public function create() { + // Check if the authenticated user has the required permission to create holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.create')) { + abort(403, 'Sorry! You are not allowed to create holiday calendars.'); + } + return view('basicdata::holidaycalendar.create'); } public function edit($id) { + // Check if the authenticated user has the required permission to update holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.update')) { + abort(403, 'Sorry! You are not allowed to update holiday calendars.'); + } + $holiday = HolidayCalendar::find($id); return view('basicdata::holidaycalendar.create', compact('holiday')); } public function update(HolidayCalendarRequest $request, $id) { + // Check if the authenticated user has the required permission to update holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.update')) { + abort(403, 'Sorry! You are not allowed to update holiday calendars.'); + } + $validate = $request->validated(); if ($validate) { @@ -74,6 +112,12 @@ public function destroy($id) { + // Check if the authenticated user has the required permission to delete holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.delete')) { + abort(403, 'Sorry! You are not allowed to delete holiday calendars.'); + } + try { $holiday = HolidayCalendar::find($id); $holiday->delete(); @@ -90,15 +134,23 @@ public function deleteMultiple(Request $request) { + // Check if the authenticated user has the required permission to delete holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.delete')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to delete holiday calendars.'], 403); + } + $ids = $request->input('ids'); HolidayCalendar::whereIn('id', $ids)->delete(); - return response()->json(['message' => 'Holidays deleted successfully']); + return response()->json(['success' => true, 'message' => 'Holidays deleted successfully']); } public function dataForDatatables(Request $request) { - if (is_null($this->user) || !$this->user->can('currency.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + // Check if the authenticated user has the required permission to view holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.read')) { + return response()->json(['success' => false, 'message' => 'Sorry! You are not allowed to view holiday calendars.'], 403); } // Retrieve data from the database @@ -159,6 +211,12 @@ public function export() { + // Check if the authenticated user has the required permission to export holiday calendars + $user = $this->getUser(); + if (is_null($user) || !$user->can('basic-data.export')) { + abort(403, 'Sorry! You are not allowed to export holiday calendars.'); + } + return Excel::download(new HolidayCalendarExport, 'holiday_calendar.xlsx'); } } diff --git a/resources/views/holidaycalendar/create.blade.php b/resources/views/holidaycalendar/create.blade.php index 37f0ee2..106367b 100644 --- a/resources/views/holidaycalendar/create.blade.php +++ b/resources/views/holidaycalendar/create.blade.php @@ -6,71 +6,79 @@ @section('content')
- @if(isset($holiday->id)) -
+ + @csrf + @if(isset($holiday->id)) @method('PUT') - @else - - @endif - @csrf -
-
-

- {{ isset($holiday->id) ? 'Edit' : 'Tambah' }} Hari Libur -

-
- Back -
-
-
-
- -
- - @error('date') - {{ $message }} - @enderror -
-
-
- -
- - @error('description') - {{ $message }} - @enderror -
-
-
- -
- - @error('type') - {{ $message }} - @enderror -
-
-
- -
-
+ @endif +
+
+

+ {{ isset($holiday->id) ? 'Edit' : 'Tambah' }} Hari Libur +

+
+ Back +
+
+
+
+ +
+ + @error('date') + {{ $message }} + @enderror
- +
+
+ +
+ + @error('description') + {{ $message }} + @enderror +
+
+
+ +
+ + @error('type') + {{ $message }} + @enderror +
+
+
+ @if(isset($holiday->id)) + @can('basic-data.update') + + @endcan + @else + @can('basic-data.create') + + @endcan + @endif +
+
+
+
@endsection diff --git a/resources/views/holidaycalendar/index.blade.php b/resources/views/holidaycalendar/index.blade.php index 2ea577c..df72b66 100644 --- a/resources/views/holidaycalendar/index.blade.php +++ b/resources/views/holidaycalendar/index.blade.php @@ -19,9 +19,15 @@
+ @can('basic-data.export') Export to Excel + @endcan + @can('basic-data.create') Tambah Hari Libur + @endcan + @can('basic-data.delete') + @endcan
@@ -177,14 +183,22 @@ actions: { title: 'Action', render: (item, data) => { - return `
- + let html = `
`; + + @can('basic-data.update') + html += ` - - + `; + @endcan + + @can('basic-data.delete') + html += ` - -
`; + `; + @endcan + + html += `
`; + return html; }, } }, diff --git a/tests/Feature/HolidayCalendarControllerTest.php b/tests/Feature/HolidayCalendarControllerTest.php new file mode 100644 index 0000000..ada4327 --- /dev/null +++ b/tests/Feature/HolidayCalendarControllerTest.php @@ -0,0 +1,285 @@ + 'basic-data', + 'slug' => 'basic-data' + ]); + + // Create permissions with permission_group_id + Permission::create([ + 'name' => 'basic-data.create', + 'guard_name' => 'web', + 'permission_group_id' => $permissionGroup->id + ]); + Permission::create([ + 'name' => 'basic-data.read', + 'guard_name' => 'web', + 'permission_group_id' => $permissionGroup->id + ]); + Permission::create([ + 'name' => 'basic-data.update', + 'guard_name' => 'web', + 'permission_group_id' => $permissionGroup->id + ]); + Permission::create([ + 'name' => 'basic-data.delete', + 'guard_name' => 'web', + 'permission_group_id' => $permissionGroup->id + ]); + Permission::create([ + 'name' => 'basic-data.export', + 'guard_name' => 'web', + 'permission_group_id' => $permissionGroup->id + ]); + + // Create admin role with all permissions + $this->adminRole = Role::create(['name' => 'admin', 'guard_name' => 'web']); + $this->adminRole->givePermissionTo(Permission::all()); + + // Create a user with admin role + $this->user = User::factory()->create(); + $this->user->assignRole($this->adminRole); + + // Create a holiday calendar for testing + $this->holiday = HolidayCalendar::create([ + 'date' => '2023-01-01', + 'description' => 'New Year', + 'type' => 'national_holiday' + ]); + } + + #[Test] + public function user_with_permission_can_view_holidays_index() + { + $response = $this->actingAs($this->user) + ->get(route('basicdata.holidaycalendar.index')); + + $response->assertStatus(200); + } + + #[Test] + public function user_without_permission_cannot_view_holidays_index() + { + // Create a role without permissions + $role = Role::create(['name' => 'viewer', 'guard_name' => 'web']); + + // Create a user with the viewer role + $user = User::factory()->create(); + $user->assignRole($role); + + $response = $this->actingAs($user) + ->get(route('basicdata.holidaycalendar.index')); + + $response->assertStatus(403); + } + + #[Test] + public function user_with_permission_can_create_holiday() + { + $response = $this->actingAs($this->user) + ->get(route('basicdata.holidaycalendar.create')); + + $response->assertStatus(200); + } + + #[Test] + public function user_without_permission_cannot_create_holiday() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $response = $this->actingAs($user) + ->get(route('basicdata.holidaycalendar.create')); + + $response->assertStatus(403); + } + + #[Test] + public function user_with_permission_can_store_holiday() + { + $holidayData = [ + 'date' => '2023-12-25', + 'description' => 'Christmas', + 'type' => 'national_holiday' + ]; + + $response = $this->actingAs($this->user) + ->post(route('basicdata.holidaycalendar.store'), $holidayData); + + $response->assertRedirect(route('basicdata.holidaycalendar.index')); + $this->assertDatabaseHas('holiday_calendars', $holidayData); + } + + #[Test] + public function user_without_permission_cannot_store_holiday() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $holidayData = [ + 'date' => '2023-12-25', + 'description' => 'Christmas', + 'type' => 'national_holiday' + ]; + + $response = $this->actingAs($user) + ->post(route('basicdata.holidaycalendar.store'), $holidayData); + + $response->assertStatus(403); + $this->assertDatabaseMissing('holiday_calendars', $holidayData); + } + + #[Test] + public function user_with_permission_can_edit_holiday() + { + $response = $this->actingAs($this->user) + ->get(route('basicdata.holidaycalendar.edit', $this->holiday->id)); + + $response->assertStatus(200); + } + + #[Test] + public function user_without_permission_cannot_edit_holiday() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $response = $this->actingAs($user) + ->get(route('basicdata.holidaycalendar.edit', $this->holiday->id)); + + $response->assertStatus(403); + } + + #[Test] + public function user_with_permission_can_update_holiday() + { + $updatedData = [ + 'date' => '2023-01-01', + 'description' => 'New Year Updated', + 'type' => 'collective_leave' + ]; + + $response = $this->actingAs($this->user) + ->put(route('basicdata.holidaycalendar.update', $this->holiday->id), $updatedData); + + $response->assertRedirect(route('basicdata.holidaycalendar.index')); + $this->assertDatabaseHas('holiday_calendars', $updatedData); + } + + #[Test] + public function user_without_permission_cannot_update_holiday() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $updatedData = [ + 'date' => '2023-01-01', + 'description' => 'New Year Updated', + 'type' => 'collective_leave' + ]; + + $response = $this->actingAs($user) + ->put(route('basicdata.holidaycalendar.update', $this->holiday->id), $updatedData); + + $response->assertStatus(403); + $this->assertDatabaseMissing('holiday_calendars', $updatedData); + } + + #[Test] + public function user_with_permission_can_delete_holiday() + { + $response = $this->actingAs($this->user) + ->delete(route('basicdata.holidaycalendar.destroy', $this->holiday->id)); + + $response->assertRedirect(route('basicdata.holidaycalendar.index')); + $this->assertSoftDeleted($this->holiday); + } + + #[Test] + public function user_without_permission_cannot_delete_holiday() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $response = $this->actingAs($user) + ->delete(route('basicdata.holidaycalendar.destroy', $this->holiday->id)); + + $response->assertStatus(403); + $this->assertDatabaseHas('holiday_calendars', ['id' => $this->holiday->id, 'deleted_at' => null]); + } + + #[Test] + public function user_with_permission_can_export_holidays() + { + $response = $this->actingAs($this->user) + ->get(route('basicdata.holidaycalendar.export')); + + $response->assertStatus(200); + } + + #[Test] + public function user_without_permission_cannot_export_holidays() + { + // Create a role with only read permission + $role = Role::create(['name' => 'reader', 'guard_name' => 'web']); + $role->givePermissionTo('basic-data.read'); + + // Create a user with the reader role + $user = User::factory()->create(); + $user->assignRole($role); + + $response = $this->actingAs($user) + ->get(route('basicdata.holidaycalendar.export')); + + $response->assertStatus(403); + } +}