protected function getRates($shipping_id, $items, $address, $total)
 {
     $plugin = shopShipping::getPlugin(null, $shipping_id);
     $weight_unit = $plugin->allowedWeightUnit();
     $dimension = shopDimension::getInstance()->getDimension('weight');
     if ($weight_unit != $dimension['base_unit']) {
         foreach ($items as $item_id => $item) {
             if ($item['weight']) {
                 $items[$item_id]['weight'] = $item['weight'] / $dimension['units'][$weight_unit]['multiplier'];
             }
         }
     }
     $currency = $plugin->allowedCurrency();
     $currrent_currency = wa()->getConfig()->getCurrency(false);
     if ($currency != $currrent_currency) {
         $total = shop_currency($total, $currrent_currency, $currency, false);
     }
     $rates = $plugin->getRates($items, $address, array('total_price' => $total));
     if (is_array($rates)) {
         $is_html = waRequest::request('html');
         foreach ($rates as $r_id => &$r) {
             $r['id'] = $r_id;
             $r['rate_html'] = $is_html ? shop_currency_html($r['rate'], $r['currency']) : shop_currency($r['rate'], $r['currency']);
             $r['rate'] = shop_currency($r['rate'], $r['currency']);
         }
         unset($r);
         return array_values($rates);
     }
     return $rates;
 }
 public function execute()
 {
     try {
         $discountcard = waRequest::post('discountcard', array());
         $model = new shopDiscountcardsPluginModel();
         if (!empty($discountcard['id'])) {
             $model->updateById($discountcard['id'], $discountcard);
             $discountcard = $model->getById($discountcard['id']);
         } elseif (empty($discountcard['discountcard'])) {
             throw new waException('Ошибка: Не указан номер дисконтной карты');
         } else {
             if ($model->getByField('discountcard', $discountcard['discountcard'])) {
                 throw new waException('Ошибка: Номер дисконтной карты не уникален');
             }
             $id = $model->insert($discountcard);
             $discountcard = $model->getById($id);
         }
         if (!empty($discountcard['contact_id'])) {
             $contact = new waContact($discountcard['contact_id']);
             $discountcard['contact_name'] = $contact->get('name');
         }
         $discountcard['amount'] = shop_currency($discountcard['amount']);
         $this->response = $discountcard;
     } catch (Exception $ex) {
         $this->setError($ex->getMessage());
     }
 }
Esempio n. 3
0
 public static function prepareSkus($skus = array(), $contact_id = null, $currency = null)
 {
     $app_settings_model = new waAppSettingsModel();
     if ($app_settings_model->get(self::$plugin_id, 'status') && shopPrice::getDomainSetting('status')) {
         $category_ids = self::getUserCategoryId($contact_id);
         $domain_hash = shopPrice::getRouteHash();
         $params = array('domain_hash' => $domain_hash, 'category_id' => $category_ids);
         $price_model = new shopPricePluginModel();
         $prices = $price_model->getPriceByParams($params, true);
         if ($prices) {
             foreach ($skus as &$sku) {
                 foreach ($prices as $price) {
                     $price_field = "price_plugin_{$price['id']}";
                     if (!empty($sku[$price_field]) && $sku[$price_field] > 0) {
                         //if (!empty($sku['unconverted_currency']) && !empty($sku['currency'])) {
                         //    $sku['price'] = shop_currency($sku[$price_field], $sku['unconverted_currency'], $sku['currency'], false);
                         //} else {
                         if (!$currency) {
                             $sku['price'] = $sku[$price_field];
                         } else {
                             $product_model = new shopProductModel();
                             $product = $product_model->getById($sku['product_id']);
                             $sku['price'] = shop_currency($sku[$price_field], $product['currency'], $currency, false);
                         }
                         //}
                         break;
                     }
                 }
             }
             unset($sku);
         }
     }
     return $skus;
 }
 public function checkOrder()
 {
     $domain_settings = shopOnestep::getDomainSettings();
     $cart = new shopCart();
     $def_currency = wa('shop')->getConfig()->getCurrency(true);
     $cur_currency = wa('shop')->getConfig()->getCurrency(false);
     $total = $cart->total(true);
     $total = shop_currency($total, $cur_currency, $def_currency, false);
     $min_sum = $domain_settings['min_sum'];
     if ($total < $min_sum) {
         return false;
     }
     return true;
 }
 public function checkOrder()
 {
     $app_settings_model = new waAppSettingsModel();
     $settings = $app_settings_model->get(array('shop', 'onestep'));
     $cart = new shopCart();
     $def_currency = wa('shop')->getConfig()->getCurrency(true);
     $cur_currency = wa('shop')->getConfig()->getCurrency(false);
     $total = $cart->total(true);
     $total = shop_currency($total, $cur_currency, $def_currency, false);
     $min_sum = $settings['min_sum'];
     if ($total < $min_sum) {
         return false;
     }
     return true;
 }
 public function execute()
 {
     $app_settings_model = new waAppSettingsModel();
     $query = waRequest::get('term');
     $count = $app_settings_model->get($this->plugin_id, 'autocomplete_count');
     $collection = new shopProductsCollection('search/query=' . $query);
     $products = $collection->getProducts('*', 0, $count);
     $result = array();
     foreach ($products as $product) {
         $size = $app_settings_model->get($this->plugin_id, 'img_size');
         $product['value'] = $product['name'];
         $product['price_str'] = shop_currency($product['price']);
         $product['img_url'] = $product['image_id'] ? shopImage::getUrl(array('id' => $product['image_id'], 'product_id' => $product['id'], 'filename' => $product['image_filename'], 'ext' => $product['ext']), $size) : '';
         array_push($result, $product);
     }
     $this->response = $result;
 }
 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 execute()
 {
     try {
         $app_settings_model = new waAppSettingsModel();
         if (waRequest::post('cancel')) {
             wa()->getStorage()->set('shop/discountcard', '');
             wa()->getStorage()->set('shop/discountcard/customer_id', '');
         } else {
             if ($discountcard_number = waRequest::post('discountcard')) {
                 if (!($customer_id = waRequest::post('customer_id', 0, waRequest::TYPE_INT))) {
                     throw new waException('Укажите покупателя');
                 }
                 $model = new shopDiscountcardsPluginModel();
                 if ($app_settings_model->get(shopDiscountcardsPlugin::$plugin_id, 'binding_customer')) {
                     $discountcard = $model->getByField(array('contact_id' => $customer_id, 'discountcard' => $discountcard_number));
                     if (empty($discountcard)) {
                         $discountcard = $model->getByField(array('contact_id' => 0, 'discountcard' => $discountcard_number));
                     }
                 } else {
                     $discountcard = $model->getByField('discountcard', $discountcard_number);
                 }
                 if ($discountcard) {
                     wa()->getStorage()->set('shop/discountcard', $discountcard['discountcard']);
                     wa()->getStorage()->set('shop/discountcard/customer_id', $customer_id);
                     $discountcard['amount_format'] = shop_currency($discountcard['amount']);
                     $contact = new waContact($discountcard['contact_id']);
                     $discountcard['contact_name'] = $contact->get('name');
                     $this->response = $discountcard;
                 } else {
                     throw new waException('Дисконтная карта не найдена');
                 }
             } else {
                 throw new waException('Укажите номер дисконтной карты');
             }
         }
     } catch (Exception $ex) {
         $this->setError($ex->getMessage());
     }
 }
