Page 1 of 2
Shopping Cart Design
Posted: Tue Feb 27, 2007 2:59 pm
by kendall
Hey guys...I'm having a application design issue for which i need your adivce on...
I have built a very simple shopping cart system that uses ajax to simply add an item's id, name and price to an array in a class held in a session.
After doing this the client now wants to have a situation that allows for "incremental discounts" to be added to the total price in the cart based on the # of items the person chooses. thus a subscriber choosing up 3 items get 3% while choosing 5 mite be 7%.
My question is...given the situation...
1. Should I implement this discount feature as part of my generic logic for the shopping cart system?
2. Should i custom taylor something further down the payment system to cater for this.?
3. Should I apply this discount before hand before adding the item(s) to the cart?(this would require doing a hack that would have nothing to do with the cart or payment system already implemented)
I'm reluctant to make adjustments to the cart system as if there arised another instance where i might need to use the same cart system I'd be in a jam...
However , I could make and implementation in my cart system to allow for managin discounts so whether or not there is a situation that presents it self for using discount or not the system can adjust without have to do hacks...
What do you think is the best approach?
Kemdall
Posted: Tue Feb 27, 2007 3:10 pm
by Begby
If this cart is class based its just a matter of modifying the getTotal() cart method to count the number of items in the cart and return the discounted price.
I would say #3 is least desireable, you would need to radjust the price of everything in the cart every time you add an item, it would be better do adjust the price of the while viewing the cart or getting the total.
How is your cart setup? Is it all in ajax?
Also, passing the price from ajax into a session isn't a good idea if you are doing it that way, you should just be passing a productID of some sort along with a quantity and have the server side code look up the price, otherwise someone could easily send their own prices into your cart.
Posted: Tue Feb 27, 2007 3:22 pm
by kendall
Begby,
ok...i see your point...but my mind begins racing...as it is he's putting discount on one particular item (pants)...but now he comes and adds shoes to his list of things he wants to sell...and the shoes has nothing to do with discount...how do i handle that?
How is your cart setup? Is it all in ajax?
yeah im using ajax/ php
Also, passing the price from ajax into a session isn't a good idea if you are doing it that way
I didnt even realise the severity of it...see...I don't really have a products table as everything was spread out thus...different items are in different tables (This is not the normal ecommerce mall merchandise thing...i didnt see it coming) so my shopping cart would not have known where to look to get the price of whatever is beeing given to it.
What should i do there....build a product table and do some sort of reference right...sigh (and the drama begins)?
Posted: Tue Feb 27, 2007 3:29 pm
by Christopher
You want to do #1 and #2, the question is how?
Posted: Tue Feb 27, 2007 3:34 pm
by Begby
Well you could just have a table server side with product ID, price, and type. Then get the price and type and see if you need to apply a discount. Its kind of hackish but would work.
I would write this as one products table all server side with methods accessible by ajax, like a method to get a product list, methods to add/remove/edit items in the cart, and then methods to get the cart items and a total price. It wouldn't be all that difficult to calculate discounts in PHP if you had all the types, prices, and quantities in front of you in an array.
Posted: Tue Feb 27, 2007 11:41 pm
by Christopher
Begby wrote:Well you could just have a table server side with product ID, price, and type. Then get the price and type and see if you need to apply a discount. Its kind of hackish but would work.
Except for discounts that are not based on type, like discounts for members, or for discount codes, or for a date range, etc. You need a plug-in mechanism for you subtotal/total/grandtotal calculation system so you can add discounts into the system in a clean way.
Posted: Wed Feb 28, 2007 8:13 am
by kendall
Arboint,
Except for discounts that are not based on type, like discounts for members, or for discount codes, or for a date range, etc. You need a plug-in mechanism for you subtotal/total/grandtotal calculation system so you can add discounts into the system in a clean way.
I like how that sounds...
personally I find that the shopping cart and check out system should not have the responsiblity of dealing with "discounts" calculation and should be done before hand. All it really shud be doing is keeping inventory of products and total cash calculations...
I think doe that ill will probably try to make adjustments so that my shopping cart can cater for making discount calculations
its sounds wierd reading this...wierd

