From 326e1f10283fdac636e6f00fbfe9641de9fe9f20 Mon Sep 17 00:00:00 2001 From: antv Date: Thu, 9 Jul 2026 10:27:47 +0700 Subject: [PATCH] refactor: refactor controllers, services, validation and introduce DTOs, FormRequests and domain exceptions --- app/DTOs/DashboardDataDto.php | 41 +++++ app/DTOs/UserFilterDto.php | 33 ++++ app/Exceptions/ThankCardException.php | 10 ++ .../Controllers/Admin/AdminController.php | 142 ++++++++---------- app/Http/Controllers/User/UserController.php | 120 +++++++++------ app/Http/Requests/Admin/StoreUserRequest.php | 31 ++++ .../Requests/Admin/UpdateAddCardRequest.php | 28 ++++ app/Http/Requests/Admin/UpdateUserRequest.php | 41 +++++ .../Requests/User/SendThankCardRequest.php | 32 ++++ .../Requests/User/UpdatePasswordRequest.php | 38 +++++ .../Requests/User/UpdateProfileRequest.php | 27 ++++ app/Services/Admin/AdminService.php | 71 +++++++-- .../Admin/Contracts/AdminServiceInterface.php | 12 +- .../User/Contracts/UserServiceInterface.php | 2 + app/Services/User/UserService.php | 23 ++- 15 files changed, 501 insertions(+), 150 deletions(-) create mode 100644 app/DTOs/DashboardDataDto.php create mode 100644 app/DTOs/UserFilterDto.php create mode 100644 app/Exceptions/ThankCardException.php create mode 100644 app/Http/Requests/Admin/StoreUserRequest.php create mode 100644 app/Http/Requests/Admin/UpdateAddCardRequest.php create mode 100644 app/Http/Requests/Admin/UpdateUserRequest.php create mode 100644 app/Http/Requests/User/SendThankCardRequest.php create mode 100644 app/Http/Requests/User/UpdatePasswordRequest.php create mode 100644 app/Http/Requests/User/UpdateProfileRequest.php diff --git a/app/DTOs/DashboardDataDto.php b/app/DTOs/DashboardDataDto.php new file mode 100644 index 0000000..bba7f41 --- /dev/null +++ b/app/DTOs/DashboardDataDto.php @@ -0,0 +1,41 @@ + $this->administrations, + 'selectedMonth' => $this->selectedMonth, + 'user' => $this->user, + 'receivedRankers' => $this->receivedRankers, + 'receivedCurrentUserRankItem' => $this->receivedCurrentUserRankItem, + 'sentRankers' => $this->sentRankers, + 'sentCurrentUserRankItem' => $this->sentCurrentUserRankItem, + 'receivedCount' => $this->receivedCount, + 'sentCount' => $this->sentCount, + 'currentRank' => $this->currentRank, + ]; + } +} diff --git a/app/DTOs/UserFilterDto.php b/app/DTOs/UserFilterDto.php new file mode 100644 index 0000000..5fa135c --- /dev/null +++ b/app/DTOs/UserFilterDto.php @@ -0,0 +1,33 @@ +input('month', Carbon::now()->format('Y-m')), + search: $request->input('search'), + status: $request->has('status') ? (string) $request->input('status') : '1', + role: $request->input('role'), + department: $request->input('department'), + flagSend: $request->input('flag_send') + ); + } +} diff --git a/app/Exceptions/ThankCardException.php b/app/Exceptions/ThankCardException.php new file mode 100644 index 0000000..0ed7a6b --- /dev/null +++ b/app/Exceptions/ThankCardException.php @@ -0,0 +1,10 @@ +input('month', Carbon::now()->format('Y-m')); - $search = $request->input('search'); - $status = $request->input('status', (string)config('constants.STATUS_ACTIVE')); - $role = $request->input('role'); - $department = $request->input('department'); - $flagSend = $request->input('flag_send'); + $filters = UserFilterDto::fromRequest($request); [ 'users' => $users, @@ -29,11 +33,11 @@ class AdminController extends Controller 'topSentUser' => $topSentUser, 'topReceivedUsers' => $topReceivedUsers, 'topSentUsers' => $topSentUsers - ] = $this->adminService->getUserListWithStats($selectedMonth, $search, $status, $role, $department, $flagSend); + ] = $this->adminService->getUserListWithStats($filters); if ($request->ajax() || $request->wantsJson()) { return response()->json([ - 'title' => view('admin.users.partials.title', compact('selectedMonth'))->render(), + 'title' => view('admin.users.partials.title', ['selectedMonth' => $filters->selectedMonth])->render(), 'stats' => view('admin.users.partials.stats', compact('topReceivedUser', 'topSentUser', 'topReceivedUsers', 'topSentUsers'))->render(), 'table' => view('admin.users.partials.table', compact('users'))->render(), ]); @@ -41,117 +45,91 @@ class AdminController extends Controller return view('admin.users.index', compact( 'users', - 'selectedMonth', 'topReceivedUser', 'topSentUser', 'topReceivedUsers', - 'topSentUsers', - 'search', - 'status', - 'role', - 'department', - 'flagSend' - )); + 'topSentUsers' + ))->with([ + 'selectedMonth' => $filters->selectedMonth, + 'search' => $filters->search, + 'status' => $filters->status, + 'role' => $filters->role, + 'department' => $filters->department, + 'flagSend' => $filters->flagSend, + ]); } - public function create() + /** + * Show the form for creating a new user. + */ + public function create(): View { return view('admin.users.create'); } - public function store(Request $request) + /** + * Store a newly created user in storage. + */ + public function store(StoreUserRequest $request): RedirectResponse { - $request->validate([ - 'msnv' => 'required|integer|unique:user,msnv', - 'name' => 'required|string|max:255', - 'mail' => 'required|email|unique:user,mail', - 'departments' => 'required|string|in:' . implode(',', config('constants.DEPARTMENTS')), - 'password' => 'required|string', - 'role' => 'required|in:' . config('constants.ROLE_MEMBER') . ',' . config('constants.ROLE_ADMIN'), - ]); - - $this->adminService->createUser($request->only('msnv', 'name', 'mail', 'departments', 'password', 'role')); + $this->adminService->createUser($request->validated()); return redirect()->route('admin.users.index')->with('success', __('messages.user_create_success')); } - public function edit(Request $request, $msnv) + /** + * Show the form for editing the specified user. + */ + public function edit(Request $request, string $msnv): View { - $user = User::where('msnv', $msnv)->firstOrFail(); - $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); - + $user = $this->adminService->getUserByMsnv($msnv); + $selectedMonth = (string) $request->input('month', Carbon::now()->format('Y-m')); $administrations = $this->adminService->getUserTransactions($msnv, $selectedMonth); - - $addCards = \App\Models\AddCard::with('sellerUser') - ->where('buyer', $user->msnv) - ->orderBy('date', 'desc') - ->orderBy('id', 'desc') - ->get(); - - $admins = User::where('role', config('constants.ROLE_ADMIN')) - ->where('status', config('constants.STATUS_ACTIVE')) - ->get(); + $addCards = $this->adminService->getAddCardsHistory($user->msnv); + $admins = $this->adminService->getActiveAdmins(); return view('admin.users.edit', compact('user', 'administrations', 'selectedMonth', 'addCards', 'admins')); } - public function update(Request $request, $msnv) + /** + * Update the specified user in storage. + */ + public function update(UpdateUserRequest $request, string $msnv): RedirectResponse { - $user = User::where('msnv', $msnv)->firstOrFail(); + $user = $this->adminService->getUserByMsnv($msnv); - $request->validate([ - 'card' => 'nullable|integer|min:0', - 'num_card' => 'nullable|integer|min:1', - 'role' => 'nullable|in:' . config('constants.ROLE_MEMBER') . ',' . config('constants.ROLE_ADMIN'), - 'status' => 'nullable|in:' . config('constants.STATUS_INACTIVE') . ',' . config('constants.STATUS_ACTIVE'), - 'flag_send' => 'nullable|in:0,1', - 'first_login' => 'nullable|in:' . config('constants.FIRST_LOGIN_FALSE') . ',' . config('constants.FIRST_LOGIN_TRUE'), - ]); - - $cardValue = $user->card; - if ($request->has('num_card') && !is_null($request->num_card)) { - $cardValue = $user->card + intval($request->num_card); - } elseif ($request->has('card')) { - $cardValue = intval($request->card); - } - - $data = [ - 'card' => $cardValue, - 'role' => $request->input('role', $user->role), - 'status' => $request->input('status', $user->status), - 'flag_send' => $request->has('flag_send') ? config('constants.FLAG_SEND_ENABLED') : config('constants.FLAG_SEND_DISABLED'), - 'first_login' => $request->input('first_login', $user->first_login), - ]; - - $this->adminService->updateUser($msnv, $data); + $this->adminService->updateUser($user, $request->validated()); return redirect()->back()->with('success', __('messages.user_update_success')); } - public function destroy($msnv) + /** + * Remove (deactivate) the specified user from storage. + */ + public function destroy(string $msnv): RedirectResponse { $this->adminService->deactivateUser($msnv); return redirect()->route('admin.users.index')->with('success', __('messages.user_deactivate_success')); } - public function updateAddCard(Request $request, $id) + /** + * Update card allocation history record. + */ + public function updateAddCard(UpdateAddCardRequest $request, int $id): RedirectResponse { - $request->validate([ - 'num_card' => 'required|integer|min:1', - 'seller' => 'required|exists:user,msnv', - 'date' => 'required|date', - ]); - try { - $this->adminService->updateAddCard(intval($id), $request->only('num_card', 'seller', 'date')); + $this->adminService->updateAddCard($id, $request->validated()); return redirect()->back()->with('success', 'Cập nhật lịch sử cấp phát thẻ thành công.'); } catch (\Exception $e) { return redirect()->back()->withErrors(['error' => $e->getMessage()]); } } - public function resetCards() + /** + * Reset all cards for active users. + */ + public function resetCards(): RedirectResponse { $this->adminService->resetAllCards(); diff --git a/app/Http/Controllers/User/UserController.php b/app/Http/Controllers/User/UserController.php index 984d991..36dfd57 100644 --- a/app/Http/Controllers/User/UserController.php +++ b/app/Http/Controllers/User/UserController.php @@ -3,102 +3,122 @@ namespace App\Http\Controllers\User; use App\Http\Controllers\Controller; -use App\Models\Administration; +use App\Http\Requests\User\SendThankCardRequest; +use App\Http\Requests\User\UpdateProfileRequest; +use App\Http\Requests\User\UpdatePasswordRequest; +use App\DTOs\DashboardDataDto; +use App\Exceptions\ThankCardException; use App\Services\User\Contracts\UserServiceInterface; use Carbon\Carbon; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\View\View; class UserController extends Controller { public function __construct( - private UserServiceInterface $userService + private readonly UserServiceInterface $userService ) {} - public function index(Request $request) + /** + * Display the user dashboard with transaction history, stats, and rankings. + */ + public function index(Request $request): View { - $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); + $selectedMonth = (string) $request->input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $administrations = $this->userService->getDashboard($user, $selectedMonth); - $stats = $this->userService->getPersonalStats($user, $selectedMonth); + $stats = $this->userService->getPersonalStats($user, $selectedMonth); $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); - $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); + $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); - return view('user.dashboard', array_merge([ - 'administrations' => $administrations, - 'selectedMonth' => $selectedMonth, - 'user' => $user, - 'receivedRankers' => $receivedRanking['rankers'], - 'receivedCurrentUserRankItem' => $receivedRanking['currentUserRankItem'], - 'sentRankers' => $sentRanking['rankers'], - 'sentCurrentUserRankItem' => $sentRanking['currentUserRankItem'] - ], $stats)); + $dashboardData = new DashboardDataDto( + administrations: $administrations, + selectedMonth: $selectedMonth, + user: $user, + receivedRankers: $receivedRanking['rankers'], + receivedCurrentUserRankItem: $receivedRanking['currentUserRankItem'], + sentRankers: $sentRanking['rankers'], + sentCurrentUserRankItem: $sentRanking['currentUserRankItem'], + receivedCount: (int) $stats['receivedCount'], + sentCount: (int) $stats['sentCount'], + currentRank: (int) $stats['currentRank'] + ); + + return view('user.dashboard', $dashboardData->toArray()); } - public function sendThankcards() + /** + * Show the form to send thank cards. + */ + public function sendThankcards(): View { $users = $this->userService->getOtherActiveUsers(Auth::user()); return view('user.send', compact('users')); } - public function storeThankcards(Request $request) + /** + * Store and execute sending thank cards to another user. + */ + public function storeThankcards(SendThankCardRequest $request): JsonResponse { - $request->validate([ - 'receiver' => [ - 'required', - \Illuminate\Validation\Rule::exists('user', 'msnv')->where('status', config('constants.STATUS_ACTIVE')) - ], - 'amount' => 'required|integer|min:1|max:' . Administration::MAX_SEND_CARD_PER_MONTH, - ]); - try { $this->userService->sendThankcards( Auth::user(), - $request->receiver, - (int) $request->amount + (string) $request->input('receiver'), + (int) $request->input('amount') ); - } catch (\RuntimeException $e) { + } catch (ThankCardException $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 422); } return response()->json(['success' => true, 'message' => __('messages.thank_card_send_success')]); } - public function changePasswordForm() + /** + * Show the change password form. + */ + public function changePasswordForm(): View { return view('user.change_password'); } - // Show edit profile page (avatar & password) - public function editProfile() + /** + * Handle user password change. + */ + public function updatePassword(UpdatePasswordRequest $request): RedirectResponse + { + $user = Auth::user(); + $this->userService->updatePassword($user, $request->input('password')); + + $route = $user->role == config('constants.ROLE_ADMIN') ? 'admin.dashboard' : 'user.dashboard'; + return redirect()->route($route)->with('success', __('messages.password_change_success')); + } + + /** + * Show the edit profile page (avatar & password). + */ + public function editProfile(): View { return view('user.edit'); } - // Handle avatar upload and optional password change - public function updateProfile(Request $request) + /** + * Handle avatar upload and optional password change. + */ + public function updateProfile(UpdateProfileRequest $request): RedirectResponse { - $request->validate([ - 'avatar' => 'nullable|image|max:2048', // 2MB max - 'new_password' => 'nullable|min:6|confirmed', - ]); - $user = Auth::user(); - // Avatar handling - if ($request->hasFile('avatar')) { - $path = $request->file('avatar')->store('avatars', 'public'); - $user->avatar = 'storage/' . $path; - } - - // Password handling (optional) - if ($request->filled('new_password')) { - $this->userService->updatePassword($user, $request->new_password); - } - - $user->save(); + $this->userService->updateProfile( + $user, + $request->file('avatar'), + $request->filled('new_password') ? $request->input('new_password') : null + ); return redirect()->route('user.edit')->with('success', 'Cập nhật hồ sơ thành công'); } diff --git a/app/Http/Requests/Admin/StoreUserRequest.php b/app/Http/Requests/Admin/StoreUserRequest.php new file mode 100644 index 0000000..35f976c --- /dev/null +++ b/app/Http/Requests/Admin/StoreUserRequest.php @@ -0,0 +1,31 @@ + 'required|integer|unique:user,msnv', + 'name' => 'required|string|max:255', + 'mail' => 'required|email|unique:user,mail', + 'departments' => 'required|string|in:' . implode(',', config('constants.DEPARTMENTS')), + 'password' => 'required|string', + 'role' => 'required|in:' . config('constants.ROLE_MEMBER') . ',' . config('constants.ROLE_ADMIN'), + ]; + } +} diff --git a/app/Http/Requests/Admin/UpdateAddCardRequest.php b/app/Http/Requests/Admin/UpdateAddCardRequest.php new file mode 100644 index 0000000..d6f6c93 --- /dev/null +++ b/app/Http/Requests/Admin/UpdateAddCardRequest.php @@ -0,0 +1,28 @@ + 'required|integer|min:1', + 'seller' => 'required|exists:user,msnv', + 'date' => 'required|date', + ]; + } +} diff --git a/app/Http/Requests/Admin/UpdateUserRequest.php b/app/Http/Requests/Admin/UpdateUserRequest.php new file mode 100644 index 0000000..9e977a3 --- /dev/null +++ b/app/Http/Requests/Admin/UpdateUserRequest.php @@ -0,0 +1,41 @@ +isMethod('put') || $this->isMethod('patch')) && !$this->has('flag_send')) { + $this->merge([ + 'flag_send' => config('constants.FLAG_SEND_DISABLED'), + ]); + } + } + + /** + * Get the validation rules that apply to the request. + */ + public function rules(): array + { + return [ + 'card' => 'nullable|integer|min:0', + 'num_card' => 'nullable|integer|min:1', + 'role' => 'nullable|in:' . config('constants.ROLE_MEMBER') . ',' . config('constants.ROLE_ADMIN'), + 'status' => 'nullable|in:' . config('constants.STATUS_INACTIVE') . ',' . config('constants.STATUS_ACTIVE'), + 'flag_send' => 'nullable|in:0,1', + 'first_login' => 'nullable|in:' . config('constants.FIRST_LOGIN_FALSE') . ',' . config('constants.FIRST_LOGIN_TRUE'), + ]; + } +} diff --git a/app/Http/Requests/User/SendThankCardRequest.php b/app/Http/Requests/User/SendThankCardRequest.php new file mode 100644 index 0000000..beb360f --- /dev/null +++ b/app/Http/Requests/User/SendThankCardRequest.php @@ -0,0 +1,32 @@ + [ + 'required', + Rule::exists('user', 'msnv')->where('status', config('constants.STATUS_ACTIVE')) + ], + 'amount' => 'required|integer|min:1|max:' . Administration::MAX_SEND_CARD_PER_MONTH, + ]; + } +} diff --git a/app/Http/Requests/User/UpdatePasswordRequest.php b/app/Http/Requests/User/UpdatePasswordRequest.php new file mode 100644 index 0000000..7d09dd3 --- /dev/null +++ b/app/Http/Requests/User/UpdatePasswordRequest.php @@ -0,0 +1,38 @@ + 'required|min:6|confirmed', + ]; + } + + /** + * Get the custom validation error messages. + */ + public function messages(): array + { + return [ + 'password.required' => 'Mật khẩu mới không được để trống.', + 'password.min' => 'Mật khẩu mới phải có ít nhất 6 ký tự.', + 'password.confirmed' => 'Mật khẩu xác nhận không trùng khớp.', + ]; + } +} diff --git a/app/Http/Requests/User/UpdateProfileRequest.php b/app/Http/Requests/User/UpdateProfileRequest.php new file mode 100644 index 0000000..23e9cce --- /dev/null +++ b/app/Http/Requests/User/UpdateProfileRequest.php @@ -0,0 +1,27 @@ + 'nullable|image|max:2048', // 2MB max + 'new_password' => 'nullable|min:6|confirmed', + ]; + } +} diff --git a/app/Services/Admin/AdminService.php b/app/Services/Admin/AdminService.php index b148cf0..37c8ec3 100644 --- a/app/Services/Admin/AdminService.php +++ b/app/Services/Admin/AdminService.php @@ -12,18 +12,33 @@ 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 getUserListWithStats( - string $selectedMonth, - ?string $search = null, + string|UserFilterDto $monthOrFilters, + ?string $search = null, ?string $status = '1', ?string $role = null, ?string $department = null, ?string $flagSend = null ): array { - $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); - $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); + 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([ @@ -51,22 +66,27 @@ class AdminService implements AdminServiceInterface $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) { @@ -109,12 +129,20 @@ class AdminService implements AdminServiceInterface ]); } - public function updateUser(string $msnv, array $data): void + public function updateUser(string|User $userOrMsnv, array $data): void { - $user = User::where('msnv', $msnv)->firstOrFail(); + $user = $userOrMsnv instanceof User + ? $userOrMsnv + : User::where('msnv', $userOrMsnv)->firstOrFail(); DB::transaction(function () use ($data, $user) { - $newCard = intval($data['card']); + $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) { @@ -128,10 +156,10 @@ class AdminService implements AdminServiceInterface } $user->card = $newCard; - $user->role = intval($data['role']); - $user->status = intval($data['status']); - $user->flag_send = intval($data['flag_send']); - $user->first_login = intval($data['first_login']); + $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(); }); } @@ -185,4 +213,25 @@ class AdminService implements AdminServiceInterface $addCard->save(); }); } + + public function getUserByMsnv(string $msnv): User + { + return User::where('msnv', $msnv)->firstOrFail(); + } + + public function getAddCardsHistory(string $buyerMsnv): \Illuminate\Database\Eloquent\Collection + { + return AddCard::with('sellerUser') + ->where('buyer', $buyerMsnv) + ->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(); + } } \ No newline at end of file diff --git a/app/Services/Admin/Contracts/AdminServiceInterface.php b/app/Services/Admin/Contracts/AdminServiceInterface.php index 032165f..eb4e80c 100644 --- a/app/Services/Admin/Contracts/AdminServiceInterface.php +++ b/app/Services/Admin/Contracts/AdminServiceInterface.php @@ -7,8 +7,8 @@ use Illuminate\Pagination\LengthAwarePaginator; interface AdminServiceInterface { public function getUserListWithStats( - string $selectedMonth, - ?string $search = null, + string|\App\DTOs\UserFilterDto $monthOrFilters, + ?string $search = null, ?string $status = '1', ?string $role = null, ?string $department = null, @@ -19,11 +19,17 @@ interface AdminServiceInterface public function createUser(array $data): void; - public function updateUser(string $msnv, array $data): void; + public function updateUser(string|\App\Models\User $userOrMsnv, array $data): void; public function deactivateUser(string $msnv): void; public function resetAllCards(): void; public function updateAddCard(int $id, array $data): void; + + public function getUserByMsnv(string $msnv): \App\Models\User; + + public function getAddCardsHistory(string $buyerMsnv): \Illuminate\Database\Eloquent\Collection; + + public function getActiveAdmins(): \Illuminate\Database\Eloquent\Collection; } \ No newline at end of file diff --git a/app/Services/User/Contracts/UserServiceInterface.php b/app/Services/User/Contracts/UserServiceInterface.php index ac57fca..499c91d 100644 --- a/app/Services/User/Contracts/UserServiceInterface.php +++ b/app/Services/User/Contracts/UserServiceInterface.php @@ -18,4 +18,6 @@ interface UserServiceInterface public function getPersonalStats(User $user, string $selectedMonth): array; public function getRankingList(string $type, string $selectedMonth, User $currentUser): array; + + public function updateProfile(User $user, ?\Illuminate\Http\UploadedFile $avatarFile, ?string $newPassword): void; } \ No newline at end of file diff --git a/app/Services/User/UserService.php b/app/Services/User/UserService.php index a20796a..8f43648 100644 --- a/app/Services/User/UserService.php +++ b/app/Services/User/UserService.php @@ -36,12 +36,12 @@ class UserService implements UserServiceInterface public function sendThankcards(User $sender, string $receiverMsnv, int $amount): void { if ($sender->flag_send == config('constants.FLAG_SEND_DISABLED')) { - throw new \RuntimeException(__('messages.error.no_send_permission')); + throw new \App\Exceptions\ThankCardException(__('messages.error.no_send_permission')); } $receiver = User::where('msnv', $receiverMsnv)->first(); if (!$receiver || $receiver->status != config('constants.STATUS_ACTIVE')) { - throw new \RuntimeException(__('messages.error.receiver_invalid')); + throw new \App\Exceptions\ThankCardException(__('messages.error.receiver_invalid')); } $startOfMonth = Carbon::now()->startOfMonth(); @@ -53,7 +53,7 @@ class UserService implements UserServiceInterface ->sum('sent'); if ($cardsSentToThisUserThisMonth + $amount > Administration::MAX_SEND_CARD_PER_MONTH) { - throw new \RuntimeException( + throw new \App\Exceptions\ThankCardException( __('messages.error.max_send_limit_template', [ 'max' => Administration::MAX_SEND_CARD_PER_MONTH, 'sent' => $cardsSentToThisUserThisMonth @@ -62,7 +62,7 @@ class UserService implements UserServiceInterface } if ($sender->card < $amount) { - throw new \RuntimeException(__('messages.error.not_enough_cards')); + throw new \App\Exceptions\ThankCardException(__('messages.error.not_enough_cards')); } DB::transaction(function () use ($sender, $receiverMsnv, $amount) { @@ -213,4 +213,19 @@ class UserService implements UserServiceInterface 'currentUserRankItem' => $currentUserRankItem ]; } + + public function updateProfile(User $user, ?\Illuminate\Http\UploadedFile $avatarFile, ?string $newPassword): void + { + if ($avatarFile) { + $path = $avatarFile->store('avatars', 'public'); + $user->avatar = 'storage/' . $path; + } + + if ($newPassword) { + $user->pass = md5($newPassword); + $user->first_login = config('constants.FIRST_LOGIN_FALSE'); + } + + $user->save(); + } } \ No newline at end of file