Exemplo n.º 1
0
 private function convertPrice($price, $from)
 {
     if (!$this->currency_model) {
         $this->currency_model = new shopCurrencyModel();
     }
     if (!$this->primary_currency) {
         $this->primary_currency = wa('shop')->getConfig()->getCurrency();
     }
     return $this->currency_model->convert($price, $from, $this->primary_currency);
 }
Exemplo n.º 2
0
 /** Coupon discounts implementation. */
 protected static function byCoupons(&$order, $contact, $apply)
 {
     $currency = isset($order['currency']) ? $order['currency'] : wa('shop')->getConfig()->getCurrency(false);
     $checkout_data = wa('shop')->getStorage()->read('shop/checkout');
     if (empty($checkout_data['coupon_code'])) {
         return 0;
         // !!! Will this fail when recalculating existing order?
     }
     $cm = new shopCouponModel();
     $coupon = $cm->getByField('code', $checkout_data['coupon_code']);
     if (!$coupon || !shopCouponsAction::isEnabled($coupon)) {
         return 0;
     }
     switch ($coupon['type']) {
         case '$FS':
             $order['shipping'] = 0;
             $result = 0;
             break;
         case '%':
             $result = max(0.0, min(100.0, (double) $coupon['value'])) * $order['total'] / 100.0;
             break;
         default:
             // Flat value in currency
             $result = max(0.0, (double) $coupon['value']);
             if ($currency != $coupon['type']) {
                 $crm = new shopCurrencyModel();
                 $result = (double) $crm->convert($result, $coupon['type'], $currency);
             }
             break;
     }
     if ($apply) {
         $cm->useOne($coupon['id']);
         if (empty($order['params'])) {
             $order['params'] = array();
         }
         $order['params']['coupon_id'] = $coupon['id'];
         $order['params']['coupon_discount'] = $result;
     }
     return $result;
 }
