Go to the documentation of this file.00001 <?php
00002
00009 class oxVoucher extends oxBase
00010 {
00011
00012 protected $_oSerie = null;
00013
00020 protected $_blDisableShopCheck = true;
00021
00025 protected $_sClassName = 'oxvoucher';
00026
00030 public function __construct()
00031 {
00032 parent::__construct();
00033 $this->init('oxvouchers');
00034 }
00035
00047 public function getVoucherByNr($sVoucherNr, $aVouchers = array(), $blCheckavalability = false)
00048 {
00049 $oRet = null;
00050 if (!is_null($sVoucherNr)) {
00051
00052 $sViewName = $this->getViewName();
00053 $sSeriesViewName = getViewName('oxvoucherseries');
00054 $oDb = oxDb::getDb();
00055
00056 $sQ = "select {$sViewName}.* from {$sViewName}, {$sSeriesViewName} where
00057 {$sSeriesViewName}.oxid = {$sViewName}.oxvoucherserieid and
00058 {$sViewName}.oxvouchernr = " . $oDb->quote($sVoucherNr) . " and ";
00059
00060 if (is_array($aVouchers)) {
00061 foreach ($aVouchers as $sVoucherId => $sSkipVoucherNr) {
00062 $sQ .= "{$sViewName}.oxid != " . $oDb->quote($sVoucherId) . " and ";
00063 }
00064 }
00065 $sQ .= "( {$sViewName}.oxorderid is NULL || {$sViewName}.oxorderid = '' ) ";
00066 $sQ .= " and ( {$sViewName}.oxdateused is NULL || {$sViewName}.oxdateused = 0 ) ";
00067
00068
00069 if ($blCheckavalability) {
00070 $iTime = time() - $this->_getVoucherTimeout();
00071 $sQ .= " and {$sViewName}.oxreserved < '{$iTime}' ";
00072 }
00073
00074 $sQ .= " limit 1";
00075
00076 if (!($oRet = $this->assignRecord($sQ))) {
00077 $oEx = oxNew('oxVoucherException');
00078 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00079 $oEx->setVoucherNr($sVoucherNr);
00080 throw $oEx;
00081 }
00082 }
00083
00084 return $oRet;
00085 }
00086
00094 public function markAsUsed($sOrderId, $sUserId, $dDiscount)
00095 {
00096
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", oxRegistry::get("oxUtilsDate")->getTime()));
00102 $this->save();
00103 }
00104 }
00105
00109 public function markAsReserved()
00110 {
00111
00112 $sVoucherID = $this->oxvouchers__oxid->value;
00113
00114 if ($sVoucherID) {
00115 $oDb = oxDb::getDb();
00116 $sQ = "update oxvouchers set oxreserved = " . time() . " where oxid = " . $oDb->quote($sVoucherID);
00117 $oDb->Execute($sQ);
00118 }
00119 }
00120
00124 public function unMarkAsReserved()
00125 {
00126
00127 $sVoucherID = $this->oxvouchers__oxid->value;
00128
00129 if ($sVoucherID) {
00130 $oDb = oxDb::getDb();
00131 $sQ = "update oxvouchers set oxreserved = 0 where oxid = " . $oDb->quote($sVoucherID);
00132 $oDb->Execute($sQ);
00133 }
00134 }
00135
00145 public function getDiscountValue($dPrice)
00146 {
00147 if ($this->_isProductVoucher()) {
00148 return $this->_getProductDiscoutValue((double) $dPrice);
00149 } elseif ($this->_isCategoryVoucher()) {
00150 return $this->_getCategoryDiscoutValue((double) $dPrice);
00151 } else {
00152 return $this->_getGenericDiscoutValue((double) $dPrice);
00153 }
00154 }
00155
00156
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
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
00198 return true;
00199 }
00200
00210 protected function _isAvailablePrice($dPrice)
00211 {
00212 $oSeries = $this->getSerie();
00213 $oCur = $this->getConfig()->getActShopCurrencyObject();
00214 if ($oSeries->oxvoucherseries__oxminimumvalue->value && $dPrice < ($oSeries->oxvoucherseries__oxminimumvalue->value * $oCur->rate)) {
00215 $oEx = oxNew('oxVoucherException');
00216 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_INCORRECTPRICE');
00217 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00218 throw $oEx;
00219 }
00220
00221 return true;
00222 }
00223
00235 protected function _isAvailableWithSameSeries($aVouchers)
00236 {
00237 if (is_array($aVouchers)) {
00238 $sId = $this->getId();
00239 if (isset($aVouchers[$sId])) {
00240 unset($aVouchers[$sId]);
00241 }
00242 $oSeries = $this->getSerie();
00243 if (!$oSeries->oxvoucherseries__oxallowsameseries->value) {
00244 foreach ($aVouchers as $voucherId => $voucherNr) {
00245 $oVoucher = oxNew('oxVoucher');
00246 $oVoucher->load($voucherId);
00247 if ($this->oxvouchers__oxvoucherserieid->value == $oVoucher->oxvouchers__oxvoucherserieid->value) {
00248 $oEx = oxNew('oxVoucherException');
00249 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTALLOWEDSAMESERIES');
00250 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00251 throw $oEx;
00252 }
00253 }
00254 }
00255 }
00256
00257 return true;
00258 }
00259
00270 protected function _isAvailableWithOtherSeries($aVouchers)
00271 {
00272 if (is_array($aVouchers) && count($aVouchers)) {
00273 $oSeries = $this->getSerie();
00274 $sIds = implode(',', oxDb::getInstance()->quoteArray(array_keys($aVouchers)));
00275 $blAvailable = true;
00276 $oDb = oxDb::getDb();
00277 if (!$oSeries->oxvoucherseries__oxallowotherseries->value) {
00278
00279 $sSql = "select 1 from oxvouchers where oxvouchers.oxid in ($sIds) and ";
00280 $sSql .= "oxvouchers.oxvoucherserieid != " . $oDb->quote($this->oxvouchers__oxvoucherserieid->value);
00281 $blAvailable &= !$oDb->getOne($sSql);
00282 } else {
00283
00284 $sSql = "select 1 from oxvouchers left join oxvoucherseries on oxvouchers.oxvoucherserieid=oxvoucherseries.oxid ";
00285 $sSql .= "where oxvouchers.oxid in ($sIds) and oxvouchers.oxvoucherserieid != " . $oDb->quote($this->oxvouchers__oxvoucherserieid->value);
00286 $sSql .= "and not oxvoucherseries.oxallowotherseries";
00287 $blAvailable &= !$oDb->getOne($sSql);
00288 }
00289 if (!$blAvailable) {
00290 $oEx = oxNew('oxVoucherException');
00291 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTALLOWEDOTHERSERIES');
00292 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00293 throw $oEx;
00294 }
00295 }
00296
00297 return true;
00298 }
00299
00307 protected function _isValidDate()
00308 {
00309 $oSeries = $this->getSerie();
00310 $iTime = time();
00311
00312
00313 $iTomorrow = mktime(0, 0, 0, date("m"), date("d") + 1, date("Y"));
00314 $iYesterday = mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"));
00315
00316
00317 $iFrom = ((int) $oSeries->oxvoucherseries__oxbegindate->value) ?
00318 strtotime($oSeries->oxvoucherseries__oxbegindate->value) : $iYesterday;
00319
00320
00321 $iTo = ((int) $oSeries->oxvoucherseries__oxenddate->value) ?
00322 strtotime($oSeries->oxvoucherseries__oxenddate->value) : $iTomorrow;
00323
00324 if ($iFrom < $iTime && $iTo > $iTime) {
00325 return true;
00326 }
00327
00328 $oEx = oxNew('oxVoucherException');
00329 $oEx->setMessage('MESSAGE_COUPON_EXPIRED');
00330 if ($iFrom > $iTime && $iTo > $iTime) {
00331 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOVOUCHER');
00332 }
00333 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00334 throw $oEx;
00335 }
00336
00344 protected function _isNotReserved()
00345 {
00346
00347 if ($this->oxvouchers__oxreserved->value < time() - $this->_getVoucherTimeout()) {
00348 return true;
00349 }
00350
00351 $oEx = oxNew('oxVoucherException');
00352 $oEx->setMessage('EXCEPTION_VOUCHER_ISRESERVED');
00353 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00354 throw $oEx;
00355 }
00356
00357
00367 public function checkUserAvailability($oUser)
00368 {
00369
00370 $this->_isAvailableInOtherOrder($oUser);
00371 $this->_isValidUserGroup($oUser);
00372
00373
00374 return true;
00375 }
00376
00386 protected function _isAvailableInOtherOrder($oUser)
00387 {
00388 $oSeries = $this->getSerie();
00389 if (!$oSeries->oxvoucherseries__oxallowuseanother->value) {
00390
00391 $oDb = oxDb::getDb();
00392 $sSelect = 'select count(*) from ' . $this->getViewName() . ' where oxuserid = ' . $oDb->quote($oUser->oxuser__oxid->value) . ' and ';
00393 $sSelect .= 'oxvoucherserieid = ' . $oDb->quote($this->oxvouchers__oxvoucherserieid->value) . ' and ';
00394 $sSelect .= '((oxorderid is not NULL and oxorderid != "") or (oxdateused is not NULL and oxdateused != 0)) ';
00395
00396 if ($oDb->getOne($sSelect)) {
00397 $oEx = oxNew('oxVoucherException');
00398 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTALLOWEDSAMESERIES');
00399 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00400 throw $oEx;
00401 }
00402 }
00403
00404 return true;
00405 }
00406
00416 protected function _isValidUserGroup($oUser)
00417 {
00418 $oVoucherSeries = $this->getSerie();
00419 $oUserGroups = $oVoucherSeries->setUserGroups();
00420
00421 if (!$oUserGroups->count()) {
00422 return true;
00423 }
00424
00425 if ($oUser) {
00426 foreach ($oUserGroups as $oGroup) {
00427 if ($oUser->inGroup($oGroup->getId())) {
00428 return true;
00429 }
00430 }
00431 }
00432
00433 $oEx = oxNew('oxVoucherException');
00434 $oEx->setMessage('ERROR_MESSAGE_VOUCHER_NOTVALIDUSERGROUP');
00435 $oEx->setVoucherNr($this->oxvouchers__oxvouchernr->value);
00436 throw $oEx;
00437 }
00438
00444 public function getSimpleVoucher()
00445 {
00446 $oVoucher = new stdClass();
00447 $oVoucher->sVoucherId = $this->getId();
00448 $oVoucher->sVoucherNr = $this->oxvouchers__oxvouchernr->value;
00449
00450
00451
00452 return $oVoucher;
00453 }
00454
00460 public function getSerie()
00461 {
00462 if ($this->_oSerie !== null) {
00463 return $this->_oSerie;
00464 }
00465 $oSeries = oxNew('oxVoucherSerie');
00466 if (!$oSeries->load($this->oxvouchers__oxvoucherserieid->value)) {
00467 throw oxNew("oxObjectException");
00468 }
00469 $this->_oSerie = $oSeries;
00470
00471 return $oSeries;
00472 }
00473
00479 protected function _isProductVoucher()
00480 {
00481 $oDb = oxDb::getDb();
00482 $oSeries = $this->getSerie();
00483 $sSelect = "select 1 from oxobject2discount where oxdiscountid = " . $oDb->quote($oSeries->getId()) . " and oxtype = 'oxarticles'";
00484 $blOk = ( bool ) $oDb->getOne($sSelect);
00485
00486 return $blOk;
00487 }
00488
00494 protected function _isCategoryVoucher()
00495 {
00496 $oDb = oxDb::getDb();
00497 $oSeries = $this->getSerie();
00498 $sSelect = "select 1 from oxobject2discount where oxdiscountid = " . $oDb->quote($oSeries->getId()) . " and oxtype = 'oxcategories'";
00499 $blOk = ( bool ) $oDb->getOne($sSelect);
00500
00501 return $blOk;
00502 }
00503
00509 protected function _getSerieDiscount()
00510 {
00511 $oSeries = $this->getSerie();
00512 $oDiscount = oxNew('oxDiscount');
00513
00514 $oDiscount->setId($oSeries->getId());
00515 $oDiscount->oxdiscount__oxshopid = new oxField($oSeries->oxvoucherseries__oxshopid->value);
00516 $oDiscount->oxdiscount__oxactive = new oxField(true);
00517 $oDiscount->oxdiscount__oxactivefrom = new oxField($oSeries->oxvoucherseries__oxbegindate->value);
00518 $oDiscount->oxdiscount__oxactiveto = new oxField($oSeries->oxvoucherseries__oxenddate->value);
00519 $oDiscount->oxdiscount__oxtitle = new oxField($oSeries->oxvoucherseries__oxserienr->value);
00520 $oDiscount->oxdiscount__oxamount = new oxField(1);
00521 $oDiscount->oxdiscount__oxamountto = new oxField(MAX_64BIT_INTEGER);
00522 $oDiscount->oxdiscount__oxprice = new oxField(0);
00523 $oDiscount->oxdiscount__oxpriceto = new oxField(MAX_64BIT_INTEGER);
00524 $oDiscount->oxdiscount__oxaddsumtype = new oxField($oSeries->oxvoucherseries__oxdiscounttype->value == 'percent' ? '%' : 'abs');
00525 $oDiscount->oxdiscount__oxaddsum = new oxField($oSeries->oxvoucherseries__oxdiscount->value);
00526 $oDiscount->oxdiscount__oxitmartid = new oxField();
00527 $oDiscount->oxdiscount__oxitmamount = new oxField();
00528 $oDiscount->oxdiscount__oxitmmultiple = new oxField();
00529
00530 return $oDiscount;
00531 }
00532
00540 protected function _getBasketItems($oDiscount = null)
00541 {
00542 if ($this->oxvouchers__oxorderid->value) {
00543 return $this->_getOrderBasketItems($oDiscount);
00544 } elseif ($this->getSession()->getBasket()) {
00545 return $this->_getSessionBasketItems($oDiscount);
00546 } else {
00547 return array();
00548 }
00549 }
00550
00558 protected function _getOrderBasketItems($oDiscount = null)
00559 {
00560 if (is_null($oDiscount)) {
00561 $oDiscount = $this->_getSerieDiscount();
00562 }
00563
00564 $oOrder = oxNew('oxOrder');
00565 $oOrder->load($this->oxvouchers__oxorderid->value);
00566
00567 $aItems = array();
00568 $iCount = 0;
00569
00570 foreach ($oOrder->getOrderArticles(true) as $oOrderArticle) {
00571 if (!$oOrderArticle->skipDiscounts() && $oDiscount->isForBasketItem($oOrderArticle)) {
00572 $aItems[$iCount] = array(
00573 'oxid' => $oOrderArticle->getProductId(),
00574 'price' => $oOrderArticle->oxorderarticles__oxbprice->value,
00575 'discount' => $oDiscount->getAbsValue($oOrderArticle->oxorderarticles__oxbprice->value),
00576 'amount' => $oOrderArticle->oxorderarticles__oxamount->value,
00577 );
00578 $iCount++;
00579 }
00580 }
00581
00582 return $aItems;
00583 }
00584
00592 protected function _getSessionBasketItems($oDiscount = null)
00593 {
00594 if (is_null($oDiscount)) {
00595 $oDiscount = $this->_getSerieDiscount();
00596 }
00597
00598 $oBasket = $this->getSession()->getBasket();
00599 $aItems = array();
00600 $iCount = 0;
00601
00602 foreach ($oBasket->getContents() as $oBasketItem) {
00603 if (!$oBasketItem->isDiscountArticle() && ($oArticle = $oBasketItem->getArticle()) && !$oArticle->skipDiscounts() && $oDiscount->isForBasketItem($oArticle)) {
00604
00605 $aItems[$iCount] = array(
00606 'oxid' => $oArticle->getId(),
00607 'price' => $oArticle->getBasketPrice($oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket)->getPrice(),
00608 'discount' => $oDiscount->getAbsValue($oArticle->getBasketPrice($oBasketItem->getAmount(), $oBasketItem->getSelList(), $oBasket)->getPrice()),
00609 'amount' => $oBasketItem->getAmount(),
00610 );
00611
00612 $iCount++;
00613 }
00614 }
00615
00616 return $aItems;
00617 }
00618
00628 protected function _getGenericDiscoutValue($dPrice)
00629 {
00630 $oSeries = $this->getSerie();
00631 if ($oSeries->oxvoucherseries__oxdiscounttype->value == 'absolute') {
00632 $oCur = $this->getConfig()->getActShopCurrencyObject();
00633 $dDiscount = $oSeries->oxvoucherseries__oxdiscount->value * $oCur->rate;
00634 } else {
00635 $dDiscount = $oSeries->oxvoucherseries__oxdiscount->value / 100 * $dPrice;
00636 }
00637
00638 if ($dDiscount > $dPrice) {
00639 $dDiscount = $dPrice;
00640 }
00641
00642 return $dDiscount;
00643 }
00644
00645
00651 public function getDiscount()
00652 {
00653 $oSeries = $this->getSerie();
00654
00655 return $oSeries->oxvoucherseries__oxdiscount->value;
00656 }
00657
00663 public function getDiscountType()
00664 {
00665 $oSeries = $this->getSerie();
00666
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
00771 return ($dVoucher > $dProduct) ? $dProduct : $dVoucher;
00772 }
00773
00781 public function __get($sName)
00782 {
00783 switch ($sName) {
00784
00785
00786 case 'sVoucherId':
00787 return $this->getId();
00788 break;
00789 case 'sVoucherNr':
00790 return $this->oxvouchers__oxvouchernr;
00791 break;
00792 case 'fVoucherdiscount':
00793 return $this->oxvouchers__oxdiscount;
00794 break;
00795 }
00796 return parent::__get($sName);
00797 }
00798
00805 protected function _getVoucherTimeout()
00806 {
00807 $iVoucherTimeout = intval(oxRegistry::getConfig()->getConfigParam('iVoucherTimeout')) ?
00808 intval(oxRegistry::getConfig()->getConfigParam('iVoucherTimeout')) :
00809 3 * 3600;
00810
00811 return $iVoucherTimeout;
00812 }
00813 }