Правки (#18)
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/18
This commit was merged in pull request #18.
This commit is contained in:
+118
-3
@@ -849,12 +849,127 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
|
||||
resolved.Value.Steps.ShouldContain(s => s.ExecutorEmail == "mechanic.kps@tnsu.kz");
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Резолв: если Директор Tansu совпадает с одним из Директоров компаний, эта строка убирается из CompanyDirectors, а не конфликтует")]
|
||||
[Fact(DisplayName = "Резолв: один и тот же директор двух разных компаний инициатора в CompanyDirectors схлопывается в одну строку")]
|
||||
public async Task ResolveAsync_ByHeadTypeCompanyDirectors_SamePersonDirectorOfTwoCompanies_CollapsesToOneRow()
|
||||
{
|
||||
// Arrange — инициатор числится в двух компаниях, и директор у них ОДИН и тот же
|
||||
// человек (например, холдинговая структура) — оба GetEmployeeByPositionAsync
|
||||
// возвращают один и тот же email.
|
||||
var portalClient = new Mock<ITnsuPortalClient>();
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByEmailAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<EmployeeDirectoryInfo>
|
||||
{
|
||||
new(CompanyId, DepartmentId, "ТОО TANSU Construction", "Начальник отдела службы безопасности"),
|
||||
new(Guid.NewGuid(), DepartmentId, "ТОО СТ Global", "Начальник отдела службы безопасности")
|
||||
});
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByPositionAsync("Директор", "ТОО TANSU Construction", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new EmployeeLookupResult(true, "same.director@tnsu.kz", "Общий директор"));
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByPositionAsync("Генеральный директор", "ТОО СТ Global", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new EmployeeLookupResult(true, "same.director@tnsu.kz", "Общий директор"));
|
||||
|
||||
var services = TestServiceProviderFactory.Build(_connectionString, portalClient: portalClient.Object);
|
||||
var routeService = services.GetRequiredService<TemplateRouteService>();
|
||||
var requestTypeService = services.GetRequiredService<RequestTypeService>();
|
||||
var stepService = services.GetRequiredService<TemplateRouteStepService>();
|
||||
|
||||
var requestTypeId = (await requestTypeService.CreateAsync(
|
||||
new CreateRequestTypeRequest("CompanyDirectors same person request", "/company-directors-same-person", null, null, "General"),
|
||||
CancellationToken.None)).Value.Id;
|
||||
var route = await routeService.CreateAsync(
|
||||
new CreateTemplateRouteRequest(requestTypeId, DepartmentId, CompanyId, ByProject: false, RequiresControl: false),
|
||||
CancellationToken.None);
|
||||
await stepService.CreateAsync(
|
||||
route.Value.Id,
|
||||
new CreateTemplateRouteStepRequest(1, null, null, null, HeadType.CompanyDirectors, RouteStepStatus.Approval, false, null),
|
||||
CancellationToken.None);
|
||||
|
||||
// Action
|
||||
var resolved = await routeService.ResolveAsync(
|
||||
new ResolveTemplateRouteRequest(requestTypeId, "someone@tnsu.kz", null, RouteStepStatus.Approval),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert — один человек не должен согласовывать одну и ту же заявку дважды
|
||||
// только из-за того, что он директор двух компаний инициатора одновременно.
|
||||
resolved.IsSuccess.ShouldBeTrue();
|
||||
resolved.Value.Steps.ShouldHaveSingleItem();
|
||||
resolved.Value.Steps[0].ExecutorEmail.ShouldBe("same.director@tnsu.kz");
|
||||
resolved.Value.Steps[0].PositionCode.ShouldBe(HeadType.CompanyDirectors);
|
||||
resolved.Value.Steps[0].Warning.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Резолв: один и тот же человек под РАЗНЫМИ email (общий Id в справочнике) в CompanyDirectors схлопывается в одну строку")]
|
||||
public async Task ResolveAsync_ByHeadTypeCompanyDirectors_SamePersonDifferentEmailsSameId_CollapsesToOneRow()
|
||||
{
|
||||
// Arrange — в справочнике api.tnsu.kz это один человек (один Guid Id), но у
|
||||
// него разные email в разных компаниях. Дедуп по email это бы не поймал —
|
||||
// отсюда и был реальный баг (одна и та же строка дважды на одном шаге).
|
||||
var personId = Guid.NewGuid();
|
||||
var portalClient = new Mock<ITnsuPortalClient>();
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByEmailAsync("someone@tnsu.kz", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<EmployeeDirectoryInfo>
|
||||
{
|
||||
new(CompanyId, DepartmentId, "ТОО TANSU Construction", "Начальник отдела службы безопасности"),
|
||||
new(Guid.NewGuid(), DepartmentId, "ТОО СТ Global", "Начальник отдела службы безопасности")
|
||||
});
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByPositionAsync("Директор", "ТОО TANSU Construction", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new EmployeeLookupResult(true, "director.tansu.email@tnsu.kz", "Общий директор"));
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByPositionAsync("Генеральный директор", "ТОО СТ Global", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new EmployeeLookupResult(true, "director.stglobal.email@tnsu.kz", "Общий директор"));
|
||||
// Оба email в справочнике резолвятся в ОДНОГО и того же человека (общий Id) —
|
||||
// как в реальном порталe, где у сотрудника может быть несколько адресов.
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByEmailAsync("director.tansu.email@tnsu.kz", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<EmployeeDirectoryInfo>
|
||||
{
|
||||
new(CompanyId, DepartmentId, "ТОО TANSU Construction", "Директор", personId)
|
||||
});
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByEmailAsync("director.stglobal.email@tnsu.kz", It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<EmployeeDirectoryInfo>
|
||||
{
|
||||
new(Guid.NewGuid(), DepartmentId, "ТОО СТ Global", "Генеральный директор", personId)
|
||||
});
|
||||
|
||||
var services = TestServiceProviderFactory.Build(_connectionString, portalClient: portalClient.Object);
|
||||
var routeService = services.GetRequiredService<TemplateRouteService>();
|
||||
var requestTypeService = services.GetRequiredService<RequestTypeService>();
|
||||
var stepService = services.GetRequiredService<TemplateRouteStepService>();
|
||||
|
||||
var requestTypeId = (await requestTypeService.CreateAsync(
|
||||
new CreateRequestTypeRequest("CompanyDirectors same person different emails request", "/company-directors-same-person-different-emails", null, null, "General"),
|
||||
CancellationToken.None)).Value.Id;
|
||||
var route = await routeService.CreateAsync(
|
||||
new CreateTemplateRouteRequest(requestTypeId, DepartmentId, CompanyId, ByProject: false, RequiresControl: false),
|
||||
CancellationToken.None);
|
||||
await stepService.CreateAsync(
|
||||
route.Value.Id,
|
||||
new CreateTemplateRouteStepRequest(1, null, null, null, HeadType.CompanyDirectors, RouteStepStatus.Approval, false, null),
|
||||
CancellationToken.None);
|
||||
|
||||
// Action
|
||||
var resolved = await routeService.ResolveAsync(
|
||||
new ResolveTemplateRouteRequest(requestTypeId, "someone@tnsu.kz", null, RouteStepStatus.Approval),
|
||||
CancellationToken.None);
|
||||
|
||||
// Assert — дедуп по Id сотрудника, а не по email: одна строка, а не две.
|
||||
resolved.IsSuccess.ShouldBeTrue();
|
||||
resolved.Value.Steps.ShouldHaveSingleItem();
|
||||
resolved.Value.Steps[0].PositionCode.ShouldBe(HeadType.CompanyDirectors);
|
||||
resolved.Value.Steps[0].Warning.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Резолв: если Директор Tansu совпадает с одним из Директоров компаний, эта строка убирается из CompanyDirectors")]
|
||||
public async Task ResolveAsync_DirectorTansuMatchesOneOfCompanyDirectors_RemovesDuplicateFromCompanyDirectors()
|
||||
{
|
||||
// Arrange — директор ТОО TANSU Construction (из шага CompanyDirectors, OrderNo 5)
|
||||
// и Директор Tansu (из шага DirectorTansu, OrderNo 10, идёт в маршруте последним) —
|
||||
// один и тот же человек с одним и тем же email.
|
||||
// и Директор Tansu (из шага DirectorTansu, OrderNo 10) — один и тот же человек
|
||||
// с одним и тем же email.
|
||||
var portalClient = new Mock<ITnsuPortalClient>();
|
||||
portalClient
|
||||
.Setup(x => x.GetEmployeeByEmailAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
|
||||
Reference in New Issue
Block a user