From 1f27acc63a0514b6514ac29be280430ce5c13884 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sat, 27 Jun 2026 21:51:48 +0700 Subject: [PATCH] refactor: remove owner verification index functionality and related components, streamline approval and rejection processes --- .../Manage/OwnerVerificationController.php | 50 +-- app/Http/Middleware/HandleInertiaRequests.php | 13 - .../Manage/ApproveVerificationRequest.php | 6 +- .../Manage/RejectVerificationRequest.php | 6 +- .../Manage/OwnerVerificationService.php | 4 +- app/Services/Manage/PurchaseService.php | 2 +- app/Services/Manage/StockService.php | 8 +- app/Services/Master/ProductService.php | 2 +- app/Services/Master/RawMaterialService.php | 2 +- .../System/Setting/MarketplaceService.php | 2 +- resources/js/components/AppSidebar.vue | 5 +- resources/js/components/MobileBottomNav.vue | 11 +- .../manage/owner-verifications/Index.vue | 143 ------- .../table/OwnerVerificationDetailModal.vue | 120 ------ .../owner-verifications/table/columns.ts | 70 ---- .../table/data-table-actions.vue | 22 -- resources/js/types/owner-verification.ts | 51 --- routes/web.php | 3 - .../Admin/Manage/OwnerVerificationTest.php | 354 ------------------ tests/Feature/Admin/Manage/PurchaseTest.php | 4 +- tests/Feature/Admin/Master/ProductTest.php | 4 +- .../Feature/Admin/Master/RawMaterialTest.php | 2 +- 22 files changed, 26 insertions(+), 858 deletions(-) delete mode 100644 resources/js/pages/admin/manage/owner-verifications/Index.vue delete mode 100644 resources/js/pages/admin/manage/owner-verifications/table/OwnerVerificationDetailModal.vue delete mode 100644 resources/js/pages/admin/manage/owner-verifications/table/columns.ts delete mode 100644 resources/js/pages/admin/manage/owner-verifications/table/data-table-actions.vue delete mode 100644 resources/js/types/owner-verification.ts delete mode 100644 tests/Feature/Admin/Manage/OwnerVerificationTest.php diff --git a/app/Http/Controllers/Admin/Manage/OwnerVerificationController.php b/app/Http/Controllers/Admin/Manage/OwnerVerificationController.php index 98c43bf..1f52d67 100644 --- a/app/Http/Controllers/Admin/Manage/OwnerVerificationController.php +++ b/app/Http/Controllers/Admin/Manage/OwnerVerificationController.php @@ -2,10 +2,7 @@ namespace App\Http\Controllers\Admin\Manage; -use App\Enums\OwnerVerificationAction; -use App\Enums\OwnerVerificationStatus; use App\Http\Controllers\Concerns\FlashesEntityMessage; -use App\Http\Controllers\Concerns\ParsesDataTableQuery; use App\Http\Controllers\Controller; use App\Http\Requests\Admin\Manage\ApproveVerificationRequest; use App\Http\Requests\Admin\Manage\RejectVerificationRequest; @@ -14,45 +11,16 @@ use App\Services\Manage\OwnerVerificationService; use App\Services\Manage\StockService; use Illuminate\Http\RedirectResponse; -use Illuminate\Http\Request; -use Inertia\Inertia; -use Inertia\Response; class OwnerVerificationController extends Controller { - use FlashesEntityMessage, ParsesDataTableQuery; + use FlashesEntityMessage; public function __construct( private readonly OwnerVerificationService $ownerVerificationService, private readonly StockService $stockService, ) {} - public function index(Request $request): Response - { - $tableQuery = $this->parseDataTableQuery($request); - $status = $request->string('status')->toString(); - $subjectType = $request->string('subject_type')->toString(); - $action = $request->string('action')->toString(); - - return Inertia::render('admin/manage/owner-verifications/Index', [ - 'verificationRequests' => $this->ownerVerificationService->paginateForIndex( - $request->user(), - $tableQuery, - $status, - $subjectType, - $action, - ), - 'filters' => $this->dataTableFilters($tableQuery, [ - 'status' => $status, - 'subject_type' => $subjectType, - 'action' => $action, - ]), - 'statusOptions' => OwnerVerificationStatus::selectOptions(), - 'subjectOptions' => $this->ownerVerificationService->subjectTypeOptions($request->user()), - 'actionOptions' => OwnerVerificationAction::selectOptions(), - ]); - } - public function approveCutting(ApproveVerificationRequest $request, Cutting $cutting): RedirectResponse { $this->stockService->approveVerification( @@ -63,9 +31,7 @@ public function approveCutting(ApproveVerificationRequest $request, Cutting $cut $this->flashSuccess('Verifikasi cutting berhasil disetujui. Stok produk telah ditambahkan ke toko.'); - $fallback = route('admin.manage.owner_verifications.index'); - - return back(302, [], $fallback); + return back(302); } public function rejectCutting(RejectVerificationRequest $request, Cutting $cutting): RedirectResponse @@ -78,9 +44,7 @@ public function rejectCutting(RejectVerificationRequest $request, Cutting $cutti $this->flashSuccess('Verifikasi cutting berhasil ditolak.'); - $fallback = route('admin.manage.owner_verifications.index'); - - return back(302, [], $fallback); + return back(302); } public function approveRequest( @@ -95,9 +59,7 @@ public function approveRequest( $this->flashSuccess('Verifikasi berhasil disetujui.'); - $fallback = route('admin.manage.owner_verifications.index'); - - return back(302, [], $fallback); + return back(302); } public function rejectRequest( @@ -112,8 +74,6 @@ public function rejectRequest( $this->flashSuccess('Verifikasi berhasil ditolak.'); - $fallback = route('admin.manage.owner_verifications.index'); - - return back(302, [], $fallback); + return back(302); } } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 2722d2e..7df5ea4 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -5,7 +5,6 @@ use App\Models\Cutting; use App\Models\EmployeeAdvance; use App\Models\LeaveRequest; -use App\Services\Manage\OwnerVerificationService; use App\Services\System\Setting\SystemService; use App\Settings\SystemSettings; use Illuminate\Http\Request; @@ -72,7 +71,6 @@ public function share(Request $request): array 'pendingLeaveRequests' => fn () => $this->pendingLeaveRequests($request), 'pendingEmployeeAdvances' => fn () => $this->pendingEmployeeAdvances($request), 'pendingCuttings' => fn () => $this->pendingCuttings($request), - 'pendingOwnerVerifications' => fn () => $this->pendingOwnerVerifications($request), ]; } @@ -114,15 +112,4 @@ private function pendingCuttings(Request $request): int ->completed() ->count(); } - - private function pendingOwnerVerifications(Request $request): int - { - $user = $request->user(); - - if ($user === null || ! $user->can('owner_verifications.view')) { - return 0; - } - - return app(OwnerVerificationService::class)->pendingCountForUser($user); - } } diff --git a/app/Http/Requests/Admin/Manage/ApproveVerificationRequest.php b/app/Http/Requests/Admin/Manage/ApproveVerificationRequest.php index e6a61aa..57cbadd 100644 --- a/app/Http/Requests/Admin/Manage/ApproveVerificationRequest.php +++ b/app/Http/Requests/Admin/Manage/ApproveVerificationRequest.php @@ -2,19 +2,15 @@ namespace App\Http\Requests\Admin\Manage; -use App\Enums\Permission; use Illuminate\Foundation\Http\FormRequest; class ApproveVerificationRequest extends FormRequest { public function authorize(): bool { - return $this->user()?->can(Permission::OWNER_VERIFICATIONS_VERIFY->value) ?? false; + return true; } - /** - * @return array - */ public function rules(): array { return [ diff --git a/app/Http/Requests/Admin/Manage/RejectVerificationRequest.php b/app/Http/Requests/Admin/Manage/RejectVerificationRequest.php index ef2b780..9807de2 100644 --- a/app/Http/Requests/Admin/Manage/RejectVerificationRequest.php +++ b/app/Http/Requests/Admin/Manage/RejectVerificationRequest.php @@ -2,19 +2,15 @@ namespace App\Http\Requests\Admin\Manage; -use App\Enums\Permission; use Illuminate\Foundation\Http\FormRequest; class RejectVerificationRequest extends FormRequest { public function authorize(): bool { - return $this->user()?->can(Permission::OWNER_VERIFICATIONS_REJECT->value) ?? false; + return true; } - /** - * @return array - */ public function rules(): array { return [ diff --git a/app/Services/Manage/OwnerVerificationService.php b/app/Services/Manage/OwnerVerificationService.php index f3bd9f3..8f1c570 100644 --- a/app/Services/Manage/OwnerVerificationService.php +++ b/app/Services/Manage/OwnerVerificationService.php @@ -265,7 +265,7 @@ public function rejectRequest( '❌ Pengajuan Ditolak', "Pengajuan {$request->action->label()} {$subjectLabel} '{$title}' ditolak dengan alasan: '{$reason}'.", ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.dashboard'), ); $this->notifyRequestSubmitter( @@ -527,7 +527,7 @@ private function notifyRequestSubmitter( RawMaterial::class => route('admin.master.raw_materials.index'), Purchase::class => route('admin.manage.purchases.index'), MarketplaceSettings::class => route('admin.system.settings.index'), - default => route('admin.manage.owner_verifications.index'), + default => route('admin.dashboard'), }; $this->pushNotificationService->sendToUser( diff --git a/app/Services/Manage/PurchaseService.php b/app/Services/Manage/PurchaseService.php index fd7fd2d..8d58562 100644 --- a/app/Services/Manage/PurchaseService.php +++ b/app/Services/Manage/PurchaseService.php @@ -544,7 +544,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ "📦 {$typeLabel} Menunggu Persetujuan Owner", $body, ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.manage.purchases.index'), ); $this->pushNotificationService->sendToUser( diff --git a/app/Services/Manage/StockService.php b/app/Services/Manage/StockService.php index 11bc9cf..459ebc1 100644 --- a/app/Services/Manage/StockService.php +++ b/app/Services/Manage/StockService.php @@ -134,7 +134,7 @@ public function submitVerification( '📦 Verifikasi Stok Menunggu Persetujuan', "Cutting dengan deskripsi '{$description}' telah diajukan verifikasi dan menunggu persetujuan owner.", ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.manage.stocks.index'), ); } @@ -187,7 +187,7 @@ public function approveVerification( '📦 Stok Cutting Diverifikasi', "Cutting dengan deskripsi '{$description}' telah disetujui owner dan stok produk telah ditambahkan ke toko.", ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.manage.stocks.index'), ); } @@ -232,7 +232,7 @@ public function rejectVerification( '📦 Verifikasi Cutting Ditolak Owner', "Cutting dengan deskripsi '{$description}' ditolak oleh owner dengan alasan: '{$reason}'.", ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.manage.stocks.index'), ); if ($cutting->submitted_by_id) { @@ -240,7 +240,7 @@ public function rejectVerification( '📦 Verifikasi Cutting Ditolak Owner', "Cutting dengan deskripsi '{$description}' yang Anda verifikasi ditolak oleh owner dengan alasan: '{$reason}'.", $cutting->submitted_by_id, - route('admin.manage.owner_verifications.index'), + route('admin.manage.stocks.index'), ); } } diff --git a/app/Services/Master/ProductService.php b/app/Services/Master/ProductService.php index b81b3a1..b8b9b13 100644 --- a/app/Services/Master/ProductService.php +++ b/app/Services/Master/ProductService.php @@ -432,7 +432,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ "📦 {$typeLabel} Menunggu Persetujuan Owner", $body, ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.master.products.index'), ); $this->pushNotificationService->sendToUser( diff --git a/app/Services/Master/RawMaterialService.php b/app/Services/Master/RawMaterialService.php index f285116..571c943 100644 --- a/app/Services/Master/RawMaterialService.php +++ b/app/Services/Master/RawMaterialService.php @@ -307,7 +307,7 @@ private function notifyForPendingRequest(User $user, string $typeLabel, string $ "📦 {$typeLabel} Menunggu Persetujuan Owner", $body, ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.master.raw_materials.index'), ); $this->pushNotificationService->sendToUser( diff --git a/app/Services/System/Setting/MarketplaceService.php b/app/Services/System/Setting/MarketplaceService.php index 8eccf46..f9f6361 100644 --- a/app/Services/System/Setting/MarketplaceService.php +++ b/app/Services/System/Setting/MarketplaceService.php @@ -125,7 +125,7 @@ public function updateMarketplace(array $validated, User $user): void '⚙️ Pengaturan Marketplace Menunggu Persetujuan Owner', "Pengajuan ubah pengaturan marketplace oleh '{$user->username}' menunggu verifikasi owner.", ['owner', 'developer'], - route('admin.manage.owner_verifications.index'), + route('admin.system.settings.index'), ); $this->pushNotificationService->sendToUser( diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index 4335808..b416de0 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -1,6 +1,6 @@ - - diff --git a/resources/js/pages/admin/manage/owner-verifications/table/OwnerVerificationDetailModal.vue b/resources/js/pages/admin/manage/owner-verifications/table/OwnerVerificationDetailModal.vue deleted file mode 100644 index d6762c9..0000000 --- a/resources/js/pages/admin/manage/owner-verifications/table/OwnerVerificationDetailModal.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - diff --git a/resources/js/pages/admin/manage/owner-verifications/table/columns.ts b/resources/js/pages/admin/manage/owner-verifications/table/columns.ts deleted file mode 100644 index ee6cd73..0000000 --- a/resources/js/pages/admin/manage/owner-verifications/table/columns.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { ColumnDef } from '@tanstack/vue-table'; -import { h } from 'vue'; -import { Badge } from '@/components/ui/badge'; -import { DataTableColumnHeader } from '@/components/data-table'; -import type { OwnerVerificationItem } from '@/types/owner-verification'; -import DataTableActions from './data-table-actions.vue'; - -function statusBadgeVariant(status: string): 'default' | 'destructive' | 'outline' | 'secondary' { - if (status === 'approved') { - return 'default'; - } - - if (status === 'rejected') { - return 'destructive'; - } - - return 'outline'; -} - -export function createColumns( - onView: (item: OwnerVerificationItem) => void, -): ColumnDef[] { - return [ - { - accessorKey: 'created_at_formatted', - enableSorting: true, - header: () => h(DataTableColumnHeader, { title: 'Waktu', column: 'created_at' }), - cell: ({ row }) => row.original.created_at_formatted ?? '-', - }, - { - accessorKey: 'submitted_by_name', - enableSorting: false, - header: 'Diajukan Oleh', - }, - { - accessorKey: 'action_label', - enableSorting: true, - header: () => h(DataTableColumnHeader, { title: 'Aksi', column: 'action' }), - }, - { - accessorKey: 'subject_label', - enableSorting: false, - header: 'Modul', - }, - { - accessorKey: 'title', - enableSorting: false, - header: 'Item', - }, - { - accessorKey: 'status_label', - enableSorting: true, - header: () => h(DataTableColumnHeader, { title: 'Status', column: 'status' }), - cell: ({ row }) => h( - Badge, - { variant: statusBadgeVariant(row.original.status) }, - () => row.original.status_label, - ), - }, - { - id: 'actions', - enableSorting: false, - enableHiding: false, - cell: ({ row }) => h(DataTableActions, { - item: row.original, - onView: () => onView(row.original), - }), - }, - ]; -} diff --git a/resources/js/pages/admin/manage/owner-verifications/table/data-table-actions.vue b/resources/js/pages/admin/manage/owner-verifications/table/data-table-actions.vue deleted file mode 100644 index 288ad0e..0000000 --- a/resources/js/pages/admin/manage/owner-verifications/table/data-table-actions.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/resources/js/types/owner-verification.ts b/resources/js/types/owner-verification.ts deleted file mode 100644 index 2488c65..0000000 --- a/resources/js/types/owner-verification.ts +++ /dev/null @@ -1,51 +0,0 @@ -export type OwnerVerificationSource = 'cutting' | 'request'; - -export interface VerificationChange { - field: string; - old: unknown; - new: unknown; -} - -export interface OwnerVerificationItem { - id: number; - source: OwnerVerificationSource; - subject_type: string | null; - subject_label: string; - subject_id: number | null; - action: string; - action_label: string; - status: string; - status_label: string; - title: string; - summary?: string; - submitted_by_name: string; - verified_by_name?: string | null; - verified_at_formatted?: string | null; - created_at?: string | null; - created_at_formatted: string | null; - changes: VerificationChange[]; - rejection_reason?: string | null; - is_pending: boolean; - detail?: Record; -} - -/** @deprecated Use OwnerVerificationItem */ -export type OwnerVerificationRequestItem = OwnerVerificationItem; - -export interface SelectOption { - value: string; - label: string; -} - -export interface PaginatedOwnerVerificationRequests { - data: OwnerVerificationItem[]; - current_page: number; - per_page: number; - last_page: number; - total: number; - links: Array<{ - url: string | null; - label: string; - active: boolean; - }>; -} diff --git a/routes/web.php b/routes/web.php index 60b2b8a..0aa49ed 100644 --- a/routes/web.php +++ b/routes/web.php @@ -356,10 +356,7 @@ }); Route::prefix('owner-verifications')->name('owner_verifications.') - ->middleware('permission:'.Permission::OWNER_VERIFICATIONS_VIEW->value) ->group(function () { - Route::get('/', [OwnerVerificationController::class, 'index'])->name('index'); - Route::post('cuttings/{cutting}/approve', [OwnerVerificationController::class, 'approveCutting']) ->middleware('permission:'.Permission::OWNER_VERIFICATIONS_VERIFY->value) ->name('approve'); diff --git a/tests/Feature/Admin/Manage/OwnerVerificationTest.php b/tests/Feature/Admin/Manage/OwnerVerificationTest.php deleted file mode 100644 index 781cf61..0000000 --- a/tests/Feature/Admin/Manage/OwnerVerificationTest.php +++ /dev/null @@ -1,354 +0,0 @@ -seed(RolePermissionSeeder::class); -}); - -function createOwnerVerificationRequestFor(User $submitter, ?Product $product = null): OwnerVerificationRequest -{ - $product ??= Product::factory()->create(['is_active' => false]); - - return OwnerVerificationRequest::query()->create([ - 'action' => OwnerVerificationAction::CREATE, - 'status' => OwnerVerificationStatus::PENDING, - 'subject_type' => Product::class, - 'subject_id' => $product->id, - 'submitted_by_id' => $submitter->id, - 'payload' => ['old' => null, 'new' => ['name' => $product->name]], - ]); -} - -function createOwnerVerifierUser(): User -{ - $user = User::factory()->create(); - $user->assignRole(RoleEnum::OWNER->value); - $user->forgetCachedPermissions(); - - return $user; -} - -function createPendingCutting(?User $submitter = null): Cutting -{ - $submitter ??= User::factory()->create(); - - return Cutting::factory()->create([ - 'status' => CuttingStatus::PENDING_VERIFICATION, - 'submitted_by_id' => $submitter->id, - 'created_by_id' => $submitter->id, - 'description' => 'Cutting test pending', - ]); -} - -describe('Owner Verification Index', function () { - test('submitter with view permission only sees own verification requests', function () { - $submitter = User::factory()->create(); - $submitter->assignRole(RoleEnum::ADMIN_TOKO->value); - $submitter->forgetCachedPermissions(); - - $otherUser = User::factory()->create(); - $otherUser->assignRole(RoleEnum::ADMIN_TOKO->value); - $otherUser->forgetCachedPermissions(); - - $ownRequest = createOwnerVerificationRequestFor($submitter); - createOwnerVerificationRequestFor($otherUser); - - $response = $this->actingAs($submitter) - ->get(route('admin.manage.owner_verifications.index')); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->component('admin/manage/owner-verifications/Index') - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.id', $ownRequest->id) - ->where('verificationRequests.data.0.source', 'request') - ); - }); - - test('verifier sees all verification requests', function () { - $submitter = User::factory()->create(); - $submitter->assignRole(RoleEnum::ADMIN_TOKO->value); - $submitter->forgetCachedPermissions(); - - $verifier = createOwnerVerifierUser(); - - createOwnerVerificationRequestFor($submitter); - createOwnerVerificationRequestFor($submitter); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index')); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->component('admin/manage/owner-verifications/Index') - ->has('verificationRequests.data', 2) - ); - }); - - test('submitter cannot approve verification request', function () { - $submitter = User::factory()->create(); - $submitter->assignRole(RoleEnum::ADMIN_TOKO->value); - $submitter->forgetCachedPermissions(); - - $request = createOwnerVerificationRequestFor($submitter); - - $this->actingAs($submitter) - ->post(route('admin.manage.owner_verifications.approve_request', $request)) - ->assertForbidden(); - }); - - test('admin toko role has owner verification view permission', function () { - $user = User::factory()->create(); - $user->assignRole(RoleEnum::ADMIN_TOKO->value); - $user->forgetCachedPermissions(); - - expect($user->can(PermissionEnum::OWNER_VERIFICATIONS_VIEW->value))->toBeTrue(); - expect($user->can(PermissionEnum::OWNER_VERIFICATIONS_VERIFY->value))->toBeFalse(); - }); - - test('admin bahan baku role has owner verification view permission', function () { - $user = User::factory()->create(); - $user->assignRole(RoleEnum::ADMIN_BAHAN_BAKU->value); - $user->forgetCachedPermissions(); - - expect($user->can(PermissionEnum::OWNER_VERIFICATIONS_VIEW->value))->toBeTrue(); - expect($user->can(PermissionEnum::OWNER_VERIFICATIONS_VERIFY->value))->toBeFalse(); - }); -}); - -describe('Owner Verification Unified Cutting List', function () { - test('verifier sees pending cuttings in the same verification table', function () { - $verifier = createOwnerVerifierUser(); - $cutting = createPendingCutting(); - $request = createOwnerVerificationRequestFor(User::factory()->create()); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index')); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->component('admin/manage/owner-verifications/Index') - ->has('verificationRequests.data', 2) - ->where('verificationRequests.data.0.source', 'cutting') - ->where('verificationRequests.data.0.id', $cutting->id) - ->where('verificationRequests.data.0.action', OwnerVerificationAction::STOCK_VERIFY->value) - ->where('verificationRequests.data.0.subject_type', Cutting::class) - ->where('verificationRequests.data.1.source', 'request') - ->where('verificationRequests.data.1.id', $request->id) - ); - }); - - test('submitter does not see pending cuttings in verification table', function () { - $submitter = User::factory()->create(); - $submitter->assignRole(RoleEnum::ADMIN_TOKO->value); - $submitter->forgetCachedPermissions(); - - createPendingCutting(); - createOwnerVerificationRequestFor($submitter); - - $response = $this->actingAs($submitter) - ->get(route('admin.manage.owner_verifications.index')); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->component('admin/manage/owner-verifications/Index') - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.source', 'request') - ); - }); - - test('filtering by cutting module shows only pending cuttings', function () { - $verifier = createOwnerVerifierUser(); - $cutting = createPendingCutting(); - createOwnerVerificationRequestFor(User::factory()->create()); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index', [ - 'subject_type' => Cutting::class, - ])); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.source', 'cutting') - ->where('verificationRequests.data.0.id', $cutting->id) - ); - }); - - test('filtering by stock verify action shows only pending cuttings', function () { - $verifier = createOwnerVerifierUser(); - $cutting = createPendingCutting(); - createOwnerVerificationRequestFor(User::factory()->create()); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index', [ - 'action' => OwnerVerificationAction::STOCK_VERIFY->value, - ])); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.source', 'cutting') - ->where('verificationRequests.data.0.id', $cutting->id) - ); - }); - - test('filtering by approved status hides pending cuttings', function () { - $verifier = createOwnerVerifierUser(); - createPendingCutting(); - - OwnerVerificationRequest::query()->create([ - 'action' => OwnerVerificationAction::CREATE, - 'status' => OwnerVerificationStatus::APPROVED, - 'subject_type' => Product::class, - 'subject_id' => Product::factory()->create()->id, - 'submitted_by_id' => User::factory()->create()->id, - 'payload' => ['old' => null, 'new' => ['name' => 'Approved Product']], - 'verified_by_id' => $verifier->id, - 'verified_at' => now(), - ]); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index', [ - 'status' => OwnerVerificationStatus::APPROVED->value, - ])); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.source', 'request') - ->where('verificationRequests.data.0.status', OwnerVerificationStatus::APPROVED->value) - ); - }); - - test('subject options include cutting when pending cuttings exist', function () { - $verifier = createOwnerVerifierUser(); - createPendingCutting(); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index')); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->where('subjectOptions', fn ($options) => collect($options)->contains( - fn (array $option) => $option['value'] === Cutting::class - && $option['label'] === ModelLabel::for(Cutting::class), - )) - ); - }); - - test('verifier can approve pending cutting from verification page', function () { - $verifier = createOwnerVerifierUser(); - $cutting = createPendingCutting(); - - $this->actingAs($verifier) - ->post(route('admin.manage.owner_verifications.approve', $cutting)) - ->assertRedirect(route('admin.manage.owner_verifications.index')); - - expect($cutting->fresh()->status)->toBe(CuttingStatus::VERIFIED); - }); - - test('verifier can reject pending cutting from verification page', function () { - $verifier = createOwnerVerifierUser(); - $cutting = createPendingCutting(); - - $this->actingAs($verifier) - ->post(route('admin.manage.owner_verifications.reject', $cutting), [ - 'reason' => 'Data tidak sesuai', - ]) - ->assertRedirect(route('admin.manage.owner_verifications.index')); - - $cutting->refresh(); - - expect($cutting->status)->toBe(CuttingStatus::COMPLETED); - expect($cutting->rejection?->reason)->toBe('Data tidak sesuai'); - expect($cutting->rejection?->rejected_by_id)->toBe($verifier->id); - }); -}); - -describe('Owner Verification Purchase Module', function () { - test('verifier sees purchase verification requests in index', function () { - $verifier = createOwnerVerifierUser(); - $submitter = User::factory()->create(); - $purchase = Purchase::factory()->create(); - - OwnerVerificationRequest::query()->create([ - 'action' => OwnerVerificationAction::CREATE, - 'status' => OwnerVerificationStatus::PENDING, - 'subject_type' => Purchase::class, - 'subject_id' => $purchase->id, - 'submitted_by_id' => $submitter->id, - 'payload' => [ - 'old' => null, - 'new' => ['supplier_name' => $purchase->supplier?->name ?? 'Supplier'], - ], - ]); - - $response = $this->actingAs($verifier) - ->get(route('admin.manage.owner_verifications.index', [ - 'subject_type' => Purchase::class, - ])); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.source', 'request') - ->where('verificationRequests.data.0.subject_type', Purchase::class) - ->where('verificationRequests.data.0.subject_id', $purchase->id) - ); - }); - - test('purchase submitter sees only own purchase verification requests', function () { - $submitter = User::factory()->create(); - $submitter->assignRole(RoleEnum::ADMIN_BAHAN_BAKU->value); - $submitter->forgetCachedPermissions(); - - $otherUser = User::factory()->create(); - $ownPurchase = Purchase::factory()->create(['created_by_id' => $submitter->id]); - $otherPurchase = Purchase::factory()->create(['created_by_id' => $otherUser->id]); - - OwnerVerificationRequest::query()->create([ - 'action' => OwnerVerificationAction::CREATE, - 'status' => OwnerVerificationStatus::PENDING, - 'subject_type' => Purchase::class, - 'subject_id' => $ownPurchase->id, - 'submitted_by_id' => $submitter->id, - 'payload' => ['old' => null, 'new' => ['supplier_name' => 'Own']], - ]); - - OwnerVerificationRequest::query()->create([ - 'action' => OwnerVerificationAction::CREATE, - 'status' => OwnerVerificationStatus::PENDING, - 'subject_type' => Purchase::class, - 'subject_id' => $otherPurchase->id, - 'submitted_by_id' => $otherUser->id, - 'payload' => ['old' => null, 'new' => ['supplier_name' => 'Other']], - ]); - - $response = $this->actingAs($submitter) - ->get(route('admin.manage.owner_verifications.index', [ - 'subject_type' => Purchase::class, - ])); - - $response->assertOk(); - $response->assertInertia(fn ($page) => $page - ->has('verificationRequests.data', 1) - ->where('verificationRequests.data.0.subject_id', $ownPurchase->id) - ); - }); -}); diff --git a/tests/Feature/Admin/Manage/PurchaseTest.php b/tests/Feature/Admin/Manage/PurchaseTest.php index e80cb32..62bbd83 100644 --- a/tests/Feature/Admin/Manage/PurchaseTest.php +++ b/tests/Feature/Admin/Manage/PurchaseTest.php @@ -56,7 +56,7 @@ function approveLatestPurchaseVerificationRequest(User $verifier): OwnerVerifica test()->actingAs($verifier) ->post(route('admin.manage.owner_verifications.approve_request', $verificationRequest)) - ->assertRedirect(route('admin.manage.owner_verifications.index')); + ->assertRedirect(); return $verificationRequest->fresh(); } @@ -263,7 +263,7 @@ function approveLatestPurchaseVerificationRequest(User $verifier): OwnerVerifica ->post(route('admin.manage.owner_verifications.reject_request', $verificationRequest), [ 'reason' => 'Tidak sesuai', ]) - ->assertRedirect(route('admin.manage.owner_verifications.index')); + ->assertRedirect(); expect(Purchase::query()->whereKey($purchase->id)->exists())->toBeFalse(); expect(PurchaseItem::query()->where('purchase_id', $purchase->id)->exists())->toBeFalse(); diff --git a/tests/Feature/Admin/Master/ProductTest.php b/tests/Feature/Admin/Master/ProductTest.php index aa964fa..65e3ba6 100644 --- a/tests/Feature/Admin/Master/ProductTest.php +++ b/tests/Feature/Admin/Master/ProductTest.php @@ -76,7 +76,7 @@ function approveLatestOwnerVerificationRequest(User $verifier): OwnerVerificatio test()->actingAs($verifier) ->post(route('admin.manage.owner_verifications.approve_request', $verificationRequest)) - ->assertRedirect(route('admin.manage.owner_verifications.index')); + ->assertRedirect(); return $verificationRequest->fresh(); } @@ -431,7 +431,7 @@ function variantWithImage(string $name = 'All Size', int $stock = 10): array ->post(route('admin.manage.owner_verifications.reject_request', $verificationRequest), [ 'reason' => 'Tidak sesuai standar', ]) - ->assertRedirect(route('admin.manage.owner_verifications.index')); + ->assertRedirect(); $this->assertSoftDeleted('products', ['id' => $product->id]); }); diff --git a/tests/Feature/Admin/Master/RawMaterialTest.php b/tests/Feature/Admin/Master/RawMaterialTest.php index 896ab47..12e17e4 100644 --- a/tests/Feature/Admin/Master/RawMaterialTest.php +++ b/tests/Feature/Admin/Master/RawMaterialTest.php @@ -84,7 +84,7 @@ function approveLatestOwnerVerificationRequest(User $verifier): OwnerVerificatio test()->actingAs($verifier) ->post(route('admin.manage.owner_verifications.approve_request', $verificationRequest)) - ->assertRedirect(route('admin.manage.owner_verifications.index')); + ->assertRedirect(); return $verificationRequest->fresh(); }