Reminders: убрать Category из общей части DTO, добавить ReceiverEmail/ReceiverName, ограничить чтение испытательного срока последними партициями
Tests / frontend-test (pull_request) Successful in 45s
Tests / backend-test (pull_request) Successful in 1m54s

- ReminderDto: базовый класс сузился до ReceiverEmail/ReceiverName/Url;
  RequestTypeId/RequestTypeName/RequestId/Status/RequestUniqueCode остались
  только в ApprovalOverdueReminderDto — ProbationEndingReminderDto они не
  нужны. Дискриминатор полиморфной сериализации ($type) больше не дублируется
  отдельным enum-полем Category.
- ApprovalOverdueReminderDto: старый Email сохранён рядом с унаследованным
  ReceiverEmail (то же значение) — контракт можно переключать постепенно.
- ApprovalRow/RowSelect: добавлен Title согласующего (TansuSiteApprover/Title)
  — заполняет ReceiverName для просроченных шагов, когда он есть в SharePoint.
- EmployeeDirectorySnapshot.NameByEmail: обратный поиск ФИО руководителя по
  email — заполняет ReceiverName для напоминаний об испытательном сроке без
  лишнего похода в api.tnsu.kz (данные уже загружены для EmailOf).
- GetProbationEndingAsync: испытательный срок не длиннее 6 месяцев, поэтому
  читаем только текущую и последнюю архивную партицию (не весь архив) и
  фильтруем строки по HireDate не старше 6 месяцев — экономим лишние запросы
  к SharePoint без потери актуальных заявок.
This commit is contained in:
gorbenko.pavel
2026-08-27 14:12:39 +05:00
parent 5d7503209a
commit cfc2b393bd
9 changed files with 184 additions and 83 deletions
@@ -15,6 +15,7 @@ internal sealed record ApprovalRow(
string Phase,
DateTimeOffset? Date,
string? ApproverEmail,
string? ApproverName,
int? SlaHours,
bool? AskOverdueReason)
{
@@ -23,9 +24,9 @@ internal sealed record ApprovalRow(
// TicketId — Lookup на заявку; без него строку не с чем связать.
if (!TryGetInt(item, "TicketId", out var ticketId)) return null;
var approver = item.TryGetProperty("TansuSiteApprover", out var a) && a.ValueKind == JsonValueKind.Object
? GetString(a, "EMail")
: null;
var approverObject = item.TryGetProperty("TansuSiteApprover", out var a) && a.ValueKind == JsonValueKind.Object
? a
: (JsonElement?)null;
return new ApprovalRow(
TryGetInt(item, "Id", out var id) ? id : 0,
@@ -35,7 +36,10 @@ internal sealed record ApprovalRow(
// трактуем как «Согласование» (так же поступает request-portal).
GetString(item, "Phase") is { Length: > 0 } phase ? phase : ApprovalPhases.Approval,
TryGetDate(item, "Date"),
approver,
approverObject is { } ao ? GetString(ao, "EMail") : null,
// Title у персонального поля — не всегда заполнен (например, у
// системных/сервисных учёток) — тогда ReceiverName в DTO остаётся null.
approverObject is { } an ? GetString(an, "Title") : null,
TryGetInt(item, "SLAhours", out var sla) ? sla : null,
TryGetBool(item, "AskOverdueReason", out var ask) ? ask : null);
}