feat: implement transaction management in RawMaterialService for create, update, delete, and toggle status operations; refactor error handling for improved clarity; enhance tests for raw material and price models to ensure proper functionality and validation
This commit is contained in:
parent
80e1542151
commit
9d0075d7b2
@ -10,17 +10,18 @@
|
|||||||
use App\Models\RawMaterial;
|
use App\Models\RawMaterial;
|
||||||
use App\Models\RawMaterialPrice;
|
use App\Models\RawMaterialPrice;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Services\Concerns\RunsInTransaction;
|
||||||
use App\Services\Media\MediaService;
|
use App\Services\Media\MediaService;
|
||||||
use App\Services\System\PushNotificationService;
|
use App\Services\System\PushNotificationService;
|
||||||
use App\Support\Media\MediaPresenter;
|
use App\Support\Media\MediaPresenter;
|
||||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class RawMaterialService
|
class RawMaterialService
|
||||||
{
|
{
|
||||||
|
use RunsInTransaction;
|
||||||
|
|
||||||
private const MAX_VARIANT_IMAGES = 5;
|
private const MAX_VARIANT_IMAGES = 5;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@ -114,8 +115,8 @@ public function create(array $validated, User $user): void
|
|||||||
{
|
{
|
||||||
$isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value);
|
$isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value);
|
||||||
|
|
||||||
try {
|
$this->runInTransaction(
|
||||||
DB::transaction(function () use ($validated, $user, $isOwner): void {
|
function () use ($validated, $user, $isOwner): void {
|
||||||
$rawMaterial = RawMaterial::create([
|
$rawMaterial = RawMaterial::create([
|
||||||
'name' => $validated['name'],
|
'name' => $validated['name'],
|
||||||
'unit' => $validated['unit'],
|
'unit' => $validated['unit'],
|
||||||
@ -139,18 +140,9 @@ public function create(array $validated, User $user): void
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
} catch (ValidationException $e) {
|
'Gagal membuat bahan baku',
|
||||||
throw $e;
|
);
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Log::error('Gagal membuat bahan baku: '.$e->getMessage(), [
|
|
||||||
'trace' => $e->getTraceAsString(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $isOwner) {
|
if (! $isOwner) {
|
||||||
$this->notifyForPendingRequest(
|
$this->notifyForPendingRequest(
|
||||||
@ -167,8 +159,8 @@ public function update(RawMaterial $rawMaterial, array $validated, User $user):
|
|||||||
{
|
{
|
||||||
$isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value);
|
$isOwner = $user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value);
|
||||||
|
|
||||||
try {
|
$this->runInTransaction(
|
||||||
DB::transaction(function () use ($validated, $rawMaterial, $user, $isOwner): void {
|
function () use ($validated, $rawMaterial, $user, $isOwner): void {
|
||||||
if ($isOwner) {
|
if ($isOwner) {
|
||||||
$payload = $this->enrichPayload($this->buildPayloadFromValidated($validated));
|
$payload = $this->enrichPayload($this->buildPayloadFromValidated($validated));
|
||||||
$this->applyPayloadToRawMaterial($rawMaterial, $payload);
|
$this->applyPayloadToRawMaterial($rawMaterial, $payload);
|
||||||
@ -201,18 +193,9 @@ public function update(RawMaterial $rawMaterial, array $validated, User $user):
|
|||||||
$this->syncRequestPriceImages($verificationRequest, $priceData, $index, required: $isNewPrice);
|
$this->syncRequestPriceImages($verificationRequest, $priceData, $index, required: $isNewPrice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
} catch (ValidationException $e) {
|
'Gagal memperbarui bahan baku',
|
||||||
throw $e;
|
);
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Log::error('Gagal memperbarui bahan baku: '.$e->getMessage(), [
|
|
||||||
'trace' => $e->getTraceAsString(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $isOwner) {
|
if (! $isOwner) {
|
||||||
$this->notifyForPendingRequest(
|
$this->notifyForPendingRequest(
|
||||||
@ -235,27 +218,22 @@ public function delete(RawMaterial $rawMaterial, User $user): void
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$this->runInTransaction(
|
||||||
OwnerVerificationRequest::create([
|
function () use ($rawMaterial, $user): void {
|
||||||
'action' => OwnerVerificationAction::DELETE,
|
OwnerVerificationRequest::create([
|
||||||
'status' => OwnerVerificationStatus::PENDING,
|
'action' => OwnerVerificationAction::DELETE,
|
||||||
'subject_type' => RawMaterial::class,
|
'status' => OwnerVerificationStatus::PENDING,
|
||||||
'subject_id' => $rawMaterial->id,
|
'subject_type' => RawMaterial::class,
|
||||||
'submitted_by_id' => $user->id,
|
'subject_id' => $rawMaterial->id,
|
||||||
'payload' => [
|
'submitted_by_id' => $user->id,
|
||||||
'old' => $this->snapshotRawMaterial($rawMaterial),
|
'payload' => [
|
||||||
'new' => null,
|
'old' => $this->snapshotRawMaterial($rawMaterial),
|
||||||
],
|
'new' => null,
|
||||||
]);
|
],
|
||||||
} catch (\Throwable $e) {
|
]);
|
||||||
Log::error('Gagal mengajukan penghapusan bahan baku: '.$e->getMessage(), [
|
},
|
||||||
'trace' => $e->getTraceAsString(),
|
'Gagal mengajukan penghapusan bahan baku',
|
||||||
]);
|
);
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->notifyForPendingRequest(
|
$this->notifyForPendingRequest(
|
||||||
$user,
|
$user,
|
||||||
@ -278,33 +256,28 @@ public function toggleStatus(RawMaterial $rawMaterial, array $validated, User $u
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$this->runInTransaction(
|
||||||
OwnerVerificationRequest::create([
|
function () use ($rawMaterial, $validated, $user): void {
|
||||||
'action' => OwnerVerificationAction::TOGGLE_STATUS,
|
OwnerVerificationRequest::create([
|
||||||
'status' => OwnerVerificationStatus::PENDING,
|
'action' => OwnerVerificationAction::TOGGLE_STATUS,
|
||||||
'subject_type' => RawMaterial::class,
|
'status' => OwnerVerificationStatus::PENDING,
|
||||||
'subject_id' => $rawMaterial->id,
|
'subject_type' => RawMaterial::class,
|
||||||
'submitted_by_id' => $user->id,
|
'subject_id' => $rawMaterial->id,
|
||||||
'payload' => [
|
'submitted_by_id' => $user->id,
|
||||||
'old' => [
|
'payload' => [
|
||||||
'name' => $rawMaterial->name,
|
'old' => [
|
||||||
'is_active' => $rawMaterial->is_active,
|
'name' => $rawMaterial->name,
|
||||||
|
'is_active' => $rawMaterial->is_active,
|
||||||
|
],
|
||||||
|
'new' => [
|
||||||
|
'name' => $rawMaterial->name,
|
||||||
|
'is_active' => (bool) $validated['is_active'],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'new' => [
|
]);
|
||||||
'name' => $rawMaterial->name,
|
},
|
||||||
'is_active' => (bool) $validated['is_active'],
|
'Gagal mengajukan perubahan status bahan baku',
|
||||||
],
|
);
|
||||||
],
|
|
||||||
]);
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Log::error('Gagal mengajukan perubahan status bahan baku: '.$e->getMessage(), [
|
|
||||||
'trace' => $e->getTraceAsString(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$statusLabel = $validated['is_active'] ? 'aktif' : 'nonaktif';
|
$statusLabel = $validated['is_active'] ? 'aktif' : 'nonaktif';
|
||||||
|
|
||||||
@ -418,13 +391,16 @@ public function applyDelete(OwnerVerificationRequest $verificationRequest): void
|
|||||||
|
|
||||||
private function applyDeleteSubject(RawMaterial $rawMaterial): void
|
private function applyDeleteSubject(RawMaterial $rawMaterial): void
|
||||||
{
|
{
|
||||||
DB::transaction(function () use ($rawMaterial): void {
|
$this->runInTransaction(
|
||||||
$rawMaterial->prices()->each(function (RawMaterialPrice $price): void {
|
function () use ($rawMaterial): void {
|
||||||
$price->clearMediaCollection('images');
|
$rawMaterial->prices()->each(function (RawMaterialPrice $price): void {
|
||||||
});
|
$price->clearMediaCollection('images');
|
||||||
$rawMaterial->prices()->delete();
|
});
|
||||||
$rawMaterial->delete();
|
$rawMaterial->prices()->delete();
|
||||||
});
|
$rawMaterial->delete();
|
||||||
|
},
|
||||||
|
'Gagal menghapus bahan baku',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyToggleStatus(OwnerVerificationRequest $verificationRequest): void
|
public function applyToggleStatus(OwnerVerificationRequest $verificationRequest): void
|
||||||
@ -510,13 +486,16 @@ private function rejectCreate(OwnerVerificationRequest $verificationRequest): vo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::transaction(function () use ($rawMaterial): void {
|
$this->runInTransaction(
|
||||||
$rawMaterial->prices()->each(function (RawMaterialPrice $price): void {
|
function () use ($rawMaterial): void {
|
||||||
$price->clearMediaCollection('images');
|
$rawMaterial->prices()->each(function (RawMaterialPrice $price): void {
|
||||||
});
|
$price->clearMediaCollection('images');
|
||||||
$rawMaterial->prices()->delete();
|
});
|
||||||
$rawMaterial->delete();
|
$rawMaterial->prices()->delete();
|
||||||
});
|
$rawMaterial->delete();
|
||||||
|
},
|
||||||
|
'Gagal menolak bahan baku',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function rollbackUpdate(OwnerVerificationRequest $verificationRequest): void
|
private function rollbackUpdate(OwnerVerificationRequest $verificationRequest): void
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
use App\Enums\OwnerVerificationStatus;
|
use App\Enums\OwnerVerificationStatus;
|
||||||
use App\Enums\Permission as PermissionEnum;
|
use App\Enums\Permission as PermissionEnum;
|
||||||
use App\Enums\RawMaterialUnit;
|
use App\Enums\RawMaterialUnit;
|
||||||
|
use App\Models\OwnerVerificationRequest;
|
||||||
use App\Models\RawMaterial;
|
use App\Models\RawMaterial;
|
||||||
use App\Models\RawMaterialPrice;
|
use App\Models\RawMaterialPrice;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
@ -11,6 +12,7 @@
|
|||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
uses(RefreshDatabase::class);
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
@ -53,11 +55,16 @@ function createRawMaterialWithPrices(): RawMaterial
|
|||||||
|
|
||||||
function priceWithImage(string $variant = 'Default', int $price = 50000, float $stock = 10): array
|
function priceWithImage(string $variant = 'Default', int $price = 50000, float $stock = 10): array
|
||||||
{
|
{
|
||||||
|
$disk = config('filesystems.default') === 's3' ? 's3' : config('filesystems.default', 'public');
|
||||||
|
$key = 'raw-materials/'.Str::uuid().".jpg";
|
||||||
|
$imageContent = UploadedFile::fake()->image("{$variant}.jpg", 100, 100)->get();
|
||||||
|
Storage::disk($disk)->put($key, $imageContent);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'variant' => $variant,
|
'variant' => $variant,
|
||||||
'price' => $price,
|
'price' => $price,
|
||||||
'stock' => $stock,
|
'stock' => $stock,
|
||||||
'images' => [UploadedFile::fake()->image("{$variant}.jpg", 100, 100)],
|
's3_keys' => [$key],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,4 +732,178 @@ function createRawMaterialVerifierUser(): User
|
|||||||
|
|
||||||
expect($rawMaterial->unit_abbreviation)->toBe('kg');
|
expect($rawMaterial->unit_abbreviation)->toBe('kg');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('raw material has total_stock_formatted accessor', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create(['unit' => RawMaterialUnit::METER->value]);
|
||||||
|
RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id, 'stock' => 10.5]);
|
||||||
|
RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id, 'stock' => 5.25]);
|
||||||
|
|
||||||
|
expect($rawMaterial->fresh()->total_stock_formatted)->toContain('15,75');
|
||||||
|
expect($rawMaterial->fresh()->total_stock_formatted)->toContain('m');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── RawMaterialPrice Model ────────────────────────────────
|
||||||
|
|
||||||
|
describe('RawMaterialPrice Model', function () {
|
||||||
|
test('price has price cast to integer', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
$price = RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id, 'price' => 75000]);
|
||||||
|
|
||||||
|
expect($price->price)->toBeInt();
|
||||||
|
expect($price->price)->toBe(75000);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('price has formatted price accessor', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
$price = RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id, 'price' => 1500000]);
|
||||||
|
|
||||||
|
expect($price->price_formatted)->toBe('Rp 1.500.000');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('price has price_input accessor', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
$price = RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id, 'price' => 200000]);
|
||||||
|
|
||||||
|
expect($price->price_input)->toBe('200000');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('price belongs to raw material', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
$price = RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id]);
|
||||||
|
|
||||||
|
expect($price->rawMaterial)->not->toBeNull();
|
||||||
|
expect($price->rawMaterial->id)->toBe($rawMaterial->id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('price uses soft deletes', function () {
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
$price = RawMaterialPrice::factory()->create(['raw_material_id' => $rawMaterial->id]);
|
||||||
|
|
||||||
|
$price->delete();
|
||||||
|
|
||||||
|
expect($price->trashed())->toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── Owner Direct Actions ──────────────────────────────────
|
||||||
|
|
||||||
|
describe('Owner Direct Actions', function () {
|
||||||
|
test('owner can create raw material directly without verification', function () {
|
||||||
|
$owner = createRawMaterialUserWithPermission(
|
||||||
|
PermissionEnum::RAW_MATERIALS_VIEW,
|
||||||
|
PermissionEnum::RAW_MATERIALS_CREATE,
|
||||||
|
PermissionEnum::OWNER_VERIFICATIONS_VERIFY,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->actingAs($owner)
|
||||||
|
->post(route('admin.master.raw_materials.store'), [
|
||||||
|
'name' => 'Kain Owner',
|
||||||
|
'unit' => RawMaterialUnit::METER->value,
|
||||||
|
'prices' => [
|
||||||
|
priceWithImage('Merah', 75000, 50),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->assertRedirect(route('admin.master.raw_materials.index'));
|
||||||
|
|
||||||
|
$rawMaterial = RawMaterial::where('name', 'Kain Owner')->first();
|
||||||
|
expect($rawMaterial)->not->toBeNull();
|
||||||
|
expect($rawMaterial->is_active)->toBeTrue();
|
||||||
|
|
||||||
|
$this->assertDatabaseMissing('owner_verification_requests', [
|
||||||
|
'subject_id' => $rawMaterial->id,
|
||||||
|
'subject_type' => RawMaterial::class,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('owner can update raw material directly without verification', function () {
|
||||||
|
$owner = createRawMaterialUserWithPermission(
|
||||||
|
PermissionEnum::RAW_MATERIALS_VIEW,
|
||||||
|
PermissionEnum::RAW_MATERIALS_UPDATE,
|
||||||
|
PermissionEnum::OWNER_VERIFICATIONS_VERIFY,
|
||||||
|
);
|
||||||
|
|
||||||
|
$rawMaterial = createRawMaterialWithPrices();
|
||||||
|
$price = $rawMaterial->prices->first();
|
||||||
|
|
||||||
|
$this->actingAs($owner)
|
||||||
|
->put(route('admin.master.raw_materials.update', $rawMaterial), [
|
||||||
|
'name' => 'Kain Updated',
|
||||||
|
'unit' => RawMaterialUnit::KILOGRAM->value,
|
||||||
|
'prices' => [
|
||||||
|
['id' => $price->id, 'variant' => 'Putih', 'price' => 90000, 'stock' => 25],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->assertRedirect(route('admin.master.raw_materials.index'));
|
||||||
|
|
||||||
|
expect($rawMaterial->fresh()->name)->toBe('Kain Updated');
|
||||||
|
expect($price->fresh()->variant)->toBe('Putih');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('owner can delete raw material directly without verification', function () {
|
||||||
|
$owner = createRawMaterialUserWithPermission(
|
||||||
|
PermissionEnum::RAW_MATERIALS_VIEW,
|
||||||
|
PermissionEnum::RAW_MATERIALS_DELETE,
|
||||||
|
PermissionEnum::OWNER_VERIFICATIONS_VERIFY,
|
||||||
|
);
|
||||||
|
|
||||||
|
$rawMaterial = createRawMaterialWithPrices();
|
||||||
|
|
||||||
|
$this->actingAs($owner)
|
||||||
|
->delete(route('admin.master.raw_materials.destroy', $rawMaterial))
|
||||||
|
->assertRedirect(route('admin.master.raw_materials.index'));
|
||||||
|
|
||||||
|
$this->assertSoftDeleted('raw_materials', ['id' => $rawMaterial->id]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('owner can toggle raw material status directly without verification', function () {
|
||||||
|
$owner = createRawMaterialUserWithPermission(
|
||||||
|
PermissionEnum::RAW_MATERIALS_VIEW,
|
||||||
|
PermissionEnum::RAW_MATERIALS_TOGGLE_STATUS,
|
||||||
|
PermissionEnum::OWNER_VERIFICATIONS_VERIFY,
|
||||||
|
);
|
||||||
|
|
||||||
|
$rawMaterial = RawMaterial::factory()->create();
|
||||||
|
|
||||||
|
$this->actingAs($owner)
|
||||||
|
->patch(route('admin.master.raw_materials.toggle_status', $rawMaterial), [
|
||||||
|
'is_active' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($rawMaterial->fresh()->is_active)->toBeFalse();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ─── Reject Update Request ─────────────────────────────────
|
||||||
|
|
||||||
|
describe('Reject Update Request', function () {
|
||||||
|
test('rejecting update request rolls back to old values', function () {
|
||||||
|
$user = createRawMaterialUserWithPermission(PermissionEnum::RAW_MATERIALS_VIEW, PermissionEnum::RAW_MATERIALS_UPDATE);
|
||||||
|
$verifier = createRawMaterialVerifierUser();
|
||||||
|
|
||||||
|
$rawMaterial = createRawMaterialWithPrices();
|
||||||
|
$price = $rawMaterial->prices->first();
|
||||||
|
$originalName = $rawMaterial->name;
|
||||||
|
$originalVariant = $price->variant;
|
||||||
|
|
||||||
|
$this->actingAs($user)
|
||||||
|
->put(route('admin.master.raw_materials.update', $rawMaterial), [
|
||||||
|
'name' => 'Nama Diubah',
|
||||||
|
'unit' => RawMaterialUnit::KILOGRAM->value,
|
||||||
|
'prices' => [
|
||||||
|
['id' => $price->id, 'variant' => 'Putih', 'price' => 90000, 'stock' => 25],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$verificationRequest = OwnerVerificationRequest::query()->pending()->latest()->firstOrFail();
|
||||||
|
|
||||||
|
$this->actingAs($verifier)
|
||||||
|
->post(route('admin.manage.owner_verifications.reject_request', $verificationRequest), [
|
||||||
|
'reason' => 'Tidak sesuai standar',
|
||||||
|
])
|
||||||
|
->assertRedirect();
|
||||||
|
|
||||||
|
expect($rawMaterial->fresh()->name)->toBe($originalName);
|
||||||
|
expect($price->fresh()->variant)->toBe($originalVariant);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user