From 38dd8253f07b20b81a8c192752a0b8f0bf5cda86 Mon Sep 17 00:00:00 2001 From: mohammad sedighi Date: Wed, 24 Jun 2026 01:32:32 +0330 Subject: [PATCH] fix report 2 --- .../Controllers/Admin/WalletController.php | 2 +- app/Http/Controllers/Controller.php | 16 +- app/Services/BalanceReportService.php | 182 ++++++++++++++++-- app/Services/ConfigService.php | 14 ++ 4 files changed, 190 insertions(+), 24 deletions(-) diff --git a/app/Http/Controllers/Admin/WalletController.php b/app/Http/Controllers/Admin/WalletController.php index 8b97fac..c0d28db 100644 --- a/app/Http/Controllers/Admin/WalletController.php +++ b/app/Http/Controllers/Admin/WalletController.php @@ -385,7 +385,7 @@ class WalletController extends Controller $records = Transaction::with([ 'customer', - 'wallet.product:id,metal_id', + 'wallet.product:id,title,metal_id', 'product:id,title,metal_id,group_type,unit,amount,trade_by_quantity,direct_price', ])->whereNull('fund_id'); TableEngine::create($records, $request->all()) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 125ff2f..44f73b8 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -253,6 +253,14 @@ class Controller extends BaseController return self::metalTypeLabel(); } + /** عنوان محصول(ات) کیف اصلی از `main_wallet_products` */ + public static function mainWalletProductLabel(): string + { + $labels = app(ConfigService::class)->mainWalletProductLabels(); + + return $labels !== '' ? $labels : self::mainWalletMetalLabel(); + } + /** برچسب معاملات آبشده: مقدار setting یا «آبشده» */ public static function meltedGoldLabel(): string { @@ -328,22 +336,22 @@ class Controller extends BaseController public static function mainMetalBuyTitle(): string { - return self::productBuyTitle(self::mainWalletMetalLabel()); + return self::productBuyTitle(self::mainWalletProductLabel()); } public static function mainMetalSellTitle(): string { - return self::productSellTitle(self::mainWalletMetalLabel()); + return self::productSellTitle(self::mainWalletProductLabel()); } public static function mainMetalDepositTitle(): string { - return 'واریز ' . self::mainWalletMetalLabel(); + return 'واریز ' . self::mainWalletProductLabel(); } public static function mainMetalWithdrawTitle(): string { - return 'برداشت ' . self::mainWalletMetalLabel(); + return 'برداشت ' . self::mainWalletProductLabel(); } /** diff --git a/app/Services/BalanceReportService.php b/app/Services/BalanceReportService.php index 4a79a17..7495338 100644 --- a/app/Services/BalanceReportService.php +++ b/app/Services/BalanceReportService.php @@ -280,23 +280,160 @@ class BalanceReportService public function resolveTransactionDisplayTypeStr(mixed $transaction, ?int $metalId = null): ?string { - $type = (int) ($this->lineValue($transaction, 'type') ?? 0); - if (!in_array($type, [1, 2, 7, 10], true)) { + $type = $this->resolveTransactionType($transaction); + if (in_array($type, [3, 4, 8, 9], true)) { return null; } - $metalId ??= $this->resolveTransactionMetalId($transaction); - $label = $this->metalLabel($metalId); + $currentLabel = trim((string) ($this->lineValue($transaction, 'type_str') ?? '')); + $prefix = $this->resolveTransactionActionPrefix($transaction); + $productLabel = $this->resolveTransactionProductLabel($transaction); - return match ($type) { - 1 => 'خرید ' . $label, - 2 => 'فروش ' . $label, - 7 => 'واریز ' . $label, - 10 => 'برداشت ' . $label, + if ($prefix !== null && $productLabel !== null) { + return trim($prefix . ' ' . $productLabel); + } + + if ($prefix !== null) { + $metalId ??= $this->resolveTransactionMetalId($transaction); + + return trim($prefix . ' ' . $this->metalLabel($metalId)); + } + + if ($currentLabel === 'تعریف نشده' || $currentLabel === '') { + return $this->resolveFallbackMetalTransactionLabel($transaction, $metalId); + } + + if ($this->shouldReplaceGenericTransactionLabel($currentLabel) && $productLabel !== null) { + $fallbackPrefix = $this->resolveTransactionActionPrefix($transaction) + ?? $this->inferActionPrefixFromLabel($currentLabel) + ?? $this->inferActionPrefixFromGold($transaction); + + if ($fallbackPrefix !== null) { + return trim($fallbackPrefix . ' ' . $productLabel); + } + } + + return null; + } + + private function resolveFallbackMetalTransactionLabel(mixed $transaction, ?int $metalId = null): ?string + { + $gold = (float) ($this->lineValue($transaction, 'gold') ?? 0); + if (abs($gold) < 0.0000001) { + return null; + } + + $prefix = $this->resolveTransactionActionPrefix($transaction) + ?? $this->inferActionPrefixFromGold($transaction); + if ($prefix === null) { + return null; + } + + $productLabel = $this->resolveTransactionProductLabel($transaction); + if ($productLabel !== null) { + return trim($prefix . ' ' . $productLabel); + } + + $metalId ??= $this->resolveTransactionMetalId($transaction); + + return trim($prefix . ' ' . $this->metalLabel($metalId)); + } + + private function resolveTransactionType(mixed $transaction): int + { + $type = $this->lineValue($transaction, 'type'); + if ($type !== null && $type !== '' && is_numeric($type)) { + return (int) $type; + } + + return 0; + } + + private function resolveTransactionActionPrefix(mixed $transaction): ?string + { + $type = $this->resolveTransactionType($transaction); + $gold = (float) ($this->lineValue($transaction, 'gold') ?? 0); + + return match (true) { + $type === 1 => 'خرید', + $type === 2 => 'فروش', + $type === 51 => 'اصلاح', + in_array($type, [6, 10], true) => 'برداشت', + $type === 5 => 'واریز', + $type === 7 => $gold >= 0 ? 'واریز' : 'برداشت', + $type === 12 => 'برداشت وجه', + abs($gold) > 0 => $gold > 0 ? 'واریز' : 'برداشت', default => null, }; } + private function inferActionPrefixFromGold(mixed $transaction): ?string + { + $gold = (float) ($this->lineValue($transaction, 'gold') ?? 0); + if (abs($gold) < 0.0000001) { + return null; + } + + return $gold > 0 ? 'واریز' : 'برداشت'; + } + + private function inferActionPrefixFromLabel(string $label): ?string + { + if (preg_match('/^خرید/u', $label)) { + return 'خرید'; + } + if (preg_match('/^فروش/u', $label)) { + return 'فروش'; + } + if (preg_match('/^برداشت/u', $label)) { + return 'برداشت'; + } + if (preg_match('/^(واریز|موجودی)/u', $label)) { + return 'واریز'; + } + + return null; + } + + private function shouldReplaceGenericTransactionLabel(string $label): bool + { + if ($label === 'تعریف نشده') { + return true; + } + + $generic = [ + 'واریز', + 'برداشت', + 'واریز طلایی', + 'برداشت طلایی', + 'خرید طلا', + 'فروش طلا', + ]; + + return in_array($label, $generic, true); + } + + public function resolveTransactionProductLabel(mixed $transaction): ?string + { + $product = $this->transactionProduct($transaction); + if ($product !== null && !empty($product->title)) { + return trim((string) $product->title); + } + + $walletProduct = $this->transactionWalletProduct($transaction); + if ($walletProduct !== null && !empty($walletProduct->title)) { + return trim((string) $walletProduct->title); + } + + if ($this->isMainWalletMetalTransaction($transaction)) { + $labels = $this->configService->mainWalletProductLabels(); + + return $labels !== '' ? $labels : null; + } + + return null; + } + public function transactionGoldGrams(mixed $transaction): float { $gold = (float) ($this->lineValue($transaction, 'gold') ?? 0); @@ -354,6 +491,11 @@ class BalanceReportService $metalId = $this->resolveTransactionMetalId($row); $metalLabel = $this->metalLabel($metalId); $displayType = $this->resolveTransactionDisplayTypeStr($row, $metalId); + $currentTypeStr = trim((string) ($this->lineValue($row, 'type_str') ?? '')); + + if ($displayType === null && ($currentTypeStr === 'تعریف نشده' || $currentTypeStr === '')) { + $displayType = $this->resolveFallbackMetalTransactionLabel($row, $metalId); + } if (is_array($row)) { $row['metal_gold'] = $metalMap; @@ -419,25 +561,27 @@ class BalanceReportService private function isMainWalletMetalTransaction(mixed $transaction): bool { - $type = (int) ($this->lineValue($transaction, 'type') ?? 0); - if (!in_array($type, [1, 2, 7, 10], true)) { - return false; - } - $wallet = $this->lineValue($transaction, 'wallet'); if ($wallet === null) { return true; } if (is_object($wallet)) { - return $wallet->product_id === null && $wallet->fund_id === null; + if ($wallet->product_id !== null || $wallet->fund_id !== null) { + return false; + } + } elseif (is_array($wallet)) { + if (($wallet['product_id'] ?? null) !== null || ($wallet['fund_id'] ?? null) !== null) { + return false; + } + } else { + return true; } - if (is_array($wallet)) { - return ($wallet['product_id'] ?? null) === null && ($wallet['fund_id'] ?? null) === null; - } + $type = $this->resolveTransactionType($transaction); + $gold = (float) ($this->lineValue($transaction, 'gold') ?? 0); - return true; + return in_array($type, [1, 2, 5, 6, 7, 10, 51], true) || abs($gold) > 0; } public function resolveOrderMetalId(mixed $order): int diff --git a/app/Services/ConfigService.php b/app/Services/ConfigService.php index 4be95a9..c060f63 100644 --- a/app/Services/ConfigService.php +++ b/app/Services/ConfigService.php @@ -244,6 +244,20 @@ class ConfigService return $metalId > 0 ? $metalId : 1; } + /** عنوان محصول(ات) متصل به کیف اصلی — ترتیب همان main_wallet_products */ + public function mainWalletProductLabels(): string + { + $titles = []; + foreach ($this->mainWalletProductIds() as $productId) { + $title = Product::query()->whereKey($productId)->value('title'); + if ($title !== null && trim((string) $title) !== '') { + $titles[] = trim((string) $title); + } + } + + return implode(' و ', $titles); + } + /** * شناسه محصول آبشده: اول settings، بعد const. * مقدار settings می‌تواند id عددی (مثل 13) یا reading_method (مثل estjt_...) باشد.