diff --git a/app/Http/Controllers/Site/ReportController.php b/app/Http/Controllers/Site/ReportController.php index 5521032..ac4cd0b 100644 --- a/app/Http/Controllers/Site/ReportController.php +++ b/app/Http/Controllers/Site/ReportController.php @@ -89,59 +89,36 @@ class ReportController extends Controller protected function buildUpDownPrices(): array { - $feeSettings = Setting::whereIn('key', ['fee_single', 'buy_fee', 'sell_fee']) - ->pluck('value', 'key'); - $difference = (float) ($feeSettings->get('fee_single') ?? 0); - $diffBuy = (float) ($feeSettings->get('buy_fee') ?: $difference); - $diffSell = (float) ($feeSettings->get('sell_fee') ?: $difference); + $config = app(ConfigService::class); + $diffBuy = $config->displayBuySpreadRial(); + $diffSell = $config->displaySellSpreadRial(); - $upSetting = Setting::where('key', 'up_price')->first(); - $downSetting = Setting::where('key', 'down_price')->first(); + $extremes = $config->resolvedDailyBaseExtremes(); + $up = $extremes['up']; + $down = $extremes['down']; - if ($upSetting && $downSetting) { - $down = (float) ($downSetting->value ?: 0); - $up = (float) ($upSetting->value ?: 0); - - if ($down > 0 && $up > 0) { - return [ - 'sell' => $down - $diffSell, - 'buy' => $up + $diffBuy, - ]; - } + if ($up > 0 && $down > 0) { + return [ + 'sell' => max(0, (int) ceil($down - $diffSell)), + 'buy' => (int) ceil($up + $diffBuy), + ]; } - $today = Carbon::now()->format("Y-m-d"); - $prises = Price::where('date_at', $today)->get("price"); - - $minP = 0; - $maxP = 0; - - foreach ($prises as $p) { - if ($minP == 0 || $p->price < $minP) { - $minP = $p->price; - } - - if ($maxP == 0 || $p->price > $maxP) { - $maxP = $p->price; - } - } - if (count($prises) === 0) { - $config = app(ConfigService::class); - if (!$config->getBool('show_last_price', false)) { - return ['sell' => 0, 'buy' => 0]; - } - - $price = Price::orderBy('id', 'desc')->first(); - $priceValue = $price ? (float) $price->price : 0.0; - - if ($priceValue <= 0) { - return ['sell' => 0, 'buy' => 0]; - } - - return ['sell' => $priceValue - $diffSell, 'buy' => $priceValue + $diffBuy]; + if (!$config->getBool('show_last_price', false)) { + return ['sell' => 0, 'buy' => 0]; } - return ['sell' => $minP - $diffSell, 'buy' => $maxP + $diffBuy]; + $price = Price::orderByDesc('id')->first(); + $priceValue = $price ? (float) $price->price : 0.0; + + if ($priceValue <= 0) { + return ['sell' => 0, 'buy' => 0]; + } + + return [ + 'sell' => max(0, (int) ceil($priceValue - $diffSell)), + 'buy' => (int) ceil($priceValue + $diffBuy), + ]; } protected function appendUpPrices(array $payload): array diff --git a/app/Services/ConfigService.php b/app/Services/ConfigService.php index bf37cbd..22585fb 100644 --- a/app/Services/ConfigService.php +++ b/app/Services/ConfigService.php @@ -3,6 +3,8 @@ namespace App\Services; use App\Models\Cnt; +use App\Models\Price; +use App\Models\PriceCandle; use App\Models\Product; use App\Models\Setting; @@ -247,6 +249,10 @@ class ConfigService $currentUp = (float) ($upSetting->value ?: 0); $currentDown = (float) ($downSetting->value ?: 0); + if ($currentUp > 0 && $priceInt < (int) ($currentUp * 0.9)) { + return; + } + if ($currentUp <= 0 || $priceInt > $currentUp) { $this->UpdateConfig('up_price', $priceInt); } @@ -254,4 +260,78 @@ class ConfigService $this->UpdateConfig('down_price', $priceInt); } } + + /** + * بیشترین/کمترین قیمت پایه امروز — با اصلاح outlier در down_price. + * + * @return array{up: int, down: int} + */ + public function resolvedDailyBaseExtremes(): array + { + $up = $this->getInt('up_price', 0); + $down = $this->getInt('down_price', 0); + + $candle = PriceCandle::whereDate('date_at', now()->toDateString())->first(); + $candleHigh = $candle ? (int) round((float) $candle->high) : 0; + $candleLow = $candle ? (int) round((float) $candle->low) : 0; + + if ($up > 0 && $down > 0 && $down < (int) ($up * 0.9)) { + $correctedDown = $candleLow >= (int) ($up * 0.9) ? $candleLow : $up; + $down = $correctedDown; + $this->UpdateConfig('down_price', $correctedDown); + } + + if ($up <= 0 || $down <= 0) { + $fromTable = $this->filteredTodayMinMax(); + if ($up <= 0 && $fromTable['max'] > 0) { + $up = $fromTable['max']; + } + if ($down <= 0 && $fromTable['min'] > 0) { + $down = $fromTable['min']; + } + } + + if ($up <= 0 && $candleHigh > 0) { + $up = $candleHigh; + } + if ($down <= 0 && $candleLow > 0) { + $down = $candleLow; + } + + if ($up > 0 && $down > 0 && $down > $up) { + [$up, $down] = [$down, $up]; + } + + return ['up' => $up, 'down' => $down]; + } + + /** + * @return array{min: int, max: int} + */ + public function filteredTodayMinMax(): array + { + $prices = Price::query() + ->whereDate('date_at', now()->toDateString()) + ->pluck('price') + ->map(fn ($price) => (int) round((float) $price)) + ->filter(fn (int $price) => $price > 0) + ->values(); + + if ($prices->isEmpty()) { + return ['min' => 0, 'max' => 0]; + } + + $max = (int) $prices->max(); + $threshold = (int) ($max * 0.9); + $valid = $prices->filter(fn (int $price) => $price >= $threshold); + + if ($valid->isEmpty()) { + return ['min' => $max, 'max' => $max]; + } + + return [ + 'min' => (int) $valid->min(), + 'max' => $max, + ]; + } }