Fix/by approver silent failures #25

Merged
gorbenko.pavel merged 6 commits from fix/by-approver-silent-failures into main 2026-10-05 04:38:37 +00:00
Showing only changes of commit 99ce7ed9b2 - Show all commits
@@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using FluentResults; using FluentResults;
@@ -266,6 +267,29 @@ public sealed class RequestManageService(
return result; return result;
} }
// Пара «список согласования → (его заголовок, адрес парного списка данных)»
// не меняется, пока список не переименуют, — запоминаем на время жизни процесса,
// чтобы не тратить два запроса к SharePoint на каждый вызов. Ключ — адрес списка.
private static readonly ConcurrentDictionary<string, (string ApprovalTitle, string DataListUrl)> ListPairs =
new(StringComparer.OrdinalIgnoreCase);
private async Task<(string ApprovalTitle, string DataListUrl)?> ResolveListPairAsync(
string siteUrl, string approvalListUrl, CancellationToken cancellationToken)
{
if (ListPairs.TryGetValue(approvalListUrl, out var cached)) return cached;
var approvalList = await sharePoint.GetListByUrlAsync(siteUrl, approvalListUrl, cancellationToken);
if (approvalList is null || !ApprovalListSuffix.IsMatch(approvalList.Title)) return null;
var dataTitle = ApprovalListSuffix.Replace(approvalList.Title, " — данные");
var dataList = await sharePoint.GetListByTitleAsync(siteUrl, dataTitle, cancellationToken);
if (dataList is null) return null;
var pair = (approvalList.Title, dataList.ServerRelativeUrl);
ListPairs[approvalListUrl] = pair;
return pair;
}
private static string? ListUrlFromHitPath(string? path) private static string? ListUrlFromHitPath(string? path)
{ {
if (string.IsNullOrWhiteSpace(path) || !Uri.TryCreate(path, UriKind.Absolute, out var uri)) return null; if (string.IsNullOrWhiteSpace(path) || !Uri.TryCreate(path, UriKind.Absolute, out var uri)) return null;
@@ -287,18 +311,15 @@ public sealed class RequestManageService(
{ {
try try
{ {
var approvalList = await sharePoint.GetListByUrlAsync(siteUrl, approvalListUrl, cancellationToken); var pair = await ResolveListPairAsync(siteUrl, approvalListUrl, cancellationToken);
if (approvalList is null || !ApprovalListSuffix.IsMatch(approvalList.Title)) return []; if (pair is null) return [];
var (approvalTitle, dataListUrl) = pair.Value;
var dataTitle = ApprovalListSuffix.Replace(approvalList.Title, " — данные");
var dataList = await sharePoint.GetListByTitleAsync(siteUrl, dataTitle, cancellationToken);
if (dataList is null) return [];
// Какому типу заявок принадлежит эта партиция (текущая или архивная). // Какому типу заявок принадлежит эта партиция (текущая или архивная).
var requestType = siteTypes.FirstOrDefault(rt => var requestType = siteTypes.FirstOrDefault(rt =>
string.Equals(rt.ListId, dataList.ServerRelativeUrl, StringComparison.OrdinalIgnoreCase) string.Equals(rt.ListId, dataListUrl, StringComparison.OrdinalIgnoreCase)
|| archivedByType[rt.Id].Any(a => || archivedByType[rt.Id].Any(a =>
string.Equals(a.ListId, dataList.ServerRelativeUrl, StringComparison.OrdinalIgnoreCase))); string.Equals(a.ListId, dataListUrl, StringComparison.OrdinalIgnoreCase)));
if (requestType is null) return []; if (requestType is null) return [];
var rows = new List<ManagedApprovalRowDto>(); var rows = new List<ManagedApprovalRowDto>();
@@ -318,12 +339,12 @@ public sealed class RequestManageService(
if (matched.Count == 0) return []; if (matched.Count == 0) return [];
var dataById = await ReadDataRowsAsync( var dataById = await ReadDataRowsAsync(
siteUrl, dataList.ServerRelativeUrl, matched.Select(r => r.TicketId).Distinct().ToList(), siteUrl, dataListUrl, matched.Select(r => r.TicketId).Distinct().ToList(),
cancellationToken); cancellationToken);
return matched return matched
.Select(r => ToUserRow( .Select(r => ToUserRow(
r, requestType, siteUrl, dataList.ServerRelativeUrl, approvalList.Title, r, requestType, siteUrl, dataListUrl, approvalTitle,
dataById.GetValueOrDefault(r.TicketId))) dataById.GetValueOrDefault(r.TicketId)))
.ToList(); .ToList();
} }