< Summary

Information
Class: OzonOrdersWeb.Filters.SupplierQuotationHistoryFilter
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Filters/SupplierQuotationHistoryFilter.cs
Line coverage
30%
Covered lines: 17
Uncovered lines: 39
Coverable lines: 56
Total lines: 82
Line coverage: 30.3%
Branch coverage
50%
Covered branches: 70
Total branches: 140
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
OnActionExecutionAsync()0%812280%
ResolveProviderKey(...)76.08%4439265.38%
ToNullableInt(...)0%110100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Filters/SupplierQuotationHistoryFilter.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Text.Json;
 3using Microsoft.AspNetCore.Mvc;
 4using Microsoft.AspNetCore.Mvc.Filters;
 5using Services.ApiSupplierSettingsServices;
 6
 7namespace OzonOrdersWeb.Filters;
 8
 9/// <summary>Фиксирует результат проценки после формирования обычного HTTP-ответа.</summary>
 10public sealed class SupplierQuotationHistoryFilter : IAsyncActionFilter
 11{
 12    private readonly ISupplierQuotationHistoryService _history;
 13
 014    public SupplierQuotationHistoryFilter(ISupplierQuotationHistoryService history) => _history = history;
 15
 16    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
 17    {
 018        var startedAtUtc = DateTime.UtcNow;
 019        var stopwatch = Stopwatch.StartNew();
 020        var executed = await next();
 021        stopwatch.Stop();
 22
 023        if (context.HttpContext.Items.ContainsKey(SupplierWarehouseRestrictionFilter.SkipQuotationHistoryItemKey))
 024            return;
 25
 026        var providerKey = ResolveProviderKey(executed.Controller.GetType().Name);
 027        if (providerKey == null || !context.ActionArguments.TryGetValue("code", out var codeValue) || codeValue is not s
 028            return;
 29
 030        var brand = context.ActionArguments.TryGetValue("brand", out var brandValue) ? brandValue as string : null;
 031        var orderId = ToNullableInt(context.ActionArguments.TryGetValue("orderId", out var orderIdValue) ? orderIdValue 
 032        var result = executed.Result as ObjectResult;
 033        var offers = SupplierQuotationResultReader.ExtractOffers(result?.Value);
 34        // Необработанное исключение — это отказ проценки, а не «поставщик ничего не предложил»:
 35        // без этой ветки такой запрос попадал в историю со статусом Empty и терялся среди пустых.
 036        var error = executed.Exception is { } exception
 037            ? $"{exception.GetType().Name}: {exception.Message}"
 038            : SupplierQuotationResultReader.ExtractError(result?.Value) ?? (result is { StatusCode: >= 400 } ? $"HTTP {r
 039        var parameters = context.ActionArguments
 040            .Where(x => x.Value is string or int or bool or decimal or null)
 041            .ToDictionary(x => x.Key, x => x.Value);
 042        await _history.RecordAsync(providerKey, orderId, code, brand, null, offers, startedAtUtc, stopwatch, error,
 043            JsonSerializer.Serialize(parameters),
 044            context.HttpContext.RequestAborted);
 045    }
 46
 47    /// <summary>Сопоставляет контроллер проценки с ProviderKey. Новый *PriceController обязан
 48    /// добавить сюда свою пару — иначе история проценки для него молча не пишется.</summary>
 2449    public static string? ResolveProviderKey(string controllerTypeName) => controllerTypeName switch
 2450    {
 151        "ArmtekPriceController" => "Armtek",
 152        "ArmtekByPriceController" => "ArmtekBy",
 153        "ShateMPriceController" => "ShateM",
 654        "AvdPriceController" => "Avd",
 555        "BergPriceController" => "Berg",
 056        "JapartsPriceController" => "Japarts",
 157        "MotexPriceController" => "Motex",
 158        "MlAutoPriceController" => "MlAuto",
 159        "MlAutoRuPriceController" => "MlAutoRu",
 160        "ForumAutoPriceController" => "ForumAuto",
 161        "ForumAutoInterpartsPriceController" => "ForumAutoInterparts",
 062        "ForumAutoPiterPriceController" => "ForumAutoPiter",
 063        "ForumAutoRostovPriceController" => "ForumAutoRostov",
 164        "ForumAutoIstraPriceController" => "ForumAutoIstra",
 065        "FavoritPartsPriceController" => "FavoritParts",
 066        "ProfitLigaPriceController" => "ProfitLiga",
 067        "NikeiPriceController" => "Nikei",
 168        "FavoritPartsIstraPriceController" => "FavoritPartsIstra",
 169        "FavoritPartsRostovPriceController" => "FavoritPartsRostov",
 070        "MoskvorechieIstraPriceController" => "MoskvorechieIstra",
 071        "MikadoMskHod20PriceController" => "MikadoMskHod20",
 072        "ZZapMoscowPriceController" => "ZZapMoscow",
 273        _ => null
 2474    };
 75
 076    private static int? ToNullableInt(object? value) => value switch
 077    {
 078        int id when id > 0 => id,
 079        string text when int.TryParse(text, out var id) && id > 0 => id,
 080        _ => null
 081    };
 82}