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

This commit is contained in:
2026-05-05 23:20:29 +02:00
parent eb8b04a621
commit e335a8d5bf
5 changed files with 7 additions and 218 deletions

View File

@@ -23,6 +23,7 @@ final class Router
private const BOOTSTRAP_SNAPSHOT_LIMIT = 40;
private const LONG_REQUEST_BUDGET_SECONDS = 8.0;
private const OVERVIEW_WINDOW_DAYS = 15;
private const FX_FETCH_MAX_AGE_HOURS = 3.0;
private string $moduleBasePath;
private ModuleConfig $config;
@@ -143,14 +144,6 @@ final class Router
$this->respond(['data' => $this->connectionStatus()]);
}
if ($resource === 'fx-refresh' && $method === 'POST') {
$this->respond(['data' => $this->refreshFxRates(Http::input())], 201);
}
if ($resource === 'fx-probe' && $method === 'POST') {
$this->respond(['data' => $this->probeFxRates(Http::input())], 200);
}
if ($resource === 'fx-history' && $method === 'GET') {
$this->respond(['data' => $this->fxHistory()]);
}
@@ -332,7 +325,7 @@ final class Router
'report_currency' => 'EUR',
'crypto_currency' => 'DOGE',
'display_timezone' => 'Europe/Berlin',
'fx_max_age_hours' => 3,
'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS,
'module_theme_mode' => 'inherit',
'module_theme_accent' => 'teal',
'preferred_currencies' => ['DOGE', 'USD', 'EUR'],
@@ -525,7 +518,7 @@ final class Router
'report_currency' => $backup['settings']['report_currency'] ?? 'EUR',
'crypto_currency' => $backup['settings']['crypto_currency'] ?? 'DOGE',
'display_timezone' => $backup['settings']['display_timezone'] ?? 'Europe/Berlin',
'fx_max_age_hours' => $backup['settings']['fx_max_age_hours'] ?? 3,
'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS,
'module_theme_mode' => $backup['settings']['module_theme_mode'] ?? 'inherit',
'module_theme_accent' => $backup['settings']['module_theme_accent'] ?? 'teal',
'preferred_currencies' => $backup['settings']['preferred_currencies'] ?? ['DOGE', 'USD', 'EUR'],
@@ -725,36 +718,6 @@ final class Router
}
}
private function refreshFxRates(array $input): array
{
$base = strtoupper(trim((string) ($input['base'] ?? 'EUR')));
$this->debug->add('fx.refresh.start', [
'base' => $base,
]);
try {
$result = $this->fx()->refreshLatestRates(null, $base);
$this->debug->add('fx.refresh.end', [
'base' => $base,
'fetch_id' => $result['fetch']['id'] ?? null,
'rate_count' => is_array($result['rates'] ?? null) ? count($result['rates']) : null,
]);
return $result;
} catch (\Throwable $exception) {
$this->debug->add('fx.refresh.error', [
'base' => $base,
'message' => $exception->getMessage(),
]);
throw $exception;
}
}
private function probeFxRates(array $input): array
{
$base = strtoupper(trim((string) ($input['base'] ?? 'EUR')));
return $this->fx()->probeLatestRates($base);
}
private function fxHistory(): array
{
if (!modules()->isEnabled('fx-rates') || !modules()->hasFunction('fx-rates', 'recent_fetches')) {
@@ -1170,7 +1133,6 @@ final class Router
'report_currency' => 'EUR',
'crypto_currency' => 'DOGE',
'display_timezone' => 'Europe/Berlin',
'fx_max_age_hours' => 3,
'module_theme_mode' => 'inherit',
'module_theme_accent' => 'teal',
'preferred_currencies' => $this->preferredCurrencies(),
@@ -1178,9 +1140,6 @@ final class Router
if (!$this->isValidTimezone((string) ($base['display_timezone'] ?? ''))) {
$base['display_timezone'] = 'Europe/Berlin';
}
if (!is_numeric($base['fx_max_age_hours'] ?? null) || (float) $base['fx_max_age_hours'] <= 0) {
$base['fx_max_age_hours'] = 3;
}
if (!in_array((string) ($base['module_theme_mode'] ?? ''), ['inherit', 'custom'], true)) {
$base['module_theme_mode'] = 'inherit';
}
@@ -1213,7 +1172,7 @@ final class Router
'report_currency' => $this->requiredCurrency($input['report_currency'] ?? 'EUR', 'report_currency'),
'crypto_currency' => $this->requiredCurrency($input['crypto_currency'] ?? 'DOGE', 'crypto_currency'),
'display_timezone' => $displayTimezone,
'fx_max_age_hours' => $this->requiredPositiveDecimal($input['fx_max_age_hours'] ?? 3, 'fx_max_age_hours'),
'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS,
'module_theme_mode' => $this->requiredEnum($input['module_theme_mode'] ?? 'inherit', 'module_theme_mode', ['inherit', 'custom']),
'module_theme_accent' => $this->requiredEnum($input['module_theme_accent'] ?? 'teal', 'module_theme_accent', ['teal', 'logo', 'pink', 'cyan', 'orange', 'green']),
'preferred_currencies' => $this->optionalCurrencyList($input['preferred_currencies'] ?? []),
@@ -2188,11 +2147,7 @@ final class Router
private function resolveMeasurementFxFetchId(string $projectKey, array $payload, bool $allowRefresh, ?float $maxAgeHoursOverride = null): ?int
{
$measuredAt = trim((string) ($payload['measured_at'] ?? ''));
$maxAgeHours = $maxAgeHoursOverride;
if ($maxAgeHours === null) {
$settings = $this->settings($projectKey);
$maxAgeHours = is_numeric($settings['fx_max_age_hours'] ?? null) ? (float) $settings['fx_max_age_hours'] : 3.0;
}
$maxAgeHours = $maxAgeHoursOverride ?? self::FX_FETCH_MAX_AGE_HOURS;
if ($allowRefresh && $measuredAt !== '' && $this->isRecentTimestamp($measuredAt, $maxAgeHours)) {
$fresh = $this->fx()->ensureFreshLatestRates($maxAgeHours, 'USD');
@@ -2225,7 +2180,7 @@ final class Router
private function ensureMeasurementFxReferences(string $projectKey, array $rows, ?array $settings = null): array
{
$maxAgeHours = is_numeric($settings['fx_max_age_hours'] ?? null) ? (float) $settings['fx_max_age_hours'] : 3.0;
$maxAgeHours = self::FX_FETCH_MAX_AGE_HOURS;
$resolvedByTimestamp = [];
$resolved = [];
foreach ($rows as $row) {