< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.Directories.WarehouseMappingController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/Directories/WarehouseMappingController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 141
Coverable lines: 141
Total lines: 262
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 74
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()100%210%
Create()0%4260%
Create()0%2040%
Edit()0%620%
Edit()0%7280%
Details()0%620%
Delete()0%620%
DeleteConfirmed()0%620%
PopulateDropdownsAsync()0%812280%
PopulateEmptyDropdowns()0%7280%
FindDuplicateAsync()100%210%

File(s)

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

#LineLine coverage
 1using Microsoft.AspNetCore.Authorization;
 2using Microsoft.AspNetCore.Mvc;
 3using Microsoft.AspNetCore.Mvc.Rendering;
 4using OzonDomains.Models;
 5using OzonOrdersWeb.Areas.Studio2.ViewModels.Warehouse;
 6using Services.ApiServices;
 7using Services.Authorization.Services;
 8using Services.DataServices;
 9
 10namespace OzonOrdersWeb.Areas.Studio2.Controllers.Directories;
 11
 12[Authorize(Roles = "User,Admin")]
 13[Area("Studio2")]
 14public class WarehouseMappingController : Controller
 15{
 16    private readonly WarehouseMappingDataServices _service;
 17    private readonly WarehouseDataServices _warehouseDataServices;
 18    private readonly OzonClientServices _clientDataServices;
 19    private readonly SupplierDataServices _supplierDataServices;
 20    private readonly OneCDataManager _cDataManager;
 21    private readonly IScopeFilterValuesService _scopeFilterValuesService;
 22
 023    public WarehouseMappingController(WarehouseMappingDataServices service,
 024        WarehouseDataServices warehouseDataServices,
 025        OzonClientServices clientDataServices,
 026        SupplierDataServices supplierDataServices,
 027        OneCDataManager oneCDataManager,
 028        IScopeFilterValuesService scopeFilterValuesService)
 29    {
 030        _service = service;
 031        _warehouseDataServices = warehouseDataServices;
 032        _clientDataServices = clientDataServices;
 033        _supplierDataServices = supplierDataServices;
 034        _cDataManager = oneCDataManager;
 035        _scopeFilterValuesService = scopeFilterValuesService;
 036    }
 37
 38    /// <summary>Весь справочник связей складов для грида AG Grid: фильтры, сортировка и поиск — на клиенте.</summary>
 39    public async Task<IActionResult> Index()
 40    {
 041        var mappings = (await _service.GetWarehouseMappings())
 042            .OrderBy(m => m.OzonClient?.Name)
 043            .ThenBy(m => m.OzonWarehouseName)
 044            .ThenBy(m => m.Priority)
 045            .ToList();
 046        return View(mappings);
 047    }
 48
 49    public async Task<IActionResult> Create(
 50        int? ozonClientId = null,
 51        string? ozonWarehouseName = null,
 52        string? deliveryType = null)
 53    {
 054        var prefilled = new WarehouseMapping
 055        {
 056            OzonClientId = ozonClientId,
 057            OzonWarehouseName = ozonWarehouseName?.Trim() ?? string.Empty,
 058            DeliveryType = string.IsNullOrWhiteSpace(deliveryType) ? null : deliveryType.Trim()
 059        };
 60
 61        try
 62        {
 063            await PopulateDropdownsAsync(prefilled.OzonClientId, selectedOzonWarehouse: prefilled.OzonWarehouseName);
 064            return View(prefilled);
 65        }
 066        catch (Exception ex)
 67        {
 068            PopulateEmptyDropdowns();
 069            TempData["ErrorMessage"] = $"Ошибка загрузки данных для создания: {ex.Message}";
 070            return View(prefilled);
 71        }
 072    }
 73
 74    [HttpPost]
 75    [ValidateAntiForgeryToken]
 76    public async Task<IActionResult> Create(WarehouseMapping model)
 77    {
 078        if (!ModelState.IsValid)
 79        {
 080            await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, model.S
 081            return View(model);
 82        }
 83
 84        try
 85        {
 086            var duplicate = await FindDuplicateAsync(model, null);
 087            if (duplicate != null)
 88            {
 089                ModelState.AddModelError(string.Empty,
 090                    "Такая связь уже существует для выбранного клиента, Bitrix склада и Ozon склада.");
 091                await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, mod
 092                return View(model);
 93            }
 94
 095            await _service.AddWarehouseMapping(model);
 096            TempData["SuccessMessage"] = "Связь складов успешно создана!";
 097            return RedirectToAction(nameof(Index));
 98        }
 099        catch (Exception ex)
 100        {
 0101            ModelState.AddModelError(string.Empty, $"Ошибка при создании связи: {ex.Message}");
 0102            await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, model.S
 0103            return View(model);
 104        }
 0105    }
 106
 107    public async Task<IActionResult> Edit(int id)
 108    {
 109        try
 110        {
 0111            var mapping = await _service.GetWarehouseMappingAsync(id);
 0112            if (mapping == null)
 113            {
 0114                TempData["ErrorMessage"] = $"Связь складов с ID {id} не найдена.";
 0115                return RedirectToAction(nameof(Index));
 116            }
 117
 0118            await PopulateDropdownsAsync(mapping.OzonClientId, mapping.BitrixWarehouseName, mapping.OzonWarehouseName, m
 0119            return View(mapping);
 120        }
 0121        catch (Exception ex)
 122        {
 0123            TempData["ErrorMessage"] = $"Ошибка при загрузке связи для редактирования: {ex.Message}";
 0124            return RedirectToAction(nameof(Index));
 125        }
 0126    }
 127
 128    [HttpPost]
 129    [ValidateAntiForgeryToken]
 130    public async Task<IActionResult> Edit(WarehouseMapping model)
 131    {
 132        // Пустой тип доставки означает общую связку склада и не должен блокировать сохранение.
 0133        model.DeliveryType = string.IsNullOrWhiteSpace(model.DeliveryType) ? null : model.DeliveryType.Trim();
 0134        ModelState.Remove(nameof(WarehouseMapping.DeliveryType));
 135
 0136        if (!ModelState.IsValid)
 137        {
 0138            await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, model.S
 0139            return View(model);
 140        }
 141
 142        try
 143        {
 0144            var existing = await _service.GetWarehouseMappingAsync(model.Id);
 0145            if (existing == null)
 146            {
 0147                TempData["ErrorMessage"] = $"Связь складов с ID {model.Id} не найдена.";
 0148                return RedirectToAction(nameof(Index));
 149            }
 150
 0151            var duplicate = await FindDuplicateAsync(model, model.Id);
 0152            if (duplicate != null)
 153            {
 0154                ModelState.AddModelError(string.Empty,
 0155                    "Такая связь уже существует для выбранного клиента, Bitrix склада и Ozon склада.");
 0156                await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, mod
 0157                return View(model);
 158            }
 159
 0160            await _service.UpdateWarehouseMapping(model);
 0161            TempData["SuccessMessage"] = "Связь складов успешно обновлена!";
 0162            return RedirectToAction(nameof(Index));
 163        }
 0164        catch (Exception ex)
 165        {
 0166            ModelState.AddModelError(string.Empty, $"Ошибка при обновлении: {ex.Message}");
 0167            await PopulateDropdownsAsync(model.OzonClientId, model.BitrixWarehouseName, model.OzonWarehouseName, model.S
 0168            return View(model);
 169        }
 0170    }
 171
 172    public async Task<IActionResult> Details(int id)
 173    {
 0174        var mapping = await _service.GetWarehouseMappingAsync(id);
 0175        if (mapping == null)
 0176            return NotFound();
 177
 0178        return View(mapping);
 0179    }
 180
 181    public async Task<IActionResult> Delete(int id)
 182    {
 0183        var mapping = await _service.GetWarehouseMappingAsync(id);
 0184        if (mapping == null)
 0185            return NotFound();
 186
 0187        return View(mapping);
 0188    }
 189
 190    [HttpPost, ActionName("Delete")]
 191    [ValidateAntiForgeryToken]
 192    public async Task<IActionResult> DeleteConfirmed(int id)
 193    {
 0194        var mapping = await _service.GetWarehouseMappingAsync(id);
 0195        if (mapping != null)
 196        {
 0197            await _service.DeleteWarehouseMapping(mapping);
 0198            TempData["SuccessMessage"] = "Связь складов удалена!";
 199        }
 200
 0201        return RedirectToAction(nameof(Index));
 0202    }
 203
 204    private async Task PopulateDropdownsAsync(int? selectedClientId = null, string? selectedBitrixWarehouse = null,
 205        string? selectedOzonWarehouse = null, int? selectedSupplierId = null)
 206    {
 0207        var warehouses = await _warehouseDataServices.GetWarehouses();
 0208        var bitrixWarehouses = await _cDataManager.GetWarehouseListAsync();
 0209        var clients = await _clientDataServices.GetOzonClients();
 0210        var suppliers = await _supplierDataServices.GetSuppliers();
 211
 0212        ViewBag.Warehouses = warehouses != null
 0213            ? new SelectList(warehouses.OrderBy(a => a.Name), "Name", "Name", selectedOzonWarehouse)
 0214            : new SelectList(Enumerable.Empty<SelectListItem>());
 215
 0216        var bitrixWarehouseNames = bitrixWarehouses?
 0217            .Where(wh => wh != null && !string.IsNullOrEmpty(wh.Name))
 0218            .Select(wh => wh.Name!)
 0219            .OrderBy(name => name)
 0220            .ToList() ?? new List<string>();
 221
 0222        var userId = User?.Claims?.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier)?.Valu
 0223        if (!string.IsNullOrWhiteSpace(userId))
 224        {
 0225            var allowed = await _scopeFilterValuesService.GetAllowedValuesAsync(userId, "BitrixWarehouse", HttpContext.R
 0226            if (allowed.TryGetValue("Name", out var allowedNames) && allowedNames.Count > 0)
 227            {
 0228                bitrixWarehouseNames = bitrixWarehouseNames
 0229                    .Where(n => allowedNames.Contains(n, StringComparer.Ordinal))
 0230                    .OrderBy(n => n)
 0231                    .ToList();
 232            }
 0233        }
 234
 0235        ViewBag.BitrixWarehouses = new SelectList(bitrixWarehouseNames, selectedBitrixWarehouse);
 0236        ViewBag.Clients = clients != null
 0237            ? new SelectList(clients, "Id", "Name", selectedClientId)
 0238            : new SelectList(Enumerable.Empty<SelectListItem>());
 0239        ViewBag.Suppliers = new SelectList(suppliers.OrderBy(s => s.Name), "Id", "Name", selectedSupplierId);
 0240    }
 241
 242    private void PopulateEmptyDropdowns()
 243    {
 0244        ViewBag.Warehouses = new SelectList(Enumerable.Empty<SelectListItem>());
 0245        ViewBag.BitrixWarehouses = new SelectList(Enumerable.Empty<string>());
 0246        ViewBag.Clients = new SelectList(Enumerable.Empty<SelectListItem>());
 0247        ViewBag.Suppliers = new SelectList(Enumerable.Empty<SelectListItem>());
 0248    }
 249
 250    private async Task<WarehouseMapping?> FindDuplicateAsync(WarehouseMapping model, int? excludeId)
 251    {
 0252        var mappings = await _service.GetWarehouseMappings();
 0253        return mappings.FirstOrDefault(m =>
 0254            m.Id != excludeId &&
 0255            m.OzonClientId == model.OzonClientId &&
 0256            m.SupplierId == model.SupplierId &&
 0257            string.Equals(m.BitrixWarehouseName?.Trim(), model.BitrixWarehouseName?.Trim(),
 0258                StringComparison.OrdinalIgnoreCase) &&
 0259            string.Equals(m.OzonWarehouseName?.Trim(), model.OzonWarehouseName?.Trim(),
 0260                StringComparison.OrdinalIgnoreCase));
 0261    }
 262}