< Summary

Information
Class: Services.OzonReturnsServices.ReturnsRunSummary
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/OzonReturnsServices/ReturnsLoadModels.cs
Line coverage
96%
Covered lines: 31
Uncovered lines: 1
Coverable lines: 32
Total lines: 91
Line coverage: 96.8%
Branch coverage
100%
Covered branches: 20
Total branches: 20
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Processed()100%11100%
get_Inserted()100%11100%
get_StatusChanged()100%11100%
get_Linked()100%11100%
get_Errors()100%11100%
get_ClientTotals()100%11100%
.ctor()100%11100%
get_FromDate()100%11100%
get_ToDate()100%11100%
get_Incremental()100%11100%
get_HasErrors()100%210%
get_HasChanges()100%11100%
BuildParts()100%1010100%
BuildAlertText()100%11100%
BuildReport()100%22100%
BuildTelegramBody()100%88100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/OzonReturnsServices/ReturnsLoadModels.cs

#LineLine coverage
 1using System.Text;
 2
 3namespace Services.OzonReturnsServices;
 4
 5/// <summary>Итоги загрузки по одному клиенту Ozon за прогон.</summary>
 6public readonly record struct ClientLoadTotals(int Processed, int Inserted, int StatusChanged, int Linked)
 7{
 8    public ClientLoadTotals Add(int processed, int inserted, int statusChanged, int linked) =>
 9        new(Processed + processed, Inserted + inserted, StatusChanged + statusChanged, Linked + linked);
 10}
 11
 12/// <summary>Итог одного прогона загрузки возвратов.</summary>
 13/// <param name="Report">Краткий текст для Hangfire и SignalR.</param>
 14/// <param name="Errors">Ошибки по клиентам; непустой список означает неуспешный прогон.</param>
 15public sealed record ReturnsLoadOutcome(string Report, IReadOnlyList<string> Errors)
 16{
 17    public bool HasErrors => Errors.Count > 0;
 18
 19    public static ReturnsLoadOutcome Success(string report) => new(report, Array.Empty<string>());
 20
 21    public static ReturnsLoadOutcome Failure(string report, IReadOnlyList<string> errors) => new(report, errors);
 22}
 23
 24/// <summary>
 25/// Сводка прогона: счётчики -> тексты для тоста, Telegram и Hangfire.
 26/// Чистое форматирование, вынесенное из джоба, чтобы его можно было проверить тестами.
 27/// </summary>
 28public sealed class ReturnsRunSummary
 29{
 2130    public int Processed { get; init; }
 3831    public int Inserted { get; init; }
 3432    public int StatusChanged { get; init; }
 3033    public int Linked { get; init; }
 5634    public IReadOnlyList<string> Errors { get; init; } = Array.Empty<string>();
 1935    public IReadOnlyDictionary<string, ClientLoadTotals> ClientTotals { get; init; } =
 1736        new Dictionary<string, ClientLoadTotals>();
 1837    public DateTime FromDate { get; init; }
 1838    public DateTime ToDate { get; init; }
 1839    public bool Incremental { get; init; }
 40
 041    public bool HasErrors => Errors.Count > 0;
 42
 43    /// <summary>Что-то реально изменилось в БД — единственный повод беспокоить людей на регулярном тике.</summary>
 444    public bool HasChanges => Inserted + StatusChanged > 0;
 45
 46    /// <summary>Короткие части сводки; нулевые счётчики не печатаются вовсе.</summary>
 47    public IReadOnlyList<string> BuildParts()
 48    {
 849        var parts = new List<string>();
 1350        if (Inserted > 0) parts.Add($"новых {Inserted}");
 951        if (StatusChanged > 0) parts.Add($"статус {StatusChanged}");
 952        if (Linked > 0) parts.Add($"заказов {Linked}");
 1053        if (Errors.Count > 0) parts.Add($"ошибок {Errors.Count}");
 1054        if (parts.Count == 0) parts.Add("без изменений");
 855        return parts;
 56    }
 57
 58    /// <summary>Однострочный текст тоста в общей системе алертов.</summary>
 859    public string BuildAlertText() => string.Join(" | ", BuildParts());
 60
 61    /// <summary>
 62    /// Текст для Hangfire и SignalR. Счётчики честные: «получено» — размер выдачи API,
 63    /// «новых» и «со сменой статуса» — то, что действительно изменилось в БД.
 64    /// </summary>
 65    public string BuildReport() =>
 266        $"Получено {Processed} возвратов: новых {Inserted}, со сменой статуса {StatusChanged}, " +
 267        $"связано с заказами {Linked}." +
 268        (Errors.Count > 0 ? $" Ошибок: {Errors.Count}." : string.Empty);
 69
 70    /// <summary>
 71    /// Развёрнутая сводка для Telegram: период, итог, разбивка по клиентам (только когда их больше
 72    /// одного) и тексты ошибок.
 73    /// </summary>
 74    public string BuildTelegramBody()
 75    {
 476        var sb = new StringBuilder();
 477        sb.AppendLine($"{FromDate:dd.MM.yyyy} — {ToDate:dd.MM.yyyy}{(Incremental ? ", инкрементально" : "")}");
 478        sb.AppendLine(BuildAlertText());
 79
 480        if (ClientTotals.Count > 1)
 81        {
 682            foreach (var kv in ClientTotals)
 283                sb.AppendLine($"  {kv.Key}: новых {kv.Value.Inserted}, статус {kv.Value.StatusChanged}, заказов {kv.Valu
 84        }
 85
 1286        foreach (var error in Errors)
 287            sb.AppendLine($"  ! {error}");
 88
 489        return sb.ToString();
 90    }
 91}