seedRolesAndPermissions(); } /** * Test can view cashier ledger */ public function test_can_view_cashier_ledger(): void { $cashier = $this->createCashier(); $response = $this->actingAs($cashier)->get( route('admin.cashier-ledger.index') ); $response->assertStatus(200); } /** * Test ledger entry created from payment order */ public function test_ledger_entry_created_from_payment_order(): void { $cashier = $this->createCashier(); $order = $this->createPaymentOrder([ 'status' => PaymentOrder::STATUS_COMPLETED, ]); $response = $this->actingAs($cashier)->post( route('admin.cashier-ledger.store'), [ 'payment_order_id' => $order->id, 'entry_type' => 'expense', 'entry_date' => now()->toDateString(), ] ); $response->assertRedirect(); $this->assertDatabaseHas('cashier_ledgers', [ 'payment_order_id' => $order->id, ]); } /** * Test ledger tracks income entries */ public function test_ledger_tracks_income_entries(): void { $cashier = $this->createCashier(); $response = $this->actingAs($cashier)->post( route('admin.cashier-ledger.store'), [ 'entry_type' => 'income', 'amount' => 50000, 'description' => '會員繳費收入', 'entry_date' => now()->toDateString(), ] ); $this->assertDatabaseHas('cashier_ledgers', [ 'entry_type' => 'income', 'amount' => 50000, ]); } /** * Test ledger tracks expense entries */ public function test_ledger_tracks_expense_entries(): void { $cashier = $this->createCashier(); $order = $this->createPaymentOrder([ 'status' => PaymentOrder::STATUS_COMPLETED, ]); $entry = $this->createCashierLedgerEntry([ 'payment_order_id' => $order->id, 'entry_type' => 'expense', ]); $this->assertEquals('expense', $entry->entry_type); } /** * Test ledger balance calculation */ public function test_ledger_balance_calculation(): void { $cashier = $this->createCashier(); // Create income $this->createCashierLedgerEntry([ 'entry_type' => 'income', 'amount' => 100000, ]); // Create expense $this->createCashierLedgerEntry([ 'entry_type' => 'expense', 'amount' => 30000, ]); $balance = CashierLedger::calculateBalance(); $this->assertEquals(70000, $balance); } /** * Test ledger date range filter */ public function test_ledger_date_range_filter(): void { $cashier = $this->createCashier(); $this->createCashierLedgerEntry([ 'entry_date' => now()->subMonth(), ]); $this->createCashierLedgerEntry([ 'entry_date' => now(), ]); $response = $this->actingAs($cashier)->get( route('admin.cashier-ledger.index', [ 'start_date' => now()->startOfMonth()->toDateString(), 'end_date' => now()->endOfMonth()->toDateString(), ]) ); $response->assertStatus(200); } /** * Test ledger entry validation */ public function test_ledger_entry_validation(): void { $cashier = $this->createCashier(); $response = $this->actingAs($cashier)->post( route('admin.cashier-ledger.store'), [ 'entry_type' => 'income', 'amount' => -1000, // Invalid negative amount 'entry_date' => now()->toDateString(), ] ); $response->assertSessionHasErrors('amount'); } /** * Test ledger entry requires date */ public function test_ledger_entry_requires_date(): void { $cashier = $this->createCashier(); $response = $this->actingAs($cashier)->post( route('admin.cashier-ledger.store'), [ 'entry_type' => 'income', 'amount' => 5000, // Missing entry_date ] ); $response->assertSessionHasErrors('entry_date'); } /** * Test ledger monthly summary */ public function test_ledger_monthly_summary(): void { $cashier = $this->createCashier(); $this->createCashierLedgerEntry([ 'entry_type' => 'income', 'amount' => 100000, 'entry_date' => now(), ]); $this->createCashierLedgerEntry([ 'entry_type' => 'expense', 'amount' => 50000, 'entry_date' => now(), ]); $response = $this->actingAs($cashier)->get( route('admin.cashier-ledger.summary', [ 'year' => now()->year, 'month' => now()->month, ]) ); $response->assertStatus(200); } /** * Test ledger export */ public function test_ledger_export(): void { $cashier = $this->createCashier(); $this->createCashierLedgerEntry(); $this->createCashierLedgerEntry(); $response = $this->actingAs($cashier)->get( route('admin.cashier-ledger.export', ['format' => 'csv']) ); $response->assertStatus(200); } /** * Test ledger entry cannot be edited after reconciliation */ public function test_ledger_entry_cannot_be_edited_after_reconciliation(): void { $cashier = $this->createCashier(); $entry = $this->createCashierLedgerEntry([ 'is_reconciled' => true, ]); $response = $this->actingAs($cashier)->patch( route('admin.cashier-ledger.update', $entry), ['amount' => 99999] ); $response->assertSessionHasErrors(); } }