diff --git a/app/Services/User/UserService.php b/app/Services/User/UserService.php
index b9eebc9..465f4af 100644
--- a/app/Services/User/UserService.php
+++ b/app/Services/User/UserService.php
@@ -115,8 +115,13 @@ class UserService implements UserServiceInterface
->whereColumn('msnv', 'user.msnv')
->whereBetween('date', [$startOfMonth, $endOfMonth])
])
- ->orderByDesc('score')
- ->get();
+ ->get()
+ ->filter(fn($u) => $u->score > 0)
+ ->sortBy([
+ ['score', 'desc'],
+ ['msnv', 'asc']
+ ])
+ ->values();
$currentRank = 0;
$prevScore = null;
@@ -157,8 +162,13 @@ class UserService implements UserServiceInterface
->whereColumn('msnv', 'user.msnv')
->whereBetween('date', [$startOfMonth, $endOfMonth])
])
- ->orderByDesc('score')
- ->get();
+ ->get()
+ ->filter(fn($u) => $u->score > 0)
+ ->sortBy([
+ ['score', 'desc'],
+ ['msnv', 'asc']
+ ])
+ ->values();
$prevScore = null;
$rank = 1;
@@ -181,15 +191,23 @@ class UserService implements UserServiceInterface
$currentUserRankItem = $userItem;
}
- if ($index < 5) {
+ if ($index < 4) {
$rankers[] = $userItem;
}
$rank++;
}
+ $showCurrentUserAtBottom = false;
+ if ($currentUserRankItem) {
+ $currentUserIndex = $users->search(fn($u) => $u->msnv == $currentUser->msnv);
+ if ($currentUserIndex !== false && $currentUserIndex >= 4) {
+ $showCurrentUserAtBottom = true;
+ }
+ }
+
return [
'rankers' => $rankers,
- 'currentUserRankItem' => $currentUserRankItem
+ 'currentUserRankItem' => $showCurrentUserAtBottom ? $currentUserRankItem : null
];
}
}
\ No newline at end of file
diff --git a/resources/views/user/partials/ranking_list.blade.php b/resources/views/user/partials/ranking_list.blade.php
index dc27b1c..f1a63a7 100644
--- a/resources/views/user/partials/ranking_list.blade.php
+++ b/resources/views/user/partials/ranking_list.blade.php
@@ -18,7 +18,7 @@
/>
@endforeach
- @if($currentUserRankItem && $currentUserRankItem->rank > 5)
+ @if($currentUserRankItem)
assertSee('User A', false);
$response->assertSee('User B', false);
}
+
+ public function test_dashboard_ranking_empty_state_when_no_data(): void
+ {
+ $user = \App\Models\User::create([
+ 'msnv' => 5001,
+ 'name' => 'User A',
+ 'mail' => 'usera@runsystem.net',
+ 'pass' => md5('password'),
+ 'departments' => 1,
+ 'role' => \App\Models\User::ROLE_MEMBER,
+ 'status' => \App\Models\User::STATUS_ACTIVE,
+ 'card' => 10,
+ 'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
+ 'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
+ ]);
+
+ $this->actingAs($user);
+
+ $response = $this->get('/my-page');
+ $response->assertOk();
+ $response->assertSee('Chưa có xếp hạng cho tháng này', false);
+ }
+
+ public function test_dashboard_ranking_dense_rank_and_deterministic_order(): void
+ {
+ $users = [];
+ for ($i = 1; $i <= 5; $i++) {
+ $char = chr(64 + $i);
+ $users[$i] = \App\Models\User::create([
+ 'msnv' => 5000 + $i,
+ 'name' => "User {$char}",
+ 'mail' => "user{$char}@runsystem.net",
+ 'pass' => md5('password'),
+ 'departments' => 1,
+ 'role' => \App\Models\User::ROLE_MEMBER,
+ 'status' => \App\Models\User::STATUS_ACTIVE,
+ 'card' => 10,
+ 'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
+ 'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
+ ]);
+
+ \App\Models\Administration::create([
+ 'msnv' => 5000 + $i,
+ 'received' => 9,
+ 'sender' => 9999,
+ 'sent' => 0,
+ 'receiver' => null,
+ 'date' => \Carbon\Carbon::now()->format('Y-m-d')
+ ]);
+ }
+
+ $this->actingAs($users[5]);
+
+ $response = $this->get('/my-page');
+ $response->assertOk();
+
+ $response->assertSee('User A', false);
+ $response->assertSee('User B', false);
+ $response->assertSee('User C', false);
+ $response->assertSee('User D', false);
+ $response->assertSee('User E', false);
+ }
+
+ public function test_dashboard_ranking_inactive_users_excluded(): void
+ {
+ $activeUser = \App\Models\User::create([
+ 'msnv' => 5001,
+ 'name' => 'Active User',
+ 'mail' => 'active@runsystem.net',
+ 'pass' => md5('password'),
+ 'departments' => 1,
+ 'role' => \App\Models\User::ROLE_MEMBER,
+ 'status' => \App\Models\User::STATUS_ACTIVE,
+ 'card' => 10,
+ 'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
+ 'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
+ ]);
+
+ $inactiveUser = \App\Models\User::create([
+ 'msnv' => 5002,
+ 'name' => 'Inactive User',
+ 'mail' => 'inactive@runsystem.net',
+ 'pass' => md5('password'),
+ 'departments' => 1,
+ 'role' => \App\Models\User::ROLE_MEMBER,
+ 'status' => \App\Models\User::STATUS_INACTIVE,
+ 'card' => 10,
+ 'flag_send' => \App\Models\User::FLAG_SEND_ENABLED,
+ 'first_login' => \App\Models\User::FIRST_LOGIN_FALSE,
+ ]);
+
+ \App\Models\Administration::create([
+ 'msnv' => 5001,
+ 'received' => 10,
+ 'sender' => 9999,
+ 'sent' => 0,
+ 'receiver' => null,
+ 'date' => \Carbon\Carbon::now()->format('Y-m-d')
+ ]);
+
+ \App\Models\Administration::create([
+ 'msnv' => 5002,
+ 'received' => 20,
+ 'sender' => 9999,
+ 'sent' => 0,
+ 'receiver' => null,
+ 'date' => \Carbon\Carbon::now()->format('Y-m-d')
+ ]);
+
+ $this->actingAs($activeUser);
+
+ $response = $this->get('/my-page');
+ $response->assertOk();
+
+ $response->assertSee('Active User', false);
+ $response->assertDontSee('Inactive User', false);
+ }
}