Posted: Wed Feb 28, 2007 8:23 am
by Begby
The shopping cart or checkout must be responsible for discounts and such if the discounts are based on quantities. You cannot have a product discount itself if it requires knowledge of the other items in the cart.
Posted: Wed Feb 28, 2007 8:30 am
by kendall
Begby wrote:The shopping cart or checkout must be responsible for discounts and such if the discounts are based on quantities. You cannot have a product discount itself if it requires knowledge of the other items in the cart.
VALID POINT...I stand corrected!
Posted: Wed Feb 28, 2007 12:07 pm
by Christopher
The thing about discounts is that there is not just one kind. There are discounts on single SKUs, discounts on product categories, discounts on the grand total, discounts only on orders over a certain amount, and on and on. I have plugins at both the item total calculation and cart total calculation points.
Posted: Wed Feb 28, 2007 12:15 pm
by kendall
Arborint,
hmmm...So you used plugins at both points? interesting...how has it easy has it been trying to adapt...I think its a bit pains taking. Right now I am trying to alter my "check-out" system just to accommodate this little issue. I am not altering the code per-say...but i am trying to separate the general code and specific code so as to keep a standard code to be re-used somewhere else later on...isn't going to well doe it must say.
Kendall
Posted: Wed Feb 28, 2007 12:25 pm
by Christopher
They are really just plug-in commands, so if you wanted to add a discount to a sku it might look something like this:
Code: Select all
class SkuDiscount {
function SkuDiscount($sku, $discount) {
$this->sku = $sku;
$this->discount= $discount;
}
function run($item) {
if ($item->sku == $this->sku) {
$item->total += $item->price * $this->discount;
}
}
}
$item->addFilter(new SkuDiscount('ABC123', 0.15); // 15%
$item->addFilter(new SkuDiscount('XYZ321', 0.25); // 25%
Extending Shopping Cart class to customise shopping cart
Posted: Tue Mar 06, 2007 9:54 am
by kendall
Ok...
So i have really been hacking away at this thing trying to get an effective solution. and i came up with this
Code: Select all
class ShoppingCart {
var $sID;
var $owner;
var $items = array();
var $total = 0;
var $final_total = 0;
function ShoppingCart(){
$this->sID = time();
}
function add_item($item_id,$item_name=NULL,$price=0,$qty=1,$product_type){
$this->items[$item_id] = array("name"=>$item_name,"price"=>$price,"qty"=>$qty ,"type"=>$product_type);
}
function remove_item($item_id){
$items = array();
foreach($this->items as $id => $item){
if($id != $item_id)
$items[$id] = $item;
}
$this->items = $items;
}
function calculate_total(){
$total = 0;
foreach($this->items as $item)
$total = $total+($item['price']*$item['qty']);
$this->total = $total;
}
// calculate final total ...a discount extension needs to exist with a property of 'discount_total'
function calculate_final_total($add_discount = false){
$this->final_total = ($add_discount)? ($this->total - $this->$discount_total) : $this->total;
}
}
Code: Select all
class ShoppingCartDiscount extends ShoppingCart
{
var $percentage = 0;
var $discount_arr = array();
var $discount_total = 0;
function ShoppingCartDiscount($discount_percentage){
if(is_array($discount_precentage))
$this->$discount_arr = $discount_precentage;
else if(is_int($discount_percentage))
$this->$percentage = $discount_precentage;
}
function get_discount($price){
return $price * $this->percentage;
}
function set_percentage($discount){
$this->percentage = $discount/100;
}
/*
special function created for subscription discounts where the
discount is based on the # of subscription being purchased.
the discount range affects # items total that can be discounted.
*/
function calculate_subscription_discount($discount_range){
$total_price = 0;
$no_subscriptions = 0;
foreach($this->items as $item){
if(($item['type'] == 'subscriptions') && ($no_subscriptions < $discount_range)){
$no_subscriptions++;
$total_price += $item['price'];
}
}
// discount is worked out by no of items
if(array_key_exists($no_subscriptons,$discount_arr)){
$this->set_percentage($discount_arr[$no_subscriptions]);
}
return $this->discount_total = $this->get_discount($total_price);
}
}
It means now that i can now use my shopping cart class over and over and if i want to do anything with discounts to extend the class
What do you think?
Posted: Tue Mar 06, 2007 10:08 am
by Begby
I think you are on the right track, couple of things though.
A base class that is used on its own, should not require any knowledge of the classes that extend it. For instance your calculate total method is looking for a discount total. Your code will need to know if should pass true or false to that method when calculating the total.
Lets say you use shopping cart in a site without discounts, and all over in that code, like in 30 places, you call calculate_final_total. Now the customer wants you to use discounts, so now you need to find all 30 places and add in true.
The proper way to do it would be to override calculate_final_total in the discounted cart. That way if the customer changes his mind all you have to do is change your code so that the discounted cart us used and not have to worry about passing true or false to calculate_final_total.
Posted: Tue Mar 06, 2007 10:13 am
by kendall
The proper way to do it would be to override calculate_final_total in the discounted cart. That way if the customer changes his mind all you have to do is change your code so that the discounted cart us used and not have to worry about passing true or false to calculate_final_total.
So you can overwrite a function from the original class in the extended one?
would you believe me if i said i was just asking that same question?
thanks...
im not to good with OOP