Files
SIG-CM/src/SIGCM.Infrastructure/Repositories/ClientRepository.cs

159 lines
5.8 KiB
C#
Raw Normal View History

2025-12-23 15:12:57 -03:00
using Dapper;
using SIGCM.Domain.Entities;
using SIGCM.Infrastructure.Data;
namespace SIGCM.Infrastructure.Repositories;
public class ClientRepository
{
private readonly IDbConnectionFactory _db;
public ClientRepository(IDbConnectionFactory db)
{
_db = db;
}
2026-01-06 10:34:06 -03:00
// Búsqueda inteligente redireccionada a Users
2025-12-23 15:12:57 -03:00
public async Task<IEnumerable<Client>> SearchAsync(string query)
{
using var conn = _db.CreateConnection();
var sql = @"
2026-01-05 10:30:04 -03:00
SELECT TOP 10
Id,
2026-01-06 10:34:06 -03:00
ISNULL(BillingName, Username) as Name,
ISNULL(BillingTaxId, '') as DniOrCuit,
2026-01-06 14:20:44 -03:00
Email, Phone, BillingAddress as Address, BillingTaxType as TaxType,
Username, IsActive, Role
2026-01-06 10:34:06 -03:00
FROM Users
WHERE BillingName LIKE @Query OR BillingTaxId LIKE @Query OR Username LIKE @Query
ORDER BY BillingName";
2025-12-23 15:12:57 -03:00
return await conn.QueryAsync<Client>(sql, new { Query = $"%{query}%" });
}
2026-01-06 10:34:06 -03:00
// Asegurar existencia (Upsert en la tabla Users)
2025-12-23 15:12:57 -03:00
public async Task<int> EnsureClientExistsAsync(string name, string dni)
{
using var conn = _db.CreateConnection();
var existingId = await conn.ExecuteScalarAsync<int?>(
2026-01-06 10:34:06 -03:00
"SELECT Id FROM Users WHERE BillingTaxId = @Dni", new { Dni = dni });
2025-12-23 15:12:57 -03:00
if (existingId.HasValue)
{
2026-01-06 10:34:06 -03:00
await conn.ExecuteAsync("UPDATE Users SET BillingName = @Name WHERE Id = @Id", new { Name = name, Id = existingId });
2025-12-23 15:12:57 -03:00
return existingId.Value;
}
else
{
2026-01-06 10:34:06 -03:00
// Si no existe, creamos un usuario con rol Cliente (sin password por ahora, es solo para gestión de mostrador)
2025-12-23 15:12:57 -03:00
var sql = @"
2026-01-06 10:34:06 -03:00
INSERT INTO Users (Username, Role, BillingName, BillingTaxId, PasswordHash, MustChangePassword)
VALUES (@Username, 'Client', @Name, @Dni, 'N/A', 0);
2025-12-23 15:12:57 -03:00
SELECT CAST(SCOPE_IDENTITY() as int);";
2026-01-06 10:34:06 -03:00
// El username será el DNI para asegurar unicidad si no hay otro dato
return await conn.QuerySingleAsync<int>(sql, new { Username = dni, Name = name, Dni = dni });
2025-12-23 15:12:57 -03:00
}
}
2026-01-06 14:20:44 -03:00
// Obtener con estadísticas desde Users (con filtro y límite para performance)
public async Task<IEnumerable<dynamic>> GetAllWithStatsAsync(string? searchTerm = null)
2025-12-23 15:12:57 -03:00
{
using var conn = _db.CreateConnection();
var sql = @"
2026-01-06 14:20:44 -03:00
SELECT TOP 100
2026-01-06 10:34:06 -03:00
u.Id as id,
ISNULL(u.BillingName, u.Username) as name,
ISNULL(u.BillingTaxId, 'S/D') as dniOrCuit,
ISNULL(u.Email, 'Sin correo') as email,
ISNULL(u.Phone, 'Sin teléfono') as phone,
2026-01-06 14:20:44 -03:00
ISNULL(u.BillingTaxType, 'Consumidor Final') as taxType,
u.Username as username,
u.IsActive as isActive,
u.Role as role,
2026-01-06 10:34:06 -03:00
(SELECT COUNT(1) FROM Listings l WHERE l.ClientId = u.Id) as totalAds,
ISNULL((SELECT SUM(AdFee) FROM Listings l WHERE l.ClientId = u.Id), 0) as totalSpent
FROM Users u
2026-01-06 14:20:44 -03:00
WHERE Role IN ('Client', 'User')";
if (!string.IsNullOrWhiteSpace(searchTerm))
{
sql += " AND (u.BillingName LIKE @Query OR u.BillingTaxId LIKE @Query OR u.Username LIKE @Query)";
}
sql += " ORDER BY name";
2026-02-21 19:23:17 -03:00
2026-01-06 14:20:44 -03:00
return await conn.QueryAsync(sql, new { Query = $"%{searchTerm}%" });
2025-12-23 15:12:57 -03:00
}
2026-01-05 10:30:04 -03:00
public async Task UpdateAsync(Client client)
2025-12-23 15:12:57 -03:00
{
using var conn = _db.CreateConnection();
2026-01-05 10:30:04 -03:00
var sql = @"
2026-01-06 10:34:06 -03:00
UPDATE Users
SET BillingName = @Name,
BillingTaxId = @DniOrCuit,
2026-01-05 10:30:04 -03:00
Email = @Email,
Phone = @Phone,
2026-01-06 14:20:44 -03:00
BillingAddress = @Address,
BillingTaxType = @TaxType,
Username = @Username,
IsActive = @IsActive
2026-01-05 10:30:04 -03:00
WHERE Id = @Id";
await conn.ExecuteAsync(sql, client);
}
public async Task<dynamic?> GetClientSummaryAsync(int clientId)
{
using var conn = _db.CreateConnection();
var sql = @"
SELECT
2026-01-06 10:34:06 -03:00
u.Id,
ISNULL(u.BillingName, u.Username) as Name,
u.BillingTaxId as DniOrCuit, u.Email, u.Phone, u.BillingAddress as Address,
2026-01-06 14:20:44 -03:00
u.BillingTaxType as TaxType,
u.Username, u.IsActive, u.Role,
2026-01-06 10:34:06 -03:00
(SELECT COUNT(1) FROM Listings WHERE ClientId = u.Id) as TotalAds,
ISNULL((SELECT SUM(AdFee) FROM Listings WHERE ClientId = u.Id), 0) as TotalInvested,
(SELECT MAX(CreatedAt) FROM Listings WHERE ClientId = u.Id) as LastAdDate,
(SELECT COUNT(1) FROM Listings WHERE ClientId = u.Id AND Status = 'Published') as ActiveAds,
2026-01-05 10:30:04 -03:00
ISNULL((
SELECT TOP 1 cat.Name
FROM Listings l
JOIN Categories cat ON l.CategoryId = cat.Id
2026-01-06 10:34:06 -03:00
WHERE l.ClientId = u.Id
2026-01-05 10:30:04 -03:00
GROUP BY cat.Name
ORDER BY COUNT(l.Id) DESC
), 'N/A') as PreferredCategory
2026-01-06 10:34:06 -03:00
FROM Users u
WHERE u.Id = @Id";
2026-01-05 10:30:04 -03:00
return await conn.QuerySingleOrDefaultAsync<dynamic>(sql, new { Id = clientId });
2025-12-23 15:12:57 -03:00
}
2026-01-06 14:20:44 -03:00
public async Task ResetPasswordAsync(int clientId, string passwordHash)
{
using var conn = _db.CreateConnection();
var sql = "UPDATE Users SET PasswordHash = @Hash, MustChangePassword = 1 WHERE Id = @Id";
await conn.ExecuteAsync(sql, new { Hash = passwordHash, Id = clientId });
}
2026-02-21 19:23:17 -03:00
public async Task<int> CreateFullClientAsync(Client client)
{
using var conn = _db.CreateConnection();
var sql = @"
INSERT INTO Users (
Username, PasswordHash, Role,
BillingName, BillingTaxId, Email, Phone, BillingAddress, BillingTaxType,
MustChangePassword, IsActive, CreatedAt
)
VALUES (
@DniOrCuit, 'N/A', 'Client',
@Name, @DniOrCuit, @Email, @Phone, @Address, @TaxType,
0, 1, GETUTCDATE()
);
SELECT CAST(SCOPE_IDENTITY() as int);";
// Usamos el CUIT como username por defecto para garantizar unicidad
return await conn.QuerySingleAsync<int>(sql, client);
}
2025-12-23 15:12:57 -03:00
}