diff --git a/app/Http/Controllers/Admin/Manage/Purchase/PurchaseController.php b/app/Http/Controllers/Admin/Manage/Purchase/PurchaseController.php index a382dbc..529c565 100644 --- a/app/Http/Controllers/Admin/Manage/Purchase/PurchaseController.php +++ b/app/Http/Controllers/Admin/Manage/Purchase/PurchaseController.php @@ -25,10 +25,13 @@ public function __construct( public function index(Request $request): Response { $tableQuery = $this->parseDataTableQuery($request); + $tableQuery['search_id'] = $request->string('search_id')->trim()->toString(); return Inertia::render('admin/manage/purchases/Index', [ 'purchases' => $this->purchaseService->paginateForIndex($tableQuery), - 'filters' => $this->dataTableFilters($tableQuery), + 'filters' => $this->dataTableFilters($tableQuery, [ + 'search_id' => $tableQuery['search_id'], + ]), ]); } diff --git a/app/Http/Controllers/Admin/Master/ProductController.php b/app/Http/Controllers/Admin/Master/ProductController.php index 3cc48cd..29e3c71 100644 --- a/app/Http/Controllers/Admin/Master/ProductController.php +++ b/app/Http/Controllers/Admin/Master/ProductController.php @@ -30,6 +30,7 @@ public function __construct( public function index(Request $request): Response { $tableQuery = $this->parseDataTableQuery($request); + $tableQuery['search_id'] = $request->string('search_id')->trim()->toString(); $isActive = $request->string('is_active')->toString(); $categoryId = $request->string('category_id')->toString(); $stockStatus = $request->string('stock_status')->toString(); @@ -41,6 +42,7 @@ public function index(Request $request): Response 'is_active' => $isActive, 'category_id' => $categoryId, 'stock_status' => $stockStatus, + 'search_id' => $tableQuery['search_id'], ]), ]); } diff --git a/app/Http/Controllers/Admin/Master/RawMaterialController.php b/app/Http/Controllers/Admin/Master/RawMaterialController.php index 688d9d4..952a63b 100644 --- a/app/Http/Controllers/Admin/Master/RawMaterialController.php +++ b/app/Http/Controllers/Admin/Master/RawMaterialController.php @@ -29,6 +29,7 @@ public function __construct( public function index(Request $request): Response { $tableQuery = $this->parseDataTableQuery($request); + $tableQuery['search_id'] = $request->string('search_id')->trim()->toString(); $isActive = $request->string('is_active')->toString(); $stockStatus = $request->string('stock_status')->toString(); $rawMaterialId = $request->string('raw_material_id')->toString(); @@ -39,6 +40,7 @@ public function index(Request $request): Response 'is_active' => $isActive, 'stock_status' => $stockStatus, 'raw_material_id' => $rawMaterialId, + 'search_id' => $tableQuery['search_id'], ]), 'rawMaterialsList' => RawMaterial::query()->orderBy('name')->get(['id', 'name'])->map(fn ($r) => ['value' => (string) $r->id, 'label' => $r->name])->all(), ]); diff --git a/app/Services/Manage/OwnerVerificationService.php b/app/Services/Manage/OwnerVerificationService.php index 5699245..dd045d2 100644 --- a/app/Services/Manage/OwnerVerificationService.php +++ b/app/Services/Manage/OwnerVerificationService.php @@ -520,56 +520,23 @@ private function requestTitle(OwnerVerificationRequest $request): string private function requestSearchTerm(OwnerVerificationRequest $request): ?string { - if ($request->subject_type === Product::class) { - if ($request->subject instanceof Product) { - return $request->subject->name; - } - $payload = is_array($request->payload) ? $request->payload : []; - foreach (['new', 'old'] as $key) { - $section = $payload[$key] ?? null; - if (is_array($section) && isset($section['name'])) { - return (string) $section['name']; - } - } + if ($request->subject_type === MarketplaceSettings::class) { + return null; } if ($request->subject_type === ProductVariant::class) { + if ($request->subject instanceof ProductVariant) { + return (string) $request->subject->product_id; + } $payload = is_array($request->payload) ? $request->payload : []; $newData = $payload['new'] ?? []; - if (isset($newData['product_name']) && $newData['product_name'] !== '-') { - return $newData['product_name']; - } - if ($request->subject instanceof ProductVariant) { - return $request->subject->product?->name ?? $request->subject->name; + if (isset($newData['product_id'])) { + return (string) $newData['product_id']; } } - if ($request->subject_type === RawMaterial::class) { - if ($request->subject instanceof RawMaterial) { - return $request->subject->name; - } - $payload = is_array($request->payload) ? $request->payload : []; - foreach (['new', 'old'] as $key) { - $section = $payload[$key] ?? null; - if (is_array($section) && isset($section['name'])) { - return (string) $section['name']; - } - } - } - - if ($request->subject_type === Purchase::class) { - if ($request->subject instanceof Purchase) { - $request->subject->loadMissing('supplier'); - - return $request->subject->supplier?->name; - } - $payload = is_array($request->payload) ? $request->payload : []; - foreach (['new', 'old'] as $key) { - $section = $payload[$key] ?? null; - if (is_array($section) && isset($section['supplier_name'])) { - return (string) $section['supplier_name']; - } - } + if ($request->subject_id !== null) { + return (string) $request->subject_id; } return null; @@ -585,7 +552,7 @@ private function notifyRequestSubmitter( } $searchTerm = $this->requestSearchTerm($request); - $routeParams = $searchTerm !== null ? ['search' => $searchTerm] : []; + $routeParams = $searchTerm !== null ? ['search_id' => $searchTerm] : []; $url = match ($request->subject_type) { Product::class, ProductVariant::class => route('admin.master.products.index', $routeParams), diff --git a/app/Services/Manage/PurchaseService.php b/app/Services/Manage/PurchaseService.php index b9f62fa..30407b7 100644 --- a/app/Services/Manage/PurchaseService.php +++ b/app/Services/Manage/PurchaseService.php @@ -43,7 +43,10 @@ public function paginateForIndex(array $tableQuery): LengthAwarePaginator 'items.rawMaterialPrice.rawMaterial:id,name,unit', 'media', ]) - ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + ->when(($tableQuery['search_id'] ?? '') !== '', function (Builder $query) use ($tableQuery): void { + $query->where('purchases.id', $tableQuery['search_id']); + }) + ->when(($tableQuery['search_id'] ?? '') === '' && $tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { $search = $tableQuery['search']; $query->where(function (Builder $query) use ($search): void { $query->where('notes', 'like', "%{$search}%") @@ -232,7 +235,7 @@ public function createVariantAndDraft(array $validated, User $user): array '🆕 Varian Baru Ditambahkan', "{$user->name} menambahkan varian \"{$price->variant}\" ke bahan baku \"{$rawMaterial->name}\".", ['owner', 'developer', 'direktur'], - route('admin.master.raw_materials.index', ['search' => $rawMaterial->name]), + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), ); return [ @@ -428,8 +431,8 @@ function () use ($validated, $user, $isOwner): Purchase { $user, 'Tambah Belanja', "Pengajuan belanja dari supplier {$purchase->supplier->name} senilai {$purchase->total_formatted} menunggu verifikasi owner.", - route('admin.manage.purchases.index', ['search' => $purchase->supplier->name]), - $purchase->supplier->name, + route('admin.manage.purchases.index', ['search_id' => $purchase->id]), + (string) $purchase->id, ); } @@ -480,8 +483,8 @@ function () use ($purchase, $validated, $user, $isOwner): void { $user, 'Ubah Belanja', "Pengajuan ubah belanja dari supplier {$purchase->supplier->name} menunggu verifikasi owner.", - route('admin.manage.purchases.index', ['search' => $purchase->supplier->name]), - $purchase->supplier->name, + route('admin.manage.purchases.index', ['search_id' => $purchase->id]), + (string) $purchase->id, ); } @@ -524,8 +527,8 @@ function () use ($purchase, $user): void { $user, 'Hapus Belanja', "Pengajuan hapus belanja dari supplier {$purchase->supplier->name} menunggu verifikasi owner.", - route('admin.manage.purchases.index', ['search' => $purchase->supplier->name]), - $purchase->supplier->name, + route('admin.manage.purchases.index', ['search_id' => $purchase->id]), + (string) $purchase->id, ); } @@ -685,7 +688,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ { $ownerUrl = route('admin.manage.purchases.index'); if ($search !== null) { - $ownerUrl = route('admin.manage.purchases.index', ['search' => $search]); + $ownerUrl = route('admin.manage.purchases.index', ['search_id' => $search]); } $this->pushNotificationService->sendToRoles( diff --git a/app/Services/Manage/RetailStockService.php b/app/Services/Manage/RetailStockService.php index 2f50e60..6b753cb 100644 --- a/app/Services/Manage/RetailStockService.php +++ b/app/Services/Manage/RetailStockService.php @@ -33,13 +33,11 @@ public function transfer(int $variantId, int $quantity, User $user, ?string $not $this->executeTransfer($variant, $quantity, $user, $notes); - $productName = $variant->product?->name ?? $variant->name; - $this->pushNotificationService->sendToRoles( '📦 Perubahan Stok Ecer', "Perubahan {$quantity} pcs stok ecer untuk varian '{$variant->name}' telah diterapkan.", ['owner', 'developer', 'direktur'], - route('admin.master.products.index', ['search' => $productName]), + route('admin.master.products.index', ['search_id' => $variant->product_id]), ); } diff --git a/app/Services/Master/ProductService.php b/app/Services/Master/ProductService.php index 6ea1163..8bc8f90 100644 --- a/app/Services/Master/ProductService.php +++ b/app/Services/Master/ProductService.php @@ -43,7 +43,10 @@ public function paginateForIndex(array $tableQuery, string $isActive, string $ca $query->where('name', 'like', "%{$tableQuery['search']}%"); }), ]) - ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + ->when(($tableQuery['search_id'] ?? '') !== '', function (Builder $query) use ($tableQuery): void { + $query->where('products.id', $tableQuery['search_id']); + }) + ->when(($tableQuery['search_id'] ?? '') === '' && $tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { $search = $tableQuery['search']; $query->whereHas('variants', fn (Builder $query) => $query->where('name', 'like', "%{$search}%")); }) @@ -118,8 +121,8 @@ public function create(array $validated, User $user): void { $isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value); - $this->runInTransaction( - function () use ($validated, $user, $isOwner): void { + $product = $this->runInTransaction( + function () use ($validated, $user, $isOwner): Product { $product = Product::create([ 'name' => $validated['name'], 'description' => $validated['description'] ?? null, @@ -160,6 +163,8 @@ function () use ($validated, $user, $isOwner): void { ], ]); } + + return $product; }, 'Gagal membuat produk', ); @@ -173,8 +178,8 @@ function () use ($validated, $user, $isOwner): void { $user, 'Tambah Produk', "Pengajuan tambah produk '{$validated['name']}' menunggu verifikasi owner.", - route('admin.master.products.index', ['search' => $validated['name']]), - $validated['name'], + route('admin.master.products.index', ['search_id' => $product->id]), + (string) $product->id, ); } } @@ -286,16 +291,16 @@ function () use ($validated, $product, $user, $isOwner): void { $user, 'Ubah Varian Produk', "Pengajuan ubah varian '{$variantsStr}' pada produk '{$product->name}' menunggu verifikasi owner.", - route('admin.master.products.index', ['search' => $product->name]), - $product->name, + route('admin.master.products.index', ['search_id' => $product->id]), + (string) $product->id, ); } else { $this->notifyForPendingRequest( $user, 'Ubah Produk', "Pengajuan ubah produk '{$product->name}' menunggu verifikasi owner.", - route('admin.master.products.index', ['search' => $product->name]), - $product->name, + route('admin.master.products.index', ['search_id' => $product->id]), + (string) $product->id, ); } } @@ -334,8 +339,8 @@ function () use ($product, $user): void { $user, 'Hapus Produk', "Pengajuan hapus produk '{$product->name}' menunggu verifikasi owner.", - route('admin.master.products.index', ['search' => $product->name]), - $product->name, + route('admin.master.products.index', ['search_id' => $product->id]), + (string) $product->id, ); } @@ -383,8 +388,8 @@ function () use ($product, $validated, $user): void { $user, 'Ubah Status Produk', "Pengajuan ubah status produk '{$product->name}' menjadi {$statusLabel} menunggu verifikasi owner.", - route('admin.master.products.index', ['search' => $product->name]), - $product->name, + route('admin.master.products.index', ['search_id' => $product->id]), + (string) $product->id, ); } @@ -584,7 +589,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ { $ownerUrl = route('admin.master.products.index'); if ($search !== null) { - $ownerUrl = route('admin.master.products.index', ['search' => $search]); + $ownerUrl = route('admin.master.products.index', ['search_id' => $search]); } $this->pushNotificationService->sendToRoles( diff --git a/app/Services/Master/RawMaterialService.php b/app/Services/Master/RawMaterialService.php index eff3251..aa55a0b 100644 --- a/app/Services/Master/RawMaterialService.php +++ b/app/Services/Master/RawMaterialService.php @@ -42,7 +42,10 @@ public function paginateForIndex(array $tableQuery, string $isActive, string $st $query->where('variant', 'like', "%{$tableQuery['search']}%"); }), ]) - ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + ->when(($tableQuery['search_id'] ?? '') !== '', function (Builder $query) use ($tableQuery): void { + $query->where('raw_materials.id', $tableQuery['search_id']); + }) + ->when(($tableQuery['search_id'] ?? '') === '' && $tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { $search = $tableQuery['search']; $query->whereHas('prices', fn (Builder $query) => $query->where('variant', 'like', "%{$search}%")); }) @@ -117,8 +120,8 @@ public function create(array $validated, User $user): void { $isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value); - $this->runInTransaction( - function () use ($validated, $user, $isOwner): void { + $rawMaterial = $this->runInTransaction( + function () use ($validated, $user, $isOwner): RawMaterial { $rawMaterial = RawMaterial::create([ 'name' => $validated['name'], 'unit' => $validated['unit'], @@ -142,6 +145,8 @@ function () use ($validated, $user, $isOwner): void { ], ]); } + + return $rawMaterial; }, 'Gagal membuat bahan baku', ); @@ -155,8 +160,8 @@ function () use ($validated, $user, $isOwner): void { $user, 'Tambah Bahan Baku', "Pengajuan tambah bahan baku '{$validated['name']}' menunggu verifikasi owner.", - route('admin.master.raw_materials.index', ['search' => $validated['name']]), - $validated['name'], + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), + (string) $rawMaterial->id, ); } } @@ -239,16 +244,16 @@ function () use ($validated, $rawMaterial, $user, $isOwner): void { $user, 'Ubah Varian Bahan Baku', "Pengajuan ubah varian '{$variantsStr}' pada bahan baku '{$rawMaterial->name}' menunggu verifikasi owner.", - route('admin.master.raw_materials.index', ['search' => $rawMaterial->name]), - $rawMaterial->name, + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), + (string) $rawMaterial->id, ); } else { $this->notifyForPendingRequest( $user, 'Ubah Bahan Baku', "Pengajuan ubah bahan baku '{$rawMaterial->name}' menunggu verifikasi owner.", - route('admin.master.raw_materials.index', ['search' => $rawMaterial->name]), - $rawMaterial->name, + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), + (string) $rawMaterial->id, ); } } @@ -286,8 +291,8 @@ function () use ($rawMaterial, $user): void { $user, 'Hapus Bahan Baku', "Pengajuan hapus bahan baku '{$rawMaterial->name}' menunggu verifikasi owner.", - route('admin.master.raw_materials.index', ['search' => $rawMaterial->name]), - $rawMaterial->name, + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), + (string) $rawMaterial->id, ); } @@ -334,8 +339,8 @@ function () use ($rawMaterial, $validated, $user): void { $user, 'Ubah Status Bahan Baku', "Pengajuan ubah status bahan baku '{$rawMaterial->name}' menjadi {$statusLabel} menunggu verifikasi owner.", - route('admin.master.raw_materials.index', ['search' => $rawMaterial->name]), - $rawMaterial->name, + route('admin.master.raw_materials.index', ['search_id' => $rawMaterial->id]), + (string) $rawMaterial->id, ); } @@ -383,7 +388,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ { $ownerUrl = route('admin.master.raw_materials.index'); if ($search !== null) { - $ownerUrl = route('admin.master.raw_materials.index', ['search' => $search]); + $ownerUrl = route('admin.master.raw_materials.index', ['search_id' => $search]); } $this->pushNotificationService->sendToRoles( diff --git a/tests/Feature/Admin/Manage/PurchaseTest.php b/tests/Feature/Admin/Manage/PurchaseTest.php index 17c13b0..16b0ad3 100644 --- a/tests/Feature/Admin/Manage/PurchaseTest.php +++ b/tests/Feature/Admin/Manage/PurchaseTest.php @@ -400,6 +400,23 @@ function getPurchaseItemsPayload(RawMaterialPrice $price, float $quantity = 2): ->get(route('admin.manage.purchases.index', ['search' => 'Kain'])) ->assertOk(); }); + + test('index can search purchases by id', function () { + $user = createPurchaseUserWithPermission(PermissionEnum::PURCHASES_VIEW); + + $supplier = Supplier::factory()->create(['name' => 'Supplier Kain']); + $purchase1 = Purchase::factory()->create(['supplier_id' => $supplier->id, 'created_by_id' => $user->id]); + $purchase2 = Purchase::factory()->create(['supplier_id' => $supplier->id, 'created_by_id' => $user->id]); + + $response = $this->actingAs($user) + ->get(route('admin.manage.purchases.index', ['search_id' => $purchase1->id])); + + $response->assertOk(); + $response->assertInertia(fn ($page) => $page + ->has('purchases.data', 1) + ->where('purchases.data.0.id', $purchase1->id) + ); + }); }); // ─── Create ─────────────────────────────────────────────── diff --git a/tests/Feature/Admin/Master/ProductTest.php b/tests/Feature/Admin/Master/ProductTest.php index a994691..e33b992 100644 --- a/tests/Feature/Admin/Master/ProductTest.php +++ b/tests/Feature/Admin/Master/ProductTest.php @@ -163,6 +163,28 @@ function variantUpdateData(int $id, string $name = 'Updated Variant', int $stock ->assertOk(); }); + test('index can search products by id', function () { + $user = createProductUserWithPermission(PermissionEnum::PRODUCTS_VIEW); + + $category = Category::factory()->create(); + $product1 = Product::factory()->create(['name' => 'Batik Modern']); + $product1->categories()->attach($category->id); + ProductVariant::factory()->create(['product_id' => $product1->id]); + + $product2 = Product::factory()->create(['name' => 'Baju Sutra']); + $product2->categories()->attach($category->id); + ProductVariant::factory()->create(['product_id' => $product2->id]); + + $response = $this->actingAs($user) + ->get(route('admin.master.products.index', ['search_id' => $product1->id])); + + $response->assertOk(); + $response->assertInertia(fn ($page) => $page + ->has('products.data', 1) + ->where('products.data.0.id', $product1->id) + ); + }); + test('index can filter by active status', function () { $user = createProductUserWithPermission(PermissionEnum::PRODUCTS_VIEW); diff --git a/tests/Feature/Admin/Master/RawMaterialTest.php b/tests/Feature/Admin/Master/RawMaterialTest.php index 0768ea9..d2106e2 100644 --- a/tests/Feature/Admin/Master/RawMaterialTest.php +++ b/tests/Feature/Admin/Master/RawMaterialTest.php @@ -132,6 +132,25 @@ function createRawMaterialVerifierUser(): User ->assertOk(); }); + test('index can search raw materials by id', function () { + $user = createRawMaterialUserWithPermission(PermissionEnum::RAW_MATERIALS_VIEW); + + $rawMaterial1 = RawMaterial::factory()->create(['name' => 'Kain Batik']); + RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial1->id]); + + $rawMaterial2 = RawMaterial::factory()->create(['name' => 'Sutra Premium']); + RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial2->id]); + + $response = $this->actingAs($user) + ->get(route('admin.master.raw_materials.index', ['search_id' => $rawMaterial1->id])); + + $response->assertOk(); + $response->assertInertia(fn ($page) => $page + ->has('rawMaterials.data', 1) + ->where('rawMaterials.data.0.id', $rawMaterial1->id) + ); + }); + test('index can filter by active status', function () { $user = createRawMaterialUserWithPermission(PermissionEnum::RAW_MATERIALS_VIEW);