This commit is contained in:
gorbenko.pavel
2026-08-17 15:38:15 +05:00
parent b92897254d
commit a6281dea55
2 changed files with 64 additions and 13 deletions
@@ -1,3 +1,4 @@
using System.Diagnostics;
using Microsoft.Extensions.Logging;
namespace Tnsu.ApprovalRoute.Infrastructure.SharePoint;
@@ -23,6 +24,11 @@ public sealed class SharePointListProvisioner(
int number,
CancellationToken cancellationToken)
{
logger.LogInformation(
"Дублирую пару списков №{Number} на {SiteUrl} по образцу {SourceListId}.",
number, siteUrl, sourceDataListId);
var stopwatch = Stopwatch.StartNew();
var sourceData = await sharePoint.GetListByUrlAsync(siteUrl, sourceDataListId, cancellationToken)
?? throw new InvalidOperationException(
$"Исходный список {sourceDataListId} не найден на {siteUrl} — дублировать нечего.");
@@ -31,11 +37,16 @@ public sealed class SharePointListProvisioner(
siteUrl,
sourceData,
ListTitleConvention.WithNumber(sourceData.Title, number),
role: "данные",
retarget: null,
cancellationToken);
await CloneApprovalPairAsync(siteUrl, sourceData, newData, number, cancellationToken);
logger.LogInformation(
"Пара списков №{Number} готова за {ElapsedMs} мс: данные «{Title}» ({ListId}).",
number, stopwatch.ElapsedMilliseconds, newData.Title, newData.ServerRelativeUrl);
return new ProvisionedList(newData.ServerRelativeUrl, newData.Title);
}
@@ -73,6 +84,7 @@ public sealed class SharePointListProvisioner(
siteUrl,
sourceApproval,
ListTitleConvention.WithNumber(sourceApproval.Title, number),
role: "согласование",
// Ticket списка согласования смотрит на список данных — в дубле он должен
// смотреть на НОВЫЙ список данных, иначе строки маршрута новых заявок
// будут ссылаться в старый список.
@@ -80,10 +92,15 @@ public sealed class SharePointListProvisioner(
cancellationToken);
}
/// <summary>
/// role — только для логов («данные»/«согласование»): по нему в логе видно, какую
/// половину пары обрабатывает конкретный вызов, не заглядывая в стек вызовов.
/// </summary>
private async Task<SharePointListInfo> CloneAsync(
string siteUrl,
SharePointListInfo source,
string newTitle,
string role,
(Guid From, Guid To)? retarget,
CancellationToken cancellationToken)
{
@@ -91,13 +108,16 @@ public sealed class SharePointListProvisioner(
var target = existing ?? await sharePoint.CreateListAsync(siteUrl, newTitle, cancellationToken);
logger.LogInformation(
existing is null ? "Создан список «{Title}»." : "Список «{Title}» уже существует — дозаполняю колонки.",
newTitle);
existing is null
? "Список {Role} «{Title}» создан."
: "Список {Role} «{Title}» уже существует — дозаполняю недостающие колонки.",
role, newTitle);
var sourceFields = await sharePoint.GetCustomFieldsAsync(siteUrl, source.ServerRelativeUrl, cancellationToken);
var targetFields = await sharePoint.GetCustomFieldsAsync(siteUrl, target.ServerRelativeUrl, cancellationToken);
var alreadyThere = targetFields.Select(x => x.InternalName).ToHashSet(StringComparer.OrdinalIgnoreCase);
var copied = 0;
foreach (var field in sourceFields)
{
if (alreadyThere.Contains(field.InternalName)) continue;
@@ -107,9 +127,19 @@ public sealed class SharePointListProvisioner(
: RetargetLookup(field.SchemaXml, retarget.Value.From, retarget.Value.To);
await sharePoint.AddFieldFromXmlAsync(siteUrl, target.Id, schemaXml, cancellationToken);
logger.LogInformation(" колонка {InternalName} → «{Title}»", field.InternalName, newTitle);
copied++;
// По каждой колонке — только на Debug: при штатной первой партии их
// десятки на список, и на Information это был бы шум. Итог всё равно
// виден в сводке ниже.
logger.LogDebug(
"Список {Role} «{Title}»: скопирована колонка {InternalName}.", role, newTitle, field.InternalName);
}
logger.LogInformation(
"Список {Role} «{Title}»: скопировано колонок {Copied}, уже было {AlreadyThere}.",
role, newTitle, copied, sourceFields.Count - copied);
return target;
}