Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Voltiq.Application.Common.Interfaces;

public interface IAuthenticatedRequest<TResponse> : IRequest<TResponse>
public interface IAuthenticatedRequest<out TResponse> : IRequest<TResponse>
{
Guid UserId { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public async Task<ErrorOr<BudgetDetailResponse>> Handle(
return Error.NotFound(description: ResourceErrorMessages.CLIENTE_NAO_ENCONTRADO);

var materialLookup = new Dictionary<Guid, Material>();
foreach (var item in command.Items.Where(i => i.MaterialId.HasValue))
foreach (var materialId in command.Items.Where(i => i.MaterialId.HasValue).Select(i => i.MaterialId!.Value).Distinct())
{
var material = await materialReadOnly.GetByIdAndUserIdAsync(
item.MaterialId!.Value, command.UserId, cancellationToken);
materialId, command.UserId, cancellationToken);

if (material is null)
return Error.NotFound(description: ResourceErrorMessages.MATERIAL_NAO_ENCONTRADO);

materialLookup[item.MaterialId!.Value] = material;
materialLookup[materialId] = material;
}

var budget = Budget.Register(command.UserId, command.ClientId);
Expand Down
11 changes: 0 additions & 11 deletions src/Voltiq.Functions/GenerateReportFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class GenerateReportMessage
public class GenerateReportFunction
{
private readonly ILogger<GenerateReportFunction> _logger;
private readonly IBudgetReadOnlyRepository _budgetRepository;
private readonly IBudgetUpdateOnlyRepository _budgetUpdateRepository;
private readonly IClientReadOnlyRepository _clientRepository;
private readonly IReportGenerator _reportGenerator;
Expand All @@ -26,15 +25,13 @@ public class GenerateReportFunction

public GenerateReportFunction(
ILogger<GenerateReportFunction> logger,
IBudgetReadOnlyRepository budgetRepository,
IBudgetUpdateOnlyRepository budgetUpdateRepository,
IClientReadOnlyRepository clientRepository,
IReportGenerator reportGenerator,
IStorageService storageService,
IUnitOfWork unitOfWork)
{
_logger = logger;
_budgetRepository = budgetRepository;
_budgetUpdateRepository = budgetUpdateRepository;
_clientRepository = clientRepository;
_reportGenerator = reportGenerator;
Expand All @@ -45,8 +42,6 @@ public GenerateReportFunction(
[Function(nameof(GenerateReportFunction))]
public async Task Run([QueueTrigger("budget-reports")] string message, CancellationToken cancellationToken)
{
_logger.LogInformation("Processing report generation message: {Message}", message);

try
{
var msg = JsonSerializer.Deserialize<GenerateReportMessage>(message);
Expand Down Expand Up @@ -79,31 +74,25 @@ public async Task Run([QueueTrigger("budget-reports")] string message, Cancellat

try
{
_logger.LogInformation("Generating PDF for Budget ID: {BudgetId}", budget.Id);
var pdfBytes = await _reportGenerator.GenerateAsync(reportData, cancellationToken);

var fileName = $"budget-{budget.Id}.pdf";

_logger.LogInformation("Uploading PDF for Budget ID: {BudgetId} to Blob Storage", budget.Id);
var uri = await _storageService.UploadAsync(fileName, pdfBytes, "application/pdf", cancellationToken);

budget.SetPdfGenerationSuccess(uri);
await _unitOfWork.SaveChangesAsync(cancellationToken);

_logger.LogInformation("Report generated and budget status updated successfully. URI: {Uri}", uri);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error generating report for budget ID: {BudgetId}", budget.Id);
budget.SetPdfGenerationFailed();
await _unitOfWork.SaveChangesAsync(CancellationToken.None);
throw;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing report generation for message: {Message}", message);
throw;
}
}
}
2 changes: 1 addition & 1 deletion src/Voltiq.Functions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@
.UseFunctionsWorkerDefaults()
.UseAzureMonitorExporter();

builder.Build().Run();
await builder.Build().RunAsync();
4 changes: 2 additions & 2 deletions src/Voltiq.Infrastructure/Auth/Argon2PasswordHasher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public string Hash(string password)
return $"{Convert.ToBase64String(salt)}.{Convert.ToBase64String(hash)}";
}

public bool Verify(string password, string storedHash)
public bool Verify(string password, string hash)
{
var parts = storedHash.Split('.');
var parts = hash.Split('.');
if (parts.Length != 2) return false;

var salt = Convert.FromBase64String(parts[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ public void Remove(Domain.Entities.Budget entity)
}

public async Task<Domain.Entities.Budget?> GetTrackedByIdAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Budgets
.FirstOrDefaultAsync(b => b.Id == id && b.UserId == userId, cancellationToken);
}

public async Task<Domain.Entities.Budget?> GetTrackedByIdWithItemsAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Budgets
.Include(b => b.Items)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public sealed class ClientRepository(ApplicationDbContext context)
}

public async Task<Domain.Entities.Client?> GetByIdAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Clients
.AsNoTracking()
Expand All @@ -37,7 +37,7 @@ public async Task<bool> ExistsWithEmailForUserAsync(
}

public async Task<Domain.Entities.Client?> GetTrackedByIdAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Clients
.FirstOrDefaultAsync(c => c.Id == id && c.UserId == userId, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public sealed class MaterialRepository(ApplicationDbContext context)
}

public async Task<Domain.Entities.Material?> GetByIdAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Materials
.AsNoTracking()
Expand All @@ -41,7 +41,7 @@ public sealed class MaterialRepository(ApplicationDbContext context)
}

public async Task<Domain.Entities.Material?> GetTrackedByIdAndUserIdAsync(
Guid id, Guid userId, CancellationToken cancellationToken)
Guid id, Guid userId, CancellationToken cancellationToken = default)
{
return await context.Materials
.FirstOrDefaultAsync(m => m.Id == id && m.UserId == userId, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ public async Task GetByUserIdWithClientAsync_ShouldReturnBudgetsWithClientLoaded
var budgets = await _budgetRepository.GetByUserIdWithClientAsync(user.Id, TestContext.Current.CancellationToken);

budgets.Count.ShouldBe(1);
budgets.First().Client.ShouldNotBeNull();
budgets.First().Client.Name.ShouldBe(client.Name);
budgets[0].Client.ShouldNotBeNull();
budgets[0].Client.Name.ShouldBe(client.Name);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ClientRepositoryTests(PostgreSqlContainerFixture fixture)
private static readonly Guid UserId = Guid.NewGuid();

private ClientRepository _clientRepository = null!;
private IClientReadOnlyRepository _clientReadOnly = null!;
private ClientRepository? _clientReadOnly;

private ApplicationDbContext _dbContext = null!;
private UnitOfWork _unitOfWork = null!;
Expand Down Expand Up @@ -49,7 +49,7 @@ public async Task AddAndGetById_ShouldPersistClient()
var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id);

var found =
await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken);
await _clientReadOnly!.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken);

found.ShouldNotBeNull();
found.Id.ShouldBe(client.Id);
Expand Down Expand Up @@ -89,7 +89,7 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnClient_WhenBelongsToUser()
var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork);
var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user.Id);

