示例#1
0
        public void Clone_NonEmptyContainer_ReturnsContainerWithSameUnits()
        {
            // Arrange
            var        mockDelegate = CreateMockDelegate();
            IDimension mass         = CreateStubDimension("M");
            IUnit      g            = CreateStubUnit("g", mass);
            IUnit      kg           = CreateStubUnit("kg", mass);
            IUnit      lbs          = CreateStubUnit("lbs", mass);

            DimensionContainer original = new DimensionContainer(mass, mockDelegate.Object.Create);

            original.SetBaseUnit(g);
            original.AddUnit(g, kg);
            original.AddUnit(g, lbs);

            // Act
            DimensionContainer cloned = (DimensionContainer)original.Clone();

            // Assert
            Assert.AreSame(original.BaseUnit, cloned.BaseUnit);
            CollectionAssert.AreEquivalent(original.Units, cloned.Units);
            Assert.True(cloned.CanConvert(g, kg));
            Assert.True(cloned.CanConvert(g, lbs));
            Assert.True(cloned.CanConvert(kg, lbs));
        }
示例#2
0
        public void AddUnit_BaseunitNotRegistred_ThrowsNullReferenceException()
        {
            // Arrange
            var                mockDelegate = CreateMockDelegate();
            IDimension         dimension    = CreateStubDimension("M");
            IUnit              baseunit     = CreateStubUnit("g", dimension);
            IUnit              scaledunit   = CreateStubUnit("kg", dimension);
            DimensionContainer container    = new DimensionContainer(dimension, mockDelegate.Object.Create);

            // Act/Assert
            Assert.Throws <NullReferenceException>(() => container.AddUnit(baseunit, scaledunit));
        }
        public static decimal CalculateProfitMargin(DimensionContainer dimensionContainer, FeeCategory feeCategory, decimal lowestPrice, decimal purchasePrice, Func <decimal, decimal> funcShippingCost = null)
        {
            if (lowestPrice <= 0)
            {
                throw new InvalidOperationException("lowestPrice must be greater than 0.");
            }

            decimal breakEvenPrice = CalculateBreakEven(dimensionContainer, feeCategory, purchasePrice, funcShippingCost);

            decimal feePercentage = GetCategoryFee(feeCategory);

            return((((lowestPrice - breakEvenPrice) * (1 - feePercentage)) - (c_returnPercentage * lowestPrice)) / lowestPrice);
        }
示例#4
0
        public void Clone_EmptyContainer_ReturnsEmptyContainer()
        {
            // Arrange
            var                mockDelegate = CreateMockDelegate();
            IDimension         dimension    = CreateStubDimension();
            DimensionContainer original     = new DimensionContainer(dimension, mockDelegate.Object.Create);

            // Act
            DimensionContainer cloned = (DimensionContainer)original.Clone();

            // Assert
            Assert.NotNull(cloned);
            Assert.AreSame(original.Dimension, cloned.Dimension);
        }
示例#5
0
        public void AddUnit_DimensionMismatch_ThrowsArgumentException()
        {
            // Arrange
            var                mockDelegate = new Mock <ICreateAdjacentValueConverterDelegateFunctor>();
            IDimension         mass         = CreateStubDimension("M");
            IDimension         length       = CreateStubDimension("L");
            IUnit              kg           = CreateStubUnit("kg", mass);
            IUnit              m            = CreateStubUnit("m", length);
            DimensionContainer container    = new DimensionContainer(mass, mockDelegate.Object.Create);

            container.SetBaseUnit(kg);

            // Act/Assert
            Assert.Throws <ArgumentException>(() => container.AddUnit(kg, m));
        }
        public static decimal CalculateBreakEven(DimensionContainer dimensionContainer, FeeCategory feeCategory, decimal purchasePrice, Func <decimal, decimal> funcShippingcost = null)
        {
            List <decimal> dimensions = new List <decimal>
            {
                dimensionContainer.Length,
                dimensionContainer.Width,
                dimensionContainer.Height,
            }
            .OrderByDescending(o => o)
            .ToList();

            decimal weight = dimensionContainer.Weight;

            decimal longestSide  = dimensions[0];
            decimal medianSide   = dimensions[1];
            decimal shortestSide = dimensions[2];

            ProductSizeTier productSizeTier = GetProductSize(longestSide, medianSide, shortestSide, weight);

            // Shipping Cost to Amazon (estimate) = 0.72 * max(0.25, product weight)
            decimal estimateShippingCostToAmazon = funcShippingcost != null
                                ? funcShippingcost.Invoke(weight)
                                : c_costPerPoundToShip *Math.Max(0.25m, weight);

            // Cost to get to AMZN = Base Price + Shipping Cost to Amazon (estimate)
            decimal costToGetToAmazon = purchasePrice + estimateShippingCostToAmazon;

            // Average Storage Fee = 1.2 * (Width/12) * (Length/12) * (Height/12)
            // TODO: Update storage fee cost to update starting 3/1/2016: http://www.amazon.com/gp/help/customer/display.html?nodeId=201648210
            decimal averageStorageFee = 1.2m * (longestSide / 12) * (medianSide / 12) * (shortestSide / 12);

            // Need to use the Outbound Shipping Weight for calculating the weight fee.

            decimal dimensionalWeight = CalculateDimensionalWeight(longestSide, medianSide, shortestSide);

            decimal outboundShippingWeight = CalculateOutboundShippingWeight(weight, dimensionalWeight, productSizeTier);

            // Size Fee => Multiply flat fee * ProductSizeTier
            decimal sizeFee = GetSizeFee(productSizeTier);

            decimal weightFee = GetWeightFee(productSizeTier, outboundShippingWeight);

            decimal feeCategoryPercentage = GetCategoryFee(feeCategory);

            // TODO: Implement the Zero Fee Fulfillment. Which applies to Small Standard-Size and Large Standard-Size. Price > $300, means no fulfillment fees.
            // Break Even Price = (Cost to get to AMZN + Average Storage Fee + Size Fee + Weight Fee) / (1 - Category Fee Pct)
            return((costToGetToAmazon + averageStorageFee + sizeFee + weightFee) / (1 - feeCategoryPercentage));
        }
