318 lines
12 KiB
PHP
318 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Admin;
|
|
|
|
use App\Models\AddCard;
|
|
use App\Models\Administration;
|
|
use App\Models\User;
|
|
use App\Services\Admin\Contracts\AdminServiceInterface;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
|
|
use App\DTOs\UserFilterDto;
|
|
|
|
class AdminService implements AdminServiceInterface
|
|
{
|
|
public function __construct(
|
|
private readonly \App\Services\User\Contracts\UserServiceInterface $userService
|
|
) {}
|
|
public function getUserListWithStats(
|
|
string|UserFilterDto $monthOrFilters,
|
|
?string $search = null,
|
|
?string $status = '1',
|
|
?string $role = null,
|
|
?string $department = null,
|
|
?string $flagSend = null
|
|
): array {
|
|
if ($monthOrFilters instanceof UserFilterDto) {
|
|
$filters = $monthOrFilters;
|
|
} else {
|
|
$filters = new UserFilterDto(
|
|
selectedMonth: $monthOrFilters,
|
|
search: $search,
|
|
status: $status,
|
|
role: $role,
|
|
department: $department,
|
|
flagSend: $flagSend
|
|
);
|
|
}
|
|
$selectedMonth = $filters->selectedMonth;
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth();
|
|
|
|
$usersQuery = User::select('user.*')
|
|
->addSelect([
|
|
'total_received' => Administration::selectRaw('COALESCE(SUM(received), 0)')
|
|
->whereColumn('msnv', 'user.msnv')
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth]),
|
|
'total_sent' => Administration::selectRaw('COALESCE(SUM(sent), 0)')
|
|
->whereColumn('msnv', 'user.msnv')
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
]);
|
|
|
|
$activeUsers = (clone $usersQuery)->where('status', config('constants.STATUS_ACTIVE'))->get();
|
|
|
|
$maxReceived = $activeUsers->max('total_received') ?? 0;
|
|
$maxSent = $activeUsers->max('total_sent') ?? 0;
|
|
|
|
$topReceivedUsers = $maxReceived > 0
|
|
? $activeUsers->filter(fn($u) => $u->total_received == $maxReceived)->values()
|
|
: collect();
|
|
|
|
$topSentUsers = $maxSent > 0
|
|
? $activeUsers->filter(fn($u) => $u->total_sent == $maxSent)->values()
|
|
: collect();
|
|
|
|
$topReceivedUser = $topReceivedUsers->first();
|
|
$topSentUser = $topSentUsers->first();
|
|
|
|
$status = $filters->status;
|
|
if (!is_null($status) && $status !== '') {
|
|
$usersQuery->where('status', intval($status));
|
|
}
|
|
|
|
$role = $filters->role;
|
|
if (!is_null($role) && $role !== '') {
|
|
$usersQuery->where('role', intval($role));
|
|
}
|
|
|
|
$department = $filters->department;
|
|
if (!is_null($department) && $department !== '') {
|
|
$usersQuery->where('departments', $department);
|
|
}
|
|
|
|
$flagSend = $filters->flagSend;
|
|
if (!is_null($flagSend) && $flagSend !== '') {
|
|
$usersQuery->where('flag_send', intval($flagSend));
|
|
}
|
|
|
|
$search = $filters->search;
|
|
if (!is_null($search) && trim($search) !== '') {
|
|
$search = trim($search);
|
|
$usersQuery->where(function ($q) use ($search) {
|
|
$q->whereRaw('LOWER(msnv) LIKE ?', ['%' . strtolower($search) . '%'])
|
|
->orWhereRaw('LOWER(name) LIKE ?', ['%' . strtolower($search) . '%'])
|
|
->orWhereRaw('LOWER(mail) LIKE ?', ['%' . strtolower($search) . '%']);
|
|
});
|
|
}
|
|
$users = $usersQuery->paginate(20)->withQueryString();
|
|
|
|
return compact('users', 'topReceivedUser', 'topSentUser', 'topReceivedUsers', 'topSentUsers');
|
|
}
|
|
|
|
public function getUserTransactions(string $msnv, string $selectedMonth): LengthAwarePaginator
|
|
{
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth();
|
|
|
|
return Administration::with(['senderUser', 'receiverUser'])
|
|
->where('msnv', $msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->orderBy('date', 'desc')
|
|
->paginate(10)
|
|
->withQueryString();
|
|
}
|
|
|
|
public function createUser(array $data): void
|
|
{
|
|
User::create([
|
|
'msnv' => $data['msnv'],
|
|
'name' => $data['name'],
|
|
'mail' => $data['mail'],
|
|
'pass' => md5($data['password']),
|
|
'departments' => $data['departments'],
|
|
'role' => $data['role'],
|
|
'status' => config('constants.STATUS_ACTIVE'),
|
|
'card' => 0,
|
|
'flag_send' => config('constants.FLAG_SEND_DISABLED'),
|
|
'first_login' => $data['role'] == config('constants.ROLE_ADMIN') ? config('constants.FIRST_LOGIN_FALSE') : config('constants.FIRST_LOGIN_TRUE'),
|
|
]);
|
|
}
|
|
|
|
public function updateUser(string|User $userOrMsnv, array $data): void
|
|
{
|
|
$user = $userOrMsnv instanceof User
|
|
? $userOrMsnv
|
|
: User::where('msnv', $userOrMsnv)->firstOrFail();
|
|
|
|
DB::transaction(function () use ($data, $user) {
|
|
// Update profile fields (name & avatar) via UserService
|
|
$this->userService->updateProfile($user, [
|
|
'name' => $data['name'] ?? null,
|
|
], request()->file('avatar'));
|
|
|
|
if (isset($data['mail'])) {
|
|
$user->mail = $data['mail'];
|
|
}
|
|
|
|
if (isset($data['departments'])) {
|
|
$user->departments = $data['departments'];
|
|
}
|
|
|
|
$newCard = $user->card;
|
|
if (isset($data['num_card'])) {
|
|
$newCard = $user->card + intval($data['num_card']);
|
|
} elseif (isset($data['card'])) {
|
|
$newCard = intval($data['card']);
|
|
}
|
|
|
|
$oldCard = intval($user->card);
|
|
|
|
if ($newCard > $oldCard) {
|
|
$diff = $newCard - $oldCard;
|
|
$todayRecord = AddCard::where('buyer', $user->msnv)
|
|
->where('seller', Auth::user()->msnv)
|
|
->whereDate('date', Carbon::today())
|
|
->first();
|
|
if ($todayRecord) {
|
|
$todayRecord->num_card += $diff;
|
|
$todayRecord->save();
|
|
} else {
|
|
AddCard::create([
|
|
'buyer' => $user->msnv,
|
|
'num_card' => $diff,
|
|
'seller' => Auth::user()->msnv,
|
|
'date' => Carbon::today(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
$user->card = $newCard;
|
|
$user->role = isset($data['role']) ? intval($data['role']) : $user->role;
|
|
$user->status = isset($data['status']) ? intval($data['status']) : $user->status;
|
|
$user->flag_send = isset($data['flag_send']) ? intval($data['flag_send']) : $user->flag_send;
|
|
$user->first_login = isset($data['first_login']) ? intval($data['first_login']) : $user->first_login;
|
|
$user->save();
|
|
});
|
|
}
|
|
|
|
public function deactivateUser(string $msnv): void
|
|
{
|
|
$user = User::where('msnv', $msnv)->firstOrFail();
|
|
$user->status = config('constants.STATUS_INACTIVE');
|
|
$user->save();
|
|
}
|
|
|
|
public function resetAllCards(): void
|
|
{
|
|
User::where('status', config('constants.STATUS_ACTIVE'))->update([
|
|
'card' => 0,
|
|
'flag_send' => config('constants.FLAG_SEND_DISABLED'),
|
|
]);
|
|
}
|
|
|
|
public function updateAddCard(int $id, array $data): void
|
|
{
|
|
$addCard = AddCard::findOrFail($id);
|
|
|
|
$currentMonth = Carbon::now()->format('Y-m');
|
|
$recordMonth = Carbon::parse($addCard->date)->format('Y-m');
|
|
|
|
if ($recordMonth !== $currentMonth) {
|
|
throw new \Exception('Không cho phép chỉnh sửa dữ liệu card của các tháng trước.');
|
|
}
|
|
|
|
$newDateMonth = Carbon::parse($data['date'])->format('Y-m');
|
|
if ($newDateMonth !== $currentMonth) {
|
|
throw new \Exception('Chỉ được phép chỉnh sửa dữ liệu của tháng hiện tại.');
|
|
}
|
|
|
|
$user = User::where('msnv', $addCard->buyer)->firstOrFail();
|
|
|
|
$startOfMonth = Carbon::now()->startOfMonth();
|
|
$endOfMonth = Carbon::now()->endOfMonth();
|
|
$totalSentThisMonth = Administration::where('msnv', $user->msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->sum('sent');
|
|
|
|
DB::transaction(function () use ($addCard, $user, $data, $totalSentThisMonth) {
|
|
$oldNumCard = intval($addCard->num_card);
|
|
$newNumCard = intval($data['num_card']);
|
|
$diff = $newNumCard - $oldNumCard;
|
|
$newCardBalance = $user->card + $diff;
|
|
if ($newCardBalance < 0) {
|
|
throw new \Exception('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.');
|
|
}
|
|
|
|
if ($newCardBalance < $totalSentThisMonth) {
|
|
throw new \Exception('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 (' . $totalSentThisMonth . ' card).');
|
|
}
|
|
|
|
$user->card += $diff;
|
|
$user->save();
|
|
|
|
$addCard->num_card = $newNumCard;
|
|
$addCard->seller = $data['seller'];
|
|
$addCard->date = $data['date'];
|
|
$addCard->save();
|
|
});
|
|
}
|
|
|
|
public function destroyAddCard(int $id): void
|
|
{
|
|
$addCard = AddCard::findOrFail($id);
|
|
|
|
$currentMonth = Carbon::now()->format('Y-m');
|
|
$recordMonth = Carbon::parse($addCard->date)->format('Y-m');
|
|
|
|
if ($recordMonth !== $currentMonth) {
|
|
throw new \Exception('Không cho phép xóa dữ liệu card của các tháng trước.');
|
|
}
|
|
|
|
$user = User::where('msnv', $addCard->buyer)->firstOrFail();
|
|
|
|
$startOfMonth = Carbon::now()->startOfMonth();
|
|
$endOfMonth = Carbon::now()->endOfMonth();
|
|
$totalSentThisMonth = Administration::where('msnv', $user->msnv)
|
|
->whereBetween('date', [$startOfMonth, $endOfMonth])
|
|
->sum('sent');
|
|
|
|
DB::transaction(function () use ($addCard, $user, $totalSentThisMonth) {
|
|
$newCardBalance = $user->card - intval($addCard->num_card);
|
|
|
|
if ($newCardBalance < 0) {
|
|
throw new \Exception('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 0.');
|
|
}
|
|
|
|
if ($newCardBalance < $totalSentThisMonth) {
|
|
throw new \Exception('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 (' . $totalSentThisMonth . ' card).');
|
|
}
|
|
|
|
$user->card = $newCardBalance;
|
|
$user->save();
|
|
|
|
$addCard->delete();
|
|
});
|
|
}
|
|
|
|
public function getUserByMsnv(string $msnv): User
|
|
{
|
|
return User::where('msnv', $msnv)->firstOrFail();
|
|
}
|
|
|
|
public function getAddCardsHistory(string $buyerMsnv, ?string $selectedMonth = null): \Illuminate\Database\Eloquent\Collection
|
|
{
|
|
$query = AddCard::with('sellerUser')
|
|
->where('buyer', $buyerMsnv);
|
|
|
|
if ($selectedMonth) {
|
|
$startOfMonth = Carbon::parse($selectedMonth)->startOfMonth()->format('Y-m-d');
|
|
$endOfMonth = Carbon::parse($selectedMonth)->endOfMonth()->format('Y-m-d');
|
|
$query->whereBetween('date', [$startOfMonth, $endOfMonth]);
|
|
}
|
|
|
|
return $query->orderBy('date', 'desc')
|
|
->orderBy('id', 'desc')
|
|
->get();
|
|
}
|
|
|
|
public function getActiveAdmins(): \Illuminate\Database\Eloquent\Collection
|
|
{
|
|
return User::where('role', config('constants.ROLE_ADMIN'))
|
|
->where('status', config('constants.STATUS_ACTIVE'))
|
|
->get();
|
|
}
|
|
} |