From ef4325921b4c5313b7044ee19c602843183d0e7f Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Wed, 19 Aug 2026 11:14:49 +0500 Subject: [PATCH] =?UTF-8?q?=D1=83=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D1=8E=D1=89=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TemplateRoutes/TemplateRouteService.cs | 7 +++++-- .../TnsuPortal/CachingTnsuPortalClient.cs | 2 +- .../TnsuPortal/HttpTnsuPortalClient.cs | 7 ++++--- .../TnsuPortal/ITnsuPortalClient.cs | 2 +- .../TnsuPortal/TnsuPortalDtos.cs | 3 +++ .../ApplicationServices/TemplateRouteServiceTests.cs | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/backend/Tnsu.ApprovalRoute.Application/TemplateRoutes/TemplateRouteService.cs b/backend/Tnsu.ApprovalRoute.Application/TemplateRoutes/TemplateRouteService.cs index aae5af9..e1122c3 100644 --- a/backend/Tnsu.ApprovalRoute.Application/TemplateRoutes/TemplateRouteService.cs +++ b/backend/Tnsu.ApprovalRoute.Application/TemplateRoutes/TemplateRouteService.cs @@ -261,9 +261,12 @@ public sealed class TemplateRouteService( } else if (!string.IsNullOrWhiteSpace(step.Position)) { - resolvedEmail = await portalClient.GetEmployeeByPositionAsync(step.Position, initiatorCompany, cancellationToken); - if (string.IsNullOrWhiteSpace(resolvedEmail)) + var employeeByPosition = await portalClient.GetEmployeeByPositionAsync(step.Position, initiatorCompany, cancellationToken); + resolvedEmail = employeeByPosition.Email; + if (!employeeByPosition.Found) warning = $"Не найден сотрудник на должности «{step.Position}» в компании «{initiatorCompany}»."; + else if (string.IsNullOrWhiteSpace(resolvedEmail)) + warning = $"Сотрудник {employeeByPosition.Fio} на должности «{step.Position}» найден, но email не указан в системе портала."; } else if (step.ProjectRole is not (null or ProjectRole.None)) { diff --git a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/CachingTnsuPortalClient.cs b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/CachingTnsuPortalClient.cs index 6ddab54..785e246 100644 --- a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/CachingTnsuPortalClient.cs +++ b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/CachingTnsuPortalClient.cs @@ -22,7 +22,7 @@ public sealed class CachingTnsuPortalClient(HttpTnsuPortalClient inner, IMemoryC $"emp:email:{email.ToLowerInvariant()}", () => inner.GetEmployeeByEmailAsync(email, cancellationToken)); - public Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) => + public Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) => GetOrAddAsync( $"emp:position:{position.ToLowerInvariant()}|{company.ToLowerInvariant()}", () => inner.GetEmployeeByPositionAsync(position, company, cancellationToken)); diff --git a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/HttpTnsuPortalClient.cs b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/HttpTnsuPortalClient.cs index 24bd5e7..9c050ac 100644 --- a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/HttpTnsuPortalClient.cs +++ b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/HttpTnsuPortalClient.cs @@ -25,12 +25,12 @@ public sealed class HttpTnsuPortalClient( return new EmployeeDirectoryInfo(employee.CompanyId ?? Guid.Empty, employee.DepartmentId, employee.Company ?? string.Empty, employee.Position); } - public async Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) + public async Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) { var employee = await GetAsync( $"/Employee/ByPosition?position={Uri.EscapeDataString(position)}&company={Uri.EscapeDataString(company)}", cancellationToken); - return employee?.Email; + return new EmployeeLookupResult(employee is not null, employee?.Email, employee?.Fio); } public async Task GetManagerAsync(string email, string managerType, CancellationToken cancellationToken) @@ -107,7 +107,8 @@ public sealed class HttpTnsuPortalClient( [property: JsonPropertyName("company")] string? Company, [property: JsonPropertyName("companyId")] Guid? CompanyId, [property: JsonPropertyName("departmentId")] Guid? DepartmentId, - [property: JsonPropertyName("position")] string? Position); + [property: JsonPropertyName("position")] string? Position, + [property: JsonPropertyName("fio")] string? Fio); private sealed record ManagerResponse( [property: JsonPropertyName("managerEmail")] string? ManagerEmail); diff --git a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/ITnsuPortalClient.cs b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/ITnsuPortalClient.cs index 502affa..2821d9d 100644 --- a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/ITnsuPortalClient.cs +++ b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/ITnsuPortalClient.cs @@ -4,7 +4,7 @@ public interface ITnsuPortalClient { Task GetEmployeeByEmailAsync(string email, CancellationToken cancellationToken); - Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken); + Task GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken); Task GetManagerAsync(string email, string managerType, CancellationToken cancellationToken); diff --git a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/TnsuPortalDtos.cs b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/TnsuPortalDtos.cs index 29fe375..9a0636b 100644 --- a/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/TnsuPortalDtos.cs +++ b/backend/Tnsu.ApprovalRoute.Infrastructure/TnsuPortal/TnsuPortalDtos.cs @@ -5,3 +5,6 @@ namespace Tnsu.ApprovalRoute.Infrastructure.TnsuPortal; public sealed record EmployeeDirectoryInfo(Guid CompanyId, Guid? DepartmentId, string Company, string? Position); public sealed record ProjectExecutorInfo(ProjectRole ProjectRole, string Email); + +/// Найден ли сотрудник вообще — отдельно от того, заполнен ли у него email в портале (это разные проблемы). +public sealed record EmployeeLookupResult(bool Found, string? Email, string? Fio); diff --git a/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/TemplateRouteServiceTests.cs b/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/TemplateRouteServiceTests.cs index cc77636..ad5e0e7 100644 --- a/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/TemplateRouteServiceTests.cs +++ b/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/TemplateRouteServiceTests.cs @@ -560,7 +560,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture x.GetEmployeeByPositionAsync("Lead", "ТОО TANSU Construction", It.IsAny())) - .ReturnsAsync("lead@tnsu.kz"); + .ReturnsAsync(new EmployeeLookupResult(true, "lead@tnsu.kz", "Иванов Иван Иванович")); var services = TestServiceProviderFactory.Build(_connectionString, portalClient: portalClient.Object); var routeService = services.GetRequiredService();