< Summary

Class:SVETA.Api.Services.Implements.ShowcaseSidebarFilter
Assembly:SVETA.Api
File(s):/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/ShowcaseWorker.cs
Covered lines:0
Uncovered lines:31
Coverable lines:31
Total lines:308
Line coverage:0% (0 of 31)
Covered branches:0
Total branches:8
Branch coverage:0% (0 of 8)

Metrics

MethodLine coverage Branch coverage
get_brands()0%100%
get_country()0%100%
get_minQuantity()0%100%
get_price()0%100%
FromJson(...)0%0%

File(s)

/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/ShowcaseWorker.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading.Tasks;
 5using SVETA.Api.Data.DTO.Showcase;
 6using SVETA.Api.Services.Interfaces;
 7using WinSolutions.Sveta.Server.Services.Interfaces;
 8using Microsoft.Extensions.Logging;
 9using AutoMapper;
 10using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 11using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 12using SVETA.Api.Data.DTO;
 13using WinSolutions.Sveta.Server.Data.DataModel.Extensions;
 14using Microsoft.Extensions.Options;
 15using SVETA.Api.Data.Domain;
 16using Newtonsoft.Json;
 17using WinSolutions.Sveta.Common.Extensions;
 18using Clave.Expressionify;
 19using System.Diagnostics;
 20using Microsoft.EntityFrameworkCore.Internal;
 21
 22namespace SVETA.Api.Services.Implements
 23{
 24    public class ShowcaseWorker : IShowcaseWorker
 25    {
 26        private readonly ILogger<ShowcaseWorker> _logger;
 27        private readonly IGoodService _goodService;
 28        private readonly IDepartmentService _departmentService;
 29        private readonly IContragentService _contragentService;
 30        private readonly IDiscountColorService _discountColorService;
 31        private readonly ImagesSettings _imageSettings;
 32        List<DiscountColor> discountColors;
 33
 34
 35        public ShowcaseWorker(ILogger<ShowcaseWorker> logger, IGoodService goodService,
 36            IDepartmentService departmentService, IContragentService contragentService,
 37            IDiscountColorService discountColorService, IOptions<ImagesSettings> options)
 38        {
 39            _logger = logger;
 40            _goodService = goodService;
 41            _departmentService = departmentService;
 42            _contragentService = contragentService;
 43            _discountColorService = discountColorService;
 44            _imageSettings = options.Value;
 45
 46            discountColors = _discountColorService.GetDiscountColors(0, int.MaxValue, null, null).Result.Result;
 47        }
 48
 49        Department CheckDepartment(Department department)
 50        {
 51            if(department == null)
 52            {
 53                throw new ArgumentException("Не найден магазин");
 54            }
 55
 56            if(department.Cluster == null || department.Cluster.IsDeleted)
 57            {
 58                throw new ArgumentException("Не найден кластер");
 59            }
 60
 61            if (department.Cluster.Warehouse == null || department.Cluster.Warehouse.IsDeleted)
 62            {
 63                throw new ArgumentException("Не найден склад-владелец");
 64            }
 65
 66            return department;
 67        }
 68
 69        public async Task<IQueryable<Good>> GetShowcaseGoodsBaseQuery(long? categoryId, long departmentId, bool showNA)
 70        {
 71            var dep = CheckDepartment(await _departmentService.GetDepartment(departmentId));
 72            return _goodService.GetShowcaseGoodsBaseQuery(categoryId, dep.Cluster, showNA);
 73        }
 74
 75        public List<ShowcaseGoodDTO> GetShowcaseGoods(long? categoryId, long departmentId, bool showNA, int page, int li
 76            out int count, out int filteredCount, string labelname = default)
 77        {
 78            var dep = CheckDepartment(_departmentService.GetDepartment(departmentId).Result);
 79
 80            var ratio = GetContractRatio(dep).Result;
 81            if (ratio == 0 || dep.Cluster.RatioForCalculations == 0)
 82            {
 83                count = filteredCount = 0;
 84                return new List<ShowcaseGoodDTO>();
 85            }
 86
 87            // запрос для всех товаров заданной категории
 88            var allGoods = _goodService.GetShowcaseGoodsBaseQuery(categoryId, dep.Cluster, showNA);
 89            count = filteredCount = allGoods.Count();
 90
 91            // отфильтрованный запрос товаров заданной категории
 92            var sidebarFilter = ShowcaseSidebarFilter.FromJson(sidebarFilterJson);
 93            if (sidebarFilter != null || !string.IsNullOrWhiteSpace(filter) || !string.IsNullOrEmpty(labelname))
 94            {
 95                allGoods = _goodService.GetFilteredShowcaseGoodsQuery(allGoods, dep.Cluster, ratio,
 96                    filter, sidebarFilter?.brands, sidebarFilter?.country, sidebarFilter?.minQuantity,
 97                    sidebarFilter?.price?.priceFrom, sidebarFilter?.price?.priceTo, labelname);
 98                filteredCount = allGoods.Count();
 99            }
 100
 101            // применяем сотировку и пагинацию
 102            var pagedGoods = _goodService.GetPagedShowcaseGoodsQuery(allGoods, dep.Cluster, page, limit, sort).ToList();
 103            pagedGoods.ForEach(g => g.Photos.SetPhotoUrl(_imageSettings));
 104
 105            var result = ToGoodDtoMapper(dep, ratio, discountColors, _imageSettings)
 106                .Map<List<ShowcaseGoodDTO>>(pagedGoods)
 107                .ToList();
 108            result.ForEach(x => PrepareGoodDTO(x));
 109
 110            return result;
 111        }
 112
 113        void PrepareGoodDTO(ShowcaseGoodDTO dto)
 114        {
 115            if(dto.OldPrice.GetValueOrDefault(0) <= dto.Price)
 116            {
 117                dto.OldPrice = null;
 118                dto.Discount = null;
 119                dto.LabelColor = null;
 120            }
 121        }
 122
 123        public async Task<decimal> GetContractRatio(Department buyerStore)
 124        {
 125            var buyer = await _contragentService.GetContragentWithContracts(buyerStore.Contragent.Id);
 126            var seller = (await _departmentService.GetDepartment(buyerStore.Cluster.Warehouse.Id)).Contragent;
 127            var contract = buyer.ContractsAsBuyer
 128                .Where(x => !x.IsDeleted
 129                    && x.Seller.Id == seller.Id
 130                    && x.BeginDate <= DateTime.UtcNow
 131                    && x.EndDate >= DateTime.UtcNow)
 132                .FirstOrDefault();
 133            if(contract == null)
 134            {
 135                throw new ArgumentException("Контракт не найден");
 136            }
 137            return contract.RatioForCalculations;
 138        }
 139
 140        public async Task<ShowcaseGoodDTO> GetShowcaseGood(long goodId, long departmentId)
 141        {
 142            var dep = CheckDepartment(await _departmentService.GetDepartment(departmentId));
 143            var ratio = await GetContractRatio(dep);
 144
 145            var good = await _goodService.GetShowcaseGood(goodId, dep.Cluster);
 146            if(good == null)
 147            {
 148                throw new ArgumentException("Не найден товар");
 149            }
 150            //установим урлы для картинок товара
 151            good.Photos.SetPhotoUrl(_imageSettings);
 152
 153            var result = ToGoodDtoMapper(dep, ratio, discountColors, _imageSettings).Map<ShowcaseGoodDTO>(good);
 154            PrepareGoodDTO(result);
 155            return result;
 156        }
 157
 158        private static IMapper ToGoodDtoMapper(Department department, decimal contractRatio, List<DiscountColor> discoun
 159        {
 160            var config = new MapperConfiguration(cfg =>
 161            {
 162                cfg.CreateMap<Good, ShowcaseGoodDTO>()
 163                    .ForMember(d => d.VendorCode, e => e.MapFrom(x => x.GetActualVendorCode(department.Cluster.Warehouse
 164                    .ForMember(d => d.Price, e => e.MapFrom(x => x.CurrentPrice(department.Cluster, contractRatio)))
 165                    .ForMember(d => d.OldPrice, e => e.MapFrom(x => x.OldPrice(department.Cluster, contractRatio)))
 166                    .ForMember(d => d.Discount,
 167                        e => e.MapFrom(x => x.Prices.Actual(department.Cluster.WarehouseId).DiscountForLabelDisplay()))
 168                    .ForMember(d => d.LabelColor,
 169                        e => e.MapFrom(x => GetDiscountColor(x.Prices.Actual(department.Cluster.WarehouseId).DiscountFor
 170                    .ForMember(d => d.TextColor,
 171                        e => e.MapFrom(x => GetDiscountTextColor(x.Prices.Actual(department.Cluster.WarehouseId).Discoun
 172                    .ForMember(d => d.Transparency,
 173                        e => e.MapFrom(x => GetDiscountTransparency(x.Prices.Actual(department.Cluster.WarehouseId).Disc
 174                    .ForMember(d => d.RestQuantity, e => e.MapFrom(x => x.Rests.ActualQuantity(department.Cluster.Wareho
 175                    .ForMember(d => d.MinQuantity,
 176                        e => e.MapFrom(x => x.DepartmentGoodSettings.ActualMinQuantity(department.Cluster.WarehouseId)))
 177                    .ForMember(d => d.MainBarcode, e => e.MapFrom(
 178                        s => new BarCodeDTO
 179                        {
 180                            Id = s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary) != null ?
 181                                s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary).BarCode.Id
 182                                : s.DefaultBarCode.Id,
 183                            Code = s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary) != null ?
 184                                s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary).BarCode.Code
 185                                : s.DefaultBarCode.Code
 186                        }))
 187                    .ForMember(d => d.Barcodes, e => e.MapFrom(
 188                        s => s.GoodBarcodes.Where(b => !b.IsPrimary).Count() > 0 ? s.GoodBarcodes.Where(b => !b.IsPrimar
 189                        {
 190                            Code = b.BarCode != null ? b.BarCode.Code : default
 191                        })
 192                            : new List<BarCodeDTO>()
 193                    ))
 194                    .ForMember(d => d.Labels, e => e.MapFrom(
 195                        s => s.DepartmentGoodSettings
 196                            .Where(x => !x.IsDeleted && x.ShowcaseVisible && x.DepartmentId == department.Cluster.Wareho
 197                            .SelectMany(x => x.GoodSettingsLabels)
 198                            .Where(x => !x.GoodLabel.IsDeleted && x.GoodLabel.ShowcaseVisible)
 199                            .Select(x => new ShowcaseGoodLabelDTO(x.GoodLabel))
 200                            .OrderBy(x => x.Priority)
 201                            .ToList()
 202                    ))
 203                    .ForMember(d => d.PickingQuantum,
 204                        e => e.MapFrom(x => x.DepartmentGoodSettings.ActualPickingQuantum(department.Cluster.WarehouseId
 205                    .ForMember(d => d.VatKind,
 206                        e => e.MapFrom(s => new EnumDB_DTO
 207                            {Id = s.VatsKind.Id, Code = s.VatsKind.Code, Name = s.VatsKind.Name}))
 208                    .ForMember(d => d.UnitKind,
 209                        e => e.MapFrom(s => new EnumDB_DTO
 210                            {Id = s.UnitsKind.Id, Code = s.UnitsKind.Code, Name = s.UnitsKind.Name}));
 211                cfg.CreateMap<Photo, PhotoDTO>();
 212                cfg.CreateMap<Category, CategoryForFeedDTO>()
 213                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 214                    .ForMember(d => d.Name, e => e.MapFrom(s => s.Name))
 215                    .ForMember(d => d.ExcludeFromGoogleFeed, e => e.MapFrom(s => s.ExcludeFromGoogleFeed))
 216                    .ForMember(d => d.ExcludeFromYandexFeed, e => e.MapFrom(s => s.ExcludeFromYandexFeed))
 217                    .ForMember(d => d.GoogleProductCategoryCode, e => e.MapFrom(s => s.GoogleProductCategoryCode));
 218                cfg.CreateMap<Contragent, IdNameDTO>()
 219                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 220                    .ForMember(d => d.Name, e => e.MapFrom(s => s.ShortName));
 221                cfg.CreateMap<Brand, IdNameDTO>()
 222                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 223                    .ForMember(d => d.Name, e => e.MapFrom(s => s.Name));
 224                cfg.CreateMap<BarCode, BarCodeDTO>();
 225                cfg.CreateMap<Country, IdNameDTO>();
 226            });
 227            var mapper = config.CreateMapper();
 228            return mapper;
 229        }
 230
 231        static string GetDiscountColor(int? discount, List<DiscountColor> discountColors)
 232        {
 233            return discount.HasValue
 234                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).S
 235                : null;
 236        }
 237
 238        static string GetDiscountTextColor(int? discount, List<DiscountColor> discountColors)
 239        {
 240            return discount.HasValue
 241                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).F
 242                : null;
 243        }
 244
 245        static decimal GetDiscountTransparency(int? discount, List<DiscountColor> discountColors)
 246        {
 247            var color = discount.HasValue
 248                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).F
 249                : null;
 250            return color != null ? color.Transparency : 0;
 251        }
 252    }
 253
 254    class ShowcaseSidebarPriceFilter
 255    {
 256        public string price_from { get; set; }
 257
 258        public string price_to { get; set; }
 259
 260        public decimal? priceFrom { get; set; }
 261
 262        public decimal? priceTo { get; set; }
 263    }
 264
 265    class ShowcaseSidebarFilter
 266    {
 0267        public List<long> brands { get; set; }
 268
 0269        public List<long> country { get; set; }
 270
 0271        public List<decimal> minQuantity { get; set; }
 272
 0273        public ShowcaseSidebarPriceFilter price { get; set; }
 274
 275        public static ShowcaseSidebarFilter FromJson(string json)
 0276        {
 0277            ShowcaseSidebarFilter result = null;
 0278            if (!string.IsNullOrWhiteSpace(json))
 0279            {
 280                try
 0281                {
 0282                    result = JsonConvert.DeserializeObject<ShowcaseSidebarFilter>(json);
 0283                    if (result.price != null)
 0284                    {
 0285                        if (!string.IsNullOrEmpty(result.price.price_from))
 0286                        {
 0287                            result.price.priceFrom = result.price.price_from.ToDecimal();
 0288                        }
 289
 0290                        if (!string.IsNullOrEmpty(result.price.price_to))
 0291                        {
 0292                            result.price.priceTo = result.price.price_to.ToDecimal();
 0293                        }
 0294                    }
 295                    else
 0296                    {
 0297                        result.price = new ShowcaseSidebarPriceFilter();
 0298                    }
 0299                }
 0300                catch
 0301                {
 0302                    throw new ArgumentException("Некорректный sidebarFilterJson");
 303                }
 0304            }
 0305            return result;
 0306        }
 307    }
 308}