< Summary

Information
Class: OzonOrdersWeb.WebServices.TransactionJobs.ExecutionReportLoadRow
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/TransactionJobs/ExecutionDetailsGridRows.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 3
Coverable lines: 3
Total lines: 169
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_Id()100%210%
get_Status()100%210%

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
 012public sealed record ExecutionReportLoadRow(
 013    long Id, string Client, string? ReportCode, string? FileName, string? FileUrl, DateTime PeriodFrom, DateTime PeriodT
 014    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    {
 44        var stepRows = steps.OrderBy(s => s.StepNumber).Select(Step).ToList();
 45        var loadRows = loads.Select(Load).ToList();
 46        var resultRows = results.Select(Result).ToList();
 47
 48        var summary = new ExecutionDetailsSummary(
 49            schedule?.Name ?? "-",
 50            JobType(execution.JobType),
 51            TriggerType(execution.TriggerType),
 52            ExecutionStatus(execution.Status).Text,
 53            ExecutionStatus(execution.Status).Tone,
 54            Utc(execution.StartedAt),
 55            execution.CompletedAt.HasValue ? Utc(execution.CompletedAt.Value) : null,
 56            execution.DurationMs,
 57            execution.TotalOrders,
 58            execution.MatchedOrders,
 59            execution.ProcessedOrders,
 60            execution.SuccessfulOrders,
 61            execution.FailedOrders,
 62            string.IsNullOrWhiteSpace(execution.ErrorMessage) ? null : execution.ErrorMessage);
 63
 64        return new ExecutionDetailsGridData(summary, stepRows, loadRows, resultRows, resultRows.Count(r => r.IsDraft));
 65    }
 66
 67    public static ExecutionStepRow Step(BackgroundJobStep s)
 68    {
 69        var status = ExecutionStatus(s.Status);
 70        return new ExecutionStepRow(
 71            s.Id, s.StepNumber, StepName(s.StepName), s.StepName, status.Text, status.Code, status.Tone,
 72            Utc(s.StartedAt), s.CompletedAt.HasValue ? Utc(s.CompletedAt.Value) : null, s.DurationMs,
 73            Blank(s.InputData), Blank(s.OutputData), Blank(s.ErrorMessage));
 74    }
 75
 76    public static ExecutionReportLoadRow Load(BackgroundReportLoad r)
 77    {
 78        var status = LoadStatus(r.Status);
 79        return new ExecutionReportLoadRow(
 80            r.Id, r.OzonClient?.Name ?? "-", r.ReportCode, r.FileName, Blank(r.FileUrl),
 81            Utc(r.ReportPeriodFrom), Utc(r.ReportPeriodTo), status.Text, status.Code, status.Tone,
 82            r.TotalRows, r.RowsWithRequiredData, r.UniqueOrderNumbers, Blank(r.ErrorMessage));
 83    }
 84
 85    public static ExecutionResultRow Result(BackgroundTransactionResult r)
 86    {
 87        var status = ResultStatus(r.Status);
 88        return new ExecutionResultRow(
 89            r.Id, r.OrderId, r.Order?.ShipmentNumber, r.WarehouseName, r.TransactionId, r.OneCDocumentId,
 90            Blank(r.OneCDocumentNumber), r.IsPosted, IsDraft(r), status.Text, status.Code, status.Tone,
 91            Blank(r.Comment), Blank(r.ErrorMessage));
 92    }
 93
 94    /// <summary>Документ записан в 1С, но не проведён.</summary>
 95    public static bool IsDraft(BackgroundTransactionResult r)
 96        => !r.IsPosted && (!string.IsNullOrEmpty(r.OneCDocumentId) || !string.IsNullOrEmpty(r.OneCDocumentNumber));
 97
 98    public static ExecutionDetailsLabel ExecutionStatus(string? status) => status switch
 99    {
 100        "Running" => new(status, "Выполняется", "warning"),
 101        "Completed" => new(status, "Завершено", "success"),
 102        "PartialSuccess" => new(status, "Частично успешно", "warning"),
 103        "Success" => new(status, "Успешно", "success"),
 104        "Failed" => new(status, "Ошибка", "danger"),
 105        "Skipped" => new(status, "Пропущено", "warning"),
 106        _ => new(status ?? "", status ?? "-", "muted")
 107    };
 108
 109    public static ExecutionDetailsLabel LoadStatus(string? status) => status switch
 110    {
 111        "Requested" => new(status, "Запрошен", "warning"),
 112        "Ready" => new(status, "Готов", "warning"),
 113        "Downloaded" => new(status, "Загружен", "success"),
 114        "Failed" => new(status, "Ошибка", "danger"),
 115        _ => new(status ?? "", status ?? "-", "muted")
 116    };
 117
 118    public static ExecutionDetailsLabel ResultStatus(string? status) => status switch
 119    {
 120        "Created" => new(status, "Создано", "success"),
 121        "PostedTo1C" => new(status, "Проведено в 1С", "success"),
 122        "DraftIn1C" => new(status, "Черновик в 1С", "warning"),
 123        "SystemOnly" => new(status, "Только в системе", "accent"),
 124        "Skipped" => new(status, "Пропущено", "warning"),
 125        "Failed" => new(status, "Ошибка", "danger"),
 126        _ => new(status ?? "", status ?? "-", "muted")
 127    };
 128
 129    public static string TriggerType(string? triggerType) => triggerType switch
 130    {
 131        "Scheduled" => "По расписанию",
 132        "Manual" => "Вручную",
 133        "Retry" => "Повтор",
 134        _ => triggerType ?? "-"
 135    };
 136
 137    public static string JobType(string? jobType) => jobType switch
 138    {
 139        "ShippedToCommissioner" => "Отгрузка комиссионеру",
 140        "CustomerReturn" => "Возврат покупателя",
 141        "ShippedToClient" => "Отгрузка клиенту",
 142        _ => jobType ?? "-"
 143    };
 144
 145    public static string StepName(string? stepName) => stepName switch
 146    {
 147        "LoadReport" => "Загрузка отчёта",
 148        "ParseReport" => "Парсинг отчёта",
 149        "FilterByDate" => "Фильтрация по дате",
 150        "MatchOrders" => "Сопоставление заказов",
 151        "ExcludeProcessedOrders" => "Исключение уже проведённых",
 152        "FilterEligibleOrders" => "Фильтрация подходящих заказов",
 153        "GroupByWarehouse" => "Группировка по складам",
 154        "CreateTransactions" => "Создание транзакций",
 155        "PostTo1C" => "Проведение в 1С",
 156        "Finalize" => "Финализация",
 157        _ => stepName ?? "-"
 158    };
 159
 160    private static string? Blank(string? value) => string.IsNullOrWhiteSpace(value) ? null : value;
 161
 162    /// <summary>Время в БД — UTC; клиент показывает его в МСК. Kind нормализуется, чтобы JSON получил суффикс Z.</summa
 163    private static DateTime Utc(DateTime value) => value.Kind switch
 164    {
 165        DateTimeKind.Utc => value,
 166        DateTimeKind.Local => value.ToUniversalTime(),
 167        _ => DateTime.SpecifyKind(value, DateTimeKind.Utc)
 168    };
 169}