From c21f71563f2c798d18d71a453fd29f9312578f63 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 10 Jun 2026 15:48:34 +0700 Subject: [PATCH] Add supplier management features including Supplier model, SupplierController for CRUD operations, and SupplierRequest for validation. Integrate permissions in the Permission and Role enums, and update routes for supplier management. Enhance UI components for supplier listing and management, including a data table and form modal. Update sidebar for supplier navigation. --- app/Enums/Permission.php | 12 ++ app/Enums/Role.php | 19 +++ .../Admin/Master/SupplierController.php | 59 ++++++++ .../Requests/Admin/Master/SupplierRequest.php | 30 ++++ app/Models/Supplier.php | 13 ++ app/Services/Master/SupplierService.php | 67 +++++++++ ...26_06_10_080632_create_suppliers_table.php | 34 +++++ resources/js/components/AppSidebar.vue | 11 +- .../master/suppliers/SupplierFormModal.vue | 134 ++++++++++++++++++ .../admin/master/suppliers/columns.ts | 34 +++++ .../master/suppliers/data-table-actions.vue | 70 +++++++++ .../js/pages/admin/master/suppliers/Index.vue | 108 ++++++++++++++ resources/js/types/supplier.ts | 31 ++++ routes/web.php | 20 +++ 14 files changed, 641 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Admin/Master/SupplierController.php create mode 100644 app/Http/Requests/Admin/Master/SupplierRequest.php create mode 100644 app/Models/Supplier.php create mode 100644 app/Services/Master/SupplierService.php create mode 100644 database/migrations/2026_06_10_080632_create_suppliers_table.php create mode 100644 resources/js/components/admin/master/suppliers/SupplierFormModal.vue create mode 100644 resources/js/components/admin/master/suppliers/columns.ts create mode 100644 resources/js/components/admin/master/suppliers/data-table-actions.vue create mode 100644 resources/js/pages/admin/master/suppliers/Index.vue create mode 100644 resources/js/types/supplier.ts diff --git a/app/Enums/Permission.php b/app/Enums/Permission.php index 798c144..a37c8cc 100644 --- a/app/Enums/Permission.php +++ b/app/Enums/Permission.php @@ -22,6 +22,11 @@ enum Permission: string case CATEGORIES_UPDATE = 'categories.update'; case CATEGORIES_DELETE = 'categories.delete'; + case SUPPLIERS_VIEW = 'suppliers.view'; + case SUPPLIERS_CREATE = 'suppliers.create'; + case SUPPLIERS_UPDATE = 'suppliers.update'; + case SUPPLIERS_DELETE = 'suppliers.delete'; + case PRODUCTS_VIEW = 'products.view'; case PRODUCTS_CREATE = 'products.create'; case PRODUCTS_UPDATE = 'products.update'; @@ -51,6 +56,11 @@ public function label(): string self::CATEGORIES_UPDATE => 'Ubah Kategori', self::CATEGORIES_DELETE => 'Hapus Kategori', + self::SUPPLIERS_VIEW => 'Lihat Supplier', + self::SUPPLIERS_CREATE => 'Tambah Supplier', + self::SUPPLIERS_UPDATE => 'Ubah Supplier', + self::SUPPLIERS_DELETE => 'Hapus Supplier', + self::PRODUCTS_VIEW => 'Lihat Produk', self::PRODUCTS_CREATE => 'Tambah Produk', self::PRODUCTS_UPDATE => 'Ubah Produk', @@ -73,6 +83,8 @@ public function group(): string self::EMPLOYEES_DELETE, self::EMPLOYEES_RESET_PASSWORD, self::EMPLOYEES_TOGGLE_STATUS => 'Pegawai', self::CATEGORIES_VIEW, self::CATEGORIES_CREATE, self::CATEGORIES_UPDATE, self::CATEGORIES_DELETE => 'Kategori', + self::SUPPLIERS_VIEW, self::SUPPLIERS_CREATE, self::SUPPLIERS_UPDATE, + self::SUPPLIERS_DELETE => 'Supplier', self::PRODUCTS_VIEW, self::PRODUCTS_CREATE, self::PRODUCTS_UPDATE, self::PRODUCTS_DELETE, self::PRODUCTS_TOGGLE_STATUS => 'Produk', self::RAW_MATERIALS_VIEW, self::RAW_MATERIALS_CREATE, self::RAW_MATERIALS_UPDATE, diff --git a/app/Enums/Role.php b/app/Enums/Role.php index ef3b76e..c6e530f 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -48,6 +48,10 @@ public function permissions(): array Permission::CATEGORIES_CREATE, Permission::CATEGORIES_UPDATE, Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, Permission::PRODUCTS_VIEW, Permission::PRODUCTS_CREATE, Permission::PRODUCTS_UPDATE, @@ -70,6 +74,10 @@ public function permissions(): array Permission::CATEGORIES_CREATE, Permission::CATEGORIES_UPDATE, Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, Permission::PRODUCTS_VIEW, Permission::PRODUCTS_CREATE, Permission::PRODUCTS_UPDATE, @@ -83,6 +91,10 @@ public function permissions(): array Permission::CATEGORIES_CREATE, Permission::CATEGORIES_UPDATE, Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, Permission::RAW_MATERIALS_VIEW, Permission::RAW_MATERIALS_CREATE, Permission::RAW_MATERIALS_UPDATE, @@ -93,6 +105,13 @@ public function permissions(): array Permission::DASHBOARD_VIEW, Permission::EMPLOYEES_VIEW, Permission::CATEGORIES_VIEW, + Permission::CATEGORIES_CREATE, + Permission::CATEGORIES_UPDATE, + Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, Permission::PRODUCTS_VIEW, ], self::NON_OPERATOR => [ diff --git a/app/Http/Controllers/Admin/Master/SupplierController.php b/app/Http/Controllers/Admin/Master/SupplierController.php new file mode 100644 index 0000000..e37307d --- /dev/null +++ b/app/Http/Controllers/Admin/Master/SupplierController.php @@ -0,0 +1,59 @@ +parseDataTableQuery($request); + + return Inertia::render('admin/master/suppliers/Index', [ + 'suppliers' => $this->supplierService->paginateForIndex($tableQuery), + 'filters' => $this->dataTableFilters($tableQuery), + ]); + } + + public function store(SupplierRequest $request): RedirectResponse + { + $this->supplierService->create($request->validated()); + + Inertia::flash('success', 'Supplier berhasil ditambahkan.'); + + return redirect()->route('admin.master.suppliers.index'); + } + + public function update(SupplierRequest $request, Supplier $supplier): RedirectResponse + { + $this->supplierService->update($supplier, $request->validated()); + + Inertia::flash('success', 'Supplier berhasil diperbarui.'); + + return redirect()->route('admin.master.suppliers.index'); + } + + public function destroy(Supplier $supplier): RedirectResponse + { + $this->supplierService->delete($supplier); + + Inertia::flash('success', 'Supplier berhasil dihapus.'); + + return redirect()->route('admin.master.suppliers.index'); + } +} diff --git a/app/Http/Requests/Admin/Master/SupplierRequest.php b/app/Http/Requests/Admin/Master/SupplierRequest.php new file mode 100644 index 0000000..010cac0 --- /dev/null +++ b/app/Http/Requests/Admin/Master/SupplierRequest.php @@ -0,0 +1,30 @@ +isMethod('POST') + ? Permission::SUPPLIERS_CREATE + : Permission::SUPPLIERS_UPDATE; + + return $this->user()?->can($permission->value) ?? false; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:200'], + 'address' => ['required', 'string'], + 'phone_number' => ['required', 'string', 'max:20'], + ]; + } +} diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php new file mode 100644 index 0000000..b313adc --- /dev/null +++ b/app/Models/Supplier.php @@ -0,0 +1,13 @@ +when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + $search = $tableQuery['search']; + $query->where(function (Builder $query) use ($search): void { + $query->where('name', 'like', "%{$search}%") + ->orWhere('phone_number', 'like', "%{$search}%") + ->orWhere('address', 'like', "%{$search}%"); + }); + }); + + $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); + + return $query + ->paginate(10) + ->withQueryString(); + } + + /** + * @param array $validated + */ + public function create(array $validated): void + { + Supplier::create($validated); + } + + /** + * @param array $validated + */ + public function update(Supplier $supplier, array $validated): void + { + $supplier->name = $validated['name']; + $supplier->phone_number = $validated['phone_number']; + $supplier->address = $validated['address']; + $supplier->save(); + } + + public function delete(Supplier $supplier): void + { + $supplier->delete(); + } + + private function applySorting(Builder $query, string $sort, string $direction): void + { + if (in_array($sort, ['name', 'phone_number', 'address'], true)) { + $query->orderBy($sort, $direction); + + return; + } + + $query->latest(); + } +} diff --git a/database/migrations/2026_06_10_080632_create_suppliers_table.php b/database/migrations/2026_06_10_080632_create_suppliers_table.php new file mode 100644 index 0000000..fe186e3 --- /dev/null +++ b/database/migrations/2026_06_10_080632_create_suppliers_table.php @@ -0,0 +1,34 @@ +id(); + + $table->string('name', 200); + $table->string('phone_number', 20)->nullable(); + $table->text('address')->nullable(); + + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('suppliers'); + } +}; diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index cfa7af2..9318fc6 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -1,6 +1,6 @@ + +