< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.AvdPriceController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/AvdPriceController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 69
Coverable lines: 69
Total lines: 111
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 40
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
.ctor(...)100%210%
Search()0%4260%
<Search()0%2040%
Map(...)0%930300%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/AvdPriceController.cs

#LineLine coverage
 1using System.Globalization;
 2using Microsoft.AspNetCore.Authorization;
 3using Microsoft.AspNetCore.Mvc;
 4using Microsoft.Extensions.Caching.Memory;
 5using OzonDomains;
 6using Services.ApiServices.AvdApi;
 7using Services.ApiServices.TradesoftApi.Models.Response;
 8using Services.ApiSupplierSettingsServices;
 9using OzonOrdersWeb.Filters;
 10
 11namespace OzonOrdersWeb.Areas.Studio2.Controllers;
 12
 13[Area("Studio2")]
 14[Authorize(Roles = "User,Admin")]
 15[ServiceFilter(typeof(SupplierQuotationHistoryFilter), Order = 0)]
 16[ServiceFilter(typeof(SupplierDeliverySurchargeFilter), Order = 1)]
 17[ServiceFilter(typeof(SupplierWarehouseRestrictionFilter), Order = 2)]
 18public sealed class AvdPriceController : Controller
 19{
 20    private readonly AvdDataManager _avd;
 21    private readonly ApiSupplierSettingsService _settings;
 22    private readonly IMemoryCache _cache;
 23
 24    /// <summary>Проценка страницы транзакции повторяется при каждом открытии документа, а цены
 25    /// поставщика за минуту не меняются — короткий кэш убирает лишние обращения к API.</summary>
 026    private static readonly TimeSpan QuotationTtl = TimeSpan.FromMinutes(1);
 27
 028    public AvdPriceController(AvdDataManager avd, ApiSupplierSettingsService settings, IMemoryCache cache)
 29    {
 030        _avd = avd;
 031        _settings = settings;
 032        _cache = cache;
 033    }
 34
 35    [HttpGet]
 36    public async Task<IActionResult> Search(string code, string? brand, int? orderId = null)
 37    {
 038        if (string.IsNullOrWhiteSpace(code)) return Ok(Array.Empty<PreOrderItem>());
 39        try
 40        {
 041            var settings = await _settings.GetAvdAsync(HttpContext.RequestAborted);
 042            if (!settings.IsQuotationEnabled) return Ok(Array.Empty<PreOrderItem>());
 043            var article = code.Trim();
 044            var cacheKey = $"quotation:avd:{article}:{brand?.Trim()}";
 045            var items = await _cache.GetOrCreateAsync(cacheKey, async entry =>
 046            {
 047                entry.AbsoluteExpirationRelativeToNow = QuotationTtl;
 048                var catalogs = await _avd.GetCatalogsListAsync(article, HttpContext.RequestAborted);
 049                var catalog = catalogs.FirstOrDefault(x => !string.IsNullOrWhiteSpace(brand) && string.Equals(x, brand.T
 050                    ?? catalogs.FirstOrDefault();
 051                var offers = await _avd.GetOriginalPriceAsync(article, catalog, null, HttpContext.RequestAborted);
 052                return offers.Select(x => Map(x, settings.SupplierId, settings.Supplier?.CurrencyCode, settings.Delivery
 053                    .Where(x => x != null).Cast<PreOrderItem>()
 054                    .GroupBy(x => x.ItemId, StringComparer.Ordinal).Select(x => x.First()).ToList();
 055            });
 056            return Ok(items);
 57        }
 058        catch (AvdApiException ex) { return Ok(new { items = Array.Empty<PreOrderItem>(), error = ex.Message }); }
 059        catch (Exception ex) when (ex is HttpRequestException or TimeoutException or TaskCanceledException)
 60        {
 061            return Ok(new { items = Array.Empty<PreOrderItem>(), error = "Сервис АВД временно недоступен." });
 62        }
 063    }
 64
 65    private static PreOrderItem? Map(AvdPriceOffer offer, int? supplierId, CurrencyCode? supplierCurrency,
 66        string? deliveryDestination)
 67    {
 068        if (offer.Price is null) return null;
 069        var itemId = string.Join("|", offer.ItemNumber, offer.CatalogName, offer.SupplierName, offer.Price.Value.ToStrin
 070        var days = offer.SupplierPeriod ?? 0;
 071        var description = string.Join("; ", new[]
 072        {
 073            $"Артикул: {offer.ItemNumber}", $"Каталог: {offer.CatalogName}",
 074            $"Поставщик: {offer.SupplierName}", $"Наличие: {offer.Quantity?.ToString(CultureInfo.InvariantCulture) ?? "0
 075            $"Срок поставщика: {offer.SupplierPeriod?.ToString() ?? "не указан"} д.",
 076            string.IsNullOrWhiteSpace(offer.PriceAverage) ? null : $"Средний срок: {offer.PriceAverage}",
 077            string.IsNullOrWhiteSpace(offer.PriceStatistic) ? null : $"Статистика: {offer.PriceStatistic}%",
 078            string.IsNullOrWhiteSpace(offer.DatePrice) ? null : $"Прайс обновлён: {offer.DatePrice}"
 079        }.Where(x => !string.IsNullOrWhiteSpace(x)));
 080        return new PreOrderItem
 081        {
 082            Caption = string.IsNullOrWhiteSpace(offer.ItemName) ? offer.ItemNumber : offer.ItemName,
 083            Producer = offer.CatalogName,
 084            Code = offer.ItemNumber,
 085            Rest = (offer.Quantity ?? 0m).ToString("0.##", CultureInfo.InvariantCulture),
 086            MinQuantity = offer.Multiply ?? 0,
 087            DeliveryDays = offer.SupplierPeriod?.ToString(CultureInfo.InvariantCulture) ?? "-",
 088            DeliveryDaysMin = days,
 089            DeliveryDaysMax = days,
 090            Price = offer.Price.Value.ToString("0.##", CultureInfo.InvariantCulture),
 091            CostPrice = offer.Price.Value.ToString("0.##", CultureInfo.InvariantCulture),
 092            CostPriceFormatted = offer.Price.Value.ToString("0.##", CultureInfo.InvariantCulture),
 093            CurrencyCode = "RUB",
 094            SourcePrice = offer.Price.Value,
 095            SourceCurrencyCode = "RUB",
 096            Direction = string.IsNullOrWhiteSpace(offer.DealerStore) ? offer.SupplierName : offer.DealerStore,
 097            Title = "АВД",
 098            SiteUrl = "https://www.avdmotors.ru/",
 099            ItemId = itemId,
 0100            ItemHash = offer.Hash,
 0101            Description = description,
 0102            PriceDescription = $"Цена АВД: {offer.Price.Value:0.##} RUB",
 0103            PreferredSupplierId = supplierId,
 0104            PreferredSupplierCurrencyCode = supplierCurrency?.ToString(),
 0105            ProviderData = string.IsNullOrWhiteSpace(deliveryDestination) ? null : new Dictionary<string, string?>
 0106            {
 0107                ["deliveryDestination"] = deliveryDestination.Trim()
 0108            }
 0109        };
 110    }
 111}