Feat Varios 3

This commit is contained in:
2026-01-06 10:34:06 -03:00
parent 0fa77e4a98
commit 9fa21ebec3
65 changed files with 2897 additions and 373 deletions

View File

@@ -13,59 +13,63 @@ public class ClientRepository
_db = db;
}
// Búsqueda inteligente con protección de nulos
// Búsqueda inteligente redireccionada a Users
public async Task<IEnumerable<Client>> SearchAsync(string query)
{
using var conn = _db.CreateConnection();
var sql = @"
SELECT TOP 10
Id,
ISNULL(Name, 'Sin Nombre') as Name,
ISNULL(DniOrCuit, '') as DniOrCuit,
Email, Phone, Address
FROM Clients
WHERE Name LIKE @Query OR DniOrCuit LIKE @Query
ORDER BY Name";
ISNULL(BillingName, Username) as Name,
ISNULL(BillingTaxId, '') as DniOrCuit,
Email, Phone, BillingAddress as Address
FROM Users
WHERE BillingName LIKE @Query OR BillingTaxId LIKE @Query OR Username LIKE @Query
ORDER BY BillingName";
return await conn.QueryAsync<Client>(sql, new { Query = $"%{query}%" });
}
// Asegurar existencia (Upsert)
// Asegurar existencia (Upsert en la tabla Users)
public async Task<int> EnsureClientExistsAsync(string name, string dni)
{
using var conn = _db.CreateConnection();
var existingId = await conn.ExecuteScalarAsync<int?>(
"SELECT Id FROM Clients WHERE DniOrCuit = @Dni", new { Dni = dni });
"SELECT Id FROM Users WHERE BillingTaxId = @Dni", new { Dni = dni });
if (existingId.HasValue)
{
await conn.ExecuteAsync("UPDATE Clients SET Name = @Name WHERE Id = @Id", new { Name = name, Id = existingId });
await conn.ExecuteAsync("UPDATE Users SET BillingName = @Name WHERE Id = @Id", new { Name = name, Id = existingId });
return existingId.Value;
}
else
{
// Si no existe, creamos un usuario con rol Cliente (sin password por ahora, es solo para gestión de mostrador)
var sql = @"
INSERT INTO Clients (Name, DniOrCuit) VALUES (@Name, @Dni);
INSERT INTO Users (Username, Role, BillingName, BillingTaxId, PasswordHash, MustChangePassword)
VALUES (@Username, 'Client', @Name, @Dni, 'N/A', 0);
SELECT CAST(SCOPE_IDENTITY() as int);";
return await conn.QuerySingleAsync<int>(sql, new { Name = name, Dni = dni });
// 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 });
}
}
// Obtener todos con estadísticas (ISNULL agregado para seguridad)
// Obtener todos con estadísticas desde Users
public async Task<IEnumerable<dynamic>> GetAllWithStatsAsync()
{
using var conn = _db.CreateConnection();
var sql = @"
SELECT
c.Id as id,
ISNULL(c.Name, 'Sin Nombre') as name,
ISNULL(c.DniOrCuit, 'S/D') as dniOrCuit,
ISNULL(c.Email, 'Sin correo') as email,
ISNULL(c.Phone, 'Sin teléfono') as phone,
(SELECT COUNT(1) FROM Listings l WHERE l.ClientId = c.Id) as totalAds,
ISNULL((SELECT SUM(AdFee) FROM Listings l WHERE l.ClientId = c.Id), 0) as totalSpent
FROM Clients c
ORDER BY c.Name";
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,
(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
WHERE Role IN ('Client', 'User') -- Mostramos tanto clientes puros como usuarios web
ORDER BY name";
return await conn.QueryAsync(sql);
}
@@ -73,12 +77,12 @@ public class ClientRepository
{
using var conn = _db.CreateConnection();
var sql = @"
UPDATE Clients
SET Name = @Name,
DniOrCuit = @DniOrCuit,
UPDATE Users
SET BillingName = @Name,
BillingTaxId = @DniOrCuit,
Email = @Email,
Phone = @Phone,
Address = @Address
BillingAddress = @Address
WHERE Id = @Id";
await conn.ExecuteAsync(sql, client);
}
@@ -88,21 +92,23 @@ public class ClientRepository
using var conn = _db.CreateConnection();
var sql = @"
SELECT
c.Id, c.Name, c.DniOrCuit, c.Email, c.Phone, c.Address,
(SELECT COUNT(1) FROM Listings WHERE ClientId = c.Id) as TotalAds,
ISNULL((SELECT SUM(AdFee) FROM Listings WHERE ClientId = c.Id), 0) as TotalInvested,
(SELECT MAX(CreatedAt) FROM Listings WHERE ClientId = c.Id) as LastAdDate,
(SELECT COUNT(1) FROM Listings WHERE ClientId = c.Id AND Status = 'Published') as ActiveAds,
u.Id,
ISNULL(u.BillingName, u.Username) as Name,
u.BillingTaxId as DniOrCuit, u.Email, u.Phone, u.BillingAddress as Address,
(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,
ISNULL((
SELECT TOP 1 cat.Name
FROM Listings l
JOIN Categories cat ON l.CategoryId = cat.Id
WHERE l.ClientId = c.Id
WHERE l.ClientId = u.Id
GROUP BY cat.Name
ORDER BY COUNT(l.Id) DESC
), 'N/A') as PreferredCategory
FROM Clients c
WHERE c.Id = @Id";
FROM Users u
WHERE u.Id = @Id";
return await conn.QuerySingleOrDefaultAsync<dynamic>(sql, new { Id = clientId });
}