PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Sales/Model/Service/Order.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 443 lines | 296 code | 33 blank | 114 comment | 80 complexity | fd2fbf2c4a5ab992321dfed882a83e66 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Sales
  23. * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Quote submit service model
  28. */
  29. class Mage_Sales_Model_Service_Order
  30. {
  31. /**
  32. * Order object
  33. *
  34. * @var Mage_Sales_Model_Order
  35. */
  36. protected $_order;
  37. /**
  38. * Quote convert object
  39. *
  40. * @var Mage_Sales_Model_Convert_Order
  41. */
  42. protected $_convertor;
  43. /**
  44. * Class constructor
  45. *
  46. * @param Mage_Sales_Model_Order $order
  47. */
  48. public function __construct(Mage_Sales_Model_Order $order)
  49. {
  50. $this->_order = $order;
  51. $this->_convertor = Mage::getModel('sales/convert_order');
  52. }
  53. /**
  54. * Quote convertor declaration
  55. *
  56. * @param Mage_Sales_Model_Convert_Order $convertor
  57. * @return Mage_Sales_Model_Service_Order
  58. */
  59. public function setConvertor(Mage_Sales_Model_Convert_Order $convertor)
  60. {
  61. $this->_convertor = $convertor;
  62. return $this;
  63. }
  64. /**
  65. * Get assigned order object
  66. *
  67. * @return Mage_Sales_Model_Order
  68. */
  69. public function getOrder()
  70. {
  71. return $this->_order;
  72. }
  73. /**
  74. * Prepare order invoice based on order data and requested items qtys
  75. *
  76. * @param array $data
  77. * @return Mage_Sales_Model_Order_Invoice
  78. */
  79. public function prepareInvoice($qtys = array())
  80. {
  81. $invoice = $this->_convertor->toInvoice($this->_order);
  82. $totalQty = 0;
  83. foreach ($this->_order->getAllItems() as $orderItem) {
  84. if (!$this->_canInvoiceItem($orderItem, $qtys)) {
  85. continue;
  86. }
  87. $item = $this->_convertor->itemToInvoiceItem($orderItem);
  88. if ($orderItem->isDummy()) {
  89. $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1;
  90. } else {
  91. if (isset($qtys[$orderItem->getId()])) {
  92. $qty = (float) $qtys[$orderItem->getId()];
  93. } elseif (!count($qtys)) {
  94. $qty = $orderItem->getQtyToInvoice();
  95. } else {
  96. continue;
  97. }
  98. }
  99. $totalQty += $qty;
  100. $item->setQty($qty);
  101. $invoice->addItem($item);
  102. }
  103. $invoice->setTotalQty($totalQty);
  104. $invoice->collectTotals();
  105. $this->_order->getInvoiceCollection()->addItem($invoice);
  106. return $invoice;
  107. }
  108. /**
  109. * Prepare order shipment based on order items and requested items qty
  110. *
  111. * @param array $data
  112. * @return Mage_Sales_Model_Order_Shipment
  113. */
  114. public function prepareShipment($qtys = array())
  115. {
  116. $totalQty = 0;
  117. $shipment = $this->_convertor->toShipment($this->_order);
  118. foreach ($this->_order->getAllItems() as $orderItem) {
  119. if (!$this->_canShipItem($orderItem, $qtys)) {
  120. continue;
  121. }
  122. $item = $this->_convertor->itemToShipmentItem($orderItem);
  123. if ($orderItem->isDummy(true)) {
  124. $qty = 1;
  125. } else {
  126. if (isset($qtys[$orderItem->getId()])) {
  127. $qty = min($qtys[$orderItem->getId()], $orderItem->getQtyToShip());
  128. } elseif (!count($qtys)) {
  129. $qty = $orderItem->getQtyToShip();
  130. } else {
  131. continue;
  132. }
  133. }
  134. $totalQty += $qty;
  135. $item->setQty($qty);
  136. $shipment->addItem($item);
  137. }
  138. $shipment->setTotalQty($totalQty);
  139. return $shipment;
  140. }
  141. /**
  142. * Prepare order creditmemo based on order items and requested params
  143. *
  144. * @param array $data
  145. * @return Mage_Sales_Model_Order_Creditmemo
  146. */
  147. public function prepareCreditmemo($data = array())
  148. {
  149. $totalQty = 0;
  150. $creditmemo = $this->_convertor->toCreditmemo($this->_order);
  151. $qtys = isset($data['qtys']) ? $data['qtys'] : array();
  152. foreach ($this->_order->getAllItems() as $orderItem) {
  153. if (!$this->_canRefundItem($orderItem, $qtys)) {
  154. continue;
  155. }
  156. $item = $this->_convertor->itemToCreditmemoItem($orderItem);
  157. if ($orderItem->isDummy()) {
  158. $qty = 1;
  159. } else {
  160. if (isset($qtys[$orderItem->getId()])) {
  161. $qty = (float) $qtys[$orderItem->getId()];
  162. } elseif (!count($qtys)) {
  163. $qty = $orderItem->getQtyToRefund();
  164. } else {
  165. continue;
  166. }
  167. }
  168. $totalQty += $qty;
  169. $item->setQty($qty);
  170. $creditmemo->addItem($item);
  171. }
  172. $creditmemo->setTotalQty($totalQty);
  173. $this->_initCreditmemoData($creditmemo, $data);
  174. $creditmemo->collectTotals();
  175. return $creditmemo;
  176. }
  177. /**
  178. * Prepare order creditmemo based on invoice items and requested requested params
  179. *
  180. * @param array $data
  181. * @return Mage_Sales_Model_Order_Creditmemo
  182. */
  183. public function prepareInvoiceCreditmemo($invoice, $data = array())
  184. {
  185. $totalQty = 0;
  186. $qtys = isset($data['qtys']) ? $data['qtys'] : array();
  187. $creditmemo = $this->_convertor->toCreditmemo($this->_order);
  188. $creditmemo->setInvoice($invoice);
  189. $invoiceQtysRefunded = array();
  190. foreach($invoice->getOrder()->getCreditmemosCollection() as $createdCreditmemo) {
  191. if ($createdCreditmemo->getState() != Mage_Sales_Model_Order_Creditmemo::STATE_CANCELED
  192. && $createdCreditmemo->getInvoiceId() == $invoice->getId()) {
  193. foreach($createdCreditmemo->getAllItems() as $createdCreditmemoItem) {
  194. $orderItemId = $createdCreditmemoItem->getOrderItem()->getId();
  195. if (isset($invoiceQtysRefunded[$orderItemId])) {
  196. $invoiceQtysRefunded[$orderItemId] += $createdCreditmemoItem->getQty();
  197. } else {
  198. $invoiceQtysRefunded[$orderItemId] = $createdCreditmemoItem->getQty();
  199. }
  200. }
  201. }
  202. }
  203. $invoiceQtysRefundLimits = array();
  204. foreach($invoice->getAllItems() as $invoiceItem) {
  205. $invoiceQtyCanBeRefunded = $invoiceItem->getQty();
  206. $orderItemId = $invoiceItem->getOrderItem()->getId();
  207. if (isset($invoiceQtysRefunded[$orderItemId])) {
  208. $invoiceQtyCanBeRefunded = $invoiceQtyCanBeRefunded - $invoiceQtysRefunded[$orderItemId];
  209. }
  210. $invoiceQtysRefundLimits[$orderItemId] = $invoiceQtyCanBeRefunded;
  211. }
  212. foreach ($invoice->getAllItems() as $invoiceItem) {
  213. $orderItem = $invoiceItem->getOrderItem();
  214. if (!$this->_canRefundItem($orderItem, $qtys, $invoiceQtysRefundLimits)) {
  215. continue;
  216. }
  217. $item = $this->_convertor->itemToCreditmemoItem($orderItem);
  218. if ($orderItem->isDummy()) {
  219. $qty = 1;
  220. } else {
  221. if (isset($qtys[$orderItem->getId()])) {
  222. $qty = (float) $qtys[$orderItem->getId()];
  223. } elseif (!count($qtys)) {
  224. $qty = $orderItem->getQtyToRefund();
  225. } else {
  226. continue;
  227. }
  228. if (isset($invoiceQtysRefundLimits[$orderItem->getId()])) {
  229. $qty = min($qty, $invoiceQtysRefundLimits[$orderItem->getId()]);
  230. }
  231. }
  232. $qty = min($qty, $invoiceItem->getQty());
  233. $totalQty += $qty;
  234. $item->setQty($qty);
  235. $creditmemo->addItem($item);
  236. }
  237. $creditmemo->setTotalQty($totalQty);
  238. $this->_initCreditmemoData($creditmemo, $data);
  239. if (!isset($data['shipping_amount'])) {
  240. $order = $invoice->getOrder();
  241. $isShippingInclTax = Mage::getSingleton('tax/config')->displaySalesShippingInclTax($order->getStoreId());
  242. if ($isShippingInclTax) {
  243. $baseAllowedAmount = $order->getBaseShippingInclTax()
  244. - $order->getBaseShippingRefunded()
  245. - $order->getBaseShippingTaxRefunded();
  246. } else {
  247. $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded();
  248. $baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount());
  249. }
  250. $creditmemo->setBaseShippingAmount($baseAllowedAmount);
  251. }
  252. $creditmemo->collectTotals();
  253. return $creditmemo;
  254. }
  255. /**
  256. * Initialize creditmemo state based on requested parameters
  257. *
  258. * @param Mage_Sales_Model_Order_Creditmemo $creditmemo
  259. * @param array $data
  260. */
  261. protected function _initCreditmemoData($creditmemo, $data)
  262. {
  263. if (isset($data['shipping_amount'])) {
  264. $creditmemo->setBaseShippingAmount((float)$data['shipping_amount']);
  265. }
  266. if (isset($data['adjustment_positive'])) {
  267. $creditmemo->setAdjustmentPositive($data['adjustment_positive']);
  268. }
  269. if (isset($data['adjustment_negative'])) {
  270. $creditmemo->setAdjustmentNegative($data['adjustment_negative']);
  271. }
  272. }
  273. /**
  274. * Check if order item can be invoiced. Dummy item can be invoiced or with his childrens or
  275. * with parent item which is included to invoice
  276. *
  277. * @param Mage_Sales_Model_Order_Item $item
  278. * @param array $qtys
  279. * @return bool
  280. */
  281. protected function _canInvoiceItem($item, $qtys=array())
  282. {
  283. if ($item->getLockedDoInvoice()) {
  284. return false;
  285. }
  286. if ($item->isDummy()) {
  287. if ($item->getHasChildren()) {
  288. foreach ($item->getChildrenItems() as $child) {
  289. if (empty($qtys)) {
  290. if ($child->getQtyToInvoice() > 0) {
  291. return true;
  292. }
  293. } else {
  294. if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
  295. return true;
  296. }
  297. }
  298. }
  299. return false;
  300. } else if($item->getParentItem()) {
  301. $parent = $item->getParentItem();
  302. if (empty($qtys)) {
  303. return $parent->getQtyToInvoice() > 0;
  304. } else {
  305. return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
  306. }
  307. }
  308. } else {
  309. return $item->getQtyToInvoice() > 0;
  310. }
  311. }
  312. /**
  313. * Check if order item can be shiped. Dummy item can be shiped or with his childrens or
  314. * with parent item which is included to shipment
  315. *
  316. * @param Mage_Sales_Model_Order_Item $item
  317. * @param array $qtys
  318. * @return bool
  319. */
  320. protected function _canShipItem($item, $qtys=array())
  321. {
  322. if ($item->getIsVirtual() || $item->getLockedDoShip()) {
  323. return false;
  324. }
  325. if ($item->isDummy(true)) {
  326. if ($item->getHasChildren()) {
  327. if ($item->isShipSeparately()) {
  328. return true;
  329. }
  330. foreach ($item->getChildrenItems() as $child) {
  331. if ($child->getIsVirtual()) {
  332. continue;
  333. }
  334. if (empty($qtys)) {
  335. if ($child->getQtyToShip() > 0) {
  336. return true;
  337. }
  338. } else {
  339. if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
  340. return true;
  341. }
  342. }
  343. }
  344. return false;
  345. } else if($item->getParentItem()) {
  346. $parent = $item->getParentItem();
  347. if (empty($qtys)) {
  348. return $parent->getQtyToShip() > 0;
  349. } else {
  350. return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
  351. }
  352. }
  353. } else {
  354. return $item->getQtyToShip()>0;
  355. }
  356. }
  357. /**
  358. * Check if order item can be refunded
  359. *
  360. * @param Mage_Sales_Model_Order_Item $item
  361. * @param array $qtys
  362. * @param array $invoiceQtysRefundLimits
  363. * @return bool
  364. */
  365. protected function _canRefundItem($item, $qtys=array(), $invoiceQtysRefundLimits=array())
  366. {
  367. if ($item->isDummy()) {
  368. if ($item->getHasChildren()) {
  369. foreach ($item->getChildrenItems() as $child) {
  370. if (empty($qtys)) {
  371. if ($this->_canRefundNoDummyItem($child, $invoiceQtysRefundLimits)) {
  372. return true;
  373. }
  374. } else {
  375. if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
  376. return true;
  377. }
  378. }
  379. }
  380. return false;
  381. } else if($item->getParentItem()) {
  382. $parent = $item->getParentItem();
  383. if (empty($qtys)) {
  384. return $this->_canRefundNoDummyItem($parent, $invoiceQtysRefundLimits);
  385. } else {
  386. return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
  387. }
  388. }
  389. } else {
  390. return $this->_canRefundNoDummyItem($item, $invoiceQtysRefundLimits);
  391. }
  392. }
  393. /**
  394. * Check if no dummy order item can be refunded
  395. *
  396. * @param Mage_Sales_Model_Order_Item $item
  397. * @param array $invoiceQtysRefundLimits
  398. * @return bool
  399. */
  400. protected function _canRefundNoDummyItem($item, $invoiceQtysRefundLimits=array())
  401. {
  402. if ($item->getQtyToRefund() < 0) {
  403. return false;
  404. }
  405. if (isset($invoiceQtysRefundLimits[$item->getId()])) {
  406. return $invoiceQtysRefundLimits[$item->getId()] > 0;
  407. }
  408. return true;
  409. }
  410. }