138 lines
4.9 KiB
C#
138 lines
4.9 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Service for managing booking category operations within the current club context.
|
|
/// </summary>
|
|
public class BookingCategoryService : IBookingCategoryService
|
|
{
|
|
private readonly IBookingCategoryRepository _repository;
|
|
private readonly ICurrentClubContext _clubContext;
|
|
private readonly IMapper _mapper;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="BookingCategoryService"/> class.
|
|
/// </summary>
|
|
public BookingCategoryService(
|
|
IBookingCategoryRepository repository,
|
|
ICurrentClubContext clubContext,
|
|
IMapper mapper)
|
|
{
|
|
_repository = repository;
|
|
_clubContext = clubContext;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<List<BookingCategoryDto>> GetAllAsync(bool includeInactive = false, CancellationToken ct = default)
|
|
{
|
|
var categories = await _repository.GetByClubIdAsync(_clubContext.ClubId, includeInactive, ct);
|
|
return _mapper.Map<List<BookingCategoryDto>>(categories);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<BookingCategoryDto?> 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<BookingCategoryDto>(category);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<BookingCategoryDto> 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<BookingCategoryDto>(created);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<BookingCategoryDto> 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<BookingCategoryDto>(updated);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<bool> 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;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|