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: class Mage_Adminhtml_Sales_Order_ShipmentController extends Mage_Adminhtml_Controller_Sales_Shipment
35: {
36: 37: 38:
39: protected function _getItemQtys()
40: {
41: $data = $this->getRequest()->getParam('shipment');
42: if (isset($data['items'])) {
43: $qtys = $data['items'];
44: } else {
45: $qtys = array();
46: }
47: return $qtys;
48: }
49:
50: 51: 52: 53: 54:
55: protected function _initShipment()
56: {
57: $this->_title($this->__('Sales'))->_title($this->__('Shipments'));
58:
59: $shipment = false;
60: $shipmentId = $this->getRequest()->getParam('shipment_id');
61: $orderId = $this->getRequest()->getParam('order_id');
62: if ($shipmentId) {
63: $shipment = Mage::getModel('sales/order_shipment')->load($shipmentId);
64: } elseif ($orderId) {
65: $order = Mage::getModel('sales/order')->load($orderId);
66:
67: 68: 69:
70: if (!$order->getId()) {
71: $this->_getSession()->addError($this->__('The order no longer exists.'));
72: return false;
73: }
74: 75: 76:
77: if ($order->getForcedDoShipmentWithInvoice()) {
78: $this->_getSession()->addError($this->__('Cannot do shipment for the order separately from invoice.'));
79: return false;
80: }
81: 82: 83:
84: if (!$order->canShip()) {
85: $this->_getSession()->addError($this->__('Cannot do shipment for the order.'));
86: return false;
87: }
88: $savedQtys = $this->_getItemQtys();
89: $shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($savedQtys);
90:
91: $tracks = $this->getRequest()->getPost('tracking');
92: if ($tracks) {
93: foreach ($tracks as $data) {
94: if (empty($data['number'])) {
95: Mage::throwException($this->__('Tracking number cannot be empty.'));
96: }
97: $track = Mage::getModel('sales/order_shipment_track')
98: ->addData($data);
99: $shipment->addTrack($track);
100: }
101: }
102: }
103:
104: Mage::register('current_shipment', $shipment);
105: return $shipment;
106: }
107:
108: 109: 110: 111: 112: 113:
114: protected function _saveShipment($shipment)
115: {
116: $shipment->getOrder()->setIsInProcess(true);
117: $transactionSave = Mage::getModel('core/resource_transaction')
118: ->addObject($shipment)
119: ->addObject($shipment->getOrder())
120: ->save();
121:
122: return $this;
123: }
124:
125: 126: 127:
128: public function viewAction()
129: {
130: if ($this->_initShipment()) {
131: $this->_title($this->__('View Shipment'));
132:
133: $this->loadLayout();
134: $this->getLayout()->getBlock('sales_shipment_view')
135: ->updateBackButtonUrl($this->getRequest()->getParam('come_from'));
136: $this->_setActiveMenu('sales/order')
137: ->renderLayout();
138: } else {
139: $this->_forward('noRoute');
140: }
141: }
142:
143: 144: 145:
146: public function startAction()
147: {
148: 149: 150:
151: $this->_redirect('*/*/new', array('order_id'=>$this->getRequest()->getParam('order_id')));
152: }
153:
154: 155: 156:
157: public function newAction()
158: {
159: if ($shipment = $this->_initShipment()) {
160: $this->_title($this->__('New Shipment'));
161:
162: $comment = Mage::getSingleton('adminhtml/session')->getCommentText(true);
163: if ($comment) {
164: $shipment->setCommentText($comment);
165: }
166:
167: $this->loadLayout()
168: ->_setActiveMenu('sales/order')
169: ->renderLayout();
170: } else {
171: $this->_redirect('*/sales_order/view', array('order_id'=>$this->getRequest()->getParam('order_id')));
172: }
173: }
174:
175: 176: 177: 178: 179: 180:
181: public function saveAction()
182: {
183: $data = $this->getRequest()->getPost('shipment');
184: if (!empty($data['comment_text'])) {
185: Mage::getSingleton('adminhtml/session')->setCommentText($data['comment_text']);
186: }
187:
188: try {
189: $shipment = $this->_initShipment();
190: if (!$shipment) {
191: $this->_forward('noRoute');
192: return;
193: }
194:
195: $shipment->register();
196: $comment = '';
197: if (!empty($data['comment_text'])) {
198: $shipment->addComment(
199: $data['comment_text'],
200: isset($data['comment_customer_notify']),
201: isset($data['is_visible_on_front'])
202: );
203: if (isset($data['comment_customer_notify'])) {
204: $comment = $data['comment_text'];
205: }
206: }
207:
208: if (!empty($data['send_email'])) {
209: $shipment->setEmailSent(true);
210: }
211:
212: $shipment->getOrder()->setCustomerNoteNotify(!empty($data['send_email']));
213: $responseAjax = new Varien_Object();
214: $isNeedCreateLabel = isset($data['create_shipping_label']) && $data['create_shipping_label'];
215:
216: if ($isNeedCreateLabel && $this->_createShippingLabel($shipment)) {
217: $responseAjax->setOk(true);
218: }
219:
220: $this->_saveShipment($shipment);
221:
222: $shipment->sendEmail(!empty($data['send_email']), $comment);
223:
224: $shipmentCreatedMessage = $this->__('The shipment has been created.');
225: $labelCreatedMessage = $this->__('The shipping label has been created.');
226:
227: $this->_getSession()->addSuccess($isNeedCreateLabel ? $shipmentCreatedMessage . ' ' . $labelCreatedMessage
228: : $shipmentCreatedMessage);
229: Mage::getSingleton('adminhtml/session')->getCommentText(true);
230: } catch (Mage_Core_Exception $e) {
231: if ($isNeedCreateLabel) {
232: $responseAjax->setError(true);
233: $responseAjax->setMessage($e->getMessage());
234: } else {
235: $this->_getSession()->addError($e->getMessage());
236: $this->_redirect('*/*/new', array('order_id' => $this->getRequest()->getParam('order_id')));
237: }
238: } catch (Exception $e) {
239: Mage::logException($e);
240: if ($isNeedCreateLabel) {
241: $responseAjax->setError(true);
242: $responseAjax->setMessage(
243: Mage::helper('sales')->__('An error occurred while creating shipping label.'));
244: } else {
245: $this->_getSession()->addError($this->__('Cannot save shipment.'));
246: $this->_redirect('*/*/new', array('order_id' => $this->getRequest()->getParam('order_id')));
247: }
248:
249: }
250: if ($isNeedCreateLabel) {
251: $this->getResponse()->setBody($responseAjax->toJson());
252: } else {
253: $this->_redirect('*/sales_order/view', array('order_id' => $shipment->getOrderId()));
254: }
255: }
256:
257: 258: 259:
260: public function emailAction()
261: {
262: try {
263: $shipment = $this->_initShipment();
264: if ($shipment) {
265: $shipment->sendEmail(true)
266: ->setEmailSent(true)
267: ->save();
268: $historyItem = Mage::getResourceModel('sales/order_status_history_collection')
269: ->getUnnotifiedForInstance($shipment, Mage_Sales_Model_Order_Shipment::HISTORY_ENTITY_NAME);
270: if ($historyItem) {
271: $historyItem->setIsCustomerNotified(1);
272: $historyItem->save();
273: }
274: $this->_getSession()->addSuccess($this->__('The shipment has been sent.'));
275: }
276: } catch (Mage_Core_Exception $e) {
277: $this->_getSession()->addError($e->getMessage());
278: } catch (Exception $e) {
279: $this->_getSession()->addError($this->__('Cannot send shipment information.'));
280: }
281: $this->_redirect('*/*/view', array(
282: 'shipment_id' => $this->getRequest()->getParam('shipment_id')
283: ));
284: }
285:
286: 287: 288:
289: public function addTrackAction()
290: {
291: try {
292: $carrier = $this->getRequest()->getPost('carrier');
293: $number = $this->getRequest()->getPost('number');
294: $title = $this->getRequest()->getPost('title');
295: if (empty($carrier)) {
296: Mage::throwException($this->__('The carrier needs to be specified.'));
297: }
298: if (empty($number)) {
299: Mage::throwException($this->__('Tracking number cannot be empty.'));
300: }
301: $shipment = $this->_initShipment();
302: if ($shipment) {
303: $track = Mage::getModel('sales/order_shipment_track')
304: ->setNumber($number)
305: ->setCarrierCode($carrier)
306: ->setTitle($title);
307: $shipment->addTrack($track)
308: ->save();
309:
310: $this->loadLayout();
311: $response = $this->getLayout()->getBlock('shipment_tracking')->toHtml();
312: } else {
313: $response = array(
314: 'error' => true,
315: 'message' => $this->__('Cannot initialize shipment for adding tracking number.'),
316: );
317: }
318: } catch (Mage_Core_Exception $e) {
319: $response = array(
320: 'error' => true,
321: 'message' => $e->getMessage(),
322: );
323: } catch (Exception $e) {
324: $response = array(
325: 'error' => true,
326: 'message' => $this->__('Cannot add tracking number.'),
327: );
328: }
329: if (is_array($response)) {
330: $response = Mage::helper('core')->jsonEncode($response);
331: }
332: $this->getResponse()->setBody($response);
333: }
334:
335: 336: 337:
338: public function removeTrackAction()
339: {
340: $trackId = $this->getRequest()->getParam('track_id');
341: $shipmentId = $this->getRequest()->getParam('shipment_id');
342: $track = Mage::getModel('sales/order_shipment_track')->load($trackId);
343: if ($track->getId()) {
344: try {
345: if ($this->_initShipment()) {
346: $track->delete();
347:
348: $this->loadLayout();
349: $response = $this->getLayout()->getBlock('shipment_tracking')->toHtml();
350: } else {
351: $response = array(
352: 'error' => true,
353: 'message' => $this->__('Cannot initialize shipment for delete tracking number.'),
354: );
355: }
356: } catch (Exception $e) {
357: $response = array(
358: 'error' => true,
359: 'message' => $this->__('Cannot delete tracking number.'),
360: );
361: }
362: } else {
363: $response = array(
364: 'error' => true,
365: 'message' => $this->__('Cannot load track with retrieving identifier.'),
366: );
367: }
368: if (is_array($response)) {
369: $response = Mage::helper('core')->jsonEncode($response);
370: }
371: $this->getResponse()->setBody($response);
372: }
373:
374: 375: 376:
377: public function viewTrackAction()
378: {
379: $trackId = $this->getRequest()->getParam('track_id');
380: $shipmentId = $this->getRequest()->getParam('shipment_id');
381: $track = Mage::getModel('sales/order_shipment_track')->load($trackId);
382: if ($track->getId()) {
383: try {
384: $response = $track->getNumberDetail();
385: } catch (Exception $e) {
386: $response = array(
387: 'error' => true,
388: 'message' => $this->__('Cannot retrieve tracking number detail.'),
389: );
390: }
391: } else {
392: $response = array(
393: 'error' => true,
394: 'message' => $this->__('Cannot load track with retrieving identifier.'),
395: );
396: }
397:
398: if ( is_object($response)){
399: $className = Mage::getConfig()->getBlockClassName('adminhtml/template');
400: $block = new $className();
401: $block->setType('adminhtml/template')
402: ->setIsAnonymous(true)
403: ->setTemplate('sales/order/shipment/tracking/info.phtml');
404:
405: $block->setTrackingInfo($response);
406:
407: $this->getResponse()->setBody($block->toHtml());
408: } else {
409: if (is_array($response)) {
410: $response = Mage::helper('core')->jsonEncode($response);
411: }
412:
413: $this->getResponse()->setBody($response);
414: }
415: }
416:
417: 418: 419:
420: public function ()
421: {
422: try {
423: $this->getRequest()->setParam(
424: 'shipment_id',
425: $this->getRequest()->getParam('id')
426: );
427: $data = $this->getRequest()->getPost('comment');
428: if (empty($data['comment'])) {
429: Mage::throwException($this->__('Comment text field cannot be empty.'));
430: }
431: $shipment = $this->_initShipment();
432: $shipment->addComment(
433: $data['comment'],
434: isset($data['is_customer_notified']),
435: isset($data['is_visible_on_front'])
436: );
437: $shipment->sendUpdateEmail(!empty($data['is_customer_notified']), $data['comment']);
438: $shipment->save();
439:
440: $this->loadLayout(false);
441: $response = $this->getLayout()->getBlock('shipment_comments')->toHtml();
442: } catch (Mage_Core_Exception $e) {
443: $response = array(
444: 'error' => true,
445: 'message' => $e->getMessage()
446: );
447: $response = Mage::helper('core')->jsonEncode($response);
448: } catch (Exception $e) {
449: $response = array(
450: 'error' => true,
451: 'message' => $this->__('Cannot add new comment.')
452: );
453: $response = Mage::helper('core')->jsonEncode($response);
454: }
455: $this->getResponse()->setBody($response);
456: }
457:
458:
459:
460: 461: 462: 463: 464: 465: 466: 467: 468: 469:
470: protected function _needToAddDummy($item, $qtys) {
471: if ($item->getHasChildren()) {
472: foreach ($item->getChildrenItems() as $child) {
473: if ($child->getIsVirtual()) {
474: continue;
475: }
476: if ((isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0)
477: || (!isset($qtys[$child->getId()]) && $child->getQtyToShip())) {
478: return true;
479: }
480: }
481: return false;
482: } else if($item->getParentItem()) {
483: if ($item->getIsVirtual()) {
484: return false;
485: }
486: if ((isset($qtys[$item->getParentItem()->getId()]) && $qtys[$item->getParentItem()->getId()] > 0)
487: || (!isset($qtys[$item->getParentItem()->getId()]) && $item->getParentItem()->getQtyToShip())) {
488: return true;
489: }
490: return false;
491: }
492: }
493:
494: 495: 496: 497: 498: 499:
500: protected function _createShippingLabel(Mage_Sales_Model_Order_Shipment $shipment)
501: {
502: if (!$shipment) {
503: return false;
504: }
505: $carrier = $shipment->getOrder()->getShippingCarrier();
506: if (!$carrier->isShippingLabelsAvailable()) {
507: return false;
508: }
509: $shipment->setPackages($this->getRequest()->getParam('packages'));
510: $response = Mage::getModel('shipping/shipping')->requestToShipment($shipment);
511: if ($response->hasErrors()) {
512: Mage::throwException($response->getErrors());
513: }
514: if (!$response->hasInfo()) {
515: return false;
516: }
517: $labelsContent = array();
518: $trackingNumbers = array();
519: $info = $response->getInfo();
520: foreach ($info as $inf) {
521: if (!empty($inf['tracking_number']) && !empty($inf['label_content'])) {
522: $labelsContent[] = $inf['label_content'];
523: $trackingNumbers[] = $inf['tracking_number'];
524: }
525: }
526: $outputPdf = $this->_combineLabelsPdf($labelsContent);
527: $shipment->setShippingLabel($outputPdf->render());
528: $carrierCode = $carrier->getCarrierCode();
529: $carrierTitle = Mage::getStoreConfig('carriers/'.$carrierCode.'/title', $shipment->getStoreId());
530: if ($trackingNumbers) {
531: foreach ($trackingNumbers as $trackingNumber) {
532: $track = Mage::getModel('sales/order_shipment_track')
533: ->setNumber($trackingNumber)
534: ->setCarrierCode($carrierCode)
535: ->setTitle($carrierTitle);
536: $shipment->addTrack($track);
537: }
538: }
539: return true;
540: }
541:
542: 543: 544: 545:
546: public function createLabelAction()
547: {
548: $response = new Varien_Object();
549: try {
550: $shipment = $this->_initShipment();
551: if ($this->_createShippingLabel($shipment)) {
552: $shipment->save();
553: $this->_getSession()->addSuccess(Mage::helper('sales')->__('The shipping label has been created.'));
554: $response->setOk(true);
555: }
556: } catch (Mage_Core_Exception $e) {
557: $response->setError(true);
558: $response->setMessage($e->getMessage());
559: } catch (Exception $e) {
560: Mage::logException($e);
561: $response->setError(true);
562: $response->setMessage(Mage::helper('sales')->__('An error occurred while creating shipping label.'));
563: }
564:
565: $this->getResponse()->setBody($response->toJson());
566: }
567:
568: 569: 570: 571:
572: public function printLabelAction()
573: {
574: try {
575: $shipment = $this->_initShipment();
576: $labelContent = $shipment->getShippingLabel();
577: if ($labelContent) {
578: $pdfContent = null;
579: if (stripos($labelContent, '%PDF-') !== false) {
580: $pdfContent = $labelContent;
581: } else {
582: $pdf = new Zend_Pdf();
583: $page = $this->_createPdfPageFromImageString($labelContent);
584: if (!$page) {
585: $this->_getSession()->addError(Mage::helper('sales')->__('File extension not known or unsupported type in the following shipment: %s', $shipment->getIncrementId()));
586: }
587: $pdf->pages[] = $page;
588: $pdfContent = $pdf->render();
589: }
590:
591: return $this->_prepareDownloadResponse(
592: 'ShippingLabel(' . $shipment->getIncrementId() . ').pdf',
593: $pdfContent,
594: 'application/pdf'
595: );
596: }
597: } catch (Mage_Core_Exception $e) {
598: $this->_getSession()->addError($e->getMessage());
599: } catch (Exception $e) {
600: Mage::logException($e);
601: $this->_getSession()
602: ->addError(Mage::helper('sales')->__('An error occurred while creating shipping label.'));
603: }
604: $this->_redirect('*/sales_order_shipment/view', array(
605: 'shipment_id' => $this->getRequest()->getParam('shipment_id')
606: ));
607: }
608:
609: 610: 611: 612: 613:
614: public function printPackageAction()
615: {
616: $shipment = $this->_initShipment();
617:
618: if ($shipment) {
619: $pdf = Mage::getModel('sales/order_pdf_shipment_packaging')->getPdf($shipment);
620: $this->_prepareDownloadResponse('packingslip'.Mage::getSingleton('core/date')->date('Y-m-d_H-i-s').'.pdf',
621: $pdf->render(), 'application/pdf'
622: );
623: }
624: else {
625: $this->_forward('noRoute');
626: }
627: }
628:
629: 630: 631: 632: 633: 634:
635: public function massPrintShippingLabelAction()
636: {
637: $request = $this->getRequest();
638: $ids = $request->getParam('order_ids');
639: $createdFromOrders = !empty($ids);
640: $shipments = null;
641: $labelsContent = array();
642: switch ($request->getParam('massaction_prepare_key')) {
643: case 'shipment_ids':
644: $ids = $request->getParam('shipment_ids');
645: array_filter($ids, 'intval');
646: if (!empty($ids)) {
647: $shipments = Mage::getResourceModel('sales/order_shipment_collection')
648: ->addFieldToFilter('entity_id', array('in' => $ids));
649: }
650: break;
651: case 'order_ids':
652: $ids = $request->getParam('order_ids');
653: array_filter($ids, 'intval');
654: if (!empty($ids)) {
655: $shipments = Mage::getResourceModel('sales/order_shipment_collection')
656: ->setOrderFilter(array('in' => $ids));
657: }
658: break;
659: }
660:
661: if ($shipments && $shipments->getSize()) {
662: foreach ($shipments as $shipment) {
663: $labelContent = $shipment->getShippingLabel();
664: if ($labelContent) {
665: $labelsContent[] = $labelContent;
666: }
667: }
668: }
669:
670: if (!empty($labelsContent)) {
671: $outputPdf = $this->_combineLabelsPdf($labelsContent);
672: $this->_prepareDownloadResponse('ShippingLabels.pdf', $outputPdf->render(), 'application/pdf');
673: return;
674: } else {
675: $createdFromPartErrorMsg = $createdFromOrders ? 'orders' : 'shipments';
676: $this->_getSession()
677: ->addError(Mage::helper('sales')->__('There are no shipping labels related to selected %s.', $createdFromPartErrorMsg));
678: }
679: if ($createdFromOrders) {
680: $this->_redirect('*/sales_order/index');
681: } else {
682: $this->_redirect('*/sales_order_shipment/index');
683: }
684: }
685:
686: 687: 688: 689: 690: 691:
692: protected function _combineLabelsPdf(array $labelsContent)
693: {
694: $outputPdf = new Zend_Pdf();
695: foreach ($labelsContent as $content) {
696: if (stripos($content, '%PDF-') !== false) {
697: $pdfLabel = Zend_Pdf::parse($content);
698: foreach ($pdfLabel->pages as $page) {
699: $outputPdf->pages[] = clone $page;
700: }
701: } else {
702: $page = $this->_createPdfPageFromImageString($content);
703: if ($page) {
704: $outputPdf->pages[] = $page;
705: }
706: }
707: }
708: return $outputPdf;
709: }
710:
711: 712: 713: 714: 715: 716:
717: protected function _createPdfPageFromImageString($imageString)
718: {
719: $image = imagecreatefromstring($imageString);
720: if (!$image) {
721: return false;
722: }
723:
724: $xSize = imagesx($image);
725: $ySize = imagesy($image);
726: $page = new Zend_Pdf_Page($xSize, $ySize);
727:
728: imageinterlace($image, 0);
729: $tmpFileName = sys_get_temp_dir() . DS . 'shipping_labels_'
730: . uniqid(mt_rand()) . time() . '.png';
731: imagepng($image, $tmpFileName);
732: $pdfImage = Zend_Pdf_Image::imageWithPath($tmpFileName);
733: $page->drawImage($pdfImage, 0, 0, $xSize, $ySize);
734: unlink($tmpFileName);
735: return $page;
736: }
737:
738: 739: 740: 741: 742:
743: public function getShippingItemsGridAction()
744: {
745: $this->_initShipment();
746: return $this->getResponse()->setBody(
747: $this->getLayout()
748: ->createBlock('adminhtml/sales_order_shipment_packaging_grid')
749: ->setIndex($this->getRequest()->getParam('index'))
750: ->toHtml()
751: );
752: }
753: }
754: