<commit_before>'use strict';
var _ = require('lodash');

/**@ngInject*/
var CartService = function($q, $state, OrdersResource) {
  this.$q = $q;
  this.OrdersResource = OrdersResource;
  this.$state = $state;

  this.cart = this._getResource();
};

CartService.prototype = {

  /**
   * Get Cart Count
   *
   * @returns {Number}
   */
  getCount: function() {
    return this.cart.length;
  },

  /**
   * Return all cart items.
   *
   * @returns {Array}
   */
  getItems: function() {
    return this.cart;
  },

  /**
   * Clear Cart
   */
  clearCart: function() {
    this.cart = [];
    this._updateResource();
  },

  /**
   * Remove Item from Cart by Cart Index
   *
   * @param key
   */
  removeItemByKey: function(key) {
    this.cart.splice(key, 1);
    this._updateResource();
  },

  /**
   * Add item to cart
   *
   * @param requestedBy (User)
   * @param project
   * @param product
   */
  add: function (requestedBy, project, product) {
    var tmpInCartPrice = this._getInCartPrice(product);
    product.in_cart_price = this._formatCurrency(tmpInCartPrice, 2, 3, ',', '.');
    this.cart.push({
      requestedBy: requestedBy,
      project:     project,
      product:     product
    });
    this._updateResource();
  },

  /**
   * Checkout
   * Creates order for each of the items
   *
   * @param checkoutCallback (optional)
   */
  checkout: function(checkoutCallback) {

    var orderItems = [];
    var staffId;

    _.each(this.cart, _.bind(function(item, key, cart) {
      orderItems.push({
        product_id: item.product.id,
        project_id: item.project.id
      });

      staffId = item.requestedBy.id;

    }, this));

    var order = {
      staff_id: staffId,
      order_items: orderItems
    };

    this.OrdersResource.save(order).$promise.then(_.bind(function() {

      // Empty the Cart.
      this.clearCart();

      /**
       * If the state we are on is a project, reload it to get the new data.
       * If we are not on a project, when the user goes back to it, it will be reloaded
       * on state change.
       * @todo This is probably not the best way to handle this, but since the cart can be launched
       *       from anywhere, it's hard to pass in a callback without making an equally ugly global one.
       */
      if (this.$state.is('base.authed.project.view')) {
        this.$state.reload();
      }

      // Call defined callback if exists.
      if (_.isFunction(checkoutCallback)) {
        checkoutCallback();
      }

    }, this), function() {
      // @todo Error/Reject case.
    });
  },

  /**
   * Returns sum of prices in cart
   *
   * @returns Float
   */
  getTotalPrice: function() {
    this.totalPrice = 0;
    _.each(this.cart, _.bind(function(item, key, cart) {
      this.totalPrice=parseFloat(this.totalPrice)+(parseFloat(this._getInCartPrice(item.product))*10000);
    }, this));
    this.totalPrice = this.totalPrice/10000;
    this.totalPrice = this._formatCurrency(this.totalPrice, 2, 3, ',', '.');
    return this.totalPrice;
  },

  /**
   * Formats the prices to have at least 2 places after the decimal point,
   * adds commas to separate every three places in the whole numbers.
   * @param number  v: the value to be formatted
   * @param integer n: length of decimal
   * @param integer x: length of whole part
   * @param mixed   s: sections delimiter
   * @param mixed   c: decimal delimiter
   *
   * source: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript
   * @private
   */
  _formatCurrency: function(v, n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',<commit_msg>added additional properties to order on checkout<commit_after>'use strict';
var _ = require('lodash');

/**@ngInject*/
var CartService = function($q, $state, OrdersResource) {
  this.$q = $q;
  this.OrdersResource = OrdersResource;
  this.$state = $state;

  this.cart = this._getResource();
};

CartService.prototype = {

  /**
   * Get Cart Count
   *
   * @returns {Number}
   */
  getCount: function() {
    return this.cart.length;
  },

  /**
   * Return all cart items.
   *
   * @returns {Array}
   */
  getItems: function() {
    return this.cart;
  },

  /**
   * Clear Cart
   */
  clearCart: function() {
    this.cart = [];
    this._updateResource();
  },

  /**
   * Remove Item from Cart by Cart Index
   *
   * @param key
   */
  removeItemByKey: function(key) {
    this.cart.splice(key, 1);
    this._updateResource();
  },

  /**
   * Add item to cart
   *
   * @param requestedBy (User)
   * @param project
   * @param product
   */
  add: function (requestedBy, project, product) {
    var tmpInCartPrice = this._getInCartPrice(product);
    product.in_cart_price = this._formatCurrency(tmpInCartPrice, 2, 3, ',', '.');
    this.cart.push({
      requestedBy: requestedBy,
      project:     project,
      product:     product
    });
    this._updateResource();
  },

  /**
   * Checkout
   * Creates order for each of the items
   *
   * @param checkoutCallback (optional)
   */
  checkout: function(checkoutCallback) {

    var orderItems = [];
    var staffId;

    _.each(this.cart, _.bind(function(item, key, cart) {
      orderItems.push({
        product_id: item.product.id,
        project_id: item.project.id
      });

      staffId = item.requestedBy.id;

    }, this));

    var order = {
      staff_id: staffId,
      order_items: orderItems,
      total: this.totalPrice,
      provision_status: "active"
    };

    this.OrdersResource.save(order).$promise.then(_.bind(function() {

      // Empty the Cart.
      this.clearCart();

      /**
       * If the state we are on is a project, reload it to get the new data.
       * If we are not on a project, when the user goes back to it, it will be reloaded
       * on state change.
       * @todo This is probably not the best way to handle this, but since the cart can be launched
       *       from anywhere, it's hard to pass in a callback without making an equally ugly global one.
       */
      if (this.$state.is('base.authed.project.view')) {
        this.$state.reload();
      }

      // Call defined callback if exists.
      if (_.isFunction(checkoutCallback)) {
        checkoutCallback();
      }

    }, this), function() {
      // @todo Error/Reject case.
    });
  },

  /**
   * Returns sum of prices in cart
   *
   * @returns Float
   */
  getTotalPrice: function() {
    this.totalPrice = 0;
    _.each(this.cart, _.bind(function(item, key, cart) {
      this.totalPrice=parseFloat(this.totalPrice)+(parseFloat(this._getInCartPrice(item.product))*10000);
    }, this));
    this.totalPrice = this.totalPrice/10000;
    return this._formatCurrency(this.totalPrice, 2, 3, ',', '.');
  },

  /**
   * Formats the prices to have at least 2 places after the decimal point,
   * adds commas to separate every three places in the whole numbers.
   * @param number  v: the value to be formatted
   * @param integer n: length of decimal
   * @param integer x: length of whole part
   * @param mixed   s: sections delimiter
   * @param mixed   c: decimal delimiter
   *
   * source: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript
   * @private
   */
  _formatCurrency: function(v, n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
{'fraction_non_alphanumeric': 0.13962621885157098, 'fraction_numerical': 0.006771397616468039, 'mean_word_length': 2.459016393442623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7569187', 'n_tokens_mistral': 2431, 'n_tokens_neox': 2332, 'n_words': 636}