I would like to see if a feature exists that would allow an admin to apply discounts on orders under certain circumstances. I currently have a need for a "10% off orders over $200" type of feature. If such a feature exists, please direct me in the right direction.
Otherwise, if I were to spec the metadata for such a module out, I would start with:
Name: [string] (e.g. "10% Off Orders Over $200 Today Only!")
Deduction: [float] (e.g. "10.000")
Type: [enum] {"percent"|"deduct amt"} (e.g. "percent")
Price From: [float] (e.g. 200)
Price To: [float] (e.g. -1)
Start Date: [int] (e.g. 1122335173)
End Date: [int] (e.g. 1122421573)
Applies To: [enum] {"products"|"order totals"|"categories"} (e.g. "order totals")
Exclusivity:[enum] {"always apply discount"|"only apply first discount"} (e.g. "always apply discount")
Weight: [int] (specifies what order to apply multiple qualifying discounts. e.g. 10)
This notion was adapted from ZenCart's SaleMaker feature. This would cover my needs, as well as add flat-rate discounts and product-, category- and order total-specific discounts. This would need more concrete definition to be useful, but it's what I could think of off the top of my head. If anyone has ideas to contribute, I'm very interested to hear them.
Thanks.
| Comment | File | Size | Author |
|---|---|---|---|
| #15 | discount.mysql | 517 bytes | javanaut |
| #14 | discount.module | 17.15 KB | javanaut |
Comments
Comment #1
matt westgate commentedThe ecommerce package currently doesn't have a discount system this robust. We can apply role based discounts on all products, but that's about it.
Two things that will be helpful in this pursuit is the new checkoutapi and the product_adujst_price() function.
Comment #2
javanaut commentedThanks for the info. I saw references to the checkout api in CVS, but not in the 4.6 release.
A few question:
Is the CVS version of the ecommerce module currently drupal 4.6.x compatible?
Do you have any idea when the checkout api will be finished/stable (if it's not already)?
Does this fit into the bigger ecommerce module picture in a way that you see as useful?
Thanks again!
Comment #3
matt westgate commentedNope. I've added some Ajax functionality and the ecommerce HEAD update.php script only works with well, HEAD.
The checkout api is finished and was built to allow the very thing you want to do: inject content/forms into the checkout process.
Discounts? Very much so. I'd love the system to be abstract enough to allow admins to define 'discount rules', sort of how some email client filter systems work. For example, I'd like to yank the user roles discounts currently ecommerce core and have them become another set of discount rules. I took this approach with the new tax module I committed to HEAD (although it could still be improved).
Comment #4
javanaut commentedI thought of two more ideas for this module:
1. Provide a list of required product types to be purchased as a group.
e.g. "10% off all orders when you purchase a lamp with a chair"
2. Indicating the discount on the cart page. This could be made generic for price adjustments. Basically, it would add info to the cart page indicating which discounts were applied, what they were applied to, and how. This would render differently for Product discounts as opposed to Gross Purchase Price discounts and Category discounts, etc.
..and to incorporate the role-based discounts, if the person editing the discount has "administer users" priviledge (would this be necessary?), offer a list of roles that the discount applies to.
Just some thoughts.
Comment #5
javanaut commentedI've started work on this as a 4.6 module. I have a heavily customized 4.6 ecommerce setup, but I'm hoping that at least the discount.module should remain..well..modular. I also intend to keep its functionality abstracted enough to easily transition to the checkoutapi, etc that the latest ecommerce version is using.
Comment #6
javanaut commentedSeeking advice..
I've compiled the basics of the module, but the longer I work on it, the greater the complexity grows.
I have the "order total"-based filter implemented such that discounts are applied to the order total (as opposed to an individual product's price or applying to products in a specific category). For auditing purposes, I feel the need to store the results of applying the discounts along with the transaction. Additionally, I'd like to store shipping costs there as well. Would it make sense to organize all of these price adjustments into a common format?
Here's an example of what I'm talking about:
Would it make sense to store all of this data with the transaction in the same way that products (items) are currently stored? This would allow you to reconstruct historical orders after shipping costs and/or discounts have changed. Is there a preference whether this would be serialized data vs. independent db tables?
Currently, the ec_store_transaction_product table looks like:
Should this be expanded to include more generic order details such as those mentioned above? This could tie into the price adjustment api, too. In my current implementation, I've created a separate table that holds minimal discount details associated with a transaction, but I see a pattern here that could be made more general-purpose.
(btw, apologies if my illustrations look wonky. The 'preview' option here on drupal.org doesn't appear to be working today.)
Comment #7
moshe weitzman commentedOh, the complexities of ecommerce. I work for an e-tailer, and we have lots of these columns. For each item, we store the original price ("list price") and price is the price which was actually paid. I agree that it is essential to preserve this information. How else can you learn if your discount programs are contributing positively? You will also need a 'promotions' table where you store things like "qty > 1 save 20%". The ID of this promotion should also appear on the item record.
These sorts of columns beg for reporting, so serialized columns are not an option IMO. I see 2 options:
1. new tables joined by item ID and txnID
2. expect admins to simply add columns to the order and item tables. The transaction code should automatically store and load any data which is in the transaction object where a corrosponding DB column is found. See user_load() and user_save() for insiration. This is a great, seldom used feature of the user.module
Stay away from order level discounts as long as they can. They have to be allocated to each line for tax purposes and thats not fun.
Comment #8
javanaut commentedThanks for the input. Unfortunately, the only real promotion/discount that I need for the site I'm working on is order-based, not product-based. Also, for my purposes, I'm sending orders off to another existing backend system for fulfillment/processing and only using Drupal's e-commerce modules as a frontend. Somebody else is handling tax allocation ;)
As for logging transaction details, option 1 seems like the more flexible arrangement. That way, store.module can develop a transaction API for loading/saving transactions. The discount module could implement a hook that would store extra transaction details in a separate table. This would mean that
store_transaction_save($edit)could call something likemodule_invoke_all('store_transactionapi', 'update', $edit);andmodule_invoke_all('store_transactionapi', 'insert', $edit);Loading transactions could involve the invocation of something like
$data['extra_details'] = module_invoke_all('store_transactionapi', 'load', $txnid);I basically have code in all of those locations persisting the discount data, but I think this could be made much more generic with something like this. I do have concerns of how this would impact other parts of the ecommerce modules. For instance, I've had to rewrite the cart/view pages (as well as the block) to accommodate these details. Also, I wonder how useful it would be given the transaction array's current structure - with products as items, shipping_cost, etc. all being pre-defined elements. There would be a lot of things rewritten to use this.
For instance, calculating the total would involve all of these plus the items array.
items + product adjustments + order adjustments + tax + shipping = total
I could see creative vendors wanting other means of adjusting prices, and this could document those adjustments.
In my mind at least, this seems like the way to go. I just know that I don't have enough time (or background knowledge) to rewrite all of the pieces of the ecommerce modules to utilize the reorganized data structure. Also, I haven't looked at cvs/4.7 lately, so something like this might be irrelevant for that.
Comment #9
moshe weitzman commentedwould be nice if mathias chimed in here. i think javanaut's proposal is reasonable ... i certainly know that any e-tailer worth her salt wants to persist all discount info.
Comment #10
MrMattles commentedI believe the discount module is a very handy module, there is a very handy contrib for oscommerce that allows you to set various dicount coupons to "All" "some categories" "some products" etc
It is useful because you can create various and varied coupons to assist in promotions to targeted markets.
Perhaps this is something to consider.
Comment #11
javanaut commentedThat's where I'm heading with the module. For reference, here's what a discount currently looks like on my dev site:
Additionally, making this Discount node a member of a particular category will restrict the application of this discount to that category. This allows you to filter the application of discounts based on date range, taxonomy and price. The discount can be applied to product price or order total. Giving a weight to the discount sets the order in which multiple discounts are applied, and the exclusivity parameter allows you the option of only applying the first matching discount.
I think this would cover a lot of circumstances. The only one that I haven't yet given a lot of attention to is the per-product discount. I don't think that would be too dificult to implement, though.
Unfortunately for me, my client seems to be reluctant to pay for the ecommerce site that would be using this module. I'm therefore losing motivation to continue development on it. I will post the current working version of the module and a patch of all required ecommerce module changes against the latest 4.6 branch soon.
Comment #12
MrMattles commentedI would love to help out but I am not a programmer, would be willing to give it a go, no sense in throwing away good work.
So will this module work by having the Shopper enter a "Coupon" Number????
Comment #13
syllance commentedwould be interested to look at this :)
i'm currently working on ecommerce to implement other features (pre-orders and per product user roles inheritance), but wouldn't mind seeing your discount module features added at the same time :)
so let me know if i can help in any way.
Comment #14
javanaut commentedThis is only the module, and not any of the required ec module changes required to use it. I haven't fully documented it, either, but I suppose it'll have to do for now. I'd like to put together a patch with all of the minimum changes required to use it, too. That'll come later.
Comment #15
javanaut commenteddb schema
Comment #16
syllance commentedthanks for posting the module. i suspect i'll need this kind of things in the near future, so i'll have a look at it :)
Comment #17
afool commentedI am very interested in the module, which make the discount easy for extention.
Any patch could be release as you mentioned above?
Comment #18
sym commentedWhat is the status of this?
Thanks
Comment #19
gordon commentedI have taken a look at it, and it does need a lot of work.
firstly a discount should not be a node, the configurations of the discounts need to only be edited in the admin like admin > store > settings > discount
This should be using the checkoutapi() which will allow you to add additional fields and manipulate the transaction while the user is moving through the checkout.
Comment #20
simeWe are not supporting 4.6 now. Please re-open if any problems.
4.7 this should be done with flexicharge ;-)