< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.Directories.OzonClientsController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/Directories/OzonClientsController .cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 245
Coverable lines: 245
Total lines: 478
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 100
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
Index()0%2040%
Create()0%2040%
Create()0%420200%
Edit()0%930300%
Edit()0%420200%
Delete()0%2040%
DeleteConfirmed()0%620%
SearchCounterparties()100%210%
SearchOrganizations()100%210%
GetAllowedBitrixWarehouseSelectItemsAsync()0%7280%
IsAllowedBitrixWarehouseNameAsync()0%620%
ValidateOzonApiCredentialsAsync()0%7280%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/Directories/OzonClientsController .cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Mvc;
 3using Microsoft.AspNetCore.Mvc.Rendering;
 4using Microsoft.EntityFrameworkCore;
 5using Microsoft.Extensions.Http;
 6using SlqStudio.Application.Services.EmailService;
 7using OzonDomains;
 8using OzonDomains.Models;
 9using OzonOrdersWeb.ViewModels.OzonClientViewModels;
 10using OzonOrdersWeb.WebServices.Directories;
 11using Services.ApiServices;
 12using Services.ApiServices.OzonApi;
 13using Services.ApiServices.OzonApi.Filters;
 14using Services.ApiServices.YandexApi;
 15using Services.DataServices;
 16using Services.Authorization.Services;
 17using System.Security.Claims;
 18
 19
 20namespace OzonOrdersWeb.Areas.Studio2.Controllers.Directories
 21{
 22    [Authorize(Roles = "Admin")]
 23    [Area("Studio2")]
 24    public class OzonClientsController : Controller
 25    {
 26        private readonly OzonClientServices _ozonClientServices;
 27        private readonly OzonJsonDataBuilder _jsonDataBuilder;
 28        private readonly YandexDataManager _yandexDataManager;
 29        private readonly OneCDataManager _oneCDataManager;
 30        private readonly IHttpClientFactory _httpClientFactory;
 31        private readonly IEmailService? _emailService;
 32        private readonly IScopeFilterValuesService _scopeFilterValuesService;
 33
 034        public OzonClientsController(OzonClientServices ozonClientServices,
 035            OzonJsonDataBuilder jsonDataBuilder,
 036            YandexDataManager yandexDataManager,
 037            OneCDataManager oneCDataManager,
 038            IScopeFilterValuesService scopeFilterValuesService,
 039            IHttpClientFactory httpClientFactory,
 040            IEmailService? emailService = null)
 41        {
 042            _ozonClientServices = ozonClientServices;
 043            _jsonDataBuilder = jsonDataBuilder;
 044            _yandexDataManager = yandexDataManager;
 045            _oneCDataManager = oneCDataManager;
 046            _scopeFilterValuesService = scopeFilterValuesService;
 047            _httpClientFactory = httpClientFactory;
 048            _emailService = emailService;
 049        }
 50
 51        /// <summary>Весь список клиентов для грида AG Grid: фильтры и сортировка — на клиенте, правка — на странице Edi
 52        public async Task<IActionResult> Index()
 53        {
 054            var ozonClients = (await _ozonClientServices.GetOzonClients()).OrderBy(c => c.Name).ToList();
 55
 56            List<SupplierResponse> counterparties;
 57            try
 58            {
 059                counterparties = (await _oneCDataManager.GetSupplierListAsync())?.ToList() ?? new List<SupplierResponse>
 060            }
 061            catch (Exception)
 62            {
 063                counterparties = [];
 064            }
 65
 066            return View(DirectoryGridRows.BuildOzonClients(ozonClients, counterparties));
 067        }
 68
 69        public async Task<IActionResult> Create()
 70        {
 071            if (TempData.ContainsKey("CreateInfo") && TempData["CreateInfo"] != null)
 72            {
 073                string? result = TempData["CreateInfo"] as string;
 074                ViewData["CreateInfo"] = result;
 75            }
 76
 077            var viewModel = new CreateOzonClientViewModel()
 078            {
 079                CurrencyCodes = new List<SelectListItem>
 080                {
 081                    new SelectListItem { Value = CurrencyCode.RUB.ToString(), Text = "RUB" },
 082                    new SelectListItem { Value = CurrencyCode.USD.ToString(), Text = "USD" },
 083                    new SelectListItem { Value = CurrencyCode.EUR.ToString(), Text = "EUR" },
 084                    new SelectListItem { Value = CurrencyCode.BYN.ToString(), Text = "BYN" },
 085                },
 086                ClientTypes = new List<SelectListItem>
 087                {
 088                    new SelectListItem { Value = ClientType.ALL.ToString(), Text = "Другое" },
 089                    new SelectListItem { Value = ClientType.OZON.ToString(), Text = "Ozon" },
 090                    new SelectListItem { Value = ClientType.YANDEX.ToString(), Text = "Yandex" }
 091                },
 092                YandexClients = await _yandexDataManager.GetAccountCampaigns(),
 093                YandexApiKey = await _yandexDataManager.GetApiKey(),
 094                BitrixWarehouseNames = (await GetAllowedBitrixWarehouseSelectItemsAsync())
 095            };
 96
 097            return View(viewModel);
 098        }
 99
 100        [HttpPost]
 101        [ValidateAntiForgeryToken]
 102        public async Task<IActionResult> Create(
 103            [Bind("Id,Name,WarehouseName,ClientId,ApiKey,CurrencyCode,ClientType,INNCode")]
 104            OzonClient ozonClient)
 105        {
 0106            if (!await IsAllowedBitrixWarehouseNameAsync(ozonClient.WarehouseName))
 107            {
 0108                TempData["CreateInfo"] = "Название склада должно быть выбрано из разрешенного списка складов Bitrix.";
 0109                return RedirectToAction(nameof(Create));
 110            }
 111
 0112            if (await _ozonClientServices.GetOzonClientAsync(ozonClient) == null)
 113            {
 0114                if (ozonClient.ClientId != null && ozonClient.ApiKey != null)
 115                {
 0116                    var clients = await _ozonClientServices.GetOzonClients();
 0117                    if (ozonClient.ClientType == ClientType.OZON)
 118                    {
 0119                        if (!clients.Where(c => c.DecryptApiKey == ozonClient.ApiKey).Any())
 120                        {
 0121                            var (isValid, errorDetails) =
 0122                                await ValidateOzonApiCredentialsAsync(ozonClient.ClientId, ozonClient.ApiKey);
 0123                            if (isValid)
 124                            {
 0125                                await _ozonClientServices.AddOzonClient(ozonClient);
 0126                                return RedirectToAction(nameof(Index));
 127                            }
 128                            else
 129                            {
 0130                                TempData["CreateInfo"] =
 0131                                    $"Api данные некорректны. Не удалось пройти тестовый запрос Ozon API. " +
 0132                                    $"{errorDetails}";
 0133                                return RedirectToAction(nameof(Create));
 134                            }
 135                        }
 136                        else
 137                        {
 0138                            TempData["CreateInfo"] = "Клиент с таким Api Key уже существует.";
 0139                            return RedirectToAction(nameof(Create));
 140                        }
 141                    }
 0142                    else if (ozonClient.ClientType == ClientType.YANDEX)
 143                    {
 0144                        if (!clients.Where(c => c.DecryptClientId == ozonClient.ClientId).Any())
 145                        {
 0146                            if (await _yandexDataManager.GetTestRequest(ozonClient.ClientId, ozonClient.ApiKey))
 147                            {
 0148                                await _ozonClientServices.AddOzonClient(ozonClient);
 0149                                return RedirectToAction(nameof(Index));
 150                            }
 151                            else
 152                            {
 0153                                TempData["CreateInfo"] = "Api данные некорректны. Ошибка при отправке тестового запроса 
 0154                                return RedirectToAction(nameof(Create));
 155                            }
 156                        }
 157                        else
 158                        {
 0159                            TempData["CreateInfo"] = "Клиент с таким ClientId уже существует.";
 0160                            return RedirectToAction(nameof(Create));
 161                        }
 162                    }
 163                    else
 164                    {
 0165                        await _ozonClientServices.AddOzonClient(ozonClient);
 0166                        return RedirectToAction(nameof(Index));
 167                    }
 168                }
 169                else
 170                {
 0171                    await _ozonClientServices.AddOzonClient(ozonClient);
 0172                    return RedirectToAction(nameof(Index));
 173                }
 174            }
 175            else
 176            {
 0177                TempData["CreateInfo"] = $"Клиент `{ozonClient.Name}` уже существует.";
 0178                return RedirectToAction(nameof(Create));
 179            }
 0180        }
 181
 182        public async Task<IActionResult> Edit(int id, string? info = null)
 183        {
 0184            var innInfo = await _oneCDataManager.GetSupplierListAsync();
 185
 0186            if (TempData.ContainsKey("EditInfo") && TempData["EditInfo"] != null)
 187            {
 0188                string? result = TempData["EditInfo"] as string;
 0189                ViewData["EditInfo"] = result;
 190            }
 191
 0192            if (info != null)
 193            {
 0194                ViewData["EditInfo"] = info;
 195            }
 196
 0197            var ozonClient = await _ozonClientServices.GetOzonClientAsync(id);
 0198            if (ozonClient == null)
 199            {
 0200                return NotFound();
 201            }
 202
 203            // Подготовка списка подсказок для ИНН
 0204            var innSuggestions = new List<SupplierResponse>();
 0205            if (innInfo != null)
 206            {
 0207                innSuggestions = innInfo
 0208                    .Where(s => !string.IsNullOrEmpty(s.Unp))
 0209                    .OrderBy(s => s.Unp)
 0210                    .ToList();
 211            }
 212
 213            // Проверка ролей API для клиента Ozon
 0214            List<Role> apiRoles = new List<Role>();
 0215            bool hasApiAccess = false;
 0216            SellerInfoResponse? sellerInfo = null;
 0217            bool hasSellerInfo = false;
 218
 0219            if (ozonClient.ClientType == ClientType.OZON &&
 0220                !string.IsNullOrEmpty(ozonClient.DecryptClientId) &&
 0221                !string.IsNullOrEmpty(ozonClient.DecryptApiKey))
 222            {
 223                try
 224                {
 0225                    var ozonApiManager = new OzonApiDataManager(_httpClientFactory, _emailService, ozonClient.DecryptCli
 0226                    var rolesResponse = await ozonApiManager.GetApiRoles();
 227
 0228                    if (rolesResponse?.Roles != null)
 229                    {
 0230                        apiRoles = rolesResponse.Roles;
 0231                        hasApiAccess = true;
 232                    }
 233
 234                    // Получение информации о продавце
 235                    try
 236                    {
 0237                        sellerInfo = await ozonApiManager.GetSellerInfo();
 0238                        if (sellerInfo != null && (sellerInfo.Company != null || sellerInfo.Ratings != null ||
 0239                                                   sellerInfo.Subscription != null))
 240                        {
 0241                            hasSellerInfo = true;
 242                        }
 0243                    }
 0244                    catch (Exception ex)
 245                    {
 246                        // Игнорируем ошибки при получении информации о продавце
 0247                        Console.WriteLine($"Ошибка при получении информации о продавце: {ex.Message}");
 0248                    }
 0249                }
 0250                catch (Exception ex)
 251                {
 0252                    apiRoles.Add(new Role
 0253                    {
 0254                        Name = "Ошибка",
 0255                        Methods = new List<string> { $"Ошибка при проверке прав: {ex.Message}" }
 0256                    });
 0257                }
 258            }
 259
 0260            var viewModel = new EditOzonClientViewModel
 0261            {
 0262                OzonClient = ozonClient,
 0263                CurrencyCodes = new List<SelectListItem>
 0264                {
 0265                    new SelectListItem { Value = CurrencyCode.RUB.ToString(), Text = "RUB" },
 0266                    new SelectListItem { Value = CurrencyCode.USD.ToString(), Text = "USD" },
 0267                    new SelectListItem { Value = CurrencyCode.EUR.ToString(), Text = "EUR" },
 0268                    new SelectListItem { Value = CurrencyCode.BYN.ToString(), Text = "BYN" },
 0269                },
 0270                ClientTypes = new List<SelectListItem>
 0271                {
 0272                    new SelectListItem { Value = ClientType.ALL.ToString(), Text = "Другое" },
 0273                    new SelectListItem { Value = ClientType.OZON.ToString(), Text = "Ozon" },
 0274                    new SelectListItem { Value = ClientType.YANDEX.ToString(), Text = "Yandex" }
 0275                },
 0276                INNSuggestions = innSuggestions,
 0277                ApiRoles = apiRoles,
 0278                HasApiAccess = hasApiAccess,
 0279                SellerInfo = sellerInfo ?? new SellerInfoResponse(),
 0280                HasSellerInfo = hasSellerInfo,
 0281                BitrixWarehouseNames = (await GetAllowedBitrixWarehouseSelectItemsAsync())
 0282            };
 283
 0284            return View(viewModel);
 0285        }
 286
 287
 288        [HttpPost]
 289        [ValidateAntiForgeryToken]
 290        public async Task<IActionResult> Edit(int id, OzonClient ozonClient)
 291        {
 0292            if (id != ozonClient.Id)
 293            {
 0294                return NotFound();
 295            }
 296
 0297            if (!await IsAllowedBitrixWarehouseNameAsync(ozonClient.WarehouseName))
 298            {
 0299                return RedirectToAction(nameof(Edit), new
 0300                {
 0301                    id,
 0302                    info = "Название склада должно быть выбрано из разрешенного списка складов Bitrix."
 0303                });
 304            }
 305
 0306            if (ModelState.IsValid)
 307            {
 308                try
 309                {
 0310                    if (ozonClient.ClientId != null && ozonClient.ApiKey != null)
 311                    {
 0312                        if (ozonClient.ClientType == ClientType.OZON)
 313                        {
 0314                            var (isValid, errorDetails) =
 0315                                await ValidateOzonApiCredentialsAsync(ozonClient.ClientId, ozonClient.ApiKey);
 0316                            if (isValid)
 317                            {
 0318                                await _ozonClientServices.Update(ozonClient);
 0319                                return RedirectToAction(nameof(Index));
 320                            }
 321                            else
 322                            {
 0323                                return RedirectToAction(nameof(Edit), new
 0324                                {
 0325                                    id,
 0326                                    info = $"Api данные некорректны. Не удалось пройти тестовый запрос Ozon API. {errorD
 0327                                });
 328                            }
 329                        }
 0330                        else if (ozonClient.ClientType == ClientType.YANDEX)
 331                        {
 0332                            if (await _yandexDataManager.GetTestRequest(ozonClient.ClientId, ozonClient.ApiKey))
 333                            {
 0334                                await _ozonClientServices.Update(ozonClient);
 0335                                return RedirectToAction(nameof(Index));
 336                            }
 337                            else
 338                            {
 0339                                return RedirectToAction(nameof(Edit), new
 0340                                {
 0341                                    id,
 0342                                    info = "Api данные некорректны. Ошибка при отправке тестового запроса Yandex API."
 0343                                });
 344                            }
 345                        }
 346                        else
 347                        {
 0348                            await _ozonClientServices.Update(ozonClient);
 0349                            return RedirectToAction(nameof(Index));
 350                        }
 351                    }
 352                    else
 353                    {
 0354                        await _ozonClientServices.Update(ozonClient);
 0355                        return RedirectToAction(nameof(Index));
 356                    }
 357                }
 0358                catch (DbUpdateConcurrencyException)
 359                {
 0360                    throw;
 361                }
 362            }
 363
 0364            return RedirectToAction(nameof(Edit), new { id });
 0365        }
 366
 367
 368        // GET: OzonClients/Delete/5
 369        public async Task<IActionResult> Delete(int id)
 370        {
 0371            var ozonClient = await _ozonClientServices.GetOzonClientAsync(id);
 0372            if (ozonClient == null)
 0373                return NotFound();
 374
 0375            ozonClient.DecryptApiKey = new string('•', ozonClient.DecryptApiKey?.Length ?? 0);
 0376            return View(ozonClient);
 0377        }
 378
 379        // POST: OzonClients/Delete/5
 380        [HttpPost, ActionName("Delete")]
 381        [ValidateAntiForgeryToken]
 382        public async Task<IActionResult> DeleteConfirmed(int id)
 383        {
 0384            var ozonClient = await _ozonClientServices.GetOzonClientAsync(id);
 0385            if (ozonClient != null)
 386            {
 0387                await _ozonClientServices.DeleteOzonClient(ozonClient);
 388            }
 389
 0390            return RedirectToAction(nameof(Index));
 0391        }
 392
 393        [HttpGet]
 394        public async Task<IActionResult> SearchCounterparties(string? q, int limit = 15)
 395        {
 0396            limit = Math.Min(limit, 30);
 0397            var results = await _oneCDataManager.SearchCounterpartiesAsync(q, limit);
 0398            return Json(results.Select(c => new { inn = c.Identifier, name = c.Description }));
 0399        }
 400
 401        [HttpGet]
 402        public async Task<IActionResult> SearchOrganizations(string? q, int limit = 15)
 403        {
 0404            limit = Math.Min(limit, 30);
 0405            var results = await _oneCDataManager.SearchOrganizationsAsync(q, limit);
 0406            return Json(results.Select(o => new { inn = o.Inn, name = o.Description }));
 0407        }
 408
 409        private async Task<List<SelectListItem>> GetAllowedBitrixWarehouseSelectItemsAsync()
 410        {
 0411            var names = (await _oneCDataManager.GetWarehouseListAsync())
 0412                .Select(x => x.Name?.Trim())
 0413                .Where(x => !string.IsNullOrWhiteSpace(x))
 0414                .Distinct(StringComparer.OrdinalIgnoreCase)
 0415                .OrderBy(x => x)
 0416                .ToList();
 417
 0418            var userId = User?.FindFirstValue(ClaimTypes.NameIdentifier);
 0419            if (!string.IsNullOrWhiteSpace(userId))
 420            {
 0421                var allowed = await _scopeFilterValuesService.GetAllowedValuesAsync(
 0422                    userId,
 0423                    "BitrixWarehouse",
 0424                    HttpContext.RequestAborted);
 425
 0426                if (allowed.TryGetValue("Name", out var allowedNames) && allowedNames.Count > 0)
 427                {
 0428                    names = names
 0429                        .Where(n => allowedNames.Contains(n!))
 0430                        .OrderBy(n => n)
 0431                        .ToList();
 432                }
 0433            }
 434
 0435            return names
 0436                .Select(x => new SelectListItem { Value = x, Text = x })
 0437                .ToList();
 0438        }
 439
 440        private async Task<bool> IsAllowedBitrixWarehouseNameAsync(string? warehouseName)
 441        {
 0442            if (string.IsNullOrWhiteSpace(warehouseName))
 443            {
 0444                return false;
 445            }
 446
 0447            var allowedValues = await GetAllowedBitrixWarehouseSelectItemsAsync();
 0448            return allowedValues.Any(x => string.Equals(x.Value, warehouseName.Trim(), StringComparison.OrdinalIgnoreCas
 0449        }
 450
 451        private async Task<(bool IsValid, string ErrorDetails)> ValidateOzonApiCredentialsAsync(
 452            string? clientId,
 453            string? apiKey)
 454        {
 0455            if (string.IsNullOrWhiteSpace(clientId) || string.IsNullOrWhiteSpace(apiKey))
 456            {
 0457                return (false, "Не заполнены ClientId и/или ApiKey.");
 458            }
 459
 460            try
 461            {
 0462                var ozonApiManager = new OzonApiDataManager(_httpClientFactory, _emailService, clientId, apiKey);
 0463                await ozonApiManager.GetApiRoles();
 0464                return (true, string.Empty);
 465            }
 0466            catch (Exception ex)
 467            {
 0468                var message = ex.Message?.Replace("\r", " ").Replace("\n", " ").Trim();
 0469                if (string.IsNullOrWhiteSpace(message))
 470                {
 0471                    message = "Неизвестная ошибка при обращении к Ozon API.";
 472                }
 473
 0474                return (false, $"Детали: {message}");
 475            }
 0476        }
 477    }
 478}