Esempio n. 10
0
 public function execute()
 {
     $this->getResponse()->addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
     $this->getResponse()->addHeader("Expires", date("r"));
     if (waRequest::method() == 'post') {
         $data = wa()->getStorage()->get('shop/checkout', array());
         if ($coupon_code = waRequest::post('coupon_code')) {
             $data['coupon_code'] = $coupon_code;
         } elseif (isset($data['coupon_code'])) {
             unset($data['coupon_code']);
         }
         if (($use = waRequest::post('use_affiliate')) !== null) {
             if ($use) {
                 $data['use_affiliate'] = 1;
             } elseif (isset($data['use_affiliate'])) {
                 unset($data['use_affiliate']);
             }
         }
         if ($coupon_code || $use) {
             wa()->getStorage()->set('shop/checkout', $data);
             wa()->getStorage()->remove('shop/cart');
         }
     }
     $cart_model = new shopCartItemsModel();
     $cart = new shopCart();
     $code = $cart->getCode();
     $errors = array();
     if (waRequest::post('checkout')) {
         $saved_quantity = $cart_model->select('id,quantity')->where("type='product' AND code = s:code", array('code' => $code))->fetchAll('id');
         $quantity = waRequest::post('quantity');
         foreach ($quantity as $id => $q) {
             if ($q != $saved_quantity[$id]) {
                 $cart->setQuantity($id, $q);
             }
         }
         $not_available_items = $cart_model->getNotAvailableProducts($code, !wa()->getSetting('ignore_stock_count'));
         foreach ($not_available_items as $row) {
             if ($row['sku_name']) {
                 $row['name'] .= ' (' . $row['sku_name'] . ')';
             }
             if ($row['available']) {
                 $errors[$row['id']] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $row['count'], $row['name']);
             } else {
                 $errors[$row['id']] = _w('Oops! %s is not available for purchase at the moment. Please remove this product from your shopping cart to proceed.');
             }
         }
         if (!$errors) {
             $this->redirect(wa()->getRouteUrl('/frontend/checkout'));
         }
     }
     $this->setThemeTemplate('cart.html');
     $items = $cart_model->where('code= ?', $code)->order('parent_id')->fetchAll('id');
     $product_ids = $sku_ids = $service_ids = $type_ids = array();
     foreach ($items as $item) {
         $product_ids[] = $item['product_id'];
         $sku_ids[] = $item['sku_id'];
     }
     $product_ids = array_unique($product_ids);
     $sku_ids = array_unique($sku_ids);
     $product_model = new shopProductModel();
     if (waRequest::param('url_type') == 2) {
         $products = $product_model->getWithCategoryUrl($product_ids);
     } else {
         $products = $product_model->getById($product_ids);
     }
     $sku_model = new shopProductSkusModel();
     $skus = $sku_model->getByField('id', $sku_ids, 'id');
     $image_model = new shopProductImagesModel();
     $delete_items = array();
     foreach ($items as $item_id => &$item) {
         if (!isset($skus[$item['sku_id']])) {
             unset($items[$item_id]);
             $delete_items[] = $item_id;
             continue;
         }
         if ($item['type'] == 'product') {
             $item['product'] = $products[$item['product_id']];
             $sku = $skus[$item['sku_id']];
             if ($sku['image_id'] && $sku['image_id'] != $item['product']['image_id']) {
                 $img = $image_model->getById($sku['image_id']);
                 if ($img) {
                     $item['product']['image_id'] = $sku['image_id'];
                     $item['product']['ext'] = $img['ext'];
                 }
             }
             $item['sku_name'] = $sku['name'];
             $item['sku_code'] = $sku['sku'];
             $item['price'] = $sku['price'];
             $item['compare_price'] = $sku['compare_price'];
             $item['currency'] = $item['product']['currency'];
             $type_ids[] = $item['product']['type_id'];
             if (isset($errors[$item_id])) {
                 $item['error'] = $errors[$item_id];
                 if (strpos($item['error'], '%s') !== false) {
                     $item['error'] = sprintf($item['error'], $item['product']['name'] . ($item['sku_name'] ? ' (' . $item['sku_name'] . ')' : ''));
                 }
             }
         }
     }
     unset($item);
     if ($delete_items) {
         $cart_model->deleteByField(array('code' => $code, 'id' => $delete_items));
     }
     $type_ids = array_unique($type_ids);
     // get available services for all types of products
     $type_services_model = new shopTypeServicesModel();
     $rows = $type_services_model->getByField('type_id', $type_ids, true);
     $type_services = array();
     foreach ($rows as $row) {
         $service_ids[] = $row['service_id'];
         $type_services[$row['type_id']][$row['service_id']] = true;
     }
     // get services for all products
     $product_services_model = new shopProductServicesModel();
     $rows = $product_services_model->getByProducts($product_ids);
     $product_services = $sku_services = array();
     foreach ($rows as $row) {
         if ($row['sku_id'] && !in_array($row['sku_id'], $sku_ids)) {
             continue;
         }
         $service_ids[] = $row['service_id'];
         if (!$row['sku_id']) {
             $product_services[$row['product_id']][$row['service_id']]['variants'][$row['service_variant_id']] = $row;
         }
         if ($row['sku_id']) {
             $sku_services[$row['sku_id']][$row['service_id']]['variants'][$row['service_variant_id']] = $row;
         }
     }
     $service_ids = array_unique($service_ids);
     $service_model = new shopServiceModel();
     $variant_model = new shopServiceVariantsModel();
     $services = $service_model->getByField('id', $service_ids, 'id');
     foreach ($services as &$s) {
         unset($s['id']);
     }
     unset($s);
     $rows = $variant_model->getByField('service_id', $service_ids, true);
     foreach ($rows as $row) {
         $services[$row['service_id']]['variants'][$row['id']] = $row;
         unset($services[$row['service_id']]['variants'][$row['id']]['id']);
     }
     foreach ($items as $item_id => $item) {
         if ($item['type'] == 'product') {
             $p = $item['product'];
             $item_services = array();
             // services from type settings
             if (isset($type_services[$p['type_id']])) {
                 foreach ($type_services[$p['type_id']] as $service_id => &$s) {
                     $item_services[$service_id] = $services[$service_id];
                 }
             }
             // services from product settings
             if (isset($product_services[$item['product_id']])) {
                 foreach ($product_services[$item['product_id']] as $service_id => $s) {
                     if (!isset($s['status']) || $s['status']) {
                         if (!isset($item_services[$service_id])) {
                             $item_services[$service_id] = $services[$service_id];
                         }
                         // update variants
                         foreach ($s['variants'] as $variant_id => $v) {
                             if ($v['status']) {
                                 if ($v['price'] !== null) {
                                     $item_services[$service_id]['variants'][$variant_id]['price'] = $v['price'];
                                 }
                             } else {
                                 unset($item_services[$service_id]['variants'][$variant_id]);
                             }
                         }
                     } elseif (isset($item_services[$service_id])) {
                         // remove disabled service
                         unset($item_services[$service_id]);
                     }
                 }
             }
             // services from sku settings
             if (isset($sku_services[$item['sku_id']])) {
                 foreach ($sku_services[$item['sku_id']] as $service_id => $s) {
                     if (!isset($s['status']) || $s['status']) {
                         // update variants
                         foreach ($s['variants'] as $variant_id => $v) {
                             if ($v['status']) {
                                 if ($v['price'] !== null) {
                                     $item_services[$service_id]['variants'][$variant_id]['price'] = $v['price'];
                                 }
                             } else {
                                 unset($item_services[$service_id]['variants'][$variant_id]);
                             }
                         }
                     } elseif (isset($item_services[$service_id])) {
                         // remove disabled service
                         unset($item_services[$service_id]);
                     }
                 }
             }
             foreach ($item_services as $s_id => &$s) {
                 if (!$s['variants']) {
                     unset($item_services[$s_id]);
                     continue;
                 }
                 if ($s['currency'] == '%') {
                     foreach ($s['variants'] as $v_id => $v) {
                         $s['variants'][$v_id]['price'] = $v['price'] * $item['price'] / 100;
                     }
                     $s['currency'] = $item['currency'];
                 }
                 if (count($s['variants']) == 1) {
                     $v = reset($s['variants']);
                     $s['price'] = $v['price'];
                     unset($s['variants']);
                 }
             }
             unset($s);
             uasort($item_services, array('shopServiceModel', 'sortServices'));
             $items[$item_id]['services'] = $item_services;
         } else {
             $items[$item['parent_id']]['services'][$item['service_id']]['id'] = $item['id'];
             if (isset($item['service_variant_id'])) {
                 $items[$item['parent_id']]['services'][$item['service_id']]['variant_id'] = $item['service_variant_id'];
             }
             unset($items[$item_id]);
         }
     }
     foreach ($items as $item_id => $item) {
         $price = shop_currency($item['price'] * $item['quantity'], $item['currency'], null, false);
         if (isset($item['services'])) {
             foreach ($item['services'] as $s) {
                 if (!empty($s['id'])) {
                     if (isset($s['variants'])) {
                         $price += shop_currency($s['variants'][$s['variant_id']]['price'] * $item['quantity'], $s['currency'], null, false);
                     } else {
                         $price += shop_currency($s['price'] * $item['quantity'], $s['currency'], null, false);
                     }
                 }
             }
         }
         $items[$item_id]['full_price'] = $price;
     }
     $total = $cart->total(false);
     $order = array('total' => $total, 'items' => $items);
     $order['discount'] = $discount = shopDiscounts::calculate($order);
     $order['total'] = $total = $total - $order['discount'];
     $data = wa()->getStorage()->get('shop/checkout');
     $this->view->assign('cart', array('items' => $items, 'total' => $total, 'count' => $cart->count()));
     $this->view->assign('coupon_code', isset($data['coupon_code']) ? $data['coupon_code'] : '');
     if (shopAffiliate::isEnabled()) {
         $affiliate_bonus = 0;
         if ($this->getUser()->isAuth()) {
             $customer_model = new shopCustomerModel();
             $customer = $customer_model->getById($this->getUser()->getId());
             $affiliate_bonus = $customer ? round($customer['affiliate_bonus'], 2) : 0;
         }
         $this->view->assign('affiliate_bonus', $affiliate_bonus);
         $use = !empty($data['use_affiliate']);
         $this->view->assign('use_affiliate', $use);
         if ($use) {
             $discount -= shop_currency(shopAffiliate::convertBonus($order['params']['affiliate_bonus']), $this->getConfig()->getCurrency(true), null, false);
             $this->view->assign('used_affiliate_bonus', $order['params']['affiliate_bonus']);
         }
         $order['currency'] = $this->getConfig()->getCurrency(false);
         $add_affiliate_bonus = shopAffiliate::calculateBonus($order);
         $this->view->assign('add_affiliate_bonus', round($add_affiliate_bonus, 2));
     }
     $this->view->assign('discount', $discount);
     /**
      * @event frontend_cart
      * @return array[string]string $return[%plugin_id%] html output
      */
     $this->view->assign('frontend_cart', wa()->event('frontend_cart'));
     $this->getResponse()->setTitle(_w('Cart'));
     $checkout_flow = new shopCheckoutFlowModel();
     $checkout_flow->add(array('code' => $code, 'step' => 0, 'description' => null));
 }
 public static function checkCart(&$cart = null)
 {
     $error = false;
     $cart = new shopCart();
     $code = $cart->getCode();
     $view = wa()->getView();
     if (!wa()->getSetting('ignore_stock_count')) {
         $cart_model = new shopCartItemsModel();
         $sku_model = new shopProductSkusModel();
         $product_model = new shopProductModel();
         $items = $cart->items(false);
         foreach ($items as &$item) {
             if (!isset($item['product_id'])) {
                 $sku = $sku_model->getById($item['sku_id']);
                 $product = $product_model->getById($sku['product_id']);
             } else {
                 $product = $product_model->getById($item['product_id']);
                 if (isset($item['sku_id'])) {
                     $sku = $sku_model->getById($item['sku_id']);
                 } else {
                     if (isset($item['features'])) {
                         $product_features_model = new shopProductFeaturesModel();
                         $sku_id = $product_features_model->getSkuByFeatures($product['id'], $item['features']);
                         if ($sku_id) {
                             $sku = $sku_model->getById($sku_id);
                         } else {
                             $sku = null;
                         }
                     } else {
                         $sku = $sku_model->getById($product['sku_id']);
                         if (!$sku['available']) {
                             $sku = $sku_model->getByField(array('product_id' => $product['id'], 'available' => 1));
                         }
                         if (!$sku) {
                             $item['error'] = _w('This product is not available for purchase');
                             $error = true;
                         }
                     }
                 }
             }
             $quantity = $item['quantity'];
             $c = $cart_model->countSku($code, $sku['id']);
             if ($sku['count'] !== null && $c + $quantity > $sku['count']) {
                 $quantity = $sku['count'] - $c;
                 $name = $product['name'] . ($sku['name'] ? ' (' . $sku['name'] . ')' : '');
                 if ($quantity < 0) {
                     $item['error'] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $sku['count'], $name);
                     $error = true;
                 }
             }
         }
         unset($item);
         foreach ($items as $item_id => $item) {
             $price = shop_currency($item['price'] * $item['quantity'], $item['currency'], null, false);
             if (isset($item['services'])) {
                 foreach ($item['services'] as $s) {
                     if (!empty($s['id'])) {
                         if (isset($s['variants'])) {
                             $price += shop_currency($s['variants'][$s['variant_id']]['price'] * $item['quantity'], $s['currency'], null, false);
                         } else {
                             $price += shop_currency($s['price'] * $item['quantity'], $s['currency'], null, false);
                         }
                     }
                 }
             }
             $items[$item_id]['full_price'] = $price;
         }
         $cart = array('items' => $items, 'total' => $cart->total(false), 'count' => $cart->count());
     }
     return $error;
 }
 public function execute($data = null)
 {
     if (wa()->getEnv() == 'frontend') {
         // Now we are in frontend, so fill stock_id for items. Stock_id get from storefront-settings
         // But:
         //   - some skus may have not any stock
         //   - stock_id from storefront isn't setted (empty)
         $sku_ids = array();
         foreach ($data['items'] as $item) {
             if ($item['type'] == 'product') {
                 $sku_ids[] = (int) $item['sku_id'];
             }
         }
         $product_stocks_model = new shopProductStocksModel();
         $sku_ids = $product_stocks_model->filterSkusByNoStocks($sku_ids);
         $sku_ids_map = array_fill_keys($sku_ids, true);
         // storefront stock-id
         $stock_id = waRequest::param('stock_id');
         $stock_model = new shopStockModel();
         if (!$stock_id || !$stock_model->stockExists($stock_id)) {
             $stock_id = $stock_model->select('id')->order('sort')->limit(1)->fetchField();
         }
         foreach ($data['items'] as &$item) {
             if ($item['type'] == 'product') {
                 if (!isset($sku_ids_map[$item['sku_id']])) {
                     // have stocks
                     $item['stock_id'] = $stock_id;
                 }
             }
         }
     }
     $currency = wa()->getConfig()->getCurrency(false);
     $rate_model = new shopCurrencyModel();
     $row = $rate_model->getById($currency);
     $rate = $row['rate'];
     // Save contact
     if (isset($data['contact'])) {
         if (is_numeric($data['contact'])) {
             $contact = new waContact($data['contact']);
         } else {
             /**
              * @var waContact $contact
              */
             $contact = $data['contact'];
             if (!$contact->getId()) {
                 $contact->save();
                 // if user has been created
                 if ($contact['password']) {
                     $signup_action = new shopSignupAction();
                     $signup_action->send($contact);
                 }
             }
         }
     } else {
         $data['contact'] = $contact = wa()->getUser();
     }
     $subtotal = 0;
     foreach ($data['items'] as &$item) {
         if ($currency != $item['currency']) {
             $item['price'] = shop_currency($item['price'], $item['currency'], null, false);
             if (!empty($item['purchase_price'])) {
                 $item['purchase_price'] = shop_currency($item['purchase_price'], $item['currency'], null, false);
             }
             $item['currency'] = $currency;
         }
         $subtotal += $item['price'] * $item['quantity'];
     }
     unset($item);
     if ($data['discount'] === '') {
         $data['total'] = $subtotal;
         $data['discount'] = shopDiscounts::apply($data);
     }
     $shipping_address = $contact->getFirst('address.shipping');
     if (!$shipping_address) {
         $shipping_address = $contact->getFirst('address');
     }
     $billing_address = $contact->getFirst('address.billing');
     if (!$billing_address) {
         $billing_address = $contact->getFirst('address');
     }
     $discount_rate = $subtotal ? $data['discount'] / $subtotal : 0;
     $taxes = shopTaxes::apply($data['items'], array('shipping' => isset($shipping_address['data']) ? $shipping_address['data'] : array(), 'billing' => isset($billing_address['data']) ? $billing_address['data'] : array(), 'discount_rate' => $discount_rate));
     $tax = $tax_included = 0;
     foreach ($taxes as $t) {
         if (isset($t['sum'])) {
             $tax += $t['sum'];
         }
         if (isset($t['sum_included'])) {
             $tax_included += $t['sum_included'];
         }
     }
     $order = array('state_id' => 'new', 'total' => $subtotal - $data['discount'] + $data['shipping'] + $tax, 'currency' => $currency, 'rate' => $rate, 'tax' => $tax_included + $tax, 'discount' => $data['discount'], 'shipping' => $data['shipping'], 'comment' => isset($data['comment']) ? $data['comment'] : '');
     $order['contact_id'] = $contact->getId();
     // Add contact to 'shop' category
     $contact->addToCategory('shop');
     // Save order
     $order_model = new shopOrderModel();
     $order_id = $order_model->insert($order);
     // Create record in shop_customer, or update existing record
     $scm = new shopCustomerModel();
     $scm->updateFromNewOrder($order['contact_id'], $order_id);
     // save items
     $items_model = new shopOrderItemsModel();
     $parent_id = null;
     foreach ($data['items'] as $item) {
         $item['order_id'] = $order_id;
         if ($item['type'] == 'product') {
             $parent_id = $items_model->insert($item);
         } elseif ($item['type'] == 'service') {
             $item['parent_id'] = $parent_id;
             $items_model->insert($item);
         }
     }
     // Order params
     if (empty($data['params'])) {
         $data['params'] = array();
     }
     $data['params']['auth_code'] = self::generateAuthCode($order_id);
     $data['params']['auth_pin'] = self::generateAuthPin();
     // Save params
     $params_model = new shopOrderParamsModel();
     $params_model->set($order_id, $data['params']);
     $log_model = new waLogModel();
     $log_model->add('order_create', $order_id, null, $order['contact_id']);
     return array('order_id' => $order_id, 'contact_id' => wa()->getEnv() == 'frontend' ? $contact->getId() : wa()->getUser()->getId());
 }
