Storing self-referencing application logic functions in Mongo and running them?

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
I'm making a web store in Meteor and I've got a collection called Discounts in MongoDB and each document contains info for a different discount / coupon code.

I came to realize that applying a discount code to someone's order isn't that straightforward - there needs to be a way to determine if the discount is valid or not, and it would be amazing if the ability to check validity was stored right in each separate discount object itself. There could be a huge range of different discounts, each with a different "rule" for determining validity, and it doesn't always make sense to store the rules separate from the discounts.

I want each discount object to contain a function that takes the customer's order form data (things like order date, total price, customer's email, etc) and checks it all to see if the conditions are valid for applying the coupon code.

If so, it'll return a discount. If not valid, it won't return any discount.

Code:
// if the customer's order contains RAM and is in 2015, they get $100 off
{
  sku: 'RAM-50-2015',
  discountAmount: -100,
  discountCode: 'SAVEONRAM'
  check: function(orderFormContents) {
    if (orderFormContents.ram && orderFormContents.year === 2015) {
      return this.discountAmount;
    } else {
      return "order not valid for this coupon"
    };
  }
}, {
  // If the customer's order is in Oct 2015 with at least $100 in total price, they get 20% off their order
  sku: 'OCT-2015-Promo',
  discountAmount: -0.20,
  discountCode: 'OCTSAVINGS',
  check: function(orderFormContents) {
    if (orderFormContents.totalPrice >= 100 && orderFormContents.month === 10 && orderFormContents.year === 2015) {
      return orderFormContents.totalPrice * this.discountAmount;
    } else {
      return "order not valid for this coupon"
    };
  },
}, {
  // If the customer has any credits in their account, they can be applied via a coupon code
  sku: 'CustomerCredit',
  discountAmount: function(email) {
    return db.Customers.findOne({
      email: email
    }).creditAmount;
  },
  discountCode: 'CUSTOMERCREDIT',
  check: function(orderFormContents) {
    var customerCredit = this.discountAmount(orderFormContents.customerInfo.email);
    if (customerCredit > 0) {
      return orderFormContents.totalPrice - customerCredit;
    } else {
      return "You have no credits in your account."
    };
  }
}

I know that Mongo is primarily a data store and should not be used for storing and calling functions for application logic:

http://docs.mongodb.org/manual/tutorial/store-javascript-function-on-server/

However, using system.js outlined in the docs above seems really, really cumbersome, especially since the functions won't be able to utilize this like in my examples above to reference the objects that they're currently inside.

I'm hoping that there's an easier way to store self-referencing functions inside objects and then run them when I need them?
 
Last edited:

DaveSimmons

Elite Member
Aug 12, 2001
40,730
670
126
Note that you still need some overall controlling logic to check for conflicts between the discounts, otherwise you might accept 10% off, 15% off and 20% off coupons for the same order. You might intended that all coupons expire separately then mess up and have overlapping date ranges.

If you use the self-contained logic by itself you could limit customers to one discount per order.
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
Note that you still need some overall controlling logic to check for conflicts between the discounts, otherwise you might accept 10% off, 15% off and 20% off coupons for the same order. You might intended that all coupons expire separately then mess up and have overlapping date ranges.

If you use the self-contained logic by itself you could limit customers to one discount per order.
Very good point.

Are there any patterns or ways I should be modeling a discount coupon system then? To have a combo of external checks and internal checks?
 

purbeast0

No Lifer
Sep 13, 2001
52,931
5,803
126
why not have a discount document in the mongo table and just have the discount on the order check if it exists in the db, and if it does, verify that it meets all conditions?

then just have a job on the server that runs daily that will expire coupons once the date passes when they are no longer valid?
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
why not have a discount document in the mongo table and just have the discount on the order check if it exists in the db, and if it does, verify that it meets all conditions?

then just have a job on the server that runs daily that will expire coupons once the date passes when they are no longer valid?
Would the conditions themselves be stored in the discount document itself as well?
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
This can be quite complicated IMO. Say that you were coding a backend system where a user can create a custom discount code with numerous custom conditions and discount amounts that could change based on which or how many conditions are fulfilled.