Exemplo n.º 3
0
 public function execute()
 {
     $id = waRequest::request('id', 0, 'int');
     $coupm = new shopCouponModel();
     $coupon = $coupm->getById($id);
     if ($coupon) {
         $coupon['value'] = (double) $coupon['value'];
         if (waRequest::request('delete')) {
             $coupm->delete($id);
             exit;
         }
     } else {
         if ($id) {
             throw new waException('Coupon not found.', 404);
         } else {
             // show form to create new coupon
             $coupon = $coupm->getEmptyRow();
             $coupon['code'] = self::generateCode();
         }
     }
     //
     // Process POST data
     //
     $duplicate_code_error = null;
     if (waRequest::post()) {
         $post_coupon = waRequest::post('coupon');
         if (is_array($post_coupon)) {
             $post_coupon = array_intersect_key($post_coupon, $coupon) + array('code' => '', 'type' => '%');
             if (empty($post_coupon['limit'])) {
                 $post_coupon['limit'] = null;
             }
             if (!empty($post_coupon['value'])) {
                 $post_coupon['value'] = (double) str_replace(',', '.', $post_coupon['value']);
             }
             if (empty($post_coupon['code'])) {
                 throw new waException('Bad parameters', 500);
                 // rely on JS validation
             }
             if (!empty($post_coupon['expire_datetime']) && strlen($post_coupon['expire_datetime']) == 10) {
                 $post_coupon['expire_datetime'] .= ' 23:59:59';
             }
             if ($post_coupon['type'] == '%') {
                 $post_coupon['value'] = min(max($post_coupon['value'], 0), 100);
             }
             if ($id) {
                 $coupm->updateById($id, $post_coupon);
                 echo '<script>window.location.hash = "#/coupons/' . $id . '";$.orders.dispatch();</script>';
                 exit;
             } else {
                 $post_coupon['create_contact_id'] = wa()->getUser()->getId();
                 $post_coupon['create_datetime'] = date('Y-m-d H:i:s');
                 try {
                     $id = $coupm->insert($post_coupon);
                     echo '<script>' . 'var counter = $("#s-coupons .count");' . 'var cnt = parseInt(counter.text(), 10) || 0;' . 'counter.text(cnt + 1);' . 'window.location.hash = "#/coupons/' . $id . '";' . '</script>';
                     exit;
                 } catch (waDbException $e) {
                     // Duplicate code. Show error in form.
                     $coupon = $post_coupon + $coupon;
                     $duplicate_code_error = true;
                 }
             }
         }
     }
     // Coupon types
     $curm = new shopCurrencyModel();
     $currencies = $curm->getAll('code');
     $types = self::getTypes($currencies);
     // Orders this coupon was used for
     $orders = array();
     $overall_discount = 0;
     $overall_discount_formatted = '';
     if ($coupon['id']) {
         $om = new shopOrderModel();
         $cm = new shopCurrencyModel();
         $orders = $om->getByCoupon($coupon['id']);
         shopHelper::workupOrders($orders);
         foreach ($orders as &$o) {
             $discount = ifset($o['params']['coupon_discount'], 0);
             $o['coupon_discount_formatted'] = waCurrency::format('%{s}', $discount, $o['currency']);
             if ($discount) {
                 $overall_discount += $cm->convert($discount, $o['currency'], $cm->getPrimaryCurrency());
                 $o['coupon_discount_percent'] = round($discount * 100.0 / ($discount + $o['total']), 1);
             } else {
                 $o['coupon_discount_percent'] = 0;
             }
         }
         unset($o);
         $overall_discount_formatted = waCurrency::format('%{s}', $overall_discount, $cm->getPrimaryCurrency());
     }
     $this->view->assign('types', $types);
     $this->view->assign('orders', $orders);
     $this->view->assign('coupon', $coupon);
     $this->view->assign('duplicate_code_error', $duplicate_code_error);
     $this->view->assign('overall_discount', $overall_discount);
     $this->view->assign('overall_discount_formatted', $overall_discount_formatted);
     $this->view->assign('formatted_value', shopCouponsAction::formatValue($coupon, $currencies));
     $this->view->assign('is_enabled', shopCouponsAction::isEnabled($coupon));
 }
 /**
  * @param string $field
  * @param mixed $value
  * @param array $info
  * @param array $data
  * @param null $sku_data
  * @return mixed|string
  */
 private function format($field, $value, $info = array(), $data = array(), $sku_data = null)
 {
     /**
      * @todo cpa field
      */
     /**
      * <yml_catalog>
      * <shop>
      * <currencies>
      * <categories>
      * <local_delivery_cost>
      * <offers>
      * <picture>
      * <description> и <name>
      * <delivery>, <pickup> и <store>
      * <adult>
      * <barcode>
      * <cpa> TODO
      * <rec>
      * <param> (name,unit,value)
      * <vendor>
      */
     static $currency_model;
     static $size;
     switch ($field) {
         case 'group_id':
             if ($value === 'auto') {
                 if (!empty($data['market_category'])) {
                     $value = $this->plugin()->isGroupedCategory($data['market_category']) ? $data['id'] : null;
                 } else {
                     $info['format'] = false;
                 }
             }
             break;
         case 'market_category':
             //it's product constant field
             //TODO verify it
             break;
         case 'name':
             if (!empty($sku_data['name']) && !empty($data['name']) && $sku_data['name'] != $data['name']) {
                 $value = sprintf('%s (%s)', $value, $sku_data['name']);
             }
             $value = preg_replace('/<br\\/?\\s*>/', "\n", $value);
             $value = preg_replace("/[\r\n]+/", "\n", $value);
             $value = strip_tags($value);
             $value = trim($value);
             if (mb_strlen($value) > 255) {
                 $value = mb_substr($value, 0, 252) . '...';
             }
             break;
         case 'description':
             $value = preg_replace('/<br\\/?\\s*>/', "\n", $value);
             $value = preg_replace("/[\r\n]+/", "\n", $value);
             $value = strip_tags($value);
             $value = trim($value);
             if (mb_strlen($value) > 512) {
                 $value = mb_substr($value, 0, 509) . '...';
             }
             break;
         case 'barcode':
             //может содержать несколько элементов
             $value = preg_replace('@\\D+@', '', $value);
             if (!in_array(strlen($value), array(8, 12, 13))) {
                 $value = null;
             }
             break;
         case 'sales_notes':
             $value = trim($value);
             if (mb_strlen($value) > 50) {
                 $value = mb_substr($value, 0, 50);
             }
             break;
         case 'typePrefix':
             $model = new shopTypeModel();
             if ($type = $model->getById($value)) {
                 $value = $type['name'];
             }
             break;
         case 'url':
             //max 512
             $value = preg_replace_callback('@([^\\[\\]a-zA-Z\\d_/-\\?=%&,\\.]+)@i', array(__CLASS__, 'rawurlencode'), $value);
             if ($this->data['utm']) {
                 $value .= (strpos($value, '?') ? '&' : '?') . $this->data['utm'];
             }
             $value = 'http://' . ifempty($this->data['base_url'], 'localhost') . $value;
             break;
         case 'oldprice':
             if (empty($value) || empty($this->data['export']['compare_price'])) {
                 $value = null;
                 break;
             }
         case 'price':
             if (!$currency_model) {
                 $currency_model = new shopCurrencyModel();
             }
             if ($sku_data) {
                 if (!in_array($data['currency'], $this->data['currency'])) {
                     $value = $currency_model->convert($value, $data['currency'], $this->data['primary_currency']);
                     $data['currency'] = $this->data['primary_currency'];
                 }
             } else {
                 if (!in_array($data['currency'], $this->data['currency'])) {
                     #value in default currency
                     if ($this->data['default_currency'] != $this->data['primary_currency']) {
                         $value = $currency_model->convert($value, $this->data['default_currency'], $this->data['primary_currency']);
                     }
                     $data['currency'] = $this->data['primary_currency'];
                 } elseif ($this->data['default_currency'] != $data['currency']) {
                     $value = $currency_model->convert($value, $this->data['default_currency'], $data['currency']);
                 }
             }
             break;
         case 'currencyId':
             if (!in_array($value, $this->data['currency'])) {
                 $value = $this->data['primary_currency'];
             }
             break;
         case 'rate':
             if (!in_array($value, array('CB', 'CBRF', 'NBU', 'NBK'))) {
                 $info['format'] = '%0.4f';
             }
             break;
         case 'available':
             if (!empty($sku_data) && isset($sku_data['available']) && empty($sku_data['available'])) {
                 $value = 'false';
             }
             if (is_object($value)) {
                 switch (get_class($value)) {
                     case 'shopBooleanValue':
                         /**
                          * @var $value shopBooleanValue
                          */
                         $value = $value->value ? 'true' : 'false';
                         break;
                 }
             }
             $value = ($value <= 0 || $value === 'false' || empty($value)) && $value !== null && $value !== 'true' ? 'false' : 'true';
             break;
         case 'store':
         case 'pickup':
         case 'delivery':
         case 'adult ':
             if (is_object($value)) {
                 switch (get_class($value)) {
                     case 'shopBooleanValue':
                         /**
                          * @var $value shopBooleanValue
                          */
                         $value = $value->value ? 'true' : 'false';
                         break;
                 }
             }
             $value = empty($value) || $value === 'false' ? 'false' : 'true';
             break;
         case 'picture':
             //max 512
             $values = array();
             $limit = 10;
             if (!empty($sku_data['image_id'])) {
                 $value = array(ifempty($value[$sku_data['image_id']]));
             }
             while (is_array($value) && ($image = array_shift($value)) && $limit--) {
                 if (!$size) {
                     $shop_config = wa('shop')->getConfig();
                     /**
                      * @var $shop_config shopConfig
                      */
                     $size = $shop_config->getImageSize('big');
                 }
                 $values[] = 'http://' . ifempty($this->data['base_url'], 'localhost') . shopImage::getUrl($image, $size);
             }
             $value = $values;
             break;
         case 'page_extent':
             $value = max(1, intval($value));
             break;
         case 'seller_warranty':
         case 'manufacturer_warranty':
         case 'expiry':
             /**
              * ISO 8601, например: P1Y2M10DT2H30M
              */
             $pattern = '@P((\\d+S)?(\\d+M)(\\d+D)?)?(T(\\d+H)?(\\d+M)(\\d+S)?)?@';
             $class = is_object($value) ? get_class($value) : false;
             switch ($class) {
                 case 'shopBooleanValue':
                     /**
                      * @var $value shopBooleanValue
                      */
                     $value = $value->value ? 'true' : 'false';
                     break;
                 case 'shopDimensionValue':
                     /**
                      * @var $value shopDimensionValue
                      */
                     $value = $value->convert('s', false);
                     /**
                      * @var $value int
                      */
                     if (empty($value)) {
                         $value = 'false';
                     } else {
                         $value = $this->formatCustom($value, 'ISO8601');
                     }
                     break;
                 default:
                     $value = (string) $value;
                     if (empty($value) || $value == 'false') {
                         $value = 'false';
                     } elseif (preg_match('@^\\d+$@', trim($value))) {
                         $value = $this->formatCustom(intval($value) * 3600 * 24, 'ISO8601');
                     } elseif (!preg_match($pattern, $value)) {
                         $value = 'true';
                     }
                     break;
             }
             break;
         case 'year':
             if (empty($value)) {
                 $value = null;
             }
             break;
         case 'ISBN':
             /**
              * @todo verify format
              * Код книги, если их несколько, то указываются через запятую.
              * Форматы ISBN и SBN проверяются на корректность. Валидация кодов происходит не только по длине,
              * также проверяется контрольная цифра (check-digit) – последняя цифра кода должна согласовываться
              * с остальными цифрами по определенной формуле. При разбиении ISBN на части при помощи дефиса
              * (например, 978-5-94878-004-7) код проверяется на соответствие дополнительным требованиям к
              * количеству цифр в каждой из частей.
              * Необязательный элемент.
              **/
             break;
         case 'recording_length':
             /**
              * Время звучания задается в формате mm.ss (минуты.секунды).
              **/
             if (is_object($value)) {
                 switch (get_class($value)) {
                     case 'shopDimensionValue':
                         /**
                          * @var $value shopDimensionValue
                          */
                         $value = $value->convert('s', false);
                         break;
                     default:
                         $value = (int) $value;
                         break;
                 }
             }
             $value = sprintf('%02d.%02d', floor($value / 60), $value % 60);
             break;
         case 'weight':
             /**
              * Элемент предназначен для указания веса товара. Вес указывается в килограммах с учетом упаковки.
              * Формат элемента: положительное число с точностью 0.001, разделитель целой и дробной части — точка.
              * При указании более высокой точности значение автоматически округляется следующим способом:
              * — если 4-ый знак после разделителя меньше 5, то 3-й знак сохраняется, а все последующие обнуляются;
              * — если 4-ый знак после разделителя больше или равен 5, то 3-й знак увеличивается на единицу, а все последующие обнуляются.
              **/
             if (is_object($value)) {
                 switch (get_class($value)) {
                     case 'shopDimensionValue':
                         /**
                          * @var $value shopDimensionValue
                          */
                         if ($value->type == 'weight') {
                             $value = $value->convert('kg', '%0.3f');
                         }
                         break;
                     default:
                         $value = floatval($value);
                         break;
                 }
             } else {
                 $value = floatval($value);
             }
             break;
         case 'dimensions':
             /**
              *
              * Элемент предназначен для указания габаритов товара (длина, ширина, высота) в упаковке. Размеры указываются в сантиметрах.
              * Формат элемента: три положительных числа с точностью 0.001, разделитель целой и дробной части — точка. Числа должны быть разделены символом «/» без пробелов.
              * При указании более высокой точности значение автоматически округляется следующим способом:
              * — если 4-ый знак после разделителя меньше 5, то 3-й знак сохраняется, а все последующие обнуляются;
              * — если 4-ый знак после разделителя больше или равен 5, то 3-й знак увеличивается на единицу, а все последующие обнуляются.
              **/
             /**
              * @todo use cm
              *
              */
             $parsed_value = array();
             $class = is_object($value) ? get_class($value) : false;
             switch ($class) {
                 case 'shopCompositeValue':
                     /**
                      * @var $value shopCompositeValue
                      */
                     for ($i = 0; $i < 3; $i++) {
                         $value_item = $value[$i];
                         $class_item = is_object($value_item) ? get_class($value_item) : false;
                         switch ($class_item) {
                             case 'shopDimensionValue':
                                 /**
                                  * @var $value_item shopDimensionValue
                                  */
                                 if ($value_item->type == '3d.length') {
                                     $parsed_value[] = $value_item->convert('cm', '%0.4f');
                                 } else {
                                     $parsed_value[] = sprintf('%0.4f', (string) $value_item);
                                 }
                                 break;
                             default:
                                 $parsed_value[] = sprintf('%0.4f', (string) $value_item);
                                 break;
                         }
                     }
                     break;
                 default:
                     $parsed_value = array_map('floatval', explode(':', preg_replace('@[^\\d\\.,]+@', ':', $value), 3));
                     break;
             }
             foreach ($parsed_value as &$p) {
                 $p = str_replace(',', '.', sprintf('%0.4f', $p));
                 unset($p);
             }
             $value = implode('/', $parsed_value);
             break;
         case 'age':
             /**
              * @todo
              * unit="year": 0, 6, 12, 16, 18
              * unit="month": 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
              */
             if (is_object($value)) {
                 switch (get_class($value)) {
                     case 'shopDimensionValue':
                         /**
                          * @var $value shopDimensionValue
                          */
                         if ($value->type == 'time') {
                             $value = $value->convert('month', false);
                         }
                         break;
                     default:
                         $value = intval($value);
                         break;
                 }
             } else {
                 /**
                  * @var $value shopDimensionValue
                  */
                 if (preg_match('@^(year|month)s?:(\\d+)$@', trim($value), $matches)) {
                     $value = array('unit' => $matches[1], 'value' => intval($matches[2]));
                 } else {
                     $value = intval($value);
                 }
             }
             if (!is_array($value)) {
                 if ($value > 12) {
                     $value = array('unit' => 'year', 'value' => floor($value / 12));
                 } else {
                     $value = array('unit' => 'month', 'value' => intval($value));
                 }
             }
             break;
         case 'country_of_origin':
             /**
              * @todo
              * @see http://partner.market.yandex.ru/pages/help/Countries.pdf
              */
             break;
         case 'local_delivery_cost':
             if ($value !== '') {
                 $value = max(0, floatval($value));
             }
             break;
         case 'days':
             $value = max(1, intval($value));
             break;
         case 'dataTour':
             /**
              * @todo
              * Даты заездов.
              * Необязательный элемент. Элемент <offer> может содержать несколько элементов <dataTour>.
              **/
             break;
         case 'hotel_stars':
             /**
              * @todo
              * Звезды отеля.
              * Необязательный элемент.
              **/
             break;
         case 'room':
             /**
              * @todo
              * Тип комнаты (SNG, DBL, ...).
              * Необязательный элемент.
              **/
             break;
         case 'meal':
             /**
              * @todo
              * Тип питания (All, HB, ...).
              * Необязательный элемент.
              **/
             break;
         case 'date':
             /**
              * @todo
              * Дата и время сеанса. Указываются в формате ISO 8601: YYYY-MM-DDThh:mm.
              **/
             break;
         case 'hall':
             /**
              * @todo
              * max 512
              * Ссылка на изображение с планом зала.
              **/
             //plan - property
             break;
         case 'param':
             $unit = null;
             $name = ifset($info['source_name'], '');
             if ($value instanceof shopDimensionValue) {
                 $unit = $value->unit_name;
                 $value = $value->format('%s');
             } elseif (is_array($value)) {
                 $_value = reset($value);
                 if ($_value instanceof shopDimensionValue) {
                     $unit = $_value->unit_name;
                     $values = array();
                     foreach ($value as $_value) {
                         /**
                          * @var shopDimensionValue $_value
                          */
                         $values[] = $_value->convert($unit, '%s');
                     }
                     $value = implode(', ', $values);
                 } else {
                     if (preg_match('@^(.+)\\s*\\(([^\\)]+)\\)\\s*$@', $name, $matches)) {
                         //feature name based unit
                         $unit = $matches[2];
                         $name = $matches[1];
                     }
                     $value = implode(', ', $value);
                 }
             } elseif (preg_match('@^(.+)\\s*\\(([^\\)]+)\\)\\s*$@', $name, $matches)) {
                 //feature name based unit
                 $unit = $matches[2];
                 $name = $matches[1];
             }
             $value = trim((string) $value);
             if (in_array($value, array(null, false, ''), true)) {
                 $value = null;
             } else {
                 $value = array('name' => $name, 'unit' => $unit, 'value' => trim((string) $value));
             }
             break;
     }
     $format = ifempty($info['format'], '%s');
     if (is_array($value)) {
         /**
          * @var $value array
          */
         reset($value);
         if (key($value) == 0) {
             foreach ($value as &$item) {
                 $item = str_replace('&nbsp;', ' ', $item);
                 $item = str_replace('&', '&amp;', $item);
                 $item = $this->sprintf($format, $item);
             }
             unset($item);
         }
         if (!in_array($field, array('email', 'picture', 'dataTour', 'additional', 'barcode', 'param', 'related_offer'))) {
             $value = implode(', ', $value);
         }
     } elseif ($value !== null) {
         /**
          * @var $value string
          */
         $value = str_replace('&nbsp;', ' ', $value);
         $value = str_replace('&', '&amp;', $value);
         $value = $this->sprintf($format, $value);
     }
     return $value;
 }
