public function execute()
 {
     $id = waRequest::get('id');
     $model = new shopNotificationModel();
     $n = $model->getById($id);
     $params_model = new shopNotificationParamsModel();
     $params = $params_model->getParams($id);
     // Orders used as sample data for testing
     $om = new shopOrderModel();
     $test_orders = $om->where("paid_date IS NOT NULL AND state_id <> 'deleted'")->order('id DESC')->limit(10)->fetchAll('id');
     shopHelper::workupOrders($test_orders);
     $im = new shopOrderItemsModel();
     foreach ($im->getByField('order_id', array_keys($test_orders), true) as $i) {
         $test_orders[$i['order_id']]['items'][] = $i;
     }
     foreach ($test_orders as &$o) {
         $o['items'] = ifset($o['items'], array());
         $o['total_formatted'] = waCurrency::format('%{s}', $o['total'], $o['currency']);
     }
     $this->view->assign('n', $n);
     $this->view->assign('params', $params);
     $this->view->assign('transports', self::getTransports());
     $this->view->assign('events', $this->getEvents());
     $this->view->assign('test_orders', $test_orders);
     $this->view->assign('default_email_from', $this->getConfig()->getGeneralSettings('email'));
     $this->view->assign('sms_from', $this->getSmsFrom());
     $this->view->assign('routes', wa()->getRouting()->getByApp('shop'));
 }
 /**
  * Sends a test notification.
  * 
  * @param int $id Notification id stored in table shop_notification
  * @param array $data Order data array
  * @param string|null $to Recipient address/number. If not specified, recipient address/number from notification parameters is used.
  */
 public static function sendOne($id, $data, $to = null)
 {
     $n = self::getModel()->getOne($id);
     if ($n) {
         $params_model = new shopOrderParamsModel();
         $data['order']['params'] = $params_model->get($data['order']['id']);
         $items_model = new shopOrderItemsModel();
         $data['order']['items'] = $items_model->getItems($data['order']['id']);
         foreach ($data['order']['items'] as &$i) {
             if (!empty($i['file_name'])) {
                 $i['download_link'] = wa()->getRouteUrl('/frontend/myOrderDownload', array('id' => $data['order']['id'], 'code' => $data['order']['params']['auth_code'], 'item' => $i['id']), true);
             }
         }
         unset($i);
         if (!empty($data['order']['params']['shipping_id'])) {
             try {
                 $data['shipping_plugin'] = shopShipping::getPlugin($data['order']['params']['shipping_plugin'], $data['order']['params']['shipping_id']);
             } catch (waException $e) {
             }
         }
         $method = 'send' . ucfirst($n['transport']);
         if (method_exists('shopNotifications', $method)) {
             if ($to !== null) {
                 $n['to'] = $to;
             }
             self::$method($n, $data);
         }
     }
 }
