SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Multiple pricing information for shopping cart

    I'm not sure how to handle this one. I need to allow products in my shopping cart to display one of three different levels of pricing depending on user level. The first is open to the public, the last two will involve wholesaler accounts. I'm trying to figure out the best way to allow this to happen without cramming a million ifs in my code.

    I currently have a shopping Cart object that contains many Items which each contain a single Product + quantity of that product. Where would the most logical place be to specify which price to use? Should each product have all three prices, and delegate the job of displaying the correct price to other code? Or should the actual price for each product be calculated at instantiation?

  2. #2
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could make a 'getUserPrice(User $user)' function on your individual 'Product' row objects that would return the price for that user.

  3. #3
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That works... I was thinking a getter for each price or the price being calculated when the product is instantiated, but I like your idea better

  4. #4
    SitePoint Evangelist
    Join Date
    Mar 2006
    Location
    Sweden
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Or, if you want to remove the pricing logic from the cart, since that might get complex over time:
    PHP Code:
    <?php
    $pricestrategy 
    = new CartPricingStrategy($user);
    $cart = new Cart($pricestrategy);
    // This call gets forwarded to CartPricingStrategy
    $price $cart->getPrice();
    ?>
    That way, the Cart doesn't care how CartPricingStrategy calculates the price, if the user object is involved or any other objects for that matter.

  5. #5
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by wysiwyg View Post
    Or, if you want to remove the pricing logic from the cart, since that might get complex over time:
    PHP Code:
    <?php
    $pricestrategy 
    = new CartPricingStrategy($user);
    $cart = new Cart($pricestrategy);
    // This call gets forwarded to CartPricingStrategy
    $price $cart->getPrice();
    ?>
    That way, the Cart doesn't care how CartPricingStrategy calculates the price, if the user object is involved or any other objects for that matter.
    Well, I also have the prices being viewed in several different non-cart places, so I think keeping the pricing logic within the Product class makes sense. If there was a nonstandard way of calculating price within the cart (ie, discounts), though, I'd agree with you.

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It can be a good idea to move the price calculations up on the cart level, since you may easily get pricing rules that isn't tied to a particular product. For example "get 3 for the price of 2" etc. If it bothers you that it's called CartPricingStrategy, you could rebrand it to something more generic like PricingStrategy.

  7. #7
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    Adding to the question really, lets say the final price also was influenced by :

    Currency (Euros, Dollars and exchange rates)
    Delivery costs
    (I like the thought of "3 for 2" deals too)

    Does this make it more important the Price belongs to the PriceStrategy, or is delivery cost pushed to the final stage of the transaction?

  8. #8
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    It can be a good idea to move the price calculations up on the cart level, since you may easily get pricing rules that isn't tied to a particular product. For example "get 3 for the price of 2" etc.
    That's actually a good point. You could then allow custom configurable pricing rules (ala Magento) and complex discount structures. It could be setup like:

    PHP Code:
    // Setup cart with user object (for registrations, etc)
    $cart = new Cart(User $user);
    $product = new Product(124);

    // Use cart to return the price
    $productPrice $cart->getProductPrice(Product $product); 
    That way the cart and user info could be used for calculation of the final price. That would allow you to do all kinds of nifty things with the price like quantity range table rates and multi-product combo prices, etc. You could also use the cart user info for customer loyalty discounts, your wholesaler requirements, etc. Opens up the possibility for some neat stuff.

  9. #9
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,194
    Mentioned
    17 Post(s)
    Tagged
    5 Thread(s)
    Using the cart to apply the transformation seems like the best approach.

    Czaries example is on the money.
    The only code I hate more than my own is everyone else's.

  10. #10
    Spirit Coder allspiritseve's Avatar
    Join Date
    Dec 2002
    Location
    Ann Arbor, MI (USA)
    Posts
    648
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    It can be a good idea to move the price calculations up on the cart level, since you may easily get pricing rules that isn't tied to a particular product. For example "get 3 for the price of 2" etc.
    Well, I do have discount strategy objects that apply to the cart as a whole. I need to display the product price in several places before it's in the cart though, so I need a way to get the correct price--- czaries' original post seemed to do that easily. Then from the correct price, the cart can calculate 3 for 2 discounts or whatever.

    Quote Originally Posted by Cups View Post
    Adding to the question really, lets say the final price also was influenced by: Currency (Euros, Dollars and exchange rates
    That would add a whole new spin on things. Maybe I need some sort of strategy object that can be used both in the cart and outside the cart to determine a product's correct price. Something like this?

    PHP Code:
    $pricingStrategy = new PricingStragegy($user$currency);
    $price $product->getPrice($pricingStrategy); 
    Quote Originally Posted by Cups View Post
    Delivery costs
    Already doing that in the cart.

    Quote Originally Posted by Czaries View Post
    That's actually a good point. You could then allow custom configurable pricing rules (ala Magento) and complex discount structures... That way the cart and user info could be used for calculation of the final price. That would allow you to do all kinds of nifty things with the price like quantity range table rates and multi-product combo prices, etc. You could also use the cart user info for customer loyalty discounts, your wholesaler requirements, etc. Opens up the possibility for some neat stuff.
    That seems weird to me to ask the cart for the price of a product. I guess I'd prefer some strategy object that took care of individual product prices, and then the cart can determine cart totals, discounts, etc.

  11. #11
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by allspiritseve View Post
    That seems weird to me to ask the cart for the price of a product. I guess I'd prefer some strategy object that took care of individual product prices, and then the cart can determine cart totals, discounts, etc.
    Yes, I was thinking about this last night. If you're just rendering a customer specific mailshot or more likely, a page with their pricing on, it would seem a little strange to ask a cart for a price.

    Much like dragging your shopping to a till in just to find out 'your' price for something.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  12. #12
    <?php while(!sleep()){code();} G.Schuster's Avatar
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    428
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just think of real life.
    A "cart" is a dumb object storage where you put products (objects) in.
    A price is an attribute of your product (object).
    So whom should you ask for the price?

    The same applies to delivery cost and rebate calculation - it's not really the "cart" that handles those - it's at the checkout (or the collector/cashpoint in real life).

    Transferring virtual problems into real life examples makes it easier to find solutions on where to place what logic - as the virtual environments mostly descend from the real world.

  13. #13
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by G.Schuster View Post
    A price is an attribute of your product (object).
    So whom should you ask for the price?
    Is the price 'really' an attribute of a product though, sure it has a relationship, but I don't see how the product should need to know it's own price.

    What about...

    PHP Code:
    <?php
    $oPricingStategy 
    = new PricingStrategy(new User(5), new Currency('GBP'));
    $iPrice $oPricingStategy->getPriceForProduct(new Product(56));
    ?>
    This makes more sense to me, thoughts?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  14. #14
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by G.Schuster View Post
    Just think of real life.
    I'm not sure the "think of objects as metaphors for real world phenomena" always works out (Although it's a fine rule of thumb). Abstract and concrete are not absolute sizes; They form a continuum.

    In any case, "price" is a fairly intangible concept. It may be an attribute of a product, but then it might not. It really depends on how you wish to define the concept. Maybe you have two different types of prices, a unit-price and a contextual-price. The first could be an attribute of the product, and one that you could list in a catalogue. The former is the actual price, in the context of a sale. The latter would probably be based on the former.

  15. #15
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by G.Schuster View Post
    Just think of real life.
    What if the shopping cart was one of those self-scanning carts though, or if the shopper held a scanner?

    In effect each cart/shopper brings its own total to the checkout.

    Just an observation on how this real life object has evolved, thats all, bending the metaphor a bit.

    Like that cart/shopper though, the store devolves some responsibility to the cart/shopper, but may need to apply further checks and balances for the sake of integrity.

    The store can delegate tasks, but not responsibility (eurggh, my retail background surfacing again).

  16. #16
    PHP/Rails Developer Czaries's Avatar
    Join Date
    May 2004
    Location
    Central USA
    Posts
    806
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by G.Schuster View Post
    Just think of real life.
    A "cart" is a dumb object storage where you put products (objects) in.
    A price is an attribute of your product (object).
    So whom should you ask for the price?
    Real life situations can't always be applied clearly to your code. And is a price really an attribute of the product? The same exact product could be sitting on a shelf in the store next door, 20 feet away, and have a different price.

    The price depends on the context, not the product. A candy bar at a large retailer may be $0.49, but at a convenience store the same candy bar is $1.00. The price could also depend on other things you buy at the same time, like "3 for $1.00 or $0.49 each". It would be impossible for the product to know it's own price without having more information. Clearly, you can't always ask the product itself for it's price.

    I ask the cart for the price, because that is the context of where the other products are that you are also going to buy. It's more convenient to put the price calculations there, because it knows the context. In real life we have checkout stands, but it may not always be that way, and that's not really the best way to do it anyways. RFID tags on every product in the future may enable some scanning system to scan the cart for all the products in it to calculate a total price and you just swipe a card, replacing checkout stands as we know them today.

    My method may not be "the best", but it works and it's easy to follow. If it makes you feel better about your code, you can add a "Checkout" class that accepts the "Cart" as a constructor parameter that will calculate the final price and can return individual product prices too, fully calculated with tax, shipping, discounts, etc. That would be closer to the way it works in real life instead of adding some abstract pricing strategy middle layer.


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •