diff --git a/backend/src/Socialize.Api/Modules/Feedback/Handlers/AttachMyFeedbackScreenshot.cs b/backend/src/Socialize.Api/Modules/Feedback/Handlers/AttachMyFeedbackScreenshot.cs index 63e5593..49128ee 100644 --- a/backend/src/Socialize.Api/Modules/Feedback/Handlers/AttachMyFeedbackScreenshot.cs +++ b/backend/src/Socialize.Api/Modules/Feedback/Handlers/AttachMyFeedbackScreenshot.cs @@ -38,8 +38,7 @@ public class AttachMyFeedbackScreenshotHandler( Guid reporterUserId = User.GetUserId(); FeedbackReport? report = await dbContext.FeedbackReports - .Include(candidate => candidate.Tags) - .Include(candidate => candidate.Screenshot) + .AsNoTracking() .SingleOrDefaultAsync( candidate => candidate.Id == id && candidate.ReporterUserId == reporterUserId, ct); @@ -50,7 +49,11 @@ public class AttachMyFeedbackScreenshotHandler( return; } - if (report.Screenshot is not null) + bool hasScreenshot = await dbContext.FeedbackScreenshots + .AsNoTracking() + .AnyAsync(candidate => candidate.FeedbackReportId == report.Id, ct); + + if (hasScreenshot) { AddError("A screenshot is already attached to this feedback report."); await SendErrorsAsync(StatusCodes.Status409Conflict, ct); @@ -94,7 +97,7 @@ public class AttachMyFeedbackScreenshotHandler( } DateTimeOffset now = DateTimeOffset.UtcNow; - report.Screenshot = new FeedbackScreenshot + FeedbackScreenshot screenshot = new() { Id = screenshotId, FeedbackReportId = report.Id, @@ -105,10 +108,45 @@ public class AttachMyFeedbackScreenshotHandler( BlobName = blobName, CreatedAt = now, }; - report.LastActivityAt = now; - await dbContext.SaveChangesAsync(ct); - await SendOkAsync(report.ToDto(), ct); + await using Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = + await dbContext.Database.BeginTransactionAsync(ct); + + dbContext.FeedbackScreenshots.Add(screenshot); + try + { + await dbContext.SaveChangesAsync(ct); + } + catch (DbUpdateException) + { + await transaction.RollbackAsync(ct); + AddError("A screenshot is already attached to this feedback report."); + await SendErrorsAsync(StatusCodes.Status409Conflict, ct); + return; + } + + int updatedRows = await dbContext.FeedbackReports + .Where(candidate => candidate.Id == report.Id && candidate.ReporterUserId == reporterUserId) + .ExecuteUpdateAsync( + setters => setters.SetProperty(candidate => candidate.LastActivityAt, now), + ct); + + if (updatedRows == 0) + { + await transaction.RollbackAsync(ct); + await SendNotFoundAsync(ct); + return; + } + + await transaction.CommitAsync(ct); + + FeedbackReport responseReport = await dbContext.FeedbackReports + .AsNoTracking() + .Include(candidate => candidate.Tags) + .Include(candidate => candidate.Screenshot) + .SingleAsync(candidate => candidate.Id == report.Id, ct); + + await SendOkAsync(responseReport.ToDto(), ct); } private static string NormalizeFileName(string? fileName, string extension)