feat: Add initial SaaS application structure with .htaccess, index.php, and environment setup scripts
- Create .htaccess for Apache front-controller routing - Add README.md for public directory with project overview - Implement index.php as the main entry point with a preview of SaaS modules - Introduce PowerShell scripts to check prerequisites and prepare environment
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# Kaffeeliste SaaS Workspace
|
||||
|
||||
Dieses Repository ist jetzt `SaaS-first` organisiert.
|
||||
|
||||
- `saas-app/` enthaelt die neue Zielanwendung fuer die mandantenfaehige
|
||||
Kaffeeliste.
|
||||
- `docs/` enthaelt Architektur-, Installations- und Migrationsdokumentation.
|
||||
- `legacy-app/` enthaelt den bisherigen PHP-Bestand als archivierte Referenz fuer
|
||||
Fachlogik und Datenmigration.
|
||||
|
||||
## Produktkern
|
||||
|
||||
Die SaaS-Version behaelt die wesentlichen Funktionen der alten Anwendung bei:
|
||||
|
||||
- persoenliches Dashboard mit Kontostand, Verbrauch und letzten Buchungen
|
||||
- Mitgliederverwaltung pro Mandant
|
||||
- Kaffee-Striche, Einzahlungen und Salden als gemeinsames Ledger
|
||||
- Hinweise, FAQ und tenantbezogene Inhalte
|
||||
- operative Importe, Exporte und Benachrichtigungen
|
||||
|
||||
Nicht mehr priorisierte Sonderseiten und Einmalskripte bleiben nur noch im
|
||||
Archivbestand erhalten.
|
||||
|
||||
## Einstieg
|
||||
|
||||
1. Lies [docs/implementation-foundation.md](docs/implementation-foundation.md)
|
||||
fuer Zielbild und Scope.
|
||||
2. Nutze [docs/installationshandbuch.md](docs/installationshandbuch.md) fuer
|
||||
Setup, Hosting und Betriebsablauf.
|
||||
3. Arbeite anschliessend in [saas-app/README.md](saas-app/README.md) weiter.
|
||||
|
||||
## Hilfsskripte
|
||||
|
||||
- `scripts/check-prerequisites.ps1` prueft lokale Voraussetzungen.
|
||||
- `scripts/prepare-saas-env.ps1` legt aus `.env.example` eine lokale `.env` an.
|
||||
|
||||
## Hinweise Zum Umbau
|
||||
|
||||
- `legacy-app/` ist absichtlich nicht geloescht, sondern als Referenz fuer die
|
||||
Daten- und Fachmigration verschoben.
|
||||
- Das aktuelle `saas-app/` ist eine konsistente Zielarchitektur mit ueberarbeiteten
|
||||
Views, Modulgrenzen und Betriebsdokumentation.
|
||||
- Ein vollstaendiges Laravel-Bootstrap mit Composer und Runtime bleibt der
|
||||
naechste technische Ausbauschritt.
|
||||
@@ -1,33 +1,52 @@
|
||||
# Implementation Foundation
|
||||
# SaaS First Zielbild
|
||||
|
||||
Das neue Zielprojekt liegt in `saas-app/`, damit der bisherige PHP-Bestand
|
||||
unangetastet als Referenz bestehen bleibt.
|
||||
Dieses Repository wird schrittweise von der Legacy-PHP-Anwendung auf eine
|
||||
mandantenfaehige SaaS-Struktur umgestellt. Das neue Zielprojekt liegt in
|
||||
`saas-app/`. Der Root-Bestand bleibt nur noch als Referenz fuer die bestehende
|
||||
Fachlogik erhalten.
|
||||
|
||||
Foundation-Stand:
|
||||
## Was in die SaaS-Version gehoert
|
||||
|
||||
- Laravel-nahe Ordnerstruktur ohne externe Downloads
|
||||
- Tenant-Resolution-Skelett ueber Host/Subdomain
|
||||
- Request-Context-Platzhalter
|
||||
- Grundrouten fuer Landing, Login und Dashboard
|
||||
- erste SQL-Migrationsskizzen fuer:
|
||||
- `tenants`
|
||||
- `users`
|
||||
- `tenant_users`
|
||||
- `roles`
|
||||
- `tenant_user_roles`
|
||||
- Blade-Layouts als Platzhalter fuer SSR-Ansatz auf Webspace
|
||||
Der fachliche Kern der bisherigen Anwendung ist klein und wird in der neuen
|
||||
Version gebuendelt:
|
||||
|
||||
Naechste Programmierphase:
|
||||
- Dashboard mit Kontostand und aktueller Uebersicht
|
||||
- Mitgliederverwaltung pro Mandant
|
||||
- Einzahlungen und Kaffee-Striche als Ledger-Buchungen
|
||||
- Hinweise, FAQ und einfache Inhalte
|
||||
- Export- und Import-Funktionen fuer den operativen Betrieb
|
||||
- Mandanten- und Rollenverwaltung
|
||||
|
||||
1. Identity-/Tenant-Agent auf `saas-app/app` und Auth-/Tenant-Module
|
||||
2. Ledger-/Core-Agent auf Mitglieder, Striche, Einzahlungen und Dashboard
|
||||
3. spaeter Operations-Agent fuer Importe, Mail, Umfragen und Exporte
|
||||
## Was bewusst entfallen kann
|
||||
|
||||
Blocker ausserhalb des Repos:
|
||||
Diese Bereiche sind fuer den ersten SaaS-Stand nicht zwingend notwendig und
|
||||
koennen spaeter nachgezogen oder ganz entfallen:
|
||||
|
||||
- `php` lokal nicht installiert
|
||||
- `composer` lokal nicht installiert
|
||||
- echtes Laravel-Scaffolding daher noch nicht moeglich
|
||||
- Jahresauswertung als Sonderprozess
|
||||
- CSV-Sonderlogiken aus der alten Webanwendung
|
||||
- manuelle Mail-Sammelaktionen ohne Workflow-Einbindung
|
||||
- Umfrage-Module, sofern sie fachlich nicht mehr benoetigt werden
|
||||
- alte PHP-Einzeldateien im Root, sobald die SaaS-Variante produktiv ist
|
||||
|
||||
Sobald Tooling vorhanden ist, soll dieses Geruest in ein vollstaendiges
|
||||
Laravel-Projekt ueberfuehrt werden.
|
||||
## Migrationspfad
|
||||
|
||||
1. Legacy-Fachlogik aus dem Root als Referenz verstehen.
|
||||
2. Kernbereiche in `saas-app/` neu umsetzen.
|
||||
3. Datenmodell auf Mandanten, Benutzer, Mitglieder, Buchungen und Inhalte
|
||||
normalisieren.
|
||||
4. Root-Anwendung nur noch fuer die Uebergangsphase vorhalten.
|
||||
5. Nach erfolgreichem Cutover alte Root-Seiten deaktivieren oder archivieren.
|
||||
|
||||
## Technische Leitplanken
|
||||
|
||||
- `saas-app/` ist die Zielstruktur.
|
||||
- Der Betrieb ist auf klassisches PHP-Hosting ausgerichtet.
|
||||
- Cron-Jobs ersetzen dauerhafte Worker.
|
||||
- OIDC ist der bevorzugte SSO-Pfad.
|
||||
- Blade-Views und SSR sind fuer einfache Hosting-Setups vorgesehen.
|
||||
|
||||
## Derzeitiger Stand
|
||||
|
||||
Das Zielgeruest ist bewusst schlank gehalten. Es beschreibt die Architektur und
|
||||
die Aufteilung der Module, ersetzt aber noch kein voll installiertes Laravel-
|
||||
Projekt mit lauffaehiger Runtime.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# Installationshandbuch
|
||||
|
||||
Diese Anleitung beschreibt den vorgesehenen Weg fuer die SaaS-Version in
|
||||
`saas-app/`. Sie ist auf Webspace-Betrieb ohne Docker und ohne dauerhafte
|
||||
Worker ausgelegt.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- PHP 8.2 oder neuer
|
||||
- Composer
|
||||
- SQL Server oder eine kompatible Datenbank fuer das Zielsystem
|
||||
- Webserver mit Document-Root auf `public/` des Zielprojekts
|
||||
- Cron-Zugang
|
||||
- optional: SMTP-Zugang fuer Mails
|
||||
- optional: OIDC-Provider fuer SSO
|
||||
|
||||
## Installation lokal
|
||||
|
||||
1. Repository klonen.
|
||||
2. In `saas-app/` wechseln.
|
||||
3. Abhaengigkeiten mit Composer installieren.
|
||||
4. `.env` aus `.env.example` ableiten.
|
||||
5. Datenbankzugang, URL, Mail und Tenancy-Werte eintragen.
|
||||
6. Migrations ausfuehren.
|
||||
7. Einen ersten Mandanten anlegen.
|
||||
8. Einen ersten Benutzer und eine Mitgliedszuordnung anlegen.
|
||||
|
||||
## Wichtige Umgebungswerte
|
||||
|
||||
Die wichtigsten Werte liegen in `saas-app/.env.example` und muessen fuer die
|
||||
eigene Umgebung angepasst werden:
|
||||
|
||||
- `APP_URL`
|
||||
- `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`
|
||||
- `TENANCY_MODE`
|
||||
- `TENANCY_CENTRAL_DOMAINS`
|
||||
- `TENANCY_FALLBACK_TENANT`
|
||||
- `OIDC_ENABLED`
|
||||
- Mail-Zugangsdaten
|
||||
|
||||
## Webspace-Deployment
|
||||
|
||||
1. Den Inhalt von `saas-app/` auf den Zielserver hochladen.
|
||||
2. Das Document-Root auf `public/` zeigen lassen.
|
||||
3. Schreibrechte fuer `storage/`, Cache und Queue-Tabellen sicherstellen.
|
||||
4. `.env` serverseitig hinterlegen.
|
||||
5. Die Anwendung einmal per Browser aufrufen und die Grundseiten pruefen.
|
||||
|
||||
## Cron- und Batch-Betrieb
|
||||
|
||||
Die Zielarchitektur nutzt Cron statt dauerhafter Worker.
|
||||
|
||||
Typische Aufgaben:
|
||||
|
||||
- Queue-Jobs verarbeiten
|
||||
- Import-Jobs abarbeiten
|
||||
- Export-Jobs erzeugen
|
||||
- Benachrichtigungen versenden
|
||||
- Aufraeum- und Statusjobs ausfuehren
|
||||
|
||||
Empfehlung: pro Aufgabe einen klar benannten Cron-Eintrag anlegen und die
|
||||
Ausgabe in Logdateien schreiben.
|
||||
|
||||
## Migration aus dem Legacy-System
|
||||
|
||||
Wenn Daten aus der alten Root-Anwendung uebernommen werden sollen, folgt die
|
||||
Reihenfolge:
|
||||
|
||||
1. Mitglieder und Rollen migrieren.
|
||||
2. Einzahlungen und Kaffeebuchungen uebernehmen.
|
||||
3. Hinweise, FAQ und Inhaltsseiten importieren.
|
||||
4. Mandanten-Zuordnung pruefen.
|
||||
5. Danach alte Root-Seiten nur noch lesend oder gar nicht mehr betreiben.
|
||||
|
||||
## Betriebscheck
|
||||
|
||||
Nach dem Setup sollten diese Punkte funktionieren:
|
||||
|
||||
- Login oder SSO-Startseite
|
||||
- Dashboard pro Mandant
|
||||
- Mitgliederliste
|
||||
- Buchungen und Kontostand
|
||||
- Hinweise und Content
|
||||
- Import- und Export-Status
|
||||
|
||||
Wenn einer dieser Bereiche fehlt, liegt meist entweder ein Tenancy-Fehler, ein
|
||||
DB-Problem oder eine unvollstaendige Deployment-Konfiguration vor.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Legacy Zu SaaS Mapping
|
||||
|
||||
Diese Uebersicht verbindet die bisherige Root-Anwendung mit der neuen
|
||||
SaaS-Zielstruktur in `saas-app/`.
|
||||
|
||||
## Kernmodule
|
||||
|
||||
| Legacy-Datei | Bisherige Aufgabe | SaaS-Zielmodul |
|
||||
| --- | --- | --- |
|
||||
| `legacy-app/index.php` | persoenliches Dashboard, Kontostand, letzte Buchungen, Schnellaktion fuer Striche | Dashboard, Ledger, Payments |
|
||||
| `legacy-app/stricheintragen.php` | Sammelerfassung von Kaffee-Strichen | Ledger |
|
||||
| `legacy-app/einzahlung.php` | Sammelerfassung von Einzahlungen | Payments |
|
||||
| `legacy-app/kaffeeliste.php` | operative Gesamtuebersicht aller Mitglieder | Members, Ledger |
|
||||
| `legacy-app/mitarbeiterverwalten.php` | Mitgliederpflege, Aktivstatus, Admin-Rolle | Members, Tenants |
|
||||
| `legacy-app/letzteneintraege.php` | Korrektur und Loeschung letzter Buchungen | Ledger |
|
||||
| `legacy-app/teilnehmerauswertung.php` | Detailauswertung pro Person | Dashboard, Members, Exports |
|
||||
| `legacy-app/namenanpassen.php` | Pflege des Anzeigenamens | Members, Identity |
|
||||
| `legacy-app/hinweise.php` | Pflege globaler Hinweise | Content |
|
||||
| `legacy-app/faq.php` | statische Hilfeseite | Content |
|
||||
|
||||
## Zusatzmodule
|
||||
|
||||
| Legacy-Datei | Einordnung | SaaS-Strategie |
|
||||
| --- | --- | --- |
|
||||
| `legacy-app/csvupload.php` | operativer CSV-Sonderimport | optionales Import-Modul |
|
||||
| `legacy-app/exportKaffeeliste.php` | PDF-Export fuer Papierprozess | optionales Export-Modul |
|
||||
| `legacy-app/mailversenden.php` | Sammelbenachrichtigungen | Notifications |
|
||||
| `legacy-app/jahresauswertung.php` | Sonderprozess | spaeter oder Entfall |
|
||||
| `legacy-app/umfrage.php` | Zusatzfunktion | optionales Survey-Modul |
|
||||
| `legacy-app/umfrageergebnisse.php` | Zusatzfunktion | optionales Survey-Modul |
|
||||
| `legacy-app/mailausgebe.php` | Hilfs-/Debugseite | Entfall |
|
||||
|
||||
## Datenmodell
|
||||
|
||||
| Legacy-Tabelle | SaaS-Ziel |
|
||||
| --- | --- |
|
||||
| `kl_Mitarbeiter` | `users`, `tenant_users`, `members` |
|
||||
| `kl_Kaffeeverbrauch` | `coffee_entries`, `ledger_entries` |
|
||||
| `kl_Einzahlungen` | `payment_entries`, `ledger_entries` |
|
||||
| `kl_hinweise` | `announcements` |
|
||||
| `kl_config` | tenantbezogene Einstellungen und Feature-Flags |
|
||||
|
||||
## Prioritaet Fuer Die Umsetzung
|
||||
|
||||
1. Dashboard, Members, Ledger und Payments funktional schliessen.
|
||||
2. Content und Hinweise tenantfaehig machen.
|
||||
3. Importe, Exporte und Notifications als Backoffice-Module ergaenzen.
|
||||
4. Surveys und Sonderprozesse nur bei echtem Bedarf uebernehmen.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Legacy App Archiv
|
||||
|
||||
Dieses Verzeichnis enthaelt den bisherigen PHP-Bestand der Kaffeeliste.
|
||||
|
||||
Es bleibt aus drei Gruenden im Repository:
|
||||
|
||||
- als Referenz fuer die bestehende Fachlogik
|
||||
- als Quelle fuer Datenmigrationen in die SaaS-Version
|
||||
- als Rueckfalloption waehrend der Uebergangsphase
|
||||
|
||||
## Wichtige Legacy-Bereiche
|
||||
|
||||
- `index.php`: persoenliches Dashboard
|
||||
- `stricheintragen.php`: Sammelerfassung fuer Kaffee-Striche
|
||||
- `einzahlung.php`: Sammelerfassung fuer Einzahlungen
|
||||
- `kaffeeliste.php`: operative Gesamtuebersicht
|
||||
- `mitarbeiterverwalten.php`: Mitglieder- und Rollenpflege
|
||||
- `letzteneintraege.php`: Korrektur letzter Buchungen
|
||||
- `hinweise.php`: Banner/Hinweise
|
||||
|
||||
## Umgang Mit Dem Archiv
|
||||
|
||||
- Keine neuen Produktfunktionen mehr hier entwickeln.
|
||||
- Nur noch fuer Referenz, Datenabgleich oder Notfallbetrieb verwenden.
|
||||
- Neue Arbeit findet ausschliesslich in `../saas-app/` und `../docs/` statt.
|
||||
@@ -1,9 +1,9 @@
|
||||
@import url(fontawesome-all.min.css);
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,400italic,600italic|Roboto+Slab:400,700");
|
||||
/*
|
||||
Editorial by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
/*
|
||||
Editorial by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
*/
|
||||
html, body, div, span, applet, object,
|
||||
iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
|
||||
@@ -1,2 +1,2 @@
|
||||
/* breakpoints.js v1.0 | @ajlkn | MIT licensed */
|
||||
/* breakpoints.js v1.0 | @ajlkn | MIT licensed */
|
||||
var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e<t.events.length;e++)n=t.events[e],t.active(n.query)?n.state||(n.state=!0,n.handler()):n.state&&(n.state=!1)}};return e._=t,e.on=function(e,n){t.on(e,n)},e.active=function(e){return t.active(e)},e}();!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.breakpoints=t()}(this,function(){return breakpoints});
|
||||
@@ -1,2 +1,2 @@
|
||||
/* browser.js v1.0.1 | @ajlkn | MIT licensed */
|
||||
/* browser.js v1.0.1 | @ajlkn | MIT licensed */
|
||||
var browser=function(){"use strict";var t={name:null,version:null,os:null,osVersion:null,touch:null,mobile:null,_canUse:null,canUse:function(e){t._canUse||(t._canUse=document.createElement("div"));var n=t._canUse.style,r=e.charAt(0).toUpperCase()+e.slice(1);return e in n||"Moz"+r in n||"Webkit"+r in n||"O"+r in n||"ms"+r in n},init:function(){for(var e=navigator.userAgent,n="other",r=0,i=[["firefox",/Firefox\/([0-9\.]+)/],["bb",/BlackBerry.+Version\/([0-9\.]+)/],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/],["opera",/OPR\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)/],["edge",/Edge\/([0-9\.]+)/],["safari",/Version\/([0-9\.]+).+Safari/],["chrome",/Chrome\/([0-9\.]+)/],["ie",/MSIE ([0-9]+)/],["ie",/Trident\/.+rv:([0-9]+)/]],o=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(RegExp.$1);break}for(t.name=n,t.version=r,n="other",i=[["ios",/([0-9_]+) like Mac OS X/,function(e){return e.replace("_",".").replace("_","")}],["ios",/CPU like Mac OS X/,function(e){return 0}],["wp",/Windows Phone ([0-9\.]+)/,null],["android",/Android ([0-9\.]+)/,null],["mac",/Macintosh.+Mac OS X ([0-9_]+)/,function(e){return e.replace("_",".").replace("_","")}],["windows",/Windows NT ([0-9\.]+)/,null],["bb",/BlackBerry.+Version\/([0-9\.]+)/,null],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/,null],["linux",/Linux/,null],["bsd",/BSD/,null],["unix",/X11/,null]],o=r=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(i[o][2]?i[o][2](RegExp.$1):RegExp.$1);break}"mac"==n&&"ontouchstart"in window&&(1024==screen.width&&1366==screen.height||834==screen.width&&1112==screen.height||810==screen.width&&1080==screen.height||768==screen.width&&1024==screen.height)&&(n="ios"),t.os=n,t.osVersion=r,t.touch="wp"==t.os?0<navigator.msMaxTouchPoints:!!("ontouchstart"in window),t.mobile="wp"==t.os||"android"==t.os||"ios"==t.os||"bb"==t.os}};return t.init(),t}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser});
|
||||
@@ -1,262 +1,262 @@
|
||||
/*
|
||||
Editorial by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var $window = $(window),
|
||||
$head = $('head'),
|
||||
$body = $('body');
|
||||
|
||||
// Breakpoints.
|
||||
breakpoints({
|
||||
xlarge: [ '1281px', '1680px' ],
|
||||
large: [ '981px', '1280px' ],
|
||||
medium: [ '737px', '980px' ],
|
||||
small: [ '481px', '736px' ],
|
||||
xsmall: [ '361px', '480px' ],
|
||||
xxsmall: [ null, '360px' ],
|
||||
'xlarge-to-max': '(min-width: 1681px)',
|
||||
'small-to-xlarge': '(min-width: 481px) and (max-width: 1680px)'
|
||||
});
|
||||
|
||||
// Stops animations/transitions until the page has ...
|
||||
|
||||
// ... loaded.
|
||||
$window.on('load', function() {
|
||||
window.setTimeout(function() {
|
||||
$body.removeClass('is-preload');
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// ... stopped resizing.
|
||||
var resizeTimeout;
|
||||
|
||||
$window.on('resize', function() {
|
||||
|
||||
// Mark as resizing.
|
||||
$body.addClass('is-resizing');
|
||||
|
||||
// Unmark after delay.
|
||||
clearTimeout(resizeTimeout);
|
||||
|
||||
resizeTimeout = setTimeout(function() {
|
||||
$body.removeClass('is-resizing');
|
||||
}, 100);
|
||||
|
||||
});
|
||||
|
||||
// Fixes.
|
||||
|
||||
// Object fit images.
|
||||
if (!browser.canUse('object-fit')
|
||||
|| browser.name == 'safari')
|
||||
$('.image.object').each(function() {
|
||||
|
||||
var $this = $(this),
|
||||
$img = $this.children('img');
|
||||
|
||||
// Hide original image.
|
||||
$img.css('opacity', '0');
|
||||
|
||||
// Set background.
|
||||
$this
|
||||
.css('background-image', 'url("' + $img.attr('src') + '")')
|
||||
.css('background-size', $img.css('object-fit') ? $img.css('object-fit') : 'cover')
|
||||
.css('background-position', $img.css('object-position') ? $img.css('object-position') : 'center');
|
||||
|
||||
});
|
||||
|
||||
// Sidebar.
|
||||
var $sidebar = $('#sidebar'),
|
||||
$sidebar_inner = $sidebar.children('.inner');
|
||||
|
||||
// Inactive by default on <= large.
|
||||
breakpoints.on('<=large', function() {
|
||||
$sidebar.addClass('inactive');
|
||||
});
|
||||
|
||||
breakpoints.on('>large', function() {
|
||||
$sidebar.removeClass('inactive');
|
||||
});
|
||||
|
||||
// Hack: Workaround for Chrome/Android scrollbar position bug.
|
||||
if (browser.os == 'android'
|
||||
&& browser.name == 'chrome')
|
||||
$('<style>#sidebar .inner::-webkit-scrollbar { display: none; }</style>')
|
||||
.appendTo($head);
|
||||
|
||||
// Toggle.
|
||||
$('<a href="#sidebar" class="toggle">Toggle</a>')
|
||||
.appendTo($sidebar)
|
||||
.on('click', function(event) {
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Toggle.
|
||||
$sidebar.toggleClass('inactive');
|
||||
|
||||
});
|
||||
|
||||
// Events.
|
||||
|
||||
// Link clicks.
|
||||
$sidebar.on('click', 'a', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Vars.
|
||||
var $a = $(this),
|
||||
href = $a.attr('href'),
|
||||
target = $a.attr('target');
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Check URL.
|
||||
if (!href || href == '#' || href == '')
|
||||
return;
|
||||
|
||||
// Hide sidebar.
|
||||
$sidebar.addClass('inactive');
|
||||
|
||||
// Redirect to href.
|
||||
setTimeout(function() {
|
||||
|
||||
if (target == '_blank')
|
||||
window.open(href);
|
||||
else
|
||||
window.location.href = href;
|
||||
|
||||
}, 500);
|
||||
|
||||
});
|
||||
|
||||
// Prevent certain events inside the panel from bubbling.
|
||||
$sidebar.on('click touchend touchstart touchmove', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Prevent propagation.
|
||||
event.stopPropagation();
|
||||
|
||||
});
|
||||
|
||||
// Hide panel on body click/tap.
|
||||
$body.on('click touchend', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Deactivate.
|
||||
$sidebar.addClass('inactive');
|
||||
|
||||
});
|
||||
|
||||
// Scroll lock.
|
||||
// Note: If you do anything to change the height of the sidebar's content, be sure to
|
||||
// trigger 'resize.sidebar-lock' on $window so stuff doesn't get out of sync.
|
||||
|
||||
$window.on('load.sidebar-lock', function() {
|
||||
|
||||
var sh, wh, st;
|
||||
|
||||
// Reset scroll position to 0 if it's 1.
|
||||
if ($window.scrollTop() == 1)
|
||||
$window.scrollTop(0);
|
||||
|
||||
$window
|
||||
.on('scroll.sidebar-lock', function() {
|
||||
|
||||
var x, y;
|
||||
|
||||
// <=large? Bail.
|
||||
if (breakpoints.active('<=large')) {
|
||||
|
||||
$sidebar_inner
|
||||
.data('locked', 0)
|
||||
.css('position', '')
|
||||
.css('top', '');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Calculate positions.
|
||||
x = Math.max(sh - wh, 0);
|
||||
y = Math.max(0, $window.scrollTop() - x);
|
||||
|
||||
// Lock/unlock.
|
||||
if ($sidebar_inner.data('locked') == 1) {
|
||||
|
||||
if (y <= 0)
|
||||
$sidebar_inner
|
||||
.data('locked', 0)
|
||||
.css('position', '')
|
||||
.css('top', '');
|
||||
else
|
||||
$sidebar_inner
|
||||
.css('top', -1 * x);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (y > 0)
|
||||
$sidebar_inner
|
||||
.data('locked', 1)
|
||||
.css('position', 'fixed')
|
||||
.css('top', -1 * x);
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.on('resize.sidebar-lock', function() {
|
||||
|
||||
// Calculate heights.
|
||||
wh = $window.height();
|
||||
sh = $sidebar_inner.outerHeight() + 30;
|
||||
|
||||
// Trigger scroll.
|
||||
$window.trigger('scroll.sidebar-lock');
|
||||
|
||||
})
|
||||
.trigger('resize.sidebar-lock');
|
||||
|
||||
});
|
||||
|
||||
// Menu.
|
||||
var $menu = $('#menu'),
|
||||
$menu_openers = $menu.children('ul').find('.opener');
|
||||
|
||||
// Openers.
|
||||
$menu_openers.each(function() {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$this.on('click', function(event) {
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
|
||||
// Toggle.
|
||||
$menu_openers.not($this).removeClass('active');
|
||||
$this.toggleClass('active');
|
||||
|
||||
// Trigger resize (sidebar lock).
|
||||
$window.triggerHandler('resize.sidebar-lock');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Editorial by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var $window = $(window),
|
||||
$head = $('head'),
|
||||
$body = $('body');
|
||||
|
||||
// Breakpoints.
|
||||
breakpoints({
|
||||
xlarge: [ '1281px', '1680px' ],
|
||||
large: [ '981px', '1280px' ],
|
||||
medium: [ '737px', '980px' ],
|
||||
small: [ '481px', '736px' ],
|
||||
xsmall: [ '361px', '480px' ],
|
||||
xxsmall: [ null, '360px' ],
|
||||
'xlarge-to-max': '(min-width: 1681px)',
|
||||
'small-to-xlarge': '(min-width: 481px) and (max-width: 1680px)'
|
||||
});
|
||||
|
||||
// Stops animations/transitions until the page has ...
|
||||
|
||||
// ... loaded.
|
||||
$window.on('load', function() {
|
||||
window.setTimeout(function() {
|
||||
$body.removeClass('is-preload');
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// ... stopped resizing.
|
||||
var resizeTimeout;
|
||||
|
||||
$window.on('resize', function() {
|
||||
|
||||
// Mark as resizing.
|
||||
$body.addClass('is-resizing');
|
||||
|
||||
// Unmark after delay.
|
||||
clearTimeout(resizeTimeout);
|
||||
|
||||
resizeTimeout = setTimeout(function() {
|
||||
$body.removeClass('is-resizing');
|
||||
}, 100);
|
||||
|
||||
});
|
||||
|
||||
// Fixes.
|
||||
|
||||
// Object fit images.
|
||||
if (!browser.canUse('object-fit')
|
||||
|| browser.name == 'safari')
|
||||
$('.image.object').each(function() {
|
||||
|
||||
var $this = $(this),
|
||||
$img = $this.children('img');
|
||||
|
||||
// Hide original image.
|
||||
$img.css('opacity', '0');
|
||||
|
||||
// Set background.
|
||||
$this
|
||||
.css('background-image', 'url("' + $img.attr('src') + '")')
|
||||
.css('background-size', $img.css('object-fit') ? $img.css('object-fit') : 'cover')
|
||||
.css('background-position', $img.css('object-position') ? $img.css('object-position') : 'center');
|
||||
|
||||
});
|
||||
|
||||
// Sidebar.
|
||||
var $sidebar = $('#sidebar'),
|
||||
$sidebar_inner = $sidebar.children('.inner');
|
||||
|
||||
// Inactive by default on <= large.
|
||||
breakpoints.on('<=large', function() {
|
||||
$sidebar.addClass('inactive');
|
||||
});
|
||||
|
||||
breakpoints.on('>large', function() {
|
||||
$sidebar.removeClass('inactive');
|
||||
});
|
||||
|
||||
// Hack: Workaround for Chrome/Android scrollbar position bug.
|
||||
if (browser.os == 'android'
|
||||
&& browser.name == 'chrome')
|
||||
$('<style>#sidebar .inner::-webkit-scrollbar { display: none; }</style>')
|
||||
.appendTo($head);
|
||||
|
||||
// Toggle.
|
||||
$('<a href="#sidebar" class="toggle">Toggle</a>')
|
||||
.appendTo($sidebar)
|
||||
.on('click', function(event) {
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Toggle.
|
||||
$sidebar.toggleClass('inactive');
|
||||
|
||||
});
|
||||
|
||||
// Events.
|
||||
|
||||
// Link clicks.
|
||||
$sidebar.on('click', 'a', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Vars.
|
||||
var $a = $(this),
|
||||
href = $a.attr('href'),
|
||||
target = $a.attr('target');
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Check URL.
|
||||
if (!href || href == '#' || href == '')
|
||||
return;
|
||||
|
||||
// Hide sidebar.
|
||||
$sidebar.addClass('inactive');
|
||||
|
||||
// Redirect to href.
|
||||
setTimeout(function() {
|
||||
|
||||
if (target == '_blank')
|
||||
window.open(href);
|
||||
else
|
||||
window.location.href = href;
|
||||
|
||||
}, 500);
|
||||
|
||||
});
|
||||
|
||||
// Prevent certain events inside the panel from bubbling.
|
||||
$sidebar.on('click touchend touchstart touchmove', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Prevent propagation.
|
||||
event.stopPropagation();
|
||||
|
||||
});
|
||||
|
||||
// Hide panel on body click/tap.
|
||||
$body.on('click touchend', function(event) {
|
||||
|
||||
// >large? Bail.
|
||||
if (breakpoints.active('>large'))
|
||||
return;
|
||||
|
||||
// Deactivate.
|
||||
$sidebar.addClass('inactive');
|
||||
|
||||
});
|
||||
|
||||
// Scroll lock.
|
||||
// Note: If you do anything to change the height of the sidebar's content, be sure to
|
||||
// trigger 'resize.sidebar-lock' on $window so stuff doesn't get out of sync.
|
||||
|
||||
$window.on('load.sidebar-lock', function() {
|
||||
|
||||
var sh, wh, st;
|
||||
|
||||
// Reset scroll position to 0 if it's 1.
|
||||
if ($window.scrollTop() == 1)
|
||||
$window.scrollTop(0);
|
||||
|
||||
$window
|
||||
.on('scroll.sidebar-lock', function() {
|
||||
|
||||
var x, y;
|
||||
|
||||
// <=large? Bail.
|
||||
if (breakpoints.active('<=large')) {
|
||||
|
||||
$sidebar_inner
|
||||
.data('locked', 0)
|
||||
.css('position', '')
|
||||
.css('top', '');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Calculate positions.
|
||||
x = Math.max(sh - wh, 0);
|
||||
y = Math.max(0, $window.scrollTop() - x);
|
||||
|
||||
// Lock/unlock.
|
||||
if ($sidebar_inner.data('locked') == 1) {
|
||||
|
||||
if (y <= 0)
|
||||
$sidebar_inner
|
||||
.data('locked', 0)
|
||||
.css('position', '')
|
||||
.css('top', '');
|
||||
else
|
||||
$sidebar_inner
|
||||
.css('top', -1 * x);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (y > 0)
|
||||
$sidebar_inner
|
||||
.data('locked', 1)
|
||||
.css('position', 'fixed')
|
||||
.css('top', -1 * x);
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.on('resize.sidebar-lock', function() {
|
||||
|
||||
// Calculate heights.
|
||||
wh = $window.height();
|
||||
sh = $sidebar_inner.outerHeight() + 30;
|
||||
|
||||
// Trigger scroll.
|
||||
$window.trigger('scroll.sidebar-lock');
|
||||
|
||||
})
|
||||
.trigger('resize.sidebar-lock');
|
||||
|
||||
});
|
||||
|
||||
// Menu.
|
||||
var $menu = $('#menu'),
|
||||
$menu_openers = $menu.children('ul').find('.opener');
|
||||
|
||||
// Openers.
|
||||
$menu_openers.each(function() {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$this.on('click', function(event) {
|
||||
|
||||
// Prevent default.
|
||||
event.preventDefault();
|
||||
|
||||
// Toggle.
|
||||
$menu_openers.not($this).removeClass('active');
|
||||
$this.toggleClass('active');
|
||||
|
||||
// Trigger resize (sidebar lock).
|
||||
$window.triggerHandler('resize.sidebar-lock');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,39 @@
|
||||
<?php
|
||||
|
||||
### ZUGANGSDATEN AD
|
||||
$aduser = '';
|
||||
$adpassword = '';
|
||||
$domain = '';
|
||||
## OU für die Suche der Benutzerkonten
|
||||
#$basedn = '';
|
||||
$basedn = '';
|
||||
## OU für die Suche der Benutzerkonten
|
||||
#$basednandereKasse = '';
|
||||
## OU für die Suche der Gruppen
|
||||
$basedngroup = '';
|
||||
## Zugriffsgruppe für Automatisierungsclient
|
||||
$zugriffsACgroup = '';
|
||||
## Zugriffsgruppe für Automatische Abwesenheitsnachricht
|
||||
$zugriffsAbwesenheitgroup = '';
|
||||
## Zugriffsgruppe für alle Anfragen des Automatisierungsclient
|
||||
$zugriffsalleACgroup = '';
|
||||
## Zugriffsgruppe für Anfragen der Abwesenheitsnachrichten
|
||||
$zugriffsalleAbwesenheitgroup = '';
|
||||
## Zugriff auf alles
|
||||
$zugriffsAdminsgroup = '';
|
||||
|
||||
// Verbindung zur Datenbank herstellen (ersetze die Platzhalter durch deine Daten)
|
||||
$serverName = "";
|
||||
$connectionOptions = array(
|
||||
"Database" => "",
|
||||
"Uid" => "",
|
||||
"PWD" => "",
|
||||
"TrustServerCertificate"=>true
|
||||
);
|
||||
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
// Überprüfen der Verbindung
|
||||
if (!$conn) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
|
||||
### ZUGANGSDATEN AD
|
||||
$aduser = '';
|
||||
$adpassword = '';
|
||||
$domain = '';
|
||||
## OU für die Suche der Benutzerkonten
|
||||
#$basedn = '';
|
||||
$basedn = '';
|
||||
## OU für die Suche der Benutzerkonten
|
||||
#$basednandereKasse = '';
|
||||
## OU für die Suche der Gruppen
|
||||
$basedngroup = '';
|
||||
## Zugriffsgruppe für Automatisierungsclient
|
||||
$zugriffsACgroup = '';
|
||||
## Zugriffsgruppe für Automatische Abwesenheitsnachricht
|
||||
$zugriffsAbwesenheitgroup = '';
|
||||
## Zugriffsgruppe für alle Anfragen des Automatisierungsclient
|
||||
$zugriffsalleACgroup = '';
|
||||
## Zugriffsgruppe für Anfragen der Abwesenheitsnachrichten
|
||||
$zugriffsalleAbwesenheitgroup = '';
|
||||
## Zugriff auf alles
|
||||
$zugriffsAdminsgroup = '';
|
||||
|
||||
// Verbindung zur Datenbank herstellen (ersetze die Platzhalter durch deine Daten)
|
||||
$serverName = "";
|
||||
$connectionOptions = array(
|
||||
"Database" => "",
|
||||
"Uid" => "",
|
||||
"PWD" => "",
|
||||
"TrustServerCertificate"=>true
|
||||
);
|
||||
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
// Überprüfen der Verbindung
|
||||
if (!$conn) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
?>
|
||||
@@ -1,218 +1,218 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Funktion zum Überprüfen, ob der Mitarbeiter in der Tabelle vorhanden ist
|
||||
function isMitarbeiterExist($conn, $name)
|
||||
{
|
||||
$sql = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Name = ?";
|
||||
$params = array($name);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
return ($row !== false);
|
||||
}
|
||||
|
||||
// Funktion zum Überprüfen, ob ein identischer Eintrag bereits vorhanden ist
|
||||
function isDuplicateEntry($conn, $mitarbeiterID, $betrag, $datum)
|
||||
{
|
||||
// Um nur den gleichen Tag zu vergleichen, konvertieren wir den Datum-String zu einem DateTime-Objekt und verwenden die Funktion CONVERT
|
||||
$convertedDatum = date_format(date_create($datum), 'Y-m-d');
|
||||
|
||||
#$sql = "SELECT count FROM dbo.kl_Einzahlungen WHERE MitarbeiterID = ? AND Betrag = ? AND CONVERT(VARCHAR, Datum, 23) = ?";
|
||||
$sql = "SELECT * FROM dbo.kl_Einzahlungen WHERE MitarbeiterID = ? AND Betrag = ? AND CONVERT(VARCHAR, Datum, 23) = ?";
|
||||
$params = array($mitarbeiterID, $betrag, $convertedDatum);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
return ($row['MitarbeiterID'] > 0);
|
||||
}
|
||||
|
||||
// Funktion zum Verarbeiten der CSV-Datei und Rückgabe der Ergebnisse
|
||||
function processCSV($conn, $file)
|
||||
{
|
||||
$handle = fopen($file, "r");
|
||||
$success_entries = [];
|
||||
$failed_entries = [];
|
||||
|
||||
// Überspringe die erste Zeile (Header) der CSV-Datei
|
||||
fgetcsv($handle);
|
||||
|
||||
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||
$name = $data[3]; // Index 3 entspricht dem "Name"-Feld in der CSV
|
||||
$betrag = $data[7]; // Index 7 entspricht dem "Brutto"-Feld in der CSV
|
||||
$betrag = str_replace(",", ".", $betrag);
|
||||
#echo "<br>";
|
||||
#$Ausgabe = array($data[0], $data[3], $data[7]);
|
||||
// Überprüfen, ob der Mitarbeiter existiert und der Betrag positiv ist
|
||||
if (isMitarbeiterExist($conn, $name) && $betrag > 0) {
|
||||
|
||||
$mitarbeiterID = getMitarbeiterID($conn, $name);
|
||||
$datum = $data[0]; // Index 0 entspricht dem "Datum"-Feld in der CSV
|
||||
|
||||
// Überprüfen, ob ein identischer Eintrag bereits vorhanden ist
|
||||
if (!isDuplicateEntry($conn, $mitarbeiterID, $betrag, $datum)) {
|
||||
|
||||
// Eintrag in die Tabelle dbo.kl_Einzahlungen einfügen
|
||||
$sql = "INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum) VALUES (?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $betrag, $datum);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt) {
|
||||
$success_entries[] = array($data[0], $data[3], $data[7], 0);
|
||||
} else {
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 1);
|
||||
#die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}else {
|
||||
#echo "Eintrag bereits vorhanden: " . print_r($data, true) . "\n";
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 2);
|
||||
}
|
||||
|
||||
} else {
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return ['success' => $success_entries, 'failed' => $failed_entries];
|
||||
}
|
||||
|
||||
// Funktion zum Abrufen der MitarbeiterID
|
||||
function getMitarbeiterID($conn, $name)
|
||||
{
|
||||
$sql = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Name = ? or paypalname = ?";
|
||||
$params = array($name);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
|
||||
{
|
||||
return $row['MitarbeiterID'];
|
||||
}
|
||||
#echo $mitarbeiterid;
|
||||
|
||||
}
|
||||
|
||||
// Überprüfen, ob das Formular abgeschickt wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Überprüfen, ob eine Datei hochgeladen wurde
|
||||
if (isset($_FILES["csv_file"]) && $_FILES["csv_file"]["error"] == 0) {
|
||||
$file_name = $_FILES["csv_file"]["name"];
|
||||
$file_tmp = $_FILES["csv_file"]["tmp_name"];
|
||||
|
||||
// Datei in den Upload-Ordner verschieben
|
||||
move_uploaded_file($file_tmp, "uploads/" . $file_name);
|
||||
|
||||
// CSV-Datei verarbeiten
|
||||
$result = processCSV($conn, "uploads/" . $file_name);
|
||||
|
||||
echo "CSV-Datei erfolgreich verarbeitet.\n";
|
||||
|
||||
echo "<h3>Auswertung</h3>";
|
||||
echo "<table>
|
||||
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Datum</th>
|
||||
<th>Betrag</th>
|
||||
<th>Ergebnis</th>
|
||||
</tr>";
|
||||
|
||||
foreach ($result['success'] as $eintrag){
|
||||
echo "<tr>
|
||||
<td>$eintrag[0]</td>
|
||||
<td>$eintrag[1]</td>
|
||||
<td>$eintrag[2]</td>
|
||||
<td>Erfolgreich gespeichert</td>
|
||||
</tr>";
|
||||
}
|
||||
foreach ($result['failed'] as $eintrag){
|
||||
echo "<tr>
|
||||
<td>$eintrag[0]</td>
|
||||
<td>$eintrag[1]</td>
|
||||
<td>$eintrag[2]</td>
|
||||
<td>";
|
||||
if($eintrag[3] == 1){
|
||||
echo "SQL Fehler";
|
||||
}elseif($eintrag[3] == 2){
|
||||
echo "Eintrag schon vorhanden";
|
||||
}elseif($eintrag[3] == 3){
|
||||
echo "Benutzer nicht gefunden";
|
||||
}
|
||||
|
||||
echo "</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
} else {
|
||||
echo "Fehler beim Hochladen der Datei.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CSV Verarbeitung</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" enctype="multipart/form-data">
|
||||
<label for="csv_file">CSV-Datei auswählen:</label>
|
||||
<input type="file" name="csv_file" accept=".csv" required>
|
||||
<button type="submit">Datei hochladen</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Funktion zum Überprüfen, ob der Mitarbeiter in der Tabelle vorhanden ist
|
||||
function isMitarbeiterExist($conn, $name)
|
||||
{
|
||||
$sql = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Name = ?";
|
||||
$params = array($name);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
return ($row !== false);
|
||||
}
|
||||
|
||||
// Funktion zum Überprüfen, ob ein identischer Eintrag bereits vorhanden ist
|
||||
function isDuplicateEntry($conn, $mitarbeiterID, $betrag, $datum)
|
||||
{
|
||||
// Um nur den gleichen Tag zu vergleichen, konvertieren wir den Datum-String zu einem DateTime-Objekt und verwenden die Funktion CONVERT
|
||||
$convertedDatum = date_format(date_create($datum), 'Y-m-d');
|
||||
|
||||
#$sql = "SELECT count FROM dbo.kl_Einzahlungen WHERE MitarbeiterID = ? AND Betrag = ? AND CONVERT(VARCHAR, Datum, 23) = ?";
|
||||
$sql = "SELECT * FROM dbo.kl_Einzahlungen WHERE MitarbeiterID = ? AND Betrag = ? AND CONVERT(VARCHAR, Datum, 23) = ?";
|
||||
$params = array($mitarbeiterID, $betrag, $convertedDatum);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
return ($row['MitarbeiterID'] > 0);
|
||||
}
|
||||
|
||||
// Funktion zum Verarbeiten der CSV-Datei und Rückgabe der Ergebnisse
|
||||
function processCSV($conn, $file)
|
||||
{
|
||||
$handle = fopen($file, "r");
|
||||
$success_entries = [];
|
||||
$failed_entries = [];
|
||||
|
||||
// Überspringe die erste Zeile (Header) der CSV-Datei
|
||||
fgetcsv($handle);
|
||||
|
||||
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||
$name = $data[3]; // Index 3 entspricht dem "Name"-Feld in der CSV
|
||||
$betrag = $data[7]; // Index 7 entspricht dem "Brutto"-Feld in der CSV
|
||||
$betrag = str_replace(",", ".", $betrag);
|
||||
#echo "<br>";
|
||||
#$Ausgabe = array($data[0], $data[3], $data[7]);
|
||||
// Überprüfen, ob der Mitarbeiter existiert und der Betrag positiv ist
|
||||
if (isMitarbeiterExist($conn, $name) && $betrag > 0) {
|
||||
|
||||
$mitarbeiterID = getMitarbeiterID($conn, $name);
|
||||
$datum = $data[0]; // Index 0 entspricht dem "Datum"-Feld in der CSV
|
||||
|
||||
// Überprüfen, ob ein identischer Eintrag bereits vorhanden ist
|
||||
if (!isDuplicateEntry($conn, $mitarbeiterID, $betrag, $datum)) {
|
||||
|
||||
// Eintrag in die Tabelle dbo.kl_Einzahlungen einfügen
|
||||
$sql = "INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum) VALUES (?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $betrag, $datum);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt) {
|
||||
$success_entries[] = array($data[0], $data[3], $data[7], 0);
|
||||
} else {
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 1);
|
||||
#die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}else {
|
||||
#echo "Eintrag bereits vorhanden: " . print_r($data, true) . "\n";
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 2);
|
||||
}
|
||||
|
||||
} else {
|
||||
$failed_entries[] = array($data[0], $data[3], $data[7], 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return ['success' => $success_entries, 'failed' => $failed_entries];
|
||||
}
|
||||
|
||||
// Funktion zum Abrufen der MitarbeiterID
|
||||
function getMitarbeiterID($conn, $name)
|
||||
{
|
||||
$sql = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Name = ? or paypalname = ?";
|
||||
$params = array($name);
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
|
||||
{
|
||||
return $row['MitarbeiterID'];
|
||||
}
|
||||
#echo $mitarbeiterid;
|
||||
|
||||
}
|
||||
|
||||
// Überprüfen, ob das Formular abgeschickt wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Überprüfen, ob eine Datei hochgeladen wurde
|
||||
if (isset($_FILES["csv_file"]) && $_FILES["csv_file"]["error"] == 0) {
|
||||
$file_name = $_FILES["csv_file"]["name"];
|
||||
$file_tmp = $_FILES["csv_file"]["tmp_name"];
|
||||
|
||||
// Datei in den Upload-Ordner verschieben
|
||||
move_uploaded_file($file_tmp, "uploads/" . $file_name);
|
||||
|
||||
// CSV-Datei verarbeiten
|
||||
$result = processCSV($conn, "uploads/" . $file_name);
|
||||
|
||||
echo "CSV-Datei erfolgreich verarbeitet.\n";
|
||||
|
||||
echo "<h3>Auswertung</h3>";
|
||||
echo "<table>
|
||||
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Datum</th>
|
||||
<th>Betrag</th>
|
||||
<th>Ergebnis</th>
|
||||
</tr>";
|
||||
|
||||
foreach ($result['success'] as $eintrag){
|
||||
echo "<tr>
|
||||
<td>$eintrag[0]</td>
|
||||
<td>$eintrag[1]</td>
|
||||
<td>$eintrag[2]</td>
|
||||
<td>Erfolgreich gespeichert</td>
|
||||
</tr>";
|
||||
}
|
||||
foreach ($result['failed'] as $eintrag){
|
||||
echo "<tr>
|
||||
<td>$eintrag[0]</td>
|
||||
<td>$eintrag[1]</td>
|
||||
<td>$eintrag[2]</td>
|
||||
<td>";
|
||||
if($eintrag[3] == 1){
|
||||
echo "SQL Fehler";
|
||||
}elseif($eintrag[3] == 2){
|
||||
echo "Eintrag schon vorhanden";
|
||||
}elseif($eintrag[3] == 3){
|
||||
echo "Benutzer nicht gefunden";
|
||||
}
|
||||
|
||||
echo "</td>
|
||||
</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
} else {
|
||||
echo "Fehler beim Hochladen der Datei.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CSV Verarbeitung</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" enctype="multipart/form-data">
|
||||
<label for="csv_file">CSV-Datei auswählen:</label>
|
||||
<input type="file" name="csv_file" accept=".csv" required>
|
||||
<button type="submit">Datei hochladen</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,152 +1,152 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" ) {
|
||||
// Iteriere über alle Mitarbeiter
|
||||
foreach ($_POST["anzahlBetrag"] as $mitarbeiterID => $anzahlBetrag) {
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
#$anzahlBetrag = $anzahlBetrag;
|
||||
$anzahlBetrag = floatval($anzahlBetrag);
|
||||
|
||||
if($anzahlBetrag != 0){
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum) VALUES (?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $anzahlBetrag, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Einträge erfolgreich hinzugefügt.";
|
||||
}elseif($_SERVER["REQUEST_METHOD"] == "GET" AND isset($_GET["action"])){
|
||||
|
||||
if($_GET["action"] == "vorderseite"){
|
||||
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, GETDATE()) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
|
||||
}elseif( $_GET["action"] == "rueckseite"){
|
||||
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, GETDATE())
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;";
|
||||
}elseif($_GET["action"] == "alle"){
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
}
|
||||
|
||||
}else{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
|
||||
}
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// Schließe die Verbindung zur Datenbank
|
||||
#sqlsrv_close($conn);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Einzahlung</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Einzahlungen für alle Mitarbeiter</h2>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=vorderseite" method="get">
|
||||
<button type="submit">Vorderseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=rueckseite" method="get">
|
||||
<button type="submit">Rückseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=alle" method="get">
|
||||
<button type="submit">Alle</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="letzteneintraege.php" method="get">
|
||||
<button type="submit">Letzten Einträge</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="csvupload.php" method="get">
|
||||
<button type="submit">CSV Upload</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<?php
|
||||
|
||||
echo "<table>";
|
||||
echo " <tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Betrag</th>
|
||||
</tr>";
|
||||
// Iteriere über alle Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row["MitarbeiterID"];
|
||||
$mitarbeiterName = $row["Name"];
|
||||
echo "<tr>";
|
||||
// Formularfeld für die Anzahl der Striche
|
||||
echo "<td><label for='anzahlBetrag[$mitarbeiterID]'>$mitarbeiterName </label></td>";
|
||||
echo "<td><input type='number' name='anzahlBetrag[$mitarbeiterID]' step='0.01'></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
?>
|
||||
|
||||
<button type="submit" name="submit" value="Speichern" >Eintragen</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" ) {
|
||||
// Iteriere über alle Mitarbeiter
|
||||
foreach ($_POST["anzahlBetrag"] as $mitarbeiterID => $anzahlBetrag) {
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
#$anzahlBetrag = $anzahlBetrag;
|
||||
$anzahlBetrag = floatval($anzahlBetrag);
|
||||
|
||||
if($anzahlBetrag != 0){
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum) VALUES (?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $anzahlBetrag, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Einträge erfolgreich hinzugefügt.";
|
||||
}elseif($_SERVER["REQUEST_METHOD"] == "GET" AND isset($_GET["action"])){
|
||||
|
||||
if($_GET["action"] == "vorderseite"){
|
||||
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, GETDATE()) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
|
||||
}elseif( $_GET["action"] == "rueckseite"){
|
||||
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, GETDATE())
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;";
|
||||
}elseif($_GET["action"] == "alle"){
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
}
|
||||
|
||||
}else{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
|
||||
}
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// Schließe die Verbindung zur Datenbank
|
||||
#sqlsrv_close($conn);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Einzahlung</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Einzahlungen für alle Mitarbeiter</h2>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=vorderseite" method="get">
|
||||
<button type="submit">Vorderseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=rueckseite" method="get">
|
||||
<button type="submit">Rückseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="einzahlung.php?aktion=alle" method="get">
|
||||
<button type="submit">Alle</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="letzteneintraege.php" method="get">
|
||||
<button type="submit">Letzten Einträge</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="csvupload.php" method="get">
|
||||
<button type="submit">CSV Upload</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<?php
|
||||
|
||||
echo "<table>";
|
||||
echo " <tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Betrag</th>
|
||||
</tr>";
|
||||
// Iteriere über alle Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row["MitarbeiterID"];
|
||||
$mitarbeiterName = $row["Name"];
|
||||
echo "<tr>";
|
||||
// Formularfeld für die Anzahl der Striche
|
||||
echo "<td><label for='anzahlBetrag[$mitarbeiterID]'>$mitarbeiterName </label></td>";
|
||||
echo "<td><input type='number' name='anzahlBetrag[$mitarbeiterID]' step='0.01'></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
?>
|
||||
|
||||
<button type="submit" name="submit" value="Speichern" >Eintragen</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,224 +1,224 @@
|
||||
<?php
|
||||
|
||||
include "config.php";
|
||||
#include_once "functionsLDAP.php";
|
||||
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgaben pro Mitarbeiter
|
||||
$sqlAusgaben = "SELECT SUM(Kosten) AS Gesamtausgaben FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgaben = sqlsrv_query($conn, $sqlAusgaben, array($mitarbeiterID));
|
||||
$rowAusgaben = sqlsrv_fetch_array($stmtAusgaben, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgaben = $rowAusgaben['Gesamtausgaben'];
|
||||
|
||||
return $gesamtausgaben;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE))) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, ',', '.');
|
||||
|
||||
// TCPDF-Bibliothek einbinden
|
||||
require_once('tcpdf/tcpdf.php');
|
||||
|
||||
class MyCustomPDFWithWatermark extends TCPDF {
|
||||
public function Header() {
|
||||
// Get the current page break margin
|
||||
$bMargin = $this->getBreakMargin();
|
||||
|
||||
// Get current auto-page-break mode
|
||||
$auto_page_break = $this->AutoPageBreak;
|
||||
|
||||
// Disable auto-page-break
|
||||
$this->SetAutoPageBreak(false, 0);
|
||||
|
||||
// Define the path to the image that you want to use as watermark.
|
||||
$img_file = './watermark.jpg';
|
||||
$this->SetAlpha(0.35);
|
||||
// Render the image
|
||||
$this->Image($img_file, 0, 0, 223, 280, '', '', '', false, 300, '', false, false, 0);
|
||||
$this->SetAlpha(1);
|
||||
// Restore the auto-page-break status
|
||||
$this->SetAutoPageBreak($auto_page_break, $bMargin);
|
||||
|
||||
// Set the starting point for the page content
|
||||
$this->setPageMark();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PDF-Objekt erstellen
|
||||
#$pdf = new TCPDF();
|
||||
$pdf = new MyCustomPDFWithWatermark(PDF_PAGE_ORIENTATION, 'mm', 'A4', true, 'UTF-8', false);
|
||||
|
||||
|
||||
// PDF-Header setzen
|
||||
$pdf->SetHeaderData("", 0, "Kaffeestrichliste", "");
|
||||
|
||||
// PDF-Header und Footer auf jeder Seite anzeigen
|
||||
#$pdf->SetPrintHeader(false);
|
||||
$pdf->SetPrintFooter(false);
|
||||
$pdf->SetMargins('5', '5', '5');
|
||||
$pdf->SetAutoPageBreak(TRUE, 5);
|
||||
// Seitenformat setzen
|
||||
#$pdf->SetFormat('A4', 'portrait');
|
||||
$pdf->SetFont('helvetica', '', 9.5);
|
||||
// PDF-Inhalt starten
|
||||
$pdf->AddPage();
|
||||
|
||||
|
||||
|
||||
// Tabelle erstellen
|
||||
$html = '
|
||||
<table border="1" style="white-space:nowrap;">
|
||||
<tr style="height: 25px;background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);" valign="bottom">
|
||||
<th style="width:30%;font-size: 13px;" colspan="2"><b>Kaffeeliste - Vieltrinker</b></th>
|
||||
<th style="width:70%;" valign="bottom">1 Strich = ' . $KostenproStrich . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
||||
</tr>
|
||||
<tr >
|
||||
<td style="width:20%"><b>Name</b></td>
|
||||
<td style="width:10%"><b>Guthaben</b></td>
|
||||
<td ><b>Striche</b></td>
|
||||
</tr>';
|
||||
$y=1;
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
$y++;
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
$gesamtausgaben = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgaben;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$html .= '<tr style="height: 16px;">';
|
||||
$html .= "<td>{$name}</td>";
|
||||
#$pdf->writeHTML($html, true, false, true, false, '');
|
||||
#$html = "";
|
||||
if($differenztemp < -10.00){
|
||||
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}elseif($differenztemp > 5.00){
|
||||
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}else{
|
||||
$html .= "<td>{$differenz} €</td>";
|
||||
}
|
||||
$html .= "<td></td>";
|
||||
$html .= "</tr>";
|
||||
}
|
||||
|
||||
for ($i = $y; $i < 64; $i++) {
|
||||
$html .= '<tr><td> </td><td> </td><td> </td></tr>';
|
||||
}
|
||||
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>Rückseite beachten!</b></td></tr>';
|
||||
$html .= '</table>';
|
||||
|
||||
|
||||
#echo $html;
|
||||
// Tabelle ins PDF einfügen
|
||||
$pdf->writeHTML($html, true, false, true, false, '');
|
||||
|
||||
|
||||
// PDF-Inhalt starten
|
||||
$pdf->AddPage();
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "
|
||||
SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE)))
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;
|
||||
";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
// Tabelle erstellen
|
||||
$html = '
|
||||
<table border="1" style="white-space:nowrap;">
|
||||
<tr style="background-color: rgb(91, 209, 215);color: rgb(0, 0, 0);vertical-align: bottom;">
|
||||
<th style="width:30%;font-size: 12px;" colspan="2"><b>Kaffeeliste - Wenigtrinker</b></th>
|
||||
<th style="width:70%;" valign="bottom">1 Strich = ' . $KostenproStrich . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
||||
</tr>
|
||||
<tr >
|
||||
<td style="width:20%"><b>Name</b></td>
|
||||
<td style="width:10%"><b>Guthaben</b></td>
|
||||
<td ><b>Striche</b></td>
|
||||
</tr>';
|
||||
$y=1;
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
$y++;
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
$gesamtausgaben = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgaben;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$html .= "<tr>";
|
||||
$html .= "<td>{$name}</td>";
|
||||
#$pdf->writeHTML($html, true, false, true, false, '');
|
||||
#$html = "";
|
||||
if($differenztemp < -10.00){
|
||||
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}elseif($differenztemp > 5.00){
|
||||
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}else{
|
||||
$html .= "<td>{$differenz} €</td>";
|
||||
}
|
||||
$html .= "<td></td>";
|
||||
$html .= "</tr>";
|
||||
}
|
||||
|
||||
for ($i = $y; $i < 65; $i++) {
|
||||
$html .= '<tr><td> </td><td> </td><td> </td></tr>';
|
||||
}
|
||||
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>Vorderseite beachten!</b></td></tr>';
|
||||
$html .= '</table>';
|
||||
|
||||
|
||||
|
||||
#echo $html;
|
||||
// Tabelle ins PDF einfügen
|
||||
$pdf->writeHTML($html, true, false, true, false, '');
|
||||
|
||||
// PDF-Ausgabe
|
||||
$pdf->Output('Kaffeestrichliste.pdf', 'D');
|
||||
|
||||
|
||||
?>
|
||||
<?php
|
||||
|
||||
include "config.php";
|
||||
#include_once "functionsLDAP.php";
|
||||
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgaben pro Mitarbeiter
|
||||
$sqlAusgaben = "SELECT SUM(Kosten) AS Gesamtausgaben FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgaben = sqlsrv_query($conn, $sqlAusgaben, array($mitarbeiterID));
|
||||
$rowAusgaben = sqlsrv_fetch_array($stmtAusgaben, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgaben = $rowAusgaben['Gesamtausgaben'];
|
||||
|
||||
return $gesamtausgaben;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE))) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, ',', '.');
|
||||
|
||||
// TCPDF-Bibliothek einbinden
|
||||
require_once('tcpdf/tcpdf.php');
|
||||
|
||||
class MyCustomPDFWithWatermark extends TCPDF {
|
||||
public function Header() {
|
||||
// Get the current page break margin
|
||||
$bMargin = $this->getBreakMargin();
|
||||
|
||||
// Get current auto-page-break mode
|
||||
$auto_page_break = $this->AutoPageBreak;
|
||||
|
||||
// Disable auto-page-break
|
||||
$this->SetAutoPageBreak(false, 0);
|
||||
|
||||
// Define the path to the image that you want to use as watermark.
|
||||
$img_file = './watermark.jpg';
|
||||
$this->SetAlpha(0.35);
|
||||
// Render the image
|
||||
$this->Image($img_file, 0, 0, 223, 280, '', '', '', false, 300, '', false, false, 0);
|
||||
$this->SetAlpha(1);
|
||||
// Restore the auto-page-break status
|
||||
$this->SetAutoPageBreak($auto_page_break, $bMargin);
|
||||
|
||||
// Set the starting point for the page content
|
||||
$this->setPageMark();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PDF-Objekt erstellen
|
||||
#$pdf = new TCPDF();
|
||||
$pdf = new MyCustomPDFWithWatermark(PDF_PAGE_ORIENTATION, 'mm', 'A4', true, 'UTF-8', false);
|
||||
|
||||
|
||||
// PDF-Header setzen
|
||||
$pdf->SetHeaderData("", 0, "Kaffeestrichliste", "");
|
||||
|
||||
// PDF-Header und Footer auf jeder Seite anzeigen
|
||||
#$pdf->SetPrintHeader(false);
|
||||
$pdf->SetPrintFooter(false);
|
||||
$pdf->SetMargins('5', '5', '5');
|
||||
$pdf->SetAutoPageBreak(TRUE, 5);
|
||||
// Seitenformat setzen
|
||||
#$pdf->SetFormat('A4', 'portrait');
|
||||
$pdf->SetFont('helvetica', '', 9.5);
|
||||
// PDF-Inhalt starten
|
||||
$pdf->AddPage();
|
||||
|
||||
|
||||
|
||||
// Tabelle erstellen
|
||||
$html = '
|
||||
<table border="1" style="white-space:nowrap;">
|
||||
<tr style="height: 25px;background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);" valign="bottom">
|
||||
<th style="width:30%;font-size: 13px;" colspan="2"><b>Kaffeeliste - Vieltrinker</b></th>
|
||||
<th style="width:70%;" valign="bottom">1 Strich = ' . $KostenproStrich . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
||||
</tr>
|
||||
<tr >
|
||||
<td style="width:20%"><b>Name</b></td>
|
||||
<td style="width:10%"><b>Guthaben</b></td>
|
||||
<td ><b>Striche</b></td>
|
||||
</tr>';
|
||||
$y=1;
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
$y++;
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
$gesamtausgaben = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgaben;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$html .= '<tr style="height: 16px;">';
|
||||
$html .= "<td>{$name}</td>";
|
||||
#$pdf->writeHTML($html, true, false, true, false, '');
|
||||
#$html = "";
|
||||
if($differenztemp < -10.00){
|
||||
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}elseif($differenztemp > 5.00){
|
||||
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}else{
|
||||
$html .= "<td>{$differenz} €</td>";
|
||||
}
|
||||
$html .= "<td></td>";
|
||||
$html .= "</tr>";
|
||||
}
|
||||
|
||||
for ($i = $y; $i < 64; $i++) {
|
||||
$html .= '<tr><td> </td><td> </td><td> </td></tr>';
|
||||
}
|
||||
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>Rückseite beachten!</b></td></tr>';
|
||||
$html .= '</table>';
|
||||
|
||||
|
||||
#echo $html;
|
||||
// Tabelle ins PDF einfügen
|
||||
$pdf->writeHTML($html, true, false, true, false, '');
|
||||
|
||||
|
||||
// PDF-Inhalt starten
|
||||
$pdf->AddPage();
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "
|
||||
SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE)))
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;
|
||||
";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
// Tabelle erstellen
|
||||
$html = '
|
||||
<table border="1" style="white-space:nowrap;">
|
||||
<tr style="background-color: rgb(91, 209, 215);color: rgb(0, 0, 0);vertical-align: bottom;">
|
||||
<th style="width:30%;font-size: 12px;" colspan="2"><b>Kaffeeliste - Wenigtrinker</b></th>
|
||||
<th style="width:70%;" valign="bottom">1 Strich = ' . $KostenproStrich . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
||||
</tr>
|
||||
<tr >
|
||||
<td style="width:20%"><b>Name</b></td>
|
||||
<td style="width:10%"><b>Guthaben</b></td>
|
||||
<td ><b>Striche</b></td>
|
||||
</tr>';
|
||||
$y=1;
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
$y++;
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
$gesamtausgaben = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgaben;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$html .= "<tr>";
|
||||
$html .= "<td>{$name}</td>";
|
||||
#$pdf->writeHTML($html, true, false, true, false, '');
|
||||
#$html = "";
|
||||
if($differenztemp < -10.00){
|
||||
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}elseif($differenztemp > 5.00){
|
||||
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' .$differenz . ' €</td>';
|
||||
}else{
|
||||
$html .= "<td>{$differenz} €</td>";
|
||||
}
|
||||
$html .= "<td></td>";
|
||||
$html .= "</tr>";
|
||||
}
|
||||
|
||||
for ($i = $y; $i < 65; $i++) {
|
||||
$html .= '<tr><td> </td><td> </td><td> </td></tr>';
|
||||
}
|
||||
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>Vorderseite beachten!</b></td></tr>';
|
||||
$html .= '</table>';
|
||||
|
||||
|
||||
|
||||
#echo $html;
|
||||
// Tabelle ins PDF einfügen
|
||||
$pdf->writeHTML($html, true, false, true, false, '');
|
||||
|
||||
// PDF-Ausgabe
|
||||
$pdf->Output('Kaffeestrichliste.pdf', 'D');
|
||||
|
||||
|
||||
?>
|
||||
@@ -1,90 +1,90 @@
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
echo "<h2>FAQ - Kaffeeliste</h2>";
|
||||
echo "<br>";
|
||||
?>
|
||||
|
||||
<p><b>Wie werde ich Mitglied der Kaffeeliste?</b>
|
||||
</b></p><p>Neumitglieder können sich einfach in diese Liste eintragen und zahlen aktuell keine Aufnahmegebühr. Es ist keine weitere Rücksprache nötig.
|
||||
Schon mal ausgetretene Mitglieder können erst nach einem Jahr wiederaufgenommen werden. Die Kaffeeliste behält sich vor Mitglieder von der Liste streichen zu können.
|
||||
<p><b>Wo finde ich Milch, Zucker und Kaffee?
|
||||
</b></p><p>Milch findet ihr im Kühlschrank (XXX auf dem Deckel), Zucker und Süßstoff steht neben der Kaffeemaschine. Nachschub findet Ihr im Schrank über der Maschine.
|
||||
Sollte dort nichts mehr vorhanden sein, schaut bitte auf der Webseite https://kaffeeliste.arge.aok nach ob es einen Hinweis gibt. Sollte kein Hinweis erscheinen, informiert bitte den Ansprechpartner der Kaffeeliste. <br>
|
||||
Dieser bestellt im Laufe einer Woche die Verbrauchsgüter nach. Sollte dieses nicht ausreichen, dann können in diesem Ausnahmefall auch selbst die Verbrauchsgüter besorgt werden.
|
||||
Die Unkosten werden gegen Vorlage des Bon (z.B. per Mail) der einreichenden Person auf der Kaffeeliste gutgeschrieben.
|
||||
|
||||
<p><b>Welche Arten von Kaffee bekomme ich an der Kaffeemaschine?
|
||||
</b></p><p>Es gibt für euch nur noch vier Tasten mit jeweils einem Bild.<br>
|
||||
<b>Espresso</b> – Ausgabe von ca. 100ml Kaffee<br>
|
||||
<b>Coffee</b> – Ausgabe von ca. 150ml Kaffee<br>
|
||||
<b>Hot Water</b> – Ausgabe von ca. 200ml warmen Wasser (extra Ausgabe)<br>
|
||||
<b>Americano</b> – Ausgabe von ca. 300ml (150ml Kaffee + 150ml warmes Wasser)<br>
|
||||
<br>
|
||||
Eine persönliche Einstellung der Kaffeemenge ist nicht mehr möglich.
|
||||
Die Stärke muss durch die Menge des Wassers definiert werden.
|
||||
Alle Kaffeespezialitäten bekommen aktuell ca. 11g Kaffee.
|
||||
Durch den automatischen Doppelbezug und die verschiedenen Mengen sollten aber die meisten Wünsche erfüllt werden können.
|
||||
</p>
|
||||
<p><b>Wie nutze ich die Kaffeemaschine?
|
||||
</b></p><p>Mit einem Klick auf das jeweilige Symbol bekommt ihr eine Tasse (1 Strich auf der Kaffeeliste).
|
||||
Mit zweimaligem Drücken auf die jeweilige Taste bekommt ihr zwei Tassen (2 Strich auf der Kaffeeliste).
|
||||
Läuft das Programm könnt ihr mit einem weiteren Klick auf das jeweilige Symbol den Vorgang vorzeitig beenden.
|
||||
<p><b>Wie viel kostet ein Kaffee?
|
||||
</b></p><p>Den aktuellen Preis pro Strich steht immer oben rechts auf der Kaffeeliste. Somit kann ein einfacher Kaffee ein oder auch zwei Striche kosten.
|
||||
<p><b>Wie erfolgt die Abrechnung?
|
||||
</b></p><p>Je nach dem was du an der Maschine bezogen hast, machst du die entsprechenden Striche auf der Liste. Also: ein Klick = ein Strich und zwei Klicks = zwei Striche.
|
||||
Etwa ein Mal im Monat wird die Liste aktualisiert. In diesem Fall bekommst eine E-Mail, wenn du bezahlen musst.
|
||||
<p><b>Wie kann ich bezahlen?
|
||||
</b></p><p>Aktuell kann nur per Paypal bezahlt werden. Du erhältst einen entsprechenden Link per Mail.<br>
|
||||
Bezahle immer über die Freunde Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.
|
||||
<p><b>Muss ich bei der Bezahlung per PayPal gesondert bestätigen oder jemand benachrichtigen?
|
||||
</b></p><p>Nein, du musst die Bezahlung nicht gesondert bestätigen. Deine Zahlungen von PayPal werden verrechnet und du siehst dieses auf der nächsten Kaffeeliste. Nach der Verarbeitung deiner Einzahlung bekommst du eine schriftliche Bestätigung per Mail.
|
||||
<p><b>Ich habe einen negativen Wert auf der Kaffeeliste?
|
||||
</b></p><p>Ein negativer Betrag in der Spalte "offen" stellen deine Schulden dar. Ein positiver Betrag ist ein Guthaben.
|
||||
<p><b>Ich habe eine rote Markierung in der Liste. Was bedeutet das?
|
||||
</b></p><p>Du hast einen höheren offenen Betrag. Bitte bezahle deinen ausstehenden Betrag per PayPal.
|
||||
<p><b>Ich habe bezahlt und der rote Eintrag in der Liste verschwindet nicht!
|
||||
</b></p><p>Die Liste wird etwa ein Mal im Monat aktualisiert. Bis zur Aktualisierung der Liste bleibt dein Betrag vom letzten Mal auf der Liste stehen.
|
||||
<p><b>Was passiert, wenn ich die Striche auf der Liste zu undeutlich oder nicht in Fünferblocks mache?
|
||||
</b></p><p>Nicht klar erkennbare Stiche führen ohne weitere Vorwarnung zu einer pauschalen Strafe von 10 Strichen bei der Auswertung der Liste. <br>
|
||||
Sollten die Striche nicht im Quinärsystem - also nach vier Strichen ein Querstrich über diese - (Beispiel: <a href="https://de.wikipedia.org/wiki/Strichliste" >Strichliste</a>) gemacht werden, führt dieses ohne weitere Vorwarnung zu einer pauschalen Strafe von 10 Strichen bei der Auswertung der Liste.
|
||||
<p><b>Ich habe das Gefühl mein Betrag/Guthaben passt nicht. Was soll ich machen?
|
||||
</b></p><p>Fehler können leider auch in der Kaffeeliste passieren. Melde dich einfach per Mail und wir schauen uns einmal die Abrechnung an. In der Regel findet sich dann der Fehler oder eine Lösung.
|
||||
<p><b>Wie erfolgt die Wartung der Maschine?
|
||||
</b></p><p>Die Wartung der Maschine (Reinigung und Entkalkung) erfolgt etwa einmal im Monaten. Bei jeder Entkalkung findet auch ein Wechsel des Wasserfilters statt.
|
||||
</p>
|
||||
<p><b>Wie kann ich mich einbringen?
|
||||
</b></p><p>Zunächst ist ein freundliches Miteinander wichtig! <br>
|
||||
Schaut gerne immer mal nach, ob die Verbrauchsmaterialen noch entsprechend vorhanden sind.
|
||||
Wenn du dich weitere Punkte wie Wartung oder ähnliches kümmern möchtest, melde dich gerne beim Ansprechpartner der Kaffeeliste.
|
||||
<p><b>Ich habe eine Frage und diese steht hier nicht!
|
||||
</b></p><p>Dann wenden dich gerne an den Ansprechpartner der Kaffeeliste (kaffeelistesb3@nds.aok.de). Dieser wird dir sicherlich weiterhelfen.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
echo "<h2>FAQ - Kaffeeliste</h2>";
|
||||
echo "<br>";
|
||||
?>
|
||||
|
||||
<p><b>Wie werde ich Mitglied der Kaffeeliste?</b>
|
||||
</b></p><p>Neumitglieder können sich einfach in diese Liste eintragen und zahlen aktuell keine Aufnahmegebühr. Es ist keine weitere Rücksprache nötig.
|
||||
Schon mal ausgetretene Mitglieder können erst nach einem Jahr wiederaufgenommen werden. Die Kaffeeliste behält sich vor Mitglieder von der Liste streichen zu können.
|
||||
<p><b>Wo finde ich Milch, Zucker und Kaffee?
|
||||
</b></p><p>Milch findet ihr im Kühlschrank (XXX auf dem Deckel), Zucker und Süßstoff steht neben der Kaffeemaschine. Nachschub findet Ihr im Schrank über der Maschine.
|
||||
Sollte dort nichts mehr vorhanden sein, schaut bitte auf der Webseite https://kaffeeliste.arge.aok nach ob es einen Hinweis gibt. Sollte kein Hinweis erscheinen, informiert bitte den Ansprechpartner der Kaffeeliste. <br>
|
||||
Dieser bestellt im Laufe einer Woche die Verbrauchsgüter nach. Sollte dieses nicht ausreichen, dann können in diesem Ausnahmefall auch selbst die Verbrauchsgüter besorgt werden.
|
||||
Die Unkosten werden gegen Vorlage des Bon (z.B. per Mail) der einreichenden Person auf der Kaffeeliste gutgeschrieben.
|
||||
|
||||
<p><b>Welche Arten von Kaffee bekomme ich an der Kaffeemaschine?
|
||||
</b></p><p>Es gibt für euch nur noch vier Tasten mit jeweils einem Bild.<br>
|
||||
<b>Espresso</b> – Ausgabe von ca. 100ml Kaffee<br>
|
||||
<b>Coffee</b> – Ausgabe von ca. 150ml Kaffee<br>
|
||||
<b>Hot Water</b> – Ausgabe von ca. 200ml warmen Wasser (extra Ausgabe)<br>
|
||||
<b>Americano</b> – Ausgabe von ca. 300ml (150ml Kaffee + 150ml warmes Wasser)<br>
|
||||
<br>
|
||||
Eine persönliche Einstellung der Kaffeemenge ist nicht mehr möglich.
|
||||
Die Stärke muss durch die Menge des Wassers definiert werden.
|
||||
Alle Kaffeespezialitäten bekommen aktuell ca. 11g Kaffee.
|
||||
Durch den automatischen Doppelbezug und die verschiedenen Mengen sollten aber die meisten Wünsche erfüllt werden können.
|
||||
</p>
|
||||
<p><b>Wie nutze ich die Kaffeemaschine?
|
||||
</b></p><p>Mit einem Klick auf das jeweilige Symbol bekommt ihr eine Tasse (1 Strich auf der Kaffeeliste).
|
||||
Mit zweimaligem Drücken auf die jeweilige Taste bekommt ihr zwei Tassen (2 Strich auf der Kaffeeliste).
|
||||
Läuft das Programm könnt ihr mit einem weiteren Klick auf das jeweilige Symbol den Vorgang vorzeitig beenden.
|
||||
<p><b>Wie viel kostet ein Kaffee?
|
||||
</b></p><p>Den aktuellen Preis pro Strich steht immer oben rechts auf der Kaffeeliste. Somit kann ein einfacher Kaffee ein oder auch zwei Striche kosten.
|
||||
<p><b>Wie erfolgt die Abrechnung?
|
||||
</b></p><p>Je nach dem was du an der Maschine bezogen hast, machst du die entsprechenden Striche auf der Liste. Also: ein Klick = ein Strich und zwei Klicks = zwei Striche.
|
||||
Etwa ein Mal im Monat wird die Liste aktualisiert. In diesem Fall bekommst eine E-Mail, wenn du bezahlen musst.
|
||||
<p><b>Wie kann ich bezahlen?
|
||||
</b></p><p>Aktuell kann nur per Paypal bezahlt werden. Du erhältst einen entsprechenden Link per Mail.<br>
|
||||
Bezahle immer über die Freunde Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.
|
||||
<p><b>Muss ich bei der Bezahlung per PayPal gesondert bestätigen oder jemand benachrichtigen?
|
||||
</b></p><p>Nein, du musst die Bezahlung nicht gesondert bestätigen. Deine Zahlungen von PayPal werden verrechnet und du siehst dieses auf der nächsten Kaffeeliste. Nach der Verarbeitung deiner Einzahlung bekommst du eine schriftliche Bestätigung per Mail.
|
||||
<p><b>Ich habe einen negativen Wert auf der Kaffeeliste?
|
||||
</b></p><p>Ein negativer Betrag in der Spalte "offen" stellen deine Schulden dar. Ein positiver Betrag ist ein Guthaben.
|
||||
<p><b>Ich habe eine rote Markierung in der Liste. Was bedeutet das?
|
||||
</b></p><p>Du hast einen höheren offenen Betrag. Bitte bezahle deinen ausstehenden Betrag per PayPal.
|
||||
<p><b>Ich habe bezahlt und der rote Eintrag in der Liste verschwindet nicht!
|
||||
</b></p><p>Die Liste wird etwa ein Mal im Monat aktualisiert. Bis zur Aktualisierung der Liste bleibt dein Betrag vom letzten Mal auf der Liste stehen.
|
||||
<p><b>Was passiert, wenn ich die Striche auf der Liste zu undeutlich oder nicht in Fünferblocks mache?
|
||||
</b></p><p>Nicht klar erkennbare Stiche führen ohne weitere Vorwarnung zu einer pauschalen Strafe von 10 Strichen bei der Auswertung der Liste. <br>
|
||||
Sollten die Striche nicht im Quinärsystem - also nach vier Strichen ein Querstrich über diese - (Beispiel: <a href="https://de.wikipedia.org/wiki/Strichliste" >Strichliste</a>) gemacht werden, führt dieses ohne weitere Vorwarnung zu einer pauschalen Strafe von 10 Strichen bei der Auswertung der Liste.
|
||||
<p><b>Ich habe das Gefühl mein Betrag/Guthaben passt nicht. Was soll ich machen?
|
||||
</b></p><p>Fehler können leider auch in der Kaffeeliste passieren. Melde dich einfach per Mail und wir schauen uns einmal die Abrechnung an. In der Regel findet sich dann der Fehler oder eine Lösung.
|
||||
<p><b>Wie erfolgt die Wartung der Maschine?
|
||||
</b></p><p>Die Wartung der Maschine (Reinigung und Entkalkung) erfolgt etwa einmal im Monaten. Bei jeder Entkalkung findet auch ein Wechsel des Wasserfilters statt.
|
||||
</p>
|
||||
<p><b>Wie kann ich mich einbringen?
|
||||
</b></p><p>Zunächst ist ein freundliches Miteinander wichtig! <br>
|
||||
Schaut gerne immer mal nach, ob die Verbrauchsmaterialen noch entsprechend vorhanden sind.
|
||||
Wenn du dich weitere Punkte wie Wartung oder ähnliches kümmern möchtest, melde dich gerne beim Ansprechpartner der Kaffeeliste.
|
||||
<p><b>Ich habe eine Frage und diese steht hier nicht!
|
||||
</b></p><p>Dann wenden dich gerne an den Ansprechpartner der Kaffeeliste (kaffeelistesb3@nds.aok.de). Dieser wird dir sicherlich weiterhelfen.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,61 +1,61 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar -->
|
||||
<div id="sidebar">
|
||||
<div class="inner">
|
||||
<!-- Menu -->
|
||||
<nav id="menu">
|
||||
<header class="major">
|
||||
<h2>Menü</h2>
|
||||
</header>
|
||||
<ul>
|
||||
<li><a href="index.php">Meine Kaffeeliste</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
?>
|
||||
|
||||
<li><a href="einzahlung.php">Einzahlung eintragen</a></li>
|
||||
<li><a href="stricheintragen.php"> Striche eintragen</a></li>
|
||||
<li><a href="kaffeeliste.php">Kaffeeliste anzeigen</a></li>
|
||||
<li><a href="mitarbeiterverwalten.php">Mitglieder verwalten</a></li>
|
||||
<li><a href="hinweise.php">Hinweise verwalten</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<li><a href="faq.php">FAQ Kaffeeliste</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<!-- Footer -->
|
||||
|
||||
<footer id="footer">
|
||||
<p class="copyright">© Copyright: Clemens Creutzburg All rights reserved. Design: <a href="http://html5up.net">HTML5 UP</a></p>
|
||||
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="assets/js/jquery.min.js"></script>
|
||||
<script src="assets/js/browser.min.js"></script>
|
||||
<script src="assets/js/breakpoints.min.js"></script>
|
||||
<script src="assets/js/util.js"></script>
|
||||
<script src="assets/js/main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar -->
|
||||
<div id="sidebar">
|
||||
<div class="inner">
|
||||
<!-- Menu -->
|
||||
<nav id="menu">
|
||||
<header class="major">
|
||||
<h2>Menü</h2>
|
||||
</header>
|
||||
<ul>
|
||||
<li><a href="index.php">Meine Kaffeeliste</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
?>
|
||||
|
||||
<li><a href="einzahlung.php">Einzahlung eintragen</a></li>
|
||||
<li><a href="stricheintragen.php"> Striche eintragen</a></li>
|
||||
<li><a href="kaffeeliste.php">Kaffeeliste anzeigen</a></li>
|
||||
<li><a href="mitarbeiterverwalten.php">Mitglieder verwalten</a></li>
|
||||
<li><a href="hinweise.php">Hinweise verwalten</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<li><a href="faq.php">FAQ Kaffeeliste</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<!-- Footer -->
|
||||
|
||||
<footer id="footer">
|
||||
<p class="copyright">© Copyright: Clemens Creutzburg All rights reserved. Design: <a href="http://html5up.net">HTML5 UP</a></p>
|
||||
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="assets/js/jquery.min.js"></script>
|
||||
<script src="assets/js/browser.min.js"></script>
|
||||
<script src="assets/js/breakpoints.min.js"></script>
|
||||
<script src="assets/js/util.js"></script>
|
||||
<script src="assets/js/main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,69 +1,69 @@
|
||||
<?php
|
||||
|
||||
include_once "config.php";
|
||||
|
||||
$kennungtemp = $_SERVER['AUTH_USER'];
|
||||
$teile = explode("\\", $kennungtemp);
|
||||
$kennung = $teile[1];
|
||||
|
||||
|
||||
include_once "functionsLDAP.php";
|
||||
|
||||
function getUserName($conn, $mail){
|
||||
|
||||
$sqlMitglieder = "SELECT Name FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' ";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
#$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)
|
||||
while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) {
|
||||
return trim($row['Name']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getUserId($conn, $mail){
|
||||
|
||||
$sqlMitglieder = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' ";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
#$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)
|
||||
while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) {
|
||||
return trim($row['MitarbeiterID']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function checkKaffeelisteAccess($conn, $mail)
|
||||
{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND aktiv='1'";
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered"));
|
||||
$row_count = sqlsrv_num_rows( $stmtMitarbeiter );
|
||||
#return $row_count;
|
||||
if ($row_count == 1)
|
||||
{
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkKaffeelisteAdmin($conn, $mail)
|
||||
{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND admin='1'";
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered"));
|
||||
$row_count = sqlsrv_num_rows( $stmtMitarbeiter );
|
||||
#return $row_count;
|
||||
if ($row_count == 1)
|
||||
{
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
include_once "config.php";
|
||||
|
||||
$kennungtemp = $_SERVER['AUTH_USER'];
|
||||
$teile = explode("\\", $kennungtemp);
|
||||
$kennung = $teile[1];
|
||||
|
||||
|
||||
include_once "functionsLDAP.php";
|
||||
|
||||
function getUserName($conn, $mail){
|
||||
|
||||
$sqlMitglieder = "SELECT Name FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' ";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
#$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)
|
||||
while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) {
|
||||
return trim($row['Name']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getUserId($conn, $mail){
|
||||
|
||||
$sqlMitglieder = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' ";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
#$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)
|
||||
while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) {
|
||||
return trim($row['MitarbeiterID']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function checkKaffeelisteAccess($conn, $mail)
|
||||
{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND aktiv='1'";
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered"));
|
||||
$row_count = sqlsrv_num_rows( $stmtMitarbeiter );
|
||||
#return $row_count;
|
||||
if ($row_count == 1)
|
||||
{
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkKaffeelisteAdmin($conn, $mail)
|
||||
{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND admin='1'";
|
||||
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered"));
|
||||
$row_count = sqlsrv_num_rows( $stmtMitarbeiter );
|
||||
#return $row_count;
|
||||
if ($row_count == 1)
|
||||
{
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -1,166 +1,166 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
#$kennungtemp = $_SERVER['AUTH_USER'];
|
||||
#$teile = explode("\\", $kennungtemp);
|
||||
#$kennung = $teile[1];
|
||||
|
||||
$ad = ldap_connect("ldap://{$domain}") or die('Could not connect to LDAP server.');
|
||||
|
||||
ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ad, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
@ldap_bind($ad, "{$aduser}@{$domain}", $adpassword) or die('Could not bind to AD.');
|
||||
|
||||
$userdn = getDN($ad, $kennung, $basedn);
|
||||
$mailadress = getADMail($ad, $kennung, $basedn);
|
||||
|
||||
|
||||
ldap_unbind($ad);
|
||||
|
||||
/**
|
||||
* This function searchs in LDAP tree entry specified by samaccountname and
|
||||
* returns its DN or epmty string on failure.
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $samaccountname
|
||||
* The sAMAccountName, logon name.
|
||||
* @param string $basedn
|
||||
* The base DN for the directory.
|
||||
* @return string
|
||||
*/
|
||||
function getDN($ad, $samaccountname, $basedn)
|
||||
{
|
||||
$result = ldap_search($ad, $basedn, "(samaccountname={$samaccountname})", array(
|
||||
'dn'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
if ($entries['count'] > 0)
|
||||
{
|
||||
return $entries[0]['dn'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getADMail($ad, $samaccountname, $basedn)
|
||||
{
|
||||
$attributes = array('mail');
|
||||
$resultz = ldap_search($ad, $basedn, "(samaccountname={$samaccountname})", $attributes);
|
||||
$entriesz = ldap_get_entries($ad, $resultz);
|
||||
|
||||
#return $entriesz[0]['mail'];
|
||||
# $entries = ldap_get_entries($ad, $result);
|
||||
if ($entriesz['count'] > 0)
|
||||
{
|
||||
return $entriesz[0]['mail'][0];
|
||||
}
|
||||
|
||||
return 'nichts gefunden';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function retrieves and returns Common Name from a given Distinguished
|
||||
* Name.
|
||||
*
|
||||
* @param string $dn
|
||||
* The Distinguished Name.
|
||||
* @return string The Common Name.
|
||||
*/
|
||||
function getCN($dn)
|
||||
{
|
||||
preg_match('/[^,]*/', $dn, $matchs, PREG_OFFSET_CAPTURE, 3);
|
||||
return $matchs[0][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks group membership of the user, searching only in
|
||||
* specified group (not recursively).
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $userdn
|
||||
* The user Distinguished Name.
|
||||
* @param string $groupdn
|
||||
* The group Distinguished Name.
|
||||
* @return boolean Return true if user is a member of group, and false if not
|
||||
* a member.
|
||||
*/
|
||||
function checkGroup($ad, $userdn, $groupdn)
|
||||
{
|
||||
$result = ldap_read($ad, $userdn, "(memberof={$groupdn})", array(
|
||||
'members'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
|
||||
return ($entries['count'] > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks group membership of the user, searching in specified
|
||||
* group and groups which is its members (recursively).
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $userdn
|
||||
* The user Distinguished Name.
|
||||
* @param string $groupdn
|
||||
* The group Distinguished Name.
|
||||
* @return boolean Return true if user is a member of group, and false if not
|
||||
* a member.
|
||||
*/
|
||||
function checkGroupEx($ad, $userdn, $groupdn)
|
||||
{
|
||||
if ($groupdn == "")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = ldap_read($ad, $userdn, '(objectclass=*)', array(
|
||||
'memberof'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
if ($entries['count'] <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($entries[0]['memberof']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $entries[0]['memberof']['count']; $i ++)
|
||||
{
|
||||
if ($entries[0]['memberof'][$i] == $groupdn)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
elseif (checkGroupEx($ad, $entries[0]['memberof'][$i], $groupdn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
#$kennungtemp = $_SERVER['AUTH_USER'];
|
||||
#$teile = explode("\\", $kennungtemp);
|
||||
#$kennung = $teile[1];
|
||||
|
||||
$ad = ldap_connect("ldap://{$domain}") or die('Could not connect to LDAP server.');
|
||||
|
||||
ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ad, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
@ldap_bind($ad, "{$aduser}@{$domain}", $adpassword) or die('Could not bind to AD.');
|
||||
|
||||
$userdn = getDN($ad, $kennung, $basedn);
|
||||
$mailadress = getADMail($ad, $kennung, $basedn);
|
||||
|
||||
|
||||
ldap_unbind($ad);
|
||||
|
||||
/**
|
||||
* This function searchs in LDAP tree entry specified by samaccountname and
|
||||
* returns its DN or epmty string on failure.
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $samaccountname
|
||||
* The sAMAccountName, logon name.
|
||||
* @param string $basedn
|
||||
* The base DN for the directory.
|
||||
* @return string
|
||||
*/
|
||||
function getDN($ad, $samaccountname, $basedn)
|
||||
{
|
||||
$result = ldap_search($ad, $basedn, "(samaccountname={$samaccountname})", array(
|
||||
'dn'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
if ($entries['count'] > 0)
|
||||
{
|
||||
return $entries[0]['dn'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getADMail($ad, $samaccountname, $basedn)
|
||||
{
|
||||
$attributes = array('mail');
|
||||
$resultz = ldap_search($ad, $basedn, "(samaccountname={$samaccountname})", $attributes);
|
||||
$entriesz = ldap_get_entries($ad, $resultz);
|
||||
|
||||
#return $entriesz[0]['mail'];
|
||||
# $entries = ldap_get_entries($ad, $result);
|
||||
if ($entriesz['count'] > 0)
|
||||
{
|
||||
return $entriesz[0]['mail'][0];
|
||||
}
|
||||
|
||||
return 'nichts gefunden';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function retrieves and returns Common Name from a given Distinguished
|
||||
* Name.
|
||||
*
|
||||
* @param string $dn
|
||||
* The Distinguished Name.
|
||||
* @return string The Common Name.
|
||||
*/
|
||||
function getCN($dn)
|
||||
{
|
||||
preg_match('/[^,]*/', $dn, $matchs, PREG_OFFSET_CAPTURE, 3);
|
||||
return $matchs[0][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks group membership of the user, searching only in
|
||||
* specified group (not recursively).
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $userdn
|
||||
* The user Distinguished Name.
|
||||
* @param string $groupdn
|
||||
* The group Distinguished Name.
|
||||
* @return boolean Return true if user is a member of group, and false if not
|
||||
* a member.
|
||||
*/
|
||||
function checkGroup($ad, $userdn, $groupdn)
|
||||
{
|
||||
$result = ldap_read($ad, $userdn, "(memberof={$groupdn})", array(
|
||||
'members'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
|
||||
return ($entries['count'] > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks group membership of the user, searching in specified
|
||||
* group and groups which is its members (recursively).
|
||||
*
|
||||
* @param resource $ad
|
||||
* An LDAP link identifier, returned by ldap_connect().
|
||||
* @param string $userdn
|
||||
* The user Distinguished Name.
|
||||
* @param string $groupdn
|
||||
* The group Distinguished Name.
|
||||
* @return boolean Return true if user is a member of group, and false if not
|
||||
* a member.
|
||||
*/
|
||||
function checkGroupEx($ad, $userdn, $groupdn)
|
||||
{
|
||||
if ($groupdn == "")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = ldap_read($ad, $userdn, '(objectclass=*)', array(
|
||||
'memberof'
|
||||
));
|
||||
if (! $result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$entries = ldap_get_entries($ad, $result);
|
||||
if ($entries['count'] <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($entries[0]['memberof']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $entries[0]['memberof']['count']; $i ++)
|
||||
{
|
||||
if ($entries[0]['memberof'][$i] == $groupdn)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
elseif (checkGroupEx($ad, $entries[0]['memberof'][$i], $groupdn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,38 +1,38 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Miniport by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Kaffeeliste</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<link rel="stylesheet" href="assets/css/main.css" />
|
||||
</head>
|
||||
<body class="is-preload">
|
||||
<?php
|
||||
|
||||
//echo "<div style='background-color: #ffeb3b; padding: 10px; text-align: center; font-weight: bold;'>1</div>";
|
||||
// Aktuelle Hinweise abrufen
|
||||
$sql = "SELECT nachricht FROM kl_hinweise WHERE gueltig_bis >= SYSDATETIME() ORDER BY gueltig_bis ASC";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
echo "<div style='background-color: #ffeb3b; padding: 25px; text-align: center; font-weight: bold; font-size: 20px;'>"
|
||||
. htmlspecialchars($row['nachricht']) .
|
||||
"</div>";
|
||||
}
|
||||
|
||||
?>
|
||||
<!-- Wrapper -->
|
||||
<div id="wrapper">
|
||||
|
||||
<!-- Main -->
|
||||
<div id="main">
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Miniport by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Kaffeeliste</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<link rel="stylesheet" href="assets/css/main.css" />
|
||||
</head>
|
||||
<body class="is-preload">
|
||||
<?php
|
||||
|
||||
//echo "<div style='background-color: #ffeb3b; padding: 10px; text-align: center; font-weight: bold;'>1</div>";
|
||||
// Aktuelle Hinweise abrufen
|
||||
$sql = "SELECT nachricht FROM kl_hinweise WHERE gueltig_bis >= SYSDATETIME() ORDER BY gueltig_bis ASC";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
echo "<div style='background-color: #ffeb3b; padding: 25px; text-align: center; font-weight: bold; font-size: 20px;'>"
|
||||
. htmlspecialchars($row['nachricht']) .
|
||||
"</div>";
|
||||
}
|
||||
|
||||
?>
|
||||
<!-- Wrapper -->
|
||||
<div id="wrapper">
|
||||
|
||||
<!-- Main -->
|
||||
<div id="main">
|
||||
<div class="inner">
|
||||
@@ -1,95 +1,95 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste - Hinweise</h2>";
|
||||
|
||||
// Hinweis löschen
|
||||
if (isset($_GET['delete'])) {
|
||||
$id = (int)$_GET['delete'];
|
||||
$stmt = sqlsrv_query($conn, "DELETE FROM kl_hinweise WHERE id = ?", [$id]);
|
||||
}
|
||||
|
||||
// Hinweis speichern
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$nachricht = $_POST['nachricht'];
|
||||
|
||||
|
||||
$gueltig_bis = $_POST['gueltig_bis']; // z.B. "2025-09-03T14:00"
|
||||
$dt = DateTime::createFromFormat('Y-m-d\TH:i', $gueltig_bis);
|
||||
|
||||
if ($dt) {
|
||||
$gueltig_bis_sql = $dt->format('Y-d-m H:i:s'); // z.B. "2025-03-09 14:00:00"
|
||||
} else {
|
||||
die("Ungültiges Datumsformat");
|
||||
}
|
||||
|
||||
if (!empty($nachricht) && !empty($gueltig_bis_sql)) {
|
||||
|
||||
$stmt = sqlsrv_query($conn,
|
||||
"INSERT INTO kl_hinweise (nachricht, gueltig_bis) VALUES (?, ?)",
|
||||
[$nachricht, $gueltig_bis_sql]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Hinweise abrufen
|
||||
$hinweise = [];
|
||||
$stmt = sqlsrv_query($conn, "SELECT id, nachricht, gueltig_bis FROM kl_hinweise ORDER BY gueltig_bis DESC");
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$hinweise[] = $row;
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<h2>Neuen Hinweis hinzufügen</h2>
|
||||
<form method="post">
|
||||
<label>Nachricht:</label><br>
|
||||
<textarea name="nachricht" required></textarea><br><br>
|
||||
<label>Gültig bis:</label><br>
|
||||
<input type="datetime-local" name="gueltig_bis" required><br><br>
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
|
||||
<h2>Alle Hinweise</h2>
|
||||
<?php foreach ($hinweise as $hinweis): ?>
|
||||
<div class="hinweis">
|
||||
<strong><?= htmlspecialchars($hinweis['nachricht']) ?></strong><br>
|
||||
<small>Gültig bis: <?= $hinweis['gueltig_bis']->format('d.m.Y H:i') ?></small><br>
|
||||
<a href="?delete=<?= $hinweis['id'] ?>" onclick="return confirm('Diesen Hinweis wirklich löschen?')">🗑️ Löschen</a>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste - Hinweise</h2>";
|
||||
|
||||
// Hinweis löschen
|
||||
if (isset($_GET['delete'])) {
|
||||
$id = (int)$_GET['delete'];
|
||||
$stmt = sqlsrv_query($conn, "DELETE FROM kl_hinweise WHERE id = ?", [$id]);
|
||||
}
|
||||
|
||||
// Hinweis speichern
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$nachricht = $_POST['nachricht'];
|
||||
|
||||
|
||||
$gueltig_bis = $_POST['gueltig_bis']; // z.B. "2025-09-03T14:00"
|
||||
$dt = DateTime::createFromFormat('Y-m-d\TH:i', $gueltig_bis);
|
||||
|
||||
if ($dt) {
|
||||
$gueltig_bis_sql = $dt->format('Y-d-m H:i:s'); // z.B. "2025-03-09 14:00:00"
|
||||
} else {
|
||||
die("Ungültiges Datumsformat");
|
||||
}
|
||||
|
||||
if (!empty($nachricht) && !empty($gueltig_bis_sql)) {
|
||||
|
||||
$stmt = sqlsrv_query($conn,
|
||||
"INSERT INTO kl_hinweise (nachricht, gueltig_bis) VALUES (?, ?)",
|
||||
[$nachricht, $gueltig_bis_sql]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Hinweise abrufen
|
||||
$hinweise = [];
|
||||
$stmt = sqlsrv_query($conn, "SELECT id, nachricht, gueltig_bis FROM kl_hinweise ORDER BY gueltig_bis DESC");
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$hinweise[] = $row;
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<h2>Neuen Hinweis hinzufügen</h2>
|
||||
<form method="post">
|
||||
<label>Nachricht:</label><br>
|
||||
<textarea name="nachricht" required></textarea><br><br>
|
||||
<label>Gültig bis:</label><br>
|
||||
<input type="datetime-local" name="gueltig_bis" required><br><br>
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
|
||||
<h2>Alle Hinweise</h2>
|
||||
<?php foreach ($hinweise as $hinweis): ?>
|
||||
<div class="hinweis">
|
||||
<strong><?= htmlspecialchars($hinweis['nachricht']) ?></strong><br>
|
||||
<small>Gültig bis: <?= $hinweis['gueltig_bis']->format('d.m.Y H:i') ?></small><br>
|
||||
<a href="?delete=<?= $hinweis['id'] ?>" onclick="return confirm('Diesen Hinweis wirklich löschen?')">🗑️ Löschen</a>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
+240
-240
@@ -1,241 +1,241 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$gesamtstriche = $rowAusgabe['Gesamtstriche'];
|
||||
$aktuellerStand = $gesamteinzahlung - $gesamtausgabe;
|
||||
|
||||
// Gesamteinzahlung pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy') ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$yeareinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy')";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$yearausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$yearstriche = $rowAusgabe['Gesamtstriche'];
|
||||
|
||||
return array('Jahresausgabe' => $yearausgabe, 'Jahresstriche' => $yearstriche, 'Jahreseinzahlung' => $yeareinzahlung, 'Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
#return array('Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
|
||||
}
|
||||
function AusgabeletztenEinzahlungen($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT Betrag,Datum FROM kl_Einzahlungen WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Einzahlungen</h4><table><tr><th style='width:120'>Datum</th><th>Einzahlung</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . number_format($row["Betrag"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
function AusgabeletztenStriche($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT AnzahlStriche,Kosten,Datum FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Striche</h4><table ><tr><th style='width:120'>Datum</th><th>Striche</th><th>Kosten</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . $row["AnzahlStriche"] . "</td><td>" . number_format($row["Kosten"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
|
||||
// E-Mail-Adresse des Mitarbeiters (ersetze durch die tatsächliche E-Mail)
|
||||
$email = $mailadress;
|
||||
|
||||
// Berechne Gesamtausgabe und Gesamtstriche für den Mitarbeiter
|
||||
$result = berechneGesamtausgabe($email, $conn);
|
||||
|
||||
if ($result !== null) {
|
||||
|
||||
#echo "<h2>Gesamtausgabe und Gesamtstriche</h2>";
|
||||
#echo "<p>E-Mail: $email</p>";
|
||||
#echo "Gesamtausgabe: " . number_format($result['Gesamtausgabe'], 2, ',', '') . " €<br>";
|
||||
#echo "Gesamtstriche: {$result['Gesamtstriche']}<br>";
|
||||
#echo "<p>Gesamteinzahlung: " . number_format($result['Gesamteinzahlung'], 2, ',', '') . " €<br>";
|
||||
$aktuellerstand = number_format($result['aktuellerStand'], 2, ',', '.');
|
||||
if($result['aktuellerStand'] > 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Guthaben)</p>";
|
||||
}elseif($result['aktuellerStand'] < 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Schulden)</p>";
|
||||
}else{
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} €</p>";
|
||||
}
|
||||
echo "</b>";
|
||||
echo "<h2>Jahresübersicht</h2>";
|
||||
echo "Ausgabe im aktuellem Jahr: " . number_format($result['Jahresausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche im aktuellem Jahr: {$result['Jahresstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung im aktuellem Jahr: " . number_format($result['Jahreseinzahlung'], 2, ',', '') . " €<br>";
|
||||
|
||||
|
||||
$sqlconfig = "SELECT paypaluse,paypallink,strichperweb FROM kl_config";
|
||||
$stmtconfig = sqlsrv_query($conn, $sqlconfig, array($email));
|
||||
$rowconfig = sqlsrv_fetch_array($stmtconfig, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if($rowconfig["strichperweb"] == 1){
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, ',', '');
|
||||
|
||||
echo "<h2>Eintrag in die Strichliste</h2>";
|
||||
echo '<b>Hier kannst du einen oder zwei Striche für dich in der Kaffeeliste eintragen. <br>Dafür benötigst du keinen Eintrag auf der Liste durchführen.</b><br>Aktueller Preis pro Strich: '.$KostenproStrich . ' €<br><br>';
|
||||
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form method="post" action="' . htmlspecialchars($_SERVER["PHP_SELF"]) . '"><button type="submit">Einen Strich eintragen</button><input type="hidden" name="anzahlStriche" value="1" ></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form method="post" action="' . htmlspecialchars($_SERVER["PHP_SELF"]) . '"><button type="submit">Zwei Striche eintragen</button><input type="hidden" name="anzahlStriche" value="2" ></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
$anzahlStriche = $_POST["anzahlStriche"];
|
||||
$anzahlStriche = (int)$anzahlStriche;
|
||||
$kostenproStrich = floatval($KostenproStrichtemp);
|
||||
$kosten = floatval($anzahlStriche * $KostenproStrichtemp);
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
if($anzahlStriche != 0){
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Kaffeeverbrauch (MitarbeiterID, AnzahlStriche, Kosten, KostenproStrich, Datum, Eintragsart) VALUES (?, ?, ?, ?, ?, 2)";
|
||||
$params = array(getUserId($conn,$email), $anzahlStriche, $kosten, $kostenproStrich, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
echo '<div class="hint-box success"> <i class="fas fa-check-circle"></i> <p><b>Stricheintragung wurde erfolgreich eingetragen!</b><br>Du kannst den Eintrag weiter unten kontrollieren.</p> </div><br>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if($rowconfig["paypaluse"] == 1){
|
||||
echo "<h2>Paypal-Einzahlungen</h2>";
|
||||
echo '<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.</b><br>';
|
||||
|
||||
$paypallink = trim($rowconfig["paypallink"]);
|
||||
echo "<br>";
|
||||
if($result['aktuellerStand'] < 0){
|
||||
|
||||
echo '<form action="' . $paypallink .'' . $aktuellerstand . '" target="_blank" ><button type="submit">'. $aktuellerstand . ' € bezahlen</button></form>';
|
||||
|
||||
|
||||
}
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form action="' . $paypallink .'5" target="_blank" ><button type="submit">5,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'10" target="_blank" ><button type="submit">10,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'15" target="_blank" ><button type="submit">15,00 € einzahlen</button></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
}
|
||||
echo "<br>";
|
||||
echo "<br>";
|
||||
echo AusgabeletztenEinzahlungen($email, $conn);
|
||||
echo "<br>";
|
||||
echo AusgabeletztenStriche($email, $conn);
|
||||
?>
|
||||
<br><br>
|
||||
|
||||
<!-- Formular mit Button zum Anpassen des Namens -->
|
||||
<form action="namenanpassen.php" method="get">
|
||||
<button type="submit">Namensanpassung</button>
|
||||
</form>
|
||||
<?php
|
||||
} else {
|
||||
echo "<p>Mitarbeiter mit der E-Mail-Adresse $email wurde nicht gefunden.</p>";
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$gesamtstriche = $rowAusgabe['Gesamtstriche'];
|
||||
$aktuellerStand = $gesamteinzahlung - $gesamtausgabe;
|
||||
|
||||
// Gesamteinzahlung pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy') ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$yeareinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy')";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$yearausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$yearstriche = $rowAusgabe['Gesamtstriche'];
|
||||
|
||||
return array('Jahresausgabe' => $yearausgabe, 'Jahresstriche' => $yearstriche, 'Jahreseinzahlung' => $yeareinzahlung, 'Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
#return array('Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
|
||||
}
|
||||
function AusgabeletztenEinzahlungen($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT Betrag,Datum FROM kl_Einzahlungen WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Einzahlungen</h4><table><tr><th style='width:120'>Datum</th><th>Einzahlung</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . number_format($row["Betrag"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
function AusgabeletztenStriche($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT AnzahlStriche,Kosten,Datum FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Striche</h4><table ><tr><th style='width:120'>Datum</th><th>Striche</th><th>Kosten</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . $row["AnzahlStriche"] . "</td><td>" . number_format($row["Kosten"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
|
||||
// E-Mail-Adresse des Mitarbeiters (ersetze durch die tatsächliche E-Mail)
|
||||
$email = $mailadress;
|
||||
|
||||
// Berechne Gesamtausgabe und Gesamtstriche für den Mitarbeiter
|
||||
$result = berechneGesamtausgabe($email, $conn);
|
||||
|
||||
if ($result !== null) {
|
||||
|
||||
#echo "<h2>Gesamtausgabe und Gesamtstriche</h2>";
|
||||
#echo "<p>E-Mail: $email</p>";
|
||||
#echo "Gesamtausgabe: " . number_format($result['Gesamtausgabe'], 2, ',', '') . " €<br>";
|
||||
#echo "Gesamtstriche: {$result['Gesamtstriche']}<br>";
|
||||
#echo "<p>Gesamteinzahlung: " . number_format($result['Gesamteinzahlung'], 2, ',', '') . " €<br>";
|
||||
$aktuellerstand = number_format($result['aktuellerStand'], 2, ',', '.');
|
||||
if($result['aktuellerStand'] > 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Guthaben)</p>";
|
||||
}elseif($result['aktuellerStand'] < 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Schulden)</p>";
|
||||
}else{
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} €</p>";
|
||||
}
|
||||
echo "</b>";
|
||||
echo "<h2>Jahresübersicht</h2>";
|
||||
echo "Ausgabe im aktuellem Jahr: " . number_format($result['Jahresausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche im aktuellem Jahr: {$result['Jahresstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung im aktuellem Jahr: " . number_format($result['Jahreseinzahlung'], 2, ',', '') . " €<br>";
|
||||
|
||||
|
||||
$sqlconfig = "SELECT paypaluse,paypallink,strichperweb FROM kl_config";
|
||||
$stmtconfig = sqlsrv_query($conn, $sqlconfig, array($email));
|
||||
$rowconfig = sqlsrv_fetch_array($stmtconfig, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if($rowconfig["strichperweb"] == 1){
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, ',', '');
|
||||
|
||||
echo "<h2>Eintrag in die Strichliste</h2>";
|
||||
echo '<b>Hier kannst du einen oder zwei Striche für dich in der Kaffeeliste eintragen. <br>Dafür benötigst du keinen Eintrag auf der Liste durchführen.</b><br>Aktueller Preis pro Strich: '.$KostenproStrich . ' €<br><br>';
|
||||
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form method="post" action="' . htmlspecialchars($_SERVER["PHP_SELF"]) . '"><button type="submit">Einen Strich eintragen</button><input type="hidden" name="anzahlStriche" value="1" ></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form method="post" action="' . htmlspecialchars($_SERVER["PHP_SELF"]) . '"><button type="submit">Zwei Striche eintragen</button><input type="hidden" name="anzahlStriche" value="2" ></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
$anzahlStriche = $_POST["anzahlStriche"];
|
||||
$anzahlStriche = (int)$anzahlStriche;
|
||||
$kostenproStrich = floatval($KostenproStrichtemp);
|
||||
$kosten = floatval($anzahlStriche * $KostenproStrichtemp);
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
if($anzahlStriche != 0){
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Kaffeeverbrauch (MitarbeiterID, AnzahlStriche, Kosten, KostenproStrich, Datum, Eintragsart) VALUES (?, ?, ?, ?, ?, 2)";
|
||||
$params = array(getUserId($conn,$email), $anzahlStriche, $kosten, $kostenproStrich, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
echo '<div class="hint-box success"> <i class="fas fa-check-circle"></i> <p><b>Stricheintragung wurde erfolgreich eingetragen!</b><br>Du kannst den Eintrag weiter unten kontrollieren.</p> </div><br>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if($rowconfig["paypaluse"] == 1){
|
||||
echo "<h2>Paypal-Einzahlungen</h2>";
|
||||
echo '<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.</b><br>';
|
||||
|
||||
$paypallink = trim($rowconfig["paypallink"]);
|
||||
echo "<br>";
|
||||
if($result['aktuellerStand'] < 0){
|
||||
|
||||
echo '<form action="' . $paypallink .'' . $aktuellerstand . '" target="_blank" ><button type="submit">'. $aktuellerstand . ' € bezahlen</button></form>';
|
||||
|
||||
|
||||
}
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form action="' . $paypallink .'5" target="_blank" ><button type="submit">5,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'10" target="_blank" ><button type="submit">10,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'15" target="_blank" ><button type="submit">15,00 € einzahlen</button></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
}
|
||||
echo "<br>";
|
||||
echo "<br>";
|
||||
echo AusgabeletztenEinzahlungen($email, $conn);
|
||||
echo "<br>";
|
||||
echo AusgabeletztenStriche($email, $conn);
|
||||
?>
|
||||
<br><br>
|
||||
|
||||
<!-- Formular mit Button zum Anpassen des Namens -->
|
||||
<form action="namenanpassen.php" method="get">
|
||||
<button type="submit">Namensanpassung</button>
|
||||
</form>
|
||||
<?php
|
||||
} else {
|
||||
echo "<p>Mitarbeiter mit der E-Mail-Adresse $email wurde nicht gefunden.</p>";
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
@@ -1,177 +1,177 @@
|
||||
<?php
|
||||
// Einstellungen
|
||||
// Verbindung zur Datenbank herstellen (ersetze die Platzhalter durch deine Daten)
|
||||
$serverName = "sql-nds-autoclient-prod.aoknds.aok";
|
||||
$connectionOptions = array(
|
||||
"Database" => "Automatisierungsclient",
|
||||
"Uid" => "ac_admin",
|
||||
"PWD" => "allacc3ssPW",
|
||||
"TrustServerCertificate"=>true
|
||||
);
|
||||
|
||||
$stricheAnzupassen = 490; // Anzahl der neuen Striche
|
||||
$betragProStrich = 0.20; // Betrag pro Strich in Euro
|
||||
|
||||
// Testmodus aktivieren
|
||||
$testmodus = false;
|
||||
|
||||
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require 'PHPMailer/src/Exception.php';
|
||||
require 'PHPMailer/src/PHPMailer.php';
|
||||
require 'PHPMailer/src/SMTP.php';
|
||||
|
||||
// PHPMailer konfigurieren
|
||||
function sendeMail($empfaenger, $betreff, $inhalt, $testmodus)
|
||||
{
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
// Server-Einstellungen
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'smtpv.aoknds.aok'; // SMTP-Server
|
||||
$mail->Timeout = 180;
|
||||
$mail->SMTPAuth = false;
|
||||
$mail->Port = 25;
|
||||
|
||||
// Absender
|
||||
$mail->setFrom('kaffeelistesb3@nds.aok.de', 'Kaffeeliste');
|
||||
|
||||
// Empfänger
|
||||
if ($testmodus) {
|
||||
$mail->addAddress('kaffeelistesb3@nds.aok.de'); // Testadresse
|
||||
} else {
|
||||
$mail->addAddress($empfaenger); // Tatsächlicher Empfänger
|
||||
}
|
||||
|
||||
// Inhalt
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $betreff;
|
||||
$mail->Body = utf8_decode($inhalt);
|
||||
|
||||
// Senden
|
||||
$mail->send();
|
||||
echo "E-Mail erfolgreich gesendet an: " . ($testmodus ? 'kaffeelistesb3@nds.aok.de' : $empfaenger) . "\n";
|
||||
} catch (Exception $e) {
|
||||
echo "E-Mail konnte nicht gesendet werden. Fehler: {$mail->ErrorInfo}\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Verbindung herstellen
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
// Aktuelles Jahr ermitteln
|
||||
$currentYear = date("Y");
|
||||
|
||||
// SQL-Abfrage: Gesamtanzahl der Striche pro Mitarbeiter im aktuellen Jahr mit Namen und E-Mail
|
||||
$sql = "
|
||||
SELECT
|
||||
m.MitarbeiterID,
|
||||
m.Name,
|
||||
m.Email,
|
||||
SUM(v.AnzahlStriche) AS GesamtStriche
|
||||
FROM kl_Kaffeeverbrauch v
|
||||
JOIN kl_Mitarbeiter m ON v.MitarbeiterID = m.MitarbeiterID
|
||||
WHERE YEAR(v.Datum) = ? AND m.aktiv = 1
|
||||
GROUP BY m.MitarbeiterID, m.Name, m.Email
|
||||
";
|
||||
$params = [$currentYear];
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
// Ergebnisse verarbeiten
|
||||
$mitarbeiterDaten = [];
|
||||
$gesamtStriche = 0;
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterDaten[] = $row;
|
||||
$gesamtStriche += $row['GesamtStriche'];
|
||||
}
|
||||
|
||||
echo $gesamtStriche;
|
||||
|
||||
// Neue Striche proportional verteilen
|
||||
$verteilung = [];
|
||||
|
||||
foreach ($mitarbeiterDaten as $mitarbeiter) {
|
||||
$mitarbeiterID = $mitarbeiter['MitarbeiterID'];
|
||||
$anteil = $mitarbeiter['GesamtStriche'] / $gesamtStriche;
|
||||
$neueStriche = round($anteil * $stricheAnzupassen);
|
||||
$betrag = $neueStriche * $betragProStrich;
|
||||
|
||||
$verteilung[] = [
|
||||
'MitarbeiterID' => $mitarbeiterID,
|
||||
'Name' => $mitarbeiter['Name'],
|
||||
'Email' => $mitarbeiter['Email'],
|
||||
'JahrStriche' => $mitarbeiter['GesamtStriche'],
|
||||
'NeueStriche' => $neueStriche,
|
||||
'Betrag' => $betrag
|
||||
];
|
||||
|
||||
// SQL-Befehl vorbereiten
|
||||
$insertSql = "
|
||||
INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum)
|
||||
VALUES (?, ?, GETDATE())
|
||||
";
|
||||
$insertParams = [$mitarbeiterID, $betrag];
|
||||
|
||||
if ($testmodus) {
|
||||
// SQL-Befehl und Parameter anzeigen
|
||||
echo "SQL-Befehl: $insertSql\n";
|
||||
echo "Parameter: " . json_encode($insertParams) . "\n";
|
||||
// E-Mail vorbereiten
|
||||
|
||||
} else {
|
||||
// SQL-Befehl ausführen
|
||||
$insertStmt = sqlsrv_query($conn, $insertSql, $insertParams);
|
||||
if ($insertStmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
// E-Mail vorbereiten
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$betreff = "Kaffeeliste - Weihnachten";
|
||||
$inhalt = "
|
||||
<p>Hallo {$mitarbeiter['Name']},</p>
|
||||
<p>vielen Dank für deine Nutzung der Kaffeeliste in diesem Jahr!</p>
|
||||
<p>Du hast dieses Jahr {$mitarbeiter['GesamtStriche']} Kaffee bezogen.</p>
|
||||
<p>Deswegen wurden dir $betrag Euro auf deinem Konto gutgeschrieben.</p>
|
||||
<br><br>
|
||||
<p>Wir wünschen dir eine frohe Weihnachtszeit und einen guten Rutsch ins neue Jahr.</p>
|
||||
<p>Deine ARGE Kaffeeliste</p>
|
||||
";
|
||||
$empfaenger = $mitarbeiter['Email'];
|
||||
// E-Mail senden
|
||||
sendeMail($empfaenger, $betreff, $inhalt, $testmodus);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Sortiere die Verteilung nach JahrStriche (absteigend)
|
||||
usort($verteilung, function ($a, $b) {
|
||||
return $b['JahrStriche'] <=> $a['JahrStriche'];
|
||||
});
|
||||
|
||||
// Ergebnisse ausgeben
|
||||
header('Content-Type: application/json');
|
||||
#echo json_encode($verteilung, JSON_PRETTY_PRINT);
|
||||
|
||||
// Verbindung schließen
|
||||
sqlsrv_close($conn);
|
||||
?>
|
||||
|
||||
<?php
|
||||
// Einstellungen
|
||||
// Verbindung zur Datenbank herstellen (ersetze die Platzhalter durch deine Daten)
|
||||
$serverName = "sql-nds-autoclient-prod.aoknds.aok";
|
||||
$connectionOptions = array(
|
||||
"Database" => "Automatisierungsclient",
|
||||
"Uid" => "ac_admin",
|
||||
"PWD" => "allacc3ssPW",
|
||||
"TrustServerCertificate"=>true
|
||||
);
|
||||
|
||||
$stricheAnzupassen = 490; // Anzahl der neuen Striche
|
||||
$betragProStrich = 0.20; // Betrag pro Strich in Euro
|
||||
|
||||
// Testmodus aktivieren
|
||||
$testmodus = false;
|
||||
|
||||
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require 'PHPMailer/src/Exception.php';
|
||||
require 'PHPMailer/src/PHPMailer.php';
|
||||
require 'PHPMailer/src/SMTP.php';
|
||||
|
||||
// PHPMailer konfigurieren
|
||||
function sendeMail($empfaenger, $betreff, $inhalt, $testmodus)
|
||||
{
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
// Server-Einstellungen
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'smtpv.aoknds.aok'; // SMTP-Server
|
||||
$mail->Timeout = 180;
|
||||
$mail->SMTPAuth = false;
|
||||
$mail->Port = 25;
|
||||
|
||||
// Absender
|
||||
$mail->setFrom('kaffeelistesb3@nds.aok.de', 'Kaffeeliste');
|
||||
|
||||
// Empfänger
|
||||
if ($testmodus) {
|
||||
$mail->addAddress('kaffeelistesb3@nds.aok.de'); // Testadresse
|
||||
} else {
|
||||
$mail->addAddress($empfaenger); // Tatsächlicher Empfänger
|
||||
}
|
||||
|
||||
// Inhalt
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $betreff;
|
||||
$mail->Body = utf8_decode($inhalt);
|
||||
|
||||
// Senden
|
||||
$mail->send();
|
||||
echo "E-Mail erfolgreich gesendet an: " . ($testmodus ? 'kaffeelistesb3@nds.aok.de' : $empfaenger) . "\n";
|
||||
} catch (Exception $e) {
|
||||
echo "E-Mail konnte nicht gesendet werden. Fehler: {$mail->ErrorInfo}\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Verbindung herstellen
|
||||
$conn = sqlsrv_connect($serverName, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
// Aktuelles Jahr ermitteln
|
||||
$currentYear = date("Y");
|
||||
|
||||
// SQL-Abfrage: Gesamtanzahl der Striche pro Mitarbeiter im aktuellen Jahr mit Namen und E-Mail
|
||||
$sql = "
|
||||
SELECT
|
||||
m.MitarbeiterID,
|
||||
m.Name,
|
||||
m.Email,
|
||||
SUM(v.AnzahlStriche) AS GesamtStriche
|
||||
FROM kl_Kaffeeverbrauch v
|
||||
JOIN kl_Mitarbeiter m ON v.MitarbeiterID = m.MitarbeiterID
|
||||
WHERE YEAR(v.Datum) = ? AND m.aktiv = 1
|
||||
GROUP BY m.MitarbeiterID, m.Name, m.Email
|
||||
";
|
||||
$params = [$currentYear];
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
// Ergebnisse verarbeiten
|
||||
$mitarbeiterDaten = [];
|
||||
$gesamtStriche = 0;
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterDaten[] = $row;
|
||||
$gesamtStriche += $row['GesamtStriche'];
|
||||
}
|
||||
|
||||
echo $gesamtStriche;
|
||||
|
||||
// Neue Striche proportional verteilen
|
||||
$verteilung = [];
|
||||
|
||||
foreach ($mitarbeiterDaten as $mitarbeiter) {
|
||||
$mitarbeiterID = $mitarbeiter['MitarbeiterID'];
|
||||
$anteil = $mitarbeiter['GesamtStriche'] / $gesamtStriche;
|
||||
$neueStriche = round($anteil * $stricheAnzupassen);
|
||||
$betrag = $neueStriche * $betragProStrich;
|
||||
|
||||
$verteilung[] = [
|
||||
'MitarbeiterID' => $mitarbeiterID,
|
||||
'Name' => $mitarbeiter['Name'],
|
||||
'Email' => $mitarbeiter['Email'],
|
||||
'JahrStriche' => $mitarbeiter['GesamtStriche'],
|
||||
'NeueStriche' => $neueStriche,
|
||||
'Betrag' => $betrag
|
||||
];
|
||||
|
||||
// SQL-Befehl vorbereiten
|
||||
$insertSql = "
|
||||
INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Datum)
|
||||
VALUES (?, ?, GETDATE())
|
||||
";
|
||||
$insertParams = [$mitarbeiterID, $betrag];
|
||||
|
||||
if ($testmodus) {
|
||||
// SQL-Befehl und Parameter anzeigen
|
||||
echo "SQL-Befehl: $insertSql\n";
|
||||
echo "Parameter: " . json_encode($insertParams) . "\n";
|
||||
// E-Mail vorbereiten
|
||||
|
||||
} else {
|
||||
// SQL-Befehl ausführen
|
||||
$insertStmt = sqlsrv_query($conn, $insertSql, $insertParams);
|
||||
if ($insertStmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
// E-Mail vorbereiten
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$betreff = "Kaffeeliste - Weihnachten";
|
||||
$inhalt = "
|
||||
<p>Hallo {$mitarbeiter['Name']},</p>
|
||||
<p>vielen Dank für deine Nutzung der Kaffeeliste in diesem Jahr!</p>
|
||||
<p>Du hast dieses Jahr {$mitarbeiter['GesamtStriche']} Kaffee bezogen.</p>
|
||||
<p>Deswegen wurden dir $betrag Euro auf deinem Konto gutgeschrieben.</p>
|
||||
<br><br>
|
||||
<p>Wir wünschen dir eine frohe Weihnachtszeit und einen guten Rutsch ins neue Jahr.</p>
|
||||
<p>Deine ARGE Kaffeeliste</p>
|
||||
";
|
||||
$empfaenger = $mitarbeiter['Email'];
|
||||
// E-Mail senden
|
||||
sendeMail($empfaenger, $betreff, $inhalt, $testmodus);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Sortiere die Verteilung nach JahrStriche (absteigend)
|
||||
usort($verteilung, function ($a, $b) {
|
||||
return $b['JahrStriche'] <=> $a['JahrStriche'];
|
||||
});
|
||||
|
||||
// Ergebnisse ausgeben
|
||||
header('Content-Type: application/json');
|
||||
#echo json_encode($verteilung, JSON_PRETTY_PRINT);
|
||||
|
||||
// Verbindung schließen
|
||||
sqlsrv_close($conn);
|
||||
?>
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
|
||||
return $gesamtausgabe;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Aktive Mitarbeiter mit Gesamtstand</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Aktive Mitarbeiter mit Gesamtstand</h2>
|
||||
<br>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="exportKaffeeliste.php" method="get">
|
||||
<button type="submit">Kaffeeliste exportieren</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="letzteneintraege.php" method="get">
|
||||
<button type="submit">Letzten Einträge</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="csvupload.php" method="get">
|
||||
<button type="submit">CSV Upload</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<table border="1" class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Aktueller Stand</th>
|
||||
<th>Gesamtausgabe (€)</th>
|
||||
<th>Gesamtstriche</th>
|
||||
<th>Gesamteinzahlungen</th>
|
||||
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
$gesamtausgabe = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$gesamtstriche = berechneGesamtstriche($mitarbeiterID, $conn);
|
||||
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgabe;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$gesamtausgabe = number_format($gesamtausgabe, 2, ',', '.');
|
||||
$gesamteinzahlungen = number_format($gesamteinzahlungen, 2, ',', '.');
|
||||
$gesamtstriche = number_format($gesamtstriche, 0, ',', '.');
|
||||
|
||||
echo "<tr>";
|
||||
echo "<td><a href=teilnehmerauswertung.php?user_id=$mitarbeiterID>{$name}</a></td>";
|
||||
echo "<td>{$email}</td>";
|
||||
echo "<td>{$differenz} €</td>";
|
||||
echo "<td>{$gesamtausgabe} €</td>";
|
||||
echo "<td>{$gesamtstriche}</td>";
|
||||
echo "<td>{$gesamteinzahlungen} €</td>";
|
||||
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
</table>
|
||||
<br><br>
|
||||
|
||||
<form action="mailversenden.php" method="get">
|
||||
<button type="submit">Info-Mail versenden</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
|
||||
return $gesamtausgabe;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Aktive Mitarbeiter mit Gesamtstand</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Aktive Mitarbeiter mit Gesamtstand</h2>
|
||||
<br>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="exportKaffeeliste.php" method="get">
|
||||
<button type="submit">Kaffeeliste exportieren</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="letzteneintraege.php" method="get">
|
||||
<button type="submit">Letzten Einträge</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="csvupload.php" method="get">
|
||||
<button type="submit">CSV Upload</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<table border="1" class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Aktueller Stand</th>
|
||||
<th>Gesamtausgabe (€)</th>
|
||||
<th>Gesamtstriche</th>
|
||||
<th>Gesamteinzahlungen</th>
|
||||
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
$gesamtausgabe = berechneGesamtausgabe($mitarbeiterID, $conn);
|
||||
$gesamtstriche = berechneGesamtstriche($mitarbeiterID, $conn);
|
||||
|
||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
||||
|
||||
$differenztemp = $gesamteinzahlungen - $gesamtausgabe;
|
||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
||||
$gesamtausgabe = number_format($gesamtausgabe, 2, ',', '.');
|
||||
$gesamteinzahlungen = number_format($gesamteinzahlungen, 2, ',', '.');
|
||||
$gesamtstriche = number_format($gesamtstriche, 0, ',', '.');
|
||||
|
||||
echo "<tr>";
|
||||
echo "<td><a href=teilnehmerauswertung.php?user_id=$mitarbeiterID>{$name}</a></td>";
|
||||
echo "<td>{$email}</td>";
|
||||
echo "<td>{$differenz} €</td>";
|
||||
echo "<td>{$gesamtausgabe} €</td>";
|
||||
echo "<td>{$gesamtstriche}</td>";
|
||||
echo "<td>{$gesamteinzahlungen} €</td>";
|
||||
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
</table>
|
||||
<br><br>
|
||||
|
||||
<form action="mailversenden.php" method="get">
|
||||
<button type="submit">Info-Mail versenden</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,238 +1,238 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
|
||||
return $gesamtausgabe;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Funktion zum Löschen einer Einzahlung
|
||||
function loescheEinzahlung($einzahlungID, $conn) {
|
||||
try {
|
||||
$sql = "DELETE FROM kl_Einzahlungen WHERE EinzahlungsID = ?";
|
||||
$params = array($einzahlungID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich gelöscht
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob ein Löschvorgang angefordert wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "loescheneinzahlung") {
|
||||
$einzahlungID = $_POST["einzahlungID"];
|
||||
|
||||
$ergebnis = loescheEinzahlung($einzahlungID, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Einzahlung erfolgreich gelöscht.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// SQL-Abfrage für die letzten 100 Einzahlungen
|
||||
$sqlEinzahlungen = "SELECT TOP 100 kl_Mitarbeiter.Name AS MitarbeiterName, kl_Einzahlungen.EinzahlungsID, kl_Einzahlungen.Betrag, kl_Einzahlungen.Datum
|
||||
FROM kl_Einzahlungen
|
||||
JOIN kl_Mitarbeiter ON kl_Einzahlungen.MitarbeiterID = kl_Mitarbeiter.MitarbeiterID
|
||||
ORDER BY kl_Einzahlungen.Datum DESC";
|
||||
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen);
|
||||
|
||||
?>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Letzte 100 Einzahlungen</title>
|
||||
</head>
|
||||
|
||||
|
||||
<h2>Letzte 100 Einzahlungen</h2>
|
||||
|
||||
<table border="1" class="table table-striped">
|
||||
<tr>
|
||||
<th>Name des Mitarbeiters</th>
|
||||
<th>Betrag</th>
|
||||
<th>Datum</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC)) {
|
||||
$einzahlungID = $row['EinzahlungsID'];
|
||||
$mitarbeiterName = $row['MitarbeiterName'];
|
||||
$betrag = $row['Betrag'];
|
||||
$datum = $row['Datum']->format('Y-m-d H:i:s'); // Das Format kann angepasst werden
|
||||
$betrag = number_format($betrag, 2, ',', '.');
|
||||
echo "<tr>";
|
||||
echo "<td>{$mitarbeiterName}</td>";
|
||||
echo "<td>{$betrag}</td>";
|
||||
echo "<td>{$datum}</td>";
|
||||
echo "<td>";
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='loescheneinzahlung'>";
|
||||
echo "<input type='hidden' name='einzahlungID' value='{$einzahlungID}'>";
|
||||
echo "<button type='submit'>Löschen</button>";
|
||||
echo "</form>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
<br><br>
|
||||
<?php
|
||||
// Funktion zum Löschen eines Strich-Eintrags
|
||||
function loescheStrichEintrag($strichID, $conn) {
|
||||
try {
|
||||
$sql = "DELETE FROM kl_Kaffeeverbrauch WHERE VerbrauchID = ?";
|
||||
$params = array($strichID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich gelöscht
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob ein Löschvorgang angefordert wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "loeschen") {
|
||||
$strichID = $_POST["strichID"];
|
||||
|
||||
$ergebnis = loescheStrichEintrag($strichID, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Strich-Eintrag erfolgreich gelöscht.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
// SQL-Abfrage für die letzten 100 Strich-Einträge
|
||||
$sqlStriche = "SELECT TOP 100 kl_Kaffeeverbrauch.VerbrauchID, kl_Mitarbeiter.Name AS MitarbeiterName, kl_Kaffeeverbrauch.AnzahlStriche, kl_Kaffeeverbrauch.Kosten, kl_Kaffeeverbrauch.Datum
|
||||
FROM kl_Kaffeeverbrauch
|
||||
JOIN kl_Mitarbeiter ON kl_Kaffeeverbrauch.MitarbeiterID = kl_Mitarbeiter.MitarbeiterID
|
||||
ORDER BY kl_Kaffeeverbrauch.Datum DESC";
|
||||
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche);
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Letzte 100 Strich-Einträge</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Letzte 100 Strich-Einträge</h2>
|
||||
|
||||
<table border="1" class="table table-striped">
|
||||
<tr>
|
||||
<th>Name des Mitarbeiters</th>
|
||||
<th>Anzahlstriche</th>
|
||||
<th>Betrag</th>
|
||||
<th>Datum</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC)) {
|
||||
$strichID = $row['VerbrauchID'];
|
||||
$mitarbeiterName = $row['MitarbeiterName'];
|
||||
$anzahlStriche = $row['AnzahlStriche'];
|
||||
$betrag = $row['Kosten'];
|
||||
$datum = $row['Datum']->format('Y-m-d H:i:s'); // Das Format kann angepasst werden
|
||||
$anzahlStriche = number_format($anzahlStriche, 0, ',', '.');
|
||||
$betrag = number_format($betrag, 0, ',', '.');
|
||||
echo "<tr>";
|
||||
echo "<td>{$mitarbeiterName}</td>";
|
||||
echo "<td>{$anzahlStriche}</td>";
|
||||
echo "<td>{$betrag}</td>";
|
||||
echo "<td>{$datum}</td>";
|
||||
echo "<td>";
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='loeschen'>";
|
||||
echo "<input type='hidden' name='strichID' value='{$strichID}'>";
|
||||
echo "<button type='submit'>Löschen</button>";
|
||||
echo "</form>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
|
||||
return $gesamtausgabe;
|
||||
}
|
||||
|
||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
||||
// Gesamtstriche pro Mitarbeiter
|
||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtstriche = $rowStriche['Gesamtstriche'];
|
||||
|
||||
return $gesamtstriche;
|
||||
}
|
||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
||||
// Gesamteinzahlungen pro Mitarbeiter
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'];
|
||||
|
||||
return $gesamteinzahlungen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Funktion zum Löschen einer Einzahlung
|
||||
function loescheEinzahlung($einzahlungID, $conn) {
|
||||
try {
|
||||
$sql = "DELETE FROM kl_Einzahlungen WHERE EinzahlungsID = ?";
|
||||
$params = array($einzahlungID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich gelöscht
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob ein Löschvorgang angefordert wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "loescheneinzahlung") {
|
||||
$einzahlungID = $_POST["einzahlungID"];
|
||||
|
||||
$ergebnis = loescheEinzahlung($einzahlungID, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Einzahlung erfolgreich gelöscht.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// SQL-Abfrage für die letzten 100 Einzahlungen
|
||||
$sqlEinzahlungen = "SELECT TOP 100 kl_Mitarbeiter.Name AS MitarbeiterName, kl_Einzahlungen.EinzahlungsID, kl_Einzahlungen.Betrag, kl_Einzahlungen.Datum
|
||||
FROM kl_Einzahlungen
|
||||
JOIN kl_Mitarbeiter ON kl_Einzahlungen.MitarbeiterID = kl_Mitarbeiter.MitarbeiterID
|
||||
ORDER BY kl_Einzahlungen.Datum DESC";
|
||||
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen);
|
||||
|
||||
?>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Letzte 100 Einzahlungen</title>
|
||||
</head>
|
||||
|
||||
|
||||
<h2>Letzte 100 Einzahlungen</h2>
|
||||
|
||||
<table border="1" class="table table-striped">
|
||||
<tr>
|
||||
<th>Name des Mitarbeiters</th>
|
||||
<th>Betrag</th>
|
||||
<th>Datum</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC)) {
|
||||
$einzahlungID = $row['EinzahlungsID'];
|
||||
$mitarbeiterName = $row['MitarbeiterName'];
|
||||
$betrag = $row['Betrag'];
|
||||
$datum = $row['Datum']->format('Y-m-d H:i:s'); // Das Format kann angepasst werden
|
||||
$betrag = number_format($betrag, 2, ',', '.');
|
||||
echo "<tr>";
|
||||
echo "<td>{$mitarbeiterName}</td>";
|
||||
echo "<td>{$betrag}</td>";
|
||||
echo "<td>{$datum}</td>";
|
||||
echo "<td>";
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='loescheneinzahlung'>";
|
||||
echo "<input type='hidden' name='einzahlungID' value='{$einzahlungID}'>";
|
||||
echo "<button type='submit'>Löschen</button>";
|
||||
echo "</form>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
<br><br>
|
||||
<?php
|
||||
// Funktion zum Löschen eines Strich-Eintrags
|
||||
function loescheStrichEintrag($strichID, $conn) {
|
||||
try {
|
||||
$sql = "DELETE FROM kl_Kaffeeverbrauch WHERE VerbrauchID = ?";
|
||||
$params = array($strichID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich gelöscht
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob ein Löschvorgang angefordert wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "loeschen") {
|
||||
$strichID = $_POST["strichID"];
|
||||
|
||||
$ergebnis = loescheStrichEintrag($strichID, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Strich-Eintrag erfolgreich gelöscht.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
// SQL-Abfrage für die letzten 100 Strich-Einträge
|
||||
$sqlStriche = "SELECT TOP 100 kl_Kaffeeverbrauch.VerbrauchID, kl_Mitarbeiter.Name AS MitarbeiterName, kl_Kaffeeverbrauch.AnzahlStriche, kl_Kaffeeverbrauch.Kosten, kl_Kaffeeverbrauch.Datum
|
||||
FROM kl_Kaffeeverbrauch
|
||||
JOIN kl_Mitarbeiter ON kl_Kaffeeverbrauch.MitarbeiterID = kl_Mitarbeiter.MitarbeiterID
|
||||
ORDER BY kl_Kaffeeverbrauch.Datum DESC";
|
||||
|
||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche);
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Letzte 100 Strich-Einträge</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Letzte 100 Strich-Einträge</h2>
|
||||
|
||||
<table border="1" class="table table-striped">
|
||||
<tr>
|
||||
<th>Name des Mitarbeiters</th>
|
||||
<th>Anzahlstriche</th>
|
||||
<th>Betrag</th>
|
||||
<th>Datum</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC)) {
|
||||
$strichID = $row['VerbrauchID'];
|
||||
$mitarbeiterName = $row['MitarbeiterName'];
|
||||
$anzahlStriche = $row['AnzahlStriche'];
|
||||
$betrag = $row['Kosten'];
|
||||
$datum = $row['Datum']->format('Y-m-d H:i:s'); // Das Format kann angepasst werden
|
||||
$anzahlStriche = number_format($anzahlStriche, 0, ',', '.');
|
||||
$betrag = number_format($betrag, 0, ',', '.');
|
||||
echo "<tr>";
|
||||
echo "<td>{$mitarbeiterName}</td>";
|
||||
echo "<td>{$anzahlStriche}</td>";
|
||||
echo "<td>{$betrag}</td>";
|
||||
echo "<td>{$datum}</td>";
|
||||
echo "<td>";
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='loeschen'>";
|
||||
echo "<input type='hidden' name='strichID' value='{$strichID}'>";
|
||||
echo "<button type='submit'>Löschen</button>";
|
||||
echo "</form>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}else{
|
||||
echo "<h2>Kein Zugriff</h2>";
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,50 +1,50 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
echo "{$email};";
|
||||
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
echo "{$email};";
|
||||
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
@@ -1,142 +1,142 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require 'PHPMailer/src/Exception.php';
|
||||
require 'PHPMailer/src/PHPMailer.php';
|
||||
require 'PHPMailer/src/SMTP.php';
|
||||
|
||||
|
||||
// Funktion zum Berechnen des Gesamtstands
|
||||
function berechneGesamtstand($mitarbeiterID, $conn) {
|
||||
// Kosten aus Kaffeeverbrauch abrufen
|
||||
$sqlKosten = "SELECT SUM(Kosten) AS GesamtKosten FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$paramsKosten = array($mitarbeiterID);
|
||||
$stmtKosten = sqlsrv_query($conn, $sqlKosten, $paramsKosten);
|
||||
|
||||
if ($stmtKosten === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$rowKosten = sqlsrv_fetch_array($stmtKosten, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtKosten = $rowKosten['GesamtKosten'];
|
||||
|
||||
// Einzahlungen abrufen
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS GesamtEinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$paramsEinzahlungen = array($mitarbeiterID);
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, $paramsEinzahlungen);
|
||||
|
||||
if ($stmtEinzahlungen === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtEinzahlungen = $rowEinzahlungen['GesamtEinzahlungen'];
|
||||
|
||||
// Gesamtstand berechnen (Kosten - Einzahlungen)
|
||||
$gesamtstand = $gesamtKosten - $gesamtEinzahlungen;
|
||||
|
||||
return $gesamtstand;
|
||||
}
|
||||
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv='1'";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// E-Mail-Versand für jeden Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = trim($row['Name']);
|
||||
$email = $row['Email'];
|
||||
// Gesamtstand berechnen
|
||||
$gesamtstand = berechneGesamtstand($mitarbeiterID, $conn);
|
||||
$stand = abs($gesamtstand);
|
||||
$body = "Hallo $name,<br><br>";
|
||||
|
||||
if($gesamtstand > 0){
|
||||
$body .= "hier ist dein aktueller negativer Kaffeekassenstand. <br>
|
||||
Bitte zahle folgenden Betrag in die Kaffeekasse ein: {$stand} Euro.<br>
|
||||
<br>Es kann nur noch per Paypal bezahlt werden.<br>
|
||||
Dein Link: https://www.paypal.me/kaffeekassesb3/{$stand}<br>
|
||||
<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des eingezahlten Betrags als Gebühr in Rechnung.</b><br>
|
||||
";
|
||||
|
||||
}else{
|
||||
$body .= "hier ist dein aktuelles Guthaben in der Kaffeeliste: {$stand} Euro.<br>
|
||||
<br>";
|
||||
}
|
||||
|
||||
$body .= "
|
||||
Deinen aktuellen Stand findest du auch hier: <a href='https://kaffeeliste.arge.aok/'>https://kaffeeliste.arge.aok/</a><br>
|
||||
<br>
|
||||
<b>Hast du Fragen oder Probleme? Dann lies immer zu erst unsere <a href=https://kaffeeliste.arge.aok/faq.php>FAQs</a>. Danke! </b><br>
|
||||
<br>
|
||||
Vielen Dank!<br>
|
||||
Deine Kaffeekasse<br>
|
||||
<br>
|
||||
Dein Guthaben ist auf dem nächsten Ausdruck der Kaffeeliste einsehbar. Um die Umwelt zu schonen erfolgt ein neuer Ausdruck erst, wenn die Liste voll ist.<br>
|
||||
";
|
||||
|
||||
|
||||
|
||||
// PHPMailer initialisieren
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
//Server settings
|
||||
$mail->SMTPDebug = SMTP::DEBUG_OFF; // Disable debugging
|
||||
$mail->Timeout = 120;
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'smtpv.aoknds.aok'; // SMTP server
|
||||
|
||||
## Hier wird absichtlich keine Authentifizierung genutzt.
|
||||
|
||||
|
||||
#$mail->SMTPAuth = true;
|
||||
#$mail->Username = ''; // SMTP username
|
||||
#$mail->Password = ''; // SMTP password
|
||||
#$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
|
||||
#$mail->Port = 587; // TCP port to connect to
|
||||
|
||||
//Recipients
|
||||
$mail->setFrom('kaffeelistesb3@nds.aok.de', 'Kaffeeliste ARGE');
|
||||
$mail->addAddress($email, $name); // Add a recipient
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Subject = "Kaffeeliste ARGE - Dein Stand";
|
||||
$mail->Body = utf8_decode($body);
|
||||
|
||||
$mail->send();
|
||||
echo "E-Mail erfolgreich an $name gesendet.<br>";
|
||||
} catch (Exception $e) {
|
||||
echo "E-Mail konnte nicht gesendet werden. Fehler: {$mail->ErrorInfo}<br>";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require 'PHPMailer/src/Exception.php';
|
||||
require 'PHPMailer/src/PHPMailer.php';
|
||||
require 'PHPMailer/src/SMTP.php';
|
||||
|
||||
|
||||
// Funktion zum Berechnen des Gesamtstands
|
||||
function berechneGesamtstand($mitarbeiterID, $conn) {
|
||||
// Kosten aus Kaffeeverbrauch abrufen
|
||||
$sqlKosten = "SELECT SUM(Kosten) AS GesamtKosten FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$paramsKosten = array($mitarbeiterID);
|
||||
$stmtKosten = sqlsrv_query($conn, $sqlKosten, $paramsKosten);
|
||||
|
||||
if ($stmtKosten === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$rowKosten = sqlsrv_fetch_array($stmtKosten, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtKosten = $rowKosten['GesamtKosten'];
|
||||
|
||||
// Einzahlungen abrufen
|
||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS GesamtEinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$paramsEinzahlungen = array($mitarbeiterID);
|
||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, $paramsEinzahlungen);
|
||||
|
||||
if ($stmtEinzahlungen === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtEinzahlungen = $rowEinzahlungen['GesamtEinzahlungen'];
|
||||
|
||||
// Gesamtstand berechnen (Kosten - Einzahlungen)
|
||||
$gesamtstand = $gesamtKosten - $gesamtEinzahlungen;
|
||||
|
||||
return $gesamtstand;
|
||||
}
|
||||
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv='1'";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// E-Mail-Versand für jeden Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = trim($row['Name']);
|
||||
$email = $row['Email'];
|
||||
// Gesamtstand berechnen
|
||||
$gesamtstand = berechneGesamtstand($mitarbeiterID, $conn);
|
||||
$stand = abs($gesamtstand);
|
||||
$body = "Hallo $name,<br><br>";
|
||||
|
||||
if($gesamtstand > 0){
|
||||
$body .= "hier ist dein aktueller negativer Kaffeekassenstand. <br>
|
||||
Bitte zahle folgenden Betrag in die Kaffeekasse ein: {$stand} Euro.<br>
|
||||
<br>Es kann nur noch per Paypal bezahlt werden.<br>
|
||||
Dein Link: https://www.paypal.me/kaffeekassesb3/{$stand}<br>
|
||||
<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des eingezahlten Betrags als Gebühr in Rechnung.</b><br>
|
||||
";
|
||||
|
||||
}else{
|
||||
$body .= "hier ist dein aktuelles Guthaben in der Kaffeeliste: {$stand} Euro.<br>
|
||||
<br>";
|
||||
}
|
||||
|
||||
$body .= "
|
||||
Deinen aktuellen Stand findest du auch hier: <a href='https://kaffeeliste.arge.aok/'>https://kaffeeliste.arge.aok/</a><br>
|
||||
<br>
|
||||
<b>Hast du Fragen oder Probleme? Dann lies immer zu erst unsere <a href=https://kaffeeliste.arge.aok/faq.php>FAQs</a>. Danke! </b><br>
|
||||
<br>
|
||||
Vielen Dank!<br>
|
||||
Deine Kaffeekasse<br>
|
||||
<br>
|
||||
Dein Guthaben ist auf dem nächsten Ausdruck der Kaffeeliste einsehbar. Um die Umwelt zu schonen erfolgt ein neuer Ausdruck erst, wenn die Liste voll ist.<br>
|
||||
";
|
||||
|
||||
|
||||
|
||||
// PHPMailer initialisieren
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
//Server settings
|
||||
$mail->SMTPDebug = SMTP::DEBUG_OFF; // Disable debugging
|
||||
$mail->Timeout = 120;
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'smtpv.aoknds.aok'; // SMTP server
|
||||
|
||||
## Hier wird absichtlich keine Authentifizierung genutzt.
|
||||
|
||||
|
||||
#$mail->SMTPAuth = true;
|
||||
#$mail->Username = ''; // SMTP username
|
||||
#$mail->Password = ''; // SMTP password
|
||||
#$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
|
||||
#$mail->Port = 587; // TCP port to connect to
|
||||
|
||||
//Recipients
|
||||
$mail->setFrom('kaffeelistesb3@nds.aok.de', 'Kaffeeliste ARGE');
|
||||
$mail->addAddress($email, $name); // Add a recipient
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Subject = "Kaffeeliste ARGE - Dein Stand";
|
||||
$mail->Body = utf8_decode($body);
|
||||
|
||||
$mail->send();
|
||||
echo "E-Mail erfolgreich an $name gesendet.<br>";
|
||||
} catch (Exception $e) {
|
||||
echo "E-Mail konnte nicht gesendet werden. Fehler: {$mail->ErrorInfo}<br>";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,262 +1,262 @@
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Funktion zum Anlegen, Bearbeiten und Deaktivieren von Mitgliedern
|
||||
function bearbeiteMitglied($aktion, $mitgliedID, $name, $email, $aktiv, $admin, $conn) {
|
||||
try {
|
||||
if ($aktion === 'anlegen') {
|
||||
$sql = "INSERT INTO kl_Mitarbeiter (Name, Email, aktiv, admin) VALUES (?, ?, ?, ?)";
|
||||
} elseif ($aktion === 'bearbeitenspeichern') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET Name = ?, Email = ?, aktiv = ?, admin = ? WHERE MitarbeiterID = ?";
|
||||
} elseif ($aktion === 'aktivieren') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET aktiv = 1 WHERE MitarbeiterID = ?";
|
||||
} elseif ($aktion === 'deaktivieren') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET aktiv = 0 WHERE MitarbeiterID = ?";
|
||||
} else {
|
||||
throw new Exception("Ungültige Aktion.");
|
||||
}
|
||||
|
||||
$params = array($name, $email, $aktiv, $admin);
|
||||
|
||||
// Füge die MitarbeiterID nur bei Bearbeitung hinzu
|
||||
if ($aktion === 'bearbeitenspeichern' ) {
|
||||
array_push($params, $mitgliedID);
|
||||
}elseif($aktion === 'aktivieren' || $aktion === 'deaktivieren'){
|
||||
$params = array($mitgliedID);
|
||||
}
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}?>
|
||||
|
||||
<!-- Formular für das Bearbeiten von Mitgliedern -->
|
||||
<?php
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] === 'bearbeiten') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
// Informationen des ausgewählten Mitglieds abrufen
|
||||
$sqlEinzelmitglied = "SELECT * FROM kl_Mitarbeiter WHERE MitarbeiterID = ?";
|
||||
$stmtEinzelmitglied = sqlsrv_query($conn, $sqlEinzelmitglied, array($mitgliedID));
|
||||
$einzelmitglied = sqlsrv_fetch_array($stmtEinzelmitglied, SQLSRV_FETCH_ASSOC);
|
||||
?>
|
||||
<h3>Bearbeiten von <?php echo $einzelmitglied['Name']; ?></h3>
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<input type="hidden" name="aktion" value="bearbeitenspeichern">
|
||||
<input type="hidden" name="mitgliedID" value="<?php echo $mitgliedID; ?>">
|
||||
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" name="name" id="name" value="<?php echo $einzelmitglied['Name']; ?>" required>
|
||||
|
||||
<label for="email">E-Mail:</label>
|
||||
<input type="email" name="email" id="email" value="<?php echo $einzelmitglied['Email']; ?>" required>
|
||||
<br>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="aktiv" id="aktiv" <?php echo $einzelmitglied['aktiv'] ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="aktiv">Aktiv:</label>
|
||||
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="admin" id="admin" <?php echo $einzelmitglied['admin'] ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="admin">Administrator:</label>
|
||||
|
||||
</div>
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
elseif ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$aktion = $_POST["aktion"];
|
||||
|
||||
if ($aktion === 'anlegen' || $aktion === 'bearbeitenspeichern') {
|
||||
$mitgliedID = isset($_POST["mitgliedID"]) ? $_POST["mitgliedID"] : null;
|
||||
$name = $_POST["name"];
|
||||
$email = $_POST["email"];
|
||||
$aktiv = isset($_POST["aktiv"]) ? 1 : 0;
|
||||
$admin = isset($_POST["admin"]) ? 1 : 0;
|
||||
|
||||
$ergebnis = bearbeiteMitglied($aktion, $mitgliedID, $name, $email, $aktiv, $admin, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Aktion erfolgreich durchgeführt.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
} elseif ($aktion === 'aktivieren') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
$ergebnis = bearbeiteMitglied('aktivieren', $mitgliedID, null, null, null, null, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Mitglied erfolgreich aktiviert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
} elseif ($aktion === 'deaktivieren') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
$ergebnis = bearbeiteMitglied('deaktivieren', $mitgliedID, null, null, null, null, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Mitglied erfolgreich deaktiviert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email, aktiv, admin FROM kl_Mitarbeiter ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Mitglieder verwalten</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Mitglieder verwalten</h2>
|
||||
|
||||
<!-- Formular für das Anlegen und Bearbeiten von Mitgliedern -->
|
||||
<form method="post" action="<?php # echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<input type="hidden" name="aktion" id="aktion" value="anlegen">
|
||||
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" name="name" id="name" required>
|
||||
|
||||
<label for="email">E-Mail:</label>
|
||||
<input type="email" name="email" id="email" required>
|
||||
<br>
|
||||
<div class="form-check">
|
||||
|
||||
<input class="form-check-input" type="checkbox" name="aktiv" id="aktiv" checked>
|
||||
<label class="form-check-label" for="aktiv">Aktiv</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
|
||||
<input class="form-check-input" type="checkbox" name="admin" id="admin" >
|
||||
<label class="form-check-label" for="admin">Administrator</label>
|
||||
</div>
|
||||
<button type="submit">Mitglied anlegen</button>
|
||||
</form>
|
||||
|
||||
|
||||
<!-- Tabelle zur Anzeige und Bearbeitung von Mitgliedern -->
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Mitglied ID</th>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Aktiv</th>
|
||||
<th>Administrator</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
|
||||
echo '<tr >';
|
||||
echo "<td>{$row['MitarbeiterID']}</td>";
|
||||
echo "<td>{$row['Name']}</td>";
|
||||
echo "<td>{$row['Email']}</td>";
|
||||
echo "<td>{$row['aktiv']}</td>";
|
||||
echo "<td>{$row['admin']}</td>";
|
||||
echo "<td>";
|
||||
echo '<ul class="actions">
|
||||
<li>';
|
||||
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='bearbeiten'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Bearbeiten</button>";
|
||||
echo "</form></li><li>";
|
||||
|
||||
|
||||
if ($row['aktiv'] == 1) {
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='deaktivieren'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Deaktivieren</button>";
|
||||
echo "</form>";
|
||||
} else {
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='aktivieren'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Aktivieren</button>";
|
||||
echo "</form>";
|
||||
}
|
||||
echo "</li></ul></td>";
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
## Auskommentierung
|
||||
##<link rel="stylesheet" href="/DataTables/datatables.css" />
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<script src="/DataTables/datatables.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready( function () {
|
||||
$('#myTable').DataTable();
|
||||
} );
|
||||
</script>
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Funktion zum Anlegen, Bearbeiten und Deaktivieren von Mitgliedern
|
||||
function bearbeiteMitglied($aktion, $mitgliedID, $name, $email, $aktiv, $admin, $conn) {
|
||||
try {
|
||||
if ($aktion === 'anlegen') {
|
||||
$sql = "INSERT INTO kl_Mitarbeiter (Name, Email, aktiv, admin) VALUES (?, ?, ?, ?)";
|
||||
} elseif ($aktion === 'bearbeitenspeichern') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET Name = ?, Email = ?, aktiv = ?, admin = ? WHERE MitarbeiterID = ?";
|
||||
} elseif ($aktion === 'aktivieren') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET aktiv = 1 WHERE MitarbeiterID = ?";
|
||||
} elseif ($aktion === 'deaktivieren') {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET aktiv = 0 WHERE MitarbeiterID = ?";
|
||||
} else {
|
||||
throw new Exception("Ungültige Aktion.");
|
||||
}
|
||||
|
||||
$params = array($name, $email, $aktiv, $admin);
|
||||
|
||||
// Füge die MitarbeiterID nur bei Bearbeitung hinzu
|
||||
if ($aktion === 'bearbeitenspeichern' ) {
|
||||
array_push($params, $mitgliedID);
|
||||
}elseif($aktion === 'aktivieren' || $aktion === 'deaktivieren'){
|
||||
$params = array($mitgliedID);
|
||||
}
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}?>
|
||||
|
||||
<!-- Formular für das Bearbeiten von Mitgliedern -->
|
||||
<?php
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] === 'bearbeiten') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
// Informationen des ausgewählten Mitglieds abrufen
|
||||
$sqlEinzelmitglied = "SELECT * FROM kl_Mitarbeiter WHERE MitarbeiterID = ?";
|
||||
$stmtEinzelmitglied = sqlsrv_query($conn, $sqlEinzelmitglied, array($mitgliedID));
|
||||
$einzelmitglied = sqlsrv_fetch_array($stmtEinzelmitglied, SQLSRV_FETCH_ASSOC);
|
||||
?>
|
||||
<h3>Bearbeiten von <?php echo $einzelmitglied['Name']; ?></h3>
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<input type="hidden" name="aktion" value="bearbeitenspeichern">
|
||||
<input type="hidden" name="mitgliedID" value="<?php echo $mitgliedID; ?>">
|
||||
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" name="name" id="name" value="<?php echo $einzelmitglied['Name']; ?>" required>
|
||||
|
||||
<label for="email">E-Mail:</label>
|
||||
<input type="email" name="email" id="email" value="<?php echo $einzelmitglied['Email']; ?>" required>
|
||||
<br>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="aktiv" id="aktiv" <?php echo $einzelmitglied['aktiv'] ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="aktiv">Aktiv:</label>
|
||||
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="admin" id="admin" <?php echo $einzelmitglied['admin'] ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="admin">Administrator:</label>
|
||||
|
||||
</div>
|
||||
<button type="submit">Speichern</button>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
elseif ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$aktion = $_POST["aktion"];
|
||||
|
||||
if ($aktion === 'anlegen' || $aktion === 'bearbeitenspeichern') {
|
||||
$mitgliedID = isset($_POST["mitgliedID"]) ? $_POST["mitgliedID"] : null;
|
||||
$name = $_POST["name"];
|
||||
$email = $_POST["email"];
|
||||
$aktiv = isset($_POST["aktiv"]) ? 1 : 0;
|
||||
$admin = isset($_POST["admin"]) ? 1 : 0;
|
||||
|
||||
$ergebnis = bearbeiteMitglied($aktion, $mitgliedID, $name, $email, $aktiv, $admin, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Aktion erfolgreich durchgeführt.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
} elseif ($aktion === 'aktivieren') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
$ergebnis = bearbeiteMitglied('aktivieren', $mitgliedID, null, null, null, null, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Mitglied erfolgreich aktiviert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
} elseif ($aktion === 'deaktivieren') {
|
||||
$mitgliedID = $_POST["mitgliedID"];
|
||||
|
||||
$ergebnis = bearbeiteMitglied('deaktivieren', $mitgliedID, null, null, null, null, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Mitglied erfolgreich deaktiviert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
|
||||
// Mitglieder aus der Datenbank abrufen
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email, aktiv, admin FROM kl_Mitarbeiter ORDER BY Name";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Mitglieder verwalten</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Mitglieder verwalten</h2>
|
||||
|
||||
<!-- Formular für das Anlegen und Bearbeiten von Mitgliedern -->
|
||||
<form method="post" action="<?php # echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<input type="hidden" name="aktion" id="aktion" value="anlegen">
|
||||
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" name="name" id="name" required>
|
||||
|
||||
<label for="email">E-Mail:</label>
|
||||
<input type="email" name="email" id="email" required>
|
||||
<br>
|
||||
<div class="form-check">
|
||||
|
||||
<input class="form-check-input" type="checkbox" name="aktiv" id="aktiv" checked>
|
||||
<label class="form-check-label" for="aktiv">Aktiv</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
|
||||
<input class="form-check-input" type="checkbox" name="admin" id="admin" >
|
||||
<label class="form-check-label" for="admin">Administrator</label>
|
||||
</div>
|
||||
<button type="submit">Mitglied anlegen</button>
|
||||
</form>
|
||||
|
||||
|
||||
<!-- Tabelle zur Anzeige und Bearbeitung von Mitgliedern -->
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Mitglied ID</th>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Aktiv</th>
|
||||
<th>Administrator</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
|
||||
echo '<tr >';
|
||||
echo "<td>{$row['MitarbeiterID']}</td>";
|
||||
echo "<td>{$row['Name']}</td>";
|
||||
echo "<td>{$row['Email']}</td>";
|
||||
echo "<td>{$row['aktiv']}</td>";
|
||||
echo "<td>{$row['admin']}</td>";
|
||||
echo "<td>";
|
||||
echo '<ul class="actions">
|
||||
<li>';
|
||||
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='bearbeiten'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Bearbeiten</button>";
|
||||
echo "</form></li><li>";
|
||||
|
||||
|
||||
if ($row['aktiv'] == 1) {
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='deaktivieren'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Deaktivieren</button>";
|
||||
echo "</form>";
|
||||
} else {
|
||||
echo "<form method='post' action='{$_SERVER["PHP_SELF"]}'>";
|
||||
echo "<input type='hidden' name='aktion' value='aktivieren'>";
|
||||
echo "<input type='hidden' name='mitgliedID' value='{$row['MitarbeiterID']}'>";
|
||||
echo "<button type='submit'>Aktivieren</button>";
|
||||
echo "</form>";
|
||||
}
|
||||
echo "</li></ul></td>";
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
## Auskommentierung
|
||||
##<link rel="stylesheet" href="/DataTables/datatables.css" />
|
||||
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<script src="/DataTables/datatables.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready( function () {
|
||||
$('#myTable').DataTable();
|
||||
} );
|
||||
</script>
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
|
||||
@@ -1,122 +1,122 @@
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
<br>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Anzeigenamen aktualisieren</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Anzeigenamen aktualisieren</h2>
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter ORDER BY Name";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
}else{
|
||||
|
||||
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>Hier kannst du deinen Anzeigenamen anpassen.<br>Dieser wird auf der Kaffeeliste und E-Mail genutzt.<br>";
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE Email ='" . $mailadress . "'";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Funktion zum Aktualisieren des Anzeigenamens
|
||||
function aktualisiereAnzeigenamen($mitarbeiterID, $neuerName, $conn) {
|
||||
try {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET Name = ? WHERE MitarbeiterID = ?";
|
||||
$params = array($neuerName, $mitarbeiterID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich aktualisiert
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob das Formular abgesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "aktualisieren") {
|
||||
$mitarbeiterID = $_POST["mitarbeiterID"];
|
||||
$neuerName = $_POST["neuerName"];
|
||||
|
||||
$ergebnis = aktualisiereAnzeigenamen($mitarbeiterID, $neuerName, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Anzeigename erfolgreich aktualisiert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
|
||||
<label for="mitarbeiterID">Mitarbeiter auswählen:</label><br>
|
||||
<select name="mitarbeiterID" id="mitarbeiterID">
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
echo "<option value='{$mitarbeiterID}'>{$name}</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<br>
|
||||
|
||||
<label for="neuerName">Neuer Anzeigename: (maximal 20 Zeichen)</label><br>
|
||||
<input type="text" name="neuerName" id="neuerName" maxlength="20" required>
|
||||
<br><br>
|
||||
|
||||
<input type="hidden" name="aktion" value="aktualisieren">
|
||||
<button type="submit">Anzeigename aktualisieren</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
<br>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Anzeigenamen aktualisieren</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Anzeigenamen aktualisieren</h2>
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter ORDER BY Name";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
}else{
|
||||
|
||||
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>Hier kannst du deinen Anzeigenamen anpassen.<br>Dieser wird auf der Kaffeeliste und E-Mail genutzt.<br>";
|
||||
// SQL-Abfrage für alle Mitarbeiter
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE Email ='" . $mailadress . "'";
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Funktion zum Aktualisieren des Anzeigenamens
|
||||
function aktualisiereAnzeigenamen($mitarbeiterID, $neuerName, $conn) {
|
||||
try {
|
||||
$sql = "UPDATE kl_Mitarbeiter SET Name = ? WHERE MitarbeiterID = ?";
|
||||
$params = array($neuerName, $mitarbeiterID);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
throw new Exception(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
return true; // Erfolgreich aktualisiert
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage(); // Fehlermeldung zurückgeben
|
||||
}
|
||||
}
|
||||
|
||||
// Überprüfen, ob das Formular abgesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["aktion"]) && $_POST["aktion"] == "aktualisieren") {
|
||||
$mitarbeiterID = $_POST["mitarbeiterID"];
|
||||
$neuerName = $_POST["neuerName"];
|
||||
|
||||
$ergebnis = aktualisiereAnzeigenamen($mitarbeiterID, $neuerName, $conn);
|
||||
|
||||
if ($ergebnis === true) {
|
||||
echo "Anzeigename erfolgreich aktualisiert.";
|
||||
} else {
|
||||
echo "Fehler: $ergebnis";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
|
||||
<label for="mitarbeiterID">Mitarbeiter auswählen:</label><br>
|
||||
<select name="mitarbeiterID" id="mitarbeiterID">
|
||||
<?php
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
echo "<option value='{$mitarbeiterID}'>{$name}</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<br>
|
||||
|
||||
<label for="neuerName">Neuer Anzeigename: (maximal 20 Zeichen)</label><br>
|
||||
<input type="text" name="neuerName" id="neuerName" maxlength="20" required>
|
||||
<br><br>
|
||||
|
||||
<input type="hidden" name="aktion" value="aktualisieren">
|
||||
<button type="submit">Anzeigename aktualisieren</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,161 +1,161 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Kosten pro Strich übernehmen:
|
||||
$kostenproStrich = $_POST["kostenproStrich"];
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
foreach ($_POST["anzahlStriche"] as $mitarbeiterID => $anzahlStriche) {
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
$anzahlStriche = (int)$anzahlStriche;
|
||||
$kostenproStrich = floatval($kostenproStrich);
|
||||
$kosten = floatval($anzahlStriche * $kostenproStrich);
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
if($anzahlStriche != 0){
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Kaffeeverbrauch (MitarbeiterID, AnzahlStriche, Kosten, KostenproStrich, Datum) VALUES (?, ?, ?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $anzahlStriche, $kosten, $kostenproStrich, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Einträge erfolgreich hinzugefügt.";
|
||||
}elseif($_SERVER["REQUEST_METHOD"] == "GET" AND isset($_GET["action"])){
|
||||
|
||||
if($_GET["action"] == "vorderseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE))) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
|
||||
}elseif( $_GET["action"] == "rueckseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch))
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;";
|
||||
}elseif($_GET["action"] == "alle"){
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
|
||||
}
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, '.', '');
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Anzahl der Striche für alle Mitarbeiter</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Anzahl der Striche für alle Mitarbeiter</h2>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="vorderseite">
|
||||
<button type="submit">Vorderseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="rueckseite">
|
||||
<button type="submit">Rückseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="alle">
|
||||
<button type="submit">Alle</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<?php
|
||||
|
||||
echo "<label for='kostenproStrich'>Kosten pro Strich:</label>
|
||||
<input type='number' name='kostenproStrich' step='0.01' value='" . $KostenproStrich . "'><br>";
|
||||
|
||||
echo "<table>";
|
||||
echo " <tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Anzahl Striche</th>
|
||||
</tr>";
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row["MitarbeiterID"];
|
||||
$mitarbeiterName = $row["Name"];
|
||||
echo "<tr>";
|
||||
|
||||
// Formularfeld für die Anzahl der Striche
|
||||
echo "<td><label for='anzahlStriche[$mitarbeiterID]'>$mitarbeiterName:</label></td>";
|
||||
echo "<td><input type='number' name='anzahlStriche[$mitarbeiterID]' ></td>";
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
?>
|
||||
|
||||
<button type="submit">Eintragen</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Kosten pro Strich übernehmen:
|
||||
$kostenproStrich = $_POST["kostenproStrich"];
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
foreach ($_POST["anzahlStriche"] as $mitarbeiterID => $anzahlStriche) {
|
||||
// Validierung könnte hier hinzugefügt werden
|
||||
$anzahlStriche = (int)$anzahlStriche;
|
||||
$kostenproStrich = floatval($kostenproStrich);
|
||||
$kosten = floatval($anzahlStriche * $kostenproStrich);
|
||||
$datum = date("Y-d-m H:i:s"); // Das aktuelle Datum verwenden
|
||||
if($anzahlStriche != 0){
|
||||
// SQL-Abfrage zum Einfügen der Daten
|
||||
$sql = "INSERT INTO kl_Kaffeeverbrauch (MitarbeiterID, AnzahlStriche, Kosten, KostenproStrich, Datum) VALUES (?, ?, ?, ?, ?)";
|
||||
$params = array($mitarbeiterID, $anzahlStriche, $kosten, $kostenproStrich, $datum);
|
||||
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
|
||||
if ($stmt === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Einträge erfolgreich hinzugefügt.";
|
||||
}elseif($_SERVER["REQUEST_METHOD"] == "GET" AND isset($_GET["action"])){
|
||||
|
||||
if($_GET["action"] == "vorderseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE))) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
|
||||
}elseif( $_GET["action"] == "rueckseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch))
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;";
|
||||
}elseif($_GET["action"] == "alle"){
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
|
||||
}
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, '.', '');
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaffeeliste - Anzahl der Striche für alle Mitarbeiter</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>Anzahl der Striche für alle Mitarbeiter</h2>
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="vorderseite">
|
||||
<button type="submit">Vorderseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="rueckseite">
|
||||
<button type="submit">Rückseite</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="alle">
|
||||
<button type="submit">Alle</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<?php
|
||||
|
||||
echo "<label for='kostenproStrich'>Kosten pro Strich:</label>
|
||||
<input type='number' name='kostenproStrich' step='0.01' value='" . $KostenproStrich . "'><br>";
|
||||
|
||||
echo "<table>";
|
||||
echo " <tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Anzahl Striche</th>
|
||||
</tr>";
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row["MitarbeiterID"];
|
||||
$mitarbeiterName = $row["Name"];
|
||||
echo "<tr>";
|
||||
|
||||
// Formularfeld für die Anzahl der Striche
|
||||
echo "<td><label for='anzahlStriche[$mitarbeiterID]'>$mitarbeiterName:</label></td>";
|
||||
echo "<td><input type='number' name='anzahlStriche[$mitarbeiterID]' ></td>";
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
?>
|
||||
|
||||
<button type="submit">Eintragen</button>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php"; ?>
|
||||
@@ -1,213 +1,213 @@
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Sichere Entgegennahme
|
||||
$userId = filter_input(INPUT_GET, 'user_id', FILTER_VALIDATE_INT);
|
||||
|
||||
if ($userId === null) {
|
||||
http_response_code(400);
|
||||
exit('Fehlender Parameter');
|
||||
}
|
||||
if ($userId === false) {
|
||||
http_response_code(400);
|
||||
exit('Ungültige Benutzer-ID');
|
||||
}
|
||||
|
||||
echo "<h2>Auswertung</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$gesamtstriche = $rowAusgabe['Gesamtstriche'];
|
||||
$aktuellerStand = $gesamteinzahlung - $gesamtausgabe;
|
||||
|
||||
// Gesamteinzahlung pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy') ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$yeareinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy')";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$yearausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$yearstriche = $rowAusgabe['Gesamtstriche'];
|
||||
|
||||
return array('Jahresausgabe' => $yearausgabe, 'Jahresstriche' => $yearstriche, 'Jahreseinzahlung' => $yeareinzahlung, 'Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
#return array('Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
|
||||
}
|
||||
function AusgabeletztenEinzahlungen($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT Betrag,Datum FROM kl_Einzahlungen WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Einzahlungen</h4><table><tr><th style='width:120'>Datum</th><th>Einzahlung</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . number_format($row["Betrag"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
function AusgabeletztenStriche($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT AnzahlStriche,Kosten,Datum FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Striche</h4><table ><tr><th style='width:120'>Datum</th><th>Striche</th><th>Kosten</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . $row["AnzahlStriche"] . "</td><td>" . number_format($row["Kosten"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE MitarbeiterID = $userId";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Berechne Gesamtausgabe und Gesamtstriche für den Mitarbeiter
|
||||
$result = berechneGesamtausgabe($email, $conn);
|
||||
|
||||
if ($result !== null) {
|
||||
|
||||
echo "<h2>Gesamtausgabe und Gesamtstriche</h2>";
|
||||
echo "<p>Name: $name</p>";
|
||||
echo "<p>E-Mail: $email</p>";
|
||||
echo "Gesamtausgabe: " . number_format($result['Gesamtausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche: {$result['Gesamtstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung: " . number_format($result['Gesamteinzahlung'], 2, ',', '') . " €<br>";
|
||||
$aktuellerstand = number_format($result['aktuellerStand'], 2, ',', '.');
|
||||
if($result['aktuellerStand'] > 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Guthaben)</p>";
|
||||
}elseif($result['aktuellerStand'] < 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Schulden)</p>";
|
||||
}else{
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} €</p>";
|
||||
}
|
||||
echo "</b>";
|
||||
echo "<h2>Jahresübersicht</h2>";
|
||||
echo "Ausgabe im aktuellem Jahr: " . number_format($result['Jahresausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche im aktuellem Jahr: {$result['Jahresstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung im aktuellem Jahr: " . number_format($result['Jahreseinzahlung'], 2, ',', '') . " €<br>";
|
||||
|
||||
$sqlconfig = "SELECT paypaluse,paypallink FROM kl_config";
|
||||
$stmtconfig = sqlsrv_query($conn, $sqlconfig, array($email));
|
||||
$rowconfig = sqlsrv_fetch_array($stmtconfig, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if($rowconfig["paypaluse"] == 1){
|
||||
echo "<h2>Paypal-Einzahlungen</h2>";
|
||||
echo '<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.</b><br>';
|
||||
|
||||
$paypallink = trim($rowconfig["paypallink"]);
|
||||
echo "<br>";
|
||||
if($result['aktuellerStand'] < 0){
|
||||
|
||||
echo '<form action="' . $paypallink .'' . $aktuellerstand . '" target="_blank" ><button type="submit">'. $aktuellerstand . ' € bezahlen</button></form>';
|
||||
|
||||
|
||||
}
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form action="' . $paypallink .'5" target="_blank" ><button type="submit">5,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'10" target="_blank" ><button type="submit">10,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'15" target="_blank" ><button type="submit">15,00 € einzahlen</button></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
}
|
||||
echo "<br>";
|
||||
echo "<br>";
|
||||
echo AusgabeletztenEinzahlungen($email, $conn);
|
||||
echo "<br>";
|
||||
echo AusgabeletztenStriche($email, $conn);
|
||||
?>
|
||||
<br><br>
|
||||
|
||||
<!-- Formular mit Button zum Anpassen des Namens -->
|
||||
<form action="namenanpassen.php" method="get">
|
||||
<button type="submit">Namensanpassung</button>
|
||||
</form>
|
||||
<?php
|
||||
} else {
|
||||
echo "<p>Mitarbeiter mit der E-Mail-Adresse $email wurde nicht gefunden.</p>";
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
||||
|
||||
|
||||
// Sichere Entgegennahme
|
||||
$userId = filter_input(INPUT_GET, 'user_id', FILTER_VALIDATE_INT);
|
||||
|
||||
if ($userId === null) {
|
||||
http_response_code(400);
|
||||
exit('Fehlender Parameter');
|
||||
}
|
||||
if ($userId === false) {
|
||||
http_response_code(400);
|
||||
exit('Ungültige Benutzer-ID');
|
||||
}
|
||||
|
||||
echo "<h2>Auswertung</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
||||
function berechneGesamtausgabe($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$gesamteinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$gesamtstriche = $rowAusgabe['Gesamtstriche'];
|
||||
$aktuellerStand = $gesamteinzahlung - $gesamtausgabe;
|
||||
|
||||
// Gesamteinzahlung pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqleinzahlung = "SELECT SUM(Betrag) AS Gesamteinzahlung FROM kl_Einzahlungen WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy') ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$roweinzahlung = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC);
|
||||
$yeareinzahlung = $roweinzahlung['Gesamteinzahlung'];
|
||||
|
||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter und Aktuellem Jahr
|
||||
$sqlAusgabe = "SELECT SUM(AnzahlStriche) AS Gesamtstriche, SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? AND FORMAT(Datum, 'yyyy') = FORMAT(GETDATE(), 'yyyy')";
|
||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
||||
$yearausgabe = $rowAusgabe['Gesamtausgabe'];
|
||||
$yearstriche = $rowAusgabe['Gesamtstriche'];
|
||||
|
||||
return array('Jahresausgabe' => $yearausgabe, 'Jahresstriche' => $yearstriche, 'Jahreseinzahlung' => $yeareinzahlung, 'Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
#return array('Gesamtausgabe' => $gesamtausgabe, 'Gesamtstriche' => $gesamtstriche, 'Gesamteinzahlung' => $gesamteinzahlung, 'aktuellerStand' => $aktuellerStand);
|
||||
|
||||
}
|
||||
function AusgabeletztenEinzahlungen($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT Betrag,Datum FROM kl_Einzahlungen WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Einzahlungen</h4><table><tr><th style='width:120'>Datum</th><th>Einzahlung</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . number_format($row["Betrag"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
function AusgabeletztenStriche($email, $conn) {
|
||||
// MitarbeiterID anhand der E-Mail-Adresse abrufen
|
||||
$sqlMitarbeiterID = "SELECT TOP 20 MitarbeiterID FROM kl_Mitarbeiter WHERE Email = ?";
|
||||
$stmtMitarbeiterID = sqlsrv_query($conn, $sqlMitarbeiterID, array($email));
|
||||
$rowMitarbeiterID = sqlsrv_fetch_array($stmtMitarbeiterID, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if (!$rowMitarbeiterID) {
|
||||
return null; // Mitarbeiter nicht gefunden
|
||||
}
|
||||
$mitarbeiterID = $rowMitarbeiterID["MitarbeiterID"];
|
||||
// Gesamteinzahlung pro Mitarbeiter
|
||||
$sqleinzahlung = "SELECT AnzahlStriche,Kosten,Datum FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ? ORDER BY Datum DESC ";
|
||||
$stmteinzahlung = sqlsrv_query($conn, $sqleinzahlung, array($mitarbeiterID));
|
||||
$ausgabe = "<h4>Letzte Striche</h4><table ><tr><th style='width:120'>Datum</th><th>Striche</th><th>Kosten</th></tr>";
|
||||
while ($row = sqlsrv_fetch_array($stmteinzahlung, SQLSRV_FETCH_ASSOC)) {
|
||||
$ausgabe .= "<tr><td>" . date_format($row["Datum"],"d.m.Y") . "</td><td>" . $row["AnzahlStriche"] . "</td><td>" . number_format($row["Kosten"], 2, ',', '') . "€</td></tr>";
|
||||
}
|
||||
$ausgabe .= "</table>";
|
||||
return $ausgabe;
|
||||
}
|
||||
|
||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE MitarbeiterID = $userId";
|
||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
||||
|
||||
|
||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row['MitarbeiterID'];
|
||||
$name = $row['Name'];
|
||||
$email = $row['Email'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Berechne Gesamtausgabe und Gesamtstriche für den Mitarbeiter
|
||||
$result = berechneGesamtausgabe($email, $conn);
|
||||
|
||||
if ($result !== null) {
|
||||
|
||||
echo "<h2>Gesamtausgabe und Gesamtstriche</h2>";
|
||||
echo "<p>Name: $name</p>";
|
||||
echo "<p>E-Mail: $email</p>";
|
||||
echo "Gesamtausgabe: " . number_format($result['Gesamtausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche: {$result['Gesamtstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung: " . number_format($result['Gesamteinzahlung'], 2, ',', '') . " €<br>";
|
||||
$aktuellerstand = number_format($result['aktuellerStand'], 2, ',', '.');
|
||||
if($result['aktuellerStand'] > 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Guthaben)</p>";
|
||||
}elseif($result['aktuellerStand'] < 0){
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} € (Schulden)</p>";
|
||||
}else{
|
||||
echo "<p><b>Aktueller Stand: {$aktuellerstand} €</p>";
|
||||
}
|
||||
echo "</b>";
|
||||
echo "<h2>Jahresübersicht</h2>";
|
||||
echo "Ausgabe im aktuellem Jahr: " . number_format($result['Jahresausgabe'], 2, ',', '') . " €<br>";
|
||||
echo "Gesamtstriche im aktuellem Jahr: {$result['Jahresstriche']}<br>";
|
||||
echo "<p>Gesamteinzahlung im aktuellem Jahr: " . number_format($result['Jahreseinzahlung'], 2, ',', '') . " €<br>";
|
||||
|
||||
$sqlconfig = "SELECT paypaluse,paypallink FROM kl_config";
|
||||
$stmtconfig = sqlsrv_query($conn, $sqlconfig, array($email));
|
||||
$rowconfig = sqlsrv_fetch_array($stmtconfig, SQLSRV_FETCH_ASSOC);
|
||||
|
||||
if($rowconfig["paypaluse"] == 1){
|
||||
echo "<h2>Paypal-Einzahlungen</h2>";
|
||||
echo '<b>Bezahle immer über die Freunde-Funktion von Paypal. Ansonsten stellen wir 20% des Betrags als Gebühr in Rechnung.</b><br>';
|
||||
|
||||
$paypallink = trim($rowconfig["paypallink"]);
|
||||
echo "<br>";
|
||||
if($result['aktuellerStand'] < 0){
|
||||
|
||||
echo '<form action="' . $paypallink .'' . $aktuellerstand . '" target="_blank" ><button type="submit">'. $aktuellerstand . ' € bezahlen</button></form>';
|
||||
|
||||
|
||||
}
|
||||
echo'<ul class="actions">
|
||||
<li>';
|
||||
echo '<form action="' . $paypallink .'5" target="_blank" ><button type="submit">5,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'10" target="_blank" ><button type="submit">10,00 € einzahlen</button></form>';
|
||||
echo '</li><li>';
|
||||
echo '<form action="' . $paypallink .'15" target="_blank" ><button type="submit">15,00 € einzahlen</button></form>';
|
||||
echo '</li></ul>';
|
||||
|
||||
}
|
||||
echo "<br>";
|
||||
echo "<br>";
|
||||
echo AusgabeletztenEinzahlungen($email, $conn);
|
||||
echo "<br>";
|
||||
echo AusgabeletztenStriche($email, $conn);
|
||||
?>
|
||||
<br><br>
|
||||
|
||||
<!-- Formular mit Button zum Anpassen des Namens -->
|
||||
<form action="namenanpassen.php" method="get">
|
||||
<button type="submit">Namensanpassung</button>
|
||||
</form>
|
||||
<?php
|
||||
} else {
|
||||
echo "<p>Mitarbeiter mit der E-Mail-Adresse $email wurde nicht gefunden.</p>";
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
@@ -1,342 +1,342 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
<style>
|
||||
/* Hartes Reset für Inputs nur im Umfrage-Formular */
|
||||
html body form#coffeeSurvey input[type="checkbox"],
|
||||
html body form#coffeeSurvey input[type="radio"]{
|
||||
all: revert !important; /* setzt ALLES zurück */
|
||||
appearance: auto !important;
|
||||
-webkit-appearance: auto !important;
|
||||
|
||||
display: inline-block !important;
|
||||
position: static !important;
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
margin: 0 6px 0 0 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
html body form#coffeeSurvey label{
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
$geschlossen = true;
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
|
||||
// Beispiel: falls $conn nicht global ist, musst du es wie in deiner Seite erzeugen.
|
||||
if (!isset($conn)) {
|
||||
die("DB Verbindung (\$conn) fehlt.");
|
||||
}
|
||||
|
||||
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
|
||||
$errors = [];
|
||||
$success = false;
|
||||
|
||||
$emailNorm = mb_strtolower(trim((string)$mailadress));
|
||||
if ($emailNorm === '' || !filter_var($emailNorm, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = "Keine gültige E-Mail im System gefunden (Variable \$mailadress).";
|
||||
}
|
||||
|
||||
// Options
|
||||
$drinks = [
|
||||
'espresso' => 'Espresso',
|
||||
'crema' => 'Café Crema',
|
||||
'cappuccino' => 'Cappuccino',
|
||||
'latte' => 'Latte Macchiato',
|
||||
'americano' => 'Americano',
|
||||
'decaf' => 'Entkoffeiniert',
|
||||
'other' => 'Andere',
|
||||
];
|
||||
|
||||
$problems = [
|
||||
'forget' => 'Vergesse Eintrag',
|
||||
'empty' => 'Kaffee leer',
|
||||
'water' => 'Wasser auffüllen',
|
||||
'too_little' => 'zu wenig Kaffeeausgabe',
|
||||
'too_much' => 'zu viel Kaffeeausgabe',
|
||||
'none' => 'Kein Problem',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
$improvements = [
|
||||
'easier_entry' => 'Einfacherer Eintrag',
|
||||
'overview' => 'Übersicht über Kosten/Verbrauch',
|
||||
'more_mails' => 'Mehr Info-Mails',
|
||||
'adjust_amount' => 'Menge der Kaffeeausgabe anpassen',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
function post($k, $def='') { return $_POST[$k] ?? $def; }
|
||||
function postArr($k) { $v = $_POST[$k] ?? []; return is_array($v) ? $v : []; }
|
||||
|
||||
// Schon abgestimmt?
|
||||
$alreadyVoted = true;
|
||||
if (!$errors) {
|
||||
$sqlChk = "SELECT 1 FROM dbo.CoffeeSurveyVotedEmails WHERE EmailNorm = ?";
|
||||
$stmtChk = sqlsrv_query($conn, $sqlChk, [$emailNorm]);
|
||||
if ($stmtChk === false) {
|
||||
$errors[] = "DB-Fehler (Vote-Check): " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
$alreadyVoted = (sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_NUMERIC) !== null);
|
||||
}
|
||||
}
|
||||
|
||||
// POST Handling
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !$errors) {
|
||||
if ($alreadyVoted) {
|
||||
$errors[] = "Du hast bereits abgestimmt.";
|
||||
} else {
|
||||
|
||||
$q1 = (int)post('q1_listease', 0); // 1 sehr einfach .. 5 sehr schwierig
|
||||
$q2 = (int)post('q2_listsat', 0); // 1 sehr zufrieden .. 5 sehr unzufrieden
|
||||
$q3 = (int)post('q3_quality', 0);
|
||||
$q4 = (int)post('q4_websat', 0);
|
||||
|
||||
$q5 = postArr('q5_drinks'); // array
|
||||
$q5_other = trim((string)post('q5_drinks_other',''));
|
||||
|
||||
$q6 = trim((string)post('q6_newvarieties',''));
|
||||
|
||||
$q7 = (string)post('q7_problem','');
|
||||
$q7_other = trim((string)post('q7_problem_other',''));
|
||||
|
||||
$q8 = postArr('q8_improvements');
|
||||
$q8_other = trim((string)post('q8_improvements_other',''));
|
||||
|
||||
$q9 = trim((string)post('q9_betterideas',''));
|
||||
|
||||
// Validate scales
|
||||
foreach ([1=>$q1,2=>$q2,3=>$q3,4=>$q4] as $idx=>$val) {
|
||||
if ($val < 1 || $val > 5) $errors[] = "Bitte bei Frage {$idx} einen Wert von 1 bis 5 wählen.";
|
||||
}
|
||||
|
||||
// Validate drinks
|
||||
$allowedDrinks = array_keys($drinks);
|
||||
$q5 = array_values(array_unique(array_filter($q5, fn($v)=>in_array($v,$allowedDrinks,true))));
|
||||
if (count($q5) === 0) $errors[] = "Bitte bei Frage 5 mindestens eine Kaffeesorte auswählen.";
|
||||
if (in_array('other',$q5,true) && $q5_other === '') $errors[] = "Bitte bei Frage 5 'Andere' kurz beschreiben.";
|
||||
|
||||
// Validate problem
|
||||
if (!array_key_exists($q7, $problems)) $errors[] = "Bitte bei Frage 7 eine Option wählen.";
|
||||
if ($q7 === 'other' && $q7_other === '') $errors[] = "Bitte bei Frage 7 'Sonstiges' kurz beschreiben.";
|
||||
|
||||
// Validate improvements
|
||||
$allowedImp = array_keys($improvements);
|
||||
$q8 = array_values(array_unique(array_filter($q8, fn($v)=>in_array($v,$allowedImp,true))));
|
||||
if (count($q8) === 0) $errors[] = "Bitte bei Frage 8 mindestens eine Verbesserung auswählen.";
|
||||
if (in_array('other',$q8,true) && $q8_other === '') $errors[] = "Bitte bei Frage 8 'Sonstiges' kurz beschreiben.";
|
||||
|
||||
if (!$errors) {
|
||||
$q5_csv = implode(',', $q5);
|
||||
$q8_csv = implode(',', $q8);
|
||||
|
||||
// Transaction (sqlsrv)
|
||||
sqlsrv_begin_transaction($conn);
|
||||
|
||||
// 1) Sperre (E-Mail) eintragen
|
||||
$sqlEmail = "INSERT INTO dbo.CoffeeSurveyVotedEmails (EmailNorm) VALUES (?)";
|
||||
$stmtEmail = sqlsrv_query($conn, $sqlEmail, [$emailNorm]);
|
||||
|
||||
if ($stmtEmail === false) {
|
||||
sqlsrv_rollback($conn);
|
||||
$errors[] = "Speichern fehlgeschlagen (E-Mail-Sperre). " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
// 2) Antworten speichern (ohne E-Mail)
|
||||
$sqlIns = "
|
||||
INSERT INTO dbo.CoffeeSurveyResponses
|
||||
(Q1_ListEase, Q2_ListSatisfaction, Q3_CoffeeQuality, Q4_WebsiteSatisfaction,
|
||||
Q5_Drinks, Q5_DrinksOther, Q6_NewVarieties,
|
||||
Q7_ListProblem, Q7_ListProblemOther,
|
||||
Q8_Improvements, Q8_ImprovementsOther,
|
||||
Q9_BetterIdeas)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
";
|
||||
$params = [
|
||||
$q1, $q2, $q3, $q4,
|
||||
$q5_csv, ($q5_other !== '' ? $q5_other : null), ($q6 !== '' ? $q6 : null),
|
||||
$q7, ($q7_other !== '' ? $q7_other : null),
|
||||
$q8_csv, ($q8_other !== '' ? $q8_other : null),
|
||||
($q9 !== '' ? $q9 : null),
|
||||
];
|
||||
|
||||
$stmtIns = sqlsrv_query($conn, $sqlIns, $params);
|
||||
|
||||
if ($stmtIns === false) {
|
||||
sqlsrv_rollback($conn);
|
||||
$errors[] = "Speichern fehlgeschlagen (Antworten). " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
sqlsrv_commit($conn);
|
||||
$success = true;
|
||||
$alreadyVoted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<p><b>Danke!</b> Deine Antwort wurde gespeichert.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($alreadyVoted && !$success && !$errors): ?>
|
||||
<p><h2><b>Hinweis:</b> Du hast bereits abgestimmt.</h2></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($errors): ?>
|
||||
<div style="border:1px solid #cc0000; padding:10px; margin:10px 0;">
|
||||
<b>Bitte korrigieren:</b>
|
||||
<ul>
|
||||
<?php foreach ($errors as $e): ?>
|
||||
<li><?php echo h($e); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<?php if ($geschlossen):
|
||||
echo "<p><b>Danke!</b> Umfrage abgeschlossen.</p>";
|
||||
|
||||
else:
|
||||
?>
|
||||
<form id="coffeeSurvey" method="post" action="<?php echo h($_SERVER["PHP_SELF"]); ?>">
|
||||
|
||||
<label for="q1_listease">Wie einfach ist die Kaffeeliste für dich zu benutzen?</label><br>
|
||||
<select name="q1_listease" id="q1_listease" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr einfach)" : (($i===5) ? "5 (sehr schwierig)" : (string)$i);
|
||||
$sel = ((string)post('q1_listease','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q2_listsat">Wie zufrieden bist du mit der Kaffeeliste insgesamt?</label><br>
|
||||
<select name="q2_listsat" id="q2_listsat" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q2_listsat','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q3_quality">Wie zufrieden bist du mit der Kaffeequalität insgesamt?</label><br>
|
||||
<select name="q3_quality" id="q3_quality" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q3_quality','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q4_websat">Wie zufrieden bist du mit der Webseite der Kaffeeliste insgesamt?</label><br>
|
||||
<select name="q4_websat" id="q4_websat" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q4_websat','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label>Welche Kaffeearten/Sorten trinkst du am häufigsten? (Mehrfachauswahl)</label><br>
|
||||
<?php foreach ($drinks as $val => $label): ?>
|
||||
<?php $checked = in_array($val, postArr('q5_drinks'), true) ? "checked" : ""; ?>
|
||||
<input type="checkbox" name="q5_drinks[]" value="<?php echo h($val); ?>" <?php echo $checked; ?>>
|
||||
<?php echo h($label); ?><br>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
<label for="q5_drinks_other">Andere (Text):</label><br>
|
||||
<input type="text" name="q5_drinks_other" id="q5_drinks_other" value="<?php echo h((string)post('q5_drinks_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
<label for="q6_newvarieties">Welche zusätzlichen Sorten würdest du dir wünschen? (Freitext)</label><br>
|
||||
<textarea name="q6_newvarieties" id="q6_newvarieties" rows="3"><?php echo h((string)post('q6_newvarieties','')); ?></textarea>
|
||||
<br><br>
|
||||
|
||||
<label for="q7_problem">Was ist dein häufigstes Problem mit der Kaffeeliste?</label><br>
|
||||
<select name="q7_problem" id="q7_problem" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php foreach ($problems as $val => $label): ?>
|
||||
<?php $sel = ((string)post('q7_problem','') === (string)$val) ? "selected" : ""; ?>
|
||||
<option value="<?php echo h($val); ?>" <?php echo $sel; ?>><?php echo h($label); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q7_problem_other">Sonstiges (Text):</label><br>
|
||||
<input type="text" name="q7_problem_other" id="q7_problem_other" value="<?php echo h((string)post('q7_problem_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
<label>Welche Verbesserungen wünschst du dir für die Kaffeeliste? (Mehrfachauswahl)</label><br>
|
||||
<?php foreach ($improvements as $val => $label): ?>
|
||||
<?php $checked = in_array($val, postArr('q8_improvements'), true) ? "checked" : ""; ?>
|
||||
<input type="checkbox" name="q8_improvements[]" value="<?php echo h($val); ?>" <?php echo $checked; ?>>
|
||||
<?php echo h($label); ?><br>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
<label for="q8_improvements_other">Sonstiges (Text):</label><br>
|
||||
<input type="text" name="q8_improvements_other" id="q8_improvements_other" value="<?php echo h((string)post('q8_improvements_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
|
||||
<label for="q9_betterideas">Was kann die Kaffeeliste noch besser machen? (Freitext)</label><br>
|
||||
<textarea name="q9_betterideas" id="q9_betterideas" rows="4"><?php echo h((string)post('q9_betterideas','')); ?></textarea>
|
||||
<br><br>
|
||||
|
||||
<input type="hidden" name="aktion" value="umfrage_absenden">
|
||||
<button type="submit" <?php echo $alreadyVoted ? 'disabled' : ''; ?>>Umfrage absenden</button>
|
||||
</form>
|
||||
<?php
|
||||
endif;?>
|
||||
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
<style>
|
||||
/* Hartes Reset für Inputs nur im Umfrage-Formular */
|
||||
html body form#coffeeSurvey input[type="checkbox"],
|
||||
html body form#coffeeSurvey input[type="radio"]{
|
||||
all: revert !important; /* setzt ALLES zurück */
|
||||
appearance: auto !important;
|
||||
-webkit-appearance: auto !important;
|
||||
|
||||
display: inline-block !important;
|
||||
position: static !important;
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
margin: 0 6px 0 0 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
html body form#coffeeSurvey label{
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
$geschlossen = true;
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
|
||||
// Beispiel: falls $conn nicht global ist, musst du es wie in deiner Seite erzeugen.
|
||||
if (!isset($conn)) {
|
||||
die("DB Verbindung (\$conn) fehlt.");
|
||||
}
|
||||
|
||||
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
|
||||
$errors = [];
|
||||
$success = false;
|
||||
|
||||
$emailNorm = mb_strtolower(trim((string)$mailadress));
|
||||
if ($emailNorm === '' || !filter_var($emailNorm, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = "Keine gültige E-Mail im System gefunden (Variable \$mailadress).";
|
||||
}
|
||||
|
||||
// Options
|
||||
$drinks = [
|
||||
'espresso' => 'Espresso',
|
||||
'crema' => 'Café Crema',
|
||||
'cappuccino' => 'Cappuccino',
|
||||
'latte' => 'Latte Macchiato',
|
||||
'americano' => 'Americano',
|
||||
'decaf' => 'Entkoffeiniert',
|
||||
'other' => 'Andere',
|
||||
];
|
||||
|
||||
$problems = [
|
||||
'forget' => 'Vergesse Eintrag',
|
||||
'empty' => 'Kaffee leer',
|
||||
'water' => 'Wasser auffüllen',
|
||||
'too_little' => 'zu wenig Kaffeeausgabe',
|
||||
'too_much' => 'zu viel Kaffeeausgabe',
|
||||
'none' => 'Kein Problem',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
$improvements = [
|
||||
'easier_entry' => 'Einfacherer Eintrag',
|
||||
'overview' => 'Übersicht über Kosten/Verbrauch',
|
||||
'more_mails' => 'Mehr Info-Mails',
|
||||
'adjust_amount' => 'Menge der Kaffeeausgabe anpassen',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
function post($k, $def='') { return $_POST[$k] ?? $def; }
|
||||
function postArr($k) { $v = $_POST[$k] ?? []; return is_array($v) ? $v : []; }
|
||||
|
||||
// Schon abgestimmt?
|
||||
$alreadyVoted = true;
|
||||
if (!$errors) {
|
||||
$sqlChk = "SELECT 1 FROM dbo.CoffeeSurveyVotedEmails WHERE EmailNorm = ?";
|
||||
$stmtChk = sqlsrv_query($conn, $sqlChk, [$emailNorm]);
|
||||
if ($stmtChk === false) {
|
||||
$errors[] = "DB-Fehler (Vote-Check): " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
$alreadyVoted = (sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_NUMERIC) !== null);
|
||||
}
|
||||
}
|
||||
|
||||
// POST Handling
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !$errors) {
|
||||
if ($alreadyVoted) {
|
||||
$errors[] = "Du hast bereits abgestimmt.";
|
||||
} else {
|
||||
|
||||
$q1 = (int)post('q1_listease', 0); // 1 sehr einfach .. 5 sehr schwierig
|
||||
$q2 = (int)post('q2_listsat', 0); // 1 sehr zufrieden .. 5 sehr unzufrieden
|
||||
$q3 = (int)post('q3_quality', 0);
|
||||
$q4 = (int)post('q4_websat', 0);
|
||||
|
||||
$q5 = postArr('q5_drinks'); // array
|
||||
$q5_other = trim((string)post('q5_drinks_other',''));
|
||||
|
||||
$q6 = trim((string)post('q6_newvarieties',''));
|
||||
|
||||
$q7 = (string)post('q7_problem','');
|
||||
$q7_other = trim((string)post('q7_problem_other',''));
|
||||
|
||||
$q8 = postArr('q8_improvements');
|
||||
$q8_other = trim((string)post('q8_improvements_other',''));
|
||||
|
||||
$q9 = trim((string)post('q9_betterideas',''));
|
||||
|
||||
// Validate scales
|
||||
foreach ([1=>$q1,2=>$q2,3=>$q3,4=>$q4] as $idx=>$val) {
|
||||
if ($val < 1 || $val > 5) $errors[] = "Bitte bei Frage {$idx} einen Wert von 1 bis 5 wählen.";
|
||||
}
|
||||
|
||||
// Validate drinks
|
||||
$allowedDrinks = array_keys($drinks);
|
||||
$q5 = array_values(array_unique(array_filter($q5, fn($v)=>in_array($v,$allowedDrinks,true))));
|
||||
if (count($q5) === 0) $errors[] = "Bitte bei Frage 5 mindestens eine Kaffeesorte auswählen.";
|
||||
if (in_array('other',$q5,true) && $q5_other === '') $errors[] = "Bitte bei Frage 5 'Andere' kurz beschreiben.";
|
||||
|
||||
// Validate problem
|
||||
if (!array_key_exists($q7, $problems)) $errors[] = "Bitte bei Frage 7 eine Option wählen.";
|
||||
if ($q7 === 'other' && $q7_other === '') $errors[] = "Bitte bei Frage 7 'Sonstiges' kurz beschreiben.";
|
||||
|
||||
// Validate improvements
|
||||
$allowedImp = array_keys($improvements);
|
||||
$q8 = array_values(array_unique(array_filter($q8, fn($v)=>in_array($v,$allowedImp,true))));
|
||||
if (count($q8) === 0) $errors[] = "Bitte bei Frage 8 mindestens eine Verbesserung auswählen.";
|
||||
if (in_array('other',$q8,true) && $q8_other === '') $errors[] = "Bitte bei Frage 8 'Sonstiges' kurz beschreiben.";
|
||||
|
||||
if (!$errors) {
|
||||
$q5_csv = implode(',', $q5);
|
||||
$q8_csv = implode(',', $q8);
|
||||
|
||||
// Transaction (sqlsrv)
|
||||
sqlsrv_begin_transaction($conn);
|
||||
|
||||
// 1) Sperre (E-Mail) eintragen
|
||||
$sqlEmail = "INSERT INTO dbo.CoffeeSurveyVotedEmails (EmailNorm) VALUES (?)";
|
||||
$stmtEmail = sqlsrv_query($conn, $sqlEmail, [$emailNorm]);
|
||||
|
||||
if ($stmtEmail === false) {
|
||||
sqlsrv_rollback($conn);
|
||||
$errors[] = "Speichern fehlgeschlagen (E-Mail-Sperre). " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
// 2) Antworten speichern (ohne E-Mail)
|
||||
$sqlIns = "
|
||||
INSERT INTO dbo.CoffeeSurveyResponses
|
||||
(Q1_ListEase, Q2_ListSatisfaction, Q3_CoffeeQuality, Q4_WebsiteSatisfaction,
|
||||
Q5_Drinks, Q5_DrinksOther, Q6_NewVarieties,
|
||||
Q7_ListProblem, Q7_ListProblemOther,
|
||||
Q8_Improvements, Q8_ImprovementsOther,
|
||||
Q9_BetterIdeas)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
";
|
||||
$params = [
|
||||
$q1, $q2, $q3, $q4,
|
||||
$q5_csv, ($q5_other !== '' ? $q5_other : null), ($q6 !== '' ? $q6 : null),
|
||||
$q7, ($q7_other !== '' ? $q7_other : null),
|
||||
$q8_csv, ($q8_other !== '' ? $q8_other : null),
|
||||
($q9 !== '' ? $q9 : null),
|
||||
];
|
||||
|
||||
$stmtIns = sqlsrv_query($conn, $sqlIns, $params);
|
||||
|
||||
if ($stmtIns === false) {
|
||||
sqlsrv_rollback($conn);
|
||||
$errors[] = "Speichern fehlgeschlagen (Antworten). " . print_r(sqlsrv_errors(), true);
|
||||
} else {
|
||||
sqlsrv_commit($conn);
|
||||
$success = true;
|
||||
$alreadyVoted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<p><b>Danke!</b> Deine Antwort wurde gespeichert.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($alreadyVoted && !$success && !$errors): ?>
|
||||
<p><h2><b>Hinweis:</b> Du hast bereits abgestimmt.</h2></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($errors): ?>
|
||||
<div style="border:1px solid #cc0000; padding:10px; margin:10px 0;">
|
||||
<b>Bitte korrigieren:</b>
|
||||
<ul>
|
||||
<?php foreach ($errors as $e): ?>
|
||||
<li><?php echo h($e); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<?php if ($geschlossen):
|
||||
echo "<p><b>Danke!</b> Umfrage abgeschlossen.</p>";
|
||||
|
||||
else:
|
||||
?>
|
||||
<form id="coffeeSurvey" method="post" action="<?php echo h($_SERVER["PHP_SELF"]); ?>">
|
||||
|
||||
<label for="q1_listease">Wie einfach ist die Kaffeeliste für dich zu benutzen?</label><br>
|
||||
<select name="q1_listease" id="q1_listease" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr einfach)" : (($i===5) ? "5 (sehr schwierig)" : (string)$i);
|
||||
$sel = ((string)post('q1_listease','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q2_listsat">Wie zufrieden bist du mit der Kaffeeliste insgesamt?</label><br>
|
||||
<select name="q2_listsat" id="q2_listsat" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q2_listsat','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q3_quality">Wie zufrieden bist du mit der Kaffeequalität insgesamt?</label><br>
|
||||
<select name="q3_quality" id="q3_quality" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q3_quality','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q4_websat">Wie zufrieden bist du mit der Webseite der Kaffeeliste insgesamt?</label><br>
|
||||
<select name="q4_websat" id="q4_websat" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<?php
|
||||
$text = ($i===1) ? "1 (sehr zufrieden)" : (($i===5) ? "5 (sehr unzufrieden)" : (string)$i);
|
||||
$sel = ((string)post('q4_websat','') === (string)$i) ? "selected" : "";
|
||||
?>
|
||||
<option value="<?php echo $i; ?>" <?php echo $sel; ?>><?php echo h($text); ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label>Welche Kaffeearten/Sorten trinkst du am häufigsten? (Mehrfachauswahl)</label><br>
|
||||
<?php foreach ($drinks as $val => $label): ?>
|
||||
<?php $checked = in_array($val, postArr('q5_drinks'), true) ? "checked" : ""; ?>
|
||||
<input type="checkbox" name="q5_drinks[]" value="<?php echo h($val); ?>" <?php echo $checked; ?>>
|
||||
<?php echo h($label); ?><br>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
<label for="q5_drinks_other">Andere (Text):</label><br>
|
||||
<input type="text" name="q5_drinks_other" id="q5_drinks_other" value="<?php echo h((string)post('q5_drinks_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
<label for="q6_newvarieties">Welche zusätzlichen Sorten würdest du dir wünschen? (Freitext)</label><br>
|
||||
<textarea name="q6_newvarieties" id="q6_newvarieties" rows="3"><?php echo h((string)post('q6_newvarieties','')); ?></textarea>
|
||||
<br><br>
|
||||
|
||||
<label for="q7_problem">Was ist dein häufigstes Problem mit der Kaffeeliste?</label><br>
|
||||
<select name="q7_problem" id="q7_problem" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
<?php foreach ($problems as $val => $label): ?>
|
||||
<?php $sel = ((string)post('q7_problem','') === (string)$val) ? "selected" : ""; ?>
|
||||
<option value="<?php echo h($val); ?>" <?php echo $sel; ?>><?php echo h($label); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<label for="q7_problem_other">Sonstiges (Text):</label><br>
|
||||
<input type="text" name="q7_problem_other" id="q7_problem_other" value="<?php echo h((string)post('q7_problem_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
<label>Welche Verbesserungen wünschst du dir für die Kaffeeliste? (Mehrfachauswahl)</label><br>
|
||||
<?php foreach ($improvements as $val => $label): ?>
|
||||
<?php $checked = in_array($val, postArr('q8_improvements'), true) ? "checked" : ""; ?>
|
||||
<input type="checkbox" name="q8_improvements[]" value="<?php echo h($val); ?>" <?php echo $checked; ?>>
|
||||
<?php echo h($label); ?><br>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
<label for="q8_improvements_other">Sonstiges (Text):</label><br>
|
||||
<input type="text" name="q8_improvements_other" id="q8_improvements_other" value="<?php echo h((string)post('q8_improvements_other','')); ?>">
|
||||
<br><br>
|
||||
|
||||
|
||||
<label for="q9_betterideas">Was kann die Kaffeeliste noch besser machen? (Freitext)</label><br>
|
||||
<textarea name="q9_betterideas" id="q9_betterideas" rows="4"><?php echo h((string)post('q9_betterideas','')); ?></textarea>
|
||||
<br><br>
|
||||
|
||||
<input type="hidden" name="aktion" value="umfrage_absenden">
|
||||
<button type="submit" <?php echo $alreadyVoted ? 'disabled' : ''; ?>>Umfrage absenden</button>
|
||||
</form>
|
||||
<?php
|
||||
endif;?>
|
||||
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
@@ -1,370 +1,370 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
|
||||
// Annahme: $conn ist bereits vorhanden (sqlsrv_connect in deiner Infrastruktur)
|
||||
if (!isset($conn)) {
|
||||
die("DB Verbindung (\$conn) fehlt.");
|
||||
}
|
||||
|
||||
function h($s): string {
|
||||
return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* OPTIONAL: Admin-Schutz via Basic Auth (auskommentieren, wenn nicht gewünscht)
|
||||
*/
|
||||
/*
|
||||
$ADMIN_USER = 'admin';
|
||||
$ADMIN_PASS = 'changeme';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])
|
||||
|| $_SERVER['PHP_AUTH_USER'] !== $ADMIN_USER || $_SERVER['PHP_AUTH_PW'] !== $ADMIN_PASS) {
|
||||
header('WWW-Authenticate: Basic realm="Umfrage Admin"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo "Unauthorized";
|
||||
exit;
|
||||
}
|
||||
*/
|
||||
|
||||
$drinks = [
|
||||
'espresso' => 'Espresso',
|
||||
'crema' => 'Café Crema',
|
||||
'cappuccino' => 'Cappuccino',
|
||||
'latte' => 'Latte Macchiato',
|
||||
'americano' => 'Americano',
|
||||
'decaf' => 'Entkoffeiniert',
|
||||
'other' => 'Andere',
|
||||
];
|
||||
|
||||
$problems = [
|
||||
'forget' => 'Vergesse Eintrag',
|
||||
'empty' => 'Kaffee leer',
|
||||
'water' => 'Wasser auffüllen',
|
||||
'too_little' => 'zu wenig Kaffeeausgabe',
|
||||
'too_much' => 'zu viel Kaffeeausgabe',
|
||||
'none' => 'Kein Problem',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
$improvements = [
|
||||
'easier_entry' => 'Einfacherer Eintrag',
|
||||
'overview' => 'Übersicht über Kosten/Verbrauch',
|
||||
'more_mails' => 'Mehr Info-Mails',
|
||||
'adjust_amount' => 'Menge der Kaffeeausgabe anpassen',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
// Helper: SQL scalar
|
||||
function sql_scalar($conn, string $sql, array $params = []) {
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
if ($stmt === false) return null;
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_NUMERIC);
|
||||
return $row ? $row[0] : null;
|
||||
}
|
||||
|
||||
// Helper: SQL all rows
|
||||
function sql_all($conn, string $sql, array $params = []): array {
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
if ($stmt === false) return [];
|
||||
$rows = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$rows[] = $r;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
$totalResponses = (int)(sql_scalar($conn, "SELECT COUNT(*) FROM dbo.CoffeeSurveyResponses") ?? 0);
|
||||
$totalVotedEmails = (int)(sql_scalar($conn, "SELECT COUNT(*) FROM dbo.CoffeeSurveyVotedEmails") ?? 0);
|
||||
|
||||
// Skalen-Auswertung (Avg + Count pro Wert 1..5)
|
||||
function scale_stats($conn, string $col): array {
|
||||
$sql = "
|
||||
SELECT
|
||||
AVG(CAST([$col] AS FLOAT)) AS avgVal,
|
||||
SUM(CASE WHEN [$col] = 1 THEN 1 ELSE 0 END) AS c1,
|
||||
SUM(CASE WHEN [$col] = 2 THEN 1 ELSE 0 END) AS c2,
|
||||
SUM(CASE WHEN [$col] = 3 THEN 1 ELSE 0 END) AS c3,
|
||||
SUM(CASE WHEN [$col] = 4 THEN 1 ELSE 0 END) AS c4,
|
||||
SUM(CASE WHEN [$col] = 5 THEN 1 ELSE 0 END) AS c5
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
";
|
||||
$rows = sql_all($conn, $sql);
|
||||
if (!$rows) return ['avg'=>null,'c'=>[0,0,0,0,0]];
|
||||
$r = $rows[0];
|
||||
return [
|
||||
'avg' => $r['avgVal'] !== null ? (float)$r['avgVal'] : null,
|
||||
'c' => [(int)$r['c1'], (int)$r['c2'], (int)$r['c3'], (int)$r['c4'], (int)$r['c5']]
|
||||
];
|
||||
}
|
||||
|
||||
$q1 = scale_stats($conn, 'Q1_ListEase');
|
||||
$q2 = scale_stats($conn, 'Q2_ListSatisfaction');
|
||||
$q3 = scale_stats($conn, 'Q3_CoffeeQuality');
|
||||
$q4 = scale_stats($conn, 'Q4_WebsiteSatisfaction');
|
||||
|
||||
// Problem (Q7) Gruppiert
|
||||
$q7Rows = sql_all($conn, "
|
||||
SELECT Q7_ListProblem AS keyVal, COUNT(*) AS cnt
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
GROUP BY Q7_ListProblem
|
||||
ORDER BY cnt DESC
|
||||
");
|
||||
|
||||
// CSV-Felder + Freitext sammeln (limit)
|
||||
$limit = 500; // genug für Auswertung, falls riesig: erhöhen oder paginieren
|
||||
$dataRows = sql_all($conn, "
|
||||
SELECT TOP ($limit)
|
||||
CreatedAt,
|
||||
Q5_Drinks, Q5_DrinksOther,
|
||||
Q6_NewVarieties,
|
||||
Q8_Improvements, Q8_ImprovementsOther,
|
||||
Q9_BetterIdeas
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
ORDER BY CreatedAt DESC
|
||||
");
|
||||
|
||||
// Aggregation in PHP für Mehrfachauswahl
|
||||
$drinkCounts = array_fill_keys(array_keys($drinks), 0);
|
||||
$drinkOtherTexts = [];
|
||||
|
||||
$impCounts = array_fill_keys(array_keys($improvements), 0);
|
||||
$impOtherTexts = [];
|
||||
|
||||
$newVarietiesTexts = [];
|
||||
$betterIdeasTexts = [];
|
||||
|
||||
foreach ($dataRows as $r) {
|
||||
// Q5 drinks CSV
|
||||
$csv = trim((string)($r['Q5_Drinks'] ?? ''));
|
||||
if ($csv !== '') {
|
||||
$parts = array_filter(array_map('trim', explode(',', $csv)));
|
||||
foreach ($parts as $p) {
|
||||
if (array_key_exists($p, $drinkCounts)) $drinkCounts[$p]++;
|
||||
}
|
||||
}
|
||||
$ot = trim((string)($r['Q5_DrinksOther'] ?? ''));
|
||||
if ($ot !== '') $drinkOtherTexts[] = $ot;
|
||||
|
||||
// Q8 improvements CSV
|
||||
$csv2 = trim((string)($r['Q8_Improvements'] ?? ''));
|
||||
if ($csv2 !== '') {
|
||||
$parts2 = array_filter(array_map('trim', explode(',', $csv2)));
|
||||
foreach ($parts2 as $p2) {
|
||||
if (array_key_exists($p2, $impCounts)) $impCounts[$p2]++;
|
||||
}
|
||||
}
|
||||
$ot2 = trim((string)($r['Q8_ImprovementsOther'] ?? ''));
|
||||
if ($ot2 !== '') $impOtherTexts[] = $ot2;
|
||||
|
||||
// Q6 / Q9 Freitext
|
||||
$t6 = trim((string)($r['Q6_NewVarieties'] ?? ''));
|
||||
if ($t6 !== '') $newVarietiesTexts[] = $t6;
|
||||
|
||||
$t9 = trim((string)($r['Q9_BetterIdeas'] ?? ''));
|
||||
if ($t9 !== '') $betterIdeasTexts[] = $t9;
|
||||
}
|
||||
|
||||
// Hilfsfunktion Prozent
|
||||
function pct(int $n, int $total): string {
|
||||
if ($total <= 0) return "0%";
|
||||
return round(($n / $total) * 100, 1) . "%";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<h1>Umfrage – Ergebnisse</h1>
|
||||
<p class="muted">
|
||||
Antworten: <b><?php echo (int)$totalResponses; ?></b>
|
||||
|
||||
<?php if ($limit && $totalResponses > $limit): ?>
|
||||
| Auswertung basiert auf den letzten <?php echo (int)$limit; ?> Antworten
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
|
||||
<div class="grid">
|
||||
<div class="box">
|
||||
<h3>1) Kaffeeliste benutzen (1 sehr einfach … 5 sehr schwierig)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q1['avg'] !== null ? number_format($q1['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q1['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q1['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>2) Zufriedenheit Kaffeeliste (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q2['avg'] !== null ? number_format($q2['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q2['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q2['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>3) Zufriedenheit Kaffeequalität (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q3['avg'] !== null ? number_format($q3['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q3['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q3['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>4) Zufriedenheit Webseite (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q4['avg'] !== null ? number_format($q4['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q4['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q4['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>5) Häufigste Kaffeearten (Mehrfachauswahl)</h3>
|
||||
<table>
|
||||
<tr><th>Sorte</th><th>Anzahl</th><th>Anteil (bezogen auf Antworten)</th></tr>
|
||||
<?php foreach ($drinks as $key => $label): ?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo (int)$drinkCounts[$key]; ?></td>
|
||||
<td><?php echo pct((int)$drinkCounts[$key], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if (count($drinkOtherTexts) > 0): ?>
|
||||
<p class="small"><b>„Andere“ – Texte (letzte 30):</b></p>
|
||||
<ul>
|
||||
<?php foreach (array_slice($drinkOtherTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>7) Häufigstes Problem mit der Kaffeeliste</h3>
|
||||
<table>
|
||||
<tr><th>Problem</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php
|
||||
// Map rows -> counts
|
||||
$tmp = [];
|
||||
foreach ($q7Rows as $r) $tmp[(string)$r['keyVal']] = (int)$r['cnt'];
|
||||
foreach ($problems as $k => $label):
|
||||
$c = $tmp[$k] ?? 0;
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo $c; ?></td>
|
||||
<td><?php echo pct($c, $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>8) Gewünschte Verbesserungen (Mehrfachauswahl)</h3>
|
||||
<table>
|
||||
<tr><th>Verbesserung</th><th>Anzahl</th><th>Anteil (bezogen auf Antworten)</th></tr>
|
||||
<?php foreach ($improvements as $key => $label): ?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo (int)$impCounts[$key]; ?></td>
|
||||
<td><?php echo pct((int)$impCounts[$key], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if (count($impOtherTexts) > 0): ?>
|
||||
<p class="small"><b>„Sonstiges“ – Texte (letzte 30):</b></p>
|
||||
<ul>
|
||||
<?php foreach (array_slice($impOtherTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="box">
|
||||
<h3>6) Zusätzliche Sorten (Freitext) – letzte 30</h3>
|
||||
<?php if (!$newVarietiesTexts): ?>
|
||||
<p class="muted">Keine Einträge.</p>
|
||||
<?php else: ?>
|
||||
<ul>
|
||||
<?php foreach (array_slice($newVarietiesTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>9) Was kann die Kaffeeliste noch besser machen? – letzte 30</h3>
|
||||
<?php if (!$betterIdeasTexts): ?>
|
||||
<p class="muted">Keine Einträge.</p>
|
||||
<?php else: ?>
|
||||
<ul>
|
||||
<?php foreach (array_slice($betterIdeasTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
include "functions.php";
|
||||
include "header.php";
|
||||
include "headerline.php";
|
||||
include "nav.php";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<!-- Banner -->
|
||||
<section id="banner">
|
||||
<div class="content">
|
||||
|
||||
<?php
|
||||
|
||||
if(checkKaffeelisteAccess($conn, $mailadress)){
|
||||
|
||||
echo "<h2>Kaffeeliste</h2>";
|
||||
echo "Hallo " . getUserName($conn,$mailadress) . "!<br><br>";
|
||||
|
||||
|
||||
// Annahme: $conn ist bereits vorhanden (sqlsrv_connect in deiner Infrastruktur)
|
||||
if (!isset($conn)) {
|
||||
die("DB Verbindung (\$conn) fehlt.");
|
||||
}
|
||||
|
||||
function h($s): string {
|
||||
return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* OPTIONAL: Admin-Schutz via Basic Auth (auskommentieren, wenn nicht gewünscht)
|
||||
*/
|
||||
/*
|
||||
$ADMIN_USER = 'admin';
|
||||
$ADMIN_PASS = 'changeme';
|
||||
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])
|
||||
|| $_SERVER['PHP_AUTH_USER'] !== $ADMIN_USER || $_SERVER['PHP_AUTH_PW'] !== $ADMIN_PASS) {
|
||||
header('WWW-Authenticate: Basic realm="Umfrage Admin"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo "Unauthorized";
|
||||
exit;
|
||||
}
|
||||
*/
|
||||
|
||||
$drinks = [
|
||||
'espresso' => 'Espresso',
|
||||
'crema' => 'Café Crema',
|
||||
'cappuccino' => 'Cappuccino',
|
||||
'latte' => 'Latte Macchiato',
|
||||
'americano' => 'Americano',
|
||||
'decaf' => 'Entkoffeiniert',
|
||||
'other' => 'Andere',
|
||||
];
|
||||
|
||||
$problems = [
|
||||
'forget' => 'Vergesse Eintrag',
|
||||
'empty' => 'Kaffee leer',
|
||||
'water' => 'Wasser auffüllen',
|
||||
'too_little' => 'zu wenig Kaffeeausgabe',
|
||||
'too_much' => 'zu viel Kaffeeausgabe',
|
||||
'none' => 'Kein Problem',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
$improvements = [
|
||||
'easier_entry' => 'Einfacherer Eintrag',
|
||||
'overview' => 'Übersicht über Kosten/Verbrauch',
|
||||
'more_mails' => 'Mehr Info-Mails',
|
||||
'adjust_amount' => 'Menge der Kaffeeausgabe anpassen',
|
||||
'other' => 'Sonstiges',
|
||||
];
|
||||
|
||||
// Helper: SQL scalar
|
||||
function sql_scalar($conn, string $sql, array $params = []) {
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
if ($stmt === false) return null;
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_NUMERIC);
|
||||
return $row ? $row[0] : null;
|
||||
}
|
||||
|
||||
// Helper: SQL all rows
|
||||
function sql_all($conn, string $sql, array $params = []): array {
|
||||
$stmt = sqlsrv_query($conn, $sql, $params);
|
||||
if ($stmt === false) return [];
|
||||
$rows = [];
|
||||
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
|
||||
$rows[] = $r;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
$totalResponses = (int)(sql_scalar($conn, "SELECT COUNT(*) FROM dbo.CoffeeSurveyResponses") ?? 0);
|
||||
$totalVotedEmails = (int)(sql_scalar($conn, "SELECT COUNT(*) FROM dbo.CoffeeSurveyVotedEmails") ?? 0);
|
||||
|
||||
// Skalen-Auswertung (Avg + Count pro Wert 1..5)
|
||||
function scale_stats($conn, string $col): array {
|
||||
$sql = "
|
||||
SELECT
|
||||
AVG(CAST([$col] AS FLOAT)) AS avgVal,
|
||||
SUM(CASE WHEN [$col] = 1 THEN 1 ELSE 0 END) AS c1,
|
||||
SUM(CASE WHEN [$col] = 2 THEN 1 ELSE 0 END) AS c2,
|
||||
SUM(CASE WHEN [$col] = 3 THEN 1 ELSE 0 END) AS c3,
|
||||
SUM(CASE WHEN [$col] = 4 THEN 1 ELSE 0 END) AS c4,
|
||||
SUM(CASE WHEN [$col] = 5 THEN 1 ELSE 0 END) AS c5
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
";
|
||||
$rows = sql_all($conn, $sql);
|
||||
if (!$rows) return ['avg'=>null,'c'=>[0,0,0,0,0]];
|
||||
$r = $rows[0];
|
||||
return [
|
||||
'avg' => $r['avgVal'] !== null ? (float)$r['avgVal'] : null,
|
||||
'c' => [(int)$r['c1'], (int)$r['c2'], (int)$r['c3'], (int)$r['c4'], (int)$r['c5']]
|
||||
];
|
||||
}
|
||||
|
||||
$q1 = scale_stats($conn, 'Q1_ListEase');
|
||||
$q2 = scale_stats($conn, 'Q2_ListSatisfaction');
|
||||
$q3 = scale_stats($conn, 'Q3_CoffeeQuality');
|
||||
$q4 = scale_stats($conn, 'Q4_WebsiteSatisfaction');
|
||||
|
||||
// Problem (Q7) Gruppiert
|
||||
$q7Rows = sql_all($conn, "
|
||||
SELECT Q7_ListProblem AS keyVal, COUNT(*) AS cnt
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
GROUP BY Q7_ListProblem
|
||||
ORDER BY cnt DESC
|
||||
");
|
||||
|
||||
// CSV-Felder + Freitext sammeln (limit)
|
||||
$limit = 500; // genug für Auswertung, falls riesig: erhöhen oder paginieren
|
||||
$dataRows = sql_all($conn, "
|
||||
SELECT TOP ($limit)
|
||||
CreatedAt,
|
||||
Q5_Drinks, Q5_DrinksOther,
|
||||
Q6_NewVarieties,
|
||||
Q8_Improvements, Q8_ImprovementsOther,
|
||||
Q9_BetterIdeas
|
||||
FROM dbo.CoffeeSurveyResponses
|
||||
ORDER BY CreatedAt DESC
|
||||
");
|
||||
|
||||
// Aggregation in PHP für Mehrfachauswahl
|
||||
$drinkCounts = array_fill_keys(array_keys($drinks), 0);
|
||||
$drinkOtherTexts = [];
|
||||
|
||||
$impCounts = array_fill_keys(array_keys($improvements), 0);
|
||||
$impOtherTexts = [];
|
||||
|
||||
$newVarietiesTexts = [];
|
||||
$betterIdeasTexts = [];
|
||||
|
||||
foreach ($dataRows as $r) {
|
||||
// Q5 drinks CSV
|
||||
$csv = trim((string)($r['Q5_Drinks'] ?? ''));
|
||||
if ($csv !== '') {
|
||||
$parts = array_filter(array_map('trim', explode(',', $csv)));
|
||||
foreach ($parts as $p) {
|
||||
if (array_key_exists($p, $drinkCounts)) $drinkCounts[$p]++;
|
||||
}
|
||||
}
|
||||
$ot = trim((string)($r['Q5_DrinksOther'] ?? ''));
|
||||
if ($ot !== '') $drinkOtherTexts[] = $ot;
|
||||
|
||||
// Q8 improvements CSV
|
||||
$csv2 = trim((string)($r['Q8_Improvements'] ?? ''));
|
||||
if ($csv2 !== '') {
|
||||
$parts2 = array_filter(array_map('trim', explode(',', $csv2)));
|
||||
foreach ($parts2 as $p2) {
|
||||
if (array_key_exists($p2, $impCounts)) $impCounts[$p2]++;
|
||||
}
|
||||
}
|
||||
$ot2 = trim((string)($r['Q8_ImprovementsOther'] ?? ''));
|
||||
if ($ot2 !== '') $impOtherTexts[] = $ot2;
|
||||
|
||||
// Q6 / Q9 Freitext
|
||||
$t6 = trim((string)($r['Q6_NewVarieties'] ?? ''));
|
||||
if ($t6 !== '') $newVarietiesTexts[] = $t6;
|
||||
|
||||
$t9 = trim((string)($r['Q9_BetterIdeas'] ?? ''));
|
||||
if ($t9 !== '') $betterIdeasTexts[] = $t9;
|
||||
}
|
||||
|
||||
// Hilfsfunktion Prozent
|
||||
function pct(int $n, int $total): string {
|
||||
if ($total <= 0) return "0%";
|
||||
return round(($n / $total) * 100, 1) . "%";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<h1>Umfrage – Ergebnisse</h1>
|
||||
<p class="muted">
|
||||
Antworten: <b><?php echo (int)$totalResponses; ?></b>
|
||||
|
||||
<?php if ($limit && $totalResponses > $limit): ?>
|
||||
| Auswertung basiert auf den letzten <?php echo (int)$limit; ?> Antworten
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
|
||||
<div class="grid">
|
||||
<div class="box">
|
||||
<h3>1) Kaffeeliste benutzen (1 sehr einfach … 5 sehr schwierig)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q1['avg'] !== null ? number_format($q1['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q1['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q1['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>2) Zufriedenheit Kaffeeliste (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q2['avg'] !== null ? number_format($q2['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q2['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q2['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>3) Zufriedenheit Kaffeequalität (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q3['avg'] !== null ? number_format($q3['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q3['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q3['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>4) Zufriedenheit Webseite (1 sehr zufrieden … 5 sehr unzufrieden)</h3>
|
||||
<p class="small">Durchschnitt: <b><?php echo $q4['avg'] !== null ? number_format($q4['avg'], 2, ',', '.') : '-'; ?></b></p>
|
||||
<table>
|
||||
<tr><th>Wert</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php for ($i=1;$i<=5;$i++): ?>
|
||||
<tr>
|
||||
<td><?php echo $i; ?></td>
|
||||
<td><?php echo $q4['c'][$i-1]; ?></td>
|
||||
<td><?php echo pct($q4['c'][$i-1], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>5) Häufigste Kaffeearten (Mehrfachauswahl)</h3>
|
||||
<table>
|
||||
<tr><th>Sorte</th><th>Anzahl</th><th>Anteil (bezogen auf Antworten)</th></tr>
|
||||
<?php foreach ($drinks as $key => $label): ?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo (int)$drinkCounts[$key]; ?></td>
|
||||
<td><?php echo pct((int)$drinkCounts[$key], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if (count($drinkOtherTexts) > 0): ?>
|
||||
<p class="small"><b>„Andere“ – Texte (letzte 30):</b></p>
|
||||
<ul>
|
||||
<?php foreach (array_slice($drinkOtherTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>7) Häufigstes Problem mit der Kaffeeliste</h3>
|
||||
<table>
|
||||
<tr><th>Problem</th><th>Anzahl</th><th>Anteil</th></tr>
|
||||
<?php
|
||||
// Map rows -> counts
|
||||
$tmp = [];
|
||||
foreach ($q7Rows as $r) $tmp[(string)$r['keyVal']] = (int)$r['cnt'];
|
||||
foreach ($problems as $k => $label):
|
||||
$c = $tmp[$k] ?? 0;
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo $c; ?></td>
|
||||
<td><?php echo pct($c, $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>8) Gewünschte Verbesserungen (Mehrfachauswahl)</h3>
|
||||
<table>
|
||||
<tr><th>Verbesserung</th><th>Anzahl</th><th>Anteil (bezogen auf Antworten)</th></tr>
|
||||
<?php foreach ($improvements as $key => $label): ?>
|
||||
<tr>
|
||||
<td><?php echo h($label); ?></td>
|
||||
<td><?php echo (int)$impCounts[$key]; ?></td>
|
||||
<td><?php echo pct((int)$impCounts[$key], $totalResponses); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
|
||||
<?php if (count($impOtherTexts) > 0): ?>
|
||||
<p class="small"><b>„Sonstiges“ – Texte (letzte 30):</b></p>
|
||||
<ul>
|
||||
<?php foreach (array_slice($impOtherTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="box">
|
||||
<h3>6) Zusätzliche Sorten (Freitext) – letzte 30</h3>
|
||||
<?php if (!$newVarietiesTexts): ?>
|
||||
<p class="muted">Keine Einträge.</p>
|
||||
<?php else: ?>
|
||||
<ul>
|
||||
<?php foreach (array_slice($newVarietiesTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>9) Was kann die Kaffeeliste noch besser machen? – letzte 30</h3>
|
||||
<?php if (!$betterIdeasTexts): ?>
|
||||
<p class="muted">Keine Einträge.</p>
|
||||
<?php else: ?>
|
||||
<ul>
|
||||
<?php foreach (array_slice($betterIdeasTexts, 0, 30) as $t): ?>
|
||||
<li><?php echo h($t); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}else{
|
||||
echo "<h2>Sie haben keine Zugang zu dieser Webseite</h2>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include "footer.php";
|
||||
|
||||
?>
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
+51
-19
@@ -1,26 +1,58 @@
|
||||
# SaaS App Foundation
|
||||
# SaaS App
|
||||
|
||||
Dieses Verzeichnis enthaelt das neue, Laravel-nahe Zielprojekt fuer die
|
||||
mandantenfaehige SaaS-Version.
|
||||
`saas-app/` ist das Zielprojekt fuer die mandantenfaehige Neuimplementierung
|
||||
der Kaffeeliste als SaaS.
|
||||
|
||||
Aktueller Stand:
|
||||
## Kurzueberblick
|
||||
|
||||
- downloadfreies Foundation-Geruest
|
||||
- modulare Zielstruktur fuer Webspace-Betrieb
|
||||
- Tenant-Resolution-Skelett
|
||||
- Basismigrationen fuer Mandanten, Benutzer und Rollen
|
||||
- einfache Web-Routen und Blade-Platzhalter
|
||||
- Mandantenfaehigkeit ueber Host/Subdomain
|
||||
- Rollen und Benutzerbindung pro Tenant
|
||||
- Kernfunktionen fuer Dashboard, Mitglieder, Einzahlungen und Striche
|
||||
- Inhalte, Hinweise, Importe, Exporte und Benachrichtigungen als eigene Module
|
||||
- SSR-orientierter Betrieb fuer klassischen Webspace
|
||||
- Cron-basierter Betrieb statt dauerhafter Worker
|
||||
|
||||
Zielrahmen:
|
||||
## Installation
|
||||
|
||||
- klassischer Webspace / PHP-Hosting
|
||||
- SSR-orientiert
|
||||
- Cron statt dauerhaft laufender Worker
|
||||
- OIDC zuerst, SAML spaeter optional
|
||||
Die komplette Installationsanleitung steht im Repo unter
|
||||
`../docs/installationshandbuch.md`.
|
||||
|
||||
Hinweis:
|
||||
Kurzfassung:
|
||||
|
||||
Dieses Geruest ersetzt noch kein vollstaendig installiertes Laravel-Projekt.
|
||||
Sobald `php` und `composer` verfuegbar sind, soll auf dieser Struktur ein
|
||||
vollwertiges Laravel-Projekt aufgesetzt oder diese Struktur in ein solches
|
||||
ueberfuehrt werden.
|
||||
1. `saas-app/` als Projektrahmen bereitstellen.
|
||||
2. PHP 8.2+ und Composer verwenden.
|
||||
3. `.env` aus `.env.example` ableiten und anpassen.
|
||||
4. Datenbank und Tenancy-Werte konfigurieren.
|
||||
5. Migrations ausfuehren.
|
||||
6. Einen ersten Mandanten und erste Benutzer anlegen.
|
||||
7. Den Webserver auf `public/` ausrichten.
|
||||
8. Cron-Jobs fuer Queue, Import, Export und Benachrichtigungen einrichten.
|
||||
|
||||
## Migration Aus Dem Legacy-System
|
||||
|
||||
Die fachliche Roadmap und der Uebergang aus dem alten Root-System sind in
|
||||
`../docs/implementation-foundation.md` beschrieben.
|
||||
|
||||
Der relevante Kern der alten Anwendung besteht im Wesentlichen aus:
|
||||
|
||||
- Dashboard und Kontostand
|
||||
- Mitgliederverwaltung
|
||||
- Kaffee-Striche
|
||||
- Einzahlungen
|
||||
- Hinweise und Inhalte
|
||||
- Exporte und operative Hilfsfunktionen
|
||||
|
||||
## Hosting-Hinweise
|
||||
|
||||
- Das Projekt ist fuer Webspace geeignet, solange PHP, DB-Zugang und Cron
|
||||
vorhanden sind.
|
||||
- Dauerhafte Queue-Worker sind nicht vorausgesetzt.
|
||||
- Der zentrale Einstieg erfolgt ueber die mandantenfaehige Weboberflaeche.
|
||||
- OIDC ist als bevorzugter SSO-Pfad vorgesehen, klassische Logins bleiben als
|
||||
Fallback moeglich.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
Das Verzeichnis ist als Zielarchitektur vorbereitet. Es ersetzt den Legacy-Root
|
||||
noch nicht vollstaendig, sondern dient als naechster konsistenter Zielzustand
|
||||
fuer die SaaS-Umstellung.
|
||||
|
||||
@@ -13,6 +13,22 @@ declare(strict_types=1);
|
||||
*/
|
||||
|
||||
return [
|
||||
'status' => 'foundation-skeleton',
|
||||
'status' => 'saas-first-blueprint',
|
||||
'framework' => 'laravel-near',
|
||||
'runtime_target' => 'webspace-ssr',
|
||||
'modules' => [
|
||||
'dashboard',
|
||||
'members',
|
||||
'ledger',
|
||||
'payments',
|
||||
'content',
|
||||
'imports',
|
||||
'exports',
|
||||
'notifications',
|
||||
'tenants',
|
||||
'identity',
|
||||
],
|
||||
'optional_modules' => [
|
||||
'surveys',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
return [
|
||||
'mode' => env('TENANCY_MODE', 'subdomain'),
|
||||
'central_domains' => [
|
||||
'app.example.com',
|
||||
'www.app.example.com',
|
||||
],
|
||||
'central_domains' => explode(',', (string) env('TENANCY_CENTRAL_DOMAINS', 'localhost')),
|
||||
'tenant_parameter' => 'tenant',
|
||||
'default_route' => 'dashboard',
|
||||
'fallback_tenant' => env('TENANCY_FALLBACK_TENANT'),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
@@ -0,0 +1,9 @@
|
||||
Dieses Verzeichnis ist fuer den Webserver-Document-Root vorgesehen.
|
||||
|
||||
Aktuell enthaelt es bereits:
|
||||
|
||||
- `index.php` als Preview-Einstieg fuer die neue SaaS-Struktur
|
||||
- `.htaccess` fuer einen einfachen Front-Controller-Pfad auf Apache
|
||||
|
||||
Sobald die Zielanwendung als vollwertiges Laravel-Projekt gebootstrapped ist,
|
||||
zeigt der Webserver weiterhin auf `saas-app/public/`.
|
||||
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$modules = [
|
||||
[
|
||||
'title' => 'Dashboard',
|
||||
'copy' => 'Kontostand, Monatsverbrauch, letzte Buchungen und Self-Service fuer Kaffee-Striche.',
|
||||
'tone' => 'core',
|
||||
],
|
||||
[
|
||||
'title' => 'Members',
|
||||
'copy' => 'Mitglieder, Rollen, Aktivstatus und Identitaeten pro Mandant.',
|
||||
'tone' => 'core',
|
||||
],
|
||||
[
|
||||
'title' => 'Ledger',
|
||||
'copy' => 'Kaffee-Striche, Einzahlungen und Korrekturen in einer nachvollziehbaren Sicht.',
|
||||
'tone' => 'core',
|
||||
],
|
||||
[
|
||||
'title' => 'Payments',
|
||||
'copy' => 'Sammelerfassung, PayPal-Pfade und spaetere Zahlungsreferenzen.',
|
||||
'tone' => 'core',
|
||||
],
|
||||
[
|
||||
'title' => 'Content',
|
||||
'copy' => 'Hinweise, FAQ und tenantbezogene Inhalte statt Root-Einzeldateien.',
|
||||
'tone' => 'ops',
|
||||
],
|
||||
[
|
||||
'title' => 'Operations',
|
||||
'copy' => 'Importe, Exporte und Benachrichtigungen als saubere Backoffice-Module.',
|
||||
'tone' => 'ops',
|
||||
],
|
||||
];
|
||||
|
||||
?><!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Kaffeeliste SaaS Preview</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #f7f1e8;
|
||||
--ink: #24170f;
|
||||
--muted: #6a5649;
|
||||
--brand: #0f766e;
|
||||
--accent: #b45309;
|
||||
--card: rgba(255, 252, 247, 0.88);
|
||||
--line: rgba(36, 23, 15, 0.12);
|
||||
--shadow: 0 24px 60px rgba(61, 38, 24, 0.12);
|
||||
--radius: 28px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Aptos", "Segoe UI", sans-serif;
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(180, 83, 9, 0.16), transparent 28%),
|
||||
radial-gradient(circle at top right, rgba(15, 118, 110, 0.14), transparent 24%),
|
||||
linear-gradient(180deg, #fbf7f0 0%, var(--bg) 100%);
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1180px, calc(100vw - 32px));
|
||||
margin: 24px auto 40px;
|
||||
}
|
||||
|
||||
.hero,
|
||||
.card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
background: var(--card);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 34px;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 252, 247, 0.96), rgba(255, 252, 247, 0.82)),
|
||||
radial-gradient(circle at bottom left, rgba(15, 118, 110, 0.12), transparent 26%);
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-block;
|
||||
margin-bottom: 14px;
|
||||
color: var(--accent);
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
margin: 0 0 14px;
|
||||
font-family: "Georgia", serif;
|
||||
line-height: 1.04;
|
||||
}
|
||||
|
||||
h1 { font-size: clamp(2.2rem, 4vw, 4rem); }
|
||||
h2 { font-size: 1.35rem; }
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.actions,
|
||||
.meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.button,
|
||||
.pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
padding: 12px 18px;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.button {
|
||||
background: linear-gradient(135deg, var(--brand), #115e59);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.button.secondary {
|
||||
background: transparent;
|
||||
border: 1px solid rgba(15, 118, 110, 0.2);
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.pill {
|
||||
padding: 9px 14px;
|
||||
background: rgba(15, 118, 110, 0.08);
|
||||
color: var(--brand);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
margin-top: 22px;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 22px;
|
||||
}
|
||||
|
||||
.tone-core {
|
||||
border-top: 5px solid rgba(15, 118, 110, 0.72);
|
||||
}
|
||||
|
||||
.tone-ops {
|
||||
border-top: 5px solid rgba(180, 83, 9, 0.72);
|
||||
}
|
||||
|
||||
.note {
|
||||
margin-top: 22px;
|
||||
padding: 18px 20px;
|
||||
border-radius: 20px;
|
||||
background: rgba(15, 118, 110, 0.08);
|
||||
border: 1px solid rgba(15, 118, 110, 0.16);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 18px;
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<section class="hero">
|
||||
<div class="eyebrow">Kaffeeliste SaaS Preview</div>
|
||||
<h1>Der Root ist jetzt SaaS-first aufgebaut.</h1>
|
||||
<p>
|
||||
Diese Preview-Seite markiert den neuen Document-Root unter `saas-app/public/`.
|
||||
Der Legacy-Bestand wurde nach `legacy-app/` verschoben, die Zielarchitektur
|
||||
und die neu gestalteten Produktseiten liegen unter `saas-app/`.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<a class="button" href="../README.md">Workspace lesen</a>
|
||||
<a class="button secondary" href="../docs/installationshandbuch.md">Installation ansehen</a>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<span class="pill">Mandantenfaehig</span>
|
||||
<span class="pill">Webspace-tauglich</span>
|
||||
<span class="pill">Legacy archiviert</span>
|
||||
</div>
|
||||
<div class="note">
|
||||
Die eigentliche Runtime bleibt der naechste Schritt nach Composer-Bootstrap.
|
||||
Layout, Module, Dokumentation und Hosting-Zielbild sind bereits auf die
|
||||
SaaS-Zielstruktur umgestellt.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid">
|
||||
<?php foreach ($modules as $module): ?>
|
||||
<article class="card tone-<?= htmlspecialchars($module['tone'], ENT_QUOTES) ?>">
|
||||
<h2><?= htmlspecialchars($module['title'], ENT_QUOTES) ?></h2>
|
||||
<p><?= htmlspecialchars($module['copy'], ENT_QUOTES) ?></p>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
|
||||
<p class="footer">Kaffeeliste SaaS Preview · Einstieg fuer Hosting, Review und weitere Implementierung</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +1,54 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Passwort zuruecksetzen</h2>
|
||||
<p>Platzhalter fuer den webspace-tauglichen Passwort-Reset-Prozess per E-Mail.</p>
|
||||
@section('page_title', 'Kaffeeliste SaaS - Passwort Reset')
|
||||
|
||||
<form method="post" action="/forgot-password">
|
||||
<label for="email">E-Mail</label>
|
||||
<input id="email" name="email" type="email" autocomplete="email">
|
||||
<button type="submit">Reset-Link anfordern</button>
|
||||
</form>
|
||||
@section('content')
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Reset flow</p>
|
||||
<h2 class="hero__title">Ein einfacher Reset-Prozess fuer lokale Zugangswege.</h2>
|
||||
<p class="hero__lead">
|
||||
Wenn ein Mandant keinen SSO-Provider nutzt oder ein lokaler Fallback aktiv
|
||||
bleibt, fuehrt diese Seite den Passwort-Reset ueber Mailversand und
|
||||
zeitlich begrenzte Tokens.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">SMTP</span>
|
||||
<span class="badge">Token storage</span>
|
||||
<span class="badge badge--solid">Webspace fit</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="form-panel">
|
||||
<p class="card__eyebrow">Reset anstossen</p>
|
||||
<h3>Reset-Link anfordern</h3>
|
||||
<form class="form-grid" method="post" action="/forgot-password">
|
||||
<div class="field">
|
||||
<label for="email">E-Mail</label>
|
||||
<input id="email" name="email" type="email" autocomplete="email" placeholder="mitglied@example.com">
|
||||
</div>
|
||||
<button type="submit">Reset-Link anfordern</button>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h3>Betriebshinweise</h3>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Tenant-Kontext beachten</p>
|
||||
<p class="timeline__meta">Der Link gilt nur fuer das aktive Mandantenumfeld.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Mail korrekt konfigurieren</p>
|
||||
<p class="timeline__meta">SMTP, Absender und Ablaufzeiten muessen in der finalen Runtime gesetzt werden.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Nur fuer lokale Accounts</p>
|
||||
<p class="timeline__meta">Externe OIDC-Provider behalten ihre eigenen Reset-Wege.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,28 +1,59 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Login')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Login</h2>
|
||||
<p>Mandantenbezogener Einstieg fuer lokalen Login oder spaetere SSO-Anmeldung.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Identity</p>
|
||||
<h2 class="hero__title">Mandantenbezogener Login mit lokalem Fallback und OIDC-Zielbild.</h2>
|
||||
<p class="hero__lead">
|
||||
Die Legacy-Anbindung ueber `AUTH_USER` und LDAP wird in eine flexiblere
|
||||
Identity-Schicht ueberfuehrt. SSO bleibt bevorzugt, lokaler Login und
|
||||
Reset-Prozess sichern den Betrieb ab.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Tenant erkannt</span>
|
||||
<span class="badge">OIDC first</span>
|
||||
<span class="badge badge--solid">Fallback bereit</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<form method="post" action="/login">
|
||||
<label for="email">E-Mail</label>
|
||||
<input id="email" name="email" type="email" autocomplete="username">
|
||||
<section class="split">
|
||||
<article class="form-panel">
|
||||
<p class="card__eyebrow">Lokaler Login</p>
|
||||
<h3>Mit Passwort anmelden</h3>
|
||||
<form class="form-grid" method="post" action="/login">
|
||||
<div class="field">
|
||||
<label for="email">E-Mail</label>
|
||||
<input id="email" name="email" type="email" autocomplete="username" placeholder="mitglied@example.com">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Passwort</label>
|
||||
<input id="password" name="password" type="password" autocomplete="current-password" placeholder="........">
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<button type="submit">Mit Passwort anmelden</button>
|
||||
<a class="button button--ghost" href="/forgot-password">Passwort vergessen?</a>
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
<label for="password">Passwort</label>
|
||||
<input id="password" name="password" type="password" autocomplete="current-password">
|
||||
|
||||
<button type="submit">Mit Passwort anmelden</button>
|
||||
</form>
|
||||
|
||||
<p><a href="/forgot-password">Passwort vergessen?</a></p>
|
||||
|
||||
<section>
|
||||
<article class="panel">
|
||||
<h3>Single Sign-on</h3>
|
||||
<p>Hier werden spaeter tenantbezogene OIDC-/ADFS-Provider angeboten.</p>
|
||||
<ul>
|
||||
<li><a href="/auth/oidc/entra-default">Mit SSO anmelden</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
<p class="muted">
|
||||
Tenant-Admins hinterlegen je Mandant einen oder mehrere OIDC-Provider.
|
||||
So wird die bisherige AD-Naehe in ein flexibles SaaS-Modell ueberfuehrt.
|
||||
</p>
|
||||
<div class="stack" style="margin-top: 18px;">
|
||||
<a class="button" href="/auth/oidc/entra-default">Mit OIDC / Entra anmelden</a>
|
||||
<span class="badge">Provider: entra-default</span>
|
||||
<span class="badge">Tenant: demo</span>
|
||||
</div>
|
||||
<div class="note" style="margin-top: 18px;">
|
||||
Lokaler Login bleibt wichtig fuer Initialsetup, Notfallbetrieb und kleinere Tenants ohne SSO.
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,78 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Content')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Hinweise und FAQ</h2>
|
||||
<p>Platzhalter fuer tenantbezogene Hinweise, FAQ-Eintraege und spaetere Redaktionsfunktionen.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Content</p>
|
||||
<h2 class="hero__title">Hinweise, Banner und FAQ werden tenantbezogene Inhalte.</h2>
|
||||
<p class="hero__lead">
|
||||
Die globale Hinweislogik aus der alten Oberflaeche wird zu einem
|
||||
eigenstaendigen Redaktionsbereich. Banner, FAQ und Hilfetexte sind nicht
|
||||
mehr im Root versteckt, sondern pro Mandant pflegbar.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Announcements</span>
|
||||
<span class="badge">FAQ</span>
|
||||
<span class="badge badge--solid">Tenant scoped</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Aktiv</p>
|
||||
<h3>Hinweise im Umlauf</h3>
|
||||
</div>
|
||||
<span class="pill">Header + Dashboard</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<th>Sichtbar bis</th>
|
||||
<th>Kanal</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Monatsabschluss am Freitag</td>
|
||||
<td>31.03.2026</td>
|
||||
<td>Dashboard</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Neuer Preis pro Strich</td>
|
||||
<td>15.04.2026</td>
|
||||
<td>Header</td>
|
||||
<td><span class="status status--warning">Geplant</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h3>Redaktioneller Nutzen</h3>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Hinweise ohne Code-Aenderung</p>
|
||||
<p class="timeline__meta">Tenant-Admins koennen sichtbare Meldungen direkt verwalten.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">FAQ je Organisation</p>
|
||||
<p class="timeline__meta">Hilfeinhalte koennen pro Mandant und Prozess gepflegt werden.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Saubere Sichtbarkeit</p>
|
||||
<p class="timeline__meta">Dashboard, Header und spaetere Mailtexte greifen auf denselben Content-Pool zu.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,13 +1,102 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Dashboard')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Dashboard</h2>
|
||||
<p>Platzhalter fuer Kontostand, Monatsverbrauch und letzte Buchungen.</p>
|
||||
<ul>
|
||||
<li>Kontostand: 7,50 EUR</li>
|
||||
<li>Striche diesen Monat: 5</li>
|
||||
<li>Einzahlungen diesen Monat: 1</li>
|
||||
</ul>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Tenant overview</p>
|
||||
<h2 class="hero__title">Dein Kaffeeliste-Stand auf einen Blick.</h2>
|
||||
<p class="hero__lead">
|
||||
Das Dashboard zeigt den aktuellen Kontostand, die Nutzung im Monat und die letzten Buchungen.
|
||||
Die Werte sind hier bewusst als fachliche Anker platziert und koennen spaeter direkt aus dem Ledger gespeist werden.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Letzte Synchronisation: heute</span>
|
||||
<span class="badge">Tenant: Demo-Workspace</span>
|
||||
<span class="badge badge--solid">Saldo aktiv</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--4">
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Kontostand</p>
|
||||
<div class="metric__value">7,50 EUR</div>
|
||||
<p class="muted">Positiver Puffer fuer den laufenden Monat.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Striche diesen Monat</p>
|
||||
<div class="metric__value">5</div>
|
||||
<p class="muted">Verbrauch seit Monatsbeginn.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Einzahlungen diesen Monat</p>
|
||||
<div class="metric__value">1</div>
|
||||
<p class="muted">Alle gebuchten Zahlungen im aktuellen Zeitraum.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Letzte Buchung</p>
|
||||
<div class="metric__value">Heute</div>
|
||||
<p class="muted">Aktuelle Aktivitaet im Mandantenbereich.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="split" style="margin-top: 18px;">
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Aktivitaet</p>
|
||||
<h3>Letzte Buchungen</h3>
|
||||
</div>
|
||||
<span class="pill">Live feed</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Zeit</th>
|
||||
<th>Typ</th>
|
||||
<th>Betrag</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>09:00</td>
|
||||
<td>Einzahlung</td>
|
||||
<td>10,00 EUR</td>
|
||||
<td><span class="status">Gebucht</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10:30</td>
|
||||
<td>Strich</td>
|
||||
<td>-2,50 EUR</td>
|
||||
<td><span class="status status--warning">Verbraucht</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>12:15</td>
|
||||
<td>Hinweis</td>
|
||||
<td>Info</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h3>Arbeitsbereich</h3>
|
||||
<p class="muted">Schnellzugriffe fuer die wichtigsten Arbeitsschritte im Tagesbetrieb.</p>
|
||||
<div class="stack">
|
||||
<a class="button" href="/members">Mitglieder verwalten</a>
|
||||
<a class="button button--ghost" href="/ledger">Ledger pruefen</a>
|
||||
<a class="button button--ghost" href="/payments">Zahlungen ansehen</a>
|
||||
<a class="button button--ghost" href="/imports">CSV-Import starten</a>
|
||||
</div>
|
||||
<div class="note" style="margin-top: 18px;">
|
||||
Der alte Funktionskern bleibt sichtbar: Saldo, Striche, Einzahlungen und letzte Aktionen bilden die produktive Achse.
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,75 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Exports')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Exporte</h2>
|
||||
<p>Platzhalter fuer Reports, Export-Jobs und spaetere Download-Ansichten.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Exports</p>
|
||||
<h2 class="hero__title">Reports und Drucklisten bleiben moeglich, aber nicht mehr als Spezialskript.</h2>
|
||||
<p class="hero__lead">
|
||||
Das fruehere PDF fuer die Papierliste wandert in ein Export-Modul. Neben
|
||||
Drucklisten entstehen hier Reports fuer Finance, Mitglieder und
|
||||
Monatsabschluesse.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">PDF optional</span>
|
||||
<span class="badge">Reports</span>
|
||||
<span class="badge badge--solid">Digital first</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="panel">
|
||||
<h3>Exportziele</h3>
|
||||
<ul class="list-reset">
|
||||
<li><span class="status">Kontostandsreport</span> Standardausgabe fuer Finance und Monatsabschluss.</li>
|
||||
<li><span class="status">Mitgliederexport</span> Snapshot der aktiven und inaktiven Nutzer pro Tenant.</li>
|
||||
<li><span class="status">Papierliste</span> Optionaler PDF-Weg fuer Teams mit analogem Prozess.</li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Downloads</p>
|
||||
<h3>Letzte Exportjobs</h3>
|
||||
</div>
|
||||
<span class="pill">Report history</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Export</th>
|
||||
<th>Ziel</th>
|
||||
<th>Format</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Monatsreport Maerz</td>
|
||||
<td>Finance</td>
|
||||
<td>CSV</td>
|
||||
<td><span class="status">Bereit</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Papierliste Vieltrinker</td>
|
||||
<td>Kueche</td>
|
||||
<td>PDF</td>
|
||||
<td><span class="status">Bereit</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mitglieder-Snapshot</td>
|
||||
<td>Tenant Admin</td>
|
||||
<td>XLSX spaeter</td>
|
||||
<td><span class="status status--warning">Geplant</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,83 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Imports')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Importe</h2>
|
||||
<p>Platzhalter fuer CSV-Importe, Cron-gesteuerte Verarbeitungen und Statusanzeigen.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Imports</p>
|
||||
<h2 class="hero__title">Dateiimporte werden kontrollierte Jobs statt einmaliger Root-Skripte.</h2>
|
||||
<p class="hero__lead">
|
||||
CSV-Uploads und Legacy-Datenuebernahmen bleiben moeglich, laufen aber als
|
||||
nachvollziehbare Importjobs mit Vorschau, Mapping und Statusmeldungen.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">CSV optional</span>
|
||||
<span class="badge">Cron ready</span>
|
||||
<span class="badge badge--solid">Migration friendly</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="panel">
|
||||
<h3>Import-Pipeline</h3>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">1. Datei pruefen</p>
|
||||
<p class="timeline__meta">Format, Pflichtspalten und Deduplikation werden vorab validiert.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">2. Mapping anwenden</p>
|
||||
<p class="timeline__meta">Legacy-Zahlungen und Verbrauch werden auf Members, Payments und Ledger abgebildet.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">3. Job ausfuehren</p>
|
||||
<p class="timeline__meta">Verarbeitung laeuft ueber Cron und schreibt einen nachvollziehbaren Status.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Queue</p>
|
||||
<h3>Letzte Importjobs</h3>
|
||||
</div>
|
||||
<span class="pill">Backoffice</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Job</th>
|
||||
<th>Quelle</th>
|
||||
<th>Ergebnis</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>members-2026-03</td>
|
||||
<td>Legacy Export</td>
|
||||
<td>48 Datensaetze</td>
|
||||
<td><span class="status">Fertig</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>payments-2026-03</td>
|
||||
<td>CSV PayPal</td>
|
||||
<td>12 Buchungen</td>
|
||||
<td><span class="status">Verarbeitet</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ledger-replay</td>
|
||||
<td>Archivbestand</td>
|
||||
<td>3 Warnungen</td>
|
||||
<td><span class="status status--warning">Pruefen</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -3,15 +3,370 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ $title ?? 'Kaffeeliste SaaS' }}</title>
|
||||
<meta name="color-scheme" content="light">
|
||||
<title>@yield('page_title', $title ?? 'Kaffeeliste SaaS')</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #f4efe6;
|
||||
--bg-elevated: rgba(255, 255, 255, 0.86);
|
||||
--bg-soft: rgba(249, 242, 231, 0.9);
|
||||
--text: #1f2933;
|
||||
--muted: #667085;
|
||||
--brand: #0f766e;
|
||||
--brand-strong: #134e4a;
|
||||
--accent: #b45309;
|
||||
--line: rgba(31, 41, 51, 0.12);
|
||||
--shadow: 0 24px 60px rgba(15, 23, 42, 0.08);
|
||||
--radius-xl: 28px;
|
||||
--radius-lg: 20px;
|
||||
--content-width: 1220px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
color: var(--text);
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(180, 83, 9, 0.12), transparent 32%),
|
||||
radial-gradient(circle at top right, rgba(15, 118, 110, 0.14), transparent 28%),
|
||||
linear-gradient(180deg, #faf7f1 0%, var(--bg) 100%);
|
||||
font-family: "Segoe UI", "Aptos", "Trebuchet MS", sans-serif;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
a { color: var(--brand-strong); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
img { max-width: 100%; }
|
||||
|
||||
.app-shell { min-height: 100vh; }
|
||||
.app-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: rgba(251, 248, 242, 0.88);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
.app-header__inner,
|
||||
.app-main,
|
||||
.app-footer__inner {
|
||||
width: min(var(--content-width), calc(100% - 32px));
|
||||
margin: 0 auto;
|
||||
}
|
||||
.app-header__inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
padding: 18px 0;
|
||||
}
|
||||
.brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
|
||||
.brand__mark {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 16px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--brand) 0%, #115e59 55%, var(--accent) 100%);
|
||||
box-shadow: 0 18px 40px rgba(15, 118, 110, 0.25);
|
||||
}
|
||||
.brand__text { display: grid; gap: 2px; min-width: 0; }
|
||||
.brand__title { margin: 0; font-size: 1.02rem; font-weight: 700; letter-spacing: 0.01em; }
|
||||
.brand__subtitle { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
||||
.header-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.badge,
|
||||
.pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: var(--bg-soft);
|
||||
padding: 0.42rem 0.75rem;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
.badge--solid { background: var(--brand); color: #fff; border-color: transparent; }
|
||||
.app-nav {
|
||||
width: min(var(--content-width), calc(100% - 32px));
|
||||
margin: 0 auto 18px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
.app-nav a {
|
||||
padding: 0.65rem 0.95rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid transparent;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
color: var(--text);
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.app-nav a:hover {
|
||||
text-decoration: none;
|
||||
border-color: rgba(15, 118, 110, 0.2);
|
||||
background: #fff;
|
||||
}
|
||||
.app-main { padding: 34px 0 56px; }
|
||||
.hero {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 28px;
|
||||
padding: 30px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-xl);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.8)),
|
||||
radial-gradient(circle at top right, rgba(180, 83, 9, 0.15), transparent 28%),
|
||||
radial-gradient(circle at bottom left, rgba(15, 118, 110, 0.16), transparent 26%);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.hero__kicker {
|
||||
margin: 0 0 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.15em;
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
.hero__title {
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 4vw, 3.6rem);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.hero__lead {
|
||||
margin: 0;
|
||||
max-width: 68ch;
|
||||
color: var(--muted);
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"] {
|
||||
appearance: none;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
padding: 0.8rem 1.15rem;
|
||||
background: linear-gradient(135deg, var(--brand) 0%, #115e59 100%);
|
||||
color: #fff;
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 12px 24px rgba(15, 118, 110, 0.18);
|
||||
}
|
||||
.button--ghost {
|
||||
background: transparent;
|
||||
color: var(--brand-strong);
|
||||
border: 1px solid rgba(15, 118, 110, 0.18);
|
||||
box-shadow: none;
|
||||
}
|
||||
.grid { display: grid; gap: 18px; }
|
||||
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||
.card,
|
||||
.panel,
|
||||
.form-panel,
|
||||
.table-card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--bg-elevated);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: var(--shadow);
|
||||
padding: 22px;
|
||||
}
|
||||
.card__eyebrow {
|
||||
margin: 0 0 10px;
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
.metric { display: grid; gap: 8px; }
|
||||
.metric__value {
|
||||
font-size: clamp(1.6rem, 2.5vw, 2.4rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.metric__label,
|
||||
.muted { color: var(--muted); }
|
||||
.list-reset { margin: 0; padding: 0; list-style: none; }
|
||||
.list-reset li + li { margin-top: 12px; }
|
||||
.stack { display: grid; gap: 14px; }
|
||||
.split {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.9fr);
|
||||
}
|
||||
.toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.toolbar .badge { background: #fff; }
|
||||
.table-card { overflow: hidden; padding: 0; }
|
||||
.table-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 22px 22px 12px;
|
||||
}
|
||||
.table-card__body {
|
||||
padding: 0 22px 22px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
min-width: 680px;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 0.95rem 0.8rem;
|
||||
border-bottom: 1px solid rgba(31, 41, 51, 0.08);
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
th {
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--muted);
|
||||
font-weight: 700;
|
||||
background: rgba(249, 242, 231, 0.6);
|
||||
}
|
||||
tr:last-child td { border-bottom: 0; }
|
||||
.status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 0.38rem 0.65rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(15, 118, 110, 0.11);
|
||||
color: var(--brand-strong);
|
||||
font-weight: 700;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
.status--warning { background: rgba(180, 83, 9, 0.12); color: #92400e; }
|
||||
.status--danger { background: rgba(185, 28, 28, 0.12); color: #991b1b; }
|
||||
.form-grid { display: grid; gap: 16px; }
|
||||
.field { display: grid; gap: 8px; }
|
||||
label { font-size: 0.9rem; font-weight: 700; }
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
border: 1px solid rgba(31, 41, 51, 0.14);
|
||||
border-radius: 16px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 0.85rem 0.95rem;
|
||||
font: inherit;
|
||||
color: var(--text);
|
||||
}
|
||||
textarea { min-height: 120px; resize: vertical; }
|
||||
.note {
|
||||
padding: 14px 16px;
|
||||
border-radius: 16px;
|
||||
background: rgba(15, 118, 110, 0.08);
|
||||
border: 1px solid rgba(15, 118, 110, 0.12);
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
.timeline { display: grid; gap: 14px; }
|
||||
.timeline__item {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding: 14px 16px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border: 1px solid rgba(31, 41, 51, 0.08);
|
||||
}
|
||||
.timeline__title { margin: 0; font-weight: 700; }
|
||||
.timeline__meta { margin: 0; color: var(--muted); font-size: 0.92rem; }
|
||||
.app-footer { padding: 0 0 38px; }
|
||||
.app-footer__inner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 18px;
|
||||
color: var(--muted);
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
@media (max-width: 960px) {
|
||||
.grid--2,
|
||||
.grid--3,
|
||||
.grid--4,
|
||||
.split { grid-template-columns: 1fr; }
|
||||
.app-header__inner { flex-direction: column; align-items: flex-start; }
|
||||
.header-meta { justify-content: flex-start; }
|
||||
.hero,
|
||||
.card,
|
||||
.panel,
|
||||
.form-panel,
|
||||
.table-card { padding: 18px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Kaffeeliste SaaS</h1>
|
||||
<p>Mandantenfaehige Webspace-Zielanwendung</p>
|
||||
</header>
|
||||
<main>
|
||||
@yield('content')
|
||||
</main>
|
||||
<body class="@yield('body_class')">
|
||||
<div class="app-shell">
|
||||
<header class="app-header">
|
||||
<div class="app-header__inner">
|
||||
<div class="brand">
|
||||
<div class="brand__mark">K</div>
|
||||
<div class="brand__text">
|
||||
<h1 class="brand__title">Kaffeeliste SaaS</h1>
|
||||
<p class="brand__subtitle">Mandantenfaehige Buchungen, Mitglieder und Auswertungen</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-meta">
|
||||
<span class="badge">Webspace-ready</span>
|
||||
<span class="badge badge--solid">Tenant aware</span>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="app-nav" aria-label="Hauptnavigation">
|
||||
<a href="/">Landing</a>
|
||||
<a href="/dashboard">Dashboard</a>
|
||||
<a href="/members">Mitglieder</a>
|
||||
<a href="/ledger">Ledger</a>
|
||||
<a href="/payments">Payments</a>
|
||||
<a href="/content">Content</a>
|
||||
<a href="/imports">Imports</a>
|
||||
<a href="/exports">Exports</a>
|
||||
<a href="/notifications">Notifications</a>
|
||||
<a href="/surveys">Surveys</a>
|
||||
<a href="/tenants">Tenants</a>
|
||||
<a href="/login">Login</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="app-main">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<footer class="app-footer">
|
||||
<div class="app-footer__inner">
|
||||
<span>Kaffeeliste SaaS</span>
|
||||
<span>Mitglieder, Striche, Einzahlungen, Hinweise und Exporte in einem System</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,8 +1,81 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Ledger')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Ledger</h2>
|
||||
<p>Platzhalter fuer Buchungen, Kontostand und Korrekturen.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Accounting flow</p>
|
||||
<h2 class="hero__title">Ledger fuer Buchungen, Verbrauch und Korrekturen.</h2>
|
||||
<p class="hero__lead">
|
||||
Die fachliche Kernlogik der alten Kaffeeliste bleibt erhalten: Einzahlungen, Striche und Saldo
|
||||
werden in einer nachvollziehbaren Buchungsspur zusammengefuehrt.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Saldo: 7,50 EUR</span>
|
||||
<span class="badge">Korrekturen: 2</span>
|
||||
<span class="badge badge--solid">Buchungsspur geordnet</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--3">
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Offener Saldo</p>
|
||||
<div class="metric__value">7,50 EUR</div>
|
||||
<p class="muted">Positiv, daher kein Handlungsdruck.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Verbrauchsumfang</p>
|
||||
<div class="metric__value">5 Striche</div>
|
||||
<p class="muted">Aktueller Buchungsumfang im laufenden Zeitraum.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Letzte Korrektur</p>
|
||||
<div class="metric__value">Heute</div>
|
||||
<p class="muted">Sichtbar fuer Admins und Audit.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="table-card" style="margin-top: 18px;">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Buchungen</p>
|
||||
<h3>Ledger-Eintraege</h3>
|
||||
</div>
|
||||
<span class="pill">Audit trail</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Beschreibung</th>
|
||||
<th>Typ</th>
|
||||
<th>Betrag</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>21.03.2026</td>
|
||||
<td>Einzahlung Demo-Workspace</td>
|
||||
<td>Payment</td>
|
||||
<td>+10,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>21.03.2026</td>
|
||||
<td>2 Striche Kaffee</td>
|
||||
<td>Consumption</td>
|
||||
<td>-2,50 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>20.03.2026</td>
|
||||
<td>Manuelle Korrektur</td>
|
||||
<td>Adjustment</td>
|
||||
<td>+0,50 EUR</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,76 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Mitglieder')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Mitglieder</h2>
|
||||
<p>Platzhalter fuer tenantbezogene Mitgliederverwaltung und Statusanzeige.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Member management</p>
|
||||
<h2 class="hero__title">Mitgliederverwaltung pro Mandant.</h2>
|
||||
<p class="hero__lead">
|
||||
Hier sind aktive Mitglieder, Rollen und Status klar gegliedert. Diese Sicht entspricht der alten
|
||||
Mitgliederverwaltung, nur als SaaS-taugliche, aufgeraeumte Oberflaeche.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Aktiv: 18</span>
|
||||
<span class="badge">Admins: 3</span>
|
||||
<span class="badge badge--solid">Tenant: Demo-Workspace</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--2">
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Aktive Mitglieder</p>
|
||||
<div class="metric__value">18</div>
|
||||
<p class="muted">Fuer Buchungen, Auswertungen und Benachrichtigungen freigeschaltet.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Sperrstatus</p>
|
||||
<div class="metric__value">2</div>
|
||||
<p class="muted">Inaktive Konten bleiben sichtbar, aber ohne Schreibrechte.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="table-card" style="margin-top: 18px;">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Mitgliederliste</p>
|
||||
<h3>Aktive Zuordnungen</h3>
|
||||
</div>
|
||||
<span class="pill">Rollenkonzept</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Rolle</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Max Beispiel</td>
|
||||
<td>max@example.com</td>
|
||||
<td>Member</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jana Muster</td>
|
||||
<td>jana@example.com</td>
|
||||
<td>Admin</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Chris Reserve</td>
|
||||
<td>chris@example.com</td>
|
||||
<td>Member</td>
|
||||
<td><span class="status status--warning">Pausiert</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,84 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Notifications')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Benachrichtigungen</h2>
|
||||
<p>Platzhalter fuer Mailversand, Versandstatus und Cron-basierte Zustellung.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Notifications</p>
|
||||
<h2 class="hero__title">Benachrichtigungen werden planbare Betriebsprozesse.</h2>
|
||||
<p class="hero__lead">
|
||||
Die alte Sammelmail-Funktion geht in ein Modul ueber, das Versandregeln,
|
||||
Cron-Ausfuehrung und Ergebnisprotokolle sauber trennt. Damit werden
|
||||
Schuldenhinweise und Service-Meldungen tenantfaehig.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Mail templates</span>
|
||||
<span class="badge">Cron dispatch</span>
|
||||
<span class="badge badge--solid">Audit logs</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="split">
|
||||
<article class="panel">
|
||||
<h3>Benachrichtigungsarten</h3>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Saldo-Erinnerung</p>
|
||||
<p class="timeline__meta">Automatisch bei negativem Kontostand oder Schwellwerten.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Import- und Exportstatus</p>
|
||||
<p class="timeline__meta">Backoffice meldet Erfolge, Warnungen und Fehler an Admins.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">Service-Kommunikation</p>
|
||||
<p class="timeline__meta">Hinweise zu Preisen, Wartung oder Monatsabschluss zentral ausspielen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Versandprotokoll</p>
|
||||
<h3>Letzte Benachrichtigungen</h3>
|
||||
</div>
|
||||
<span class="pill">Tenant scoped</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Typ</th>
|
||||
<th>Empfaenger</th>
|
||||
<th>Ausloeser</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Saldo-Erinnerung</td>
|
||||
<td>6 Mitglieder</td>
|
||||
<td>negativer Kontostand</td>
|
||||
<td><span class="status">Gesendet</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Import-Report</td>
|
||||
<td>Tenant Admin</td>
|
||||
<td>Importjob fertig</td>
|
||||
<td><span class="status">Bereitgestellt</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service-Hinweis</td>
|
||||
<td>alle Mitglieder</td>
|
||||
<td>Preisanpassung</td>
|
||||
<td><span class="status status--warning">Eingeplant</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,96 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Payments')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Einzahlungen</h2>
|
||||
<p>Platzhalter fuer Zahlungseintraege und spaetere Zahlungsreferenzen.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Payments</p>
|
||||
<h2 class="hero__title">Einzahlungen und Zahlungswege werden zu einem eigenen SaaS-Modul.</h2>
|
||||
<p class="hero__lead">
|
||||
Die fruehere Sammelerfassung bleibt als Kernfunktion erhalten, wird aber um
|
||||
Status, Referenzen und tenantbezogene Bezahlwege erweitert. So passen
|
||||
manuelle Buchung, PayPal und spaetere Automatisierungen in denselben Ablauf.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">PayPal optional</span>
|
||||
<span class="badge">Finance workflow</span>
|
||||
<span class="badge badge--solid">Saldo-relevant</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--3">
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Offene Zahlungen</p>
|
||||
<div class="metric__value">6</div>
|
||||
<p class="muted">Noch zu bestaetigende oder abzugleichende Vorgaege.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Monatssumme</p>
|
||||
<div class="metric__value">245 EUR</div>
|
||||
<p class="muted">Gebuchte Einzahlungen im aktuellen Abrechnungszeitraum.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Schnellwege</p>
|
||||
<div class="metric__value">3</div>
|
||||
<p class="muted">Bar, PayPal und spaetere Referenzimporte aus Drittsystemen.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="split" style="margin-top: 18px;">
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Zahlungsjournal</p>
|
||||
<h3>Letzte Zahlungseintraege</h3>
|
||||
</div>
|
||||
<span class="pill">Finance Sicht</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Mitglied</th>
|
||||
<th>Methode</th>
|
||||
<th>Betrag</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Max Beispiel</td>
|
||||
<td>PayPal</td>
|
||||
<td>10,00 EUR</td>
|
||||
<td><span class="status">Gebucht</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Julia Betrieb</td>
|
||||
<td>Bar</td>
|
||||
<td>5,00 EUR</td>
|
||||
<td><span class="status">Bestaetigt</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rene Muster</td>
|
||||
<td>SEPA Import</td>
|
||||
<td>15,00 EUR</td>
|
||||
<td><span class="status status--warning">Pruefen</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h3>Was aus dem Legacy-System bleibt</h3>
|
||||
<ul class="list-reset">
|
||||
<li><span class="status">Sammelerfassung</span> Admins buchen mehrere Einzahlungen in einem Schritt.</li>
|
||||
<li><span class="status">Dashboard-Link</span> Direkte Einzahlung oder Schuldenausgleich bleibt moeglich.</li>
|
||||
<li><span class="status">Ledger Sync</span> Jede Einzahlung wirkt unmittelbar auf den Kontostand.</li>
|
||||
</ul>
|
||||
<div class="note" style="margin-top: 18px;">
|
||||
Das Payments-Modul ersetzt keine Funktionalitaet, sondern gibt ihr eine saubere Prozessstruktur.
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,42 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Surveys')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Umfragen</h2>
|
||||
<p>Platzhalter fuer Umfragen, Fragen, Antworten und spaetere Auswertungen.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Optionales Modul</p>
|
||||
<h2 class="hero__title">Umfragen bleiben moeglich, sind aber nicht mehr Teil des Pflichtkerns.</h2>
|
||||
<p class="hero__lead">
|
||||
Das Survey-Modul ist weiterhin vorgesehen, wird aber bewusst als optionaler
|
||||
Baustein gefuehrt. So bleibt der eigentliche Produktkern schlank und die
|
||||
fruehere Zusatzfunktion geht nicht verloren.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Feature flag</span>
|
||||
<span class="badge">Tenant scoped</span>
|
||||
<span class="badge badge--solid">Optional</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--2">
|
||||
<article class="panel">
|
||||
<h3>Typische Einsatzfaelle</h3>
|
||||
<ul class="list-reset">
|
||||
<li><span class="status">Feedback</span> Kurze Stimmungsbilder zu Kaffee, Preisen oder Ausstattung.</li>
|
||||
<li><span class="status">Organisation</span> Abstimmungen zu Office-Regeln und Betriebsroutinen.</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article class="panel">
|
||||
<h3>Produktentscheidung</h3>
|
||||
<p class="muted">
|
||||
Das Modul ist vorbereitet, blockiert aber weder Migration noch Go-live. Aktiviert wird es nur,
|
||||
wenn ein Mandant den Bedarf wirklich hat.
|
||||
</p>
|
||||
<div class="note" style="margin-top: 18px;">
|
||||
Surveys bleiben ein Erweiterungsmodul und ueberlagern nicht mehr Dashboard, Ledger oder Payments.
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,25 +1,93 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Tenant-Verwaltung</h2>
|
||||
<p>Platzhalter fuer die spaetere Verwaltung von Mandanten, Domains, Rollen und SSO-Providern.</p>
|
||||
@section('page_title', 'Kaffeeliste SaaS - Tenants')
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Mandant</th>
|
||||
<th>Tenant Key</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Demo Tenant</td>
|
||||
<td>demo</td>
|
||||
<td>active</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@section('content')
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Central admin</p>
|
||||
<h2 class="hero__title">Mandanten, Domains und SSO sauber zentral verwalten.</h2>
|
||||
<p class="hero__lead">
|
||||
Die SaaS-Version fuehrt eine echte Mandantenebene ein. So werden mehrere
|
||||
Teams, Standorte oder Fachbereiche in derselben Plattform betrieben, aber
|
||||
fachlich und organisatorisch getrennt.
|
||||
</p>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="badge">Subdomain routing</span>
|
||||
<span class="badge">OIDC first</span>
|
||||
<span class="badge badge--solid">Tenant aware</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--3">
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Mandanten</p>
|
||||
<div class="metric__value">3</div>
|
||||
<p class="muted">Aktive Bereiche auf gemeinsamer Plattform.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Domains</p>
|
||||
<div class="metric__value">5</div>
|
||||
<p class="muted">Zentrale und tenantbezogene Hosts fuer Login und Betrieb.</p>
|
||||
</article>
|
||||
<article class="card metric">
|
||||
<p class="metric__label">Provider</p>
|
||||
<div class="metric__value">2</div>
|
||||
<p class="muted">OIDC-Provider plus lokaler Fallback.</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="split" style="margin-top: 18px;">
|
||||
<article class="table-card">
|
||||
<div class="table-card__header">
|
||||
<div>
|
||||
<p class="card__eyebrow">Mandantenlandschaft</p>
|
||||
<h3>Aktive Tenants</h3>
|
||||
</div>
|
||||
<span class="pill">Central view</span>
|
||||
</div>
|
||||
<div class="table-card__body">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Mandant</th>
|
||||
<th>Tenant Key</th>
|
||||
<th>Domain</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Office Berlin</td>
|
||||
<td>berlin</td>
|
||||
<td>berlin.kaffeeliste.app</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Office Koeln</td>
|
||||
<td>koeln</td>
|
||||
<td>koeln.kaffeeliste.app</td>
|
||||
<td><span class="status">Aktiv</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Shared Demo</td>
|
||||
<td>demo</td>
|
||||
<td>demo.kaffeeliste.app</td>
|
||||
<td><span class="status status--warning">Sandbox</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="panel">
|
||||
<h3>Zentrale Aufgaben</h3>
|
||||
<ul class="list-reset">
|
||||
<li><span class="status">Domain Setup</span> Host und Tenant Key fuer saubere Aufloesung.</li>
|
||||
<li><span class="status">Identity</span> OIDC-Provider pro Mandant hinterlegen.</li>
|
||||
<li><span class="status">Feature Flags</span> PayPal, Surveys oder Self-Service-Striche je Tenant steuern.</li>
|
||||
</ul>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -1,8 +1,67 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('page_title', 'Kaffeeliste SaaS - Landing')
|
||||
|
||||
@section('content')
|
||||
<section>
|
||||
<h2>Neue SaaS-Plattform</h2>
|
||||
<p>Dieses Grundgeruest dient als Startpunkt fuer die mandantenfaehige Neuimplementierung.</p>
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="hero__kicker">Coffee operations cloud</p>
|
||||
<h2 class="hero__title">Die neue SaaS-Zentrale fuer Kaffeeliste, Mitglieder und Buchungen.</h2>
|
||||
<p class="hero__lead">
|
||||
Diese Version stellt den Produktkern sichtbar in den Vordergrund: Mandanten, Login, Kontostaende,
|
||||
Striche, Einzahlungen, Hinweise und Auswertungen in einer klaren, webspace-tauglichen Oberflaeche.
|
||||
</p>
|
||||
<div class="hero__actions">
|
||||
<a class="button" href="/dashboard">Zum Dashboard</a>
|
||||
<a class="button button--ghost" href="/login">Login pruefen</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid--3">
|
||||
<article class="card">
|
||||
<p class="card__eyebrow">MVP</p>
|
||||
<h3>Kernfunktionen bleiben erhalten</h3>
|
||||
<p class="muted">Mitglieder, Ledger, Einzahlungen, Striche und Hinweise sind fachlich sichtbar modelliert.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<p class="card__eyebrow">SaaS</p>
|
||||
<h3>Mandantenfaehig gedacht</h3>
|
||||
<p class="muted">Jede Organisation bekommt ihren eigenen Bereich, eigene Rollen und eigene Inhalte.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<p class="card__eyebrow">Hosting</p>
|
||||
<h3>Webspace und Cron zuerst</h3>
|
||||
<p class="muted">Die Zielarchitektur bleibt leichtgewichtig und vermeidet dauerhaft laufende Worker.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid--2">
|
||||
<article class="panel">
|
||||
<h3>Was die Plattform abdeckt</h3>
|
||||
<ul class="list-reset">
|
||||
<li><span class="status">Dashboard</span> Kontostand, Monatswerte und letzte Aktionen.</li>
|
||||
<li><span class="status">Ledger</span> Einzahlungen, Verbrauch und Korrekturen in einer Sicht.</li>
|
||||
<li><span class="status">Members</span> Aktivitaet, Rollen und Mitgliedsstatus pro Mandant.</li>
|
||||
<li><span class="status">Operations</span> Importe, Exporte, Notifications und Surveys als Zusatzmodule.</li>
|
||||
</ul>
|
||||
</article>
|
||||
<article class="panel">
|
||||
<h3>Projektfokus</h3>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">1. Root modernisieren</p>
|
||||
<p class="timeline__meta">Die alte PHP-Oberflaeche wird fachlich in die SaaS-Struktur ueberfuehrt.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">2. Nicht benoetigte Seiten entlasten</p>
|
||||
<p class="timeline__meta">Sonderlogik wandert in optionale Module oder faellt bewusst weg.</p>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<p class="timeline__title">3. Doku und Betrieb</p>
|
||||
<p class="timeline__meta">Installationsanleitung, Hosting-Hinweise und Migrationspfad bleiben nachvollziehbar.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
param(
|
||||
[string]$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$saasAppPath = Join-Path $ProjectRoot 'saas-app'
|
||||
$envExamplePath = Join-Path $saasAppPath '.env.example'
|
||||
|
||||
function Test-Command {
|
||||
param([string]$Name)
|
||||
|
||||
return $null -ne (Get-Command $Name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Write-Check {
|
||||
param(
|
||||
[string]$Label,
|
||||
[bool]$Passed,
|
||||
[string]$Detail
|
||||
)
|
||||
|
||||
$status = if ($Passed) { '[OK]' } else { '[FEHLT]' }
|
||||
Write-Host "$status $Label - $Detail"
|
||||
}
|
||||
|
||||
Write-Host 'Pruefe lokale Voraussetzungen fuer Kaffeeliste SaaS...'
|
||||
Write-Host "Projektwurzel: $ProjectRoot"
|
||||
Write-Host ''
|
||||
|
||||
$phpExists = Test-Command 'php'
|
||||
$composerExists = Test-Command 'composer'
|
||||
$gitExists = Test-Command 'git'
|
||||
|
||||
Write-Check -Label 'PHP' -Passed $phpExists -Detail ($(if ($phpExists) { (php -r "echo PHP_VERSION;") } else { 'nicht gefunden' }))
|
||||
Write-Check -Label 'Composer' -Passed $composerExists -Detail ($(if ($composerExists) { (composer --version | Select-Object -First 1) } else { 'nicht gefunden' }))
|
||||
Write-Check -Label 'Git' -Passed $gitExists -Detail ($(if ($gitExists) { 'verfuegbar' } else { 'nicht gefunden' }))
|
||||
Write-Check -Label 'SaaS-App' -Passed (Test-Path $saasAppPath) -Detail $saasAppPath
|
||||
Write-Check -Label '.env.example' -Passed (Test-Path $envExamplePath) -Detail $envExamplePath
|
||||
|
||||
$envPath = Join-Path $saasAppPath '.env'
|
||||
Write-Check -Label '.env' -Passed (Test-Path $envPath) -Detail ($(if (Test-Path $envPath) { 'vorhanden' } else { 'noch nicht angelegt' }))
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Naechste Schritte:'
|
||||
Write-Host '1. Falls Composer fehlt, zuerst Composer installieren.'
|
||||
Write-Host '2. Mit scripts/prepare-saas-env.ps1 eine lokale .env anlegen.'
|
||||
Write-Host '3. Danach saas-app konfigurieren und die Installationsanleitung in docs/installationshandbuch.md befolgen.'
|
||||
@@ -0,0 +1,23 @@
|
||||
param(
|
||||
[string]$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path,
|
||||
[switch]$Force
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$saasAppPath = Join-Path $ProjectRoot 'saas-app'
|
||||
$sourcePath = Join-Path $saasAppPath '.env.example'
|
||||
$targetPath = Join-Path $saasAppPath '.env'
|
||||
|
||||
if (-not (Test-Path $sourcePath)) {
|
||||
throw "Quelle nicht gefunden: $sourcePath"
|
||||
}
|
||||
|
||||
if ((Test-Path $targetPath) -and -not $Force) {
|
||||
throw ".env existiert bereits. Nutze -Force, wenn sie neu erzeugt werden soll."
|
||||
}
|
||||
|
||||
Copy-Item -Path $sourcePath -Destination $targetPath -Force
|
||||
|
||||
Write-Host "Lokale .env wurde angelegt: $targetPath"
|
||||
Write-Host 'Passe jetzt DB-, Mail-, Tenancy- und OIDC-Werte an.'
|
||||
Reference in New Issue
Block a user