Fase 3: Implementación de Listings (Avisos) - Entidades, Repositorio, API y Frontend Wizard integración

This commit is contained in:
2025-12-17 13:51:48 -03:00
parent f1bd25ea79
commit 1b88394b00
12 changed files with 353 additions and 4 deletions

View File

@@ -123,6 +123,37 @@ BEGIN
FOREIGN KEY (CategoryId) REFERENCES Categories(Id) ON DELETE CASCADE
);
END
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Listings')
BEGIN
CREATE TABLE Listings (
Id INT IDENTITY(1,1) PRIMARY KEY,
CategoryId INT NOT NULL,
OperationId INT NOT NULL,
Title NVARCHAR(200) NOT NULL,
Description NVARCHAR(MAX) NULL,
Price DECIMAL(18,2) NOT NULL DEFAULT 0,
Currency NVARCHAR(3) DEFAULT 'ARS',
CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
Status NVARCHAR(20) DEFAULT 'Draft',
UserId INT NULL,
FOREIGN KEY (CategoryId) REFERENCES Categories(Id),
FOREIGN KEY (OperationId) REFERENCES Operations(Id),
FOREIGN KEY (UserId) REFERENCES Users(Id)
);
END
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ListingAttributeValues')
BEGIN
CREATE TABLE ListingAttributeValues (
Id INT IDENTITY(1,1) PRIMARY KEY,
ListingId INT NOT NULL,
AttributeDefinitionId INT NOT NULL,
Value NVARCHAR(MAX) NOT NULL,
FOREIGN KEY (ListingId) REFERENCES Listings(Id) ON DELETE CASCADE,
FOREIGN KEY (AttributeDefinitionId) REFERENCES AttributeDefinitions(Id) ON DELETE NO ACTION
);
END
";
await connection.ExecuteAsync(schemaSql);
}

View File

@@ -18,6 +18,7 @@ public static class DependencyInjection
services.AddScoped<ITokenService, Services.TokenService>();
services.AddScoped<IAuthService, Services.AuthService>();
services.AddScoped<IAttributeDefinitionRepository, AttributeDefinitionRepository>();
services.AddScoped<IListingRepository, ListingRepository>();
return services;
}
}
@@ -25,3 +26,4 @@ public static class DependencyInjection

View File

@@ -0,0 +1,73 @@
using System.Data;
using Dapper;
using SIGCM.Application.DTOs;
using SIGCM.Domain.Entities;
using SIGCM.Domain.Interfaces;
using SIGCM.Infrastructure.Data;
namespace SIGCM.Infrastructure.Repositories;
public class ListingRepository : IListingRepository
{
private readonly IDbConnectionFactory _connectionFactory;
public ListingRepository(IDbConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public async Task<int> CreateAsync(Listing listing, Dictionary<int, string> attributes)
{
using var conn = _connectionFactory.CreateConnection();
conn.Open();
using var transaction = conn.BeginTransaction();
try
{
var sqlListing = @"
INSERT INTO Listings (CategoryId, OperationId, Title, Description, Price, Currency, CreatedAt, Status, UserId)
VALUES (@CategoryId, @OperationId, @Title, @Description, @Price, @Currency, @CreatedAt, @Status, @UserId);
SELECT CAST(SCOPE_IDENTITY() as int);";
var listingId = await conn.QuerySingleAsync<int>(sqlListing, listing, transaction);
if (attributes != null && attributes.Any())
{
var sqlAttr = @"
INSERT INTO ListingAttributeValues (ListingId, AttributeDefinitionId, Value)
VALUES (@ListingId, @AttributeDefinitionId, @Value)";
foreach (var attr in attributes)
{
await conn.ExecuteAsync(sqlAttr, new { ListingId = listingId, AttributeDefinitionId = attr.Key, Value = attr.Value }, transaction);
}
}
transaction.Commit();
return listingId;
}
catch
{
transaction.Rollback();
throw;
}
}
public async Task<Listing?> GetByIdAsync(int id)
{
using var conn = _connectionFactory.CreateConnection();
return await conn.QuerySingleOrDefaultAsync<Listing>("SELECT * FROM Listings WHERE Id = @Id", new { Id = id });
}
public async Task<IEnumerable<Listing>> GetAllAsync()
{
using var conn = _connectionFactory.CreateConnection();
// A simple query for now
var sql = @"
SELECT l.*
FROM Listings l
ORDER BY l.CreatedAt DESC";
return await conn.QueryAsync<Listing>(sql);
}
}