Пример #1
0
        public SmCalcProduct(SmScenario scenario, int modelId, SmProduct product, List <SmDenseSchedule> schedules, SmDepth depth)
        {
            ClientId      = scenario.OrganisationId;
            ModelId       = modelId;
            ScenarioId    = scenario.ScenarioId;
            ProductId     = product.ProductId;
            ProductName   = product.Name;
            PriceLadderId = product.PriceLadder.PriceLadderId;

            Recommendations = new List <SmCalcRecommendation>();

            HierarchyId   = product.HierarchyId;
            HierarchyName = product.HierarchyName;

            ScheduleCount                  = schedules.Count;
            ScheduleCrossProductCount      = 0;
            ScheduleProductMaskFilterCount = 0;
            ScheduleMaxMarkdownFilterCount = 0;
            ScheduleExceededFlowlineThresholdFilterCount = 0;

            HighPredictionCount      = 0;
            NegativeRevenueCount     = 0;
            InvalidMarkdownTypeCount = 0;
            MinimumAbsolutePriceChangeNotMetCount           = 0;
            MinimumRelativePercentagePriceChangeNotMetCount = 0;
            DiscountPercentageOutsideAllowedRangeCount      = 0;

            CurrentMarkdownCount = product.CurrentMarkdownCount;
            CurrentMarkdownType  = product.CurrentMarkdownType;
            CurrentSellingPrice  = product.CurrentSellingPrice;
            OriginalSellingPrice = product.OriginalSellingPrice;
            CurrentCostPrice     = product.CurrentCostPrice;
            CurrentStock         = product.CurrentStock;
            CurrentSalesQuantity = product.CurrentSalesQuantity;

            SellThroughTarget = product.SellThrough;

            SalesFlexFactor = product.SalesFlexFactor;

            MarkdownTypeConstraint               = product.MarkdownTypeConstraint;
            MinimumAbsolutePriceChange           = product.MinimumAbsolutePriceChange;
            MinimumRelativePercentagePriceChange = product.MinimumRelativePercentagePriceChange;
            MinDiscountsNew     = product.MinDiscountsNew;
            MinDiscountsFurther = product.MinDiscountsFurther;
            MaxDiscountsNew     = product.MaxDiscountsNew;
            MaxDiscountsFurther = product.MaxDiscountsFurther;

            CurrentMarkdownDepth       = depth.MarkdownDepth;
            CurrentDiscountLadderDepth = depth.DiscountLadderDepth;

            State         = ProductState.Fatal;
            DecisionState = scenario.DefaultDecisionState;
        }
