PrestaShop Forum

The best place in the world to ask questions about PrestaShop and get advice from our passionate community!

PrestaShop Forum

Jump to content

 

Newbie looking for item count/quantity discount add-on

37 replies to this topic
#1
dgf15215

    PrestaShop Newbie

  • Members
  • Pip
  • 14 posts
I am attempting to use PrestaShop to sell items that offer a discount based on the cumulative number of items ordered and am looking for an add-on that will continually show in the shopping cart the number of items in the cart and the discount that the user is entitled to based on that quantity. So if you were to order three boxes of item "X" the cart would show a message that you're entitled to a 0% discount on three items but if you added any two more items you would be entitled to a 5% discount on everything. If anyone is interested in developing an add-on like this I'd love to talk to you.

#2
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
I am interested in this. I do some programming work, so I probably will start to look at it. Our needs here are very simple, probably only a certain % discount for either a certain number of items or a total order over a certain amount. I think we will also have to have a way to indicate that a given product is exempt from both counting against the "discount quantity count/amount" as well as having the discount applied to it. Beyond that, I don't think we need much.

If you had thoughts about what kind of parameters you might need, I can at least consider them before I start work. I'm not promising anything, but if I am going to look into it, I might as well see if I can help others as well.

#3
vezy

    PrestaShop Apprentice

  • Members
  • PipPip
  • 113 posts
Hi guys,
I'm really interested in this possible feature too. I've tried to implement it using coupon codes that the client would have to manually enter into cart. What is missing to be able to do this is a possibility to define the number of products per coupon. I don't know much about coding so I won't be able to help, but it seems to me that you would just need to duplicate the function that defines the cart 'amount' but change it to 'quantity' in the 'discounts' file. Could be a quick first solution.

What you're looking to do is a good step ahead of this - if you manage to implement it, I'm sure you'll have many a user.
Quantity discounts is really a function that every shopping cart should be able to offer.

Good luck and hope all goes well. Look forward to some news on this topic.
Happy to be on board !

http://www.maedupandco.com
(Adieu WP ecommerce et Hello Prestashop!! Yihaaa! Goodbye WPecommerce and Hello Prestashop!! Yupee!! )

#4
dgf15215

    PrestaShop Newbie

  • Members
  • Pip
  • 14 posts
It is a moments like these that I so regret not having paid attention in French Class during my college years. It doesn't even bother me when I'm actually in France because so many of you speak English, but when clicking on your web site and seeing such beautiful items and then not having a clue what they are . . . well, that's payback for my lack of attention.

I have located someone who believes that they can fairly quickly add a feature to a shopping cart that will apply an across the board discount to all items in the cart based on the total number of items ordered which is exactly what I want. More importantly, what I need the modification to do is constantly update each line item in the sales cart to reflect the current discounted price and to prompt the buyer to achieve a greater discount on all items by adding "x" number of items to the order.

I will certainly let the community know how this works out and when the site is up and active demonstrate it.

Vezy, is Maedup & Co. a physical store? I'm asking because my wife and I will be in Southern France this late summer.

Don Friedman
Pittsburgh, PA USA

#5
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
A very quick pass at this, because it's all that our needs dictate, but eventually they may change and I'd have to round this out a bit more.

I created a discount/voucher "10PCTOFFQ20PLUS" which is a 10% off voucher.

Then, a few simple mods to /cart.php:

At the top, I modified the existing code where it loops through to validate the discounts. First, a global flag to see if the discount is in the cart already. We'll need that later.

And, since we do not want to ever invalidate this discount code no matter how many times it's used, I also skip the checkDiscountValidity() check on this particular code. However, other code still checks and won't apply the discount/voucher if the quantities are exhausted, so I'll set it to some extremely large value and then create some cron job or something to reset it daily and make sure it is kept in-stock. This seems odd that every discount has to have a fixed number of uses.


