From b4edb7390caee8889044bda6350dc0e53a73aa37 Mon Sep 17 00:00:00 2001 From: adonis Date: Thu, 9 Jul 2026 17:55:55 +0330 Subject: [PATCH] fix buy and sell information 3 --- .../FixMisplacedProductGoldCommand.php | 262 ++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 app/Console/Commands/FixMisplacedProductGoldCommand.php diff --git a/app/Console/Commands/FixMisplacedProductGoldCommand.php b/app/Console/Commands/FixMisplacedProductGoldCommand.php new file mode 100644 index 0000000..f823bfd --- /dev/null +++ b/app/Console/Commands/FixMisplacedProductGoldCommand.php @@ -0,0 +1,262 @@ +option('customer'); + $productId = (int) $this->option('product'); + $execute = (bool) $this->option('execute'); + + if ($customerId <= 0 || $productId <= 0) { + $this->error('پارامترهای --customer و --product الزامی هستند.'); + + return self::FAILURE; + } + + $customer = Customer::find($customerId); + if (!$customer) { + $this->error("مشتری {$customerId} یافت نشد."); + + return self::FAILURE; + } + + $product = Product::find($productId); + if (!$product) { + $this->error("محصول {$productId} یافت نشد."); + + return self::FAILURE; + } + + if ($configService->isMainWalletProduct($productId)) { + $this->error("محصول {$productId} به کیف اصلی متصل است؛ نیازی به انتقال نیست."); + + return self::FAILURE; + } + + $goldAmount = $this->resolveGoldAmount($customerId, $productId); + if ($goldAmount === null || $goldAmount <= 0) { + $this->error('مقدار طلا مشخص نشد. از --gold یا --order یا --transaction استفاده کنید.'); + + return self::FAILURE; + } + + $ownerType = (int) $customer->type; + $mainWallet = Wallet::query() + ->where('owner', $customerId) + ->where('owner_type', $ownerType) + ->whereNull('fund_id') + ->whereNull('product_id') + ->first(); + + if (!$mainWallet) { + $this->error('کیف اصلی مشتری یافت نشد.'); + + return self::FAILURE; + } + + $effectiveProductId = Controller::effectiveProductWalletId($productId); + $productWallet = Wallet::query() + ->where('owner', $customerId) + ->where('owner_type', $ownerType) + ->whereNull('fund_id') + ->where('product_id', $effectiveProductId) + ->first(); + + $productWalletGold = (float) ($productWallet?->gold ?? 0); + $mainWalletGold = (float) $mainWallet->gold; + + $this->info('--- پیش‌نمایش اصلاح موجودی ---'); + $this->line("مشتری: {$customerId} ({$customer->name})"); + $this->line("محصول: {$productId} ({$product->title})"); + $this->line('مقدار انتقال: ' . round($goldAmount, 5) . ' گرم'); + $this->line('کیف اصلی قبل: ' . round($mainWalletGold, 5) . ' گرم'); + $this->line('کیف محصول قبل: ' . round($productWalletGold, 5) . ' گرم'); + $this->line('کیف اصلی بعد: ' . round($mainWalletGold - $goldAmount, 5) . ' گرم'); + $this->line('کیف محصول بعد: ' . round($productWalletGold + $goldAmount, 5) . ' گرم'); + + if ($mainWalletGold < $goldAmount) { + $this->error('موجودی کیف اصلی کافی نیست.'); + + return self::FAILURE; + } + + if ($this->alreadyCorrected($customerId, $productId, $goldAmount)) { + $this->warn('به نظر می‌رسد این اصلاح قبلاً انجام شده است. برای اطمینان دوباره اجرا نمی‌شود.'); + + return self::SUCCESS; + } + + if (!$execute) { + $this->newLine(); + $this->warn('حالت پیش‌نمایش — برای اجرا فلگ --execute را اضافه کنید.'); + + return self::SUCCESS; + } + + DB::transaction(function () use ($customer, $customerId, $ownerType, $productId, $product, $goldAmount, $effectiveProductId) { + $note = 'اصلاح موجودی — انتقال ' . round($goldAmount, 5) . ' گرم از کیف اصلی به کیف «' . $product->title . '"'; + $orderId = (int) ($this->option('order') ?? 0); + if ($orderId > 0) { + $note .= " (سفارش {$orderId})"; + } + + $withdraw = Withdraw::create([ + 'user_id' => 0, + 'customer_id' => $customerId, + 'gold' => 0, + 'note' => $note, + 'sts' => 4, + ]); + + $mainWalletInterface = new WalletInterface($customerId, $ownerType); + new TransactionInterface($mainWalletInterface, [ + 'cash' => 0, + 'gold' => $goldAmount, + 'product_id' => $productId, + 'expire_at' => now(), + 'note' => $note, + 'withdraw_id' => $withdraw->id, + 'order_id' => $orderId > 0 ? $orderId : null, + 'active' => true, + 'title' => 'اصلاح موجودی — کسر از کیف اصلی', + ], 7, false, false); + + $productWalletInterface = new WalletInterface($customerId, $ownerType, null, $effectiveProductId); + new TransactionInterface($productWalletInterface, [ + 'cash' => 0, + 'gold' => $goldAmount, + 'product_id' => $productId, + 'expire_at' => now(), + 'note' => $note, + 'withdraw_id' => $withdraw->id, + 'order_id' => $orderId > 0 ? $orderId : null, + 'active' => true, + 'title' => 'اصلاح موجودی — واریز به کیف محصول', + ], 7, true, false); + + app(WalletBroadcastService::class)->broadcastForCustomer($customerId, $ownerType); + }); + + $this->newLine(); + $this->info('اصلاح با موفقیت انجام شد.'); + + return self::SUCCESS; + } + + private function resolveGoldAmount(int $customerId, int $productId): ?float + { + $explicitGold = $this->option('gold'); + if ($explicitGold !== null && $explicitGold !== '') { + return round((float) $explicitGold, 5); + } + + $transactionId = (int) ($this->option('transaction') ?? 0); + if ($transactionId > 0) { + $transaction = Transaction::query() + ->where('id', $transactionId) + ->where('customer_id', $customerId) + ->first(); + + if ($transaction && (float) $transaction->gold > 0) { + return round(abs((float) $transaction->gold), 5); + } + + $this->warn("تراکنش {$transactionId} یافت نشد یا مقدار طلا ندارد."); + } + + $orderId = (int) ($this->option('order') ?? 0); + if ($orderId > 0) { + $order = Order::query() + ->where('id', $orderId) + ->where('customer_id', $customerId) + ->first(); + + if ($order) { + $orderProductId = (int) ($order->product_id ?? $order->abshode_id ?? 0); + if ($orderProductId === $productId && (float) $order->amount > 0) { + return round((float) $order->amount, 5); + } + + $this->warn("سفارش {$orderId} به محصول {$productId} مرتبط نیست یا amount ندارد."); + } else { + $this->warn("سفارش {$orderId} یافت نشد."); + } + } + + return $this->detectFromMainWalletTransactions($customerId, $productId); + } + + private function detectFromMainWalletTransactions(int $customerId, int $productId): ?float + { + $ownerType = (int) (Customer::find($customerId)?->type ?? 2); + $mainWalletId = Wallet::query() + ->where('owner', $customerId) + ->where('owner_type', $ownerType) + ->whereNull('fund_id') + ->whereNull('product_id') + ->value('id'); + + if (!$mainWalletId) { + return null; + } + + $total = Transaction::query() + ->where('wallet', $mainWalletId) + ->where('customer_id', $customerId) + ->where('product_id', $productId) + ->where('type', 1) + ->where('gold', '>', 0) + ->sum('gold'); + + if ($total > 0) { + $this->line('مقدار از تراکنش‌های خرید روی کیف اصلی تشخیص داده شد: ' . round((float) $total, 5) . ' گرم'); + + return round((float) $total, 5); + } + + return null; + } + + private function alreadyCorrected(int $customerId, int $productId, float $goldAmount): bool + { + $orderId = (int) ($this->option('order') ?? 0); + $needle = $orderId > 0 ? "سفارش {$orderId}" : 'اصلاح موجودی'; + + $exists = Transaction::query() + ->where('customer_id', $customerId) + ->where('product_id', $productId) + ->where('gold', '>=', $goldAmount - 0.00001) + ->where('note', 'like', '%' . $needle . '%') + ->where('title', 'like', '%واریز به کیف محصول%') + ->exists(); + + return $exists; + } +}