oxbasket.php

Go to the documentation of this file.
00001 <?php
00002 
00007 class oxBasket extends oxSuperCfg
00008 {
00014     protected $_aBasketContents = array();
00015 
00021     protected $_iProductsCnt = 0;
00022 
00028     protected $_dItemsCnt = 0.0;
00029 
00035     protected $_dWeight = 0.0;
00036 
00042     protected $_oPrice = null;
00043 
00049     protected $_isCalculationModeNetto = null;
00050 
00056     protected $_dNettoSum = null;
00057 
00063     protected $_dBruttoSum = null;
00064 
00070     protected $_oProductsPriceList = null;
00071 
00077     protected $_aDiscounts = array();
00078 
00084     protected $_aItemDiscounts = array();
00085 
00091     protected $_sOrderId = null;
00092 
00098     protected $_aVouchers = array();
00099 
00105     protected $_aCosts = array();
00106 
00112     protected $_oDiscountProductsPriceList = null;
00113 
00119     protected $_oNotDiscountedProductsPriceList = null;
00120 
00126     protected $_blUpdateNeeded = true;
00127 
00133     protected $_aBasketSummary = null;
00134 
00140     protected $_sPaymentId = null;
00141 
00147     protected $_sShippingSetId = null;
00148 
00154     protected $_oUser = null;
00155 
00161     protected $_oTotalDiscount = null;
00162 
00168     protected $_oVoucherDiscount = null;
00169 
00175     protected $_oCurrency = null;
00176 
00182     protected $_blSkipVouchersAvailabilityChecking = null;
00183 
00189     protected $_dDiscountedProductNettoPrice = null;
00190 
00196     protected $_aDiscountedVats = null;
00197 
00203     protected $_blSkipDiscounts = false;
00204 
00210     protected $_oDeliveryPrice = null;
00211 
00217      protected $_blCheckStock = true;
00218 
00224     protected $_blCalcDiscounts = true;
00225 
00231     protected $_sBasketCategoryId = null;
00232 
00238     protected $_blShowCatChangeWarning = false;
00239 
00245     protected $_sTsProductId = null;
00246 
00251     protected $_blNewITemAdded = null;
00252 
00257     protected $_blDownloadableProducts = null;
00258 
00259 
00265     public function isCalculationModeNetto()
00266     {
00267         if ( $this->_isCalculationModeNetto === null ) {
00268             $this->setCalculationModeNetto( $this->isPriceViewModeNetto() );
00269         }
00270 
00271         return $this->_isCalculationModeNetto;
00272     }
00273 
00281     public function setCalculationModeNetto( $blNettoMode = true )
00282     {
00283         $this->_isCalculationModeNetto = (bool) $blNettoMode;
00284     }
00285 
00291     public function getNettoSum()
00292     {
00293         return $this->_dNettoSum;
00294     }
00295 
00301     public function getBruttoSum()
00302     {
00303         return $this->_dBruttoSum;
00304     }
00305 
00313     public function setNettoSum( $dNettoSum )
00314     {
00315         $this->_dNettoSum = $dNettoSum;
00316     }
00317 
00325     public function setBruttoSum( $dBruttoSum )
00326     {
00327         $this->_dBruttoSum = $dBruttoSum;
00328     }
00329 
00335     public function isEnabled()
00336     {
00337         return !oxRegistry::getUtils()->isSearchEngine();
00338     }
00339 
00349     protected function _changeBasketItemKey($sOldKey, $sNewKey, $value = null)
00350     {
00351         reset($this->_aBasketContents);
00352         $iOldKeyPlace = 0;
00353         while (key($this->_aBasketContents) != $sOldKey && next($this->_aBasketContents)) {
00354             ++$iOldKeyPlace;
00355         }
00356         $aNewCopy = array_merge(
00357             array_slice($this->_aBasketContents, 0, $iOldKeyPlace, true),
00358             array($sNewKey => $value),
00359             array_slice($this->_aBasketContents, $iOldKeyPlace+1, count($this->_aBasketContents)-$iOldKeyPlace, true)
00360         );
00361         $this->_aBasketContents = $aNewCopy;
00362     }
00363 
00379     public function addToBasket( $sProductID, $dAmount, $aSel = null, $aPersParam = null, $blOverride = false, $blBundle = false, $sOldBasketItemId = null )
00380     {
00381         // enabled ?
00382         if ( !$this->isEnabled() )
00383             return null;
00384 
00385         // basket exclude
00386         if ( $this->getConfig()->getConfigParam( 'blBasketExcludeEnabled' ) ) {
00387             if ( !$this->canAddProductToBasket( $sProductID ) ) {
00388                 $this->setCatChangeWarningState( true );
00389                 return null;
00390             } else {
00391                 $this->setCatChangeWarningState( false );
00392             }
00393         }
00394 
00395         $sItemId = $this->getItemKey( $sProductID, $aSel, $aPersParam, $blBundle );
00396         if ( $sOldBasketItemId && ( strcmp( $sOldBasketItemId, $sItemId ) != 0 ) ) {
00397             if ( isset( $this->_aBasketContents[$sItemId] ) ) {
00398                 // we are merging, so params will just go to the new key
00399                 unset( $this->_aBasketContents[$sOldBasketItemId] );
00400                 // do not override stock
00401                 $blOverride = false;
00402             } else {
00403                 // value is null - means isset will fail and real values will be filled
00404                 $this->_changeBasketItemKey( $sOldBasketItemId, $sItemId );
00405             }
00406         }
00407 
00408         // after some checks item must be removed from basket
00409         $blRemoveItem = false;
00410 
00411         // initialling exception storage
00412         $oEx = null;
00413 
00414         if ( isset( $this->_aBasketContents[$sItemId] ) ) {
00415 
00416             //updating existing
00417             try {
00418                 // setting stock check status
00419                 $this->_aBasketContents[$sItemId]->setStockCheckStatus( $this->getStockCheckMode() );
00420                 //validate amount
00421                 //possibly throws exception
00422                 $this->_aBasketContents[$sItemId]->setAmount( $dAmount, $blOverride, $sItemId );
00423             } catch( oxOutOfStockException $oEx ) {
00424                 // rethrow later
00425             }
00426 
00427         } else {
00428             //inserting new
00429             $oBasketItem = oxNew( 'oxbasketitem' );
00430             try {
00431                 $oBasketItem->setStockCheckStatus( $this->getStockCheckMode() );
00432                 $oBasketItem->init( $sProductID, $dAmount, $aSel, $aPersParam, $blBundle );
00433             } catch( oxNoArticleException $oEx ) {
00434                 // in this case that the article does not exist remove the item from the basket by setting its amount to 0
00435                 //$oBasketItem->dAmount = 0;
00436                 $blRemoveItem = true;
00437 
00438             } catch( oxOutOfStockException $oEx ) {
00439                 // rethrow later
00440             } catch ( oxArticleInputException $oEx ) {
00441                 // rethrow later
00442                 $blRemoveItem = true;
00443             }
00444 
00445             $this->_aBasketContents[$sItemId] = $oBasketItem;
00446         }
00447 
00448         //in case amount is 0 removing item
00449         if ( $this->_aBasketContents[$sItemId]->getAmount() == 0 || $blRemoveItem ) {
00450             $this->removeItem( $sItemId );
00451         } elseif ( $blBundle ) {
00452             //marking bundles
00453             $this->_aBasketContents[$sItemId]->setBundle( true );
00454         }
00455 
00456         //calling update method
00457         $this->onUpdate();
00458 
00459         if ( $oEx ) {
00460             throw $oEx;
00461         }
00462 
00463         // notifying that new basket item was added
00464         if (!$blBundle) {
00465             $this->_addedNewItem( $sProductID, $dAmount, $aSel, $aPersParam, $blOverride, $blBundle, $sOldBasketItemId );
00466         }
00467 
00468         // returning basket item object
00469         return $this->_aBasketContents[$sItemId];
00470     }
00471 
00479     public function addOrderArticleToBasket( $oOrderArticle )
00480     {
00481         // adding only if amount > 0
00482         if ( $oOrderArticle->oxorderarticles__oxamount->value > 0 && !$oOrderArticle->isBundle() ) {
00483 
00484             $this->_isForOrderRecalculation = true;
00485             $sItemId = $oOrderArticle->getId();
00486 
00487             //inserting new
00488             $this->_aBasketContents[$sItemId] = oxNew( 'oxbasketitem' );
00489             $this->_aBasketContents[$sItemId]->initFromOrderArticle( $oOrderArticle );
00490             $this->_aBasketContents[$sItemId]->setWrapping( $oOrderArticle->oxorderarticles__oxwrapid->value );
00491             $this->_aBasketContents[$sItemId]->setBundle( $oOrderArticle->isBundle() );
00492 
00493             //calling update method
00494             $this->onUpdate();
00495 
00496             return $this->_aBasketContents[$sItemId];
00497         } elseif ( $oOrderArticle->isBundle() ) {
00498             // deleting bundles, they are handled automatically
00499             $oOrderArticle->delete();
00500         }
00501 
00502         return null;
00503     }
00504 
00512     public function setStockCheckMode( $blCheck )
00513     {
00514         $this->_blCheckStock = $blCheck;
00515     }
00516 
00522     public function getStockCheckMode()
00523     {
00524         return $this->_blCheckStock;
00525     }
00526 
00539     public function getItemKey( $sProductId, $aSel = null, $aPersParam = null, $blBundle = false, $sAdditionalParam = '' )
00540     {
00541         $aSel = ( $aSel != null) ? $aSel : array (0=>'0');
00542 
00543         $sItemKey = md5( $sProductId.'|'.serialize( $aSel ).'|'.serialize( $aPersParam ).'|'.( int ) $blBundle . '|' . serialize( $sAdditionalParam ) );
00544 
00545         return $sItemKey;
00546     }
00547 
00548 
00556     public function removeItem( $sItemKey )
00557     {
00558         if ($this->getConfig()->getConfigParam( 'blPsBasketReservationEnabled' )) {
00559             if (isset($this->_aBasketContents[$sItemKey])) {
00560                 $sArticleId = $this->_aBasketContents[$sItemKey]->getProductId();
00561                 if ($sArticleId) {
00562                     $this->getSession()
00563                             ->getBasketReservations()
00564                             ->discardArticleReservation($sArticleId);
00565                 }
00566             }
00567         }
00568         unset( $this->_aBasketContents[$sItemKey] );
00569 
00570         // basket exclude
00571         if ( !count($this->_aBasketContents) && $this->getConfig()->getConfigParam( 'blBasketExcludeEnabled' ) ) {
00572             $this->setBasketRootCatId(null);
00573         }
00574     }
00575 
00581     protected function _clearBundles()
00582     {
00583         reset( $this->_aBasketContents );
00584         while ( list( $sItemKey, $oBasketItem ) = each( $this->_aBasketContents ) ) {
00585             if ( $oBasketItem->isBundle() ) {
00586                 $this->removeItem( $sItemKey );
00587             }
00588         }
00589     }
00590 
00598     protected function _getArticleBundles( $oBasketItem )
00599     {
00600         $aBundles = array();
00601 
00602         if ( $oBasketItem->isBundle() ) {
00603             return $aBundles;
00604         }
00605 
00606         $oArticle = $oBasketItem->getArticle( true );
00607         if ( $oArticle && $oArticle->oxarticles__oxbundleid->value ) {
00608             $aBundles[$oArticle->oxarticles__oxbundleid->value] = 1;
00609         }
00610 
00611         return $aBundles;
00612     }
00613 
00622     protected function _getItemBundles( $oBasketItem, $aBundles = array() )
00623     {
00624         if ( $oBasketItem->isBundle() ) {
00625             return array();
00626         }
00627 
00628         // does this object still exists ?
00629         if ( $oArticle = $oBasketItem->getArticle() ) {
00630             $aDiscounts = oxRegistry::get("oxDiscountList")->getBasketItemBundleDiscounts( $oArticle, $this, $this->getBasketUser() );
00631 
00632             foreach ( $aDiscounts as $oDiscount ) {
00633 
00634                 $iAmnt = $oDiscount->getBundleAmount( $oBasketItem->getAmount() );
00635                 if ( $iAmnt ) {
00636                     //init array element
00637                     if ( !isset( $aBundles[$oDiscount->oxdiscount__oxitmartid->value] ) ) {
00638                         $aBundles[$oDiscount->oxdiscount__oxitmartid->value] = 0;
00639                     }
00640 
00641                     if ($oDiscount->oxdiscount__oxitmmultiple->value) {
00642                         $aBundles[$oDiscount->oxdiscount__oxitmartid->value] += $iAmnt;
00643                     } else {
00644                         $aBundles[$oDiscount->oxdiscount__oxitmartid->value] = $iAmnt;
00645                     }
00646                 }
00647             }
00648         }
00649 
00650         return $aBundles;
00651     }
00652 
00660     protected function _getBasketBundles( $aBundles = array() )
00661     {
00662         $aDiscounts = oxRegistry::get("oxDiscountList")->getBasketBundleDiscounts( $this, $this->getBasketUser() );
00663 
00664         // calculating amount of non bundled/discount items
00665         $dAmount = 0;
00666         foreach ( $this->_aBasketContents as $oBasketItem ) {
00667             if ( !( $oBasketItem->isBundle() || $oBasketItem->isDiscountArticle() ) ) {
00668                 $dAmount += $oBasketItem->getAmount();
00669             }
00670         }
00671 
00672         foreach ( $aDiscounts as $oDiscount ) {
00673             if ($oDiscount->oxdiscount__oxitmartid->value) {
00674                 if ( !isset( $aBundles[$oDiscount->oxdiscount__oxitmartid->value] ) ) {
00675                     $aBundles[$oDiscount->oxdiscount__oxitmartid->value] = 0;
00676                 }
00677 
00678                 $aBundles[$oDiscount->oxdiscount__oxitmartid->value] += $oDiscount->getBundleAmount( $dAmount );
00679             }
00680         }
00681 
00682         return $aBundles;
00683     }
00684 
00691     protected function _addBundles()
00692     {
00693         $aBundles = array();
00694         // iterating through articles and binding bundles
00695         foreach ( $this->_aBasketContents as $key => $oBasketItem ) {
00696             try {
00697                 // adding discount type bundles
00698                 if ( !$oBasketItem->isDiscountArticle() && !$oBasketItem->isBundle() ) {
00699                     $aBundles = $this->_getItemBundles( $oBasketItem, $aBundles );
00700                 } else {
00701                     continue;
00702                 }
00703 
00704                     // adding item type bundles
00705                     $aArtBundles = $this->_getArticleBundles( $oBasketItem );
00706 
00707                     // adding bundles to basket
00708                     $this->_addBundlesToBasket( $aArtBundles );
00709             } catch ( oxNoArticleException $oEx ) {
00710                 $this->removeItem( $key );
00711                 oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx );
00712             } catch( oxArticleInputException $oEx ) {
00713                 $this->removeItem( $key );
00714                 oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx );
00715             }
00716         }
00717 
00718         // adding global basket bundles
00719         $aBundles = $this->_getBasketBundles( $aBundles );
00720 
00721         // adding all bundles to basket
00722         if ( $aBundles ) {
00723             $this->_addBundlesToBasket( $aBundles );
00724         }
00725     }
00726 
00734     protected function _addBundlesToBasket( $aBundles )
00735     {
00736         foreach ( $aBundles as $sBundleId => $dAmount ) {
00737             if ( $dAmount ) {
00738                 try {
00739                     if ( $oBundleItem = $this->addToBasket( $sBundleId, $dAmount, null, null, false, true ) ) {
00740                         $oBundleItem->setAsDiscountArticle( true );
00741                     }
00742                 } catch(oxArticleException $oEx) {
00743                     // caught and ignored
00744                 }
00745             }
00746         }
00747 
00748     }
00749 
00755     protected function _calcItemsPrice()
00756     {
00757         // resetting
00758         $this->setSkipDiscounts( false );
00759         $this->_iProductsCnt = 0; // count different types
00760         $this->_dItemsCnt    = 0; // count of item units
00761         $this->_dWeight      = 0; // basket weight
00762 
00763         $this->_oProductsPriceList = oxNew( 'oxpricelist' );
00764         $this->_oDiscountProductsPriceList = oxNew( 'oxpricelist' );
00765         $this->_oNotDiscountedProductsPriceList = oxNew( 'oxpricelist' );
00766 
00767         $oDiscountList = oxRegistry::get("oxDiscountList");
00768 
00769         foreach ( $this->_aBasketContents as $oBasketItem ) {
00770             $this->_iProductsCnt++;
00771             $this->_dItemsCnt += $oBasketItem->getAmount();
00772             $this->_dWeight   += $oBasketItem->getWeight();
00773 
00774             if ( !$oBasketItem->isDiscountArticle() && ( $oArticle = $oBasketItem->getArticle( true ) ) ) {
00775 
00776                 $oBasketPrice = $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $this );
00777                 $oBasketItem->setRegularUnitPrice( clone $oBasketPrice );
00778 
00779                 if ( !$oArticle->skipDiscounts() && $this->canCalcDiscounts() ) {
00780                     // apply basket type discounts for item
00781                     $aDiscounts = $oDiscountList->getBasketItemDiscounts( $oArticle, $this, $this->getBasketUser() );
00782                     reset( $aDiscounts );
00783                     foreach ( $aDiscounts as $oDiscount ) {
00784                         $oBasketPrice->setDiscount($oDiscount->getAddSum(), $oDiscount->getAddSumType());
00785                     }
00786                     $oBasketPrice->calculateDiscount();
00787                 } else {
00788                     $oBasketItem->setSkipDiscounts( true );
00789                     $this->setSkipDiscounts( true );
00790                 }
00791 
00792                 $oBasketItem->setPrice( $oBasketPrice );
00793                 $this->_oProductsPriceList->addToPriceList( $oBasketItem->getPrice() );
00794 
00795                 //P collect discount values for basket items which are discountable
00796                 if ( !$oArticle->skipDiscounts() ) {
00797 
00798                     $this->_oDiscountProductsPriceList->addToPriceList( $oBasketItem->getPrice() );
00799                 } else {
00800                     $this->_oNotDiscountedProductsPriceList->addToPriceList( $oBasketItem->getPrice() );
00801                     $oBasketItem->setSkipDiscounts( true );
00802                     $this->setSkipDiscounts( true );
00803                 }
00804             } elseif ( $oBasketItem->isBundle() ) {
00805                 // if bundles price is set to zero
00806                 $oPrice = oxNew( "oxprice");
00807                 $oBasketItem->setPrice( $oPrice );
00808             }
00809         }
00810     }
00811 
00819     public function setDiscountCalcMode( $blCalcDiscounts )
00820     {
00821         $this->_blCalcDiscounts = $blCalcDiscounts;
00822     }
00823 
00829     public function canCalcDiscounts()
00830     {
00831         return $this->_blCalcDiscounts;
00832     }
00833 
00843     protected function _mergeDiscounts( $aDiscounts, $aItemDiscounts)
00844     {
00845         foreach ( $aItemDiscounts as $sKey => $oDiscount ) {
00846             // add prices of the same discounts
00847             if ( array_key_exists ($sKey, $aDiscounts) ) {
00848                 $aDiscounts[$sKey]->dDiscount += $oDiscount->dDiscount;
00849             } else {
00850                 $aDiscounts[$sKey] = $oDiscount;
00851             }
00852         }
00853         return $aDiscounts;
00854     }
00855 
00861     protected function _calcDeliveryCost()
00862     {
00863         if ( $this->_oDeliveryPrice !== null ) {
00864             return $this->_oDeliveryPrice;
00865         }
00866         $myConfig  = $this->getConfig();
00867         $oDeliveryPrice = oxNew( 'oxprice' );
00868 
00869         if ( $this->getConfig()->getConfigParam( 'blDeliveryVatOnTop' ) ) {
00870             $oDeliveryPrice->setNettoPriceMode();
00871         } else {
00872             $oDeliveryPrice->setBruttoPriceMode();
00873         }
00874 
00875         // don't calculate if not logged in
00876         $oUser = $this->getBasketUser();
00877 
00878         if ( !$oUser && !$myConfig->getConfigParam( 'blCalculateDelCostIfNotLoggedIn' ) ) {
00879             return $oDeliveryPrice;
00880         }
00881 
00882         // VAT for delivery will be calculated always (#3757)
00883         // blCalcVATForDelivery option is @deprecated since 2012-03-23 in version 4.6
00884         // the option blShowVATForDelivery will be used only for displaying
00885         $fDelVATPercent = $this->getAdditionalServicesVatPercent();
00886         $oDeliveryPrice->setVat( $fDelVATPercent );
00887 
00888         // list of active delivery costs
00889         if ( $myConfig->getConfigParam('bl_perfLoadDelivery') ) {
00890             $aDeliveryList = oxRegistry::get("oxDeliveryList")->getDeliveryList( $this,
00891                                         $oUser,
00892                                         $this->_findDelivCountry(),
00893                                         $this->getShippingId()
00894                                     );
00895 
00896             if ( count( $aDeliveryList ) > 0 ) {
00897                 foreach ( $aDeliveryList as $oDelivery ) {
00898                     //debug trace
00899                     if ( $myConfig->getConfigParam( 'iDebug' ) == 5 ) {
00900                         echo( "DelCost : ".$oDelivery->oxdelivery__oxtitle->value."<br>" );
00901                     }
00902                     $oDeliveryPrice->addPrice( $oDelivery->getDeliveryPrice( $fDelVATPercent ) );
00903                 }
00904             }
00905         }
00906 
00907         return $oDeliveryPrice;
00908     }
00909 
00915     public function getBasketUser()
00916     {
00917         if ( $this->_oUser == null ) {
00918             return $this->getUser();
00919         }
00920 
00921         return $this->_oUser;
00922     }
00923 
00931     public function setBasketUser( $oUser )
00932     {
00933         $this->_oUser = $oUser;
00934     }
00935 
00936     //P
00942     public function getMostUsedVatPercent()
00943     {
00944         if ( $this->_oProductsPriceList ) {
00945             return $this->_oProductsPriceList->getMostUsedVatPercent();
00946         }
00947 
00948         return null;
00949     }
00950 
00956     public function getAdditionalServicesVatPercent()
00957     {
00958         if ( $this->_oProductsPriceList ) {
00959             if ( $this->getConfig()->getConfigParam( 'sAdditionalServVATCalcMethod') == 'proportional') {
00960                 return $this->_oProductsPriceList->getProportionalVatPercent();
00961             } else {
00962                 return $this->_oProductsPriceList->getMostUsedVatPercent();
00963             }
00964         }
00965 
00966         return 0;
00967     }
00968 
00974     public function isProportionalCalculationOn()
00975     {
00976         if ( $this->getConfig()->getConfigParam( 'sAdditionalServVATCalcMethod') == 'proportional' ) {
00977             return true;
00978         }
00979         return false;
00980     }
00981 
00982 
00983  //P
00990     protected function _calcTotalPrice()
00991     {
00992         // 1. add products price
00993         $dprice = $this->_dBruttoSum;//$this->_oProductsPriceList->getBruttoSum();
00994         $this->_oPrice = oxNew( 'oxPrice' );
00995         $this->_oPrice->setBruttoPriceMode();
00996         $this->_oPrice->setPrice( $dprice );
00997 
00998         // 2. substract discounts
00999         if ( $dprice && !$this->isCalculationModeNetto() ) {
01000 
01001             // 2.1 applying basket item discounts
01002             /*foreach ( $this->_aItemDiscounts as $oDiscount ) {
01003 
01004                 // skipping bundle discounts
01005                 if ( $oDiscount->sType == 'itm' ) {
01006                     continue;
01007                 }
01008                 $this->_oPrice->subtract( $oDiscount->dDiscount );
01009             }*/
01010 
01011             // 2.2 applying basket discounts
01012             $this->_oPrice->subtract( $this->_oTotalDiscount->getBruttoPrice() );
01013 
01014             // 2.3 applying voucher discounts
01015             if ($oVoucherDisc = $this->getVoucherDiscount()) {
01016                 $this->_oPrice->subtract( $oVoucherDisc->getBruttoPrice() );
01017             }
01018         }
01019 
01020         // 2.3 add delivery cost
01021         if ( isset( $this->_aCosts['oxdelivery'] ) ) {
01022             $this->_oPrice->add( $this->_aCosts['oxdelivery']->getBruttoPrice() );
01023         }
01024 
01025         // 2.4 add wrapping price
01026         if ( isset( $this->_aCosts['oxwrapping'] ) ) {
01027             $this->_oPrice->add( $this->_aCosts['oxwrapping']->getBruttoPrice() );
01028         }
01029         if ( isset( $this->_aCosts['oxgiftcard'] ) ) {
01030             $this->_oPrice->add( $this->_aCosts['oxgiftcard']->getBruttoPrice() );
01031         }
01032 
01033         // 2.5 add payment price
01034         if ( isset( $this->_aCosts['oxpayment'] ) ) {
01035             $this->_oPrice->add( $this->_aCosts['oxpayment']->getBruttoPrice() );
01036         }
01037 
01038         // 2.6 add TS protection price
01039         if ( isset( $this->_aCosts['oxtsprotection'] ) ) {
01040             $this->_oPrice->add( $this->_aCosts['oxtsprotection']->getBruttoPrice() );
01041         }
01042 
01043     }
01044 
01052     public function setVoucherDiscount( $dDiscount )
01053     {
01054         $this->_oVoucherDiscount = oxNew( 'oxPrice' );
01055         $this->_oVoucherDiscount->setBruttoPriceMode();
01056         $this->_oVoucherDiscount->add( $dDiscount );
01057     }
01058 
01064     protected function _calcVoucherDiscount()
01065     {
01066         if ( $this->getConfig()->getConfigParam( 'bl_showVouchers' ) && ($this->_oVoucherDiscount === null || ( $this->_blUpdateNeeded && !$this->isAdmin() ) ) ) {
01067 
01068             $this->_oVoucherDiscount = $this->_getPriceObject();
01069 
01070             // calculating price to apply discount
01071             $dPrice = $this->_oDiscountProductsPriceList->getSum( $this->isCalculationModeNetto() ) - $this->_oTotalDiscount->getPrice();
01072 
01073             // recalculating
01074             if ( count( $this->_aVouchers ) ) {
01075                 $oLang = oxRegistry::getLang();
01076                 foreach ( $this->_aVouchers as $sVoucherId => $oStdVoucher ) {
01077                     $oVoucher = oxNew( 'oxvoucher' );
01078                     try { // checking
01079                         $oVoucher->load( $oStdVoucher->sVoucherId );
01080 
01081                         if ( !$this->_blSkipVouchersAvailabilityChecking ) {
01082                             $oVoucher->checkBasketVoucherAvailability( $this->_aVouchers, $dPrice );
01083                             $oVoucher->checkUserAvailability( $this->getBasketUser() );
01084                         }
01085 
01086                         // assigning real voucher discount value as this is the only place where real value is calculated
01087                         $dVoucherdiscount = $oVoucher->getDiscountValue( $dPrice );
01088 
01089                         if ( $dVoucherdiscount > 0 ) {
01090 
01091                             if ( $oVoucher->getDiscountType() == 'absolute' ) {
01092                                 $dVatPart = ( $dPrice - $dVoucherdiscount ) / $dPrice * 100;
01093                             } else {
01094                                 $dVatPart = 100 - $oVoucher->getDiscount();
01095                             }
01096 
01097                             if ( !$this->_aDiscountedVats ) {
01098                                 if ( $oPriceList = $this->getDiscountProductsPrice() ) {
01099                                     $this->_aDiscountedVats = $oPriceList->getVatInfo( $this->isCalculationModeNetto() );
01100                                 }
01101                             }
01102 
01103                             // apply discount to vat
01104                             foreach ( $this->_aDiscountedVats as $sKey => $dVat ) {
01105                                 $this->_aDiscountedVats[$sKey] = oxPrice::percent( $dVat, $dVatPart);
01106                             }
01107                         }
01108 
01109                         // accumulating discount value
01110                         $this->_oVoucherDiscount->add( $dVoucherdiscount );
01111 
01112                         // collecting formatted for preview
01113                         $oStdVoucher->fVoucherdiscount = $oLang->formatCurrency( $dVoucherdiscount, $this->getBasketCurrency() );
01114                         $oStdVoucher->dVoucherdiscount = $dVoucherdiscount;
01115 
01116                         // subtracting voucher discount
01117                         $dPrice = $dPrice - $dVoucherdiscount;
01118 
01119 
01120 
01121                     } catch ( oxVoucherException $oEx ) {
01122 
01123                         // removing voucher on error
01124                         $oVoucher->unMarkAsReserved();
01125                         unset( $this->_aVouchers[$sVoucherId] );
01126 
01127                         // storing voucher error info
01128                         oxRegistry::get("oxUtilsView")->addErrorToDisplay($oEx, false, true);
01129                     }
01130                 }
01131             }
01132         }
01133     }
01134 
01141     protected function _applyDiscounts()
01142     {
01143         $dBruttoPrice = 0;
01144 
01145         //apply discounts for brutto price
01146         $dDiscountedBruttoPrice = $this->_getDiscountedProductsSum();
01147         $oTotalDiscount   = $this->getTotalDiscount();
01148         $oVoucherDiscount = $this->getVoucherDiscount();
01149 
01150         $oUtils = oxRegistry::getUtils();
01151         $dVatSum = 0;
01152         foreach ( $this->_aDiscountedVats as $dVat ) {
01153             $dVatSum +=  $oUtils->fRound( $dVat, $this->_oCurrency);
01154         }
01155 
01156         $oNotDiscounted = $this->getNotDiscountProductsPrice();
01157 
01158         if ( $this->isCalculationModeNetto() ) {
01159             // netto view mode
01160             $this->setNettoSum($this->getProductsPrice()->getSum());
01161             $this->setBruttoSum($oNotDiscounted->getSum(false) + $dDiscountedBruttoPrice + $dVatSum);
01162         } else {
01163             // brutto view mode
01164             $this->setNettoSum( $oNotDiscounted->getSum() + $dDiscountedBruttoPrice - $dVatSum );
01165             $this->setBruttoSum( $this->getProductsPrice()->getSum(false) );
01166         }
01167     }
01173     public function isPriceViewModeNetto()
01174     {
01175         $blResult = (bool) $this->getConfig()->getConfigParam('blShowNetPrice');
01176         $oUser = $this->getBasketUser();
01177         if ( $oUser ) {
01178             $blResult = $oUser->isPriceViewModeNetto();
01179         }
01180 
01181         return $blResult;
01182     }
01183 
01189     protected function _getPriceObject()
01190     {
01191         $oPrice = oxNew( 'oxPrice' );
01192 
01193         if ( $this->isCalculationModeNetto() ) {
01194             $oPrice->setNettoPriceMode();
01195         } else {
01196             $oPrice->setBruttoPriceMode();
01197         }
01198 
01199         return $oPrice;
01200     }
01201 
01207     protected function _calcBasketDiscount()
01208     {
01209         // resetting
01210         $this->_aDiscounts = array();
01211 
01212         // P using prices sum which has discount, not sum of skipped discounts
01213         $dOldprice = $this->_oDiscountProductsPriceList->getSum( $this->isCalculationModeNetto() );
01214 
01215         // add basket discounts
01216         if ( $this->_oTotalDiscount !== null  && isset($this->_isForOrderRecalculation) && $this->_isForOrderRecalculation ) {
01217             //if total discutn was setted on order recalculation
01218             $oTotalPrice = $this->getTotalDiscount();
01219             $oDiscount = oxNew('oxDiscount');
01220             $oDiscount->oxdiscount__oxaddsum = new oxField( $oTotalPrice->getPrice() );
01221             $oDiscount->oxdiscount__oxaddsumtype = new oxField( 'abs' );
01222             $aDiscounts[] = $oDiscount;
01223         } else {
01224             // discounts for basket
01225             $aDiscounts = oxRegistry::get("oxDiscountList")->getBasketDiscounts( $this, $this->getBasketUser() );
01226         }
01227 
01228         if ( $oPriceList = $this->getDiscountProductsPrice() ) {
01229                 $this->_aDiscountedVats = $oPriceList->getVatInfo( $this->isCalculationModeNetto() );
01230         }
01231 
01232         foreach ( $aDiscounts as $oDiscount ) {
01233 
01234             // storing applied discounts
01235             $oStdDiscount = $oDiscount->getSimpleDiscount();
01236 
01237             // skipping bundle discounts
01238             if ( $oDiscount->oxdiscount__oxaddsumtype->value == 'itm' ) {
01239                 continue;
01240             }
01241 
01242             // saving discount info
01243             $oStdDiscount->dDiscount = $oDiscount->getAbsValue( $dOldprice );
01244 
01245             //var_dump($oDiscount->getPercentage( $dOldprice ));
01246 
01247             $dVatPart = 100 - $oDiscount->getPercentage( $dOldprice );
01248 
01249             // if discount is more than basket sum
01250             if ( $dOldprice < $oStdDiscount->dDiscount ) {
01251                 $oStdDiscount->dDiscount = $dOldprice;
01252                 $dVatPart = 0;
01253             }
01254 
01255             // apply discount to vat
01256             foreach ( $this->_aDiscountedVats as $sKey => $dVat ) {
01257                 $this->_aDiscountedVats[$sKey] = oxPrice::percent( $dVat, $dVatPart);
01258             }
01259 
01260             //storing discount
01261             if ($oStdDiscount->dDiscount != 0) {
01262                 $this->_aDiscounts[$oDiscount->getId()] = $oStdDiscount;
01263                 // subtracting product price after discount
01264                 $dOldprice = $dOldprice - $oStdDiscount->dDiscount;
01265             }
01266         }
01267     }
01268 
01274     protected function _calcBasketTotalDiscount()
01275     {
01276         if ( $this->_oTotalDiscount === null || ( !$this->isAdmin() ) ) {
01277 
01278             $this->_oTotalDiscount = $this->_getPriceObject();
01279 
01280             if ( is_array($this->_aDiscounts) ) {
01281                 foreach ( $this->_aDiscounts as $oDiscount ) {
01282 
01283                     // skipping bundle discounts
01284                     if ( $oDiscount->sType == 'itm' ) {
01285                         continue;
01286                     }
01287 
01288                     // add discount value to total basket discount
01289                     $this->_oTotalDiscount->add( $oDiscount->dDiscount );
01290                 }
01291             }
01292         }
01293     }
01294 
01303     protected function _calcBasketWrapping()
01304     {
01305         $oWrappingPrices = oxNew( 'oxPriceList' );
01306 
01307         foreach ( $this->_aBasketContents as $oBasketItem ) {
01308 
01309             if ( ( $oWrapping = $oBasketItem->getWrapping() ) ) {
01310 
01311                 $oWrappingPrice = $oWrapping->getWrappingPrice( $oBasketItem->getAmount() );
01312                 $oWrappingPrice->setVat( $oBasketItem->getPrice()->getVat() );
01313 
01314                 $oWrappingPrices->addToPriceList( $oWrappingPrice );
01315             }
01316         }
01317 
01318         if ( $oWrappingPrices->getCount() ) {
01319             $oWrappingCost = oxNew( 'oxPrice' );
01320             $oWrappingCost = $oWrappingPrices->calculateToPrice();
01321         }
01322 
01323         return $oWrappingCost;
01324     }
01325 
01334     protected function _calcBasketGiftCard()
01335     {
01336         $oGiftCardPrice = oxNew( 'oxPrice' );
01337 
01338         if ( $this->getConfig()->getConfigParam( 'blWrappingVatOnTop' ) ) {
01339             $oGiftCardPrice->setNettoPriceMode();
01340         } else {
01341             $oGiftCardPrice->setBruttoPriceMode();
01342         }
01343 
01344         $dVATPercent = $this->getAdditionalServicesVatPercent();
01345 
01346         $oGiftCardPrice->setVat( $dVATPercent );
01347 
01348         // gift card price calculation
01349         if ( ( $oCard = $this->getCard() ) ) {
01350             if ($dVATPercent !== null) {
01351                 $oCard->setWrappingVat($dVATPercent);
01352             }
01353             $oGiftCardPrice->addPrice( $oCard->getWrappingPrice() );
01354         }
01355 
01356         return $oGiftCardPrice;
01357     }
01358 
01365     protected function _calcPaymentCost()
01366     {
01367         // resetting values
01368         $oPaymentPrice = oxNew( 'oxPrice' );
01369 
01370         // payment
01371         if ( ( $this->_sPaymentId = $this->getPaymentId() ) ) {
01372 
01373             $oPayment = oxNew( 'oxpayment' );
01374             $oPayment->load( $this->_sPaymentId );
01375 
01376             $oPayment->calculate( $this );
01377             $oPaymentPrice = $oPayment->getPrice();
01378         }
01379 
01380         return $oPaymentPrice;
01381     }
01382 
01389     protected function _calcTsProtectionCost()
01390     {
01391         if ( ( $this->getTsProductId() ) ) {
01392             $oTsProtection = oxNew('oxtsprotection');
01393             $oTsProduct = $oTsProtection->getTsProduct( $this->getTsProductId() );
01394             $oProtectionPrice = $oTsProduct->getPrice();
01395             $oProtectionPrice->setVat( $this->getAdditionalServicesVatPercent() );
01396         } else {
01397             $oProtectionPrice = oxNew( 'oxPrice' );
01398         }
01399 
01400         return $oProtectionPrice;
01401     }
01402 
01411     public function setCost( $sCostName, $oPrice = null )
01412     {
01413         $this->_aCosts[$sCostName] = $oPrice;
01414     }
01415 
01424     public function calculateBasket( $blForceUpdate = false )
01425     {
01426         /*
01427         //would be good to perform the reset of previous calculation
01428         //at least you can use it for the debug
01429         $this->_aDiscounts = array();
01430         $this->_aItemDiscounts = array();
01431         $this->_oTotalDiscount = null;
01432         $this->_dDiscountedProductNettoPrice = 0;
01433         $this->_aDiscountedVats = array();
01434         $this->_oPrice = null;
01435         $this->_oNotDiscountedProductsPriceList = null;
01436         $this->_oProductsPriceList = null;
01437         $this->_oDiscountProductsPriceList = null;*/
01438 
01439         if ( !$this->isEnabled() ) {
01440             return;
01441         }
01442 
01443         if ( $blForceUpdate ) {
01444             $this->onUpdate();
01445         }
01446 
01447         if ( !($this->_blUpdateNeeded || $blForceUpdate) ) {
01448             return;
01449         }
01450 
01451         $this->_aCosts = array();
01452 
01453         //  1. saving basket to the database
01454         $this->_save();
01455 
01456         //  2. remove all bundles
01457         $this->_clearBundles();
01458 
01459         //  3. generate bundle items
01460         $this->_addBundles();
01461 
01462         // reserve active basket
01463         if ($this->getConfig()->getConfigParam( 'blPsBasketReservationEnabled' )) {
01464             $this->getSession()->getBasketReservations()->reserveBasket($this);
01465         }
01466 
01467         //  4. calculating item prices
01468         $this->_calcItemsPrice();
01469 
01470         //  5. calculating/applying discounts
01471         $this->_calcBasketDiscount();
01472 
01473         //  6. calculating basket total discount
01474         $this->_calcBasketTotalDiscount();
01475 
01476         //  7. check for vouchers
01477         $this->_calcVoucherDiscount();
01478 
01479         //  8. applies all discounts to pricelist
01480         $this->_applyDiscounts();
01481 
01482         //  9. calculating additional costs:
01483         //  9.1: delivery
01484         $this->setCost( 'oxdelivery', $this->_calcDeliveryCost() );
01485 
01486         //  9.2: adding wrapping and gift card costs
01487         $this->setCost( 'oxwrapping', $this->_calcBasketWrapping() );
01488 
01489         $this->setCost( 'oxgiftcard', $this->_calcBasketGiftCard() );
01490 
01491         //  9.3: adding payment cost
01492         $this->setCost( 'oxpayment', $this->_calcPaymentCost() );
01493 
01494         //  9.4: adding TS protection cost
01495         $this->setCost( 'oxtsprotection', $this->_calcTsProtectionCost() );
01496 
01497         //  10. calculate total price
01498         $this->_calcTotalPrice();
01499 
01500         //  11. formatting discounts
01501         $this->formatDiscount();
01502 
01503         //  12.setting to up-to-date status
01504         $this->afterUpdate();
01505     }
01506 
01512     public function onUpdate()
01513     {
01514         $this->_blUpdateNeeded = true;
01515     }
01516 
01522     public function afterUpdate()
01523     {
01524         $this->_blUpdateNeeded = false;
01525     }
01526 
01534     public function getBasketSummary()
01535     {
01536         if ( $this->_blUpdateNeeded || $this->_aBasketSummary === null ) {
01537             $this->_aBasketSummary = new stdclass();
01538             $this->_aBasketSummary->aArticles = array();
01539             $this->_aBasketSummary->aCategories = array();
01540             $this->_aBasketSummary->iArticleCount = 0;
01541             $this->_aBasketSummary->dArticlePrice = 0;
01542             $this->_aBasketSummary->dArticleDiscountablePrice = 0;
01543         }
01544 
01545         if ( !$this->isEnabled() ) {
01546             return $this->_aBasketSummary;
01547         }
01548 
01549         $myConfig = $this->getConfig();
01550         foreach ( $this->_aBasketContents as $oBasketItem ) {
01551             if ( !$oBasketItem->isBundle() && $oArticle = $oBasketItem->getArticle(false) ) {
01552                 $aCatIds = $oArticle->getCategoryIds();
01553                 //#M530 if price is not loaded for articles
01554                 $dPrice = 0;
01555                 $dDiscountablePrice = 0;
01556                 if ( ( $oPrice = $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $this ) ) ) {
01557                     $dPrice = $oPrice->getPrice();
01558                     if ( !$oArticle->skipDiscounts() ) {
01559                         $dDiscountablePrice = $dPrice;
01560                     }
01561                 }
01562 
01563                 foreach ( $aCatIds as $sCatId ) {
01564                     if ( !isset( $this->_aBasketSummary->aCategories[$sCatId] ) ) {
01565                         $this->_aBasketSummary->aCategories[$sCatId] = new stdClass();
01566                     }
01567 
01568                     $this->_aBasketSummary->aCategories[$sCatId]->dPrice  += $dPrice * $oBasketItem->getAmount();
01569                     $this->_aBasketSummary->aCategories[$sCatId]->dDiscountablePrice += $dDiscountablePrice * $oBasketItem->getAmount();
01570                     $this->_aBasketSummary->aCategories[$sCatId]->dAmount += $oBasketItem->getAmount();
01571                     $this->_aBasketSummary->aCategories[$sCatId]->iCount++;
01572                 }
01573 
01574                 // variant handling
01575                 if ( ($sParentId = $oArticle->getProductParentId()) && $myConfig->getConfigParam( 'blVariantParentBuyable' ) ) {
01576                     if ( !isset( $this->_aBasketSummary->aArticles[$sParentId] ) ) {
01577                         $this->_aBasketSummary->aArticles[$sParentId] = 0;
01578                     }
01579                     $this->_aBasketSummary->aArticles[$sParentId] += $oBasketItem->getAmount();
01580                 }
01581 
01582                 if ( !isset( $this->_aBasketSummary->aArticles[$oBasketItem->getProductId()] ) ) {
01583                     $this->_aBasketSummary->aArticles[$oBasketItem->getProductId()] = 0;
01584                 }
01585 
01586                 $this->_aBasketSummary->aArticles[$oBasketItem->getProductId()] += $oBasketItem->getAmount();
01587                 $this->_aBasketSummary->iArticleCount += $oBasketItem->getAmount();
01588                 $this->_aBasketSummary->dArticlePrice += $dPrice * $oBasketItem->getAmount();
01589                 $this->_aBasketSummary->dArticleDiscountablePrice += $dDiscountablePrice * $oBasketItem->getAmount();
01590             }
01591         }
01592         return $this->_aBasketSummary;
01593     }
01594 
01606     public function addVoucher( $sVoucherId )
01607     {
01608         // calculating price to check
01609         // P using prices sum which has discount, not sum of skipped discounts
01610         $dPrice = 0;
01611         if ( $this->_oDiscountProductsPriceList ) {
01612             $dPrice = $this->_oDiscountProductsPriceList->getSum( $this->isCalculationModeNetto() );
01613         }
01614 
01615         try { // trying to load voucher and apply it
01616 
01617             $oVoucher = oxNew( 'oxvoucher' );
01618 
01619             if ( !$this->_blSkipVouchersAvailabilityChecking ) {
01620                 $oVoucher->getVoucherByNr( $sVoucherId, $this->_aVouchers, true );
01621                 $oVoucher->checkVoucherAvailability( $this->_aVouchers, $dPrice );
01622                 $oVoucher->checkUserAvailability( $this->getBasketUser() );
01623                 $oVoucher->markAsReserved();
01624             } else {
01625                 $oVoucher->load( $sVoucherId );
01626             }
01627 
01628             // saving voucher info
01629             $this->_aVouchers[$oVoucher->oxvouchers__oxid->value] = $oVoucher->getSimpleVoucher();
01630         } catch ( oxVoucherException $oEx ) {
01631 
01632             // problems adding voucher
01633             oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx, false, true );
01634         }
01635 
01636         $this->onUpdate();
01637     }
01638 
01646     public function removeVoucher( $sVoucherId )
01647     {
01648         // removing if it exists
01649         if ( isset( $this->_aVouchers[$sVoucherId] ) ) {
01650 
01651             $oVoucher = oxNew( 'oxvoucher' );
01652             $oVoucher->load( $sVoucherId );
01653 
01654             $oVoucher->unMarkAsReserved();
01655 
01656             // unsetting it if exists this voucher in DB or not
01657             unset( $this->_aVouchers[$sVoucherId] );
01658             $this->onUpdate();
01659         }
01660 
01661     }
01662 
01668     public function resetUserInfo()
01669     {
01670         $this->setPayment( null );
01671         $this->setShipping( null );
01672     }
01673 
01679     protected function formatDiscount()
01680     {
01681         // discount information
01682         // formatting discount value
01683         $this->aDiscounts = $this->getDiscounts();
01684         if ( count($this->aDiscounts) > 0 ) {
01685             $oLang = oxRegistry::getLang();
01686             foreach ($this->aDiscounts as $oDiscount) {
01687                 $oDiscount->fDiscount = $oLang->formatCurrency( $oDiscount->dDiscount, $this->getBasketCurrency() );
01688             }
01689         }
01690     }
01691 
01692 
01698     protected function _canSaveBasket()
01699     {
01700         $blCanSave = !$this->getConfig()->getConfigParam( 'blPerfNoBasketSaving' );
01701         return $blCanSave;
01702     }
01703 
01709     public function load()
01710     {
01711         $oUser = $this->getBasketUser();
01712         if ( !$oUser ) {
01713             return;
01714         }
01715 
01716         $oBasket = $oUser->getBasket( 'savedbasket' );
01717 
01718         // restoring from saved history
01719         $aSavedItems = $oBasket->getItems();
01720         foreach ( $aSavedItems as $oItem ) {
01721             try {
01722                 $oSelList = $oItem->getSelList();
01723 
01724                 $this->addToBasket( $oItem->oxuserbasketitems__oxartid->value, $oItem->oxuserbasketitems__oxamount->value, $oSelList, $oItem->getPersParams(), true );
01725             } catch( oxArticleException $oEx ) {
01726                 // caught and ignored
01727             }
01728         }
01729     }
01730 
01736     protected function _save()
01737     {
01738         if ( $this->_canSaveBasket() ) {
01739 
01740             if ( $oUser = $this->getBasketUser() ) {
01741                 //first delete all contents
01742                 //#2039
01743                 $oSavedBasket = $oUser->getBasket( 'savedbasket' );
01744                 $oSavedBasket->delete();
01745 
01746                 //then save
01747                 foreach ( $this->_aBasketContents as $oBasketItem ) {
01748                     // discount or bundled products will be added automatically if available
01749                     if ( !$oBasketItem->isBundle() && !$oBasketItem->isDiscountArticle() ) {
01750                        $oSavedBasket->addItemToBasket( $oBasketItem->getProductId(), $oBasketItem->getAmount(), $oBasketItem->getSelList(), true, $oBasketItem->getPersParams() );
01751                     }
01752                 }
01753             }
01754         }
01755     }
01756 
01764     protected function _deleteSavedBasket()
01765     {
01766         // deleting basket if session user available
01767         if ( $oUser = $this->getBasketUser() ) {
01768             $oUser->getBasket( 'savedbasket' )->delete();
01769         }
01770 
01771         // basket exclude
01772         if ( $this->getConfig()->getConfigParam( 'blBasketExcludeEnabled' )) {
01773             $this->setBasketRootCatId(null);
01774         }
01775     }
01776 
01782     protected function _findDelivCountry()
01783     {
01784         $myConfig = $this->getConfig();
01785         $oUser    = $this->getBasketUser();
01786 
01787         $sDelivCountry = null;
01788 
01789         if ( !$oUser ) {
01790             // don't calculate if not logged in unless specified otherwise
01791             $aHomeCountry = $myConfig->getConfigParam( 'aHomeCountry' );
01792             if ( $myConfig->getConfigParam( 'blCalculateDelCostIfNotLoggedIn' ) && is_array( $aHomeCountry ) ) {
01793                 $sDelivCountry = current( $aHomeCountry );
01794             }
01795         } else {
01796 
01797             // ok, logged in
01798             if ( $sCountryId = $myConfig->getGlobalParameter( 'delcountryid' ) ) {
01799                 $sDelivCountry = $sCountryId;
01800             } elseif ( $sAddressId = oxSession::getVar( 'deladrid' ) ) {
01801 
01802                 $oDelAdress = oxNew( 'oxaddress' );
01803                 if ( $oDelAdress->load( $sAddressId ) ) {
01804                     $sDelivCountry = $oDelAdress->oxaddress__oxcountryid->value;
01805                 }
01806             }
01807 
01808             // still not found ?
01809             if ( !$sDelivCountry ) {
01810                 $sDelivCountry = $oUser->oxuser__oxcountryid->value;
01811             }
01812         }
01813 
01814         return $sDelivCountry;
01815     }
01816 
01822     public function deleteBasket()
01823     {
01824         $this->_aBasketContents = array();
01825         $this->getSession()->delBasket();
01826 
01827         if ($this->getConfig()->getConfigParam( 'blPsBasketReservationEnabled' )) {
01828             $this->getSession()->getBasketReservations()->discardReservations();
01829         }
01830 
01831         // merging basket history
01832         $this->_deleteSavedBasket();
01833     }
01834 
01842     public function setPayment( $sPaymentId = null )
01843     {
01844         $this->_sPaymentId = $sPaymentId;
01845     }
01846 
01852     public function getPaymentId()
01853     {
01854         if ( !$this->_sPaymentId ) {
01855              $this->_sPaymentId = oxSession::getVar( 'paymentid' );
01856         }
01857         return $this->_sPaymentId;
01858     }
01859 
01867     public function setShipping( $sShippingSetId = null )
01868     {
01869         $this->_sShippingSetId = $sShippingSetId;
01870         oxSession::setVar( 'sShipSet', $sShippingSetId );
01871     }
01872 
01880     public function setDeliveryPrice( $oShippingPrice = null )
01881     {
01882         $this->_oDeliveryPrice = $oShippingPrice;
01883     }
01884 
01890     public function getShippingId()
01891     {
01892         if ( !$this->_sShippingSetId ) {
01893              $this->_sShippingSetId = oxSession::getVar( 'sShipSet' );
01894         }
01895 
01896         $sActPaymentId = $this->getPaymentId();
01897         // setting default if none is set
01898         if ( !$this->_sShippingSetId && $sActPaymentId != 'oxempty' ) {
01899             $oUser = $this->getUser();
01900 
01901             // choosing first preferred delivery set
01902             list( , $sActShipSet ) = oxRegistry::get("oxDeliverySetList")->getDeliverySetData( null, $oUser, $this );
01903             // in case nothing was found and no user set - choosing default
01904             $this->_sShippingSetId = $sActShipSet ? $sActShipSet : ( $oUser ? null : 'oxidstandard' );
01905         } elseif ( !$this->isAdmin() && $sActPaymentId == 'oxempty' ) {
01906             // in case 'oxempty' is payment id - delivery set must be reset
01907             $this->_sShippingSetId = null;
01908         }
01909 
01910         return $this->_sShippingSetId;
01911     }
01912 
01918     public function getBasketArticles()
01919     {
01920         $aBasketArticles = array();
01921 
01922         foreach ( $this->_aBasketContents as $sItemKey => $oBasketItem ) {
01923             try {
01924                 $oProduct = $oBasketItem->getArticle( true );
01925 
01926                 if ( $this->getConfig()->getConfigParam( 'bl_perfLoadSelectLists' ) ) {
01927                     // marking chosen select list
01928                     $aSelList = $oBasketItem->getSelList();
01929                     if ( is_array( $aSelList ) && ( $aSelectlist = $oProduct->getSelectLists( $sItemKey ) ) ) {
01930                         reset( $aSelList );
01931                         while ( list( $conkey, $iSel ) = each( $aSelList ) ) {
01932                             $aSelectlist[$conkey][$iSel]->selected = 1;
01933                         }
01934                         $oProduct->setSelectlist( $aSelectlist );
01935                     }
01936                 }
01937             } catch ( oxNoArticleException $oEx ) {
01938                 oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx );
01939                 $this->removeItem( $sItemKey );
01940                 $this->calculateBasket( true );
01941                 continue;
01942             } catch ( oxArticleInputException $oEx ) {
01943                 oxRegistry::get("oxUtilsView")->addErrorToDisplay( $oEx );
01944                 $this->removeItem( $sItemKey );
01945                 $this->calculateBasket( true );
01946                 continue;
01947             }
01948 
01949             $aBasketArticles[$sItemKey] = $oProduct;
01950         }
01951         return $aBasketArticles;
01952     }
01953 
01959     public function getDiscountProductsPrice()
01960     {
01961         return $this->_oDiscountProductsPriceList;
01962     }
01963 
01969     public function getProductsPrice()
01970     {
01971         if ( is_null($this->_oProductsPriceList) ) {
01972             $this->_oProductsPriceList = oxNew( 'oxPriceList' );
01973         }
01974 
01975         return $this->_oProductsPriceList;
01976     }
01977 
01983     public function getPrice()
01984     {
01985         if ( is_null($this->_oPrice) ) {
01986             $this->_oPrice = oxNew( 'oxprice' );
01987         }
01988 
01989         return $this->_oPrice;
01990     }
01991 
01998     public function getOrderId()
01999     {
02000         return $this->_sOrderId;
02001     }
02002 
02010     public function setOrderId( $sId )
02011     {
02012         $this->_sOrderId = $sId;
02013     }
02014 
02023     public function getCosts( $sId = null )
02024     {
02025         // if user want some specific cost - return it
02026         if ( $sId ) {
02027             return isset( $this->_aCosts[$sId] )?$this->_aCosts[$sId]:null;
02028         }
02029         return $this->_aCosts;
02030     }
02031 
02037     public function getVouchers()
02038     {
02039         return $this->_aVouchers;
02040     }
02041 
02047     public function getProductsCount()
02048     {
02049         return $this->_iProductsCnt;
02050     }
02051 
02057     public function getItemsCount()
02058     {
02059         return $this->_dItemsCnt;
02060     }
02061 
02067     public function getWeight()
02068     {
02069         return $this->_dWeight;
02070     }
02071 
02077     public function getContents()
02078     {
02079         return $this->_aBasketContents;
02080     }
02081 
02089     public function getProductVats( $blFormatCurrency = true )
02090     {
02091         if ( !$this->_oNotDiscountedProductsPriceList ) {
02092             return array();
02093         }
02094 
02095         $aVats = $this->_oNotDiscountedProductsPriceList->getVatInfo( $this->isCalculationModeNetto() );
02096 
02097         $oUtils = oxRegistry::getUtils();
02098         foreach ( $this->_aDiscountedVats as $sKey => $dVat ) {
02099             if ( !isset( $aVats[$sKey] ) ) {
02100                 $aVats[$sKey] = 0;
02101             }
02102             // add prices of the same discounts
02103             $aVats[$sKey] += $oUtils->fRound( $dVat, $this->_oCurrency );
02104         }
02105 
02106         if ( $blFormatCurrency ) {
02107             $oLang = oxRegistry::getLang();
02108             foreach ( $aVats as $sKey => $dVat ) {
02109                 $aVats[$sKey] = $oLang->formatCurrency( $dVat, $this->getBasketCurrency() );
02110             }
02111         }
02112 
02113         return $aVats;
02114     }
02115 
02123     public function getDiscountedNettoPrice()
02124     {
02125         if ( $this->_oNotDiscountedProductsPriceList ) {
02126             return $this->_dDiscountedProductNettoPrice + $this->_oNotDiscountedProductsPriceList->getNettoSum();
02127         }
02128         return false;
02129     }
02130 
02138     public function setCardMessage( $sMessage )
02139     {
02140         $this->_sCardMessage = $sMessage;
02141     }
02142 
02148     public function getCardMessage()
02149     {
02150         return $this->_sCardMessage;
02151     }
02152 
02160     public function setCardId( $sCardId )
02161     {
02162         $this->_sCardId = $sCardId;
02163     }
02164 
02170     public function getCardId()
02171     {
02172         return $this->_sCardId;
02173     }
02174 
02180     public function getCard()
02181     {
02182         $oCard = null;
02183         if ( $sCardId = $this->getCardId() ) {
02184             $oCard = oxNew( 'oxwrapping' );
02185             $oCard->load( $sCardId );
02186             $oCard->setWrappingVat( $this->getAdditionalServicesVatPercent() );
02187         }
02188         return $oCard;
02189     }
02190 
02196     public function getTotalDiscount()
02197     {
02198         return $this->_oTotalDiscount;
02199     }
02200 
02206     public function getDiscounts()
02207     {
02208         if ( $this->getTotalDiscount() && $this->getTotalDiscount()->getBruttoPrice() == 0 && count($this->_aItemDiscounts) == 0) {
02209             return null;
02210         }
02211 
02212         return array_merge($this->_aItemDiscounts, $this->_aDiscounts);
02213     }
02214 
02220     public function getVoucherDiscount()
02221     {
02222         if ($this->getConfig()->getConfigParam( 'bl_showVouchers' )) {
02223             return $this->_oVoucherDiscount;
02224         }
02225         return null;
02226     }
02227 
02235     public function setBasketCurrency( $oCurrency )
02236     {
02237         $this->_oCurrency = $oCurrency;
02238     }
02239 
02245     public function getBasketCurrency()
02246     {
02247         if ( $this->_oCurrency === null ) {
02248             $this->_oCurrency = $this->getConfig()->getActShopCurrencyObject();
02249         }
02250 
02251         return $this->_oCurrency;
02252     }
02253 
02261     public function setSkipVouchersChecking( $blSkipChecking = null )
02262     {
02263         $this->_blSkipVouchersAvailabilityChecking = $blSkipChecking;
02264     }
02265 
02271     public function hasSkipedDiscount()
02272     {
02273         return $this->_blSkipDiscounts;
02274     }
02275 
02283     public function setSkipDiscounts( $blSkip )
02284     {
02285         $this->_blSkipDiscounts = $blSkip;
02286     }
02287 
02295     public function getProductsNetPrice()
02296     {
02297         return oxRegistry::getLang()->formatCurrency( $this->getNettoSum(), $this->getBasketCurrency() );
02298     }
02299 
02307     public function getFProductsPrice()
02308     {
02309         return oxRegistry::getLang()->formatCurrency( $this->getBruttoSum(), $this->getBasketCurrency() );
02310     }
02311 
02319     public function getDelCostVatPercent()
02320     {
02321         return $this->getCosts( 'oxdelivery' )->getVat();
02322     }
02323 
02331     public function getDelCostVat()
02332     {
02333         $dDelVAT = $this->getCosts( 'oxdelivery' )->getVatValue();
02334 
02335         // blShowVATForDelivery option will be used, only for displaying, but not calculation
02336         if ( $dDelVAT > 0 && $this->getConfig()->getConfigParam( 'blShowVATForDelivery' )) {
02337             return oxRegistry::getLang()->formatCurrency( $dDelVAT, $this->getBasketCurrency() );
02338         }
02339         return false;
02340     }
02341 
02349     public function getDelCostNet()
02350     {
02351         $oConfig = $this->getConfig();
02352 
02353         // blShowVATForDelivery option will be used, only for displaying, but not calculation
02354         if ( $oConfig->getConfigParam( 'blShowVATForDelivery' ) && ( $this->getBasketUser() || $oConfig->getConfigParam( 'blCalculateDelCostIfNotLoggedIn' ) ) ) {
02355             $dNetPrice = $this->getCosts( 'oxdelivery' )->getNettoPrice();
02356             if ( $dNetPrice > 0 ) {
02357                 return oxRegistry::getLang()->formatCurrency( $dNetPrice, $this->getBasketCurrency() );
02358             }
02359         }
02360         return false;
02361     }
02362 
02370     public function getPayCostVatPercent()
02371     {
02372         return $this->getCosts( 'oxpayment' )->getVat();
02373     }
02374 
02382     public function getPayCostVat()
02383     {
02384         $dPayVAT = $this->getCosts( 'oxpayment' )->getVatValue();
02385 
02386         // blShowVATForPayCharge option will be used, only for displaying, but not calculation
02387         if ( $dPayVAT > 0 && $this->getConfig()->getConfigParam( 'blShowVATForPayCharge' ) ) {
02388             return oxRegistry::getLang()->formatCurrency( $dPayVAT, $this->getBasketCurrency() );
02389         }
02390         return false;
02391     }
02392 
02400     public function getPayCostNet()
02401     {
02402         // blShowVATForPayCharge option will be used, only for displaying, but not calculation
02403         if ( $this->getConfig()->getConfigParam( 'blShowVATForPayCharge' ) ) {
02404             $oPaymentCost = $this->getCosts( 'oxpayment' );
02405             if ( $oPaymentCost && $oPaymentCost->getNettoPrice() ) {
02406                 return oxRegistry::getLang()->formatCurrency( $this->getCosts( 'oxpayment' )->getNettoPrice(), $this->getBasketCurrency() );
02407             }
02408         }
02409         return false;
02410     }
02411 
02419     public function getPaymentCosts()
02420     {
02421         $oPaymentCost = $this->getCosts( 'oxpayment' );
02422         if ( $oPaymentCost && $oPaymentCost->getBruttoPrice() ) {
02423             return $oPaymentCost->getBruttoPrice();
02424         }
02425     }
02426 
02432     public function getPaymentCost()
02433     {
02434         return $this->getCosts( 'oxpayment' );
02435     }
02436 
02444     public function getFPaymentCosts()
02445     {
02446         $oPaymentCost = $this->getCosts( 'oxpayment' );
02447         if ( $oPaymentCost && $oPaymentCost->getBruttoPrice() ) {
02448             return oxRegistry::getLang()->formatCurrency( $oPaymentCost->getBruttoPrice(), $this->getBasketCurrency() );
02449         }
02450         return false;
02451     }
02452 
02458     public function getVoucherDiscValue()
02459     {
02460         if ( $this->getVoucherDiscount() ) {
02461             return $this->getVoucherDiscount()->getBruttoPrice();
02462         }
02463         return false;
02464     }
02465 
02473     public function getFVoucherDiscountValue()
02474     {
02475         if ( $oVoucherDiscount = $this->getVoucherDiscount() ) {
02476             if ( $oVoucherDiscount->getBruttoPrice() ) {
02477                 return oxRegistry::getLang()->formatCurrency( $oVoucherDiscount->getBruttoPrice(), $this->getBasketCurrency() );
02478             }
02479         }
02480         return false;
02481     }
02482 
02483 
02491     public function getWrappCostVatPercent()
02492     {
02493         return $this->getCosts( 'oxwrapping' )->getVat();
02494     }
02495 
02496 
02504     public function getGiftCardCostVatPercent()
02505     {
02506         return $this->getCosts( 'oxgiftcard' )->getVat();
02507     }
02508 
02516     public function getWrappCostVat()
02517     {
02518         // blShowVATForWrapping option will be used, only for displaying, but not calculation
02519         if ( $this->getConfig()->getConfigParam( 'blShowVATForWrapping' ) ) {
02520             $oPrice = $this->getCosts( 'oxwrapping' );
02521 
02522             if ( $oPrice && $oPrice->getVatValue() > 0 ) {
02523                 return oxRegistry::getLang()->formatCurrency( $oPrice->getVatValue(), $this->getBasketCurrency() );
02524             }
02525         }
02526 
02527         return false;
02528     }
02529 
02537     public function getWrappCostNet()
02538     {
02539         // blShowVATForWrapping option will be used, only for displaying, but not calculation
02540         if ( $this->getConfig()->getConfigParam( 'blShowVATForWrapping' ) ) {
02541             $oPrice = $this->getCosts( 'oxwrapping' );
02542 
02543              if ( $oPrice && $oPrice->getNettoPrice() > 0 ) {
02544                  return  oxRegistry::getLang()->formatCurrency( $oPrice->getNettoPrice(), $this->getBasketCurrency() );
02545              }
02546         }
02547 
02548         return false;
02549     }
02550 
02558     public function getFWrappingCosts()
02559     {
02560         $oPrice = $this->getCosts( 'oxwrapping' );
02561 
02562         if ( $oPrice && $oPrice->getBruttoPrice() ) {
02563             return oxRegistry::getLang()->formatCurrency( $oPrice->getBruttoPrice(), $this->getBasketCurrency() );
02564         }
02565 
02566         return false;
02567     }
02568 
02574     public function getWrappingCost()
02575     {
02576         return $this->getCosts( 'oxwrapping' );
02577     }
02578 
02586     public function getGiftCardCostVat()
02587     {
02588         // blShowVATForWrapping option will be used, only for displaying, but not calculation
02589         if ( $this->getConfig()->getConfigParam( 'blShowVATForWrapping' ) ) {
02590             $oPrice = $this->getCosts( 'oxgiftcard' );
02591 
02592             if ( $oPrice && $oPrice->getVatValue() > 0 ) {
02593                 return oxLang::getInstance()->formatCurrency( $oPrice->getVatValue(), $this->getBasketCurrency() );
02594             }
02595         }
02596 
02597         return false;
02598 
02599     }
02600 
02608     public function getGiftCardCostNet()
02609     {
02610         // blShowVATForWrapping option will be used, only for displaying, but not calculation
02611         if ( $this->getConfig()->getConfigParam( 'blShowVATForWrapping' ) ) {
02612             $oPrice = $this->getCosts( 'oxgiftcard' );
02613 
02614             if ( $oPrice && $oPrice->getNettoPrice() > 0 ) {
02615                 return  oxLang::getInstance()->formatCurrency( $oPrice->getNettoPrice(), $this->getBasketCurrency() );
02616             }
02617         }
02618 
02619         return false;
02620     }
02621 
02629     public function getFGiftCardCosts()
02630     {
02631         $oPrice = $this->getCosts( 'oxgiftcard' );
02632 
02633         if ( $oPrice && $oPrice->getBruttoPrice() ) {
02634             return oxLang::getInstance()->formatCurrency( $oPrice->getBruttoPrice(), $this->getBasketCurrency() );
02635         }
02636         return false;
02637     }
02638 
02644     public function getGiftCardCost()
02645     {
02646         return $this->getCosts( 'oxgiftcard' );
02647     }
02648 
02656     public function getFPrice()
02657     {
02658         return oxRegistry::getLang()->formatCurrency( $this->getPrice()->getBruttoPrice(), $this->getBasketCurrency() );
02659     }
02660 
02668     public function getFDeliveryCosts()
02669     {
02670         $oPrice = $this->getCosts( 'oxdelivery' );
02671 
02672         if ( $oPrice && ( $this->getBasketUser() || $this->getConfig()->getConfigParam( 'blCalculateDelCostIfNotLoggedIn' ) ) ) {
02673             return oxRegistry::getLang()->formatCurrency( $oPrice->getBruttoPrice(), $this->getBasketCurrency() );
02674         }
02675         return false;
02676     }
02677 
02685     public function getDeliveryCosts()
02686     {
02687         if ( $oDeliveryCost = $this->getCosts( 'oxdelivery' ) ) {
02688             return $oDeliveryCost->getBruttoPrice();
02689         }
02690         return false;
02691     }
02692 
02698     public function getDeliveryCost()
02699     {
02700         return $this->getCosts( 'oxdelivery' );
02701     }
02702 
02710     public function setTotalDiscount( $dDiscount )
02711     {
02712         $this->_oTotalDiscount = oxNew( 'oxPrice' );
02713         $this->_oTotalDiscount->setBruttoPriceMode();
02714         $this->_oTotalDiscount->add( $dDiscount );
02715     }
02716 
02723     public function getPriceForPayment()
02724     {
02725         $dPrice = $this->getDiscountedProductsBruttoPrice();
02726         //#1905 not discounted products should be included in payment amount calculation
02727         if ( $oPriceList = $this->getNotDiscountProductsPrice() ) {
02728             $dPrice += $oPriceList->getBruttoSum();
02729         }
02730 
02731         // adding delivery price to final price
02732         if ( $oDeliveryPrice = $this->_aCosts['oxdelivery'] ) {
02733             $dPrice += $oDeliveryPrice->getBruttoPrice();
02734         }
02735 
02736         return $dPrice;
02737     }
02738 
02739 
02745     public function _getDiscountedProductsSum()
02746     {
02747         if ( $oProductsPrice = $this->getDiscountProductsPrice() ) {
02748             $dPrice = $oProductsPrice->getSum( $this->isCalculationModeNetto() );
02749         }
02750 
02751         // substracting total discount
02752         if ( $oPrice = $this->getTotalDiscount() ) {
02753             $dPrice -= $oPrice->getPrice();
02754         }
02755 
02756         if ( $oVoucherPrice = $this->getVoucherDiscount() ) {
02757             $dPrice -= $oVoucherPrice->getPrice();
02758         }
02759 
02760         return $dPrice;
02761     }
02762 
02768     public function getDiscountedProductsBruttoPrice()
02769     {
02770         if ( $oProductsPrice = $this->getDiscountProductsPrice() ) {
02771             $dPrice = $oProductsPrice->getBruttoSum();
02772         }
02773 
02774         // substracting total discount
02775         if ( $oPrice = $this->getTotalDiscount() ) {
02776             $dPrice -= $oPrice->getBruttoPrice();
02777         }
02778 
02779         if ( $oVoucherPrice = $this->getVoucherDiscount() ) {
02780             $dPrice -= $oVoucherPrice->getBruttoPrice();
02781         }
02782 
02783         return $dPrice;
02784     }
02785 
02791     public function isBelowMinOrderPrice()
02792     {
02793         $blIsBelowMinOrderPrice = false;
02794         $sConfValue = $this->getConfig()->getConfigParam( 'iMinOrderPrice' );
02795         if ( is_numeric($sConfValue) && $this->getProductsCount() ) {
02796             $dMinOrderPrice = oxPrice::getPriceInActCurrency( ( double ) $sConfValue );
02797             $dNotDiscountedProductPrice = 0;
02798             if ( $oPrice = $this->getNotDiscountProductsPrice() ) {
02799                 $dNotDiscountedProductPrice = $oPrice->getBruttoSum();
02800             }
02801             $blIsBelowMinOrderPrice = ($dMinOrderPrice > ($this->getDiscountedProductsBruttoPrice() + $dNotDiscountedProductPrice));
02802         }
02803 
02804         return $blIsBelowMinOrderPrice;
02805 
02806     }
02807 
02816     public function getArtStockInBasket( $sArtId, $sExpiredArtId = null )
02817     {
02818         $dArtStock = 0;
02819         foreach ( $this->_aBasketContents as $sItemKey => $oOrderArticle ) {
02820             if ( $oOrderArticle && ( $sExpiredArtId == null || $sExpiredArtId != $sItemKey ) ) {
02821                 if ( $oOrderArticle->getArticle( true )->getId() == $sArtId ) {
02822                     $dArtStock += $oOrderArticle->getAmount();
02823                 }
02824             }
02825         }
02826 
02827         return $dArtStock;
02828     }
02829 
02837     public function canAddProductToBasket( $sProductId )
02838     {
02839         $blCanAdd = null;
02840 
02841         // if basket category is not set..
02842         if ( $this->_sBasketCategoryId === null ) {
02843             $oCat = null;
02844 
02845             // request category
02846             if ( $oView = $this->getConfig()->getActiveView() ) {
02847                 if ( $oCat = $oView->getActiveCategory() ) {
02848                     if ( !$this->_isProductInRootCategory( $sProductId, $oCat->oxcategories__oxrootid->value ) ) {
02849                         $oCat = null;
02850                     } else {
02851                         $blCanAdd = true;
02852                     }
02853                 }
02854             }
02855 
02856             // product main category
02857             if ( !$oCat ) {
02858                 $oProduct = oxNew( "oxarticle" );
02859                 if ( $oProduct->load( $sProductId ) ) {
02860                     $oCat = $oProduct->getCategory();
02861                 }
02862             }
02863 
02864             // root category id
02865             if ( $oCat ) {
02866                 $this->setBasketRootCatId($oCat->oxcategories__oxrootid->value);
02867             }
02868         }
02869 
02870         // avoiding double check..
02871         if ( $blCanAdd === null ) {
02872             $blCanAdd = $this->_sBasketCategoryId ? $this->_isProductInRootCategory( $sProductId, $this->getBasketRootCatId() ) : true;
02873         }
02874 
02875         return $blCanAdd;
02876     }
02877 
02886     protected function _isProductInRootCategory( $sProductId, $sRootCatId )
02887     {
02888         $sO2CTable = getViewName( 'oxobject2category' );
02889         $sCatTable = getViewName( 'oxcategories' );
02890 
02891         $oDb = oxDb::getDb();
02892         $sParentId  = $oDb->getOne( "select oxparentid from oxarticles where oxid = ".$oDb->quote( $sProductId ) );
02893         $sProductId = $sParentId ? $sParentId : $sProductId;
02894 
02895         $sQ = "select 1 from {$sO2CTable}
02896                  left join {$sCatTable} on {$sCatTable}.oxid = {$sO2CTable}.oxcatnid
02897                  where {$sO2CTable}.oxobjectid = ".$oDb->quote( $sProductId )." and
02898                        {$sCatTable}.oxrootid = ".$oDb->quote( $sRootCatId );
02899 
02900         return (bool) $oDb->getOne( $sQ );
02901     }
02902 
02910     public function setBasketRootCatId($sRoot)
02911     {
02912         $this->_sBasketCategoryId = $sRoot;
02913     }
02914 
02920     public function getBasketRootCatId()
02921     {
02922         return $this->_sBasketCategoryId;
02923     }
02924 
02932     public function setCatChangeWarningState( $blShow )
02933     {
02934         $this->_blShowCatChangeWarning = $blShow;
02935     }
02936 
02942     public function showCatChangeWarning()
02943     {
02944         return $this->_blShowCatChangeWarning;
02945     }
02946 
02954     public function setTsProductId( $sProductId )
02955     {
02956         $this->_sTsProductId = $sProductId;
02957     }
02958 
02964     public function getTsProductId()
02965     {
02966         return $this->_sTsProductId;
02967     }
02968 
02976     public function getFTsProtectionCosts()
02977     {
02978         $oProtectionCost = $this->getCosts( 'oxtsprotection' );
02979         if ( $oProtectionCost && $oProtectionCost->getBruttoPrice() ) {
02980             return oxRegistry::getLang()->formatCurrency( $oProtectionCost->getBruttoPrice(), $this->getBasketCurrency() );
02981         }
02982         return false;
02983     }
02984 
02992     public function getTsProtectionVatPercent()
02993     {
02994         return $this->getCosts( 'oxtsprotection' )->getVat();
02995     }
02996 
03004     public function getTsProtectionVat()
03005     {
03006         $dProtectionVAT = $this->getCosts( 'oxtsprotection' )->getVatValue();
03007         // blShowVATForPayCharge option will be used, only for displaying, but not calculation
03008         if ( $dProtectionVAT > 0 && $this->getConfig()->getConfigParam( 'blShowVATForPayCharge' ) ) {
03009             return oxRegistry::getLang()->formatCurrency( $dProtectionVAT, $this->getBasketCurrency() );
03010         }
03011         return false;
03012     }
03013 
03021     public function getTsProtectionNet()
03022     {
03023         // blShowVATForPayCharge option will be used, only for displaying, but not calculation
03024         if ( $this->getConfig()->getConfigParam( 'blShowVATForPayCharge' ) ) {
03025             return oxRegistry::getLang()->formatCurrency( $this->getCosts( 'oxtsprotection' )->getNettoPrice(), $this->getBasketCurrency() );
03026         }
03027         return false;
03028     }
03029 
03037     public function getTsProtectionCosts()
03038     {
03039         $oProtection = $this->getCosts( 'oxtsprotection' );
03040         if ( $oProtection ) {
03041             return $oProtection->getBruttoPrice();
03042         }
03043         return false;
03044     }
03045 
03051     public function getTrustedShopProtectionCost()
03052     {
03053         return $this->getCosts( 'oxtsprotection' );
03054     }
03055 
03056 
03062     public function getNotDiscountProductsPrice()
03063     {
03064         return $this->_oNotDiscountedProductsPriceList;
03065     }
03066 
03080     protected function _addedNewItem( $sProductID, $dAmount, $aSel, $aPersParam, $blOverride, $blBundle, $sOldBasketItemId )
03081     {
03082         if ( !$blOverride ) {
03083             $this->_blNewITemAdded = null;
03084             oxSession::setVar( "blAddedNewItem", true );
03085         }
03086     }
03087 
03093     public function __wakeUp()
03094     {
03095         $this->_blNewITemAdded = null;
03096         $this->_isCalculationModeNetto = null;
03097     }
03098 
03104     public function isNewItemAdded()
03105     {
03106         if ( $this->_blNewITemAdded == null ) {
03107             $this->_blNewITemAdded = (bool) oxSession::getVar( "blAddedNewItem" );
03108             oxSession::deleteVar( "blAddedNewItem" );
03109         }
03110         return $this->_blNewITemAdded;
03111     }
03112 
03118     public function hasDownloadableProducts()
03119     {
03120         $this->_blDownloadableProducts = false;
03122         foreach ( $this->_aBasketContents as $oBasketItem ) {
03123             if ( $oBasketItem->getArticle(false) && $oBasketItem->getArticle(false)->isDownloadable() ) {
03124                 $this->_blDownloadableProducts = true;
03125                 break;
03126             }
03127         }
03128 
03129         return $this->_blDownloadableProducts;
03130     }
03131 
03137     public function hasArticlesWithIntangibleAgreement()
03138     {
03139         $blHasArticlesWithIntangibleAgreement = false;
03140 
03142         foreach ($this->_aBasketContents as $oBasketItem) {
03143             if ($oBasketItem->getArticle(false) && $oBasketItem->getArticle(false)->hasIntangibleAgreement()) {
03144                 $blHasArticlesWithIntangibleAgreement = true;
03145                 break;
03146             }
03147         }
03148 
03149         return $blHasArticlesWithIntangibleAgreement;
03150     }
03151 
03157     public function hasArticlesWithDownloadableAgreement()
03158     {
03159         $blHasArticlesWithIntangibleAgreement = false;
03160 
03162         foreach ($this->_aBasketContents as $oBasketItem) {
03163             if ($oBasketItem->getArticle(false) && $oBasketItem->getArticle(false)->hasDownloadableAgreement()) {
03164                 $blHasArticlesWithIntangibleAgreement = true;
03165                 break;
03166             }
03167         }
03168 
03169         return $blHasArticlesWithIntangibleAgreement;
03170     }
03171 
03177     public function getMinOrderPrice()
03178     {
03179         return oxPrice::getPriceInActCurrency( $this->getConfig()->getConfigParam( 'iMinOrderPrice' ) );
03180     }
03181 
03182 }