$globalQtyDiscount = false;
$cartDiscounts = $cart->getDiscounts();
foreach ($cartDiscounts AS $k => $cartDiscount) {
if ($cartDiscount['name'] == "10PCTOFFQ20PLUS") {
$globalQtyDiscount = true;
} else {
if ($error = $cart->checkDiscountValidity(new Discount(intval($cartDiscount['id_discount'])), $cartDiscounts, $orderTotal, $cart->getProducts()))
$cart->deleteDiscount(intval($cartDiscount['id_discount']));
}
}


Then, down later in the file, right ABOVE this block:


if (!sizeof($errors))
{
$queryString = Tools::safeOutput(Tools::getValue('query', NULL));
if ($queryString AND !Configuration::get('PS_CART_REDIRECT'))
Tools::redirect('search.php?search='.$queryString);
if (isset($_SERVER['HTTP_REFERER']))
{
// Redirect to previous page
preg_match('!http(s?)://(.*)/(.*)!', $_SERVER['HTTP_REFERER'], $regs);
if (isset($regs[3]) AND !Configuration::get('PS_CART_REDIRECT') AND Tools::getValue('ajax') != 'true')
Tools::redirect($regs[3]);
}
}


(incidentally, I don't know why this is a separate if() test of the same condition the above block is, must be leftover from when this wasn't the case.)

Insert this code above that block:


// For some reason, the cart functions that return quantity are off here, becuase after the
// just-executed add/delete it isn't going to the database, it's using a class internal counter
// which has not been updated yet. The Cart::update() will force this internal counter to be
// invalid so that the calls to getNbProducts() will re-query the database. Strange.
$cart->update();
$globalQtyDiscountID = intval(Discount::getIdByName('10PCTOFFQ20PLUS'));
if ($globalQtyDiscount) {
// Test by global product count - in the future we may have to walk through the list
// so we can count our own, excluding certain products if necessary from the qty tally
if (Cart::getNbProducts(intval($cart->id)) < 20) {
$cart->deleteDiscount($globalQtyDiscountID);
}
} elseif (Cart::getNbProducts(intval($cart->id)) >= 20) {
$cart->addDiscount($globalQtyDiscountID);
}


Ideally, a module would be written to manage the name of the Discount and the QTY where the breakpoint is, it wouldn't be hard-coded in here. But for now, this at least is functional, and in our case we probably won't be changing it.

I suppose that module could also implement the 'cart' hook to display a message on the cart about the "Only XX more items to get 10% discount!" message. Right now we aren't interested in that either, so it isn't implemented.

This isn't terribly well tested, I just did a test order and it seems to flow from front to back as it should. Since it is such a simple implementation, it won't appeal to many, but if anyone can use it, I thought I'd put it out here.

-Steve

#6
vezy

    PrestaShop Apprentice

  • Members
  • PipPip
  • 113 posts
Thanks for sharing - !
Happy to be on board !

http://www.maedupandco.com
(Adieu WP ecommerce et Hello Prestashop!! Yihaaa! Goodbye WPecommerce and Hello Prestashop!! Yupee!! )

#7
nzrobert

    PrestaShop Apprentice

  • Members
  • PipPip
  • 76 posts

From 1265982839:

It is a moments like these that I so regret not having paid attention in French Class during my college years.


HAHA.... So true!

#8
nzrobert

    PrestaShop Apprentice

  • Members
  • PipPip
  • 76 posts
Heya Steve,

Thanks for sharing!

From 1266598069:

so I'll set it to some extremely large value and then create some cron job or something to reset it daily and make sure it is kept in-stock.


Will this need to happen for this discount to code to stay valid? Is there anyway of just creating a discount code which can be used indefinately?

Also will this code be applied automatically or will we need to (as a customer) enter this as a code?

Cheers
Robert

#9
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
I don't see any way to have Prestashop allow a voucher code with unlimited use. I wish they did. :) So I set it to a very high value, like 999999999 and will have to do some magic to keep that number from running out. If anyone knows of a way to have a voucher that isn't limited, I'd love to know about it, if it is there I've missed it.

The modification I posed adds or removes the discount automatically as they adjust the cart quantity above/below the number you specify in the program code.

