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         $myDB = oxDb::getDb();
00099 
00100         $sDiscountIdQuoted = $myDB->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 ( !$myDB->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 ( $myDB->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 ( $myDB->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         $myDB = oxDb::getDb();
00167 
00168         // check if this article is assigned
00169         $sQ  = "select 1 from oxobject2discount where oxdiscountid = ".$myDB->quote( $this->oxdiscount__oxid->value)." and oxtype = 'oxarticles' ";
00170         $sQ .= $this->_getProductCheckQuery( $oArticle );
00171         if ( !( $blOk = ( bool ) $myDB->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         $sQ = 'select 1 from oxobject2discount where oxdiscountid = '.oxDb::getDb()->quote($this->oxdiscount__oxid->value).' and oxtype in ("oxarticles", "oxcategories" ) ';
00266 
00267         return !( (bool) oxDb::getDb()->getOne( $sQ ) );
00268     }
00269 
00277     public function isForBundleItem( $oArticle )
00278     {
00279         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00280             return false;
00281         }
00282 
00283         $oDb = oxDb::getDb();
00284         $sQ  = "select 1 from oxobject2discount where oxdiscountid=".$oDb->quote( $this->getId() );
00285         $sQ .= $this->_getProductCheckQuery( $oArticle );
00286         if ( !( $blOk = (bool) $oDb->getOne( $sQ ) ) ) {
00287             // additional checks for amounts and other dependencies
00288             $blOk = $this->_checkForArticleCategories( $oArticle );
00289         }
00290         return $blOk;
00291     }
00292 
00300     public function isForBundleBasket( $oBasket )
00301     {
00302         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00303             return false;
00304         }
00305 
00306         return $this->isForBasket( $oBasket );
00307     }
00308 
00317     public function getAbsValue( $dPrice, $dAmount = 1 )
00318     {
00319         if ( $this->oxdiscount__oxaddsumtype->value == '%' ) {
00320             return $dPrice * ( $this->oxdiscount__oxaddsum->value / 100 );
00321         } else {
00322             $oCur = $this->getConfig()->getActShopCurrencyObject();
00323             return $this->oxdiscount__oxaddsum->value * $dAmount * $oCur->rate;
00324         }
00325     }
00326 
00335     public function applyDiscount( $oPrice, $dAmount = 1 )
00336     {
00337         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00338 
00339             $oCur = $this->getConfig()->getActShopCurrencyObject();
00340 
00341             $oDiscountPrice = oxNew( 'oxprice' );
00342             $oDiscountPrice->setBruttoPriceMode();
00343             $oDiscountPrice->setPrice( $this->oxdiscount__oxaddsum->value * $oCur->rate, $oPrice->getVat() );
00344         } else {
00345 
00346             $oDiscountPrice = oxNew( 'oxprice' );
00347             $oDiscountPrice->setBruttoPriceMode();
00348             $oDiscountPrice->setPrice( $oPrice->getBruttoPrice() / 100 * $this->oxdiscount__oxaddsum->value, $oPrice->getVat() );
00349 
00350 
00351 
00352         }
00353         $oDiscountPrice->multiply( $dAmount * -1 );
00354         $oPrice->addPrice( $oDiscountPrice );
00355     }
00356 
00364     public function getBundleAmount( $dAmount )
00365     {
00366         $dItemAmount = $this->oxdiscount__oxitmamount->value;
00367 
00368         // Multiplying bundled articles count, if allowed
00369         if ( $this->oxdiscount__oxitmmultiple->value && $this->oxdiscount__oxamount->value > 0 ) {
00370             $dItemAmount = floor( $dAmount / $this->oxdiscount__oxamount->value ) * $this->oxdiscount__oxitmamount->value;
00371         }
00372 
00373         return $dItemAmount;
00374     }
00375 
00383     protected function _checkForArticleCategories( $oArticle )
00384     {
00385         // check if article is in some assigned category
00386         $aCatIds = $oArticle->getCategoryIds();
00387         if (!$aCatIds || !count($aCatIds)) {
00388             // no categories are set for article, so no discounts from categories..
00389             return false;
00390         }
00391 
00392         $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00393 
00394         $oDb = oxDb::getDb();
00395         // getOne appends limit 1, so this one should be fast enough
00396         $sQ = "select oxobjectid from oxobject2discount where oxdiscountid = ".$oDb->quote($this->oxdiscount__oxid->value)." and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00397 
00398         return $oDb->getOne( $sQ );
00399     }
00400 
00406     public function getSimpleDiscount()
00407     {
00408         $oDiscount = new OxStdClass();
00409         $oDiscount->sOXID     = $this->getId();
00410         $oDiscount->sDiscount = $this->oxdiscount__oxtitle->value;
00411         $oDiscount->sType     = $this->oxdiscount__oxaddsumtype->value;
00412 
00413         return $oDiscount;
00414     }
00415 
00424     protected function _getProductCheckQuery( $oProduct )
00425     {
00426         $oDb = oxDb::getDb();
00427         // check if this article is assigned
00428         if ( ( $sParentId = $oProduct->getProductParentId() ) ) {
00429             $sArticleId = " and ( oxobjectid = ".$oDb->quote( $oProduct->getProductId() )." or oxobjectid = ".$oDb->quote( $sParentId ) . " )";
00430         } else {
00431             $sArticleId = " and oxobjectid = ".$oDb->quote( $oProduct->getProductId() );
00432         }
00433 
00434         return $sArticleId;
00435     }
00436 
00437 }