fix some bug

This commit is contained in:
2026-07-01 20:59:24 +03:30
parent e3a883d224
commit a69316e0de
10 changed files with 226 additions and 14 deletions
+80
View File
@@ -3,6 +3,7 @@
namespace App\Services;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\Price;
use App\Models\Product;
use Illuminate\Support\Collection;
@@ -60,6 +61,13 @@ class AssetSummaryService
$mainWalletProductIds
);
$totalRialValue = $cashWallet + $assetsRialValue;
$portfolio = $this->buildPortfolioInsight(
$customerId,
$metalTotals,
$cashWallet,
$assetsRialValue,
$totalRialValue
);
return [
'meta' => [
@@ -78,6 +86,78 @@ class AssetSummaryService
'metal_totals' => $metalTotals,
'assets_rial_value' => round($assetsRialValue, 0),
'total_rial_value' => round($totalRialValue, 0),
'profit_loss' => $portfolio['unrealized_profit_rial'],
'portfolio' => $portfolio,
];
}
/**
* خلاصه دارایی برای داشبورد — ارزش کل، تفکیک نقد/فلز، سود/زیان تحقق‌نیافته طلا.
*
* @return array{
* total_rial_value: float,
* cash_rial: float,
* metal_rial_value: float,
* gold_weight: float,
* gold_rial_value: float,
* average_buy_price: float|null,
* cost_basis_rial: float|null,
* unrealized_profit_rial: float|null,
* unrealized_profit_percent: float|null,
* live_gold_price: float
* }
*/
private function buildPortfolioInsight(
int $customerId,
array $metalTotals,
float $cashWallet,
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)
: 0.0;
$averageBuyPrice = null;
$costBasisRial = null;
$unrealizedProfitRial = null;
$unrealizedProfitPercent = null;
if ($goldWeight > 0) {
$buyOrders = Order::query()
->where('customer_id', $customerId)
->where('direction', 1)
->where('sts', 2)
->where('amount', '>', 0)
->get(['amount', 'price']);
$totalBought = (float) $buyOrders->sum('amount');
$weightedSum = (float) $buyOrders->sum(fn (Order $order) => (float) $order->price * (float) $order->amount);
if ($totalBought > 0 && $weightedSum > 0) {
$averageBuyPrice = round($weightedSum / $totalBought, 0);
$costBasisRial = round($averageBuyPrice * $goldWeight, 0);
$unrealizedProfitRial = round($goldRialValue - $costBasisRial, 0);
if ($costBasisRial > 0) {
$unrealizedProfitPercent = round(($unrealizedProfitRial / $costBasisRial) * 100, 2);
}
}
}
return [
'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,
'average_buy_price' => $averageBuyPrice,
'cost_basis_rial' => $costBasisRial,
'unrealized_profit_rial' => $unrealizedProfitRial,
'unrealized_profit_percent' => $unrealizedProfitPercent,
'live_gold_price' => round($liveGoldPrice, 0),
];
}
+9
View File
@@ -139,6 +139,15 @@ class ConfigService
return (float) config('fee.service_charge_percentage', 0);
}
/**
* روشن: کارمزد از مقدار طلا (فروش = واریز ریالی گرد دقیق، خرید = دریافت کامل طلا).
* خاموش (پیش‌فرض): کارمزد از ریال در فروش و از طلا در خرید — رفتار قبلی.
*/
public function feeDeductFromGold(): bool
{
return $this->getBool('fee_deduct_from_gold', false);
}
/**
* sell / buy / price_last — یک منبع حقیقت برای lastPrice و buildFromDatabase.
*
+70
View File
@@ -242,12 +242,16 @@ class WalletBalanceService
public function enrichWalletTableRow(mixed &$row, array $catalogMetalIds, int $mainWalletMetalId): void
{
$metalMap = $this->walletLineMetalGoldMap($row, $catalogMetalIds, $mainWalletMetalId);
$meta = $this->buildWalletTableRowMeta($row, $mainWalletMetalId);
if (is_array($row)) {
$row['metal_gold'] = $metalMap;
foreach ($catalogMetalIds as $metalId) {
$row['metal_gold_' . $metalId] = $metalMap[(string) $metalId] ?? 0.0;
}
foreach ($meta as $key => $value) {
$row[$key] = $value;
}
return;
}
@@ -257,9 +261,60 @@ class WalletBalanceService
foreach ($catalogMetalIds as $metalId) {
$row->{'metal_gold_' . $metalId} = $metalMap[(string) $metalId] ?? 0.0;
}
foreach ($meta as $key => $value) {
$row->{$key} = $value;
}
}
}
/**
* @return array<string, mixed>
*/
private function buildWalletTableRowMeta(mixed $row, int $mainWalletMetalId): array
{
$fundId = $this->lineValue($row, 'fund_id');
$productId = $this->lineValue($row, 'product_id');
$product = $this->lineProduct($row);
$fund = $this->lineFund($row);
$cash = (float) ($this->lineValue($row, 'cash') ?? 0);
if ($fundId !== null) {
$kind = 'fund';
$kindLabel = 'قلک (صندوق)';
$fundTitle = trim((string) ($fund?->title ?? ''));
$subject = $fundTitle !== '' ? "قلک «{$fundTitle}»" : 'قلک بدون عنوان';
} elseif ($productId === null) {
$kind = 'main';
$kindLabel = 'کیف اصلی';
$subject = 'کیف اصلی — ریال و طلای آبشده';
} else {
$kind = 'product';
$kindLabel = 'کیف محصول';
$title = trim((string) ($product?->title ?? ''));
$subject = $title !== '' ? "محصول «{$title}»" : "محصول کد {$productId}";
}
$metalId = $this->resolveWalletLineMetalId($row, $mainWalletMetalId);
$goldGrams = $this->walletLineGoldGrams($row);
$goldToCash = $goldGrams > 0 ? (int) round($goldGrams * $this->livePricePerGram($metalId)) : 0;
return [
'wallet_kind' => $kind,
'wallet_kind_label' => $kindLabel,
'wallet_subject' => $subject,
'product_title' => $product?->title ?? null,
'product_group_type' => $product?->group_type ?? null,
'product_unit' => $product?->unit ?? null,
'product_amount' => $product?->amount ?? null,
'fund_title' => $fund?->title ?? null,
'wallet_metal_id' => $metalId,
'wallet_metal_label' => $this->balanceReportService->metalLabel($metalId),
'gold_to_cash' => $goldToCash,
'gold_grams' => round($goldGrams, 3),
'total_rial_value' => (int) round($cash + $goldToCash),
];
}
private function livePricePerGram(int $metalId): float
{
if ($metalId === 1) {
@@ -303,6 +358,21 @@ class WalletBalanceService
return null;
}
private function lineFund(mixed $line): ?object
{
if (is_object($line) && isset($line->fund)) {
return $line->fund;
}
if (is_array($line) && isset($line['fund'])) {
$fund = $line['fund'];
return is_object($fund) ? $fund : (object) $fund;
}
return null;
}
private function walletLineGoldGrams(mixed $line): float
{
$gold = (float) ($this->lineValue($line, 'gold') ?? 0);