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:
2026-03-21 17:32:57 +01:00
parent c4a3f9544a
commit f298802c38
77 changed files with 6381 additions and 4599 deletions
+44
View File
@@ -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.
+44 -25
View File
@@ -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.
+87
View File
@@ -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.
+48
View File
@@ -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.
+25
View File
@@ -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});
+261 -261
View File
@@ -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
+39 -39
View File
@@ -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));
}
?>
+217 -217
View File
@@ -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"; ?>
+151 -151
View File
@@ -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>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>';
}
$html .= '<tr><td>&nbsp;</td><td>&nbsp;</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>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>';
}
$html .= '<tr><td>&nbsp;</td><td>&nbsp;</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>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>';
}
$html .= '<tr><td>&nbsp;</td><td>&nbsp;</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>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>';
}
$html .= '<tr><td>&nbsp;</td><td>&nbsp;</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');
?>
+89 -89
View File
@@ -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

+61 -61
View File
@@ -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">&copy; 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">&copy; 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>
+68 -68
View File
@@ -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;
}
}
?>
+165 -165
View File
@@ -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;
}
?>
+37 -37
View File
@@ -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">
+94 -94
View File
@@ -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
View File
@@ -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);
?>
+147 -147
View File
@@ -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"; ?>
+49 -49
View File
@@ -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";
?>
+141 -141
View File
@@ -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"; ?>
+121 -121
View File
@@ -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"; ?>
+3 -3
View File
@@ -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";
?>
+341 -341
View File
@@ -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): ?>
&nbsp;|&nbsp; 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): ?>
&nbsp;|&nbsp; 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
View File
@@ -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.
+17 -1
View File
@@ -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 -4
View File
@@ -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'),
];
+6
View File
@@ -0,0 +1,6 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
</IfModule>
+9
View File
@@ -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/`.
+234
View File
@@ -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
+51 -20
View File
@@ -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
+364 -9
View File
@@ -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
+62 -3
View File
@@ -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
+48
View File
@@ -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.'
+23
View File
@@ -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.'