Initial commit
This commit is contained in:
308
tests/Feature/CashierLedgerWorkflowTest.php
Normal file
308
tests/Feature/CashierLedgerWorkflowTest.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\CashierLedgerEntry;
|
||||
use App\Models\FinanceDocument;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Cashier Ledger Workflow Feature Tests
|
||||
*
|
||||
* Tests cashier ledger entry creation and balance tracking
|
||||
*/
|
||||
class CashierLedgerWorkflowTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, WithFaker;
|
||||
|
||||
protected User $cashier;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Role::create(['name' => 'finance_cashier']);
|
||||
|
||||
$this->cashier = User::factory()->create(['email' => 'cashier@test.com']);
|
||||
$this->cashier->assignRole('finance_cashier');
|
||||
$this->cashier->givePermissionTo(['record_cashier_entry', 'view_cashier_ledger']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cashier_can_create_receipt_entry()
|
||||
{
|
||||
$this->actingAs($this->cashier);
|
||||
|
||||
$response = $this->post(route('admin.cashier-ledger.store'), [
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now()->format('Y-m-d'),
|
||||
'amount' => 5000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Test Bank 1234567890',
|
||||
'receipt_number' => 'RCP001',
|
||||
'notes' => 'Test receipt entry',
|
||||
]);
|
||||
|
||||
$response->assertRedirect();
|
||||
|
||||
$this->assertDatabaseHas('cashier_ledger_entries', [
|
||||
'entry_type' => 'receipt',
|
||||
'amount' => 5000,
|
||||
'bank_account' => 'Test Bank 1234567890',
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function receipt_entry_increases_balance()
|
||||
{
|
||||
// Create initial entry
|
||||
$entry1 = CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 10000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test Account',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 10000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertEquals(10000, $entry1->balance_after);
|
||||
|
||||
// Create second receipt entry
|
||||
$entry2 = CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 5000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test Account',
|
||||
'balance_before' => 10000,
|
||||
'balance_after' => 15000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertEquals(15000, $entry2->balance_after);
|
||||
$this->assertEquals(15000, CashierLedgerEntry::getLatestBalance('Test Account'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function payment_entry_decreases_balance()
|
||||
{
|
||||
// Create initial balance
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 20000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test Account',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 20000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
// Create payment entry
|
||||
$paymentEntry = CashierLedgerEntry::create([
|
||||
'entry_type' => 'payment',
|
||||
'entry_date' => now(),
|
||||
'amount' => 8000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test Account',
|
||||
'balance_before' => 20000,
|
||||
'balance_after' => 12000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertEquals(12000, $paymentEntry->balance_after);
|
||||
$this->assertEquals(12000, CashierLedgerEntry::getLatestBalance('Test Account'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function balance_calculation_is_correct()
|
||||
{
|
||||
$entry = new CashierLedgerEntry([
|
||||
'entry_type' => 'receipt',
|
||||
'amount' => 5000,
|
||||
]);
|
||||
|
||||
$newBalance = $entry->calculateBalanceAfter(10000);
|
||||
$this->assertEquals(15000, $newBalance);
|
||||
|
||||
$entry->entry_type = 'payment';
|
||||
$newBalance = $entry->calculateBalanceAfter(10000);
|
||||
$this->assertEquals(5000, $newBalance);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function separate_balances_are_maintained_for_different_accounts()
|
||||
{
|
||||
// Account 1
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 10000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Bank A - 1111',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 10000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
// Account 2
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 5000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Bank B - 2222',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 5000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertEquals(10000, CashierLedgerEntry::getLatestBalance('Bank A - 1111'));
|
||||
$this->assertEquals(5000, CashierLedgerEntry::getLatestBalance('Bank B - 2222'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function ledger_entry_can_be_linked_to_finance_document()
|
||||
{
|
||||
$financeDoc = FinanceDocument::factory()->create([
|
||||
'amount' => 3000,
|
||||
'status' => 'approved_accountant',
|
||||
]);
|
||||
|
||||
$entry = CashierLedgerEntry::create([
|
||||
'finance_document_id' => $financeDoc->id,
|
||||
'entry_type' => 'payment',
|
||||
'entry_date' => now(),
|
||||
'amount' => 3000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test Account',
|
||||
'balance_before' => 10000,
|
||||
'balance_after' => 7000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertEquals($financeDoc->id, $entry->finance_document_id);
|
||||
$this->assertInstanceOf(FinanceDocument::class, $entry->financeDocument);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function entry_type_helper_methods_work_correctly()
|
||||
{
|
||||
$receiptEntry = new CashierLedgerEntry(['entry_type' => 'receipt']);
|
||||
$this->assertTrue($receiptEntry->isReceipt());
|
||||
$this->assertFalse($receiptEntry->isPayment());
|
||||
|
||||
$paymentEntry = new CashierLedgerEntry(['entry_type' => 'payment']);
|
||||
$this->assertTrue($paymentEntry->isPayment());
|
||||
$this->assertFalse($paymentEntry->isReceipt());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function payment_method_text_is_correctly_displayed()
|
||||
{
|
||||
$entry1 = new CashierLedgerEntry(['payment_method' => 'cash']);
|
||||
$this->assertEquals('現金', $entry1->getPaymentMethodText());
|
||||
|
||||
$entry2 = new CashierLedgerEntry(['payment_method' => 'bank_transfer']);
|
||||
$this->assertEquals('銀行轉帳', $entry2->getPaymentMethodText());
|
||||
|
||||
$entry3 = new CashierLedgerEntry(['payment_method' => 'check']);
|
||||
$this->assertEquals('支票', $entry3->getPaymentMethodText());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cashier_can_view_balance_report()
|
||||
{
|
||||
// Create multiple entries
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 100000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Main Account',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 100000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'payment',
|
||||
'entry_date' => now(),
|
||||
'amount' => 30000,
|
||||
'payment_method' => 'bank_transfer',
|
||||
'bank_account' => 'Main Account',
|
||||
'balance_before' => 100000,
|
||||
'balance_after' => 70000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$this->actingAs($this->cashier);
|
||||
|
||||
$response = $this->get(route('admin.cashier-ledger.balance-report'));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertViewHas('accounts');
|
||||
$response->assertViewHas('monthlySummary');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function zero_balance_is_returned_for_new_account()
|
||||
{
|
||||
$balance = CashierLedgerEntry::getLatestBalance('New Account');
|
||||
$this->assertEquals(0, $balance);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function ledger_entries_can_be_filtered_by_date_range()
|
||||
{
|
||||
$this->actingAs($this->cashier);
|
||||
|
||||
// Create entries with different dates
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now()->subDays(10),
|
||||
'amount' => 1000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test',
|
||||
'balance_before' => 0,
|
||||
'balance_after' => 1000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now()->subDays(10),
|
||||
]);
|
||||
|
||||
CashierLedgerEntry::create([
|
||||
'entry_type' => 'receipt',
|
||||
'entry_date' => now(),
|
||||
'amount' => 2000,
|
||||
'payment_method' => 'cash',
|
||||
'bank_account' => 'Test',
|
||||
'balance_before' => 1000,
|
||||
'balance_after' => 3000,
|
||||
'recorded_by_cashier_id' => $this->cashier->id,
|
||||
'recorded_at' => now(),
|
||||
]);
|
||||
|
||||
$response = $this->get(route('admin.cashier-ledger.index', [
|
||||
'date_from' => now()->subDays(5)->format('Y-m-d'),
|
||||
'date_to' => now()->format('Y-m-d'),
|
||||
]));
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user