CartService - Angular shopping cart service
angular
.module('sarStoreApp')
.service('CartService', function ($http) {
var self = this;
var totalDiscountedItems = 0;
var isDiscountApplied = false;
var hasDiscountError = false;
var hasTax = false;
var cart = {
items: [],
totalCost: 0
};
var activeDiscount = {
id: null,
type: null,
amount: null,
code: null,
minimum: null,
category_ids: [],
parent_category_ids: [],
totalAmountDiscounted: 0
};
this.addItemToCart = function (itemId, itemQuantity, itemVariantId) {
var item = {
itemId: itemId,
itemQuantity: itemQuantity
};
if (itemVariantId != 'select_variant') {
item.itemVariantId = parseInt(itemVariantId);
}
$http.post('/api/v1/store/item/cart/add', item)
.success(function (data, status, headers, config) {
self._addToCart(data, itemQuantity, itemVariantId);
}).
error(function (data, status, headers, config) {
});
};
this.addPersonalizedItemToCart = function (itemId, itemQuantity, itemVariantId, personalizationFields) {
var personalizedItem = {
itemId: itemId,
itemQuantity: itemQuantity,
personalizationFields: personalizationFields
};
if (itemVariantId != 'select_variant') {
personalizedItem.itemVariantId = parseInt(itemVariantId);
}
$http.post('/api/v1/store/item/cart/add', personalizedItem)
.success(function (data, status, headers, config) {
self._addToCart(data, itemQuantity, itemVariantId, personalizedItem.personalizationFields);
}).
error(function (data, status, headers, config) {
});
};
//Internal function to add item to cart. Will check if item is already in the cart
this._addToCart = function (item, itemQuantity, itemVariantId, personalizedFields) {
if (!self.checkIfItemIsInCart(item.id, itemVariantId, personalizedFields)) {
item.quantity = itemQuantity;
cart.items.push(item)
} else {
//update quantity
angular.forEach(cart.items, function (cartItem) {
//need to see if item as variants
if (cartItem.variant) {
if (itemVariantId == cartItem.variant.id) {
if (personalizedFields != null) {
//check if fields are the same
if (self.checkIfItemHasPersonalizedFields(cartItem, personalizedFields)) {
cartItem.quantity += parseInt(itemQuantity)
}
} else {
cartItem.quantity += parseInt(itemQuantity)
}
}
} else {
if (item.id == cartItem.id) {
if (personalizedFields != null) {
//check if fields are the same
if (self.checkIfItemHasPersonalizedFields(cartItem, personalizedFields)) {
cartItem.quantity += parseInt(itemQuantity)
}
} else {
cartItem.quantity += parseInt(itemQuantity)
}
}
}
});
}
//jquery in angular controller. Not my favorite
$('.right-drawer').toggleClass('visible');
$('.curtain').toggleClass('visible');
self.updateTotalPriceOfOrder()
};
this.removeItemFromCart = function (index) {
$http.post('/api/v1/store/item/cart/remove', cart.items[index].id)
.success(function (data, status, headers, config) {
cart.items.splice(index, 1);
self.updateTotalPriceOfOrder()
}).
error(function (data, status, headers, config) {
});
};
this.removeCartQuantity = function (index) {
//don't bring the number below zero
if (cart.items[index].quantity != 1) {
cart.items[index].quantity -= 1;
}
self.updateCart();
self.updateTotalPriceOfOrder()
};
this.addCartQuantity = function (index) {
cart.items[index].quantity += 1;
self.updateCart();
self.updateTotalPriceOfOrder()
};
this.updateTotalPriceOfOrder = function () {
cart.totalCost = 0;
//check if discount has been applied to keep the order total correct
if (isDiscountApplied == true) {
self.applyDiscount();
}
angular.forEach(cart.items, function (cartItem) {
var totalCostForItem = 0;
if (isDiscountApplied == true && self.checkIfCanApplyDiscount() && cartItem.discountPrice
&& cartItem.discountPrice != 0 && cartItem.hasDiscountApplied == true) {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.discountPrice);
}
else if (cartItem.variant && cartItem.variant.price && cartItem.variant.price != 0) {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.variant.price);
}
else if (cartItem.sale_price > 0) {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.sale_price);
} else {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.base_price);
}
cart.totalCost += totalCostForItem;
});
//if cart is empty
if (cart.items.length == 0) {
cart.totalCost = 0;
}
};
this.totalPriceOfOrderBeforeDiscount = function () {
var totalCost = 0;
angular.forEach(cart.items, function (cartItem) {
var totalCostForItem = 0;
if (cartItem.variant && cartItem.variant.price && cartItem.variant.price != 0) {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.variant.price);
}
else if (cartItem.sale_price > 0) {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.sale_price);
} else {
totalCostForItem = parseInt(cartItem.quantity) * parseFloat(cartItem.base_price);
}
totalCost += totalCostForItem;
});
return totalCost;
};
this.updateCart = function () {
var payload = {
cart_items: cart.items
};
$http.post('/api/v1/store/item/cart/update', payload)
.success(function (data, status, headers, config) {
}).
error(function (data, status, headers, config) {
});
};
this.getCartItems = function () {
$http.get('/api/v1/store/item/cart')
.success(function (data, status, headers, config) {
if (data.cart != null) {
cart.items = data.cart;
}
if (data.discount != null) {
activeDiscount.id = data.discount.id;
activeDiscount.type = data.discount.amount_type;
activeDiscount.amount = data.discount.amount;
activeDiscount.code = data.discount.code;
activeDiscount.category_ids = data.discount.category_ids;
activeDiscount.parent_category_ids = data.discount.parent_category_ids;
activeDiscount.minimum = data.discount.minimum;
isDiscountApplied = true
}
self.updateTotalPriceOfOrder();
})
};
this.taxAmount = function (taxPercentage) {
return ((self.totalPriceOfOrder() + self.getShippingCost()) * taxPercentage)
};
this.applyDiscount = function () {
var countOfDiscountedItems = 0;
activeDiscount.totalAmountDiscounted = 0;
self.removeDiscountsFromCartItems();
if (this.checkIfCanApplyDiscount() == true) {
angular.forEach(cart.items, function (cartItem) {
if (activeDiscount.type == 0 && cartItem.is_discountable == 1) {
//if item category (or it's parent) is in the categories selected with the discount or if discount has no categories
if (activeDiscount.category_ids.length == 0 || activeDiscount.category_ids.indexOf(cartItem.category_id) != -1
|| activeDiscount.parent_category_ids.indexOf(cartItem.category_id) != -1) {
var itemPrice = 0;
var amountSaved = 0;
//if item variant has a price set
if (cartItem.variant && cartItem.variant.price && cartItem.variant.price != 0) {
itemPrice = parseFloat(cartItem.variant.price)
}
//if item is on sale
else if (cartItem.sale_price > 0) {
itemPrice = parseFloat(cartItem.sale_price);
} else {
itemPrice = parseFloat(cartItem.base_price);
}
if (activeDiscount.type == 0) {
cartItem.discountPrice = itemPrice - (itemPrice * (parseFloat(activeDiscount.amount) / 100));
amountSaved = parseInt(cartItem.quantity) * (itemPrice * (parseFloat(activeDiscount.amount) / 100));
}
cartItem.hasDiscountApplied = true;
activeDiscount.totalAmountDiscounted += amountSaved;
countOfDiscountedItems++;
}
}
});
}
totalDiscountedItems = countOfDiscountedItems;
if (self.checkIfCanApplyDiscount() == true && activeDiscount.type == 1) {
cart.totalCost = cart.totalCost - parseFloat(activeDiscount.amount);
activeDiscount.totalAmountDiscounted = parseFloat(activeDiscount.amount);
}
};
this.removeDiscount = function () {
$http.post('/api/v1/store/item/cart/remove-discount', {})
.success(function (data, status, headers, config) {
isDiscountApplied = false;
activeDiscount = {
id: null,
type: null,
amount: null,
code: null,
minimum: null,
category_ids: [],
parent_category_ids: [],
totalAmountDiscounted: 0
};
self.updateTotalPriceOfOrder()
}).
error(function (data, status, headers, config) {
});
self.removeDiscountsFromCartItems()
};
this.getDiscount = function (discountCode) {
var payload = {
discountCode: discountCode
};
$http.post('/api/v1/store/item/cart/get-discount', payload)
.success(function (data, status, headers, config) {
activeDiscount.id = data.id;
activeDiscount.type = data.amount_type;
activeDiscount.amount = data.amount;
activeDiscount.code = data.code;
activeDiscount.category_ids = data.category_ids;
activeDiscount.parent_category_ids = data.parent_category_ids;
activeDiscount.minimum = data.minimum;
isDiscountApplied = true;
hasDiscountError = false;
self.updateTotalPriceOfOrder();
})
.error(function (data, status, headers, config) {
if (status == 404) {
isDiscountApplied = false;
hasDiscountError = true;
}
})
};
this.removeDiscountsFromCartItems = function () {
angular.forEach(cart.items, function (cartItem) {
cartItem.hasDiscountApplied = false;
});
};
//checks
this.checkIfItemIsInCart = function (itemId, itemVariantId, personalizedFields) {
var match = false;
angular.forEach(cart.items, function (cartItem) {
if (cartItem.id == itemId) {
//need to see if item as variants
if (itemVariantId != 'select_variant' && cartItem.variant) {
if (personalizedFields != null) {
if ((self.checkIfItemHasPersonalizedFields(cartItem, personalizedFields)) && itemVariantId == cartItem.variant.id) {
match = true;
}
} else if (itemVariantId == cartItem.variant.id) {
match = true;
}
} else {
if (personalizedFields != null) {
if (self.checkIfItemHasPersonalizedFields(cartItem, personalizedFields)) {
match = true;
}
} else {
match = true;
}
}
}
});
return match;
};
this.checkIfCanApplyDiscount = function () {
var cartTotal = 0;
angular.forEach(cart.items, function (cartItem) {
var itemPrice = 0;
if (cartItem.is_discountable == 1) {
//if item variant has a price set
if (cartItem.variant && cartItem.variant.price && cartItem.variant.price != 0) {
itemPrice = parseFloat(cartItem.variant.price)
}
//if item is on sale
else if (cartItem.sale_price > 0) {
itemPrice = parseFloat(cartItem.sale_price);
} else {
itemPrice = parseFloat(cartItem.base_price);
}
}
cartTotal += itemPrice * parseInt(cartItem.quantity);
});
return cartTotal >= activeDiscount.minimum;
};
this.checkIfItemHasPersonalizedFields = function (item, personalizedFields) {
var hasSameFields = true;
angular.forEach(personalizedFields, function (field, id) {
if (item.personalizationFields && item.personalizationFields[id] != field) {
hasSameFields = false;
}
});
return hasSameFields;
};
//getter functions
this.countOfItemsInCart = function () {
return cart.items.length;
};
this.totalPriceOfOrder = function () {
return cart.totalCost;
};
this.cartItems = function () {
return cart.items;
};
this.amountDiscounted = function () {
return activeDiscount.totalAmountDiscounted;
};
this.discountType = function () {
return activeDiscount.type;
};
this.discountAmount = function () {
return activeDiscount.amount;
};
this.discountCode = function () {
return activeDiscount.code;
};
this.getIsDiscountApplied = function () {
return isDiscountApplied;
};
this.getDiscountError = function () {
return hasDiscountError;
};
this.getDiscountData = function () {
return activeDiscount;
};
this.getCountOfDiscountedItems = function () {
return totalDiscountedItems;
};
this.getHasTax = function () {
return hasTax;
};
this.getShippingCost = function () {
var subTotal = this.totalPriceOfOrderBeforeDiscount();
var shipping_total = 0;
/*switch (true) {
case (subTotal > 0 && subTotal <= 5.00):
shipping_total = 3.75;
break;
case (subTotal > 5.00 && subTotal <= 10.00):
shipping_total = 5.75;
break;
case (subTotal > 10.00 && subTotal <= 20.00):
shipping_total = 6.50;
break;
case (subTotal > 20.00 && subTotal <= 40.00):
shipping_total = 7.50;
break;
case (subTotal > 40.00 && subTotal <= 60.00):
shipping_total = 8.50;
break;
case (subTotal > 60.00 && subTotal <= 80.00):
shipping_total = 9.50;
break;
case (subTotal > 80.00 && subTotal <= 100.00):
shipping_total = 10.50;
break;
case (subTotal > 100.00 && subTotal <= 200.00):
shipping_total = 13.50;
break;
case (subTotal > 200.00 && subTotal <= 300.00):
shipping_total = 15;
break;
case (subTotal > 300.00 && subTotal <= 400.00):
shipping_total = 17;
break;
case (subTotal > 400.00 && subTotal <= 500.00):
shipping_total = 20;
break;
case (subTotal > 500.00 && subTotal <= 600.00):
shipping_total = 22;
break;
case (subTotal > 600.00 && subTotal <= 700.00):
shipping_total = 24;
break;
case (subTotal > 700.00 && subTotal <= 800.00):
shipping_total = 26;
break;
case (subTotal > 800.00 && subTotal <= 900.00):
shipping_total = 29;
break;
case (subTotal > 900.00 && subTotal <= 1000.00):
shipping_total = 31;
break;
case (subTotal > 1000.00):
shipping_total = 31;
break;
default:
shipping_total = 0;
break;
}*/
//check if discount is a free shipping discount
if (activeDiscount.type == 2 && subTotal >= activeDiscount.minimum) {
activeDiscount.totalAmountDiscounted = shipping_total;
shipping_total = 0;
}
return shipping_total;
};
//setters
this.setHasTax = function ($value) {
hasTax = $value;
};
});