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: class Mage_Sales_Model_Service_Order
31: {
32: 33: 34: 35: 36:
37: protected $_order;
38:
39: 40: 41: 42: 43:
44: protected $_convertor;
45:
46: 47: 48: 49: 50:
51: public function __construct(Mage_Sales_Model_Order $order)
52: {
53: $this->_order = $order;
54: $this->_convertor = Mage::getModel('sales/convert_order');
55: }
56:
57: 58: 59: 60: 61: 62:
63: public function setConvertor(Mage_Sales_Model_Convert_Order $convertor)
64: {
65: $this->_convertor = $convertor;
66: return $this;
67: }
68:
69: 70: 71: 72: 73:
74: public function getOrder()
75: {
76: return $this->_order;
77: }
78:
79: 80: 81: 82: 83: 84: 85:
86: public function prepareInvoice($qtys = array())
87: {
88: $invoice = $this->_convertor->toInvoice($this->_order);
89: $totalQty = 0;
90: foreach ($this->_order->getAllItems() as $orderItem) {
91: if (!$this->_canInvoiceItem($orderItem, array())) {
92: continue;
93: }
94: $item = $this->_convertor->itemToInvoiceItem($orderItem);
95: if ($orderItem->isDummy()) {
96: $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1;
97: } else if (!empty($qtys)) {
98: if (isset($qtys[$orderItem->getId()])) {
99: $qty = (float) $qtys[$orderItem->getId()];
100: }
101: } else {
102: $qty = $orderItem->getQtyToInvoice();
103: }
104: $totalQty += $qty;
105: $item->setQty($qty);
106: $invoice->addItem($item);
107: }
108: $invoice->setTotalQty($totalQty);
109: $invoice->collectTotals();
110: $this->_order->getInvoiceCollection()->addItem($invoice);
111: return $invoice;
112: }
113:
114: 115: 116: 117: 118: 119:
120: public function prepareShipment($qtys = array())
121: {
122: $totalQty = 0;
123: $shipment = $this->_convertor->toShipment($this->_order);
124: foreach ($this->_order->getAllItems() as $orderItem) {
125: if (!$this->_canShipItem($orderItem, $qtys)) {
126: continue;
127: }
128:
129: $item = $this->_convertor->itemToShipmentItem($orderItem);
130:
131: if ($orderItem->isDummy(true)) {
132: $qty = 0;
133: if (isset($qtys[$orderItem->getParentItemId()])) {
134: $productOptions = $orderItem->getProductOptions();
135: if (isset($productOptions['bundle_selection_attributes'])) {
136: $bundleSelectionAttributes = unserialize($productOptions['bundle_selection_attributes']);
137:
138: if ($bundleSelectionAttributes) {
139: $qty = $bundleSelectionAttributes['qty'] * $qtys[$orderItem->getParentItemId()];
140: $qty = min($qty, $orderItem->getSimpleQtyToShip());
141:
142: $item->setQty($qty);
143: $shipment->addItem($item);
144: continue;
145: } else {
146: $qty = 1;
147: }
148: }
149: } else {
150: $qty = 1;
151: }
152: } else {
153: if (isset($qtys[$orderItem->getId()])) {
154: $qty = min($qtys[$orderItem->getId()], $orderItem->getQtyToShip());
155: } elseif (!count($qtys)) {
156: $qty = $orderItem->getQtyToShip();
157: } else {
158: continue;
159: }
160: }
161: $totalQty += $qty;
162: $item->setQty($qty);
163: $shipment->addItem($item);
164: }
165:
166: $shipment->setTotalQty($totalQty);
167: return $shipment;
168: }
169:
170: 171: 172: 173: 174: 175:
176: public function prepareCreditmemo($data = array())
177: {
178: $totalQty = 0;
179: $creditmemo = $this->_convertor->toCreditmemo($this->_order);
180: $qtys = isset($data['qtys']) ? $data['qtys'] : array();
181:
182: foreach ($this->_order->getAllItems() as $orderItem) {
183: if (!$this->_canRefundItem($orderItem, $qtys)) {
184: continue;
185: }
186:
187: $item = $this->_convertor->itemToCreditmemoItem($orderItem);
188: if ($orderItem->isDummy()) {
189: $qty = 1;
190: $orderItem->setLockedDoShip(true);
191: } else {
192: if (isset($qtys[$orderItem->getId()])) {
193: $qty = (float) $qtys[$orderItem->getId()];
194: } elseif (!count($qtys)) {
195: $qty = $orderItem->getQtyToRefund();
196: } else {
197: continue;
198: }
199: }
200: $totalQty += $qty;
201: $item->setQty($qty);
202: $creditmemo->addItem($item);
203: }
204: $creditmemo->setTotalQty($totalQty);
205:
206: $this->_initCreditmemoData($creditmemo, $data);
207:
208: $creditmemo->collectTotals();
209: return $creditmemo;
210: }
211:
212: 213: 214: 215: 216: 217:
218: public function prepareInvoiceCreditmemo($invoice, $data = array())
219: {
220: $totalQty = 0;
221: $qtys = isset($data['qtys']) ? $data['qtys'] : array();
222: $creditmemo = $this->_convertor->toCreditmemo($this->_order);
223: $creditmemo->setInvoice($invoice);
224:
225: $invoiceQtysRefunded = array();
226: foreach($invoice->getOrder()->getCreditmemosCollection() as $createdCreditmemo) {
227: if ($createdCreditmemo->getState() != Mage_Sales_Model_Order_Creditmemo::STATE_CANCELED
228: && $createdCreditmemo->getInvoiceId() == $invoice->getId()) {
229: foreach($createdCreditmemo->getAllItems() as $createdCreditmemoItem) {
230: $orderItemId = $createdCreditmemoItem->getOrderItem()->getId();
231: if (isset($invoiceQtysRefunded[$orderItemId])) {
232: $invoiceQtysRefunded[$orderItemId] += $createdCreditmemoItem->getQty();
233: } else {
234: $invoiceQtysRefunded[$orderItemId] = $createdCreditmemoItem->getQty();
235: }
236: }
237: }
238: }
239:
240: $invoiceQtysRefundLimits = array();
241: foreach($invoice->getAllItems() as $invoiceItem) {
242: $invoiceQtyCanBeRefunded = $invoiceItem->getQty();
243: $orderItemId = $invoiceItem->getOrderItem()->getId();
244: if (isset($invoiceQtysRefunded[$orderItemId])) {
245: $invoiceQtyCanBeRefunded = $invoiceQtyCanBeRefunded - $invoiceQtysRefunded[$orderItemId];
246: }
247: $invoiceQtysRefundLimits[$orderItemId] = $invoiceQtyCanBeRefunded;
248: }
249:
250:
251: foreach ($invoice->getAllItems() as $invoiceItem) {
252: $orderItem = $invoiceItem->getOrderItem();
253:
254: if (!$this->_canRefundItem($orderItem, $qtys, $invoiceQtysRefundLimits)) {
255: continue;
256: }
257:
258: $item = $this->_convertor->itemToCreditmemoItem($orderItem);
259: if ($orderItem->isDummy()) {
260: $qty = 1;
261: } else {
262: if (isset($qtys[$orderItem->getId()])) {
263: $qty = (float) $qtys[$orderItem->getId()];
264: } elseif (!count($qtys)) {
265: $qty = $orderItem->getQtyToRefund();
266: } else {
267: continue;
268: }
269: if (isset($invoiceQtysRefundLimits[$orderItem->getId()])) {
270: $qty = min($qty, $invoiceQtysRefundLimits[$orderItem->getId()]);
271: }
272: }
273: $qty = min($qty, $invoiceItem->getQty());
274: $totalQty += $qty;
275: $item->setQty($qty);
276: $creditmemo->addItem($item);
277: }
278: $creditmemo->setTotalQty($totalQty);
279:
280: $this->_initCreditmemoData($creditmemo, $data);
281: if (!isset($data['shipping_amount'])) {
282: $order = $invoice->getOrder();
283: $isShippingInclTax = Mage::getSingleton('tax/config')->displaySalesShippingInclTax($order->getStoreId());
284: if ($isShippingInclTax) {
285: $baseAllowedAmount = $order->getBaseShippingInclTax()
286: - $order->getBaseShippingRefunded()
287: - $order->getBaseShippingTaxRefunded();
288: } else {
289: $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded();
290: $baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount());
291: }
292: $creditmemo->setBaseShippingAmount($baseAllowedAmount);
293: }
294:
295: $creditmemo->collectTotals();
296: return $creditmemo;
297: }
298:
299: 300: 301: 302: 303: 304:
305: protected function _initCreditmemoData($creditmemo, $data)
306: {
307: if (isset($data['shipping_amount'])) {
308: $creditmemo->setBaseShippingAmount((float)$data['shipping_amount']);
309: }
310:
311: if (isset($data['adjustment_positive'])) {
312: $creditmemo->setAdjustmentPositive($data['adjustment_positive']);
313: }
314:
315: if (isset($data['adjustment_negative'])) {
316: $creditmemo->setAdjustmentNegative($data['adjustment_negative']);
317: }
318: }
319:
320: 321: 322: 323: 324: 325: 326: 327:
328: protected function _canInvoiceItem($item, $qtys=array())
329: {
330: if ($item->getLockedDoInvoice()) {
331: return false;
332: }
333: if ($item->isDummy()) {
334: if ($item->getHasChildren()) {
335: foreach ($item->getChildrenItems() as $child) {
336: if (empty($qtys)) {
337: if ($child->getQtyToInvoice() > 0) {
338: return true;
339: }
340: } else {
341: if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
342: return true;
343: }
344: }
345: }
346: return false;
347: } else if($item->getParentItem()) {
348: $parent = $item->getParentItem();
349: if (empty($qtys)) {
350: return $parent->getQtyToInvoice() > 0;
351: } else {
352: return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
353: }
354: }
355: } else {
356: return $item->getQtyToInvoice() > 0;
357: }
358: }
359:
360: 361: 362: 363: 364: 365: 366: 367:
368: protected function _canShipItem($item, $qtys=array())
369: {
370: if ($item->getIsVirtual() || $item->getLockedDoShip()) {
371: return false;
372: }
373: if ($item->isDummy(true)) {
374: if ($item->getHasChildren()) {
375: if ($item->isShipSeparately()) {
376: return true;
377: }
378: foreach ($item->getChildrenItems() as $child) {
379: if ($child->getIsVirtual()) {
380: continue;
381: }
382: if (empty($qtys)) {
383: if ($child->getQtyToShip() > 0) {
384: return true;
385: }
386: } else {
387: if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
388: return true;
389: }
390: }
391: }
392: return false;
393: } else if($item->getParentItem()) {
394: $parent = $item->getParentItem();
395: if (empty($qtys)) {
396: return $parent->getQtyToShip() > 0;
397: } else {
398: return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
399: }
400: }
401: } else {
402: return $item->getQtyToShip()>0;
403: }
404: }
405:
406: 407: 408: 409: 410: 411: 412: 413:
414: protected function _canRefundItem($item, $qtys=array(), $invoiceQtysRefundLimits=array())
415: {
416: if ($item->isDummy()) {
417: if ($item->getHasChildren()) {
418: foreach ($item->getChildrenItems() as $child) {
419: if (empty($qtys)) {
420: if ($this->_canRefundNoDummyItem($child, $invoiceQtysRefundLimits)) {
421: return true;
422: }
423: } else {
424: if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) {
425: return true;
426: }
427: }
428: }
429: return false;
430: } else if($item->getParentItem()) {
431: $parent = $item->getParentItem();
432: if (empty($qtys)) {
433: return $this->_canRefundNoDummyItem($parent, $invoiceQtysRefundLimits);
434: } else {
435: return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0;
436: }
437: }
438: } else {
439: return $this->_canRefundNoDummyItem($item, $invoiceQtysRefundLimits);
440: }
441: }
442:
443: 444: 445: 446: 447: 448: 449:
450: protected function _canRefundNoDummyItem($item, $invoiceQtysRefundLimits=array())
451: {
452: if ($item->getQtyToRefund() < 0) {
453: return false;
454: }
455:
456: if (isset($invoiceQtysRefundLimits[$item->getId()])) {
457: return $invoiceQtysRefundLimits[$item->getId()] > 0;
458: }
459:
460: return true;
461: }
462:
463: }
464: