правки
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
namespace Tnsu.ApprovalRoute.Application.Reminders;
|
||||
|
||||
/// <summary>
|
||||
/// Какой вид напоминаний запросить у <see cref="ReminderService.GetRemindersAsync(DateTimeOffset, ReminderFeed, CancellationToken)"/>.
|
||||
///
|
||||
/// GetRemindersAsync изначально (до появления ProbationEnding) отдавал только
|
||||
/// просроченные шаги согласования — этот вид и остаётся значением по умолчанию
|
||||
/// (0), чтобы старые потребители (Power Automate), не указывающие feed явно,
|
||||
/// продолжали получать ровно то же, что и раньше.
|
||||
/// </summary>
|
||||
public enum ReminderFeed
|
||||
{
|
||||
None = 0,
|
||||
ApprovalOverdue = 1,
|
||||
ProbationEnding = 2
|
||||
}
|
||||
@@ -24,6 +24,7 @@ public sealed class ReminderService(
|
||||
ISharePointClient sharePoint,
|
||||
ListPartitionRegistry partitionRegistry,
|
||||
ITnsuPortalClient portalClient,
|
||||
TimeProvider timeProvider,
|
||||
IOptions<RemindersOptions> options,
|
||||
ILogger<ReminderService> logger)
|
||||
{
|
||||
@@ -32,17 +33,30 @@ public sealed class ReminderService(
|
||||
private const string ActiveStatusFilter =
|
||||
$"$filter=ApprovalStatus eq '{ApprovalStatuses.OnApproval}' or ApprovalStatus eq '{ApprovalStatuses.OnExecution}'";
|
||||
|
||||
/// <summary>Оба вида напоминаний разом — то, что реально отдаёт контроллер.</summary>
|
||||
public async Task<Result<IReadOnlyList<ReminderDto>>> GetRemindersAsync(
|
||||
DateTimeOffset now, CancellationToken cancellationToken)
|
||||
/// <summary>
|
||||
/// Оверлоад без feed — для обратной совместимости со старыми вызовами: раньше
|
||||
/// это был единственный вид напоминаний, и без явного выбора им и остаётся.
|
||||
/// </summary>
|
||||
public Task<Result<IReadOnlyList<ReminderDto>>> GetRemindersAsync(CancellationToken cancellationToken) =>
|
||||
GetRemindersAsync(ReminderFeed.ApprovalOverdue, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// То, что реально отдаёт контроллер — один вид напоминаний по выбору вызывающей
|
||||
/// стороны. Момент «сейчас» берётся здесь же, из <see cref="TimeProvider"/>, а не
|
||||
/// пробрасывается вызывающей стороной — во всех проде это <c>TimeProvider.System</c>
|
||||
/// (см. Program.cs), в тестах подменяется, а нижестоящие GetOverdueAsync/
|
||||
/// GetProbationEndingAsync по-прежнему принимают <c>now</c> явным параметром: так
|
||||
/// их сценарии остаются детерминированными без своего TimeProvider на каждый тест.
|
||||
/// </summary>
|
||||
public Task<Result<IReadOnlyList<ReminderDto>>> GetRemindersAsync(
|
||||
ReminderFeed feed, CancellationToken cancellationToken)
|
||||
{
|
||||
var overdue = await GetOverdueAsync(now, cancellationToken);
|
||||
if (overdue.IsFailed) return overdue;
|
||||
|
||||
var probation = await GetProbationEndingAsync(now, cancellationToken);
|
||||
if (probation.IsFailed) return probation;
|
||||
|
||||
return Result.Ok<IReadOnlyList<ReminderDto>>(overdue.Value.Concat(probation.Value).ToList());
|
||||
var now = timeProvider.GetUtcNow();
|
||||
return feed switch
|
||||
{
|
||||
ReminderFeed.ProbationEnding => GetProbationEndingAsync(now, cancellationToken),
|
||||
_ => GetOverdueAsync(now, cancellationToken),
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Result<IReadOnlyList<ReminderDto>>> GetOverdueAsync(
|
||||
@@ -191,9 +205,17 @@ public sealed class ReminderService(
|
||||
// ДО появления колонки (см. ApprovalRow) или если request-portal
|
||||
// почему-то не проставил её при активации. Без даты старта SLA не
|
||||
// от чего отсчитывать — пропускаем, а не подставляем сейчас.
|
||||
//
|
||||
// RequestTypeId — всегда, чтобы искать TicketId в правильном типе
|
||||
// заявок. RequestUniqueCode — то, по чему заявку реально ищут в
|
||||
// портале, добавляется, только если он уже есть (строка данных
|
||||
// могла ещё не появиться или заявка старше появления колонки).
|
||||
var identifier = uniqueCodes.GetValueOrDefault(row.TicketId) is { Length: > 0 } code
|
||||
? $"requestTypeId={type.Id}, code={code}"
|
||||
: $"requestTypeId={type.Id}";
|
||||
logger.LogWarning(
|
||||
"Строка {Row} заявки {Ticket} активна, но дата активации (Date) не заполнена — пропущена",
|
||||
row.Id, row.TicketId);
|
||||
"Строка {Row} заявки {Ticket} ({Identifier}) активна, но дата активации (Date) не заполнена — пропущена",
|
||||
row.Id, row.TicketId, identifier);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user