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)); }
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); }
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); }
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)); }
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)); }
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); }
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()); }
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); }