You have each individual condition, and then AND / OR, then you have the different formulas for calculating discounts depending on how the conditions get evaluated.
 

purbeast0

No Lifer
Sep 13, 2001
52,931
5,803
126
This can be quite complicated IMO. Say that you were coding a backend system where a user can create a custom discount code with numerous custom conditions and discount amounts that could change based on which or how many conditions are fulfilled.

You have each individual condition, and then AND / OR, then you have the different formulas for calculating discounts depending on how the conditions get evaluated.

still doesn't change the fact that you can store all of that in a discount document and have the conditions in there.

then just check if the conditions are met when the user goes to pay.

what the conditions are really irrelevant as long as you check against them when the user goes to checkout. if they match, apply the coupon. if they don't match, the coupon is invalid for the order.
 

Dissipate

Diamond Member
Jan 17, 2004
6,815
0
0
I used to work on a retail-based ERP system that had to support discounts based on promotion codes at checkout. The problem was that the business logic for these promo codes were constantly changing (e.g. if the customer checks out with a Coogi item on the 3rd Wednesday of the month, give them a 10% discount). We had a logic system to make the business logic more flexible, but it was still quite inflexible as to what conditions it would support.

It was actually after I left that job that I found out that what they needed was a rules engine. A rules engine is exactly what is good for this situation:
The expression of arbitrary, frequently changing business logic is a major source of complexity. Clara aims to rein in this complexity by untangling business logic, expressing it as composable rules while...

https://github.com/rbrush/clara-rules/wiki/Introduction

The rules engine Clara is written in Clojure, so you probably need something else. But it is a good example of what you should be looking for.

You add/remove rules on the fly, then just pass your data through the rules to see what matches. In your case, once your rules engine is set up, you wouldn't store actual code (which is a major security nightmare waiting to happen BTW), you would just store the simple rules, then load them into memory to check an order against at checkout.
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
I used to work on a retail-based ERP system that had to support discounts based on promotion codes at checkout. The problem was that the business logic for these promo codes were constantly changing (e.g. if the customer checks out with a Coogi item on the 3rd Wednesday of the month, give them a 10% discount). We had a logic system to make the business logic more flexible, but it was still quite inflexible as to what conditions it would support.

It was actually after I left that job that I found out that what they needed was a rules engine. A rules engine is exactly what is good for this situation:

https://github.com/rbrush/clara-rules/wiki/Introduction

The rules engine Clara is written in Clojure, so you probably need something else. But it is a good example of what you should be looking for.

You add/remove rules on the fly, then just pass your data through the rules to see what matches. In your case, once your rules engine is set up, you wouldn't store actual code (which is a major security nightmare waiting to happen BTW), you would just store the simple rules, then load them into memory to check an order against at checkout.
Ah, gotcha. I'll read up on it. I was initially thinking I needed to build up a Truth Table or something.

Rules Engine. Interesting...
 

fuzzybabybunny

Moderator<br>Digital & Video Cameras
Moderator
Jan 2, 2006
10,455
35
91
I used to work on a retail-based ERP system that had to support discounts based on promotion codes at checkout. The problem was that the business logic for these promo codes were constantly changing (e.g. if the customer checks out with a Coogi item on the 3rd Wednesday of the month, give them a 10% discount). We had a logic system to make the business logic more flexible, but it was still quite inflexible as to what conditions it would support.

It was actually after I left that job that I found out that what they needed was a rules engine. A rules engine is exactly what is good for this situation:

https://github.com/rbrush/clara-rules/wiki/Introduction

The rules engine Clara is written in Clojure, so you probably need something else. But it is a good example of what you should be looking for.

You add/remove rules on the fly, then just pass your data through the rules to see what matches. In your case, once your rules engine is set up, you wouldn't store actual code (which is a major security nightmare waiting to happen BTW), you would just store the simple rules, then load them into memory to check an order against at checkout.
Node-Rules seems pretty promising for my application?

https://github.com/mithunsatheesh/node-rules/blob/master/examples/2.MultipleRules.js
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |