using AutoMapper; using Koogle.Application.DTOs; using Koogle.Application.Interfaces; using Koogle.Domain.Entities; using Koogle.Domain.Enums; using Koogle.Domain.Interfaces; namespace Koogle.Application.Services; /// /// Service for managing booking category operations within the current club context. /// public class BookingCategoryService : IBookingCategoryService { private readonly IBookingCategoryRepository _repository; private readonly ICurrentClubContext _clubContext; private readonly IMapper _mapper; /// /// Initializes a new instance of the class. /// public BookingCategoryService( IBookingCategoryRepository repository, ICurrentClubContext clubContext, IMapper mapper) { _repository = repository; _clubContext = clubContext; _mapper = mapper; } /// public async Task> GetAllAsync(bool includeInactive = false, CancellationToken ct = default) { var categories = await _repository.GetByClubIdAsync(_clubContext.ClubId, includeInactive, ct); return _mapper.Map>(categories); } /// public async Task GetByIdAsync(Guid id, CancellationToken ct = default) { var category = await _repository.GetByIdAsync(id, ct); if (category is null || category.ClubId != _clubContext.ClubId) return null; return _mapper.Map(category); } /// public async Task CreateAsync(CreateBookingCategoryDto dto, CancellationToken ct = default) { var entity = new BookingCategory { Id = Guid.NewGuid(), ClubId = _clubContext.ClubId, Name = dto.Name, Description = dto.Description, CategoryType = dto.CategoryType, IsSystemCategory = false, Color = dto.Color, Icon = dto.Icon, IsActive = true, CreatedAt = DateTime.UtcNow }; var created = await _repository.AddAsync(entity, ct); return _mapper.Map(created); } /// public async Task UpdateAsync(UpdateBookingCategoryDto dto, CancellationToken ct = default) { var existing = await _repository.GetByIdAsync(dto.Id, ct) ?? throw new InvalidOperationException($"Category with id {dto.Id} not found."); if (existing.ClubId != _clubContext.ClubId) throw new InvalidOperationException("Category does not belong to current club."); existing.Name = dto.Name; existing.Description = dto.Description; existing.Color = dto.Color; existing.Icon = dto.Icon; existing.IsActive = dto.IsActive; existing.ModifiedAt = DateTime.UtcNow; var updated = await _repository.UpdateAsync(existing, ct); return _mapper.Map(updated); } /// public async Task DeleteAsync(Guid id, CancellationToken ct = default) { var existing = await _repository.GetByIdAsync(id, ct); if (existing is null || existing.ClubId != _clubContext.ClubId) return false; if (existing.IsSystemCategory) throw new InvalidOperationException("System categories cannot be deleted."); existing.IsDeleted = true; existing.ModifiedAt = DateTime.UtcNow; await _repository.UpdateAsync(existing, ct); return true; } /// public async Task EnsureSystemCategoriesAsync(CancellationToken ct = default) { var systemCategories = new[] { new { Name = "Spielstrafe", Type = BookingCategoryType.Income, Color = "#4CAF50", Icon = "Gavel" }, new { Name = "Mitgliedsbeitrag", Type = BookingCategoryType.Income, Color = "#2196F3", Icon = "CardMembership" }, new { Name = "Korrekturbuchung", Type = BookingCategoryType.Income, Color = "#FF9800", Icon = "Build" }, new { Name = "Saldoanpassung", Type = BookingCategoryType.Income, Color = "#9E9E9E", Icon = "Balance" } }; foreach (var cat in systemCategories) { var existing = await _repository.GetSystemCategoryAsync(_clubContext.ClubId, cat.Name, ct); if (existing is null) { await _repository.AddAsync(new BookingCategory { Id = Guid.NewGuid(), ClubId = _clubContext.ClubId, Name = cat.Name, CategoryType = cat.Type, IsSystemCategory = true, Color = cat.Color, Icon = cat.Icon, IsActive = true, CreatedAt = DateTime.UtcNow }, ct); } } } }