oxvoucher.php

Go to the documentation of this file.
00001 <?php
00002 
00008 class oxVoucher extends oxBase
00009 {
00010 
00011     protected $_oSerie = null;
00012 
00018     protected $_blDisableShopCheck = true;
00019 
00023     protected $_sClassName = 'oxvoucher';
00024 
00028     public function __construct()
00029     {
00030         parent::__construct();
00031         $this->init( 'oxvouchers' );
00032     }
00033 
00045     public function getVoucherByNr( $sVoucherNr, $aVouchers = array(), $blCheckavalability = false )
00046     {
00047         $oRet = null;
00048         if ( !is_null( $sVoucherNr ) ) {
00049 
00050             $sViewName = $this->getViewName();
00051             $sSeriesViewName = getViewName( 'oxvoucherseries' );
00052             $myDB = oxDb::getDb();
00053 
00054             $sQ  = "select {$sViewName}.* from {$sViewName}, {$sSeriesViewName} where
00055                         {$sSeriesViewName}.oxid = {$sViewName}.oxvoucherserieid and
00056                         {$sViewName}.oxvouchernr = " . $myDB->quote( $sVoucherNr ) . " and ";
00057 
00058             if ( is_array( $aVouchers ) ) {
00059                 foreach ( $aVouchers as $sVoucherId => $sSkipVoucherNr ) {
00060                     $sQ .= "{$sViewName}.oxid != " . $myDB->quote( $sVoucherId ) . " and ";
00061                 }
00062             }
00063             $sQ .= "( {$sViewName}.oxorderid is NULL || {$sViewName}.oxorderid = '' ) ";
00064 
00065             //voucher timeout for 3 hours
00066             if ( $blCheckavalability ) {
00067                 $iTime = time() - 3600 * 3;
00068                 $sQ .= " and {$sViewName}.oxreserved < '{$iTime}' ";
00069             }
00070 
00071             $sQ .= " limit 1";
00072 
00073             if ( ! ( $oRet = $this->assignRecord( $sQ ) ) ) {
00074                 $oEx = oxNew( 'oxVoucherException' );
00075                 $oEx->setMessage( 'EXCEPTION_VOUCHER_NOVOUCHER' );
00076                 $oEx->setVoucherNr( $sVoucherNr );
00077                 throw $oEx;
00078             }
00079         }
00080 
00081         return $oRet;
00082     }
00083 
00093     public function markAsUsed( $sOrderId, $sUserId, $dDiscount )
00094     {
00095         //saving oxreserved field
00096         if ( $this->oxvouchers__oxid->value ) {
00097             $this->oxvouchers__oxorderid->setValue($sOrderId);
00098             $this->oxvouchers__oxuserid->setValue($sUserId);
00099             $this->oxvouchers__oxdiscount->setValue($dDiscount);
00100             $this->oxvouchers__oxdateused->setValue(date( "Y-m-d", oxUtilsDate::getInstance()->getTime() ));
00101             $this->save();
00102         }
00103     }
00104 
00110     public function markAsReserved()
00111     {
00112         //saving oxreserved field
00113         $sVoucherID = $this->oxvouchers__oxid->value;
00114 
00115         if ( $sVoucherID ) {
00116             $myDB = oxDb::getDb();
00117             $sQ = "update oxvouchers set oxreserved = " . time() . " where oxid = " . $myDB->quote( $sVoucherID );
00118             $myDB->Execute( $sQ );
00119         }
00120     }
00121 
00127     public function unMarkAsReserved()
00128     {
00129         //saving oxreserved field
00130         $sVoucherID = $this->oxvouchers__oxid->value;
00131 
00132         if ( $sVoucherID ) {
00133             $myDB = oxDb::getDb();
00134             $sQ = "update oxvouchers set oxreserved = 0 where oxid = " . $myDB->quote( $sVoucherID );
00135             $myDB->Execute($sQ);
00136         }
00137     }
00138 
00148     public function getDiscountValue( $dPrice )
00149     {
00150         if ($this->_isProductVoucher()) {
00151             return $this->_getProductDiscoutValue( $dPrice );
00152         } elseif ($this->_isCategoryVoucher()) {
00153             return $this->_getCategoryDiscoutValue( $dPrice );
00154         } else {
00155             return $this->_getGenericDiscoutValue( $dPrice );
00156         }
00157     }
00158 
00159     // Checking General Availability
00170     public function checkVoucherAvailability( $aVouchers, $dPrice )
00171     {
00172         $this->_isAvailableWithSameSeries( $aVouchers );
00173         $this->_isAvailableWithOtherSeries( $aVouchers );
00174         $this->_isValidDate();
00175         $this->_isAvailablePrice( $dPrice );
00176         $this->_isNotReserved();
00177 
00178         // returning true - no exception was thrown
00179         return true;
00180     }
00181 
00193     public function checkBasketVoucherAvailability( $aVouchers, $dPrice )
00194     {
00195         $this->_isAvailableWithSameSeries( $aVouchers );
00196         $this->_isAvailableWithOtherSeries( $aVouchers );
00197         $this->_isValidDate();
00198         $this->_isAvailablePrice( $dPrice );
00199 
00200         // returning true - no exception was thrown
00201         return true;
00202     }
00203 
00213     protected function _isAvailablePrice( $dPrice )
00214     {
00215         if ( $this->getDiscountValue( $dPrice ) < 0 ) {
00216             $oEx = oxNew( 'oxVoucherException' );
00217             $oEx->setMessage('EXCEPTION_VOUCHER_TOTALBELOWZERO');
00218             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00219             throw $oEx;
00220         }
00221         $oSerie = $this->getSerie();
00222         $oCur = $this->getConfig()->getActShopCurrencyObject();
00223         if ( $oSerie->oxvoucherseries__oxminimumvalue->value && $dPrice < ($oSerie->oxvoucherseries__oxminimumvalue->value*$oCur->rate) ) {
00224             $oEx = oxNew( 'oxVoucherException' );
00225             $oEx->setMessage('EXCEPTION_VOUCHER_INCORRECTPRICE');
00226             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00227             throw $oEx;
00228         }
00229 
00230         return true;
00231     }
00232 
00244     protected function _isAvailableWithSameSeries( $aVouchers )
00245     {
00246         if ( is_array( $aVouchers ) ) {
00247             $sId = $this->getId();
00248             if (isset($aVouchers[$sId])) {
00249                 unset($aVouchers[$sId]);
00250             }
00251             $oSerie = $this->getSerie();
00252             if (!$oSerie->oxvoucherseries__oxallowsameseries->value) {
00253                 foreach ( $aVouchers as $voucherId => $voucherNr ) {
00254                     $oVoucher = oxNew( 'oxvoucher' );
00255                     $oVoucher->load($voucherId);
00256                     if ( $this->oxvouchers__oxvoucherserieid->value == $oVoucher->oxvouchers__oxvoucherserieid->value ) {
00257                             $oEx = oxNew( 'oxVoucherException' );
00258                             $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDSAMESERIES');
00259                             $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00260                             throw $oEx;
00261                     }
00262                 }
00263             }
00264         }
00265 
00266         return true;
00267     }
00268 
00279     protected function _isAvailableWithOtherSeries( $aVouchers )
00280     {
00281         if ( is_array( $aVouchers ) && count($aVouchers) ) {
00282             $oSerie = $this->getSerie();
00283             $sIds = implode(',', oxDb::getInstance()->quoteArray( array_keys( $aVouchers ) ) );
00284             $blAvailable = true;
00285             $myDB = oxDb::getDb();
00286             if (!$oSerie->oxvoucherseries__oxallowotherseries->value) {
00287                 // just search for vouchers with different series
00288                 $sSql  = "select 1 from oxvouchers where oxvouchers.oxid in ($sIds) and ";
00289                 $sSql .= "oxvouchers.oxvoucherserieid != " . $myDB->quote( $this->oxvouchers__oxvoucherserieid->value ) ;
00290                 $blAvailable &= !$myDB->getOne($sSql);
00291             } else {
00292                 // search for vouchers with different series and those vouchers do not allow other series
00293                 $sSql  = "select 1 from oxvouchers left join oxvoucherseries on oxvouchers.oxvoucherserieid=oxvoucherseries.oxid ";
00294                 $sSql .= "where oxvouchers.oxid in ($sIds) and oxvouchers.oxvoucherserieid != " . $myDB->quote( $this->oxvouchers__oxvoucherserieid->value );
00295                 $sSql .= "and not oxvoucherseries.oxallowotherseries";
00296                 $blAvailable &= !$myDB->getOne($sSql);
00297             }
00298             if ( !$blAvailable ) {
00299                     $oEx = oxNew( 'oxVoucherException' );
00300                     $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDOTHERSERIES');
00301                     $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00302                     throw $oEx;
00303             }
00304         }
00305 
00306         return true;
00307     }
00308 
00316     protected function _isValidDate()
00317     {
00318         $oSerie = $this->getSerie();
00319         // if time is not set - keep it as active by default
00320         $sDefTimeStamp = oxUtilsDate::getInstance()->formatDBDate( '-' );
00321         if ( $oSerie->oxvoucherseries__oxbegindate->value == $sDefTimeStamp &&
00322              $oSerie->oxvoucherseries__oxenddate->value == $sDefTimeStamp ) {
00323             return true;
00324         }
00325 
00326         if ( ( strtotime( $oSerie->oxvoucherseries__oxbegindate->value ) < time() &&
00327               strtotime( $oSerie->oxvoucherseries__oxenddate->value ) > time() ) ||
00328             !$oSerie->oxvoucherseries__oxenddate->value ||
00329             $oSerie->oxvoucherseries__oxenddate->value == $sDefTimeStamp ) {
00330             return true;
00331         }
00332 
00333         $oEx = oxNew( 'oxVoucherException' );
00334         $oEx->setMessage('EXCEPTION_VOUCHER_ISNOTVALIDDATE');
00335         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00336         throw $oEx;
00337     }
00338 
00346     protected function _isNotReserved()
00347     {
00348 
00349         if ( $this->oxvouchers__oxreserved->value < time() - 3600 * 3 ) {
00350             return true;
00351         }
00352 
00353         $oEx = oxNew( 'oxVoucherException' );
00354         $oEx->setMessage('EXCEPTION_VOUCHER_ISRESERVED');
00355         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00356         throw $oEx;
00357     }
00358 
00359     // Checking User Availability
00369     public function checkUserAvailability( $oUser )
00370     {
00371 
00372         $this->_isAvailableInOtherOrder( $oUser );
00373         $this->_isValidUserGroup( $oUser );
00374 
00375         // returning true if no exception was thrown
00376         return true;
00377     }
00378 
00388     protected function _isAvailableInOtherOrder( $oUser )
00389     {
00390         $oSerie = $this->getSerie();
00391         if ( !$oSerie->oxvoucherseries__oxallowuseanother->value ) {
00392 
00393             $myDB = oxDb::getDb();
00394             $sSelect  = 'select count(*) from '.$this->getViewName().' where oxuserid = '. $myDB->quote( $oUser->oxuser__oxid->value ) . ' and ';
00395             $sSelect .= 'oxvoucherserieid = ' . $myDB->quote( $this->oxvouchers__oxvoucherserieid->value ) . ' and ';
00396             $sSelect .= 'oxorderid is not NULL and oxorderid != "" ';
00397 
00398             if ( $myDB->getOne( $sSelect )) {
00399                 $oEx = oxNew( 'oxVoucherException' );
00400                 $oEx->setMessage('EXCEPTION_VOUCHER_NOTAVAILABLEINOTHERORDER');
00401                 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00402                 throw $oEx;
00403             }
00404         }
00405 
00406         return true;
00407     }
00408 
00418     protected function _isValidUserGroup( $oUser )
00419     {
00420         $oVoucherSerie = $this->getSerie();
00421         $oUserGroups = $oVoucherSerie->setUserGroups();
00422 
00423         // dodger Task #1555 R Voucher does not work for not logged user?
00424         if ( !$oUserGroups->count() ) {
00425             return true;
00426         }
00427 
00428         if ( $oUser ) {
00429             foreach ( $oUserGroups as $oGroup ) {
00430                 if ( $oUser->inGroup( $oGroup->getId() ) ) {
00431                     return true;
00432                 }
00433             }
00434         }
00435 
00436         $oEx = oxNew( 'oxVoucherException' );
00437         $oEx->setMessage( 'EXCEPTION_VOUCHER_NOTVALIDUSERGROUP' );
00438         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00439         throw $oEx;
00440     }
00441 
00447     public function getSimpleVoucher()
00448     {
00449         $oVoucher = new oxStdClass();
00450         $oVoucher->sVoucherId = $this->getId();
00451         $oVoucher->sVoucherNr = $this->oxvouchers__oxvouchernr->value;
00452         // R. setted in oxbasket : $oVoucher->fVoucherdiscount = oxLang::getInstance()->formatCurrency( $this->oxvouchers__oxdiscount->value );
00453 
00454         return $oVoucher;
00455     }
00456 
00462     public function getSerie()
00463     {
00464         if ($this->_oSerie !== null) {
00465             return $this->_oSerie;
00466         }
00467         $oSerie = oxNew('oxvoucherserie');
00468         if (!$oSerie->load($this->oxvouchers__oxvoucherserieid->value)) {
00469             throw oxNew( "oxObjectException" );
00470         }
00471         $this->_oSerie = $oSerie;
00472         return $oSerie;
00473     }
00474 
00480     protected function _isProductVoucher()
00481     {
00482         $myDB    = oxDb::getDb();
00483         $oSerie  = $this->getSerie();
00484         $sSelect = "select 1 from oxobject2discount where oxdiscountid = ".$myDB->quote( $oSerie->getId() )." and oxtype = 'oxarticles'";
00485         $blOk    = ( bool ) $myDB->getOne( $sSelect );
00486 
00487         return $blOk;
00488     }
00489 
00495     protected function _isCategoryVoucher()
00496     {
00497         $myDB    = oxDb::getDb();
00498         $oSerie  = $this->getSerie();
00499         $sSelect = "select 1 from oxobject2discount where oxdiscountid = ". $myDB->quote( $oSerie->getId() )." and oxtype = 'oxcategories'";
00500         $blOk    = ( bool ) $myDB->getOne( $sSelect );
00501 
00502         return $blOk;
00503     }
00504 
00510     protected function _getSerieDiscount( )
00511     {
00512         $oSerie    = $this->getSerie();
00513         $oDiscount = oxNew('oxDiscount');
00514 
00515         $oDiscount->setId($oSerie->getId());
00516         $oDiscount->oxdiscount__oxshopid      = new oxField($oSerie->oxvoucherseries__oxshopid->value);
00517         $oDiscount->oxdiscount__oxactive      = new oxField(true);
00518         $oDiscount->oxdiscount__oxactivefrom  = new oxField($oSerie->oxvoucherseries__oxbegindate->value);
00519         $oDiscount->oxdiscount__oxactiveto    = new oxField($oSerie->oxvoucherseries__oxenddate->value);
00520         $oDiscount->oxdiscount__oxtitle       = new oxField($oSerie->oxvoucherseries__oxserienr->value);
00521         $oDiscount->oxdiscount__oxamount      = new oxField(1);
00522         $oDiscount->oxdiscount__oxamountto    = new oxField(MAX_64BIT_INTEGER);
00523         $oDiscount->oxdiscount__oxprice       = new oxField(0);
00524         $oDiscount->oxdiscount__oxpriceto     = new oxField(MAX_64BIT_INTEGER);
00525         $oDiscount->oxdiscount__oxaddsumtype  = new oxField($oSerie->oxvoucherseries__oxdiscounttype->value=='percent'?'%':'abs');
00526         $oDiscount->oxdiscount__oxaddsum      = new oxField($oSerie->oxvoucherseries__oxdiscount->value);
00527         $oDiscount->oxdiscount__oxitmartid    = new oxField();
00528         $oDiscount->oxdiscount__oxitmamount   = new oxField();
00529         $oDiscount->oxdiscount__oxitmmultiple = new oxField();
00530 
00531         return $oDiscount;
00532     }
00533 
00541     protected function _getBasketItems($oDiscount = null)
00542     {
00543         if ($this->oxvouchers__oxorderid->value) {
00544             return $this->_getOrderBasketItems($oDiscount);
00545         } elseif ( $this->getSession()->getBasket() ) {
00546             return $this->_getSessionBasketItems($oDiscount);
00547         } else {
00548             return array();
00549         }
00550     }
00551 
00559     protected function _getOrderBasketItems($oDiscount = null)
00560     {
00561         if (is_null($oDiscount)) {
00562             $oDiscount = $this->_getSerieDiscount();
00563         }
00564 
00565         $oOrder = oxNew('oxorder');
00566         $oOrder->load($this->oxvouchers__oxorderid->value);
00567 
00568         $aItems  = array();
00569         $iCount  = 0;
00570 
00571         foreach ( $oOrder->getOrderArticles(true) as $oOrderArticle ) {
00572             if (!$oOrderArticle->skipDiscounts() && $oDiscount->isForBasketItem($oOrderArticle)) {
00573                 $aItems[$iCount] = array(
00574                     'oxid'     => $oOrderArticle->getProductId(),
00575                     'price'    => $oOrderArticle->oxorderarticles__oxprice->value,
00576                     'discount' => $oDiscount->getAbsValue($oOrderArticle->oxorderarticles__oxprice->value),
00577                     'amount'   => $oOrderArticle->oxorderarticles__oxamount->value,
00578                 );
00579                 $iCount ++;
00580             }
00581         }
00582 
00583         return $aItems;
00584     }
00585 
00593     protected function _getSessionBasketItems($oDiscount = null)
00594     {
00595         if (is_null($oDiscount)) {
00596             $oDiscount = $this->_getSerieDiscount();
00597         }
00598 
00599         $oBasket = $this->getSession()->getBasket();
00600         $aItems  = array();
00601         $iCount  = 0;
00602 
00603         foreach ( $oBasket->getContents() as $oBasketItem ) {
00604             if ( !$oBasketItem->isDiscountArticle() && ( $oArticle = $oBasketItem->getArticle() ) && !$oArticle->skipDiscounts() && $oDiscount->isForBasketItem($oArticle) ) {
00605 
00606                 $aItems[$iCount] = array(
00607                     'oxid'     => $oArticle->getId(),
00608                     'price'    => $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice(),
00609                     'discount' => $oDiscount->getAbsValue($oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice()),
00610                     'amount'   => $oBasketItem->getAmount(),
00611                 );
00612 
00613                 $iCount ++;
00614             }
00615         }
00616 
00617         return $aItems;
00618     }
00619 
00629     protected function _getGenericDiscoutValue( $dPrice )
00630     {
00631         $oSerie = $this->getSerie();
00632         if ( $oSerie->oxvoucherseries__oxdiscounttype->value == 'absolute' ) {
00633             $oCur = $this->getConfig()->getActShopCurrencyObject();
00634             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value * $oCur->rate;
00635         } else {
00636             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value / 100 * $dPrice;
00637         }
00638 
00639         if ( $dDiscount > $dPrice ) {
00640             $oEx = oxNew( 'oxVoucherException' );
00641             $oEx->setMessage('EXCEPTION_VOUCHER_TOTALBELOWZERO');
00642             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00643             throw $oEx;
00644         }
00645 
00646         return $dDiscount;
00647     }
00648 
00658     protected function _getProductDiscoutValue( $dPrice )
00659     {
00660         $oDiscount    = $this->_getSerieDiscount();
00661         $aBasketItems = $this->_getBasketItems($oDiscount);
00662 
00663         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00664         if (!count($aBasketItems) && !$this->isAdmin() ) {
00665             $oEx = oxNew( 'oxVoucherException' );
00666             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00667             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00668             throw $oEx;
00669         }
00670 
00671         $oSerie    = $this->getSerie();
00672 
00673         $oVoucherPrice  = oxNew('oxPrice');
00674         $oDiscountPrice = oxNew('oxPrice');
00675         $oProductPrice  = oxNew('oxPrice');
00676         $oProductTotal  = oxNew('oxPrice');
00677 
00678         foreach ( $aBasketItems as $aBasketItem ) {
00679 
00680             $oDiscountPrice->setPrice($aBasketItem['discount']);
00681             $oProductPrice->setPrice($aBasketItem['price']);
00682 
00683             // Individual voucher is not multiplied by article amount
00684             if (!$oSerie->oxvoucherseries__oxcalculateonce->value) {
00685                 $oDiscountPrice->multiply($aBasketItem['amount']);
00686                 $oProductPrice->multiply($aBasketItem['amount']);
00687             }
00688 
00689             $oVoucherPrice->add($oDiscountPrice->getBruttoPrice());
00690             $oProductTotal->add($oProductPrice->getBruttoPrice());
00691         }
00692 
00693         $dVoucher = $oVoucherPrice->getBruttoPrice();
00694         $dProduct = $oProductTotal->getBruttoPrice();
00695 
00696         if ( $dVoucher > $dProduct ) {
00697             return $dProduct;
00698         }
00699 
00700         return $dVoucher;
00701     }
00702 
00712     protected function _getCategoryDiscoutValue( $dPrice )
00713     {
00714         $oDiscount    = $this->_getSerieDiscount();
00715         $aBasketItems = $this->_getBasketItems( $oDiscount );
00716 
00717         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00718         if ( !count( $aBasketItems ) && !$this->isAdmin() ) {
00719             $oEx = oxNew( 'oxVoucherException' );
00720             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00721             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00722             throw $oEx;
00723         }
00724 
00725         $oProductPrice = oxNew('oxPrice');
00726         $oProductTotal = oxNew('oxPrice');
00727 
00728         foreach ( $aBasketItems as $aBasketItem ) {
00729             $oProductPrice->setPrice( $aBasketItem['price'] );
00730             $oProductPrice->multiply( $aBasketItem['amount'] );
00731             $oProductTotal->add( $oProductPrice->getBruttoPrice() );
00732         }
00733 
00734         $dProduct = $oProductTotal->getBruttoPrice();
00735         $dVoucher = $oDiscount->getAbsValue( $dProduct );
00736         return ( $dVoucher > $dProduct ) ? $dProduct : $dVoucher;
00737     }
00738 
00746     public function __get( $sName )
00747     {
00748         switch ( $sName ) {
00749 
00750             // simple voucher mapping
00751             case 'sVoucherId':
00752                 return $this->getId();
00753                 break;
00754             case 'sVoucherNr':
00755                 return $this->oxvouchers__oxvouchernr;
00756                 break;
00757             case 'fVoucherdiscount':
00758                 return $this->oxvouchers__oxdiscount;
00759                 break;
00760         }
00761         return parent::__get($sName);
00762     }
00763 }