I was told that this version is too simple, that need something more complex. I added Entity Framework.
Here my code:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace SalesTaxes
{
public class ShoppingCartContext : DbContext
{
public DbSet<ShoppingCart> Carts { get; set; }
public DbSet<ShoppingCartItem> Items { get; set; }
public DbSet<Product> Products { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var db = new ShoppingCartContext())
{
var basket = 0;
Console.WriteLine("Please enter basket number: 1, 2 or 3:");
try
{
basket = Int32.Parse(Console.ReadLine());
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
var cart = new ShoppingCart(GetItemsList(basket));
cart.Name = "Basket #" + basket.ToString();
db.Carts.Add(cart);
db.SaveChanges();
cart.PrintReceipt(basket);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
private static List<ShoppingCartItem> GetItemsList(int basket)
{
switch (basket)
{
case 1:
return new List<ShoppingCartItem>
{
new ShoppingCartItem(new Product( "Book", 12.49m, Product.ProductType.Book, false), 1),
new ShoppingCartItem(new Product("music CD", 14.99m, Product.ProductType.Other, false), 1),
new ShoppingCartItem(new Product("chocolate bar", 0.85m, Product.ProductType.Food, false), 1)
};
case 2:
return new List<ShoppingCartItem>
{
new ShoppingCartItem(new Product("imported box of chocolates", 10.00m, Product.ProductType.Food, true), 1),
new ShoppingCartItem(new Product("imported bottle of perfume", 47.50m, Product.ProductType.Other, true), 1)
};
case 3:
return new List<ShoppingCartItem>
{
new ShoppingCartItem(new Product("imported bottle of perfume", 27.99m, Product.ProductType.Other, true), 1),
new ShoppingCartItem(new Product("bottle of perfume", 18.99m, Product.ProductType.Other, false), 1),
new ShoppingCartItem(new Product("packet of headache pills", 9.75m, Product.ProductType.Medical, false), 1),
new ShoppingCartItem(new Product("box of imported chocolates", 11.25m, Product.ProductType.Food, true), 1),
};
default:
return new List<ShoppingCartItem>();
}
}
}
public class ShoppingCart
{
public ShoppingCart(List<ShoppingCartItem> items)
{
Items = items;
TotalTax = Items.Sum(x => x.Taxes);
Total = Items.Sum(x => x.Price) + TotalTax;
}
[Key]
public int CartID { get; set; }
public string Name { get; set; }
public virtual IList<ShoppingCartItem> Items { get; set; }
public decimal TotalTax { get; set; }
public decimal Total { get; set; }
public void PrintReceipt(int basket)
{
Console.WriteLine("Receipt {0}", basket);
foreach (var item in Items)
{
Console.WriteLine("{0} {1}: ${2} ", item.Quantity, item.Item.Name, item.Price + item.Taxes);
}
Console.WriteLine("Total Taxes: ${0} ", TotalTax);
Console.WriteLine("Total: ${0} ", Total);
}
}
public class ShoppingCartItem
{
const decimal TaxRate = 0.1m;
const decimal ImpTaxRate = 0.05m;
public ShoppingCartItem(Product product,int quantity)
{
Item = product;
Quantity = quantity;
Price = Quantity * Item.Price;
Taxes = Quantity*Math.Round(Item.Price * (CalculateTaxRate() + CalculateImportRate()), 2);
}
[Key]
public int ItemID { get; set; }
public virtual Product Item { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Taxes { get; set; }
private decimal CalculateTaxRate()
{
return Item.IsExempt
? 0
: TaxRate;
}
private decimal CalculateImportRate()
{
return Item.IsImport
? ImpTaxRate
: 0;
}
}
public class Product
{
public Product(string name, decimal price, ProductType type, bool isimport)
{
Name = name;
Price = price;
Type = type;
IsImport = isimport;
IsExempt = (Type != ProductType.Other);
}
public enum ProductType
{
Food = 1,
Book = 2,
Medical = 3,
Other = 4
};
[Key]
public int ProductID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public ProductType Type { get; set; }
public bool IsImport { get; set; }
public bool IsExempt { get; set; }
}
}
I need also Unit Testing, but I'm not sure, because I almost don't have methods here.
But anyway this is my try:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SalesTaxes;
namespace UnitTests
{
[TestClass]
public class SalestaxesUnitTest
{
[TestMethod]
public void TestProduct1()
{
var product1 = new Product("Book", 12.49m,Product.ProductType.Book, false);
var item1 = new ShoppingCartItem(product1, 1);
var actual = item1.Taxes;
decimal expected = 0.00m;
Assert.AreEqual(expected, actual, "Should be zero taxes");
}
[TestMethod]
public void TestProduct2()
{
var product1 = new Product("music CD", 14.99m, Product.ProductType.Other,false);
var item1 = new ShoppingCartItem(product1, 1);
var actual = item1.Taxes;
decimal expected = 1.5m;
Assert.AreEqual(expected, actual, "Wrong taxes");
}
[TestMethod]
public void TestProduct3()
{
var product1 = new Product("imported box of chocolates", 10.00m, Product.ProductType.Food, true);
var item1 = new ShoppingCartItem(product1, 1);
var actual = item1.Taxes;
decimal expected = 0.50m;
Assert.AreEqual(expected, actual, "Wrong taxes");
}
[TestMethod]
public void TestProduct4()
{
var product1 = new Product("imported bottle of perfume", 47.50m, Product.ProductType.Other, true);
var item1 = new ShoppingCartItem(product1, 1);
var actual = item1.Taxes;
decimal expected = 7.12m;
Assert.AreEqual(expected, actual, "Wrong taxes");
}
}
}
Maybe I need to use MOQ Framework for Unit Testing, but not sure how it can be used in this case.