oxdiscount.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxDiscount extends oxI18n
00007 {
00013     protected $_sClassName = 'oxdiscount';
00014 
00020     protected $_dAmount = null;
00021 
00027     protected $_sBasketIdent = null;
00028 
00034     protected $_blIsForArticleOrForCategory = null;
00035 
00041     protected $_aHasArticleDiscounts = array();
00042 
00046     public function __construct()
00047     {
00048         parent::__construct();
00049         $this->init( 'oxdiscount' );
00050     }
00051 
00059     public function delete( $sOXID = null )
00060     {
00061         if ( !$sOXID ) {
00062             $sOXID = $this->getId();
00063         }
00064         if ( !$sOXID ) {
00065             return false;
00066         }
00067 
00068 
00069         $oDb = oxDb::getDb();
00070         $oDb->execute( 'delete from oxobject2discount where oxobject2discount.oxdiscountid = '.$oDb->quote($sOXID) );
00071 
00072         return parent::delete( $sOXID );
00073     }
00074 
00082     public function isForArticle( $oArticle )
00083     {
00084 
00085         // item discounts may only be applied for basket
00086         if ( $this->oxdiscount__oxaddsumtype->value == 'itm' ) {
00087             return false;
00088         }
00089 
00090         if ( $this->oxdiscount__oxamount->value || $this->oxdiscount__oxprice->value ) {
00091             return false;
00092         }
00093 
00094         if ( $this->oxdiscount__oxpriceto->value && ($this->oxdiscount__oxpriceto->value < $oArticle->getBasePrice()) ) {
00095             return false;
00096         }
00097 
00098         $oDb = oxDb::getDb();
00099 
00100         $sDiscountIdQuoted = $oDb->quote($this->oxdiscount__oxid->value);
00101 
00102         //check for global discount (no articles, no categories)
00103         if ( $this->_blIsForArticleOrForCategory ) {
00104             return true;
00105         } elseif ( $this->_blIsForArticleOrForCategory === null ) {
00106 
00107             $this->_blIsForArticleOrForCategory = false;
00108             $sQ = "select 1 from oxobject2discount where oxdiscountid = $sDiscountIdQuoted and ( oxtype = 'oxarticles' or oxtype = 'oxcategories')";
00109             if ( ! $oDb->getOne( $sQ ) ) {
00110                 $this->_blIsForArticleOrForCategory = true;
00111                 return true;
00112             }
00113         }
00114 
00115         $sArticleId = $oArticle->getProductId();
00116 
00117         if ( !$this->_blIsForArticleAndForCategory && !isset($this->_aHasArticleDiscounts[ $sArticleId ] ) ) {
00118 
00119             $this->_aHasArticleDiscounts[ $sArticleId ] = false ;
00120 
00121             // check if this article is assigned
00122             $sQ  = "select 1 from oxobject2discount where oxdiscountid = {$sDiscountIdQuoted} and oxtype = 'oxarticles' ";
00123             $sQ .= $this->_getProductCheckQuery( $oArticle );
00124 
00125             if ( $oDb->getOne( $sQ ) ) {
00126                 $this->_aHasArticleDiscounts[ $sArticleId ] = true;
00127                 return true;
00128             } else {
00129                 // check if article is in some assigned category
00130                 $aCatIds = $oArticle->getCategoryIds();
00131                 if (!$aCatIds || !count($aCatIds)) {
00132                     // no categories are set for article, so no discounts from categories..
00133                     return false;
00134                 }
00135                 $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00136                 // getOne appends limit 1, so this one should be fast enough
00137                 $sQ = "select 1 from oxobject2discount where oxdiscountid = {$sDiscountIdQuoted} and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00138                 if ( $oDb->getOne( $sQ ) ) {
00139                     $this->_aHasArticleDiscounts[ $sArticleId ] = true;
00140                     return true;
00141                 }
00142             }
00143         }
00144 
00145         return $this->_aHasArticleDiscounts[ $sArticleId ];
00146     }
00147 
00155     public function isForBasketItem( $oArticle )
00156     {
00157         if ( $this->oxdiscount__oxamount->value == 0 && $this->oxdiscount__oxprice->value == 0 ) {
00158             return false;
00159         }
00160 
00161         // skipping bundle discounts
00162         if ( $this->oxdiscount__oxaddsumtype->value == 'itm' ) {
00163             return false;
00164         }
00165 
00166         $oDb = oxDb::getDb();
00167 
00168         // check if this article is assigned
00169         $sQ  = "select 1 from oxobject2discount where oxdiscountid = ".$oDb->quote( $this->oxdiscount__oxid->value)." and oxtype = 'oxarticles' ";
00170         $sQ .= $this->_getProductCheckQuery( $oArticle );
00171         if ( !( $blOk = ( bool ) $oDb->getOne( $sQ ) ) ) {
00172 
00173             // checkin article cateogry
00174             $blOk = $this->_checkForArticleCategories( $oArticle );
00175         }
00176 
00177         return $blOk;
00178     }
00179 
00187     public function isForBasketAmount( $oBasket )
00188     {
00189         $dAmount = 0;
00190         $aBasketItems = $oBasket->getContents();
00191         foreach ( $aBasketItems as $oBasketItem ) {
00192 
00193             $oBasketArticle = $oBasketItem->getArticle(false);
00194 
00195             $blForBasketItem = false;
00196             if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00197                 $blForBasketItem = $this->isForBasketItem( $oBasketArticle );
00198             } else {
00199                 $blForBasketItem = $this->isForBundleItem( $oBasketArticle );
00200             }
00201 
00202             if ( $blForBasketItem ) {
00203                 $dRate = $oBasket->getBasketCurrency()->rate;
00204                 if ( $this->oxdiscount__oxprice->value ) {
00205                     if ( ( $oPrice = $oBasketArticle->getPrice() ) ) {
00206                         $dAmount += ($oPrice->getBruttoPrice() * $oBasketItem->getAmount())/$dRate;
00207                     }
00208                 } elseif ( $this->oxdiscount__oxamount->value ) {
00209                     $dAmount += $oBasketItem->getAmount();
00210                 }
00211             }
00212         }
00213 
00214         return $this->isForAmount( $dAmount );
00215     }
00216 
00224     public function isForAmount( $dAmount )
00225     {
00226         $blIs = true;
00227 
00228         if ( $this->oxdiscount__oxprice->value &&
00229             ( $dAmount < $this->oxdiscount__oxprice->value || $dAmount > $this->oxdiscount__oxpriceto->value ) ) {
00230             $blIs = false;
00231         } elseif ( $this->oxdiscount__oxamount->value &&
00232             ( $dAmount < $this->oxdiscount__oxamount->value || $dAmount > $this->oxdiscount__oxamountto->value ) ) {
00233             $blIs = false;
00234         }
00235         return $blIs;
00236     }
00237 
00245     public function isForBasket( $oBasket )
00246     {
00247         // initial configuration check
00248         if ( $this->oxdiscount__oxamount->value == 0 && $this->oxdiscount__oxprice->value == 0 ) {
00249             return false;
00250         }
00251 
00252         $oSummary = $oBasket->getBasketSummary();
00253         // amounts check
00254         if ( $this->oxdiscount__oxamount->value && ( $oSummary->iArticleCount < $this->oxdiscount__oxamount->value || $oSummary->iArticleCount > $this->oxdiscount__oxamountto->value ) ) {
00255             return false;
00256             // price check
00257         } elseif ($this->oxdiscount__oxprice->value) {
00258             $dRate = $oBasket->getBasketCurrency()->rate;
00259             if ( $oSummary->dArticleDiscountablePrice < $this->oxdiscount__oxprice->value*$dRate || $oSummary->dArticleDiscountablePrice > $this->oxdiscount__oxpriceto->value*$dRate ) {
00260                 return false;
00261             }
00262         }
00263 
00264         // oxobject2discount configuration check
00265         $oDb = oxDb::getDb();
00266         $sQ = 'select 1 from oxobject2discount where oxdiscountid = ' . $oDb->quote($this->oxdiscount__oxid->value).' and oxtype in ("oxarticles", "oxcategories" ) ';
00267 
00268         return !( (bool) $oDb->getOne( $sQ ) );
00269     }
00270 
00278     public function isForBundleItem( $oArticle )
00279     {
00280         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00281             return false;
00282         }
00283 
00284         $oDb = oxDb::getDb();
00285         $sQ  = "select 1 from oxobject2discount where oxdiscountid=".$oDb->quote( $this->getId() );
00286         $sQ .= $this->_getProductCheckQuery( $oArticle );
00287         if ( !( $blOk = (bool) $oDb->getOne( $sQ ) ) ) {
00288             // additional checks for amounts and other dependencies
00289             $blOk = $this->_checkForArticleCategories( $oArticle );
00290         }
00291         return $blOk;
00292     }
00293 
00301     public function isForBundleBasket( $oBasket )
00302     {
00303         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00304             return false;
00305         }
00306 
00307         return $this->isForBasket( $oBasket );
00308     }
00309 
00318     public function getAbsValue( $dPrice, $dAmount = 1 )
00319     {
00320         if ( $this->oxdiscount__oxaddsumtype->value == '%' ) {
00321             return $dPrice * ( $this->oxdiscount__oxaddsum->value / 100 );
00322         } else {
00323             $oCur = $this->getConfig()->getActShopCurrencyObject();
00324             return $this->oxdiscount__oxaddsum->value * $dAmount * $oCur->rate;
00325         }
00326     }
00327 
00336     public function applyDiscount( $oPrice, $dAmount = 1 )
00337     {
00338         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00339 
00340             $oCur = $this->getConfig()->getActShopCurrencyObject();
00341 
00342             $oDiscountPrice = oxNew( 'oxprice' );
00343             $oDiscountPrice->setBruttoPriceMode();
00344             $oDiscountPrice->setPrice( $this->oxdiscount__oxaddsum->value * $oCur->rate, $oPrice->getVat() );
00345             //#3587
00346             $oDiscountPrice->multiply( $dAmount * -1);
00347         } else {
00348             //percent discount
00349             $oDiscountPrice = oxNew( 'oxprice' );
00350             $oDiscountPrice->setBruttoPriceMode();
00351             $oDiscountPrice->setPrice( $oPrice->getBruttoPrice() / 100 * $this->oxdiscount__oxaddsum->value, $oPrice->getVat() );
00352             //#3587
00353             $oDiscountPrice->multiply(-1);
00354         }
00355            //#3587
00356         //$oDiscountPrice->multiply( $dAmount * -1 );
00357         $oPrice->addPrice( $oDiscountPrice );
00358 
00359         if ( $oPrice->getBruttoPrice() < 0 || $oPrice->getNettoPrice() < 0 ) {
00360             $oPrice->setPrice(0);
00361         }
00362     }
00363 
00371     public function getBundleAmount( $dAmount )
00372     {
00373         $dItemAmount = $this->oxdiscount__oxitmamount->value;
00374 
00375         // Multiplying bundled articles count, if allowed
00376         if ( $this->oxdiscount__oxitmmultiple->value && $this->oxdiscount__oxamount->value > 0 ) {
00377             $dItemAmount = floor( $dAmount / $this->oxdiscount__oxamount->value ) * $this->oxdiscount__oxitmamount->value;
00378         }
00379 
00380         return $dItemAmount;
00381     }
00382 
00390     protected function _checkForArticleCategories( $oArticle )
00391     {
00392         // check if article is in some assigned category
00393         $aCatIds = $oArticle->getCategoryIds();
00394         if (!$aCatIds || !count($aCatIds)) {
00395             // no categories are set for article, so no discounts from categories..
00396             return false;
00397         }
00398 
00399         $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00400 
00401         $oDb = oxDb::getDb();
00402         // getOne appends limit 1, so this one should be fast enough
00403         $sQ = "select oxobjectid from oxobject2discount where oxdiscountid = ".$oDb->quote($this->oxdiscount__oxid->value)." and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00404 
00405         return $oDb->getOne( $sQ );
00406     }
00407 
00413     public function getSimpleDiscount()
00414     {
00415         $oDiscount = new OxStdClass();
00416         $oDiscount->sOXID     = $this->getId();
00417         $oDiscount->sDiscount = $this->oxdiscount__oxtitle->value;
00418         $oDiscount->sType     = $this->oxdiscount__oxaddsumtype->value;
00419 
00420         return $oDiscount;
00421     }
00422 
00431     protected function _getProductCheckQuery( $oProduct )
00432     {
00433         $oDb = oxDb::getDb();
00434         // check if this article is assigned
00435         if ( ( $sParentId = $oProduct->getProductParentId() ) ) {
00436             $sArticleId = " and ( oxobjectid = ".$oDb->quote( $oProduct->getProductId() )." or oxobjectid = ".$oDb->quote( $sParentId ) . " )";
00437         } else {
00438             $sArticleId = " and oxobjectid = ".$oDb->quote( $oProduct->getProductId() );
00439         }
00440 
00441         return $sArticleId;
00442     }
00443 
00444 }