dfsdf
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-24 00:06:34 +02:00
parent e5f32f8a6a
commit c2c91032db
2 changed files with 646 additions and 547 deletions

View File

@@ -13,453 +13,502 @@
<?php endif; ?> <?php endif; ?>
<?php if ($isAdmin): ?> <?php if ($isAdmin): ?>
<div class="bc-panel"> <section class="module-box">
<strong>Benutzer-Scope</strong> <div class="module-box-head">
<form method="get" style="margin-top:.75rem; display:flex; gap:10px; flex-wrap:wrap; align-items:end;"> <div>
<label class="setup-field muted" style="margin:0; min-width:260px;"> <h2 class="module-box-title">Benutzer-Scope</h2>
<span>Depots von Benutzer</span> <p>Depots anderer Benutzer sind nur fuer `appadmin` sichtbar und bearbeitbar.</p>
<select name="owner_sub"> </div>
<?php foreach ($availableOwners as $owner): ?> </div>
<option value="<?= e((string) $owner['sub']) ?>" <?= (string) $ownerSub === (string) $owner['sub'] ? 'selected' : '' ?>> <form method="get" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
<?= e((string) $owner['label']) ?> <label class="setup-field muted" style="margin:0; min-width:260px;">
</option> <span>Depots von Benutzer</span>
<?php endforeach; ?> <select name="owner_sub">
</select> <?php foreach ($availableOwners as $owner): ?>
</label> <option value="<?= e((string) $owner['sub']) ?>" <?= (string) $ownerSub === (string) $owner['sub'] ? 'selected' : '' ?>>
<button class="bc-button bc-button--primary" type="submit">Anzeigen</button> <?= e((string) $owner['label']) ?>
</form> </option>
</div> <?php endforeach; ?>
</select>
</label>
<button class="bc-button bc-button--primary" type="submit">Anzeigen</button>
</form>
</section>
<?php endif; ?> <?php endif; ?>
<div class="grid" style="margin-top:1rem;"> <div class="module-box-grid module-box-grid--panels">
<div class="bc-panel"> <section class="module-box">
<strong><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></strong> <div class="module-box-head">
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
<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 style="display:flex; gap:10px; flex-wrap:wrap;">
<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>
</div>
<div class="bc-panel">
<strong>API / FX</strong>
<p class="muted" style="margin-top:.75rem;">
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:.75rem;">
Aktienkurse werden ueber Alpha Vantage anhand des hinterlegten API-Symbols / Tickers pro Aktie abgerufen.
</p>
<div style="display:flex; gap:10px; flex-wrap:wrap; margin-top:1rem;">
<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_alpha_vantage_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:.75rem;">
Alpha Vantage Mindestabstand: <?= e((string) $alphaMinIntervalMinutes) ?> Min.
</div>
<div class="muted" style="margin-top:.35rem;">
API-Key und Timeout werden ueber <a class="bc-button bc-button--secondary" href="/modules/setup/boersenchecker">Modul-Setup</a> gepflegt.
</div>
<div class="muted" style="margin-top:.75rem;">
Standard-Berichtswahrung: <?= e($defaultReportCurrency) ?> · Max. Alter: <?= e((string) $fxMaxAgeHours) ?>h
</div>
</div>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong><?= $editPosition ? 'Position bearbeiten' : 'Neue Position' ?></strong>
<?php if ($portfolios === []): ?>
<div class="muted" style="margin-top:.75rem;">Bitte zuerst ein Depot anlegen.</div>
<?php else: ?>
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
<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 style="display:flex; gap:10px; flex-wrap:wrap;">
<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; ?>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>API-Symbol suchen</strong>
<p class="muted" style="margin-top:.75rem;">
Suche nach Firma oder Ticker ueber den Alpha-Vantage-`SYMBOL_SEARCH`-Endpoint und uebernimm einen Treffer direkt ins Positionsformular.
</p>
<form method="post" style="margin-top:.75rem; 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>
<?php if ($symbolSearchResults !== []): ?>
<div class="bc-table-shell" style="margin-top:1rem;">
<table class="bc-table">
<thead>
<tr style="text-align:left; border-bottom:1px solid var(--border);">
<th style="padding:8px;">Symbol</th>
<th style="padding:8px;">Name</th>
<th style="padding:8px;">Typ</th>
<th style="padding:8px;">Region</th>
<th style="padding:8px;">Waehrung</th>
<th style="padding:8px;">Match</th>
<th style="padding:8px;">Aktion</th>
</tr>
</thead>
<tbody>
<?php foreach ($symbolSearchResults as $result): ?>
<tr style="border-bottom:1px solid var(--border); vertical-align:top;">
<td style="padding:8px;"><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
<td style="padding:8px;"><?= e((string) ($result['name'] ?? '')) ?></td>
<td style="padding:8px;"><?= e((string) ($result['type'] ?? '')) ?></td>
<td style="padding:8px;"><?= e((string) ($result['region'] ?? '')) ?></td>
<td style="padding:8px;"><?= e((string) ($result['currency'] ?? '')) ?></td>
<td style="padding:8px;"><?= e((string) ($result['match_score'] ?? '')) ?></td>
<td style="padding:8px;">
<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'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>&quote_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
In Formular uebernehmen
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>Manuellen Kurs erfassen</strong>
<?php if ($instrumentList === []): ?>
<div class="muted" style="margin-top:.75rem;">Sobald Positionen vorhanden sind, koennen hier Kurse mit Uhrzeit gespeichert werden.</div>
<?php else: ?>
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
<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(date('Y-m-d\TH:i')) ?>" required>
</label>
<label class="setup-field muted">
<span>Quelle</span>
<input type="text" name="quote_source" value="manual">
</label>
</div>
<div>
<button class="bc-button bc-button--primary" type="submit">Kurs speichern</button>
</div>
</form>
<?php endif; ?>
</div>
<div style="margin-top:1rem;" class="grid">
<?php if ($portfolios === []): ?>
<div class="bc-panel">
<div class="muted">Noch keine Depots vorhanden.</div>
</div>
<?php else: ?>
<?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];
?>
<div class="bc-panel">
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
<div> <div>
<strong><?= e((string) $portfolio['name']) ?></strong> <h2 class="module-box-title"><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></h2>
<div class="muted"><?= e((string) $portfolio['base_currency']) ?> · <?= e((string) $stats['positions']) ?> Position(en)</div> <p>Stammdaten und Berichtswahrung fuer ein Depot pflegen.</p>
</div>
<div style="display:flex; gap:10px; flex-wrap:wrap;">
<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>
</div> </div>
<?php if (!empty($portfolio['notes'])): ?> <form method="post" style="margin-top:16px; display:grid; gap:12px;">
<div class="muted" style="margin-top:.65rem;"><?= e((string) $portfolio['notes']) ?></div> <input type="hidden" name="action" value="save_portfolio">
<?php endif; ?> <input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
<div class="grid" style="margin-top:1rem; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); gap:10px;"> <input type="hidden" name="portfolio_id" value="<?= e((string) ($editPortfolio['id'] ?? '0')) ?>">
<div class="bc-stat"> <label class="setup-field muted">
<div class="muted">Investiert</div> <span>Depotname</span>
<strong><?= $stats['has_invested'] ? e($fmtNumber((float) $stats['invested'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong> <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> </div>
<div class="bc-stat"> </form>
<div class="muted">Aktuell</div> </section>
<strong><?= $stats['has_current'] ? e($fmtNumber((float) $stats['current'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
</div> <section class="module-box">
<div class="bc-stat"> <div class="module-box-head">
<div class="muted">Gewinn / Verlust</div> <div>
<strong><?= $stats['gain'] !== null ? e($fmtNumber((float) $stats['gain'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong> <h2 class="module-box-title">API / FX</h2>
<p>Kurs- und Waehrungsdaten zentral aktualisieren.</p>
</div> </div>
</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 Alpha Vantage anhand des hinterlegten API-Symbols / Tickers pro Aktie abgerufen.
</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_alpha_vantage_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;">
Alpha Vantage Mindestabstand: <?= e((string) $alphaMinIntervalMinutes) ?> 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> </div>
<?php endforeach; ?> <?php if ($portfolios === []): ?>
<?php endif; ?> <div class="muted" style="margin-top:16px;">Bitte zuerst ein Depot anlegen.</div>
</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>
<div class="bc-panel" style="margin-top:1rem;"> <section class="module-box-table">
<strong>Positionen</strong> <div class="module-box-head">
<?php if ($positions === []): ?> <div>
<div class="muted" style="margin-top:.75rem;">Noch keine Positionen vorhanden.</div> <h2 class="module-box-title">API-Symbol suchen</h2>
<?php else: ?> <p>Alpha-Vantage-Symbole suchen und direkt ins Positionsformular uebernehmen.</p>
<div class="bc-table-shell" style="margin-top:.75rem;"> </div>
<table class="bc-table"> </div>
<thead> <div class="module-box-copy">
<tr style="text-align:left; border-bottom:1px solid var(--border);"> <form method="post" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
<th style="padding:8px;">Depot</th> <input type="hidden" name="action" value="search_symbol">
<th style="padding:8px;">Aktie</th> <input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
<th style="padding:8px;">ISIN / WKN</th> <label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
<th style="padding:8px;">Stueck</th> <span>Suchbegriff</span>
<th style="padding:8px;">Kauf</th> <input type="text" name="search_keywords" value="<?= e($symbolSearchKeywords) ?>" placeholder="z.B. Mercedes, AAPL, Allianz" required>
<th style="padding:8px;">Letzter Kurs</th> </label>
<th style="padding:8px;">Wert</th> <button class="bc-button bc-button--primary" type="submit">Suchen</button>
<th style="padding:8px;">Delta</th> </form>
<th style="padding:8px;">Aktion</th> </div>
</tr>
</thead> <?php if ($symbolSearchResults !== []): ?>
<tbody> <table class="bc-table">
<?php foreach ($positions as $position): ?> <thead>
<tr style="border-bottom:1px solid var(--border); vertical-align:top;"> <tr>
<td style="padding:8px;"><?= e((string) ($portfolioById[(int) $position['portfolio_id']]['name'] ?? '')) ?></td> <th>Symbol</th>
<td style="padding:8px;"> <th>Name</th>
<strong><?= e((string) $position['instrument_name']) ?></strong> <th>Typ</th>
<?php if (!empty($position['symbol'])): ?> <th>Region</th>
<div class="muted"><?= e((string) $position['symbol']) ?></div> <th>Waehrung</th>
<?php endif; ?> <th>Match</th>
</td> <th>Aktion</th>
<td style="padding:8px;"> </tr>
<?= e((string) ($position['isin'] ?: '-')) ?> </thead>
<div class="muted"><?= e((string) ($position['wkn'] ?: '-')) ?></div> <tbody>
</td> <?php foreach ($symbolSearchResults as $result): ?>
<td style="padding:8px;"><?= e($fmtNumber((float) $position['quantity'], 6)) ?></td> <tr>
<td style="padding:8px;"> <td><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
<?= e($fmtNumber((float) $position['purchase_price'], 4)) ?> <?= e((string) $position['purchase_currency']) ?> <td><?= e((string) ($result['name'] ?? '')) ?></td>
<div class="muted"><?= e((string) $position['purchase_date']) ?></div> <td><?= e((string) ($result['type'] ?? '')) ?></td>
</td> <td><?= e((string) ($result['region'] ?? '')) ?></td>
<td style="padding:8px;"> <td><?= e((string) ($result['currency'] ?? '')) ?></td>
<?php if ($position['latest_price'] !== null): ?> <td><?= e((string) ($result['match_score'] ?? '')) ?></td>
<?= e($fmtNumber((float) $position['latest_price'], 4)) ?> <?= e((string) $position['latest_currency']) ?> <td>
<div class="muted"><?= e((string) $position['latest_quoted_at']) ?></div> <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'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>&quote_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
<?php else: ?> In Formular uebernehmen
<span class="muted">kein Kurs</span> </a>
<?php endif; ?> </td>
</td> </tr>
<td style="padding:8px;"> <?php endforeach; ?>
<?php if ($position['current_total_base'] !== null): ?> </tbody>
<?= e($fmtNumber((float) $position['current_total_base'])) ?> <?= e((string) $position['base_currency']) ?> </table>
<?php else: ?> <?php else: ?>
<span class="muted">n/a</span> <div class="module-box-copy">
<?php endif; ?> <div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
</td> </div>
<td style="padding:8px;"> <?php endif; ?>
<?php if ($position['gain_base'] !== null): ?> </section>
<?= e($fmtNumber((float) $position['gain_base'])) ?> <?= e((string) $position['base_currency']) ?>
<?php else: ?> <section class="module-box">
<span class="muted">n/a</span> <div class="module-box-head">
<?php endif; ?> <div>
</td> <h2 class="module-box-title">Manuellen Kurs erfassen</h2>
<td style="padding:8px;"> <p>Kurse mit Uhrzeit und Quelle direkt in die Historie schreiben.</p>
<div style="display:flex; gap:8px; flex-wrap:wrap;"> </div>
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&edit_position=<?= e((string) $position['id']) ?>">Bearbeiten</a> </div>
<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> <?php if ($instrumentList === []): ?>
<form method="post"> <div class="muted" style="margin-top:16px;">Sobald Positionen vorhanden sind, koennen hier Kurse mit Uhrzeit gespeichert werden.</div>
<input type="hidden" name="action" value="refresh_alpha_vantage_position"> <?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(date('Y-m-d\TH:i')) ?>" 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="owner_sub" value="<?= e((string) $ownerSub) ?>">
<input type="hidden" name="position_id" value="<?= e((string) $position['id']) ?>"> <input type="hidden" name="portfolio_id" value="<?= e((string) $portfolioId) ?>">
<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> <button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
</form> </form>
</div> </div>
</td> </div>
</tr> <?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; ?> <?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>Kursverlauf</strong>
<?php if ($instrumentList === []): ?>
<div class="muted" style="margin-top:.75rem;">Noch keine Kursdaten vorhanden.</div>
<?php else: ?>
<?php foreach ($instrumentList as $instrumentId => $instrument): ?>
<?php $history = array_slice($quoteHistory[$instrumentId] ?? [], 0, 10); ?>
<div class="bc-panel" style="margin-top:1rem;">
<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> </div>
<?php if ($history === []): ?> <?php endif; ?>
<div class="muted" style="margin-top:.75rem;">Noch keine historischen Kurse vorhanden.</div> </section>
<?php else: ?>
<div class="bc-table-shell" style="margin-top:.75rem;"> <section class="module-box-table">
<table class="bc-table"> <div class="module-box-head">
<thead> <div>
<tr style="text-align:left; border-bottom:1px solid var(--border);"> <h2 class="module-box-title">Positionen</h2>
<th style="padding:8px;">Zeitpunkt</th> <p>Alle Positionen mit Kaufdaten, letztem Kurs und aktuellen Werten.</p>
<th style="padding:8px;">Kurs</th> </div>
<th style="padding:8px;">Quelle</th>
<th style="padding:8px;">Aktion</th>
</tr>
</thead>
<tbody>
<?php foreach ($history as $quote): ?>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;"><?= e((string) $quote['quoted_at']) ?></td>
<td style="padding:8px;"><?= e($fmtNumber((float) $quote['price'], 4)) ?> <?= e((string) $quote['currency']) ?></td>
<td style="padding:8px;"><?= e((string) $quote['source']) ?></td>
<td style="padding:8px;">
<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; ?>
</div> </div>
<?php endforeach; ?> <?php if ($positions === []): ?>
<?php endif; ?> <div class="module-box-copy">
</div> <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((string) $position['latest_quoted_at']) ?></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_alpha_vantage_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((string) $quote['quoted_at']) ?></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> </div>
</div> </div>

View File

@@ -11,131 +11,181 @@
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div> <div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
<?php endif; ?> <?php endif; ?>
<div class="grid" style="margin-top:1rem;"> <div class="module-box-grid module-box-grid--panels">
<div class="bc-panel"> <section class="module-box">
<strong>Aktie waehlen</strong> <div class="module-box-head">
<form method="get" style="margin-top:.75rem;"> <div>
<label class="setup-field muted"> <h2 class="module-box-title">Aktie waehlen</h2>
<span>Aktien aller Depots</span> <p>Systemweit vorhandene Aktie aus allen Depots auswaehlen.</p>
<select name="instrument_id" onchange="this.form.submit()"> </div>
<?php foreach ($instruments as $instrument): ?> </div>
<option value="<?= e((string) $instrument['id']) ?>" <?= (string) $selectedInstrumentId === (string) $instrument['id'] ? 'selected' : '' ?>> <form method="get" style="margin-top:16px;">
<?= e((string) $instrument['name']) ?><?= !empty($instrument['symbol']) ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?> <label class="setup-field muted">
</option> <span>Aktien aller Depots</span>
<?php endforeach; ?> <select name="instrument_id" onchange="this.form.submit()">
</select> <?php foreach ($instruments as $instrument): ?>
</label> <option value="<?= e((string) $instrument['id']) ?>" <?= (string) $selectedInstrumentId === (string) $instrument['id'] ? 'selected' : '' ?>>
</form> <?= e((string) $instrument['name']) ?><?= !empty($instrument['symbol']) ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?>
</div> </option>
<?php endforeach; ?>
</select>
</label>
</form>
</section>
<div class="bc-panel"> <section class="module-box-table">
<strong>Symbolsuche</strong> <div class="module-box-head">
<form method="post" style="margin-top:.75rem; display:flex; gap:10px; flex-wrap:wrap; align-items:end;"> <div>
<input type="hidden" name="action" value="search_symbol"> <h2 class="module-box-title">Symbolsuche</h2>
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>"> <p>Alpha-Vantage-Symbole finden und direkt fuer die Aktie uebernehmen.</p>
<label class="setup-field muted" style="margin:0; min-width:260px; flex:1;"> </div>
<span>Suchbegriff</span> </div>
<input type="text" name="search_keywords" value="<?= e($searchKeywords) ?>" placeholder="z.B. Apple, AAPL, Allianz" required> <div class="module-box-copy">
</label> <form method="post" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
<button class="bc-button bc-button--primary" type="submit">Suchen</button> <input type="hidden" name="action" value="search_symbol">
</form> <input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
<?php if ($searchResults !== []): ?> <label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
<div class="bc-table-shell" style="margin-top:1rem;"> <span>Suchbegriff</span>
<input type="text" name="search_keywords" value="<?= e($searchKeywords) ?>" placeholder="z.B. Apple, AAPL, Allianz" required>
</label>
<button class="bc-button bc-button--primary" type="submit">Suchen</button>
</form>
</div>
<?php if ($searchResults !== []): ?>
<table class="bc-table">
<thead>
<tr>
<th>Symbol</th>
<th>Name</th>
<th>Region</th>
<th>Waehrung</th>
<th>Aktion</th>
</tr>
</thead>
<tbody>
<?php foreach ($searchResults as $result): ?>
<tr>
<td><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
<td><?= e((string) ($result['name'] ?? '')) ?></td>
<td><?= e((string) ($result['region'] ?? '')) ?></td>
<td><?= e((string) ($result['currency'] ?? '')) ?></td>
<td>
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/aktienverwaltung?instrument_id=<?= e((string) $selectedInstrumentId) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>&quote_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
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>
</div>
<section class="module-box">
<div class="module-box-head">
<div>
<h2 class="module-box-title">Aktie bearbeiten</h2>
<p>Stammdaten, Markt und Kurswaehrung zentral fuer die Aktie pflegen.</p>
</div>
</div>
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</div>
<?php else: ?>
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
<input type="hidden" name="action" value="save_instrument">
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
<label class="setup-field muted"><span>Name</span><input type="text" name="instrument_name" value="<?= e((string) (($selectedInstrument['name'] ?? '') ?: ($_GET['instrument_name_candidate'] ?? ''))) ?>" required></label>
<label class="setup-field muted"><span>Symbol</span><input type="text" name="symbol" value="<?= e((string) (($selectedInstrument['symbol'] ?? '') ?: ($_GET['symbol_candidate'] ?? ''))) ?>"></label>
<label class="setup-field muted"><span>ISIN</span><input type="text" name="isin" value="<?= e((string) ($selectedInstrument['isin'] ?? '')) ?>"></label>
<label class="setup-field muted"><span>WKN</span><input type="text" name="wkn" value="<?= e((string) ($selectedInstrument['wkn'] ?? '')) ?>"></label>
<label class="setup-field muted"><span>Markt</span><input type="text" name="market" value="<?= e((string) (($selectedInstrument['market'] ?? '') ?: ($_GET['market_candidate'] ?? ''))) ?>"></label>
<label class="setup-field muted"><span>Kurswaehrung</span><input type="text" name="quote_currency" value="<?= e((string) (($selectedInstrument['quote_currency'] ?? $defaultReportCurrency) ?: ($_GET['quote_currency_candidate'] ?? $defaultReportCurrency))) ?>"></label>
</div>
<div class="bc-actions">
<button class="bc-button bc-button--primary" type="submit">Aktie speichern</button>
</div>
</form>
<form method="post" style="margin-top:12px;">
<input type="hidden" name="action" value="refresh_alpha_vantage_instrument">
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<button class="bc-button bc-button--secondary" type="submit">Aktuellen API-Kurs abrufen</button>
</form>
<?php endif; ?>
</section>
<section class="module-box">
<div class="module-box-head">
<div>
<h2 class="module-box-title">Manuellen Kurs eingeben</h2>
<p>Einzelne Kurse mit Zeitstempel und Quelle fuer die ausgewaehlte Aktie speichern.</p>
</div>
</div>
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</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="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
<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((string) ($selectedInstrument['quote_currency'] ?? $defaultReportCurrency)) ?>" required></label>
<label class="setup-field muted"><span>Zeitpunkt</span><input type="datetime-local" name="quoted_at" value="<?= e(date('Y-m-d\TH:i')) ?>" 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-table">
<div class="module-box-head">
<div>
<h2 class="module-box-title">Kursverlauf</h2>
<p>Gespeicherte Kursdaten der ausgewaehlten Aktie mit Quelle und Loeschoption.</p>
</div>
</div>
<?php if ($quotes === []): ?>
<div class="module-box-copy">
<div class="muted">Keine Kursdaten vorhanden.</div>
</div>
<?php else: ?>
<table class="bc-table"> <table class="bc-table">
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Kurs</th>
<th>Quelle</th>
<th>Aktion</th>
</tr>
</thead>
<tbody> <tbody>
<?php foreach ($searchResults as $result): ?> <?php foreach ($quotes as $quote): ?>
<tr style="border-bottom:1px solid var(--border);"> <tr>
<td style="padding:8px;"><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td> <td><?= e((string) $quote['quoted_at']) ?></td>
<td style="padding:8px;"><?= e((string) ($result['name'] ?? '')) ?></td> <td><?= e(number_format((float) $quote['price'], 4, ',', '.')) ?> <?= e((string) $quote['currency']) ?></td>
<td style="padding:8px;"><?= e((string) ($result['region'] ?? '')) ?></td> <td><?= e((string) $quote['source']) ?></td>
<td style="padding:8px;"><?= e((string) ($result['currency'] ?? '')) ?></td> <td>
<td style="padding:8px;"> <form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/aktienverwaltung?instrument_id=<?= e((string) $selectedInstrumentId) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>&quote_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>"> <input type="hidden" name="action" value="delete_quote">
Uebernehmen <input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
</a> <input type="hidden" name="quote_id" value="<?= e((string) $quote['id']) ?>">
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
</form>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
</table> </table>
</div> <?php endif; ?>
<?php endif; ?> </section>
</div>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>Aktie bearbeiten</strong>
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
<div class="muted" style="margin-top:.75rem;">Keine Aktie vorhanden.</div>
<?php else: ?>
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
<input type="hidden" name="action" value="save_instrument">
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
<label class="setup-field muted"><span>Name</span><input type="text" name="instrument_name" value="<?= e((string) (($selectedInstrument['name'] ?? '') ?: ($_GET['instrument_name_candidate'] ?? ''))) ?>" required></label>
<label class="setup-field muted"><span>Symbol</span><input type="text" name="symbol" value="<?= e((string) (($selectedInstrument['symbol'] ?? '') ?: ($_GET['symbol_candidate'] ?? ''))) ?>"></label>
<label class="setup-field muted"><span>ISIN</span><input type="text" name="isin" value="<?= e((string) ($selectedInstrument['isin'] ?? '')) ?>"></label>
<label class="setup-field muted"><span>WKN</span><input type="text" name="wkn" value="<?= e((string) ($selectedInstrument['wkn'] ?? '')) ?>"></label>
<label class="setup-field muted"><span>Markt</span><input type="text" name="market" value="<?= e((string) (($selectedInstrument['market'] ?? '') ?: ($_GET['market_candidate'] ?? ''))) ?>"></label>
<label class="setup-field muted"><span>Kurswaehrung</span><input type="text" name="quote_currency" value="<?= e((string) (($selectedInstrument['quote_currency'] ?? $defaultReportCurrency) ?: ($_GET['quote_currency_candidate'] ?? $defaultReportCurrency))) ?>"></label>
</div>
<button class="bc-button bc-button--primary" type="submit">Aktie speichern</button>
</form>
<form method="post" style="margin-top:.75rem;">
<input type="hidden" name="action" value="refresh_alpha_vantage_instrument">
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<button class="bc-button bc-button--secondary" type="submit">Aktuellen API-Kurs abrufen</button>
</form>
<?php endif; ?>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>Manuellen Kurs eingeben</strong>
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
<div class="muted" style="margin-top:.75rem;">Keine Aktie vorhanden.</div>
<?php else: ?>
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
<input type="hidden" name="action" value="save_quote">
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
<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((string) ($selectedInstrument['quote_currency'] ?? $defaultReportCurrency)) ?>" required></label>
<label class="setup-field muted"><span>Zeitpunkt</span><input type="datetime-local" name="quoted_at" value="<?= e(date('Y-m-d\TH:i')) ?>" required></label>
<label class="setup-field muted"><span>Quelle</span><input type="text" name="quote_source" value="manual"></label>
</div>
<button class="bc-button bc-button--primary" type="submit">Kurs speichern</button>
</form>
<?php endif; ?>
</div>
<div class="bc-panel" style="margin-top:1rem;">
<strong>Kursverlauf</strong>
<?php if ($quotes === []): ?>
<div class="muted" style="margin-top:.75rem;">Keine Kursdaten vorhanden.</div>
<?php else: ?>
<div class="bc-table-shell" style="margin-top:.75rem;">
<table class="bc-table">
<tbody>
<?php foreach ($quotes as $quote): ?>
<tr style="border-bottom:1px solid var(--border);">
<td style="padding:8px;"><?= e((string) $quote['quoted_at']) ?></td>
<td style="padding:8px;"><?= e(number_format((float) $quote['price'], 4, ',', '.')) ?> <?= e((string) $quote['currency']) ?></td>
<td style="padding:8px;"><?= e((string) $quote['source']) ?></td>
<td style="padding:8px;">
<form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
<input type="hidden" name="action" value="delete_quote">
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
<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; ?>
</div>
</div> </div>
</div> </div>
</div> </div>