From ba026bda316a952a8ea9887a464bd46924c5e44b Mon Sep 17 00:00:00 2001 From: rxf Date: Mon, 1 Dec 2025 19:11:46 +0100 Subject: [PATCH] umgestellt auf DB4js_all --- sternwarte/DB4js_all.php | 456 ++++++++++++++++---- sternwarte/anmeldung.php | 6 +- sternwarte/anmeldung.php_404_1 | 5 +- sternwarte/anmeldung_offline.php | 5 +- sternwarte/css/sternwarte1.css | 2 +- sternwarte/index.php | 5 +- sternwarte/index_maint.php | 2 +- sternwarte/intern/sofue/js/sofue.js | 4 +- sternwarte/intern/statistik/js/statistic.js | 2 +- sternwarte/kalender/css/kalender.css | 4 + sternwarte/kalender/index.html | 4 +- sternwarte/kalender/js/kalender.js | 84 ++-- sternwarte/kalender/js/version.js | 9 +- sternwarte/phpmailer/dosendmail.php | 6 +- sternwarte/sofianmeldung.php | 9 +- sternwarte/storno/js/storno.js | 2 +- 16 files changed, 454 insertions(+), 151 deletions(-) diff --git a/sternwarte/DB4js_all.php b/sternwarte/DB4js_all.php index 8515705..ab60a35 100644 --- a/sternwarte/DB4js_all.php +++ b/sternwarte/DB4js_all.php @@ -164,6 +164,7 @@ class DB $st->execute($params); return $st->fetchAll(); } + //"SELECT * FROM SoFue2 WHERE deleted=0 AND status=? AND wtermin >= NOW() ORDER BY wtermin DESC, id DESC LIMIT ? OFFSET ?" public static function one(string $sql, array $params = []): ?array { @@ -527,22 +528,88 @@ class RepoSoFue } public static function getRecords(string $status = 'all', int $rows = 10, int $page = 1, ?string $termin = null): array { - $offset = ($page - 1) * $rows; + // Lastdate: 9 Monate zurück + $lastdate = new DateTime(); + $lastdate->sub(new DateInterval('P9M')); + $lastdateStr = $lastdate->format('Y-m-d'); + $params = []; - $sql = "SELECT * FROM " . TBL_SOFUE . " WHERE deleted=0"; + $countSql = "SELECT COUNT(*) as count FROM " . TBL_SOFUE . " WHERE deleted=0"; + + // WHERE Bedingungen aufbauen if ($status !== 'all') { - $sql .= " AND status=?"; - $params[] = (int)$status; + if ((int)$status === 4) { + $countSql .= " AND stattgefunden=1"; + } else { + $countSql .= " AND status=?"; + $params[] = (int)$status; + } } - if ($termin) { - $sql .= " AND wtermin=?"; - $params[] = $termin; + // Bei status=4 (stattgefunden) macht 'neu' keinen Sinn, ignoriere termin + // termin kann 'all', 'neu' sein - nur 'neu' wird behandelt + if ($termin === 'neu' && (int)$status !== 4) { + $countSql .= " AND wtermin >= NOW()"; } + + // Lastdate-Filter auch beim Count hinzufügen + $countSql .= " AND DATE(wtermin) >= ?"; + $params[] = $lastdateStr; + + // Anzahl der Records holen + $countResult = DB::one($countSql, $params); + $count = (int)($countResult['count'] ?? 0); + + // Anzahl der Seiten berechnen + $totalPages = $rows > 0 ? ceil($count / $rows) : 1; + + // Falls angeforderte Seite > Anzahl der Seiten, letzte Seite verwenden + if ($page > $totalPages && $totalPages > 0) { + $page = $totalPages; + } + + // Start-Record berechnen + $offset = $rows * ($page - 1); + if ($offset < 0) { + $offset = 0; + } + + // Daten abrufen mit lastdate-Filter + $sql = "SELECT * FROM " . TBL_SOFUE . " WHERE deleted=0"; + $dataParams = []; + + if ($status !== 'all') { + if ((int)$status === 4) { + $sql .= " AND stattgefunden=1"; + } else { + $sql .= " AND status=?"; + $dataParams[] = (int)$status; + } + } + // Bei status=4 (stattgefunden) macht 'neu' keinen Sinn, ignoriere termin + // termin kann 'all', 'neu' sein - nur 'neu' wird behandelt + if ($termin === 'neu' && (int)$status !== 4) { + $sql .= " AND wtermin >= NOW()"; + } + + // Lastdate-Filter hinzufügen + $sql .= " AND DATE(wtermin) >= ?"; + $dataParams[] = $lastdateStr; + $sql .= " ORDER BY wtermin DESC, id DESC LIMIT ? OFFSET ?"; - $params[] = $rows; - $params[] = $offset; - return DB::all($sql, $params); + $dataParams[] = $rows; + $dataParams[] = $offset; + + $records = DB::all($sql, $dataParams); + + // Response mit Pagination-Info + return [ + 'page' => $page, + 'total' => $totalPages, + 'records' => $count, + 'rows' => $records + ]; } +// "SELECT * FROM SoFue2 WHERE deleted=0 AND stattgefunden=1 AND wtermin >= NOW() AND DATE(wtermin) >= ? ORDER BY wtermin DESC, id DESC LIMIT ? OFFSET ?" public static function update(int $id, array $d): int { $sql = "UPDATE " . TBL_SOFUE . " SET mitarbeiter=?,status=?,bemerkung=?,wtermin=?,atermin=?,erledigt_datum=? WHERE id=?"; @@ -611,6 +678,183 @@ class RepoStatistik } } +// ---- Statistik Jahre Repository (StatistikJahre table) ---- +class RepoStatistikJahre +{ + const TBL = 'StatistikJahre'; + + public static function getByDate(string $datum): ?array + { + return DB::one("SELECT * FROM " . self::TBL . " WHERE datum=?", [$datum]); + } + + public static function getByYear(int $year): array + { + $sql = "SELECT * FROM " . self::TBL . " WHERE YEAR(datum)=? ORDER BY datum"; + $data = DB::all($sql, [$year]); + + // Calculate sums + $sumB = 0; + $sumA = 0; + $sumBZ = 0; + $sumBT = 0; + foreach ($data as $row) { + $sumB += ($row['besucherNormal'] ?? 0) + ($row['besucherSonder'] ?? 0) + ($row['besucherToT'] ?? 0); + $sumA += ($row['fuehrungen'] ?? 0) + ($row['beobachtungen'] ?? 0) + ($row['techdienst'] ?? 0); + $sumBZ += ($row['beoZeit'] ?? 0); + $sumBT += ($row['beoTage'] ?? 0); + } + + // Get Gesamt bemerkung + $gesamt = DB::one("SELECT bemerkung FROM StatistikGesamt WHERE jahr=?", [$year]); + $bemG = $gesamt['bemerkung'] ?? ''; + + return [ + 'data' => $data, + 'sumB' => $sumB, + 'sumA' => $sumA, + 'sumBZ' => $sumBZ, + 'sumBT' => $sumBT, + 'bemG' => $bemG + ]; + } + + public static function createOrUpdate(array $post): array + { + $existing = self::getByDate($post['datum']); + + if (!$existing) { + // Insert + $sql = "INSERT INTO " . self::TBL . " (fuehrungen, beobachtungen, techdienst, besucherNormal, besucherSonder, besucherToT, bemerkung, datum, beoZeit, beoTage) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + DB::exec($sql, [ + $post['fueh'] ?? 0, + $post['beob'] ?? 0, + $post['tech'] ?? 0, + $post['besN'] ?? 0, + $post['besS'] ?? 0, + $post['besT'] ?? 0, + $post['beme'] ?? '', + $post['datum'], + $post['beoZ'] ?? 0, + $post['beoT'] ?? 0 + ]); + } else { + // Update + $sql = "UPDATE " . self::TBL . " SET fuehrungen=?, beobachtungen=?, techdienst=?, besucherNormal=?, besucherSonder=?, besucherToT=?, bemerkung=?, beoZeit=?, beoTage=? WHERE datum=?"; + DB::exec($sql, [ + $post['fueh'] ?? 0, + $post['beob'] ?? 0, + $post['tech'] ?? 0, + $post['besN'] ?? 0, + $post['besS'] ?? 0, + $post['besT'] ?? 0, + $post['beme'] ?? '', + $post['beoZ'] ?? 0, + $post['beoT'] ?? 0, + $post['datum'] + ]); + } + + return ['datum' => $post['datum']]; + } + + public static function getYearList(): array + { + $sql = "SELECT YEAR(datum) as jahr FROM " . self::TBL . " GROUP BY YEAR(datum) ORDER BY YEAR(datum) DESC"; + $rows = DB::all($sql); + return array_map(fn($r) => (int)$r['jahr'], $rows); + } +} + +// ---- Statistik Gesamt Repository (StatistikGesamt table) ---- +class RepoStatistikGesamt +{ + const TBL = 'StatistikGesamt'; + + public static function getAll(): array + { + $data = DB::all("SELECT * FROM " . self::TBL . " ORDER BY jahr DESC"); + + // Get last date info + $lastYearRow = DB::one("SELECT MAX(YEAR(datum)) as lastYear FROM StatistikJahre"); + $lastYear = $lastYearRow['lastYear'] ?? date('Y'); + + $fullYear = DB::all("SELECT * FROM StatistikJahre WHERE YEAR(datum)=?", [$lastYear]); + + // Calculate sums + $sumB = DB::one("SELECT SUM(besucher) as sum FROM " . self::TBL)['sum'] ?? 0; + $sumA = DB::one("SELECT SUM(aktivitaeten) as sum FROM " . self::TBL)['sum'] ?? 0; + + return [ + 'data' => $data, + 'lastDate' => [ + 'lastYear' => (int)$lastYear, + 'fullYear' => $fullYear + ], + 'sumB' => (int)$sumB, + 'sumA' => (int)$sumA + ]; + } + + public static function getByYear(int $year): ?array + { + return DB::one("SELECT * FROM " . self::TBL . " WHERE jahr=?", [$year]); + } + + public static function createOrUpdate(array $post): array + { + $existing = self::getByYear((int)$post['jahr']); + + if (!$existing) { + // Insert + $sql = "INSERT INTO " . self::TBL . " (aktivitaeten, besucher, bemerkung, jahr) VALUES (?, ?, ?, ?)"; + DB::exec($sql, [ + $post['suma'] ?? 0, + $post['sumb'] ?? 0, + $post['bemG'] ?? '', + $post['jahr'] + ]); + } else { + // Update + $sql = "UPDATE " . self::TBL . " SET aktivitaeten=?, besucher=?, bemerkung=? WHERE jahr=?"; + DB::exec($sql, [ + $post['suma'] ?? 0, + $post['sumb'] ?? 0, + $post['bemG'] ?? '', + $post['jahr'] + ]); + } + + return ['datum' => $post['jahr']]; + } +} + +// ---- Kalender Repository ---- +class RepoKalender +{ + const TBL = 'kalender'; + + public static function getEntries(string $start, string $end): array + { + $s = date('Ymd', strtotime($start)); + $e = date('Ymd', strtotime($end)); + return DB::all("SELECT * FROM " . self::TBL . " WHERE start >= ? AND start <= ?", [$s, $e]); + } + + public static function insert(array $data): bool + { + $sql = "INSERT INTO " . self::TBL . " (start, end, title, description) VALUES (?, ?, ?, ?)"; + DB::exec($sql, [$data['start'], $data['end'] ?? $data['start'], $data['title'], $data['description'] ?? '']); + return true; + } + + public static function delete(int $id): bool + { + DB::exec("DELETE FROM " . self::TBL . " WHERE id=?", [$id]); + return true; + } +} + // ---- Email Service (einfach) ---- class Mailer { @@ -671,37 +915,25 @@ class Commands { public const MAP = [ 'PING' => 'Health-Check', - 'GET_ANMELD' => 'Liste Anmeldungen für fid', - 'GET_ANMELDNEW' => 'Anmeldungen-Varianten (legacy: special/date)', - 'GET_SONDERNEW' => 'Sonderführungen-Varianten (legacy: special/date)', + 'GET_ANMELD' => 'Liste Anmeldungen für fid/Datum', + 'GET_ANMELDNEW' => 'Anmeldungen-Varianten (special/date)', 'GET_TEILN_ID' => 'Teilnehmer nach id', 'GET_TEILN_NAME' => 'Teilnehmer nach Name/Vorname', - 'GET_GROUP' => 'Gruppenbezeichnung für fdates dateTime', - 'GET_ONEANMELD' => 'Eine Anmeldung nach id', - 'GET_COUNTS' => 'Summe Anmeldungen für fid', - 'GET_COUNTS_DATE' => 'Summe Anmeldungen für Datum (YYYY-MM-DD)', - 'INSERT_TLN' => 'Anmeldung anlegen', + 'GET_COUNTS' => 'Summe Anmeldungen für fid/Datum', + 'GET_COUNTS_DATE' => 'Summe Anmeldungen für Datum', 'UPDATE_TLN' => 'Anmeldung ändern', 'DELETE_TLN' => 'Anmeldung löschen', - 'UPDATE_TLN_BULK' => 'Mehrere Anmeldungen Feld-Update (legacy updateEntries)', + 'UPDATE_TLN_BULK' => 'Mehrere Anmeldungen Feld-Update', 'DELETEONE' => 'Teilnehmer löschen (Alias)', 'GET_LASTANMELDUNG' => 'Letzte Anmeldung (Datum) ab Start', 'UPDATECOUNT' => 'Zähler in fdatum1 für Datum reduzieren', - 'GET_SOFIANMELD' => 'Alle/sofue_id bezogene Sonderführungs-Anmeldungen', - 'GET_ONESOFIANMELD' => 'Eine Sonderführungs-Anmeldung', - 'GET_SOFIANMELD_COUNT' => 'Zähler Sonderführungs-Anmeldungen', - 'INSERT_SOFIANMELD' => 'Neue Sonderführungs-Anmeldung', - 'UPDATE_SOFIANMELD' => 'Sonderführungs-Anmeldung ändern', - 'DELETE_SOFIANMELD' => 'Sonderführungs-Anmeldung löschen', 'GET_TERMINE' => 'Termine öffentliche Führungen', 'GET_DATES' => 'Nächste Führungstermine (limit + ab Datum)', - 'GET_ONETERMIN' => 'Termin nach id', 'GET_FID' => 'Fid für Datum', 'GET_TIME' => 'Uhrzeit für Datum', 'GET_BEOS' => 'Liste BEOs optional nur Guides', 'GET_ONEBEO' => 'Ein BEO nach name', 'GET_ONE' => 'Sonderführung nach id', - 'GET_ONETERMIN_SOFUE' => 'Sonderführung nach Termin', 'GET_MANY' => 'Gefilterte Sonderführungen', 'UPDATE' => 'Sonderführung Standard-Update', 'UPDATEAFTER' => 'Nachbearbeitung Sonderführung', @@ -710,11 +942,28 @@ class Commands 'GET_STATISTIK_ANMELD' => 'Statistik öffentliche Führungen Jahr', 'GET_STATISTIK_BEO' => 'Statistik BEO Jahr', 'GET_STATISTIK_GESAMT' => 'Gesamtstatistik Jahr', - 'SEND_CONFIRMATION' => 'Einfache Bestätigungs-Mail', + 'SENDMYMAIL' => 'Mail mit BCC versenden', 'SENDMAILZUSAGE' => 'Zusage an Anfragenden', 'SENDMAIL2BEO' => 'Mail an Mitarbeiter', 'SENDMAIL2LISTE' => 'Mail an Verteiler', - 'PUT2KALENDER' => 'Kalender-Eintrag (Platzhalter)', + 'PUT2KALENDER' => 'Kalender-Eintrag', + 'GET_FDATES' => 'Führungstermine für Kalenderansicht', + 'GET_CALENTRIES' => 'Kalendereinträge abrufen', + 'PUT_CALENTRY' => 'Kalendereintrag erstellen', + 'DEL_CALENTRY' => 'Kalendereintrag löschen', + 'GET_YEARS' => 'Liste verfügbare Jahre (Statistik)', + 'GET_ONE_A' => 'Statistik-Eintrag für Datum', + 'GET_ALL_A' => 'Alle Statistik-Einträge für Jahr', + 'CRUP_A' => 'Statistik-Eintrag erstellen/aktualisieren (Jahre)', + 'GET_ALL_G' => 'Gesamtstatistik alle Jahre', + 'GET_ONE_G' => 'Gesamtstatistik für Jahr', + 'CRUP_G' => 'Gesamtstatistik erstellen/aktualisieren', + 'GET_TIME_BY_DATE' => 'Uhrzeit für Datum abrufen', + 'DELETE_ENTRY' => 'Anmeldung löschen (Storno)', + 'GET_FUEHRUNGEN' => 'Führungen in Zeitbereich', + 'UPDATETLNFD' => 'Teilnehmer-Datum aktualisieren', + 'SEND_MAIL_HTML' => 'Mail versenden (Text)', + 'GET_ALLTEILN' => 'Alle Teilnehmer ab Datum', 'LIST_COMMANDS' => 'Liste aller Kommandos' ]; } @@ -754,22 +1003,11 @@ try { $special = $input['special'] ?? 'alllater'; $date = $input['date'] ?? date('Ymd'); respond(RepoAnmeld::getNew($special, $date)); - case 'GET_SONDERNEW': - $special = $input['special'] ?? 'alllater'; - $date = $input['date'] ?? date('Ymd'); - if ($special !== 'alllater') respond([]); - respond(RepoSoFue::getAfterDate($date)); case 'GET_TEILN_ID': $r = RepoAnmeld::getById((int)$input['id'], $typ); respond($r ? [$r] : []); case 'GET_TEILN_NAME': respond(RepoAnmeld::getByName($input['name'])); - case 'GET_GROUP': - $grp = RepoFdates::groupByDate($input['date']); - respond(['grp' => $grp]); - case 'GET_ONEANMELD': - $r = RepoAnmeld::getById((int)$input['id'], $typ); - respond($r ?: ['error' => 'Not found']); case 'GET_COUNTS': if (isset($input['fdate'])) { respond(RepoAnmeld::countByDate($input['fdate'], $typ)); @@ -786,11 +1024,6 @@ try { respondError('Missing identifier for GET_COUNTS'); case 'GET_COUNTS_DATE': respond(['count' => RepoAnmeld::countByDate($input['date'], $typ)]); - case 'INSERT_TLN': - if (!isset($input['name'], $input['email'], $input['anzahl'], $input['fid'])) respondError('Missing fields'); - if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) respondError('Invalid email'); - $id = RepoAnmeld::insert($input); - respond(['success' => true, 'id' => $id]); case 'UPDATE_TLN': if (!isset($input['id'])) respondError('id missing'); RepoAnmeld::update((int)$input['id'], $input); @@ -809,28 +1042,6 @@ try { $n = RepoAnmeld::bulkUpdateField($ids, (string)$input['field'], $val); respond(['success' => $n > 0, 'updated' => $n]); - // Sonderführungs-Anmeldungen - case 'GET_SOFIANMELD': - if (isset($input['sofue_id'])) respond(RepoSoFiAnmeld::getBySoFue((int)$input['sofue_id'])); - respond(RepoSoFiAnmeld::getAll()); - case 'GET_ONESOFIANMELD': - $r = RepoSoFiAnmeld::getById((int)$input['id']); - respond($r ?: ['error' => 'Not found']); - case 'GET_SOFIANMELD_COUNT': - respond(['count' => RepoSoFiAnmeld::countBySoFue((int)$input['sofue_id'])]); - case 'INSERT_SOFIANMELD': - if (!isset($input['name'], $input['email'], $input['anzahl'], $input['sofue_id'])) respondError('Missing fields'); - if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) respondError('Invalid email'); - $id = RepoSoFiAnmeld::insert($input); - respond(['success' => true, 'id' => $id]); - case 'UPDATE_SOFIANMELD': - if (!isset($input['id'])) respondError('id missing'); - RepoSoFiAnmeld::update((int)$input['id'], $input); - respond(['success' => true]); - case 'DELETE_SOFIANMELD': - RepoSoFiAnmeld::delete((int)$input['id']); - respond(['success' => true]); - // Termine case 'GET_TERMINE': respond(RepoTermine::getAll(($input['includeOld'] ?? 'false') === 'true')); @@ -838,9 +1049,6 @@ try { $amount = isset($input['anzahl']) ? (int)$input['anzahl'] : 50; $from = $input['date'] ?? date('Ymd'); respond(RepoTermine::getNextDates($amount, $from, $typ)); - case 'GET_ONETERMIN': - $r = RepoTermine::getById((int)$input['id']); - respond($r ?: ['error' => 'Not found']); case 'GET_FID': respond(['fid' => RepoTermine::fidByDate($input['datum'], $typ)]); case 'GET_TIME': @@ -866,9 +1074,6 @@ try { case 'GET_ONE': $r = RepoSoFue::getById((int)$input['id']); respond($r ?: ['error' => 'Not found']); - case 'GET_ONETERMIN_SOFUE': - $r = RepoSoFue::getByTermin($input['termin']); - respond($r ?: ['error' => 'Not found']); case 'GET_MANY': respond(RepoSoFue::getRecords($input['status'] ?? 'all', (int)($input['rows'] ?? 10), (int)($input['page'] ?? 1), $input['termin'] ?? null)); case 'UPDATE': @@ -901,10 +1106,6 @@ try { respond(RepoStatistik::gesamt((int)($input['year'] ?? date('Y')))); // Mail - case 'SEND_CONFIRMATION': - if (!isset($input['to'], $input['subject'], $input['body'])) respondError('Missing mail fields'); - $ok = Mailer::sendPlain($input['to'], $input['subject'], $input['body']); - respond(['success' => $ok]); case 'SENDMYMAIL': // Legacy-compatible mail send with BCC list $subject = $input['subject'] ?? ($input['betreff'] ?? null); @@ -949,6 +1150,107 @@ try { if (!isset($input['id'], $input['termin'], $input['mitarbeiter'])) respondError('Missing fields'); error_log('Kalender-Eintrag: ' . $input['id'] . ' ' . $input['termin'] . ' ' . $input['mitarbeiter']); respond(['success' => true]); + case 'GET_FDATES': + // Returns führungen for calendar display + $start = $input['start'] ?? date('Ymd'); + $end = $input['end'] ?? date('Ymd', strtotime('+1 year')); + $s = date('Ymd', strtotime($start)); + $e = date('Ymd', strtotime($end)); + $sql = "SELECT * FROM " . TBL_FDATUM . " WHERE datum >= ? AND datum <= ? ORDER BY datum ASC"; + $rows = DB::all($sql, [$s, $e]); + $result = []; + foreach ($rows as $r) { + $count = RepoAnmeld::countByDate($r['datum'], 'regular'); + $result[] = [ + 'start' => $r['datum'], + 'uhr' => substr($r['uhrzeit'] ?? '', 0, 2), + 'title' => $r['gruppe'] ?? '', + 'count' => $count + ]; + } + respond($result); + case 'GET_CALENTRIES': + respond(RepoKalender::getEntries($input['start'], $input['end'])); + case 'PUT_CALENTRY': + RepoKalender::insert($input['data']); + respond(['success' => true]); + case 'DEL_CALENTRY': + RepoKalender::delete((int)$input['id']); + respond(['success' => true]); + + // Statistik - Jahre + case 'GET_YEARS': + respond(RepoStatistikJahre::getYearList()); + case 'GET_ONE_A': + $datum = $input['datum'] ?? respondError('datum missing'); + $result = RepoStatistikJahre::getByDate($datum); + if ($result) { + // Add bemG from Gesamt + $year = substr($datum, 0, 4); + $gesamt = RepoStatistikGesamt::getByYear((int)$year); + $result['bemG'] = $gesamt['bemerkung'] ?? ''; + } + respond($result ?: ['error' => 'Not found']); + case 'GET_ALL_A': + $year = (int)($input['jahr'] ?? date('Y')); + respond(RepoStatistikJahre::getByYear($year)); + case 'CRUP_A': + if (!isset($input['toInsert'])) respondError('toInsert missing'); + respond(RepoStatistikJahre::createOrUpdate($input['toInsert'])); + + // Statistik - Gesamt + case 'GET_ALL_G': + respond(RepoStatistikGesamt::getAll()); + case 'GET_ONE_G': + $year = (int)($input['jahr'] ?? date('Y')); + $result = RepoStatistikGesamt::getByYear($year); + respond($result ?: ['error' => 'Not found']); + case 'CRUP_G': + if (!isset($input['toInsert'])) respondError('toInsert missing'); + respond(RepoStatistikGesamt::createOrUpdate($input['toInsert'])); + + // Storno module commands + case 'GET_TIME_BY_DATE': + $dt = $input['dt'] ?? respondError('dt missing'); + $typ = $input['typ'] ?? 'regular'; + if ($typ === 'sonnen') { + respond(['time' => '11 Uhr']); + } + $time = DB::one("SELECT uhrzeit FROM " . TBL_FDATUM . " WHERE datum=?", [$dt]); + respond(['time' => $time['uhrzeit'] ?? '']); + case 'DELETE_ENTRY': + $id = (int)($input['id'] ?? respondError('id missing')); + DB::exec("DELETE FROM " . TBL_ANMELD . " WHERE id=?", [$id]); + respond(['success' => true]); + case 'GET_FUEHRUNGEN': + $start = $input['start'] ?? respondError('start missing'); + $end = $input['end'] ?? respondError('end missing'); + $typ = $input['typ'] ?? 'regular'; + $table = ($typ === 'sonnen') ? 'sonnedatum' : TBL_FDATUM; + $sql = "SELECT * FROM $table WHERE datum >= ? AND datum <= ? ORDER BY datum ASC"; + respond(DB::all($sql, [$start, $end])); + case 'UPDATETLNFD': + if (!isset($input['id'], $input['fdatum'], $input['fid'])) respondError('Missing fields'); + $sql = "UPDATE " . TBL_ANMELD . " SET fdatum=?, fid=?, abgesagt=NULL WHERE id=?"; + DB::exec($sql, [$input['fdatum'], $input['fid'], $input['id']]); + respond(['success' => true]); + case 'SEND_MAIL_HTML': + if (!isset($input['subject'], $input['to'], $input['body_txt'])) respondError('Missing mail fields'); + require_once __DIR__ . '/phpmailer/dosendmail.php'; + // Note: body_html is ignored because sendmail doesn't support it + $result = sendmail( + $input['subject'], + 'noreply@sternwarte-welzheim.de', + $input['body_txt'], + [], + [], + is_array($input['to']) ? $input['to'] : [$input['to']] + ); + respond(['success' => !($result['error'] ?? false)]); + case 'GET_ALLTEILN': + $fdatum = $input['fdatum'] ?? respondError('fdatum missing'); + $sql = "SELECT * FROM " . TBL_ANMELD . " WHERE fdatum >= ? ORDER BY fid ASC"; + respond(DB::all($sql, [$fdatum])); case 'LIST_COMMANDS': respond(['commands' => Commands::MAP, 'count' => count(Commands::MAP)]); diff --git a/sternwarte/anmeldung.php b/sternwarte/anmeldung.php index 19b79d9..426b9e6 100644 --- a/sternwarte/anmeldung.php +++ b/sternwarte/anmeldung.php @@ -292,7 +292,6 @@ "$stern_vorname $stern_name am " . preg_replace("/(\d+) Uhr/","um $0",$stern_datum) . " für $stern_teil $person " . // $stern_teil == 1 ? "Person" : "Personen" . ".\r\n\r\n" . - "Bitte bringen Sie diese Bestätigung als Ausdruck oder digital zur Führung mit. \r\n\r\n". "Die Führung findet NUR bei sternklarem Himmel statt. Falls der Himmel bedeckt ist \r\n" . "und die Führung ausfällt, erhalten Sie bis spätestens eine Stunde vor Führungsbeginn \r\n" . "eine Email. Sie können sich dann gerne zu einem neuen Termin anmelden.\r\n\r\n" . @@ -379,8 +378,7 @@

