< Summary

Class:SVETA.Api.Controllers.ClustersController
Assembly:SVETA.Api
File(s):/opt/dev/sveta_api_build/SVETA.Api/Controllers/ClustersController.cs
Covered lines:0
Uncovered lines:111
Coverable lines:111
Total lines:371
Line coverage:0% (0 of 111)
Covered branches:0
Total branches:68
Branch coverage:0% (0 of 68)

Metrics

MethodLine coverage Branch coverage
.ctor(...)0%100%
GetClusters()0%0%
GetClustersCount()0%0%
GetCluster()0%0%
GetClusterMinimumSum()0%0%
CreateCluster()0%0%
UpdateCluster()0%0%
DeleteCluster()0%0%
DeactivateCluster()0%0%
ActivateCluster()0%0%
PrepareCluster()0%0%

File(s)

/opt/dev/sveta_api_build/SVETA.Api/Controllers/ClustersController.cs

#LineLine coverage
 1using System;
 2using WinSolutions.Sveta.Common.Extensions;
 3using System.Collections.Generic;
 4using System.Linq;
 5using System.Threading.Tasks;
 6using AutoMapper;
 7using Microsoft.AspNetCore.Mvc;
 8using Microsoft.Extensions.Logging;
 9using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 10using Microsoft.AspNetCore.Authorization;
 11using SVETA.Api.Data.Domain;
 12using WinSolutions.Sveta.Server.Services.Interfaces;
 13using SVETA.Api.Data.DTO;
 14using SVETA.Api.Helpers.Authorize;
 15using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 16using Swashbuckle.AspNetCore.Annotations;
 17using WinSolutions.Sveta.Server.Domain;
 18using WinSolutions.Sveta.Common;
 19using DocumentFormat.OpenXml.Office.CustomUI;
 20using SVETA.Api.Services.Interfaces;
 21using Microsoft.CodeAnalysis.CSharp;
 22
 23namespace SVETA.Api.Controllers
 24{
 25    [Authorize]
 26    [Route("api/v1/Clusters")]
 27    [ApiController]
 28    public class ClustersController : SvetaController
 29    {
 30        const string _routeUrl = "api/v1/Clusters";
 31        readonly IClusterService _service;
 32        readonly IAuthenticationService _authService;
 33        readonly IContragentService _contrService;
 34        readonly IDepartmentService _departService;
 35        readonly IUserService _userService;
 36        readonly IDirectoriesService _dirService;
 37        readonly ILogger<ClustersController> _logger;
 38        public ClustersController(IClusterService service, IContragentService contrService, IAuthenticationService authS
 039            IDepartmentService departService, IDirectoriesService dirService, IUserService userService, ILogger<Clusters
 040        {
 041            _service = service;
 042            _authService = authService;
 043            _userService = userService;
 044            _dirService = dirService;
 045            _contrService = contrService;
 046            _departService = departService;
 047            _logger = logger;
 048        }
 49
 50        /// <summary>
 51        /// Возвращает все кластера
 52        /// </summary>
 53        /// <remarks>author i.rebenok</remarks>
 54        /// <param name="page">Любое значение ниже нуля изменится на 1, пагинация: номер страницы</param>
 55        /// <param name="limit">Любое значение ниже нуля изменится на 10, пагинация: размер страницы</param>
 56        /// <param name="filter">фильтр по значимым полям: имя кластера</param>
 57        /// <param name="sortByNameDesc">сортировать по имени DESC - true or false</param>
 58        /// <param name = "contragentId" > id контрагента.Если 0, то все кластера выводить, если >0, то только по этому 
 59        /// <param name="warehouseId">id склада владельца. Если 0, то все кластера выводить в рамках КА, если >0,то толь
 60        /// <param name="active">true, если выводить только активные кластера. По умолчанию false</param>
 61        [HttpGet("")]
 62        [SwaggerResponse(200, "Успешно", typeof(IEnumerable<ClusterDTO_GET>))]
 63        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 64        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 65        [Authorize(Roles = Role.SystemAdmin + "," + Role.SystemOperator + "," + Role.SupplierOwner)]
 66        public async Task<IActionResult> GetClusters(int page = 1, int limit = 10, string filter = null, bool sortByName
 067        {
 068            filter = filter.NormalizeName();
 069            page = page < 1 ? 1 : page;
 070            limit = limit < 1 ? 10 : limit;
 071            contragentId = _authService.IsUserPlatform() ? contragentId : _authService.ContragentId;
 072            var result = await _service.GetClusters(page - 1, limit, filter, sortByNameDesc, contragentId, active, wareh
 073            var param = $"sortByNameDesc={sortByNameDesc}&contragentId={contragentId}&active={active}";
 074            var response = new BaseResponseDTO<ClusterDTO_GET>(_routeUrl, page, limit, result.TotalFilteredCount, result
 075            {
 076                Data = result.Result.Select(x => new ClusterDTO_GET(x)).ToList(),
 077            };
 078            return Ok(response);
 079        }
 80
 81        /// <summary>
 82        /// Возвращает количество кластеров с фильтром по значимым полям
 83        /// </summary>
 84        /// <remarks>author i.rebenok</remarks>
 85        /// <param name="filter">фильтр по значимым полям: имя кластера</param>
 86        /// <param name = "contragentId" > id контрагента.Если 0, то все кластера выводить, если >0, то только по этому 
 87        /// <param name="warehouseId">id склада владельца. Если 0, то все кластера выводить в рамках КА, если >0,то толь
 88        /// <param name="active">true, если выводить только активные кластера. По умолчанию false</param>
 89        [HttpGet("Count")]
 90        [SwaggerResponse(200, "Успешно", typeof(CountDTO))]
 91        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 92        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 93        [Authorize(Roles = Role.SystemAdmin + "," + Role.SystemOperator + "," + Role.SupplierOwner)]
 94        public async Task<IActionResult> GetClustersCount(string filter = null, long contragentId = 0, long warehouseId 
 095        {
 096            filter = filter.NormalizeName();
 097            contragentId = _authService.IsUserPlatform() ? contragentId : _authService.ContragentId;
 098            int result = await Task.FromResult(_service.GetClusters(1, 1, filter, true, contragentId, active, warehouseI
 099            return Ok(new CountDTO(result));
 0100        }
 101
 102        /// <summary>
 103        /// Получить кластер по ID
 104        /// </summary>
 105        /// <remarks>author i.rebenok</remarks>
 106        /// <param name="id">id кластера</param>
 107        [HttpGet("{id}")]
 108        [SwaggerResponse(200, "Успешно", typeof(ClusterDTO_GET))]
 109        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 110        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 111        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 112        [Authorize(Roles = Role.SystemAdmin + "," + Role.SystemOperator + "," + Role.SupplierOwner)]
 113        public async Task<IActionResult> GetCluster([SwaggerParameter(Required = true)] long id)
 0114        {
 0115            var result = _authService.IsUserPlatform() ? await _service.GetCluster(id) : await _service.GetCluster(id, _
 0116            if (result == null)
 0117                return NotFoundResult($"Кластер с id={id} не найден");
 0118            return Ok(new ClusterDTO_GET(result));
 0119        }
 120
 121        /// <summary>
 122        /// Получение типа доставки для кластера
 123        /// </summary>
 124        /// <param name="id">Идентификатор кластера</param>
 125        /// <returns></returns>
 126        [HttpGet("{id}/Delivery")]
 127        [SwaggerResponse(200, "Успешно", typeof(List<DeliveryTypeResponseDto>))]
 128        [SwaggerResponse(400, "Нет записей", typeof(ErrorDTO))]
 129        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 130        [AllowAnonymous]
 131        public async Task<IActionResult> GetClusterDeliveryType(long id)
 132        {
 133            var result = await _service.GetCluster(id) ??
 134                         throw new ArgumentException($"Кластер {id} не найден");
 135            if (result.ClusterDeliveryTypes == null || result.ClusterDeliveryTypes.Count == 0)
 136                return Ok(new List<DeliveryTypeResponseDto>());
 137
 0138            return Ok(result.ClusterDeliveryTypes.Select(d => new DeliveryTypeResponseDto(d.DeliveryType)));
 139        }
 140
 141        /// <summary>
 142        /// Получение минимальной суммы заказа для кластера
 143        /// </summary>
 144        /// <param name="id">Идентификатор кластера</param>
 145        /// <returns></returns>
 146        [HttpGet("{id}/MinOrderSum")]
 147        [SwaggerResponse(200, "Успешно", typeof(int))]
 148        [SwaggerResponse(400, "Нет записей", typeof(ErrorDTO))]
 149        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 150        [AllowAnonymous]
 151        public async Task<IActionResult> GetClusterMinimumSum(long id)
 0152        {
 0153            var result = await _service.GetCluster(id) ??
 0154                         throw new ArgumentException($"Кластер {id} не найден");
 0155            return Ok(result.MinOrderSum);
 0156        }
 157
 158        /// <summary>
 159        /// Создает кластер, привязывает ТТ и возвращает созданный объект
 160        /// </summary>
 161        /// <remarks>author i.rebenok</remarks>
 162        /// <param name="clusterDto">JSON ClusterRequestDTO</param>
 163        [HttpPost("")]
 164        [SwaggerResponse(201, "Успешно создано", typeof(ClusterDTO_GET))]
 165        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 166        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 167        [SwaggerResponse(400, "Некорректные входные данные", typeof(ErrorDTO))]
 168        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 169        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 170        public async Task<IActionResult> CreateCluster([FromBody] [SwaggerParameter(Required = true)] ClusterRequestDTO 
 0171        {
 0172            var cluster = await PrepareCluster(new Cluster(), clusterDto);
 0173            await _service.CreateCluster(cluster);
 0174            return CreatedAtAction("GetCluster", new { id = cluster.Id }, new ClusterDTO_GET(cluster));
 0175        }
 176
 177        /// <summary>
 178        /// Обновляет поля кластера и привязывает/отвязывает ТТ
 179        /// </summary>
 180        /// <remarks>author i.rebenok</remarks>
 181        /// <param name="id">id кластера</param>
 182        /// <param name="clusterDto">JSON ClusterRequestDTO</param>
 183        [HttpPut("{id}")]
 184        [SwaggerResponse(200, "Успешно обновлено", typeof(ClusterDTO_GET))]
 185        [SwaggerResponse(400, "Некорректные входные данные", typeof(ErrorDTO))]
 186        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 187        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 188        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 189        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 190        public async Task<IActionResult> UpdateCluster([SwaggerParameter(Required = true)] long id, [FromBody] [SwaggerP
 0191        {
 0192            var cluster = _authService.IsUserPlatform() ? await _service.GetCluster(id) : await _service.GetCluster(id, 
 0193            if (cluster == null)
 0194                throw new KeyNotFoundException($"Кластер с id={id} не найден");
 0195            cluster = await PrepareCluster(cluster, clusterDto);
 0196            await _service.UpdateCluster(cluster);
 0197            return Ok(new ClusterDTO_GET(cluster));
 0198        }
 199
 200        /// <summary>
 201        /// Удаляет кластер по id
 202        /// </summary>
 203        /// <remarks>author i.rebenok</remarks>
 204        /// <param name="id">id кластера</param>
 205        [HttpDelete("{id}")]
 206        [SwaggerResponse(200, "Успешно удалено", typeof(EmptyResult))]
 207        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 208        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 209        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 210        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 211        public async Task<IActionResult> DeleteCluster([SwaggerParameter(Required = true)] long id)
 0212        {
 0213            var cluster = User.IsInRole(Role.SystemAdmin) ? await _service.GetCluster(id) : await _service.GetCluster(id
 0214            if (cluster == null)
 0215                return NotFoundResult($"Кластер с id={id} не найден");
 0216            await _service.DeleteCluster(id);
 0217            return Ok();
 0218        }
 219
 220        /// <summary>
 221        /// Деактивирует кластер по id
 222        /// </summary>
 223        /// <remarks>author i.rebenok</remarks>
 224        /// <param name="id">id кластера</param>
 225        [HttpPatch("{id}/Deactivate")]
 226        [SwaggerResponse(200, "Успешно", typeof(EmptyResult))]
 227        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 228        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 229        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 230        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 231        public async Task<IActionResult> DeactivateCluster([SwaggerParameter(Required = true)] long id)
 0232        {
 0233            var cluster = _authService.IsUserPlatform() ? await _service.GetCluster(id) : await _service.GetCluster(id, 
 0234            if (cluster == null)
 0235                return NotFoundResult($"Кластер с id={id} не найден");
 0236            if (cluster.RecState.Id != (int)RecordState.Inactive)
 0237            {
 0238                cluster.RecState = await _dirService.GetRecordState((int)RecordState.Inactive);
 0239                await _service.UpdateCluster(cluster);
 0240            }
 0241            return Ok();
 0242        }
 243
 244        /// <summary>
 245        /// Активирует кластер по id
 246        /// </summary>
 247        /// <remarks>author i.rebenok</remarks>
 248        /// <param name="id">id кластера</param>
 249        [HttpPatch("{id}/Activate")]
 250        [SwaggerResponse(200, "Успешно", typeof(EmptyResult))]
 251        [SwaggerResponse(404, "Нет записей", typeof(ErrorDTO))]
 252        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 253        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 254        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 255        public async Task<IActionResult> ActivateCluster([SwaggerParameter(Required = true)] long id)
 0256        {
 0257            var cluster = _authService.IsUserPlatform() ? await _service.GetCluster(id) : await _service.GetCluster(id, 
 0258            if (cluster == null)
 0259                return NotFoundResult($"Кластер с id={id} не найден");
 0260            if (cluster.RecState.Id != (int)RecordState.Active)
 0261            {
 0262                cluster.RecState = await _dirService.GetRecordState((int)RecordState.Active);
 0263                await _service.UpdateCluster(cluster);
 0264            }
 0265            return Ok();
 0266        }
 267
 268        /// <summary>
 269        /// Сравнивает список ТО со списком ТО в других кластерах конкретного склада-владельца. Возвращает список ТО,
 270        /// которые привязаны к другим кластерам и для них требуется подтверждение на перепривязку.
 271        /// </summary>
 272        /// <remarks>author i.rebenok</remarks>
 273        /// <param name="clusterDTO">JSON ClusterValidateDepDTO</param>
 274        [HttpPost("Validate")]
 275        [SwaggerResponse(200, "Успешно", typeof(List<ClusterDepartmentDTO>))]
 276        [SwaggerResponse(400, "Некорректные данные", typeof(ErrorDTO))]
 277        [SwaggerResponse(500, "Ошибка на стороне сервера", typeof(ErrorDTO))]
 278        [SwaggerResponse(403, "Не разрешено для этого пользователя", typeof(ErrorDTO))]
 279        [Authorize(Roles = Role.SystemAdmin + "," + Role.SupplierOwner)]
 280        public async Task<IActionResult> ValidateDeparments([FromBody] [SwaggerParameter(Required = true)] ClusterValida
 281        {
 282            if (!ModelState.IsValid)
 283                return BadRequestResult("Некорректные входные данные");
 0284            var listDepratments = (await _service.GetClustersByWarehouse(clusterDTO.WarehouseOwnerId)).Select(x => new C
 0285                .Where(x => x.DepartmentsCount > 0).Select(x => new List<ClusterDepartmentDTO>(x.Departments)).ToList();
 286            List<ClusterDepartmentDTO> diff = new List<ClusterDepartmentDTO>();
 287            foreach (var l in listDepratments)
 0288                diff.AddRange(clusterDTO.Departments.Where(n => l.Any(t => t.Id == n.Id)));
 289            return Ok(diff);
 290        }
 291
 292        /// <summary>
 293        /// Подготавливает оъект кластера для создания/обновления
 294        /// </summary>
 295        /// <param name="cluster">экземпляр класса Cluster</param>
 296        /// <param name="clusterDto">ДТО с данными по кластеру</param>
 297        /// <returns>обновленный экземпляр класса Cluster</returns>
 298        private async Task<Cluster> PrepareCluster(Cluster cluster, ClusterRequestDTO clusterDto)
 0299        {
 0300            if (clusterDto.DeliveryTypesId.Count == 0)
 0301                throw new ArgumentException("Необходимо указать тип доставки");
 0302            if (cluster.Warehouse?.Id != clusterDto.WarehouseId)
 0303            {
 304                // Если админ, то не паримся и любой склад привязываем. Если поставщик, то привязанный склад должен быть
 0305                cluster.Warehouse = _authService.IsUserPlatform() ? await _departService.GetDepartment(clusterDto.Wareho
 0306                    : await _departService.GetDepartment(clusterDto.WarehouseId, _authService.ContragentId);
 0307                if (cluster.Warehouse == null)
 0308                    throw new KeyNotFoundException($"Указанный склад с id={clusterDto.WarehouseId} не найден");
 0309            }
 0310            if ((_service.GetClustersByName(clusterDto.Name))
 0311               .Where(d => d.Warehouse.Id == cluster.Warehouse.Id && d.Id != cluster.Id)
 0312               .ToList().Count > 0)
 0313                throw new ArgumentException($"Кластер с именем {clusterDto.Name} уже существует");
 0314            cluster.Name = clusterDto.Name;
 0315            cluster.TradeRatio = clusterDto.TradeRatio;
 0316            cluster.MinOrderSum = clusterDto.MinOrderSum;
 0317            cluster.Departments = await ManageBindDepartments(clusterDto.DepartmentsBindId, cluster.Departments);
 0318            cluster.ClusterDeliveryTypes = await ManageDeliveryTypes(clusterDto.DeliveryTypesId, cluster.ClusterDelivery
 0319            cluster.RecState = await _dirService.GetRecordState((int)RecordState.Active) ?? throw new KeyNotFoundExcepti
 0320            return cluster;
 0321        }
 322
 323        /// <summary>
 324        /// привязывает/отвязывает магазины от кластера.
 325        /// </summary>
 326        /// <param name="departmentsId">список id магазинов для привязки. Этот список будет привязан. Все, чего в нем не
 327        /// <param name="departmentsInCluster">список уже привязанных магазинов к кластеру</param>
 328        /// <returns>возвращает обновленный список магазинов к кластеру</returns>
 329        private async Task<List<Department>> ManageBindDepartments(List<long> departmentsId, List<Department> department
 330        {
 331            //отвязываем то, чего нет в массиве с фронта
 332            foreach (Department dep in new List<Department>(departmentsInCluster)) //в новый список загоняем, чтобы не б
 333            {
 0334                if (!departmentsId.Any(x => x == dep.Id)) departmentsInCluster.Remove(dep);
 335            }
 336
 337            //привязываем то, ччто есть в массиве с фронта
 338            foreach (long dep in departmentsId)
 339            {
 0340                if (!departmentsInCluster.Any(x => x.Id == dep))
 341                {
 342                    var result = await _departService.GetDepartment(dep);
 343                    if (result != null)
 344                        departmentsInCluster.Add(result);
 345                    else
 346                        throw new ArgumentException($"Подразделение с id={dep} не найдено");
 347                }
 348            }
 349            return departmentsInCluster;
 350        }
 351
 352        /// <summary>
 353        /// привязывает/отвязывает типы доставки от кластера.
 354        /// </summary>
 355        /// <param name="deliveryTypesId">список id типов доставки для привязки. Этот список будет привязан. Все, чего в
 356        /// <param name="deliveryTypesinCluster">список уже привязанных типов доставки к кластеру</param>
 357        /// <returns>возвращает обновленный список типов доставки к кластеру</returns>
 358        private async Task<List<ClusterDeliveryType>> ManageDeliveryTypes(List<long> deliveryTypesId, List<ClusterDelive
 359        {
 0360            deliveryTypesinCluster.RemoveAll(x => x.Cluster != null);
 361            foreach (long item in deliveryTypesId)
 362            {
 363                var result = await _dirService.GetDeliveryType(item);
 364                if (result == null)
 365                    throw new ArgumentException($"Тип доставки с id={item} не найден");
 366                deliveryTypesinCluster.Add(new ClusterDeliveryType() { DeliveryType = result });
 367            }
 368            return deliveryTypesinCluster;
 369        }
 370    }
 371}