Online Shop COUPON CODE functionality?

Hi guys, I’m working on a coupon code function that am finding pretty damn tricky. Basically I need to write a function that takes in some variables like discount amount, percentage, minimum spend etc and spit out a discount amount. Obviously it also needs to check if the discount code entered matches the code stored in the DB.

There are two objects, one for the cart item and one for the coupon parameters. They look like this:

couponParams = { 
                id: 1,
                name: '10OFF',
                couponExpiry: null,
                initialDiscountPercentage: 10,
                initialDiscountValue: 400,
                minWatermark: null,
                maxWatermark: null,
                maxWatermarkDiscountPercentage: null,
                maxWatermarkDiscountValue: null,
                renewalLength: null,
                status: 'active',
              }

              cartItem = { 
                subtotal: 454.55,
                tax: 45.45,
                totalNoFees: 500,
                total: 500 
              }

More than anything, I’m just wondering how I should set my function up to take in all the variables and make sense of them. Here is what I have so far. It doesnt really work but I’m wondering if anyone could help shine some light on the problem? Thank you :slight_smile:

var calculateDiscount = function(storedCoupon, customerCoupon, options, total) {
                
               var calculateDiscount = function(storedCoupon, customerCoupon, options, total) {
                var absoluteTotal = total;
                var discount;

                options.initialDiscountPercentage = options.initialDiscountPercentage || 0;
                options.initialDiscountValue      = options.initialDiscountValue || 0;
                options.minWatermark              = options.minWatermark || 0;

                if (customerCoupon === storedCoupon) {
                  getDiscountAmount();
                }
                
                options = options || 0;
                if (options === 0) {
                  return total;
                } 

                function getDiscountAmount() {
                  if (options.initialDiscountPercentage > 0 && options.initialDiscountValue > 0) {
                    discount = total - ((total / 100) * options.initialDiscountPercentage);
                  }
                  return discount;
                }

                console.log("DISCOUNT AMOUNT: ", absoluteTotal - discount);

                return (absoluteTotal - discount);
              }

              calculateDiscount(storedCoupon, customerCoupon, couponParams, cartItem.total);
1 Like

Hey @JackEdwardLyons

I was just going through this amazing Clean-Code guide and saw this useful link that I thought would be helpful for you according to your question. I hope this helps you.

1 Like

Thank you thats a great guide. I have passed an object into the function which i can then dissect within the function according to what is required out of the object.

1 Like

I’ve been working to refine my code, I’ve still got a few things to consider… But I’m also wondering how i should go about this, without too many if ... else statements. Here’s what I have:


/* FOR REFERENCE 
-----------------*/
var couponDBVals = {
  id: 1,
  name: '10OFF',
  couponExpiry: null,
  initialDiscountPercentage: 5,
  initialDiscountValue: 100,
  minWatermark: 500,

  maxWatermark: null,
  maxWatermarkDiscountPercentage: null,
  maxWatermarkDiscountValue: null,

  renewalLength: null,
  status: 'active'
}

cartItem = {
    subtotal: 454.55,
    tax: 45.45,
    totalNoFees: 500,
    total: 500
  }
  /* FOR REFERENCE 
  -----------------*/
var total = cartItem.total;
var storedCoupon = 'HELLOWORLD';
var customerCoupon = 'OO';
var appliedDiscount;
var discountAmount = 0;

if (customerCoupon === storedCoupon) {
  calculateDiscount(couponDBVals, total);
}
// Coupon Function
// working to create some cases for various coupons
// 
function calculateDiscount(options, total) {
  var absoluteTotal = total;
  var discount = 0;
  var initialDiscVal     = options.initialDiscountValue;
  var initialDiscPercent = options.initialDiscountPercentage;

  if (absoluteTotal >= options.minWatermark) {
    // basic formula to find discount value
    discount = (absoluteTotal / 100) * options.initialDiscountPercentage;
    // if the discount value is greater than the maximum disocunt amount
    if (  discount >= initialDiscVal ) {
      // discount is now the maximum discount amount
      discount = initialDiscVal;
    } else {
      // initial discount remains
      discount = discount;
    } 
  }
  console.log("DISCOUNT AMOUNT: $" + discount);
}

calculateDiscount(couponDBVals, total);

// end Coupon Function

In my opinion I think you don’t need the else statement at all. Because if discount >= intinialDicVal returns false then this change will never happen and discount will by default will be equal to discount.

if (absoluteTotal >= options.minWatermark) {
// basic formula to find discount value
discount = (absoluteTotal / 100) * options.initialDiscountPercentage;
// if the discount value is greater than the maximum disocunt amount
if (  discount >= initialDiscVal ) {
  // discount is now the maximum discount amount
  discount = initialDiscVal;
} 

}

1 Like

After this, I have some more conditions that need to be met, things like a second level watermark. For example here is a scenario:

COUPON

  • 10% || $150 discount
  • minimum spend (watermark 1) $00

If (spend over $2000) (level 2 watermark)

  • 5% discount || $200

I know I can just if...else my way through the formula, but that could get messy… Would there be another approach to consider?

1 Like

Although I don’t have a vast experience myself to share with you but I know the feeling (of using multiple if...else statements) that you are going through right now, It really makes us think that we are doing something wrong but with my experience so far in programming I can say that this is how somethings are meant to be done. First write the complete code and then at the end we can review and refactor the code to make it less tangled and more readable. Switch statements are an other option but not as versatile as the other.

EDIT: A little bit of googling brought me to this link. Am not really sure if this approach could be useful in your case. Just have a read and try to think if you can utilize this.

Also note that ternary operator can be used as well to make the code look a little less messy.

1 Like

Thanks for the response, I appreciate the help. I made a codepen here, it actually doesn’t look too ugly, but I don’t think its 100 per cent finished anyway. Next thing I need to consider is the expiry date of the coupon.

http://codepen.io/JackEdwardLyons/pen/qrxeLN?editors=0011

1 Like

The two if statements were very similar to each other so to avoid duplication I created another function that could get called for each case. See attached pen.

1 Like

Very true, that was my next step. Thank you for the help. I appreciate it :wink:

1 Like

Your are welcomed :blush: . I guess this is now as close to perfect as it can be. What you say? :confused:

Yeah it’s getting there for sure.

Some edge cases include coupon expiry date, the renewal length of the purchased item (it’s for a yearly subscription), and whether the particular coupon is ‘active’. But those all all simple conditions that can be checked before we enter the math calculations.

Thanks !!

1 Like