Пример #1
0
        private async Task <SmRecommendationProductSummary> UpdateState(int clientId, int scenarioId, int productId, DecisionState state)
        {
            // Update decision state changing 'DecisionRecommendationGuid'
            await _recommendationProductRepository.SetDecisionState(clientId, scenarioId, productId, state);

            // Return updated product and 'DecisionRecommendationGuid'
            var result = await _recommendationProductSummaryRepository.GetByScenarioAndProductId(clientId, scenarioId, productId);

            return(SmRecommendationProductSummary.Build(result));
        }
Пример #2
0
        public async Task <QueryResults <SmRecommendationProductSummary> > GetRecommendations(int scenarioId,
                                                                                              int pageIndex,
                                                                                              int pageSize,
                                                                                              List <IFilter> filters,
                                                                                              List <ISort> sorts)
        {
            // TODO validate access to scenarioId/guid
            var results = await _recommendationProductSummaryRepository.GetAll(scenarioId, pageIndex, pageSize, filters, sorts);

            return(SmRecommendationProductSummary.Build(results));
        }
Пример #3
0
        public static VmRecommendation Build(SmRecommendationProductSummary model)
        {
            if (model == null)
            {
                return(null);
            }

            var decision = model.DecisionRecommendation;

            return(new VmRecommendation
            {
                RecommendationProductGuid = model.RecommendationProductGuid,
                RecommendationGuid = decision?.RecommendationSummaryGuid ?? model.RecommendationProductGuid,
                ScenarioId = model.ScenarioId,
                RevisionId = decision?.RevisionId ?? 0,
                ScheduleId = decision?.ScheduleId ?? 0,
                ScheduleMask = decision?.ScheduleMask ?? 0,
                PriceLadderId = model.PriceLadderId,
                ProductId = model.ProductId,
                ProductName = model.ProductName,
                HierarchyName = model.HierarchyName,
                OriginalSellingPrice = model.OriginalSellingPrice,
                CurrentSellingPrice = model.CurrentSellingPrice,
                CurrentMarkdownDepth = model.CurrentMarkdownDepth,
                CurrentDiscountLadderDepth = model.CurrentDiscountLadderDepth,
                SellThroughTarget = decision?.SellThroughTarget ?? 0,
                TerminalStockUnits = decision?.TerminalStock ?? 0,
                PricePathPrices = string.Join(";", decision?.Projections?.Select(x => x.Price) ?? new List <decimal>()),
                PricePathDiscounts = string.Join(";", decision?.Projections?.Select(x => x.Discount) ?? new List <decimal>()),
                TotalRevenue = decision?.TotalRevenue ?? 0,
                Projections = VmRecommendationProjection.Build(decision, decision?.Projections),
                MarkdownCost = decision?.TotalMarkdownCost ?? 0,
                Status = model.DecisionState.ToString().ToUpper(),
                CalcStatus = decision?.Projections?.Any() ?? false ? RecommendationStatus.Ok : RecommendationStatus.Fatal,
                CalcSubStatus = decision?.Projections?.Any() ?? false ? RecommendationSubStatus.Ok : RecommendationSubStatus.NoSchedules
            });
        }
Пример #4
0
 public async Task Upload(IMarkdownFunctionSettings settings, SmRecommendationProductSummary product, int revisionId, List <SmCalcRecommendation> recommendations, int userId)
 {
     var seededHash = MurmurHash.Create128(seed: (uint)product.ClientId);
     var entities   = Build(seededHash, product, recommendations, userId);
     await _recommendationRepository.Write(clientId : product.ClientId, scenarioId : product.ScenarioId, revisionId : revisionId, partitionId : product.PartitionNumber, productId : product.ProductId, entities : entities);
 }
Пример #5
0
        private static List <Recommendation> Build(Murmur128 hash, SmRecommendationProductSummary product, IEnumerable <SmCalcRecommendation> recommendations, int userId)

        {
            var results = new List <Recommendation>();

            foreach (var recommendation in recommendations)
            {
                var recommendationEntity = new Recommendation(hash)
                {
                    ClientId   = product.ClientId,
                    ScenarioId = product.ScenarioId,

                    ScheduleId            = recommendation.ScheduleId,
                    ScheduleMask          = recommendation.ScheduleMask,
                    ScheduleMarkdownCount = recommendation.ScheduleMarkdownCount,
                    IsCsp             = recommendation.IsCsp,
                    PricePathPrices   = string.Join(";", recommendation.PricePath),
                    PricePathHashCode = string.Join(";", recommendation.PricePath).GetHashCode(),
                    RevisionId        = recommendation.RevisionId,

                    Rank = recommendation.Rank,
                    TotalMarkdownCount  = recommendation.TotalMarkdownCount,
                    TerminalStock       = recommendation.TerminalStock,
                    TotalRevenue        = recommendation.TotalRevenue,
                    TotalCost           = recommendation.TotalCost,
                    TotalMarkdownCost   = recommendation.TotalMarkdownCost,
                    FinalDiscount       = recommendation.FinalDiscount,
                    StockValue          = recommendation.StockValue,
                    EstimatedProfit     = recommendation.EstimatedProfit,
                    EstimatedSales      = recommendation.EstimatedSales,
                    SellThroughRate     = recommendation.SellThroughRate,
                    SellThroughTarget   = recommendation.SellThroughTarget,
                    FinalMarkdownTypeId = (int)recommendation.FinalMarkdownType,

                    RecommendationProductGuid = product.RecommendationProductGuid,
                    CreatedBy = userId
                };

                recommendationEntity.Projections = recommendation
                                                   .Projections
                                                   .Select(x => new RecommendationProjection(hash)
                {
                    ClientId   = product.ClientId,
                    ScenarioId = product.ScenarioId,

                    Week                     = x.Week,
                    Discount                 = x.Discount,
                    Price                    = x.Price,
                    Quantity                 = x.Quantity,
                    Revenue                  = x.Revenue,
                    Stock                    = x.Stock,
                    MarkdownCost             = x.MarkdownCost,
                    AccumulatedMarkdownCount = x.AccumulatedMarkdownCount,
                    MarkdownCount            = x.MarkdownCount,
                    Elasticity               = x.Elasticity,
                    Decay                    = x.Decay,
                    MarkdownTypeId           = (int)x.MarkdownType,

                    Recommendation = recommendationEntity
                })
                                                   .ToList();

                results.Add(recommendationEntity);
            }

            return(results);
        }
