215 lines
7.0 KiB
PHP
215 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\User;
|
|
|
|
use App\Models\Administration;
|
|
use App\Models\User;
|
|
use App\Services\User\Contracts\UserServiceInterface;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
|
|
class UserService implements UserServiceInterface
|
|
{
|
|
public function getDashboard(User $user, string $selectedMonth): LengthAwarePaginator
|
|
{
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth();
|
|
|
|
return Administration::where('msnv', $user->msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->orderBy('date', 'desc')
|
|
->paginate(10)
|
|
->withQueryString();
|
|
}
|
|
|
|
public function getOtherActiveUsers(User $currentUser): Collection
|
|
{
|
|
return User::where('status', User::STATUS_ACTIVE)
|
|
->where('msnv', '!=', $currentUser->msnv)
|
|
->get();
|
|
}
|
|
|
|
public function sendThankcards(User $sender, string $receiverMsnv, int $amount): void
|
|
{
|
|
if ($sender->flag_send == User::FLAG_SEND_DISABLED) {
|
|
throw new \RuntimeException(__('messages.error.no_send_permission'));
|
|
}
|
|
|
|
$receiver = User::where('msnv', $receiverMsnv)->first();
|
|
if (!$receiver || $receiver->status != User::STATUS_ACTIVE) {
|
|
throw new \RuntimeException(__('messages.error.receiver_invalid'));
|
|
}
|
|
|
|
$startOfMonth = Carbon::now()->startOfMonth();
|
|
$endOfMonth = Carbon::now()->endOfMonth();
|
|
|
|
$cardsSentToThisUserThisMonth = Administration::where('msnv', $sender->msnv)
|
|
->where('receiver', $receiverMsnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->sum('sent');
|
|
|
|
if ($cardsSentToThisUserThisMonth + $amount > Administration::MAX_SEND_CARD_PER_MONTH) {
|
|
throw new \RuntimeException(
|
|
__('messages.error.max_send_limit_template', [
|
|
'max' => Administration::MAX_SEND_CARD_PER_MONTH,
|
|
'sent' => $cardsSentToThisUserThisMonth
|
|
])
|
|
);
|
|
}
|
|
|
|
if ($sender->card < $amount) {
|
|
throw new \RuntimeException(__('messages.error.not_enough_cards'));
|
|
}
|
|
|
|
DB::transaction(function () use ($sender, $receiverMsnv, $amount) {
|
|
Administration::create([
|
|
'msnv' => $receiverMsnv,
|
|
'received' => $amount,
|
|
'sender' => $sender->msnv,
|
|
'sent' => 0,
|
|
'receiver' => null,
|
|
'date' => Carbon::today(),
|
|
]);
|
|
|
|
Administration::create([
|
|
'msnv' => $sender->msnv,
|
|
'received' => 0,
|
|
'sender' => null,
|
|
'sent' => $amount,
|
|
'receiver' => $receiverMsnv,
|
|
'date' => Carbon::today(),
|
|
]);
|
|
|
|
$sender->card -= $amount;
|
|
$sender->save();
|
|
});
|
|
}
|
|
|
|
public function updatePassword(User $user, string $newPassword): void
|
|
{
|
|
$user->pass = md5($newPassword);
|
|
$user->first_login = User::FIRST_LOGIN_FALSE;
|
|
$user->save();
|
|
}
|
|
|
|
public function getPersonalStats(User $user, string $selectedMonth): array
|
|
{
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth();
|
|
|
|
$receivedCount = (int) Administration::where('msnv', $user->msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->sum('received');
|
|
|
|
$sentCount = (int) Administration::where('msnv', $user->msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->sum('sent');
|
|
|
|
// Calculate current rank (based on received)
|
|
$rankings = User::where('status', User::STATUS_ACTIVE)
|
|
->addSelect([
|
|
'score' => Administration::selectRaw('COALESCE(SUM(received), 0)')
|
|
->whereColumn('msnv', 'user.msnv')
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
])
|
|
->get()
|
|
->filter(fn($u) => $u->score > 0)
|
|
->sortBy([
|
|
['score', 'desc'],
|
|
['msnv', 'asc']
|
|
])
|
|
->values();
|
|
|
|
$currentRank = 0;
|
|
$prevScore = null;
|
|
$rank = 1;
|
|
$denseRank = 0;
|
|
|
|
foreach ($rankings as $item) {
|
|
$score = (int) $item->score;
|
|
if ($score !== $prevScore) {
|
|
$denseRank = $rank;
|
|
$prevScore = $score;
|
|
}
|
|
|
|
if ($item->msnv == $user->msnv) {
|
|
$currentRank = $denseRank;
|
|
break;
|
|
}
|
|
$rank++;
|
|
}
|
|
|
|
return [
|
|
'receivedCount' => $receivedCount,
|
|
'sentCount' => $sentCount,
|
|
'currentRank' => $currentRank
|
|
];
|
|
}
|
|
|
|
public function getRankingList(string $type, string $selectedMonth, User $currentUser): array
|
|
{
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth();
|
|
|
|
$column = $type === 'sent' ? 'sent' : 'received';
|
|
|
|
$allActiveUsers = User::where('status', User::STATUS_ACTIVE)
|
|
->addSelect([
|
|
'score' => Administration::selectRaw('COALESCE(SUM(' . $column . '), 0)')
|
|
->whereColumn('msnv', 'user.msnv')
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
])
|
|
->get();
|
|
|
|
$rankedUsers = $allActiveUsers->filter(fn($u) => $u->score > 0)
|
|
->sortBy([
|
|
['score', 'desc'],
|
|
['msnv', 'asc']
|
|
])
|
|
->values();
|
|
|
|
$prevScore = null;
|
|
$rank = 1;
|
|
$denseRank = 0;
|
|
|
|
$rankers = [];
|
|
$currentUserRankItem = null;
|
|
|
|
foreach ($rankedUsers as $index => $userItem) {
|
|
$score = (int) $userItem->score;
|
|
if ($score !== $prevScore) {
|
|
$denseRank = $rank;
|
|
$prevScore = $score;
|
|
}
|
|
|
|
$userItem->rank = $denseRank;
|
|
$userItem->score = $score;
|
|
|
|
if ($userItem->msnv == $currentUser->msnv) {
|
|
$currentUserRankItem = $userItem;
|
|
}
|
|
|
|
if ($index < 4) {
|
|
$rankers[] = $userItem;
|
|
}
|
|
$rank++;
|
|
}
|
|
|
|
if (!$currentUserRankItem) {
|
|
$currentUserModel = $allActiveUsers->first(fn($u) => $u->msnv == $currentUser->msnv);
|
|
if ($currentUserModel) {
|
|
$currentUserRankItem = clone $currentUserModel;
|
|
$currentUserRankItem->score = 0;
|
|
$currentUserRankItem->rank = 0;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'rankers' => $rankers,
|
|
'currentUserRankItem' => $currentUserRankItem
|
|
];
|
|
}
|
|
} |