Esempio n. 13
0
 /**
  * Returns total cost of current shopping cart's item with specified id, expressed in default currency.
  * 
  * @param int|array $item_id Item id or item data array.
  * @return float
  */
 public function getItemTotal($item_id)
 {
     if (is_array($item_id)) {
         $item = $item_id;
     } else {
         $item = $this->getItem($item_id);
     }
     $cart_items_model = new shopCartItemsModel();
     $items = $cart_items_model->getByField('parent_id', $item['id'], true);
     $price = shop_currency($item['price'] * $item['quantity'], $item['currency'], null, false);
     if (!$items) {
         return $price;
     }
     $variants = array();
     foreach ($items as $s) {
         $variants[] = $s['service_variant_id'];
     }
     $product_services_model = new shopProductServicesModel();
     $sql = "SELECT v.id, s.currency, ps.sku_id, ps.price, v.price base_price FROM shop_service_variants v\n                LEFT JOIN shop_product_services ps ON\n                v.id = ps.service_variant_id AND ps.product_id = i:0 AND (ps.sku_id = i:1 OR ps.sku_id IS NULL)\n                JOIN shop_service s ON v.service_id = s.id\n                WHERE v.id IN (i:2)\n                ORDER BY ps.sku_id";
     $rows = $product_services_model->query($sql, $item['product_id'], $item['sku_id'], $variants)->fetchAll();
     $prices = array();
     foreach ($rows as $row) {
         if (!isset($prices[$row['id']]) || $row['price']) {
             if ($row['price'] === null) {
                 $row['price'] = $row['base_price'];
             }
             $prices[$row['id']] = $row;
         }
     }
     foreach ($items as $s) {
         $v = $prices[$s['service_variant_id']];
         if ($v['currency'] == '%') {
             $v['price'] = $v['price'] * $item['price'] / 100;
             $v['currency'] = $item['currency'];
         }
         $price += shop_currency($v['price'] * $item['quantity'], $v['currency'], null, false);
     }
     return $price;
 }
