diff --git a/app/Http/Controllers/Admin/WalletController.php b/app/Http/Controllers/Admin/WalletController.php index dbea549..15384e7 100644 --- a/app/Http/Controllers/Admin/WalletController.php +++ b/app/Http/Controllers/Admin/WalletController.php @@ -806,11 +806,12 @@ class WalletController extends Controller public function adjustPhysicalWithdraw(Request $request, $id, AssetSummaryService $assetSummaryService) { $payload = $request->validate([ - 'transaction_id' => 'required|integer|exists:transactions,id', - 'direction' => 'required|in:increase,decrease', + 'items' => 'required|array|min:1', + 'items.*.transaction_id' => 'required|integer|exists:transactions,id', + 'items.*.value' => 'required|numeric|min:0.0001', ]); - $withdraw = Withdraw::with(['Transaction.product'])->findOrFail($id); + $withdraw = Withdraw::with(['Transaction.product', 'customer'])->findOrFail($id); if (!Withdraw::isPhysicalWithdrawNote($withdraw->note)) { return response()->json(['message' => 'این سند برداشت فیزیکی نیست'], 422); } @@ -818,70 +819,151 @@ class WalletController extends Controller return response()->json(['message' => 'تغییر مقدار فقط در وضعیت «در انتظار ارسال» مجاز است'], 422); } - $transaction = Transaction::with('product')->findOrFail($payload['transaction_id']); - if ((int) $transaction->withdraw_id !== (int) $withdraw->id) { - return response()->json(['message' => 'تراکنش به این سند تعلق ندارد'], 422); - } - - $product = $transaction->product; - if (!$product) { - return response()->json(['message' => 'محصول تراکنش یافت نشد'], 422); - } - - $step = 1.0; - $currentUnits = abs((float) $transaction->gold); - $direction = $payload['direction']; - - if ($direction === 'decrease' && $currentUnits <= $step) { - return response()->json(['message' => 'حداقل مقدار قابل برداشت یک واحد است'], 422); - } - $customer = Customer::findOrFail($withdraw->customer_id); - $effectiveProductId = $assetSummaryService->effectiveProductWalletIdForCustomer( - (int) $customer->id, - (int) $customer->type, - (int) $product->id - ); - $walletInterface = new WalletInterface( - (int) $customer->id, - (int) $customer->type, - null, - $effectiveProductId - ); - $wallet = $walletInterface->wallet; - if (!$wallet) { - return response()->json(['message' => 'کیف پول مشتری یافت نشد'], 422); - } + $transactionsById = $withdraw->Transaction->keyBy('id'); - if ($direction === 'increase') { - $available = $assetSummaryService->productDisplayQuantity( - (int) $customer->id, - (int) $customer->type, - (int) $product->id - ); - if ($available < $step) { - return response()->json(['message' => "موجودی {$product->title} کافی نیست"], 422); + DB::transaction(function () use ( + $payload, + $withdraw, + $customer, + $transactionsById, + $assetSummaryService + ) { + foreach ($payload['items'] as $item) { + $transaction = $transactionsById->get((int) $item['transaction_id']); + if (!$transaction) { + throw new UnprocessableEntityHttpException('تراکنش به این سند تعلق ندارد'); + } + + $product = $transaction->product; + if (!$product) { + throw new UnprocessableEntityHttpException('محصول تراکنش یافت نشد'); + } + + $newValue = round((float) $item['value'], 6); + $currentUnits = round(abs((float) $transaction->gold), 6); + if (abs($newValue - $currentUnits) < 0.000001) { + continue; + } + + $tradeByQuantity = (bool) ($product->trade_by_quantity ?? false); + $minValue = $tradeByQuantity ? 1.0 : 0.001; + + if ($newValue < $minValue) { + throw new UnprocessableEntityHttpException( + "حداقل مقدار برای {$product->title} برابر {$minValue} است" + ); + } + + if ($tradeByQuantity && abs($newValue - round($newValue)) > 0.000001) { + throw new UnprocessableEntityHttpException( + "مقدار {$product->title} باید عدد صحیح باشد" + ); + } + + $delta = round($newValue - $currentUnits, 6); + $effectiveProductId = $assetSummaryService->effectiveProductWalletIdForCustomer( + (int) $customer->id, + (int) $customer->type, + (int) $product->id + ); + $walletInterface = new WalletInterface( + (int) $customer->id, + (int) $customer->type, + null, + $effectiveProductId + ); + $wallet = $walletInterface->wallet; + if (!$wallet) { + throw new UnprocessableEntityHttpException('کیف پول مشتری یافت نشد'); + } + + if ($delta > 0) { + $available = $assetSummaryService->productDisplayQuantity( + (int) $customer->id, + (int) $customer->type, + (int) $product->id + ); + if ($delta > $available + 0.000001) { + throw new UnprocessableEntityHttpException( + "موجودی {$product->title} کافی نیست. حداکثر قابل افزودن: {$available}" + ); + } + $wallet->gold -= $delta; + } else { + $wallet->gold += abs($delta); + } + + $transaction->gold = -$newValue; + $transaction->number = (float) $product->amount * $newValue; + $transaction->balance_gold = $wallet->gold; + $wallet->save(); + $transaction->save(); + $walletInterface->set_hash(); } - - $wallet->gold -= $step; - $transaction->gold = -($currentUnits + $step); - $transaction->number = (float) $transaction->number + ((float) $product->amount * $step); - } else { - $wallet->gold += $step; - $transaction->gold = -($currentUnits - $step); - $transaction->number = max(0, (float) $transaction->number - ((float) $product->amount * $step)); - } - - $transaction->balance_gold = $wallet->gold; - $wallet->save(); - $transaction->save(); - $walletInterface->set_hash(); + }); $this->broadcastCustomerWalletAssets($customer); return response()->json([ - 'message' => 'مقدار برداشت به‌روزرسانی شد', - 'transaction' => $transaction->fresh('product'), + 'message' => 'مقادیر برداشت به‌روزرسانی شد', + 'withdraw' => $withdraw->fresh(['Transaction.product', 'customer']), + ]); + } + + public function physicalWithdrawAdjustInfo($id, AssetSummaryService $assetSummaryService) + { + $withdraw = Withdraw::with(['Transaction.product', 'customer'])->findOrFail($id); + if (!Withdraw::isPhysicalWithdrawNote($withdraw->note)) { + return response()->json(['message' => 'این سند برداشت فیزیکی نیست'], 422); + } + if ((int) $withdraw->sts !== 50) { + return response()->json(['message' => 'تغییر مقدار فقط در وضعیت «در انتظار ارسال» مجاز است'], 422); + } + + $customer = $withdraw->customer; + if (!$customer) { + return response()->json(['message' => 'مشتری یافت نشد'], 422); + } + + $lines = $withdraw->Transaction->map(function (Transaction $transaction) use ( + $customer, + $assetSummaryService + ) { + $product = $transaction->product; + $current = round(abs((float) $transaction->gold), 6); + $availableAdd = $product + ? $assetSummaryService->productDisplayQuantity( + (int) $customer->id, + (int) $customer->type, + (int) $product->id + ) + : 0.0; + $tradeByQuantity = (bool) ($product->trade_by_quantity ?? false); + + return [ + 'transaction_id' => (int) $transaction->id, + 'title' => trim((string) $transaction->title) ?: ($product->title ?? 'محصول'), + 'current_value' => $current, + 'available_add' => round((float) $availableAdd, 6), + 'max_value' => round($current + (float) $availableAdd, 6), + 'min_value' => $tradeByQuantity ? 1 : 0.001, + 'allows_decimal' => !$tradeByQuantity, + 'unit' => $product + ? self::productQuantityUnit([ + 'unit' => $product->unit ?? null, + 'direct_price' => $product->direct_price ?? null, + 'group_type' => $product->group_type ?? null, + ]) + : 'گرم', + ]; + })->values(); + + return response()->json([ + 'withdraw_id' => (int) $withdraw->id, + 'customer_name' => (string) ($customer->name ?? ''), + 'customer_mobile' => (string) ($customer->mobile ?? ''), + 'lines' => $lines, ]); } diff --git a/routes/admin.php b/routes/admin.php index df64414..73f0bd2 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -125,6 +125,7 @@ Route::middleware('auth:user')->group(function (){ Route::post('/wallet/withdraw_physical/table',[WalletController::class,'indexPhysicalWithdraw']); Route::get('/wallet/withdraw_physical/options/{customerId}',[WalletController::class,'physicalWithdrawOptions']); Route::post('/wallet/withdraw_physical',[WalletController::class,'createPhysicalWithdraw']); + Route::get('/wallet/withdraw_physical/{id}/adjust-info',[WalletController::class,'physicalWithdrawAdjustInfo']); Route::post('/wallet/withdraw_physical/{id}/adjust',[WalletController::class,'adjustPhysicalWithdraw']); //---------------order