Refactor the currency management system to eliminate the redundant `rate_to_aed` field and transition to a single-base model where all rates are stored relative to the Iranian Rial (IRR). Key changes: - Removed `rate_to_aed` from `currencies` table via new migration. - Updated `ExchangeRateService` to handle rates using a single `currency_code` parameter instead of currency pairs. - Refactored `UpdateExchangeRates` command to fetch rates from the Exir.io API and support multiple currencies (AED, USD, EUR, CNY). - Updated Filament resources (`CurrencyResource`, `ExchangeRateHistoryResource`) and widgets to reflect the new single-base architecture. - Improved `PriceCalculatorService` to use the updated service methodology for fetching the AED/IRR conversion rate. - Localized console command output to Persian.
106 lines
3.8 KiB
PHP
106 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Currency;
|
|
use App\Models\ExchangeRateHistory;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
class UpdateExchangeRates extends Command
|
|
{
|
|
protected $signature = 'ifnex:update-rates';
|
|
protected $description = 'دریافت نرخ ارز از API ایرانی (Exir.io) و ایجاد پیشنهاد در انتظار تأیید مدیر';
|
|
|
|
public function handle(): int
|
|
{
|
|
$this->info('در حال دریافت نرخ از API ایرانی (Exir.io)...');
|
|
|
|
try {
|
|
$rates = $this->fetchFromExir();
|
|
} catch (\Throwable $e) {
|
|
$this->error("خطا در دریافت نرخ: {$e->getMessage()}");
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
if ($rates && count($rates) > 0) {
|
|
foreach ($rates as $currencyCode => $rate) {
|
|
$this->updateRate($currencyCode, $rate);
|
|
}
|
|
$this->info('✅ پیشنهاد نرخ ارز ایجاد شد (منتظر تأیید مدیر در پنل).');
|
|
} else {
|
|
$this->warn('⚠️ دریافت نرخ ناموفق بود. نرخ زنده تغییر نکرد.');
|
|
}
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
private function updateRate(string $currencyCode, float $newRate): void
|
|
{
|
|
$currency = Currency::where('code', $currencyCode)->first();
|
|
if (!$currency) {
|
|
return;
|
|
}
|
|
|
|
$oldRate = (float) $currency->rate_to_rial;
|
|
|
|
// فقط اگه اختلاف نرخ بیشتر از 0.5% باشه، پیشنهاد ثبت کن
|
|
if ($oldRate > 0 && abs($newRate - $oldRate) / $oldRate > 0.005) {
|
|
$changePercent = round((($newRate - $oldRate) / $oldRate) * 100, 4);
|
|
|
|
ExchangeRateHistory::create([
|
|
'currency_from' => $currencyCode,
|
|
'currency_to' => 'IRR',
|
|
'old_rate' => $oldRate,
|
|
'new_rate' => $newRate,
|
|
'change_percent' => $changePercent,
|
|
'change_source' => 'api',
|
|
'api_source' => 'exir.io',
|
|
'status' => 'pending',
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function fetchFromExir(): ?array
|
|
{
|
|
// دریافت لیست جفتارزها از اکسیر
|
|
$response = Http::timeout(15)->get('https://api.exir.io/v2/minicharts');
|
|
|
|
if ($response->failed()) {
|
|
return null;
|
|
}
|
|
|
|
$data = $response->json();
|
|
$rates = [];
|
|
|
|
// نگاشت جفتارزهای اکسیر به کدهای استاندارد ما
|
|
// اکسیر قیمتها رو بر اساس تتر (USDT) میده، که در ایران معادل دلار نقدی هست
|
|
$symbolMap = [
|
|
'usdt-rls' => 'USD', // 1 دلار = X ریال
|
|
'usdt-aed' => 'AED', // 1 درهم = X تتر (باید در ریال ضرب بشه)
|
|
// اکسیر یورو و یوان مستقیم نداره، پس فقط دلار و درهم رو میگیریم
|
|
];
|
|
|
|
foreach ($data as $symbol => $info) {
|
|
if (!isset($symbolMap[$symbol])) {
|
|
continue;
|
|
}
|
|
|
|
$currencyCode = $symbolMap[$symbol];
|
|
$price = (float) ($info['price'] ?? 0);
|
|
|
|
if ($price > 0) {
|
|
// برای دلار: قیمت مستقیم ریاله
|
|
if ($currencyCode === 'USD') {
|
|
$rates['USD'] = round($price, 2);
|
|
}
|
|
// برای درهم: قیمت بر اساس تتره، باید در نرخ دلار ضرب بشه تا ریال بشه
|
|
if ($currencyCode === 'AED' && isset($rates['USD'])) {
|
|
$rates['AED'] = round($price * $rates['USD'], 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $rates;
|
|
}
|
|
} |