Files
kaffeekasse-saas/scripts/init-mysql-dev.php
T
clemensandClaude Opus 4.8 4acd4a2d40 Legacy-Abbau Schritt 3+4: kl_*-Tabellen und legacy_*-Spalten entfernt
Abschluss des Legacy-Abbaus. Die Migration in participants/ledger_entries war
laut Dev-DB vollstaendig (keine legacy_mitarbeiter_id, kein legacy_table), die
kl_*-Tabellen enthielten nur noch Golden-Master-Testfixtures. Da kein echter
Altbestand mehr importiert werden muss (Prod entsteht aus der jetzigen Dev-DB),
kommt die Altwelt komplett raus.

Laufzeit-Code (Schritt 3a):
- ledger.php: Option legacy_mitarbeiter_ids, die Spalten aus allen SELECTs und
  Rueckgaben, ledger_fetch_participant_summary_by_legacy_id sowie das Loeschen
  gespiegelter Legacy-Zeilen in ledger_void_entry/ledger_void_own_self_entry
  entfernt
- imports.php, paypal-inbox.php: legacy_mitarbeiter_id aus Ergebnis und
  Typannotationen entfernt
- ledger-preview.php: Spalte "Legacy" entfernt

Skripte (Schritt 3b/3c):
- die acht reinen Legacy-/Golden-Master-Skripte entfernt (backfill-*,
  seed-golden-master, golden-master-data, check-golden-master, check-m4-*,
  check-m3-saas-basis)
- init-mysql-dev.php legt jetzt einen SaaS-Mandanten mit Owner-Login,
  Teilnehmer, Journalbuchungen und Hinweis an statt kl_*-Zeilen

Schema (Schritt 4, Migration 0024):
- participants.legacy_mitarbeiter_id + uq_participants_tenant_legacy
- ledger_entries.legacy_table/legacy_id + uq_ledger_entries_tenant_legacy
- DROP der Tabellen kl_Einzahlungen, kl_Kaffeeverbrauch, kl_hinweise,
  kl_config, kl_Mitarbeiter

Verifikation unveraendert gruen: http-smoke 33/0, role-matrix 55/0,
tenant-isolation 11/1 (Altfehler), m3-auth/tenant-resolution/billing gruen.
check-m3-settings-flow 7/6 ist vorbestehend (schon bei 3e24910 rot, mit
spaeteren Settings-Feldern nicht synchron) und unabhaengig von diesem Abbau.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 08:31:08 +02:00

82 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
/**
* Richtet eine frische MySQL-Entwicklungsdatenbank ein: Schema/Migrationen
* anwenden und einen ersten SaaS-Mandanten samt Owner-Login, Teilnehmer,
* ein paar Journalbuchungen und einem Hinweis anlegen - alles idempotent.
*
* Der anzulegende Owner kommt aus DEV_AUTH_EMAIL (Anzeigename optional aus
* DEV_AUTH_NAME). Nach dem Lauf kann man sich damit ueber login.php anmelden.
*/
require __DIR__ . '/dev-db.php';
$email = getenv('DEV_AUTH_EMAIL');
if ($email === false || trim($email) === '') {
fwrite(STDERR, "Missing environment variable: DEV_AUTH_EMAIL\n");
exit(1);
}
$pdo = dev_pdo();
dev_apply_schema($pdo);
$email = strtolower(trim((string)$email));
$name = trim((string)(getenv('DEV_AUTH_NAME') ?: 'Test Admin'));
$password = trim((string)(getenv('DEV_AUTH_PASSWORD') ?: 'DevPasswort123!'));
$slug = trim((string)(getenv('DEV_TENANT_SLUG') ?: 'dev'));
// Mandant.
$tenantId = (int)($pdo->query('SELECT id FROM tenants WHERE slug = ' . $pdo->quote($slug))->fetchColumn() ?: 0);
if ($tenantId === 0) {
$pdo->prepare('INSERT INTO tenants (slug, name, status) VALUES (?, ?, ?)')
->execute([$slug, 'Dev-Mandant', 'active']);
$tenantId = (int)$pdo->lastInsertId();
}
if ((int)$pdo->query("SELECT COUNT(*) FROM tenant_settings WHERE tenant_id = {$tenantId}")->fetchColumn() === 0) {
$pdo->prepare('INSERT INTO tenant_settings (tenant_id) VALUES (?)')->execute([$tenantId]);
}
// Owner-Login.
$userId = (int)($pdo->query('SELECT id FROM users WHERE email_norm = ' . $pdo->quote($email))->fetchColumn() ?: 0);
if ($userId === 0) {
$pdo->prepare(
'INSERT INTO users (email, email_norm, display_name, password_hash, status, email_verified_at)
VALUES (?, ?, ?, ?, ?, NOW())'
)->execute([$email, $email, $name, password_hash($password, PASSWORD_DEFAULT), 'active']);
$userId = (int)$pdo->lastInsertId();
}
if ((int)$pdo->query("SELECT COUNT(*) FROM tenant_memberships WHERE tenant_id = {$tenantId} AND user_id = {$userId}")->fetchColumn() === 0) {
$pdo->prepare('INSERT INTO tenant_memberships (tenant_id, user_id, role, status, joined_at) VALUES (?, ?, ?, ?, NOW())')
->execute([$tenantId, $userId, 'owner', 'active']);
}
// Teilnehmer des Owners.
$participantId = (int)($pdo->query("SELECT id FROM participants WHERE tenant_id = {$tenantId} AND user_id = {$userId}")->fetchColumn() ?: 0);
if ($participantId === 0) {
$pdo->prepare('INSERT INTO participants (tenant_id, user_id, display_name, email, email_norm, active) VALUES (?, ?, ?, ?, ?, 1)')
->execute([$tenantId, $userId, $name, $email, $email]);
$participantId = (int)$pdo->lastInsertId();
}
// Ein paar Buchungen, damit die Seiten nicht komplett leer sind.
if ((int)$pdo->query("SELECT COUNT(*) FROM ledger_entries WHERE tenant_id = {$tenantId} AND participant_id = {$participantId}")->fetchColumn() === 0) {
$pdo->prepare(
"INSERT INTO ledger_entries (tenant_id, participant_id, type, amount_cents, booked_at, source) VALUES (?, ?, 'payment', ?, NOW(), 'manual_bulk')"
)->execute([$tenantId, $participantId, 1000]);
$pdo->prepare(
"INSERT INTO ledger_entries (tenant_id, participant_id, type, amount_cents, marks_count, unit_price_cents, booked_at, source) VALUES (?, ?, 'consumption', ?, ?, 20, NOW(), 'manual_bulk')"
)->execute([$tenantId, $participantId, -60, 3]);
}
// Hinweis.
if ((int)$pdo->query("SELECT COUNT(*) FROM notices WHERE tenant_id = {$tenantId} AND deleted_at IS NULL")->fetchColumn() === 0) {
$pdo->prepare(
'INSERT INTO notices (tenant_id, message, valid_from, valid_until, created_by_user_id)
VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY), ?)'
)->execute([$tenantId, 'Dev-Hinweis: MySQL-Testumgebung aktiv.', $userId]);
}
echo "MySQL dev schema is ready. Login: {$email} / {$password} (Mandant '{$slug}').\n";