< Summary

Information
Class: Services.ApiServices._1CApi.OData.OneCResponseErrors
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/1CApi/OData/OneCResponseErrors.cs
Line coverage
100%
Covered lines: 20
Uncovered lines: 0
Coverable lines: 20
Total lines: 59
Line coverage: 100%
Branch coverage
88%
Covered branches: 16
Total branches: 18
Branch coverage: 88.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Describe(...)100%88100%
AppendOneCDetails(...)100%66100%
Reason(...)50%44100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/1CApi/OData/OneCResponseErrors.cs

#LineLine coverage
 1using Services.ApiServices._1CApi.Models;
 2
 3namespace Services.ApiServices._1CApi.OData;
 4
 5/// <summary>
 6/// Единое место, где причина сбоя 1С попадает в <see cref="OneCResponse.ErrorDetail"/>: менеджеры
 7/// документов не собирают этот текст сами, чтобы формат был одинаковым для перемещения, расходной и приходной.
 8/// </summary>
 9public static class OneCResponseErrors
 10{
 11    /// <summary>Потолок под <c>BackgroundTransactionResults.ErrorMessage</c> (text) и DetailsJson.</summary>
 12    public const int MaxLength = 8000;
 13
 14    /// <summary>
 15    /// Полный текст ответа 1С без усечения до 500 символов: статус, код, метод, эндпоинт и причина.
 16    /// Для исключений, не пришедших из ответа 1С (сеть, таймаут), — текст исключения.
 17    /// </summary>
 18    public static string Describe(Exception ex)
 19    {
 420        var text = ex switch
 421        {
 222            OneCDocumentPostingException posting => posting.FullDetail,
 123            OneCODataException { Error: not null } odata => odata.Error.ToDetailText(),
 124            _ => ex.Message
 425        };
 26
 427        return text.Length <= MaxLength ? text : text[..MaxLength] + "…";
 28    }
 29
 30    /// <summary>
 31    /// Дописывает к краткому тексту ошибки полный ответ 1С из <see cref="OneCResponse.ErrorDetail"/> —
 32    /// только тот, чьей причины в тексте ещё нет (не дублирует, когда <c>PostingError</c> уже содержит её целиком;
 33    /// дописывает, когда причину усекли или подменили догадкой про остаток). Если дописывать нечего,
 34    /// возвращает <paramref name="text"/> как есть, поэтому существующие сводки не меняются.
 35    /// </summary>
 36    public static string? AppendOneCDetails(string? text, IEnumerable<OneCResponse> responses)
 37    {
 1338        var extra = responses
 1539            .Select(r => r.ErrorDetail)
 1540            .Where(d => !string.IsNullOrWhiteSpace(d))
 741            .Select(d => d!)
 1342            .Distinct()
 643            .Where(d => string.IsNullOrEmpty(text) || !text.Contains(Reason(d), StringComparison.Ordinal))
 1344            .ToList();
 45
 1346        if (extra.Count == 0)
 947            return text;
 48
 449        var tail = "Ответ 1С: " + string.Join("; ", extra);
 450        return string.IsNullOrWhiteSpace(text) ? tail : $"{text} | {tail}";
 51    }
 52
 53    /// <summary>Причина без служебного префикса «HTTP … метод эндпоинт: » (см. <see cref="OneCODataError.ToDetailText"/
 54    private static string Reason(string detail)
 55    {
 556        var idx = detail.IndexOf(": ", StringComparison.Ordinal);
 557        return idx >= 0 && detail.StartsWith("HTTP ", StringComparison.Ordinal) ? detail[(idx + 2)..] : detail;
 58    }
 59}