Example #3
0
 /**
  * Amount of affiliation points given order worths.
  * @param array|int $order_or_id
  * @param float $credit_rate
  * @return float
  */
 public static function calculateBonus($order_or_id, $credit_rate = null)
 {
     if (!self::isEnabled()) {
         return 0;
     }
     if ($credit_rate === null) {
         $credit_rate = wa()->getSetting('affiliate_credit_rate', 0, 'shop');
     }
     if (!$credit_rate) {
         return 0;
     }
     if (wa_is_int($order_or_id)) {
         $om = new shopOrderModel();
         $order = $om->getOrder($order_or_id);
     } else {
         $order = $order_or_id;
     }
     // Convert order total from order currency to default currency
     $curm = new shopCurrencyModel();
     $order_currency = isset($order['currency']) ? $order['currency'] : null;
     $def_cur = wa('shop')->getConfig()->getCurrency(true);
     $affiliatable_total = $curm->convert($order['total'] - ifset($order['shipping'], 0), ifempty($order_currency, $def_cur), $def_cur);
     $product_types = wa()->getSetting('affiliate_product_types', '', 'shop');
     if (!empty($product_types)) {
         //
         // When affiliation program is enabled for certain product types only,
         // we need to calculate total afiliatable amount from order items.
         //
         $product_types = array_fill_keys(explode(',', $product_types), true);
         // Make sure order data contains items
         if (empty($order['items']) && !empty($order['id'])) {
             $oim = new shopOrderItemsModel();
             $order['items'] = $oim->getItems($order['id']);
         }
         if (empty($order['items']) || !is_array($order['items'])) {
             return 0;
         }
         // Fetch product info
         $product_ids = array();
         foreach ($order['items'] as $i) {
             $product_ids[$i['product_id']] = true;
         }
         $pm = new shopProductModel();
         $products = $pm->getById(array_keys($product_ids));
         // Calculate total value of affiliatable order items
         $items_total = 0;
         foreach ($order['items'] as $i) {
             $p = $products[$i['product_id']];
             $type_id = $p['type_id'];
             if ($i['type'] == 'product' && $type_id && !empty($product_types[$type_id])) {
                 $items_total += $curm->convert($i['price'] * $i['quantity'], ifempty($p['currency'], $def_cur), $def_cur);
             }
         }
         if ($affiliatable_total > $items_total) {
             $affiliatable_total = $items_total;
         }
     }
     return $affiliatable_total / $credit_rate;
 }
 public function execute()
 {
     $data = waRequest::post();
     if (is_numeric($data['stock_id'])) {
         $orderItemsModel = new shopOrderItemsModel();
         $orderItemsModel->updateByField('order_id', $data['order_id'], array('stock_id' => $data['stock_id']));
     }
 }
 public function execute()
 {
     $data = waRequest::post();
     $orderItemsModel = new shopOrderItemsModel();
     $where = 'order_id=' . $data['order_id'];
     $where .= $data['sku_id'] ? ' AND product_id=' . $data['product_id'] . ' AND sku_id=' . $data['sku_id'] : 'AND product_id=' . $data['product_id'];
     $result = $orderItemsModel->select('stock_id')->where($where)->fetchField();
     if ($result) {
         $id = $orderItemsModel->select('id')->where($where)->fetchField();
         if ($data['stock_id'] != $result) {
             $orderItemsModel->updateById($id, array('stock_id' => $data['stock_id']));
         }
     }
 }
 public function execute()
 {
     $contact = wa()->getUser();
     $scm = new shopCustomerModel();
     // Customer orders
     $om = new shopOrderModel();
     $orders = $om->where('contact_id=?', $contact->getId())->order('id DESC')->fetchAll('id');
     // Items for all orders, one query
     $im = new shopOrderItemsModel();
     foreach ($im->getByField('order_id', array_keys($orders), true) as $row) {
         $orders[$row['order_id']]['items'][] = $row;
     }
     // Params for all orders, one query
     $opm = new shopOrderParamsModel();
     foreach ($opm->getByField('order_id', array_keys($orders), true) as $row) {
         $orders[$row['order_id']]['params'][$row['name']] = $row['value'];
     }
     // Prepare order data for template
     $url_tmpl = wa()->getRouteUrl('/frontend/myOrder', array('id' => '%ID%'));
     $workflow = new shopWorkflow();
     foreach ($orders as $k => &$o) {
         if ($o['state_id'] == 'deleted') {
             unset($orders[$k]);
             continue;
         }
         $o['id_str'] = shopHelper::encodeOrderId($o['id']);
         $o['total_formatted'] = waCurrency::format('%{s}', $o['total'], $o['currency']);
         $o['shipping_name'] = ifset($o['params']['shipping_name'], '');
         $o['payment_name'] = ifset($o['params']['payment_name'], '');
         $o['state'] = $workflow->getStateById($o['state_id']);
         $o['url'] = str_replace('%ID%', $o['id'], $url_tmpl);
     }
     $this->view->assign('orders', array_values($orders));
     $this->view->assign('my_nav_selected', 'orders');
     // Set up layout and template from theme
     $this->setThemeTemplate('my.orders.html');
     if (!waRequest::isXMLHttpRequest()) {
         $this->setLayout(new shopFrontendLayout());
         $this->getResponse()->setTitle(_w('Orders'));
         $this->view->assign('breadcrumbs', self::getBreadcrumbs());
         $this->layout->assign('nofollow', true);
     }
 }
 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());
 }
