feat: PRD-002 Product CRUD #40
@@ -1,14 +0,0 @@
|
|||||||
using SIGCM2.Application.Abstractions.Persistence;
|
|
||||||
|
|
||||||
namespace SIGCM2.Application.Products;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// STUB — PRD-002 replaces the DI binding with a real Dapper impl against dbo.Product.
|
|
||||||
/// Returns false for all queries so DeactivateProductTypeCommandHandler guard always passes.
|
|
||||||
/// This is intentional for PRD-001: the mechanism is installed; the data feed arrives in PRD-002.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class NullProductQueryRepository : IProductQueryRepository
|
|
||||||
{
|
|
||||||
public Task<bool> ExistsActiveByProductTypeAsync(int productTypeId, CancellationToken ct = default)
|
|
||||||
=> Task.FromResult(false);
|
|
||||||
}
|
|
||||||
@@ -19,16 +19,19 @@ public sealed class ProductQueryRepository : IProductQueryRepository
|
|||||||
public async Task<bool> ExistsActiveByProductTypeAsync(int productTypeId, CancellationToken ct = default)
|
public async Task<bool> ExistsActiveByProductTypeAsync(int productTypeId, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
const string sql = """
|
const string sql = """
|
||||||
SELECT COUNT(1)
|
SELECT CASE
|
||||||
FROM dbo.Product
|
WHEN EXISTS (
|
||||||
|
SELECT 1 FROM dbo.Product
|
||||||
WHERE ProductTypeId = @ProductTypeId
|
WHERE ProductTypeId = @ProductTypeId
|
||||||
AND IsActive = 1
|
AND IsActive = 1
|
||||||
|
) THEN 1 ELSE 0
|
||||||
|
END
|
||||||
""";
|
""";
|
||||||
|
|
||||||
await using var connection = _factory.CreateConnection();
|
await using var connection = _factory.CreateConnection();
|
||||||
await connection.OpenAsync(ct);
|
await connection.OpenAsync(ct);
|
||||||
|
|
||||||
var count = await connection.ExecuteScalarAsync<int>(sql, new { ProductTypeId = productTypeId });
|
var result = await connection.ExecuteScalarAsync<int>(sql, new { ProductTypeId = productTypeId });
|
||||||
return count > 0;
|
return result == 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
using FluentAssertions;
|
|
||||||
using SIGCM2.Application.Products;
|
|
||||||
|
|
||||||
namespace SIGCM2.Application.Tests.ProductTypes;
|
|
||||||
|
|
||||||
public class NullProductQueryRepositoryTests
|
|
||||||
{
|
|
||||||
private readonly NullProductQueryRepository _sut = new();
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ExistsActiveByProductTypeAsync_AlwaysReturnsFalse()
|
|
||||||
{
|
|
||||||
var result = await _sut.ExistsActiveByProductTypeAsync(productTypeId: 1);
|
|
||||||
|
|
||||||
result.Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task ExistsActiveByProductTypeAsync_WithCancellationToken_DoesNotThrow()
|
|
||||||
{
|
|
||||||
using var cts = new CancellationTokenSource();
|
|
||||||
var act = async () => await _sut.ExistsActiveByProductTypeAsync(productTypeId: 999, ct: cts.Token);
|
|
||||||
|
|
||||||
await act.Should().NotThrowAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user