Пример #6
0
        private async Task <VmRecommendation> Revise(int clientId, SmRecommendationProductSummary product, List <VmScenarioRevision> revisions)
        {
            var constraints = revisions
                              .Take(1)
                              .Concat(revisions.Zip(revisions.Skip(1), (first, second) => second.Week > first.Week && second.Discount > first.Discount ? second : null))
                              .Where(x => x != null)
                              .Select(x => SmWeekConstraint.Fixed(x.Week, (decimal)x.Discount))
                              .ToList();

            if (!constraints.Any())
            {
                throw new HttpStatusCodeException(HttpStatusCode.BadRequest, "No markdowns in the revision model data");
            }

            var scenarioSummary = await _scenarioWebService.Get(clientId, product.ScenarioId);

            if (scenarioSummary == null)
            {
                throw new HttpStatusCodeException(HttpStatusCode.InternalServerError,
                                                  $"Missing scenario for client id ${product.ClientId} with scenario id ${product.ScenarioId}");
            }

            var weeks = Enumerable.Range(scenarioSummary.Scenario.ScheduleWeekMin, scenarioSummary.Scenario.ScheduleWeekMax - scenarioSummary.Scenario.ScheduleWeekMin + 1).ToList();

            if (constraints.Select(x => x.Week).Except(weeks).Any())
            {
                throw new HttpStatusCodeException(HttpStatusCode.BadRequest, "All revision weeks must be within [ScheduleWeekMin..ScheduleWeekMax]");
            }

            var settings = MarkdownFunctionSettings.FromWebApiConfiguration(product.ModelId, 100,
                                                                            product.ScenarioId, _organisationDataProvider.OrganisationId.Value,
                                                                            _organisationDataProvider.UserId.Value, product.PartitionNumber,
                                                                            product.PartitionCount);

            var modelData = await _scenarioService.GetModelData(settings);

            var scenarioData = await _scenarioService.GetScenarioData(settings, settings.PartitionId);

            var productData = scenarioData.Item2.FirstOrDefault(x => x.ProductId == product.ProductId);

            if (productData == null)
            {
                throw new HttpStatusCodeException(HttpStatusCode.InternalServerError, "Missing original product by id " + product.ProductId);
            }

            var revisionValues = revisions.Select(x => (decimal)x.Discount).ToList();

            var constraintValues = constraints
                                   .Select(x => x.Min)
                                   .Concat(constraints.Select(x => x.Max))
                                   .Distinct()
                                   .Where(x => x != null)
                                   .Select(x => (decimal)x)
                                   .ToList();

            if (constraintValues.Except(productData.PriceLadder.Values).Any())
            {
                throw new HttpStatusCodeException(HttpStatusCode.BadRequest, "All revision discounts must be price ladder values");
            }

            var modelId = product.ModelId;

            var revisionId = product.RevisionCount + 1;

            // Caculate the mask passed in
            var revisionMask = weeks
                               .Select((x, i) => new { Week = x, Index = i })
                               .Where(item => constraints.Any(x => x.Week == item.Week))
                               .Aggregate(0, (current, item) => current | 1 << item.Index);

            var schedules = new List <SmDenseSchedule>
            {
                SmDenseSchedule.FromInteger(revisionMask, weeks.First(), weeks.Count, constraints)
            };

            // Calculate
            var result = _markdownService.Calculate(scenarioSummary.Scenario, modelId, revisionId, schedules,
                                                    modelData.DecayHierarchies, modelData.ElasticityHierarchies, productData, revisionValues);

            // Upload
            await _scenarioResultsService.Upload(settings, product, revisionId, result.Recommendations, _organisationDataProvider.UserId.Value);

            // Update state and retrieve
            var finalResult = await _recommendationProductService.Revise(

                clientId : product.ClientId,
                scenarioId : product.ScenarioId,
                productId : product.ProductId);

            return(VmRecommendation.Build(finalResult));
        }
Пример #7
0
        public async Task <SmRecommendationProductSummary> GetRecommendationByScenarioAndProductId(int clientId, int scenarioId, int productId)
        {
            var result = await _recommendationProductSummaryRepository.GetByScenarioAndProductId(clientId, scenarioId, productId);

            return(result == null ? null : SmRecommendationProductSummary.Build(result));
        }
Пример #8
0
        public async Task <SmRecommendationProductSummary> GetRecommendationByGuid(int clientId, Guid guid)
        {
            var result = await _recommendationProductSummaryRepository.GetByRecommendationGuid(clientId, guid);

            return(result == null ? null : SmRecommendationProductSummary.Build(result));
        }