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             $oDb = oxDb::getDb();
00053 
00054             $sQ  = "select {$sViewName}.* from {$sViewName}, {$sSeriesViewName} where
00055                         {$sSeriesViewName}.oxid = {$sViewName}.oxvoucherserieid and
00056                         {$sViewName}.oxvouchernr = " . $oDb->quote( $sVoucherNr ) . " and ";
00057 
00058             if ( is_array( $aVouchers ) ) {
00059                 foreach ( $aVouchers as $sVoucherId => $sSkipVoucherNr ) {
00060                     $sQ .= "{$sViewName}.oxid != " . $oDb->quote( $sVoucherId ) . " and ";
00061                 }
00062             }
00063             $sQ .= "( {$sViewName}.oxorderid is NULL || {$sViewName}.oxorderid = '' ) ";
00064             $sQ .= " and ( {$sViewName}.oxdateused is NULL || {$sViewName}.oxdateused = 0 ) ";
00065 
00066             //voucher timeout for 3 hours
00067             if ( $blCheckavalability ) {
00068                 $iTime = time() - 3600 * 3;
00069                 $sQ .= " and {$sViewName}.oxreserved < '{$iTime}' ";
00070             }
00071 
00072             $sQ .= " limit 1";
00073 
00074             if ( ! ( $oRet = $this->assignRecord( $sQ ) ) ) {
00075                 $oEx = oxNew( 'oxVoucherException' );
00076                 $oEx->setMessage( 'EXCEPTION_VOUCHER_NOVOUCHER' );
00077                 $oEx->setVoucherNr( $sVoucherNr );
00078                 throw $oEx;
00079             }
00080         }
00081 
00082         return $oRet;
00083     }
00084 
00094     public function markAsUsed( $sOrderId, $sUserId, $dDiscount )
00095     {
00096         //saving oxreserved field
00097         if ( $this->oxvouchers__oxid->value ) {
00098             $this->oxvouchers__oxorderid->setValue($sOrderId);
00099             $this->oxvouchers__oxuserid->setValue($sUserId);
00100             $this->oxvouchers__oxdiscount->setValue($dDiscount);
00101             $this->oxvouchers__oxdateused->setValue(date( "Y-m-d", oxUtilsDate::getInstance()->getTime() ));
00102             $this->save();
00103         }
00104     }
00105 
00111     public function markAsReserved()
00112     {
00113         //saving oxreserved field
00114         $sVoucherID = $this->oxvouchers__oxid->value;
00115 
00116         if ( $sVoucherID ) {
00117             $oDb = oxDb::getDb();
00118             $sQ = "update oxvouchers set oxreserved = " . time() . " where oxid = " . $oDb->quote( $sVoucherID );
00119             $oDb->Execute( $sQ );
00120         }
00121     }
00122 
00128     public function unMarkAsReserved()
00129     {
00130         //saving oxreserved field
00131         $sVoucherID = $this->oxvouchers__oxid->value;
00132 
00133         if ( $sVoucherID ) {
00134             $oDb = oxDb::getDb();
00135             $sQ = "update oxvouchers set oxreserved = 0 where oxid = " . $oDb->quote( $sVoucherID );
00136             $oDb->Execute($sQ);
00137         }
00138     }
00139 
00149     public function getDiscountValue( $dPrice )
00150     {
00151         if ($this->_isProductVoucher()) {
00152             return $this->_getProductDiscoutValue( (double) $dPrice );
00153         } elseif ($this->_isCategoryVoucher()) {
00154             return $this->_getCategoryDiscoutValue( (double) $dPrice );
00155         } else {
00156             return $this->_getGenericDiscoutValue( (double) $dPrice );
00157         }
00158     }
00159 
00160     // Checking General Availability
00171     public function checkVoucherAvailability( $aVouchers, $dPrice )
00172     {
00173         $this->_isAvailableWithSameSeries( $aVouchers );
00174         $this->_isAvailableWithOtherSeries( $aVouchers );
00175         $this->_isValidDate();
00176         $this->_isAvailablePrice( $dPrice );
00177         $this->_isNotReserved();
00178 
00179         // returning true - no exception was thrown
00180         return true;
00181     }
00182 
00194     public function checkBasketVoucherAvailability( $aVouchers, $dPrice )
00195     {
00196         $this->_isAvailableWithSameSeries( $aVouchers );
00197         $this->_isAvailableWithOtherSeries( $aVouchers );
00198         $this->_isValidDate();
00199         $this->_isAvailablePrice( $dPrice );
00200 
00201         // returning true - no exception was thrown
00202         return true;
00203     }
00204 
00214     protected function _isAvailablePrice( $dPrice )
00215     {
00216         if ( $this->getDiscountValue( $dPrice ) < 0 ) {
00217             $oEx = oxNew( 'oxVoucherException' );
00218             $oEx->setMessage('EXCEPTION_VOUCHER_TOTALBELOWZERO');
00219             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00220             throw $oEx;
00221         }
00222         $oSerie = $this->getSerie();
00223         $oCur = $this->getConfig()->getActShopCurrencyObject();
00224         if ( $oSerie->oxvoucherseries__oxminimumvalue->value && $dPrice < ($oSerie->oxvoucherseries__oxminimumvalue->value*$oCur->rate) ) {
00225             $oEx = oxNew( 'oxVoucherException' );
00226             $oEx->setMessage('EXCEPTION_VOUCHER_INCORRECTPRICE');
00227             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00228             throw $oEx;
00229         }
00230 
00231         return true;
00232     }
00233 
00245     protected function _isAvailableWithSameSeries( $aVouchers )
00246     {
00247         if ( is_array( $aVouchers ) ) {
00248             $sId = $this->getId();
00249             if (isset($aVouchers[$sId])) {
00250                 unset($aVouchers[$sId]);
00251             }
00252             $oSerie = $this->getSerie();
00253             if (!$oSerie->oxvoucherseries__oxallowsameseries->value) {
00254                 foreach ( $aVouchers as $voucherId => $voucherNr ) {
00255                     $oVoucher = oxNew( 'oxvoucher' );
00256                     $oVoucher->load($voucherId);
00257                     if ( $this->oxvouchers__oxvoucherserieid->value == $oVoucher->oxvouchers__oxvoucherserieid->value ) {
00258                             $oEx = oxNew( 'oxVoucherException' );
00259                             $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDSAMESERIES');
00260                             $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00261                             throw $oEx;
00262                     }
00263                 }
00264             }
00265         }
00266 
00267         return true;
00268     }
00269 
00280     protected function _isAvailableWithOtherSeries( $aVouchers )
00281     {
00282         if ( is_array( $aVouchers ) && count($aVouchers) ) {
00283             $oSerie = $this->getSerie();
00284             $sIds = implode(',', oxDb::getInstance()->quoteArray( array_keys( $aVouchers ) ) );
00285             $blAvailable = true;
00286             $oDb = oxDb::getDb();
00287             if (!$oSerie->oxvoucherseries__oxallowotherseries->value) {
00288                 // just search for vouchers with different series
00289                 $sSql  = "select 1 from oxvouchers where oxvouchers.oxid in ($sIds) and ";
00290                 $sSql .= "oxvouchers.oxvoucherserieid != " . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value ) ;
00291                 $blAvailable &= !$oDb->getOne($sSql);
00292             } else {
00293                 // search for vouchers with different series and those vouchers do not allow other series
00294                 $sSql  = "select 1 from oxvouchers left join oxvoucherseries on oxvouchers.oxvoucherserieid=oxvoucherseries.oxid ";
00295                 $sSql .= "where oxvouchers.oxid in ($sIds) and oxvouchers.oxvoucherserieid != " . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value );
00296                 $sSql .= "and not oxvoucherseries.oxallowotherseries";
00297                 $blAvailable &= !$oDb->getOne($sSql);
00298             }
00299             if ( !$blAvailable ) {
00300                     $oEx = oxNew( 'oxVoucherException' );
00301                     $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDOTHERSERIES');
00302                     $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00303                     throw $oEx;
00304             }
00305         }
00306 
00307         return true;
00308     }
00309 
00317     protected function _isValidDate()
00318     {
00319         $oSerie = $this->getSerie();
00320         
00321         // If date is not set will add day before and day after to check if voucher valid today.
00322         $iTomorrow = mktime( 0, 0, 0, date( "m" ), date( "d" )+1, date( "Y" ) );
00323         $iYesterday = mktime( 0, 0, 0, date( "m" ), date( "d" )-1, date( "Y" ) );
00324 
00325         // Checks if beginning date is set, if not set $iFrom to yesterday so it will be valid.
00326         $iFrom = ( (int)$oSerie->oxvoucherseries__oxbegindate->value ) ?
00327                    strtotime( $oSerie->oxvoucherseries__oxbegindate->value ) : $iYesterday;
00328 
00329         // Checks if end date is set, if no set $iTo to tomorrow so it will be valid.
00330         $iTo = ( (int)$oSerie->oxvoucherseries__oxenddate->value ) ?
00331                    strtotime( $oSerie->oxvoucherseries__oxenddate->value ) : $iTomorrow;
00332 
00333         if ( $iFrom < time() && $iTo > time() ) {
00334             return true;
00335         }
00336 
00337         $oEx = oxNew( 'oxVoucherException' );
00338         $oEx->setMessage('EXCEPTION_VOUCHER_ISNOTVALIDDATE');
00339         if ( $iFrom > time() && $iTo > time() ) {
00340             $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00341         }
00342         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00343         throw $oEx;
00344     }
00345 
00353     protected function _isNotReserved()
00354     {
00355 
00356         if ( $this->oxvouchers__oxreserved->value < time() - 3600 * 3 ) {
00357             return true;
00358         }
00359 
00360         $oEx = oxNew( 'oxVoucherException' );
00361         $oEx->setMessage('EXCEPTION_VOUCHER_ISRESERVED');
00362         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00363         throw $oEx;
00364     }
00365 
00366     // Checking User Availability
00376     public function checkUserAvailability( $oUser )
00377     {
00378 
00379         $this->_isAvailableInOtherOrder( $oUser );
00380         $this->_isValidUserGroup( $oUser );
00381 
00382         // returning true if no exception was thrown
00383         return true;
00384     }
00385 
00395     protected function _isAvailableInOtherOrder( $oUser )
00396     {
00397         $oSerie = $this->getSerie();
00398         if ( !$oSerie->oxvoucherseries__oxallowuseanother->value ) {
00399 
00400             $oDb = oxDb::getDb();
00401             $sSelect  = 'select count(*) from '.$this->getViewName().' where oxuserid = '. $oDb->quote( $oUser->oxuser__oxid->value ) . ' and ';
00402             $sSelect .= 'oxvoucherserieid = ' . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value ) . ' and ';
00403             $sSelect .= '((oxorderid is not NULL and oxorderid != "") or (oxdateused is not NULL and oxdateused != 0)) ';
00404 
00405             if ( $oDb->getOne( $sSelect )) {
00406                 $oEx = oxNew( 'oxVoucherException' );
00407                 $oEx->setMessage('EXCEPTION_VOUCHER_NOTAVAILABLEINOTHERORDER');
00408                 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00409                 throw $oEx;
00410             }
00411         }
00412 
00413         return true;
00414     }
00415 
00425     protected function _isValidUserGroup( $oUser )
00426     {
00427         $oVoucherSerie = $this->getSerie();
00428         $oUserGroups = $oVoucherSerie->setUserGroups();
00429 
00430         // dodger Task #1555 R Voucher does not work for not logged user?
00431         if ( !$oUserGroups->count() ) {
00432             return true;
00433         }
00434 
00435         if ( $oUser ) {
00436             foreach ( $oUserGroups as $oGroup ) {
00437                 if ( $oUser->inGroup( $oGroup->getId() ) ) {
00438                     return true;
00439                 }
00440             }
00441         }
00442 
00443         $oEx = oxNew( 'oxVoucherException' );
00444         $oEx->setMessage( 'EXCEPTION_VOUCHER_NOTVALIDUSERGROUP' );
00445         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00446         throw $oEx;
00447     }
00448 
00454     public function getSimpleVoucher()
00455     {
00456         $oVoucher = new oxStdClass();
00457         $oVoucher->sVoucherId = $this->getId();
00458         $oVoucher->sVoucherNr = $this->oxvouchers__oxvouchernr->value;
00459         // R. setted in oxbasket : $oVoucher->fVoucherdiscount = oxLang::getInstance()->formatCurrency( $this->oxvouchers__oxdiscount->value );
00460 
00461         return $oVoucher;
00462     }
00463 
00469     public function getSerie()
00470     {
00471         if ($this->_oSerie !== null) {
00472             return $this->_oSerie;
00473         }
00474         $oSerie = oxNew('oxvoucherserie');
00475         if (!$oSerie->load($this->oxvouchers__oxvoucherserieid->value)) {
00476             throw oxNew( "oxObjectException" );
00477         }
00478         $this->_oSerie = $oSerie;
00479         return $oSerie;
00480     }
00481 
00487     protected function _isProductVoucher()
00488     {
00489         $oDb    = oxDb::getDb();
00490         $oSerie  = $this->getSerie();
00491         $sSelect = "select 1 from oxobject2discount where oxdiscountid = ".$oDb->quote( $oSerie->getId() )." and oxtype = 'oxarticles'";
00492         $blOk    = ( bool ) $oDb->getOne( $sSelect );
00493 
00494         return $blOk;
00495     }
00496 
00502     protected function _isCategoryVoucher()
00503     {
00504         $oDb    = oxDb::getDb();
00505         $oSerie  = $this->getSerie();
00506         $sSelect = "select 1 from oxobject2discount where oxdiscountid = ". $oDb->quote( $oSerie->getId() )." and oxtype = 'oxcategories'";
00507         $blOk    = ( bool ) $oDb->getOne( $sSelect );
00508 
00509         return $blOk;
00510     }
00511 
00517     protected function _getSerieDiscount( )
00518     {
00519         $oSerie    = $this->getSerie();
00520         $oDiscount = oxNew('oxDiscount');
00521 
00522         $oDiscount->setId($oSerie->getId());
00523         $oDiscount->oxdiscount__oxshopid      = new oxField($oSerie->oxvoucherseries__oxshopid->value);
00524         $oDiscount->oxdiscount__oxactive      = new oxField(true);
00525         $oDiscount->oxdiscount__oxactivefrom  = new oxField($oSerie->oxvoucherseries__oxbegindate->value);
00526         $oDiscount->oxdiscount__oxactiveto    = new oxField($oSerie->oxvoucherseries__oxenddate->value);
00527         $oDiscount->oxdiscount__oxtitle       = new oxField($oSerie->oxvoucherseries__oxserienr->value);
00528         $oDiscount->oxdiscount__oxamount      = new oxField(1);
00529         $oDiscount->oxdiscount__oxamountto    = new oxField(MAX_64BIT_INTEGER);
00530         $oDiscount->oxdiscount__oxprice       = new oxField(0);
00531         $oDiscount->oxdiscount__oxpriceto     = new oxField(MAX_64BIT_INTEGER);
00532         $oDiscount->oxdiscount__oxaddsumtype  = new oxField($oSerie->oxvoucherseries__oxdiscounttype->value=='percent'?'%':'abs');
00533         $oDiscount->oxdiscount__oxaddsum      = new oxField($oSerie->oxvoucherseries__oxdiscount->value);
00534         $oDiscount->oxdiscount__oxitmartid    = new oxField();
00535         $oDiscount->oxdiscount__oxitmamount   = new oxField();
00536         $oDiscount->oxdiscount__oxitmmultiple = new oxField();
00537 
00538         return $oDiscount;
00539     }
00540 
00548     protected function _getBasketItems($oDiscount = null)
00549     {
00550         if ($this->oxvouchers__oxorderid->value) {
00551             return $this->_getOrderBasketItems($oDiscount);
00552         } elseif ( $this->getSession()->getBasket() ) {
00553             return $this->_getSessionBasketItems($oDiscount);
00554         } else {
00555             return array();
00556         }
00557     }
00558 
00566     protected function _getOrderBasketItems($oDiscount = null)
00567     {
00568         if (is_null($oDiscount)) {
00569             $oDiscount = $this->_getSerieDiscount();
00570         }
00571 
00572         $oOrder = oxNew('oxorder');
00573         $oOrder->load($this->oxvouchers__oxorderid->value);
00574 
00575         $aItems  = array();
00576         $iCount  = 0;
00577 
00578         foreach ( $oOrder->getOrderArticles(true) as $oOrderArticle ) {
00579             if (!$oOrderArticle->skipDiscounts() && $oDiscount->isForBasketItem($oOrderArticle)) {
00580                 $aItems[$iCount] = array(
00581                     'oxid'     => $oOrderArticle->getProductId(),
00582                     'price'    => $oOrderArticle->oxorderarticles__oxprice->value,
00583                     'discount' => $oDiscount->getAbsValue($oOrderArticle->oxorderarticles__oxprice->value),
00584                     'amount'   => $oOrderArticle->oxorderarticles__oxamount->value,
00585                 );
00586                 $iCount ++;
00587             }
00588         }
00589 
00590         return $aItems;
00591     }
00592 
00600     protected function _getSessionBasketItems($oDiscount = null)
00601     {
00602         if (is_null($oDiscount)) {
00603             $oDiscount = $this->_getSerieDiscount();
00604         }
00605 
00606         $oBasket = $this->getSession()->getBasket();
00607         $aItems  = array();
00608         $iCount  = 0;
00609 
00610         foreach ( $oBasket->getContents() as $oBasketItem ) {
00611             if ( !$oBasketItem->isDiscountArticle() && ( $oArticle = $oBasketItem->getArticle() ) && !$oArticle->skipDiscounts() && $oDiscount->isForBasketItem($oArticle) ) {
00612 
00613                 $aItems[$iCount] = array(
00614                     'oxid'     => $oArticle->getId(),
00615                     'price'    => $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice(),
00616                     'discount' => $oDiscount->getAbsValue($oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice()),
00617                     'amount'   => $oBasketItem->getAmount(),
00618                 );
00619 
00620                 $iCount ++;
00621             }
00622         }
00623 
00624         return $aItems;
00625     }
00626 
00636     protected function _getGenericDiscoutValue( $dPrice )
00637     {
00638         $oSerie = $this->getSerie();
00639         if ( $oSerie->oxvoucherseries__oxdiscounttype->value == 'absolute' ) {
00640             $oCur = $this->getConfig()->getActShopCurrencyObject();
00641             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value * $oCur->rate;
00642         } else {
00643             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value / 100 * $dPrice;
00644         }
00645 
00646         if ( $dDiscount > $dPrice ) {
00647             $dDiscount = $dPrice;
00648         }
00649 
00650         return $dDiscount;
00651     }
00652 
00662     protected function _getProductDiscoutValue( $dPrice )
00663     {
00664         $oDiscount    = $this->_getSerieDiscount();
00665         $aBasketItems = $this->_getBasketItems($oDiscount);
00666 
00667         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00668         if (!count($aBasketItems) && !$this->isAdmin() ) {
00669             $oEx = oxNew( 'oxVoucherException' );
00670             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00671             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00672             throw $oEx;
00673         }
00674 
00675         $oSerie    = $this->getSerie();
00676 
00677         $oVoucherPrice  = oxNew('oxPrice');
00678         $oDiscountPrice = oxNew('oxPrice');
00679         $oProductPrice  = oxNew('oxPrice');
00680         $oProductTotal  = oxNew('oxPrice');
00681 
00682         foreach ( $aBasketItems as $aBasketItem ) {
00683 
00684             $oDiscountPrice->setPrice($aBasketItem['discount']);
00685             $oProductPrice->setPrice($aBasketItem['price']);
00686 
00687             // Individual voucher is not multiplied by article amount
00688             if (!$oSerie->oxvoucherseries__oxcalculateonce->value) {
00689                 $oDiscountPrice->multiply($aBasketItem['amount']);
00690                 $oProductPrice->multiply($aBasketItem['amount']);
00691             }
00692 
00693             $oVoucherPrice->add($oDiscountPrice->getBruttoPrice());
00694             $oProductTotal->add($oProductPrice->getBruttoPrice());
00695         }
00696 
00697         $dVoucher = $oVoucherPrice->getBruttoPrice();
00698         $dProduct = $oProductTotal->getBruttoPrice();
00699 
00700         if ( $dVoucher > $dProduct ) {
00701             return $dProduct;
00702         }
00703 
00704         return $dVoucher;
00705     }
00706 
00716     protected function _getCategoryDiscoutValue( $dPrice )
00717     {
00718         $oDiscount    = $this->_getSerieDiscount();
00719         $aBasketItems = $this->_getBasketItems( $oDiscount );
00720 
00721         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00722         if ( !count( $aBasketItems ) && !$this->isAdmin() ) {
00723             $oEx = oxNew( 'oxVoucherException' );
00724             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00725             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00726             throw $oEx;
00727         }
00728 
00729         $oProductPrice = oxNew('oxPrice');
00730         $oProductTotal = oxNew('oxPrice');
00731 
00732         foreach ( $aBasketItems as $aBasketItem ) {
00733             $oProductPrice->setPrice( $aBasketItem['price'] );
00734             $oProductPrice->multiply( $aBasketItem['amount'] );
00735             $oProductTotal->add( $oProductPrice->getBruttoPrice() );
00736         }
00737 
00738         $dProduct = $oProductTotal->getBruttoPrice();
00739         $dVoucher = $oDiscount->getAbsValue( $dProduct );
00740         return ( $dVoucher > $dProduct ) ? $dProduct : $dVoucher;
00741     }
00742 
00750     public function __get( $sName )
00751     {
00752         switch ( $sName ) {
00753 
00754             // simple voucher mapping
00755             case 'sVoucherId':
00756                 return $this->getId();
00757                 break;
00758             case 'sVoucherNr':
00759                 return $this->oxvouchers__oxvouchernr;
00760                 break;
00761             case 'fVoucherdiscount':
00762                 return $this->oxvouchers__oxdiscount;
00763                 break;
00764         }
00765         return parent::__get($sName);
00766     }
00767 }