shoc-backend/SeaHavenIndustries.Tests/WorkOrderAccountScopeTests.cs
Arthur Bassi 61923b2a7d feat(work-orders): stamp board create account from location
Org-wide create no longer depends on customer name. POST /workorders/board requires locationId and stamps WorkOrder.AccountId from Location.AccountId.
2026-08-26 09:12:48 -03:00

766 lines
28 KiB
C#

using System.Security.Claims;
using FluentValidation;
using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
using Microsoft.EntityFrameworkCore;
using SeaHaven.DataServices.Implementation;
using SeaHaven.Services.DTOs;
using SeaHaven.Services.Exceptions;
using SeaHaven.Services.Helpers;
using SeaHaven.Services.Implementation;
using SeaHaven.Services.Validation;
using Xunit;
namespace SeaHavenIndustries.Tests;
public class WorkOrderAccountScopeTests
{
private static ApplicationDbContext CreateContext()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
return new ApplicationDbContext(options);
}
private static WorkOrderBoardCreateService CreateBoardCreate(ApplicationDbContext context)
{
var resolver = WorkOrderAccountTestHelpers.Resolver(context);
var boardData = new WorkOrderBoardDataService(context);
var mutationData = new WorkOrderBoardMutationDataService(context);
var boardService = new WorkOrderBoardService(boardData, resolver);
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
return new WorkOrderBoardCreateService(
boardData, mutationData, boardService, audit, new WorkOrderBoardCreateValidation(), resolver);
}
[Fact]
public async Task BoardCreate_WithAccountClaim_StampsAccountId()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 7, "Scoped Co");
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 11, accountId: 7);
var create = CreateBoardCreate(context);
var user = WorkOrderAccountTestHelpers.AccountUser("actor-1", 7, "Dispatcher");
var row = await create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 11
},
user,
"actor-1");
var wo = await context.workOrders.AsNoTracking().SingleAsync(w => w.Id == row.Id);
Assert.Equal(7, wo.AccountId);
Assert.Equal(11, wo.LocationId);
}
[Fact]
public async Task BoardCreate_MissingScope_ThrowsForbidden()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 11, accountId: 1);
var create = CreateBoardCreate(context);
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 11
},
WorkOrderAccountTestHelpers.MissingScope(),
"actor-1"));
Assert.Equal("Forbidden", ex.Code);
Assert.Empty(context.workOrders);
}
[Fact]
public async Task BoardCreate_OrgWide_WithLocationAccount_StampsAccountId()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 3, "Unique Customer");
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 22, accountId: 3, name: "DAL");
var create = CreateBoardCreate(context);
var row = await create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PO,
SiteCode = "DAL",
LocationId = 22,
Customer = "Ignored Client Customer"
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1");
var wo = await context.workOrders.AsNoTracking().SingleAsync(w => w.Id == row.Id);
Assert.Equal(3, wo.AccountId);
Assert.Equal(22, wo.LocationId);
Assert.Equal("Ignored Client Customer", wo.Customer);
}
[Fact]
public async Task BoardCreate_OrgWide_LocationWithoutAccount_ThrowsAccountUnresolved()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 33, accountId: null);
var create = CreateBoardCreate(context);
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 33
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1"));
Assert.Equal("AccountUnresolved", ex.Code);
Assert.Empty(context.workOrders);
}
[Fact]
public async Task BoardCreate_OrgWide_MissingLocation_ThrowsNotFound()
{
await using var context = CreateContext();
var create = CreateBoardCreate(context);
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 404
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1"));
Assert.Equal("NotFound", ex.Code);
Assert.Empty(context.workOrders);
}
[Fact]
public async Task BoardCreate_MissingLocationId_ThrowsValidation()
{
await using var context = CreateContext();
var create = CreateBoardCreate(context);
await Assert.ThrowsAsync<ValidationException>(() =>
create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5"
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1"));
Assert.Empty(context.workOrders);
}
[Fact]
public async Task BoardCreate_Scoped_LocationOfOtherAccount_ThrowsForbidden()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 50, accountId: 2);
var create = CreateBoardCreate(context);
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 50
},
WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher"),
"disp-1"));
Assert.Equal("Forbidden", ex.Code);
Assert.Empty(context.workOrders);
}
[Fact]
public async Task BoardCreate_OrgWide_ServiceOmitted_Succeeds()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 3, "Org");
await WorkOrderAccountTestHelpers.EnsureLocationAsync(context, id: 60, accountId: 3);
var create = CreateBoardCreate(context);
var row = await create.CreateAsync(
new WorkOrderBoardCreateRequestDto
{
WorkOrderType = WorkOrderType.PM,
SiteCode = "BK5",
LocationId = 60
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1");
Assert.Null(row.Pm);
var wo = await context.workOrders.AsNoTracking().SingleAsync(w => w.Id == row.Id);
Assert.Equal(3, wo.AccountId);
}
[Fact]
public async Task Board_ScopedUser_HidesOtherAccountAndNullAccountRows()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
context.workOrders.AddRange(
new WorkOrder
{
Id = 1,
InternalWONumber = "00000000001",
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
ScheduledDate = new DateTime(2026, 8, 10),
istemplate = false
},
new WorkOrder
{
Id = 2,
InternalWONumber = "00000000002",
AccountId = 2,
LifecycleStatus = LifecycleStatus.Scheduled,
ScheduledDate = new DateTime(2026, 8, 11),
istemplate = false
},
new WorkOrder
{
Id = 3,
InternalWONumber = "00000000003",
AccountId = null,
LifecycleStatus = LifecycleStatus.Scheduled,
ScheduledDate = new DateTime(2026, 8, 12),
istemplate = false
});
await context.SaveChangesAsync();
var resolver = WorkOrderAccountTestHelpers.Resolver(context);
var boardService = new WorkOrderBoardService(new WorkOrderBoardDataService(context), resolver);
var scoped = await boardService.GetBoardAsync(
new WorkOrderBoardQueryDto
{
WeekStart = new DateOnly(2026, 8, 10),
WeekEnd = new DateOnly(2026, 8, 14)
},
WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher"),
"disp-1");
Assert.Single(scoped.Scheduled);
Assert.Equal(1, scoped.Scheduled[0].Id);
var orgWide = await boardService.GetBoardAsync(
new WorkOrderBoardQueryDto
{
WeekStart = new DateOnly(2026, 8, 10),
WeekEnd = new DateOnly(2026, 8, 14)
},
WorkOrderAccountTestHelpers.OrgWideAdmin(),
"admin-1");
Assert.Equal(3, orgWide.Scheduled.Count);
}
[Fact]
public async Task Detail_CrossAccount_ReturnsNull()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
context.workOrders.Add(new WorkOrder
{
Id = 10,
InternalWONumber = "00000000010",
AccountId = 2,
LifecycleStatus = LifecycleStatus.Incomplete,
istemplate = false
});
await context.SaveChangesAsync();
var resolver = WorkOrderAccountTestHelpers.Resolver(context);
var boardService = new WorkOrderBoardService(new WorkOrderBoardDataService(context), resolver);
var detail = new WorkOrderDetailService(
boardService,
new WorkOrderDetailDataService(context),
new CompletionDocTemplateDataService(context),
new UserDataService(context),
resolver);
var result = await detail.GetDetailAsync(
10,
WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher"));
Assert.Null(result);
}
[Fact]
public async Task Ingest_UnresolvedCustomer_SkipsCreate()
{
await using var context = CreateContext();
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
var ingest = new WorkOrderIngestService(
new WorkOrderIngestDataService(context),
new SyncFieldMergePolicy(fieldLocks),
fieldLocks,
audit,
WorkOrderAccountTestHelpers.Resolver(context));
var result = await ingest.UpsertBatchAsync(new[]
{
new WorkOrderIngestPayloadDto
{
ExternalWorkOrderId = "EXT-1",
Description = "No account",
Customer = "Unknown Customer"
}
});
Assert.Equal(1, result.Skipped);
Assert.Equal(0, result.Created);
Assert.Empty(context.workOrders);
}
[Fact]
public async Task Ingest_UniqueCustomer_StampsAccountId()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 9, "Ingest Customer");
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
var ingest = new WorkOrderIngestService(
new WorkOrderIngestDataService(context),
new SyncFieldMergePolicy(fieldLocks),
fieldLocks,
audit,
WorkOrderAccountTestHelpers.Resolver(context));
var result = await ingest.UpsertBatchAsync(new[]
{
new WorkOrderIngestPayloadDto
{
ExternalWorkOrderId = "EXT-9",
Description = "Has account",
Customer = "Ingest Customer"
}
});
Assert.Equal(1, result.Created);
var wo = Assert.Single(context.workOrders);
Assert.Equal(9, wo.AccountId);
}
[Fact]
public async Task ResolveAccountFilter_MissingScope_ThrowsForbidden()
{
await using var context = CreateContext();
var resolver = WorkOrderAccountTestHelpers.Resolver(context);
var ex = Assert.Throws<WorkOrderBoardValidationException>(() =>
resolver.ResolveAccountFilter(WorkOrderAccountTestHelpers.MissingScope()));
Assert.Equal("Forbidden", ex.Code);
}
[Fact]
public async Task LegacyList_ScopedUser_HidesOtherAccountAndNullAccountRows()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var data = new WorkOrderDataService(context);
var scoped = (await data.GetAllWithDetailsAsync(accountId: 1)).ToList();
var dd = await data.GetNonTemplateWorkOrdersWithLocationsAsync(accountId: 1);
Assert.Single(scoped);
Assert.Equal(1, scoped[0].Id);
Assert.Single(dd);
Assert.Equal(1, dd[0].Id);
}
[Fact]
public async Task LegacyList_OrgWide_IncludesNullAccountRows()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var data = new WorkOrderDataService(context);
var orgWide = (await data.GetAllWithDetailsAsync(accountId: null)).ToList();
Assert.Equal(3, orgWide.Count);
}
[Fact]
public async Task LegacyDetail_CrossAccount_ReturnsNull()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var data = new WorkOrderDataService(context);
var detail = await data.GetWorkOrderDetailAsync(2, accountId: 1);
Assert.Null(detail);
}
[Fact]
public async Task LegacyDetail_SameAccount_ReturnsRow()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var data = new WorkOrderDataService(context);
var detail = await data.GetWorkOrderDetailAsync(1, accountId: 1);
Assert.NotNull(detail);
Assert.Equal(1, detail!.Id);
}
[Fact]
public async Task LegacyDetail_OrgWide_CanReadNullAccountRow()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var data = new WorkOrderDataService(context);
var detail = await data.GetWorkOrderDetailAsync(3, accountId: null);
Assert.NotNull(detail);
Assert.Equal(3, detail!.Id);
}
[Fact]
public async Task LegacyFiltered_ScopedUser_HidesOtherAccountAndNullAccountRows()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
var service = CreateLegacyReadService(context);
var page = await service.GetFilteredWorkOrdersAsync(
Array.Empty<string>(), null, null, null, null,
search: "", sort: "", sortby: "", page: 1, pageSize: 50, accountId: 1);
Assert.Equal(1, page.TotalCount);
Assert.Single(page.Data);
Assert.Equal(1, page.Data.First().Id);
}
private static WorkOrderService CreateLegacyReadService(ApplicationDbContext context)
{
return new WorkOrderService(
new WorkOrderDataService(context),
new CommentDataService(context),
new UserDataService(context),
new QuotesDataService(context),
fileStorage: null!,
new CreateWorkOrderValidation(),
new UpdateWorkOrderValidation(),
WorkOrderAccountTestHelpers.Resolver(context));
}
private static async Task SeedThreeAccountRowsAsync(ApplicationDbContext context)
{
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
context.workOrders.AddRange(
new WorkOrder
{
Id = 1,
InternalWONumber = "00000000001",
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
istemplate = false
},
new WorkOrder
{
Id = 2,
InternalWONumber = "00000000002",
AccountId = 2,
LifecycleStatus = LifecycleStatus.Scheduled,
istemplate = false
},
new WorkOrder
{
Id = 3,
InternalWONumber = "00000000003",
AccountId = null,
LifecycleStatus = LifecycleStatus.Scheduled,
istemplate = false
});
await context.SaveChangesAsync();
}
[Fact]
public async Task Comments_CrossAccount_GetAddUpdate_ReturnNotFound()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
context.Users.Add(new ApplicationUser
{
Id = "author-1",
UserName = "author",
FirstName = "Ann",
LastName = "Author"
});
context.workOrders.Add(new WorkOrder
{
Id = 20,
InternalWONumber = "00000000020",
AccountId = 2,
LifecycleStatus = LifecycleStatus.Scheduled,
istemplate = false
});
context.Comments.Add(new Comments
{
Id = 5,
WorkerOrderId = 20,
UserId = "author-1",
Commenttext = "Secret",
CommentType = "General",
RecordType = "WorkOrder",
CreatedDate = DateTime.UtcNow
});
await context.SaveChangesAsync();
var service = new WorkOrderCommentService(
new WorkOrderDetailDataService(context),
new CommentDataService(context),
new UserDataService(context),
WorkOrderAccountTestHelpers.Resolver(context));
var scoped = WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher");
Assert.Null(await service.GetCommentsAsync(20, scoped));
var addEx = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
service.AddCommentAsync(20, new WorkOrderCommentCreateDto { Text = "Nope" }, scoped, "disp-1"));
Assert.Equal("NotFound", addEx.Code);
var updateEx = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
service.UpdateCommentAsync(
20, 5, new WorkOrderCommentCreateDto { Text = "Nope" }, scoped, "author-1"));
Assert.Equal("NotFound", updateEx.Code);
}
[Fact]
public async Task Comments_SameAccount_AddSucceeds()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
context.Users.Add(new ApplicationUser
{
Id = "disp-1",
UserName = "disp",
FirstName = "Dee",
LastName = "Spatch"
});
context.workOrders.Add(new WorkOrder
{
Id = 21,
InternalWONumber = "00000000021",
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
istemplate = false
});
await context.SaveChangesAsync();
var service = new WorkOrderCommentService(
new WorkOrderDetailDataService(context),
new CommentDataService(context),
new UserDataService(context),
WorkOrderAccountTestHelpers.Resolver(context));
var scoped = WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher");
var result = await service.AddCommentAsync(
21, new WorkOrderCommentCreateDto { Text = "In scope" }, scoped, "disp-1");
Assert.Equal("In scope", result.Text);
Assert.Equal("disp-1", result.AuthorId);
}
[Fact]
public async Task LegacyCommentsByWorkOrder_CrossAccount_ReturnsNull()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
context.Comments.Add(new Comments
{
WorkerOrderId = 2,
Commenttext = "Other account",
CreatedDate = DateTime.UtcNow
});
await context.SaveChangesAsync();
var service = CreateLegacyReadService(context);
var result = await service.GetCommentsByWorkorderIdAsync(
2, WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher"));
Assert.Null(result);
}
[Fact]
public async Task CompletionDoc_CrossAccount_EnsureAndUpload_ThrowNotFound()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "B");
context.workOrders.Add(new WorkOrder
{
Id = 30,
InternalWONumber = "00000000030",
AccountId = 2,
LifecycleStatus = LifecycleStatus.Scheduled,
DocStatus = DocStatus.No,
RowVersion = new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 },
istemplate = false
});
await context.SaveChangesAsync();
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
var service = new WorkOrderCompletionService(
new WorkOrderCompletionDataService(context),
new CompletionDocTemplateDataService(context),
new WorkOrderDetailDataService(context),
audit,
WorkOrderAccountTestHelpers.Resolver(context));
var scoped = WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher");
var ensureEx = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
service.EnsureCanUploadCompletionDocAsync(30, scoped, "disp-1"));
Assert.Equal("NotFound", ensureEx.Code);
var uploadEx = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
service.UploadCompletionDocAsync(
30,
new WorkOrderCompletionDocUploadDto
{
WorkOrderVersion = Convert.ToBase64String(new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 })
},
"https://example.com/should-not-stick.pdf",
scoped,
"disp-1"));
Assert.Equal("NotFound", uploadEx.Code);
var wo = await context.workOrders.AsNoTracking().SingleAsync(w => w.Id == 30);
Assert.Null(wo.SignOffAttachment);
Assert.Equal(DocStatus.No, wo.DocStatus);
}
[Fact]
public async Task CompletionDoc_SameAccount_EnsureAllowsUpload()
{
await using var context = CreateContext();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1, "A");
var rowVersion = new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 };
context.workOrders.Add(new WorkOrder
{
Id = 31,
InternalWONumber = "00000000031",
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
DocStatus = DocStatus.No,
RowVersion = rowVersion,
istemplate = false
});
await context.SaveChangesAsync();
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
var service = new WorkOrderCompletionService(
new WorkOrderCompletionDataService(context),
new CompletionDocTemplateDataService(context),
new WorkOrderDetailDataService(context),
audit,
WorkOrderAccountTestHelpers.Resolver(context));
var scoped = WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher");
await service.EnsureCanUploadCompletionDocAsync(31, scoped, "disp-1");
var result = await service.UploadCompletionDocAsync(
31,
new WorkOrderCompletionDocUploadDto
{
WorkOrderVersion = Convert.ToBase64String(rowVersion)
},
"https://example.com/ok.pdf",
scoped,
"disp-1");
Assert.Equal(DocStatus.Yes, result.DocStatus);
Assert.Equal("https://example.com/ok.pdf", result.SignOffAttachment);
}
[Fact]
public async Task LegacyGetComments_ScopedUser_HidesOtherAccountComments()
{
await using var context = CreateContext();
await SeedThreeAccountRowsAsync(context);
context.Comments.AddRange(
new Comments
{
WorkerOrderId = 1,
Commenttext = "Account A note",
Documents = "a.pdf",
CreatedDate = DateTime.UtcNow
},
new Comments
{
WorkerOrderId = 2,
Commenttext = "Account B secret",
Documents = "b.pdf",
CreatedDate = DateTime.UtcNow
},
new Comments
{
WorkerOrderId = 3,
Commenttext = "Null account note",
CreatedDate = DateTime.UtcNow
});
await context.SaveChangesAsync();
var service = CreateLegacyReadService(context);
var scoped = await service.GetCommentsAsync(
WorkOrderAccountTestHelpers.AccountUser("disp-1", 1, "Dispatcher"));
Assert.Single(scoped);
Assert.Equal("Account A note", scoped.Single().Commenttext);
Assert.DoesNotContain(scoped, c => c.Commenttext == "Account B secret");
Assert.DoesNotContain(scoped, c => c.Commenttext == "Null account note");
var orgWide = await service.GetCommentsAsync(WorkOrderAccountTestHelpers.OrgWideAdmin());
Assert.Equal(3, orgWide.Count());
var missingEx = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
service.GetCommentsAsync(WorkOrderAccountTestHelpers.MissingScope()));
Assert.Equal("Forbidden", missingEx.Code);
}
}