Example #8
0
 public function reduceProductsFromStocks($order_id)
 {
     $order_params_model = new shopOrderParamsModel();
     $reduced = $order_params_model->getOne($order_id, 'reduced');
     if ($reduced) {
         return;
     }
     $items_model = new shopOrderItemsModel();
     $items = $items_model->select('*')->where("type='product' AND order_id = " . (int) $order_id)->fetchAll();
     $sku_stock = array();
     foreach ($items as $item) {
         if (!isset($sku_stock[$item['sku_id']][$item['stock_id']])) {
             $sku_stock[$item['sku_id']][$item['stock_id']] = 0;
         }
         $sku_stock[$item['sku_id']][$item['stock_id']] -= $item['quantity'];
     }
     $items_model->updateStockCount($sku_stock);
     $order_params_model->setOne($order_id, 'reduced', 1);
 }
 private function _getOrderData($order_id)
 {
     $order_model = new shopOrderModel();
     $order = $order_model->getById($order_id);
     if (!$order) {
         return false;
     }
     $order_items_model = new shopOrderItemsModel();
     $items_res = $order_items_model->getByField('order_id', $order_id, true);
     $items = array();
     $total_price = 0;
     $sku_model = new shopProductSkusModel();
     $ret = new stdClass();
     foreach ($items_res as $product) {
         $skus = $sku_model->getDataByProductId($product['product_id']);
         $product['product'] = reset($skus);
         $product_id = $product['product_id'];
         if ($product['sku_id'] != $product['product']['id']) {
             $product_id .= 's' . $product['sku_id'];
         }
         $items[] = array('product_id' => $product_id, 'qnt' => $product['quantity'], 'price' => $product['price'], 'product_name' => $product['name']);
         $total_price = $total_price + $product['price'] * $product['quantity'];
     }
     $ret->order_id = $order_id;
     $ret->items = $items;
     $ret->revenue = $total_price;
     $ret->state = $this->_switchState($order['state_id']);
     $ret->order = $order;
     return $ret;
 }
