ifnex/04_Laravel/app/Console/Commands/UpdateExchangeRates.php
Kazem Alghasi 3848f0b399 feat(finance): rate approval + multi-currency credit system (درخواست ۹)
- rate approval: API creates pending proposals, manager approves
- customer_credits + credit_settlements tables
- CustomerCreditService (grant/settle via wallet)
- rebuilt CustomerCreditResource
- CustomerFinancialController: real foreign-currency debt
- WP login redirect + custom login page wiring
2026-09-30 05:14:31 +03:30

114 lines
4.0 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\SystemSetting;
use App\Models\ExchangeRateHistory;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class UpdateExchangeRates extends Command
{
protected $signature = 'ifnex:update-rates {--source=ecb : Data source for exchange rates (ecb or freecurrencyapi)}';
protected $description = 'Fetch exchange rates from external APIs and create PENDING proposals (awaiting manager approval)';
public function handle(): int
{
$source = $this->option('source');
$this->info("Fetching exchange rates from source: {$source}...");
try {
$rates = match ($source) {
'freecurrencyapi' => $this->fetchFromFreeCurrencyApi(),
default => $this->fetchFromEcb(),
};
} catch (\Throwable $e) {
$this->error("Failed to fetch rates: {$e->getMessage()}");
return Command::FAILURE;
}
if ($rates) {
$this->updateRate('aed_to_irr', $rates['aed_to_irr'], 'api', null, $source);
$this->updateRate('usd_to_irr', $rates['usd_to_irr'], 'api', null, $source);
$this->info("✅ Pending rate proposals created (awaiting manager approval in panel):");
$this->line(" AED/IRR proposed: " . number_format($rates['aed_to_irr']));
$this->line(" USD/IRR proposed: " . number_format($rates['usd_to_irr']));
$this->line(" Live rate unchanged until manager approves.");
} else {
$this->warn("⚠️ API fetch failed. No pending rate created. Live rate unchanged.");
}
return Command::SUCCESS;
}
/**
* نرخ زنده (SystemSetting) دست‌نخورده می‌مونه.
* فقط یک رکورد «در انتظار تأیید» در تاریخچه ثبت می‌شه.
* مدیر صبح در پنل → تأیید می‌کنه → اون‌وقت روی نرخ زنده اعمال می‌شه.
*/
private function updateRate(string $key, float $newRate, string $source, ?int $userId, ?string $apiSource = null): void
{
$setting = SystemSetting::where('key', $key)->first();
$oldRate = $setting ? (float) $setting->value : 0;
if ($oldRate > 0 && abs($newRate - $oldRate) > 0.01) {
$currencyFrom = str_starts_with($key, 'aed') ? 'AED' : 'USD';
$changePercent = round((($newRate - $oldRate) / $oldRate) * 100, 4);
ExchangeRateHistory::create([
'currency_from' => $currencyFrom,
'currency_to' => 'IRR',
'old_rate' => $oldRate,
'new_rate' => $newRate,
'change_percent' => $changePercent,
'change_source' => $source,
'changed_by' => $userId,
'api_source' => $apiSource,
'notes' => null,
'status' => 'pending',
]);
}
}
private function fetchFromEcb(): ?array
{
$response = Http::timeout(10)->get('https://api.exchangerate-api.com/v4/latest/AED');
if ($response->failed()) {
return null;
}
$data = $response->json();
return [
'aed_to_irr' => round($data['rates']['IRR'] ?? 455000, 2),
'usd_to_irr' => round(($data['rates']['IRR'] ?? 425000) / 1.07, 2),
];
}
private function fetchFromFreeCurrencyApi(): ?array
{
$response = Http::timeout(10)->get('https://api.freecurrencyapi.com/v1/latest', [
'apikey' => config('ifnex.currency.api_key'),
'base_currency' => 'AED',
]);
if ($response->failed()) {
return null;
}
$data = $response->json();
if (!isset($data['data'])) {
return null;
}
return [
'aed_to_irr' => round(($data['data']['IRR'] ?? 455000), 2),
'usd_to_irr' => round(($data['data']['IRR'] ?? 425000) / 1.07, 2),
];
}
}