select box
This commit is contained in:
@@ -146,6 +146,31 @@ class AdminController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete card allocation history record.
|
||||
*/
|
||||
public function destroyAddCard(Request $request, int $id)
|
||||
{
|
||||
try {
|
||||
$this->adminService->destroyAddCard($id);
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Xóa lịch sử cấp phát thẻ thành công.',
|
||||
]);
|
||||
}
|
||||
return redirect()->back()->with('success', 'Xóa lịch sử cấp phát thẻ thành công.');
|
||||
} catch (\Exception $e) {
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], 422);
|
||||
}
|
||||
return redirect()->back()->withErrors(['error' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all cards for active users.
|
||||
*/
|
||||
|
||||
@@ -116,8 +116,8 @@ class UserController extends Controller
|
||||
|
||||
$this->userService->updateProfile(
|
||||
$user,
|
||||
$request->file('avatar'),
|
||||
$request->filled('new_password') ? $request->input('new_password') : null
|
||||
$request->validated(),
|
||||
$request->file('avatar')
|
||||
);
|
||||
|
||||
return redirect()->route('user.edit')->with('success', 'Cập nhật hồ sơ thành công');
|
||||
|
||||
@@ -29,6 +29,8 @@ class UpdateUserRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$msnv = $this->route('msnv');
|
||||
|
||||
return [
|
||||
'card' => 'nullable|integer|min:0',
|
||||
'num_card' => 'nullable|integer|min:1',
|
||||
@@ -36,6 +38,12 @@ class UpdateUserRequest extends FormRequest
|
||||
'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'),
|
||||
|
||||
// Editable basic info
|
||||
'name' => 'sometimes|required|string|max:255',
|
||||
'mail' => 'sometimes|required|email|unique:user,mail,' . $msnv . ',msnv',
|
||||
'departments' => 'sometimes|required|string|in:' . implode(',', config('constants.DEPARTMENTS')),
|
||||
'avatar' => 'nullable|image|max:2048',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,35 @@ class UpdateProfileRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'avatar' => 'nullable|image|max:2048', // 2MB max
|
||||
'new_password' => 'nullable|min:6|confirmed',
|
||||
'name' => 'required|string|max:255',
|
||||
'avatar' => 'nullable|image|max:2048', // 2MB max
|
||||
'current_password' => [
|
||||
'nullable',
|
||||
'required_with:new_password',
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($value && md5($value) !== auth()->user()->pass) {
|
||||
$fail('Mật khẩu hiện tại không chính xác.');
|
||||
}
|
||||
},
|
||||
],
|
||||
'new_password' => 'nullable|min:6|confirmed|different:current_password',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error messages for the defined validation rules.
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Họ và tên không được để trống.',
|
||||
'name.string' => 'Họ và tên phải là chuỗi ký tự.',
|
||||
'name.max' => 'Họ và tên không được vượt quá 255 ký tự.',
|
||||
'avatar.image' => 'Ảnh đại diện phải là tệp ảnh.',
|
||||
'avatar.max' => 'Ảnh đại diện không được vượt quá 2MB.',
|
||||
'new_password.min' => 'Mật khẩu mới phải có ít nhất 6 ký tự.',
|
||||
'new_password.confirmed' => 'Mật khẩu xác nhận không trùng khớp.',
|
||||
'new_password.different' => 'Mật khẩu mới phải khác mật khẩu hiện tại.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ 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,
|
||||
@@ -136,6 +139,19 @@ class AdminService implements AdminServiceInterface
|
||||
: 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']);
|
||||
@@ -147,12 +163,21 @@ class AdminService implements AdminServiceInterface
|
||||
|
||||
if ($newCard > $oldCard) {
|
||||
$diff = $newCard - $oldCard;
|
||||
AddCard::create([
|
||||
'buyer' => $user->msnv,
|
||||
'num_card' => $diff,
|
||||
'seller' => Auth::user()->msnv,
|
||||
'date' => Carbon::today(),
|
||||
]);
|
||||
$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;
|
||||
@@ -173,14 +198,16 @@ class AdminService implements AdminServiceInterface
|
||||
|
||||
public function resetAllCards(): void
|
||||
{
|
||||
User::where('status', config('constants.STATUS_ACTIVE'))->update(['card' => 0]);
|
||||
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');
|
||||
|
||||
@@ -195,15 +222,25 @@ class AdminService implements AdminServiceInterface
|
||||
|
||||
$user = User::where('msnv', $addCard->buyer)->firstOrFail();
|
||||
|
||||
DB::transaction(function () use ($addCard, $user, $data) {
|
||||
$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;
|
||||
|
||||
if ($user->card + $diff < 0) {
|
||||
$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();
|
||||
|
||||
@@ -214,6 +251,43 @@ class AdminService implements AdminServiceInterface
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
@@ -27,6 +27,8 @@ interface AdminServiceInterface
|
||||
|
||||
public function updateAddCard(int $id, array $data): void;
|
||||
|
||||
public function destroyAddCard(int $id): void;
|
||||
|
||||
public function getUserByMsnv(string $msnv): \App\Models\User;
|
||||
|
||||
public function getAddCardsHistory(string $buyerMsnv, ?string $selectedMonth = null): \Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
@@ -19,5 +19,5 @@ interface UserServiceInterface
|
||||
|
||||
public function getRankingList(string $type, string $selectedMonth, User $currentUser): array;
|
||||
|
||||
public function updateProfile(User $user, ?\Illuminate\Http\UploadedFile $avatarFile, ?string $newPassword): void;
|
||||
public function updateProfile(User $user, array $data, ?\Illuminate\Http\UploadedFile $avatarFile = null): void;
|
||||
}
|
||||
@@ -214,15 +214,19 @@ class UserService implements UserServiceInterface
|
||||
];
|
||||
}
|
||||
|
||||
public function updateProfile(User $user, ?\Illuminate\Http\UploadedFile $avatarFile, ?string $newPassword): void
|
||||
public function updateProfile(User $user, array $data, ?\Illuminate\Http\UploadedFile $avatarFile = null): void
|
||||
{
|
||||
if (isset($data['name'])) {
|
||||
$user->name = $data['name'];
|
||||
}
|
||||
|
||||
if ($avatarFile) {
|
||||
$path = $avatarFile->store('avatars', 'public');
|
||||
$user->avatar = 'storage/' . $path;
|
||||
}
|
||||
|
||||
if ($newPassword) {
|
||||
$user->pass = md5($newPassword);
|
||||
if (!empty($data['new_password'])) {
|
||||
$user->pass = md5($data['new_password']);
|
||||
$user->first_login = config('constants.FIRST_LOGIN_FALSE');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user