added claude planning
This commit is contained in:
parent
9491ff26d8
commit
b9dd2b2af0
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(dotnet --version:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
162
CLAUDE.md
162
CLAUDE.md
|
|
@ -2,87 +2,119 @@
|
|||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Build & Test Commands
|
||||
## Project Overview
|
||||
|
||||
Blazor Server app (.NET 9.0) with Clean Architecture: Domain, Application, Infrastructure, Web layers. Uses ASP.NET Core Identity with dual DbContext pattern (AppDbContext for domain, AppIdentityDbContext for auth), MudBlazor UI, and Fluxor state management.
|
||||
|
||||
The name for the App is KOOGLE. Koogle is an app for club management.
|
||||
|
||||
### Functional
|
||||
- Club management
|
||||
- Management of match days and games
|
||||
- Registration of participants (members and guests)
|
||||
- Automatic or rule-based cost allocation
|
||||
- Evaluation per person/day/game
|
||||
- User-related actions (CurrentUserService)
|
||||
|
||||
### Technical
|
||||
- ASP.NET Core backend
|
||||
- EF Core
|
||||
- Multi-client capable (club as scope)
|
||||
- Future web or mobile app realistic
|
||||
|
||||
### Target group
|
||||
- primarily Bowling clubs (Kegelclub / Kegelvereine) - In German "Kegeln" is a bit different to bowling
|
||||
- maybe in future also for darts, soccer betting pools, Leisure groups, Sport clubs, etc.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
**Phase 1 MVP:** See [docs/IMPLEMENTATION_PLAN.md](./docs/IMPLEMENTATION_PLAN.md)
|
||||
- 23 granular phases (A1-F3)
|
||||
- Foundation → Clubs → Users → Persons → Days → Dashboard
|
||||
- Track progress via checkboxes in plan
|
||||
- ~75 files total
|
||||
|
||||
## Architecture
|
||||
|
||||
**Clean Architecture Layers:**
|
||||
- `Koogle.Domain`: Entities, Enums, Interfaces (no dependencies)
|
||||
- `Koogle.Application`: DTOs, Services, Mapping (depends on Domain, Infrastructure)
|
||||
- `Koogle.Infrastructure`: DbContexts, Repositories, Identity, Security (depends on Domain)
|
||||
- `Koogle.Web`: Blazor components, Controllers, Fluxor Store (depends on Application)
|
||||
|
||||
- `KoogleApp`: Is a former approach, and not part of the project. We just use it to copy stuff into the actual project.
|
||||
|
||||
**Dual DbContext Pattern:**
|
||||
- `AppDbContext`: Domain entities → `app` schema → `__EFMigrationsHistory_App`
|
||||
- `AppIdentityDbContext`: ASP.NET Identity → `auth` schema → `__EFMigrationsHistory_Auth`
|
||||
|
||||
**Key Technologies:**
|
||||
- Fluxor (Redux pattern): Store in `src/Koogle.Web/Store/`, Actions/Reducers/Effects pattern
|
||||
- ASP.NET Identity: Custom `ApplicationUser`, `ApplicationRole`, `CustomClaimsPrincipalFactory`
|
||||
- Authorization: Club-based roles (Viewer/Editor/Admin) via `ClubRoleRequirement`/`ClubRoleHandler`
|
||||
- AutoMapper (Application layer), MudBlazor UI components
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Build & Run
|
||||
```bash
|
||||
# Build solution
|
||||
dotnet build KoogleApp.sln
|
||||
|
||||
# Run the application
|
||||
dotnet run --project KoogleApp/KoogleApp.csproj
|
||||
|
||||
# Run all tests
|
||||
dotnet test
|
||||
|
||||
# Run specific test class
|
||||
dotnet test --filter "FullyQualifiedName~Koogle.Tests.ReducerTests.ThrowPanelStateTests"
|
||||
|
||||
# Run specific test method
|
||||
dotnet test --filter "FullyQualifiedName~Koogle.Tests.GameTraining.GameTrainingServiceTest.ServiceWorksCorrectly"
|
||||
dotnet build
|
||||
dotnet run --project src/Koogle.Web
|
||||
```
|
||||
|
||||
## Entity Framework Migrations
|
||||
### Database Migrations
|
||||
|
||||
**AppDbContext (domain data):**
|
||||
```bash
|
||||
# Create migration
|
||||
dotnet ef migrations add <MigrationName> --project ./KoogleApp/KoogleApp.csproj
|
||||
dotnet ef migrations add [Name] --project src/Koogle.Infrastructure --startup-project src/Koogle.Web --context AppDbContext --output-dir Data/Migrations
|
||||
|
||||
# Update database (Development)
|
||||
dotnet ef --startup-project ./KoogleApp/KoogleApp.csproj --project ./KoogleApp/KoogleApp.csproj database update -- Development
|
||||
# Apply migration
|
||||
dotnet ef database update -p src/Koogle.Infrastructure -s src/Koogle.Web --context AppDbContext
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
**AppIdentityDbContext (auth data):**
|
||||
```bash
|
||||
# Create migration
|
||||
dotnet ef migrations add [Name] --project src/Koogle.Infrastructure --startup-project src/Koogle.Web --context AppIdentityDbContext --output-dir Identity/Migrations
|
||||
|
||||
This is a **Blazor Server** application (.NET 9) for tracking a 9-pin bowling (Kegeln) game. It uses:
|
||||
- **Fluxor** for state management (Redux pattern)
|
||||
- **MudBlazor** for UI components
|
||||
- **SignalR** for real-time synchronization between clients
|
||||
- **Entity Framework Core** with SQL Server
|
||||
# Apply migration
|
||||
dotnet ef database update -p src/Koogle.Infrastructure -s src/Koogle.Web --context AppIdentityDbContext
|
||||
```
|
||||
|
||||
### Fluxor Store Structure (`Store/`)
|
||||
**Update EF Tools:**
|
||||
```bash
|
||||
dotnet tool update --global dotnet-ef --version 9.0.11
|
||||
```
|
||||
|
||||
The state is organized into feature slices following the Redux pattern:
|
||||
- **`Store/Game/`** - Core game state management
|
||||
- `ThrowPanel/` - Pin states (9 pins), throw counter, throw mode (Reposition/Decrease)
|
||||
- `Participants/` - Active players and turn order
|
||||
- `Setup/` - Game configuration state
|
||||
- `UndoRedo/` - History management for game actions
|
||||
- `Menus/` - Game-specific menu actions
|
||||
- `ThrowTimer/` - Timer state for throws
|
||||
- **`Store/Player/`** - Player management (CRUD)
|
||||
- **`Store/DayFeature/`** - Day/session management
|
||||
- **`Store/ModelFeature/`** - Shared model state
|
||||
### Testing
|
||||
```bash
|
||||
dotnet test test/Koogle.Tests
|
||||
```
|
||||
Test framework: xUnit with FluentAssertions, Moq
|
||||
|
||||
Each feature contains: `State.cs`, `Actions.cs`, `Reducers.cs`, `Effects.cs`, `Selectors.cs`
|
||||
## Development Notes
|
||||
|
||||
### Game Plugin System (`Games/`)
|
||||
**DependencyInjection:**
|
||||
- Each layer has `DependencyInjection.cs` registering services via extension methods
|
||||
- Call order in `Program.cs`: AddInfrastructure → AddApplication → AddFluxor
|
||||
|
||||
Games are implemented as plugins via `IKnownGame` interface:
|
||||
- `IKnownGame` - Defines game metadata and component types
|
||||
- `IGameService` - Handles game logic (throws, player progression)
|
||||
- `IGameSetupModel` / `IGameModel` / `IGameState` - Data contracts with JSON serialization support
|
||||
**Authentication Flow:**
|
||||
- Cookie-based auth (`/login` path)
|
||||
- `CurrentUserService` (ICurrentUserService) provides user context
|
||||
- `BootstrapSeeder` seeds super-admin, `IdentityRoleSeeder` seeds roles
|
||||
- Blazor: `AuthStateInitializer.razor` syncs auth state, Fluxor `AuthState` for client state
|
||||
|
||||
Current implementations:
|
||||
- `Games/Training/` - Training mode
|
||||
- `Games/Shit/` - "Shit" game variant
|
||||
**Authorization:**
|
||||
- Custom club-based policies: `ClubViewer`, `ClubEditor`, `ClubAdmin`
|
||||
- `ICurrentClubContext` provides club context for authorization decisions
|
||||
- `ClubRoleHandler` evaluates requirements based on user's club membership
|
||||
|
||||
To add a new game:
|
||||
1. Create folder in `Games/` with `IKnownGame` implementation
|
||||
2. Create setup component (Razor), board component, and `IGameService` implementation
|
||||
3. Add JSON type discriminator to `IGameState` and `IGameSetupModel` interfaces
|
||||
**Blazor Components:**
|
||||
- Interactive server mode
|
||||
- Layout: `MainLayout.razor`, `NavMenu.razor`
|
||||
- Auth components: `AuthTest.razor`, `LogoutButton.razor`, `Account/Login.razor`
|
||||
|
||||
### Key Models
|
||||
|
||||
- `ThrowPanelState` - Contains 9 pin states (`PinStatus`: Standing/Fallen/Disabled), throw mode, throw counter
|
||||
- `GameProgress` - Tracks state transitions during a throw (before/after states)
|
||||
- `ParticipantsState` - Player order and turn tracking
|
||||
|
||||
### Real-time Sync
|
||||
|
||||
`SharedModelHub` (SignalR) broadcasts state changes between connected clients. `HubConnectionService` manages client-side connections.
|
||||
|
||||
### Services Registration
|
||||
|
||||
`Services/ServiceExtension.cs` contains DI registration:
|
||||
- `AddDbServices()` - Database and Identity
|
||||
- `AddAppServices()` - Fluxor, repositories, game services (auto-discovered via reflection)
|
||||
**Connection String:**
|
||||
- Key: `AppDb` in `appsettings.json`
|
||||
- Both contexts share same connection, different schemas/migration tables
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{63E5B7FE-38C2-47E8-9CF8-AB846B5B4281}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
docs\build.md = docs\build.md
|
||||
CLAUDE.md = CLAUDE.md
|
||||
todos.md = todos.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
|
|
|||
|
|
@ -0,0 +1,710 @@
|
|||
# Koogle App - Analyse & Vorschlag für Bereiche und Pages
|
||||
|
||||
## Zweck der Anwendung (abgeleitet aus Datenmodell)
|
||||
|
||||
**Koogle** ist eine Vereinsverwaltung für Kegelvereine mit Schwerpunkt auf:
|
||||
|
||||
### Kernfunktionen
|
||||
1. **Vereinsverwaltung**: Multi-Mandanten-System, jeder Verein = eigener Scope
|
||||
2. **Mitglieder & Gäste**: Verwaltung von Personen mit Status (Member/Guest)
|
||||
3. **Spieltagsorganisation**: Planung und Durchführung von Kegeltagen (Days)
|
||||
- Status-Workflow: New → Started → Closed (oder Postponed)
|
||||
- Zuordnung von Teilnehmern pro Spieltag
|
||||
4. **Spielverwaltung**: Mehrere Games pro Day möglich
|
||||
- JSON-basierte Spielstände (GameData)
|
||||
- Teilnehmerzuordnung pro Game
|
||||
5. **Kostenmanagement**:
|
||||
- Vordefinierte Kosten/Strafen (Expenses) pro Verein
|
||||
- Automatische Trigger (z.B. Pudel, Pumpe, Aus, Kranz, etc.)
|
||||
- Variable/Fixe Preise, Inverse Kosten (alle außer einem zahlen)
|
||||
- One-Click Kosten für schnelle Erfassung
|
||||
6. **Abrechnung**:
|
||||
- Pro Person, pro Tag, pro Spiel
|
||||
- Berechnungsmethoden: None, Average, Maximum (für fehlende Personen)
|
||||
- Status: Open/Done für PersonExpenses
|
||||
7. **Benutzer & Berechtigungen**:
|
||||
- ASP.NET Identity mit Custom UserProfile
|
||||
- Rollen pro Verein: Viewer, Editor, Admin
|
||||
- SuperAdmin für vereinsübergreifende Verwaltung
|
||||
- Multi-Club Zugehörigkeit möglich
|
||||
|
||||
---
|
||||
|
||||
## Bestehende Implementierung
|
||||
|
||||
### Vollständig implementiert
|
||||
- ✅ Authentication/Authorization Framework
|
||||
- ✅ Login mit Vereinsauswahl
|
||||
- ✅ Fluxor State Management (AuthState)
|
||||
- ✅ Rollenbasierte Berechtigungen
|
||||
- ✅ MudBlazor UI Framework
|
||||
- ✅ Dual DbContext (Domain + Identity)
|
||||
- ✅ Clean Architecture Struktur
|
||||
- ✅ Seeders (SuperAdmin, Roles)
|
||||
|
||||
### Teilweise implementiert
|
||||
- ⚠️ DayService (vorhanden, aber auskommentiert)
|
||||
- ⚠️ Navigation (Skelett vorhanden, kaum Menüpunkte)
|
||||
|
||||
### Nicht implementiert
|
||||
- ❌ UI für Clubs, Days, Games, Persons, Expenses
|
||||
- ❌ Services für Person, Game, Expense
|
||||
- ❌ DTOs für die meisten Domain Entities
|
||||
- ❌ Fluxor States für Domain-Daten
|
||||
- ❌ Reporting/Export-Funktionalität
|
||||
|
||||
---
|
||||
|
||||
## Vorgeschlagene Bereiche & Pages
|
||||
|
||||
### 1. DASHBOARD-BEREICH (Startseite)
|
||||
**Route:** `/` oder `/dashboard`
|
||||
|
||||
**Zweck:** Übersicht über aktuelle Aktivitäten im ausgewählten Verein
|
||||
|
||||
**Pages:**
|
||||
- **Dashboard.razor**:
|
||||
- Nächste geplante Spieltage
|
||||
- Aktuelle offene Kosten
|
||||
- Quick-Actions (neuer Spieltag, neue Person)
|
||||
- Statistiken (Anzahl Mitglieder, Gäste, offene Abrechnungen)
|
||||
|
||||
---
|
||||
|
||||
### 2. SPIELTAG-BEREICH (Day Management)
|
||||
**Route:** `/days`
|
||||
|
||||
**Pages:**
|
||||
- **DayList.razor** (`/days`):
|
||||
- Tabelle: PostDate, Status, Teilnehmeranzahl
|
||||
- Filter: Jahr, Monat, Status
|
||||
- Actions: Neu, Bearbeiten, Löschen, Schließen
|
||||
|
||||
- **DayDetail.razor** (`/days/{id}`):
|
||||
- Spieltag-Info (Datum, Status)
|
||||
- Teilnehmerliste mit Anwesenheit
|
||||
- Games des Tages
|
||||
- PersonExpenses des Tages (Übersicht)
|
||||
- Actions: Teilnehmer hinzufügen, Spiel hinzufügen, Status ändern
|
||||
|
||||
- **DayCreate.razor** (`/days/new`):
|
||||
- Formular: Datum, Vorauswahl Teilnehmer aus Mitgliedern
|
||||
|
||||
- **DayEdit.razor** (`/days/{id}/edit`):
|
||||
- Datum ändern, Teilnehmer hinzufügen/entfernen
|
||||
|
||||
---
|
||||
|
||||
### 3. SPIEL-BEREICH (Game Management)
|
||||
**Route:** `/days/{dayId}/games`
|
||||
|
||||
**Pages:**
|
||||
- **GameList.razor** (`/days/{dayId}/games`):
|
||||
- Liste der Spiele eines Spieltags
|
||||
- Actions: Neues Spiel, Bearbeiten, Löschen
|
||||
|
||||
- **GameDetail.razor** (`/days/{dayId}/games/{gameId}`):
|
||||
- GameData anzeigen/bearbeiten (JSON-Editor oder strukturierte Eingabe)
|
||||
- Teilnehmer des Spiels
|
||||
- Kosten des Spiels (PersonExpenses mit GameId)
|
||||
- Trigger-Events erfassen (z.B. "Pudel" → Expense zuweisen)
|
||||
|
||||
- **GameCreate.razor** (`/days/{dayId}/games/new`):
|
||||
- Teilnehmer auswählen (aus DayPersons)
|
||||
- Optionale GameData-Initialisierung
|
||||
|
||||
---
|
||||
|
||||
### 4. KOSTEN-BEREICH (Expense Management)
|
||||
**Route:** `/expenses`
|
||||
|
||||
**Pages:**
|
||||
- **ExpenseList.razor** (`/expenses`):
|
||||
- Vordefinierte Expenses des Vereins
|
||||
- Spalten: Name, Preis, Typ, IsOneClick, IsInverse, IsVariable
|
||||
- Actions: Neu, Bearbeiten, Löschen
|
||||
|
||||
- **ExpenseCreate.razor** (`/expenses/new`):
|
||||
- Formular für neue Expense-Vorlage
|
||||
- Trigger-Zuordnung optional
|
||||
|
||||
- **PersonExpenseList.razor** (`/expenses/assigned`):
|
||||
- Alle zugewiesenen Kosten (PersonExpenses)
|
||||
- Filter: Person, Tag, Status (Open/Done), Datum
|
||||
- Bulk-Actions: Als bezahlt markieren, Löschen
|
||||
|
||||
- **ExpenseTriggerConfig.razor** (`/expenses/triggers`):
|
||||
- Trigger-Typen anzeigen
|
||||
- Zuordnung Trigger → Expense
|
||||
|
||||
---
|
||||
|
||||
### 5. PERSONEN-BEREICH (Person Management)
|
||||
**Route:** `/people`
|
||||
|
||||
**Pages:**
|
||||
- **PersonList.razor** (`/people`):
|
||||
- Tabelle: Name, Status (Member/Guest), Actions
|
||||
- Filter: Status
|
||||
- Actions: Neu, Bearbeiten, Löschen
|
||||
|
||||
- **PersonCreate.razor** (`/people/new`):
|
||||
- Name, Status
|
||||
|
||||
- **PersonDetail.razor** (`/people/{id}`):
|
||||
- Personen-Info
|
||||
- Teilnahme-Historie (DayPersons)
|
||||
- Kosten-Historie (PersonExpenses)
|
||||
- Statistiken (Gesamtkosten, Anzahl Teilnahmen)
|
||||
|
||||
---
|
||||
|
||||
### 6. AUSWERTUNGEN-BEREICH (Reports/Evaluations)
|
||||
**Route:** `/reports`
|
||||
|
||||
**Pages:**
|
||||
- **ReportOverview.razor** (`/reports`):
|
||||
- Auswahl: Pro Person, Pro Tag, Pro Spiel
|
||||
|
||||
- **PersonReport.razor** (`/reports/person/{id}`):
|
||||
- Alle Kosten einer Person
|
||||
- Summen pro Tag, pro Spiel
|
||||
- Zeitraum-Filter
|
||||
|
||||
- **DayReport.razor** (`/reports/day/{id}`):
|
||||
- Alle Kosten eines Spieltags
|
||||
- Aufschlüsselung pro Person
|
||||
- Export-Option (PDF, CSV)
|
||||
|
||||
- **PeriodReport.razor** (`/reports/period`):
|
||||
- Zeitraum wählen (von-bis)
|
||||
- Aggregierte Statistiken
|
||||
- Top-Spieler, teuerste Tage, etc.
|
||||
|
||||
---
|
||||
|
||||
### 7. STAMMDATEN-BEREICH (Master Data - Vereins-spezifisch)
|
||||
**Route:** `/masterdata`
|
||||
|
||||
**Pages:**
|
||||
- **ClubSettings.razor** (`/masterdata/club`):
|
||||
- Vereins-Name
|
||||
- ExpenseCalculation-Methode
|
||||
- Weitere Einstellungen
|
||||
|
||||
- **ExpenseTemplates.razor** (`/masterdata/expenses`):
|
||||
- Siehe Expense-Bereich (evtl. Duplikat)
|
||||
|
||||
- **TriggerConfig.razor** (`/masterdata/triggers`):
|
||||
- Siehe ExpenseTriggerConfig
|
||||
|
||||
---
|
||||
|
||||
### 8. ADMIN-BEREICH (SuperAdmin - Vereinsübergreifend)
|
||||
**Route:** `/admin`
|
||||
|
||||
**Pages:**
|
||||
- **ClubList.razor** (`/admin/clubs`):
|
||||
- Alle Vereine (SuperAdmin only)
|
||||
- Actions: Neu, Bearbeiten, Löschen
|
||||
|
||||
- **ClubCreate.razor** (`/admin/clubs/new`):
|
||||
- Name, ExpenseCalculation
|
||||
|
||||
- **UserManagement.razor** (`/admin/users`):
|
||||
- Alle UserProfiles
|
||||
- Vereinszuordnung (UserProfileClub)
|
||||
- Rollen-Zuordnung pro Verein
|
||||
|
||||
- **SystemSettings.razor** (`/admin/system`):
|
||||
- Globale Einstellungen
|
||||
|
||||
---
|
||||
|
||||
### 9. PROFIL-BEREICH (User Profile)
|
||||
**Route:** `/profile`
|
||||
|
||||
**Pages:**
|
||||
- **UserProfile.razor** (`/profile`):
|
||||
- DisplayName, Locale, TimeZone ändern
|
||||
- Passwort ändern
|
||||
- Standard-Verein festlegen (UserProfileClub.IsDefault)
|
||||
- Vereins-Mitgliedschaften anzeigen
|
||||
|
||||
---
|
||||
|
||||
## Vorgeschlagene Navigation-Struktur
|
||||
|
||||
```
|
||||
NavMenu.razor:
|
||||
├── 🏠 Dashboard (/)
|
||||
├── 📅 Spieltage (/days)
|
||||
├── 👥 Personen (/people)
|
||||
├── 💰 Kosten
|
||||
│ ├── Vorlagen (/expenses)
|
||||
│ ├── Zugewiesen (/expenses/assigned)
|
||||
│ └── Trigger (/expenses/triggers)
|
||||
├── 📊 Auswertungen (/reports)
|
||||
│ ├── Pro Person
|
||||
│ ├── Pro Tag
|
||||
│ └── Zeitraum
|
||||
├── ⚙️ Stammdaten (IsClubEditor+)
|
||||
│ ├── Verein (/masterdata/club)
|
||||
│ └── Kosten-Vorlagen
|
||||
├── 🔧 Admin (IsSuperAdmin)
|
||||
│ ├── Vereine (/admin/clubs)
|
||||
│ ├── Benutzer (/admin/users)
|
||||
│ └── System (/admin/system)
|
||||
└── 👤 Profil (/profile)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Prioritäts-Vorschlag (Phasen) - basierend auf User-Feedback
|
||||
|
||||
### Phase 1: MVP - Basis-Verwaltung (DIESE PLANUNG)
|
||||
**Scope:** User/Account-Mgmt, Club, Personen (Teilnehmer), Tage, Strafen
|
||||
|
||||
1. **User/Account-Verwaltung**
|
||||
- User-Registrierung (self-service oder Admin)
|
||||
- Passwort zurücksetzen
|
||||
- User-zu-Club Zuordnung (UserProfileClub)
|
||||
- Rollen pro Club zuweisen (UserProfileClubRoleAssignment)
|
||||
- User-Profil (DisplayName, Locale, TimeZone)
|
||||
|
||||
2. **Club-Verwaltung** (SuperAdmin)
|
||||
- Liste, Create, Edit, Delete
|
||||
- ExpenseCalculation-Methode
|
||||
|
||||
3. **Person-Verwaltung** (Club-Teilnehmer: Members + Guests)
|
||||
- Liste, Create, Edit, Delete
|
||||
- Status (Member/Guest)
|
||||
- **KEINE Login** - reine Stammdaten für Kegelclub
|
||||
|
||||
4. **Day-Verwaltung**
|
||||
- Liste, Create, Edit, Delete
|
||||
- Datum, Status (New, Started, Closed, Postponed)
|
||||
- Teilnehmer zuordnen (DayPerson)
|
||||
|
||||
5. **PersonExpense - Strafen manuell erfassen**
|
||||
- Pro Teilnehmer pro Tag Strafen hinzufügen
|
||||
- Expense-Vorlagen (Name, Preis)
|
||||
- Status: Open/Done
|
||||
|
||||
6. **Dashboard**
|
||||
- Übersicht: Nächste Tage, offene Kosten
|
||||
- Quick-Actions
|
||||
|
||||
7. **Einfache Auswertung**
|
||||
- Pro Tag: Wer schuldet was
|
||||
- Pro Person: Summe offener Kosten
|
||||
|
||||
### Phase 2: Detaillierte Spielverwaltung (SEPARATE PLANUNG SPÄTER)
|
||||
**NICHT in dieser Planung:**
|
||||
- Wurf-für-Wurf Eingabe
|
||||
- Undo-Funktion
|
||||
- Plugin-System für verschiedene Kegelspiele
|
||||
- GameData strukturiert (JSON für jetzt)
|
||||
- Automatische Trigger (Pudel, Pumpe, etc.)
|
||||
- Expense-Trigger-Engine
|
||||
|
||||
### Phase 3: Advanced Features (SPÄTER)
|
||||
- Export (PDF, CSV)
|
||||
- Benutzer-Rollen verwalten
|
||||
- Erweiterte Reports
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
# IMPLEMENTIERUNGSPLAN - Phase 1 MVP
|
||||
|
||||
## Umsetzungsreihenfolge - Übersicht
|
||||
|
||||
| ✓ | Phase | Bereich | Beschreibung | Dateien |
|
||||
|---|-------|---------|--------------|---------|
|
||||
| ☐ | A1 | Foundation | Repository Interfaces | 5 Interface-Dateien |
|
||||
| ☐ | A2 | Foundation | Repository Implementations | 5 Repository-Dateien |
|
||||
| ☐ | A3 | Foundation | DTOs | 5 DTO-Dateien |
|
||||
| ☐ | A4 | Foundation | Service Interfaces | 5 Service-Interface-Dateien |
|
||||
| ☐ | A5 | Foundation | Service Implementations | 5 Service-Dateien |
|
||||
| ☐ | A6 | Foundation | AutoMapper Profiles | 5 Mapping-Dateien |
|
||||
| ☐ | A7 | Foundation | DI Registration | 2 DI-Dateien ändern |
|
||||
| ☐ | **B1** | **Clubs** | **ClubState Fluxor** | **4 State-Dateien** |
|
||||
| ☐ | **B2** | **Clubs** | **Club Pages - ERSTES TESTBARES MVP** | **1 Razor** |
|
||||
| ☐ | C1 | User/Account | UserService erweitern | 1 Service, 1 Interface, 1 DTO |
|
||||
| ☐ | C2 | User/Account | Register Page | 1 Razor |
|
||||
| ☐ | C3 | User/Account | Password Reset Pages | 2 Razor |
|
||||
| ☐ | C4 | User/Account | Profile Page | 1 Razor |
|
||||
| ☐ | C5 | User/Account | Admin Users Page | 1 Razor |
|
||||
| ☐ | D1 | Personen | PersonState Fluxor | 4 State-Dateien |
|
||||
| ☐ | D2 | Personen | Person Pages | 1 Razor |
|
||||
| ☐ | D3 | Expenses | ExpenseState Fluxor | 4 State-Dateien |
|
||||
| ☐ | D4 | Expenses | Expense Pages | 1 Razor |
|
||||
| ☐ | E1 | Days | DayState Fluxor | 4 State-Dateien |
|
||||
| ☐ | E2 | Days | Days List Page | 1 Razor |
|
||||
| ☐ | E3 | Days | Day Details Page | 1 Razor |
|
||||
| ☐ | E4 | Days | PersonExpense Management | Components in DayDetails |
|
||||
| ☐ | F1 | Dashboard | Dashboard Page | 1 Razor |
|
||||
| ☐ | F2 | Dashboard | Evaluation Components | 2 Shared Components |
|
||||
| ☐ | F3 | Navigation | NavMenu finalisieren | 1 Razor ändern |
|
||||
|
||||
**Legende:** ☐ = Offen | ☑ = In Arbeit | ✓ = Fertig
|
||||
|
||||
**Geschätzte Dateien insgesamt: ~75 Dateien**
|
||||
|
||||
---
|
||||
|
||||
## Detaillierte Phasen
|
||||
|
||||
### **Phase A1: Repository Interfaces erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Domain/Interfaces/IClubRepository.cs`
|
||||
2. `src/Koogle.Domain/Interfaces/IPersonRepository.cs`
|
||||
3. `src/Koogle.Domain/Interfaces/IExpenseRepository.cs`
|
||||
4. `src/Koogle.Domain/Interfaces/IDayRepository.cs` (erweitern)
|
||||
5. `src/Koogle.Domain/Interfaces/IPersonExpenseRepository.cs`
|
||||
|
||||
**Methoden pro Interface:** GetAllAsync/GetByClubIdAsync, GetByIdAsync, AddAsync, UpdateAsync, DeleteAsync
|
||||
|
||||
---
|
||||
|
||||
### **Phase A2: Repository Implementations erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Infrastructure/Repositories/ClubRepository.cs`
|
||||
2. `src/Koogle.Infrastructure/Repositories/PersonRepository.cs`
|
||||
3. `src/Koogle.Infrastructure/Repositories/ExpenseRepository.cs`
|
||||
4. `src/Koogle.Infrastructure/Repositories/DayRepository.cs`
|
||||
5. `src/Koogle.Infrastructure/Repositories/PersonExpenseRepository.cs`
|
||||
|
||||
**Pattern:** IDbContextFactory<AppDbContext>, ClubId-Filter, Include Navigation Properties
|
||||
|
||||
---
|
||||
|
||||
### **Phase A3: DTOs erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Application/DTOs/ClubDto.cs` (ClubDto, CreateClubDto, UpdateClubDto)
|
||||
2. `src/Koogle.Application/DTOs/PersonDto.cs` (PersonDto, CreatePersonDto, UpdatePersonDto)
|
||||
3. `src/Koogle.Application/DTOs/ExpenseDto.cs` (ExpenseDto, CreateExpenseDto, UpdateExpenseDto)
|
||||
4. `src/Koogle.Application/DTOs/DayDto.cs` erweitern (DayDto, CreateDayDto, UpdateDayDto, DayParticipantDto)
|
||||
5. `src/Koogle.Application/DTOs/PersonExpenseDto.cs` (PersonExpenseDto, CreatePersonExpenseDto, DayEvaluationDto, PersonDayEvaluationDto)
|
||||
|
||||
---
|
||||
|
||||
### **Phase A4: Service Interfaces erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Application/Interfaces/IClubService.cs`
|
||||
2. `src/Koogle.Application/Interfaces/IPersonService.cs`
|
||||
3. `src/Koogle.Application/Interfaces/IExpenseService.cs`
|
||||
4. `src/Koogle.Application/Interfaces/IDayService.cs` (erweitern)
|
||||
5. `src/Koogle.Application/Interfaces/IPersonExpenseService.cs`
|
||||
|
||||
**Methoden:** GetAllAsync, GetByIdAsync, CreateAsync, UpdateAsync, DeleteAsync + spezifische Methoden
|
||||
|
||||
---
|
||||
|
||||
### **Phase A5: Service Implementations erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Application/Services/ClubService.cs`
|
||||
2. `src/Koogle.Application/Services/PersonService.cs`
|
||||
3. `src/Koogle.Application/Services/ExpenseService.cs`
|
||||
4. `src/Koogle.Application/Services/DayService.cs` (erweitern)
|
||||
5. `src/Koogle.Application/Services/PersonExpenseService.cs`
|
||||
|
||||
**Dependencies:** Repository, ICurrentClubContext, ICurrentUserService, IMapper
|
||||
**Business Logic:** ClubId-Injection, Audit-Felder, Validierung
|
||||
|
||||
---
|
||||
|
||||
### **Phase A6: AutoMapper Profiles erstellen**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Application/Mapping/ClubMappingProfile.cs`
|
||||
2. `src/Koogle.Application/Mapping/PersonMappingProfile.cs`
|
||||
3. `src/Koogle.Application/Mapping/ExpenseMappingProfile.cs`
|
||||
4. `src/Koogle.Application/Mapping/DayMappingProfile.cs`
|
||||
5. `src/Koogle.Application/Mapping/PersonExpenseMappingProfile.cs`
|
||||
|
||||
**Pattern:** CreateMap<Entity, Dto>() bidirektional
|
||||
|
||||
---
|
||||
|
||||
### **Phase A7: DI Registration**
|
||||
|
||||
**Dateien ändern:**
|
||||
1. `src/Koogle.Infrastructure/DependencyInjection.cs` (5 Repositories registrieren)
|
||||
2. `src/Koogle.Application/DependencyInjection.cs` (5 Services registrieren)
|
||||
|
||||
---
|
||||
|
||||
### **Phase B1: UserService erweitern**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Application/Interfaces/IUserService.cs` erweitern
|
||||
2. `src/Koogle.Application/Services/UserService.cs` erweitern
|
||||
3. `src/Koogle.Application/DTOs/UserDto.cs` erweitern (RegisterUserDto, ResetPasswordDto, UpdateUserProfileDto)
|
||||
|
||||
**Neue Methoden:**
|
||||
- RegisterUserAsync
|
||||
- RequestPasswordResetAsync
|
||||
- ResetPasswordAsync
|
||||
- UpdateProfileAsync
|
||||
- AssignUserToClubAsync, RemoveUserFromClubAsync
|
||||
- AssignClubRoleAsync, RemoveClubRoleAsync
|
||||
|
||||
---
|
||||
|
||||
### **Phase B2: Register Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Account/Register.razor`
|
||||
|
||||
**Features:** Email, Password, DisplayName, Optional ClubName für initiale Zuordnung
|
||||
|
||||
---
|
||||
|
||||
### **Phase B3: Password Reset Pages**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Account/ForgotPassword.razor`
|
||||
2. `src/Koogle.Web/Components/Pages/Account/ResetPassword.razor`
|
||||
|
||||
**Flow:** Email eingeben → Token per Email → Passwort zurücksetzen
|
||||
|
||||
---
|
||||
|
||||
### **Phase B4: Profile Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Account/Profile.razor`
|
||||
|
||||
**Features:** DisplayName, Locale, TimeZone, Club-Memberships anzeigen, Standard-Club setzen
|
||||
|
||||
---
|
||||
|
||||
### **Phase B5: Admin Users Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Admin/Users.razor`
|
||||
|
||||
**Features:** User-Liste, Club-Zuordnungen, Rollen pro Club
|
||||
|
||||
---
|
||||
|
||||
### **Phase C1: ClubState (Fluxor)**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Store/ClubState/ClubState.cs`
|
||||
2. `src/Koogle.Web/Store/ClubState/ClubActions.cs`
|
||||
3. `src/Koogle.Web/Store/ClubState/ClubReducers.cs`
|
||||
4. `src/Koogle.Web/Store/ClubState/ClubEffects.cs`
|
||||
|
||||
**Actions:** Load, Create, Update, Delete
|
||||
|
||||
---
|
||||
|
||||
### **Phase C2: Club Pages**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Admin/Clubs.razor`
|
||||
|
||||
**Features:** MudTable, CRUD-Dialogs, SuperAdmin only
|
||||
|
||||
---
|
||||
|
||||
### **Phase D1: PersonState (Fluxor)**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Store/PersonState/PersonState.cs`
|
||||
2. `src/Koogle.Web/Store/PersonState/PersonActions.cs`
|
||||
3. `src/Koogle.Web/Store/PersonState/PersonReducers.cs`
|
||||
4. `src/Koogle.Web/Store/PersonState/PersonEffects.cs`
|
||||
|
||||
---
|
||||
|
||||
### **Phase D2: Person Pages**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Persons/Persons.razor`
|
||||
|
||||
**Features:** MudTable mit Filter (Member/Guest), CRUD
|
||||
|
||||
---
|
||||
|
||||
### **Phase D3: ExpenseState (Fluxor)**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Store/ExpenseState/ExpenseState.cs`
|
||||
2. `src/Koogle.Web/Store/ExpenseState/ExpenseActions.cs`
|
||||
3. `src/Koogle.Web/Store/ExpenseState/ExpenseReducers.cs`
|
||||
4. `src/Koogle.Web/Store/ExpenseState/ExpenseEffects.cs`
|
||||
|
||||
---
|
||||
|
||||
### **Phase D4: Expense Pages**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Expenses/Expenses.razor`
|
||||
|
||||
**Features:** MudTable mit Expense-Vorlagen, CRUD
|
||||
|
||||
---
|
||||
|
||||
### **Phase E1: DayState (Fluxor)**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Store/DayState/DayState.cs`
|
||||
2. `src/Koogle.Web/Store/DayState/DayActions.cs`
|
||||
3. `src/Koogle.Web/Store/DayState/DayReducers.cs`
|
||||
4. `src/Koogle.Web/Store/DayState/DayEffects.cs`
|
||||
|
||||
**State:** Days, SelectedDay, SelectedDayExpenses, AvailablePersons
|
||||
|
||||
---
|
||||
|
||||
### **Phase E2: Days List Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Days/Days.razor`
|
||||
|
||||
**Features:** MudTable mit Jahr-Filter, Create Day
|
||||
|
||||
---
|
||||
|
||||
### **Phase E3: Day Details Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Days/DayDetails.razor`
|
||||
|
||||
**Features:**
|
||||
- Day-Header (Datum, Status)
|
||||
- Status-Workflow Buttons (New→Started→Closed)
|
||||
- Teilnehmer-Sektion (Add/Remove)
|
||||
- PersonExpense-Sektion
|
||||
|
||||
---
|
||||
|
||||
### **Phase E4: PersonExpense Management**
|
||||
|
||||
**Components in DayDetails:**
|
||||
- PersonExpense-Tabelle
|
||||
- Add Expense Dialog (Person auswählen, Expense auswählen, Preis editierbar wenn IsVariable)
|
||||
- Delete PersonExpense (nur in New/Started)
|
||||
- IsInverse Logic: 1 Person auswählen → alle anderen bekommen Expense
|
||||
|
||||
---
|
||||
|
||||
### **Phase F1: Dashboard Page**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Pages/Dashboard.razor`
|
||||
|
||||
**Features:** Summary Cards, Recent Days, Top Penalty Recipients
|
||||
|
||||
---
|
||||
|
||||
### **Phase F2: Evaluation Components**
|
||||
|
||||
**Dateien:**
|
||||
1. `src/Koogle.Web/Components/Shared/DayEvaluationComponent.razor`
|
||||
2. `src/Koogle.Web/Components/Shared/PersonEvaluationComponent.razor`
|
||||
|
||||
---
|
||||
|
||||
### **Phase F3: Navigation finalisieren**
|
||||
|
||||
**Dateien ändern:**
|
||||
1. `src/Koogle.Web/Components/Layout/NavMenu.razor`
|
||||
|
||||
**Features:** Dashboard, Spieltage, Stammdaten, Admin, Profil
|
||||
|
||||
---
|
||||
|
||||
## Zentrale Anforderungen (User-Feedback)
|
||||
|
||||
### Business Rules
|
||||
1. **PersonExpense.Price**: Bei IsVariable=true editierbar, aber vorbelegt aus Expense
|
||||
2. **Day Status-Workflow**: Strikt New→Started→Closed, keine Sprünge
|
||||
3. **User-Registrierung**: Self-Service (öffentlich)
|
||||
4. **Passwort-Reset**: Email-basiert mit Token
|
||||
5. **Day-Create**: Alle Members vorbelegt, Gäste manuell
|
||||
6. **PersonExpense löschen**: Nur in Status New/Started
|
||||
7. **Expense.IsInverse**: Automatisch - 1 Person auswählen, alle anderen bekommen Expense
|
||||
8. **Dashboard Zeitraum**: Aktuelles Jahr
|
||||
|
||||
---
|
||||
|
||||
## Code-Patterns & Konventionen
|
||||
|
||||
### Repository Pattern
|
||||
- Interface in Domain/Interfaces
|
||||
- Implementation in Infrastructure/Repositories
|
||||
- Standard-Methoden: GetAllAsync, GetByIdAsync, AddAsync, UpdateAsync, DeleteAsync
|
||||
- ClubId-Filter via ICurrentClubContext
|
||||
- IDbContextFactory<AppDbContext> für Scoping
|
||||
|
||||
### Service Pattern
|
||||
- Interface in Application/Interfaces
|
||||
- Implementation in Application/Services
|
||||
- Dependencies: Repository, ICurrentClubContext, ICurrentUserService, IMapper
|
||||
- ClubService: IsSuperAdmin Check
|
||||
- Audit-Felder auto-setzen (CreatedById, CreatedAt, ModifiedById, ModifiedAt)
|
||||
|
||||
### Fluxor Pattern (Redux)
|
||||
- State: Record mit Collections + IsLoading + Error
|
||||
- Actions: Record per Operation (Load, LoadSuccess, LoadFailure, Create, Update, Delete)
|
||||
- Reducers: Pure functions, State transformieren
|
||||
- Effects: Async Operations, Service-Calls, Dispatcher
|
||||
|
||||
### UI Pattern (Blazor + MudBlazor)
|
||||
- @inherits FluxorComponent
|
||||
- @attribute [Authorize(Policy = "...")]
|
||||
- MudTable für Listen
|
||||
- MudDialog für Create/Edit
|
||||
- MudForm mit Validation
|
||||
|
||||
---
|
||||
|
||||
## Referenzdateien für Patterns
|
||||
|
||||
**Service-Pattern:**
|
||||
- `src/Koogle.Application/Services/UserService.cs`
|
||||
|
||||
**Fluxor-Pattern:**
|
||||
- `src/Koogle.Web/Store/AuthState/AuthState.cs`
|
||||
- `src/Koogle.Web/Store/AuthState/AuthActions.cs`
|
||||
- `src/Koogle.Web/Store/AuthState/AuthReducers.cs`
|
||||
- `src/Koogle.Web/Store/AuthState/AuthEffects.cs`
|
||||
|
||||
**AutoMapper:**
|
||||
- `src/Koogle.Application/Mapping/UserProfile.cs`
|
||||
|
||||
**DI:**
|
||||
- `src/Koogle.Infrastructure/DependencyInjection.cs`
|
||||
- `src/Koogle.Application/DependencyInjection.cs`
|
||||
|
||||
**Domain:**
|
||||
- `src/Koogle.Domain/Entities/BaseEntity.cs`
|
||||
|
||||
---
|
||||
|
||||
## Berechtigungen pro Feature
|
||||
|
||||
- **Club-Verwaltung**: SuperAdmin only
|
||||
- **Person/Expense/Day CRUD**: ClubEditor+
|
||||
- **Dashboard/Auswertungen**: ClubViewer+
|
||||
|
||||
Policy: `@attribute [Authorize(Policy = "ClubViewer|ClubEditor|ClubAdmin")]`
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
**23 feine Phasen** → **~75 Dateien** → **MVP Phase 1 komplett**
|
||||
|
||||
Bereit für Implementierung Phase A1
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
# Build & Development Documentation
|
||||
|
||||
## Implementation Plan
|
||||
See [IMPLEMENTATION_PLAN.md](./IMPLEMENTATION_PLAN.md) for detailed Phase 1 MVP roadmap (23 phases, ~75 files).
|
||||
|
||||
---
|
||||
|
||||
# Entity Framework Core - Datenbank Migrationen und Updates
|
||||
|
||||
|
|
@ -32,7 +38,9 @@ dotnet ef database update -p src/Koogle.Infrastructure -s src/Koogle.Web --conte
|
|||
|
||||
# Tests
|
||||
|
||||
## Tests ausführen
|
||||
## Tests ausf<EFBFBD>hren
|
||||
```
|
||||
dotnet test tests/Koogle.Application.Tests
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ namespace Koogle.Domain.Enums
|
|||
/// <summary>
|
||||
/// different user roles within the application.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Even without these roles, users can just see content of days and games themselves have participated in.
|
||||
/// Therefore, an optional connection between users and people within clubs is needed. [] TODO: Link users to a person in a club.
|
||||
/// </remarks>
|
||||
public static class UserRole
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -27,7 +31,7 @@ namespace Koogle.Domain.Enums
|
|||
public const string Editor = "Editor";
|
||||
|
||||
/// <summary>
|
||||
/// with this role, the user can only view content within a club.
|
||||
/// With this role, the user can only view content within a club.
|
||||
/// </summary>
|
||||
public const string Viewer = "Viewer";
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
using Koogle.Domain.Entities;
|
||||
|
||||
namespace Koogle.Domain.Interfaces;
|
||||
|
||||
public interface IClubRepository
|
||||
{
|
||||
Task<List<Club>> GetAllAsync(CancellationToken ct = default);
|
||||
Task<Club?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task<Club> AddAsync(Club entity, CancellationToken ct = default);
|
||||
Task<Club> UpdateAsync(Club entity, CancellationToken ct = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using Koogle.Domain.Entities;
|
||||
|
||||
namespace Koogle.Domain.Interfaces;
|
||||
|
||||
public interface IExpenseRepository
|
||||
{
|
||||
Task<List<Expense>> GetByClubIdAsync(Guid clubId, CancellationToken ct = default);
|
||||
Task<Expense?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task<Expense> AddAsync(Expense entity, CancellationToken ct = default);
|
||||
Task<Expense> UpdateAsync(Expense entity, CancellationToken ct = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using Koogle.Domain.Entities;
|
||||
|
||||
namespace Koogle.Domain.Interfaces;
|
||||
|
||||
public interface IPersonExpenseRepository
|
||||
{
|
||||
Task<List<PersonExpense>> GetByDayIdAsync(Guid dayId, CancellationToken ct = default);
|
||||
Task<List<PersonExpense>> GetByPersonIdAsync(Guid personId, CancellationToken ct = default);
|
||||
Task<PersonExpense?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task<PersonExpense> AddAsync(PersonExpense entity, CancellationToken ct = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using Koogle.Domain.Entities;
|
||||
|
||||
namespace Koogle.Domain.Interfaces;
|
||||
|
||||
public interface IPersonRepository
|
||||
{
|
||||
Task<List<Person>> GetByClubIdAsync(Guid clubId, CancellationToken ct = default);
|
||||
Task<Person?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task<Person> AddAsync(Person entity, CancellationToken ct = default);
|
||||
Task<Person> UpdateAsync(Person entity, CancellationToken ct = default);
|
||||
Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
|
||||
}
|
||||
Loading…
Reference in New Issue