diff --git a/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs b/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs
index 0d29747..6808b87 100644
--- a/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs
+++ b/backend/Tnsu.ApprovalRoute.Application/Reminders/ReminderService.cs
@@ -191,7 +191,7 @@ public sealed class ReminderService(
reminders.Add(new ReminderDto(
row.ApproverEmail!,
(int)Math.Floor((now - deadline).TotalHours),
- BuildUrl(type, row),
+ BuildUrl(type, row, listId),
row.AskOverdueReason ?? type.AskOverdueReason ?? false,
type.Id,
type.Name,
@@ -207,12 +207,17 @@ public sealed class ReminderService(
/// Ссылка ведёт в тот раздел портала, которому принадлежит просроченный шаг:
/// исполнителя незачем высаживать в «На согласовании». Сама заявка всё равно
/// откроется панелью поверх раздела (rpmode=approve).
+ ///
+ /// listId — server-relative url партиции (см. shared/routing.ts в
+ /// request-portal, параметр rplist): без него архивная заявка открылась бы
+ /// так, будто лежит в ТЕКУЩЕЙ партиции типа, и портал не нашёл бы её.
///
- private string BuildUrl(RequestType type, ApprovalRow row) =>
+ private string BuildUrl(RequestType type, ApprovalRow row, string listId) =>
options.Value.RequestUrlTemplate
.Replace("{siteUrl}", type.SiteUrl!.TrimEnd('/'))
.Replace("{pageUrl}", type.PageUrl)
.Replace("{requestId}", row.TicketId.ToString())
+ .Replace("{listId}", Uri.EscapeDataString(listId))
.Replace("{nav}", row.Phase == ApprovalPhases.Execution ? "execution" : "approvals");
/// «Заявка на приём — данные» → «Заявка на приём — согласование».
diff --git a/backend/Tnsu.ApprovalRoute.Application/Reminders/RemindersOptions.cs b/backend/Tnsu.ApprovalRoute.Application/Reminders/RemindersOptions.cs
index 54ff0ac..2776b5e 100644
--- a/backend/Tnsu.ApprovalRoute.Application/Reminders/RemindersOptions.cs
+++ b/backend/Tnsu.ApprovalRoute.Application/Reminders/RemindersOptions.cs
@@ -3,19 +3,25 @@ namespace Tnsu.ApprovalRoute.Application.Reminders;
public sealed class RemindersOptions
{
///
- /// Шаблон ссылки на заявку. Подстановки: {siteUrl}, {pageUrl}, {requestId}, {nav}.
+ /// Шаблон ссылки на заявку. Подстановки: {siteUrl}, {pageUrl}, {requestId},
+ /// {listId}, {nav}.
///
/// Портал — одностраничный и живёт в КОРНЕ сайта, отдельного пути к странице
/// нет; всё состояние передаётся параметрами запроса (см. shared/routing.ts
/// в request-portal). Пример живой ссылки:
- /// https://tnsukz.sharepoint.com/sites/requests?rpnav=approvals&rpmode=approve&rptype=it-1c-ticket&rpid=11
+ /// https://tnsukz.sharepoint.com/sites/requests?rpnav=approvals&rpmode=approve&rptype=it-1c-ticket&rpid=11&rplist=%2Fsites%2Frequests%2FLists%2F...
///
/// {pageUrl} — это PageUrl типа заявки, то есть КЛЮЧ ФОРМЫ (it-1c-ticket), а
/// не путь к странице: в портале он и подставляется в rptype.
///
+ /// {listId} — server-relative url КОНКРЕТНОЙ партиции, где лежит строка
+ /// согласования (параметр rplist). Без него портал открывал бы заявку так,
+ /// будто она лежит в ТЕКУЩЕЙ партиции типа, и архивная заявка не находилась
+ /// бы вовсе (см. IRoute.listId в request-portal/shared/routing.ts).
+ ///
/// Вынесено в конфигурацию, чтобы смена разметки ссылок в портале правилась
/// настройкой, а не пересборкой сервиса.
///
public string RequestUrlTemplate { get; set; } =
- "{siteUrl}?rpnav={nav}&rpmode=approve&rptype={pageUrl}&rpid={requestId}";
+ "{siteUrl}?rpnav={nav}&rpmode=approve&rptype={pageUrl}&rpid={requestId}&rplist={listId}";
}
diff --git a/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/ReminderServiceTests.cs b/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/ReminderServiceTests.cs
index ce1f2bc..778b2e9 100644
--- a/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/ReminderServiceTests.cs
+++ b/backend/tests/Tnsu.ApprovalRoute.IntegrationTests/ApplicationServices/ReminderServiceTests.cs
@@ -215,8 +215,8 @@ public sealed class ReminderServiceTests : IClassFixture