Wenn Sie alle Felder ausgefüllt und abgeschickt haben (mit dem "Anmeldung senden"-Knopf), - erhalten Sie eine Anmeldebestätigung per e-mail. Diese bitte unbedingt zur Führung - ausgedruckt oder in digitaler Form mitbringen! + erhalten Sie eine Anmeldebestätigung per e-mail. diff --git a/sternwarte/index_maint.php b/sternwarte/index_maint.php index 6f68601..cd5c480 100755 --- a/sternwarte/index_maint.php +++ b/sternwarte/index_maint.php @@ -87,7 +87,7 @@ include 'maintenance.php'; Für diese Führungen gelten folgende Regeln

Anmeldung zu öffentlichen Führungen diff --git a/sternwarte/intern/sofue/js/sofue.js b/sternwarte/intern/sofue/js/sofue.js index a76d59e..d7bc793 100755 --- a/sternwarte/intern/sofue/js/sofue.js +++ b/sternwarte/intern/sofue/js/sofue.js @@ -2,7 +2,7 @@ //globale Variable var maint = false; // Wartung?? -var ajaxURL="php/sofueDB.php"; +var ajaxURL="../../DB4js_all.php" var beos = []; // 0 1 2 3 (4) (5) @@ -54,7 +54,7 @@ function buildEntryScreen(id) { // Übergenen Zeit testen, ob sie mit 1900 oder 0000 startet function check1900(termin) { - if (termin.startsWith("1900") || termin.startsWith("0000")) { + if (termin === null || termin.startsWith("1900") || termin.startsWith("0000")) { return true; } return false; diff --git a/sternwarte/intern/statistik/js/statistic.js b/sternwarte/intern/statistik/js/statistic.js index 30e74ed..e40edd7 100755 --- a/sternwarte/intern/statistik/js/statistic.js +++ b/sternwarte/intern/statistik/js/statistic.js @@ -7,7 +7,7 @@ $(document).ready(function() { // Globals: - const url = "php/statistic.php"; + const url = "../../DB4js_all.php"; const months = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ]; const colors = { besucher: ['#FFB60A','#FF6702','#E54818'], aktivitaet: ['#D1D8D1','#ABC1C5','#81ACBC'], gesamt: ['#CBD26A','#88AD63','#5A8A40'] }; const barsPerPage = 23; diff --git a/sternwarte/kalender/css/kalender.css b/sternwarte/kalender/css/kalender.css index 81dc643..647b862 100644 --- a/sternwarte/kalender/css/kalender.css +++ b/sternwarte/kalender/css/kalender.css @@ -47,3 +47,7 @@ body { #beonamen { font-size: 80%; } + +.fc { + --fc-today-bg-color: rgba(129, 222, 201, 0.75); +} \ No newline at end of file diff --git a/sternwarte/kalender/index.html b/sternwarte/kalender/index.html index 4894321..603a792 100644 --- a/sternwarte/kalender/index.html +++ b/sternwarte/kalender/index.html @@ -10,10 +10,10 @@ - + - + diff --git a/sternwarte/kalender/js/kalender.js b/sternwarte/kalender/js/kalender.js index 8f6e8e1..fac2533 100644 --- a/sternwarte/kalender/js/kalender.js +++ b/sternwarte/kalender/js/kalender.js @@ -1,9 +1,10 @@ // calendar.js document.addEventListener('DOMContentLoaded', async function () { + const DateTime = luxon.DateTime; const months_short = [0, 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']; const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstg', 'Freitag', 'Samstag', 'Sonntag']; - const url = '../DB4js.php'; + const url = '../DB4js_all.php'; const default_dauer = 90; // Standardführung dauert 90min let fuehrungszeiten; let isedit; @@ -230,7 +231,7 @@ document.addEventListener('DOMContentLoaded', async function () { $('#txtTitle').val(''); $('#txtBeschr').val(''); let ret = await putToDbase({cmd: 'DEL_CALENTRY', id: id}); - if (ret != true) { + if (ret.success != true) { alert(`Fehler beim Löschen des Eintrages !`); } calendar.refetchEvents(); @@ -291,9 +292,12 @@ document.addEventListener('DOMContentLoaded', async function () { // Return: // entweder die Startzeit, falls gefunden oder aber 20 [Uhr] function getFuehrungszeitZeit() { - if (fuehrungszeiten[3].start !== undefined) { - let st = moment(fuehrungszeiten[3].start); - return st.hour(); + if (fuehrungszeiten && fuehrungszeiten.length > 3 && fuehrungszeiten[3].start) { + let st = DateTime.fromFormat(String(fuehrungszeiten[3].start), 'yyyyMMdd'); + if (fuehrungszeiten[3].uhr) { + st = st.plus({ hours: fuehrungszeiten[3].uhr }); + } + return st.hour; } else { return 20; } @@ -309,46 +313,43 @@ document.addEventListener('DOMContentLoaded', async function () { function fillModal(st_seldate, end_seldate) { let start, end; if (isedit) { - start = moment(st_seldate); - end = moment(end_seldate); + start = DateTime.fromJSDate(st_seldate); + end = DateTime.fromJSDate(end_seldate); } else { - start = moment(st_seldate); - start.hour(getFuehrungszeitZeit()); - end = moment(st_seldate); - end.hour(getFuehrungszeitZeit()); - end = end.add(default_dauer, 'm'); + start = DateTime.fromJSDate(st_seldate).set({ hour: getFuehrungszeitZeit() }); + end = DateTime.fromJSDate(st_seldate).set({ hour: getFuehrungszeitZeit() }).plus({ minutes: default_dauer }); $('#txtTitle').val(''); $('#txtBeschr').val(''); } $('#st_date_day #end_date_day').html(''); $('#end_date_day').html(''); for (let i = 1; i <= 31; i++) { - $('#st_date_day').append(``); - $('#end_date_day').append(``); + $('#st_date_day').append(``); + $('#end_date_day').append(``); } $('#st_date_month #end_date_month').html(''); $('#end_date_month').html(''); for (let i = 1; i <= 12; i++) { - $('#st_date_month').append(``); - $('#end_date_month').append(``); + $('#st_date_month').append(``); + $('#end_date_month').append(``); } $('#st_date_year #end_date_year').html(''); $('#end_date_year').html(''); for (let i = 2020; i <= 2030; i++) { - $('#st_date_year').append(``); - $('#end_date_year').append(``); + $('#st_date_year').append(``); + $('#end_date_year').append(``); } $('#st_date_hours').html(''); $('#end_date_hours').html(''); for (let i = 0; i <= 23; i++) { - $('#st_date_hours').append(``); - $('#end_date_hours').append(``); + $('#st_date_hours').append(``); + $('#end_date_hours').append(``); } $('#st_date_minutes').html(''); $('#end_date_minutes').html(''); for (let i = 0; i <= 50; i += 10) { - $('#st_date_minutes').append(``); - $('#end_date_minutes').append(``); + $('#st_date_minutes').append(``); + $('#end_date_minutes').append(``); } } @@ -387,9 +388,9 @@ document.addEventListener('DOMContentLoaded', async function () { // Zuerst die regelmäßigen Führungen hole fuehrungszeiten = await fetchFromDbase({cmd: 'GET_FDATES', start: start, end: end}); for (let i = 0; i < fuehrungszeiten.length; i++) { - let start = moment(fuehrungszeiten[i].start); - start.add(fuehrungszeiten[i].uhr,'h') - fuehrungszeiten[i].start = moment(start).format() + let start = DateTime.fromFormat(fuehrungszeiten[i].start, 'yyyyMMdd'); + start = start.plus({ hours: fuehrungszeiten[i].uhr }); + fuehrungszeiten[i].start = start.toISO(); let kurz = checkGroupinBeos(beos, fuehrungszeiten[i]); if (kurz.k != "") { fuehrungszeiten[i].title += " " + kurz.k; @@ -433,16 +434,16 @@ document.addEventListener('DOMContentLoaded', async function () { // Array mit den Feiertagen async function getHolidays(start, end) { let data = []; - let startyear = moment(start).year(); - let endyear = moment(end).year(); + let startyear = DateTime.fromJSDate(start).year; + let endyear = DateTime.fromJSDate(end).year; let response = await fetch('https://feiertage-api.de/api/?jahr=' + startyear + '&nur_land=BW'); let holidays = await response.json(); for (const [k, v] of Object.entries(holidays)) { if(k == "Ostermontag") { - data.push({start: moment(v.datum).subtract(1,'days').format("YYYY-MM-DD"), title: "Ostersonntag"}); + data.push({start: DateTime.fromISO(v.datum).minus({ days: 1 }).toFormat('yyyy-MM-dd'), title: "Ostersonntag"}); } if(k == "Pfingstmontag") { - data.push({start: moment(v.datum).subtract(1,'days').format("YYYY-MM-DD"), title: "Pfingstsonntag"}); + data.push({start: DateTime.fromISO(v.datum).minus({ days: 1 }).toFormat('yyyy-MM-dd'), title: "Pfingstsonntag"}); } data.push({start: v.datum, title: k}); } @@ -462,20 +463,20 @@ document.addEventListener('DOMContentLoaded', async function () { // Return: // Array mit den Sonntagen function getSundays(dt) { - let year = moment(dt).year(); - const cm = moment(dt).month() - if (moment(dt).month() == 11) { + let year = DateTime.fromJSDate(dt).year; + const cm = DateTime.fromJSDate(dt).month; + if (DateTime.fromJSDate(dt).month == 12) { year += 1; } let data = []; for (let i = 1; i <= 12; i++) { - let d = moment(year + '-' + i + '-01'); - let w = d.isoWeekday(); - let dt = '' + let d = DateTime.fromObject({ year: year, month: i, day: 1 }); + let w = d.weekday; + let dt = ''; if (w == 7) { - dt = d.format('YYYY-MM-DD'); + dt = d.toFormat('yyyy-MM-dd'); } else { - dt = d.add(7 - w, 'd').format('YYYY-MM-DD') + dt = d.plus({ days: 7 - w }).toFormat('yyyy-MM-dd'); } data.push({start: dt + 'T11:00:00', uhr: 11, title: 'Sonnenführung' }) } @@ -510,17 +511,18 @@ document.addEventListener('DOMContentLoaded', async function () { // Informationen einer Regelführung für das Popup zusammenbauen function getRegularInfo(entryInfo) { - let curDate = moment(entryInfo.start).format('YYYYMMDD'); + let dt = DateTime.fromJSDate(entryInfo.start); + let curDate = dt.toFormat('yyyyMMdd'); let besucher = entryInfo._def.extendedProps.count; if (besucher == null) { besucher = "0"} besucher = parseInt(besucher) - let wtg = moment(entryInfo.start).isoWeekday(); + let wtg = dt.weekday; let nbr = entryInfo.title.split(' '); let str = `

