6 KiB
Effigenix ERP – Agent Guide
Stack
Java 21, Spring Boot 3.2, PostgreSQL, Liquibase, JWT (JJWT), Maven
Architektur
DDD + Clean Architecture. Einweg-Abhängigkeit: domain → application → infrastructure.
de.effigenix.
├── domain.{bc}/ # Reine Geschäftslogik, KEINE Framework-Deps
├── application.{bc}/ # Use Cases, Commands, DTOs
├── infrastructure.{bc}/ # JPA, REST, Security, Audit
└── shared/ # Shared Kernel (Result<E,T>, AuthorizationPort, Action)
Bounded Contexts: usermanagement (implementiert), production, quality, inventory, procurement, sales, labeling, filiales (Platzhalter).
Namenskonventionen
| Artefakt | Muster | Beispiel |
|---|---|---|
| Use Case | {Verb}{Noun} |
CreateUser, AuthenticateUser |
| Command | {Verb}{Noun}Command |
CreateUserCommand |
| Domain Entity | {Noun} |
User, Role |
| Value Object | {Noun} |
UserId, PasswordHash, RoleName |
| Create-Draft | {Noun}Draft |
SupplierDraft |
| Update-Draft | {Noun}UpdateDraft |
SupplierUpdateDraft |
| Domain Error | {Noun}Error (sealed interface) |
UserError.UsernameAlreadyExists |
| JPA Entity | {Noun}Entity |
UserEntity |
| Mapper | {Noun}Mapper |
UserMapper (Domain↔JPA) |
| Repository (Domain) | {Noun}Repository |
UserRepository (Interface) |
| Repository (Impl) | Jpa{Noun}Repository |
JpaUserRepository |
| Controller | {Noun}Controller |
UserController |
| Web DTO | {Verb}{Noun}Request |
CreateUserRequest |
| Action Enum | {Noun}Action implements Action |
ProductionAction |
EntityDraft-Pattern
Für Aggregate mit komplexer VO-Konstruktion (Address, ContactInfo, PaymentTerms u.ä.) gilt: Der Application Layer baut keine VOs – er erzeugt einen Draft-Record mit rohen Strings und übergibt ihn ans Aggregate. Das Aggregate orchestriert Validierung und VO-Konstruktion intern.
// Application Layer – nur Daten weitergeben, kein VO-Wissen
var draft = new SupplierDraft(cmd.name(), cmd.phone(), ...);
switch (Supplier.create(draft)) { ... }
// Domain Layer – validiert intern, gibt Result zurück
public static Result<SupplierError, Supplier> create(SupplierDraft draft) { ... }
public Result<SupplierError, Void> update(SupplierUpdateDraft draft) { ... }
Regeln:
- Pflichtfelder: non-null im Draft-Record
- Optionale VOs (z.B. Address, PaymentTerms):
null-Felder → VO wird nicht konstruiert - Primitive
int→Integerwenn das Feld optional/nullable sein muss - Einzelne
updateXxx(VO)-Methoden entfallen → ersetzt durch einupdate({Noun}UpdateDraft) - Uniqueness-Check bleibt im Application Layer (Repository-Concern), nach
Aggregate.create() - Invarianten-Kommentar im Aggregat aktuell halten
Error Handling
Funktional via Result<E, T> (shared.common.Result). Domain-Fehler sind sealed interfaces mit Records. Keine Exceptions im Domain/Application Layer.
Commits
Conventional Commits. Kein Co-Authored-By Header – niemals.
DDD Skill
Für neue Bounded Contexts: /ddd-implement Skill verwenden. Dokumentation unter .claude/skills/ddd-implement/SKILL.md.
GitHub CLI (gh)
WICHTIG:
gh-Befehle NIEMALS ohne ausdrückliche Zustimmung des Users ausführen! Issues anlegen, PRs erstellen, Labels/Milestones verwalten – all das verändert den Remote-Zustand und ist schwer rückgängig zu machen. IMMER vorher fragen.
gh ist nicht direkt installiert, sondern wird über Nix bereitgestellt:
# Alle gh-Befehle mit diesem Prefix ausführen:
nix shell nixpkgs#gh -c gh <command>
# Auth prüfen
nix shell nixpkgs#gh -c gh auth status
# Repo-Info
nix shell nixpkgs#gh -c gh repo view --json name,owner
Milestones (via API, kein gh milestone-Subcommand)
# Auflisten
nix shell nixpkgs#gh -c gh api repos/{owner}/{repo}/milestones
# Erstellen
nix shell nixpkgs#gh -c gh api repos/{owner}/{repo}/milestones \
-f title="Name" -f state=open -f description="Beschreibung"
Labels
# Auflisten
nix shell nixpkgs#gh -c gh label list --limit 100
# Erstellen
nix shell nixpkgs#gh -c gh label create "label-name" --color "0E8A16" --description "Beschreibung"
Issues
# Erstellen (Body via HEREDOC für Multiline)
nix shell nixpkgs#gh -c gh issue create \
--title "Titel" \
--milestone "Milestone Name" \
--label "label1,label2" \
--body "$(cat <<'EOF'
Issue-Body mit Markdown...
EOF
)"
# Auflisten (nach Milestone, State, Label)
nix shell nixpkgs#gh -c gh issue list --milestone "Name" --limit 50
nix shell nixpkgs#gh -c gh issue list --milestone "Name" --state open --json number,title,labels \
--jq '.[] | "\(.number)\t\(.title)"' | sort -n
# Details anzeigen
nix shell nixpkgs#gh -c gh issue view 3 --json title,body,projectItems
# Kommentieren
nix shell nixpkgs#gh -c gh issue comment 3 --body "Kommentar-Text"
# Schließen (mit optionalem Kommentar)
nix shell nixpkgs#gh -c gh issue close 3 --comment "$(cat <<'EOF'
Abschluss-Kommentar mit Markdown...
EOF
)"
GitHub Projects (Projektstatus ändern)
# Projekt-IDs:
# Project: PVT_kwHOAvvITc4BPlrt
# Status-Field: PVTSSF_lAHOAvvITc4BPlrtzg99FPE
# Status-Optionen:
# Todo: f75ad846
# In Progress: 47fc9ee4
# Done: 98236657
# Test: d755b468
# Completed: b7405d2f
# Item-ID eines Issues im Projekt ermitteln (z.B. Issue #3)
nix shell nixpkgs#gh -c gh api graphql -f query='{ node(id: "PVT_kwHOAvvITc4BPlrt") { ... on ProjectV2 { items(first: 50) { nodes { id content { ... on Issue { number title } } } } } } }' \
--jq '.data.node.items.nodes[] | select(.content.number == 3) | .id'
# Status ändern (Item-ID einsetzen)
nix shell nixpkgs#gh -c gh project item-edit \
--project-id PVT_kwHOAvvITc4BPlrt \
--id <ITEM_ID> \
--field-id PVTSSF_lAHOAvvITc4BPlrtzg99FPE \
--single-select-option-id 47fc9ee4 \
--format json
Doku
docs/QUICK_START.md– Lokale Entwicklung, Docker, Seed-Datendocs/USER_MANAGEMENT.md– Referenz-BC mit AuthorizationPort, JWT, AuditTODO.md– Offene Aufgaben und Waves