From d47b84fa22680c0c4ed009f1e7874583741f3172 Mon Sep 17 00:00:00 2001 From: fds2610 Date: Mon, 16 Feb 2026 21:04:36 +0100 Subject: [PATCH] new module AKTIEN - see README.md for details V.2.0 --- README.md | 17 + html/.Trash-1000/files/aktien2.php | 132 +++++++ html/.Trash-1000/info/aktien2.php.trashinfo | 3 + html/aktien.php | 397 ++++++++++++++++++++ html/assets/css/style.css | 107 +++++- html/assets/img/update.png | Bin 0 -> 20263 bytes html/config.php.sample | 7 + html/dashboard.php | 5 + html/edit_aktie.php | 161 ++++++++ html/get_symbol.php | 63 ++++ html/index.php | 4 +- html/new_aktie.php | 119 ++++++ html/register.php | 11 +- html/rep-month.php | 5 + html/rep-person.php | 5 + html/save_symbol.php | 45 +++ html/search_symbol.php | 32 ++ html/update_kurse.php | 101 +++++ init.sql | 15 + update.sql | 13 + 20 files changed, 1231 insertions(+), 11 deletions(-) create mode 100644 html/.Trash-1000/files/aktien2.php create mode 100644 html/.Trash-1000/info/aktien2.php.trashinfo create mode 100644 html/aktien.php create mode 100644 html/assets/img/update.png create mode 100644 html/edit_aktie.php create mode 100644 html/get_symbol.php create mode 100644 html/new_aktie.php create mode 100644 html/save_symbol.php create mode 100644 html/search_symbol.php create mode 100644 html/update_kurse.php diff --git a/README.md b/README.md index 5888be9..7cf589a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,23 @@ # FSCash Dokumentiere Ausgaben on-the-go als Webapp +& behalte den Überblick über Dein Aktiendepot + +## ToDo + +- [ ] Zusammenfassen von mehreren Einträgen zu einer Aktie +- [ ] Prüfen ob APIKEYS leer sind und ggfs die Aktualisierung ausblenden + +## V.2.0 + +- [X] neue Haupt-Funktion: Aktien zeigt eine Liste mit gespeicherten, zu beobachtenden Aktien +- [X] Die Tabelle errechnet automatisch den aktuellen Gewinn oder Verluststand jeder Aktieneintragung +- [X] neue Aktie hinzufügen mit Kaufdatum und Kaufpreis, wird je Benutzer separat hinterlegt (user_id) +- [X] es KANN eine ISIN oder WKN eingetragen werden +- [X] Beim Abruf von aktuellen Kursdaten muss vorher ein API Key von https://www.alphavantage.co/support/#api-key beantragt werden. +- [X] Suchen von Symbolen passend zur ISIN geht über einen API Key von https://www.openfigi.com/user/signup +- [X] Alternativ kann auch nach dem Aktiennamen bei alphavantage gesucht werden - dafür muss man auf den Namen klicken +- [X] Aktien können geändert und gelöscht werden. ## V.1.2 diff --git a/html/.Trash-1000/files/aktien2.php b/html/.Trash-1000/files/aktien2.php new file mode 100644 index 0000000..0b30fc2 --- /dev/null +++ b/html/.Trash-1000/files/aktien2.php @@ -0,0 +1,132 @@ + 12) { + $month = 1; + $year++; +} + +// Daten abrufen +$sql="SELECT +id, +WKNISIN, +Aktie, +kaufdatum, +kaufpreis, +anzahl, +(kaufpreis * anzahl) AS Kaufsumme +FROM +aktien; +"; + +$stmt = $pdo->prepare($sql); +$stmt->execute([ + 'year' => $year, + 'month' => $month +]); +$entries = $stmt->fetchAll(); +?> + + + + + +FSCash - Dashboard + + + +
+ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDWKN/ISINAktieKaufdatumKaufpreisAnzahlKaufsumme 
+ + + +
+ + + ++ +
+ + + + diff --git a/html/.Trash-1000/info/aktien2.php.trashinfo b/html/.Trash-1000/info/aktien2.php.trashinfo new file mode 100644 index 0000000..fa68f84 --- /dev/null +++ b/html/.Trash-1000/info/aktien2.php.trashinfo @@ -0,0 +1,3 @@ +[Trash Info] +Path=aktien2.php +DeletionDate=2026-02-16T15:16:44 diff --git a/html/aktien.php b/html/aktien.php new file mode 100644 index 0000000..cb252b6 --- /dev/null +++ b/html/aktien.php @@ -0,0 +1,397 @@ + 12) { + $month = 1; + $year++; +} + +// Daten abrufen +$sql="SELECT +id, +user_id, +WKNISIN, +Symbol, +Aktie, +kaufdatum, +kaufpreis, +anzahl, +kurs, +kursdatum, +(kaufpreis * anzahl) AS Kaufsumme +FROM +aktien +WHERE user_id = :userid; +"; + +$stmt = $pdo->prepare($sql); +$stmt->execute([ + 'userid' => $userid +]); +$entries = $stmt->fetchAll(); +?> + + + + + +FSCash - Dashboard + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + 0) { + $guvClass = 'guv-positive'; +} elseif ($guv < 0) { + $guvClass = 'guv-negative'; +} + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDISIN/SymbolAktieKaufdatumKaufpreisAnzahlKaufsummeKursGuV 
+
+ +
+ + + + + + + + + + + 0): ?> +
+ + +- + +
+ + 0): ?> + + +
+ + + + + + + +- + + +
+ + + +
Summe: + + +
+ + + +
+ + + ++ +
+ + + + + + + + + + + + + + + diff --git a/html/assets/css/style.css b/html/assets/css/style.css index b191a02..f53fce6 100644 --- a/html/assets/css/style.css +++ b/html/assets/css/style.css @@ -30,6 +30,35 @@ h1 { color: var(--dark-color); } +.kurs-cell { + font-size: 0.85em; + line-height: 1.2em; +} + +.kurs-datum { + font-size: 0.75em; + color: #666; +} + +.guv-positive { + color: #1a7f37; + font-weight: 600; +} + +.guv-negative { + color: #c62828; + font-weight: 600; +} + +.sum-row { + background-color: #f3f3f3; + border-top: 2px solid #999; +} + +.sum-row td { + padding-top: 10px; +} + .debug_hidden { display: none; } @@ -289,6 +318,15 @@ tr:hover { } } +.update { + color: white; + width: 25px; + height: 25px; + vertical-align: middle; + display: inline-block; +} + + /* Button */ .btn-xr { position: fixed; @@ -380,7 +418,7 @@ max-height: 0; } /* Modal */ -.modal { +.modal-l { display: flex; justify-content: center; align-items: center; @@ -393,7 +431,7 @@ max-height: 0; z-index: 1001; } -.modal-content { +.modal-l-content { background: white; padding: 40px; border-radius: var(--border-radius); @@ -405,14 +443,14 @@ max-height: 0; text-align: center; } -.modal-content h2 { +.modal-l-content h2 { font-size: 24px; margin-bottom: 20px; color: var(--primary-color); } -.modal-content input[type="text"], -.modal-content input[type="password"] { +.modal-l-content input[type="text"], +.modal-l-content input[type="password"] { width: 100%; padding: 15px; margin: 10px 0; @@ -423,13 +461,13 @@ max-height: 0; transition: border-color 0.3s ease; } -.modal-content input[type="text"]:focus, -.modal-content input[type="password"]:focus { +.modal-l-content input[type="text"]:focus, +.modal-l-content input[type="password"]:focus { border-color: var(--primary-color); outline: none; } -.modal-content button { +.modal-l-content button { width: 100%; padding: 15px; background-color: var(--primary-color); @@ -474,6 +512,59 @@ input[type="number"] { .modal-content input[type="password"], .modal-content button { font-size: 14px; + width: 100px; } } +/* Modales Fenster 2 */ + +.modal { + display: none; + position: fixed; + z-index: 9999; + inset: 0; + background: rgba(0,0,0,0.5); + justify-content: center; + align-items: center; +} + +.modal-content { + background: #fff; + width: 80%; + height: 80%; + max-width: 1000px; + max-height: 800px; + border-radius: 8px; + display: flex; + flex-direction: column; + padding: 20px; +} + +.modal-body { + flex: 1; + overflow-y: auto; + background: #f8f8f8; + padding: 10px; + font-family: monospace; + font-size: 14px; + border: 1px solid #ddd; +} + +.modal-footer { + text-align: right; + margin-top: 10px; +} + +.btn { + padding: 8px 16px; + background: #333; + color: white; + border: none; + cursor: pointer; + border-radius: 4px; + width: 100px; +} + +.btn:hover { + background: #555; +} diff --git a/html/assets/img/update.png b/html/assets/img/update.png new file mode 100644 index 0000000000000000000000000000000000000000..dd178c85bd425c096834e557d2eea9ea359fb735 GIT binary patch literal 20263 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