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

This commit is contained in:
2026-06-23 00:21:51 +02:00
parent a4378af9cf
commit b204da0319
2 changed files with 131 additions and 114 deletions

View File

@@ -8,65 +8,66 @@ use ModulesCore\ModuleHttp;
session_start(); session_start();
ModuleHttp::requireDesktopAccess(dirname(__DIR__, 3), true); header('Content-Type: application/json; charset=utf-8');
require_auth();
$user = auth_user() ?? []; try {
$ownerSub = trim((string) ($user['sub'] ?? 'local')); ModuleHttp::requireDesktopAccess(dirname(__DIR__, 3), true);
require_auth();
$instrumentId = (int) ($_GET['instrument_id'] ?? 0); $user = auth_user() ?? [];
if ($instrumentId <= 0) { $ownerSub = trim((string) ($user['sub'] ?? 'local'));
header('Content-Type: application/json; charset=utf-8');
$instrumentId = (int) ($_GET['instrument_id'] ?? 0);
if ($instrumentId <= 0) {
echo json_encode(['ok' => false, 'message' => 'instrument_id fehlt.'], JSON_UNESCAPED_UNICODE); echo json_encode(['ok' => false, 'message' => 'instrument_id fehlt.'], JSON_UNESCAPED_UNICODE);
exit; exit;
} }
$pdo = module_fn('boersenchecker', 'pdo'); $pdo = module_fn('boersenchecker', 'pdo');
module_fn('boersenchecker', 'ensure_schema'); module_fn('boersenchecker', 'ensure_schema');
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments'); $instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
$positionTable = module_fn('boersenchecker', 'table', 'positions'); $positionTable = module_fn('boersenchecker', 'table', 'positions');
$quoteTable = module_fn('boersenchecker', 'table', 'quotes'); $quoteTable = module_fn('boersenchecker', 'table', 'quotes');
$stmt = $pdo->prepare( $stmt = $pdo->prepare(
'SELECT i.id, i.name, i.symbol, i.isin, i.quote_currency 'SELECT i.id, i.name, i.symbol, i.isin, i.quote_currency
FROM ' . $instrumentTable . ' i FROM ' . $instrumentTable . ' i
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
WHERE i.id = :id AND p.owner_sub = :owner_sub WHERE i.id = :id AND p.owner_sub = :owner_sub
LIMIT 1' LIMIT 1'
); );
$stmt->execute([ $stmt->execute([
'id' => $instrumentId, 'id' => $instrumentId,
'owner_sub' => $ownerSub, 'owner_sub' => $ownerSub,
]); ]);
$instrument = $stmt->fetch(PDO::FETCH_ASSOC); $instrument = $stmt->fetch(PDO::FETCH_ASSOC);
header('Content-Type: application/json; charset=utf-8'); if (!is_array($instrument)) {
if (!is_array($instrument)) {
echo json_encode(['ok' => false, 'message' => 'Aktie nicht verfuegbar.'], JSON_UNESCAPED_UNICODE); echo json_encode(['ok' => false, 'message' => 'Aktie nicht verfuegbar.'], JSON_UNESCAPED_UNICODE);
exit; exit;
} }
$quoteStmt = $pdo->prepare( $quoteStmt = $pdo->prepare(
'SELECT id, price, currency, quoted_at, source, created_at 'SELECT id, price, currency, quoted_at, source, created_at
FROM ' . $quoteTable . ' FROM ' . $quoteTable . '
WHERE instrument_id = :instrument_id WHERE instrument_id = :instrument_id
ORDER BY quoted_at ASC, created_at ASC, id ASC' ORDER BY quoted_at ASC, created_at ASC, id ASC'
); );
$quoteStmt->execute([ $quoteStmt->execute([
'instrument_id' => $instrumentId, 'instrument_id' => $instrumentId,
]); ]);
$quotes = $quoteStmt->fetchAll(PDO::FETCH_ASSOC) ?: []; $quotes = $quoteStmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
if ($quotes === []) { if ($quotes === []) {
echo json_encode([ echo json_encode([
'ok' => false, 'ok' => false,
'message' => 'Keine lokalen Kursdaten fuer diese Aktie vorhanden.', 'message' => 'Keine lokalen Kursdaten fuer diese Aktie vorhanden.',
], JSON_UNESCAPED_UNICODE); ], JSON_UNESCAPED_UNICODE);
exit; exit;
} }
$dailyMap = []; $dailyMap = [];
foreach ($quotes as $quote) { foreach ($quotes as $quote) {
$localDate = trim((string) module_fn( $localDate = trim((string) module_fn(
'boersenchecker', 'boersenchecker',
'format_datetime_for_display', 'format_datetime_for_display',
@@ -96,20 +97,20 @@ foreach ($quotes as $quote) {
if (!isset($dailyMap[$localDate]) || strcmp($localDateTime, (string) ($dailyMap[$localDate]['quoted_at'] ?? '')) >= 0) { if (!isset($dailyMap[$localDate]) || strcmp($localDateTime, (string) ($dailyMap[$localDate]['quoted_at'] ?? '')) >= 0) {
$dailyMap[$localDate] = $point; $dailyMap[$localDate] = $point;
} }
} }
$daily = array_values($dailyMap); $daily = array_values($dailyMap);
usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date'])); usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date']));
if ($daily === []) { if ($daily === []) {
echo json_encode([ echo json_encode([
'ok' => false, 'ok' => false,
'message' => 'Keine gueltigen lokalen Schlusskurse fuer diese Aktie vorhanden.', 'message' => 'Keine gueltigen lokalen Schlusskurse fuer diese Aktie vorhanden.',
], JSON_UNESCAPED_UNICODE); ], JSON_UNESCAPED_UNICODE);
exit; exit;
} }
$aggregate = static function (array $points, string $format): array { $aggregate = static function (array $points, string $format): array {
$result = []; $result = [];
$timezone = new DateTimeZone(nexus_display_timezone_name()); $timezone = new DateTimeZone(nexus_display_timezone_name());
foreach ($points as $point) { foreach ($points as $point) {
@@ -122,9 +123,9 @@ $aggregate = static function (array $points, string $format): array {
} }
return array_values($result); return array_values($result);
}; };
echo json_encode([ echo json_encode([
'ok' => true, 'ok' => true,
'symbol' => strtoupper(trim((string) ($instrument['symbol'] ?? ''))), 'symbol' => strtoupper(trim((string) ($instrument['symbol'] ?? ''))),
'isin' => strtoupper(trim((string) ($instrument['isin'] ?? ''))), 'isin' => strtoupper(trim((string) ($instrument['isin'] ?? ''))),
@@ -135,5 +136,14 @@ echo json_encode([
'monthly' => $aggregate($daily, 'Y-m'), 'monthly' => $aggregate($daily, 'Y-m'),
'source' => 'database:quotes', 'source' => 'database:quotes',
'source_label' => 'Lokale Kurshistorie', 'source_label' => 'Lokale Kurshistorie',
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit; exit;
} catch (\Throwable $e) {
http_response_code(500);
echo json_encode([
'ok' => false,
'message' => 'Chartdaten konnten nicht geladen werden.',
'error' => $e->getMessage(),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}

View File

@@ -119,7 +119,14 @@
credentials: 'same-origin', credentials: 'same-origin',
headers: { Accept: 'application/json' } headers: { Accept: 'application/json' }
}); });
const payload = await response.json(); const responseText = await response.text();
let payload = null;
try {
payload = JSON.parse(responseText);
} catch (_error) {
const preview = responseText.trim().slice(0, 160);
throw new Error(preview !== '' ? `Chart-API liefert kein JSON: ${preview}` : 'Chart-API liefert kein JSON.');
}
if (!payload.ok) { if (!payload.ok) {
throw new Error(payload.message || 'Chartdaten konnten nicht geladen werden.'); throw new Error(payload.message || 'Chartdaten konnten nicht geladen werden.');
} }