96 lines
3.9 KiB
C#
96 lines
3.9 KiB
C#
using System.Text.Json;
|
|
|
|
namespace Tnsu.ApprovalRoute.Application.Reminders;
|
|
|
|
/// <summary>
|
|
/// Строка списка «… — согласование», разобранная из ответа SharePoint.
|
|
/// Имена колонок — как в request-portal (FIELDS в approvalList.service.ts):
|
|
/// именно он эти списки и создаёт.
|
|
/// </summary>
|
|
internal sealed record ApprovalRow(
|
|
int Id,
|
|
int TicketId,
|
|
int StepOrder,
|
|
string Status,
|
|
string Phase,
|
|
DateTimeOffset? Date,
|
|
string? ApproverEmail,
|
|
int? SlaHours,
|
|
bool? AskOverdueReason)
|
|
{
|
|
public static ApprovalRow? TryParse(JsonElement item)
|
|
{
|
|
// 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;
|
|
|
|
return new ApprovalRow(
|
|
TryGetInt(item, "Id", out var id) ? id : 0,
|
|
ticketId,
|
|
TryGetInt(item, "StepOrder", out var order) ? order : 0,
|
|
GetString(item, "ApprovalStatus") ?? string.Empty,
|
|
// Пустая фаза — старые строки, заведённые до появления колонки;
|
|
// трактуем как «Согласование» (так же поступает request-portal).
|
|
GetString(item, "Phase") is { Length: > 0 } phase ? phase : ApprovalPhases.Approval,
|
|
TryGetDate(item, "Date"),
|
|
approver,
|
|
TryGetInt(item, "SLAhours", out var sla) ? sla : null,
|
|
TryGetBool(item, "AskOverdueReason", out var ask) ? ask : null);
|
|
}
|
|
|
|
private static string? GetString(JsonElement e, string name) =>
|
|
e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String ? v.GetString() : null;
|
|
|
|
private static bool TryGetInt(JsonElement e, string name, out int value)
|
|
{
|
|
value = 0;
|
|
return e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.Number && v.TryGetInt32(out value);
|
|
}
|
|
|
|
private static bool TryGetBool(JsonElement e, string name, out bool value)
|
|
{
|
|
value = false;
|
|
if (!e.TryGetProperty(name, out var v)) return false;
|
|
if (v.ValueKind is not (JsonValueKind.True or JsonValueKind.False)) return false;
|
|
value = v.GetBoolean();
|
|
return true;
|
|
}
|
|
|
|
private static DateTimeOffset? TryGetDate(JsonElement e, string name) =>
|
|
e.TryGetProperty(name, out var v) &&
|
|
v.ValueKind == JsonValueKind.String &&
|
|
DateTimeOffset.TryParse(v.GetString(), out var parsed)
|
|
? parsed
|
|
: null;
|
|
}
|
|
|
|
internal static class ApprovalPhases
|
|
{
|
|
public const string Approval = "Согласование";
|
|
public const string Execution = "Исполнение";
|
|
}
|
|
|
|
internal static class ApprovalStatuses
|
|
{
|
|
public const string OnApproval = "На согласовании";
|
|
public const string OnExecution = "На исполнении";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Managed property статуса строки маршрута для KQL — ApprovalStatusOWSCHCS.
|
|
/// Имя нестандартное (суффикс OWSCHCS у Choice-поля, префикс группы колонок
|
|
/// сайта у самого имени) — совпадает с MP_STATUS в
|
|
/// request-portal/src/webparts/requestPortal/features/myRequests/myRequests.service.ts,
|
|
/// это тот же список и та же колонка, имя проверено там же.
|
|
/// </summary>
|
|
internal static class SlaStatus
|
|
{
|
|
private const string ManagedProperty = "ApprovalStatusOWSCHCS";
|
|
|
|
public static readonly string OnApprovalProperty = $"{ManagedProperty}:\"{ApprovalStatuses.OnApproval}\"";
|
|
public static readonly string OnExecutionProperty = $"{ManagedProperty}:\"{ApprovalStatuses.OnExecution}\"";
|
|
}
|