From 95ee496df06ee06b2d691e991ed2accb5eaf8499 Mon Sep 17 00:00:00 2001 From: adonis Date: Wed, 10 Jun 2026 17:31:38 +0330 Subject: [PATCH] added merge wallet 2 --- .../Controllers/Admin/CustomerController.php | 39 +++++++++++ app/Http/Controllers/Controller.php | 22 ++++++ .../Customer/CustomerController.php | 12 +++- .../Customer/ProductController.php | 68 +++++++++++++++++-- .../Controllers/Customer/WalletController.php | 16 ++++- .../Single/SingleOrderController.php | 45 ++++++++---- 6 files changed, 180 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Admin/CustomerController.php b/app/Http/Controllers/Admin/CustomerController.php index 4b773fa..477182c 100644 --- a/app/Http/Controllers/Admin/CustomerController.php +++ b/app/Http/Controllers/Admin/CustomerController.php @@ -73,15 +73,54 @@ class CustomerController extends SuperController } public function funds(Request $request,$customer_id) { + $mainWalletProductIds = app(\App\Services\ConfigService::class)->mainWalletProductIds(); // فقط کیف محصول‌ها (نه کیف اصلی) — هر ردیف = موجودی واقعی یک محصول/فلز $query_table = Wallet::with(['product:id,title,metal_id,unit']) ->where('owner', $customer_id) ->whereNotNull('product_id'); + if ($mainWalletProductIds !== []) { + // کیف‌های قدیمیِ محصولات متصل به کیف اصلی نمایش داده نمی‌شوند + $query_table->whereNotIn('product_id', $mainWalletProductIds); + } TableEngine::create($query_table, $request) ->initSearch($this->search) ->select(['id', 'owner', 'cash', 'gold', 'fund_id', 'product_id', 'created_at', 'updated_at']) ->export($query_table); + + // محصولات متصل به کیف اصلی: یک ردیف نماینده با موجودی کیف اصلی + if ($mainWalletProductIds !== []) { + $representative = null; + foreach ($mainWalletProductIds as $pid) { + $representative = \App\Models\Product::select(['id', 'title', 'metal_id', 'unit'])->find($pid); + if ($representative) { + break; + } + } + + $mainWallet = Wallet::where('owner', $customer_id) + ->whereNull('fund_id') + ->whereNull('product_id') + ->first(); + + if ($representative && $mainWallet) { + $mainRow = [ + 'id' => $mainWallet->id, + 'owner' => (int) $customer_id, + 'cash' => 0, + 'gold' => (float) $mainWallet->gold, + 'fund_id' => null, + 'product_id' => (int) $representative->id, + 'created_at' => $mainWallet->created_at, + 'updated_at' => $mainWallet->updated_at, + 'product' => $representative, + 'is_main_wallet' => true, + ]; + $query_table['rows'] = collect($query_table['rows'] ?? [])->prepend($mainRow)->values(); + $query_table['query']['total'] = (int) ($query_table['query']['total'] ?? 0) + 1; + } + } + return response()->json($query_table); } public function archive($id){ diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 065883f..79a8b5c 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -280,6 +280,28 @@ class Controller extends BaseController return self::productSellTitle(self::metalTypeLabel()); } + /** + * آیا محصول به کیف اصلی متصل است؟ (setting: main_wallet_products) + * موجودی این محصولات = gold کیف اصلی؛ تراکنش‌هایشان روی کیف اصلی می‌نشیند. + */ + public static function isMainWalletProduct(?int $productId): bool + { + if (!$productId) { + return false; + } + + return app(ConfigService::class)->isMainWalletProduct((int) $productId); + } + + /** + * شناسه کیف مؤثر برای تراکنش محصول. + * محصولات متصل به کیف اصلی → null (کیف اصلی)؛ بقیه → کیف محصول خودشان. + */ + public static function effectiveProductWalletId(?int $productId): ?int + { + return self::isMainWalletProduct($productId) ? null : $productId; + } + /** واحد وزن معاملات فلز — از ستینگ unit؛ پیش‌فرض گرم */ public static function tradeWeightUnit(): string { diff --git a/app/Http/Controllers/Customer/CustomerController.php b/app/Http/Controllers/Customer/CustomerController.php index f2a05b5..4f8b3bd 100644 --- a/app/Http/Controllers/Customer/CustomerController.php +++ b/app/Http/Controllers/Customer/CustomerController.php @@ -51,10 +51,13 @@ class CustomerController extends Controller ->whereNull('fund_id') ->first() ?? new Wallet(); + // کیف‌های قدیمیِ محصولات متصل به کیف اصلی (main_wallet_products) در محاسبات نمی‌آیند؛ موجودی‌شان همان gold کیف اصلی است + $mainWalletProductIds = app(\App\Services\ConfigService::class)->mainWalletProductIds(); + $treasureGrams = 0; $wallet->wp = Wallet::with('product')->where('owner', $user->id)->get(); foreach ($wallet->wp as $row) { - if ($row->product_id != null) { + if ($row->product_id != null && !in_array((int) $row->product_id, $mainWalletProductIds, true)) { $treasureGrams += self::productLineWeightToGrams($row->product, $row->gold); } } @@ -80,6 +83,9 @@ class CustomerController extends Controller $count_product = 0; foreach ($user->wallets as $walletSingle) { if ($walletSingle->product_id) { + if (in_array((int) $walletSingle->product_id, $mainWalletProductIds, true)) { + continue; + } if ($walletSingle->product->metal_id == 1) { if (!($walletSingle->product->group_type == "سکه")) { @@ -128,6 +134,10 @@ class CustomerController extends Controller $user->pwallet = Wallet::with("product")->where('owner', $user->id) ->where('owner_type', $user->type) // Ensures the wallet's owner type matches the user's type ->whereNotNull('product_id') // Filters wallets that have a non-null product_id + ->when($mainWalletProductIds !== [], function ($q) use ($mainWalletProductIds) { + // کیف قدیمی محصولات متصل به کیف اصلی نمایش داده نمی‌شود + $q->whereNotIn('product_id', $mainWalletProductIds); + }) ->get() ?? new Wallet(); // If no wallet is found, assigns a new Wallet instance to the attribute $forbiddenWords = ['tahesab', 'token']; // کلمات ممنوعه diff --git a/app/Http/Controllers/Customer/ProductController.php b/app/Http/Controllers/Customer/ProductController.php index 1c30a02..42c695d 100644 --- a/app/Http/Controllers/Customer/ProductController.php +++ b/app/Http/Controllers/Customer/ProductController.php @@ -29,17 +29,48 @@ class ProductController extends SuperController public function pTable(Request $request) { $user = auth('customer')->user(); -// $products = Product::with(['wallet' => function ($query) use ($user) { -// $query->where('owner', $user->id); -// }])->get(); - $products = Product::whereHas('wallet', function ($query) use ($user) { - $query->where('owner', $user->id); + $mainWalletProductIds = app(\App\Services\ConfigService::class)->mainWalletProductIds(); + + $products = Product::where(function ($query) use ($user, $mainWalletProductIds) { + $query->whereHas('wallet', function ($q) use ($user) { + $q->where('owner', $user->id); + }); + if ($mainWalletProductIds !== []) { + $query->orWhereIn('id', $mainWalletProductIds); + } })->with(['wallet' => function ($query) use ($user) { $query->where('owner', $user->id); }, 'file'])->get(); + // محصولات متصل به کیف اصلی (main_wallet_products): فقط نمایندهٔ لیست با موجودی کیف اصلی + $representativeId = null; + $mainWalletGold = 0.0; + if ($mainWalletProductIds !== []) { + foreach ($mainWalletProductIds as $pid) { + if ($products->firstWhere('id', $pid)) { + $representativeId = (int) $pid; + break; + } + } + + if ($representativeId !== null) { + $mainWallet = Wallet::where('owner', $user->id) + ->whereNull('fund_id') + ->whereNull('product_id') + ->first(); + $mainWalletGold = (float) ($mainWallet->gold ?? 0); + } + + $products = $products->filter(function ($product) use ($mainWalletProductIds, $representativeId) { + if (in_array((int) $product->id, array_map('intval', $mainWalletProductIds), true)) { + return (int) $product->id === $representativeId; + } + return true; + })->values(); + } + // Prepare the response - $user['rows'] = $products->map(function ($product) { + $user['rows'] = $products->map(function ($product) use ($user, $representativeId, $mainWalletGold) { $product->unit = self::productQuantityUnit([ 'unit' => $product->unit ?? null, 'direct_price' => $product->direct_price ?? null, @@ -50,6 +81,14 @@ class ProductController extends SuperController $product->file->setAttribute('full_src', $product->file->src); } + if ($representativeId !== null && (int) $product->id === $representativeId) { + // کیف محصول فقط نقش هندل را دارد؛ موجودی واقعی از کیف اصلی است + $walletInterface = new WalletInterface($user->id, $user->type, null, $product->id); + $handleWallet = $walletInterface->wallet; + $handleWallet->gold = $mainWalletGold; + $product->setRelation('wallet', $handleWallet); + } + return $product; }); @@ -103,7 +142,22 @@ class ProductController extends SuperController } public function show($id){ $query = Product::/*with(['walletMy as wallet'])->*/findOrFail($id); - $query['wallet']= $query->walletMy; + $wallet = $query->walletMy; + + // محصول متصل به کیف اصلی: موجودی از کیف اصلی خوانده می‌شود + if (self::isMainWalletProduct((int) $id)) { + $mainWallet = Wallet::where('owner', auth('customer')->id()) + ->whereNull('fund_id') + ->whereNull('product_id') + ->first(); + if ($wallet) { + $wallet->gold = (float) ($mainWallet->gold ?? 0); + } else { + $wallet = $mainWallet; + } + } + + $query['wallet'] = $wallet; return response()->json($query); } diff --git a/app/Http/Controllers/Customer/WalletController.php b/app/Http/Controllers/Customer/WalletController.php index 30f74a6..2cd6cec 100644 --- a/app/Http/Controllers/Customer/WalletController.php +++ b/app/Http/Controllers/Customer/WalletController.php @@ -275,7 +275,19 @@ class WalletController extends Controller if (!$data['wallets'][$key]['wallet']['product']) { return response()->json(['message' => 'محصولی در ولت مورد نظر یافت نشد.'], 422); } - if ($data['wallets'][$key]['value'] > $data['wallets'][$key]['wallet']['gold']){ + + // محصول متصل به کیف اصلی (main_wallet_products): موجودی و تراکنش روی کیف اصلی است + $effectiveProductId = self::effectiveProductWalletId((int) $data['wallets'][$key]['wallet']['product_id']); + $availableGold = $data['wallets'][$key]['wallet']['gold']; + if ($effectiveProductId === null) { + $mainWallet = Wallet::where('owner', auth('customer')->id()) + ->whereNull('fund_id') + ->whereNull('product_id') + ->first(); + $availableGold = (float) ($mainWallet->gold ?? 0); + } + + if ($data['wallets'][$key]['value'] > $availableGold){ return response()->json([ 'message' => "شما به اندازه کافی از {$data['wallets'][$key]['wallet']['product']['title']} ندارید" ], 422); @@ -288,7 +300,7 @@ class WalletController extends Controller } - $data['wallets'][$key]['wallet_interface'] = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $data['wallets'][$key]['wallet']["product_id"]); + $data['wallets'][$key]['wallet_interface'] = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $effectiveProductId); } $data['withdraw'] = new Withdraw(); // Create a new instance of the Withdraw model $data['withdraw']->note = "برداشت فیزیکی"; // 50 for phisicals diff --git a/app/Http/Controllers/Single/SingleOrderController.php b/app/Http/Controllers/Single/SingleOrderController.php index 55c8ce6..a88f011 100644 --- a/app/Http/Controllers/Single/SingleOrderController.php +++ b/app/Http/Controllers/Single/SingleOrderController.php @@ -300,9 +300,8 @@ class SingleOrderController extends Controller 'order_id' => $order->id, 'title' => "برداشت وجه نقد" ], 12, false, false); - $wallet_interface_product = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $data["product_id"]); - $wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold); - $wallet_interface_product->wallet->save(); + $wallet_interface_product = $this->productWalletInterface((int) $data["product_id"]); + $this->normalizeProductWalletGold($wallet_interface_product); new TransactionInterface($wallet_interface_product, [ "gold" => $data['number'], "product_id" => $data["product_id"], @@ -346,9 +345,8 @@ class SingleOrderController extends Controller 'order_id' => $order->id, 'title' => self::mainMetalSellTitle(), ], 12, false, true); - $wallet_interface_product = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $data["product_id"]); - $wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold); - $wallet_interface_product->wallet->save(); + $wallet_interface_product = $this->productWalletInterface((int) $data["product_id"]); + $this->normalizeProductWalletGold($wallet_interface_product); new TransactionInterface($wallet_interface_product, [ "gold" => $data['number'], "product_id" => $data["product_id"], @@ -410,7 +408,7 @@ class SingleOrderController extends Controller $this->enforceProductOrderLimits($data, $grossTotal); $data['service_charge'] = isset($data['fee_free']) && $data['fee_free'] === true ? 0 : ($data['product']['percent_fee_sell'] * $data['amount']); $data['service_charge_price'] = $data['service_charge'] * $data['price_original']; - $wallet_interface_product = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $data["product_id"]); + $wallet_interface_product = $this->productWalletInterface((int) $data["product_id"]); if ($wallet_interface_product->wallet->gold < $data['number']) { throw new UnprocessableEntityHttpException('موجودی شما کمتر از میزان سفارش است'); @@ -419,8 +417,7 @@ class SingleOrderController extends Controller throw new UnprocessableEntityHttpException('فروش این محصول در این لحظه مقدور نمیباشد'); } $data['order'] = $order = Order::create($data); - $wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold); - $wallet_interface_product->wallet->save(); + $this->normalizeProductWalletGold($wallet_interface_product); new TransactionInterface($wallet_interface_product, [ "gold" => $data['number'], "product_id" => $data["product_id"], @@ -454,7 +451,7 @@ class SingleOrderController extends Controller $data['service_charge'] = isset($data['fee_free']) && $data['fee_free'] === true ? 0 : ($data['product']['percent_fee_sell'] * $data['amount']); $data['total_fee'] = 0; $data['service_charge_price'] = $data['service_charge'] * $data['price_original']; - $wallet_interface_product = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $data["product_id"]); + $wallet_interface_product = $this->productWalletInterface((int) $data["product_id"]); if ($wallet_interface_product->wallet->gold < $data['number']) { throw new UnprocessableEntityHttpException('موجودی شما کمتر از میزان سفارش است'); } @@ -471,8 +468,7 @@ class SingleOrderController extends Controller 'order_id' => $order->id, 'title' => self::mainMetalBuyTitle(), ], 12, true, false); - $wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold); - $wallet_interface_product->wallet->save(); + $this->normalizeProductWalletGold($wallet_interface_product); new TransactionInterface($wallet_interface_product, [ "gold" => $data['number'], "product_id" => $data["product_id"], @@ -484,6 +480,31 @@ class SingleOrderController extends Controller ], 1, false, false); } + /** + * کیف مؤثر محصول برای تراکنش سفارش. + * محصولات متصل به کیف اصلی (main_wallet_products) مستقیماً روی کیف اصلی می‌نشینند. + */ + private function productWalletInterface(int $productId): WalletInterface + { + return new WalletInterface( + auth('customer')->id(), + auth('customer')->user()->type, + null, + self::effectiveProductWalletId($productId) + ); + } + + /** رفتار قدیمیِ رُند کردن موجودی فقط برای کیف خود محصول؛ کیف اصلی هرگز رُند نمی‌شود */ + private function normalizeProductWalletGold(WalletInterface $walletInterface): void + { + if ($walletInterface->wallet->product_id === null) { + return; + } + + $walletInterface->wallet->gold = intval($walletInterface->wallet->gold); + $walletInterface->wallet->save(); + } + private function give_order_reward(&$data, $wallet, $wallet_interface) { $data['aCustomers'] = [];