public function onActionListOrderDetails($event) { Yii::log("Running event " . print_r($event, true), 'info', 'application.' . __CLASS__ . "." . __FUNCTION__); $data_id = $event->data_id; $arrData = explode(",", $data_id); $cartId = $arrData[0]; $checkDate = $arrData[1]; $config = array('ServiceURL' => $this->getMWSUrl() . "/Orders/" . $checkDate, 'ProxyHost' => null, 'ProxyPort' => -1, 'MaxErrorRetry' => 3); $service = new MarketplaceWebServiceOrders_Client($this->MWS_ACCESS_KEY_ID, $this->MWS_SECRET_ACCESS_KEY, $this->APPLICATION_NAME, $this->APPLICATION_VERSION, $config); $request = new MarketplaceWebServiceOrders_Model_ListOrderItemsRequest(); $request->setSellerId($this->MerchantID); $request->setAmazonOrderId($cartId); // object or array of parameters $response = $this->invokeListOrderItems($service, $request); $listOrderItemsResult = $response->getListOrderItemsResult(); if ($listOrderItemsResult->isSetOrderItems()) { $objCart = Cart::LoadByIdStr($cartId); if ($objCart->cart_type == CartType::cart) { $orderItems = $listOrderItemsResult->getOrderItems(); $orderItemList = $orderItems->getOrderItem(); $shippingCost = 0; foreach ($orderItemList as $orderItem) { $strCode = $orderItem->getSellerSKU(); Yii::log("Amazon " . $cartId . " item on order " . $strCode, 'info', 'application.' . __CLASS__ . "." . __FUNCTION__); Yii::log("Order item information " . print_r($orderItem, true), 'info', 'application.' . __CLASS__ . "." . __FUNCTION__); $intQty = $orderItem->getQuantityOrdered(); $objPrice = $orderItem->getItemPrice(); $fltPrice = $objPrice->getAmount(); $strCurrency = $objPrice->getCurrencyCode(); //Amazon provides price as total for line item, but our AddToCart expects per item //so we divide if ($intQty > 1) { $fltPrice = $fltPrice / $intQty; } if ($orderItem->isSetShippingPrice()) { $objShippingPrice = $orderItem->getShippingPrice(); if ($objShippingPrice->isSetAmount()) { $shippingCost += $objShippingPrice->getAmount(); } } if ($orderItem->isSetPromotionDiscount()) { $promotionDiscount = $orderItem->getPromotionDiscount(); $fltDiscount = $promotionDiscount->getAmount(); } else { $fltDiscount = 0; } $objProduct = Product::LoadByCode($strCode); if (is_null($objProduct)) { $objCart->printed_notes .= "ERROR MISSING PRODUCT - " . "Attempted to download a product from Amazon " . $strCode . " that doesn't exist in Web Store\n"; Yii::log("Attempted to download a product from Amazon " . $strCode . " that doesn't exist in Web Store", 'error', 'application.' . __CLASS__ . "." . __FUNCTION__); } else { $objCart->AddProduct($objProduct, $intQty, CartType::order, null, $orderItem->getTitle(), $fltPrice, $fltDiscount); } $objCart->currency = $strCurrency; if (!$objCart->save()) { Yii::log("Error saving cart " . print_r($objCart->getErrors(), true), 'error', 'application.' . __CLASS__ . "." . __FUNCTION__); } } $objCart->cart_type = CartType::order; if (!$objCart->save()) { Yii::log("Error saving cart " . print_r($objCart->getErrors(), true), 'error', 'application.' . __CLASS__ . "." . __FUNCTION__); } $objShipping = $objCart->shipping; $objShipping->shipping_cost = $shippingCost; $objShipping->shipping_sell = $shippingCost; $objShipping->save(); $objCart->recalculateAndSave(); $objCart->RecalculateInventoryOnCartItems(); //A new order has been created, so run signal $objEvent = new CEventOrder('wsamazon', 'onCreateOrder', $objCart->id_str); _xls_raise_events('CEventOrder', $objEvent); } } return self::SUCCESS; }
/** * Returns an indexed array of hypothetical cart scenarios ordered by the * shipping price of the scenario from lowest to highest. * * TODO: WS-3481 Refactor this to use Cart instead of ShoppingCart. * TODO: WS-3676 Refactor Shipping::getCartScenarios to implicitly modify the cart and the checkoutform * * @param $checkoutForm * @return array Indexed array of cart scenarios where each cart scenario * is an associative array with the following keys: * formattedCartSubtotal - The formatted subtotal of the cart for this * scenario, * formattedCartTax - The formatted amount of tax on the cart, * formattedCartTotal - The formatted total price of the cart, * formattedShippingPrice - The formatted shipping price, * module - The internal module string identifier (xlsws_module.module). * priorityIndex - An index for the shipping priority (unique per provider), * priorityLabel - A label for the shipping priority, * providerId - The xlsws_module.id of the shipping provider, * providerLabel - A label for the shipping provider, * shippingLabel - A label describing the provider and priority, * shippingPrice - The shipping price for this priortity, * shoppingCart - An instance of ShoppingCart with attributes set for * this scenario, * sortOrder - The xlsws_module.sort_order. * cartItems - The individual cartItem objects for the scenario * * Formatted currencies are formatted according to the user's language. * * @throws Exception If $checkoutForm does not contain enough details to * get shipping rates. * @throws Exception If no shipping providers are enabled (via * Shipping::getAvailableShippingProviders). * @throws Exception If no shipping providers are able to provide rates * (via Shipping::addRatesToShippingProviders). */ public static function getCartScenarios($checkoutForm) { $logLevel = 'info'; if (CPropertyValue::ensureBoolean(_xls_get_conf('DEBUG_SHIPPING', false)) === true) { $logLevel = 'error'; } // TODO: This, and the setting of hasTaxModeChanged, should be // refactored out of this method. It would be better if // getCartScenarios did not have side-effects. Yii::app()->shoppingcart->setTaxCodeByCheckoutForm($checkoutForm); // We are going to modify the shopping cart and save the intermediate // values so we need to save the current value. $savedTaxId = Yii::app()->shoppingcart->tax_code_id; $cart = Yii::app()->shoppingcart->getModel(); // The call to setTaxCodeByCheckoutForm() on the shopping cart will call // recalculateAndSave(). That call is going to add taxes on shipping by // calling updateTaxShipping(). The first run will have the correct values. // On later runs, we will have taxes set in the shopping cart and add more // when we call updateTaxShipping(). Plus, we used to also make a call to // recalculateAndSave() while going through the shipping providers. Then we // would call AddTaxes() which would add taxes on top of taxes. $cart->updateTaxExclusive(); $savedStorePickup = $cart->blnStorePickup; // Get the list of shipping modules. $arrShippingProvider = self::getAvailableShippingProviders($checkoutForm); Yii::log('Got shipping modules ' . print_r($arrShippingProvider, true), $logLevel, 'application.' . __CLASS__ . '.' . __FUNCTION__); // Run each shipping module to get the rates. $arrShippingProvider = self::addRatesToShippingProviders($arrShippingProvider); // Compile each shipping providers rates into an array of "cart scenarios". // Each cart scenario is an associative array containing details about // the cart as it would be if a particular shipping option were chosen. $arrCartScenario = array(); // The shopping cart variable has to be set in case we encounter // a case where the arrShippingProvider is empty. $shoppingCart = Yii::app()->shoppingcart->getModel(); $savedStorePickup = false; foreach ($arrShippingProvider as $shippingModuleId => $shippingProvider) { // Since Store Pickup means paying local taxes, set the cart so our // scenarios work out. if ($shippingProvider['component']->IsStorePickup === true) { Yii::app()->shoppingcart->tax_code_id = TaxCode::getDefaultCode(); $cart->blnStorePickup = true; } else { Yii::app()->shoppingcart->tax_code_id = $savedTaxId; $cart->blnStorePickup = false; } // Get the "shipping" product, which may vary from module to module. $strShippingProduct = $shippingProvider['component']->LsProduct; Yii::log('Shipping Product for ' . $shippingProvider['module']->module . ' is ' . $strShippingProduct, $logLevel, 'application.' . __CLASS__ . "." . __FUNCTION__); if (Yii::app()->params['SHIPPING_TAXABLE'] == 1) { // When shipping is taxable we need to find the tax code on the actual shipping product. $objShipProduct = Product::LoadByCode($strShippingProduct); if ($objShipProduct instanceof Product === true) { $intShipProductLsid = $objShipProduct->taxStatus->lsid; } else { // We may not find a shipping product in cloud mode, so // just use -1 which skips statuses. $intShipProductLsid = -1; } } foreach ($shippingProvider['rates'] as $priorityIndex => $priority) { $priorityPrice = $priority['price']; $includeTaxInShippingPrice = false; $shippingTaxValues = array(); if (Yii::app()->params['SHIPPING_TAXABLE'] == '1') { $shippingTaxPrices = Tax::calculatePricesWithTax($priority['price'], Yii::app()->shoppingcart->tax_code_id, $intShipProductLsid); Yii::log("Shipping Taxes retrieved " . print_r($shippingTaxPrices, true), $logLevel, 'application.' . __CLASS__ . "." . __FUNCTION__); $shippingTaxValues = $shippingTaxPrices['arrTaxValues']; if (Yii::app()->params['TAX_INCLUSIVE_PRICING'] == '1') { $includeTaxInShippingPrice = true; } if ($includeTaxInShippingPrice === true) { $priorityPrice = $shippingTaxPrices['fltSellTotalWithTax']; } else { Yii::app()->shoppingcart->AddTaxes($shippingTaxValues); } } $formattedCartTax = _xls_currency(Yii::app()->shoppingcart->TaxTotal); if (Yii::app()->params['TAX_INCLUSIVE_PRICING'] == '1') { // For tax inclusive stores, we never show cart tax. This is because either: // 1. The destination is inside the tax-inclusive region, or // 2. The destination is inside a tax-exclusive region, in // which case it must be set up as 0% tax. $formattedCartTax = ''; } // TODO: Do the _xls_currency() in the formatter rather than here. $arrCartScenario[] = array('formattedCartSubtotal' => _xls_currency(Yii::app()->shoppingcart->subtotal), 'formattedCartTax' => $formattedCartTax, 'formattedCartTax1' => _xls_currency(Yii::app()->shoppingcart->tax1), 'formattedCartTax2' => _xls_currency(Yii::app()->shoppingcart->tax2), 'formattedCartTax3' => _xls_currency(Yii::app()->shoppingcart->tax3), 'formattedCartTax4' => _xls_currency(Yii::app()->shoppingcart->tax4), 'formattedCartTax5' => _xls_currency(Yii::app()->shoppingcart->tax5), 'formattedCartTotal' => _xls_currency($cart->getTotalWithShipping($priorityPrice)), 'cartTax1' => Yii::app()->shoppingcart->tax1, 'cartTax2' => Yii::app()->shoppingcart->tax2, 'cartTax3' => Yii::app()->shoppingcart->tax3, 'cartTax4' => Yii::app()->shoppingcart->tax4, 'cartTax5' => Yii::app()->shoppingcart->tax5, 'formattedShippingPrice' => _xls_currency($priorityPrice), 'module' => $shippingProvider['module']->module, 'priorityIndex' => $priorityIndex, 'priorityLabel' => $priority['label'], 'providerId' => $shippingModuleId, 'providerLabel' => $shippingProvider['component']->Name, 'shippingLabel' => $shippingProvider['component']->Name . ' ' . $priority['label'], 'shippingPrice' => $priority['price'], 'shippingPriceWithTax' => $priorityPrice, 'shippingProduct' => $strShippingProduct, 'cartAttributes' => $cart->attributes, 'cartItems' => $cart->cartItems, 'sortOrder' => $shippingProvider['module']->sort_order); // Remove shipping taxes to accommodate the next shipping priority in the loop. if (Yii::app()->params['SHIPPING_TAXABLE'] == '1' && $includeTaxInShippingPrice === false) { Yii::app()->shoppingcart->SubtractTaxes($shippingTaxValues); } } } // Restore the original storePickup boolean $cart->blnStorePickup = $savedStorePickup; // Restore the original tax code on the cart. Yii::app()->shoppingcart->setTaxCodeId($savedTaxId); // Sort the shipping options based on the price key. usort($arrCartScenario, function ($item1, $item2) { if ($item1['shippingPrice'] == $item2['shippingPrice']) { return 0; } return $item1['shippingPrice'] > $item2['shippingPrice'] ? 1 : -1; }); return $arrCartScenario; }
/** * Update shipping price and shipping tax price on the cart. */ protected function updateTaxShipping() { if (isset($this->shipping->shipping_sell) === false) { return; } if (Yii::app()->params['SHIPPING_TAXABLE'] != '1') { $this->shipping->shipping_sell_taxed = $this->shipping->shipping_sell; $this->shipping->shipping_taxable = 0; $this->shipping->save(); return; } $this->shipping->shipping_taxable = 1; $this->shipping->save(); $objNoTax = TaxCode::GetNoTaxCode(); $intNoTax = 999; if ($objNoTax instanceof TaxCode) { $intNoTax = $objNoTax->lsid; } if (Yii::app()->params['TAX_INCLUSIVE_PRICING'] == '0' && $this->tax_code_id == $intNoTax) { $this->shipping->shipping_sell_taxed = $this->shipping->shipping_sell; $this->shipping->save(); return; } $objShipProduct = Product::LoadByCode($this->shipping->shipping_method); $intTaxStatus = 0; if ($objShipProduct) { $intTaxStatus = $objShipProduct->taxStatus->lsid; } // Check if the tax status is set to no tax for it, if so, make it // default, otherwise leave it alone. if (Yii::app()->getComponent('storepickup')->IsStorePickup && $intTaxStatus) { $objTaxStatus = $objShipProduct->taxStatus; if ($objTaxStatus && $objTaxStatus->IsNoTax()) { $intTaxStatus = 0; } } $nprice_taxes = Tax::calculatePricesWithTax($this->shipping->shipping_sell, $this->tax_code_id, $intTaxStatus); $taxes = $nprice_taxes['arrTaxValues']; if ($this->tax_code_id == $intNoTax) { $this->shipping->shipping_sell_taxed = $this->shipping->shipping_sell; } else { $this->shipping->shipping_sell_taxed = $nprice_taxes['fltSellTotalWithTax']; if (Yii::app()->params['TAX_INCLUSIVE_PRICING'] != '1') { $this->tax1 += $taxes[1]; $this->tax2 += $taxes[2]; $this->tax3 += $taxes[3]; $this->tax4 += $taxes[4]; $this->tax5 += $taxes[5]; } } $this->shipping->shipping_taxable = 1; $this->shipping->save(); }