/**
  * @param $data
  */
 protected function addService($data)
 {
     $item = $this->cart_model->getById($data['parent_id']);
     if (!$item) {
         $this->errors = _w('Error');
         return;
     }
     unset($item['id']);
     $item['parent_id'] = $data['parent_id'];
     $item['type'] = 'service';
     $item['service_id'] = $data['service_id'];
     if (isset($data['service_variant_id'])) {
         $item['service_variant_id'] = $data['service_variant_id'];
     } else {
         $service_model = new shopServiceModel();
         $service = $service_model->getById($data['service_id']);
         $item['service_variant_id'] = $service['variant_id'];
     }
     $id = $this->cart->addItem($item);
     $total = $this->cart->total();
     $discount = $this->cart->discount();
     $this->response['id'] = $id;
     $this->response['total'] = $this->currencyFormat($total);
     $this->response['count'] = $this->cart->count();
     $this->response['discount'] = $this->currencyFormat($discount);
     $item_total = $this->cart->getItemTotal($data['parent_id']);
     $this->response['item_total'] = $this->currencyFormat($item_total);
     if (shopAffiliate::isEnabled()) {
         $add_affiliate_bonus = shopAffiliate::calculateBonus(array('total' => $total, 'discount' => $discount, 'items' => $this->cart->items(false)));
         $this->response['add_affiliate_bonus'] = sprintf(_w("This order will add +%s points to your affiliate bonus."), round($add_affiliate_bonus, 2));
     }
 }
 public function execute()
 {
     $cart = new shopCart();
     $item_id = waRequest::post('id');
     $cart_items_model = new shopCartItemsModel();
     $item = $cart_items_model->getById($item_id);
     $is_html = waRequest::request('html');
     if ($q = waRequest::post('quantity', 0, 'int')) {
         if (!wa()->getSetting('ignore_stock_count')) {
             if ($item['type'] == 'product') {
                 $product_model = new shopProductModel();
                 $p = $product_model->getById($item['product_id']);
                 $sku_model = new shopProductSkusModel();
                 $sku = $sku_model->getById($item['sku_id']);
                 // check quantity
                 if ($sku['count'] !== null && $q > $sku['count']) {
                     $q = $sku['count'];
                     $name = $p['name'] . ($sku['name'] ? ' (' . $sku['name'] . ')' : '');
                     $this->response['error'] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $q, $name);
                     $this->response['q'] = $q;
                 }
             }
         }
         $cart->setQuantity($item_id, $q);
         $this->response['item_total'] = $is_html ? shop_currency_html($cart->getItemTotal($item_id), true) : shop_currency($cart->getItemTotal($item_id), true);
     } elseif ($v = waRequest::post('service_variant_id')) {
         $cart->setServiceVariantId($item_id, $v);
         $this->response['item_total'] = $is_html ? shop_currency_html($cart->getItemTotal($item['parent_id']), true) : shop_currency($cart->getItemTotal($item['parent_id']), true);
     }
     $total = $cart->total();
     $discount = $cart->discount();
     $this->response['total'] = $is_html ? shop_currency_html($total, true) : shop_currency($total, true);
     $this->response['discount'] = $is_html ? shop_currency_html($discount, true) : shop_currency($discount, true);
     $this->response['discount_numeric'] = $discount;
     $this->response['count'] = $cart->count();
     if (shopAffiliate::isEnabled()) {
         $add_affiliate_bonus = shopAffiliate::calculateBonus(array('total' => $total, 'discount' => $discount, 'items' => $cart->items(false)));
         $this->response['add_affiliate_bonus'] = sprintf(_w("This order will add +%s points to your affiliate bonus."), round($add_affiliate_bonus, 2));
     }
 }
 public function execute()
 {
     $id = waRequest::post('id');
     $cart = new shopCart();
     $is_html = waRequest::request('html');
     if ($id) {
         $item = $cart->deleteItem($id);
         if ($item && !empty($item['parent_id'])) {
             $item_total = $cart->getItemTotal($item['parent_id']);
             $this->response['item_total'] = $is_html ? shop_currency_html($item_total, true) : shop_currency($item_total, true);
         }
     }
     $total = $cart->total();
     $discount = $cart->discount();
     $this->response['total'] = $is_html ? shop_currency_html($total, true) : shop_currency($total, true);
     $this->response['discount'] = $is_html ? shop_currency_html($discount, true) : shop_currency($discount, true);
     $this->response['count'] = $cart->count();
     if (shopAffiliate::isEnabled()) {
         $add_affiliate_bonus = shopAffiliate::calculateBonus(array('total' => $total, 'discount' => $discount, 'items' => $cart->items(false)));
         $this->response['add_affiliate_bonus'] = sprintf(_w("This order will add +%s points to your affiliate bonus."), round($add_affiliate_bonus, 2));
     }
 }
 public function update_cart($params = array())
 {
     if (!($tracker = $this->_include_tracker()) or !class_exists('shopCart')) {
         return false;
     }
     $cart = new shopCart();
     $products_cart_res = $cart->items();
     // fix old cart value
     if (!empty($params['cart_add'])) {
         $find_id = false;
         foreach ($products_cart_res as $id => $product) {
             if (empty($_REQUEST['sku_id']) and $product['sku_id'] == $params['product_id'] or !empty($_REQUEST['sku_id']) and $product['sku_id'] == $_REQUEST['sku_id']) {
                 $find_id = $id;
                 break;
             }
         }
         if ($find_id) {
             $products_cart_res[$find_id]['quantity']++;
         }
     }
     if (!empty($params['cart_set_quantity'])) {
         if (isset($products_cart_res[$params['id']])) {
             $products_cart_res[$params['id']]['quantity'] = $params['quantity'];
         }
     }
     // / fix old cart value
     $products_cart = array();
     foreach ($products_cart_res as $product) {
         $product_id = $product['product']['id'];
         if ($product['sku_id'] != $product['product']['sku_id']) {
             $product_id .= 's' . $product['sku_id'];
         }
         $products_cart[] = array('product_id' => $product_id, 'qnt' => $product['quantity'], 'price' => $product['price'], 'product_name' => $product['name']);
     }
     $tracker->eventUpdateCart($products_cart);
 }
 public function display()
 {
     $settings = wa('shop')->getConfig()->getCheckoutSettings();
     if (!empty($settings['confirmation']['terms']) && waRequest::get('terms')) {
         echo $settings['confirmation']['terms'];
         exit;
     }
     $cart = new shopCart();
     $items = $cart->items(false);
     $subtotal = $cart->total(false);
     $order = array('contact' => $this->getContact(), 'total' => $subtotal, 'items' => $items);
     $order['discount'] = shopDiscounts::calculate($order);
     $contact = $this->getContact();
     $view = wa()->getView();
     if (!$contact) {
         $view->assign('error', _w('Not enough data in the contact information to place the order.'));
         return;
     }
     $shipping_address = $contact->getFirst('address.shipping');
     if (!$shipping_address) {
         $shipping_address = array('data' => array(), 'value' => '');
     }
     $billing_address = $contact->getFirst('address.billing');
     if (!$billing_address) {
         $billing_address = array('data' => array(), 'value' => '');
     }
     $discount_rate = (double) $subtotal ? $order['discount'] / $subtotal : 0;
     $taxes = shopTaxes::apply($items, array('shipping' => $shipping_address['data'], 'billing' => $billing_address['data'], 'discount_rate' => $discount_rate));
     $tax = 0;
     $tax_included = 0;
     foreach ($taxes as $t) {
         if (isset($t['sum'])) {
             $tax += $t['sum'];
         }
         if (isset($t['sum_included'])) {
             $tax_included += $t['sum_included'];
         }
     }
     if (!isset($order['shipping'])) {
         $shipping_step = new shopOnestepCheckoutShipping();
         $rate = $shipping_step->getRate();
         if ($rate) {
             $order['shipping'] = $rate['rate'];
         } else {
             $order['shipping'] = 0;
         }
     }
     $plugin_model = new shopPluginModel();
     $params = array();
     if ($shipping = $this->getSessionData('shipping')) {
         $params['shipping_id'] = $shipping['id'];
         if ($shipping['id']) {
             $plugin_info = $plugin_model->getById($shipping['id']);
             $params['shipping_rate_id'] = $shipping['rate_id'];
             $params['shipping_name'] = $shipping['name'];
             $params['shipping_description'] = $plugin_info['description'];
         }
     }
     if ($payment_id = $this->getSessionData('payment')) {
         $params['payment_id'] = $payment_id;
         $plugin_info = $plugin_model->getById($payment_id);
         $params['payment_name'] = $plugin_info['name'];
         $params['payment_plugin'] = $plugin_info['plugin'];
         $params['payment_description'] = $plugin_info['description'];
     }
     $view->assign(array('params' => $params, 'contact' => $contact, 'items' => $items, 'shipping' => $order['shipping'], 'discount' => $order['discount'], 'total' => $subtotal - $order['discount'] + $order['shipping'] + $tax, 'tax' => $tax_included + $tax, 'subtotal' => $subtotal, 'shipping_address' => $shipping_address, 'billing_address' => !empty($settings['contactinfo']['fields']['address.billing']) ? $billing_address : false, 'terms' => !empty($settings['confirmation']['terms']) ? $settings['confirmation']['terms'] : false));
     $checkout_flow = new shopCheckoutFlowModel();
     $step_number = shopOnestepCheckout::getStepNumber('confirmation');
     // IF no errors
     $checkout_flow->add(array('step' => $step_number));
     // ELSE
     //        $checkout_flow->add(array(
     //            'step' => $step_number,
     //            'description' => ERROR MESSAGE HERE
     //        ));
 }
 protected function createOrder()
 {
     $checkout_data = wa()->getStorage()->get('shop/checkout');
     if (wa()->getUser()->isAuth()) {
         $contact = wa()->getUser();
     } else {
         if (!empty($checkout_data['contact']) && $checkout_data['contact'] instanceof waContact) {
             $contact = $checkout_data['contact'];
         } else {
             $contact = new waContact();
         }
     }
     $cart = new shopCart();
     $items = $cart->items(false);
     // remove id from item
     foreach ($items as &$item) {
         unset($item['id']);
         unset($item['parent_id']);
     }
     unset($item);
     $order = array('contact' => $contact, 'items' => $items, 'total' => $cart->total(false), 'params' => isset($checkout_data['params']) ? $checkout_data['params'] : array());
     $order['discount_description'] = null;
     $order['discount'] = shopDiscounts::apply($order, $order['discount_description']);
     if (isset($checkout_data['shipping'])) {
         $order['params']['shipping_id'] = $checkout_data['shipping']['id'];
         $order['params']['shipping_rate_id'] = $checkout_data['shipping']['rate_id'];
         $shipping_step = new shopOnestepCheckoutShipping();
         $rate = $shipping_step->getRate($order['params']['shipping_id'], $order['params']['shipping_rate_id']);
         $order['params']['shipping_plugin'] = $rate['plugin'];
         $order['params']['shipping_name'] = $rate['name'];
         if (isset($rate['est_delivery'])) {
             $order['params']['shipping_est_delivery'] = $rate['est_delivery'];
         }
         if (!isset($order['shipping'])) {
             $order['shipping'] = $rate['rate'];
         }
         if (!empty($order['params']['shipping'])) {
             foreach ($order['params']['shipping'] as $k => $v) {
                 $order['params']['shipping_params_' . $k] = $v;
             }
             unset($order['params']['shipping']);
         }
     } else {
         $order['shipping'] = 0;
     }
     if (isset($checkout_data['payment'])) {
         $order['params']['payment_id'] = $checkout_data['payment'];
         $plugin_model = new shopPluginModel();
         $plugin_info = $plugin_model->getById($checkout_data['payment']);
         $order['params']['payment_name'] = $plugin_info['name'];
         $order['params']['payment_plugin'] = $plugin_info['plugin'];
         if (!empty($order['params']['payment'])) {
             foreach ($order['params']['payment'] as $k => $v) {
                 $order['params']['payment_params_' . $k] = $v;
             }
             unset($order['params']['payment']);
         }
     }
     if ($skock_id = waRequest::post('stock_id')) {
         $order['params']['stock_id'] = $skock_id;
     }
     $routing_url = wa()->getRouting()->getRootUrl();
     $order['params']['storefront'] = wa()->getConfig()->getDomain() . ($routing_url ? '/' . $routing_url : '');
     if ($ref = waRequest::cookie('referer')) {
         $order['params']['referer'] = $ref;
         $ref_parts = @parse_url($ref);
         $order['params']['referer_host'] = $ref_parts['host'];
         // try get search keywords
         if (!empty($ref_parts['query'])) {
             $search_engines = array('text' => 'yandex\\.|rambler\\.', 'q' => 'bing\\.com|mail\\.|google\\.', 's' => 'nigma\\.ru', 'p' => 'yahoo\\.com');
             $q_var = false;
             foreach ($search_engines as $q => $pattern) {
                 if (preg_match('/(' . $pattern . ')/si', $ref_parts['host'])) {
                     $q_var = $q;
                     break;
                 }
             }
             // default query var name
             if (!$q_var) {
                 $q_var = 'q';
             }
             parse_str($ref_parts['query'], $query);
             if (!empty($query[$q_var])) {
                 $order['params']['keyword'] = $query[$q_var];
             }
         }
     }
     if ($utm = waRequest::cookie('utm')) {
         $utm = json_decode($utm, true);
         if ($utm && is_array($utm)) {
             foreach ($utm as $k => $v) {
                 $order['params']['utm_' . $k] = $v;
             }
         }
     }
     if (($landing = waRequest::cookie('landing')) && ($landing = @parse_url($landing))) {
         if (!empty($landing['query'])) {
             @parse_str($landing['query'], $arr);
             if (!empty($arr['gclid']) && !empty($order['params']['referer_host']) && strpos($order['params']['referer_host'], 'google') !== false) {
                 $order['params']['referer_host'] .= ' (cpc)';
                 $order['params']['cpc'] = 1;
             } else {
                 if (!empty($arr['_openstat']) && !empty($order['params']['referer_host']) && strpos($order['params']['referer_host'], 'yandex') !== false) {
                     $order['params']['referer_host'] .= ' (cpc)';
                     $order['params']['openstat'] = $arr['_openstat'];
                     $order['params']['cpc'] = 1;
                 }
             }
         }
         $order['params']['landing'] = $landing['path'];
     }
     // A/B tests
     /*
             $abtest_variants_model = new shopAbtestVariantsModel();
             foreach (waRequest::cookie() as $k => $v) {
                 if (substr($k, 0, 5) == 'waabt') {
                     $variant_id = $v;
                     $abtest_id = substr($k, 5);
                     if (wa_is_int($abtest_id) && wa_is_int($variant_id)) {
                         $row = $abtest_variants_model->getById($variant_id);
                         if ($row && $row['abtest_id'] == $abtest_id) {
                             $order['params']['abt' . $abtest_id] = $variant_id;
                         }
                     }
                 }
             }
     */
     $order['params']['ip'] = waRequest::getIp();
     $order['params']['user_agent'] = waRequest::getUserAgent();
     foreach (array('shipping', 'billing') as $ext) {
         $address = $contact->getFirst('address.' . $ext);
         if ($address) {
             foreach ($address['data'] as $k => $v) {
                 $order['params'][$ext . '_address.' . $k] = $v;
             }
         }
     }
     if (isset($checkout_data['comment'])) {
         $order['comment'] = $checkout_data['comment'];
     }
     $workflow = new shopWorkflow();
     if ($order_id = $workflow->getActionById('create')->run($order)) {
         $step_number = shopOnestepCheckout::getStepNumber();
         $checkout_flow = new shopCheckoutFlowModel();
         $checkout_flow->add(array('step' => $step_number));
         $cart->clear();
         wa()->getStorage()->remove('shop/checkout');
         wa()->getStorage()->set('shop/order_id', $order_id);
         return $order_id;
     } else {
         return false;
     }
 }
 protected function createOrder()
 {
     $checkout_data = $this->getStorage()->get('shop/checkout');
     $contact = $this->getUser()->isAuth() ? $this->getUser() : $checkout_data['contact'];
     $cart = new shopCart();
     $items = $cart->items(false);
     // remove id from item
     foreach ($items as &$item) {
         unset($item['id']);
         unset($item['parent_id']);
     }
     unset($item);
     $order = array('contact' => $contact, 'items' => $items, 'total' => $cart->total(false), 'params' => isset($checkout_data['params']) ? $checkout_data['params'] : array());
     $order['discount'] = shopDiscounts::apply($order);
     if (isset($checkout_data['shipping'])) {
         $order['params']['shipping_id'] = $checkout_data['shipping']['id'];
         $order['params']['shipping_rate_id'] = $checkout_data['shipping']['rate_id'];
         $shipping_step = new shopCheckoutShipping();
         $rate = $shipping_step->getRate($order['params']['shipping_id'], $order['params']['shipping_rate_id']);
         $order['params']['shipping_plugin'] = $rate['plugin'];
         $order['params']['shipping_name'] = $rate['name'];
         if (isset($rate['est_delivery'])) {
             $order['params']['shipping_est_delivery'] = $rate['est_delivery'];
         }
         if (!isset($order['shipping'])) {
             $order['shipping'] = $rate['rate'];
         }
         if (!empty($order['params']['shipping'])) {
             foreach ($order['params']['shipping'] as $k => $v) {
                 $order['params']['shipping_params_' . $k] = $v;
             }
             unset($order['params']['shipping']);
         }
     } else {
         $order['shipping'] = 0;
     }
     if (isset($checkout_data['payment'])) {
         $order['params']['payment_id'] = $checkout_data['payment'];
         $plugin_model = new shopPluginModel();
         $plugin_info = $plugin_model->getById($checkout_data['payment']);
         $order['params']['payment_name'] = $plugin_info['name'];
         $order['params']['payment_plugin'] = $plugin_info['plugin'];
         if (!empty($order['params']['payment'])) {
             foreach ($order['params']['payment'] as $k => $v) {
                 $order['params']['payment_params_' . $k] = $v;
             }
             unset($order['params']['payment']);
         }
     }
     if ($skock_id = waRequest::post('stock_id')) {
         $order['params']['stock_id'] = $skock_id;
     }
     $routing_url = wa()->getRouting()->getRootUrl();
     $order['params']['storefront'] = wa()->getConfig()->getDomain() . ($routing_url ? '/' . $routing_url : '');
     if (($ref = wa()->getStorage()->get('shop/referer')) || ($ref = waRequest::cookie('referer'))) {
         $order['params']['referer'] = $ref;
         $ref_parts = parse_url($ref);
         $order['params']['referer_host'] = $ref_parts['host'];
         // try get search keywords
         if (!empty($ref_parts['query'])) {
             $search_engines = array('text' => 'yandex\\.|rambler\\.', 'q' => 'bing\\.com|mail\\.|google\\.', 's' => 'nigma\\.ru', 'p' => 'yahoo\\.com');
             $q_var = false;
             foreach ($search_engines as $q => $pattern) {
                 if (preg_match('/(' . $pattern . ')/si', $ref_parts['host'])) {
                     $q_var = $q;
                     break;
                 }
             }
             // default query var name
             if (!$q_var) {
                 $q_var = 'q';
             }
             parse_str($ref_parts['query'], $query);
             if (!empty($query[$q_var])) {
                 $order['params']['keyword'] = $query[$q_var];
             }
         }
     }
     if ($utm = waRequest::cookie('utm')) {
         $utm = json_decode($utm, true);
         if ($utm && is_array($utm)) {
             foreach ($utm as $k => $v) {
                 $order['params']['utm_' . $k] = $v;
             }
         }
     }
     $order['params']['ip'] = waRequest::getIp();
     $order['params']['user_agent'] = waRequest::getUserAgent();
     foreach (array('shipping', 'billing') as $ext) {
         $address = $contact->getFirst('address.' . $ext);
         if ($address) {
             foreach ($address['data'] as $k => $v) {
                 $order['params'][$ext . '_address.' . $k] = $v;
             }
         }
     }
     if (isset($checkout_data['comment'])) {
         $order['comment'] = $checkout_data['comment'];
     }
     $workflow = new shopWorkflow();
     if ($order_id = $workflow->getActionById('create')->run($order)) {
         $step_number = shopCheckout::getStepNumber();
         $checkout_flow = new shopCheckoutFlowModel();
         $checkout_flow->add(array('step' => $step_number));
         $cart->clear();
         wa()->getStorage()->remove('shop/checkout');
         wa()->getStorage()->set('shop/order_id', $order_id);
         return true;
     }
 }
 public function getItems($weight_unit = null)
 {
     $items = array();
     $cart = new shopCart();
     $cart_items = $cart->items();
     $product_ids = $sku_ids = array();
     foreach ($cart_items as $item) {
         $product_ids[] = $item['product_id'];
         $sku_ids[] = $item['sku_id'];
     }
     $feature_model = new shopFeatureModel();
     $f = $feature_model->getByCode('weight');
     if (!$f) {
         $values = array();
     } else {
         $values_model = $feature_model->getValuesModel($f['type']);
         $values = $values_model->getProductValues($product_ids, $f['id']);
     }
     $m = null;
     if ($weight_unit) {
         $dimension = shopDimension::getInstance()->getDimension('weight');
         if ($weight_unit != $dimension['base_unit']) {
             $m = $dimension['units'][$weight_unit]['multiplier'];
         }
     }
     foreach ($cart_items as $item) {
         if (isset($values['skus'][$item['sku_id']])) {
             $w = $values['skus'][$item['sku_id']];
         } else {
             $w = isset($values[$item['product_id']]) ? $values[$item['product_id']] : 0;
         }
         if ($m !== null) {
             $w = $w / $m;
         }
         $items[] = array('name' => $item['name'], 'price' => $item['price'], 'quantity' => $item['quantity'], 'weight' => $w);
     }
     return $items;
 }