pranayaryal
8/22/2017 - 2:49 AM

CartService - Angular shopping cart service

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;
        };
    });