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 
00053             $sQ  = "select {$sViewName}.* from {$sViewName}, {$sSeriesViewName} where
00054                         {$sSeriesViewName}.oxid = {$sViewName}.oxvoucherserieid and
00055                         {$sViewName}.oxvouchernr = " . oxDb::getDb()->quote( $sVoucherNr ) . " and ";
00056 
00057             if ( is_array( $aVouchers ) ) {
00058                 foreach ( $aVouchers as $sVoucherId => $sSkipVoucherNr ) {
00059                     $sQ .= "{$sViewName}.oxid != " . oxDb::getDb()->quote( $sVoucherId ) . " and ";
00060                 }
00061             }
00062             $sQ .= "( {$sViewName}.oxorderid is NULL || {$sViewName}.oxorderid = '' ) ";
00063 
00064             //voucher timeout for 3 hours
00065             if ( $blCheckavalability ) {
00066                 $iTime = time() - 3600 * 3;
00067                 $sQ .= " and {$sViewName}.oxreserved < '{$iTime}' ";
00068             }
00069 
00070             $sQ .= " limit 1";
00071 
00072             if ( ! ( $oRet = $this->assignRecord( $sQ ) ) ) {
00073                 $oEx = oxNew( 'oxVoucherException' );
00074                 $oEx->setMessage( 'EXCEPTION_VOUCHER_NOVOUCHER' );
00075                 $oEx->setVoucherNr( $sVoucherNr );
00076                 throw $oEx;
00077             }
00078         }
00079 
00080         return $oRet;
00081     }
00082 
00092     public function markAsUsed( $sOrderId, $sUserId, $dDiscount )
00093     {
00094         //saving oxreserved field
00095         if ( $this->oxvouchers__oxid->value ) {
00096             $this->oxvouchers__oxorderid->setValue($sOrderId);
00097             $this->oxvouchers__oxuserid->setValue($sUserId);
00098             $this->oxvouchers__oxdiscount->setValue($dDiscount);
00099             $this->oxvouchers__oxdateused->setValue(date( "Y-m-d", oxUtilsDate::getInstance()->getTime() ));
00100             $this->save();
00101         }
00102     }
00103 
00109     public function markAsReserved()
00110     {
00111         //saving oxreserved field
00112         $sVoucherID = $this->oxvouchers__oxid->value;
00113 
00114         if ( $sVoucherID ) {
00115             $sQ = "update oxvouchers set oxreserved = " . time() . " where oxid = " . oxDb::getDb()->quote( $sVoucherID );
00116             oxDb::getDb()->Execute( $sQ );
00117         }
00118     }
00119 
00125     public function unMarkAsReserved()
00126     {
00127         //saving oxreserved field
00128         $sVoucherID = $this->oxvouchers__oxid->value;
00129 
00130         if ( $sVoucherID ) {
00131             $sQ = "update oxvouchers set oxreserved = 0 where oxid = " . oxDb::getDb()->quote( $sVoucherID );
00132             oxDb::getDb()->Execute($sQ);
00133         }
00134     }
00135 
00145     public function getDiscountValue( $dPrice )
00146     {
00147         if ($this->_isProductVoucher()) {
00148             return $this->_getProductDiscoutValue( $dPrice );
00149         } elseif ($this->_isCategoryVoucher()) {
00150             return $this->_getCategoryDiscoutValue( $dPrice );
00151         } else {
00152             return $this->_getGenericDiscoutValue( $dPrice );
00153         }
00154     }
00155 
00156     // Checking General Availability
00167     public function checkVoucherAvailability( $aVouchers, $dPrice )
00168     {
00169         $this->_isAvailableWithSameSeries( $aVouchers );
00170         $this->_isAvailableWithOtherSeries( $aVouchers );
00171         $this->_isValidDate();
00172         $this->_isAvailablePrice( $dPrice );
00173         $this->_isNotReserved();
00174 
00175         // returning true - no exception was thrown
00176         return true;
00177     }
00178 
00190     public function checkBasketVoucherAvailability( $aVouchers, $dPrice )
00191     {
00192         $this->_isAvailableWithSameSeries( $aVouchers );
00193         $this->_isAvailableWithOtherSeries( $aVouchers );
00194         $this->_isValidDate();
00195         $this->_isAvailablePrice( $dPrice );
00196 
00197         // returning true - no exception was thrown
00198         return true;
00199     }
00200 
00210     protected function _isAvailablePrice( $dPrice )
00211     {
00212         if ( $this->getDiscountValue( $dPrice ) < 0 ) {
00213             $oEx = oxNew( 'oxVoucherException' );
00214             $oEx->setMessage('EXCEPTION_VOUCHER_TOTALBELOWZERO');
00215             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00216             throw $oEx;
00217         }
00218         $oSerie = $this->getSerie();
00219         $oCur = $this->getConfig()->getActShopCurrencyObject();
00220         if ( $oSerie->oxvoucherseries__oxminimumvalue->value && $dPrice < ($oSerie->oxvoucherseries__oxminimumvalue->value*$oCur->rate) ) {
00221             $oEx = oxNew( 'oxVoucherException' );
00222             $oEx->setMessage('EXCEPTION_VOUCHER_INCORRECTPRICE');
00223             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00224             throw $oEx;
00225         }
00226 
00227         return true;
00228     }
00229 
00241     protected function _isAvailableWithSameSeries( $aVouchers )
00242     {
00243         if ( is_array( $aVouchers ) ) {
00244             $sId = $this->getId();
00245             if (isset($aVouchers[$sId])) {
00246                 unset($aVouchers[$sId]);
00247             }
00248             $oSerie = $this->getSerie();
00249             if (!$oSerie->oxvoucherseries__oxallowsameseries->value) {
00250                 foreach ( $aVouchers as $voucherId => $voucherNr ) {
00251                     $oVoucher = oxNew( 'oxvoucher' );
00252                     $oVoucher->load($voucherId);
00253                     if ( $this->oxvouchers__oxvoucherserieid->value == $oVoucher->oxvouchers__oxvoucherserieid->value ) {
00254                             $oEx = oxNew( 'oxVoucherException' );
00255                             $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDSAMESERIES');
00256                             $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00257                             throw $oEx;
00258                     }
00259                 }
00260             }
00261         }
00262 
00263         return true;
00264     }
00265 
00276     protected function _isAvailableWithOtherSeries( $aVouchers )
00277     {
00278         if ( is_array( $aVouchers ) && count($aVouchers) ) {
00279             $oSerie = $this->getSerie();
00280             $sIds = '\''.implode('\',\'', array_keys($aVouchers)).'\'';
00281             $blAvailable = true;
00282             if (!$oSerie->oxvoucherseries__oxallowotherseries->value) {
00283                 // just search for vouchers with different series
00284                 $sSql  = "select 1 from oxvouchers where oxvouchers.oxid in ($sIds) and ";
00285                 $sSql .= "oxvouchers.oxvoucherserieid != " . oxDb::getDb()->quote( $this->oxvouchers__oxvoucherserieid->value ) ;
00286                 $blAvailable &= !oxDb::getDb()->getOne($sSql);
00287             } else {
00288                 // search for vouchers with different series and those vouchers do not allow other series
00289                 $sSql  = "select 1 from oxvouchers left join oxvoucherseries on oxvouchers.oxvoucherserieid=oxvoucherseries.oxid ";
00290                 $sSql .= "where oxvouchers.oxid in ($sIds) and oxvouchers.oxvoucherserieid != " . oxDb::getDb()->quote( $this->oxvouchers__oxvoucherserieid->value );
00291                 $sSql .= "and not oxvoucherseries.oxallowotherseries";
00292                 $blAvailable &= !oxDb::getDb()->getOne($sSql);
00293             }
00294             if ( !$blAvailable ) {
00295                     $oEx = oxNew( 'oxVoucherException' );
00296                     $oEx->setMessage('EXCEPTION_VOUCHER_NOTALLOWEDOTHERSERIES');
00297                     $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00298                     throw $oEx;
00299             }
00300         }
00301 
00302         return true;
00303     }
00304 
00312     protected function _isValidDate()
00313     {
00314         $oSerie = $this->getSerie();
00315         // if time is not set - keep it as active by default
00316         $sDefTimeStamp = oxUtilsDate::getInstance()->formatDBDate( '-' );
00317         if ( $oSerie->oxvoucherseries__oxbegindate->value == $sDefTimeStamp &&
00318              $oSerie->oxvoucherseries__oxenddate->value == $sDefTimeStamp ) {
00319             return true;
00320         }
00321 
00322         if ( ( strtotime( $oSerie->oxvoucherseries__oxbegindate->value ) < time() &&
00323               strtotime( $oSerie->oxvoucherseries__oxenddate->value ) > time() ) ||
00324             !$oSerie->oxvoucherseries__oxenddate->value ||
00325             $oSerie->oxvoucherseries__oxenddate->value == $sDefTimeStamp ) {
00326             return true;
00327         }
00328 
00329         $oEx = oxNew( 'oxVoucherException' );
00330         $oEx->setMessage('EXCEPTION_VOUCHER_ISNOTVALIDDATE');
00331         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00332         throw $oEx;
00333     }
00334 
00342     protected function _isNotReserved()
00343     {
00344 
00345         if ( $this->oxvouchers__oxreserved->value < time() - 3600 * 3 ) {
00346             return true;
00347         }
00348 
00349         $oEx = oxNew( 'oxVoucherException' );
00350         $oEx->setMessage('EXCEPTION_VOUCHER_ISRESERVED');
00351         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00352         throw $oEx;
00353     }
00354 
00355     // Checking User Availability
00365     public function checkUserAvailability( $oUser )
00366     {
00367 
00368         $this->_isAvailableInOtherOrder( $oUser );
00369         $this->_isValidUserGroup( $oUser );
00370 
00371         // returning true if no exception was thrown
00372         return true;
00373     }
00374 
00384     protected function _isAvailableInOtherOrder( $oUser )
00385     {
00386         $oSerie = $this->getSerie();
00387         if ( !$oSerie->oxvoucherseries__oxallowuseanother->value ) {
00388 
00389             $sSelect  = 'select count(*) from '.$this->getViewName().' where oxuserid = '. oxDb::getDb()->quote( $oUser->oxuser__oxid->value ) . ' and ';
00390             $sSelect .= 'oxvoucherserieid = ' . oxDb::getDb()->quote( $this->oxvouchers__oxvoucherserieid->value ) . ' and ';
00391             $sSelect .= 'oxorderid is not NULL and oxorderid != "" ';
00392 
00393             if ( oxDb::getDb()->getOne( $sSelect )) {
00394                 $oEx = oxNew( 'oxVoucherException' );
00395                 $oEx->setMessage('EXCEPTION_VOUCHER_NOTAVAILABLEINOTHERORDER');
00396                 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00397                 throw $oEx;
00398             }
00399         }
00400 
00401         return true;
00402     }
00403 
00413     protected function _isValidUserGroup( $oUser )
00414     {
00415         $oVoucherSerie = $this->getSerie();
00416         $oUserGroups = $oVoucherSerie->setUserGroups();
00417 
00418         // dodger Task #1555 R Voucher does not work for not logged user?
00419         if ( !$oUserGroups->count() ) {
00420             return true;
00421         }
00422 
00423         if ( $oUser ) {
00424             foreach ( $oUserGroups as $oGroup ) {
00425                 if ( $oUser->inGroup( $oGroup->getId() ) ) {
00426                     return true;
00427                 }
00428             }
00429         }
00430 
00431         $oEx = oxNew( 'oxVoucherException' );
00432         $oEx->setMessage( 'EXCEPTION_VOUCHER_NOTVALIDUSERGROUP' );
00433         $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00434         throw $oEx;
00435     }
00436 
00442     public function getSimpleVoucher()
00443     {
00444         $oVoucher = new oxStdClass();
00445         $oVoucher->sVoucherId = $this->getId();
00446         $oVoucher->sVoucherNr = $this->oxvouchers__oxvouchernr->value;
00447         // R. setted in oxbasket : $oVoucher->fVoucherdiscount = oxLang::getInstance()->formatCurrency( $this->oxvouchers__oxdiscount->value );
00448 
00449         return $oVoucher;
00450     }
00451 
00457     public function getSerie()
00458     {
00459         if ($this->_oSerie !== null) {
00460             return $this->_oSerie;
00461         }
00462         $oSerie = oxNew('oxvoucherserie');
00463         if (!$oSerie->load($this->oxvouchers__oxvoucherserieid->value)) {
00464             throw new oxObjectException();
00465         }
00466         $this->_oSerie = $oSerie;
00467         return $oSerie;
00468     }
00469 
00475     protected function _isProductVoucher()
00476     {
00477         $myDB    = oxDb::getDb();
00478         $oSerie  = $this->getSerie();
00479         $sSelect = "select 1 from oxobject2discount where oxdiscountid = '".$oSerie->getId()."' and oxtype = 'oxarticles'";
00480         $blOk    = ( bool ) $myDB->getOne( $sSelect );
00481 
00482         return $blOk;
00483     }
00484 
00490     protected function _isCategoryVoucher()
00491     {
00492         $myDB    = oxDb::getDb();
00493         $oSerie  = $this->getSerie();
00494         $sSelect = "select 1 from oxobject2discount where oxdiscountid = '".$oSerie->getId()."' and oxtype = 'oxcategories'";
00495         $blOk    = ( bool ) $myDB->getOne( $sSelect );
00496 
00497         return $blOk;
00498     }
00499 
00505     protected function _getSerieDiscount( )
00506     {
00507         $oSerie    = $this->getSerie();
00508         $oDiscount = oxNew('oxDiscount');
00509 
00510         $oDiscount->setId($oSerie->getId());
00511         $oDiscount->oxdiscount__oxshopid      = new oxField($oSerie->oxvoucherseries__oxshopid->value);
00512         $oDiscount->oxdiscount__oxactive      = new oxField(true);
00513         $oDiscount->oxdiscount__oxactivefrom  = new oxField($oSerie->oxvoucherseries__oxbegindate->value);
00514         $oDiscount->oxdiscount__oxactiveto    = new oxField($oSerie->oxvoucherseries__oxenddate->value);
00515         $oDiscount->oxdiscount__oxtitle       = new oxField($oSerie->oxvoucherseries__oxserienr->value);
00516         $oDiscount->oxdiscount__oxamount      = new oxField(1);
00517         $oDiscount->oxdiscount__oxamountto    = new oxField(MAX_64BIT_INTEGER);
00518         $oDiscount->oxdiscount__oxprice       = new oxField(0);
00519         $oDiscount->oxdiscount__oxpriceto     = new oxField(MAX_64BIT_INTEGER);
00520         $oDiscount->oxdiscount__oxaddsumtype  = new oxField($oSerie->oxvoucherseries__oxdiscounttype->value=='percent'?'%':'abs');
00521         $oDiscount->oxdiscount__oxaddsum      = new oxField($oSerie->oxvoucherseries__oxdiscount->value);
00522         $oDiscount->oxdiscount__oxitmartid    = new oxField();
00523         $oDiscount->oxdiscount__oxitmamount   = new oxField();
00524         $oDiscount->oxdiscount__oxitmmultiple = new oxField();
00525 
00526         return $oDiscount;
00527     }
00528 
00536     protected function _getBasketItems($oDiscount = null)
00537     {
00538         if ($this->oxvouchers__oxorderid->value) {
00539             return $this->_getOrderBasketItems($oDiscount);
00540         } elseif ( $this->getSession()->getBasket() ) {
00541             return $this->_getSessionBasketItems($oDiscount);
00542         } else {
00543             return array();
00544         }
00545     }
00546 
00554     protected function _getOrderBasketItems($oDiscount = null)
00555     {
00556         if (is_null($oDiscount)) {
00557             $oDiscount = $this->_getSerieDiscount();
00558         }
00559 
00560         $oOrder = oxNew('oxorder');
00561         $oOrder->load($this->oxvouchers__oxorderid->value);
00562 
00563         $aItems  = array();
00564         $iCount  = 0;
00565 
00566         foreach ( $oOrder->getOrderArticles(true) as $oOrderArticle ) {
00567             if (!$oOrderArticle->skipDiscounts() && $oDiscount->isForBasketItem($oOrderArticle)) {
00568                 $aItems[$iCount] = array(
00569                     'oxid'     => $oOrderArticle->getProductId(),
00570                     'price'    => $oOrderArticle->oxorderarticles__oxprice->value,
00571                     'discount' => $oDiscount->getAbsValue($oOrderArticle->oxorderarticles__oxprice->value),
00572                     'amount'   => $oOrderArticle->oxorderarticles__oxamount->value,
00573                 );
00574                 $iCount ++;
00575             }
00576         }
00577 
00578         return $aItems;
00579     }
00580 
00588     protected function _getSessionBasketItems($oDiscount = null)
00589     {
00590         if (is_null($oDiscount)) {
00591             $oDiscount = $this->_getSerieDiscount();
00592         }
00593 
00594         $oBasket = $this->getSession()->getBasket();
00595         $aItems  = array();
00596         $iCount  = 0;
00597 
00598         foreach ( $oBasket->getContents() as $oBasketItem ) {
00599             if ( !$oBasketItem->isDiscountArticle() && ( $oArticle = $oBasketItem->getArticle() ) && !$oArticle->skipDiscounts() && $oDiscount->isForBasketItem($oArticle) ) {
00600 
00601                 $aItems[$iCount] = array(
00602                     'oxid'     => $oArticle->getId(),
00603                     'price'    => $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice(),
00604                     'discount' => $oDiscount->getAbsValue($oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getBruttoPrice()),
00605                     'amount'   => $oBasketItem->getAmount(),
00606                 );
00607 
00608                 $iCount ++;
00609             }
00610         }
00611 
00612         return $aItems;
00613     }
00614 
00624     protected function _getGenericDiscoutValue( $dPrice )
00625     {
00626         $oSerie = $this->getSerie();
00627         if ( $oSerie->oxvoucherseries__oxdiscounttype->value == 'absolute' ) {
00628             $oCur = $this->getConfig()->getActShopCurrencyObject();
00629             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value * $oCur->rate;
00630         } else {
00631             $dDiscount = $oSerie->oxvoucherseries__oxdiscount->value / 100 * $dPrice;
00632         }
00633 
00634         if ( $dDiscount > $dPrice ) {
00635             $oEx = oxNew( 'oxVoucherException' );
00636             $oEx->setMessage('EXCEPTION_VOUCHER_TOTALBELOWZERO');
00637             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00638             throw $oEx;
00639         }
00640 
00641         return $dDiscount;
00642     }
00643 
00653     protected function _getProductDiscoutValue( $dPrice )
00654     {
00655         $oDiscount    = $this->_getSerieDiscount();
00656         $aBasketItems = $this->_getBasketItems($oDiscount);
00657 
00658         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00659         if (!count($aBasketItems) && !$this->isAdmin() ) {
00660             $oEx = oxNew( 'oxVoucherException' );
00661             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00662             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00663             throw $oEx;
00664         }
00665 
00666         $oSerie    = $this->getSerie();
00667 
00668         $oVoucherPrice  = oxNew('oxPrice');
00669         $oDiscountPrice = oxNew('oxPrice');
00670         $oProductPrice  = oxNew('oxPrice');
00671         $oProductTotal  = oxNew('oxPrice');
00672 
00673         foreach ( $aBasketItems as $aBasketItem ) {
00674 
00675             $oDiscountPrice->setPrice($aBasketItem['discount']);
00676             $oProductPrice->setPrice($aBasketItem['price']);
00677 
00678             // Individual voucher is not multiplied by article amount
00679             if (!$oSerie->oxvoucherseries__oxcalculateonce->value) {
00680                 $oDiscountPrice->multiply($aBasketItem['amount']);
00681                 $oProductPrice->multiply($aBasketItem['amount']);
00682             }
00683 
00684             $oVoucherPrice->add($oDiscountPrice->getBruttoPrice());
00685             $oProductTotal->add($oProductPrice->getBruttoPrice());
00686         }
00687 
00688         $dVoucher = $oVoucherPrice->getBruttoPrice();
00689         $dProduct = $oProductTotal->getBruttoPrice();
00690 
00691         if ( $dVoucher > $dProduct ) {
00692             return $dProduct;
00693         }
00694 
00695         return $dVoucher;
00696     }
00697 
00707     protected function _getCategoryDiscoutValue( $dPrice )
00708     {
00709         $oDiscount    = $this->_getSerieDiscount();
00710         $aBasketItems = $this->_getBasketItems( $oDiscount );
00711 
00712         // Basket Item Count and isAdmin check (unble to access property $oOrder->_getOrderBasket()->_blSkipVouchersAvailabilityChecking)
00713         if ( !count( $aBasketItems ) && !$this->isAdmin() ) {
00714             $oEx = oxNew( 'oxVoucherException' );
00715             $oEx->setMessage('EXCEPTION_VOUCHER_NOVOUCHER');
00716             $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00717             throw $oEx;
00718         }
00719 
00720         $oProductPrice = oxNew('oxPrice');
00721         $oProductTotal = oxNew('oxPrice');
00722 
00723         foreach ( $aBasketItems as $aBasketItem ) {
00724             $oProductPrice->setPrice( $aBasketItem['price'] );
00725             $oProductPrice->multiply( $aBasketItem['amount'] );
00726             $oProductTotal->add( $oProductPrice->getBruttoPrice() );
00727         }
00728 
00729         $dProduct = $oProductTotal->getBruttoPrice();
00730         $dVoucher = $oDiscount->getAbsValue( $dProduct );
00731         return ( $dVoucher > $dProduct ) ? $dProduct : $dVoucher;
00732     }
00733 
00741     public function __get( $sName )
00742     {
00743         switch ( $sName ) {
00744 
00745             // simple voucher mapping
00746             case 'sVoucherId':
00747                 return $this->getId();
00748                 break;
00749             case 'sVoucherNr':
00750                 return $this->oxvouchers__oxvouchernr;
00751                 break;
00752             case 'fVoucherdiscount':
00753                 return $this->oxvouchers__oxdiscount;
00754                 break;
00755         }
00756         return parent::__get($sName);
00757     }
00758 }