Transsmart_Shipping - Version 1.0.1

Version Notes

1.0.1

Download this release

Release Info

Developer Techtwo Webdevelopment B.V.
Extension Transsmart_Shipping
Version 1.0.1
Comparing to
See all releases


Code changes from version 1.0.0 to 1.0.1

app/code/community/Transsmart/Shipping/Helper/Shipment.php CHANGED
@@ -268,8 +268,9 @@ class Transsmart_Shipping_Helper_Shipment extends Mage_Core_Helper_Abstract
268
  * Export the given shipment to the Transsmart API.
269
  *
270
  * @param Mage_Sales_Model_Order_Shipment $shipment
 
271
  */
272
- public function doExport($shipment)
273
  {
274
  // is it already exported?
275
  if ($shipment->getTranssmartDocumentId()) {
@@ -441,7 +442,12 @@ class Transsmart_Shipping_Helper_Shipment extends Mage_Core_Helper_Abstract
441
  $flags = (int)$shipment->getTranssmartFlags();
442
  try {
443
  if (($flags & Transsmart_Shipping_Helper_Shipment::FLAG_BOOKANDPRINT_ON_CREATE)) {
444
- $this->doBookAndPrint($shipment);
 
 
 
 
 
445
  }
446
  elseif (($flags & Transsmart_Shipping_Helper_Shipment::FLAG_BOOK_ON_CREATE)) {
447
  $this->doBooking($shipment);
@@ -453,6 +459,60 @@ class Transsmart_Shipping_Helper_Shipment extends Mage_Core_Helper_Abstract
453
  }
454
  }
455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  /**
457
  * Call doBookAndPrint for a Transsmart shipment and process the response. Returns TRUE if successful.
458
  *
@@ -520,7 +580,7 @@ class Transsmart_Shipping_Helper_Shipment extends Mage_Core_Helper_Abstract
520
  }
521
 
522
  /**
523
- * Call doLabel for a Transsmart shipment and return the label contents (PDF)
524
  *
525
  * @param Mage_Sales_Model_Order_Shipment $shipment
526
  * @return bool
@@ -557,4 +617,158 @@ class Transsmart_Shipping_Helper_Shipment extends Mage_Core_Helper_Abstract
557
 
558
  return true;
559
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
268
  * Export the given shipment to the Transsmart API.
269
  *
270
  * @param Mage_Sales_Model_Order_Shipment $shipment
271
+ * @param bool $allowPrint
272
  */
273
+ public function doExport($shipment, $allowPrint = true)
274
  {
275
  // is it already exported?
276
  if ($shipment->getTranssmartDocumentId()) {
442
  $flags = (int)$shipment->getTranssmartFlags();
443
  try {
444
  if (($flags & Transsmart_Shipping_Helper_Shipment::FLAG_BOOKANDPRINT_ON_CREATE)) {
445
+ if ($allowPrint) {
446
+ $this->doBookAndPrint($shipment);
447
+ }
448
+ else {
449
+ $this->doBooking($shipment);
450
+ }
451
  }
452
  elseif (($flags & Transsmart_Shipping_Helper_Shipment::FLAG_BOOK_ON_CREATE)) {
453
  $this->doBooking($shipment);
459
  }
460
  }
461
 
462
+ /**
463
+ * Create Transsmart API documents for all shipments that need to be exported.
464
+ */
465
+ public function doMassExport()
466
+ {
467
+ /** @var Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection */
468
+ $shipmentCollection = Mage::getResourceModel('sales/order_shipment_collection');
469
+
470
+ // we need only valid Transsmart shipments without document ID
471
+ $shipmentCollection
472
+ ->addFieldToFilter('transsmart_carrierprofile_id', array('notnull' => true))
473
+ ->addFieldToFilter('transsmart_shipmentlocation_id', array('notnull' => true))
474
+ ->addFieldToFilter('transsmart_emailtype_id', array('notnull' => true))
475
+ ->addFieldToFilter('transsmart_incoterm_id', array('notnull' => true))
476
+ ->addFieldToFilter('transsmart_costcenter_id', array('notnull' => true))
477
+ ->addFieldToFilter('transsmart_packages', array('notnull' => true))
478
+ ->addFieldToFilter('transsmart_document_id', array('null' => true));
479
+
480
+ /** @var Mage_Sales_Model_Order_Shipment $_shipment */
481
+ foreach ($shipmentCollection as $_shipment) {
482
+ // set original data manually (because we didn't call object load())
483
+ $_shipment->setOrigData();
484
+
485
+ $this->doExport($_shipment, false);
486
+ }
487
+
488
+ // group documentIds for all book-and-print shipments with the same QZ Host and Selected Printer
489
+ $groupedCalls = $this->_getMassPrintGroupedCalls($shipmentCollection, true);
490
+ if (count($groupedCalls) == 0) {
491
+ return;
492
+ }
493
+
494
+ $idsToSync = array();
495
+ try {
496
+ // call Transsmart API doLabel method for each group (doBooking was already called in doExport)
497
+ foreach ($groupedCalls as $_call) {
498
+ $idsToSync += $_call['doc_ids'];
499
+ Mage::helper('transsmart_shipping')->getApiClient()->doLabel(
500
+ $_call['doc_ids'],
501
+ Mage::getStoreConfig(Transsmart_Shipping_Helper_Data::XML_PATH_CONNECTION_USERNAME, 0),
502
+ false,
503
+ false,
504
+ $_call['qz_host'],
505
+ $_call['selected_printer']
506
+ );
507
+ }
508
+ }
509
+ catch (Exception $exception) {
510
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
511
+ throw $exception;
512
+ }
513
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
514
+ }
515
+
516
  /**
517
  * Call doBookAndPrint for a Transsmart shipment and process the response. Returns TRUE if successful.
518
  *
580
  }
581
 
582
  /**
583
+ * Call doLabel for a Transsmart shipment.
584
  *
585
  * @param Mage_Sales_Model_Order_Shipment $shipment
586
  * @return bool
617
 
618
  return true;
619
  }
620
+
621
+ /**
622
+ * Group documentIds for shipments with the same QZ Host and Selected Printer.
623
+ * Used by doMassBookAndPrint and doMassLabel
624
+ *
625
+ * @param Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection
626
+ * @param bool $onlyWithBookAndPrintFlag
627
+ * @return array
628
+ */
629
+ protected function _getMassPrintGroupedCalls($shipmentCollection, $onlyWithBookAndPrintFlag)
630
+ {
631
+ // group documentIds for shipments with the same QZ Host and Selected Printer.
632
+ $groupedCalls = array();
633
+ foreach ($shipmentCollection as $_shipment) {
634
+ if (!$_shipment->getTranssmartDocumentId()) {
635
+ continue;
636
+ }
637
+
638
+ // do we need only shipments with the FLAG_BOOKANDPRINT_ON_CREATE flag?
639
+ if ($onlyWithBookAndPrintFlag) {
640
+ $_flags = (int)$_shipment->getTranssmartFlags();
641
+ if (($_flags & Transsmart_Shipping_Helper_Shipment::FLAG_BOOKANDPRINT_ON_CREATE) == 0) {
642
+ continue;
643
+ }
644
+ }
645
+
646
+ $_qzHost = Mage::getStoreConfig(
647
+ Transsmart_Shipping_Helper_Data::XML_PATH_PRINT_QZHOST,
648
+ $_shipment->getStore()
649
+ );
650
+ $_selectedPrinter = Mage::getStoreConfig(
651
+ Transsmart_Shipping_Helper_Data::XML_PATH_PRINT_SELECTEDPRINTER,
652
+ $_shipment->getStore()
653
+ );
654
+
655
+ $_groupKey = $_qzHost . ':' . $_selectedPrinter;
656
+ if (!isset($groupedCalls[$_groupKey])) {
657
+ $groupedCalls[$_groupKey] = array(
658
+ 'qz_host' => $_qzHost,
659
+ 'selected_printer' => $_selectedPrinter,
660
+ 'doc_ids' => array()
661
+ );
662
+ }
663
+
664
+ $groupedCalls[$_groupKey]['doc_ids'][] = $_shipment->getTranssmartDocumentId();
665
+ }
666
+
667
+ return $groupedCalls;
668
+ }
669
+
670
+ /**
671
+ * Synchronize status for the given shipments. If idsToSync array is given, only those document IDs will be synced.
672
+ * Used by doMassBookAndPrint and doMassLabel
673
+ *
674
+ * @param Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection
675
+ * @param array|null $idsToSync
676
+ */
677
+ protected function _massSyncDocuments($shipmentCollection, $idsToSync = null)
678
+ {
679
+ if (!is_null($idsToSync) && count($idsToSync) == 0) {
680
+ return;
681
+ }
682
+
683
+ foreach ($shipmentCollection as $_shipment) {
684
+ $_documentId = $_shipment->getTranssmartDocumentId();
685
+ if (!$_documentId || (!is_null($idsToSync) && !in_array($_documentId, $idsToSync))) {
686
+ continue;
687
+ }
688
+
689
+ try {
690
+ Mage::getSingleton('transsmart_shipping/sync')->syncShipment($_shipment);
691
+ }
692
+ catch (Mage_Core_Exception $exception) {
693
+ Mage::logException($exception);
694
+ }
695
+ }
696
+ }
697
+
698
+ /**
699
+ * Call doBookAndPrint for multiple Transsmart shipments at once.
700
+ *
701
+ * @param Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection
702
+ * @return bool
703
+ * @throws Exception
704
+ */
705
+ public function doMassBookAndPrint($shipmentCollection)
706
+ {
707
+ // group documentIds for shipments with the same QZ Host and Selected Printer.
708
+ $groupedCalls = $this->_getMassPrintGroupedCalls($shipmentCollection, false);
709
+ if (count($groupedCalls) == 0) {
710
+ return;
711
+ }
712
+
713
+ $idsToSync = array();
714
+ try {
715
+ // call Transsmart API doLabel method for each group
716
+ foreach ($groupedCalls as $_call) {
717
+ $idsToSync += $_call['doc_ids'];
718
+ Mage::helper('transsmart_shipping')->getApiClient()->doBookAndPrint(
719
+ $_call['doc_ids'],
720
+ Mage::getStoreConfig(Transsmart_Shipping_Helper_Data::XML_PATH_CONNECTION_USERNAME, 0),
721
+ false,
722
+ $_call['qz_host'],
723
+ $_call['selected_printer']
724
+ );
725
+ }
726
+ }
727
+ catch (Exception $exception) {
728
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
729
+ throw $exception;
730
+ }
731
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
732
+
733
+ return true;
734
+ }
735
+
736
+ /**
737
+ * Call doLabel for multiple Transsmart shipments at once.
738
+ *
739
+ * @param Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection
740
+ * @return bool
741
+ * @throws Exception
742
+ */
743
+ public function doMassLabel($shipmentCollection)
744
+ {
745
+ // group documentIds for shipments with the same QZ Host and Selected Printer.
746
+ $groupedCalls = $this->_getMassPrintGroupedCalls($shipmentCollection, false);
747
+ if (count($groupedCalls) == 0) {
748
+ return;
749
+ }
750
+
751
+ $idsToSync = array();
752
+ try {
753
+ // call Transsmart API doLabel method for each group
754
+ foreach ($groupedCalls as $_call) {
755
+ $idsToSync += $_call['doc_ids'];
756
+ Mage::helper('transsmart_shipping')->getApiClient()->doLabel(
757
+ $_call['doc_ids'],
758
+ Mage::getStoreConfig(Transsmart_Shipping_Helper_Data::XML_PATH_CONNECTION_USERNAME, 0),
759
+ false,
760
+ false,
761
+ $_call['qz_host'],
762
+ $_call['selected_printer']
763
+ );
764
+ }
765
+ }
766
+ catch (Exception $exception) {
767
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
768
+ throw $exception;
769
+ }
770
+ $this->_massSyncDocuments($shipmentCollection, $idsToSync);
771
+
772
+ return true;
773
+ }
774
  }
app/code/community/Transsmart/Shipping/Model/Adminhtml/Observer.php CHANGED
@@ -298,6 +298,10 @@ class Transsmart_Shipping_Model_Adminhtml_Observer
298
 
299
  // TODO: make a setting for this?
300
 
 
 
 
 
301
  // export to Transsmart API
302
  Mage::helper('transsmart_shipping/shipment')->doExport($shipment);
303
  }
298
 
299
  // TODO: make a setting for this?
300
 
301
+ if ($shipment->getData('transsmart_prevent_export_on_save')) {
302
+ return;
303
+ }
304
+
305
  // export to Transsmart API
306
  Mage::helper('transsmart_shipping/shipment')->doExport($shipment);
307
  }
app/code/community/Transsmart/Shipping/Model/Client.php CHANGED
@@ -70,7 +70,7 @@ class Transsmart_Shipping_Model_Client
70
  CURLINFO_HEADER_OUT => true,
71
  CURLOPT_RETURNTRANSFER => true,
72
  CURLOPT_CONNECTTIMEOUT => 5,
73
- CURLOPT_TIMEOUT => 10,
74
  );
75
 
76
  if (!is_null($requestBody)) {
@@ -640,7 +640,7 @@ class Transsmart_Shipping_Model_Client
640
  }
641
 
642
  /**
643
- * @param int $id
644
  * @param string $username
645
  * @param int|null $pdf
646
  * @param int|null $downloadonly
@@ -651,20 +651,24 @@ class Transsmart_Shipping_Model_Client
651
  */
652
  public function doLabel($id, $username, $pdf = null, $downloadonly = null, $qzhost = null, $selectedprinter = null)
653
  {
654
- $parameters = array(
655
- 'id' => $id,
656
- 'username' => $username,
657
- );
658
- if (!is_null($pdf)) {
 
 
 
 
659
  $parameters['pdf'] = $pdf;
660
  }
661
- if (!is_null($downloadonly)) {
662
  $parameters['downloadonly'] = $downloadonly;
663
  }
664
- if (!is_null($qzhost)) {
665
  $parameters['qzhost'] = $qzhost;
666
  }
667
- if (!is_null($selectedprinter)) {
668
  $parameters['selectedprinter'] = $selectedprinter;
669
  }
670
 
@@ -678,7 +682,7 @@ class Transsmart_Shipping_Model_Client
678
  }
679
 
680
  /**
681
- * @param int $id
682
  * @param string $username
683
  * @param int|null $downloadonly
684
  * @param string|null $qzhost
@@ -688,17 +692,21 @@ class Transsmart_Shipping_Model_Client
688
  */
689
  public function doBookAndPrint($id, $username, $downloadonly = null, $qzhost = null, $selectedprinter = null)
690
  {
691
- $parameters = array(
692
- 'id' => $id,
693
- 'username' => $username,
694
- );
695
- if (!is_null($downloadonly)) {
 
 
 
 
696
  $parameters['downloadonly'] = $downloadonly;
697
  }
698
- if (!is_null($qzhost)) {
699
  $parameters['qzhost'] = $qzhost;
700
  }
701
- if (!is_null($selectedprinter)) {
702
  $parameters['selectedprinter'] = $selectedprinter;
703
  }
704
 
70
  CURLINFO_HEADER_OUT => true,
71
  CURLOPT_RETURNTRANSFER => true,
72
  CURLOPT_CONNECTTIMEOUT => 5,
73
+ CURLOPT_TIMEOUT => 20,
74
  );
75
 
76
  if (!is_null($requestBody)) {
640
  }
641
 
642
  /**
643
+ * @param int|array $id
644
  * @param string $username
645
  * @param int|null $pdf
646
  * @param int|null $downloadonly
651
  */
