cron
This commit is contained in:
@@ -567,6 +567,136 @@ $mm->registerFunction($moduleName, 'alpha_vantage_fetch_quotes', static function
|
||||
];
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'scheduled_refresh_quotes', static function (array $context = []): array {
|
||||
$pdo = module_fn('boersenchecker', 'pdo');
|
||||
$settings = modules()->settings('boersenchecker');
|
||||
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
||||
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
||||
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
||||
|
||||
$defaultReportCurrency = strtoupper(trim((string) ($settings['report_currency'] ?? 'EUR'))) ?: 'EUR';
|
||||
$minIntervalMinutes = (int) (($settings['alpha_vantage_min_interval_minutes'] ?? null) ?: 60);
|
||||
if ($minIntervalMinutes <= 0) {
|
||||
$minIntervalMinutes = 60;
|
||||
}
|
||||
|
||||
$stmt = $pdo->query(
|
||||
'SELECT DISTINCT
|
||||
i.id,
|
||||
i.name,
|
||||
i.symbol,
|
||||
i.quote_currency
|
||||
FROM ' . $positionTable . ' p
|
||||
INNER JOIN ' . $instrumentTable . ' i ON i.id = p.instrument_id
|
||||
WHERE i.symbol IS NOT NULL
|
||||
AND i.symbol <> \'\'
|
||||
ORDER BY i.name ASC'
|
||||
);
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||
if ($rows === []) {
|
||||
return [
|
||||
'ok' => true,
|
||||
'message' => 'Kein automatischer Kursabruf: keine Aktien mit Symbol vorhanden.',
|
||||
];
|
||||
}
|
||||
|
||||
$instrumentIds = array_values(array_map(static fn (array $row): int => (int) ($row['id'] ?? 0), $rows));
|
||||
$instrumentIds = array_values(array_filter($instrumentIds, static fn (int $id): bool => $id > 0));
|
||||
$latestQuotes = [];
|
||||
if ($instrumentIds !== []) {
|
||||
$placeholders = implode(',', array_fill(0, count($instrumentIds), '?'));
|
||||
$latestStmt = $pdo->prepare(
|
||||
'SELECT *
|
||||
FROM ' . $quoteTable . '
|
||||
WHERE instrument_id IN (' . $placeholders . ')
|
||||
AND source LIKE ?
|
||||
ORDER BY quoted_at DESC, created_at DESC, id DESC'
|
||||
);
|
||||
$latestStmt->execute([...$instrumentIds, 'alphavantage:%']);
|
||||
foreach ($latestStmt->fetchAll(PDO::FETCH_ASSOC) ?: [] as $row) {
|
||||
$instrumentId = (int) ($row['instrument_id'] ?? 0);
|
||||
if ($instrumentId > 0 && !isset($latestQuotes[$instrumentId])) {
|
||||
$latestQuotes[$instrumentId] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$reused = 0;
|
||||
$candidates = [];
|
||||
foreach ($rows as $row) {
|
||||
$instrumentId = (int) ($row['id'] ?? 0);
|
||||
$latest = $latestQuotes[$instrumentId] ?? null;
|
||||
$latestTimestamp = is_array($latest) ? strtotime((string) ($latest['quoted_at'] ?? '')) : false;
|
||||
if ($latestTimestamp !== false && (time() - $latestTimestamp) < ($minIntervalMinutes * 60)) {
|
||||
$reused++;
|
||||
continue;
|
||||
}
|
||||
$candidates[] = $row;
|
||||
}
|
||||
|
||||
if ($candidates === []) {
|
||||
return [
|
||||
'ok' => true,
|
||||
'message' => 'Automatischer Kursabruf uebersprungen: alle Kurse liegen noch innerhalb des Mindestabstands.',
|
||||
];
|
||||
}
|
||||
|
||||
$bulkResult = module_fn('boersenchecker', 'alpha_vantage_fetch_quotes', $candidates);
|
||||
if (empty($bulkResult['ok'])) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => (string) ($bulkResult['message'] ?? 'Automatischer Alpha-Vantage-Abruf fehlgeschlagen.'),
|
||||
];
|
||||
}
|
||||
|
||||
$quotes = is_array($bulkResult['quotes'] ?? null) ? $bulkResult['quotes'] : [];
|
||||
$errors = is_array($bulkResult['errors'] ?? null) ? $bulkResult['errors'] : [];
|
||||
$updated = 0;
|
||||
foreach ($candidates as $row) {
|
||||
$instrumentId = (int) ($row['id'] ?? 0);
|
||||
$quote = $quotes[$instrumentId] ?? null;
|
||||
if (!is_array($quote) || !is_numeric($quote['price'] ?? null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$storeResult = module_fn(
|
||||
'boersenchecker',
|
||||
'store_market_quote',
|
||||
$instrumentId,
|
||||
(float) $quote['price'],
|
||||
strtoupper(trim((string) ($quote['currency'] ?? $row['quote_currency'] ?? $defaultReportCurrency))) ?: $defaultReportCurrency,
|
||||
(string) ($quote['fetched_at'] ?? gmdate('Y-m-d H:i:s')),
|
||||
(string) ($quote['source'] ?? 'alphavantage:global_quote')
|
||||
);
|
||||
if (!empty($storeResult['inserted'])) {
|
||||
$updated++;
|
||||
} else {
|
||||
$reused++;
|
||||
}
|
||||
}
|
||||
|
||||
$message = 'Automatischer Kursabruf: ' . $updated . ' neu, ' . $reused . ' wiederverwendet, ' . count($errors) . ' Fehler.';
|
||||
if ($errors !== []) {
|
||||
$message .= ' ' . implode(' | ', array_slice($errors, 0, 3));
|
||||
}
|
||||
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Intervall-Aufgabe',
|
||||
'type' => 'scheduler:run',
|
||||
'task' => 'auto_refresh_quotes',
|
||||
'context' => $context,
|
||||
'message' => $message,
|
||||
]);
|
||||
|
||||
return [
|
||||
'ok' => $errors === [],
|
||||
'message' => $message,
|
||||
'updated' => $updated,
|
||||
'reused' => $reused,
|
||||
'errors' => $errors,
|
||||
];
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_search_symbols', static function (string $keywords): array {
|
||||
$keywords = trim($keywords);
|
||||
if ($keywords === '') {
|
||||
|
||||
Reference in New Issue
Block a user