< Summary

Information
Class: OzonOrdersWeb.WebServices.TransactionJobs.ExecutionDetailsGridRows
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/TransactionJobs/ExecutionDetailsGridRows.cs
Line coverage
66%
Covered lines: 65
Uncovered lines: 33
Coverable lines: 98
Total lines: 169
Line coverage: 66.3%
Branch coverage
52%
Covered branches: 70
Total branches: 134
Branch coverage: 52.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Build(...)62.5%88100%
Step(...)50%22100%
Load(...)0%2040%
Result(...)50%22100%
IsDraft(...)100%44100%
ExecutionStatus(...)81.25%161690%
LoadStatus(...)0%156120%
ResultStatus(...)68.75%231670%
TriggerType(...)25%13857.14%
JobType(...)25%13857.14%
StepName(...)54.16%6604835.71%
Blank(...)100%22100%
Utc(...)75%4483.33%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/TransactionJobs/ExecutionDetailsGridRows.cs

#LineLine coverage
 1using OzonDomains.Models;
 2
 3namespace OzonOrdersWeb.WebServices.TransactionJobs;
 4
 5/// <summary>Подпись и тон бейджа (accent | success | warning | danger | info | purple | muted).</summary>
 6public sealed record ExecutionDetailsLabel(string Code, string Text, string Tone);
 7
 8public sealed record ExecutionStepRow(
 9    long Id, int Number, string Name, string NameCode, string Status, string StatusCode, string StatusTone,
 10    DateTime StartedAt, DateTime? CompletedAt, long? DurationMs, string? Input, string? Output, string? Error);
 11
 12public sealed record ExecutionReportLoadRow(
 13    long Id, string Client, string? ReportCode, string? FileName, string? FileUrl, DateTime PeriodFrom, DateTime PeriodT
 14    string Status, string StatusCode, string StatusTone, int? TotalRows, int? RowsWithData, int? UniqueOrders, string? E
 15
 16public sealed record ExecutionResultRow(
 17    long Id, int OrderId, string? ShipmentNumber, string? Warehouse, int? TransactionId, string? OneCDocumentId,
 18    string? OneCDocumentNumber, bool IsPosted, bool IsDraft, string Status, string StatusCode, string StatusTone,
 19    string? Comment, string? Error);
 20
 21public sealed record ExecutionDetailsSummary(
 22    string Schedule, string JobType, string Trigger, string Status, string StatusTone, DateTime StartedAt,
 23    DateTime? CompletedAt, long? DurationMs, int TotalOrders, int MatchedOrders, int ProcessedOrders,
 24    int SuccessfulOrders, int FailedOrders, string? Error);
 25
 26public sealed record ExecutionDetailsGridData(
 27    ExecutionDetailsSummary Summary,
 28    IReadOnlyList<ExecutionStepRow> Steps,
 29    IReadOnlyList<ExecutionReportLoadRow> Loads,
 30    IReadOnlyList<ExecutionResultRow> Results,
 31    int DraftCount);
 32
 33/// <summary>
 34/// Данные страницы «Детали выполнения» для гридов AG Grid: переводы статусов/этапов и цвета бейджей раньше жили в
 35/// ExecutionDetails.cshtml — теперь они в строках, по ним работают фильтры и сортировка гридов.
 36/// </summary>
 37public static class ExecutionDetailsGridRows
 38{
 39    public static ExecutionDetailsGridData Build(
 40        BackgroundJobExecution execution, BackgroundJobSchedule? schedule,
 41        IEnumerable<BackgroundJobStep> steps, IEnumerable<BackgroundReportLoad> loads,
 42        IEnumerable<BackgroundTransactionResult> results)
 43    {
 344        var stepRows = steps.OrderBy(s => s.StepNumber).Select(Step).ToList();
 145        var loadRows = loads.Select(Load).ToList();
 146        var resultRows = results.Select(Result).ToList();
 47
 148        var summary = new ExecutionDetailsSummary(
 149            schedule?.Name ?? "-",
 150            JobType(execution.JobType),
 151            TriggerType(execution.TriggerType),
 152            ExecutionStatus(execution.Status).Text,
 153            ExecutionStatus(execution.Status).Tone,
 154            Utc(execution.StartedAt),
 155            execution.CompletedAt.HasValue ? Utc(execution.CompletedAt.Value) : null,
 156            execution.DurationMs,
 157            execution.TotalOrders,
 158            execution.MatchedOrders,
 159            execution.ProcessedOrders,
 160            execution.SuccessfulOrders,
 161            execution.FailedOrders,
 162            string.IsNullOrWhiteSpace(execution.ErrorMessage) ? null : execution.ErrorMessage);
 63
 364        return new ExecutionDetailsGridData(summary, stepRows, loadRows, resultRows, resultRows.Count(r => r.IsDraft));
 65    }
 66
 67    public static ExecutionStepRow Step(BackgroundJobStep s)
 68    {
 369        var status = ExecutionStatus(s.Status);
 370        return new ExecutionStepRow(
 371            s.Id, s.StepNumber, StepName(s.StepName), s.StepName, status.Text, status.Code, status.Tone,
 372            Utc(s.StartedAt), s.CompletedAt.HasValue ? Utc(s.CompletedAt.Value) : null, s.DurationMs,
 373            Blank(s.InputData), Blank(s.OutputData), Blank(s.ErrorMessage));
 74    }
 75
 76    public static ExecutionReportLoadRow Load(BackgroundReportLoad r)
 77    {
 078        var status = LoadStatus(r.Status);
 079        return new ExecutionReportLoadRow(
 080            r.Id, r.OzonClient?.Name ?? "-", r.ReportCode, r.FileName, Blank(r.FileUrl),
 081            Utc(r.ReportPeriodFrom), Utc(r.ReportPeriodTo), status.Text, status.Code, status.Tone,
 082            r.TotalRows, r.RowsWithRequiredData, r.UniqueOrderNumbers, Blank(r.ErrorMessage));
 83    }
 84
 85    public static ExecutionResultRow Result(BackgroundTransactionResult r)
 86    {
 587        var status = ResultStatus(r.Status);
 588        return new ExecutionResultRow(
 589            r.Id, r.OrderId, r.Order?.ShipmentNumber, r.WarehouseName, r.TransactionId, r.OneCDocumentId,
 590            Blank(r.OneCDocumentNumber), r.IsPosted, IsDraft(r), status.Text, status.Code, status.Tone,
 591            Blank(r.Comment), Blank(r.ErrorMessage));
 92    }
 93
 94    /// <summary>Документ записан в 1С, но не проведён.</summary>
 95    public static bool IsDraft(BackgroundTransactionResult r)
 596        => !r.IsPosted && (!string.IsNullOrEmpty(r.OneCDocumentId) || !string.IsNullOrEmpty(r.OneCDocumentNumber));
 97
 998    public static ExecutionDetailsLabel ExecutionStatus(string? status) => status switch
 999    {
 1100        "Running" => new(status, "Выполняется", "warning"),
 1101        "Completed" => new(status, "Завершено", "success"),
 2102        "PartialSuccess" => new(status, "Частично успешно", "warning"),
 1103        "Success" => new(status, "Успешно", "success"),
 1104        "Failed" => new(status, "Ошибка", "danger"),
 0105        "Skipped" => new(status, "Пропущено", "warning"),
 3106        _ => new(status ?? "", status ?? "-", "muted")
 9107    };
 108
 0109    public static ExecutionDetailsLabel LoadStatus(string? status) => status switch
 0110    {
 0111        "Requested" => new(status, "Запрошен", "warning"),
 0112        "Ready" => new(status, "Готов", "warning"),
 0113        "Downloaded" => new(status, "Загружен", "success"),
 0114        "Failed" => new(status, "Ошибка", "danger"),
 0115        _ => new(status ?? "", status ?? "-", "muted")
 0116    };
 117
 5118    public static ExecutionDetailsLabel ResultStatus(string? status) => status switch
 5119    {
 0120        "Created" => new(status, "Создано", "success"),
 1121        "PostedTo1C" => new(status, "Проведено в 1С", "success"),
 1122        "DraftIn1C" => new(status, "Черновик в 1С", "warning"),
 0123        "SystemOnly" => new(status, "Только в системе", "accent"),
 0124        "Skipped" => new(status, "Пропущено", "warning"),
 1125        "Failed" => new(status, "Ошибка", "danger"),
 2126        _ => new(status ?? "", status ?? "-", "muted")
 5127    };
 128
 1129    public static string TriggerType(string? triggerType) => triggerType switch
 1130    {
 0131        "Scheduled" => "По расписанию",
 1132        "Manual" => "Вручную",
 0133        "Retry" => "Повтор",
 0134        _ => triggerType ?? "-"
 1135    };
 136
 1137    public static string JobType(string? jobType) => jobType switch
 1138    {
 0139        "ShippedToCommissioner" => "Отгрузка комиссионеру",
 1140        "CustomerReturn" => "Возврат покупателя",
 0141        "ShippedToClient" => "Отгрузка клиенту",
 0142        _ => jobType ?? "-"
 1143    };
 144
 3145    public static string StepName(string? stepName) => stepName switch
 3146    {
 0147        "LoadReport" => "Загрузка отчёта",
 0148        "ParseReport" => "Парсинг отчёта",
 0149        "FilterByDate" => "Фильтрация по дате",
 1150        "MatchOrders" => "Сопоставление заказов",
 0151        "ExcludeProcessedOrders" => "Исключение уже проведённых",
 0152        "FilterEligibleOrders" => "Фильтрация подходящих заказов",
 0153        "GroupByWarehouse" => "Группировка по складам",
 0154        "CreateTransactions" => "Создание транзакций",
 0155        "PostTo1C" => "Проведение в 1С",
 0156        "Finalize" => "Финализация",
 2157        _ => stepName ?? "-"
 3158    };
 159
 24160    private static string? Blank(string? value) => string.IsNullOrWhiteSpace(value) ? null : value;
 161
 162    /// <summary>Время в БД — UTC; клиент показывает его в МСК. Kind нормализуется, чтобы JSON получил суффикс Z.</summa
 4163    private static DateTime Utc(DateTime value) => value.Kind switch
 4164    {
 3165        DateTimeKind.Utc => value,
 0166        DateTimeKind.Local => value.ToUniversalTime(),
 1167        _ => DateTime.SpecifyKind(value, DateTimeKind.Utc)
 4168    };
 169}