< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.BergPriceController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/BergPriceController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 43
Coverable lines: 43
Total lines: 92
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 26
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%600240%

File(s)

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

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Mvc;
 3using Microsoft.Extensions.Caching.Memory;
 4using Newtonsoft.Json.Linq;
 5using OzonDomains;
 6using Services.ApiServices.BergApi;
 7using Services.ApiServices.TradesoftApi.Models.Response;
 8using Services.ApiSupplierSettingsServices;
 9using Services.ProducerAliases;
 10using OzonOrdersWeb.Filters;
 11
 12namespace OzonOrdersWeb.Areas.Studio2.Controllers;
 13
 14[Area("Studio2")]
 15[Authorize(Roles = "User,Admin")]
 16[ServiceFilter(typeof(SupplierQuotationHistoryFilter), Order = 0)]
 17[ServiceFilter(typeof(SupplierDeliverySurchargeFilter), Order = 1)]
 18[ServiceFilter(typeof(SupplierWarehouseRestrictionFilter), Order = 2)]
 19public sealed class BergPriceController : Controller
 20{
 21    private readonly BergDataManager _berg;
 22    private readonly ApiSupplierSettingsService _settings;
 23    private readonly ProducerBrandAliasService _brandAliases;
 24    private readonly BergDeliveryAddressMappingService _deliveryAddresses;
 25
 26    private readonly IMemoryCache _cache;
 27
 28    /// <summary>Проценка повторяется при каждом открытии документа, а цены за минуту не меняются.</summary>
 029    private static readonly TimeSpan QuotationTtl = TimeSpan.FromMinutes(1);
 30
 031    public BergPriceController(BergDataManager berg, ApiSupplierSettingsService settings,
 032        ProducerBrandAliasService brandAliases, BergDeliveryAddressMappingService deliveryAddresses, IMemoryCache cache)
 33    {
 034        _berg = berg;
 035        _settings = settings;
 036        _brandAliases = brandAliases;
 037        _deliveryAddresses = deliveryAddresses;
 038        _cache = cache;
 039    }
 40
 41    [HttpGet]
 42    public async Task<IActionResult> Search(string code, string? brand, int? orderId = null, string? zasylWarehouseName 
 43    {
 044        if (string.IsNullOrWhiteSpace(code))
 045            return Ok(Array.Empty<PreOrderItem>());
 46
 47        try
 48        {
 049            var settings = await _settings.GetBergAsync(HttpContext.RequestAborted);
 050            if (!settings.IsQuotationEnabled)
 051                return Ok(Array.Empty<PreOrderItem>());
 52
 053            var addresses = await _berg.GetActiveShipmentAddressesAsync(HttpContext.RequestAborted);
 054            var activeAddress = addresses["shipment_address_list"]?.OfType<JObject>()
 055                .FirstOrDefault(x => x.Value<int?>("state") == 1);
 056            var addressId = activeAddress?.Value<long?>("id");
 057            var deliveryDestination = activeAddress is null ? null : string.Join(", ", new[]
 058            {
 059                activeAddress.Value<string>("city"), activeAddress.Value<string>("address"), activeAddress.Value<string>
 060            }.Where(value => !string.IsNullOrWhiteSpace(value)).Select(value => value!.Trim()).Distinct());
 061            var response = await _cache.GetOrCreateAsync(
 062                $"quotation:berg:{code.Trim()}:{brand?.Trim()}:{addressId}",
 063                entry =>
 064                {
 065                    entry.AbsoluteExpirationRelativeToNow = QuotationTtl;
 066                    return _berg.GetStockAsync(code.Trim(), brand?.Trim(), includeAnalogs: false, addressId, HttpContext
 067                });
 068            if (response is null)
 069                return Ok(Array.Empty<PreOrderItem>());
 70
 71            // Berg параметр brand_name фактически игнорирует и отдаёт все карточки артикула,
 72            // поэтому бренд отсекается здесь — с учётом алиасов, иначе «Kayaba» не совпадёт с «KYB».
 073            var aliases = await _brandAliases.GetMapAsync(HttpContext.RequestAborted);
 74            // Адрес отгрузки Berg привязан к складу заказа: без связи предложение показываем,
 75            // но заказать его через API нельзя — фронтенд узнаёт об этом по deliveryMappingLinked.
 076            var deliveryMapping = await _deliveryAddresses.ResolveAsync(orderId, zasylWarehouseName, HttpContext.Request
 077            return Ok(BergPriceMapper.Map(response, settings.SupplierId, settings.Supplier?.CurrencyCode,
 078                deliveryDestination: settings.DeliveryAddress ?? deliveryMapping?.AddressName ?? deliveryDestination,
 079                requestedBrand: brand?.Trim(), brandAliases: aliases,
 080                deliveryMappingLinked: deliveryMapping is not null,
 081                deliverySettingsUrl: Url.Action("Berg", "ApiSupplierSettings", new { area = "Studio2" })));
 82        }
 083        catch (BergApiException ex)
 84        {
 085            return Ok(new { items = Array.Empty<PreOrderItem>(), error = ex.Message });
 86        }
 087        catch (Exception ex) when (ex is HttpRequestException or TimeoutException or TaskCanceledException)
 88        {
 089            return Ok(new { items = Array.Empty<PreOrderItem>(), error = "Сервис Berg временно недоступен." });
 90        }
 091    }
 92}