This commit is contained in:
2026-06-14 21:09:43 +03:30
parent 6f86e8242c
commit b84b2df01a
9 changed files with 287 additions and 66 deletions
+4 -2
View File
@@ -29,8 +29,10 @@ class LivePriceTickService
| (قبل از sync محصولات تا آبشدهٔ «قیمت اپ» تازه باشد)
*/
$request = Request::create('/api/price/last', 'GET', ['force_refresh' => '1']);
$response = app(ReportController::class)->lastPrice($request);
$payload = json_decode($response->getContent(), true);
$result = app(ReportController::class)->lastPrice($request);
$payload = is_array($result)
? $result
: (json_decode($result->getContent(), true) ?: []);
if (! is_array($payload)) {
$payload = [];
}
+80 -8
View File
@@ -8,13 +8,16 @@ use Carbon\Carbon;
class PriceSnapshotService
{
/** حداقل قیمت معتبر آبشده (ریال) — زیر این در نمودار نمایش داده نمی‌شود */
public const MIN_VALID_CHART_PRICE_RIAL = 30_000_000;
/** هر تیک کران — ذخیره در prices برای نمودار (هرگز صفر ثبت نمی‌شود) */
public function recordTick(array $payload): void
{
$priceValue = (int) ($payload['price'] ?? 0);
if ($priceValue <= 30_000_000) {
if ($priceValue <= self::MIN_VALID_CHART_PRICE_RIAL) {
$last = Price::orderByDesc('id')->first();
if (! $last || (int) $last->price <= 30_000_000) {
if (! $last || (int) $last->price <= self::MIN_VALID_CHART_PRICE_RIAL) {
return;
}
$priceValue = (int) $last->price;
@@ -119,11 +122,7 @@ class PriceSnapshotService
->orderBy('created_at')
->get(['price', 'created_at']);
$dailyPoints = $daily->map(function (Price $row) {
$ts = ($row->created_at ?? now())->timestamp * 1000;
return ['timestamp' => $ts, 'value' => (int) $row->price];
})->values()->all();
$dailyPoints = $this->mapValidPriceRows($daily);
$weekRows = Price::query()
->where('created_at', '>=', now()->subDays(7))
@@ -153,11 +152,16 @@ class PriceSnapshotService
$lastBucket = null;
foreach ($rows as $row) {
$price = (int) $row->price;
if ($price <= self::MIN_VALID_CHART_PRICE_RIAL) {
continue;
}
$ts = $row->created_at?->timestamp ?? 0;
$bucket = (int) floor($ts / $bucketSeconds);
$point = [
'timestamp' => $ts * 1000,
'value' => (int) $row->price,
'value' => $price,
];
if ($bucket !== $lastBucket) {
@@ -170,4 +174,72 @@ class PriceSnapshotService
return $points;
}
/** @param \Illuminate\Support\Collection<int, Price> $rows */
private function mapValidPriceRows($rows): array
{
$points = [];
foreach ($rows as $row) {
$price = (int) $row->price;
if ($price <= self::MIN_VALID_CHART_PRICE_RIAL) {
continue;
}
$points[] = [
'timestamp' => ($row->created_at ?? now())->timestamp * 1000,
'value' => $price,
];
}
return $points;
}
/**
* @param array{DAILY?: array, WEEKLY?: array, MONTHLY?: array} $prices
* @return array{DAILY: array, WEEKLY: array, MONTHLY: array}
*/
public function sanitizeChartPrices(array $prices): array
{
$minScaled = intdiv(self::MIN_VALID_CHART_PRICE_RIAL, 1000);
foreach (['DAILY', 'WEEKLY', 'MONTHLY'] as $period) {
if (! isset($prices[$period]) || ! is_array($prices[$period])) {
$prices[$period] = [];
continue;
}
$lastValid = null;
$sanitized = [];
foreach ($prices[$period] as $point) {
$value = (int) ($point['value'] ?? 0);
$timestamp = (int) ($point['timestamp'] ?? 0);
if ($timestamp <= 0) {
continue;
}
$isValid = $value > self::MIN_VALID_CHART_PRICE_RIAL
|| ($value > $minScaled && $value <= self::MIN_VALID_CHART_PRICE_RIAL);
if ($isValid) {
$lastValid = $value;
} elseif ($lastValid !== null) {
$value = $lastValid;
} else {
continue;
}
$sanitized[] = [
'timestamp' => $timestamp,
'value' => $value,
];
}
$prices[$period] = $sanitized;
}
return $prices;
}
}
+6 -4
View File
@@ -93,17 +93,17 @@ class ZaarboxPriceService
if ($this->config->getBool('chart_use_local_data', false)) {
$local = app(PriceSnapshotService::class)->chartFromDatabase();
if (! empty($local['DAILY'])) {
return $local;
return app(PriceSnapshotService::class)->sanitizeChartPrices($local);
}
}
$cached = Cache::get($this->cacheKey());
if (is_array($cached) && isset($cached['prices'])) {
return $cached['prices'];
return app(PriceSnapshotService::class)->sanitizeChartPrices($cached['prices']);
}
return $this->refreshCache();
return app(PriceSnapshotService::class)->sanitizeChartPrices($this->refreshCache());
}
/**
@@ -566,7 +566,9 @@ class ZaarboxPriceService
for ($bucket = $firstBucket; $bucket <= $endMs; $bucket += $intervalMs) {
while ($index < $count && $points[$index]['timestamp'] <= $bucket) {
$lastPoint = $points[$index];
if ($points[$index]['price'] > PriceSnapshotService::MIN_VALID_CHART_PRICE_RIAL) {
$lastPoint = $points[$index];
}
$index++;
}