public function GetPrice($objTaxCode, $intTaxStatus, $taxExclusive = false)
 {
     if ($taxExclusive) {
         return $this->price;
     } elseif (_xls_get_conf('TAX_INCLUSIVE_PRICING', '') == '1') {
         $arrPrice = Tax::calculatePricesWithTax($this->price, $objTaxCode->id, $intTaxStatus);
         return $arrPrice['fltSellTotalWithTax'];
     } else {
         return $this->price;
     }
 }
Beispiel #2
0
 /**
  * Calculates the tax on an item
  * @param obj|int $taxCode      :: TaxCode or Rowid to apply
  * @param float [$fltPrice]     :: Price to calculate on
  * @return array([1] => .... [5]=>))  all the tax components
  */
 public function CalculateTax($intTaxCode, $fltPrice = false)
 {
     if ($fltPrice === false) {
         $fltPrice = $this->getPriceValue();
     }
     $arr = Tax::calculatePricesWithTax($fltPrice, $intTaxCode, $this->tax_status_id);
     $fltTaxedPrice = $arr['fltSellTotalWithTax'];
     $arrTaxes = $arr['arrTaxValues'];
     return $arrTaxes;
 }
Beispiel #3
0
 /**
  * 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;
 }
 /**
  * Add a quote item
  *
  * @param string $passkey
  * @param string $strId
  * @param int $intProductId
  * @param float $fltQty
  * @param string $strDescription
  * @param double $fltSell
  * @param double $fltDiscount
  * @return string
  */
 public function add_quote_item($passkey, $strId, $intProductId, $fltQty, $strDescription, $fltSell, $fltDiscount)
 {
     if (!$this->check_passkey($passkey)) {
         return self::FAIL_AUTH;
     }
     $objDocument = Document::LoadByIdStr($strId);
     if (!$objDocument) {
         return self::UNKNOWN_ERROR;
     }
     $objProduct = Product::model()->findByPk($intProductId);
     if (!$objProduct instanceof Product) {
         Yii::log("SOAP ERROR : Skipping Product not found for Adding to Cart (Quote) -> {$intProductId} ", 'error', 'application.' . __CLASS__ . "." . __FUNCTION__);
         return self::OK;
     }
     $strDescription = trim($strDescription);
     if (empty($strDescription)) {
         $strDescription = $objProduct->title;
     }
     if (_xls_get_conf('TAX_INCLUSIVE_PRICING') == '1') {
         $arr = Tax::calculatePricesWithTax($fltSell, $objDocument->fk_tax_code_id, $objProduct->tax_status_id);
         $fltTaxedPrice = $arr['fltSellTotalWithTax'];
     } else {
         $fltTaxedPrice = $fltSell;
     }
     $retVal = $objDocument->AddSoapProduct($objDocument->id, $objProduct, $fltQty, $strDescription, $fltTaxedPrice, $fltDiscount, CartType::quote);
     if (!$retVal) {
         return self::UNKNOWN_ERROR;
     }
     return self::OK;
 }
Beispiel #5
0
 /**
  * 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();
 }
 /**
  * Transforms an order (actually a Cart model) into an array structure
  * matching the JSON response of get_order.
  *
  * @param Cart $objCart A completed Cart model.
  * @param string[] $attributeNames An array of attribute names to return in
  * the array. Dot notation may be used for accessing model relations.
  * @return array
  */
 protected function orderToArray($objCart, $attributeNames)
 {
     // Copy the specified attributes into the array to be returned.
     $arrOrder = array();
     foreach ($attributeNames as $name) {
         // Get the relation property using dot-notation.
         $arrOrder[$name] = CHtml::value($objCart, $name);
     }
     // Add the tax rates for each cart item.
     $arrCartItems = array();
     foreach ($arrOrder['cartItems'] as $objCartItem) {
         $pricesWithTax = Tax::calculatePricesWithTax($objCartItem->sell_total, $objCart->tax_code_id, $objCartItem->product->tax_status_id);
         // Convert the CartItem from an object to an array with the
         // iterable properties.
         $arrCartItem = array();
         foreach ($objCartItem as $property => $value) {
             $arrCartItem[$property] = $value;
         }
         // Add any non-zero tax rates to the CartItem array.
         foreach ($pricesWithTax['arrTaxRates'] as $taxKey => $taxRate) {
             if ($taxRate > 0) {
                 $arrCartItem['tax' . $taxKey . '_rate'] = $taxRate;
             }
         }
         array_push($arrCartItems, $arrCartItem);
     }
     $arrOrder['cartItems'] = $arrCartItems;
     return $arrOrder;
 }