Esempio n. 14
0
 /**
  * @param array $items order items to modify
  * @param array $params 'billing' => array(...), 'shipping' => array(...), 'discount_rate' => float
  * @return array : tax_id => array ( rate => float, included => bool, name => string )
  */
 public static function apply(&$items, $params, $currency = null)
 {
     $addresses = array_intersect_key($params, array('billing' => 1, 'shipping' => 1));
     $discount_rate = ifset($params['discount_rate'], 0);
     $tax_ids = array();
     $parent_tax_id = null;
     foreach ($items as &$i) {
         if ($i['type'] == 'product') {
             $parent_tax_id = isset($i['product']['tax_id']) ? $i['product']['tax_id'] : (isset($i['tax_id']) ? $i['tax_id'] : 0);
         }
         if (!empty($i['product']['tax_id'])) {
             $tax_ids[] = $i['tax_id'] = $i['product']['tax_id'];
         } elseif (isset($i['service']['tax_id'])) {
             // inherit from product
             if ($i['service']['tax_id'] === '0') {
                 if ($parent_tax_id) {
                     $tax_ids[] = $i['tax_id'] = $parent_tax_id;
                 }
             } else {
                 $tax_ids[] = $i['tax_id'] = $i['service']['tax_id'];
             }
         } elseif (!empty($i['tax_id'])) {
             $tax_ids[] = $i['tax_id'];
         }
         $i['tax'] = 0;
         $i['tax_percent'] = 0;
         $i['tax_included'] = 0;
     }
     unset($i);
     if (empty($tax_ids)) {
         return array();
     }
     $result = array();
     $tm = new shopTaxModel();
     $trm = new shopTaxRegionsModel();
     $taxes = $tm->getById($tax_ids);
     foreach ($taxes as $t) {
         $result[$t['id']] = array('rate' => 0.0, 'included' => $t['included'], 'name' => $t['name'], 'sum_included' => 0.0, 'sum' => 0.0);
         // Check if there are rates based on country and region
         $result[$t['id']]['rate'] = $trm->getByTaxAddress($t['id'], $addresses[$t['address_type']]);
     }
     // Rates by zip code override rates by region, when applicable
     $main_country = wa()->getSetting('country');
     foreach (array('shipping', 'billing') as $addr_type) {
         // ZIP-based rates are only applied to main shop country
         if (empty($addresses[$addr_type]['zip']) || !empty($addresses[$addr_type]['country']) && $addresses[$addr_type]['country'] !== $main_country) {
             continue;
         }
         $tzcm = new shopTaxZipCodesModel();
         foreach ($tzcm->getByZip($addresses[$addr_type]['zip'], $addr_type, $tax_ids) as $tax_id => $rate) {
             $result[$tax_id]['rate'] = $rate;
             $result[$tax_id]['name'] = $taxes[$tax_id]['name'];
         }
     }
     // Compute tax values for each item, and total tax
     foreach ($items as &$i) {
         $tax_id = ifempty($i['tax_id']);
         $i['tax_percent'] = ifset($result[$tax_id]['rate'], 0.0);
         $i['tax_included'] = ifset($result[$tax_id]['included']);
         $p = shop_currency((1 - $discount_rate) * $i['price'] * $i['quantity'], $i['currency'], $currency, false);
         $r = ifset($result[$tax_id]['rate'], 0.0);
         if ($i['tax_included']) {
             $i['tax'] = $p * $r / (100.0 + $r);
         } else {
             $i['tax'] = $p * $r / 100.0;
         }
         if ($i['tax_included']) {
             $result[$tax_id]['sum_included'] += $i['tax'];
         } elseif ($i['tax']) {
             $result[$tax_id]['sum'] += $i['tax'];
         }
     }
     unset($i);
     return $result;
 }