示例#7
0
        public ActionResult EvaluateCalculate(ProductProfitabilityRequest productProfitabilityRequest)
        {
            if (productProfitabilityRequest.CostPerPoundToShip.HasValue && productProfitabilityRequest.FlatCostToShip.HasValue)
            {
                throw new InvalidOperationException("Cannot have both a CostPerPoundToShip and FlatCostToShip");
            }

            Func <decimal, decimal> funcShippingCost = null;

            if (productProfitabilityRequest.CostPerPoundToShip.HasValue)
            {
                funcShippingCost = weight => weight * productProfitabilityRequest.CostPerPoundToShip.Value;
            }
            else if (productProfitabilityRequest.FlatCostToShip.HasValue)
            {
                funcShippingCost = weight => productProfitabilityRequest.FlatCostToShip.Value;
            }

            DimensionContainer dimensionContainer = new DimensionContainer(
                productProfitabilityRequest.Length,
                productProfitabilityRequest.Width,
                productProfitabilityRequest.Height,
                productProfitabilityRequest.Weight);

            decimal profitMargin = FeeStructureUtility.CalculateProfitMargin(
                dimensionContainer,
                productProfitabilityRequest.FeeCategory,
                productProfitabilityRequest.LowestPrice,
                productProfitabilityRequest.PurchasePrice,
                funcShippingCost);

            decimal breakEven = FeeStructureUtility.CalculateBreakEven(
                dimensionContainer,
                productProfitabilityRequest.FeeCategory,
                productProfitabilityRequest.PurchasePrice,
                funcShippingCost);

            ProductProfitabilityResponse productProfitabilityViewModel = new ProductProfitabilityResponse
            {
                BreakEvenPrice = breakEven,
                ProfitMargin   = profitMargin
            };

            return(Json(productProfitabilityViewModel));
        }
示例#8
0
        public void CreateConverter_BaseUnitToDirectAnchestor_CallsCreateConverterOnce()
        {
            // Arrange
            var        mockDelegate = CreateMockDelegate();
            IDimension mass         = CreateStubDimension("M");
            IUnit      kg           = CreateStubUnit("kg", mass);
            IUnit      lbs          = CreateStubUnit("lbs", mass);

            DimensionContainer container = new DimensionContainer(mass, mockDelegate.Object.Create);

            container.SetBaseUnit(kg);
            container.AddUnit(kg, lbs);

            // Act
            IValueConverter converter = container.CreateConverter(kg, lbs);

            // Assert
            mockDelegate.Verify(x => x.Create(kg, lbs), Times.Once());
            Assert.NotNull(converter);
        }
示例#9
0
        public void CreateConverter_UnitToAnchestor_CallsCreateConverterTwice()
        {
            // Arrange
            var        mockDelegate = CreateMockDelegate();
            IDimension mass         = CreateStubDimension("M");
            IUnit      g            = CreateStubUnit("g", mass);
            IUnit      kg           = CreateStubUnit("kg", mass);
            IUnit      lbs          = CreateStubUnit("lbs", mass);

            DimensionContainer container = new DimensionContainer(mass, mockDelegate.Object.Create);

            container.SetBaseUnit(g);
            container.AddUnit(g, kg);
            container.AddUnit(kg, lbs);

            // Act
            IValueConverter converter = container.CreateConverter(kg, lbs);

            // Assert
            mockDelegate.Verify(x => x.Create(It.IsAny <IUnit>(), It.IsAny <IUnit>()), Times.Exactly(1));
            Assert.NotNull(converter);
        }
 private static void Main()
 {
     var dimensionContainer = new DimensionContainer();
     var canGroup           = dimensionContainer.CanBeGroupedWith(new NotADimensionContainer());
 }
