2026-03-03 19:41:01 +01:00
|
|
|
using Microsoft.EntityFrameworkCore;
|
2026-03-05 21:46:19 +01:00
|
|
|
using Npgsql;
|
2026-03-03 19:41:01 +01:00
|
|
|
using WorkClub.Application.Clubs.DTOs;
|
|
|
|
|
using WorkClub.Application.Interfaces;
|
2026-03-05 21:46:19 +01:00
|
|
|
using WorkClub.Domain.Enums;
|
2026-03-03 19:41:01 +01:00
|
|
|
using WorkClub.Infrastructure.Data;
|
|
|
|
|
|
|
|
|
|
namespace WorkClub.Api.Services;
|
|
|
|
|
|
|
|
|
|
public class ClubService
|
|
|
|
|
{
|
|
|
|
|
private readonly AppDbContext _context;
|
|
|
|
|
private readonly ITenantProvider _tenantProvider;
|
|
|
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
|
|
|
|
|
|
|
|
public ClubService(
|
|
|
|
|
AppDbContext context,
|
|
|
|
|
ITenantProvider tenantProvider,
|
|
|
|
|
IHttpContextAccessor httpContextAccessor)
|
|
|
|
|
{
|
|
|
|
|
_context = context;
|
|
|
|
|
_tenantProvider = tenantProvider;
|
|
|
|
|
_httpContextAccessor = httpContextAccessor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<List<ClubListDto>> GetMyClubsAsync()
|
|
|
|
|
{
|
2026-03-05 21:46:19 +01:00
|
|
|
var clubsClaim = _httpContextAccessor.HttpContext?.User.FindFirst("clubs")?.Value;
|
|
|
|
|
if (string.IsNullOrEmpty(clubsClaim))
|
2026-03-03 19:41:01 +01:00
|
|
|
{
|
|
|
|
|
return new List<ClubListDto>();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-05 21:46:19 +01:00
|
|
|
var tenantIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
|
|
|
|
.Select(t => t.Trim())
|
|
|
|
|
.Where(t => !string.IsNullOrEmpty(t) && Guid.TryParse(t, out _))
|
|
|
|
|
.ToList();
|
2026-03-03 19:41:01 +01:00
|
|
|
|
2026-03-05 21:46:19 +01:00
|
|
|
if (tenantIds.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
return new List<ClubListDto>();
|
|
|
|
|
}
|
2026-03-03 19:41:01 +01:00
|
|
|
|
|
|
|
|
var clubDtos = new List<ClubListDto>();
|
2026-03-05 21:46:19 +01:00
|
|
|
var connectionString = _context.Database.GetConnectionString();
|
|
|
|
|
|
|
|
|
|
foreach (var tenantId in tenantIds)
|
2026-03-03 19:41:01 +01:00
|
|
|
{
|
2026-03-05 21:46:19 +01:00
|
|
|
await using var connection = new NpgsqlConnection(connectionString);
|
|
|
|
|
await connection.OpenAsync();
|
|
|
|
|
|
|
|
|
|
await using var transaction = await connection.BeginTransactionAsync();
|
|
|
|
|
|
|
|
|
|
// Set RLS context
|
|
|
|
|
using (var command = connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
command.Transaction = transaction;
|
|
|
|
|
command.CommandText = $"SET LOCAL app.current_tenant_id = '{tenantId}'";
|
|
|
|
|
await command.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Guid? clubId = null;
|
|
|
|
|
string? clubName = null;
|
|
|
|
|
int? sportTypeInt = null;
|
|
|
|
|
|
|
|
|
|
// Fetch club details
|
|
|
|
|
using (var command = connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
command.Transaction = transaction;
|
|
|
|
|
command.CommandText = @"
|
|
|
|
|
SELECT c.""Id"", c.""Name"", c.""SportType""
|
|
|
|
|
FROM clubs AS c
|
|
|
|
|
WHERE c.""TenantId"" = @tenantId";
|
|
|
|
|
|
|
|
|
|
var parameter = command.CreateParameter();
|
|
|
|
|
parameter.ParameterName = "@tenantId";
|
|
|
|
|
parameter.Value = tenantId;
|
|
|
|
|
command.Parameters.Add(parameter);
|
|
|
|
|
|
|
|
|
|
using (var reader = await command.ExecuteReaderAsync())
|
|
|
|
|
{
|
|
|
|
|
if (await reader.ReadAsync())
|
|
|
|
|
{
|
|
|
|
|
clubId = reader.GetGuid(0);
|
|
|
|
|
clubName = reader.GetString(1);
|
|
|
|
|
sportTypeInt = reader.GetInt32(2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fetch member count if club exists
|
|
|
|
|
if (clubId.HasValue && clubName != null && sportTypeInt.HasValue)
|
|
|
|
|
{
|
|
|
|
|
using (var memberCommand = connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
memberCommand.Transaction = transaction;
|
|
|
|
|
memberCommand.CommandText = @"
|
|
|
|
|
SELECT COUNT(*)
|
|
|
|
|
FROM members AS m
|
|
|
|
|
WHERE m.""ClubId"" = @clubId";
|
|
|
|
|
|
|
|
|
|
var param = memberCommand.CreateParameter();
|
|
|
|
|
param.ParameterName = "@clubId";
|
|
|
|
|
param.Value = clubId;
|
|
|
|
|
memberCommand.Parameters.Add(param);
|
|
|
|
|
|
|
|
|
|
var memberCountResult = await memberCommand.ExecuteScalarAsync();
|
|
|
|
|
var memberCount = memberCountResult != null ? Convert.ToInt32(memberCountResult) : 0;
|
|
|
|
|
var sportTypeEnum = ((SportType)sportTypeInt.Value).ToString();
|
|
|
|
|
|
|
|
|
|
clubDtos.Add(new ClubListDto(
|
|
|
|
|
clubId.Value,
|
|
|
|
|
clubName,
|
|
|
|
|
sportTypeEnum,
|
2026-03-06 08:01:09 +01:00
|
|
|
memberCount,
|
|
|
|
|
Guid.Parse(tenantId)
|
2026-03-05 21:46:19 +01:00
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await transaction.CommitAsync();
|
2026-03-03 19:41:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return clubDtos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<ClubDetailDto?> GetCurrentClubAsync()
|
|
|
|
|
{
|
|
|
|
|
var tenantId = _tenantProvider.GetTenantId();
|
|
|
|
|
|
|
|
|
|
var club = await _context.Clubs
|
|
|
|
|
.FirstOrDefaultAsync(c => c.TenantId == tenantId);
|
|
|
|
|
|
|
|
|
|
if (club == null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return new ClubDetailDto(
|
|
|
|
|
club.Id,
|
|
|
|
|
club.Name,
|
|
|
|
|
club.SportType.ToString(),
|
|
|
|
|
club.Description,
|
|
|
|
|
club.CreatedAt,
|
|
|
|
|
club.UpdatedAt
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|