Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the final price of each product within a List<T>?

The goal

Calculate the final price of each product within a List<T> of C#.

The problem

I need to calculate price * quantity of a simple product and return the result to the view.

Look this syntax:

var productPrice = productsPrices.Find(x => x.productId == 1); 
productPrice.finalProductPrice = 
    (productPrice.promotionalProductPrice != 0 ? 
        productPrice.promotionalProductPrice : 
        productPrice.originalProductPrice) 
    * sessionProducts.Find(x => x.id == 1).quantity;

Just before of code fragment passed above, there is a string that stores the ids of the products, see:

string ids = string.Join(", ", sessionProducts.Select(x => x.id));

And I think that I need it to set a value to finalProductPrice of each product of my productsPrices list, but I don't know how I can perform this.

What I thought about this subject:

I had thought that I could use something like this:

productsPrices.Find(x => x.productId == productsPrices.Contains(ids))
    .finalProductPrice = 
    (productsPrices.Find(x => productsPrices.Contains(ids))
        .promotionalProductPrice != 0 ?
    productsPrices.Find(x => productsPrices.Contains(ids))
        .promotionalProductPrice : 
    productsPrices.Find(x => productsPrices.Contains(ids))
        .originalProductPrice) *
    sessionProducts.Find(x => x.id == 1).quantity;

But, of course, no success — .Contains() doesn't work with strings.

My real question

How can I define the right finalProductPrice for each product that my productsPrices list has? How can I pass each id within string ids [...] to x.productId == something?

Hints will be welcome (E.g. don't use .Find(), use .Select() instead!)

Spotlight code

Follow my ActionResult that sends all the necessary information to my view:

Compare.cs:

public ActionResult Compare()
{
    List<getMarkets_Result> markets = Markets.Build();

    SessionStore sessionStore = new SessionStore();
    List<getSpecificProductToShoppingList_Result> sessionProducts = 
        sessionStore.Get("ProductsSummary", "generic");

    string ids = string.Join(", ", sessionProducts.Select(x => x.id));
    List<getProductsPrices_Result> productsPrices = Products.PricesList(ids);

    ListComparisonViewModel listComparisonViewModel = 
       new ListComparisonViewModel
    {
        Markets = markets,
        SessionProducts = sessionStore.Get("ProductsSummary", "generic"),
        ProductsPrices = productsPrices
    };

    return View(listComparisonViewModel);
}

If necessary, the context of my productsPrice list:

public partial class getProductsPrices_Result
{
    public decimal originalProductPrice { get; set; }
    public decimal promotionalProductPrice { get; set; }
    public decimal finalProductPrice { get; set; }
    public string productName { get; set; }
    public string marketName { get; set; }
    public int productId { get; set; }
    public int marketId { get; set; }
}

And I made a model called Products(.cs) to perform the logic behind of the products. The first (and single) method that this model has is CalculateFinalPrice():

public decimal CalculateProductPriceByQuantity(decimal price, int quantity)
{
    return price * quantity;
}
like image 286
Guilherme Oderdenge Avatar asked Nov 12 '22 00:11

Guilherme Oderdenge


1 Answers

I think you should conciser creating a model that represents your data in a way that will make your business problem easier to solve. In other words, make the code work to solve you solution.

Firstly the product should not know about the quantity. Assuming this works like a cart, the product should only know about itself. So the implementation of finalProductPrice should be much easier:

public decimal finalProductPrice 
{
    get 
    {
        return (promotionalProductPrice != 0 ? 
            promotionalProductPrice : 
            originalProductPrice);
    }
}

When working with your products, create a class and contain them in that to calculate the quality and total price:

public class ProductCollection
{
    public IEnumerable<getProductsPrices_Result> Products { get; set; }
    public int Quantity { get { return Products.Count; } }
    public decimal TotalPrice 
    {
        get
        {
            return Products.Sum(p => p.finalProductPrice );
        }
    }
    public ProductCollection(IEnumerable<getProductsPrices_Result> products)
    {
        this.Products = products;
    }
}

Now your viewmodel can look something like this:

ListComparisonViewModel
{
    Markets = markets,
    Products = new ProductCollection(sessionStore.Get("ProductsSummary", "generic"))
};

One important note I would like to make here is this helps to reduce your session access surface area. Session can be "accessed by anyone" and thus can become discombobulated and cause lots of issues down the road. In almost all scenarios fewer hands in the session cookie jar the better. (fewer keys as well as fewer class types and instances)

like image 101
Jay Avatar answered Nov 14 '22 22:11

Jay