Напоминания: убрать дубль ManagerEmail, ссылка из настроек; None первым во всех enum

Напоминания:
- ProbationEndingReminderDto: ManagerEmail убран — это был унаследованный
  ReceiverEmail под вторым именем.
- Ссылка для ProbationEnding больше не ведёт на саму заявку на приём (она уже
  закрыта, решать по ней нечего) — берётся из новой настройки
  RemindersOptions.ProbationReminderUrl и ведёт в раздел, где заводят новую
  заявку. Подстановок в ней нет: адрес конкретной формы в портал не передать,
  rptype без rpid/rpsource игнорируется (см. parseRoute в request-portal).
  Заодно ушли BuildProbationUrl и ненужные больше параметры type/listId.

Стайлгайд (CLAUDE.md) — у enum первое значение None:
- ReminderFeed: None=0 трактуется как ApprovalOverdue, чтобы вызов без явного
  выбора работал как раньше.
- EmploymentStatus: заодно инвертирован switch в ReminderService — раньше
  «продолжить» было веткой по умолчанию, и новый None молча означал бы
  «сотрудник работает». Теперь по умолчанию пропуск с предупреждением.
- ConditionsLogic: None — НЕвалидное значение, отвергается валидаторами шага
  (в том числе новым PatchTemplateRouteStepRequestValidator, его не было вовсе).
  Поэтому у ConditionsLogic в Create/Update-запросах убрано значение по
  умолчанию: System.Text.Json в .NET 10 уважает дефолты параметров
  конструктора, и пропущенное поле молча означало «И». Теперь пропущенное поле
  даёт None и упирается в валидатор.

ЛОМАЮЩЕЕ ИЗМЕНЕНИЕ КОНТРАКТА: клиент, не присылающий conditionsLogic в
POST/PUT шага, получит 400 вместо прежнего молчаливого «И». Админка не
затронута — она это поле всегда отправляет.
This commit is contained in:
gorbenko.pavel
2026-08-27 15:53:31 +05:00
parent 81ed85d6ce
commit 31a0a8e9e3
11 changed files with 192 additions and 102 deletions
@@ -31,6 +31,11 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
private const string DataListTitle = "Заявка тест — данные";
private const string ApprovalListTitle = "Заявка тест — согласование";
// Своё значение (не то, что по умолчанию в RemindersOptions) — так тест
// проверяет, что ссылка действительно берётся из настроек, а не совпадает
// с ожидаемой случайно.
private const string ProbationReminderUrl = "https://portal.test/новая-заявка";
private static readonly DateTimeOffset Now = new(2026, 8, 12, 12, 0, 0, TimeSpan.Zero);
// GetOverdueAsync/GetProbationEndingAsync по-прежнему берут now параметром — их
@@ -355,7 +360,12 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
_services.GetRequiredService<ListPartitionRegistry>(),
portalClient.Object,
Clock,
Options.Create(new RemindersOptions { RecruitingHirePageUrl = pageUrl, ProbationReminderDaysBeforeEnd = daysBeforeEnd }),
Options.Create(new RemindersOptions
{
RecruitingHirePageUrl = pageUrl,
ProbationReminderDaysBeforeEnd = daysBeforeEnd,
ProbationReminderUrl = ProbationReminderUrl
}),
NullLogger<ReminderService>.Instance);
}
@@ -394,10 +404,13 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
result.IsSuccess.ShouldBeTrue();
var reminder = result.Value.ShouldHaveSingleItem().ShouldBeOfType<ProbationEndingReminderDto>();
reminder.ManagerEmail.ShouldBe("manager@tnsu.kz");
reminder.ReceiverEmail.ShouldBe("manager@tnsu.kz");
reminder.CandidateEmail.ShouldBe("candidate@tnsu.kz");
reminder.CandidateName.ShouldBe("Иванов Иван Иванович");
reminder.DaysUntilProbationEnds.ShouldBe(3);
// Ссылка ведёт не на саму заявку на приём, а на раздел, где заводят новую
// (константа из настроек, см. RemindersOptions.ProbationReminderUrl).
reminder.Url.ShouldBe(ProbationReminderUrl);
}
[Fact(DisplayName = "Кандидат уже уволен (dismissalDate заполнен) — напоминания нет")]
@@ -558,7 +571,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
var service = new ReminderService(
db, sharePoint.Object, partitionRegistry, portalClient.Object, Clock,
Options.Create(new RemindersOptions { RecruitingHirePageUrl = pageUrl }),
Options.Create(new RemindersOptions { RecruitingHirePageUrl = pageUrl, ProbationReminderUrl = ProbationReminderUrl }),
NullLogger<ReminderService>.Instance);
var result = await service.GetProbationEndingAsync(Now, CancellationToken.None);