dasdsd
This commit is contained in:
@@ -8,132 +8,142 @@ use ModulesCore\ModuleHttp;
|
|||||||
|
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
ModuleHttp::requireDesktopAccess(dirname(__DIR__, 3), true);
|
|
||||||
require_auth();
|
|
||||||
|
|
||||||
$user = auth_user() ?? [];
|
|
||||||
$ownerSub = trim((string) ($user['sub'] ?? 'local'));
|
|
||||||
|
|
||||||
$instrumentId = (int) ($_GET['instrument_id'] ?? 0);
|
|
||||||
if ($instrumentId <= 0) {
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
|
||||||
echo json_encode(['ok' => false, 'message' => 'instrument_id fehlt.'], JSON_UNESCAPED_UNICODE);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdo = module_fn('boersenchecker', 'pdo');
|
|
||||||
module_fn('boersenchecker', 'ensure_schema');
|
|
||||||
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
|
||||||
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
|
||||||
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
|
||||||
'SELECT i.id, i.name, i.symbol, i.isin, i.quote_currency
|
|
||||||
FROM ' . $instrumentTable . ' i
|
|
||||||
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
|
|
||||||
WHERE i.id = :id AND p.owner_sub = :owner_sub
|
|
||||||
LIMIT 1'
|
|
||||||
);
|
|
||||||
$stmt->execute([
|
|
||||||
'id' => $instrumentId,
|
|
||||||
'owner_sub' => $ownerSub,
|
|
||||||
]);
|
|
||||||
$instrument = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
if (!is_array($instrument)) {
|
|
||||||
echo json_encode(['ok' => false, 'message' => 'Aktie nicht verfuegbar.'], JSON_UNESCAPED_UNICODE);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$quoteStmt = $pdo->prepare(
|
try {
|
||||||
'SELECT id, price, currency, quoted_at, source, created_at
|
ModuleHttp::requireDesktopAccess(dirname(__DIR__, 3), true);
|
||||||
FROM ' . $quoteTable . '
|
require_auth();
|
||||||
WHERE instrument_id = :instrument_id
|
|
||||||
ORDER BY quoted_at ASC, created_at ASC, id ASC'
|
|
||||||
);
|
|
||||||
$quoteStmt->execute([
|
|
||||||
'instrument_id' => $instrumentId,
|
|
||||||
]);
|
|
||||||
$quotes = $quoteStmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
|
||||||
|
|
||||||
if ($quotes === []) {
|
$user = auth_user() ?? [];
|
||||||
echo json_encode([
|
$ownerSub = trim((string) ($user['sub'] ?? 'local'));
|
||||||
'ok' => false,
|
|
||||||
'message' => 'Keine lokalen Kursdaten fuer diese Aktie vorhanden.',
|
|
||||||
], JSON_UNESCAPED_UNICODE);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dailyMap = [];
|
$instrumentId = (int) ($_GET['instrument_id'] ?? 0);
|
||||||
foreach ($quotes as $quote) {
|
if ($instrumentId <= 0) {
|
||||||
$localDate = trim((string) module_fn(
|
echo json_encode(['ok' => false, 'message' => 'instrument_id fehlt.'], JSON_UNESCAPED_UNICODE);
|
||||||
'boersenchecker',
|
exit;
|
||||||
'format_datetime_for_display',
|
|
||||||
(string) ($quote['quoted_at'] ?? ''),
|
|
||||||
(string) ($quote['source'] ?? ''),
|
|
||||||
'Y-m-d'
|
|
||||||
));
|
|
||||||
$localDateTime = trim((string) module_fn(
|
|
||||||
'boersenchecker',
|
|
||||||
'format_datetime_for_display',
|
|
||||||
(string) ($quote['quoted_at'] ?? ''),
|
|
||||||
(string) ($quote['source'] ?? ''),
|
|
||||||
'Y-m-d H:i:s'
|
|
||||||
));
|
|
||||||
if ($localDate === '' || !is_numeric($quote['price'] ?? null)) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$point = [
|
$pdo = module_fn('boersenchecker', 'pdo');
|
||||||
'date' => $localDate,
|
module_fn('boersenchecker', 'ensure_schema');
|
||||||
'close' => (float) $quote['price'],
|
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
||||||
'currency' => strtoupper(trim((string) ($quote['currency'] ?? ''))),
|
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
||||||
'quoted_at' => $localDateTime,
|
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
||||||
'source' => (string) ($quote['source'] ?? ''),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!isset($dailyMap[$localDate]) || strcmp($localDateTime, (string) ($dailyMap[$localDate]['quoted_at'] ?? '')) >= 0) {
|
$stmt = $pdo->prepare(
|
||||||
$dailyMap[$localDate] = $point;
|
'SELECT i.id, i.name, i.symbol, i.isin, i.quote_currency
|
||||||
|
FROM ' . $instrumentTable . ' i
|
||||||
|
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
|
||||||
|
WHERE i.id = :id AND p.owner_sub = :owner_sub
|
||||||
|
LIMIT 1'
|
||||||
|
);
|
||||||
|
$stmt->execute([
|
||||||
|
'id' => $instrumentId,
|
||||||
|
'owner_sub' => $ownerSub,
|
||||||
|
]);
|
||||||
|
$instrument = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!is_array($instrument)) {
|
||||||
|
echo json_encode(['ok' => false, 'message' => 'Aktie nicht verfuegbar.'], JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$daily = array_values($dailyMap);
|
$quoteStmt = $pdo->prepare(
|
||||||
usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date']));
|
'SELECT id, price, currency, quoted_at, source, created_at
|
||||||
|
FROM ' . $quoteTable . '
|
||||||
|
WHERE instrument_id = :instrument_id
|
||||||
|
ORDER BY quoted_at ASC, created_at ASC, id ASC'
|
||||||
|
);
|
||||||
|
$quoteStmt->execute([
|
||||||
|
'instrument_id' => $instrumentId,
|
||||||
|
]);
|
||||||
|
$quotes = $quoteStmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||||
|
|
||||||
if ($daily === []) {
|
if ($quotes === []) {
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'ok' => false,
|
'ok' => false,
|
||||||
'message' => 'Keine gueltigen lokalen Schlusskurse fuer diese Aktie vorhanden.',
|
'message' => 'Keine lokalen Kursdaten fuer diese Aktie vorhanden.',
|
||||||
], JSON_UNESCAPED_UNICODE);
|
], JSON_UNESCAPED_UNICODE);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aggregate = static function (array $points, string $format): array {
|
$dailyMap = [];
|
||||||
$result = [];
|
foreach ($quotes as $quote) {
|
||||||
$timezone = new DateTimeZone(nexus_display_timezone_name());
|
$localDate = trim((string) module_fn(
|
||||||
foreach ($points as $point) {
|
'boersenchecker',
|
||||||
$date = DateTimeImmutable::createFromFormat('Y-m-d', (string) ($point['date'] ?? ''), $timezone);
|
'format_datetime_for_display',
|
||||||
if (!$date instanceof DateTimeImmutable) {
|
(string) ($quote['quoted_at'] ?? ''),
|
||||||
|
(string) ($quote['source'] ?? ''),
|
||||||
|
'Y-m-d'
|
||||||
|
));
|
||||||
|
$localDateTime = trim((string) module_fn(
|
||||||
|
'boersenchecker',
|
||||||
|
'format_datetime_for_display',
|
||||||
|
(string) ($quote['quoted_at'] ?? ''),
|
||||||
|
(string) ($quote['source'] ?? ''),
|
||||||
|
'Y-m-d H:i:s'
|
||||||
|
));
|
||||||
|
if ($localDate === '' || !is_numeric($quote['price'] ?? null)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$bucket = $date->format($format);
|
|
||||||
$result[$bucket] = $point;
|
$point = [
|
||||||
|
'date' => $localDate,
|
||||||
|
'close' => (float) $quote['price'],
|
||||||
|
'currency' => strtoupper(trim((string) ($quote['currency'] ?? ''))),
|
||||||
|
'quoted_at' => $localDateTime,
|
||||||
|
'source' => (string) ($quote['source'] ?? ''),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isset($dailyMap[$localDate]) || strcmp($localDateTime, (string) ($dailyMap[$localDate]['quoted_at'] ?? '')) >= 0) {
|
||||||
|
$dailyMap[$localDate] = $point;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values($result);
|
$daily = array_values($dailyMap);
|
||||||
};
|
usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date']));
|
||||||
|
|
||||||
echo json_encode([
|
if ($daily === []) {
|
||||||
'ok' => true,
|
echo json_encode([
|
||||||
'symbol' => strtoupper(trim((string) ($instrument['symbol'] ?? ''))),
|
'ok' => false,
|
||||||
'isin' => strtoupper(trim((string) ($instrument['isin'] ?? ''))),
|
'message' => 'Keine gueltigen lokalen Schlusskurse fuer diese Aktie vorhanden.',
|
||||||
'instrument_name' => (string) ($instrument['name'] ?? ''),
|
], JSON_UNESCAPED_UNICODE);
|
||||||
'currency' => strtoupper(trim((string) ($instrument['quote_currency'] ?? ''))),
|
exit;
|
||||||
'daily' => $daily,
|
}
|
||||||
'weekly' => $aggregate($daily, 'o-W'),
|
|
||||||
'monthly' => $aggregate($daily, 'Y-m'),
|
$aggregate = static function (array $points, string $format): array {
|
||||||
'source' => 'database:quotes',
|
$result = [];
|
||||||
'source_label' => 'Lokale Kurshistorie',
|
$timezone = new DateTimeZone(nexus_display_timezone_name());
|
||||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
foreach ($points as $point) {
|
||||||
exit;
|
$date = DateTimeImmutable::createFromFormat('Y-m-d', (string) ($point['date'] ?? ''), $timezone);
|
||||||
|
if (!$date instanceof DateTimeImmutable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$bucket = $date->format($format);
|
||||||
|
$result[$bucket] = $point;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($result);
|
||||||
|
};
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'ok' => true,
|
||||||
|
'symbol' => strtoupper(trim((string) ($instrument['symbol'] ?? ''))),
|
||||||
|
'isin' => strtoupper(trim((string) ($instrument['isin'] ?? ''))),
|
||||||
|
'instrument_name' => (string) ($instrument['name'] ?? ''),
|
||||||
|
'currency' => strtoupper(trim((string) ($instrument['quote_currency'] ?? ''))),
|
||||||
|
'daily' => $daily,
|
||||||
|
'weekly' => $aggregate($daily, 'o-W'),
|
||||||
|
'monthly' => $aggregate($daily, 'Y-m'),
|
||||||
|
'source' => 'database:quotes',
|
||||||
|
'source_label' => 'Lokale Kurshistorie',
|
||||||
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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.');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user