Esempio n. 15
0
 /**
  * Returns available shipping methods and rates for specified address.
  *
  * @param array $address Address data
  * @param array $items Order items
  * @param array $params Optional extra parameters:
  *     'payment'     => [int] payment method id for which available shipping methods must be returned
  *     'currency'    => [string] currency code to convert shipping rates to
  *     'total_price' => [float] arbitrary total order items cost to be taken into account for obtaining shipping rates
  * @return array
  */
 public static function getShippingMethods($address = null, $items = array(), $params = array())
 {
     $plugin_model = new shopPluginModel();
     $options = array();
     if (!empty($params[shopPluginModel::TYPE_PAYMENT])) {
         $options[shopPluginModel::TYPE_PAYMENT] = $params[shopPluginModel::TYPE_PAYMENT];
     }
     $methods = $plugin_model->listPlugins(shopPluginModel::TYPE_SHIPPING, $options);
     if ($address !== null) {
         $config = wa('shop')->getConfig();
         /**
          * @var $config shopConfig
          */
         $result = array();
         $currency = isset($params['currency']) ? $params['currency'] : $config->getCurrency();
         $dimensions = shopDimension::getInstance();
         foreach ($methods as $m) {
             if ($m['available']) {
                 $plugin = shopShipping::getPlugin($m['plugin'], $m['id']);
                 $plugin_info = $plugin->info($m['plugin']);
                 $plugin_currency = (array) $plugin->allowedCurrency();
                 $total = null;
                 if ($plugin_currency != $currency) {
                     if (!$config->getCurrencies($plugin_currency)) {
                         $result[$m['id']] = array('plugin' => $m['plugin'], 'logo' => $m['logo'], 'icon' => $plugin_info['icon'], 'img' => $plugin_info['img'], 'name' => $m['name'], 'error' => sprintf(_w('Shipping rate was not calculated because required currency %s is not defined in your store settings.'), implode(', ', $plugin_currency)), 'rate' => '', 'currency' => $currency);
                         continue;
                     }
                 }
                 if (isset($params['total_price'])) {
                     if (!in_array($currency, $plugin_currency)) {
                         $total = shop_currency($params['total_price'], $currency, reset($plugin_currency), false);
                     } else {
                         $total = $params['total_price'];
                     }
                 } else {
                     foreach ($items as $item) {
                         if (!empty($item['price'])) {
                             $total += $item['price'] * (isset($item['quantity']) ? $item['quantity'] : 1);
                         }
                         if ($total && !in_array($currency, $plugin_currency)) {
                             $total = shop_currency($total, $currency, reset($plugin_currency), false);
                         }
                     }
                 }
                 $weight_unit = $plugin->allowedWeightUnit();
                 foreach ($items as &$item) {
                     if (!empty($item['weight'])) {
                         $item['weight'] = $dimensions->convert($item['weight'], 'weight', $weight_unit);
                     }
                 }
                 unset($item);
                 $rates = $plugin->getRates($items, $address ? $address : array(), $total ? array('total_price' => $total) : array());
                 if (is_array($rates)) {
                     foreach ($rates as $rate_id => $info) {
                         if (is_array($info)) {
                             $rate = is_array($info['rate']) ? max($info['rate']) : $info['rate'];
                             $rate = (double) shop_currency($rate, reset($plugin_currency), $currency, false);
                             $result[$m['id'] . '.' . $rate_id] = array('plugin' => $m['plugin'], 'logo' => $m['logo'], 'icon' => $plugin_info['icon'], 'img' => $plugin_info['img'], 'name' => $m['name'] . (!empty($info['name']) ? ' (' . $info['name'] . ')' : ''), 'rate' => $rate, 'currency' => $currency);
                         }
                     }
                 } elseif (is_string($rates)) {
                     $result[$m['id']] = array('plugin' => $m['plugin'], 'logo' => $m['logo'], 'icon' => $plugin_info['icon'], 'img' => $plugin_info['img'], 'name' => $m['name'], 'error' => $rates, 'rate' => '', 'currency' => $currency);
                 }
             }
         }
         return $result;
     } else {
         return $methods;
     }
 }
