fix report 2

This commit is contained in:
2026-06-24 01:32:32 +03:30
parent 64a14701c7
commit 38dd8253f0
4 changed files with 190 additions and 24 deletions
@@ -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())
+12 -4
View File
@@ -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();
}
/**
+163 -19
View File
@@ -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
+14
View File
@@ -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_...) باشد.