As an aside, I am working on an extension of this so it only considers products in a certain category toward the discount and only calculates the discount based on those products. By default I am using a category named the same as the discount/voucher code. And I am building a simple module so that you can supply this code, as well as the quantity break point where the discount is added/removed. These changes may be a little while before I put it out here, because I have a very busy schedule coming up here in the next few weeks, but I will get it up when I can.

I also wished I could do this via a hook function instead of modifying core code... I know there is a hook for the cart, I may also try to see if that would let me do all I need to do so that no core code modifications are needed. But that, again, will take more time.

#10
nzrobert

    PrestaShop Apprentice

  • Members
  • PipPip
  • 76 posts
Awesome Job Steve.. Works a charm!

#11
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
Okay, here is a first-pass at a module version. This does NOT require any modifications to the /cart.php file, so you have to restore the original version of that file from your backup or from a fresh download of Prestashop if you previously modified it.

Let me know how this works for you, It is rather quick work and I have only tested it on my installation, but think it should work as well as the previous modifications.

-Steve

[UPDATED: Now includes text on product page if eligible for discount, as well as text in cart summary page to display how many more items must be purchased before discount is available.]

[UPDATED2: Now sets the quantity available on the discount back to an extremely high number when the cart is converted to an order, so it should never run out and doesn't need a separate process to keep it updated.]

[UPDATE v0.4: Case insensitive for category, voucher name, and name in module config]

Attached Files



#12
nzrobert

    PrestaShop Apprentice

  • Members
  • PipPip
  • 76 posts
Hi Steve,

What would i need to modify in the example you gave to have 2 discounts running?

For example i would like to give a 10% discount for customer who buy 2 items, 15% for 3 items and a max of 20% discount for those who buy more?

I have created 3 vouchers respectively.

#13
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
Right now it is a one-discount model only. The basic logic would extend out further, it becomes a question about how to manage them. I suppose you could have an arbitrary list of voucher codes and corresponding quantity breakpoints, and the text on the shopping cart page would "upsell" you to the next highest discount available.

I also am not sure how it scales using the category to flag eligible items. It makes sense for our one-discount model, and where all but a few items are eligible. I suppose you would probably also want a checkbox on a given discount to say that it is globally available and eliminate the need for a category at all.

The text on the product page "Eligible for discount" also would need to be re-thought if you had multiple levels, or maybe just an option to turn it off entirely and publish your discount program details separately.

The bad answer is, right now it won't support that, and it will be a little while before I could get around to extending it. Even though I have no personal use for that enhancement, I think it would be good for the community, and so if nobody else picks this up to run with it, I will take a look as time permits, but I can't make any short-term promises.

#14
nzrobert

    PrestaShop Apprentice

  • Members
  • PipPip
  • 76 posts
Hi Steve,

Thanks for your reply, i appreciate your time.

I was speaking more in relation to your post on Feb 19th.
I am currently not using the module.

Again i thoroughly appreciate the time you have spent creating this!

Cheers
Robet

#15
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
The module is doing the same thing that the previous /cart.php modifications did.

If you can program and you understand the code, it really should just be a matter of staggering the if statements to handle things appropriately for the various quantity breaks and discount codes.

Thinking out loud, if you had:


QTY CODE
2 10PCTOFF2PLUS
5 15PCTOFF5PLUS
10 20PCTOFF10PLUS


At the top code section, you'd probably have to change the code to check for all valid discount levels....


$QtyDiscount1 = false;
$QtyDiscount2 = false;
$QtyDiscount3 = false;
foreach ($cartDiscounts AS $k => $cartDiscount) {
if ($cartDiscount['name'] == "10PCTOFF2PLUS") $QtyDiscount1 = true;
if ($cartDiscount['name'] == "15PCTOFF5PLUS") $QtyDiscount2 = true;
if ($cartDiscount['name'] == "20PCTOFF10PLUS") $QtyDiscount3 = true;
if ($error = $cart->checkDiscountValidity(new Discount(intval($cartDiscount['id_discount'])), $cartDiscounts, $orderTotal, $cart->getProducts()))
$cart->deleteDiscount(intval($cartDiscount['id_discount']));
}


That sets the flag if any discount is being taken.

You would also have to change the globalQtyDiscountID variable to a variable for each voucher....


$QtyDiscountID1 = intval(Discount::getIdByName('10PCTOFF2PLUS'));
$QtyDiscountID2 = intval(Discount::getIdByName('15PCTOFF5PLUS'));
$QtyDiscountID3 = intval(Discount::getIdByName('20PCTOFF10PLUS'));


Finally, the "if" block has to deal with the staggered quantity levels....


$cartNbItems = Cart::getNbProducts(intval($cart->id));
// Remove old discounts that no longer apply
if ($QtyDiscount1 AND $cartNbItems < 2) {
$cart->deleteDiscount($QtyDiscountID1);
} elseif ($QtyDiscount2 AND $cartNbItems < 5) {
$cart->deleteDiscount($QtyDiscountID2);
} elseif ($QtyDiscount3 AND $cartNbItems < 10) {
$cart->deleteDiscount($QtyDiscountID3);
}

// Add new discounts as they might apply, remove lower level ones
if (!$QtyDiscount3 AND $cartNbItems >= 10) {
if ($QtyDiscount1) $cart->deleteDiscount($QtyDiscountID1);
if ($QtyDiscount2) $cart->deleteDiscount($QtyDiscountID2);
$cart->addDiscount($QtyDiscountID3);
} elseif (!$QtyDiscount2 AND $cartNbItems >= 5) {
if ($QtyDiscount1) $cart->deleteDiscount($QtyDiscountID1);
$cart->addDiscount($QtyDiscountID2);
} elseif (!$QtyDiscount1 AND $cartNbItems >= 2) {
$cart->addDiscount($QtyDiscountID1);
}


This is NOT tested, I just typed it in on the fly, so look it over and use with care, but I think it's the basic idea...

#16
tsmorton

    PrestaShop Newbie

  • Members
  • Pip
  • 10 posts
Steve,

Thanks for the mod, it is really needed, but I'm having a little trouble with it. Everything works good when the items are added to the cart, but when I click on the cart to view it my browser hangs saying there is a scripting issue. I have to go back into the admin panel and disable the mod to get the store to reload. When it does load there are about 50 "Discount" items in the cart made by the mod. Once all the real items are deleted then the multitude of discount items disappear.

Any ideas? I'm using the latest stable version, 1.2.5 I think.

#17
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
Are you using the latest version (v0.3) ? I don't know if I released a version that did it, but I know in testing I had called the cart refresh routine inside the module which was then re-calling the module and causing a problem like you describe. But I am not seeing that with the latest code I posted, it is working in our production 1.2.5 site.

Your problem is also strange, because if the discount item already exists it is not supposed to add another one.

And just to be clear, if you have downloaded the module version, you should not apply the changes in any of the posts above, that would cause definite problems.

#18
tsmorton

    PrestaShop Newbie

  • Members
  • Pip
  • 10 posts
Yes, it says "$this->version = '0.3';" on line #44

Also, I have not modified the code at all or implemented any of your previous changes.

I can send a screenshot of the multiple discounts if you wish.

Thanks

#19
SteveP

    PrestaShop Apprentice

  • Members
  • PipPip
  • 29 posts
I just did a fresh install of Prestashop 1.2.5 with a new database. I installed the module. I created the category 10PCTOFFQ20PLUS and put all the test store products into it. I also created a voucher with the same code "10PCTOFFQ20PLUS". I set it as a percentage discount, and cumulative with other vouchers and reductions with a initial quantity of 99999.

Everything seems to be working as it should. I don't know if it is a browser issue or not, I am on a Mac using Safari, but all of the code should be working on the server and PHP, not on the client.

Could it be a conflict with some other module you are using? What other non-standard modules might you have installed?

#20
tsmorton

    PrestaShop Newbie

  • Members
  • Pip
  • 10 posts
I don't have any other custom mods installed. The only difference I have with what you wrote is I didn't use the default name you have (10PCTOFFQ20PLUS). I called mine DOWNLOADS because the items are downloadable (catagory was already made), with a limit of 3. Also I didn't put 99999 as the quantity. Put 1000, I think.

I can't work on it any more tonight, but I'll recheck some things tomorrow and let you know.

Thanks.