示例#11
0
        public void EvaluatePriceList(PriceListFile priceListFile)
        {
            DataTable dt = ExcelUtility.ConvertExcelFileToDataTable(priceListFile.File);

            List <ManufacturerPriceListRowInput> manufacturerPriceListRowsInputs = dt.FromDataTableToList <ManufacturerPriceListRowInput>();

            // Price is always required.
            if (manufacturerPriceListRowsInputs.Any(a => !a.Price.HasValue))
            {
                throw new ArgumentException("Price must be set for all rows.");
            }

            // Need either UPC or ASIN.
            if (manufacturerPriceListRowsInputs.Any(a => a.ASIN == null && a.UPC == null))
            {
                throw new ArgumentException("ASIN or UPC must be set for all rows.");
            }

            List <ManufacturerPriceListRowOutput> manufacturerPriceListRowsOutputs = new List <ManufacturerPriceListRowOutput>();

            // Only lookup rows where either ASIN or UPC is set.
            foreach (ManufacturerPriceListRowInput manufacturerPriceListRow in manufacturerPriceListRowsInputs
                     .Where(w => !w.ASIN.IsNullOrEmptyTrimmed() || !w.UPC.IsNullOrEmptyTrimmed()))
            {
                LookupProductRequest lookupProductRequest = new LookupProductRequest
                {
                    SearchIndex   = priceListFile.SearchIndex,
                    ResponseGroup = ResponseGroup.Medium
                };

                if (manufacturerPriceListRow.ASIN != null)
                {
                    lookupProductRequest.IdType = IdType.ASIN;
                    lookupProductRequest.ItemId = manufacturerPriceListRow.ASIN;
                }
                else
                {
                    lookupProductRequest.IdType = IdType.UPC;
                    lookupProductRequest.ItemId = manufacturerPriceListRow.UPC;
                }

                LookupProductResponse lookupProductResponse = m_productAdvertisingApi.LookupProduct(lookupProductRequest);

                if (lookupProductResponse != null)
                {
                    Product product = lookupProductResponse.Product;

                    Listing listing = m_amazonApiClient.GetAllListingsForAsin(new[] { product.ASIN }).FirstOrDefault();

                    decimal?breakEven           = null;
                    decimal?profitMargin        = null;
                    decimal?lowestPrice         = null;
                    string  sellersRankCategory = null;

                    if (listing != null)
                    {
                        lowestPrice         = listing.LowestPrice;
                        sellersRankCategory = listing.SellersRankCategory;
                    }

                    if (product.Length.HasValue && product.Width.HasValue && product.Height.HasValue && product.Weight.HasValue)
                    {
                        DimensionContainer dimensionContainer = new DimensionContainer(
                            product.Length.Value,
                            product.Width.Value,
                            product.Height.Value,
                            product.Weight.Value);

                        breakEven = FeeStructureUtility.CalculateBreakEven(
                            dimensionContainer,
                            priceListFile.FeeCategory,
                            manufacturerPriceListRow.Price.Value);

                        if (lowestPrice.HasValue && lowestPrice.Value > 0)
                        {
                            profitMargin = FeeStructureUtility.CalculateProfitMargin(
                                dimensionContainer,
                                priceListFile.FeeCategory,
                                lowestPrice.Value,
                                manufacturerPriceListRow.Price.Value);
                        }
                    }

                    ManufacturerPriceListRowOutput manufacturerPriceListRowOutput = new ManufacturerPriceListRowOutput
                    {
                        ASIN                = product.ASIN,
                        UPC                 = manufacturerPriceListRow.UPC,
                        ProductName         = product.Name,
                        SellersRank         = lookupProductResponse.ProductMetadata.SalesRank,
                        SellersRankCategory = sellersRankCategory,
                        Category            = lookupProductResponse.ProductMetadata.ProductGroup,
                        Price               = manufacturerPriceListRow.Price.Value,
                        BreakEven           = breakEven.HasValue
                                                        ? breakEven.Value.ToString("F", CultureInfo.InvariantCulture)
                                                        : null,
                        LowestPrice = lowestPrice.HasValue
                                                        ? lowestPrice.Value.ToString("F", CultureInfo.InvariantCulture)
                                                        : null,
                        ProfitMargin = profitMargin.HasValue
                                                        ? string.Format("{0:0.00%}", profitMargin.Value)
                                                        : null
                    };

                    manufacturerPriceListRowsOutputs.Add(manufacturerPriceListRowOutput);
                }
            }

            ExcelUtility.WriteExcelFileToResponse(Response, manufacturerPriceListRowsOutputs, c_worksheetName, priceListFile.File.FileName);
        }