Steuerkram/CLAUDE.md

4.9 KiB
Raw Blame History

Steuerkram – Entwicklungsregeln

Tech Stack

PHP 8.3+, MySQL, PSR-4 (Namespace Steuerkram\), Composer, kein Framework. MVC: src/Controllers/, src/Models/, src/Services/, src/Views/.

Coding-Regeln

  • Kein var_dump, kein die() in Produktionscode.
  • Neue Libraries nur nach expliziter Rückfrage einbinden.
  • Bestehenden Code-Stil beibehalten (declare strict_types, 4 Spaces).
  • SQL ausschließlich über Database::fetchAll/fetchOne/execute() mit Prepared Statements.

Tests

Regel: Jedes neue Feature bekommt einen eigenen Test.

Tests liegen in tests/ und folgen dem Namensschema NN_FunktionsnameTest.php. Jede Testklasse erweitert TestCase und implementiert run().

docker compose exec -u www-data web php tests/run.php   # alle Tests ausführen
./scripts/run-tests.sh      # Tests + automatische Issue-Erstellung bei Fehlern
./scripts/run-tests.sh 42   # Tests; bei Fehlern Kommentar in Issue #42

Immer -u www-data: ohne die Option laufen die Tests als root und legen unterhalb von data/ Dateien an, die Apache/PHP später nicht mehr beschreiben kann – ein echter Beleg-Upload scheitert dann mit HTTP 500.

Neuen Test erstellen

  1. Datei tests/NN_MeinFeatureTest.php anlegen (NN = nächste freie Nummer)
  2. Klasse MeinFeatureTest extends TestCase
  3. protected string $testName = 'Test NN: Beschreibung';
  4. Methode public function run(): void mit Assertions implementieren
  5. Transaktions-Isolation ist automatisch (setUp/tearDown in TestCase)
  6. Dateien und Verzeichnisse immer über TestCase anlegen – der Rollback greift nur in der Datenbank, nicht im Dateisystem:
$pfad = $this->tempPath('.csv');                       // Pfad in /tmp, wird aufgeräumt
$dir  = $this->makeTempDir($basis . '/2026/BLG-...');  // Verzeichnis anlegen + aufräumen
$this->registerTempPath($schonVorhandenerPfad);        // nachträglich anmelden

Bleibt trotzdem etwas liegen, meldet tests/run.php das am Ende des Laufs.

Assertion-Methoden

$this->assert(bool, 'Beschreibung');
$this->assertEquals($erwartet, $ist, 'Beschreibung');
$this->assertGreaterThan($min, $wert, 'Beschreibung');
$this->assertNotEmpty($wert, 'Beschreibung');

E2E-Tests (Browser)

Die PHP-Tests erreichen Routing, Views und Formular-JavaScript nicht. Dafür gibt es Playwright-Tests in tests/e2e/, die im Container des e2e-runner laufen (auf dem Host wird nichts installiert). Details: tests/e2e/README.md.

docker compose exec web php scripts/e2e-user.php   # einmalig: Testnutzer anlegen
tests/e2e/run.sh                                   # alle E2E-Tests
docker compose exec web php scripts/e2e-cleanup.php --force   # Reste entfernen

Fehlt Docker, der Runner oder das Image, wird mit Exit 0 übersprungen.

Welche Ebene wofür: Rechen- und Model-Logik gehört in die PHP-Suite (schneller, isoliert). In tests/e2e/ gehört nur, was einen Browser braucht: Formularabläufe, Redirects, gerenderte Views, JavaScript-Umrechnungen, DOM-XSS.

Dokumentation aktuell halten

Datei Wann aktualisieren
Changes.md Bei jedem Feature, Bugfix oder strukturellen Änderung (nicht bei reinen Test- oder Doku-Commits)
README.md Wenn sich der Funktionsumfang oder der Tech Stack grundlegend ändert
docs/funktionen.md Wenn ein neues Feature hinzukommt oder ein bestehendes wesentlich geändert wird
docs/berechnungslogik.md Bei jeder Änderung an EuerCalculator.php oder UstvaCalculator.php (Zuordnungsregeln, neue Kennzahlen, geänderte Bedingungen)
docs/anlagevermögen.md Bei Änderungen am Anlagevermögens-Workflow oder den Asset-Modellen

Datenbankmigrationen

Schemaänderungen (neue Spalten, Tabellen, Kontenanpassungen) kommen ausschließlich als nummerierte Migrations-Datei in migrations/:

  • Schema: NNN_kurze_beschreibung.sql (NNN = nächste freie dreistellige Nummer, z.B. 011_...)
  • Migrationen werden nie manuell eingespielt – scripts/migrate.php erledigt das automatisch beim Container-Start
  • Jede Migration muss idempotent sein oder mit IF NOT EXISTS / ON DUPLICATE KEY abgesichert werden
# Nächste freie Nummer ermitteln:
ls migrations/ | tail -1

# Migration manuell testen (ohne Neustart):
docker compose exec web php scripts/migrate.php

Geplante Aufgaben (Cron)

Alle planmäßigen Aufgaben (z.B. Ideenagent, Automatisierungen) laufen lokal über die System-Crontab des Nutzers. Für außerplanmäßige Ausführung das jeweilige Skript direkt aufrufen:

crontab -l                                              # alle geplanten Jobs anzeigen
/home/fds/projects/Steuerkram/.claude/ideenagent-run.sh # Ideenagent manuell starten
/home/fds/projects/Steuerkram/.claude/automate-run.sh   # Automatisierung manuell starten

Remote Triggers (claude.ai) oder Claude Code Cron-Jobs werden nicht verwendet.

Commits

Fix #NR: Kurze Beschreibung der Änderung

Keine Co-Authored-By-Zeile. Keine langen Commit-Messages.