Пример #2
0
        // TODO return errors here to SmCalcProduct
        public static SmProduct Build(ILogger logger, Product entity, List <ProductHierarchy> productHierarchies,
                                      List <ProductPriceLadder> productPriceLadders, List <SmPriceLadder> priceLadders,
                                      Dictionary <int, decimal> hierarchySellThrough, Dictionary <int, Tuple <int, decimal> > productSalesTax,
                                      List <ProductParameterValues> productParameterValues, List <ProductMarkdownConstraint> productMarkdownConstraint,
                                      List <ProductSalesFlexFactor> salesFlexFactor, List <ProductMinimumAbsolutePriceChange> productMinimumAbsolutePriceChange,
                                      List <ProductWeekParameterValues> productWeekParameterValues, List <ProductWeekMarkdownTypeParameterValues> productWeekMarkdownTypeParameterValues)
        {
            if (entity == null)
            {
                return(null);
            }

            try
            {
                // TODO support multiple hierarchies
                var hierarchy = productHierarchies.FirstOrDefault(x => x.ProductId == entity.ProductId);
                if (hierarchy == null)
                {
                    logger.Error("Product {ProductId} is missing a ProductHierarchy entry", entity.ProductId);
                    return(null);
                }

                // TODO support multiple price ladders
                var priceLadderId = productPriceLadders.Where(x => x.ProductId == entity.ProductId)
                                    .Select(x => x.PriceLadderId).FirstOrDefault();
                if (priceLadderId == 0)
                {
                    logger.Error("Product {ProductId} is missing a ProductPriceLadder entry", entity.ProductId);
                    return(null);
                }

                var ladder = priceLadders.FirstOrDefault(x => x.PriceLadderId == priceLadderId);
                if (ladder == null)
                {
                    logger.Error("PriceLadders is missing price ladder {PriceLadderId} for product {ProductId}",
                                 priceLadderId, entity.ProductId);
                    return(null);
                }

                var parameterValues = productParameterValues.FirstOrDefault(x => x.ProductId == entity.ProductId);

                var markdownTypeConstraints = productMarkdownConstraint.Where(x => x.ProductId == entity.ProductId)
                                              .GroupBy(x => new { x.ProductId, x.Week, x.MarkdownTypeId })
                                              .OrderBy(y => y.Key.Week)
                                              .Select(y => y.Key.MarkdownTypeId)
                                              .ToArray();

                var flexFactors = salesFlexFactor
                                  .Where(x => x.ProductId == entity.ProductId)
                                  .OrderBy(x => x.Week)
                                  .Select(x => x.FlexFactor)
                                  .ToArray();

                if (!flexFactors.Any())
                {
                    logger.Error("Product {ProductId} is missing a SalesFlexFactor entry", entity.ProductId);
                    return(null);
                }

                var minimumAbsolutePriceChange = productMinimumAbsolutePriceChange.FirstOrDefault(x => x.ProductId == entity.ProductId);

                var minimumRelativePercentagePriceChanges = productWeekParameterValues
                                                            .Where(x => x.ProductId == entity.ProductId)
                                                            .GroupBy(x => new { x.ProductId, x.Week, x.MinimumRelativePercentagePriceChange })
                                                            .OrderBy(y => y.Key.Week)
                                                            .Select(y => y.Key.MinimumRelativePercentagePriceChange)
                                                            .ToArray();

                var minDiscountsNew = productWeekMarkdownTypeParameterValues
                                      .Where(x => x.ProductId == entity.ProductId && x.MarkdownTypeId == MarkdownType.New)
                                      .GroupBy(x => new { x.ProductId, x.Week, x.MarkdownTypeId, x.MinDiscountPercentage })
                                      .OrderBy(y => y.Key.Week)
                                      .Select(y => y.Key.MinDiscountPercentage)
                                      .ToArray();

                var minDiscountsFurther = productWeekMarkdownTypeParameterValues
                                          .Where(x => x.ProductId == entity.ProductId && x.MarkdownTypeId == MarkdownType.Further)
                                          .GroupBy(x => new { x.ProductId, x.Week, x.MarkdownTypeId, x.MinDiscountPercentage })
                                          .OrderBy(y => y.Key.Week)
                                          .Select(y => y.Key.MinDiscountPercentage)
                                          .ToArray();

                var maxDiscountsNew = productWeekMarkdownTypeParameterValues
                                      .Where(x => x.ProductId == entity.ProductId && x.MarkdownTypeId == MarkdownType.New)
                                      .GroupBy(x => new { x.ProductId, x.Week, x.MarkdownTypeId, x.MaxDiscountPercentage })
                                      .OrderBy(y => y.Key.Week)
                                      .Select(y => y.Key.MaxDiscountPercentage)
                                      .ToArray();

                var maxDiscountsFurther = productWeekMarkdownTypeParameterValues
                                          .Where(x => x.ProductId == entity.ProductId && x.MarkdownTypeId == MarkdownType.Further)
                                          .GroupBy(x => new { x.ProductId, x.Week, x.MarkdownTypeId, x.MaxDiscountPercentage })
                                          .OrderBy(y => y.Key.Week)
                                          .Select(y => y.Key.MaxDiscountPercentage)
                                          .ToArray();

                var result = new SmProduct
                {
                    ProductId            = entity.ProductId,
                    CurrentCostPrice     = entity.CurrentCostPrice,
                    CurrentMarkdownCount = entity.CurrentMarkdownCount,
                    CurrentSalesQuantity = entity.CurrentSalesQuantity,
                    CurrentSellingPrice  = entity.CurrentSellingPrice,
                    CurrentStock         = entity.CurrentStock,
                    HierarchyId          = hierarchy.HierarchyId,
                    HierarchyPath        = hierarchy.HierarchyPath,
                    HierarchyName        = hierarchy.HierarchyName,
                    Name = entity.Name,
                    OriginalSellingPrice                 = entity.OriginalSellingPrice,
                    PriceLadder                          = SmProductPriceLadder.Build(ladder),
                    CurrentCover                         = entity.CurrentCover,
                    ProductScheduleMask                  = parameterValues?.Mask,
                    ProductMaxMarkdown                   = parameterValues?.MaxMarkdown,
                    SalesFlexFactor                      = flexFactors,
                    MarkdownTypeConstraint               = markdownTypeConstraints,
                    MinimumAbsolutePriceChange           = minimumAbsolutePriceChange.MinimumAbsolutePriceChange,
                    MinimumRelativePercentagePriceChange = minimumRelativePercentagePriceChanges,
                    MinDiscountsNew                      = minDiscountsNew,
                    MinDiscountsFurther                  = minDiscountsFurther,
                    MaxDiscountsNew                      = maxDiscountsNew,
                    MaxDiscountsFurther                  = maxDiscountsFurther,
                    CurrentMarkdownType                  = entity.CurrentMarkdownType,
                    ProductHasExceededFlowlineThreshold  = parameterValues.HasExceededFlowlineThreshold
                };

                if (productSalesTax.TryGetValue(entity.ProductId, out Tuple <int, decimal> salesTax))
                {
                    result.SalesTax = salesTax;
                }

                if (hierarchySellThrough.TryGetValue(hierarchy.HierarchyId, out decimal sellThrough))
                {
                    result.SellThrough = sellThrough;
                }

                return(result);
            }
            catch (Exception e)
            {
                logger.Error(e, "There was an error building product {ProductId} from partition {PartitionNumber}",
                             entity.ProductId, entity.PartitionNumber);
                throw;
            }
        }