public function postExecute($order_id = null, $result = null)
 {
     $data = parent::postExecute($order_id, $result);
     if ($order_id != null) {
         $log_model = new waLogModel();
         $log_model->add('order_delete', $order_id);
         $order_model = new shopOrderModel();
         $app_settings_model = new waAppSettingsModel();
         if ($data['before_state_id'] != 'refunded') {
             $update_on_create = $app_settings_model->get('shop', 'update_stock_count_on_create_order');
             // for logging changes in stocks
             shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was deleted', array('order_id' => $order_id));
             if ($update_on_create) {
                 $order_model->returnProductsToStocks($order_id);
             } else {
                 if (!$update_on_create && $data['before_state_id'] != 'new') {
                     $order_model->returnProductsToStocks($order_id);
                 }
             }
             shopProductStocksLogModel::clearContext();
         }
         $order = $order_model->getById($order_id);
         if ($order && $order['paid_date']) {
             // Remember paid_date in log params for Restore action
             $olpm = new shopOrderLogParamsModel();
             $olpm->insert(array('name' => 'paid_date', 'value' => $order['paid_date'], 'order_id' => $order_id, 'log_id' => $data['id']));
             // Empty paid_date and update stats so that deleted orders do not affect reports
             $order_model->updateById($order_id, array('paid_date' => null, 'paid_year' => null, 'paid_month' => null, 'paid_quarter' => null));
             $order_model->recalculateProductsTotalSales($order_id);
             shopCustomers::recalculateTotalSpent($order['contact_id']);
         }
     }
     return $data;
 }
 public function postExecute($order_id = null, $result = null)
 {
     $data = parent::postExecute($order_id, $result);
     $log_model = new waLogModel();
     $log_model->add('order_complete', $order_id);
     $order_model = new shopOrderModel();
     if (is_array($order_id)) {
         $order = $order_id;
         $order_id = $order['id'];
     } else {
         $order = $order_model->getById($order_id);
     }
     shopCustomers::recalculateTotalSpent($order['contact_id']);
     if ($order !== null) {
         $log_model = new shopOrderLogModel();
         $state_id = $log_model->getPreviousState($order_id);
         $app_settings_model = new waAppSettingsModel();
         $update_on_create = $app_settings_model->get('shop', 'update_stock_count_on_create_order');
         if (!$update_on_create && $state_id == 'new') {
             // jump through 'processing' state - reduce
             // for logging changes in stocks
             shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was completed', array('order_id' => $order_id));
             $order_model = new shopOrderModel();
             $order_model->reduceProductsFromStocks($order_id);
             shopProductStocksLogModel::clearContext();
         }
         $order_model->recalculateProductsTotalSales($order_id);
     }
     return $data;
 }
 public function postExecute($order_id = null, $result = null)
 {
     $data = parent::postExecute($order_id, $result);
     if ($order_id != null) {
         $log_model = new waLogModel();
         $log_model->add('order_restore', $order_id);
         $order_model = new shopOrderModel();
         $app_settings_model = new waAppSettingsModel();
         if ($this->state_id != 'refunded') {
             // for logging changes in stocks
             shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was restored', array('order_id' => $order_id));
             $update_on_create = $app_settings_model->get('shop', 'update_stock_count_on_create_order');
             if ($update_on_create) {
                 $order_model->reduceProductsFromStocks($order_id);
             } else {
                 if (!$update_on_create && $this->state_id != 'new') {
                     $order_model->reduceProductsFromStocks($order_id);
                 }
             }
             shopProductStocksLogModel::clearContext();
         }
         $order = $order_model->getById($order_id);
         if ($order && $order['paid_date']) {
             shopAffiliate::applyBonus($order_id);
             shopCustomers::recalculateTotalSpent($order['contact_id']);
         }
     }
     return $data;
 }
 public function execute()
 {
     $sku_id = waRequest::post('sku_id', 0, waRequest::TYPE_INT);
     $src_stock = waRequest::post('src_stock', 0, waRequest::TYPE_INT);
     $dst_stock = waRequest::post('dst_stock', 0, waRequest::TYPE_INT);
     $count = waRequest::post('count', 0, waRequest::TYPE_INT);
     if ($src_stock == $dst_stock || !$src_stock || !$dst_stock || !$count) {
         $this->errors[] = _w("Error when transfer");
         return;
     }
     $product_skus_model = new shopProductSkusModel();
     shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_STOCK);
     if (!$product_skus_model->transfer($sku_id, $count, $src_stock, $dst_stock)) {
         $this->errors[] = _w("Error when transfer");
         return;
     }
     shopProductStocksLogModel::clearContext();
     $sku = $product_skus_model->getById($sku_id);
     /*
     $product_stocks_model = new shopProductStocksModel();
     $data = $product_stocks_model->getStocksOfProduct($sku['product_id'], array($src_stock, $dst_stock), 'sku.count DESC');
     
     foreach ($data as &$stock) {
         foreach ($stock as &$stock_sku) {
             $stock_sku['icon'] = shopHelper::getStockCountIcon($stock_sku['count']);
         }
     }
     unset($stock, $stock_sku);
     */
     $stock_skus = array();
     $product_model = new shopProductModel();
     $data = $product_model->getProductStocksByProductId($sku['product_id']);
     if (isset($data[$sku['product_id']])) {
         $data = $data[$sku['product_id']];
         if (isset($data['stocks'][$src_stock])) {
             $stock_skus[$src_stock] = array();
             foreach ($data['stocks'][$src_stock] as $stock_sku) {
                 $stock_sku['icon'] = shopHelper::getStockCountIcon($stock_sku['count'], $src_stock);
                 $stock_skus[$src_stock][] = $stock_sku;
             }
         }
         if (isset($data['stocks'][$dst_stock])) {
             $stock_skus[$dst_stock] = array();
             foreach ($data['stocks'][$dst_stock] as $stock_sku) {
                 $stock_sku['icon'] = shopHelper::getStockCountIcon($stock_sku['count'], $dst_stock);
                 $stock_skus[$dst_stock][] = $stock_sku;
             }
         }
     }
     $this->response = array('stocks' => $stock_skus ? $stock_skus : new stdClass(), 'product_id' => $sku['product_id']);
 }
 public function postExecute($order_id = null, $result = null)
 {
     $data = parent::postExecute($order_id, $result);
     if ($order_id != null) {
         $log_model = new waLogModel();
         $log_model->add('order_process', $order_id);
         $app_settings_model = new waAppSettingsModel();
         if (!$app_settings_model->get('shop', 'update_stock_count_on_create_order')) {
             // for logging changes in stocks
             shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was processed', array('order_id' => $order_id));
             $order_model = new shopOrderModel();
             $order_model->reduceProductsFromStocks($order_id);
             shopProductStocksLogModel::clearContext();
         }
     }
     return $data;
 }
 public function postExecute($order_id = null, $result = null)
 {
     $data = parent::postExecute($order_id, $result);
     $order_model = new shopOrderModel();
     if (is_array($order_id)) {
         $order = $order_id;
         $order_id = $order['id'];
     } else {
         $order = $order_model->getById($order_id);
     }
     shopCustomers::recalculateTotalSpent($order['contact_id']);
     if ($order_id != null) {
         $log_model = new waLogModel();
         $log_model->add('order_refund', $order_id);
         $order_model = new shopOrderModel();
         $order_model->updateById($order_id, array('paid_date' => null, 'paid_year' => null, 'paid_month' => null, 'paid_quarter' => null));
         // for logging changes in stocks
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was refunded', array('order_id' => $order_id));
         $order_model->returnProductsToStocks($order_id);
         shopAffiliate::cancelBonus($order_id);
         $order_model->recalculateProductsTotalSales($order_id);
     }
     return $data;
 }
 public function postExecute($params = null, $result = null)
 {
     if (is_array($params)) {
         $order_id = $params['order_id'];
     } else {
         $order_id = $params;
     }
     $data = parent::postExecute($order_id, $result);
     $log_model = new waLogModel();
     $log_model->add('order_ship', $order_id);
     $log_model = new shopOrderLogModel();
     $state_id = $log_model->getPreviousState($order_id);
     $app_settings_model = new waAppSettingsModel();
     $update_on_create = $app_settings_model->get('shop', 'update_stock_count_on_create_order');
     if (!$update_on_create && $state_id == 'new') {
         // for logging changes in stocks
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was shipped', array('order_id' => $order_id));
         // jump through 'processing' state - reduce
         $order_model = new shopOrderModel();
         $order_model->reduceProductsFromStocks($order_id);
         shopProductStocksLogModel::clearContext();
     }
     return $data;
 }
 /**
  * @usedby stepImport
  * @param $data
  * @return bool
  */
 private function stepImportSku($data)
 {
     static $sku_primary;
     static $sku_secondary;
     static $empty_sku;
     static $empty;
     if (!isset($sku_primary)) {
         $secondary = explode(':', $this->data['secondary']);
         $sku_primary = end($secondary);
     }
     if (!isset($sku_secondary)) {
         $extra_secondary = explode(':', $this->data['extra_secondary']);
         $sku_secondary = end($extra_secondary);
     }
     if (!isset($empty)) {
         $empty = $this->reader->getEmpty();
     }
     if (!isset($empty_sku)) {
         $empty_sku = ifset($empty['skus'][-1], array());
     }
     $data += $empty;
     if ($product = $this->findProduct($data)) {
         $item_sku_id = false;
         $current_id = ifset($this->data['map'][self::STAGE_PRODUCT]);
         $id = $product->getId();
         if ($this->emulate()) {
             $target = $id ? 'found' : 'add';
             $target_sku = 'add';
         } else {
             $target = $id ? 'update' : 'new';
             $target_sku = 'new';
         }
         $key = null;
         $sku_only = false;
         $product_exists = $this->emulate() ? $product->__hash == $current_id : $id;
         if ($id && isset($data['skus'][-1])) {
             if ($this->emulate() ? $product->__hash == $current_id : $id == $current_id) {
                 $sku_only = true;
             }
             $sku = $data['skus'][-1] + $empty_sku;
             $this->castSku($sku);
             unset($data['skus'][-1]);
             $item_sku_id = -1;
             $matches = 0;
             foreach ($product->skus as $sku_id => $current_sku) {
                 if ($current_sku[$sku_primary] === ifset($sku[$sku_primary], '')) {
                     //extra workaround for empty primary attribute
                     if (false && $current_sku[$sku_primary] === '' && $sku_secondary) {
                         if (ifset($sku[$sku_secondary], '') !== $current_sku[$sku_secondary]) {
                             continue;
                         }
                     }
                     if (++$matches == 1) {
                         $item_sku_id = $sku_id;
                         $target_sku = $this->emulate() ? 'found' : 'update';
                         $sku = array_merge($current_sku, $sku);
                     } else {
                         $target_sku = 'skip';
                         $item_sku_id = false;
                         break;
                     }
                 }
             }
             if ($item_sku_id !== false) {
                 if ($item_sku_id < 0 && !isset($sku['available'])) {
                     $sku['available'] = true;
                 }
                 if (!$sku_only && !$product->skus) {
                     $data['sku_id'] = $item_sku_id;
                 }
                 $data['skus'][$item_sku_id] = $sku;
                 $key = 's:';
                 if ($item_sku_id > 0) {
                     $key .= 'u:' . $item_sku_id;
                 } else {
                     $key .= 'i:';
                     $key .= $this->getKey(array($sku_primary => ifset($sku[$sku_primary], '')));
                 }
             } else {
                 unset($data['skus']);
             }
         } elseif (isset($data['skus'][-1])) {
             if ($this->emulate() && $product->__hash == $current_id) {
                 $sku_only = true;
                 $item_sku_id = true;
             } else {
             }
             $sku = $data['skus'][-1] + $empty_sku;
             $key = 's:';
             $key .= 'i:';
             $key .= $this->getKey(array($sku_primary => ifset($sku[$sku_primary], '')));
         } elseif (!empty($data['features_selectable'])) {
             if ($product_exists) {
                 $target = $this->emulate() ? 'found' : 'update';
             }
             //TODO recount virtual SKUs count
             $key = 's:v:';
             $key .= $this->getKey($data['features_selectable']);
             if ($id) {
                 $target_sku = $this->emulate() ? 'found' : 'update';
             } else {
                 //add
             }
         }
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_IMPORT);
         if ($sku_only || empty($this->data['primary'])) {
             if ($product_exists && $item_sku_id !== false) {
                 if (!$this->emulate($product->__hash, $key)) {
                     $truncated_data = array('skus' => $data['skus']);
                     $virtual_fields = array();
                     foreach ($virtual_fields as $field) {
                         if (isset($data[$field])) {
                             $truncated_data['skus'][$item_sku_id][$field] = $data[$field];
                         }
                     }
                     if (isset($data['features'])) {
                         $model = new shopFeatureModel();
                         $features = $model->getMultipleSelectableFeaturesByType($data['type_id'], 'code');
                         if (!$features) {
                             $features = array();
                         }
                         $features['weight'] = true;
                         foreach (array_keys($features) as $code) {
                             if (isset($data['features'][$code])) {
                                 if (!isset($truncated_data['skus'][$item_sku_id]['features'])) {
                                     $truncated_data['skus'][$item_sku_id]['features'] = array();
                                 }
                                 $truncated_data['skus'][$item_sku_id]['features'][$code] = $data['features'][$code];
                             }
                         }
                     }
                     $product->save($truncated_data);
                     $this->data['map'][self::STAGE_PRODUCT] = $product->getId();
                 } else {
                     $this->data['map'][self::STAGE_PRODUCT] = $product->__hash;
                 }
             }
         } else {
             if (!$this->emulate($product->__hash, $key)) {
                 $product->save($data);
                 $this->data['map'][self::STAGE_PRODUCT] = $product->getId();
                 if (!empty($data['images'])) {
                     $this->data['map'][self::STAGE_IMAGE] = $data['images'];
                     $this->data['count'][self::STAGE_IMAGE] += count($data['images']);
                 }
             } else {
                 $this->data['map'][self::STAGE_PRODUCT] = $product->__hash;
             }
             $this->data['processed_count'][self::STAGE_PRODUCT][$target]++;
         }
         shopProductStocksLogModel::clearContext();
         if ($product->getId() || $this->emulate()) {
             $this->data['processed_count'][self::STAGE_SKU][$target_sku]++;
         }
     } else {
         $this->data['processed_count'][self::STAGE_PRODUCT]['rights']++;
     }
     return true;
 }
 public function execute($data = null)
 {
     $order_model = new shopOrderModel();
     $order = $order_model->getById($data['id']);
     $subtotal = 0;
     $services = $products = array();
     foreach ($data['items'] as $item) {
         if ($item['service_id']) {
             $services[] = $item['service_id'];
         } else {
             $products[] = $item['product_id'];
         }
     }
     $service_model = new shopServiceModel();
     $product_model = new shopProductModel();
     $services = $service_model->getById($services);
     $products = $product_model->getById($products);
     foreach ($data['items'] as &$item) {
         $item['currency'] = $order['currency'];
         $item['price'] = $this->price($item['price']);
         if ($item['service_id']) {
             $item['service'] = $services[$item['service_id']];
         } else {
             $item['product'] = $products[$item['product_id']];
         }
         $subtotal += $item['price'] * $item['quantity'];
     }
     unset($item);
     foreach (array('shipping', 'discount') as $k) {
         if (!isset($data[$k])) {
             $data[$k] = 0;
         }
     }
     $contact = new waContact($order['contact_id']);
     $shipping_address = $contact->getFirst('address.shipping');
     if (!$shipping_address) {
         $shipping_address = $contact->getFirst('address');
     }
     $shipping_address = $shipping_address ? $shipping_address['data'] : array();
     $billing_address = $contact->getFirst('address.billing');
     if (!$billing_address) {
         $billing_address = $contact->getFirst('address');
     }
     $billing_address = $billing_address ? $billing_address['data'] : array();
     $discount_rate = $subtotal ? $data['discount'] / $subtotal : 0;
     $taxes = shopTaxes::apply($data['items'], array('shipping' => $shipping_address, 'billing' => $billing_address, 'discount_rate' => $discount_rate), $order['currency']);
     $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'];
         }
     }
     $data['tax'] = $tax_included + $tax;
     $data['total'] = $subtotal + $tax + $this->price($data['shipping']) - $this->price($data['discount']);
     // for logging changes in stocks
     shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was edited', array('order_id' => $data['id']));
     // update
     $order_model->update($data, $data['id']);
     $log_model = new waLogModel();
     $log_model->add('order_edit', $data['id']);
     shopProductStocksLogModel::clearContext();
     if (!empty($data['params'])) {
         $params_model = new shopOrderParamsModel();
         $params_model->set($data['id'], $data['params'], false);
     }
     return true;
 }
 public function postExecute($order_id = null, $result = null)
 {
     $order_id = $result['order_id'];
     $data = is_array($result) ? $result : array();
     $data['order_id'] = $order_id;
     $data['action_id'] = $this->getId();
     $data['before_state_id'] = '';
     $data['after_state_id'] = 'new';
     $order_log_model = new shopOrderLogModel();
     $order_log_model->add($data);
     /**
      * @event order_action.create
      */
     wa('shop')->event('order_action.create', $data);
     $order_model = new shopOrderModel();
     $order = $order_model->getById($order_id);
     $params_model = new shopOrderParamsModel();
     $order['params'] = $params_model->get($order_id);
     // send notifications
     shopNotifications::send('order.' . $this->getId(), array('order' => $order, 'customer' => new waContact($order['contact_id']), 'status' => $this->getWorkflow()->getStateById($data['after_state_id'])->getName(), 'action_data' => $data));
     // Update stock count, but take into account 'update_stock_count_on_create_order'-setting
     $app_settings_model = new waAppSettingsModel();
     if ($app_settings_model->get('shop', 'update_stock_count_on_create_order')) {
         // for logging changes in stocks
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was placed', array('order_id' => $order_id));
         $order_model->reduceProductsFromStocks($order_id);
         shopProductStocksLogModel::clearContext();
     }
     return $order_id;
 }
 public function execute()
 {
     $update = waRequest::post('update');
     // just update one or any field of product
     if ($update) {
         $this->update($update);
         return;
     }
     $data = waRequest::post('product');
     $id = empty($data['id']) || !intval($data['id']) ? null : $data['id'];
     if (!$id && isset($data['id'])) {
         unset($data['id']);
     }
     # edit product info - check rights
     $product_model = new shopProductModel();
     if ($id) {
         if (!$product_model->checkRights($id)) {
             throw new waRightsException(_w("Access denied"));
         }
     } else {
         if (!$product_model->checkRights($data)) {
             throw new waRightsException(_w("Access denied"));
         }
     }
     $skus = waRequest::post('skus', array());
     if (isset($data['skus'])) {
         foreach ($skus as $s_id => $s) {
             if (isset($data['skus'][$s_id])) {
                 $data['skus'][$s_id] += $s;
             } else {
                 $data['skus'][$s_id] = $s;
             }
         }
     } else {
         $data['skus'] = $skus;
     }
     if (empty($data['categories'])) {
         $data['categories'] = array();
     }
     if (empty($data['tags'])) {
         $data['tags'] = array();
     }
     if (empty($data['features_selectable'])) {
         $data['features_selectable'] = array();
     }
     # verify sku_type before save
     if ($data['type_id']) {
         $features_model = new shopFeatureModel();
         if ($features_model->isTypeMultipleSelectable($data['type_id'])) {
             if ($data['sku_type'] == shopProductModel::SKU_TYPE_SELECTABLE) {
                 if (empty($data['features_selectable'])) {
                     throw new waException(_w("Check at least one feature value"));
                 }
             }
         } else {
             $data['sku_type'] = shopProductModel::SKU_TYPE_FLAT;
         }
     } else {
         $data['sku_type'] = shopProductModel::SKU_TYPE_FLAT;
     }
     if ($data['sku_type'] == shopProductModel::SKU_TYPE_FLAT) {
         $data['features_selectable'] = array();
     }
     try {
         $product = new shopProduct($id);
         // for logging changes in stocks
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_PRODUCT);
         if ($product->save($data, true, $this->errors)) {
             $features_counts = null;
             if ($product->sku_type == shopProductModel::SKU_TYPE_SELECTABLE) {
                 $features_counts = array();
                 foreach ($product->features_selectable as $f) {
                     if (isset($f['selected'])) {
                         $features_counts[] = $f['selected'];
                     } else {
                         $features_counts[] = count($f['values']);
                     }
                 }
                 $features_total_count = array_product($features_counts);
                 $this->response['features_selectable_strings'] = array('options' => implode(' x ', $features_counts) . ' ' . _w('option', 'options', $features_total_count), 'skus' => _w('%d SKU in total', '%d SKUs in total', $features_total_count));
             }
             shopProductStocksLogModel::clearContext();
             if ($id) {
                 $this->logAction('product_edit', $id);
             } else {
                 $this->logAction('product_add', $product->getId());
             }
             $this->response['id'] = $product->getId();
             $this->response['name'] = $product->name;
             $this->response['url'] = $product->url;
             $this->response['frontend_urls'] = $this->getUrl($product);
             $this->response['raw'] = $this->workupData($product->getData());
             $sales_rate = waRequest::post('sales_rate', 0, waRequest::TYPE_STRING_TRIM);
             $sales_rate = (double) str_replace(',', '.', $sales_rate);
             $runout = $product->getRunout($sales_rate);
             if (!empty($runout['product'])) {
                 $runout['product']['date_str'] = wa_date("humandate", $runout['product']['date']);
                 $runout['product']['days_str'] = _w('%d day', '%d days', $runout['product']['days']);
                 if ($runout['product']['days'] < 3 * 365 && $runout['product']['days'] > 0) {
                     $runout['product_str'] = sprintf(_w('Based on last 30 days sales dynamic (%d items of %s sold during last 30 days), you will run out of %s in <strong>%d days</strong> (on %s)'), $sales_rate * 30, $product->name, $product->name, $runout['product']['days'], wa_date("humandate", $runout['product']['date']));
                 }
             } else {
                 $runout['product'] = new stdClass();
                 /* {} */
             }
             if (!empty($runout['sku'])) {
                 foreach ($runout['sku'] as &$sk_r) {
                     if (empty($sk_r['stock'])) {
                         $sk_r['date_str'] = wa_date("humandate", $sk_r['date']);
                         $sk_r['days_str'] = _w('%d day', '%d days', $sk_r['days']);
                     } else {
                         foreach ($sk_r['stock'] as &$st_r) {
                             $st_r['date_str'] = wa_date("humandate", $st_r['date']);
                             $st_r['days_str'] = _w('%d day', '%d days', $st_r['days']);
                         }
                     }
                 }
                 unset($sk_r, $st_r);
             } else {
                 $runout['sku'] = new stdClass();
                 /* {} */
             }
             $this->response['raw']['runout'] = $runout;
             $this->response['storefront_map'] = $product_model->getStorefrontMap($product->id);
         }
     } catch (Exception $ex) {
         $this->setError($ex->getMessage());
     }
 }