fix: resolve copper unit kilogram display and asset valuation calculations
This commit is contained in:
@@ -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 'کیلوگرم';
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user