652
  public function doLabel($id, $username, $pdf = null, $downloadonly = null, $qzhost = null, $selectedprinter = null)
653
  {
654
+ $parameters = array();
655
+ if (!is_array($id)) {
656
+ $parameters['id'] = $id;
657
+ }
658
+ else {
659
+ $parameters['docIds'] = implode(',', $id);
660
+ }
661
+ $parameters['username'] = $username;
662
+ if (!empty($pdf)) {
663
  $parameters['pdf'] = $pdf;
664
  }
665
+ if (!empty($downloadonly)) {
666
  $parameters['downloadonly'] = $downloadonly;
667
  }
668
+ if (!empty($qzhost)) {
669
  $parameters['qzhost'] = $qzhost;
670
  }
671
+ if (!empty($selectedprinter)) {
672
  $parameters['selectedprinter'] = $selectedprinter;
673
  }
674
 
682
  }
683
 
684
  /**
685
+ * @param int|array $id
686
  * @param string $username
687
  * @param int|null $downloadonly
688
  * @param string|null $qzhost
692
  */
693
  public function doBookAndPrint($id, $username, $downloadonly = null, $qzhost = null, $selectedprinter = null)
694
  {
695
+ $parameters = array();
696
+ if (!is_array($id)) {
697
+ $parameters['id'] = $id;
698
+ }
699
+ else {
700
+ $parameters['docIds'] = implode(',', $id);
701
+ }
702
+ $parameters['username'] = $username;
703
+ if (!empty($downloadonly)) {
704
  $parameters['downloadonly'] = $downloadonly;
705
  }
706
+ if (!empty($qzhost)) {
707
  $parameters['qzhost'] = $qzhost;
708
  }
709
+ if (!empty($selectedprinter)) {
710
  $parameters['selectedprinter'] = $selectedprinter;
711
  }
712
 
app/code/community/Transsmart/Shipping/Model/Sync.php CHANGED
@@ -513,37 +513,7 @@ class Transsmart_Shipping_Model_Sync extends Mage_Core_Model_Abstract
513
  */
514
  protected function exportShipments()
515
  {
516
- /** @var Mage_Sales_Model_Resource_Order_Shipment_Collection $shipmentCollection */
517
- $shipmentCollection = Mage::getResourceModel('sales/order_shipment_collection');
518
-
519
- // join the shipping_method column from the order table
520
- $shipmentCollection->join(
521
- array('order' => 'sales/order'),
522
- 'order.entity_id = main_table.order_id',
523
- ''
524
- );
525
-
526
- // we need only valid Transsmart shipments without document ID
527
- $shipmentCollection
528
- ->addFieldToFilter('shipping_method', array('like' => 'transsmart%\_carrierprofile\_%'))
529
- ->addFieldToFilter('transsmart_shipmentlocation_id', array('notnull' => true))
530
- ->addFieldToFilter('transsmart_emailtype_id', array('notnull' => true))
531
- ->addFieldToFilter('transsmart_incoterm_id', array('notnull' => true))
532
- ->addFieldToFilter('transsmart_costcenter_id', array('notnull' => true))
533
- ->addFieldToFilter('transsmart_packages', array('notnull' => true))
534
- ->addFieldToFilter('transsmart_document_id', array('null' => true));
535
-
536
- /** @var Transsmart_Shipping_Helper_Shipment $shipmentHelper */
537
- $shipmentHelper = Mage::helper('transsmart_shipping/shipment');
538
-
539
- /** @var Mage_Sales_Model_Order_Shipment $_shipment */
540
- foreach ($shipmentCollection as $_shipment) {
541
- // set original data manually (because we didn't call object load())
542
- $_shipment->setOrigData();
543
-
544
- $shipmentHelper->doExport($_shipment);
545
- }
546
-
547
  return $this;
548
  }
549
 
513
  */
514
  protected function exportShipments()
515
  {
516
+ Mage::helper('transsmart_shipping/shipment')->doMassExport();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
517
  return $this;
518
  }
519
 
app/code/community/Transsmart/Shipping/controllers/Adminhtml/Transsmart/Shipping/ShipmentController.php CHANGED
@@ -98,6 +98,9 @@ class Transsmart_Shipping_Adminhtml_Transsmart_Shipping_ShipmentController exten
98
  $_order->setCustomerNoteNotify(!empty($data['send_email']))
99
  ->setIsInProcess(true);
100
 
 
 
 
101
  // save changes to the shipment and order into database
102
  Mage::getModel('core/resource_transaction')
103
  ->addObject($_shipment)
@@ -121,6 +124,8 @@ class Transsmart_Shipping_Adminhtml_Transsmart_Shipping_ShipmentController exten
121
  }
122
  if ($successCount > 0) {
123
  $this->_getSession()->addSuccess($this->__('Successfully created %s shipment(s)!', $successCount));
 
 
124
  }
125
 
126
  // redirect user
@@ -169,26 +174,37 @@ class Transsmart_Shipping_Adminhtml_Transsmart_Shipping_ShipmentController exten
169
  $totalCount = 0;
170
  $successCount = 0;
171
  if ($shipmentCollection) {
 
 
 
 
 
 
 
 
 
 
 
 
172
  /** @var Mage_Sales_Model_Order_Shipment $_shipment */
173
  foreach ($shipmentCollection as $_shipment) {
174
- if (!$_shipment->getTranssmartDocumentId()) {
175
- continue;
176
- }
177
- $totalCount++;
178
 
179
- try {
180
- $shipmentHelper->doBookAndPrint($_shipment);
181
- $successCount++;
182
- }
183
- catch (Mage_Core_Exception $_exception) {
184
- $this->_getSession()->addError(
185
- $this->__(
186
- 'Shipment #%s for order #%s could not be booked and printed: %s',
187
- $_shipment->getIncrementId(),
188
- $_shipment->getOrder()->getIncrementId(),
189
- $_exception->getMessage()
190
- )
191
- );
192
  }
193
  }
194
  }
@@ -295,22 +311,34 @@ class Transsmart_Shipping_Adminhtml_Transsmart_Shipping_ShipmentController exten
295
  $totalCount = 0;
296
  $successCount = 0;
