Zum Hauptinhalt springen

Contributing & Architektur

Dieser Leitfaden richtet sich an Entwickler, die zu Gäld beitragen oder dessen Interna verstehen möchten.

Entwicklungsumgebung

Docker (empfohlen)

git clone https://github.com/Scanix/Gaeld.git
cd Gaeld/api
cp .env.example .env
docker compose up -d
docker compose exec laravel.test php artisan gaeld:install --demo

Die App ist unter http://localhost:8080 verfügbar. Das Flag --demo erstellt Beispieldaten (Rechnungen, Ausgaben, Kontakte) für die Entwicklung.

Von Docker Compose gestartete Dienste:

DienstContainerPort
Laravel (PHP + Nginx)laravel.test8080
PostgreSQL 16pgsql5432
Redis 7redis6379
MeiliSearchmeilisearch7700
Mailpit (Dev-E-Mail)mailpit8025 (Dashboard), 1025 (SMTP)

Befehle ausführen

Alle PHP-Befehle sollten innerhalb des Docker-Containers ausgeführt werden:

# Artisan-Befehle
docker compose exec laravel.test php artisan <command>

# Composer
docker compose exec laravel.test composer <command>

# PHPStan
docker compose exec laravel.test ./vendor/bin/phpstan analyse

# Tests
docker compose exec laravel.test php artisan test

Frontend

Das API-Projekt verwendet Inertia.js + Vue 3 für seine Admin-Oberfläche:

pnpm install
pnpm dev # Vite Dev Server mit HMR
pnpm build # Produktions-Build

Architekturübersicht

Tech Stack

SchichtTechnologie
BackendLaravel 12, PHP 8.4
FrontendVue 3 + Inertia.js
DatenbankPostgreSQL 16
Cache/Queue/SessionRedis 7
SucheMeiliSearch (Fallback: Datenbank)
WährungsberechnungBCMath (Strings, niemals Floats)

Domain-Driven Struktur

Die Codebase ist in Domains unter app/Domains/ organisiert, die jeweils eine Geschäftsfähigkeit kapseln:

app/Domains/
├── Accounting/ # Kontenplan, Hauptbuch, Buchungssätze, MWST, Budget
├── Api/ # REST-API-Controller, Ressourcen, Webhook-System
├── Assets/ # Anlagenvermögen und Abschreibungen
├── Banking/ # Bankkonten, CAMT-Import, Abstimmung
├── Contacts/ # Kunden, Lieferanten, Kontaktpersonen
├── Expenses/ # Ausgabenerfassung, Kategorien, Genehmigungsworkflow
├── Invoicing/ # Rechnungen, Gutschriften, Dauerrechnungen, Zahlungen
├── Migration/ # Datenimport aus externer Buchhaltungssoftware
├── Organizations/ # Multi-Tenancy, Org-Einstellungen, Onboarding
├── Payroll/ # Mitarbeiter, Gehaltsabrechnungen, Schweizer Abzüge
├── Reporting/ # Finanzberichte, Exporte
└── Users/ # Authentifizierung, Profile, 2FA, Passkeys

Jede Domain enthält typischerweise:

Domains/Invoicing/
├── Controllers/ # HTTP-Controller
├── Models/ # Eloquent-Modelle
├── Services/ # Geschäftslogik
├── Queries/ # Query Builder (Filterung, Sortierung, Suche)
├── Requests/ # Form-Request-Validierung
├── Resources/ # Inertia/API-Ressourcentransformer
├── Events/ # Domain Events
├── Enums/ # Status-Enums, Typen
└── Policies/ # Autorisierungsrichtlinien

Multi-Tenancy

Gäld verwendet ein Shared-Database-Modell mit zeilenbasierter Isolation:

  • Jede Datentabelle hat einen organization_id-Fremdschlüssel
  • Das Trait BelongsToOrganization fügt einen globalen Scope hinzu, der Abfragen automatisch filtert und die Org bei der Erstellung automatisch zuweist
  • Der Service CurrentOrganization hält die aktive Org für die aktuelle Anfrage
  • Die Middleware EnsureHasOrganization löst die Org aus der Session (Web) oder dem Token (API) auf

Wichtige Traits

