asdasd
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-29 01:19:32 +02:00
parent cea88963da
commit 1da63807eb

View File

@@ -37,10 +37,18 @@ final class FxRatesService
if ($at === null || trim($at) === '') {
$latest = $this->repository->getLatestFetch($base);
if ($latest === null) {
$latest = $this->repository->getLatestFetch(null);
if ($latest === null) {
return null;
}
}
$snapshot = $this->repository->getSnapshotByFetchId((int) $latest['id'], null);
if ($snapshot === null) {
return null;
}
return $this->repository->getSnapshotByFetchId((int) $latest['id'], $symbols);
return $this->rebaseSnapshot($snapshot, $base, $symbols);
}
$atUtc = $this->normalizeTimestamp($at);
@@ -58,7 +66,12 @@ final class FxRatesService
return null;
}
return $snapshot + [
$rebased = $this->rebaseSnapshot($snapshot, $base, $symbols);
if ($rebased === null) {
return null;
}
return $rebased + [
'requested_at' => $atUtc,
'distance_seconds' => $nearest['distance_seconds'] ?? null,
];
@@ -129,8 +142,12 @@ final class FxRatesService
public function refreshLatestRates(?array $currencies = null, ?string $baseCurrency = null): array
{
$base = $this->normalizeCurrency($baseCurrency ?: $this->defaultBaseCurrency());
$payload = $this->fetchLatestPayload($base, $currencies);
$requestedBase = $this->normalizeCurrency($baseCurrency ?: $this->defaultBaseCurrency());
$payload = $this->fetchLatestPayload($requestedBase, $currencies);
$base = $this->normalizeCurrency((string) ($payload['base'] ?? $requestedBase));
if ($base === '') {
$base = $requestedBase !== '' ? $requestedBase : 'USD';
}
$rates = is_array($payload['rates'] ?? null) ? $payload['rates'] : [];
$rateDate = $this->normalizeRateDate($payload['date'] ?? null);
$saved = $this->repository->saveFetch(
@@ -143,6 +160,7 @@ final class FxRatesService
return [
'base' => $base,
'requested_base' => $requestedBase,
'rate_date' => $rateDate,
'updated_count' => count($saved['rates'] ?? []),
'rates' => $saved['rates'] ?? [],
@@ -422,7 +440,7 @@ final class FxRatesService
return null;
}
$query = ['base_currency=' . rawurlencode($baseCurrency)];
$query = [];
$normalizedCurrencies = [];
foreach ($currencies ?? [] as $currency) {
$currency = $this->normalizeCurrency((string) $currency);
@@ -450,9 +468,8 @@ final class FxRatesService
return [
'url' => sprintf(
'%s/api/v2/rates?base=%s&output=json&key=%s',
'%s/api/v2/rates?output=json&key=%s',
$this->apiUrl(),
rawurlencode($baseCurrency),
rawurlencode($apiKey)
),
'headers' => ['Accept: application/json'],
@@ -531,10 +548,15 @@ final class FxRatesService
throw new \RuntimeException($this->extractProviderError($payload, 'FX-Kurse konnten nicht geladen werden.'));
}
$resolvedBase = $this->normalizeCurrency((string) ($payload['meta']['base_currency_code'] ?? $payload['base'] ?? $baseCurrency));
if ($resolvedBase === '') {
$resolvedBase = $baseCurrency;
}
$filter = [];
foreach ($currencies ?? [] as $currency) {
$currency = $this->normalizeCurrency((string) $currency);
if ($currency !== '' && $currency !== $baseCurrency) {
if ($currency !== '' && $currency !== $resolvedBase) {
$filter[$currency] = true;
}
}
@@ -542,7 +564,7 @@ final class FxRatesService
$rates = [];
foreach ($rawRates as $code => $rateData) {
$code = $this->normalizeCurrency((string) $code);
if ($code === '' || $code === $baseCurrency) {
if ($code === '' || $code === $resolvedBase) {
continue;
}
if ($filter !== [] && !isset($filter[$code])) {
@@ -558,12 +580,68 @@ final class FxRatesService
}
return [
'base' => $baseCurrency,
'base' => $resolvedBase,
'date' => $payload['meta']['last_updated_at'] ?? null,
'rates' => $rates,
];
}
private function rebaseSnapshot(array $snapshot, string $requestedBase, ?array $symbols = null): ?array
{
$snapshotBase = $this->normalizeCurrency((string) ($snapshot['base_currency'] ?? ''));
$rates = is_array($snapshot['rates'] ?? null) ? $snapshot['rates'] : [];
if ($snapshotBase === '') {
return null;
}
if ($requestedBase === '' || $requestedBase === $snapshotBase) {
return $snapshot + [
'base_currency' => $snapshotBase,
'rates' => $this->filterRates($rates, $symbols),
];
}
$baseRate = $rates[$requestedBase] ?? null;
if (!is_numeric($baseRate) || (float) $baseRate <= 0) {
return null;
}
$rebasedRates = [];
foreach ($rates as $code => $rate) {
$code = $this->normalizeCurrency((string) $code);
if ($code === '' || $code === $requestedBase || !is_numeric($rate)) {
continue;
}
$rebasedRates[$code] = (float) $rate / (float) $baseRate;
}
return $snapshot + [
'base_currency' => $requestedBase,
'rates' => $this->filterRates($rebasedRates, $symbols),
'snapshot_base_currency' => $snapshotBase,
];
}
private function filterRates(array $rates, ?array $symbols = null): array
{
if (!is_array($symbols) || $symbols === []) {
ksort($rates);
return $rates;
}
$filtered = [];
foreach ($symbols as $symbol) {
$symbol = $this->normalizeCurrency((string) $symbol);
if ($symbol !== '' && isset($rates[$symbol])) {
$filtered[$symbol] = (float) $rates[$symbol];
}
}
ksort($filtered);
return $filtered;
}
private function normalizeCurrencyApiComCurrenciesPayload(array $payload): array
{
$rawCurrencies = is_array($payload['data'] ?? null) ? $payload['data'] : null;