Example #10
0
 /**
  * Helper to send one message: used during real sending, as well as for test emails from follow-ups settings page.
  */
 public static function sendOne($f, $o, $customer, $contact, $to, $view = null, $general = null)
 {
     if (!$view) {
         $view = wa()->getView();
     }
     if (!$general) {
         $general = wa('shop')->getConfig()->getGeneralSettings();
     }
     $workflow = new shopWorkflow();
     $items_model = new shopOrderItemsModel();
     $o['items'] = $items_model->getItems($o['id']);
     foreach ($o['items'] as &$i) {
         if (!empty($i['file_name'])) {
             $i['download_link'] = wa()->getRouteUrl('/frontend/myOrderDownload', array('id' => $o['id'], 'code' => $o['params']['auth_code'], 'item' => $i['id']), true);
         }
     }
     unset($i);
     // Assign template vars
     $view->clearAllAssign();
     $view->assign('followup', $f);
     // row from shop_followup
     $view->assign('order', $o);
     // row from shop_order, + 'params' key
     $view->assign('customer', $contact);
     // shopCustomer
     $view->assign('order_url', wa()->getRouteUrl('/frontend/myOrderByCode', array('id' => $o['id'], 'code' => $o['params']['auth_code']), true));
     $view->assign('status', $workflow->getStateById($o['state_id'])->getName());
     // $shipping_address, $billing_address
     foreach (array('shipping', 'billing') as $k) {
         $address = shopHelper::getOrderAddress($o['params'], $k);
         $formatter = new waContactAddressOneLineFormatter(array('image' => false));
         $address = $formatter->format(array('data' => $address));
         $view->assign($k . '_address', $address['value']);
     }
     // Build email from template
     $subject = $view->fetch('string:' . $f['subject']);
     $body = $view->fetch('string:' . $f['body']);
     $from = $general['email'];
     if ($f['from']) {
         $from = $f['from'];
     }
     // Send the message
     $message = new waMailMessage($subject, $body);
     $message->setTo($to);
     $message->setFrom($from, $general['name']);
     return $message->send();
 }
 public function execute()
 {
     $id = waRequest::request('id');
     $fm = new shopFollowupModel();
     // Save data when POST came
     if ($id && waRequest::post()) {
         if (waRequest::post('delete')) {
             $f = $fm->getById($id);
             if ($f) {
                 /**
                  * @event followup_delete
                  *
                  * Notify plugins about deleted followup
                  *
                  * @param array[string]int $params['id'] followup_id
                  * @return void
                  */
                 wa()->event('followup_delete', $f);
                 $fm->deleteById($id);
             }
             exit;
         }
         $followup = waRequest::post('followup');
         if ($followup && is_array($followup)) {
             $empty_row = $fm->getEmptyRow();
             $followup = array_intersect_key($followup, $empty_row) + $empty_row;
             unset($followup['id']);
             $followup['delay'] = (double) str_replace(',', '.', ifempty($followup['delay'], '3')) * 24 * 3600;
             if (empty($followup['name'])) {
                 $followup['name'] = _w('<no name>');
             }
             $followup['from'] = $followup['from'] ? $followup['from'] : null;
             $followup['source'] = $followup['source'] ? $followup['source'] : null;
             if ($followup['from'] === 'other') {
                 $followup['from'] = waRequest::post('from');
             }
             if ($id && $id !== 'new') {
                 unset($followup['last_cron_time']);
                 $fm->updateById($id, $followup);
                 $just_created = false;
             } else {
                 $followup['last_cron_time'] = date('Y-m-d H:i:s');
                 $id = $fm->insert($followup);
                 $just_created = true;
             }
             $f = $fm->getById($id);
             if ($f) {
                 $f['just_created'] = $just_created;
                 /**
                  * Notify plugins about created or modified followup
                  * @event followup_save
                  * @param array[string]int $params['id'] followup_id
                  * @param array[string]bool $params['just_created']
                  * @return void
                  */
                 wa()->event('followup_save', $f);
             }
         }
     }
     // List of all follow-ups
     $followups = $fm->getAll('id');
     // Get data to show in form
     $followup = null;
     if ($id) {
         if (empty($followups[$id])) {
             if ($followups) {
                 $followup = reset($followups);
             }
         } else {
             $followup = $followups[$id];
         }
     }
     $test_orders = array();
     if (empty($followup)) {
         $followup = $fm->getEmptyRow();
         $followup['body'] = self::getDefaultBody();
     } else {
         // Orders used as sample data for testing
         $om = new shopOrderModel();
         $test_orders = $om->where("paid_date IS NOT NULL AND state_id <> 'deleted'")->order('id DESC')->limit(10)->fetchAll('id');
         shopHelper::workupOrders($test_orders);
         $im = new shopOrderItemsModel();
         foreach ($im->getByField('order_id', array_keys($test_orders), true) as $i) {
             $test_orders[$i['order_id']]['items'][] = $i;
         }
         foreach ($test_orders as &$o) {
             $o['items'] = ifset($o['items'], array());
             $o['total_formatted'] = waCurrency::format('%{s}', $o['total'], $o['currency']);
         }
     }
     $this->view->assign('followup', $followup);
     $this->view->assign('followups', $followups);
     $this->view->assign('test_orders', $test_orders);
     $this->view->assign('last_cron', wa()->getSetting('last_followup_cli'));
     $this->view->assign('cron_ok', wa()->getSetting('last_followup_cli') + 3600 * 36 > time());
     $this->view->assign('cron_command', 'php ' . wa()->getConfig()->getRootPath() . '/cli.php shop followup');
     $this->view->assign('default_email_from', $this->getConfig()->getGeneralSettings('email'));
     $this->view->assign('routes', wa()->getRouting()->getByApp('shop'));
 }
 public function execute()
 {
     $steps = $this->getConfig()->getCheckoutSettings();
     $current_step = waRequest::param('step', waRequest::request('step'));
     if (!$current_step) {
         $current_step = key($steps);
     }
     $title = _w('Checkout');
     if ($current_step == 'success') {
         $order_id = waRequest::get('order_id');
         if (!$order_id) {
             $order_id = wa()->getStorage()->get('shop/order_id');
             $payment_success = false;
         } else {
             $payment_success = true;
             $this->view->assign('payment_success', true);
         }
         if (!$order_id) {
             wa()->getResponse()->redirect(wa()->getRouteUrl('shop/frontend'));
         }
         $order_model = new shopOrderModel();
         $order = $order_model->getById($order_id);
         if ($order) {
             $order['_id'] = $order['id'];
         }
         if (!$payment_success) {
             $order_params_model = new shopOrderParamsModel();
             $order['params'] = $order_params_model->get($order_id);
             $order_items_model = new shopOrderItemsModel();
             $order['items'] = $order_items_model->getByField('order_id', $order_id, true);
             $payment = '';
             if (!empty($order['params']['payment_id'])) {
                 try {
                     /**
                      * @var waPayment $plugin
                      */
                     $plugin = shopPayment::getPlugin(null, $order['params']['payment_id']);
                     $payment = $plugin->payment(waRequest::post(), shopPayment::getOrderData($order, $plugin), true);
                 } catch (waException $ex) {
                     $payment = $ex->getMessage();
                 }
             }
             $order['id'] = shopHelper::encodeOrderId($order_id);
             $this->getResponse()->addGoogleAnalytics($this->getGoogleAnalytics($order));
         } else {
             $order['id'] = shopHelper::encodeOrderId($order_id);
         }
         $this->view->assign('order', $order);
         if (isset($payment)) {
             $this->view->assign('payment', $payment);
         }
     } else {
         $cart = new shopCart();
         if (!$cart->count() && $current_step != 'error') {
             $current_step = 'error';
             $this->view->assign('error', _w('Your shopping cart is empty. Please add some products to cart, and then proceed to checkout.'));
         }
         if ($current_step != 'error') {
             if (waRequest::method() == 'post') {
                 if (waRequest::post('wa_auth_login')) {
                     $login_action = new shopLoginAction();
                     $login_action->run();
                 } else {
                     $redirect = false;
                     foreach ($steps as $step_id => $step) {
                         if ($step_id == $current_step) {
                             $step_instance = $this->getStep($step_id);
                             if ($step_instance->execute()) {
                                 $redirect = true;
                             }
                         } elseif ($redirect) {
                             $this->redirect(wa()->getRouteUrl('/frontend/checkout', array('step' => $step_id)));
                         }
                     }
                     // last step
                     if ($redirect) {
                         if ($this->createOrder()) {
                             $this->redirect(wa()->getRouteUrl('/frontend/checkout', array('step' => 'success')));
                         }
                     }
                 }
             } else {
                 $this->view->assign('error', '');
             }
             $title .= ' - ' . $steps[$current_step]['name'];
             $steps[$current_step]['content'] = $this->getStep($current_step)->display();
             $this->view->assign('checkout_steps', $steps);
         }
     }
     $this->getResponse()->setTitle($title);
     $this->view->assign('checkout_current_step', $current_step);
     /**
      * @event frontend_checkout
      * @return array[string]string $return[%plugin_id%] html output
      */
     $event_params = array('step' => $current_step);
     $this->view->assign('frontend_checkout', wa()->event('frontend_checkout', $event_params));
     if (waRequest::isXMLHttpRequest()) {
         $this->setThemeTemplate('checkout.' . $current_step . '.html');
     } else {
         $this->setLayout(new shopFrontendLayout());
         $this->setThemeTemplate('checkout.html');
     }
 }