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

This commit is contained in:
2026-04-30 02:39:50 +02:00
parent 9c9ec477d0
commit 0c5c89acfa
11 changed files with 961 additions and 65 deletions

View File

@@ -68,8 +68,6 @@ $mm->registerFunction($moduleName, 'settings', static function (): array {
'preferred_currencies' => $preferredCurrencies,
'currency_catalog' => $currencyCatalog,
'currency_catalog_synced_at' => trim((string) ($saved['currency_catalog_synced_at'] ?? '')),
'daily_refresh_enabled' => array_key_exists('daily_refresh_enabled', $saved) ? (bool) $saved['daily_refresh_enabled'] : true,
'daily_refresh_hour' => max(0, min(23, (int) ($saved['daily_refresh_hour'] ?? 18))),
'schedule_timezone' => trim((string) ($saved['schedule_timezone'] ?? 'Europe/Berlin')) ?: 'Europe/Berlin',
];
});

View File

@@ -22,20 +22,24 @@
{ "name": "default_base_currency", "label": "Standard-Basiswaehrung", "type": "text", "required": false, "help": "Wird fuer taegliche Abrufe und Snapshot-Abfragen verwendet." },
{ "name": "display_base_currency", "label": "Anzeige-Basiswaehrung", "type": "select", "required": false, "help": "Basis fuer die Anzeige der zuletzt gespeicherten Kurse im Modul." },
{ "name": "preferred_currencies", "label": "Bevorzugte Waehrungen", "type": "multiselect", "required": false, "help": "Auswahl aus dem synchronisierten Waehrungskatalog." },
{ "name": "daily_refresh_enabled", "label": "Taeglichen Abruf aktivieren", "type": "checkbox", "required": false },
{ "name": "daily_refresh_hour", "label": "Taegliche Abrufstunde", "type": "number", "required": false, "help": "Lokale Stunde fuer den Scheduler, standardmaessig 18." },
{ "name": "schedule_timezone", "label": "Scheduler-Zeitzone", "type": "text", "required": false, "help": "z.B. Europe/Berlin" }
]
},
"interval_tasks": [
"cron_tasks": [
{
"name": "daily_refresh",
"label": "Taeglicher FX-Abruf",
"name": "rates_refresh",
"label": "Kursabruf",
"callback": "scheduled_refresh",
"enabled_setting": "daily_refresh_enabled",
"default_enabled": true,
"default_interval_hours": 24,
"lock_minutes": 120
"default_cron": "0 18 * * *",
"default_timezone": "Europe/Berlin",
"timezone_setting": "schedule_timezone",
"lock_minutes": 120,
"help": "Zeitgesteuerter Abruf und das Speichern neuer FX-Snapshots.",
"builder": {
"allow_manual": true,
"presets": ["daily", "every_x_days", "weekly", "monthly_day", "every_x_hours"]
}
}
],
"db_defaults": {

View File

@@ -302,42 +302,10 @@ final class FxRatesService
public function runScheduledRefresh(array $context = []): array
{
if (!$this->dailyRefreshEnabled()) {
return ['ok' => true, 'message' => 'Taeglicher FX-Abruf ist deaktiviert.', 'skipped' => true];
}
$timezone = $this->scheduleTimezone();
$nowLocal = new DateTimeImmutable('now', $timezone);
$targetHour = $this->dailyRefreshHour();
if ((int) $nowLocal->format('G') !== $targetHour) {
return [
'ok' => true,
'message' => 'Kein FX-Abruf: aktuelles Zeitfenster ist ' . $nowLocal->format('H:i') . ', Ziel ist ' . str_pad((string) $targetHour, 2, '0', STR_PAD_LEFT) . ':00.',
'skipped' => true,
'context' => $context,
];
}
$latest = $this->repository->getLatestFetch($this->defaultBaseCurrency());
if (is_array($latest) && trim((string) ($latest['fetched_at'] ?? '')) !== '') {
$latestLocal = new DateTimeImmutable((string) $latest['fetched_at'], new DateTimeZone('UTC'));
$latestLocal = $latestLocal->setTimezone($timezone);
if ($latestLocal->format('Y-m-d') === $nowLocal->format('Y-m-d') && (int) $latestLocal->format('G') >= $targetHour) {
return [
'ok' => true,
'message' => 'Kein FX-Abruf: fuer heute existiert bereits ein Snapshot nach ' . str_pad((string) $targetHour, 2, '0', STR_PAD_LEFT) . ':00.',
'skipped' => true,
'fetch' => $this->localizeFetch($latest),
'context' => $context,
];
}
}
$result = $this->refreshLatestRates(null, $this->defaultBaseCurrency());
return [
'ok' => true,
'message' => 'Taeglicher FX-Abruf ausgefuehrt: ' . (int) ($result['updated_count'] ?? 0) . ' Kurse gespeichert.',
'message' => 'Geplanter FX-Abruf ausgefuehrt: ' . (int) ($result['updated_count'] ?? 0) . ' Kurse gespeichert.',
'result' => $result,
'context' => $context,
];
@@ -980,16 +948,6 @@ final class FxRatesService
return $this->normalizeCurrency((string) ($this->settings['default_base_currency'] ?? 'EUR')) ?: 'EUR';
}
private function dailyRefreshEnabled(): bool
{
return !empty($this->settings['daily_refresh_enabled']);
}
private function dailyRefreshHour(): int
{
return max(0, min(23, (int) ($this->settings['daily_refresh_hour'] ?? 18)));
}
private function scheduleTimezone(): DateTimeZone
{
$timezone = trim((string) ($this->settings['schedule_timezone'] ?? 'Europe/Berlin'));