Esempio n. 16
0
function shop_currency_html($n, $in_currency = null, $out_currency = null, $format = 'h')
{
    return shop_currency($n, $in_currency, $out_currency, $format);
}
 /**
  * @param float $val
  * @param string|bool $currency
  * @return string
  */
 protected function currencyFormat($val, $currency = true)
 {
     return $this->is_html ? shop_currency_html($val, $currency) : shop_currency($val, $currency);
 }
 public function execute()
 {
     $category = $this->getCategory();
     $this->addCanonical();
     // breadcrumbs
     $root_category_id = $category['id'];
     if ($category['parent_id']) {
         $breadcrumbs = array();
         $path = array_reverse($this->getModel()->getPath($category['id']));
         $root_category = reset($path);
         $root_category_id = $root_category['id'];
         foreach ($path as $row) {
             $breadcrumbs[] = array('url' => wa()->getRouteUrl('/frontend/category', array('category_url' => waRequest::param('url_type') == 1 ? $row['url'] : $row['full_url'])), 'name' => $row['name']);
         }
         if ($breadcrumbs) {
             $this->view->assign('breadcrumbs', $breadcrumbs);
         }
     }
     $this->view->assign('root_category_id', $root_category_id);
     // sort
     if ($category['type'] == shopCategoryModel::TYPE_DYNAMIC && !$category['sort_products']) {
         $category['sort_products'] = 'create_datetime DESC';
     }
     if ($category['sort_products'] && !waRequest::get('sort')) {
         $sort = explode(' ', $category['sort_products']);
         $this->view->assign('active_sort', $sort[0] == 'count' ? 'stock' : $sort[0]);
     } elseif (!$category['sort_products'] && !waRequest::get('sort')) {
         $this->view->assign('active_sort', '');
     }
     $this->view->assign('category', $category);
     // products
     $collection = new shopProductsCollection('category/' . $category['id']);
     // filters
     if ($category['filter']) {
         $filter_ids = explode(',', $category['filter']);
         $feature_model = new shopFeatureModel();
         $features = $feature_model->getById(array_filter($filter_ids, 'is_numeric'));
         if ($features) {
             $features = $feature_model->getValues($features);
         }
         $category_value_ids = $collection->getFeatureValueIds();
         $filters = array();
         foreach ($filter_ids as $fid) {
             if ($fid == 'price') {
                 $range = $collection->getPriceRange();
                 if ($range['min'] != $range['max']) {
                     $filters['price'] = array('min' => shop_currency($range['min'], null, null, false), 'max' => shop_currency($range['max'], null, null, false));
                 }
             } elseif (isset($features[$fid]) && isset($category_value_ids[$fid])) {
                 $filters[$fid] = $features[$fid];
                 $min = $max = $unit = null;
                 foreach ($filters[$fid]['values'] as $v_id => $v) {
                     if (!in_array($v_id, $category_value_ids[$fid])) {
                         unset($filters[$fid]['values'][$v_id]);
                     } else {
                         if ($v instanceof shopRangeValue) {
                             $begin = $this->getFeatureValue($v->begin);
                             if ($min === null || $begin < $min) {
                                 $min = $begin;
                             }
                             $end = $this->getFeatureValue($v->end);
                             if ($max === null || $end > $max) {
                                 $max = $end;
                                 if ($v->end instanceof shopDimensionValue) {
                                     $unit = $v->end->unit;
                                 }
                             }
                         } else {
                             $tmp_v = $this->getFeatureValue($v);
                             if ($min === null || $tmp_v < $min) {
                                 $min = $tmp_v;
                             }
                             if ($max === null || $tmp_v > $max) {
                                 $max = $tmp_v;
                                 if ($v instanceof shopDimensionValue) {
                                     $unit = $v->unit;
                                 }
                             }
                         }
                     }
                 }
                 if (!$filters[$fid]['selectable'] && ($filters[$fid]['type'] == 'double' || substr($filters[$fid]['type'], 0, 6) == 'range.' || substr($filters[$fid]['type'], 0, 10) == 'dimension.')) {
                     if ($min == $max) {
                         unset($filters[$fid]);
                     } else {
                         $type = preg_replace('/^[^\\.]*\\./', '', $filters[$fid]['type']);
                         if ($type != 'double') {
                             $filters[$fid]['base_unit'] = shopDimension::getBaseUnit($type);
                             $filters[$fid]['unit'] = shopDimension::getUnit($type, $unit);
                             if ($filters[$fid]['base_unit']['value'] != $filters[$fid]['unit']['value']) {
                                 $dimension = shopDimension::getInstance();
                                 $min = $dimension->convert($min, $type, $filters[$fid]['unit']['value']);
                                 $max = $dimension->convert($max, $type, $filters[$fid]['unit']['value']);
                             }
                         }
                         $filters[$fid]['min'] = $min;
                         $filters[$fid]['max'] = $max;
                     }
                 }
             }
         }
         $this->view->assign('filters', $filters);
         $this->setCollection($collection);
         // fix prices
         $products = $this->view->getVars('products');
         $product_ids = array();
         foreach ($products as $p_id => $p) {
             if ($p['sku_count'] > 1) {
                 $product_ids[] = $p_id;
             }
         }
         if ($product_ids) {
             $min_price = $max_price = null;
             $tmp = array();
             foreach ($filters as $fid => $f) {
                 if ($fid == 'price') {
                     $min_price = waRequest::get('price_min');
                     if (!empty($min_price)) {
                         $min_price = (double) $min_price;
                     } else {
                         $min_price = null;
                     }
                     $max_price = waRequest::get('price_max');
                     if (!empty($max_price)) {
                         $max_price = (double) $max_price;
                     } else {
                         $max_price = null;
                     }
                 } else {
                     $fvalues = waRequest::get($f['code']);
                     if ($fvalues && !isset($fvalues['min']) && !isset($fvalues['max'])) {
                         $tmp[$fid] = $fvalues;
                     }
                 }
             }
             $product_skus = array();
             if ($tmp) {
                 $pf_model = new shopProductFeaturesModel();
                 $product_skus = $pf_model->getSkusByFeatures($product_ids, $tmp);
             } elseif ($min_price || $max_price) {
                 $ps_model = new shopProductSkusModel();
                 $rows = $ps_model->getByField('product_id', $product_ids, true);
                 foreach ($rows as $row) {
                     $product_skus[$row['product_id']][] = $row;
                 }
             }
             $default_currency = $this->getConfig()->getCurrency(true);
             if ($product_skus) {
                 foreach ($product_skus as $product_id => $skus) {
                     $currency = $products[$product_id]['currency'];
                     usort($skus, array($this, 'sortSkus'));
                     $k = 0;
                     if ($min_price || $max_price) {
                         foreach ($skus as $i => $sku) {
                             if ($min_price) {
                                 $tmp_price = shop_currency($min_price, true, $currency, false);
                                 if ($sku['price'] < $tmp_price) {
                                     continue;
                                 }
                             }
                             if ($max_price) {
                                 $tmp_price = shop_currency($max_price, true, $currency, false);
                                 if ($sku['price'] > $tmp_price) {
                                     continue;
                                 }
                             }
                             $k = $i;
                             break;
                         }
                     }
                     $sku = $skus[$k];
                     if ($products[$product_id]['sku_id'] != $sku['id']) {
                         $products[$product_id]['sku_id'] = $sku['id'];
                         $products[$product_id]['frontend_url'] .= '?sku=' . $sku['id'];
                         $products[$product_id]['price'] = shop_currency($sku['price'], $currency, $default_currency, false);
                         $products[$product_id]['compare_price'] = shop_currency($sku['compare_price'], $currency, $default_currency, false);
                     }
                 }
                 $this->view->assign('products', $products);
             }
         }
     } else {
         $this->setCollection($collection);
     }
     //отображение дополнительных размеров
     $products = $this->view->getVars('products');
     $product_features_model = new shopProductFeaturesSelectableModel();
     foreach ($products as &$p) {
         $sku_features = $product_features_model->getByProduct($p['id']);
         $sizes = $sku_features[3];
         if (!$sizes) {
             $p['sizes'] = array();
             continue;
         }
         $pf_names = $product_features_model->query("SELECT `id`, `value` FROM shop_feature_values_varchar where `id` IN (" . implode(',', $sizes) . ') ORDER BY `sort`;')->fetchAll();
         foreach ($pf_names as $key => $val) {
             $sizes[$val['id']] = $val['value'];
         }
         $p['sizes'] = $pf_names;
     }
     //отображение всех картинок
     foreach ($products as &$p) {
         $images_full = shopViewHelper::images($p['id']);
         if (isset($images_full[$p['id']])) {
             $p['image_ids'] = array_keys($images_full[$p['id']]);
         }
     }
     $this->view->assign('products', $products);
     // set meta
     $title = $category['meta_title'] ? $category['meta_title'] : $category['name'];
     wa()->getResponse()->setTitle($title);
     wa()->getResponse()->setMeta('keywords', $category['meta_keywords']);
     wa()->getResponse()->setMeta('description', $category['meta_description']);
     /**
      * @event frontend_category
      * @return array[string]string $return[%plugin_id%] html output for category
      */
     $this->view->assign('frontend_category', wa()->event('frontend_category', $category));
     $this->setThemeTemplate('category.html');
 }
 protected function getBasePrice($price, $currency)
 {
     return shop_currency($price, $currency, $this->getConfig()->getCurrency(true), false);
 }
