diff --git a/app/Http/Controllers/Site/ReportController.php b/app/Http/Controllers/Site/ReportController.php index 837193d..3122144 100644 --- a/app/Http/Controllers/Site/ReportController.php +++ b/app/Http/Controllers/Site/ReportController.php @@ -23,6 +23,7 @@ use Morilog\Jalali\Jalalian; use App\Services\ConfigService; use App\Services\LivePriceCacheService; use App\Services\PriceSnapshotService; +use App\Services\PriceSyncLogService; use App\Services\ProductDisplayPriceService; @@ -168,7 +169,14 @@ class ReportController extends Controller 'zaarbox' => 0, ], $this->storeLastPrice($config)); - app(PriceSnapshotService::class)->recordHalfHourBuyPrice((int) ($storePayload['buy'] ?? 0)); + if ($forceRefresh) { + $this->recordHalfHourPriceSnapshot( + (int) ($storePayload['buy'] ?? 0), + 'store', + null, + (int) ($storePayload['price'] ?? $storePayload['buy'] ?? 0) + ); + } return $this->appendUpPrices($storePayload, $forceRefresh); } @@ -415,7 +423,14 @@ class ReportController extends Controller $config->trackDailyPriceExtreme((float) $priceValue); } - app(PriceSnapshotService::class)->recordHalfHourBuyPrice((int) $buy); + if ($forceRefresh) { + $this->recordHalfHourPriceSnapshot( + (int) $buy, + (string) ($priceSource ?: ($priceProvider ?: 'legacy')), + $this->resolvePriceSourceUrl($priceSource, $config), + (int) $priceValue + ); + } return $this->appendUpPrices([ 'sell' => $sell, @@ -430,6 +445,41 @@ class ReportController extends Controller ], $forceRefresh); } + protected function recordHalfHourPriceSnapshot( + int $buyPrice, + string $source, + ?string $sourceUrl, + int $referencePrice + ): void { + if ($buyPrice <= 0) { + return; + } + + $reference = $referencePrice > 0 ? $referencePrice : $buyPrice; + + app(PriceSyncLogService::class)->recordSnapshotIfDue( + $source, + $sourceUrl, + $reference, + PriceSnapshotService::HALF_HOUR_MINUTES + ); + + app(PriceSnapshotService::class)->recordHalfHourBuyPrice($buyPrice); + } + + protected function resolvePriceSourceUrl(?string $priceSource, ConfigService $config): ?string + { + if ($priceSource === 'zaarbox') { + return app(ZaarboxPriceService::class)->apiUrl(); + } + + if ($priceSource === 'montzar') { + return rtrim($config->Config('montzar_base_url') ?: 'https://montpar.ir', '/'); + } + + return null; + } + /** * فروشگاه — منطق lastPrice قبل مرج (ghatreh): montzar_price / nasiryan / prices */ diff --git a/app/Services/PriceSyncLogService.php b/app/Services/PriceSyncLogService.php index 110f8de..d5877c4 100644 --- a/app/Services/PriceSyncLogService.php +++ b/app/Services/PriceSyncLogService.php @@ -57,6 +57,48 @@ class PriceSyncLogService return $log->load('items'); } + /** + * نمونه دوره‌ای قیمت (مثلاً هر ۳۰ دقیقه) — حتی اگر قیمت نسبت به رکورد قبلی عوض نشده باشد. + */ + public function recordSnapshot(string $source, ?string $sourceUrl, int $referencePrice): ?PriceSyncLog + { + if (! $this->isAvailable() || $referencePrice <= 0) { + return null; + } + + return PriceSyncLog::create([ + 'source' => $source, + 'source_url' => $sourceUrl, + 'liquid_gold_price' => $referencePrice, + 'products_updated' => 0, + 'created_at' => now(), + ]); + } + + /** + * ثبت در تاریخچه ادمین — حداکثر هر ۳۰ دقیقه (مستقل از تغییر قیمت). + */ + public function recordSnapshotIfDue( + string $source, + ?string $sourceUrl, + int $referencePrice, + int $intervalMinutes = 30 + ): ?PriceSyncLog { + if (! $this->isAvailable() || $referencePrice <= 0) { + return null; + } + + $loggedRecently = PriceSyncLog::query() + ->where('created_at', '>=', now()->subMinutes($intervalMinutes)) + ->exists(); + + if ($loggedRecently) { + return null; + } + + return $this->recordSnapshot($source, $sourceUrl, $referencePrice); + } + /** فقط وقتی قیمت مرجع آبشده نسبت به آخرین رکورد عوض شده باشد */ public function recordTick(string $source, ?string $sourceUrl, int $liquidGoldPrice, int $productsSynced): ?PriceSyncLog {