уточнил недостающие данные

This commit is contained in:
gorbenko.pavel
2026-08-19 11:14:49 +05:00
parent 58c27b2aa5
commit ef4325921b
6 changed files with 15 additions and 8 deletions
@@ -261,9 +261,12 @@ public sealed class TemplateRouteService(
} }
else if (!string.IsNullOrWhiteSpace(step.Position)) else if (!string.IsNullOrWhiteSpace(step.Position))
{ {
resolvedEmail = await portalClient.GetEmployeeByPositionAsync(step.Position, initiatorCompany, cancellationToken); var employeeByPosition = await portalClient.GetEmployeeByPositionAsync(step.Position, initiatorCompany, cancellationToken);
if (string.IsNullOrWhiteSpace(resolvedEmail)) resolvedEmail = employeeByPosition.Email;
if (!employeeByPosition.Found)
warning = $"Не найден сотрудник на должности «{step.Position}» в компании «{initiatorCompany}»."; 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)) else if (step.ProjectRole is not (null or ProjectRole.None))
{ {
@@ -22,7 +22,7 @@ public sealed class CachingTnsuPortalClient(HttpTnsuPortalClient inner, IMemoryC
$"emp:email:{email.ToLowerInvariant()}", $"emp:email:{email.ToLowerInvariant()}",
() => inner.GetEmployeeByEmailAsync(email, cancellationToken)); () => inner.GetEmployeeByEmailAsync(email, cancellationToken));
public Task<string?> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) => public Task<EmployeeLookupResult> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) =>
GetOrAddAsync( GetOrAddAsync(
$"emp:position:{position.ToLowerInvariant()}|{company.ToLowerInvariant()}", $"emp:position:{position.ToLowerInvariant()}|{company.ToLowerInvariant()}",
() => inner.GetEmployeeByPositionAsync(position, company, cancellationToken)); () => inner.GetEmployeeByPositionAsync(position, company, cancellationToken));
@@ -25,12 +25,12 @@ public sealed class HttpTnsuPortalClient(
return new EmployeeDirectoryInfo(employee.CompanyId ?? Guid.Empty, employee.DepartmentId, employee.Company ?? string.Empty, employee.Position); return new EmployeeDirectoryInfo(employee.CompanyId ?? Guid.Empty, employee.DepartmentId, employee.Company ?? string.Empty, employee.Position);
} }
public async Task<string?> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken) public async Task<EmployeeLookupResult> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken)
{ {
var employee = await GetAsync<EmployeeResponse>( var employee = await GetAsync<EmployeeResponse>(
$"/Employee/ByPosition?position={Uri.EscapeDataString(position)}&company={Uri.EscapeDataString(company)}", cancellationToken); $"/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<string?> GetManagerAsync(string email, string managerType, CancellationToken cancellationToken) public async Task<string?> GetManagerAsync(string email, string managerType, CancellationToken cancellationToken)
@@ -107,7 +107,8 @@ public sealed class HttpTnsuPortalClient(
[property: JsonPropertyName("company")] string? Company, [property: JsonPropertyName("company")] string? Company,
[property: JsonPropertyName("companyId")] Guid? CompanyId, [property: JsonPropertyName("companyId")] Guid? CompanyId,
[property: JsonPropertyName("departmentId")] Guid? DepartmentId, [property: JsonPropertyName("departmentId")] Guid? DepartmentId,
[property: JsonPropertyName("position")] string? Position); [property: JsonPropertyName("position")] string? Position,
[property: JsonPropertyName("fio")] string? Fio);
private sealed record ManagerResponse( private sealed record ManagerResponse(
[property: JsonPropertyName("managerEmail")] string? ManagerEmail); [property: JsonPropertyName("managerEmail")] string? ManagerEmail);
@@ -4,7 +4,7 @@ public interface ITnsuPortalClient
{ {
Task<EmployeeDirectoryInfo?> GetEmployeeByEmailAsync(string email, CancellationToken cancellationToken); Task<EmployeeDirectoryInfo?> GetEmployeeByEmailAsync(string email, CancellationToken cancellationToken);
Task<string?> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken); Task<EmployeeLookupResult> GetEmployeeByPositionAsync(string position, string company, CancellationToken cancellationToken);
Task<string?> GetManagerAsync(string email, string managerType, CancellationToken cancellationToken); Task<string?> GetManagerAsync(string email, string managerType, CancellationToken cancellationToken);
@@ -5,3 +5,6 @@ namespace Tnsu.ApprovalRoute.Infrastructure.TnsuPortal;
public sealed record EmployeeDirectoryInfo(Guid CompanyId, Guid? DepartmentId, string Company, string? Position); public sealed record EmployeeDirectoryInfo(Guid CompanyId, Guid? DepartmentId, string Company, string? Position);
public sealed record ProjectExecutorInfo(ProjectRole ProjectRole, string Email); public sealed record ProjectExecutorInfo(ProjectRole ProjectRole, string Email);
/// <summary>Найден ли сотрудник вообще — отдельно от того, заполнен ли у него email в портале (это разные проблемы).</summary>
public sealed record EmployeeLookupResult(bool Found, string? Email, string? Fio);
@@ -560,7 +560,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
.ReturnsAsync(new EmployeeDirectoryInfo(CompanyId, DepartmentId, "ТОО TANSU Construction", "Lead Engineer")); .ReturnsAsync(new EmployeeDirectoryInfo(CompanyId, DepartmentId, "ТОО TANSU Construction", "Lead Engineer"));
portalClient portalClient
.Setup(x => x.GetEmployeeByPositionAsync("Lead", "ТОО TANSU Construction", It.IsAny<CancellationToken>())) .Setup(x => x.GetEmployeeByPositionAsync("Lead", "ТОО TANSU Construction", It.IsAny<CancellationToken>()))
.ReturnsAsync("lead@tnsu.kz"); .ReturnsAsync(new EmployeeLookupResult(true, "lead@tnsu.kz", "Иванов Иван Иванович"));
var services = TestServiceProviderFactory.Build(_connectionString, portalClient: portalClient.Object); var services = TestServiceProviderFactory.Build(_connectionString, portalClient: portalClient.Object);
var routeService = services.GetRequiredService<TemplateRouteService>(); var routeService = services.GetRequiredService<TemplateRouteService>();