Esempio n. 20
0
 /**
  * @param array $transaction_data
  * @return array
  */
 public function callbackConfirmationHandler($transaction_data)
 {
     $result = $this->workflowAction('callback', $transaction_data);
     if (empty($result['error'])) {
         $order_model = new shopOrderModel();
         $order = $order_model->getById($transaction_data['order_id']);
         $result['result'] = true;
         $total = $transaction_data['amount'];
         if ($transaction_data['currency_id'] != $order['currency']) {
             $total = shop_currency($total, $transaction_data['currency_id'], $order['currency'], false);
         }
         if (abs($order['total'] - $total) > 0.01) {
             $result['result'] = false;
             $result['error'] = sprintf('Invalid order amount: expect %f, but get %f', $order['total'], $total);
         } else {
             $workflow = new shopWorkflow();
             $workflow->getActionById('process')->run($transaction_data['order_id']);
         }
     }
     return $result;
 }
Esempio n. 21
0
 public function total($code)
 {
     $sql = "SELECT SUM(s.primary_price * c.quantity) FROM " . $this->table . " c\n                JOIN shop_product_skus s ON c.sku_id = s.id\n                WHERE c.code = s:code AND type = 'product'";
     $products_total = $this->query($sql, array('code' => $code))->fetchField();
     $services_total = 0;
     $sql = "SELECT c.*, s.price, s.currency FROM " . $this->table . " c JOIN\n        shop_service s ON c.service_id = s.id WHERE c.code = s:code AND type = 'service'";
     $services = $this->query($sql, array('code' => $code))->fetchAll();
     if (!$services) {
         return shop_currency($products_total, wa('shop')->getConfig()->getCurrency(true), null, false);
     }
     $variant_ids = array();
     $product_ids = array();
     $sku_ids = array();
     foreach ($services as $s) {
         if ($s['service_variant_id']) {
             $variant_ids[] = $s['service_variant_id'];
         }
         $product_ids[] = $s['product_id'];
         if ($s['currency'] == '%') {
             $sku_ids[] = $s['sku_id'];
         }
     }
     $variant_ids = array_unique($variant_ids);
     $product_ids = array_unique($product_ids);
     $sku_ids = array_unique($sku_ids);
     // get variant settings
     $variants_model = new shopServiceVariantsModel();
     $variants = $variants_model->getWithPrice($variant_ids);
     // get products/skus settings
     $product_services_model = new shopProductServicesModel();
     $products_services = $product_services_model->getByProducts($product_ids, true);
     if ($sku_ids) {
         $sku_model = new shopProductSkusModel();
         $sku_prices = $sku_model->getPrices($sku_ids);
     }
     $primary = wa('shop')->getConfig()->getCurrency();
     foreach ($services as $s) {
         $p_id = $s['product_id'];
         $sku_id = $s['sku_id'];
         $s_id = $s['service_id'];
         $v_id = $s['service_variant_id'];
         $p_services = isset($products_services[$p_id]) ? $products_services[$p_id] : array();
         $s['price'] = $variants[$v_id]['price'];
         // price variant for sku
         if (!empty($p_services['skus'][$sku_id][$s_id]['variants'][$v_id]['price'])) {
             $s['price'] = $p_services['skus'][$sku_id][$s_id]['variants'][$v_id]['price'];
         }
         if ($s['currency'] == '%') {
             $s['price'] = $s['price'] * $sku_prices[$sku_id] / 100;
         } else {
             $s['price'] = shop_currency($s['price'], $variants[$v_id]['currency'], $primary, false);
         }
         $services_total += $s['price'] * $s['quantity'];
     }
     $total = $products_total + $services_total;
     $currency = wa('shop')->getConfig()->getCurrency(false);
     if ($currency != $primary) {
         $currencies = wa('shop')->getConfig()->getCurrencies(array($currency));
         $total = $total / $currencies[$currency]['rate'];
     }
     return (double) $total;
 }
 /**
  * Filters collection products by specified conditions. 
  * 
  * @param array $data Product filtering conditions:
  *     'in_stock_only'     => whether only products with positive or unlimited stock count must be returned
  *     'price_min'         => minimum price limit
  *     'price_max'         => maximum price limit
  *     '%feature_code%'    => feature value
  */
 public function filters($data)
 {
     if ($this->filtered) {
         return;
     }
     $delete = array('page', 'sort', 'order');
     foreach ($delete as $k) {
         if (isset($data[$k])) {
             unset($data[$k]);
         }
     }
     $config = wa('shop')->getConfig();
     if (isset($data['in_stock_only'])) {
         $this->where[] = '(p.count > 0 OR p.count IS NULL)';
     }
     if (isset($data['price_min']) && $data['price_min'] !== '') {
         $this->where[] = 'p.max_price >= ' . $this->toFloat(shop_currency($data['price_min'], true, $config->getCurrency(true), false));
         unset($data['price_min']);
     }
     if (isset($data['price_max']) && $data['price_max'] !== '') {
         $this->where[] = 'p.min_price <= ' . $this->toFloat(shop_currency($data['price_max'], true, $config->getCurrency(true), false));
         unset($data['price_max']);
     }
     $feature_model = new shopFeatureModel();
     $features = $feature_model->getByField('code', array_keys($data), 'code');
     foreach ($data as $feature_code => $values) {
         if (!is_array($values)) {
             if ($values === '') {
                 continue;
             }
             $values = array($values);
         }
         if (isset($features[$feature_code])) {
             if (isset($values['min']) || isset($values['max']) || isset($values['unit'])) {
                 if (ifset($values['min'], '') === '' && ifset($values['max'], '') === '') {
                     continue;
                 } else {
                     $unit = ifset($values['unit']);
                     $min = $max = null;
                     if (isset($values['min'])) {
                         $min = $values['min'];
                         if ($unit) {
                             $min = shopDimension::getInstance()->convert($min, $features[$feature_code]['type'], null, $unit);
                         }
                     }
                     if (isset($values['max'])) {
                         $max = $values['max'];
                         if ($unit) {
                             $max = shopDimension::getInstance()->convert($max, $features[$feature_code]['type'], null, $unit);
                         }
                     }
                     $fm = $feature_model->getValuesModel($features[$feature_code]['type']);
                     $values = $fm->getValueIdsByRange($features[$feature_code]['id'], $min, $max);
                 }
             } else {
                 foreach ($values as &$v) {
                     $v = (int) $v;
                 }
             }
             if ($values) {
                 $this->addJoin('shop_product_features', 'p.id = :table.product_id AND :table.feature_id = ' . (int) $features[$feature_code]['id'], ':table.feature_value_id IN (' . implode(',', $values) . ')');
                 $this->group_by = 'p.id';
             } else {
                 $this->where[] = '0';
             }
         }
     }
     $this->filtered = true;
 }
 protected function getPrice($price, $currency, $product_price, $product_currency)
 {
     if ($currency == '%') {
         return shop_currency($price * $product_price / 100, $product_currency, null, 0);
     } else {
         return shop_currency($price, $currency, null, 0);
     }
 }
 public function backendOrderEdit($order)
 {
     if ($this->getSettings('status')) {
         $view = wa()->getView();
         if ($discountcard_number = wa()->getStorage()->get('shop/discountcard')) {
             $model = new shopDiscountcardsPluginModel();
             if ($discountcard = $model->getByField('discountcard', $discountcard_number)) {
                 $discountcard['contact'] = new waContact($discountcard['contact_id']);
                 $discountcard['amount_format'] = shop_currency($discountcard['amount']);
                 $view->assign('discountcard', $discountcard);
             }
         }
         $template_path = wa()->getAppPath('plugins/discountcards/templates/BackendOrderEdit.html', 'shop');
         $html = $view->fetch($template_path);
         return $html;
     }
 }
 public function getRate($id = null, $rate_id = null, $contact = null)
 {
     if (!$id) {
         $shipping = $this->getSessionData('shipping');
         if (!$shipping) {
             return array();
         }
         $id = $shipping['id'];
         $rate_id = $shipping['rate_id'];
     }
     if (!$contact) {
         $contact = $this->getContact();
     }
     $plugin_model = new shopPluginModel();
     $plugin_info = $plugin_model->getById($id);
     $plugin = shopShipping::getPlugin($plugin_info['plugin'], $id);
     $cart = new shopCart();
     $total = $cart->total();
     $currency = $plugin->allowedCurrency();
     $currrent_currency = wa()->getConfig()->getCurrency(false);
     if ($currency != $currrent_currency) {
         $total = shop_currency($total, $currrent_currency, $currency, false);
     }
     $rates = $plugin->getRates($this->getItems($plugin->allowedWeightUnit()), $this->getAddress($contact), array('total_price' => $total));
     if (!$rates) {
         return false;
     }
     if (is_string($rates)) {
         return $rates;
     }
     if ($rate_id) {
         $result = $rates[$rate_id];
     } else {
         $result = array('rate' => 0);
     }
     if (is_array($result['rate'])) {
         $result['rate'] = max($result['rate']);
     }
     if ($currency != $currrent_currency) {
         $result['rate'] = shop_currency($result['rate'], $currency, $currrent_currency, false);
     }
     $result['plugin'] = $plugin->getId();
     $result['name'] = $plugin_info['name'] . (!empty($result['name']) ? ' (' . $result['name'] . ')' : '');
     return $result;
 }