From 808c272e0c6ed8e1feaf5161413386f519c98891 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Sat, 7 Nov 2026 12:24:19 +0330 Subject: [PATCH] fix: resolve copper unit kilogram display and asset valuation calculations --- app/Http/Controllers/Controller.php | 17 ++++-- app/Services/AssetSummaryService.php | 75 ++++++++++++++++++++------- app/Services/WalletBalanceService.php | 16 +++++- 3 files changed, 83 insertions(+), 25 deletions(-) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 1cc33d4..47d0049 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -503,19 +503,26 @@ class Controller extends BaseController /** واحد وزن معاملات فلز — در بورس مس پیش‌فرض کیلوگرم است */ public static function tradeWeightUnit(): string { - return self::resolveTradeWeightUnit( - app(ConfigService::class)->getString('unit') - ); + $value = app(ConfigService::class)->getString('unit'); + $resolved = self::resolveTradeWeightUnit($value); + + // در بورس مس واحد پایه همیشه کیلوگرم است + if ($resolved === 'گرم' || empty($value)) { + return 'کیلوگرم'; + } + + return $resolved; } public static function resolveTradeWeightUnit(?string $value): string { $unit = trim((string) $value); - if ($unit === 'گرم' || $unit === 'gram' || $unit === 'g') { - return 'گرم'; + if ($unit === 'کیلوگرم' || $unit === 'kg' || $unit === 'kilogram') { + return 'کیلوگرم'; } + // در بورس مس واحد مبنا کیلوگرم است return 'کیلوگرم'; } diff --git a/app/Services/AssetSummaryService.php b/app/Services/AssetSummaryService.php index e48bb89..df04dc7 100644 --- a/app/Services/AssetSummaryService.php +++ b/app/Services/AssetSummaryService.php @@ -148,11 +148,17 @@ class AssetSummaryService float $assetsRialValue, float $totalRialValue ): array { - $goldMetal = collect($metalTotals)->first(fn (array $row) => (int) ($row['metal_id'] ?? 0) === 1); - $goldWeight = (float) ($goldMetal['total_weight'] ?? 0); - $liveGoldPrice = $this->resolveLivePricePerUnit(1); - $goldRialValue = $goldWeight > 0 && $liveGoldPrice > 0 - ? round($goldWeight * $liveGoldPrice, 0) + $mainMetalId = $this->walletBalanceService->resolveMainWalletMetalId(); + $primaryMetal = collect($metalTotals)->first(fn (array $row) => (int) ($row['metal_id'] ?? 0) === (int) $mainMetalId) + ?? collect($metalTotals)->first(fn (array $row) => (int) ($row['metal_id'] ?? 0) === 3) + ?? collect($metalTotals)->first(fn (array $row) => (int) ($row['metal_id'] ?? 0) === 1) + ?? collect($metalTotals)->first(); + + $activeMetalId = (int) ($primaryMetal['metal_id'] ?? $mainMetalId); + $metalWeight = (float) ($primaryMetal['total_weight'] ?? 0); + $livePrice = $this->resolveLivePricePerUnit($activeMetalId); + $metalRialValue = $metalWeight > 0 && $livePrice > 0 + ? round($metalWeight * $livePrice, 0) : 0.0; $averageBuyPrice = null; @@ -161,7 +167,7 @@ class AssetSummaryService $unrealizedProfitPercent = null; $unrealizedProfitGold = null; - if ($goldWeight > 0) { + if ($metalWeight > 0) { $buyOrders = Order::query() ->where('customer_id', $customerId) ->where('direction', 1) @@ -174,14 +180,14 @@ class AssetSummaryService if ($totalBought > 0 && $weightedSum > 0) { $averageBuyPrice = round($weightedSum / $totalBought, 0); - $costBasisRial = round($averageBuyPrice * $goldWeight, 0); - $unrealizedProfitRial = round($goldRialValue - $costBasisRial, 0); + $costBasisRial = round($averageBuyPrice * $metalWeight, 0); + $unrealizedProfitRial = round($metalRialValue - $costBasisRial, 0); if ($costBasisRial > 0) { $unrealizedProfitPercent = round(($unrealizedProfitRial / $costBasisRial) * 100, 2); } - // سود طلایی: همان سود ریالی تبدیل‌شده به وزن طلا با قیمت زندهٔ امروز - if ($liveGoldPrice > 0) { - $unrealizedProfitGold = round($unrealizedProfitRial / $liveGoldPrice, 4); + // سود وزنی: همان سود ریالی تبدیل‌شده به وزن فلز با قیمت زندهٔ امروز + if ($livePrice > 0) { + $unrealizedProfitGold = round($unrealizedProfitRial / $livePrice, 4); } } } @@ -190,14 +196,17 @@ class AssetSummaryService 'total_rial_value' => round($totalRialValue, 0), 'cash_rial' => round($cashWallet, 0), 'metal_rial_value' => round($assetsRialValue, 0), - 'gold_weight' => round($goldWeight, 3), - 'gold_rial_value' => $goldRialValue, + 'gold_weight' => round($metalWeight, 3), + 'gold_rial_value' => $metalRialValue, + 'copper_weight' => round($metalWeight, 3), + 'copper_rial_value' => $metalRialValue, 'average_buy_price' => $averageBuyPrice, 'cost_basis_rial' => $costBasisRial, 'unrealized_profit_rial' => $unrealizedProfitRial, 'unrealized_profit_percent' => $unrealizedProfitPercent, 'unrealized_profit_gold' => $unrealizedProfitGold, - 'live_gold_price' => round($liveGoldPrice, 0), + 'live_gold_price' => round($livePrice, 0), + 'live_copper_price' => round($livePrice, 0), ]; } @@ -743,11 +752,9 @@ class AssetSummaryService return 0.0; } - if (count($catalogMetalIds) === 1) { - return (int) $catalogMetalIds[0] === (int) $metalId ? $mainWalletGrams : 0.0; - } + $mainMetalId = $this->walletBalanceService->resolveMainWalletMetalId(); - return (int) $metalId === 1 ? $mainWalletGrams : 0.0; + return (int) $metalId === (int) $mainMetalId ? $mainWalletGrams : 0.0; } /** @@ -797,8 +804,33 @@ class AssetSummaryService private function resolveLivePricePerUnit(int $metalId): float { + $prices = app(ProductDisplayPriceService::class); + $mainMetalId = $this->walletBalanceService->resolveMainWalletMetalId(); + + if ($metalId === 3 || $metalId === $mainMetalId) { + $copperProduct = Product::query() + ->where('active', 1) + ->where('metal_id', $metalId) + ->orderBy('id') + ->first(); + + if ($copperProduct) { + $base = (float) $prices->resolveOrderBasePrice($copperProduct); + if ($base > 0) { + return $base; + } + } + + $live = (float) $prices->resolveAppBasePrice(); + if ($live > 0) { + return $live; + } + + return (float) (Price::latest('id')->value('price') ?? 0); + } + if ($metalId === 1) { - $live = (int) app(ProductDisplayPriceService::class)->resolveAppBasePrice(); + $live = (int) $prices->resolveAppBasePrice(); if ($live > 0) { return (float) $live; } @@ -817,6 +849,11 @@ class AssetSummaryService return 0.0; } + $base = (float) $prices->resolveOrderBasePrice($product); + if ($base > 0) { + return $base; + } + $unitPrice = $this->productDisplayUnitPrice($product); $amount = (float) ($product->amount ?? 1); diff --git a/app/Services/WalletBalanceService.php b/app/Services/WalletBalanceService.php index 0665c20..b69cb96 100644 --- a/app/Services/WalletBalanceService.php +++ b/app/Services/WalletBalanceService.php @@ -317,10 +317,24 @@ class WalletBalanceService ->orderBy('id') ->first(); - return max(1, (int) ($product?->metal_id ?? 1)); + if ($product && (int) ($product->metal_id ?? 0) > 0) { + return (int) $product->metal_id; + } + } + + // در بورس مس، مس فلز اصلی پلتفرم است + $hasCopperProduct = Product::query() + ->where('active', 1) + ->where('metal_id', 3) + ->exists(); + if ($hasCopperProduct) { + return 3; } $metalIds = $this->catalogMetalIds(); + if (in_array(3, $metalIds, true)) { + return 3; + } return count($metalIds) === 1 ? (int) $metalIds[0] : 1; }