var found = await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user.Id,
var found = await _clientReadOnly!.GetByIdAndUserIdAsync(client.Id, user.Id,
TestContext.Current.CancellationToken);

found.ShouldNotBeNull();
Expand All @@ -105,7 +105,7 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenClientBelongsToAnot

var client = await TestDataBuilder.SeedClientAsync(_clientRepository, _unitOfWork, user1.Id);

var found = await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user2.Id,
var found = await _clientReadOnly!.GetByIdAndUserIdAsync(client.Id, user2.Id,
TestContext.Current.CancellationToken);

found.ShouldBeNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class MaterialRepositoryTests(PostgreSqlContainerFixture fixture)
private static readonly Guid UserId = Guid.NewGuid();

private MaterialRepository _materialRepository = null!;
private IMaterialReadOnlyRepository _materialReadOnly = null!;
private MaterialRepository? _materialReadOnly;
private ApplicationDbContext _dbContext = null!;
private UnitOfWork _unitOfWork = null!;
private UserRepository _userRepository = null!;
Expand Down Expand Up @@ -80,7 +80,7 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnMaterial_WhenBelongsToUser()
var user = await TestDataBuilder.SeedUserAsync(_userRepository, _unitOfWork);
var material = await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user.Id);

var found = await _materialReadOnly.GetByIdAndUserIdAsync(material.Id, user.Id, TestContext.Current.CancellationToken);
var found = await _materialReadOnly!.GetByIdAndUserIdAsync(material.Id, user.Id, TestContext.Current.CancellationToken);

found.ShouldNotBeNull();
found.Id.ShouldBe(material.Id);
Expand All @@ -95,7 +95,7 @@ public async Task GetByIdAndUserIdAsync_ShouldReturnNull_WhenMaterialBelongsToAn

var material = await TestDataBuilder.SeedMaterialAsync(_materialRepository, _unitOfWork, user1.Id);

var found = await _materialReadOnly.GetByIdAndUserIdAsync(material.Id, user2.Id, TestContext.Current.CancellationToken);
var found = await _materialReadOnly!.GetByIdAndUserIdAsync(material.Id, user2.Id, TestContext.Current.CancellationToken);

found.ShouldBeNull();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class SoftDeleteTests(PostgreSqlContainerFixture fixture)
private static readonly Guid UserId = Guid.NewGuid();

private ClientRepository _clientRepository = null!;
private IClientReadOnlyRepository _clientReadOnly = null!;
private ClientRepository? _clientReadOnly;
private ApplicationDbContext _dbContext = null!;
private UnitOfWork _unitOfWork = null!;
private UserRepository _userRepository = null!;
Expand Down Expand Up @@ -89,7 +89,7 @@ public async Task GlobalQueryFilter_ShouldExcludeDeletedEntitiesFromNormalQuerie
await _unitOfWork.SaveChangesAsync(TestContext.Current.CancellationToken);

var found =
await _clientReadOnly.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken);
await _clientReadOnly!.GetByIdAndUserIdAsync(client.Id, user.Id, TestContext.Current.CancellationToken);

found.ShouldBeNull();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ public ValueTask InitializeAsync()
return ValueTask.CompletedTask;
}

public ValueTask DisposeAsync() => ValueTask.CompletedTask;
public ValueTask DisposeAsync()
{
GC.SuppressFinalize(this);
return ValueTask.CompletedTask;
}

[Fact]
public async Task SendMessageAsync_ShouldCreateQueueAndSendMessage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public ValueTask InitializeAsync()
return ValueTask.CompletedTask;
}

public ValueTask DisposeAsync() => ValueTask.CompletedTask;
public ValueTask DisposeAsync()
{
GC.SuppressFinalize(this);
return ValueTask.CompletedTask;
}

[Fact]
public async Task UploadAsync_ShouldUploadFileAndReturnBlobUri()
Expand Down
Loading