Go to the documentation of this file.00001 <?php
00002
00009 class oxVoucher extends oxBase
00010 {
00011
00012 protected $_oSerie = null;
00013
00019 protected $_blDisableShopCheck = true;
00020
00024 protected $_sClassName = 'oxvoucher';
00025
00029 public function __construct()
00030 {
00031 parent::__construct();
00032 $this->init( 'oxvouchers' );
00033 }
00034
00046 public function getVoucherByNr( $sVoucherNr, $aVouchers = array(), $blCheckavalability = false )
00047 {
00048 $oRet = null;
00049 if ( !is_null( $sVoucherNr ) ) {
00050
00051 $sViewName = $this->getViewName();
00052 $sSeriesViewName = getViewName( 'oxvoucherseries' );
00053 $oDb = oxDb::getDb();
00054
00055 $sQ = "select {$sViewName}.* from {$sViewName}, {$sSeriesViewName} where
00056 {$sSeriesViewName}.oxid = {$sViewName}.oxvoucherserieid and
00057 {$sViewName}.oxvouchernr = " . $oDb->quote( $sVoucherNr ) . " and ";
00058
00059 if ( is_array( $aVouchers ) ) {
00060 foreach ( $aVouchers as $sVoucherId => $sSkipVoucherNr ) {
00061 $sQ .= "{$sViewName}.oxid != " . $oDb->quote( $sVoucherId ) . " and ";
00062 }
00063 }
00064 $sQ .= "( {$sViewName}.oxorderid is NULL || {$sViewName}.oxorderid = '' ) ";
00065 $sQ .= " and ( {$sViewName}.oxdateused is NULL || {$sViewName}.oxdateused = 0 ) ";
00066
00067
00068 if ( $blCheckavalability ) {
00069 $iTime = time() - $this->_getVoucherTimeout();
00070 $sQ .= " and {$sViewName}.oxreserved < '{$iTime}' ";
00071 }
00072
00073 $sQ .= " limit 1";
00074
00075 if ( ! ( $oRet = $this->assignRecord( $sQ ) ) ) {
00076 $oEx = oxNew( 'oxVoucherException' );
00077 $oEx->setMessage( 'ERROR_MESSAGE_VOUCHER_NOVOUCHER' );
00078 $oEx->setVoucherNr( $sVoucherNr );
00079 throw $oEx;
00080 }
00081 }
00082
00083 return $oRet;
00084 }
00085
00095 public function markAsUsed( $sOrderId, $sUserId, $dDiscount )
00096 {
00097
00098 if ( $this->oxvouchers__oxid->value ) {
00099 $this->oxvouchers__oxorderid->setValue($sOrderId);
00100 $this->oxvouchers__oxuserid->setValue($sUserId);
00101 $this->oxvouchers__oxdiscount->setValue($dDiscount);
00102 $this->oxvouchers__oxdateused->setValue(date( "Y-m-d", oxRegistry::get("oxUtilsDate")->getTime() ));
00103 $this->save();
00104 }
00105 }
00106
00112 public function markAsReserved()
00113 {
00114
00115 $sVoucherID = $this->oxvouchers__oxid->value;
00116
00117 if ( $sVoucherID ) {
00118 $oDb = oxDb::getDb();
00119 $sQ = "update oxvouchers set oxreserved = " . time() . " where oxid = " . $oDb->quote( $sVoucherID );
00120 $oDb->Execute( $sQ );
00121 }
00122 }
00123
00129 public function unMarkAsReserved()
00130 {
00131
00132 $sVoucherID = $this->oxvouchers__oxid->value;
00133
00134 if ( $sVoucherID ) {
00135 $oDb = oxDb::getDb();
00136 $sQ = "update oxvouchers set oxreserved = 0 where oxid = " . $oDb->quote( $sVoucherID );
00137 $oDb->Execute($sQ);
00138 }
00139 }
00140
00150 public function getDiscountValue( $dPrice )
00151 {
00152 if ($this->_isProductVoucher()) {
00153 return $this->_getProductDiscoutValue( (double) $dPrice );
00154 } elseif ($this->_isCategoryVoucher()) {
00155 return $this->_getCategoryDiscoutValue( (double) $dPrice );
00156 } else {
00157 return $this->_getGenericDiscoutValue( (double) $dPrice );
00158 }
00159 }
00160
00161
00172 public function checkVoucherAvailability( $aVouchers, $dPrice )
00173 {
00174 $this->_isAvailableWithSameSeries( $aVouchers );
00175 $this->_isAvailableWithOtherSeries( $aVouchers );
00176 $this->_isValidDate();
00177 $this->_isAvailablePrice( $dPrice );
00178 $this->_isNotReserved();
00179
00180
00181 return true;
00182 }
00183
00195 public function checkBasketVoucherAvailability( $aVouchers, $dPrice )
00196 {
00197 $this->_isAvailableWithSameSeries( $aVouchers );
00198 $this->_isAvailableWithOtherSeries( $aVouchers );
00199 $this->_isValidDate();
00200 $this->_isAvailablePrice( $dPrice );
00201
00202
00203 return true;
00204 }
00205
00215 protected function _isAvailablePrice( $dPrice )
00216 {
00217 $oSeries = $this->getSerie();
00218 $oCur = $this->getConfig()->getActShopCurrencyObject();
00219 if ( $oSeries->oxvoucherseries__oxminimumvalue->value && $dPrice < ($oSeries->oxvoucherseries__oxminimumvalue->value*$oCur->rate) ) {
00220 $oEx = oxNew( 'oxVoucherException' );
00221 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_INCORRECTPRICE');
00222 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00223 throw $oEx;
00224 }
00225
00226 return true;
00227 }
00228
00240 protected function _isAvailableWithSameSeries( $aVouchers )
00241 {
00242 if ( is_array( $aVouchers ) ) {
00243 $sId = $this->getId();
00244 if (isset($aVouchers[$sId])) {
00245 unset($aVouchers[$sId]);
00246 }
00247 $oSeries = $this->getSerie();
00248 if (!$oSeries->oxvoucherseries__oxallowsameseries->value) {
00249 foreach ( $aVouchers as $voucherId => $voucherNr ) {
00250 $oVoucher = oxNew( 'oxVoucher' );
00251 $oVoucher->load($voucherId);
00252 if ( $this->oxvouchers__oxvoucherserieid->value == $oVoucher->oxvouchers__oxvoucherserieid->value ) {
00253 $oEx = oxNew( 'oxVoucherException' );
00254 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTALLOWEDSAMESERIES');
00255 $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00256 throw $oEx;
00257 }
00258 }
00259 }
00260 }
00261
00262 return true;
00263 }
00264
00275 protected function _isAvailableWithOtherSeries( $aVouchers )
00276 {
00277 if ( is_array( $aVouchers ) && count($aVouchers) ) {
00278 $oSeries = $this->getSerie();
00279 $sIds = implode(',', oxDb::getInstance()->quoteArray( array_keys( $aVouchers ) ) );
00280 $blAvailable = true;
00281 $oDb = oxDb::getDb();
00282 if (!$oSeries->oxvoucherseries__oxallowotherseries->value) {
00283
00284 $sSql = "select 1 from oxvouchers where oxvouchers.oxid in ($sIds) and ";
00285 $sSql .= "oxvouchers.oxvoucherserieid != " . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value ) ;
00286 $blAvailable &= !$oDb->getOne($sSql);
00287 } else {
00288
00289 $sSql = "select 1 from oxvouchers left join oxvoucherseries on oxvouchers.oxvoucherserieid=oxvoucherseries.oxid ";
00290 $sSql .= "where oxvouchers.oxid in ($sIds) and oxvouchers.oxvoucherserieid != " . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value );
00291 $sSql .= "and not oxvoucherseries.oxallowotherseries";
00292 $blAvailable &= !$oDb->getOne($sSql);
00293 }
00294 if ( !$blAvailable ) {
00295 $oEx = oxNew( 'oxVoucherException' );
00296 $oEx->setMessage('ERROR_MESSAGE_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 $oSeries = $this->getSerie();
00315
00316
00317 $iTomorrow = mktime( 0, 0, 0, date( "m" ), date( "d" )+1, date( "Y" ) );
00318 $iYesterday = mktime( 0, 0, 0, date( "m" ), date( "d" )-1, date( "Y" ) );
00319
00320
00321 $iFrom = ( (int)$oSeries->oxvoucherseries__oxbegindate->value ) ?
00322 strtotime( $oSeries->oxvoucherseries__oxbegindate->value ) : $iYesterday;
00323
00324
00325 $iTo = ( (int)$oSeries->oxvoucherseries__oxenddate->value ) ?
00326 strtotime( $oSeries->oxvoucherseries__oxenddate->value ) : $iTomorrow;
00327
00328 if ( $iFrom < time() && $iTo > time() ) {
00329 return true;
00330 }
00331
00332 $oEx = oxNew( 'oxVoucherException' );
00333 $oEx->setMessage('MESSAGE_COUPON_EXPIRED');
00334 if ( $iFrom > time() && $iTo > time() ) {
00335 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00336 }
00337 $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00338 throw $oEx;
00339 }
00340
00348 protected function _isNotReserved()
00349 {
00350
00351 if ( $this->oxvouchers__oxreserved->value < time() - $this->_getVoucherTimeout() ) {
00352 return true;
00353 }
00354
00355 $oEx = oxNew( 'oxVoucherException' );
00356 $oEx->setMessage('EXCEPTION_VOUCHER_ISRESERVED');
00357 $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00358 throw $oEx;
00359 }
00360
00361
00371 public function checkUserAvailability( $oUser )
00372 {
00373
00374 $this->_isAvailableInOtherOrder( $oUser );
00375 $this->_isValidUserGroup( $oUser );
00376
00377
00378 return true;
00379 }
00380
00390 protected function _isAvailableInOtherOrder( $oUser )
00391 {
00392 $oSeries = $this->getSerie();
00393 if ( !$oSeries->oxvoucherseries__oxallowuseanother->value ) {
00394
00395 $oDb = oxDb::getDb();
00396 $sSelect = 'select count(*) from '.$this->getViewName().' where oxuserid = '. $oDb->quote( $oUser->oxuser__oxid->value ) . ' and ';
00397 $sSelect .= 'oxvoucherserieid = ' . $oDb->quote( $this->oxvouchers__oxvoucherserieid->value ) . ' and ';
00398 $sSelect .= '((oxorderid is not NULL and oxorderid != "") or (oxdateused is not NULL and oxdateused != 0)) ';
00399
00400 if ( $oDb->getOne( $sSelect )) {
00401 $oEx = oxNew( 'oxVoucherException' );
00402 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTALLOWEDSAMESERIES');
00403 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00404 throw $oEx;
00405 }
00406 }
00407
00408 return true;
00409 }
00410
00420 protected function _isValidUserGroup( $oUser )
00421 {
00422 $oVoucherSeries = $this->getSerie();
00423 $oUserGroups = $oVoucherSeries->setUserGroups();
00424
00425 if ( !$oUserGroups->count() ) {
00426 return true;
00427 }
00428
00429 if ( $oUser ) {
00430 foreach ( $oUserGroups as $oGroup ) {
00431 if ( $oUser->inGroup( $oGroup->getId() ) ) {
00432 return true;
00433 }
00434 }
00435 }
00436
00437 $oEx = oxNew( 'oxVoucherException' );
00438 $oEx->setMessage( 'ERROR_MESSAGE_VOUCHER_NOTVALIDUSERGROUP' );
00439 $oEx->setVoucherNr( $this->oxvouchers__oxvouchernr->value );
00440 throw $oEx;
00441 }
00442
00448 public function getSimpleVoucher()
00449 {
00450 $oVoucher = new stdClass();
00451 $oVoucher->sVoucherId = $this->getId();
00452 $oVoucher->sVoucherNr = $this->oxvouchers__oxvouchernr->value;
00453
00454
00455 return $oVoucher;
00456 }
00457
00463 public function getSerie()
00464 {
00465 if ($this->_oSerie !== null) {
00466 return $this->_oSerie;
00467 }
00468 $oSeries = oxNew('oxVoucherSerie');
00469 if (!$oSeries->load($this->oxvouchers__oxvoucherserieid->value)) {
00470 throw oxNew( "oxObjectException" );
00471 }
00472 $this->_oSerie = $oSeries;
00473 return $oSeries;
00474 }
00475
00481 protected function _isProductVoucher()
00482 {
00483 $oDb = oxDb::getDb();
00484 $oSeries = $this->getSerie();
00485 $sSelect = "select 1 from oxobject2discount where oxdiscountid = ".$oDb->quote( $oSeries->getId() )." and oxtype = 'oxarticles'";
00486 $blOk = ( bool ) $oDb->getOne( $sSelect );
00487
00488 return $blOk;
00489 }
00490
00496 protected function _isCategoryVoucher()
00497 {
00498 $oDb = oxDb::getDb();
00499 $oSeries = $this->getSerie();
00500 $sSelect = "select 1 from oxobject2discount where oxdiscountid = ". $oDb->quote( $oSeries->getId() )." and oxtype = 'oxcategories'";
00501 $blOk = ( bool ) $oDb->getOne( $sSelect );
00502
00503 return $blOk;
00504 }
00505
00511 protected function _getSerieDiscount( )
00512 {
00513 $oSeries = $this->getSerie();
00514 $oDiscount = oxNew('oxDiscount');
00515
00516 $oDiscount->setId($oSeries->getId());
00517 $oDiscount->oxdiscount__oxshopid = new oxField($oSeries->oxvoucherseries__oxshopid->value);
00518 $oDiscount->oxdiscount__oxactive = new oxField(true);
00519 $oDiscount->oxdiscount__oxactivefrom = new oxField($oSeries->oxvoucherseries__oxbegindate->value);
00520 $oDiscount->oxdiscount__oxactiveto = new oxField($oSeries->oxvoucherseries__oxenddate->value);
00521 $oDiscount->oxdiscount__oxtitle = new oxField($oSeries->oxvoucherseries__oxserienr->value);
00522 $oDiscount->oxdiscount__oxamount = new oxField(1);
00523 $oDiscount->oxdiscount__oxamountto = new oxField(MAX_64BIT_INTEGER);
00524 $oDiscount->oxdiscount__oxprice = new oxField(0);
00525 $oDiscount->oxdiscount__oxpriceto = new oxField(MAX_64BIT_INTEGER);
00526 $oDiscount->oxdiscount__oxaddsumtype = new oxField($oSeries->oxvoucherseries__oxdiscounttype->value=='percent'?'%':'abs');
00527 $oDiscount->oxdiscount__oxaddsum = new oxField($oSeries->oxvoucherseries__oxdiscount->value);
00528 $oDiscount->oxdiscount__oxitmartid = new oxField();
00529 $oDiscount->oxdiscount__oxitmamount = new oxField();
00530 $oDiscount->oxdiscount__oxitmmultiple = new oxField();
00531
00532 return $oDiscount;
00533 }
00534
00542 protected function _getBasketItems($oDiscount = null)
00543 {
00544 if ($this->oxvouchers__oxorderid->value) {
00545 return $this->_getOrderBasketItems($oDiscount);
00546 } elseif ( $this->getSession()->getBasket() ) {
00547 return $this->_getSessionBasketItems($oDiscount);
00548 } else {
00549 return array();
00550 }
00551 }
00552
00560 protected function _getOrderBasketItems($oDiscount = null)
00561 {
00562 if (is_null($oDiscount)) {
00563 $oDiscount = $this->_getSerieDiscount();
00564 }
00565
00566 $oOrder = oxNew('oxOrder');
00567 $oOrder->load($this->oxvouchers__oxorderid->value);
00568
00569 $aItems = array();
00570 $iCount = 0;
00571
00572 foreach ( $oOrder->getOrderArticles(true) as $oOrderArticle ) {
00573 if (!$oOrderArticle->skipDiscounts() && $oDiscount->isForBasketItem($oOrderArticle)) {
00574 $aItems[$iCount] = array(
00575 'oxid' => $oOrderArticle->getProductId(),
00576 'price' => $oOrderArticle->oxorderarticles__oxbprice->value,
00577 'discount' => $oDiscount->getAbsValue($oOrderArticle->oxorderarticles__oxbprice->value),
00578 'amount' => $oOrderArticle->oxorderarticles__oxamount->value,
00579 );
00580 $iCount ++;
00581 }
00582 }
00583
00584 return $aItems;
00585 }
00586
00594 protected function _getSessionBasketItems($oDiscount = null)
00595 {
00596 if (is_null($oDiscount)) {
00597 $oDiscount = $this->_getSerieDiscount();
00598 }
00599
00600 $oBasket = $this->getSession()->getBasket();
00601 $aItems = array();
00602 $iCount = 0;
00603
00604 foreach ( $oBasket->getContents() as $oBasketItem ) {
00605 if ( !$oBasketItem->isDiscountArticle() && ( $oArticle = $oBasketItem->getArticle() ) && !$oArticle->skipDiscounts() && $oDiscount->isForBasketItem($oArticle) ) {
00606
00607 $aItems[$iCount] = array(
00608 'oxid' => $oArticle->getId(),
00609 'price' => $oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getPrice(),
00610 'discount' => $oDiscount->getAbsValue($oArticle->getBasketPrice( $oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket )->getPrice()),
00611 'amount' => $oBasketItem->getAmount(),
00612 );
00613
00614 $iCount ++;
00615 }
00616 }
00617
00618 return $aItems;
00619 }
00620
00630 protected function _getGenericDiscoutValue( $dPrice )
00631 {
00632 $oSeries = $this->getSerie();
00633 if ( $oSeries->oxvoucherseries__oxdiscounttype->value == 'absolute' ) {
00634 $oCur = $this->getConfig()->getActShopCurrencyObject();
00635 $dDiscount = $oSeries->oxvoucherseries__oxdiscount->value * $oCur->rate;
00636 } else {
00637 $dDiscount = $oSeries->oxvoucherseries__oxdiscount->value / 100 * $dPrice;
00638 }
00639
00640 if ( $dDiscount > $dPrice ) {
00641 $dDiscount = $dPrice;
00642 }
00643
00644 return $dDiscount;
00645 }
00646
00647
00653 public function getDiscount()
00654 {
00655 $oSeries = $this->getSerie();
00656 return $oSeries->oxvoucherseries__oxdiscount->value;
00657 }
00658
00664 public function getDiscountType()
00665 {
00666 $oSeries = $this->getSerie();
00667 return $oSeries->oxvoucherseries__oxdiscounttype->value;
00668 }
00669
00670
00680 protected function _getProductDiscoutValue( $dPrice )
00681 {
00682 $oDiscount = $this->_getSerieDiscount();
00683 $aBasketItems = $this->_getBasketItems($oDiscount);
00684
00685
00686 if (!count($aBasketItems) && !$this->isAdmin() ) {
00687 $oEx = oxNew( 'oxVoucherException' );
00688 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00689 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00690 throw $oEx;
00691 }
00692
00693 $oSeries = $this->getSerie();
00694
00695 $oVoucherPrice = oxNew('oxPrice');
00696 $oDiscountPrice = oxNew('oxPrice');
00697 $oProductPrice = oxNew('oxPrice');
00698 $oProductTotal = oxNew('oxPrice');
00699
00700
00701 $blDiscountApplied = false;
00702
00703 foreach ( $aBasketItems as $aBasketItem ) {
00704
00705
00706 if ( $blDiscountApplied and !empty( $oSeries->oxvoucherseries__oxcalculateonce->value ) ) {
00707 break;
00708 }
00709
00710 $oDiscountPrice->setPrice($aBasketItem['discount']);
00711 $oProductPrice->setPrice($aBasketItem['price']);
00712
00713
00714 if (!$oSeries->oxvoucherseries__oxcalculateonce->value) {
00715 $oDiscountPrice->multiply($aBasketItem['amount']);
00716 $oProductPrice->multiply($aBasketItem['amount']);
00717 }
00718
00719 $oVoucherPrice->add($oDiscountPrice->getBruttoPrice());
00720 $oProductTotal->add($oProductPrice->getBruttoPrice());
00721
00722 if ( !empty( $aBasketItem['discount'] ) ) {
00723 $blDiscountApplied = true;
00724 }
00725 }
00726
00727 $dVoucher = $oVoucherPrice->getBruttoPrice();
00728 $dProduct = $oProductTotal->getBruttoPrice();
00729
00730 if ( $dVoucher > $dProduct ) {
00731 return $dProduct;
00732 }
00733
00734 return $dVoucher;
00735 }
00736
00746 protected function _getCategoryDiscoutValue( $dPrice )
00747 {
00748 $oDiscount = $this->_getSerieDiscount();
00749 $aBasketItems = $this->_getBasketItems( $oDiscount );
00750
00751
00752 if ( !count( $aBasketItems ) && !$this->isAdmin() ) {
00753 $oEx = oxNew( 'oxVoucherException' );
00754 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00755 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00756 throw $oEx;
00757 }
00758
00759 $oProductPrice = oxNew('oxPrice');
00760 $oProductTotal = oxNew('oxPrice');
00761
00762 foreach ( $aBasketItems as $aBasketItem ) {
00763 $oProductPrice->setPrice( $aBasketItem['price'] );
00764 $oProductPrice->multiply( $aBasketItem['amount'] );
00765 $oProductTotal->add( $oProductPrice->getBruttoPrice() );
00766 }
00767
00768 $dProduct = $oProductTotal->getBruttoPrice();
00769 $dVoucher = $oDiscount->getAbsValue( $dProduct );
00770 return ( $dVoucher > $dProduct ) ? $dProduct : $dVoucher;
00771 }
00772
00780 public function __get( $sName )
00781 {
00782 switch ( $sName ) {
00783
00784
00785 case 'sVoucherId':
00786 return $this->getId();
00787 break;
00788 case 'sVoucherNr':
00789 return $this->oxvouchers__oxvouchernr;
00790 break;
00791 case 'fVoucherdiscount':
00792 return $this->oxvouchers__oxdiscount;
00793 break;
00794 }
00795 return parent::__get($sName);
00796 }
00797
00804 protected function _getVoucherTimeout()
00805 {
00806 $iVoucherTimeout = intval(oxRegistry::getConfig()->getConfigParam( 'iVoucherTimeout' )) ?
00807 intval(oxRegistry::getConfig()->getConfigParam( 'iVoucherTimeout' )) :
00808 3 *3600;
00809 return $iVoucherTimeout;
00810 }
00811 }