Exemplo n.º 5
0
 public static function discount(&$order, $contact, $apply, $other_discounts)
 {
     if (!$contact || !$contact->getId()) {
         return 0;
     }
     $checkout_data = wa()->getStorage()->read('shop/checkout');
     if (empty($checkout_data['use_affiliate'])) {
         return 0;
         // !!! Will this fail when recalculating existing order?
     }
     $usage_rate = (double) wa()->getSetting('affiliate_usage_rate', 0, 'shop');
     if ($usage_rate <= 0) {
         return 0;
     }
     $cm = new shopCustomerModel();
     $customer = $cm->getById($contact->getId());
     if (!$customer || $customer['affiliate_bonus'] <= 0) {
         return 0;
     }
     $order_total = $order['total'] - $other_discounts;
     $max_bonus = $customer['affiliate_bonus'];
     if (!empty($order['params']['affiliate_bonus'])) {
         // Recalculating existing order: take old discount into account
         $max_bonus += $order['params']['affiliate_bonus'];
     }
     $crm = new shopCurrencyModel();
     $discount = (double) $crm->convert($max_bonus * $usage_rate, wa()->getConfig()->getCurrency(true), wa()->getConfig()->getCurrency(false));
     if ($discount > $order_total) {
         $discount = $order_total;
     }
     if ($discount < $order_total) {
         $bonus_used = $max_bonus;
     } else {
         $bonus_used = (double) $crm->convert($discount, wa()->getConfig()->getCurrency(false), wa()->getConfig()->getCurrency(true)) / $usage_rate;
     }
     if (empty($order['params'])) {
         $order['params'] = array();
     }
     $order['params']['affiliate_bonus'] = $bonus_used;
     if ($apply) {
         $balance_change = $max_bonus - $bonus_used - $customer['affiliate_bonus'];
         if (abs($balance_change) > 0.0001) {
             if (!empty($order['params']['affiliate_bonus'])) {
                 $message = sprintf_wp('Recalculation of order total, new discount: %s', waCurrency::format('%{s}', $discount, wa()->getConfig()->getCurrency()));
             } else {
                 $message = sprintf_wp('Discount of %s', waCurrency::format('%{s}', $discount, wa()->getConfig()->getCurrency()));
             }
             $atm = new shopAffiliateTransactionModel();
             $atm->applyBonus($contact->getId(), $balance_change, ifset($order['id']), $message);
         }
     }
     return $discount;
 }