${weekdays[wtg - 1]}s-Team ${nbr[1]}
`; str += `
${entryInfo._def.extendedProps.namen}
`; let btxt = besucher != 0 ? `${besucher} angemeldete Besucher` : 'Keine Anmeldungen'; str += btxt; - str += `
Von ${moment(entryInfo.start).format("HH:mm")} Uhr bis: ${moment(entryInfo.start).add(default_dauer, 'm').format("HH:mm")} Uhr`; + str += `
Von ${dt.toFormat('HH:mm')} Uhr bis: ${dt.plus({ minutes: default_dauer }).toFormat('HH:mm')} Uhr`; return str; } @@ -529,7 +531,7 @@ document.addEventListener('DOMContentLoaded', async function () { // Wird bei dem Popup und bei dem Ändern/löschen verwendent function getFuehrungsInfo(entryInfo) { let str = entryInfo._def.extendedProps.description; - str += `

Start: ${moment(entryInfo.start).format("YYYY-MM-DD HH:mm")} Uhr
Ende: ${moment(entryInfo.end).format("YYYY-MM-DD HH:mm")} Uhr`; + str += `

Start: ${DateTime.fromJSDate(entryInfo.start).toFormat('yyyy-MM-dd HH:mm')} Uhr
Ende: ${DateTime.fromJSDate(entryInfo.end).toFormat('yyyy-MM-dd HH:mm')} Uhr`; return str; } diff --git a/sternwarte/kalender/js/version.js b/sternwarte/kalender/js/version.js index 7c765ce..3639d17 100644 --- a/sternwarte/kalender/js/version.js +++ b/sternwarte/kalender/js/version.js @@ -1,12 +1,17 @@ // VersiosNummern und -Geschichte -var VERSION="1.3.2"; -var VDATE="2024-09-20"; +var VERSION="1.3.3"; +var VDATE="2025-12-01"; /* History Rev. Datum Entwickler + 1.3.3 2025-12-01 rxf + - 'heute' anders eingefärbt + - PHP-Interface nun DB4js_all.php + - anstelle 'moment' nun 'luxon' für die DateTime-Sachen verwendet + 1.3.2 2024-09-20 rxf - Sonnenführunge mit anzeigen diff --git a/sternwarte/phpmailer/dosendmail.php b/sternwarte/phpmailer/dosendmail.php index 897c69b..2452dee 100644 --- a/sternwarte/phpmailer/dosendmail.php +++ b/sternwarte/phpmailer/dosendmail.php @@ -67,7 +67,11 @@ function sendmail($subject, $from, $body, $cc=[], $bcc=[], $to=[]) { // BCC if (count($bcc) != 0) { foreach ($bcc as $bc) { - $mail->addBCC($bc); + if ($develop == 'true') { + $mail->addCC($bc); + } else { + $mail->addBCC($bc); + } } } diff --git a/sternwarte/sofianmeldung.php b/sternwarte/sofianmeldung.php index c3c3279..43caa4a 100644 --- a/sternwarte/sofianmeldung.php +++ b/sternwarte/sofianmeldung.php @@ -252,8 +252,6 @@ "$stern_vorname $stern_name um $stern_zeit Uhr " . "für $stern_teil $person." . "\r\n\r\n" . - "Bitte bringen Sie diese Bestätigung als Ausdruck oder digital zur Führung mit. \r\n". - "Ohne diese Bestätigung erfolgt ausnahmslos k e i n Einlass.\r\n\r\n" . "Die Führung findet NUR bei klarem Himmel statt. Falls der Himmel bedeckt ist " . "und die Führung ausfällt, erhalten Sie bis spätestens eine Stunde vor Beginn der Finsternis " . "eine Email.\r\n\r\n" . @@ -269,8 +267,6 @@ "auf der Sternwarte Welzheim für

" . "

$stern_vorname $stern_name um $stern_zeit Uhr " . "für $stern_teil $person.

" . - "

Bitte bringen Sie diese Bestätigung als Ausdruck oder digital zur Führung mit.
". - "Ohne diese Bestätigung erfolgt ausnahmslos kein Einlass.

" . "

Die Führung findet nur bei klarem Himmel statt. Falls der Himmel bedeckt ist " . "und die Führung ausfällt, erhalten Sie bis spätestens eine Stunde vor Beginn der Finsternis " . "eine Email.

" . @@ -357,8 +353,7 @@

Wenn Sie alle Felder ausgefüllt und abgeschickt haben (mit dem "Anmeldung senden"-Knopf), - erhalten Sie eine Anmeldebestätigung per e-mail. Diese bitte unbedingt zur Führung - ausgedruckt oder in digitaler Form mitbringen! + erhalten Sie eine Anmeldebestätigung per e-mail.

Ohne die mitgebrachte Anmeldebestätigung erfolgt ausnahmslos k e i n Einlass. @@ -472,7 +467,7 @@

Hinweis zum Datenschutz: Datenschutzerklärung

-

Letzte Änderungen: 2022-08-17 rxf

+

Letzte Änderungen: 2025-12-01 rxf

diff --git a/sternwarte/storno/js/storno.js b/sternwarte/storno/js/storno.js index 45c9049..7f9e07e 100644 --- a/sternwarte/storno/js/storno.js +++ b/sternwarte/storno/js/storno.js @@ -6,7 +6,7 @@ $(document).ready(() => { // Globale Konstanten und Variable // const ajaxURL="php/anmeldDB.php"; - const ajaxURL = "../../DB4js.php"; + const ajaxURL = "../../DB4js_all.php"; const maxVisitors = 25 const months2add = 3