- Updated ProductIndex component to improve category and product filtering with memoization. - Refactored Combobox components for better performance and usability. - Added PurchaseController routes for managing purchases with appropriate permissions. - Created comprehensive tests for purchase management, covering creation, updating, and deletion scenarios. - Ensured proper handling of raw materials and their variants during purchase operations. - Implemented validation for required fields in purchase creation and updates.
263 lines
7.8 KiB
PHP
263 lines
7.8 KiB
PHP
<?php
|
|
|
|
use App\Models\CashAccount;
|
|
use App\Models\CashTransaction;
|
|
use App\Models\Expense;
|
|
use App\Models\User;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
|
|
test('guests are redirected to the login page', function () {
|
|
$response = $this->get(route('admin.finance.expenses.index'));
|
|
$response->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('authenticated users can visit the expense index page', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->get(route('admin.finance.expenses.index'));
|
|
$response->assertOk();
|
|
});
|
|
|
|
test('expense index page displays expenses', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
|
|
$cashTransaction = CashTransaction::factory()->create([
|
|
'cash_account_id' => $cashAccount->id,
|
|
'created_by_id' => $user->id,
|
|
'type' => 'expense',
|
|
'amount' => 50000,
|
|
]);
|
|
$expense = Expense::factory()->create([
|
|
'cash_transaction_id' => $cashTransaction->id,
|
|
'created_by_id' => $user->id,
|
|
]);
|
|
|
|
$response = $this->get(route('admin.finance.expenses.index'));
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (Assert $page) => $page
|
|
->component('admin/finance/expense/index')
|
|
->has('expenses.data')
|
|
->where('expenses.current_page', 1)
|
|
->where('expenses.per_page', 25)
|
|
);
|
|
});
|
|
|
|
test('expense can be created', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 50000,
|
|
'description' => 'Belanja ATK',
|
|
'receipt_key' => 'expense/receipt-001.jpg',
|
|
]);
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect(route('admin.finance.expenses.index'));
|
|
|
|
$this->assertDatabaseHas('expenses', [
|
|
'amount' => 50000,
|
|
'description' => 'Belanja ATK',
|
|
]);
|
|
|
|
expect(CashAccount::first()->balance)->toBe(50000);
|
|
});
|
|
|
|
test('expense amount is required', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => '',
|
|
'description' => 'Test',
|
|
'receipt_key' => 'expense/receipt.jpg',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('amount');
|
|
});
|
|
|
|
test('expense amount must be at least 1', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 0,
|
|
'description' => 'Test',
|
|
'receipt_key' => 'expense/receipt.jpg',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('amount');
|
|
});
|
|
|
|
test('expense description is required', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 50000,
|
|
'description' => '',
|
|
'receipt_key' => 'expense/receipt.jpg',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('description');
|
|
});
|
|
|
|
test('expense receipt_key is required', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 50000,
|
|
'description' => 'Test',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('receipt_key');
|
|
});
|
|
|
|
test('expense fails when balance is insufficient', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 50000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 100000,
|
|
'description' => 'Test',
|
|
'receipt_key' => 'expense/receipt.jpg',
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
expect(CashAccount::first()->balance)->toBe(50000);
|
|
});
|
|
|
|
test('expense can be updated', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 100000]);
|
|
$cashTransaction = CashTransaction::factory()->create([
|
|
'cash_account_id' => $cashAccount->id,
|
|
'created_by_id' => $user->id,
|
|
'type' => 'expense',
|
|
'amount' => 30000,
|
|
'balance_after' => 70000,
|
|
]);
|
|
$expense = Expense::factory()->create([
|
|
'cash_transaction_id' => $cashTransaction->id,
|
|
'created_by_id' => $user->id,
|
|
'amount' => 30000,
|
|
]);
|
|
|
|
$response = $this->put(route('admin.finance.expenses.update', $expense), [
|
|
'amount' => 40000,
|
|
'description' => 'Belanja ATK Updated',
|
|
'receipt_key' => 'expense/receipt-updated.jpg',
|
|
]);
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect(route('admin.finance.expenses.index'));
|
|
|
|
$expense->refresh();
|
|
expect($expense->amount)->toBe(40000);
|
|
expect($expense->description)->toBe('Belanja ATK Updated');
|
|
});
|
|
|
|
test('expense update requires receipt_key', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 100000]);
|
|
$cashTransaction = CashTransaction::factory()->create([
|
|
'cash_account_id' => $cashAccount->id,
|
|
'created_by_id' => $user->id,
|
|
'type' => 'expense',
|
|
'amount' => 30000,
|
|
'balance_after' => 70000,
|
|
]);
|
|
$expense = Expense::factory()->create([
|
|
'cash_transaction_id' => $cashTransaction->id,
|
|
'created_by_id' => $user->id,
|
|
'amount' => 30000,
|
|
]);
|
|
|
|
$response = $this->put(route('admin.finance.expenses.update', $expense), [
|
|
'amount' => 40000,
|
|
'description' => 'Updated',
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('receipt_key');
|
|
});
|
|
|
|
test('expense can be deleted', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
$cashAccount = CashAccount::factory()->create(['balance' => 100000]);
|
|
$cashTransaction = CashTransaction::factory()->create([
|
|
'cash_account_id' => $cashAccount->id,
|
|
'created_by_id' => $user->id,
|
|
'type' => 'expense',
|
|
'amount' => 30000,
|
|
'balance_after' => 70000,
|
|
]);
|
|
$expense = Expense::factory()->create([
|
|
'cash_transaction_id' => $cashTransaction->id,
|
|
'created_by_id' => $user->id,
|
|
'amount' => 30000,
|
|
]);
|
|
|
|
$response = $this->delete(route('admin.finance.expenses.destroy', $expense));
|
|
|
|
$response
|
|
->assertSessionHasNoErrors()
|
|
->assertRedirect(route('admin.finance.expenses.index'));
|
|
|
|
$this->assertSoftDeleted('expenses', ['id' => $expense->id]);
|
|
expect(CashAccount::first()->balance)->toBe(130000);
|
|
});
|
|
|
|
test('expense receipt_key max length is 500', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 50000,
|
|
'description' => 'Test',
|
|
'receipt_key' => str_repeat('a', 501),
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('receipt_key');
|
|
});
|
|
|
|
test('expense receipt_key exactly 500 characters is accepted', function () {
|
|
$user = User::factory()->create();
|
|
$this->actingAs($user);
|
|
|
|
CashAccount::factory()->create(['balance' => 100000]);
|
|
|
|
$response = $this->post(route('admin.finance.expenses.store'), [
|
|
'amount' => 50000,
|
|
'description' => 'Test',
|
|
'receipt_key' => str_repeat('a', 500),
|
|
]);
|
|
|
|
$response->assertSessionHasNoErrors();
|
|
});
|