123 lines
4.0 KiB
PHP
123 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\PriceSyncLog;
|
|
use App\Models\PriceSyncLogItem;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class PriceSyncLogService
|
|
{
|
|
public function isAvailable(): bool
|
|
{
|
|
return Schema::hasTable('price_sync_logs') && Schema::hasTable('price_sync_log_items');
|
|
}
|
|
|
|
/**
|
|
* @param array<int, array<string, mixed>> $items
|
|
*/
|
|
public function record(string $source, ?string $sourceUrl, int $liquidGoldPrice, array $items): ?PriceSyncLog
|
|
{
|
|
if (! $this->isAvailable() || $items === []) {
|
|
return null;
|
|
}
|
|
|
|
$changedItems = array_values(array_filter(
|
|
$items,
|
|
static fn (array $item) => (bool) ($item['changed'] ?? false)
|
|
));
|
|
|
|
if ($changedItems === []) {
|
|
return null;
|
|
}
|
|
|
|
$log = PriceSyncLog::create([
|
|
'source' => $source,
|
|
'source_url' => $sourceUrl,
|
|
'liquid_gold_price' => $liquidGoldPrice,
|
|
'products_updated' => count($changedItems),
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
foreach ($changedItems as $item) {
|
|
PriceSyncLogItem::create([
|
|
'log_id' => $log->id,
|
|
'product_id' => $item['product_id'] ?? null,
|
|
'product_title' => $item['product_title'] ?? null,
|
|
'reading_method' => $item['reading_method'] ?? null,
|
|
'source_name' => $item['source_name'] ?? null,
|
|
'base_price' => (int) ($item['base_price'] ?? 0),
|
|
'base_profit' => (int) ($item['base_profit'] ?? 0),
|
|
'offset_percent' => (float) ($item['offset_percent'] ?? 0),
|
|
'stored_price' => (int) ($item['new_price'] ?? 0),
|
|
'previous_price' => (int) ($item['old_price'] ?? 0),
|
|
]);
|
|
}
|
|
|
|
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
|
|
{
|
|
if (! $this->isAvailable() || $liquidGoldPrice <= 0 || $source === 'database_last') {
|
|
return null;
|
|
}
|
|
|
|
$last = PriceSyncLog::query()->orderByDesc('id')->first();
|
|
if ($last && (int) $last->liquid_gold_price === $liquidGoldPrice) {
|
|
return null;
|
|
}
|
|
|
|
return PriceSyncLog::create([
|
|
'source' => $source,
|
|
'source_url' => $sourceUrl,
|
|
'liquid_gold_price' => $liquidGoldPrice,
|
|
'products_updated' => $productsSynced,
|
|
'created_at' => now(),
|
|
]);
|
|
}
|
|
}
|