adminService = $this->app->make(AdminServiceInterface::class); } public function test_user_list_stats_displays_correct_sent_and_received_cards(): void { // 1. Create mock users $userA = User::create([ 'msnv' => 1001, 'name' => 'User A', 'mail' => 'usera@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $userB = User::create([ 'msnv' => 1002, 'name' => 'User B', 'mail' => 'userb@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $selectedMonth = '2026-07'; $testDate = '2026-07-15'; // 2. Create mock transaction logs in administration table // A sends 3 cards to B Administration::create([ 'msnv' => 1001, 'received' => 0, 'sender' => null, 'sent' => 3, 'receiver' => 1002, 'date' => $testDate, ]); Administration::create([ 'msnv' => 1002, 'received' => 3, 'sender' => 1001, 'sent' => 0, 'receiver' => null, 'date' => $testDate, ]); // 3. Fetch statistics via AdminService $stats = $this->adminService->getUserListWithStats($selectedMonth); $users = $stats['users']; $topReceived = $stats['topReceivedUser']; $topSent = $stats['topSentUser']; // Find users in the paginated collection $userAResult = collect($users->items())->firstWhere('msnv', 1001); $userBResult = collect($users->items())->firstWhere('msnv', 1002); $this->assertNotNull($userAResult); $this->assertNotNull($userBResult); // Assert card counts $this->assertEquals(3, $userAResult->total_sent); $this->assertEquals(0, $userAResult->total_received); $this->assertEquals(0, $userBResult->total_sent); $this->assertEquals(3, $userBResult->total_received); // Assert top users $this->assertEquals(1002, $topReceived->msnv); $this->assertEquals(3, $topReceived->total_received); $this->assertEquals(1001, $topSent->msnv); $this->assertEquals(3, $topSent->total_sent); } public function test_user_transactions_history_displays_correct_records(): void { $userA = User::create([ 'msnv' => 1001, 'name' => 'User A', 'mail' => 'usera@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $selectedMonth = '2026-07'; $testDate = '2026-07-15'; // 1. Create a send record Administration::create([ 'msnv' => 1001, 'received' => 0, 'sender' => null, 'sent' => 3, 'receiver' => 1002, 'date' => $testDate, ]); // 2. Create a receive record Administration::create([ 'msnv' => 1001, 'received' => 5, 'sender' => 1003, 'sent' => 0, 'receiver' => null, 'date' => $testDate, ]); $transactions = $this->adminService->getUserTransactions(1001, $selectedMonth); $this->assertCount(2, $transactions->items()); // Assert specific transaction fields $sendTx = collect($transactions->items())->firstWhere('sent', 3); $receiveTx = collect($transactions->items())->firstWhere('received', 5); $this->assertNotNull($sendTx); $this->assertNotNull($receiveTx); $this->assertEquals(1002, $sendTx->receiver); $this->assertNull($sendTx->sender); $this->assertEquals(1003, $receiveTx->sender); $this->assertNull($receiveTx->receiver); } public function test_user_list_stats_filters_by_search_query(): void { // 1. Create mock users User::create([ 'msnv' => 2001, 'name' => 'DEV ALPHA', 'mail' => 'alpha@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); User::create([ 'msnv' => 2002, 'name' => 'DEV BETA', 'mail' => 'beta@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // 2. Fetch statistics via AdminService with search for '2001' (msnv) $stats = $this->adminService->getUserListWithStats('2026-07', '2001'); $users = $stats['users']; $this->assertCount(1, $users->items()); $this->assertEquals(2001, $users->items()[0]->msnv); // 3. Fetch statistics via AdminService with search for 'beta@example.com' (mail) $stats2 = $this->adminService->getUserListWithStats('2026-07', 'beta@example.com'); $users2 = $stats2['users']; $this->assertCount(1, $users2->items()); $this->assertEquals(2002, $users2->items()[0]->msnv); } public function test_user_list_stats_filters_by_status(): void { // 1. Create mock users User::create([ 'msnv' => 3001, 'name' => 'DEV ACTIVE', 'mail' => 'active@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); User::create([ 'msnv' => 3002, 'name' => 'DEV INACTIVE', 'mail' => 'inactive@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_INACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_DISABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // 2. Fetch statistics via AdminService with status = '1' $stats = $this->adminService->getUserListWithStats('2026-07', null, '1'); $users = collect($stats['users']->items()); $this->assertTrue($users->contains('msnv', 3001)); $this->assertFalse($users->contains('msnv', 3002)); // 3. Fetch statistics via AdminService with status = '0' $stats2 = $this->adminService->getUserListWithStats('2026-07', null, '0'); $users2 = collect($stats2['users']->items()); $this->assertTrue($users2->contains('msnv', 3002)); $this->assertFalse($users2->contains('msnv', 3001)); } public function test_user_list_stats_filters_by_role_department_and_flag_send(): void { // 1. Create mock users User::create([ 'msnv' => 4001, 'name' => 'ADMIN DEV ENABLED', 'mail' => 'admin_dev@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); User::create([ 'msnv' => 4002, 'name' => 'MEMBER HR DISABLED', 'mail' => 'member_hr@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[13], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_DISABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Filter by role = Admin ('1') $stats = $this->adminService->getUserListWithStats('2026-07', null, '1', '1'); $users = collect($stats['users']->items()); $this->assertTrue($users->contains('msnv', 4001)); $this->assertFalse($users->contains('msnv', 4002)); // Filter by department = HR (config('constants.DEPARTMENTS')[13]) $stats2 = $this->adminService->getUserListWithStats('2026-07', null, '1', null, config('constants.DEPARTMENTS')[13]); $users2 = collect($stats2['users']->items()); $this->assertTrue($users2->contains('msnv', 4002)); $this->assertFalse($users2->contains('msnv', 4001)); // Filter by flag_send = Enabled ('1') $stats3 = $this->adminService->getUserListWithStats('2026-07', null, '1', null, null, '1'); $users3 = collect($stats3['users']->items()); $this->assertTrue($users3->contains('msnv', 4001)); $this->assertFalse($users3->contains('msnv', 4002)); } public function test_admin_can_update_user_fields_including_card_role_status_flag_send_first_login(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 5, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $response = $this->actingAs($admin)->put(route('admin.users.update', 9002), [ 'card' => 20, // increased by 15 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_INACTIVE'), 'flag_send' => config('constants.FLAG_SEND_DISABLED'), 'first_login' => config('constants.FIRST_LOGIN_TRUE'), ]); $response->assertRedirect(); $member->refresh(); $this->assertEquals(20, $member->card); $this->assertEquals(config('constants.ROLE_ADMIN'), $member->role); $this->assertEquals(config('constants.STATUS_INACTIVE'), $member->status); $this->assertEquals(config('constants.FLAG_SEND_DISABLED'), $member->flag_send); $this->assertEquals(config('constants.FIRST_LOGIN_TRUE'), $member->first_login); // Assert AddCard record was created with diff (15) $this->assertDatabaseHas('add_card', [ 'buyer' => 9002, 'num_card' => 15, 'seller' => 9001, ]); } public function test_user_list_stats_handles_ties_for_top_sender_receiver(): void { // Clear existing mock data first to have a clean slate for ties User::truncate(); Administration::truncate(); // 1. Create three users $user1 = User::create([ 'msnv' => 3001, 'name' => 'User One', 'mail' => 'user1@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $user2 = User::create([ 'msnv' => 3002, 'name' => 'User Two', 'mail' => 'user2@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $user3 = User::create([ 'msnv' => 3003, 'name' => 'User Three', 'mail' => 'user3@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $selectedMonth = '2026-07'; $testDate = '2026-07-15'; // User 1 sends 5 cards to User 2 Administration::create([ 'msnv' => 3001, 'received' => 0, 'sender' => null, 'sent' => 5, 'receiver' => 3002, 'date' => $testDate, ]); Administration::create([ 'msnv' => 3002, 'received' => 5, 'sender' => 3001, 'sent' => 0, 'receiver' => null, 'date' => $testDate, ]); // User 3 sends 5 cards to User 1 Administration::create([ 'msnv' => 3003, 'received' => 0, 'sender' => null, 'sent' => 5, 'receiver' => 3001, 'date' => $testDate, ]); Administration::create([ 'msnv' => 3001, 'received' => 5, 'sender' => 3003, 'sent' => 0, 'receiver' => null, 'date' => $testDate, ]); // Now: // User 1 has sent = 5, received = 5 // User 2 has sent = 0, received = 5 // User 3 has sent = 5, received = 0 // Top senders should be: User 1 and User 3 (both sent 5) // Top receivers should be: User 1 and User 2 (both received 5) $stats = $this->adminService->getUserListWithStats($selectedMonth); $this->assertCount(2, $stats['topReceivedUsers']); $this->assertCount(2, $stats['topSentUsers']); $topReceivedMsnvs = $stats['topReceivedUsers']->pluck('msnv')->toArray(); $this->assertContains(3001, $topReceivedMsnvs); $this->assertContains(3002, $topReceivedMsnvs); $topSentMsnvs = $stats['topSentUsers']->pluck('msnv')->toArray(); $this->assertContains(3001, $topSentMsnvs); $this->assertContains(3003, $topSentMsnvs); } public function test_user_list_stats_handles_10_way_tie_for_top_sender_receiver(): void { $users = []; $selectedMonth = '2026-07'; $testDate = '2026-07-15'; // Create 10 users for ($i = 1; $i <= 10; $i++) { $users[$i] = User::create([ 'msnv' => 5000 + $i, 'name' => "User Tenfold {$i}", 'mail' => "user_tenfold_{$i}@example.com", 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); } // Each user sends 1 card to the next user, and user 10 sends to user 1 for ($i = 1; $i <= 10; $i++) { $senderMsnv = 5000 + $i; $receiverMsnv = 5000 + ($i % 10 + 1); // Sender record Administration::create([ 'msnv' => $senderMsnv, 'received' => 0, 'sender' => null, 'sent' => 1, 'receiver' => $receiverMsnv, 'date' => $testDate, ]); // Receiver record Administration::create([ 'msnv' => $receiverMsnv, 'received' => 1, 'sender' => $senderMsnv, 'sent' => 0, 'receiver' => null, 'date' => $testDate, ]); } // Run the service call $stats = $this->adminService->getUserListWithStats($selectedMonth); // Assert all 10 users are returned in topReceivedUsers and topSentUsers $this->assertCount(10, $stats['topReceivedUsers']); $this->assertCount(10, $stats['topSentUsers']); // Verify all their MSNVs are present for ($i = 1; $i <= 10; $i++) { $msnv = 5000 + $i; $this->assertContains($msnv, $stats['topReceivedUsers']->pluck('msnv')->toArray()); $this->assertContains($msnv, $stats['topSentUsers']->pluck('msnv')->toArray()); } } public function test_update_add_card_successfully_updates_balance(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, // currently has 10 cards 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Created in the current month $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Action: Update it from 5 to 3 (decrease of 2, new user balance should be 10 - 2 = 8) $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $addCard->id), [ 'num_card' => 3, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); $response->assertRedirect(); $addCard->refresh(); $this->assertEquals(3, $addCard->num_card); $member->refresh(); $this->assertEquals(8, $member->card); } public function test_update_add_card_fails_if_past_month(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Created in a past month $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->subMonth()->format('Y-m-d'), ]); $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $addCard->id), [ 'num_card' => 3, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); $response->assertRedirect(); $response->assertSessionHasErrors('error'); $this->assertTrue(session('errors')->has('error')); $this->assertEquals('Không cho phép chỉnh sửa dữ liệu card của các tháng trước.', session('errors')->first('error')); } public function test_update_add_card_fails_if_new_date_not_current_month(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Created in current month $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Update with date in a past month $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $addCard->id), [ 'num_card' => 3, 'seller' => 9001, 'date' => Carbon::now()->subMonth()->format('Y-m-d'), ]); $response->assertRedirect(); $response->assertSessionHasErrors('error'); $this->assertEquals('Chỉ được phép chỉnh sửa dữ liệu của tháng hiện tại.', session('errors')->first('error')); } public function test_update_add_card_fails_if_new_balance_negative(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 2, // has 2 cards left 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Created in current month $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Decrease it from 5 to 1 (decrease of 4). Since member only has 2 cards, this would make balance -2 (2 - 4 = -2), which is illegal $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $addCard->id), [ 'num_card' => 1, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); $response->assertRedirect(); $response->assertSessionHasErrors('error'); $this->assertEquals('Số lượng card cập nhật không hợp lệ vì tổng số card của user không được nhỏ hơn 0.', session('errors')->first('error')); } public function test_update_add_card_succeeds_for_older_transaction_in_current_month(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 15, // has 15 cards 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Transaction 1 (older) $oldAddCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->toDateString(), ]); // Transaction 2 (newest) $newAddCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 10, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->addDay()->toDateString(), ]); // Try to update older Transaction 1: change num_card from 5 to 6 (increase of 1) $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $oldAddCard->id), [ 'num_card' => 6, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->toDateString(), ]); $response->assertRedirect(); $response->assertSessionHasNoErrors(); $oldAddCard->refresh(); $this->assertEquals(6, $oldAddCard->num_card); $member->refresh(); $this->assertEquals(16, $member->card); } public function test_update_add_card_merges_records_on_same_date(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 0, 'flag_send' => config('constants.FLAG_SEND_DISABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 15, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // Record A on day 1 $recordA = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->toDateString(), ]); // Record B on day 10 $recordB = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 10, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->addDays(9)->toDateString(), ]); // Update Record B: set date to day 1, and set num_card to 10 $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $recordB->id), [ 'num_card' => 10, 'seller' => 9001, 'date' => Carbon::now()->startOfMonth()->toDateString(), ]); $response->assertRedirect(); $response->assertSessionHasNoErrors(); // Record B should be deleted (merged) $this->assertNull(\App\Models\AddCard::find($recordB->id)); // Record A should have 15 cards (5 + 10) $recordA->refresh(); $this->assertEquals(15, $recordA->num_card); // Member's card balance remains 15 $member->refresh(); $this->assertEquals(15, $member->card); } public function test_delete_add_card_successfully_updates_balance(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 15, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 5, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Action: delete the allocation $response = $this->actingAs($admin)->delete(route('admin.add_cards.destroy', $addCard->id)); $response->assertRedirect(); $this->assertDatabaseMissing('add_card', ['id' => $addCard->id]); $member->refresh(); $this->assertEquals(10, $member->card); } public function test_update_add_card_fails_if_balance_drops_below_sent_cards(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 10, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Member sent 6 cards this month Administration::create([ 'msnv' => 9002, 'received' => 0, 'sent' => 6, 'date' => Carbon::now()->format('Y-m-d'), ]); // Try to update num_card from 10 to 4 (decrease of 6, new user balance would be 10 - 6 = 4). // Since member sent 6 cards, 4 is less than 6, so this should fail! $response = $this->actingAs($admin)->put(route('admin.add_cards.update', $addCard->id), [ 'num_card' => 4, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); $response->assertRedirect(); $response->assertSessionHasErrors('error'); $this->assertStringContainsString('Số lượng card cập nhật không hợp lệ vì tổng số card của user không được nhỏ hơn số card đã gửi trong tháng', session('errors')->first('error')); } public function test_delete_add_card_fails_if_balance_drops_below_sent_cards(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $addCard = \App\Models\AddCard::create([ 'buyer' => 9002, 'num_card' => 10, 'seller' => 9001, 'date' => Carbon::now()->format('Y-m-d'), ]); // Member sent 6 cards this month Administration::create([ 'msnv' => 9002, 'received' => 0, 'sent' => 6, 'date' => Carbon::now()->format('Y-m-d'), ]); // Try to delete the 10 cards allocation (user balance would be 10 - 10 = 0). // Since member sent 6 cards, 0 is less than 6, so this should fail! $response = $this->actingAs($admin)->delete(route('admin.add_cards.destroy', $addCard->id)); $response->assertRedirect(); $response->assertSessionHasErrors('error'); $this->assertStringContainsString('Không thể xóa lịch sử cấp phát thẻ này vì tổng số card của user không được nhỏ hơn số card đã gửi trong tháng', session('errors')->first('error')); } public function test_card_additions_on_same_day_are_accumulated(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 0, 'flag_send' => config('constants.FLAG_SEND_DISABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $member = User::create([ 'msnv' => 9002, 'name' => 'Member User', 'mail' => 'member@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_MEMBER'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 5, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); // First allocation: add 10 cards $this->actingAs($admin)->put(route('admin.users.update', 9002), [ 'card' => 15, ]); // Second allocation: add 5 cards $this->actingAs($admin)->put(route('admin.users.update', 9002), [ 'card' => 20, ]); $member->refresh(); $this->assertEquals(20, $member->card); // There should be only 1 AddCard record with 15 cards (10 + 5) $addCards = \App\Models\AddCard::where('buyer', 9002)->where('seller', 9001)->get(); $this->assertCount(1, $addCards); $this->assertEquals(15, $addCards->first()->num_card); } public function test_admin_updating_self_status_to_inactive_logs_out(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $response = $this->actingAs($admin)->put(route('admin.users.update', 9001), [ 'status' => config('constants.STATUS_INACTIVE'), ]); $response->assertRedirect(route('login')); $this->assertFalse(\Illuminate\Support\Facades\Auth::check()); } public function test_admin_deactivating_self_via_destroy_logs_out(): void { $admin = User::create([ 'msnv' => 9001, 'name' => 'Admin User', 'mail' => 'admin@example.com', 'pass' => md5('password'), 'departments' => config('constants.DEPARTMENTS')[0], 'role' => config('constants.ROLE_ADMIN'), 'status' => config('constants.STATUS_ACTIVE'), 'card' => 10, 'flag_send' => config('constants.FLAG_SEND_ENABLED'), 'first_login' => config('constants.FIRST_LOGIN_FALSE'), ]); $response = $this->actingAs($admin)->delete(route('admin.users.destroy', 9001)); $response->assertRedirect(route('login')); $this->assertFalse(\Illuminate\Support\Facades\Auth::check()); } }