297
  if ($shipmentCollection) {
 
 
 
 
 
 
 
 
 
 
 
 
298
  /** @var Mage_Sales_Model_Order_Shipment $_shipment */
299
  foreach ($shipmentCollection as $_shipment) {
300
- // print Transsmart shipping labels
301
  if ($_shipment->getTranssmartDocumentId()) {
302
- try {
303
- $totalCount++;
304
- $shipmentHelper->doLabel($_shipment);
305
  $successCount++;
306
  }
307
- catch (Mage_Core_Exception $_exception) {
308
  $this->_getSession()->addError(
309
  $this->__(
310
  'Shipment #%s for order #%s could not be printed: %s',
311
  $_shipment->getIncrementId(),
312
  $_shipment->getOrder()->getIncrementId(),
313
- $_exception->getMessage()
314
  )
315
  );
316
  }
98
  $_order->setCustomerNoteNotify(!empty($data['send_email']))
99
  ->setIsInProcess(true);
100
 
101
+ /** @see Transsmart_Shipping_Model_Adminhtml_Observer::salesOrderShipmentSaveAfter */
102
+ $_shipment->setData('transsmart_prevent_export_on_save', true);
103
+
104
  // save changes to the shipment and order into database
105
  Mage::getModel('core/resource_transaction')
106
  ->addObject($_shipment)
124
  }
125
  if ($successCount > 0) {
126
  $this->_getSession()->addSuccess($this->__('Successfully created %s shipment(s)!', $successCount));
127
+
128
+ Mage::helper('transsmart_shipping/shipment')->doMassExport();
129
  }
130
 
131
  // redirect user
174
  $totalCount = 0;
175
  $successCount = 0;
176
  if ($shipmentCollection) {
177
+ try {
178
+ $shipmentHelper->doMassBookAndPrint($shipmentCollection);
179
+ }
180
+ catch (Mage_Core_Exception $_exception) {
181
+ $this->_getSession()->addError(
182
+ $this->__(
183
+ 'One or more shipments could not be booked and printed: %s',
184
+ $_exception->getMessage()
185
+ )
186
+ );
187
+ }
188
+
189
  /** @var Mage_Sales_Model_Order_Shipment $_shipment */
190
  foreach ($shipmentCollection as $_shipment) {
191
+ // check if Transsmart shipping labels have been printed
192
+ if ($_shipment->getTranssmartDocumentId()) {
193
+ $totalCount++;
 
194
 
195
+ if ($_shipment->getTranssmartStatus() == 'LABL') {
196
+ $successCount++;
197
+ }
198
+ else {
199
+ $this->_getSession()->addError(
200
+ $this->__(
201
+ 'Shipment #%s for order #%s could not be booked and printed: %s',
202
+ $_shipment->getIncrementId(),
203
+ $_shipment->getOrder()->getIncrementId(),
204
+ 'Error' // TODO: use ShipmentError field
205
+ )
206
+ );
207
+ }
208
  }
209
  }
210
  }
311
  $totalCount = 0;
312
  $successCount = 0;
313
  if ($shipmentCollection) {
314
+ try {
315
+ $shipmentHelper->doMassLabel($shipmentCollection);
316
+ }
317
+ catch (Mage_Core_Exception $_exception) {
318
+ $this->_getSession()->addError(
319
+ $this->__(
320
+ 'One ore more shipments could not be printed: %s',
321
+ $_exception->getMessage()
322
+ )
323
+ );
324
+ }
325
+
326
  /** @var Mage_Sales_Model_Order_Shipment $_shipment */
327
  foreach ($shipmentCollection as $_shipment) {
328
+ // check if Transsmart shipping labels have been printed
329
  if ($_shipment->getTranssmartDocumentId()) {
330
+ $totalCount++;
331
+
332
+ if ($_shipment->getTranssmartStatus() == 'LABL') {
333
  $successCount++;
334
  }
335
+ else {
336
  $this->_getSession()->addError(
337
  $this->__(
338
  'Shipment #%s for order #%s could not be printed: %s',
339
  $_shipment->getIncrementId(),
340
  $_shipment->getOrder()->getIncrementId(),
341
+ 'Error' // TODO: use ShipmentError field
342
  )
343
  );
344
  }
app/code/community/Transsmart/Shipping/etc/config.xml CHANGED
@@ -9,7 +9,7 @@
9
  <config>
10
  <modules>
11
  <Transsmart_Shipping>
12
- <version>1.0.0</version>
13
  </Transsmart_Shipping>
14
  </modules>
15
  <global>
9
  <config>
10
  <modules>
11
  <Transsmart_Shipping>
12
+ <version>1.0.1</version>
13
  </Transsmart_Shipping>
14
  </modules>
15
  <global>
app/locale/nl_NL/Transsmart_Shipping.csv CHANGED
@@ -74,10 +74,12 @@
74
  "Transsmart: Print Label(s)","Transsmart: Label(s) printen"
75
  "Transsmart document ID is not known.","Transsmart document ID is niet bekend."
76
  "Shipment #%s for order #%s could not be booked and printed: %s","Zending #%s voor bestelling #%s kon niet geboekt en geprint worden: %s"
 
77
  "Successfully booked and printed %s Transsmart shipments.","Succesvol %s Transsmart zendingen geboekt en geprint."
78
  "Shipment #%s for order #%s could not be booked: %s","Zending #%s voor bestelling #%s kon niet geboekt worden: %s"
79
  "Successfully booked %s Transsmart shipments.","Succesvol %s Transsmart zendingen geboekt."
80
  "Shipment #%s for order #%s could not be printed: %s","Zending #%s voor bestelling #%s kon niet geprint worden: %s"
 
81
  "Successfully printed %s Transsmart shipments.","Succesvol %s Transsmart zendingen geprint."
82
  "There are no Transsmart documents related to selected order(s).","Er zijn geen Transsmart documenten gerelateerd aan de geselecteerde bestelling(en)."
83
  "There are no Transsmart documents related to selected shipment(s).","Er zijn geen Transsmart documenten gerelateerd aan de geselecteerde zending(en)."
74
  "Transsmart: Print Label(s)","Transsmart: Label(s) printen"
75
  "Transsmart document ID is not known.","Transsmart document ID is niet bekend."
76
  "Shipment #%s for order #%s could not be booked and printed: %s","Zending #%s voor bestelling #%s kon niet geboekt en geprint worden: %s"
77
+ "One or more shipments could not be booked and printed: %s","Eén of meer zendingen konden niet geboekt en geprint worden: %s"
78
  "Successfully booked and printed %s Transsmart shipments.","Succesvol %s Transsmart zendingen geboekt en geprint."
79
  "Shipment #%s for order #%s could not be booked: %s","Zending #%s voor bestelling #%s kon niet geboekt worden: %s"
80
  "Successfully booked %s Transsmart shipments.","Succesvol %s Transsmart zendingen geboekt."
81
  "Shipment #%s for order #%s could not be printed: %s","Zending #%s voor bestelling #%s kon niet geprint worden: %s"
82
+ "One ore more shipments could not be printed: %s","Eén of meer zendingen konden niet geprint worden: %s"
83
  "Successfully printed %s Transsmart shipments.","Succesvol %s Transsmart zendingen geprint."
84
  "There are no Transsmart documents related to selected order(s).","Er zijn geen Transsmart documenten gerelateerd aan de geselecteerde bestelling(en)."
85
  "There are no Transsmart documents related to selected shipment(s).","Er zijn geen Transsmart documenten gerelateerd aan de geselecteerde zending(en)."
js/transsmart/shipping/pickup_selector.js CHANGED
@@ -1,899 +1,890 @@
1
- /**
2
- * @category Transsmart
3
- * @package Transsmart_Shipping
4
- * @copyright Copyright (c) 2016 Techtwo Webdevelopment B.V. (http://www.techtwo.nl)
5
- */
6
- if (!Transsmart) var Transsmart = { };
7
- if (!Transsmart.Shipping) Transsmart.Shipping = { };
8
-
9
- Transsmart.Shipping.Pickup = Class.create({
10
-
11
- /**
12
- * Define configuration for the pickup shipping method
13
- */
14
- config: {
15
- shippingMethodName: 'transsmartpickup',
16
- shippingPickupContainerId: 'tss-location-selector',
17
- shippingMethodLoadDivId: 'checkout-shipping-method-load',
18
- locationsListDivId: 'tss-ls-locations',
19
- googleMapsId: 'tss-ls-map',
20
- selectButtonId: 'tss-ls-select',
21
- closeButtonId: 'tss-ls-close',
22
- shippingPickupSelectButtonId: 'tss-ls-select-location',
23
- selectedLocationDivId: 'tss-ls-selected-location-info'
24
- },
25
-
26
- googleMaps: null,
27
- googleGeocoder: null,
28
- selectedShippingMethod: null,
29
- markers: [],
30
- infoWindow: null,
31
- selectedMarker: null,
32
- ajaxRequest: null,
33
- isLoading: false,
34
- isClosing: false,
35
-
36
- origShippingMethod: null,
37
- origPickupDivHtml: '',
38
-
39
- /**
40
- * Initialize the pickup location selector
41
- */
42
- initialize: function(config) {
43
- // Check whether the viewUrl is provided
44
- if (typeof config == 'undefined' || typeof config.lookupUrl == 'undefined') {
45
- Transsmart.Logger.log('Transsmart_Shipping: Missing lookupUrl in the supplied config');
46
- return;
47
- }
48
-
49
- // Set the view url
50
- this.config.lookupUrl = config.lookupUrl;
51
-
52
- // Check whether the carrierProfileIds is provided
53
- if (typeof config == 'undefined' || typeof config.carrierProfileIds == 'undefined') {
54
- Transsmart.Logger.log('Transsmart_Shipping: Missing carrierProfileIds in the supplied config');
55
- return;
56
- }
57
-
58
- this.config.carrierProfileIds = config.carrierProfileIds;
59
-
60
- this.attachListenHandler();
61
- this.attachFilterHandlers();
62
- this.attachSearchHandler();
63
-
64
- // attach window resize handler
65
- document.observe('dom:loaded', function() {
66
- Event.observe(window, 'resize', this.onWindowResize.bind(this));
67
- }.bind(this));
68
-
69
- // observe ajax update event
70
- Ajax.Responders.register({ onComplete: this.onAjaxComplete.bind(this) });
71
- },
72
-
73
- /**
74
- * Attaches the listen handler so that we know when we should be
75
- * showing the pickup selector popup.
76
- */
77
- attachListenHandler: function() {
78
- var self = this;
79
-
80
- // Attach click event to close button
81
- $(this.config.closeButtonId).observe('click', function(event) {
82
- self.close();
83
- event.stop();
84
- });
85
-
86
- // Wait for the dom to be ready
87
- document.observe('dom:loaded', function () {
88
- // Add our custom validator
89
- this.addValidators();
90
-
91
- if (typeof checkout.gotoSection == 'function') {
92
- // hook into Magento's OnePage checkout
93
- var parentGotoSection = checkout.gotoSection.bind(checkout);
94
-
95
- // Triggered when the checkout switches to the shipping method selection
96
- checkout.gotoSection = function (section, reloadProgressBlock) {
97
- // Remove the progress block when we switch to a different section
98
- if (['billing', 'shipping', 'shipping_method'].indexOf(section) !== -1) {
99
- if ($('tss-ls-progress-pickup-header')) {
100
- $('tss-ls-progress-pickup-header').remove();
101
- }
102
-
103
- if ($('tss-ls-progress-pickup-content')) {
104
- $('tss-ls-progress-pickup-content').remove();
105
- }
106
- }
107
-
108
- if (section == 'shipping_method') {
109
- this.updateShippingMethods();
110
- }
111
-
112
- parentGotoSection(section, reloadProgressBlock);
113
- }.bind(this);
114
- }
115
-
116
- // The shipping methods are generated dynamically
117
- // So we need to observe for dom changes and then trigger the click event based on that
118
- $(document).on('click', 'input[name=shipping_method]', function (event, element) {
119
- // Skip shipping methods that do not match the shipping method name
120
- if (element.value && element.value.indexOf(self.config.shippingMethodName) == -1) {
121
- this.removePickupDiv();
122
- return;
123
- }
124
-
125
- this.selectedShippingMethod = element.value;
126
- this.attachPickupDiv(element);
127
- }.bind(this));
128
-
129
- this.updateShippingMethods();
130
-
131
- $(this.config.selectButtonId).observe('click', function (event) {
132
- this.selectLocationAndClose();
133
- event.stop();
134
- }.bind(this));
135
- }.bind(this));
136
- },
137
-
138
- onAjaxComplete: function () {
139
- this.updateShippingMethods();
140
- },
141
-
142
- updateShippingMethods: function () {
143
- // Check which shipping method has been selected
144
- var checkedShippingMethods = $$('input[name=shipping_method]:checked');
145
-
146
- if (checkedShippingMethods.length != 0) {
147
- // The pre-selected shipping method is the pickup one.
148
- // Attach the pickup div to the radio button
149
- if (checkedShippingMethods[0].value.indexOf(this.config.shippingMethodName) != -1) {
150
- this.selectedShippingMethod = checkedShippingMethods[0].value;
151
- this.attachPickupDiv(checkedShippingMethods[0]);
152
- }
153
- }
154
- },
155
-
156
- /**
157
- * The filter handlers determine which markers should be shown
158
- */
159
- attachFilterHandlers: function() {
160
- $('tss-ls-show-open-early').observe('click', this.updateMapMarkers.bind(this));
161
- $('tss-ls-show-open-late').observe('click', this.updateMapMarkers.bind(this));
162
- $('tss-ls-show-open-sunday').observe('click', this.updateMapMarkers.bind(this));
163
- },
164
-
165
- /**
166
- * Attaches the search handler
167
- */
168
- attachSearchHandler: function() {
169
- $('tss-ls-search-btn').observe('click', this.attachSearch.bind(this));
170
- $('tss-ls-search').observe('keypress', this.attachSearch.bind(this));
171
- },
172
-
173
- /**
174
- * Perform search
175
- * @param event
176
- */
177
- attachSearch: function (event) {
178
- if (event.type == 'keypress' && event.keyCode != Event.KEY_RETURN) {
179
- return;
180
- }
181
-
182
- var searchField = $('tss-ls-search');
183
- var searchButton = $('tss-ls-search-btn');
184
-
185
- var searchValue = searchField.value;
186
- if (searchValue == '') {
187
- return;
188
- }
189
-
190
- searchField.disabled = true;
191
- searchField.addClassName('disabled');
192
- searchButton.disabled = true;
193
- searchButton.addClassName('disabled');
194
-
195
- this.retrieveLocation(searchValue, function (bounds) {
196
- searchField.disabled = false;
197
- searchField.removeClassName('disabled');
198
- searchButton.disabled = false;
199
- searchButton.removeClassName('disabled');
200
-
201
- this.updateMapMarkers();
202
-
203
- google.maps.event.trigger(this.googleMaps, 'resize');
204
- this.googleMaps.setCenter(bounds.getCenter());
205
- this.googleMaps.fitBounds(bounds);
206
-
207
- }.bind(this),
208
- function (error) {
209
- searchField.disabled = false;
210
- searchField.removeClassName('disabled');
211
- searchButton.disabled = false;
212
- searchButton.removeClassName('disabled');
213
-
214
- if (this.isClosing) {
215
- return;
216
- }
217
- Transsmart.Logger.log('Transsmart_Shipping error: ' + error);
218
- alert(Translator.translate('Search did not succeed. Please try again.'));
219
-
220
- }.bind(this));
221
- },
222
-
223
- /**
224
- * Attaches the pickup location selector div to the parent item of the input element.
225
- * @param inputElement The input radio element that's part of a carrier
226
- */
227
- attachPickupDiv: function(inputElement) {
228
- var containerItem = $(this.config.shippingPickupContainerId);
229
-
230
- // Remove the shipping pickup div if it exists
231
- if (containerItem) {
232
- containerItem.remove();
233
- }
234
-
235
- var valueBits = inputElement.value.match(/transsmartpickup_carrierprofile_([0-9]+)/);
236
-
237
- // Nothing to attach, it doesn't match
238
- if (valueBits == null || valueBits.length != 2) {
239
- return;
240
- }
241
-
242
- // Not a carrierprofile that has location selector enabled
243
- if (this.config.carrierProfileIds.indexOf(valueBits[1]) == -1) {
244
- Transsmart.Logger.log('Carrier profile with id: ' + valueBits[1] + ' does not allow location selector');
245
- Transsmart.Logger.log('Allowed location selectors are: ', this.config.carrierProfileIds);
246
- return;
247
- }
248
-
249
- // Find the container for transsmart pickup shipping method
250
- var shippingMethodContainer = this.getButtonContainer(inputElement);
251
- if (typeof shippingMethodContainer == 'undefined') {
252
- Transsmart.Logger.log('Transsmart.Shipping: ' +
253
- Translator.translate('Could not find shipping container for ' + this.config.shippingMethodName));
254
- return;
255
- }
256
-
257
- // insert the location selector button
258
- shippingMethodContainer.insert(this.getPickupDiv());
259
- $(this.config.shippingPickupSelectButtonId).observe('click', function(event) {
260
- this.showLocationPopUp();
261
- event.stop();
262
- }.bind(this));
263
- },
264
-
265
- /**
266
- * Find the container for transsmart pickup shipping method button
267
- *
268
- * @param inputElement
269
- */
270
- getButtonContainer: function (inputElement) {
271
- // Find the container for transsmart pickup shipping method
272
- var buttonContainer = inputElement.up('dd, div');
273
- return buttonContainer;
274
- },
275
-
276
- /**
277
- * Removes the pickup div element
278
- */
279
- removePickupDiv: function() {
280
- var containerItem = $(this.config.shippingPickupContainerId);
281
-
282
- if (containerItem != null) {
283
- containerItem.remove();
284
- }
285
- },
286
-
287
- /**
288
- * Returns the div that is used near the shipping radio button
289
- * @returns {string}
290
- */
291
- getPickupDiv: function() {
292
- if (this.origPickupDivHtml == '' || this.origShippingMethod != this.selectedShippingMethod) {
293
- this.origShippingMethod = this.selectedShippingMethod;
294
- this.origPickupDivHtml = '<div id="' + this.config.shippingPickupContainerId + '">' +
295
- '<button id="' + this.config.shippingPickupSelectButtonId + '" class="tss-ls-select-location button" onclick="return false">' +
296
- '<span><span>' +
297
- Translator.translate('Select pickup location') +
298
- '</span></span>' +
299
- '</button>' +
300
- '<div id="' + this.config.selectedLocationDivId + '"></div>' +
301
- '<input id="tss-ls-location-data" name="transsmart_pickup_address_data" type="hidden" class="validate-selected-location" />' +
302
- '</div>';
303
- }
304
- return this.origPickupDivHtml;
305
- },
306
-
307
- /**
308
- * Adds the required validators to the validation class.
309
- */
310
- addValidators: function() {
311
- Validation.add(
312
- 'validate-selected-location',
313
- Translator.translate("A pickup location has to be selected"),
314
- function(v) {
315
- return !Validation.get('IsEmpty').test(v);
316
- });
317
- },
318
-
319
- /**
320
- * Shows the pickup location selector popup
321
- */
322
- showLocationPopUp: function() {
323
- var pickupContainer = $('tss-pickup-container');
324
- var pickupLoader = pickupContainer.select('.tss-loader')[0];
325
- var pickupContent = pickupContainer.select('.tss-selector-container')[0];
326
-
327
- this.isClosing = false;
328
- if (this.originalLoaderHtml) {
329
- pickupLoader.innerHTML = this.originalLoaderHtml;
330
- }
331
- else {
332
- this.originalLoaderHtml = pickupLoader.innerHTML;
333
- }
334
-
335
- // remove validation advice
336
- $$('#' + this.config.shippingPickupContainerId + ' .validation-advice').each(function(item) {
337
- new Effect.Fade(item);
338
- });
339
-
340
- // Reset the markers
341
- this.clearMapMarkers();
342
-
343
- // Reset input fields
344
- $('tss-ls-search').value = '';
345
- $('tss-ls-show-open-early').checked = false;
346
- $('tss-ls-show-open-late').checked = false;
347
- $('tss-ls-show-open-sunday').checked = false;
348
-
349
- pickupLoader.show();
350
- pickupContent.hide();
351
- this.isLoading = true;
352
-
353
- // Show the pickup container
354
- pickupContainer.appear({ duration: 0.3, afterSetup: this.onWindowResize.bind(this) });
355
-
356
- this.retrieveLocation(null, function(bounds) {
357
- pickupLoader.hide();
358
- pickupContent.show();
359
- this.isLoading = false;
360
- this.onWindowResize();
361
-
362
- this.googleMaps.setCenter(bounds.getCenter());
363
- this.googleMaps.fitBounds(bounds);
364
-
365
- try {
366
- var locationData = eval('(' + atob($('tss-ls-location-data').value) + ')');
367
-
368
- for (var i = 0; i < this.markers.length; i++) {
369
- if (this.markers[i].locationData.servicepoint_id == locationData.servicepoint_id) {
370
- this.selectedMarker = this.markers[i];
371
- break;
372
- }
373
- }
374
- }
375
- catch (e) {
376
- }
377
-
378
- }.bind(this), function (error) {
379
- if (this.isClosing) {
380
- return;
381
- }
382
- Transsmart.Logger.log('Transsmart_Shipping error: ' + error);
383
- pickupLoader.innerHTML = '<p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>' +
384
- Translator.translate('Error loading pickup location selector. Please try again.') +
385
- '<p>&nbsp;</p><p>&nbsp;</p>';
386
- }.bind(this));
387
- },
388
-
389
- /**
390
- * Get the current shipping address if possible.
391
- * Needed for LightCheckout when the quote address is not updated via AJAX.
392
- */
393
- getCurrentAddress: function () {
394
- var result = null;
395
-
396
- try {
397
- // determine address prefix
398
- var addressPrefix;
399
- var billingUseForShipping1 = $('billing_use_for_shipping_yes');
400
- var billingUseForShipping2 = $('billing:use_for_shipping_yes');
401
- var shippingSameAsBilling = $('shipping:same_as_billing');
402
- if (billingUseForShipping1) {
403
- addressPrefix = billingUseForShipping1.checked ? 'billing_' : 'shipping_';
404
- }
405
- else if (shippingSameAsBilling) {
406
- // if an address is selected in the address book, ignore the address fields
407
- var addressSelect = $((shippingSameAsBilling.checked ? 'billing' : 'shipping') + '-address-select');
408
- if (addressSelect && addressSelect.value) {
409
- return result;
410
- }
411
- addressPrefix = shippingSameAsBilling.checked ? 'billing:' : 'shipping:';
412
- }
413
- else if (billingUseForShipping2) {
414
- // if an address is selected in the address book, ignore the address fields
415
- var addressSelect = $((billingUseForShipping2.checked ? 'billing' : 'shipping') + '-address-select');
416
- if (addressSelect && addressSelect.value) {
417
- return result;
418
- }
419
- addressPrefix = billingUseForShipping2.checked ? 'billing:' : 'shipping:';
420
- }
421
- else if ($('shipping_postcode')) {
422
- addressPrefix = 'shipping_';
423
- }
424
- else if ($('shipping:postcode')) {
425
- addressPrefix = 'shipping:';
426
- }
427
- else if ($('billing_postcode')) {
428
- addressPrefix = 'billing_';
429
- }
430
- else {
431
- addressPrefix = 'billing:';
432
- }
433
-
434
- var postcode = $(addressPrefix + 'postcode');
435
- var city = $(addressPrefix + 'city');
436
- var street = $(addressPrefix + 'street1');
437
- var housenr = $(addressPrefix + 'street2');
438
-
439
- if (postcode) {
440
- result = postcode.value;
441
- if (city) {
442
- result += ',' + city.value;
443
- if (street) {
444
- result += ',' + street.value;
445
- if (housenr) {
446
- result += ',' + housenr.value;
447
- }
448
- }
449
- }
450
- }
451
- }
452
- catch (e) {
453
- }
454
-
455
- return result;
456
- },
457
-
458
- /**
459
- * Retrieves location and updates the map
460
- * @param searchValue
461
- * @param callback
462
- */
463
- retrieveLocation: function(searchValue, callback, errorCallback) {
464
- // Attach the selected shipping method
465
- var url = this.config.lookupUrl;
466
- url += '?shipping_method=' + encodeURIComponent(this.selectedShippingMethod);
467
-
468
- if (!searchValue) {
469
- searchValue = this.getCurrentAddress();
470
- }
471
-
472
- if (searchValue != null) {
473
- url += '&search=' + encodeURIComponent(searchValue);
474
- }
475
-
476
- this.ajaxRequest = new Ajax.Request(url, {
477
- onComplete: function (response) {
478
- try {
479
- if (!response.responseJSON) {
480
- return errorCallback('Empty server response');
481
- }
482
- if (response.responseJSON) {
483
- if (!response.responseJSON.result) {
484
- return errorCallback(response.responseJSON.error);
485
- }
486
- }
487
-
488
- // Reset the markers
489
- this.clearMapMarkers();
490
-
491
- var currentLocation = response.responseJSON.current_location;
492
- var originLatLng = currentLocation != null ? new google.maps.LatLng(currentLocation.lat, currentLocation.lng) : null;
493
-
494
- // parse the location
495
- var locations = response.responseJSON.locations;
496
-
497
- var bounds = new google.maps.LatLngBounds();
498
- var localMarkers = [];
499
-
500
- for (var i = 0; i < locations.length; i++) {
501
- var location = locations[i];
502
-
503
- // Add the location to google maps
504
- var latLng = new google.maps.LatLng(location.lat, location.lng);
505
- var distance = originLatLng != null ? google.maps.geometry.spherical.computeDistanceBetween(originLatLng, latLng) : null;
506
-
507
- // Create a marker
508
- var marker = new google.maps.Marker({
509
- position: latLng,
510
- title: location.Name,
511
-
512
- markerId: i,
513
- locationData: location,
514
- distance: distance
515
- });
516
-
517
- localMarkers.push(marker);
518
- }
519
-
520
- // Sort the markers
521
- localMarkers.sort(this.sortMarkersByDistance);
522
-
523
- for (i = 0; i < localMarkers.length; i++) {
524
- var localMarker = localMarkers[i];
525
-
526
- // Add the marker to the map
527
- localMarker.setMap(this.googleMaps);
528
-
529
- // Only add the 5 closest to the boundaries
530
- if (i < 5) {
531
- // Add the latitude and longitude to the bounds
532
- bounds.extend(localMarker.position);
533
- }
534
-
535
- // add click listener
536
- var self = this;
537
- localMarker.addListener('click', function() {
538
- self.setSelectedMarker(this);
539
- });
540
-
541
- // Store the market
542
- this.markers[localMarker.markerId] = localMarker;
543
-
544
- // Add the location to the list
545
- this.addLocationToList(localMarker.locationData, localMarker);
546
-
547
- if (!this.selectedMarker && localMarker.locationData.selected) {
548
- this.selectedMarker = localMarker;
549
- }
550
- }
551
-
552
- callback(bounds);
553
- this.setSelectedMarker(this.selectedMarker);
554
- }
555
- catch (e) {
556
- errorCallback(e);
557
- }
558
- }.bind(this)
559
- });
560
- },
561
-
562
- /**
563
- * Updates the map markers based on the filters
564
- */
565
- updateMapMarkers: function() {
566
- // Only update the markers if there are any
567
- if (this.markers.length == 0) {
568
- return;
569
- }
570
-
571
- var shouldShowOpenEarly = $('tss-ls-show-open-early').checked;
572
- var shouldShowOpenLate = $('tss-ls-show-open-late').checked;
573
- var shouldShowOpenSunday = $('tss-ls-show-open-sunday').checked;
574
- var shouldFilter = shouldShowOpenEarly || shouldShowOpenLate || shouldShowOpenSunday;
575
-
576
- var localMarkers = [];
577
-
578
- for (var i = 0; i < this.markers.length; i++) {
579
- var currentMarker = this.markers[i];
580
- if (currentMarker) {
581
- if (shouldFilter && !(
582
- (shouldShowOpenEarly && currentMarker.locationData.is_open_early) ||
583
- (shouldShowOpenLate && currentMarker.locationData.is_open_late) ||
584
- (shouldShowOpenSunday && currentMarker.locationData.is_open_sunday))) {
585
- currentMarker.setMap(null);
586
- continue;
587
- }
588
- localMarkers.push(currentMarker);
589
- }
590
- }
591
-
592
- // Remove all list items
593
- $(this.config.locationsListDivId).update('');
594
-
595
- // Sort the markers
596
- localMarkers.sort(this.sortMarkersByDistance);
597
-
598
- for (var x = 0; x < localMarkers.length; x++) {
599
- var localMarker = localMarkers[x];
600
-
601
- // Add them back to the map, only if they aren't already on it
602
- if (localMarker.getMap() == null) {
603
- localMarker.setMap(this.googleMaps);
604
- }
605
-
606
- this.addLocationToList(localMarker.locationData, localMarker);
607
- }
608
- },
609
-
610
- /**
611
- * Removes all markers from the map and list
612
- * and resets the marker array on the shipping object
613
- */
614
- clearMapMarkers: function() {
615
- for (var i = 0; i < this.markers.length; i++) {
616
- var currentMarker = this.markers[i];
617
- if (currentMarker) {
618
- currentMarker.setMap(null);
619
- this.markers[i] = null;
620
- }
621
- }
622
- this.markers = [];
623
-
624
- $(this.config.locationsListDivId).update('');
625
- this.setSelectedMarker(null);
626
- },
627
-
628
- /**
629
- * Triggered when a marker is selected.
630
- * Enables the select button when a marker has been select.
631
- * @param marker
632
- */
633
- setSelectedMarker: function(marker) {
634
- this.selectedMarker = marker;
635
-
636
- // Remove all other selected markers
637
- $$('.tss-ls-location-item[data-marker-id].selected').each(function(element) {
638
- Element.removeClassName(element, 'selected');
639
- });
640
-
641
- var selectButton = $(this.config.selectButtonId);
642
- if (marker) {
643
- selectButton.addClassName('active');
644
-
645
- var markerId = marker.markerId;
646
- var markerListItem = $$('.tss-ls-location-item[data-marker-id=' + markerId + ']')[0];
647
- markerListItem.addClassName('selected');
648
-
649
- var contentString = this.getInfoWindowContent(marker.locationData);
650
- this.infoWindow.setContent(contentString);
651
- this.infoWindow.open(this.googleMaps, marker);
652
-
653
- // scroll list item into view
654
- var parent = $(this.config.locationsListDivId);
655
- if (parent.scrollTop > markerListItem.offsetTop - parent.offsetTop) {
656
- //parent.scrollTop = markerListItem.offsetTop - parent.offsetTop;
657
- new Effect.Tween(parent, parent.scrollTop, markerListItem.offsetTop - parent.offsetTop, { duration: 0.3 }, 'scrollTop');
658
- }
659
- else if (parent.scrollTop + parent.offsetHeight < markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight) {
660
- //parent.scrollTop = markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight - parent.offsetHeight;
661
- new Effect.Tween(parent, parent.scrollTop, markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight - parent.offsetHeight, { duration: 0.3 }, 'scrollTop');
662
- }
663
- }
664
- else {
665
- selectButton.removeClassName('active');
666
- }
667
- },
668
-
669
- /**
670
- * Adds the location and the marker to the list of locations
671
- * @param location
672
- * @param marker
673
- */
674
- addLocationToList: function(location, marker) {
675
- var locationsListDiv = $(this.config.locationsListDivId);
676
-
677
- // Don't add it to the list if it's already there
678
- if (locationsListDiv.select('div[data-marker-id="' + marker.markerId + '"]').length != 0) {
679
- return;
680
- }
681
-
682
- var html = '<div class="tss-ls-location-item" data-marker-id="' + marker.markerId + '">' +
683
- '<span class="tss-ls-name">' +
684
- '<span class="tss-ls-company-name">' + location.name.escapeHTML() + '</span>' +
685
- '<span class="tss-ls-address">' + location.street.escapeHTML() + ' ' + location.street_no.escapeHTML() + ', ' + location.city.escapeHTML() + '</span>' +
686
- '</span>' +
687
- '<span class="tss-ls-distance">(' + this.getFormattedDistanceForMarker(marker) + ')</span>' +
688
- '<span class="tss-ls-check"><span class="tss-ls-img"></span></span>' +
689
- '</div>';
690
-
691
- locationsListDiv.insert(html);
692
-
693
- locationsListDiv.select('.tss-ls-location-item[data-marker-id=' + marker.markerId + ']')[0]
694
- .stopObserving('click')
695
- .observe('click', function(event) {
696
- new google.maps.event.trigger(marker, 'click');
697
-
698
- // Prevent the event from bubbling
699
- event.stop();
700
- });
701
- },
702
-
703
- /**
704
- * Formats the marker to meters or kilometers
705
- * @param marker
706
- * @returns {string}
707
- */
708
- getFormattedDistanceForMarker: function(marker) {
709
- if (marker.distance < 1000) {
710
- return String(Math.round(marker.distance)).replace('.', ',') + ' m'
711
- }
712
-
713
- return String(Math.round((marker.distance/1000) * 100)/100).replace('.', ',') + ' km';
714
- },
715
-
716
- /**
717
- * Sorts markers by distance
718
- * @param a
719
- * @param b
720
- */
721
- sortMarkersByDistance: function(a, b) {
722
- if (a.distance < b.distance)
723
- return -1;
724
- if (a.distance > b.distance)
725
- return 1;
726
-
727
- return 0;
728
- },
729
-
730
- /**
731
- * Returns the Google Map info window content
732
- * @param location
733
- * @returns {string}
734
- */
735
- getInfoWindowContent: function(location) {
736
- var openingHoursHtml = '';
737
-
738
- if (location.has_openinghours) {
739
- openingHoursHtml = Translator.translate('Opening hours:') + '<br />'
740
- + '<table class="tss-ls-openinghours-table">';
741
-
742
- // Add the opening hours
743
- for (var x = 0; x < location.openinghours.length; x++) {
744
- var openingHoursItem = location.openinghours[x];
745
-
746
- openingHoursHtml += '<tr>' +
747
- '<td style="padding-right:8px">' + openingHoursItem.day_name.escapeHTML() + '<td>' +
748
- '<td>' + openingHoursItem.display.escapeHTML() + '</td>' +
749
- '</tr>';
750
- }
751
-
752
- openingHoursHtml += '</table>';
753
- }
754
-
755
- var contentString = '<div id="content">'+
756
- '<h1 id="firstHeading" class="firstHeading">' + location.name.escapeHTML() + '</h1>'+
757
- '<div id="bodyContent">' +
758
- '<p>' +
759
- location.street.escapeHTML() + ' ' + location.street_no.escapeHTML() + '<br />' +
760
- location.zipcode.escapeHTML() + ' ' + location.city.escapeHTML() +
761
- (location.phone != null ? '<br />' + location.phone.escapeHTML() : '') +
762
- '</p>' +
763
- openingHoursHtml +
764
- '</div>' +
765
- '</div>';
766
-
767
- return contentString;
768
- },
769
-
770
- /**
771
- * Formats the location data into HTML
772
- * @param locationData
773
- * @returns {string}
774
- */
775
- formatLocationAddress: function(locationData) {
776
- var html = '<strong>' + locationData.name.escapeHTML() + '</strong> <br />';
777
- html += locationData.street.escapeHTML() + ' ' + locationData.street_no.escapeHTML() + '<br />';
778
- html += locationData.zipcode.escapeHTML() + ' ' + locationData.city.escapeHTML() + '<br />';
779
- html += (locationData.phone != null ? locationData.phone.escapeHTML() : '');
780
-
781
- return html;
782
- },
783
-
784
- /**
785
- * Triggered when the Google maps API has been loaded.
786
- * Create the map as soon as the API has been loaded
787
- */
788
- googleMapsLoaded: function() {
789
- this.googleMaps = new google.maps.Map($(this.config.googleMapsId), {
790
- zoom: 8,
791
- center: {lat: 52.0795, lng: 5.4492},
792
- disableDefaultUI: true,
793
- zoomControl: true,
794
- panControl: false,
795
- mapTypeId: google.maps.MapTypeId.ROADMAP
796
- });
797
-
798
- this.googleGeocoder = new google.maps.Geocoder();
799
- this.infoWindow = new google.maps.InfoWindow();
800
- },
801
-
802
- /**
803
- * Called when window is resized.
804
- */
805
- onWindowResize: function () {
806
- try {
807
- var container = $('tss-pickup-container');
808
- var containerHeight = container.offsetHeight;
809
- var selector = container.select('.tss-selector')[0];
810
- var headerHeight = container.select('.tss-ls-header')[0].offsetHeight;
811
- var footerHeight = container.select('.tss-ls-footer-controls')[0].offsetHeight;
812
- var padding = 20;
813
- var contentHeight = containerHeight - headerHeight - footerHeight - (padding * 2);
814
- var minContentHeight = (this.isLoading || this.isClosing) ? 212 : 131;
815
- if (contentHeight < minContentHeight) {
816
- padding = 20 - (minContentHeight - contentHeight);
817
- if (padding < 0) {
818
- padding = 0;
819
- }
820
- contentHeight = minContentHeight;
821
- }
822
- else if (contentHeight > 460) {
823
- contentHeight = 460;
824
- }
825
- if (this.isLoading || this.isClosing) {
826
- contentHeight = 212;
827
- headerHeight = 0;
828
- footerHeight = 0;
829
- }
830
- var marginTop = Math.round((containerHeight - contentHeight - headerHeight - footerHeight) / 2);
831
- if (marginTop < padding) {
832
- marginTop = padding;
833
- }
834
-
835
- selector.style.marginTop = marginTop + 'px';
836
- if (this.isLoading || this.isClosing) {
837
- return;
838
- }
839
- $('tss-ls-map').style.height = contentHeight + 'px';
840
- $('tss-ls-locations').style.height = (contentHeight - 68) + 'px';
841
- google.maps.event.trigger(this.googleMaps, 'resize');
842
- }
843
- catch (e) {}
844
- },
845
-
846
- /**
847
- * If a location has been selected, the location data is inserted into the input
848
- * and then closed off.
849
- */
850
- selectLocationAndClose: function() {
851
- if (this.selectedMarker != null && this.selectedMarker.locationData) {
852
- var locationData = this.selectedMarker.locationData;
853
- // TODO: btoa only supports Latin1 characters. Make this work with all UTF-8 characters.
854
- $('tss-ls-location-data').value = btoa(Object.toJSON(locationData));
855
- $(this.config.selectedLocationDivId).update(this.formatLocationAddress(locationData));
856
- this.close();
857
- this.origShippingMethod = this.selectedShippingMethod;
858
- this.origPickupDivHtml = $(this.config.shippingPickupContainerId).outerHTML;
859
-
860
- // submit LightCheckout shipping methods
861
- if (typeof window.Lightcheckout == 'function' && typeof window.checkout == 'object') {
862
- if (typeof window.checkout.submit == 'function' && typeof window.checkout.getFormData == 'function') {
863
- window.checkout.submit(window.checkout.getFormData(), 'get_totals');
864
- }
865
- }
866
- }
867
- },
868
-
869
- /**
870
- * Closes off the location selector box
871
- */
872
- close: function() {
873
- this.isClosing = true;
874
- var pickupContainer = $('tss-pickup-container');
875
- var pickupLoader = pickupContainer.select('.tss-loader')[0];
876
- var pickupContent = pickupContainer.select('.tss-selector-container')[0];
877
-
878
- // Reset the markers
879
- this.clearMapMarkers();
880
-
881
- pickupLoader.show();
882
- pickupContent.hide();
883
- this.onWindowResize();
884
-
885
- // Show the pickup container
886
- pickupContainer.appear({
887
- duration: 0.3,
888
- from: 1,
889
- to: 0,
890
- afterFinish: function () {
891
- pickupContainer.hide();
892
- }
893
- });
894
-
895
- if (this.ajaxRequest) {
896
- this.ajaxRequest.transport.abort();
897
- }
898
- }
899
- });
1
+ /**
2
+ * @category Transsmart
3
+ * @package Transsmart_Shipping
4
+ * @copyright Copyright (c) 2016 Techtwo Webdevelopment B.V. (http://www.techtwo.nl)
5
+ */
6
+ if (!Transsmart) var Transsmart = { };
7
+ if (!Transsmart.Shipping) Transsmart.Shipping = { };
8
+
9
+ Transsmart.Shipping.Pickup = Class.create({
10
+
11
+ /**
12
+ * Define configuration for the pickup shipping method
13
+ */
14
+ config: {
15
+ shippingMethodName: 'transsmartpickup',
16
+ shippingPickupContainerId: 'tss-location-selector',
17
+ shippingMethodLoadDivId: 'checkout-shipping-method-load',
18
+ locationsListDivId: 'tss-ls-locations',
19
+ googleMapsId: 'tss-ls-map',
20
+ selectButtonId: 'tss-ls-select',
21
+ closeButtonId: 'tss-ls-close',
22
+ shippingPickupSelectButtonId: 'tss-ls-select-location',
23
+ selectedLocationDivId: 'tss-ls-selected-location-info'
24
+ },
25
+
26
+ googleMaps: null,
27
+ googleGeocoder: null,
28
+ selectedShippingMethod: null,
29
+ markers: [],
30
+ infoWindow: null,
31
+ selectedMarker: null,
32
+ ajaxRequest: null,
33
+ isLoading: false,
34
+ isClosing: false,
35
+
36
+ origShippingMethod: null,
37
+ origPickupDivHtml: '',
38
+
39
+ /**
40
+ * Initialize the pickup location selector
41
+ */
42
+ initialize: function(config) {
43
+ // Check whether the viewUrl is provided
44
+ if (typeof config == 'undefined' || typeof config.lookupUrl == 'undefined') {
45
+ Transsmart.Logger.log('Transsmart_Shipping: Missing lookupUrl in the supplied config');
46
+ return;
47
+ }
48
+
49
+ // Set the view url
50
+ this.config.lookupUrl = config.lookupUrl;
51
+
52
+ // Check whether the carrierProfileIds is provided
53
+ if (typeof config == 'undefined' || typeof config.carrierProfileIds == 'undefined') {
54
+ Transsmart.Logger.log('Transsmart_Shipping: Missing carrierProfileIds in the supplied config');
55
+ return;
56
+ }
57
+
58
+ this.config.carrierProfileIds = config.carrierProfileIds;
59
+
60
+ this.attachListenHandler();
61
+ this.attachFilterHandlers();
62
+ this.attachSearchHandler();
63
+
64
+ // attach window resize handler
65
+ document.observe('dom:loaded', function() {
66
+ Event.observe(window, 'resize', this.onWindowResize.bind(this));
67
+ }.bind(this));
68
+
69
+ // observe ajax update event
70
+ Ajax.Responders.register({ onComplete: this.onAjaxComplete.bind(this) });
71
+ },
72
+
73
+ /**
74
+ * Attaches the listen handler so that we know when we should be
75
+ * showing the pickup selector popup.
76
+ */
77
+ attachListenHandler: function() {
78
+ var self = this;
79
+
80
+ // Attach click event to close button
81
+ $(this.config.closeButtonId).observe('click', function(event) {
82
+ self.close();
83
+ event.stop();
84
+ });
85
+
86
+ // Wait for the dom to be ready
87
+ document.observe('dom:loaded', function () {
88
+ // Add our custom validator
89
+ this.addValidators();
90
+
91
+ if (typeof checkout.gotoSection == 'function') {
92
+ // hook into Magento's OnePage checkout
93
+ var parentGotoSection = checkout.gotoSection.bind(checkout);
94
+
95
+ // Triggered when the checkout switches to the shipping method selection
96
+ checkout.gotoSection = function (section, reloadProgressBlock) {
97
+ // Remove the progress block when we switch to a different section
98
+ if (['billing', 'shipping', 'shipping_method'].indexOf(section) !== -1) {
99
+ if ($('tss-ls-progress-pickup-header')) {
100
+ $('tss-ls-progress-pickup-header').remove();
101
+ }
102
+
103
+ if ($('tss-ls-progress-pickup-content')) {
104
+ $('tss-ls-progress-pickup-content').remove();
105
+ }
106
+ }
107
+
108
+ if (section == 'shipping_method') {
109
+ this.updateShippingMethods();
110
+ }
111
+
112
+ parentGotoSection(section, reloadProgressBlock);
113
+ }.bind(this);
114
+ }
115
+
116
+ // The shipping methods are generated dynamically
117
+ // So we need to observe for dom changes and then trigger the click event based on that
118
+ $(document).on('click', 'input[name=shipping_method]', function (event, element) {
119
+ // Skip shipping methods that do not match the shipping method name
120
+ if (element.value && element.value.indexOf(self.config.shippingMethodName) == -1) {
121
+ this.removePickupDiv();
122
+ return;
123
+ }
124
+
125
+ this.selectedShippingMethod = element.value;
126
+ this.attachPickupDiv(element);
127
+ }.bind(this));
128
+
129
+ this.updateShippingMethods();
130
+
131
+ $(this.config.selectButtonId).observe('click', function (event) {
132
+ this.selectLocationAndClose();
133
+ event.stop();
134
+ }.bind(this));
135
+ }.bind(this));
136
+ },
137
+
138
+ onAjaxComplete: function () {
139
+ this.updateShippingMethods();
140
+ },
141
+
142
+ updateShippingMethods: function () {
143
+ // Check which shipping method has been selected
144
+ var checkedShippingMethods = $$('input[name=shipping_method]:checked');
145
+
146
+ if (checkedShippingMethods.length != 0) {
147
+ // The pre-selected shipping method is the pickup one.
148
+ // Attach the pickup div to the radio button
149
+ if (checkedShippingMethods[0].value.indexOf(this.config.shippingMethodName) != -1) {
150
+ this.selectedShippingMethod = checkedShippingMethods[0].value;
151
+ this.attachPickupDiv(checkedShippingMethods[0]);
152
+ }
153
+ }
154
+ },
155
+
156
+ /**
157
+ * The filter handlers determine which markers should be shown
158
+ */
159
+ attachFilterHandlers: function() {
160
+ $('tss-ls-show-open-early').observe('click', this.updateMapMarkers.bind(this));
161
+ $('tss-ls-show-open-late').observe('click', this.updateMapMarkers.bind(this));
162
+ $('tss-ls-show-open-sunday').observe('click', this.updateMapMarkers.bind(this));
163
+ },
164
+
165
+ /**
166
+ * Attaches the search handler
167
+ */
168
+ attachSearchHandler: function() {
169
+ $('tss-ls-search-btn').observe('click', this.attachSearch.bind(this));
170
+ $('tss-ls-search').observe('keypress', this.attachSearch.bind(this));
171
+ },
172
+
173
+ /**
174
+ * Perform search
175
+ * @param event
176
+ */
177
+ attachSearch: function (event) {
178
+ if (event.type == 'keypress' && event.keyCode != Event.KEY_RETURN) {
179
+ return;
180
+ }
181
+
182
+ var searchField = $('tss-ls-search');
183
+ var searchButton = $('tss-ls-search-btn');
184
+
185
+ var searchValue = searchField.value;
186
+ if (searchValue == '') {
187
+ return;
188
+ }
189
+
190
+ searchField.disabled = true;
191
+ searchField.addClassName('disabled');
192
+ searchButton.disabled = true;
193
+ searchButton.addClassName('disabled');
194
+
195
+ this.retrieveLocation(searchValue, function (bounds) {
196
+ searchField.disabled = false;
197
+ searchField.removeClassName('disabled');
198
+ searchButton.disabled = false;
199
+ searchButton.removeClassName('disabled');
200
+
201
+ this.updateMapMarkers();
202
+
203
+ google.maps.event.trigger(this.googleMaps, 'resize');
204
+ this.googleMaps.setCenter(bounds.getCenter());
205
+ this.googleMaps.fitBounds(bounds);
206
+
207
+ }.bind(this),
208
+ function (error) {
209
+ searchField.disabled = false;
210
+ searchField.removeClassName('disabled');
211
+ searchButton.disabled = false;
212
+ searchButton.removeClassName('disabled');
213
+
214
+ if (this.isClosing) {
215
+ return;
216
+ }
217
+ Transsmart.Logger.log('Transsmart_Shipping error: ' + error);
218
+ alert(Translator.translate('Search did not succeed. Please try again.'));
219
+
220
+ }.bind(this));
221
+ },
222
+
223
+ /**
224
+ * Attaches the pickup location selector div to the parent item of the input element.
225
+ * @param inputElement The input radio element that's part of a carrier
226
+ */
227
+ attachPickupDiv: function(inputElement) {
228
+ var containerItem = $(this.config.shippingPickupContainerId);
229
+
230
+ // Remove the shipping pickup div if it exists
231
+ if (containerItem) {
232
+ containerItem.remove();
233
+ }
234
+
235
+ var valueBits = inputElement.value.match(/transsmartpickup_carrierprofile_([0-9]+)/);
236
+
237
+ // Nothing to attach, it doesn't match
238
+ if (valueBits == null || valueBits.length != 2) {
239
+ return;
240
+ }
241
+
242
+ // Not a carrierprofile that has location selector enabled
243
+ if (this.config.carrierProfileIds.indexOf(valueBits[1]) == -1) {
244
+ Transsmart.Logger.log('Carrier profile with id: ' + valueBits[1] + ' does not allow location selector');
245
+ Transsmart.Logger.log('Allowed location selectors are: ', this.config.carrierProfileIds);
246
+ return;
247
+ }
248
+
249
+ // Find the container for transsmart pickup shipping method
250
+ var shippingMethodContainer = this.getButtonContainer(inputElement);
251
+ if (typeof shippingMethodContainer == 'undefined') {
252
+ Transsmart.Logger.log('Transsmart.Shipping: ' +
253
+ Translator.translate('Could not find shipping container for ' + this.config.shippingMethodName));
254
+ return;
255
+ }
256
+
257
+ // insert the location selector button
258
+ shippingMethodContainer.insert(this.getPickupDiv());
259
+ $(this.config.shippingPickupSelectButtonId).observe('click', function(event) {
260
+ this.showLocationPopUp();
261
+ event.stop();
262
+ }.bind(this));
263
+ },
264
+
265
+ /**
266
+ * Find the container for transsmart pickup shipping method button
267
+ *
268
+ * @param inputElement
269
+ */
270
+ getButtonContainer: function (inputElement) {
271
+ // Find the container for transsmart pickup shipping method
272
+ var buttonContainer = inputElement.up('dd, div');
273
+ return buttonContainer;
274
+ },
275
+
276
+ /**
277
+ * Removes the pickup div element
278
+ */
279
+ removePickupDiv: function() {
280
+ var containerItem = $(this.config.shippingPickupContainerId);
281
+
282
+ if (containerItem != null) {
283
+ containerItem.remove();
284
+ }
285
+ },
286
+
287
+ /**
288
+ * Returns the div that is used near the shipping radio button
289
+ * @returns {string}
290
+ */
291
+ getPickupDiv: function() {
292
+ if (this.origPickupDivHtml == '' || this.origShippingMethod != this.selectedShippingMethod) {
293
+ this.origShippingMethod = this.selectedShippingMethod;
294
+ this.origPickupDivHtml = '<div id="' + this.config.shippingPickupContainerId + '">' +
295
+ '<button id="' + this.config.shippingPickupSelectButtonId + '" class="tss-ls-select-location button" onclick="return false">' +
296
+ '<span><span>' +
297
+ Translator.translate('Select pickup location') +
298
+ '</span></span>' +
299
+ '</button>' +
300
+ '<div id="' + this.config.selectedLocationDivId + '"></div>' +
301
+ '<input id="tss-ls-location-data" name="transsmart_pickup_address_data" type="hidden" class="validate-selected-location" />' +
302
+ '</div>';
303
+ }
304
+ return this.origPickupDivHtml;
305
+ },
306
+
307
+ /**
308
+ * Adds the required validators to the validation class.
309
+ */
310
+ addValidators: function() {
311
+ Validation.add(
312
+ 'validate-selected-location',
313
+ Translator.translate("A pickup location has to be selected"),
314
+ function(v) {
315
+ return !Validation.get('IsEmpty').test(v);
316
+ });
317
+ },
318
+
319
+ /**
320
+ * Shows the pickup location selector popup
321
+ */
322
+ showLocationPopUp: function() {
323
+ var pickupContainer = $('tss-pickup-container');
324
+ var pickupLoader = pickupContainer.select('.tss-loader')[0];
325
+ var pickupContent = pickupContainer.select('.tss-selector-container')[0];
326
+
327
+ this.isClosing = false;
328
+ if (this.originalLoaderHtml) {
329
+ pickupLoader.innerHTML = this.originalLoaderHtml;
330
+ }
331
+ else {
332
+ this.originalLoaderHtml = pickupLoader.innerHTML;
333
+ }
334
+
335
+ // remove validation advice
336
+ $$('#' + this.config.shippingPickupContainerId + ' .validation-advice').each(function(item) {
337
+ new Effect.Fade(item);
338
+ });
339
+
340
+ // Reset the markers
341
+ this.clearMapMarkers();
342
+
343
+ // Reset input fields
344
+ $('tss-ls-search').value = '';
345
+ $('tss-ls-show-open-early').checked = false;
346
+ $('tss-ls-show-open-late').checked = false;
347
+ $('tss-ls-show-open-sunday').checked = false;
348
+
349
+ pickupLoader.show();
350
+ pickupContent.hide();
351
+ this.isLoading = true;
352
+
353
+ // Show the pickup container
354
+ pickupContainer.appear({ duration: 0.3, afterSetup: this.onWindowResize.bind(this) });
355
+
356
+ this.retrieveLocation(null, function(bounds) {
357
+ pickupLoader.hide();
358
+ pickupContent.show();
359
+ this.isLoading = false;
360
+ this.onWindowResize();
361
+
362
+ this.googleMaps.setCenter(bounds.getCenter());
363
+ this.googleMaps.fitBounds(bounds);
364
+
365
+ try {
366
+ var locationData = eval('(' + atob($('tss-ls-location-data').value) + ')');
367
+
368
+ for (var i = 0; i < this.markers.length; i++) {
369
+ if (this.markers[i].locationData.servicepoint_id == locationData.servicepoint_id) {
370
+ this.selectedMarker = this.markers[i];
371
+ break;
372
+ }
373
+ }
374
+ }
375
+ catch (e) {
376
+ }
377
+
378
+ }.bind(this), function (error) {
379
+ if (this.isClosing) {
380
+ return;
381
+ }
382
+ Transsmart.Logger.log('Transsmart_Shipping error: ' + error);
383
+ pickupLoader.innerHTML = '<p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>' +
384
+ Translator.translate('Error loading pickup location selector. Please try again.') +
385
+ '<p>&nbsp;</p><p>&nbsp;</p>';
386
+ }.bind(this));
387
+ },
388
+
389
+ /**
390
+ * Get the current shipping address if possible.
391
+ * Needed for LightCheckout when the quote address is not updated via AJAX.
392
+ */
393
+ getCurrentAddress: function () {
394
+ var result = {};
395
+
396
+ try {
397
+ // determine address prefix
398
+ var addressPrefix;
399
+ var billingUseForShipping1 = $('billing_use_for_shipping_yes');
400
+ var billingUseForShipping2 = $('billing:use_for_shipping_yes');
401
+ var shippingSameAsBilling = $('shipping:same_as_billing');
402
+ if (billingUseForShipping1) {
403
+ addressPrefix = billingUseForShipping1.checked ? 'billing_' : 'shipping_';
404
+ }
405
+ else if (shippingSameAsBilling) {
406
+ // if an address is selected in the address book, ignore the address fields
407
+ var addressSelect = $((shippingSameAsBilling.checked ? 'billing' : 'shipping') + '-address-select');
408
+ if (addressSelect && addressSelect.value) {
409
+ return result;
410
+ }
411
+ addressPrefix = shippingSameAsBilling.checked ? 'billing:' : 'shipping:';
412
+ }
413
+ else if (billingUseForShipping2) {
414
+ // if an address is selected in the address book, ignore the address fields
415
+ var addressSelect = $((billingUseForShipping2.checked ? 'billing' : 'shipping') + '-address-select');
416
+ if (addressSelect && addressSelect.value) {
417
+ return result;
418
+ }
419
+ addressPrefix = billingUseForShipping2.checked ? 'billing:' : 'shipping:';
420
+ }
421
+ else if ($('shipping_postcode')) {
422
+ addressPrefix = 'shipping_';
423
+ }
424
+ else if ($('shipping:postcode')) {
425
+ addressPrefix = 'shipping:';
426
+ }
427
+ else if ($('billing_postcode')) {
428
+ addressPrefix = 'billing_';
429
+ }
430
+ else {
431
+ addressPrefix = 'billing:';
432
+ }
433
+
434
+ result.country = $(addressPrefix + 'country_id').value;
435
+ result.zipcode = $(addressPrefix + 'postcode').value;
436
+ result.city = $(addressPrefix + 'city').value;
437
+ result.street = $(addressPrefix + 'street1').value;
438
+ result.housenr = $(addressPrefix + 'street2').value;
439
+ }
440
+ catch (e) {
441
+ }
442
+
443
+ return result;
444
+ },
445
+
446
+ /**
447
+ * Retrieves location and updates the map
448
+ * @param searchValue
449
+ * @param callback
450
+ */
451
+ retrieveLocation: function(searchValue, callback, errorCallback) {
452
+ // Attach the selected shipping method
453
+ var url = this.config.lookupUrl;
454
+ var params = {
455
+ shipping_method: this.selectedShippingMethod,
456
+ };
457
+
458
+ if (searchValue != null) {
459
+ params.search = searchValue;
460
+ }
461
+ else {
462
+ params = Object.extend(params, this.getCurrentAddress());
463
+ }
464
+
465
+ this.ajaxRequest = new Ajax.Request(url, {
466
+ parameters: params,
467
+ method: 'get',
468
+ onComplete: function (response) {
469
+ try {
470
+ if (!response.responseJSON) {
471
+ return errorCallback('Empty server response');
472
+ }
473
+ if (response.responseJSON) {
474
+ if (!response.responseJSON.result) {
475
+ return errorCallback(response.responseJSON.error);
476
+ }
477
+ }
478
+
479
+ // Reset the markers
480
+ this.clearMapMarkers();
481
+
482
+ var currentLocation = response.responseJSON.current_location;
483
+ var originLatLng = currentLocation != null ? new google.maps.LatLng(currentLocation.lat, currentLocation.lng) : null;
484
+
485
+ // parse the location
486
+ var locations = response.responseJSON.locations;
487
+
488
+ var bounds = new google.maps.LatLngBounds();
489
+ var localMarkers = [];
490
+
491
+ for (var i = 0; i < locations.length; i++) {
492
+ var location = locations[i];
493
+
494
+ // Add the location to google maps
495
+ var latLng = new google.maps.LatLng(location.lat, location.lng);
496
+ var distance = originLatLng != null ? google.maps.geometry.spherical.computeDistanceBetween(originLatLng, latLng) : null;
497
+
498
+ // Create a marker
499
+ var marker = new google.maps.Marker({
500
+ position: latLng,
501
+ title: location.Name,
502
+
503
+ markerId: i,
504
+ locationData: location,
505
+ distance: distance
506
+ });
507
+
508
+ localMarkers.push(marker);
509
+ }
510
+
511
+ // Sort the markers
512
+ localMarkers.sort(this.sortMarkersByDistance);
513
+
514
+ for (i = 0; i < localMarkers.length; i++) {
515
+ var localMarker = localMarkers[i];
516
+
517
+ // Add the marker to the map
518
+ localMarker.setMap(this.googleMaps);
519
+
520
+ // Only add the 5 closest to the boundaries
521
+ if (i < 5) {
522
+ // Add the latitude and longitude to the bounds
523
+ bounds.extend(localMarker.position);
524
+ }
525
+
526
+ // add click listener
527
+ var self = this;
528
+ localMarker.addListener('click', function() {
529
+ self.setSelectedMarker(this);
530
+ });
531
+
532
+ // Store the market
533
+ this.markers[localMarker.markerId] = localMarker;
534
+
535
+ // Add the location to the list
536
+ this.addLocationToList(localMarker.locationData, localMarker);
537
+
538
+ if (!this.selectedMarker && localMarker.locationData.selected) {
539
+ this.selectedMarker = localMarker;
540
+ }
541
+ }
542
+
543
+ callback(bounds);
544
+ this.setSelectedMarker(this.selectedMarker);
545
+ }
546
+ catch (e) {
547
+ errorCallback(e);
548
+ }
549
+ }.bind(this)
550
+ });
551
+ },
552
+
553
+ /**
554
+ * Updates the map markers based on the filters
555
+ */
556
+ updateMapMarkers: function() {
557
+ // Only update the markers if there are any
558
+ if (this.markers.length == 0) {
559
+ return;
560
+ }
561
+
562
+ var shouldShowOpenEarly = $('tss-ls-show-open-early').checked;
563
+ var shouldShowOpenLate = $('tss-ls-show-open-late').checked;
564
+ var shouldShowOpenSunday = $('tss-ls-show-open-sunday').checked;
565
+ var shouldFilter = shouldShowOpenEarly || shouldShowOpenLate || shouldShowOpenSunday;
566
+
567
+ var localMarkers = [];
568
+
569
+ for (var i = 0; i < this.markers.length; i++) {
570
+ var currentMarker = this.markers[i];
571
+ if (currentMarker) {
572
+ if (shouldFilter && !(
573
+ (shouldShowOpenEarly && currentMarker.locationData.is_open_early) ||
574
+ (shouldShowOpenLate && currentMarker.locationData.is_open_late) ||
575
+ (shouldShowOpenSunday && currentMarker.locationData.is_open_sunday))) {
576
+ currentMarker.setMap(null);
577
+ continue;
578
+ }
579
+ localMarkers.push(currentMarker);
580
+ }
581
+ }
582
+
583
+ // Remove all list items
584
+ $(this.config.locationsListDivId).update('');
585
+
586
+ // Sort the markers
587
+ localMarkers.sort(this.sortMarkersByDistance);
588
+
589
+ for (var x = 0; x < localMarkers.length; x++) {
590
+ var localMarker = localMarkers[x];
591
+
592
+ // Add them back to the map, only if they aren't already on it
593
+ if (localMarker.getMap() == null) {
594
+ localMarker.setMap(this.googleMaps);
595
+ }
596
+
597
+ this.addLocationToList(localMarker.locationData, localMarker);
598
+ }
599
+ },
600
+
601
+ /**
602
+ * Removes all markers from the map and list
603
+ * and resets the marker array on the shipping object
604
+ */
605
+ clearMapMarkers: function() {
606
+ for (var i = 0; i < this.markers.length; i++) {
607
+ var currentMarker = this.markers[i];
608
+ if (currentMarker) {
609
+ currentMarker.setMap(null);
610
+ this.markers[i] = null;
611
+ }
612
+ }
613
+ this.markers = [];
614
+
615
+ $(this.config.locationsListDivId).update('');
616
+ this.setSelectedMarker(null);
617
+ },
618
+
619
+ /**
620
+ * Triggered when a marker is selected.
621
+ * Enables the select button when a marker has been select.
622
+ * @param marker
623
+ */
624
+ setSelectedMarker: function(marker) {
625
+ this.selectedMarker = marker;
626
+
627
+ // Remove all other selected markers
628
+ $$('.tss-ls-location-item[data-marker-id].selected').each(function(element) {
629
+ Element.removeClassName(element, 'selected');
630
+ });
631
+
632
+ var selectButton = $(this.config.selectButtonId);
633
+ if (marker) {
634
+ selectButton.addClassName('active');
635
+
636
+ var markerId = marker.markerId;
637
+ var markerListItem = $$('.tss-ls-location-item[data-marker-id=' + markerId + ']')[0];
638
+ markerListItem.addClassName('selected');
639
+
640
+ var contentString = this.getInfoWindowContent(marker.locationData);
641
+ this.infoWindow.setContent(contentString);
642
+ this.infoWindow.open(this.googleMaps, marker);
643
+
644
+ // scroll list item into view
645
+ var parent = $(this.config.locationsListDivId);
646
+ if (parent.scrollTop > markerListItem.offsetTop - parent.offsetTop) {
647
+ //parent.scrollTop = markerListItem.offsetTop - parent.offsetTop;
648
+ new Effect.Tween(parent, parent.scrollTop, markerListItem.offsetTop - parent.offsetTop, { duration: 0.3 }, 'scrollTop');
649
+ }
650
+ else if (parent.scrollTop + parent.offsetHeight < markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight) {
651
+ //parent.scrollTop = markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight - parent.offsetHeight;
652
+ new Effect.Tween(parent, parent.scrollTop, markerListItem.offsetTop - parent.offsetTop + markerListItem.offsetHeight - parent.offsetHeight, { duration: 0.3 }, 'scrollTop');
653
+ }
654
+ }
655
+ else {
656
+ selectButton.removeClassName('active');
657
+ }
658
+ },
659
+
660
+ /**
661
+ * Adds the location and the marker to the list of locations
662
+ * @param location
663
+ * @param marker
664
+ */
665
+ addLocationToList: function(location, marker) {
666
+ var locationsListDiv = $(this.config.locationsListDivId);
667
+
668
+ // Don't add it to the list if it's already there
669
+ if (locationsListDiv.select('div[data-marker-id="' + marker.markerId + '"]').length != 0) {
670
+ return;
671
+ }
672
+
673
+ var html = '<div class="tss-ls-location-item" data-marker-id="' + marker.markerId + '">' +
674
+ '<span class="tss-ls-name">' +
675
+ '<span class="tss-ls-company-name">' + location.name.escapeHTML() + '</span>' +
676
+ '<span class="tss-ls-address">' + location.street.escapeHTML() + ' ' + location.street_no.escapeHTML() + ', ' + location.city.escapeHTML() + '</span>' +
677
+ '</span>' +
678
+ '<span class="tss-ls-distance">(' + this.getFormattedDistanceForMarker(marker) + ')</span>' +
679
+ '<span class="tss-ls-check"><span class="tss-ls-img"></span></span>' +
680
+ '</div>';
681
+
682
+ locationsListDiv.insert(html);
683
+
684
+ locationsListDiv.select('.tss-ls-location-item[data-marker-id=' + marker.markerId + ']')[0]
685
+ .stopObserving('click')
686
+ .observe('click', function(event) {
687
+ new google.maps.event.trigger(marker, 'click');
688
+
689
+ // Prevent the event from bubbling
690
+ event.stop();
691
+ });
692
+ },
693
+
694
+ /**
695
+ * Formats the marker to meters or kilometers
696
+ * @param marker
697
+ * @returns {string}
698
+ */
699
+ getFormattedDistanceForMarker: function(marker) {
700
+ if (marker.distance < 1000) {
701
+ return String(Math.round(marker.distance)).replace('.', ',') + ' m'
702
+ }
703
+
704
+ return String(Math.round((marker.distance/1000) * 100)/100).replace('.', ',') + ' km';
705
+ },
706
+
707
+ /**
708
+ * Sorts markers by distance
709
+ * @param a
710
+ * @param b
711
+ */
712
+ sortMarkersByDistance: function(a, b) {
713
+ if (a.distance < b.distance)
714
+ return -1;
715
+ if (a.distance > b.distance)
716
+ return 1;
717
+
718
+ return 0;
719
+ },
720
+
721
+ /**
722
+ * Returns the Google Map info window content
723
+ * @param location
724
+ * @returns {string}
725
+ */
726
+ getInfoWindowContent: function(location) {
727
+ var openingHoursHtml = '';
728
+
729
+ if (location.has_openinghours) {
730
+ openingHoursHtml = Translator.translate('Opening hours:') + '<br />'
731
+ + '<table class="tss-ls-openinghours-table">';
732
+
733
+ // Add the opening hours
734
+ for (var x = 0; x < location.openinghours.length; x++) {
735
+ var openingHoursItem = location.openinghours[x];
736
+
737
+ openingHoursHtml += '<tr>' +
738
+ '<td style="padding-right:8px">' + openingHoursItem.day_name.escapeHTML() + '<td>' +
739
+ '<td>' + openingHoursItem.display.escapeHTML() + '</td>' +
740
+ '</tr>';
741
+ }
742
+
743
+ openingHoursHtml += '</table>';
744
+ }
745
+
746
+ var contentString = '<div id="content">'+
747
+ '<h1 id="firstHeading" class="firstHeading">' + location.name.escapeHTML() + '</h1>'+
748
+ '<div id="bodyContent">' +
749
+ '<p>' +
750
+ location.street.escapeHTML() + ' ' + location.street_no.escapeHTML() + '<br />' +
751
+ location.zipcode.escapeHTML() + ' ' + location.city.escapeHTML() +
752
+ (location.phone != null ? '<br />' + location.phone.escapeHTML() : '') +
753
+ '</p>' +
754
+ openingHoursHtml +
755
+ '</div>' +
756
+ '</div>';
757
+
758
+ return contentString;
759
+ },
760
+
761
+ /**
762
+ * Formats the location data into HTML
763
+ * @param locationData
764
+ * @returns {string}
765
+ */
766
+ formatLocationAddress: function(locationData) {
767
+ var html = '<strong>' + locationData.name.escapeHTML() + '</strong> <br />';
768
+ html += locationData.street.escapeHTML() + ' ' + locationData.street_no.escapeHTML() + '<br />';
769
+ html += locationData.zipcode.escapeHTML() + ' ' + locationData.city.escapeHTML() + '<br />';
770
+ html += (locationData.phone != null ? locationData.phone.escapeHTML() : '');
771
+
772
+ return html;
773
+ },
774
+
775
+ /**
776
+ * Triggered when the Google maps API has been loaded.
777
+ * Create the map as soon as the API has been loaded
778
+ */
779
+ googleMapsLoaded: function() {
780
+ this.googleMaps = new google.maps.Map($(this.config.googleMapsId), {
781
+ zoom: 8,
782
+ center: {lat: 52.0795, lng: 5.4492},
783
+ disableDefaultUI: true,
784
+ zoomControl: true,
785
+ panControl: false,
786
+ mapTypeId: google.maps.MapTypeId.ROADMAP
787
+ });
788
+
789
+ this.googleGeocoder = new google.maps.Geocoder();
790
+ this.infoWindow = new google.maps.InfoWindow();
791
+ },
792
+
793
+ /**
794
+ * Called when window is resized.
795
+ */
796
+ onWindowResize: function () {
797
+ try {
798
+ var container = $('tss-pickup-container');
799
+ var containerHeight = container.offsetHeight;
800
+ var selector = container.select('.tss-selector')[0];
801
+ var headerHeight = container.select('.tss-ls-header')[0].offsetHeight;
802
+ var footerHeight = container.select('.tss-ls-footer-controls')[0].offsetHeight;
803
+ var padding = 20;
804
+ var contentHeight = containerHeight - headerHeight - footerHeight - (padding * 2);
805
+ var minContentHeight = (this.isLoading || this.isClosing) ? 212 : 131;
806
+ if (contentHeight < minContentHeight) {
807
+ padding = 20 - (minContentHeight - contentHeight);
808
+ if (padding < 0) {
809
+ padding = 0;
810
+ }
811
+ contentHeight = minContentHeight;
812
+ }
813
+ else if (contentHeight > 460) {
814
+ contentHeight = 460;
815
+ }
816
+ if (this.isLoading || this.isClosing) {
817
+ contentHeight = 212;
818
+ headerHeight = 0;
819
+ footerHeight = 0;
820
+ }
821
+ var marginTop = Math.round((containerHeight - contentHeight - headerHeight - footerHeight) / 2);
822
+ if (marginTop < padding) {
823
+ marginTop = padding;
824
+ }
825
+
826
+ selector.style.marginTop = marginTop + 'px';
827
+ if (this.isLoading || this.isClosing) {
828
+ return;
829
+ }
830
+ $('tss-ls-map').style.height = contentHeight + 'px';
831
+ $('tss-ls-locations').style.height = (contentHeight - 68) + 'px';
832
+ google.maps.event.trigger(this.googleMaps, 'resize');
833
+ }
834
+ catch (e) {}
835
+ },
836
+
837
+ /**
838
+ * If a location has been selected, the location data is inserted into the input
839
+ * and then closed off.
840
+ */
841
+ selectLocationAndClose: function() {
842
+ if (this.selectedMarker != null && this.selectedMarker.locationData) {
843
+ var locationData = this.selectedMarker.locationData;
844
+ // TODO: btoa only supports Latin1 characters. Make this work with all UTF-8 characters.
845
+ $('tss-ls-location-data').value = btoa(Object.toJSON(locationData));
846
+ $(this.config.selectedLocationDivId).update(this.formatLocationAddress(locationData));
847
+ this.close();
848
+ this.origShippingMethod = this.selectedShippingMethod;
849
+ this.origPickupDivHtml = $(this.config.shippingPickupContainerId).outerHTML;
850
+
851
+ // submit LightCheckout shipping methods
852
+ if (typeof window.Lightcheckout == 'function' && typeof window.checkout == 'object') {
853
+ if (typeof window.checkout.submit == 'function' && typeof window.checkout.getFormData == 'function') {
854
+ window.checkout.submit(window.checkout.getFormData(), 'get_totals');
855
+ }
856
+ }
857
+ }
858
+ },
859
+
860
+ /**
861
+ * Closes off the location selector box
862
+ */
863
+ close: function() {
864
+ this.isClosing = true;
865
+ var pickupContainer = $('tss-pickup-container');
866
+ var pickupLoader = pickupContainer.select('.tss-loader')[0];
867
+ var pickupContent = pickupContainer.select('.tss-selector-container')[0];
868
+
869
+ // Reset the markers
870
+ this.clearMapMarkers();
871
+
872
+ pickupLoader.show();
873
+ pickupContent.hide();
874
+ this.onWindowResize();
875
+
876
+ // Show the pickup container
877
+ pickupContainer.appear({
878
+ duration: 0.3,
879
+ from: 1,
880
+ to: 0,
881
+ afterFinish: function () {
882
+ pickupContainer.hide();
883
+ }
884
+ });
885
+
886
+ if (this.ajaxRequest) {
887
+ this.ajaxRequest.transport.abort();
888
+ }
889
+ }
890
+ });
 
 
 
 
 
 
 
 
 
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Transsmart_Shipping</name>
4
- <version>1.0.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Transsmart Magento connector</summary>
10
  <description>Integrates Transsmart Shipping into Magento.</description>
11
- <notes>1.0.0</notes>
12
  <authors><author><name>Techtwo Webdevelopment B.V.</name><user>techtwo</user><email>info@techtwo.nl</email></author><author><name>Bastiaan Heeren</name><user>techtwobastiaan</user><email>bastiaan@techtwo.nl</email></author></authors>
13
- <date>2016-01-14</date>
14
- <time>12:50:12</time>
15
- <contents><target name="magecommunity"><dir name="Transsmart"><dir name="Shipping"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="bafce0b64ee9545b3a355df1b0b8e18d"/><dir name="Shipment"><dir name="Create"><file name="Detail.php" hash="b8b8b391b781f5d9de8b2578ad84d540"/><file name="Package.php" hash="7054391262f4bcc78d77bbd8d7131d61"/></dir><dir name="Masscreate"><file name="Form.php" hash="1bef6372fca204ba939fca5a02f3fa3d"/></dir><file name="Masscreate.php" hash="244adc0427800e5df7ea050947cff0d5"/><dir name="View"><file name="Detail.php" hash="0c5a780a5a4095164b02b06a5cd5ec16"/><file name="Package.php" hash="ccdda1fc1a9710ff1d317575fd53baa7"/></dir></dir><dir name="View"><dir name="Tab"><file name="Shipments.php" hash="e8b2006ed7c6541ea61c309123457c7c"/></dir></dir></dir><dir name="Shipment"><dir name="Grid"><dir name="Renderer"><file name="Link.php" hash="f42b111af0b6fa7dbdd171b9ef9f5655"/></dir></dir><file name="Grid.php" hash="931e2c538a9f61c62fc838d441419c48"/></dir></dir><dir name="Shipping"><dir name="Location"><file name="Info.php" hash="fa01c870d4a5cd521ed312a447f10dda"/></dir></dir><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Fetch.php" hash="43361767a4367c59fea55c23bb52aaed"/></dir><dir name="Fieldset"><dir name="Carrierprofile"><file name="Header.php" hash="01bda5320d4fcb5493f7fc2fd7ec01ac"/></dir><file name="Carrierprofile.php" hash="a75608f6b98458f1797d41d24a52030b"/><file name="Versioninfo.php" hash="84f740e55f0abc8fda7d95d26a638214"/></dir></dir></dir></dir></dir><dir name="Location"><file name="Selector.php" hash="f13d261827cb806fcc14c73058128653"/></dir></dir><dir name="Helper"><file name="Data.php" hash="32590b34298ed7ee39ebc011485e970e"/><file name="Location.php" hash="59dd6de96da501192e995f3688cba950"/><file name="Pickupaddress.php" hash="c71ad4ae7e2c4536a2d57c18d57b8919"/><file name="Shipment.php" hash="1b18a32b3215efa4e0e737d7378e8d1e"/></dir><dir name="Model"><file name="Abstract.php" hash="5b8973d5f3ce40cd641e9f16cdcd6620"/><dir name="Adminhtml"><file name="Observer.php" hash="308cd5a5688d799b3227fcc06cfe0a29"/><dir name="System"><dir name="Config"><dir name="Backend"><file name="Localized.php" hash="3f7ee8815b1f71168ba3fe2f2eb6389f"/></dir><dir name="Source"><dir name="Basedata"><file name="Abstract.php" hash="ac0c0632d16278357cc4128b3a5ef9a8"/><file name="Carrierprofile.php" hash="f01d6e81905f9481a8906253ccfc24e3"/><file name="Costcenter.php" hash="4dabd6942ab4e27e8c7e7032e3d01ca9"/><file name="Emailtype.php" hash="5d5d02c41970795f42e86ec4184a1072"/><file name="Incoterm.php" hash="8724e4b8bd9267fe843d62ffaa939b1e"/><file name="Packagetype.php" hash="6277448d89f3eeaae2dd15dd8a318af1"/><file name="Shipmentlocation.php" hash="f025e24746908e9c5aea82109f3b79fa"/></dir><file name="Environment.php" hash="4d011d8f728c3582022178da0c26ea66"/><dir name="Mapping"><file name="Attribute.php" hash="f2302357356f4c4b6f43cc63c408722a"/><file name="Street.php" hash="e42fa0ede4bc76876cf0c1f783189e87"/></dir><file name="Method.php" hash="672e247ef3764ff9294607102b152c78"/></dir></dir></dir></dir><file name="Carrier.php" hash="9aac846543c6b82cd3a06f9e307593ae"/><file name="Carrierprofile.php" hash="fb3bc266d34c00dbc10b76e89f6de20f"/><file name="Client.php" hash="2042bb6b78e29c41356f8e3ac7e0bbb0"/><file name="Costcenter.php" hash="bf6a9a5a95fa7cf1e0a609c6e0cf6365"/><file name="Emailtype.php" hash="b7128a27c6937c63f9a8ba14510dad13"/><file name="Incoterm.php" hash="8ebd437537680f375568f7873607ef87"/><file name="Observer.php" hash="e42f9c5c5a241e9ed8fef967fe194dee"/><file name="Packagetype.php" hash="d9f5012184c0e52429be7396e4081c69"/><dir name="Resource"><dir name="Carrier"><file name="Collection.php" hash="aabffe27624593ec59d489aaea12319c"/></dir><file name="Carrier.php" hash="57b812414155d31fe39977be1483ab1e"/><dir name="Carrierprofile"><file name="Collection.php" hash="59c40952ae124b257a30eebd72651df7"/></dir><file name="Carrierprofile.php" hash="53d9e49e8cf00b080f80489a476e43ef"/><dir name="Costcenter"><file name="Collection.php" hash="e338f05492a12988d3066bbc2f7569fe"/></dir><file name="Costcenter.php" hash="338db8721bcd09dabbece8e9c862ac92"/><dir name="Emailtype"><file name="Collection.php" hash="fe4ee29a8af109be50e7d928a8d5a9c3"/></dir><file name="Emailtype.php" hash="27b7d676aabf4e16891ccadee409aeba"/><dir name="Incoterm"><file name="Collection.php" hash="7490a144291e1b2a81f5c243173627e3"/></dir><file name="Incoterm.php" hash="5076d4828c71f71178d7d33213d2e735"/><dir name="Packagetype"><file name="Collection.php" hash="f20c13999570a2338feaf1f8af72c85b"/></dir><file name="Packagetype.php" hash="b8de7857c71a26be8915a67c38a1d347"/><dir name="Servicelevel"><dir name="Other"><file name="Collection.php" hash="c48542bc38fc957c97b90bcc2d0d0773"/></dir><file name="Other.php" hash="df8672bc7a5383a6a985703ece13041d"/><dir name="Time"><file name="Collection.php" hash="ee5e6e59deed414768205cc695b4cda3"/></dir><file name="Time.php" hash="2fc0d74b96cf8b7fe38593d9bdaf1a82"/></dir><dir name="Shipmentlocation"><file name="Collection.php" hash="c284bdadf29cf34160e7f8af189f5a43"/></dir><file name="Shipmentlocation.php" hash="99792ed958bffa3d333453888be4b1c4"/><dir name="Sync"><file name="Collection.php" hash="5b837d6fc0fde6c0a7ebef66132d7bcd"/></dir><file name="Sync.php" hash="a538626ff74fa096eb20c95ccf936794"/></dir><dir name="Sales"><dir name="Resource"><file name="Order.php" hash="f078ab890e8a294a75183bcbbb667f2e"/></dir></dir><dir name="Servicelevel"><file name="Other.php" hash="cf779fc0762b7e34974605256d941993"/><file name="Time.php" hash="60188779fd9cfb1e237fd915090acb53"/></dir><file name="Shipmentlocation.php" hash="38147d641e55c3b68a9cecd123081993"/><dir name="Shipping"><dir name="Carrier"><file name="Abstract.php" hash="65c5fc48da295a19c90153ac693c523f"/><file name="Delivery.php" hash="5c2faa12f798aea53343a657bd7c7010"/><file name="Pickup.php" hash="436630941a50a968cf54e929e25fd0c3"/></dir></dir><file name="Sync.php" hash="3bf6c2507b9f679fbda4145afdf326f1"/></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Transsmart"><dir name="Shipping"><file name="LocationController.php" hash="9ed198c21dd4569cc604c19d6865a74b"/><file name="ShipmentController.php" hash="9967e3414b80aaed728dff5a71694720"/></dir></dir><file name="TranssmartController.php" hash="b5b688249bce5a74bef95319674e5698"/></dir><file name="LocationController.php" hash="f39c3a08069cefc6169c9eed12a97f63"/></dir><dir name="etc"><file name="adminhtml.xml" hash="07f3353cf1d7275e528a18b9883b206f"/><file name="config.xml" hash="05e578944cdb0e5b0069747219a71fba"/><file name="jstranslator.xml" hash="b50cf9cd74e37d6e34b3e360f3353313"/><file name="system.xml" hash="913acd885f5c4a1d33182f022720fe10"/></dir><dir name="sql"><dir name="transsmart_shipping_setup"><file name="install-1.0.0.php" hash="242d4b2aff6d23151dcca7c9cadab352"/></dir></dir><dir name="ssl"><file name="CARoot.crt" hash="f85d1ff17b0079709f131f3ce3f288d2"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="layout"><file name="transsmart_shipping.xml" hash="c0578eb781adc2df96e79fe776e387da"/></dir><dir name="template"><dir name="transsmart"><dir name="shipping"><dir name="location"><file name="info.phtml" hash="74ce67c6f39c308995a478279ca1e1bc"/><file name="selector.phtml" hash="841e1d59d042c2b53c622593150675c6"/></dir><dir name="sales"><dir name="order"><dir name="address"><dir name="form"><file name="container.phtml" hash="57a3f3de61e96127659dbf53952a0b33"/></dir></dir><dir name="shipment"><dir name="address"><dir name="form"><file name="container.phtml" hash="9763785687d9f4dfa03d6d1887a3f867"/></dir></dir><dir name="create"><file name="action.phtml" hash="164c1c632265816113e8eb172762871c"/><file name="detail.phtml" hash="c12734fe34fb4a526eb29075d2b80120"/><file name="package.phtml" hash="a39776c6e5f95112e10b9dbc9e29bd14"/></dir><dir name="masscreate"><file name="form.phtml" hash="5e2a281942e88379fa28698a85e519ec"/></dir><dir name="view"><file name="detail.phtml" hash="e901e78ba712f7e99b82409a07c9dedd"/><file name="package.phtml" hash="4ba3f81ed371d87542102974566cb522"/></dir></dir></dir></dir><dir name="system"><dir name="config"><dir name="form"><dir name="field"><file name="fetch.phtml" hash="bf8377c0df88e37305d0d39b5ad72101"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="transsmart_shipping.xml" hash="99c0e35e1ef97c0251485fee9b39297e"/></dir><dir name="template"><dir name="transsmart"><dir name="shipping"><dir name="location"><file name="selector.phtml" hash="25000d2769c4e282cdb07dbdc6cb1722"/></dir><dir name="onepage"><dir name="progress"><file name="pickup.phtml" hash="e3874f42cb1d4a9629069d50c39f338e"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Transsmart_Shipping.xml" hash="1f526fc89db267b44b7425e2ff645a68"/></dir></target><target name="magelocale"><dir><dir name="nl_NL"><file name="Transsmart_Shipping.csv" hash="6cf4535ee1497b4df66b5526f1ec7f2f"/></dir></dir></target><target name="mageweb"><dir name="js"><dir name="transsmart"><dir name="shipping"><dir name="admin"><file name="pickup_selector.js" hash="7da3ddbbd8e5e4adc4a134faaa7fee0b"/></dir><file name="base64.js" hash="795b1ac117d08652a3a43552c83332ac"/><file name="logger.js" hash="b852d48e077a6114ffe56bd647d1ea5c"/><file name="pickup_selector.js" hash="817d84055cfea02b3f3ce7a073a6e5db"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="transsmart"><dir name="shipping"><dir name="images"><file name="arrow.png" hash="5b0966d990b40b3510cd2bb57081812d"/><file name="checkmark.png" hash="e5cf08c5943037b8ccc3a5449febdb7b"/><file name="close-btn.png" hash="975d2b3ee2879d4e4b812df8351ccf05"/><file name="info-icon.png" hash="a6baeffe65721d6995f8f06b1669a0ad"/><file name="loader.gif" hash="c5cd7f5300576ab4c88202b42f6ded62"/><file name="radio.png" hash="f149b9aa48f1c3a9da34173c40c882dc"/></dir><file name="pickup_selector.css" hash="9e4b6c280cfd0e2dc6d2d05714b94073"/><file name="styles.css" hash="d61eebd814903f153eb2210bf5f27c5f"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="transsmart"><dir name="shipping"><dir name="images"><file name="arrow.png" hash="5b0966d990b40b3510cd2bb57081812d"/><file name="close-btn.png" hash="975d2b3ee2879d4e4b812df8351ccf05"/><file name="info-icon.png" hash="a6baeffe65721d6995f8f06b1669a0ad"/><file name="loader.gif" hash="c5cd7f5300576ab4c88202b42f6ded62"/><file name="radio.png" hash="f149b9aa48f1c3a9da34173c40c882dc"/></dir><file name="pickup_selector.css" hash="9e4b6c280cfd0e2dc6d2d05714b94073"/></dir></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.3.29</min><max>5.9.9</max></php><extension><name>curl</name><min/><max/></extension></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Transsmart_Shipping</name>
4
+ <version>1.0.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Transsmart Magento connector</summary>
10
  <description>Integrates Transsmart Shipping into Magento.</description>
11
+ <notes>1.0.1</notes>
12
  <authors><author><name>Techtwo Webdevelopment B.V.</name><user>techtwo</user><email>info@techtwo.nl</email></author><author><name>Bastiaan Heeren</name><user>techtwobastiaan</user><email>bastiaan@techtwo.nl</email></author></authors>
13
+ <date>2016-01-21</date>
14
+ <time>12:36:17</time>
15
+ <contents><target name="magecommunity"><dir name="Transsmart"><dir name="Shipping"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="bafce0b64ee9545b3a355df1b0b8e18d"/><dir name="Shipment"><dir name="Create"><file name="Detail.php" hash="b8b8b391b781f5d9de8b2578ad84d540"/><file name="Package.php" hash="7054391262f4bcc78d77bbd8d7131d61"/></dir><dir name="Masscreate"><file name="Form.php" hash="1bef6372fca204ba939fca5a02f3fa3d"/></dir><file name="Masscreate.php" hash="244adc0427800e5df7ea050947cff0d5"/><dir name="View"><file name="Detail.php" hash="0c5a780a5a4095164b02b06a5cd5ec16"/><file name="Package.php" hash="ccdda1fc1a9710ff1d317575fd53baa7"/></dir></dir><dir name="View"><dir name="Tab"><file name="Shipments.php" hash="e8b2006ed7c6541ea61c309123457c7c"/></dir></dir></dir><dir name="Shipment"><dir name="Grid"><dir name="Renderer"><file name="Link.php" hash="f42b111af0b6fa7dbdd171b9ef9f5655"/></dir></dir><file name="Grid.php" hash="931e2c538a9f61c62fc838d441419c48"/></dir></dir><dir name="Shipping"><dir name="Location"><file name="Info.php" hash="fa01c870d4a5cd521ed312a447f10dda"/></dir></dir><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Fetch.php" hash="43361767a4367c59fea55c23bb52aaed"/></dir><dir name="Fieldset"><dir name="Carrierprofile"><file name="Header.php" hash="01bda5320d4fcb5493f7fc2fd7ec01ac"/></dir><file name="Carrierprofile.php" hash="a75608f6b98458f1797d41d24a52030b"/><file name="Versioninfo.php" hash="84f740e55f0abc8fda7d95d26a638214"/></dir></dir></dir></dir></dir><dir name="Location"><file name="Selector.php" hash="f13d261827cb806fcc14c73058128653"/></dir></dir><dir name="Helper"><file name="Data.php" hash="32590b34298ed7ee39ebc011485e970e"/><file name="Location.php" hash="59dd6de96da501192e995f3688cba950"/><file name="Pickupaddress.php" hash="c71ad4ae7e2c4536a2d57c18d57b8919"/><file name="Shipment.php" hash="521150f7ac5e16f23ccd6939bec2bea5"/></dir><dir name="Model"><file name="Abstract.php" hash="5b8973d5f3ce40cd641e9f16cdcd6620"/><dir name="Adminhtml"><file name="Observer.php" hash="3664f0727b0159ccdeff1cf256b5fccf"/><dir name="System"><dir name="Config"><dir name="Backend"><file name="Localized.php" hash="3f7ee8815b1f71168ba3fe2f2eb6389f"/></dir><dir name="Source"><dir name="Basedata"><file name="Abstract.php" hash="ac0c0632d16278357cc4128b3a5ef9a8"/><file name="Carrierprofile.php" hash="f01d6e81905f9481a8906253ccfc24e3"/><file name="Costcenter.php" hash="4dabd6942ab4e27e8c7e7032e3d01ca9"/><file name="Emailtype.php" hash="5d5d02c41970795f42e86ec4184a1072"/><file name="Incoterm.php" hash="8724e4b8bd9267fe843d62ffaa939b1e"/><file name="Packagetype.php" hash="6277448d89f3eeaae2dd15dd8a318af1"/><file name="Shipmentlocation.php" hash="f025e24746908e9c5aea82109f3b79fa"/></dir><file name="Environment.php" hash="4d011d8f728c3582022178da0c26ea66"/><dir name="Mapping"><file name="Attribute.php" hash="f2302357356f4c4b6f43cc63c408722a"/><file name="Street.php" hash="e42fa0ede4bc76876cf0c1f783189e87"/></dir><file name="Method.php" hash="672e247ef3764ff9294607102b152c78"/></dir></dir></dir></dir><file name="Carrier.php" hash="9aac846543c6b82cd3a06f9e307593ae"/><file name="Carrierprofile.php" hash="fb3bc266d34c00dbc10b76e89f6de20f"/><file name="Client.php" hash="9dbd3fc487adedecfc28d84eb7137842"/><file name="Costcenter.php" hash="bf6a9a5a95fa7cf1e0a609c6e0cf6365"/><file name="Emailtype.php" hash="b7128a27c6937c63f9a8ba14510dad13"/><file name="Incoterm.php" hash="8ebd437537680f375568f7873607ef87"/><file name="Observer.php" hash="e42f9c5c5a241e9ed8fef967fe194dee"/><file name="Packagetype.php" hash="d9f5012184c0e52429be7396e4081c69"/><dir name="Resource"><dir name="Carrier"><file name="Collection.php" hash="aabffe27624593ec59d489aaea12319c"/></dir><file name="Carrier.php" hash="57b812414155d31fe39977be1483ab1e"/><dir name="Carrierprofile"><file name="Collection.php" hash="59c40952ae124b257a30eebd72651df7"/></dir><file name="Carrierprofile.php" hash="53d9e49e8cf00b080f80489a476e43ef"/><dir name="Costcenter"><file name="Collection.php" hash="e338f05492a12988d3066bbc2f7569fe"/></dir><file name="Costcenter.php" hash="338db8721bcd09dabbece8e9c862ac92"/><dir name="Emailtype"><file name="Collection.php" hash="fe4ee29a8af109be50e7d928a8d5a9c3"/></dir><file name="Emailtype.php" hash="27b7d676aabf4e16891ccadee409aeba"/><dir name="Incoterm"><file name="Collection.php" hash="7490a144291e1b2a81f5c243173627e3"/></dir><file name="Incoterm.php" hash="5076d4828c71f71178d7d33213d2e735"/><dir name="Packagetype"><file name="Collection.php" hash="f20c13999570a2338feaf1f8af72c85b"/></dir><file name="Packagetype.php" hash="b8de7857c71a26be8915a67c38a1d347"/><dir name="Servicelevel"><dir name="Other"><file name="Collection.php" hash="c48542bc38fc957c97b90bcc2d0d0773"/></dir><file name="Other.php" hash="df8672bc7a5383a6a985703ece13041d"/><dir name="Time"><file name="Collection.php" hash="ee5e6e59deed414768205cc695b4cda3"/></dir><file name="Time.php" hash="2fc0d74b96cf8b7fe38593d9bdaf1a82"/></dir><dir name="Shipmentlocation"><file name="Collection.php" hash="c284bdadf29cf34160e7f8af189f5a43"/></dir><file name="Shipmentlocation.php" hash="99792ed958bffa3d333453888be4b1c4"/><dir name="Sync"><file name="Collection.php" hash="5b837d6fc0fde6c0a7ebef66132d7bcd"/></dir><file name="Sync.php" hash="a538626ff74fa096eb20c95ccf936794"/></dir><dir name="Sales"><dir name="Resource"><file name="Order.php" hash="f078ab890e8a294a75183bcbbb667f2e"/></dir></dir><dir name="Servicelevel"><file name="Other.php" hash="cf779fc0762b7e34974605256d941993"/><file name="Time.php" hash="60188779fd9cfb1e237fd915090acb53"/></dir><file name="Shipmentlocation.php" hash="38147d641e55c3b68a9cecd123081993"/><dir name="Shipping"><dir name="Carrier"><file name="Abstract.php" hash="65c5fc48da295a19c90153ac693c523f"/><file name="Delivery.php" hash="5c2faa12f798aea53343a657bd7c7010"/><file name="Pickup.php" hash="436630941a50a968cf54e929e25fd0c3"/></dir></dir><file name="Sync.php" hash="2343389f501ff24a846f2b4c6311a822"/></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Transsmart"><dir name="Shipping"><file name="LocationController.php" hash="9ed198c21dd4569cc604c19d6865a74b"/><file name="ShipmentController.php" hash="67e443bfcdc4afc3478dcf3bc80282e7"/></dir></dir><file name="TranssmartController.php" hash="b5b688249bce5a74bef95319674e5698"/></dir><file name="LocationController.php" hash="f39c3a08069cefc6169c9eed12a97f63"/></dir><dir name="etc"><file name="adminhtml.xml" hash="07f3353cf1d7275e528a18b9883b206f"/><file name="config.xml" hash="cda2f4323a1d812080821a57f9f8c9a6"/><file name="jstranslator.xml" hash="b50cf9cd74e37d6e34b3e360f3353313"/><file name="system.xml" hash="913acd885f5c4a1d33182f022720fe10"/></dir><dir name="sql"><dir name="transsmart_shipping_setup"><file name="install-1.0.0.php" hash="242d4b2aff6d23151dcca7c9cadab352"/></dir></dir><dir name="ssl"><file name="CARoot.crt" hash="f85d1ff17b0079709f131f3ce3f288d2"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="layout"><file name="transsmart_shipping.xml" hash="c0578eb781adc2df96e79fe776e387da"/></dir><dir name="template"><dir name="transsmart"><dir name="shipping"><dir name="location"><file name="info.phtml" hash="74ce67c6f39c308995a478279ca1e1bc"/><file name="selector.phtml" hash="841e1d59d042c2b53c622593150675c6"/></dir><dir name="sales"><dir name="order"><dir name="address"><dir name="form"><file name="container.phtml" hash="57a3f3de61e96127659dbf53952a0b33"/></dir></dir><dir name="shipment"><dir name="address"><dir name="form"><file name="container.phtml" hash="9763785687d9f4dfa03d6d1887a3f867"/></dir></dir><dir name="create"><file name="action.phtml" hash="164c1c632265816113e8eb172762871c"/><file name="detail.phtml" hash="c12734fe34fb4a526eb29075d2b80120"/><file name="package.phtml" hash="a39776c6e5f95112e10b9dbc9e29bd14"/></dir><dir name="masscreate"><file name="form.phtml" hash="5e2a281942e88379fa28698a85e519ec"/></dir><dir name="view"><file name="detail.phtml" hash="e901e78ba712f7e99b82409a07c9dedd"/><file name="package.phtml" hash="4ba3f81ed371d87542102974566cb522"/></dir></dir></dir></dir><dir name="system"><dir name="config"><dir name="form"><dir name="field"><file name="fetch.phtml" hash="bf8377c0df88e37305d0d39b5ad72101"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="transsmart_shipping.xml" hash="99c0e35e1ef97c0251485fee9b39297e"/></dir><dir name="template"><dir name="transsmart"><dir name="shipping"><dir name="location"><file name="selector.phtml" hash="25000d2769c4e282cdb07dbdc6cb1722"/></dir><dir name="onepage"><dir name="progress"><file name="pickup.phtml" hash="e3874f42cb1d4a9629069d50c39f338e"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Transsmart_Shipping.xml" hash="1f526fc89db267b44b7425e2ff645a68"/></dir></target><target name="magelocale"><dir><dir name="nl_NL"><file name="Transsmart_Shipping.csv" hash="759cb6f310ac469a52513c7eede0ce54"/></dir></dir></target><target name="mageweb"><dir name="js"><dir name="transsmart"><dir name="shipping"><dir name="admin"><file name="pickup_selector.js" hash="7da3ddbbd8e5e4adc4a134faaa7fee0b"/></dir><file name="base64.js" hash="795b1ac117d08652a3a43552c83332ac"/><file name="logger.js" hash="b852d48e077a6114ffe56bd647d1ea5c"/><file name="pickup_selector.js" hash="f01e4051c39218c8354a7f28ed1638ed"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="transsmart"><dir name="shipping"><dir name="images"><file name="arrow.png" hash="5b0966d990b40b3510cd2bb57081812d"/><file name="checkmark.png" hash="e5cf08c5943037b8ccc3a5449febdb7b"/><file name="close-btn.png" hash="975d2b3ee2879d4e4b812df8351ccf05"/><file name="info-icon.png" hash="a6baeffe65721d6995f8f06b1669a0ad"/><file name="loader.gif" hash="c5cd7f5300576ab4c88202b42f6ded62"/><file name="radio.png" hash="f149b9aa48f1c3a9da34173c40c882dc"/></dir><file name="pickup_selector.css" hash="9e4b6c280cfd0e2dc6d2d05714b94073"/><file name="styles.css" hash="d61eebd814903f153eb2210bf5f27c5f"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="transsmart"><dir name="shipping"><dir name="images"><file name="arrow.png" hash="5b0966d990b40b3510cd2bb57081812d"/><file name="close-btn.png" hash="975d2b3ee2879d4e4b812df8351ccf05"/><file name="info-icon.png" hash="a6baeffe65721d6995f8f06b1669a0ad"/><file name="loader.gif" hash="c5cd7f5300576ab4c88202b42f6ded62"/><file name="radio.png" hash="f149b9aa48f1c3a9da34173c40c882dc"/></dir><file name="pickup_selector.css" hash="9e4b6c280cfd0e2dc6d2d05714b94073"/></dir></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.3.29</min><max>5.9.9</max></php><extension><name>curl</name><min/><max/></extension></required></dependencies>
18
  </package>