< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.MikadoMskHod20PriceController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/MikadoMskHod20PriceController.cs
Line coverage
7%
Covered lines: 4
Uncovered lines: 48
Coverable lines: 52
Total lines: 97
Line coverage: 7.6%
Branch coverage
6%
Covered branches: 3
Total branches: 46
Branch coverage: 6.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Search()50%20627.27%
GetExpressOptions()0%2040%
Map(...)0%702260%
Value()0%2040%

File(s)

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

#LineLine coverage
 1using System.Globalization;
 2using System.Xml.Linq;
 3using Microsoft.AspNetCore.Authorization;
 4using Microsoft.AspNetCore.Mvc;
 5using OzonDomains.Models;
 6using OzonOrdersWeb.Filters;
 7using Services.ApiServices.MikadoApi;
 8using Services.ApiServices.TradesoftApi.Models.Response;
 9using Services.ApiSupplierSettingsServices;
 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 MikadoMskHod20PriceController : Controller
 19{
 20    private readonly MikadoDataManager _mikado;
 21    private readonly ApiSupplierSettingsService _settings;
 1222    public MikadoMskHod20PriceController(MikadoDataManager mikado, ApiSupplierSettingsService settings) => (_mikado, _se
 23
 24    [HttpGet]
 25    public async Task<IActionResult> Search(string code, string? brand, int? orderId = null, string? zasylWarehouseName 
 26    {
 627        if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(brand))
 628            return Ok(Array.Empty<PreOrderItem>());
 29        try
 30        {
 031            var settings = await _settings.GetMikadoMskHod20Async(HttpContext.RequestAborted);
 032            if (!settings.IsQuotationEnabled) return Ok(Array.Empty<PreOrderItem>());
 033            var xml = await _mikado.CodeBrandStockInfoAsync(code.Trim(), brand.Trim(), HttpContext.RequestAborted);
 034            return Ok(SupplierQuotationDeliveryDestination.Apply(
 035                Map(xml, code.Trim(), brand.Trim(), settings), settings.DeliveryAddress));
 36        }
 037        catch (MikadoApiException ex) { return Ok(new { items = Array.Empty<PreOrderItem>(), error = ex.Message }); }
 038        catch (Exception ex) when (ex is HttpRequestException or TimeoutException or TaskCanceledException)
 39        {
 040            return Ok(new { items = Array.Empty<PreOrderItem>(), error = "Сервис Микадо временно недоступен." });
 41        }
 642    }
 43
 44    /// <summary>Возвращает только варианты экспресс-доставки, доступные для выбранных кода и склада.</summary>
 45    [HttpGet]
 46    public async Task<IActionResult> GetExpressOptions(string orderCode, int stockId)
 47    {
 048        if (string.IsNullOrWhiteSpace(orderCode) || stockId <= 0)
 049            return BadRequest(new { error = "Не задан код детали или склад Микадо." });
 50        try
 51        {
 052            var xml = await _mikado.GetExpressOptionsAsync(orderCode.Trim(), stockId, HttpContext.RequestAborted);
 053            var options = XDocument.Parse(xml).Descendants()
 054                .Where(x => x.Elements().Any(child => child.Name.LocalName == "ExpressID"))
 055                .Select(x => new
 056                {
 057                    Id = int.TryParse(x.Elements().FirstOrDefault(child => child.Name.LocalName == "ExpressID")?.Value, 
 058                    // Ответ Express.asmx у Микадо может содержать кириллические имена элементов
 059                    // в legacy-кодировке. ExpressID стабилен, а остальные поля — подпись варианта.
 060                    Description = string.Join(" · ", x.Elements()
 061                        .Where(child => child.Name.LocalName != "ExpressID")
 062                        .Select(child => child.Value.Trim()).Where(value => !string.IsNullOrWhiteSpace(value)))
 063                })
 064                .Where(x => x.Id > 0).DistinctBy(x => x.Id)
 065                .Select(x => new { id = x.Id, label = string.IsNullOrWhiteSpace(x.Description) ? "Экспресс-доставка" : x
 066                .ToList();
 067            return Ok(options);
 68        }
 069        catch (MikadoApiException ex) { return BadRequest(new { error = ex.Message }); }
 070        catch (System.Xml.XmlException) { return BadRequest(new { error = "Микадо вернул некорректный ответ по экспресс-
 071    }
 72
 73    private static List<PreOrderItem> Map(string xml, string code, string brand, ApiSupplierSettings settings)
 74    {
 075        var result = new List<PreOrderItem>();
 076        var lines = XDocument.Parse(xml).Descendants().Where(x => x.Name.LocalName == "CodeBrandLine");
 077        foreach (var line in lines)
 78        {
 079            string? Value(string name) => line.Elements().FirstOrDefault(x => x.Name.LocalName == name)?.Value?.Trim();
 080            var priceText = Value("PriceRUR");
 081            if (!decimal.TryParse(priceText, NumberStyles.Number, CultureInfo.InvariantCulture, out var price)) continue
 082            var delayText = Value("DeliveryDelay") ?? Value("StockDelay") ?? "0";
 083            var days = int.TryParse(new string(delayText.Where(char.IsDigit).ToArray()), out var parsed) ? parsed : 0;
 084            var stockId = Value("StokID") ?? string.Empty;
 085            var itemId = string.Join("|", Value("OrderCode"), stockId, priceText);
 086            result.Add(new PreOrderItem { Caption = Value("Name") ?? code, Producer = Value("Brand") ?? brand, Code = co
 087                Rest = Value("StockQTY") ?? "0", MinQuantity = int.TryParse(Value("MinZakazQTY"), out var min) ? Math.Ma
 088                DeliveryDays = days.ToString(CultureInfo.InvariantCulture), DeliveryDaysMin = days, DeliveryDaysMax = da
 089                Price = price.ToString("0.##", CultureInfo.InvariantCulture), CostPrice = price.ToString("0.##", Culture
 090                SourcePrice = price, SourceCurrencyCode = "RUB", Direction = Value("StokName") ?? stockId, ItemId = item
 091                Title = "Микадо МскХод20", SiteUrl = "https://mikado-parts.ru", PreferredSupplierId = settings.SupplierI
 092                PreferredSupplierCurrencyCode = settings.Supplier?.CurrencyCode.ToString(), Description = $"Склад: {Valu
 093                ProviderData = new Dictionary<string, string?> { ["providerKey"] = ApiSupplierSettings.MikadoMskHod20Pro
 94        }
 095        return result;
 96    }
 97}