refactor: remove unused docblocks in SupplierService and add getSelectOptions method for improved supplier data retrieval
This commit is contained in:
parent
4f7290711d
commit
8159e45e3a
@ -8,9 +8,6 @@
|
||||
|
||||
class SupplierService
|
||||
{
|
||||
/**
|
||||
* @param array{search: string, sort: string, direction: 'asc'|'desc'} $tableQuery
|
||||
*/
|
||||
public function paginateForIndex(array $tableQuery): LengthAwarePaginator
|
||||
{
|
||||
$query = Supplier::query()
|
||||
@ -30,17 +27,11 @@ public function paginateForIndex(array $tableQuery): LengthAwarePaginator
|
||||
->withQueryString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $validated
|
||||
*/
|
||||
public function create(array $validated): void
|
||||
{
|
||||
Supplier::create($validated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $validated
|
||||
*/
|
||||
public function update(Supplier $supplier, array $validated): void
|
||||
{
|
||||
$supplier->update($validated);
|
||||
@ -51,6 +42,18 @@ public function delete(Supplier $supplier): void
|
||||
$supplier->delete();
|
||||
}
|
||||
|
||||
public function getSelectOptions(): array
|
||||
{
|
||||
return Supplier::query()
|
||||
->orderBy('name')
|
||||
->get(['id', 'name'])
|
||||
->map(fn (Supplier $supplier) => [
|
||||
'value' => $supplier->id,
|
||||
'label' => $supplier->name,
|
||||
])
|
||||
->all();
|
||||
}
|
||||
|
||||
private function applySorting(Builder $query, string $sort, string $direction): void
|
||||
{
|
||||
if (in_array($sort, ['name', 'phone_number', 'address'], true)) {
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import { Plus } from '@lucide/vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { createColumns } from './table/columns';
|
||||
import SupplierFormModal from './form/SupplierFormModal.vue';
|
||||
import { DataTable } from '@/components/data-table';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
@ -12,6 +10,8 @@ import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataT
|
||||
import AdminLayout from '@/layouts/AdminLayout.vue';
|
||||
import type { DataTableSort } from '@/types/data-table';
|
||||
import type { SupplierListItem, PaginatedSuppliers } from '@/types/supplier';
|
||||
import SupplierFormModal from './form/SupplierFormModal.vue';
|
||||
import { createColumns } from './table/columns';
|
||||
|
||||
const props = defineProps<{
|
||||
suppliers: PaginatedSuppliers;
|
||||
|
||||
349
tests/Feature/Admin/Master/SupplierTest.php
Normal file
349
tests/Feature/Admin/Master/SupplierTest.php
Normal file
@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\Permission as PermissionEnum;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Database\Seeders\RolePermissionSeeder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->seed(RolePermissionSeeder::class);
|
||||
});
|
||||
|
||||
// ─── Helper ───────────────────────────────────────────────
|
||||
|
||||
function createSupplierUserWithPermission(PermissionEnum ...$permissions): User
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$user->givePermissionTo(
|
||||
array_merge(
|
||||
[PermissionEnum::DASHBOARD_VIEW->value],
|
||||
array_map(fn (PermissionEnum $p) => $p->value, $permissions)
|
||||
)
|
||||
);
|
||||
|
||||
$user->forgetCachedPermissions();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
// ─── Index ────────────────────────────────────────────────
|
||||
|
||||
describe('Supplier Index', function () {
|
||||
test('authenticated user with permission can view supplier index', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
Supplier::factory()->count(3)->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(route('admin.master.suppliers.index'))
|
||||
->assertOk();
|
||||
});
|
||||
|
||||
test('guest is redirected to login', function () {
|
||||
$this->get(route('admin.master.suppliers.index'))
|
||||
->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('user without permission is forbidden', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(route('admin.master.suppliers.index'))
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
test('index returns suppliers with pagination', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
Supplier::factory()->count(15)->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(route('admin.master.suppliers.index'))
|
||||
->assertOk();
|
||||
});
|
||||
|
||||
test('index can search suppliers by name', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
Supplier::factory()->create(['name' => 'PT Maju Jaya']);
|
||||
Supplier::factory()->create(['name' => 'CV Berkah Tekstil']);
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(route('admin.master.suppliers.index', ['search' => 'Maju']))
|
||||
->assertOk();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Store ────────────────────────────────────────────────
|
||||
|
||||
describe('Supplier Store', function () {
|
||||
test('authenticated user with permission can create a supplier', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'phone_number' => '081234567890',
|
||||
'address' => 'Jl. Merdeka No. 1',
|
||||
])
|
||||
->assertRedirect(route('admin.master.suppliers.index'));
|
||||
|
||||
$this->assertDatabaseHas('suppliers', [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'phone_number' => '081234567890',
|
||||
'address' => 'Jl. Merdeka No. 1',
|
||||
]);
|
||||
});
|
||||
|
||||
test('guest cannot create a supplier', function () {
|
||||
$this->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
])->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('user without create permission is forbidden', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
])
|
||||
->assertForbidden();
|
||||
|
||||
$this->assertDatabaseCount('suppliers', 0);
|
||||
});
|
||||
|
||||
test('name is required', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => '',
|
||||
])
|
||||
->assertSessionHasErrors('name');
|
||||
|
||||
$this->assertDatabaseCount('suppliers', 0);
|
||||
});
|
||||
|
||||
test('name must not exceed 200 characters', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => str_repeat('a', 201),
|
||||
])
|
||||
->assertSessionHasErrors('name');
|
||||
|
||||
$this->assertDatabaseCount('suppliers', 0);
|
||||
});
|
||||
|
||||
test('phone number must start with 08', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'phone_number' => '0211234567',
|
||||
])
|
||||
->assertSessionHasErrors('phone_number');
|
||||
|
||||
$this->assertDatabaseCount('suppliers', 0);
|
||||
});
|
||||
|
||||
test('phone number can be null', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'phone_number' => null,
|
||||
])
|
||||
->assertRedirect(route('admin.master.suppliers.index'));
|
||||
|
||||
$this->assertDatabaseHas('suppliers', [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'phone_number' => null,
|
||||
]);
|
||||
});
|
||||
|
||||
test('address can be null', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('admin.master.suppliers.store'), [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'address' => null,
|
||||
])
|
||||
->assertRedirect(route('admin.master.suppliers.index'));
|
||||
|
||||
$this->assertDatabaseHas('suppliers', [
|
||||
'name' => 'PT Supplier Baru',
|
||||
'address' => null,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Update ───────────────────────────────────────────────
|
||||
|
||||
describe('Supplier Update', function () {
|
||||
test('authenticated user with permission can update a supplier', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
|
||||
|
||||
$supplier = Supplier::factory()->create(['name' => 'Nama Lama']);
|
||||
|
||||
$this->actingAs($user)
|
||||
->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => 'Nama Baru',
|
||||
'phone_number' => '089876543210',
|
||||
'address' => 'Jl. Baru No. 2',
|
||||
])
|
||||
->assertRedirect(route('admin.master.suppliers.index'));
|
||||
|
||||
$this->assertDatabaseHas('suppliers', [
|
||||
'id' => $supplier->id,
|
||||
'name' => 'Nama Baru',
|
||||
'phone_number' => '089876543210',
|
||||
'address' => 'Jl. Baru No. 2',
|
||||
]);
|
||||
});
|
||||
|
||||
test('guest cannot update a supplier', function () {
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => 'Nama Baru',
|
||||
])->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('user without update permission is forbidden', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
$supplier = Supplier::factory()->create(['name' => 'Nama Lama']);
|
||||
|
||||
$this->actingAs($user)
|
||||
->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => 'Nama Baru',
|
||||
])
|
||||
->assertForbidden();
|
||||
|
||||
$this->assertDatabaseHas('suppliers', [
|
||||
'id' => $supplier->id,
|
||||
'name' => 'Nama Lama',
|
||||
]);
|
||||
});
|
||||
|
||||
test('name is required on update', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => '',
|
||||
])
|
||||
->assertSessionHasErrors('name');
|
||||
});
|
||||
|
||||
test('name must not exceed 200 characters on update', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => str_repeat('a', 201),
|
||||
])
|
||||
->assertSessionHasErrors('name');
|
||||
});
|
||||
|
||||
test('phone number validation on update', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->put(route('admin.master.suppliers.update', $supplier), [
|
||||
'name' => 'Nama Valid',
|
||||
'phone_number' => '123invalid',
|
||||
])
|
||||
->assertSessionHasErrors('phone_number');
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Destroy ──────────────────────────────────────────────
|
||||
|
||||
describe('Supplier Destroy', function () {
|
||||
test('authenticated user with permission can delete a supplier', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_DELETE);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->delete(route('admin.master.suppliers.destroy', $supplier))
|
||||
->assertRedirect(route('admin.master.suppliers.index'));
|
||||
|
||||
$this->assertSoftDeleted('suppliers', [
|
||||
'id' => $supplier->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('guest cannot delete a supplier', function () {
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->delete(route('admin.master.suppliers.destroy', $supplier))
|
||||
->assertRedirect(route('login'));
|
||||
|
||||
$this->assertNotSoftDeleted('suppliers', [
|
||||
'id' => $supplier->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('user without delete permission is forbidden', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->delete(route('admin.master.suppliers.destroy', $supplier))
|
||||
->assertForbidden();
|
||||
|
||||
$this->assertNotSoftDeleted('suppliers', [
|
||||
'id' => $supplier->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('deleted supplier is soft deleted', function () {
|
||||
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_DELETE);
|
||||
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$this->actingAs($user)
|
||||
->delete(route('admin.master.suppliers.destroy', $supplier));
|
||||
|
||||
$this->assertSoftDeleted('suppliers', ['id' => $supplier->id]);
|
||||
$this->assertDatabaseHas('suppliers', ['id' => $supplier->id]);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Supplier Model ───────────────────────────────────────
|
||||
|
||||
describe('Supplier Model', function () {
|
||||
test('supplier uses soft deletes', function () {
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
$supplier->delete();
|
||||
|
||||
expect($supplier->trashed())->toBeTrue();
|
||||
});
|
||||
|
||||
test('supplier can have purchases', function () {
|
||||
$supplier = Supplier::factory()->create();
|
||||
|
||||
expect($supplier->purchases)->toBeInstanceOf(Collection::class);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user