< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.Controllers.Directories.ProducersController
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Controllers/Directories/ProducersController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 104
Coverable lines: 104
Total lines: 246
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 70
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%
GridRows()0%4260%
GridFacets()0%4260%
Create()100%210%
Create()0%2040%
Edit()0%2040%
Edit()0%110100%
UpdateFromApi()0%620%
UpdateMultipleFromApi()0%620%
UpdateByInputFromApi()0%2040%

File(s)

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

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using Microsoft.AspNetCore.Authorization;
 3using Microsoft.AspNetCore.Mvc;
 4using OzonDomains.Models;
 5using OzonDomains.Models.Authorization.Enums;
 6using OzonOrdersWeb.Authorization;
 7using OzonOrdersWeb.WebServices.Directories;
 8using OzonOrdersWeb.WebServices.Grid;
 9using OzonRepositories.Context;
 10using Services.DataServices;
 11using Services.CacheServices.Cache.EtProducerCache;
 12
 13namespace OzonOrdersWeb.Areas.Studio2.Controllers.Directories;
 14
 15[Authorize(Roles = "Admin")]
 16[Area("Studio2")]
 17public class ProducersController : Controller
 18{
 19    private const string PageCode = "Studio2.Producers.Index";
 20
 21    private readonly EtProducerDataServices _producerDataService;
 22    private readonly ApplicationDbContext _context;
 23    private readonly EtProducerCache _producerCache;
 24
 25
 026    public ProducersController(EtProducerDataServices producerDataService,
 027        ApplicationDbContext context,
 028        EtProducerCache producerCache)
 29    {
 030        _producerDataService = producerDataService;
 031        _context = context;
 032        _producerCache = producerCache;
 033    }
 34
 35    /// <summary>Каркас страницы: строки (~20 тыс.) грид подгружает блоками через <see cref="GridRows"/>.</summary>
 36    public async Task<IActionResult> Index(CancellationToken cancellationToken)
 37    {
 038        ViewBag.TotalCount = await _context.EtProducers.CountAsync(cancellationToken);
 039        ViewBag.WithoutMarketPrefix = await _context.EtProducers.CountAsync(p => p.MarketPrefix == null || p.MarketPrefi
 040        return View();
 041    }
 42
 43    [HttpPost("Studio2/Producers/grid")]
 44    [ValidateAntiForgeryToken]
 45    [PageAuthorize(PageCode, AccessType.View)]
 46    public async Task<IActionResult> GridRows([FromBody] ServerGridRequest? request, CancellationToken cancellationToken
 47    {
 048        var error = ServerGridQuery.Validate(request);
 049        if (error != null) return BadRequest(new { success = false, error });
 50
 051        var def = DirectoryGridDefinitions.Producers;
 052        var filtered = ServerGridQuery.ApplyFilters(_context.EtProducers.AsNoTracking(), def, request!);
 053        var total = await filtered.CountAsync(cancellationToken);
 054        var start = Math.Max(0, request!.StartRow);
 055        var take = Math.Clamp(request.EndRow - start, 1, ServerGridQuery.MaxBlockSize);
 056        var rows = start >= total
 057            ? []
 058            : await ServerGridQuery.ApplySort(filtered, def, request.SortModel).Skip(start).Take(take)
 059                .Select(p => new
 060                {
 061                    p.Id, p.RealId, p.MarketPrefix, p.Name, p.Prefix, p.Address, p.Www, p.ExistName, p.ExistId,
 062                    p.Domain, p.Rating, p.TecdocSupplierId
 063                })
 064                .ToListAsync(cancellationToken);
 065        var lastRow = start + rows.Count >= total ? total : -1;
 066        return Ok(new { success = true, rows, totalCount = total, lastRow });
 067    }
 68
 69    [HttpPost("Studio2/Producers/grid/facets")]
 70    [ValidateAntiForgeryToken]
 71    [PageAuthorize(PageCode, AccessType.View)]
 72    public async Task<IActionResult> GridFacets([FromBody] ServerGridRequest? request, CancellationToken cancellationTok
 73    {
 074        if (request is null || string.IsNullOrWhiteSpace(request.ColId)) return BadRequest(new { success = false, error 
 075        request.StartRow = 0;
 076        request.EndRow = 1;
 077        var error = ServerGridQuery.Validate(request);
 078        if (error != null) return BadRequest(new { success = false, error });
 079        var values = await ServerGridQuery.FacetsAsync(_context.EtProducers.AsNoTracking(), DirectoryGridDefinitions.Pro
 080        return Ok(new { success = true, values });
 081    }
 82
 83    public IActionResult Create()
 84    {
 085        return View();
 86    }
 87
 88    [HttpPost]
 89    [ValidateAntiForgeryToken]
 90    public async Task<IActionResult> Create(
 91        [Bind("Id,RealId,Prefix,Name,Address,Www,Rating,ExistName,ExistId,Domain,TecdocSupplierId,MarketPrefix")]
 92        EtProducer producer)
 93    {
 094        EtProducer? isOrig = (await _producerDataService.GetEtProducers()).FirstOrDefault(p =>
 095            p.Name?.ToLower() == producer?.Name?.ToLower() &&
 096            p.Prefix?.ToLower() == producer?.Prefix?.ToLower());
 097        if (isOrig == null)
 98        {
 099            if (ModelState.IsValid)
 100            {
 0101                await _producerDataService.AddEtProducer(producer);
 0102                return RedirectToAction(nameof(Index));
 103            }
 104
 0105            return View(producer);
 106        }
 107        else
 108        {
 0109            throw new Exception("Producer already exists");
 110        }
 0111    }
 112
 113    public async Task<IActionResult> Edit(string id)
 114    {
 0115        if (string.IsNullOrEmpty(id))
 116        {
 0117            return NotFound();
 118        }
 119
 0120        var producer = await _producerDataService.GetEtProducerAsync(int.Parse(id));
 0121        if (producer == null)
 122        {
 0123            return NotFound();
 124        }
 125
 0126        return View(producer);
 0127    }
 128
 129    [HttpPost]
 130    [ValidateAntiForgeryToken]
 131    public async Task<IActionResult> Edit(string id, EtProducer producer)
 132    {
 0133        if (int.Parse(id) != producer.Id)
 134        {
 0135            return NotFound();
 136        }
 137
 0138        if (ModelState.IsValid)
 139        {
 0140            EtProducer? isOrig = (await _producerDataService.GetEtProducers()).FirstOrDefault(p =>
 0141                p.Name?.ToLower() == producer?.Name?.ToLower() &&
 0142                p.Prefix?.ToLower() == producer?.Prefix?.ToLower());
 143
 144            try
 145            {
 0146                if (isOrig == null || isOrig.Id == producer.Id)
 147                {
 0148                    await _producerDataService.UpdateEtProducer(producer);
 0149                    await _producerCache.Update();
 150                }
 151                else
 152                {
 0153                    TempData["ErrorMessage"] = $"Производитель «{producer.Name}» с префиксом «{producer.Prefix}» уже ест
 154                }
 0155            }
 0156            catch (DbUpdateConcurrencyException)
 157            {
 0158                if (await _producerDataService.GetEtProducerAsync(int.Parse(id)) == null)
 159                {
 0160                    return NotFound();
 161                }
 162                else
 163                {
 0164                    throw;
 165                }
 166            }
 167
 0168            return RedirectToAction(nameof(Index));
 169        }
 170
 0171        return View(producer);
 0172    }
 173
 174    [HttpPost]
 175    [ValidateAntiForgeryToken]
 176    public async Task<IActionResult> UpdateFromApi(int id)
 177    {
 178        try
 179        {
 0180            var updatedProducer = await _producerDataService.UpdateEtProducerFromApi(id);
 181
 0182            if (updatedProducer != null)
 183            {
 0184                await _producerCache.Update();
 0185                TempData["SuccessMessage"] = $"Производитель {updatedProducer.Name} успешно обновлен из API";
 186            }
 187            else
 188            {
 0189                TempData["ErrorMessage"] = "Производитель не найден в API или не удовлетворяет условию Id eq RealId";
 190            }
 0191        }
 0192        catch (Exception ex)
 193        {
 0194            TempData["ErrorMessage"] = $"Ошибка при обновлении из API: {ex.Message}";
 0195        }
 196
 0197        return RedirectToAction(nameof(Index));
 0198    }
 199
 200    [HttpPost]
 201    [ValidateAntiForgeryToken]
 202    public async Task<IActionResult> UpdateMultipleFromApi(List<int> ids)
 203    {
 204        try
 205        {
 0206            var updatedProducers = await _producerDataService.UpdateMultipleEtProducersFromApi(ids);
 207
 0208            if (updatedProducers.Any())
 209            {
 0210                await _producerCache.Update();
 0211                TempData["SuccessMessage"] = $"Успешно обновлено {updatedProducers.Count} производителей из API";
 212            }
 213            else
 214            {
 0215                TempData["ErrorMessage"] = "Не удалось обновить ни одного производителя из API";
 216            }
 0217        }
 0218        catch (Exception ex)
 219        {
 0220            TempData["ErrorMessage"] = $"Ошибка при массовом обновлении из API: {ex.Message}";
 0221        }
 222
 0223        return RedirectToAction(nameof(Index));
 0224    }
 225
 226    [HttpPost]
 227    [ValidateAntiForgeryToken]
 228    public async Task<IActionResult> UpdateByInputFromApi(string producerIdInput)
 229    {
 0230        if (string.IsNullOrEmpty(producerIdInput))
 231        {
 0232            TempData["ErrorMessage"] = "Введите ID производителя";
 0233            return RedirectToAction(nameof(Index));
 234        }
 235
 0236        if (int.TryParse(producerIdInput, out int id))
 237        {
 0238            return await UpdateFromApi(id);
 239        }
 240        else
 241        {
 0242            TempData["ErrorMessage"] = "Некорректный формат ID производителя";
 0243            return RedirectToAction(nameof(Index));
 244        }
 0245    }
 246}