516 lines
27 KiB
PHP
516 lines
27 KiB
PHP
<?php $ownerQuery = $isAdmin ? '?owner_sub=' . urlencode((string) $ownerSub) : ''; ?>
|
|
<?= module_shell_header('boersenchecker', [
|
|
'title' => 'Depotverwaltung',
|
|
]) ?>
|
|
<div class="bc-app">
|
|
<div class="bc-grid-bg">
|
|
<div class="bc-shell bc-stack module-flow">
|
|
|
|
<?php if ($error): ?>
|
|
<div class="bc-alert bc-alert--error"><?= e($error) ?></div>
|
|
<?php elseif ($notice): ?>
|
|
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($isAdmin): ?>
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Benutzer-Scope</h2>
|
|
<p>Depots anderer Benutzer sind nur fuer `appadmin` sichtbar und bearbeitbar.</p>
|
|
</div>
|
|
</div>
|
|
<form method="get" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
|
<label class="setup-field muted" style="margin:0; min-width:260px;">
|
|
<span>Depots von Benutzer</span>
|
|
<select name="owner_sub">
|
|
<?php foreach ($availableOwners as $owner): ?>
|
|
<option value="<?= e((string) $owner['sub']) ?>" <?= (string) $ownerSub === (string) $owner['sub'] ? 'selected' : '' ?>>
|
|
<?= e((string) $owner['label']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<button class="bc-button bc-button--primary" type="submit">Anzeigen</button>
|
|
</form>
|
|
</section>
|
|
<?php endif; ?>
|
|
|
|
<div class="module-box-grid module-box-grid--panels">
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title"><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></h2>
|
|
<p>Stammdaten und Berichtswahrung fuer ein Depot pflegen.</p>
|
|
</div>
|
|
</div>
|
|
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
|
<input type="hidden" name="action" value="save_portfolio">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="portfolio_id" value="<?= e((string) ($editPortfolio['id'] ?? '0')) ?>">
|
|
<label class="setup-field muted">
|
|
<span>Depotname</span>
|
|
<input type="text" name="portfolio_name" value="<?= e((string) ($editPortfolio['name'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Berichtswahrung</span>
|
|
<input type="text" name="portfolio_base_currency" value="<?= e((string) ($editPortfolio['base_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Notizen</span>
|
|
<textarea name="portfolio_notes" rows="3"><?= e((string) ($editPortfolio['notes'] ?? '')) ?></textarea>
|
|
</label>
|
|
<div class="bc-actions">
|
|
<button class="bc-button bc-button--primary" type="submit">Depot speichern</button>
|
|
<?php if ($editPortfolio): ?>
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung<?= e($ownerQuery) ?>">Abbrechen</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">API / FX</h2>
|
|
<p>Kurs- und Waehrungsdaten zentral aktualisieren.</p>
|
|
</div>
|
|
</div>
|
|
<p class="muted" style="margin-top:16px;">
|
|
Die Umrechnung liest gespeicherte FX-Daten aus dem Mining-Checker. Eine Aktualisierung wird nur manuell
|
|
angestossen und respektiert die dortige Max-Age-Logik.
|
|
</p>
|
|
<p class="muted" style="margin-top:12px;">
|
|
Aktienkurse werden ueber Bavest per ISIN abgerufen. Das Ticker-Symbol bleibt als Zusatzinformation erhalten.
|
|
</p>
|
|
<div class="bc-actions" style="margin-top:16px;">
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_fx">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<button class="bc-button bc-button--primary" type="submit">FX-Daten aktualisieren</button>
|
|
</form>
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_market_data_all">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<button class="bc-button bc-button--secondary" type="submit">Alle API-Kurse abrufen</button>
|
|
</form>
|
|
</div>
|
|
<div class="muted" style="margin-top:12px;">
|
|
Bavest Mindestabstand: <?= e((string) $marketDataMinIntervalMinutes) ?> Min.
|
|
</div>
|
|
<div class="muted" style="margin-top:6px;">
|
|
API-Key und Timeout werden ueber <a href="/modules/setup/boersenchecker">Modul-Setup</a> gepflegt.
|
|
</div>
|
|
<div class="muted" style="margin-top:12px;">
|
|
Standard-Berichtswahrung: <?= e($defaultReportCurrency) ?> · Max. Alter: <?= e((string) $fxMaxAgeHours) ?>h
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title"><?= $editPosition ? 'Position bearbeiten' : 'Neue Position' ?></h2>
|
|
<p>Aktienpositionen fuer ein Depot mit Kaufdaten und Kurswaehrung verwalten.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($portfolios === []): ?>
|
|
<div class="muted" style="margin-top:16px;">Bitte zuerst ein Depot anlegen.</div>
|
|
<?php else: ?>
|
|
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
|
<input type="hidden" name="action" value="save_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) ($editPosition['id'] ?? '0')) ?>">
|
|
<input type="hidden" name="instrument_id" value="<?= e((string) ($editPosition['instrument_id'] ?? '0')) ?>">
|
|
<label class="setup-field muted">
|
|
<span>Depot</span>
|
|
<select name="portfolio_id" required>
|
|
<option value="">Bitte waehlen</option>
|
|
<?php foreach ($portfolios as $portfolio): ?>
|
|
<option value="<?= e((string) $portfolio['id']) ?>" <?= (string) ($editPosition['portfolio_id'] ?? '') === (string) $portfolio['id'] ? 'selected' : '' ?>>
|
|
<?= e((string) $portfolio['name']) ?> (<?= e((string) $portfolio['base_currency']) ?>)
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Aktienname</span>
|
|
<input type="text" name="instrument_name" value="<?= e((string) ($editPosition['instrument_name'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>API-Symbol / Ticker</span>
|
|
<input type="text" name="symbol" value="<?= e((string) ($editPosition['symbol'] ?? '')) ?>" placeholder="z.B. AAPL oder MBG.DE">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>ISIN</span>
|
|
<input type="text" name="isin" value="<?= e((string) ($editPosition['isin'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>WKN</span>
|
|
<input type="text" name="wkn" value="<?= e((string) ($editPosition['wkn'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Boerse / Markt</span>
|
|
<input type="text" name="market" value="<?= e((string) ($editPosition['market'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kurswaehrung</span>
|
|
<input type="text" name="quote_currency" value="<?= e((string) ($editPosition['quote_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
</div>
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Stueckzahl</span>
|
|
<input type="number" name="quantity" min="0" step="0.000001" value="<?= e((string) ($editPosition['quantity'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufpreis</span>
|
|
<input type="number" name="purchase_price" min="0" step="0.00000001" value="<?= e((string) ($editPosition['purchase_price'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufwaehrung</span>
|
|
<input type="text" name="purchase_currency" value="<?= e((string) ($editPosition['purchase_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufdatum</span>
|
|
<input type="date" name="purchase_date" value="<?= e((string) ($editPosition['purchase_date'] ?? date('Y-m-d'))) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Gebuehren</span>
|
|
<input type="number" name="fees" min="0" step="0.00000001" value="<?= e((string) ($editPosition['fees'] ?? '')) ?>">
|
|
</label>
|
|
</div>
|
|
<label class="setup-field muted">
|
|
<span>Notizen</span>
|
|
<textarea name="position_notes" rows="3"><?= e((string) ($editPosition['notes'] ?? '')) ?></textarea>
|
|
</label>
|
|
<div class="bc-actions">
|
|
<button class="bc-button bc-button--primary" type="submit">Position speichern</button>
|
|
<?php if ($editPosition): ?>
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung<?= e($ownerQuery) ?>">Abbrechen</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="module-box-table">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Wertpapiersuche</h2>
|
|
<p>Bavest-Suchergebnisse pruefen und Daten direkt ins Positionsformular uebernehmen.</p>
|
|
</div>
|
|
</div>
|
|
<div class="module-box-copy">
|
|
<form method="post" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
|
<input type="hidden" name="action" value="search_symbol">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
|
|
<span>Suchbegriff</span>
|
|
<input type="text" name="search_keywords" value="<?= e($symbolSearchKeywords) ?>" placeholder="z.B. Mercedes, AAPL, Allianz" required>
|
|
</label>
|
|
<button class="bc-button bc-button--primary" type="submit">Suchen</button>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if ($symbolSearchResults !== []): ?>
|
|
<table class="bc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Symbol</th>
|
|
<th>Name</th>
|
|
<th>Typ</th>
|
|
<th>Region</th>
|
|
<th>Waehrung</th>
|
|
<th>Match</th>
|
|
<th>Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($symbolSearchResults as $result): ?>
|
|
<tr>
|
|
<td><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
|
|
<td><?= e((string) ($result['name'] ?? '')) ?></td>
|
|
<td><?= e((string) ($result['type'] ?? '')) ?></td>
|
|
<td><?= e((string) ($result['region'] ?? '')) ?></td>
|
|
<td><?= e((string) ($result['currency'] ?? '')) ?></td>
|
|
<td><?= e((string) ($result['match_score'] ?? '')) ?></td>
|
|
<td>
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&isin_candidate=<?= urlencode((string) ($result['isin'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>"e_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
|
|
In Formular uebernehmen
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php else: ?>
|
|
<div class="module-box-copy">
|
|
<div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Manuellen Kurs erfassen</h2>
|
|
<p>Kurse mit Uhrzeit und Quelle direkt in die Historie schreiben.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($instrumentList === []): ?>
|
|
<div class="muted" style="margin-top:16px;">Sobald Positionen vorhanden sind, koennen hier Kurse mit Uhrzeit gespeichert werden.</div>
|
|
<?php else: ?>
|
|
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
|
<input type="hidden" name="action" value="save_quote">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Aktie</span>
|
|
<select name="quote_instrument_id" required>
|
|
<option value="">Bitte waehlen</option>
|
|
<?php foreach ($instrumentList as $instrument): ?>
|
|
<option value="<?= e((string) $instrument['id']) ?>" <?= $selectedInstrumentForQuote === (int) $instrument['id'] ? 'selected' : '' ?>>
|
|
<?= e((string) $instrument['name']) ?><?= $instrument['symbol'] !== '' ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kurs</span>
|
|
<input type="number" name="quote_price" min="0" step="0.00000001" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Waehrung</span>
|
|
<input type="text" name="quote_currency" value="<?= e($selectedInstrumentQuoteCurrency) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Zeitpunkt</span>
|
|
<input type="datetime-local" name="quoted_at" value="<?= e($localNowInputValue) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Quelle</span>
|
|
<input type="text" name="quote_source" value="manual">
|
|
</label>
|
|
</div>
|
|
<div class="bc-actions">
|
|
<button class="bc-button bc-button--primary" type="submit">Kurs speichern</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Depots</h2>
|
|
<p>Uebersicht aller Depots mit Kennzahlen und Schnellaktionen.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($portfolios === []): ?>
|
|
<div class="muted" style="margin-top:16px;">Noch keine Depots vorhanden.</div>
|
|
<?php else: ?>
|
|
<div class="module-box-grid module-box-grid--panels" style="margin-top:16px;">
|
|
<?php foreach ($portfolios as $portfolio): ?>
|
|
<?php
|
|
$portfolioId = (int) $portfolio['id'];
|
|
$stats = $portfolioStats[$portfolioId] ?? ['positions' => 0, 'invested' => 0.0, 'current' => 0.0, 'gain' => null, 'has_invested' => false, 'has_current' => false];
|
|
?>
|
|
<section class="module-box-soft">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
|
<div>
|
|
<strong><?= e((string) $portfolio['name']) ?></strong>
|
|
<div class="muted"><?= e((string) $portfolio['base_currency']) ?> · <?= e((string) $stats['positions']) ?> Position(en)</div>
|
|
</div>
|
|
<div class="bc-actions">
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&edit_portfolio=<?= e((string) $portfolioId) ?>">Bearbeiten</a>
|
|
<form method="post" onsubmit="return confirm('Depot wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_portfolio">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="portfolio_id" value="<?= e((string) $portfolioId) ?>">
|
|
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<?php if (!empty($portfolio['notes'])): ?>
|
|
<div class="muted" style="margin-top:10px;"><?= e((string) $portfolio['notes']) ?></div>
|
|
<?php endif; ?>
|
|
<div class="grid" style="margin-top:16px; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); gap:10px;">
|
|
<div class="bc-stat">
|
|
<div class="muted">Investiert</div>
|
|
<strong><?= $stats['has_invested'] ? e($fmtNumber((float) $stats['invested'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
<div class="bc-stat">
|
|
<div class="muted">Aktuell</div>
|
|
<strong><?= $stats['has_current'] ? e($fmtNumber((float) $stats['current'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
<div class="bc-stat">
|
|
<div class="muted">Gewinn / Verlust</div>
|
|
<strong><?= $stats['gain'] !== null ? e($fmtNumber((float) $stats['gain'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="module-box-table">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Positionen</h2>
|
|
<p>Alle Positionen mit Kaufdaten, letztem Kurs und aktuellen Werten.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($positions === []): ?>
|
|
<div class="module-box-copy">
|
|
<div class="muted">Noch keine Positionen vorhanden.</div>
|
|
</div>
|
|
<?php else: ?>
|
|
<table class="bc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Depot</th>
|
|
<th>Aktie</th>
|
|
<th>ISIN / WKN</th>
|
|
<th>Stueck</th>
|
|
<th>Kauf</th>
|
|
<th>Letzter Kurs</th>
|
|
<th>Wert</th>
|
|
<th>Delta</th>
|
|
<th>Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($positions as $position): ?>
|
|
<tr>
|
|
<td><?= e((string) ($portfolioById[(int) $position['portfolio_id']]['name'] ?? '')) ?></td>
|
|
<td>
|
|
<strong><?= e((string) $position['instrument_name']) ?></strong>
|
|
<?php if (!empty($position['symbol'])): ?>
|
|
<div class="muted"><?= e((string) $position['symbol']) ?></div>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?= e((string) ($position['isin'] ?: '-')) ?>
|
|
<div class="muted"><?= e((string) ($position['wkn'] ?: '-')) ?></div>
|
|
</td>
|
|
<td><?= e($fmtNumber((float) $position['quantity'], 6)) ?></td>
|
|
<td>
|
|
<?= e($fmtNumber((float) $position['purchase_price'], 4)) ?> <?= e((string) $position['purchase_currency']) ?>
|
|
<div class="muted"><?= e((string) $position['purchase_date']) ?></div>
|
|
</td>
|
|
<td>
|
|
<?php if ($position['latest_price'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['latest_price'], 4)) ?> <?= e((string) $position['latest_currency']) ?>
|
|
<div class="muted"><?= e($fmtDateTime((string) $position['latest_quoted_at'], (string) ($position['latest_source'] ?? ''))) ?></div>
|
|
<?php else: ?>
|
|
<span class="muted">kein Kurs</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if ($position['current_total_base'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['current_total_base'])) ?> <?= e((string) $position['base_currency']) ?>
|
|
<?php else: ?>
|
|
<span class="muted">n/a</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if ($position['gain_base'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['gain_base'])) ?> <?= e((string) $position['base_currency']) ?>
|
|
<?php else: ?>
|
|
<span class="muted">n/a</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<div class="bc-actions">
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&edit_position=<?= e((string) $position['id']) ?>">Bearbeiten</a>
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&instrument_id=<?= e((string) $position['instrument_id']) ?>">Kurs erfassen</a>
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_market_data_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) $position['id']) ?>">
|
|
<button class="bc-button bc-button--secondary" type="submit">API-Kurs</button>
|
|
</form>
|
|
<form method="post" onsubmit="return confirm('Position wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) $position['id']) ?>">
|
|
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="module-box">
|
|
<div class="module-box-head">
|
|
<div>
|
|
<h2 class="module-box-title">Kursverlauf</h2>
|
|
<p>Historische Kurse pro Aktie mit Zeitstempel und Quelle.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($instrumentList === []): ?>
|
|
<div class="muted" style="margin-top:16px;">Noch keine Kursdaten vorhanden.</div>
|
|
<?php else: ?>
|
|
<div class="module-box-grid module-box-grid--panels" style="margin-top:16px;">
|
|
<?php foreach ($instrumentList as $instrumentId => $instrument): ?>
|
|
<?php $history = array_slice($quoteHistory[$instrumentId] ?? [], 0, 10); ?>
|
|
<section class="module-box-soft">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
|
<div>
|
|
<strong><?= e((string) $instrument['name']) ?></strong>
|
|
<div class="muted">
|
|
<?= e((string) ($instrument['symbol'] ?: '-')) ?> · <?= e((string) ($instrument['isin'] ?: '-')) ?>
|
|
</div>
|
|
</div>
|
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&instrument_id=<?= e((string) $instrumentId) ?>">Neuen Kurs erfassen</a>
|
|
</div>
|
|
<?php if ($history === []): ?>
|
|
<div class="muted" style="margin-top:12px;">Noch keine historischen Kurse vorhanden.</div>
|
|
<?php else: ?>
|
|
<div class="bc-table-shell" style="margin-top:12px;">
|
|
<table class="bc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Zeitpunkt</th>
|
|
<th>Kurs</th>
|
|
<th>Quelle</th>
|
|
<th>Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($history as $quote): ?>
|
|
<tr>
|
|
<td><?= e($fmtDateTime((string) $quote['quoted_at'], (string) ($quote['source'] ?? ''))) ?></td>
|
|
<td><?= e($fmtNumber((float) $quote['price'], 4)) ?> <?= e((string) $quote['currency']) ?></td>
|
|
<td><?= e((string) $quote['source']) ?></td>
|
|
<td>
|
|
<form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_quote">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="quote_id" value="<?= e((string) $quote['id']) ?>">
|
|
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?= module_shell_footer() ?>
|