mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 10:43:13 +00:00
fix(work-orders): block comment creation on canceled work orders
This commit is contained in:
parent
f47264ec4d
commit
4b8a08fb10
2 changed files with 78 additions and 3 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using System.Security.Claims;
|
||||
using Data.SeaHavenIndustries;
|
||||
using Data.SeaHavenIndustries.Enums;
|
||||
using SeaHaven.DataServices.Interfaces;
|
||||
using SeaHaven.Services.DTOs;
|
||||
using SeaHaven.Services.Exceptions;
|
||||
|
|
@ -48,9 +49,13 @@ namespace SeaHaven.Services.Implementation
|
|||
string? documentUrl = null)
|
||||
{
|
||||
var accountId = _accountResolver.ResolveAccountFilter(user);
|
||||
if (!await _detailData.ExistsAsync(workOrderId, CancellationToken.None, accountId))
|
||||
var workOrder = await _detailData.GetWorkOrderForMediaAsync(
|
||||
workOrderId, CancellationToken.None, accountId);
|
||||
if (workOrder == null)
|
||||
throw new WorkOrderBoardValidationException("NotFound", "Work order not found.");
|
||||
|
||||
EnsureCommentMutationAllowed(workOrder.LifecycleStatus);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Text))
|
||||
throw new WorkOrderBoardValidationException("InvalidValue", "Comment text is required.");
|
||||
|
||||
|
|
@ -83,8 +88,7 @@ namespace SeaHaven.Services.Implementation
|
|||
if (workOrder == null)
|
||||
throw new WorkOrderBoardValidationException("NotFound", "Work order not found.");
|
||||
|
||||
if (!WorkOrderBoardMutationRules.CanMutateComments(workOrder.LifecycleStatus))
|
||||
throw new WorkOrderBoardValidationException("ReadOnly", "Work order is read-only in its current status.");
|
||||
EnsureCommentMutationAllowed(workOrder.LifecycleStatus);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Text))
|
||||
throw new WorkOrderBoardValidationException("InvalidValue", "Comment text is required.");
|
||||
|
|
@ -111,6 +115,12 @@ namespace SeaHaven.Services.Implementation
|
|||
return WorkOrderCommentProjection.ToDto(comment, authorNames);
|
||||
}
|
||||
|
||||
private static void EnsureCommentMutationAllowed(LifecycleStatus? status)
|
||||
{
|
||||
if (!WorkOrderBoardMutationRules.CanMutateComments(status))
|
||||
throw new WorkOrderBoardValidationException("ReadOnly", "Work order is read-only in its current status.");
|
||||
}
|
||||
|
||||
private static bool IsBoardEditableComment(Comments comment)
|
||||
=> string.Equals(comment.CommentType, "General", StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(comment.RecordType, "WorkOrder", StringComparison.OrdinalIgnoreCase);
|
||||
|
|
|
|||
|
|
@ -159,6 +159,71 @@ public class WorkOrderCompletedSelectiveLockTests
|
|||
Assert.Equal("Follow-up", result.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddComment_Completed_AddsText()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
var context = new ApplicationDbContext(options);
|
||||
context.workOrders.Add(CompletedWorkOrder());
|
||||
context.Users.Add(new ApplicationUser
|
||||
{
|
||||
Id = "user-author",
|
||||
UserName = "author",
|
||||
FirstName = "Alice",
|
||||
LastName = "Dispatcher"
|
||||
});
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
var service = new WorkOrderCommentService(
|
||||
new WorkOrderDetailDataService(context),
|
||||
new CommentDataService(context),
|
||||
new UserDataService(context),
|
||||
WorkOrderAccountTestHelpers.Resolver(context));
|
||||
|
||||
var result = await service.AddCommentAsync(
|
||||
1,
|
||||
new WorkOrderCommentCreateDto { Text = "Follow-up" },
|
||||
WorkOrderAccountTestHelpers.OrgWideAdmin("user-author"),
|
||||
"user-author");
|
||||
|
||||
Assert.Equal("Follow-up", result.Text);
|
||||
Assert.Equal("user-author", result.AuthorId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddComment_Canceled_ThrowsReadOnly()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
var context = new ApplicationDbContext(options);
|
||||
context.workOrders.Add(new WorkOrder
|
||||
{
|
||||
Id = 1,
|
||||
LifecycleStatus = LifecycleStatus.Canceled,
|
||||
RowVersion = new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 }
|
||||
});
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
var service = new WorkOrderCommentService(
|
||||
new WorkOrderDetailDataService(context),
|
||||
new CommentDataService(context),
|
||||
new UserDataService(context),
|
||||
WorkOrderAccountTestHelpers.Resolver(context));
|
||||
|
||||
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
|
||||
service.AddCommentAsync(
|
||||
1,
|
||||
new WorkOrderCommentCreateDto { Text = "Should not persist" },
|
||||
WorkOrderAccountTestHelpers.OrgWideAdmin("user-author"),
|
||||
"user-author"));
|
||||
|
||||
Assert.Equal("ReadOnly", ex.Code);
|
||||
Assert.Empty(context.Comments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddMedia_Completed_AllowsExtra()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue