00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 abstract class Mage_Sales_Model_Quote_Item_Abstract extends Mage_Core_Model_Abstract
00035 {
00036 protected $_parentItem = null;
00037 protected $_children = array();
00038 protected $_messages = array();
00039
00040
00041
00042
00043
00044
00045 abstract function getQuote();
00046
00047 protected function _beforeSave()
00048 {
00049 parent::_beforeSave();
00050 if ($this->getParentItem()) {
00051 $this->setParentItemId($this->getParentItem()->getId());
00052 }
00053 return $this;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 public function setParentItem($parentItem)
00064 {
00065 if ($parentItem) {
00066 $this->_parentItem = $parentItem;
00067 $parentItem->addChild($this);
00068 }
00069 return $this;
00070 }
00071
00072
00073
00074
00075
00076
00077 public function getParentItem()
00078 {
00079 return $this->_parentItem;
00080 }
00081
00082
00083
00084
00085
00086
00087 public function getChildren()
00088 {
00089 return $this->_children;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 public function addChild($child)
00099 {
00100 $this->setHasChildren(true);
00101 $this->_children[] = $child;
00102 return $this;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 public function setMessage($messages) {
00112 if (!is_array($messages)) {
00113 $messages = array($messages);
00114 }
00115 foreach ($messages as $message) {
00116 $this->addMessage($message);
00117 }
00118 return $this;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 public function addMessage($message)
00128 {
00129 $this->_messages[] = $message;
00130 return $this;
00131 }
00132
00133
00134
00135
00136
00137
00138 public function getMessage($string = true)
00139 {
00140 if ($string) {
00141 return join("\n", $this->_messages);
00142 }
00143 return $this->_messages;
00144 }
00145
00146
00147
00148
00149
00150
00151 public function getStore()
00152 {
00153 return $this->getQuote()->getStore();
00154 }
00155
00156
00157
00158
00159
00160
00161 public function checkData()
00162 {
00163 $this->setHasError(false);
00164 $this->unsMessage();
00165
00166 $qty = $this->getData('qty');
00167 try {
00168 $this->setQty($qty);
00169 }
00170 catch (Mage_Core_Exception $e){
00171 $this->setHasError(true);
00172 $this->setMessage($e->getMessage());
00173 }
00174 catch (Exception $e){
00175 $this->setHasError(true);
00176 $this->setMessage(Mage::helper('sales')->__('Item qty declare error'));
00177 }
00178
00179 try {
00180 $this->getProduct()->getTypeInstance(true)->checkProductBuyState($this->getProduct());
00181 } catch (Mage_Core_Exception $e) {
00182 $this->setHasError(true);
00183 $this->setMessage($e->getMessage());
00184 $this->getQuote()->setHasError(true);
00185 $this->getQuote()->addMessage(Mage::helper('sales')->__('Some of the products below don\'t have all the required options. Please remove them and add again with all the required options.'));
00186 } catch (Exception $e) {
00187 $this->setHasError(true);
00188 $this->setMessage(Mage::helper('sales')->__('Item options declare error'));
00189 $this->getQuote()->setHasError(true);
00190 $this->getQuote()->addMessage(Mage::helper('sales')->__('Items options declare error.'));
00191 }
00192
00193 return $this;
00194 }
00195
00196
00197
00198
00199
00200
00201 public function calcRowTotal()
00202 {
00203 $qty = $this->getQty();
00204
00205 if ($this->getParentItem()) {
00206 $qty = $qty*$this->getParentItem()->getQty();
00207 }
00208
00209 if ($rowTotal = $this->getRowTotalExcTax()) {
00210 $baseTotal = $rowTotal;
00211 $total = $this->getStore()->convertPrice($baseTotal);
00212 }
00213 else {
00214 $total = $this->getCalculationPrice()*$qty;
00215 $baseTotal = $this->getBaseCalculationPrice()*$qty;
00216 }
00217
00218 $this->setRowTotal($this->getStore()->roundPrice($total));
00219 $this->setBaseRowTotal($this->getStore()->roundPrice($baseTotal));
00220
00221 return $this;
00222 }
00223
00224
00225
00226
00227
00228
00229 public function calcTaxAmount()
00230 {
00231 $store = $this->getStore();
00232
00233 if (!Mage::helper('tax')->priceIncludesTax($store)) {
00234 if (Mage::helper('tax')->applyTaxAfterDiscount($store)) {
00235 $rowTotal = $this->getRowTotalWithDiscount();
00236 $rowBaseTotal = $this->getBaseRowTotalWithDiscount();
00237 } else {
00238 $rowTotal = $this->getRowTotal();
00239 $rowBaseTotal = $this->getBaseRowTotal();
00240 }
00241
00242 $taxPercent = $this->getTaxPercent()/100;
00243
00244 $this->setTaxAmount($store->roundPrice($rowTotal * $taxPercent));
00245 $this->setBaseTaxAmount($store->roundPrice($rowBaseTotal * $taxPercent));
00246
00247 $rowTotal = $this->getRowTotal();
00248 $rowBaseTotal = $this->getBaseRowTotal();
00249 $this->setTaxBeforeDiscount($store->roundPrice($rowTotal * $taxPercent));
00250 $this->setBaseTaxBeforeDiscount($store->roundPrice($rowBaseTotal * $taxPercent));
00251 } else {
00252 if (Mage::helper('tax')->applyTaxAfterDiscount($store)) {
00253 $totalBaseTax = $this->getBaseTaxAmount();
00254 $totalTax = $this->getTaxAmount();
00255
00256 if ($totalTax && $totalBaseTax) {
00257 $totalTax -= $this->getDiscountAmount()*($this->getTaxPercent()/100);
00258 $totalBaseTax -= $this->getBaseDiscountAmount()*($this->getTaxPercent()/100);
00259
00260 $this->setBaseTaxAmount($store->roundPrice($totalBaseTax));
00261 $this->setTaxAmount($store->roundPrice($totalTax));
00262 }
00263 }
00264 }
00265
00266 if (Mage::helper('tax')->discountTax($store) && !Mage::helper('tax')->applyTaxAfterDiscount($store)) {
00267 if ($this->getDiscountPercent()) {
00268 $baseTaxAmount = $this->getBaseTaxBeforeDiscount();
00269 $taxAmount = $this->getTaxBeforeDiscount();
00270
00271 $baseDiscountDisposition = $baseTaxAmount/100*$this->getDiscountPercent();
00272 $discountDisposition = $taxAmount/100*$this->getDiscountPercent();
00273
00274 $this->setDiscountAmount($this->getDiscountAmount()+$discountDisposition);
00275 $this->setBaseDiscountAmount($this->getBaseDiscountAmount()+$baseDiscountDisposition);
00276 }
00277 }
00278
00279 return $this;
00280 }
00281
00282
00283
00284
00285
00286
00287 public function getCalculationPrice()
00288 {
00289 $price = $this->getData('calculation_price');
00290 if (is_null($price)) {
00291 if ($this->hasCustomPrice()) {
00292 $price = $this->getCustomPrice();
00293 }
00294 else {
00295 $price = $this->getOriginalPrice();
00296 }
00297 $this->setData('calculation_price', $price);
00298 }
00299 return $price;
00300 }
00301
00302
00303
00304
00305
00306
00307 public function getBaseCalculationPrice()
00308 {
00309 if (!$this->hasBaseCalculationPrice()) {
00310 if ($this->hasCustomPrice()) {
00311 if ($price = (float) $this->getCustomPrice()) {
00312 $rate = $this->getStore()->convertPrice($price) / $price;
00313 $price = $price / $rate;
00314 }
00315 else {
00316 $price = $this->getCustomPrice();
00317 }
00318 } else {
00319 $price = $this->getPrice();
00320 }
00321 $this->setBaseCalculationPrice($price);
00322 }
00323 return $this->getData('base_calculation_price');
00324 }
00325
00326
00327
00328
00329
00330
00331 public function getOriginalPrice()
00332 {
00333 $price = $this->getData('original_price');
00334 if (is_null($price)) {
00335 $price = $this->getStore()->convertPrice($this->getPrice());
00336 $this->setData('original_price', $price);
00337 }
00338 return $price;
00339 }
00340
00341
00342
00343
00344
00345
00346 public function getTaxAmount()
00347 {
00348 $priceType = $this->getProduct()->getPriceType();
00349 if ($this->getHasChildren() && (null !== $priceType) && (int)$priceType === Mage_Catalog_Model_Product_Type_Abstract::CALCULATE_CHILD) {
00350 $amount = 0;
00351 foreach ($this->getChildren() as $child) {
00352 $amount+= $child->getTaxAmount();
00353 }
00354 return $amount;
00355 }
00356 else {
00357 return $this->_getData('tax_amount');
00358 }
00359 }
00360
00361
00362
00363
00364
00365
00366 public function getPrice()
00367 {
00368 $priceType = $this->getProduct()->getPriceType();
00369 if ($this->getHasChildren() && (null !== $priceType) && (int)$priceType === Mage_Catalog_Model_Product_Type_Abstract::CALCULATE_CHILD) {
00370 $price = $this->_getData('price');
00371
00372
00373
00374
00375
00376 return $price;
00377 }
00378 else {
00379 return $this->_getData('price');
00380 }
00381 }
00382
00383 public function setCustomPrice($value)
00384 {
00385 if (is_null($value)) {
00386 return $this->setData('custom_price', $value);
00387 }
00388
00389 $excludingTax = $this->_calculatePrice($value, Mage::helper('tax')->applyTaxOnCustomPrice());
00390 $this->setData('original_custom_price', $value);
00391 return $this->setData('custom_price', $excludingTax);
00392 }
00393
00394 public function setPrice($value)
00395 {
00396 $saveTaxes = true;
00397 if (Mage::helper('tax')->applyTaxOnCustomPrice() && $this->hasCustomPrice()) {
00398 $saveTaxes = false;
00399 }
00400 return $this->setData('price', $this->_calculatePrice($value, $saveTaxes));
00401 }
00402
00403 protected function _calculatePrice($value, $saveTaxes = true)
00404 {
00405 $store = $this->getQuote()->getStore();
00406
00407 if (Mage::helper('tax')->priceIncludesTax($store)) {
00408 $bAddress = $this->getQuote()->getBillingAddress();
00409 $sAddress = $this->getQuote()->getShippingAddress();
00410
00411 $address = $this->getAddress();
00412
00413 if ($address) {
00414 switch ($address->getAddressType()) {
00415 case Mage_Sales_Model_Quote_Address::TYPE_BILLING:
00416 $bAddress = $address;
00417 break;
00418 case Mage_Sales_Model_Quote_Address::TYPE_SHIPPING:
00419 $sAddress = $address;
00420 break;
00421 }
00422 }
00423
00424 if ($this->getProduct()->getIsVirtual()) {
00425 $sAddress = $bAddress;
00426 }
00427
00428 $priceExcludingTax = Mage::helper('tax')->getPrice(
00429 $this->getProduct()->setTaxPercent(null),
00430 $value,
00431 false,
00432 $sAddress,
00433 $bAddress,
00434 $this->getQuote()->getCustomerTaxClassId(),
00435 $store
00436 );
00437
00438 $priceIncludingTax = Mage::helper('tax')->getPrice(
00439 $this->getProduct()->setTaxPercent(null),
00440 $value,
00441 true,
00442 $sAddress,
00443 $bAddress,
00444 $this->getQuote()->getCustomerTaxClassId(),
00445 $store
00446 );
00447
00448 if ($saveTaxes) {
00449 $qty = $this->getQty();
00450 if ($this->getParentItem()) {
00451 $qty = $qty*$this->getParentItem()->getQty();
00452 }
00453
00454 if (Mage::helper('tax')->displayCartPriceInclTax($store)) {
00455 $rowTotal = $value*$qty;
00456 $rowTotalExcTax = Mage::helper('tax')->getPrice(
00457 $this->getProduct()->setTaxPercent(null),
00458 $rowTotal,
00459 false,
00460 $sAddress,
00461 $bAddress,
00462 $this->getQuote()->getCustomerTaxClassId(),
00463 $store
00464 );
00465 $rowTotalIncTax = Mage::helper('tax')->getPrice(
00466 $this->getProduct()->setTaxPercent(null),
00467 $rowTotal,
00468 true,
00469 $sAddress,
00470 $bAddress,
00471 $this->getQuote()->getCustomerTaxClassId(),
00472 $store
00473 );
00474 $totalBaseTax = $rowTotalIncTax-$rowTotalExcTax;
00475 $this->setRowTotalExcTax($rowTotalExcTax);
00476 }
00477 else {
00478 $taxAmount = $priceIncludingTax - $priceExcludingTax;
00479 $this->setTaxPercent($this->getProduct()->getTaxPercent());
00480 $totalBaseTax = $taxAmount*$qty;
00481 }
00482
00483 $totalTax = $this->getStore()->convertPrice($totalBaseTax);
00484 $this->setTaxBeforeDiscount($totalTax);
00485 $this->setBaseTaxBeforeDiscount($totalBaseTax);
00486
00487 $this->setTaxAmount($totalTax);
00488 $this->setBaseTaxAmount($totalBaseTax);
00489 }
00490
00491 $value = $priceExcludingTax;
00492 }
00493
00494 return $value;
00495 }
00496
00497
00498
00499
00500
00501
00502 public function __clone()
00503 {
00504 $this->setId(null);
00505 $this->_parentItem = null;
00506 $this->_children = array();
00507 return $this;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516 public function isChildrenCalculated() {
00517 if ($this->getParentItem()) {
00518 $calculate = $this->getParentItem()->getProduct()->getPriceType();
00519 } else {
00520 $calculate = $this->getProduct()->getPriceType();
00521 }
00522
00523 if ((null !== $calculate) && (int)$calculate === Mage_Catalog_Model_Product_Type_Abstract::CALCULATE_CHILD) {
00524 return true;
00525 }
00526 return false;
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536 public function isShipSeparately() {
00537 if ($this->getParentItem()) {
00538 $shipmentType = $this->getParentItem()->getProduct()->getShipmentType();
00539 } else {
00540 $shipmentType = $this->getProduct()->getShipmentType();
00541 }
00542
00543 if ((null !== $shipmentType) && (int)$shipmentType === Mage_Catalog_Model_Product_Type_Abstract::SHIPMENT_SEPARATELY) {
00544 return true;
00545 }
00546 return false;
00547 }
00548 }