Exemplo n.º 6
0
 /**
  * @param int $id
  * @return bool
  */
 public function correct($id)
 {
     if (!$id) {
         return false;
     }
     $id = (int) $id;
     $product = $this->getById($id);
     $product_skus_model = new shopProductSkusModel();
     $skus = $product_skus_model->getDataByProductId($id, true);
     $currency_model = new shopCurrencyModel();
     $currency = wa('shop')->getConfig()->getCurrency();
     $price = array();
     $update_product_data = array();
     // aggregate count by stocks for product
     // Invariant: if at least one sku.count IS NULL this aggregate count IS NULL
     $product_count = 0;
     $available_sku_count = 0;
     foreach ($skus as $sku) {
         if ($sku['available']) {
             $available_sku_count++;
         }
         $price[] = $this->castValue('double', $sku['price']);
         $sku_count = 0;
         $num_of_null = 0;
         foreach ($sku['stock'] as $count) {
             if ($count === null) {
                 // turn into NULL and is not longer changing
                 $sku_count = null;
                 $num_of_null++;
             } else {
                 // Once turned into NULL value is not changed
                 if ($sku_count !== null) {
                     $sku_count += $count;
                 }
             }
         }
         if ($num_of_null == count($sku['stock'])) {
             // all stock count is null means that not multistocking
             $sku_count = $sku['count'];
         }
         // maintain product_count invariant. See above
         if ($sku['available']) {
             if ($sku_count === null) {
                 $product_count = null;
             } elseif ($product_count !== null) {
                 $product_count += $sku_count;
             }
         }
     }
     if ($available_sku_count == 0) {
         $product_count = 0;
     }
     if (!$price) {
         $price[] = 0;
     }
     $update_product_data['sku_count'] = count($skus);
     $update_product_data['min_price'] = $currency_model->convert(min($price), $product['currency'], $currency);
     $update_product_data['max_price'] = $currency_model->convert(max($price), $product['currency'], $currency);
     $update_product_data['price'] = $currency_model->convert($skus[$product['sku_id']]['price'], $product['currency'], $currency);
     if (isset($skus[$product['sku_id']]['compare_price'])) {
         $update_product_data['compare_price'] = $currency_model->convert($skus[$product['sku_id']]['compare_price'], $product['currency'], $currency);
     }
     $update_product_data['count'] = $product_count;
     $this->updateById($product['id'], $update_product_data);
     return true;
 }