1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138:
139: class Mage_Sales_Model_Quote extends Mage_Core_Model_Abstract
140: {
141: protected $_eventPrefix = 'sales_quote';
142: protected $_eventObject = 'quote';
143:
144: 145: 146: 147: 148:
149: protected $_customer;
150:
151: 152: 153: 154: 155:
156: protected $_addresses = null;
157:
158: 159: 160: 161: 162:
163: protected $_items = null;
164:
165: 166: 167: 168: 169:
170: protected $_payments = null;
171:
172: 173: 174: 175: 176:
177: protected $_errorInfoGroups = array();
178:
179: 180: 181: 182: 183:
184: protected $_preventSaving = false;
185:
186: 187: 188:
189: protected function _construct()
190: {
191: $this->_init('sales/quote');
192: }
193:
194: 195: 196: 197: 198: 199:
200: protected function _initOldFieldsMap()
201: {
202: $this->_oldFieldsMap = Mage::helper('sales')->getOldFieldMap('quote');
203: return $this;
204: }
205:
206: 207: 208: 209: 210:
211: public function getStoreId()
212: {
213: if (!$this->hasStoreId()) {
214: return Mage::app()->getStore()->getId();
215: }
216: return $this->_getData('store_id');
217: }
218:
219: 220: 221: 222: 223:
224: public function getStore()
225: {
226: return Mage::app()->getStore($this->getStoreId());
227: }
228:
229: 230: 231: 232: 233: 234:
235: public function setStore(Mage_Core_Model_Store $store)
236: {
237: $this->setStoreId($store->getId());
238: return $this;
239: }
240:
241: 242: 243: 244: 245:
246: public function getSharedStoreIds()
247: {
248: $ids = $this->_getData('shared_store_ids');
249: if (is_null($ids) || !is_array($ids)) {
250: if ($website = $this->getWebsite()) {
251: return $website->getStoreIds();
252: }
253: return $this->getStore()->getWebsite()->getStoreIds();
254: }
255: return $ids;
256: }
257:
258: 259: 260: 261: 262:
263: protected function _beforeSave()
264: {
265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281:
282:
283: $globalCurrencyCode = Mage::app()->getBaseCurrencyCode();
284: $baseCurrency = $this->getStore()->getBaseCurrency();
285:
286: if ($this->hasForcedCurrency()){
287: $quoteCurrency = $this->getForcedCurrency();
288: } else {
289: $quoteCurrency = $this->getStore()->getCurrentCurrency();
290: }
291:
292: $this->setGlobalCurrencyCode($globalCurrencyCode);
293: $this->setBaseCurrencyCode($baseCurrency->getCode());
294: $this->setStoreCurrencyCode($baseCurrency->getCode());
295: $this->setQuoteCurrencyCode($quoteCurrency->getCode());
296:
297:
298: $this->setStoreToBaseRate($baseCurrency->getRate($globalCurrencyCode));
299: $this->setStoreToQuoteRate($baseCurrency->getRate($quoteCurrency));
300:
301: $this->setBaseToGlobalRate($baseCurrency->getRate($globalCurrencyCode));
302: $this->setBaseToQuoteRate($baseCurrency->getRate($quoteCurrency));
303:
304: if (!$this->hasChangedFlag() || $this->getChangedFlag() == true) {
305: $this->setIsChanged(1);
306: } else {
307: $this->setIsChanged(0);
308: }
309:
310: if ($this->_customer) {
311: $this->setCustomerId($this->_customer->getId());
312: }
313:
314: parent::_beforeSave();
315: }
316:
317: 318: 319: 320: 321:
322: protected function _afterSave()
323: {
324: parent::_afterSave();
325:
326: if (null !== $this->_addresses) {
327: $this->getAddressesCollection()->save();
328: }
329:
330: if (null !== $this->_items) {
331: $this->getItemsCollection()->save();
332: }
333:
334: if (null !== $this->_payments) {
335: $this->getPaymentsCollection()->save();
336: }
337: return $this;
338: }
339:
340: 341: 342: 343: 344:
345: public function loadByCustomer($customer)
346: {
347: if ($customer instanceof Mage_Customer_Model_Customer) {
348: $customerId = $customer->getId();
349: }
350: else {
351: $customerId = (int) $customer;
352: }
353: $this->_getResource()->loadByCustomerId($this, $customerId);
354: $this->_afterLoad();
355: return $this;
356: }
357:
358: 359: 360: 361: 362: 363:
364: public function loadActive($quoteId)
365: {
366: $this->_getResource()->loadActive($this, $quoteId);
367: $this->_afterLoad();
368: return $this;
369: }
370:
371: 372: 373: 374: 375: 376:
377: public function loadByIdWithoutStore($quoteId)
378: {
379: $this->_getResource()->loadByIdWithoutStore($this, $quoteId);
380: $this->_afterLoad();
381: return $this;
382: }
383:
384: 385: 386: 387: 388: 389:
390: public function assignCustomer(Mage_Customer_Model_Customer $customer)
391: {
392: return $this->assignCustomerWithAddressChange($customer);
393: }
394:
395: 396: 397: 398: 399: 400: 401: 402:
403: public function assignCustomerWithAddressChange(
404: Mage_Customer_Model_Customer $customer,
405: Mage_Sales_Model_Quote_Address $billingAddress = null,
406: Mage_Sales_Model_Quote_Address $shippingAddress = null
407: )
408: {
409: if ($customer->getId()) {
410: $this->setCustomer($customer);
411:
412: if (!is_null($billingAddress)) {
413: $this->setBillingAddress($billingAddress);
414: } else {
415: $defaultBillingAddress = $customer->getDefaultBillingAddress();
416: if ($defaultBillingAddress && $defaultBillingAddress->getId()) {
417: $billingAddress = Mage::getModel('sales/quote_address')
418: ->importCustomerAddress($defaultBillingAddress);
419: $this->setBillingAddress($billingAddress);
420: }
421: }
422:
423: if (is_null($shippingAddress)) {
424: $defaultShippingAddress = $customer->getDefaultShippingAddress();
425: if ($defaultShippingAddress && $defaultShippingAddress->getId()) {
426: $shippingAddress = Mage::getModel('sales/quote_address')
427: ->importCustomerAddress($defaultShippingAddress);
428: } else {
429: $shippingAddress = Mage::getModel('sales/quote_address');
430: }
431: }
432: $this->setShippingAddress($shippingAddress);
433: }
434:
435: return $this;
436: }
437:
438: 439: 440: 441: 442: 443:
444: public function setCustomer(Mage_Customer_Model_Customer $customer)
445: {
446: $this->_customer = $customer;
447: $this->setCustomerId($customer->getId());
448: Mage::helper('core')->copyFieldset('customer_account', 'to_quote', $customer, $this);
449: return $this;
450: }
451:
452: 453: 454: 455: 456:
457: public function getCustomer()
458: {
459: if (is_null($this->_customer)) {
460: $this->_customer = Mage::getModel('customer/customer');
461: if ($customerId = $this->getCustomerId()) {
462: $this->_customer->load($customerId);
463: if (!$this->_customer->getId()) {
464: $this->_customer->setCustomerId(null);
465: }
466: }
467: }
468: return $this->_customer;
469: }
470:
471: 472: 473: 474: 475:
476: public function getCustomerGroupId()
477: {
478: if ($this->hasData('customer_group_id')) {
479: return $this->getData('customer_group_id');
480: } else if ($this->getCustomerId()) {
481: return $this->getCustomer()->getGroupId();
482: } else {
483: return Mage_Customer_Model_Group::NOT_LOGGED_IN_ID;
484: }
485: }
486:
487: public function getCustomerTaxClassId()
488: {
489: 490: 491: 492:
493:
494: $classId = Mage::getModel('customer/group')->getTaxClassId($this->getCustomerGroupId());
495: $this->setCustomerTaxClassId($classId);
496:
497:
498: return $this->getData('customer_tax_class_id');
499: }
500:
501: 502: 503: 504: 505:
506: public function getAddressesCollection()
507: {
508: if (is_null($this->_addresses)) {
509: $this->_addresses = Mage::getModel('sales/quote_address')->getCollection()
510: ->setQuoteFilter($this->getId());
511:
512: if ($this->getId()) {
513: foreach ($this->_addresses as $address) {
514: $address->setQuote($this);
515: }
516: }
517: }
518: return $this->_addresses;
519: }
520:
521: 522: 523: 524: 525: 526:
527: protected function _getAddressByType($type)
528: {
529: foreach ($this->getAddressesCollection() as $address) {
530: if ($address->getAddressType() == $type && !$address->isDeleted()) {
531: return $address;
532: }
533: }
534:
535: $address = Mage::getModel('sales/quote_address')->setAddressType($type);
536: $this->addAddress($address);
537: return $address;
538: }
539:
540: 541: 542: 543: 544:
545: public function getBillingAddress()
546: {
547: return $this->_getAddressByType(Mage_Sales_Model_Quote_Address::TYPE_BILLING);
548: }
549:
550: 551: 552: 553: 554:
555: public function getShippingAddress()
556: {
557: return $this->_getAddressByType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING);
558: }
559:
560: public function getAllShippingAddresses()
561: {
562: $addresses = array();
563: foreach ($this->getAddressesCollection() as $address) {
564: if ($address->getAddressType()==Mage_Sales_Model_Quote_Address::TYPE_SHIPPING
565: && !$address->isDeleted()) {
566: $addresses[] = $address;
567: }
568: }
569: return $addresses;
570: }
571:
572: public function getAllAddresses()
573: {
574: $addresses = array();
575: foreach ($this->getAddressesCollection() as $address) {
576: if (!$address->isDeleted()) {
577: $addresses[] = $address;
578: }
579: }
580: return $addresses;
581: }
582:
583: 584: 585: 586: 587:
588: public function getAddressById($addressId)
589: {
590: foreach ($this->getAddressesCollection() as $address) {
591: if ($address->getId()==$addressId) {
592: return $address;
593: }
594: }
595: return false;
596: }
597:
598: public function getAddressByCustomerAddressId($addressId)
599: {
600: foreach ($this->getAddressesCollection() as $address) {
601: if (!$address->isDeleted() && $address->getCustomerAddressId()==$addressId) {
602: return $address;
603: }
604: }
605: return false;
606: }
607:
608: public function getShippingAddressByCustomerAddressId($addressId)
609: {
610: foreach ($this->getAddressesCollection() as $address) {
611: if (!$address->isDeleted() && $address->getAddressType()==Mage_Sales_Model_Quote_Address::TYPE_SHIPPING
612: && $address->getCustomerAddressId()==$addressId) {
613: return $address;
614: }
615: }
616: return false;
617: }
618:
619: public function removeAddress($addressId)
620: {
621: foreach ($this->getAddressesCollection() as $address) {
622: if ($address->getId()==$addressId) {
623: $address->isDeleted(true);
624: break;
625: }
626: }
627: return $this;
628: }
629:
630: public function removeAllAddresses()
631: {
632: foreach ($this->getAddressesCollection() as $address) {
633: $address->isDeleted(true);
634: }
635: return $this;
636: }
637:
638: public function addAddress(Mage_Sales_Model_Quote_Address $address)
639: {
640: $address->setQuote($this);
641: if (!$address->getId()) {
642: $this->getAddressesCollection()->addItem($address);
643: }
644: return $this;
645: }
646:
647: 648: 649: 650: 651: 652:
653: public function setBillingAddress(Mage_Sales_Model_Quote_Address $address)
654: {
655: $old = $this->getBillingAddress();
656:
657: if (!empty($old)) {
658: $old->addData($address->getData());
659: } else {
660: $this->addAddress($address->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_BILLING));
661: }
662: return $this;
663: }
664:
665: 666: 667: 668: 669: 670:
671: public function setShippingAddress(Mage_Sales_Model_Quote_Address $address)
672: {
673: if ($this->getIsMultiShipping()) {
674: $this->addAddress($address->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING));
675: }
676: else {
677: $old = $this->getShippingAddress();
678:
679: if (!empty($old)) {
680: $old->addData($address->getData());
681: } else {
682: $this->addAddress($address->setAddressType(Mage_Sales_Model_Quote_Address::TYPE_SHIPPING));
683: }
684: }
685: return $this;
686: }
687:
688: public function addShippingAddress(Mage_Sales_Model_Quote_Address $address)
689: {
690: $this->setShippingAddress($address);
691: return $this;
692: }
693:
694: 695: 696: 697: 698: 699:
700: public function getItemsCollection($useCache = true)
701: {
702: if ($this->hasItemsCollection()) {
703: return $this->getData('items_collection');
704: }
705: if (is_null($this->_items)) {
706: $this->_items = Mage::getModel('sales/quote_item')->getCollection();
707: $this->_items->setQuote($this);
708: }
709: return $this->_items;
710: }
711:
712: 713: 714: 715: 716:
717: public function getAllItems()
718: {
719: $items = array();
720: foreach ($this->getItemsCollection() as $item) {
721: if (!$item->isDeleted()) {
722: $items[] = $item;
723: }
724: }
725: return $items;
726: }
727:
728: 729: 730: 731: 732:
733: public function getAllVisibleItems()
734: {
735: $items = array();
736: foreach ($this->getItemsCollection() as $item) {
737: if (!$item->isDeleted() && !$item->getParentItemId()) {
738: $items[] = $item;
739: }
740: }
741: return $items;
742: }
743:
744: 745: 746: 747: 748:
749: public function hasItems()
750: {
751: return sizeof($this->getAllItems())>0;
752: }
753:
754: 755: 756: 757: 758:
759: public function hasItemsWithDecimalQty()
760: {
761: foreach ($this->getAllItems() as $item) {
762: if ($item->getProduct()->getStockItem()
763: && $item->getProduct()->getStockItem()->getIsQtyDecimal()) {
764: return true;
765: }
766: }
767: return false;
768: }
769:
770: 771: 772: 773: 774: 775:
776: public function hasProductId($productId)
777: {
778: foreach ($this->getAllItems() as $item) {
779: if ($item->getProductId() == $productId) {
780: return true;
781: }
782: }
783:
784: return false;
785: }
786:
787: 788: 789: 790: 791: 792:
793: public function getItemById($itemId)
794: {
795: return $this->getItemsCollection()->getItemById($itemId);
796: }
797:
798: 799: 800: 801: 802: 803:
804: public function removeItem($itemId)
805: {
806: $item = $this->getItemById($itemId);
807:
808: if ($item) {
809: $item->setQuote($this);
810: 811: 812:
813: $this->setIsMultiShipping(false);
814: $item->isDeleted(true);
815: if ($item->getHasChildren()) {
816: foreach ($item->getChildren() as $child) {
817: $child->isDeleted(true);
818: }
819: }
820:
821: $parent = $item->getParentItem();
822: if ($parent) {
823: $parent->isDeleted(true);
824: }
825:
826: Mage::dispatchEvent('sales_quote_remove_item', array('quote_item' => $item));
827: }
828:
829: return $this;
830: }
831:
832: 833: 834: 835: 836:
837: public function removeAllItems()
838: {
839: foreach ($this->getItemsCollection() as $itemId => $item) {
840: if (is_null($item->getId())) {
841: $this->getItemsCollection()->removeItemByKey($itemId);
842: } else {
843: $item->isDeleted(true);
844: }
845: }
846: return $this;
847: }
848:
849: 850: 851: 852: 853: 854:
855: public function addItem(Mage_Sales_Model_Quote_Item $item)
856: {
857: 858: 859: 860: 861: 862: 863: 864:
865: if ($item->isNominal() && $this->hasItems() || $this->hasNominalItems()) {
866: Mage::throwException(
867: Mage::helper('sales')->__('Nominal item can be purchased standalone only. To proceed please remove other items from the quote.')
868: );
869: }
870:
871: $item->setQuote($this);
872: if (!$item->getId()) {
873: $this->getItemsCollection()->addItem($item);
874: Mage::dispatchEvent('sales_quote_add_item', array('quote_item' => $item));
875: }
876: return $this;
877: }
878:
879: 880: 881: 882: 883: 884: 885: 886: 887:
888: public function addProductAdvanced(Mage_Catalog_Model_Product $product, $request = null, $processMode = null)
889: {
890: if ($request === null) {
891: $request = 1;
892: }
893: if (is_numeric($request)) {
894: $request = new Varien_Object(array('qty'=>$request));
895: }
896: if (!($request instanceof Varien_Object)) {
897: Mage::throwException(Mage::helper('sales')->__('Invalid request for adding product to quote.'));
898: }
899:
900: $cartCandidates = $product->getTypeInstance(true)
901: ->prepareForCartAdvanced($request, $product, $processMode);
902:
903: 904: 905:
906: if (is_string($cartCandidates)) {
907: return $cartCandidates;
908: }
909:
910: 911: 912:
913: if (!is_array($cartCandidates)) {
914: $cartCandidates = array($cartCandidates);
915: }
916:
917: $parentItem = null;
918: $errors = array();
919: $items = array();
920: foreach ($cartCandidates as $candidate) {
921:
922: $stickWithinParent = $candidate->getParentProductId() ? $parentItem : null;
923: $candidate->setStickWithinParent($stickWithinParent);
924: $item = $this->_addCatalogProduct($candidate, $candidate->getCartQty());
925: if($request->getResetCount() && !$stickWithinParent && $item->getId() === $request->getId()) {
926: $item->setData('qty', 0);
927: }
928: $items[] = $item;
929:
930: 931: 932:
933: if (!$parentItem) {
934: $parentItem = $item;
935: }
936: if ($parentItem && $candidate->getParentProductId()) {
937: $item->setParentItem($parentItem);
938: }
939:
940: 941: 942:
943: $item->addQty($candidate->getCartQty());
944:
945:
946: if ($item->getHasError()) {
947: $message = $item->getMessage();
948: if (!in_array($message, $errors)) {
949: $errors[] = $message;
950: }
951: }
952: }
953: if (!empty($errors)) {
954: Mage::throwException(implode("\n", $errors));
955: }
956:
957: Mage::dispatchEvent('sales_quote_product_add_after', array('items' => $items));
958:
959: return $item;
960: }
961:
962:
963: 964: 965: 966: 967: 968: 969: 970: 971:
972: public function addProduct(Mage_Catalog_Model_Product $product, $request = null)
973: {
974: return $this->addProductAdvanced(
975: $product,
976: $request,
977: Mage_Catalog_Model_Product_Type_Abstract::PROCESS_MODE_FULL
978: );
979: }
980:
981: 982: 983: 984: 985: 986:
987: protected function _addCatalogProduct(Mage_Catalog_Model_Product $product, $qty = 1)
988: {
989: $newItem = false;
990: $item = $this->getItemByProduct($product);
991: if (!$item) {
992: $item = Mage::getModel('sales/quote_item');
993: $item->setQuote($this);
994: if (Mage::app()->getStore()->isAdmin()) {
995: $item->setStoreId($this->getStore()->getId());
996: }
997: else {
998: $item->setStoreId(Mage::app()->getStore()->getId());
999: }
1000: $newItem = true;
1001: }
1002:
1003: 1004: 1005:
1006: if ($item->getId() && $product->getParentProductId()) {
1007: return $item;
1008: }
1009:
1010: $item->setOptions($product->getCustomOptions())
1011: ->setProduct($product);
1012:
1013:
1014: if ($newItem) {
1015: $this->addItem($item);
1016: }
1017:
1018: return $item;
1019: }
1020:
1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041:
1042: public function updateItem($itemId, $buyRequest, $params = null)
1043: {
1044: $item = $this->getItemById($itemId);
1045: if (!$item) {
1046: Mage::throwException(Mage::helper('sales')->__('Wrong quote item id to update configuration.'));
1047: }
1048: $productId = $item->getProduct()->getId();
1049:
1050:
1051:
1052: $product = Mage::getModel('catalog/product')
1053: ->setStoreId($this->getStore()->getId())
1054: ->load($productId);
1055:
1056: if (!$params) {
1057: $params = new Varien_Object();
1058: } else if (is_array($params)) {
1059: $params = new Varien_Object($params);
1060: }
1061: $params->setCurrentConfig($item->getBuyRequest());
1062: $buyRequest = Mage::helper('catalog/product')->addParamsToBuyRequest($buyRequest, $params);
1063:
1064: $buyRequest->setResetCount(true);
1065: $resultItem = $this->addProduct($product, $buyRequest);
1066:
1067: if (is_string($resultItem)) {
1068: Mage::throwException($resultItem);
1069: }
1070:
1071: if ($resultItem->getParentItem()) {
1072: $resultItem = $resultItem->getParentItem();
1073: }
1074:
1075: if ($resultItem->getId() != $itemId) {
1076: 1077: 1078: 1079:
1080: $this->removeItem($itemId);
1081:
1082: $items = $this->getAllItems();
1083: foreach ($items as $item) {
1084: if (($item->getProductId() == $productId) && ($item->getId() != $resultItem->getId())) {
1085: if ($resultItem->compare($item)) {
1086:
1087: $resultItem->setQty($resultItem->getQty() + $item->getQty());
1088: $this->removeItem($item->getId());
1089: break;
1090: }
1091: }
1092: }
1093: } else {
1094: $resultItem->setQty($buyRequest->getQty());
1095: }
1096:
1097: return $resultItem;
1098: }
1099:
1100: 1101: 1102: 1103: 1104: 1105:
1106: public function getItemByProduct($product)
1107: {
1108: foreach ($this->getAllItems() as $item) {
1109: if ($item->representProduct($product)) {
1110: return $item;
1111: }
1112: }
1113: return false;
1114: }
1115:
1116: public function getItemsSummaryQty()
1117: {
1118: $qty = $this->getData('all_items_qty');
1119: if (is_null($qty)) {
1120: $qty = 0;
1121: foreach ($this->getAllItems() as $item) {
1122: if ($item->getParentItem()) {
1123: continue;
1124: }
1125:
1126: if (($children = $item->getChildren()) && $item->isShipSeparately()) {
1127: foreach ($children as $child) {
1128: $qty+= $child->getQty()*$item->getQty();
1129: }
1130: } else {
1131: $qty+= $item->getQty();
1132: }
1133: }
1134: $this->setData('all_items_qty', $qty);
1135: }
1136: return $qty;
1137: }
1138:
1139: public function getItemVirtualQty()
1140: {
1141: $qty = $this->getData('virtual_items_qty');
1142: if (is_null($qty)) {
1143: $qty = 0;
1144: foreach ($this->getAllItems() as $item) {
1145: if ($item->getParentItem()) {
1146: continue;
1147: }
1148:
1149: if (($children = $item->getChildren()) && $item->isShipSeparately()) {
1150: foreach ($children as $child) {
1151: if ($child->getProduct()->getIsVirtual()) {
1152: $qty+= $child->getQty();
1153: }
1154: }
1155: } else {
1156: if ($item->getProduct()->getIsVirtual()) {
1157: $qty+= $item->getQty();
1158: }
1159: }
1160: }
1161: $this->setData('virtual_items_qty', $qty);
1162: }
1163: return $qty;
1164: }
1165:
1166:
1167: public function getPaymentsCollection()
1168: {
1169: if (is_null($this->_payments)) {
1170: $this->_payments = Mage::getModel('sales/quote_payment')->getCollection()
1171: ->setQuoteFilter($this->getId());
1172:
1173: if ($this->getId()) {
1174: foreach ($this->_payments as $payment) {
1175: $payment->setQuote($this);
1176: }
1177: }
1178: }
1179: return $this->_payments;
1180: }
1181:
1182: 1183: 1184:
1185: public function getPayment()
1186: {
1187: foreach ($this->getPaymentsCollection() as $payment) {
1188: if (!$payment->isDeleted()) {
1189: return $payment;
1190: }
1191: }
1192: $payment = Mage::getModel('sales/quote_payment');
1193: $this->addPayment($payment);
1194: return $payment;
1195: }
1196:
1197: public function getPaymentById($paymentId)
1198: {
1199: foreach ($this->getPaymentsCollection() as $payment) {
1200: if ($payment->getId()==$paymentId) {
1201: return $payment;
1202: }
1203: }
1204: return false;
1205: }
1206:
1207: public function addPayment(Mage_Sales_Model_Quote_Payment $payment)
1208: {
1209: $payment->setQuote($this);
1210: if (!$payment->getId()) {
1211: $this->getPaymentsCollection()->addItem($payment);
1212: }
1213: return $this;
1214: }
1215:
1216: public function setPayment(Mage_Sales_Model_Quote_Payment $payment)
1217: {
1218: if (!$this->getIsMultiPayment() && ($old = $this->getPayment())) {
1219: $payment->setId($old->getId());
1220: }
1221: $this->addPayment($payment);
1222:
1223: return $payment;
1224: }
1225:
1226: public function removePayment()
1227: {
1228: $this->getPayment()->isDeleted(true);
1229: return $this;
1230: }
1231:
1232: 1233: 1234: 1235: 1236:
1237: public function collectTotals()
1238: {
1239: 1240: 1241:
1242: if ($this->getTotalsCollectedFlag()) {
1243: return $this;
1244: }
1245: Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_before', array($this->_eventObject => $this));
1246:
1247: $this->setSubtotal(0);
1248: $this->setBaseSubtotal(0);
1249:
1250: $this->setSubtotalWithDiscount(0);
1251: $this->setBaseSubtotalWithDiscount(0);
1252:
1253: $this->setGrandTotal(0);
1254: $this->setBaseGrandTotal(0);
1255:
1256: foreach ($this->getAllAddresses() as $address) {
1257: $address->setSubtotal(0);
1258: $address->setBaseSubtotal(0);
1259:
1260: $address->setGrandTotal(0);
1261: $address->setBaseGrandTotal(0);
1262:
1263: $address->collectTotals();
1264:
1265: $this->setSubtotal((float) $this->getSubtotal() + $address->getSubtotal());
1266: $this->setBaseSubtotal((float) $this->getBaseSubtotal() + $address->getBaseSubtotal());
1267:
1268: $this->setSubtotalWithDiscount(
1269: (float) $this->getSubtotalWithDiscount() + $address->getSubtotalWithDiscount()
1270: );
1271: $this->setBaseSubtotalWithDiscount(
1272: (float) $this->getBaseSubtotalWithDiscount() + $address->getBaseSubtotalWithDiscount()
1273: );
1274:
1275: $this->setGrandTotal((float) $this->getGrandTotal() + $address->getGrandTotal());
1276: $this->setBaseGrandTotal((float) $this->getBaseGrandTotal() + $address->getBaseGrandTotal());
1277: }
1278:
1279: Mage::helper('sales')->checkQuoteAmount($this, $this->getGrandTotal());
1280: Mage::helper('sales')->checkQuoteAmount($this, $this->getBaseGrandTotal());
1281:
1282: $this->setItemsCount(0);
1283: $this->setItemsQty(0);
1284: $this->setVirtualItemsQty(0);
1285:
1286: foreach ($this->getAllVisibleItems() as $item) {
1287: if ($item->getParentItem()) {
1288: continue;
1289: }
1290:
1291: $children = $item->getChildren();
1292: if ($children && $item->isShipSeparately()) {
1293: foreach ($children as $child) {
1294: if ($child->getProduct()->getIsVirtual()) {
1295: $this->setVirtualItemsQty($this->getVirtualItemsQty() + $child->getQty()*$item->getQty());
1296: }
1297: }
1298: }
1299:
1300: if ($item->getProduct()->getIsVirtual()) {
1301: $this->setVirtualItemsQty($this->getVirtualItemsQty() + $item->getQty());
1302: }
1303: $this->setItemsCount($this->getItemsCount()+1);
1304: $this->setItemsQty((float) $this->getItemsQty()+$item->getQty());
1305: }
1306:
1307: $this->setData('trigger_recollect', 0);
1308: $this->_validateCouponCode();
1309:
1310: Mage::dispatchEvent($this->_eventPrefix . '_collect_totals_after', array($this->_eventObject => $this));
1311:
1312: $this->setTotalsCollectedFlag(true);
1313: return $this;
1314: }
1315:
1316: 1317: 1318: 1319: 1320: 1321:
1322: public function getTotals()
1323: {
1324: 1325: 1326: 1327:
1328: if ($this->isVirtual()) {
1329: return $this->getBillingAddress()->getTotals();
1330: }
1331:
1332: $shippingAddress = $this->getShippingAddress();
1333: $totals = $shippingAddress->getTotals();
1334:
1335: foreach ($this->getAddressesCollection() as $address) {
1336: if ($address->isDeleted() || $address === $shippingAddress) {
1337: continue;
1338: }
1339: foreach ($address->getTotals() as $code => $total) {
1340: if (isset($totals[$code])) {
1341: $totals[$code]->merge($total);
1342: } else {
1343: $totals[$code] = $total;
1344: }
1345: }
1346: }
1347:
1348: $sortedTotals = array();
1349: foreach ($this->getBillingAddress()->getTotalModels() as $total) {
1350:
1351: if (isset($totals[$total->getCode()])) {
1352: $sortedTotals[$total->getCode()] = $totals[$total->getCode()];
1353: }
1354: }
1355: return $sortedTotals;
1356: }
1357:
1358: public function addMessage($message, $index = 'error')
1359: {
1360: $messages = $this->getData('messages');
1361: if (is_null($messages)) {
1362: $messages = array();
1363: }
1364:
1365: if (isset($messages[$index])) {
1366: return $this;
1367: }
1368:
1369: if (is_string($message)) {
1370: $message = Mage::getSingleton('core/message')->error($message);
1371: }
1372:
1373: $messages[$index] = $message;
1374: $this->setData('messages', $messages);
1375: return $this;
1376: }
1377:
1378: 1379: 1380: 1381: 1382:
1383: public function getMessages()
1384: {
1385: $messages = $this->getData('messages');
1386: if (is_null($messages)) {
1387: $messages = array();
1388: $this->setData('messages', $messages);
1389: }
1390: return $messages;
1391: }
1392:
1393: 1394: 1395: 1396: 1397:
1398: public function getErrors()
1399: {
1400: $errors = array();
1401: foreach ($this->getMessages() as $message) {
1402:
1403: if ($message->getType() == Mage_Core_Model_Message::ERROR) {
1404: array_push($errors, $message);
1405: }
1406: }
1407: return $errors;
1408: }
1409:
1410: 1411: 1412: 1413: 1414: 1415:
1416: protected function _setHasError($flag)
1417: {
1418: return $this->setData('has_error', $flag);
1419: }
1420:
1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430:
1431: public function setHasError($flag)
1432: {
1433: if ($flag) {
1434: $this->addErrorInfo();
1435: } else {
1436: $this->_clearErrorInfo();
1437: }
1438: return $this;
1439: }
1440:
1441: 1442: 1443: 1444: 1445: 1446:
1447: protected function _clearErrorInfo()
1448: {
1449: $this->_errorInfoGroups = array();
1450: $this->_setHasError(false);
1451: return $this;
1452: }
1453:
1454: 1455: 1456: 1457: 1458: 1459: 1460: 1461: 1462: 1463: 1464:
1465: public function addErrorInfo($type = 'error', $origin = null, $code = null, $message = null, $additionalData = null)
1466: {
1467: if (!isset($this->_errorInfoGroups[$type])) {
1468: $this->_errorInfoGroups[$type] = Mage::getModel('sales/status_list');
1469: }
1470:
1471: $this->_errorInfoGroups[$type]->addItem($origin, $code, $message, $additionalData);
1472:
1473: if ($message !== null) {
1474: $this->addMessage($message, $type);
1475: }
1476: $this->_setHasError(true);
1477:
1478: return $this;
1479: }
1480:
1481: 1482: 1483: 1484: 1485: 1486: 1487: 1488: 1489:
1490: public function removeErrorInfosByParams($type = 'error', $params)
1491: {
1492: if ($type && !isset($this->_errorInfoGroups[$type])) {
1493: return $this;
1494: }
1495:
1496: $errorLists = array();
1497: if ($type) {
1498: $errorLists[] = $this->_errorInfoGroups[$type];
1499: } else {
1500: $errorLists = $this->_errorInfoGroups;
1501: }
1502:
1503: foreach ($errorLists as $type => $errorList) {
1504: $removedItems = $errorList->removeItemsByParams($params);
1505: foreach ($removedItems as $item) {
1506: if ($item['message'] !== null) {
1507: $this->removeMessageByText($type, $item['message']);
1508: }
1509: }
1510: }
1511:
1512: $errorsExist = false;
1513: foreach ($this->_errorInfoGroups as $errorListCheck) {
1514: if ($errorListCheck->getItems()) {
1515: $errorsExist = true;
1516: break;
1517: }
1518: }
1519: if (!$errorsExist) {
1520: $this->_setHasError(false);
1521: }
1522:
1523: return $this;
1524: }
1525:
1526: 1527: 1528: 1529: 1530: 1531: 1532:
1533: public function removeMessageByText($type = 'error', $text)
1534: {
1535: $messages = $this->getData('messages');
1536: if (is_null($messages)) {
1537: $messages = array();
1538: }
1539:
1540: if (!isset($messages[$type])) {
1541: return $this;
1542: }
1543:
1544: $message = $messages[$type];
1545: if ($message instanceof Mage_Core_Model_Message_Abstract) {
1546: $message = $message->getText();
1547: } else if (!is_string($message)) {
1548: return $this;
1549: }
1550: if ($message == $text) {
1551: unset($messages[$type]);
1552: $this->setData('messages', $messages);
1553: }
1554: return $this;
1555: }
1556:
1557: 1558: 1559: 1560: 1561:
1562: public function reserveOrderId()
1563: {
1564: if (!$this->getReservedOrderId()) {
1565: $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
1566: } else {
1567:
1568:
1569: if ($this->_getResource()->isOrderIncrementIdUsed($this->getReservedOrderId())) {
1570: $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
1571: }
1572: }
1573: return $this;
1574: }
1575:
1576: public function validateMinimumAmount($multishipping = false)
1577: {
1578: $storeId = $this->getStoreId();
1579: $minOrderActive = Mage::getStoreConfigFlag('sales/minimum_order/active', $storeId);
1580: $minOrderMulti = Mage::getStoreConfigFlag('sales/minimum_order/multi_address', $storeId);
1581: $minAmount = Mage::getStoreConfig('sales/minimum_order/amount', $storeId);
1582:
1583: if (!$minOrderActive) {
1584: return true;
1585: }
1586:
1587: $addresses = $this->getAllAddresses();
1588:
1589: if ($multishipping) {
1590: if ($minOrderMulti) {
1591: foreach ($addresses as $address) {
1592: foreach ($address->getQuote()->getItemsCollection() as $item) {
1593: $amount = $item->getBaseRowTotal() - $item->getBaseDiscountAmount();
1594: if ($amount < $minAmount) {
1595: return false;
1596: }
1597: }
1598: }
1599: } else {
1600: $baseTotal = 0;
1601: foreach ($addresses as $address) {
1602:
1603: $baseTotal += $address->getBaseSubtotalWithDiscount();
1604: }
1605: if ($baseTotal < $minAmount) {
1606: return false;
1607: }
1608: }
1609: } else {
1610: foreach ($addresses as $address) {
1611:
1612: if (!$address->validateMinimumAmount()) {
1613: return false;
1614: }
1615: }
1616: }
1617: return true;
1618: }
1619:
1620: 1621: 1622: 1623: 1624:
1625: public function isVirtual()
1626: {
1627: $isVirtual = true;
1628: $countItems = 0;
1629: foreach ($this->getItemsCollection() as $_item) {
1630:
1631: if ($_item->isDeleted() || $_item->getParentItemId()) {
1632: continue;
1633: }
1634: $countItems ++;
1635: if (!$_item->getProduct()->getIsVirtual()) {
1636: $isVirtual = false;
1637: break;
1638: }
1639: }
1640: return $countItems == 0 ? false : $isVirtual;
1641: }
1642:
1643: 1644: 1645: 1646: 1647:
1648: public function getIsVirtual()
1649: {
1650: return intval($this->isVirtual());
1651: }
1652:
1653: 1654: 1655: 1656: 1657:
1658: public function hasVirtualItems()
1659: {
1660: $hasVirtual = false;
1661: foreach ($this->getItemsCollection() as $_item) {
1662: if ($_item->getParentItemId()) {
1663: continue;
1664: }
1665: if ($_item->getProduct()->isVirtual()) {
1666: $hasVirtual = true;
1667: }
1668: }
1669: return $hasVirtual;
1670: }
1671:
1672: 1673: 1674: 1675: 1676: 1677:
1678: public function merge(Mage_Sales_Model_Quote $quote)
1679: {
1680: Mage::dispatchEvent(
1681: $this->_eventPrefix . '_merge_before',
1682: array(
1683: $this->_eventObject=>$this,
1684: 'source'=>$quote
1685: )
1686: );
1687:
1688: foreach ($quote->getAllVisibleItems() as $item) {
1689: $found = false;
1690: foreach ($this->getAllItems() as $quoteItem) {
1691: if ($quoteItem->compare($item)) {
1692: $quoteItem->setQty($quoteItem->getQty() + $item->getQty());
1693: $found = true;
1694: break;
1695: }
1696: }
1697:
1698: if (!$found) {
1699: $newItem = clone $item;
1700: $this->addItem($newItem);
1701: if ($item->getHasChildren()) {
1702: foreach ($item->getChildren() as $child) {
1703: $newChild = clone $child;
1704: $newChild->setParentItem($newItem);
1705: $this->addItem($newChild);
1706: }
1707: }
1708: }
1709: }
1710:
1711: 1712: 1713:
1714: if (!$this->getId()) {
1715: $this->getShippingAddress();
1716: $this->getBillingAddress();
1717: }
1718:
1719: if ($quote->getCouponCode()) {
1720: $this->setCouponCode($quote->getCouponCode());
1721: }
1722:
1723: Mage::dispatchEvent(
1724: $this->_eventPrefix . '_merge_after',
1725: array(
1726: $this->_eventObject=>$this,
1727: 'source'=>$quote
1728: )
1729: );
1730:
1731: return $this;
1732: }
1733:
1734: 1735: 1736: 1737: 1738:
1739: public function hasRecurringItems()
1740: {
1741: foreach ($this->getAllVisibleItems() as $item) {
1742: if ($item->getProduct() && $item->getProduct()->isRecurring()) {
1743: return true;
1744: }
1745: }
1746: return false;
1747: }
1748:
1749: 1750: 1751: 1752: 1753: 1754: 1755:
1756: public function hasNominalItems($countVirtual = true)
1757: {
1758: foreach ($this->getAllVisibleItems() as $item) {
1759: if ($item->isNominal()) {
1760: if ((!$countVirtual) && $item->getProduct()->isVirtual()) {
1761: continue;
1762: }
1763: return true;
1764: }
1765: }
1766: return false;
1767: }
1768:
1769: 1770: 1771: 1772: 1773:
1774: public function isNominal()
1775: {
1776: foreach ($this->getAllVisibleItems() as $item) {
1777: if (!$item->isNominal()) {
1778: return false;
1779: }
1780: }
1781: return true;
1782: }
1783:
1784: 1785: 1786: 1787: 1788:
1789: public function prepareRecurringPaymentProfiles()
1790: {
1791: if (!$this->getTotalsCollectedFlag()) {
1792:
1793: throw new Exception('Quote totals must be collected before this operation.');
1794: }
1795:
1796: $result = array();
1797: foreach ($this->getAllVisibleItems() as $item) {
1798: $product = $item->getProduct();
1799: if (is_object($product) && ($product->isRecurring())
1800: && $profile = Mage::getModel('sales/recurring_profile')->importProduct($product)
1801: ) {
1802: $profile->importQuote($this);
1803: $profile->importQuoteItem($item);
1804: $result[] = $profile;
1805: }
1806: }
1807: return $result;
1808: }
1809:
1810: protected function _validateCouponCode()
1811: {
1812: $code = $this->_getData('coupon_code');
1813: if (strlen($code)) {
1814: $addressHasCoupon = false;
1815: $addresses = $this->getAllAddresses();
1816: if (count($addresses)>0) {
1817: foreach ($addresses as $address) {
1818: if ($address->hasCouponCode()) {
1819: $addressHasCoupon = true;
1820: }
1821: }
1822: if (!$addressHasCoupon) {
1823: $this->setCouponCode('');
1824: }
1825: }
1826: }
1827: return $this;
1828: }
1829:
1830: 1831: 1832: 1833: 1834:
1835: protected function _afterLoad()
1836: {
1837:
1838: if (1 == $this->getData('trigger_recollect')) {
1839: $this->collectTotals()->save();
1840: }
1841: return parent::_afterLoad();
1842: }
1843:
1844: 1845: 1846:
1847: const CHECKOUT_METHOD_REGISTER = 'register';
1848: const CHECKOUT_METHOD_GUEST = 'guest';
1849: const CHECKOUT_METHOD_LOGIN_IN = 'login_in';
1850:
1851: 1852: 1853: 1854: 1855: 1856: 1857:
1858: public function getCheckoutMethod($originalMethod = false)
1859: {
1860: if ($this->getCustomerId() && !$originalMethod) {
1861: return self::CHECKOUT_METHOD_LOGIN_IN;
1862: }
1863: return $this->_getData('checkout_method');
1864: }
1865:
1866: 1867: 1868: 1869: 1870: 1871:
1872: public function isAllowedGuestCheckout()
1873: {
1874: return Mage::helper('checkout')->isAllowedGuestCheckout($this, $this->getStoreId());
1875: }
1876:
1877: 1878: 1879: 1880: 1881:
1882: public function preventSaving()
1883: {
1884: $this->_preventSaving = true;
1885: return $this;
1886: }
1887:
1888: 1889: 1890: 1891: 1892:
1893: public function save()
1894: {
1895: if ($this->_preventSaving) {
1896: return $this;
1897: }
1898: return parent::save();
1899: }
1900: }
1901: