Compare commits

...

2 Commits

Author SHA1 Message Date
beo3000 8e2342fd74 avoid duplicate person names 2025-12-25 19:00:42 +01:00
beo3000 60c74da842 added prompt for later 2025-12-25 18:53:16 +01:00
4 changed files with 39 additions and 1 deletions

View File

@ -1,4 +1,12 @@
## Erweiterte Registrierung & Club Mitgliedschaften
## Optimierung Spieltag-Details
Die Erfassung von Strafen muss möglichst schnell und komfortabel mögiich sein. Dafür muss die Seite DayDetails opimiert werden.
Es soll möglich sein eine Person in der Teilnehmerliste auszuwählen. Bei der Erfassung einer neuen Strafe kann diese Person direkt vorbelegt werden. Außerdem soll zusätzlich zum Button "Strafe hinzufügen" ein Menü-Button angezeigt werden, der eine Kurzwahl aller Strafen mit der Option "IsOneClick" ermöglicht.
Der Benutzer soll visuell leicht erkennen können, ob und welcher Teilnehmer aktuell markiert wurde.
## Erweiterte Registrierung & Club Mitgliedschaften - done
Die REgistrierung funktioniert, entspricht aber noch nicht den Anforderungen. Ergänze nach der Phase
F3 noch eine Phase "Erweiterte Registrierung". Dabei sollen neue User im Zuge der Registrierung erst mal
nur "pending" sein, und auf Freischaltung durch die Club-Admins warten müssen. Das Login soll nach der

View File

@ -52,6 +52,12 @@ public class PersonService : IPersonService
/// <inheritdoc />
public async Task<PersonDto> CreateAsync(CreatePersonDto dto, CancellationToken ct = default)
{
var existingPerson = await _personRepository.GetByNameAsync(_clubContext.ClubId, dto.Name, ct);
if (existingPerson != null)
{
throw new InvalidOperationException($"Person with name '{dto.Name}' already exists");
}
var entity = new Person
{
Id = Guid.NewGuid(),
@ -75,6 +81,12 @@ public class PersonService : IPersonService
if (existing.ClubId != _clubContext.ClubId)
throw new InvalidOperationException("Person does not belong to current club.");
var existingPerson = await _personRepository.GetByNameAsync(_clubContext.ClubId, dto.Name, ct);
if (existingPerson != null)
{
throw new InvalidOperationException($"Person with name '{dto.Name}' already exists");
}
existing.Name = dto.Name;
existing.PersonStatus = dto.PersonStatus;
existing.ModifiedAt = DateTime.UtcNow;

View File

@ -46,4 +46,13 @@ public interface IPersonRepository
/// <param name="ct">Cancellation token.</param>
/// <returns>True if deleted successfully; otherwise, false.</returns>
Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
/// <summary>
/// Read a person by its name within a specific club context.
/// </summary>
/// <param name="clubContextClubId"></param>
/// <param name="dtoName"></param>
/// <param name="ct"></param>
/// <returns>The person with the name or null</returns>
Task<Person?> GetByNameAsync(Guid clubContextClubId, string dtoName, CancellationToken ct);
}

View File

@ -63,4 +63,13 @@ public class PersonRepository(IDbContextFactory<AppDbContext> contextFactory) :
await context.SaveChangesAsync(ct);
return true;
}
/// <inheritdoc />
public async Task<Person?> GetByNameAsync(Guid clubContextClubId, string dtoName, CancellationToken ct)
{
await using var context = await contextFactory.CreateDbContextAsync(ct);
var entity = await context.Persons
.FirstOrDefaultAsync(p => p.ClubId == clubContextClubId && p.Name == dtoName && !p.IsDeleted, ct);
return entity;
}
}