public function display()
 {
     $settings = wa('shop')->getConfig()->getCheckoutSettings();
     if (!empty($settings['confirmation']['terms']) && waRequest::get('terms')) {
         echo $settings['confirmation']['terms'];
         exit;
     }
     $cart = new shopCart();
     $items = $cart->items(false);
     $subtotal = $cart->total(false);
     $order = array('contact' => $this->getContact(), 'total' => $subtotal, 'items' => $items);
     $order['discount'] = shopDiscounts::calculate($order);
     $contact = $this->getContact();
     $view = wa()->getView();
     if (!$contact) {
         $view->assign('error', _w('Not enough data in the contact information to place the order.'));
         return;
     }
     $shipping_address = $contact->getFirst('address.shipping');
     if (!$shipping_address) {
         $shipping_address = array('data' => array(), 'value' => '');
     }
     $billing_address = $contact->getFirst('address.billing');
     if (!$billing_address) {
         $billing_address = array('data' => array(), 'value' => '');
     }
     $discount_rate = (double) $subtotal ? $order['discount'] / $subtotal : 0;
     $taxes = shopTaxes::apply($items, array('shipping' => $shipping_address['data'], 'billing' => $billing_address['data'], 'discount_rate' => $discount_rate));
     $tax = 0;
     $tax_included = 0;
     foreach ($taxes as $t) {
         if (isset($t['sum'])) {
             $tax += $t['sum'];
         }
         if (isset($t['sum_included'])) {
             $tax_included += $t['sum_included'];
         }
     }
     if (!isset($order['shipping'])) {
         $shipping_step = new shopOnestepCheckoutShipping();
         $rate = $shipping_step->getRate();
         if ($rate) {
             $order['shipping'] = $rate['rate'];
         } else {
             $order['shipping'] = 0;
         }
     }
     $plugin_model = new shopPluginModel();
     $params = array();
     if ($shipping = $this->getSessionData('shipping')) {
         $params['shipping_id'] = $shipping['id'];
         if ($shipping['id']) {
             $plugin_info = $plugin_model->getById($shipping['id']);
             $params['shipping_rate_id'] = $shipping['rate_id'];
             $params['shipping_name'] = $shipping['name'];
             $params['shipping_description'] = $plugin_info['description'];
         }
     }
     if ($payment_id = $this->getSessionData('payment')) {
         $params['payment_id'] = $payment_id;
         $plugin_info = $plugin_model->getById($payment_id);
         $params['payment_name'] = $plugin_info['name'];
         $params['payment_plugin'] = $plugin_info['plugin'];
         $params['payment_description'] = $plugin_info['description'];
     }
     $view->assign(array('params' => $params, 'contact' => $contact, 'items' => $items, 'shipping' => $order['shipping'], 'discount' => $order['discount'], 'total' => $subtotal - $order['discount'] + $order['shipping'] + $tax, 'tax' => $tax_included + $tax, 'subtotal' => $subtotal, 'shipping_address' => $shipping_address, 'billing_address' => !empty($settings['contactinfo']['fields']['address.billing']) ? $billing_address : false, 'terms' => !empty($settings['confirmation']['terms']) ? $settings['confirmation']['terms'] : false));
     $checkout_flow = new shopCheckoutFlowModel();
     $step_number = shopOnestepCheckout::getStepNumber('confirmation');
     // IF no errors
     $checkout_flow->add(array('step' => $step_number));
     // ELSE
     //        $checkout_flow->add(array(
     //            'step' => $step_number,
     //            'description' => ERROR MESSAGE HERE
     //        ));
 }
 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;
 }
 protected function processPostData($old_tax)
 {
     if (!waRequest::post()) {
         return $old_tax;
     }
     $tm = $this->tm;
     if (waRequest::post('delete')) {
         if ($old_tax['id']) {
             $tm->deleteById($old_tax['id']);
             $this->trm->deleteByField('tax_id', $old_tax['id']);
             $this->tzcm->deleteByField('tax_id', $old_tax['id']);
         }
         echo json_encode(array('status' => 'ok', 'data' => 'ok'));
         exit;
     }
     //
     // Prepare data for shopTaxes::save()
     //
     $tax_data = waRequest::post('tax');
     if (!is_array($tax_data)) {
         return $old_tax;
     }
     if (!empty($old_tax['id'])) {
         $tax_data['id'] = $old_tax['id'];
     }
     // countries
     $tax_data['countries'] = array();
     $tax_countries = waRequest::post('countries');
     // country global rate: iso3 => float
     if ($tax_countries && is_array($tax_countries)) {
         $tax_country_regions = waRequest::post('country_regions');
         // rates by region: iso3 => region_code => float
         if (!is_array($tax_country_regions)) {
             $tax_country_regions = array();
         }
         foreach ($tax_countries as $country_iso3 => $country_global_rate) {
             $tax_data['countries'][$country_iso3] = array('global_rate' => $country_global_rate);
             if (!empty($tax_country_regions[$country_iso3]) && is_array($tax_country_regions[$country_iso3])) {
                 $tax_data['countries'][$country_iso3]['regions'] = $tax_country_regions[$country_iso3];
             }
         }
     }
     // zip codes
     $tax_data['zip_codes'] = array();
     $zip_codes = waRequest::post('tax_zip_codes');
     $zip_rates = waRequest::post('tax_zip_rates');
     if (is_array($zip_codes) && is_array($zip_rates)) {
         foreach ($zip_codes as $i => $code) {
             if ($code) {
                 $tax_data['zip_codes'][$code] = ifset($zip_rates[$i], 0);
             }
         }
     }
     return shopTaxes::save($tax_data);
 }
 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());
 }
 private function setup()
 {
     if ($country = waRequest::post('country')) {
         if (!empty($this->countries[$country])) {
             $path = $this->getConfig()->getConfigPath('data/welcome/', false);
             $country_data = (include $path . "country_{$country}.php");
             # Main country setting
             $model = new waAppSettingsModel();
             $model->set('shop', 'country', $country);
             #currency
             if (!empty($country_data['currency'])) {
                 $currency_model = new shopCurrencyModel();
                 $sort = 0;
                 foreach ($country_data['currency'] as $code => $rate) {
                     // delete old currency info is exists
                     $currency_model->deleteById($code);
                     $currency_model->insert(array('code' => $code, 'rate' => $rate, 'sort' => $sort++), 2);
                     if ($sort == 1) {
                         $model->set('shop', 'currency', $code);
                     }
                 }
             }
             #taxes
             if (!empty($country_data['taxes'])) {
                 foreach ($country_data['taxes'] as $tax_data) {
                     shopTaxes::save($tax_data);
                 }
             }
             #custom code
             $function = 'shopWelcome' . ucfirst($country);
             if (function_exists($function)) {
                 try {
                     call_user_func_array($function, array());
                 } catch (Exception $ex) {
                     //TODO
                 }
             }
         }
     }
     if (!empty($this->types)) {
         $type_model = new shopTypeModel();
         $type_features_model = new shopTypeFeaturesModel();
         $types = waRequest::post('types');
         if (empty($types)) {
             if (!$type_features_model->countAll()) {
                 $types[] = 'default';
             }
         }
         if ($types) {
             foreach ($types as $type) {
                 $type_model->insertTemplate($type);
             }
         }
     }
     $set_model = new shopSetModel();
     $set_model->add(array('id' => 'promo', 'name' => _w('Featured on homepage'), 'type' => shopSetModel::TYPE_STATIC));
     $set_model->add(array('id' => 'bestsellers', 'name' => _w('Bestsellers'), 'type' => shopSetModel::TYPE_DYNAMIC, 'count' => 8, 'rule' => 'rating DESC'));
     // notifications
     $notifications_model = new shopNotificationModel();
     if ($notifications_model->countAll() == 0) {
         $notifications_action = new shopSettingsNotificationsAddAction();
         $notifications = $notifications_action->getTemplates();
         $params_model = new shopNotificationParamsModel();
         $events = $notifications_action->getEvents();
         foreach ($notifications as $event => $n) {
             if ($event == 'order') {
                 continue;
             }
             $data = array('name' => $events[$event]['name'] . ' (' . _w('Customer') . ')', 'event' => $event, 'transport' => 'email', 'status' => 1);
             $id = $notifications_model->insert($data);
             $params = $n;
             $params['to'] = 'customer';
             $params_model->save($id, $params);
             if ($event == 'order.create') {
                 $data['name'] = $events[$event]['name'] . ' (' . _w('Store admin') . ')';
                 $id = $notifications_model->insert($data);
                 $params['to'] = 'admin';
                 $params_model->save($id, $params);
             }
         }
     }
     /* !!! import commented out on welcome screen
        switch (waRequest::post('import')) {
        case 'demo':
        //TODO create demoproducts
        $this->redirect('?action=products');
        break;
        case 'migrate':
        $plugins = $this->getConfig()->getPlugins();
        if (empty($plugins['migrate'])) {
        $url = $this->getConfig()->getBackendUrl(true).'installer/?module=update&action=manager&install=1&app_id[shop/plugins/migrate]=webasyst';
        } else {
        $url = '?action=importexport#/migrate/';
        }
        $this->redirect($url);
        break;
        case 'scratch':
        default: */
     $this->redirect('?action=products#/welcome/');
     //        break;
     //}
 }