< Summary

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

Metrics

MethodLine coverage Branch coverage
.ctor(...)0%100%
CheckDepartment(...)0%0%
GetShowcaseGoodsBaseQuery()0%100%
GetShowcaseGoods(...)0%0%
PrepareGoodDTO(...)0%0%
GetContractRatio()0%0%
GetShowcaseGood()0%0%
ToGoodDtoMapper(...)0%0%
GetDiscountColor(...)0%0%
GetDiscountTextColor(...)0%0%
GetDiscountTransparency(...)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
 035        public ShowcaseWorker(ILogger<ShowcaseWorker> logger, IGoodService goodService,
 036            IDepartmentService departmentService, IContragentService contragentService,
 037            IDiscountColorService discountColorService, IOptions<ImagesSettings> options)
 038        {
 039            _logger = logger;
 040            _goodService = goodService;
 041            _departmentService = departmentService;
 042            _contragentService = contragentService;
 043            _discountColorService = discountColorService;
 044            _imageSettings = options.Value;
 45
 046            discountColors = _discountColorService.GetDiscountColors(0, int.MaxValue, null, null).Result.Result;
 047        }
 48
 49        Department CheckDepartment(Department department)
 050        {
 051            if(department == null)
 052            {
 053                throw new ArgumentException("Не найден магазин");
 54            }
 55
 056            if(department.Cluster == null || department.Cluster.IsDeleted)
 057            {
 058                throw new ArgumentException("Не найден кластер");
 59            }
 60
 061            if (department.Cluster.Warehouse == null || department.Cluster.Warehouse.IsDeleted)
 062            {
 063                throw new ArgumentException("Не найден склад-владелец");
 64            }
 65
 066            return department;
 067        }
 68
 69        public async Task<IQueryable<Good>> GetShowcaseGoodsBaseQuery(long? categoryId, long departmentId, bool showNA)
 070        {
 071            var dep = CheckDepartment(await _departmentService.GetDepartment(departmentId));
 072            return _goodService.GetShowcaseGoodsBaseQuery(categoryId, dep.Cluster, showNA);
 073        }
 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)
 077        {
 078            var dep = CheckDepartment(_departmentService.GetDepartment(departmentId).Result);
 79
 080            var ratio = GetContractRatio(dep).Result;
 081            if (ratio == 0 || dep.Cluster.RatioForCalculations == 0)
 082            {
 083                count = filteredCount = 0;
 084                return new List<ShowcaseGoodDTO>();
 85            }
 86
 87            // запрос для всех товаров заданной категории
 088            var allGoods = _goodService.GetShowcaseGoodsBaseQuery(categoryId, dep.Cluster, showNA);
 089            count = filteredCount = allGoods.Count();
 90
 91            // отфильтрованный запрос товаров заданной категории
 092            var sidebarFilter = ShowcaseSidebarFilter.FromJson(sidebarFilterJson);
 093            if (sidebarFilter != null || !string.IsNullOrWhiteSpace(filter) || !string.IsNullOrEmpty(labelname))
 094            {
 095                allGoods = _goodService.GetFilteredShowcaseGoodsQuery(allGoods, dep.Cluster, ratio,
 096                    filter, sidebarFilter?.brands, sidebarFilter?.country, sidebarFilter?.minQuantity,
 097                    sidebarFilter?.price?.priceFrom, sidebarFilter?.price?.priceTo, labelname);
 098                filteredCount = allGoods.Count();
 099            }
 100
 101            // применяем сотировку и пагинацию
 0102            var pagedGoods = _goodService.GetPagedShowcaseGoodsQuery(allGoods, dep.Cluster, page, limit, sort).ToList();
 0103            pagedGoods.ForEach(g => g.Photos.SetPhotoUrl(_imageSettings));
 104
 0105            var result = ToGoodDtoMapper(dep, ratio, discountColors, _imageSettings)
 0106                .Map<List<ShowcaseGoodDTO>>(pagedGoods)
 0107                .ToList();
 0108            result.ForEach(x => PrepareGoodDTO(x));
 109
 0110            return result;
 0111        }
 112
 113        void PrepareGoodDTO(ShowcaseGoodDTO dto)
 0114        {
 0115            if(dto.OldPrice.GetValueOrDefault(0) <= dto.Price)
 0116            {
 0117                dto.OldPrice = null;
 0118                dto.Discount = null;
 0119                dto.LabelColor = null;
 0120            }
 0121        }
 122
 123        public async Task<decimal> GetContractRatio(Department buyerStore)
 0124        {
 0125            var buyer = await _contragentService.GetContragentWithContracts(buyerStore.Contragent.Id);
 0126            var seller = (await _departmentService.GetDepartment(buyerStore.Cluster.Warehouse.Id)).Contragent;
 0127            var contract = buyer.ContractsAsBuyer
 0128                .Where(x => !x.IsDeleted
 0129                    && x.Seller.Id == seller.Id
 0130                    && x.BeginDate <= DateTime.UtcNow
 0131                    && x.EndDate >= DateTime.UtcNow)
 0132                .FirstOrDefault();
 0133            if(contract == null)
 0134            {
 0135                throw new ArgumentException("Контракт не найден");
 136            }
 0137            return contract.RatioForCalculations;
 0138        }
 139
 140        public async Task<ShowcaseGoodDTO> GetShowcaseGood(long goodId, long departmentId)
 0141        {
 0142            var dep = CheckDepartment(await _departmentService.GetDepartment(departmentId));
 0143            var ratio = await GetContractRatio(dep);
 144
 0145            var good = await _goodService.GetShowcaseGood(goodId, dep.Cluster);
 0146            if(good == null)
 0147            {
 0148                throw new ArgumentException("Не найден товар");
 149            }
 150            //установим урлы для картинок товара
 0151            good.Photos.SetPhotoUrl(_imageSettings);
 152
 0153            var result = ToGoodDtoMapper(dep, ratio, discountColors, _imageSettings).Map<ShowcaseGoodDTO>(good);
 0154            PrepareGoodDTO(result);
 0155            return result;
 0156        }
 157
 158        private static IMapper ToGoodDtoMapper(Department department, decimal contractRatio, List<DiscountColor> discoun
 0159        {
 0160            var config = new MapperConfiguration(cfg =>
 0161            {
 0162                cfg.CreateMap<Good, ShowcaseGoodDTO>()
 0163                    .ForMember(d => d.VendorCode, e => e.MapFrom(x => x.GetActualVendorCode(department.Cluster.Warehouse
 0164                    .ForMember(d => d.Price, e => e.MapFrom(x => x.CurrentPrice(department.Cluster, contractRatio)))
 0165                    .ForMember(d => d.OldPrice, e => e.MapFrom(x => x.OldPrice(department.Cluster, contractRatio)))
 0166                    .ForMember(d => d.Discount,
 0167                        e => e.MapFrom(x => x.Prices.Actual(department.Cluster.WarehouseId).DiscountForLabelDisplay()))
 0168                    .ForMember(d => d.LabelColor,
 0169                        e => e.MapFrom(x => GetDiscountColor(x.Prices.Actual(department.Cluster.WarehouseId).DiscountFor
 0170                    .ForMember(d => d.TextColor,
 0171                        e => e.MapFrom(x => GetDiscountTextColor(x.Prices.Actual(department.Cluster.WarehouseId).Discoun
 0172                    .ForMember(d => d.Transparency,
 0173                        e => e.MapFrom(x => GetDiscountTransparency(x.Prices.Actual(department.Cluster.WarehouseId).Disc
 0174                    .ForMember(d => d.RestQuantity, e => e.MapFrom(x => x.Rests.ActualQuantity(department.Cluster.Wareho
 0175                    .ForMember(d => d.MinQuantity,
 0176                        e => e.MapFrom(x => x.DepartmentGoodSettings.ActualMinQuantity(department.Cluster.WarehouseId)))
 0177                    .ForMember(d => d.MainBarcode, e => e.MapFrom(
 0178                        s => new BarCodeDTO
 0179                        {
 0180                            Id = s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary) != null ?
 0181                                s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary).BarCode.Id
 0182                                : s.DefaultBarCode.Id,
 0183                            Code = s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary) != null ?
 0184                                s.GoodBarcodes.FirstOrDefault(b => b.IsPrimary).BarCode.Code
 0185                                : s.DefaultBarCode.Code
 0186                        }))
 0187                    .ForMember(d => d.Barcodes, e => e.MapFrom(
 0188                        s => s.GoodBarcodes.Where(b => !b.IsPrimary).Count() > 0 ? s.GoodBarcodes.Where(b => !b.IsPrimar
 0189                        {
 0190                            Code = b.BarCode != null ? b.BarCode.Code : default
 0191                        })
 0192                            : new List<BarCodeDTO>()
 0193                    ))
 0194                    .ForMember(d => d.Labels, e => e.MapFrom(
 0195                        s => s.DepartmentGoodSettings
 0196                            .Where(x => !x.IsDeleted && x.ShowcaseVisible && x.DepartmentId == department.Cluster.Wareho
 0197                            .SelectMany(x => x.GoodSettingsLabels)
 0198                            .Where(x => !x.GoodLabel.IsDeleted && x.GoodLabel.ShowcaseVisible)
 0199                            .Select(x => new ShowcaseGoodLabelDTO(x.GoodLabel))
 0200                            .OrderBy(x => x.Priority)
 0201                            .ToList()
 0202                    ))
 0203                    .ForMember(d => d.PickingQuantum,
 0204                        e => e.MapFrom(x => x.DepartmentGoodSettings.ActualPickingQuantum(department.Cluster.WarehouseId
 0205                    .ForMember(d => d.VatKind,
 0206                        e => e.MapFrom(s => new EnumDB_DTO
 0207                            {Id = s.VatsKind.Id, Code = s.VatsKind.Code, Name = s.VatsKind.Name}))
 0208                    .ForMember(d => d.UnitKind,
 0209                        e => e.MapFrom(s => new EnumDB_DTO
 0210                            {Id = s.UnitsKind.Id, Code = s.UnitsKind.Code, Name = s.UnitsKind.Name}));
 0211                cfg.CreateMap<Photo, PhotoDTO>();
 0212                cfg.CreateMap<Category, CategoryForFeedDTO>()
 0213                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 0214                    .ForMember(d => d.Name, e => e.MapFrom(s => s.Name))
 0215                    .ForMember(d => d.ExcludeFromGoogleFeed, e => e.MapFrom(s => s.ExcludeFromGoogleFeed))
 0216                    .ForMember(d => d.ExcludeFromYandexFeed, e => e.MapFrom(s => s.ExcludeFromYandexFeed))
 0217                    .ForMember(d => d.GoogleProductCategoryCode, e => e.MapFrom(s => s.GoogleProductCategoryCode));
 0218                cfg.CreateMap<Contragent, IdNameDTO>()
 0219                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 0220                    .ForMember(d => d.Name, e => e.MapFrom(s => s.ShortName));
 0221                cfg.CreateMap<Brand, IdNameDTO>()
 0222                    .ForMember(d => d.Id, e => e.MapFrom(s => s.Id))
 0223                    .ForMember(d => d.Name, e => e.MapFrom(s => s.Name));
 0224                cfg.CreateMap<BarCode, BarCodeDTO>();
 0225                cfg.CreateMap<Country, IdNameDTO>();
 0226            });
 0227            var mapper = config.CreateMapper();
 0228            return mapper;
 0229        }
 230
 231        static string GetDiscountColor(int? discount, List<DiscountColor> discountColors)
 0232        {
 0233            return discount.HasValue
 0234                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).S
 0235                : null;
 0236        }
 237
 238        static string GetDiscountTextColor(int? discount, List<DiscountColor> discountColors)
 0239        {
 0240            return discount.HasValue
 0241                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).F
 0242                : null;
 0243        }
 244
 245        static decimal GetDiscountTransparency(int? discount, List<DiscountColor> discountColors)
 0246        {
 0247            var color = discount.HasValue
 0248                ? discountColors.Where(x => x.DiscountLevel <= discount.Value).OrderByDescending(x => x.DiscountLevel).F
 0249                : null;
 0250            return color != null ? color.Transparency : 0;
 0251        }
 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    {
 267        public List<long> brands { get; set; }
 268
 269        public List<long> country { get; set; }
 270
 271        public List<decimal> minQuantity { get; set; }
 272
 273        public ShowcaseSidebarPriceFilter price { get; set; }
 274
 275        public static ShowcaseSidebarFilter FromJson(string json)
 276        {
 277            ShowcaseSidebarFilter result = null;
 278            if (!string.IsNullOrWhiteSpace(json))
 279            {
 280                try
 281                {
 282                    result = JsonConvert.DeserializeObject<ShowcaseSidebarFilter>(json);
 283                    if (result.price != null)
 284                    {
 285                        if (!string.IsNullOrEmpty(result.price.price_from))
 286                        {
 287                            result.price.priceFrom = result.price.price_from.ToDecimal();
 288                        }
 289
 290                        if (!string.IsNullOrEmpty(result.price.price_to))
 291                        {
 292                            result.price.priceTo = result.price.price_to.ToDecimal();
 293                        }
 294                    }
 295                    else
 296                    {
 297                        result.price = new ShowcaseSidebarPriceFilter();
 298                    }
 299                }
 300                catch
 301                {
 302                    throw new ArgumentException("Некорректный sidebarFilterJson");
 303                }
 304            }
 305            return result;
 306        }
 307    }
 308}