TraitZweck
BelongsToOrganizationScopt automatisch alle Abfragen auf die aktuelle Org, weist organization_id bei Erstellung zu
AuditableProtokolliert Modelländerungen im Aktivitätsprotokoll
HasUuidsVerwendet UUIDs als Primärschlüssel

Feature Flags

Funktionen werden über FEATURE_*-Umgebungsvariablen gesteuert:

FlagStandardBeschreibung
FEATURE_BANK_SYNCfalseBankverbindung und automatische Synchronisation
FEATURE_AUTO_RECONCILIATIONfalseAutomatische Zahlungszuordnung
FEATURE_AUTOMATIONfalseRegel-Engine und Automatisierung
FEATURE_MULTI_CURRENCYfalseMulti-Währungs-Unterstützung
FEATURE_API_ACCESSfalseREST-API-Zugang
FEATURE_RULE_ENGINEfalseGeschäftsregel-Engine
FEATURE_SAASfalseSaaS-Funktionen (privates Plugin)

Plugin-System

Plugins erweitern Gäld ohne den Kerncode zu verändern. Siehe den Plugin-Entwicklungsleitfaden für Details.

Testing

Gäld hat drei Test-Suiten:

# Alle Tests ausführen
docker compose exec laravel.test php artisan test

# Eine bestimmte Suite ausführen
docker compose exec laravel.test php artisan test --testsuite=Feature
docker compose exec laravel.test php artisan test --testsuite=Unit
docker compose exec laravel.test php artisan test --testsuite=Security

# Eine bestimmte Testdatei ausführen
docker compose exec laravel.test php artisan test --filter=InvoiceTest
SuiteOrtZweck
Featuretests/Feature/Integrationstests — HTTP-Anfragen, Datenbank, Full Stack
Unittests/Unit/Isolierte Unit-Tests — Services, Modelle, Hilfsfunktionen
Securitytests/Security/Sicherheitstests — Auth, Berechtigungen, CSRF, Injection

Test-Konventionen

  • Verwenden Sie das Attribut #[DataProvider('name')] (nicht die Annotation @dataProvider)
  • Web-Formularvalidierung gibt 302-Weiterleitungen zurück — prüfen Sie mit assertSessionHasErrors()
  • Alle Tests verwenden eine In-Memory-Testdatenbank (konfiguriert in phpunit.xml)
  • Test-Hilfsprogramme und gemeinsame Traits befinden sich in tests/Traits/
  • Fixture-Dateien (Beispiel-CAMT-XMLs, CSVs) befinden sich in tests/fixtures/

Statische Analyse

docker compose exec laravel.test ./vendor/bin/phpstan analyse

PHPStan ist auf Level 5 konfiguriert mit einer Baseline in phpstan-baseline.neon.

Code-Stil

docker compose exec laravel.test ./vendor/bin/pint

Verwendet Laravel Pint zur Codeformatierung (basierend auf PSR-12).

Beitrags-Workflow

  1. Forken Sie das Repository und erstellen Sie einen Branch von main
  2. Richten Sie die Entwicklungsumgebung wie oben beschrieben ein
  3. Nehmen Sie Ihre Änderungen vor — halten Sie jeden PR auf ein einzelnes Thema fokussiert
  4. Fügen Sie Tests hinzu für jedes neue Verhalten
  5. Führen Sie Checks aus vor dem Pushen:
    docker compose exec laravel.test php artisan test
    docker compose exec laravel.test ./vendor/bin/phpstan analyse
    docker compose exec laravel.test ./vendor/bin/pint --test
  6. Öffnen Sie einen Pull Request mit einer klaren Beschreibung des Was und Warum

Für grössere Änderungen eröffnen Sie bitte zuerst ein Issue, um den Ansatz zu diskutieren.

Commit-Nachrichten

Verwenden Sie klare, beschreibende Commit-Nachrichten. Stellen Sie den Domänennamen voran, wenn relevant:

invoicing: add recurring invoice frequency validation
banking: fix CAMT.053 duplicate detection
docs: update API reference with webhook events

Issues melden

Eröffnen Sie ein Issue auf GitHub mit:

  • Einem klaren Titel und Beschreibung
  • Schritten zur Reproduktion (bei einem Bug)
  • Erwartetem vs. tatsächlichem Verhalten
  • Ihrer Umgebung (PHP-Version, OS, Browser)