walletService = $walletService; } public function request(User $user, int $amount, BankCard $bankCard): WithdrawRequest { if ($bankCard->user_id !== $user->id) { throw ValidationException::withMessages(['bank_card_id' => 'کارت بانکی انتخاب‌شده معتبر نیست.']); } $balance = $this->walletService->forUser($user)->balance; $pendingAmount = WithdrawRequest::where('user_id', $user->id) ->where('status', WithdrawRequestStatusEnum::Pending->value) ->sum('amount'); if ($amount + $pendingAmount > $balance) { throw ValidationException::withMessages(['amount' => 'مجموع مبلغ درخواست‌های برداشت از موجودی کیف پول شما بیشتر است.']); } return WithdrawRequest::create([ 'amount' => $amount, 'status' => WithdrawRequestStatusEnum::Pending->value, 'user_id' => $user->id, 'bank_card_id' => $bankCard->id, ]); } public function approve(WithdrawRequest $withdrawRequest, User $admin): WithdrawRequest { return DB::transaction(function () use ($withdrawRequest, $admin) { $this->ensurePending($withdrawRequest); $this->walletService->withdraw( $withdrawRequest->user, $withdrawRequest->amount, WalletTransactionReasonEnum::Withdraw, null, $withdrawRequest ); $this->walletService->depositToWallet( $this->walletService->system(), $withdrawRequest->amount, WalletTransactionReasonEnum::Withdraw, null, $withdrawRequest ); $withdrawRequest->update([ 'status' => WithdrawRequestStatusEnum::Approved->value, 'reviewed_at' => now(), 'reviewed_by' => $admin->id, ]); return $withdrawRequest; }); } public function reject(WithdrawRequest $withdrawRequest, User $admin, ?string $note = null): WithdrawRequest { $this->ensurePending($withdrawRequest); $withdrawRequest->update([ 'status' => WithdrawRequestStatusEnum::Rejected->value, 'admin_note' => $note, 'reviewed_at' => now(), 'reviewed_by' => $admin->id, ]); return $withdrawRequest; } protected function ensurePending(WithdrawRequest $withdrawRequest): void { if ($withdrawRequest->status !== WithdrawRequestStatusEnum::Pending) { throw ValidationException::withMessages(['withdraw_request' => 'این درخواست قبلا بررسی شده است.']); } } }