Packpin_Pptrack - Version 1.0.2

Version Notes

Added detection for custom carriers (sometimes shipment list is updated through API and carrier codes match only partly)

Download this release

Release Info

Developer Packpin Packpin
Extension Packpin_Pptrack
Version 1.0.2
Comparing to
See all releases


Version 1.0.2

Files changed (62) hide show
  1. app/code/community/Packpin/Pptrack/Block/Adminhtml/Sales/Order/Shipment/Create/Tracking.php +39 -0
  2. app/code/community/Packpin/Pptrack/Block/Adminhtml/Sales/Order/Shipment/View/Tracking.php +65 -0
  3. app/code/community/Packpin/Pptrack/Block/Adminhtml/System/Config/Fieldset/Hint-owner.php +20 -0
  4. app/code/community/Packpin/Pptrack/Block/Adminhtml/System/Config/Form/Fieldset/Carrier.php +81 -0
  5. app/code/community/Packpin/Pptrack/Block/Crosssell.php +22 -0
  6. app/code/community/Packpin/Pptrack/Block/Index.php +5 -0
  7. app/code/community/Packpin/Pptrack/Block/Trackings.php +40 -0
  8. app/code/community/Packpin/Pptrack/Helper/Data.php +299 -0
  9. app/code/community/Packpin/Pptrack/Model/Api.php +127 -0
  10. app/code/community/Packpin/Pptrack/Model/Carrier.php +175 -0
  11. app/code/community/Packpin/Pptrack/Model/EnableNotifications.php +90 -0
  12. app/code/community/Packpin/Pptrack/Model/Observer.php +262 -0
  13. app/code/community/Packpin/Pptrack/Model/Order/Shipment.php +40 -0
  14. app/code/community/Packpin/Pptrack/Model/Resource/Carrier.php +10 -0
  15. app/code/community/Packpin/Pptrack/Model/Resource/Carrier/Collection.php +8 -0
  16. app/code/community/Packpin/Pptrack/Model/Resource/Setting.php +10 -0
  17. app/code/community/Packpin/Pptrack/Model/Resource/Setting/Collection.php +8 -0
  18. app/code/community/Packpin/Pptrack/Model/Resource/Track.php +10 -0
  19. app/code/community/Packpin/Pptrack/Model/Resource/Track/Collection.php +8 -0
  20. app/code/community/Packpin/Pptrack/Model/Resource/Trackdetail.php +8 -0
  21. app/code/community/Packpin/Pptrack/Model/Resource/Trackdetail/Collection.php +8 -0
  22. app/code/community/Packpin/Pptrack/Model/Resource/Trackunsubscribed.php +8 -0
  23. app/code/community/Packpin/Pptrack/Model/Resource/Trackunsubscribed/Collection.php +8 -0
  24. app/code/community/Packpin/Pptrack/Model/Setting.php +28 -0
  25. app/code/community/Packpin/Pptrack/Model/Track.php +455 -0
  26. app/code/community/Packpin/Pptrack/Model/Trackdetail.php +71 -0
  27. app/code/community/Packpin/Pptrack/Model/Trackunsubscribed.php +31 -0
  28. app/code/community/Packpin/Pptrack/Model/Translate.php +39 -0
  29. app/code/community/Packpin/Pptrack/controllers/Adminhtml/PpnotificationsController.php +29 -0
  30. app/code/community/Packpin/Pptrack/controllers/IndexController.php +40 -0
  31. app/code/community/Packpin/Pptrack/controllers/UnsubscribeController.php +31 -0
  32. app/code/community/Packpin/Pptrack/etc/adminhtml.xml +38 -0
  33. app/code/community/Packpin/Pptrack/etc/api.xml +43 -0
  34. app/code/community/Packpin/Pptrack/etc/config.xml +260 -0
  35. app/code/community/Packpin/Pptrack/etc/system.xml +467 -0
  36. app/code/community/Packpin/Pptrack/sql/pptrack_setup/mysql4-install-0.1.2.php +86 -0
  37. app/code/community/Packpin/Pptrack/sql/pptrack_setup/mysql4-upgrade-0.1.2-0.1.5.php +22 -0
  38. app/design/adminhtml/default/default/layout/pptrack.xml +10 -0
  39. app/design/adminhtml/default/default/template/pptrack/system/config/fieldset/hint-owner.phtml +6 -0
  40. app/design/frontend/base/default/layout/pptrack.xml +50 -0
  41. app/design/frontend/base/default/template/pptrack/crosssell.phtml +48 -0
  42. app/design/frontend/base/default/template/pptrack/crosssell_email.phtml +32 -0
  43. app/design/frontend/base/default/template/pptrack/email/order/shipment/track.phtml +27 -0
  44. app/design/frontend/base/default/template/pptrack/index.phtml +154 -0
  45. app/design/frontend/base/default/template/pptrack/popup.phtml +29 -0
  46. app/design/frontend/base/default/template/pptrack/unsubscribe.phtml +0 -0
  47. app/etc/modules/Packpin_Pptrack.xml +10 -0
  48. app/locale/en_US/template/email/packpin/packpin_delivered_email.html +86 -0
  49. app/locale/en_US/template/email/packpin/packpin_exception_email.html +86 -0
  50. app/locale/en_US/template/email/packpin/packpin_failed_attempt_email.html +86 -0
  51. app/locale/en_US/template/email/packpin/packpin_in_transit_email.html +86 -0
  52. app/locale/en_US/template/email/packpin/packpin_info_received_email.html +86 -0
  53. app/locale/en_US/template/email/packpin/packpin_out_for_delivery_email.html +86 -0
  54. package.xml +28 -0
  55. skin/adminhtml/default/default/pptrack/css/pptrack.css +13 -0
  56. skin/adminhtml/default/default/pptrack/images/pp_logo1.png +0 -0
  57. skin/frontend/base/default/css/pptrack.css +343 -0
  58. skin/frontend/base/default/images/pptrack/bulletIcon.png +0 -0
  59. skin/frontend/base/default/images/pptrack/checkedIcon.png +0 -0
  60. skin/frontend/base/default/images/pptrack/postnlLogo.png +0 -0
  61. skin/frontend/base/default/images/pptrack/trackingStatus.png +0 -0
  62. skin/frontend/base/default/images/pptrack/truck.png +0 -0
app/code/community/Packpin/Pptrack/Block/Adminhtml/Sales/Order/Shipment/Create/Tracking.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Block_Adminhtml_Sales_Order_Shipment_Create_Tracking extends Mage_Adminhtml_Block_Sales_Order_Shipment_Create_Tracking
4
+ {
5
+
6
+ /**
7
+ * Retrieve
8
+ *
9
+ * @return unknown
10
+ */
11
+ public function getCarriers()
12
+ {
13
+ $carriers = parent::getCarriers();
14
+
15
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
16
+ if (!$enabled)
17
+ return $carriers;
18
+
19
+ $disableDefault = isset($config['disable_default_carriers']) && $config['disable_default_carriers'] ? 1 : 0;
20
+
21
+ //get Packpin Additional carriers
22
+ $packpinCarriers = Mage::getModel('pptrack/carrier')
23
+ ->getList();
24
+ if ($packpinCarriers) {
25
+ if ($disableDefault) {
26
+ $carriers = array();
27
+ }
28
+ else {
29
+ $carriers[''] = $this->__('----- Packpin carriers -----');
30
+ }
31
+ foreach ($packpinCarriers as $item) {
32
+ $carriers[$item->getPrefixedCode()] = $item->getData('name');
33
+ }
34
+ }
35
+
36
+ return $carriers;
37
+ }
38
+
39
+ }
app/code/community/Packpin/Pptrack/Block/Adminhtml/Sales/Order/Shipment/View/Tracking.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Block_Adminhtml_Sales_Order_Shipment_View_Tracking extends Mage_Adminhtml_Block_Sales_Order_Shipment_View_Tracking
4
+ {
5
+
6
+ /**
7
+ * Carrier list for static cache
8
+ *
9
+ * @var array
10
+ */
11
+ public static $carrierList = array();
12
+
13
+ /**
14
+ * Retrieve carriers
15
+ *
16
+ * @return array
17
+ */
18
+ public function getCarriers()
19
+ {
20
+ if (!self::$carrierList) {
21
+ $carriers = parent::getCarriers();
22
+
23
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
24
+ if (!$enabled)
25
+ return $carriers;
26
+
27
+ $disableDefault = isset($config['disable_default_carriers']) && $config['disable_default_carriers'] ? 1 : 0;
28
+
29
+ //get Packpin Additional carriers
30
+ $packpinCarriers = Mage::getModel('pptrack/carrier')
31
+ ->getList();
32
+ if ($packpinCarriers) {
33
+ if ($disableDefault) {
34
+ $carriers = array();
35
+ }
36
+ else {
37
+ $carriers[''] = $this->__('----- Packpin carriers -----');
38
+ }
39
+ foreach ($packpinCarriers as $item) {
40
+ $carriers[$item->getPrefixedCode()] = $item->getData('name');
41
+ }
42
+ }
43
+
44
+ self::$carrierList = $carriers;
45
+ }
46
+
47
+ return self::$carrierList;
48
+ }
49
+
50
+ public function getCarrierTitle($code)
51
+ {
52
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
53
+ if (!$enabled)
54
+ return parent::getCarrierTitle($code);
55
+
56
+ $allCarriers = $this->getCarriers();
57
+
58
+ if (isset($allCarriers[$code]))
59
+ return $allCarriers[$code];
60
+ else
61
+ return parent::getCarrierTitle($code);
62
+
63
+ }
64
+
65
+ }
app/code/community/Packpin/Pptrack/Block/Adminhtml/System/Config/Fieldset/Hint-owner.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Block_Adminhtml_System_Config_Fieldset_Hint
4
+ extends Mage_Adminhtml_Block_Abstract
5
+ implements Varien_Data_Form_Element_Renderer_Interface
6
+ {
7
+ protected $_template = 'pptrack/system/config/fieldset/hint-owner.phtml';
8
+
9
+ /**
10
+ * Render fieldset html
11
+ *
12
+ * @param Varien_Data_Form_Element_Abstract $element
13
+ * @return string
14
+ */
15
+ public function render(Varien_Data_Form_Element_Abstract $element)
16
+ {
17
+ return $this->toHtml();
18
+ }
19
+ }
20
+
app/code/community/Packpin/Pptrack/Block/Adminhtml/System/Config/Form/Fieldset/Carrier.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Block_Adminhtml_System_Config_Form_Fieldset_Carrier extends
4
+ Mage_Adminhtml_Block_System_Config_Form_Fieldset
5
+ {
6
+ protected $_dummyElement;
7
+ protected $_fieldRenderer;
8
+ protected $_values;
9
+ protected $_dataSource;
10
+ protected $_hidden = '';
11
+
12
+ public function render(Varien_Data_Form_Element_Abstract $element)
13
+ {
14
+ $html = $this->_getHeaderHtml($element);
15
+
16
+ $carriers = Mage::getModel('pptrack/carrier')->getList(true);
17
+
18
+ //check all button
19
+ $html .= '<tr><td class="label"></td><td>';
20
+ $html .= $this->_getCheckAllButton('$$(\'.pp_carrier\').forEach(function(el){el.writeAttribute(\'checked\', true)});', $this->helper('pptrack')->__('Select All'));
21
+ $html .= ' ';
22
+ $html .= $this->_getCheckAllButton('$$(\'.pp_carrier\').forEach(function(el){el.writeAttribute(\'checked\', false)});', $this->helper('pptrack')->__('Unselect All'));
23
+ $html .= '</td></tr>';
24
+
25
+ $fields = '';
26
+ foreach ($carriers as $carrier) {
27
+ $fields .= $this->_getFieldHtml($element, $carrier);
28
+ }
29
+ $html .= $fields;
30
+ $html .= $this->_getFooterHtml($element);
31
+
32
+ return $this->_hidden . $html;
33
+ }
34
+
35
+ protected function _getFieldRenderer()
36
+ {
37
+ if (empty($this->_fieldRenderer)) {
38
+ $this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
39
+ }
40
+ return $this->_fieldRenderer;
41
+ }
42
+
43
+ protected function _getValues()
44
+ {
45
+ if (!$this->_dataSource)
46
+ $this->_dataSource = Mage::getSingleton('adminhtml/system_config_source_enabledisable')->toOptionArray();
47
+
48
+ return $this->_dataSource;
49
+ }
50
+
51
+ protected function _getFieldHtml($fieldset, $carrier)
52
+ {
53
+ $name = 'groups[carriers][fields][' . $carrier->getCode() . '][value]';
54
+ $this->_hidden .= '<input type="hidden" name="'. $name .'" value="0">';
55
+
56
+ $field = $fieldset->addField($carrier->getCode(), 'checkbox',
57
+ array(
58
+ 'name' => $name,
59
+ 'label' => $carrier->getName(),
60
+ 'class' => 'pp_carrier',
61
+ 'value' => 1,
62
+ 'checked' => $carrier->getEnabled(),
63
+ // 'values' => $this->_getValues(),
64
+ 'can_use_default_value' => 0,
65
+ 'can_use_website_value' => 0,
66
+ ))->setRenderer($this->_getFieldRenderer());
67
+
68
+ return $field->toHtml();
69
+ }
70
+
71
+ protected function _getCheckAllButton($action, $label)
72
+ {
73
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')
74
+ ->setData(array(
75
+ 'label' => $label,
76
+ 'onclick' => 'javascript:'. $action .'; return false;'
77
+ ));
78
+
79
+ return $button->toHtml();
80
+ }
81
+ }
app/code/community/Packpin/Pptrack/Block/Crosssell.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Packpin_Pptrack_Block_Crosssell extends Mage_Catalog_Block_Product_Abstract
3
+ {
4
+ public function getCrossSellingItemsByOrderId($orderId, $limit)
5
+ {
6
+ $crossSellingItemsArray = array();
7
+ $orders = Mage::getModel('sales/order')->load($orderId);
8
+ $items = $orders->getAllVisibleItems();
9
+
10
+ foreach ($items as $item) {
11
+ $product = Mage::getModel('catalog/product')->load($item->getProductId());
12
+ $crossSellCollection = $product->getCrossSellProductCollection();
13
+ $crossSellCollection->getSelect()->order(new Zend_Db_Expr('RAND()'))->limit($limit);
14
+ // $crossSellCollection->setPage(1, 5);
15
+ foreach ($crossSellCollection as $crossSellItem) {
16
+ $crossSellingItemsArray[] = Mage::getModel('catalog/product')->load($crossSellItem->getId());
17
+ }
18
+ }
19
+ return $crossSellingItemsArray;
20
+ }
21
+
22
+ }
app/code/community/Packpin/Pptrack/Block/Index.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+ class Packpin_Pptrack_Block_Index extends Mage_Core_Block_Template{
3
+
4
+
5
+ }
app/code/community/Packpin/Pptrack/Block/Trackings.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Block_Trackings extends Mage_Core_Block_Template
4
+ {
5
+
6
+ /**
7
+ * @var Packpin_Pptrack_Model_Track
8
+ */
9
+ protected $_trackModel;
10
+
11
+ /**
12
+ * Check if Packpin tracks a shipment
13
+ *
14
+ * @param Mage_Sales_Model_Order_Shipment_Track $track
15
+ * @param Mage_Sales_Model_Order $order
16
+ * @return bool
17
+ */
18
+ public function shipmentTracked(Mage_Sales_Model_Order_Shipment_Track $track, Mage_Sales_Model_Order $order)
19
+ {
20
+ $collection = Mage::getModel('pptrack/track')
21
+ ->getCollection()
22
+ ->addFieldToFilter('shipment_id', array('eq' => $track->getId()));
23
+ $this->_trackModel = $collection->getFirstItem();
24
+
25
+
26
+ if ($this->_trackModel->getId())
27
+ return true;
28
+
29
+ return false;
30
+ }
31
+
32
+ /**
33
+ * @return Packpin_Pptrack_Model_Track
34
+ */
35
+ public function getTrackModel()
36
+ {
37
+ return $this->_trackModel;
38
+ }
39
+
40
+ }
app/code/community/Packpin/Pptrack/Helper/Data.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Helper_Data
5
+ *
6
+ * API calls helpers
7
+ * see https://packpin.com/docs for more documentation
8
+ */
9
+ class Packpin_Pptrack_Helper_Data extends Mage_Core_Helper_Abstract
10
+ {
11
+ /**
12
+ * Backend
13
+ */
14
+ const API_BACKEND = 'https://api.packpin.com/v2/';
15
+
16
+ /**
17
+ * Api routes
18
+ */
19
+ const API_PATH_CARRIERS = 'carriers';
20
+ const API_PATH_TRACKINGS = 'trackings';
21
+ const API_PATH_TRACKINGS_BATCH = 'trackings/batch';
22
+ const API_PATH_TRACKING_INFO = 'trackings/%s/%s';
23
+ const API_PATH_CONNECTORS = 'connectors';
24
+ const API_PATH_TEST = 'test/1';
25
+
26
+
27
+ const API_ROLE_NAME = 'packpin_connection';
28
+
29
+ /**
30
+ * Config paths
31
+ */
32
+ const XML_PATH_API_KEY = 'pp_section_setttings/settings/api_key';
33
+
34
+ /**
35
+ * Packpin API key
36
+ *
37
+ * @var string
38
+ */
39
+ protected $_apiKey;
40
+
41
+ /**
42
+ * Last API call status code
43
+ *
44
+ * @var integer
45
+ */
46
+ protected $_lastStatusCode;
47
+
48
+ protected function _getApiKey()
49
+ {
50
+ if ($this->_apiKey === null) {
51
+ $this->_apiKey = Mage::getStoreConfig(self::XML_PATH_API_KEY);
52
+ }
53
+
54
+ return $this->_apiKey;
55
+ }
56
+
57
+ /**
58
+ * Make API request
59
+ *
60
+ * @param string $route
61
+ * @param string $method
62
+ * @param array $body
63
+ *
64
+ * @return bool|array
65
+ */
66
+ protected function _apiRequest($route, $method = 'GET', $body = array())
67
+ {
68
+ $store = Mage::app()->getStore();
69
+ $body['plugin_type'] = 'magento';
70
+ $body['plugin_version'] = $this->getExtensionVersion();
71
+ $body['plugin_shop_version'] = Mage::getVersion();
72
+ $body['plugin_user'] = Mage::getStoreConfig('trans_email/ident_general/name');
73
+ $body['plugin_email'] = Mage::getStoreConfig('trans_email/ident_general/email');
74
+ $body['plugin_url'] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
75
+
76
+ $url = self::API_BACKEND . $route;
77
+
78
+ $ch = curl_init($url);
79
+ if ($method == 'POST') {
80
+ curl_setopt($ch, CURLOPT_POST, 1);
81
+ } elseif ($method == 'PUT') {
82
+ curl_setopt($ch, CURLOPT_PUT, true);
83
+ } elseif ($method != 'PUT') {
84
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
85
+ }
86
+ //timeouts
87
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 25);
88
+ curl_setopt($ch, CURLOPT_TIMEOUT, 90);
89
+
90
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
91
+ curl_setopt($ch, CURLOPT_HEADER, 0);
92
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
93
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
94
+ $headers = array(
95
+ 'packpin-api-key: ' . $this->_getApiKey(),
96
+ 'Content-Type: application/json',
97
+ );
98
+ if ($body) {
99
+ $dataString = json_encode($body);
100
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $dataString);
101
+ $headers[] = 'Content-Length: ' . strlen($dataString);
102
+ }
103
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
104
+
105
+ $response = curl_exec($ch);
106
+ $this->_lastStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
107
+ curl_close($ch);
108
+ unset($ch);
109
+
110
+ return $response;
111
+ }
112
+
113
+ /**
114
+ * Get info about single tracking object
115
+ *
116
+ * @param string $carrierCode
117
+ * @param string $trackingCode
118
+ *
119
+ * @return array
120
+ */
121
+ public function getTrackingInfo($carrierCode, $trackingCode)
122
+ {
123
+ $info = array();
124
+
125
+ $url = sprintf(self::API_PATH_TRACKING_INFO, $carrierCode, $trackingCode);
126
+
127
+ $res = $this->_apiRequest($url, 'GET');
128
+ if ($res) {
129
+ $info = json_decode($res, true);
130
+ }
131
+
132
+ return $info;
133
+ }
134
+
135
+ /**
136
+ * Get list of available carriers
137
+ *
138
+ * @return array
139
+ */
140
+ public function getCarrierList()
141
+ {
142
+ $info = array();
143
+
144
+ $url = self::API_PATH_CARRIERS;
145
+
146
+ $res = $this->_apiRequest($url, 'GET');
147
+ if ($res) {
148
+ $info = json_decode($res, true);
149
+ }
150
+
151
+ return $info;
152
+ }
153
+
154
+ /**
155
+ * Add new tracking code
156
+ *
157
+ * @param string $carrierCode
158
+ * @param string $trackingCode
159
+ * @param string|null $description
160
+ * @param string|null $postalCode
161
+ * @param string|null $destinationCountry
162
+ * @param string|null $shipDate
163
+ *
164
+ * @return array
165
+ */
166
+ public function addTrackingCode($carrierCode, $trackingCode, $description = null, $postalCode = null, $destinationCountry = null, $shipDate = null)
167
+ {
168
+ $info = array();
169
+
170
+ $url = self::API_PATH_TRACKINGS;
171
+ $body = array(
172
+ 'code' => $trackingCode,
173
+ 'carrier' => $carrierCode,
174
+ 'description' => $description,
175
+ 'track_postal_code' => $postalCode,
176
+ 'track_ship_date' => $shipDate,
177
+ 'track_destination_country' => $destinationCountry,
178
+ );
179
+
180
+ $res = $this->_apiRequest($url, 'POST', $body);
181
+ if ($res) {
182
+ $info = json_decode($res, true);
183
+ }
184
+
185
+ return $info;
186
+ }
187
+
188
+ public function removeTrackingCode($carrierCode, $trackingCode)
189
+ {
190
+ $info = array();
191
+
192
+ $url = sprintf(self::API_PATH_TRACKING_INFO, $carrierCode, $trackingCode);
193
+
194
+ $res = $this->_apiRequest($url, 'DELETE');
195
+
196
+ if ($res) {
197
+ $info = json_decode($res, true);
198
+ } else {
199
+ $info = array(
200
+ "statusCode" => $this->_lastStatusCode
201
+ );
202
+ }
203
+
204
+ return $info;
205
+ }
206
+
207
+ public function enableConnector($status = 0)
208
+ {
209
+ $info = array();
210
+
211
+ $url = self::API_PATH_CONNECTORS;
212
+ $body = array(
213
+ 'path' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
214
+ 'enabled' => $status,
215
+ );
216
+
217
+ $res = $this->_apiRequest($url, 'POST', $body);
218
+
219
+ if ($res) {
220
+ $info = json_decode($res, true);
221
+ }
222
+
223
+ if (!$info && preg_match('#SOAP-ERROR#ui', $res, $m)) {
224
+ $info = array(
225
+ 'statusCode' => 400,
226
+ 'body' => array(
227
+ 'reason' => 'Could not connect to Magento shop API'
228
+ ),
229
+ );
230
+ }
231
+
232
+ return $info;
233
+ }
234
+
235
+ public function testApiKey()
236
+ {
237
+ $info = array();
238
+
239
+ $url = self::API_PATH_TEST;
240
+ $res = $this->_apiRequest($url, 'GET');
241
+ if ($res) {
242
+ $info = json_decode($res, true);
243
+ }
244
+
245
+ return $info;
246
+ }
247
+
248
+ public function createSoapUserAndRole($apiKey)
249
+ {
250
+
251
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
252
+ try {
253
+ $connection->beginTransaction();
254
+
255
+ $user = Mage::getModel('api/user')->loadByUsername("packpin");
256
+ $user->setUsername('packpin')->setFirstname('packpin')->setLastname('packpin')->setEmail('info@packpin.com')->setApiKey($apiKey)->setApiKeyConfirmation($apiKey)->setIsActive(1)->save();
257
+
258
+ $role = Mage::getModel('api/roles')->load(self::API_ROLE_NAME, "role_name");
259
+ if (!$role->getId()) {
260
+ $res = Mage::getModel('api/role')->setParentId('0')->setTreeLevel('1')->setSortOrder('0')->setRoleName(self::API_ROLE_NAME)->setRoleType('G')->save();
261
+ $rules = Mage::getModel('api/rules')->setRoleId($res->getRoleId())->setResources(array("pptrack", "pptrack/info", "pptrack/test"));
262
+ //for newer magento versions
263
+ $rrModel = Mage::getModel('api/resource_rules');
264
+ if ($rrModel) {
265
+ $rrModel->saveRel($rules);
266
+ }
267
+ //Mage 1.5
268
+ else {
269
+ $rules->saveRel();
270
+ }
271
+
272
+ $role = $res;
273
+ }
274
+
275
+ $user->setRoleIds(array($role->getId()))
276
+ ->setRoleUserId($user->getUserId())
277
+ ->saveRelations();
278
+
279
+
280
+ ////Stupid hack. Should be fixed properly in the future
281
+ $transactionLevel = $connection->getTransactionLevel();
282
+ for ($i = 1; $i <= $transactionLevel; $i++) {
283
+ $connection->commit();
284
+ }
285
+
286
+ } catch (Exception $e) {
287
+ $connection->rollback();
288
+ }
289
+
290
+ return true;
291
+ }
292
+
293
+ public function getExtensionVersion()
294
+ {
295
+ return (string) Mage::getConfig()->getNode()->modules->Packpin_Pptrack->version;
296
+ }
297
+
298
+ }
299
+
app/code/community/Packpin/Pptrack/Model/Api.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Api extends Mage_Api_Model_Resource_Abstract
4
+ {
5
+
6
+ const ERROR_EXTENSION_DISABLED = 'extension_disabled';
7
+ const ERROR_NOTIFICATIONS_DISABLED = 'notifications_disabled';
8
+ const ERROR_NO_TEMPLATE = 'no_template';
9
+
10
+ const DEFAULT_LOCALE = 'en_US';
11
+
12
+ /**
13
+ * Get email info
14
+ *
15
+ * @param string $carrierCode
16
+ * @param string $trackingCode
17
+ *
18
+ * @return array
19
+ */
20
+ public function info($carrierCode, $trackingCode, $status)
21
+ {
22
+ //extension disabled
23
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
24
+ if (!$enabled)
25
+ return array(
26
+ 'error' => self::ERROR_EXTENSION_DISABLED
27
+ );
28
+
29
+ //notifications disabled
30
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/pp_enable_notifications');
31
+ if (!$enabled)
32
+ return false;
33
+
34
+ $trackModel = Mage::getModel('pptrack/track')
35
+ ->loadByCarrierAndCode($carrierCode, $trackingCode);
36
+ if ($trackModel->getId()) {
37
+ $order = Mage::getModel('sales/order')->load($trackModel->getOrderId());
38
+ $store = $order->getStore();
39
+ $storeId = $store->getId();
40
+
41
+ $templateSettings = Mage::getStoreConfig('pp_section_notification_emails/' . $status, $storeId);
42
+ if (!$templateSettings || (!$templateSettings['enabled_owner'] && !$templateSettings['enabled_client']))
43
+ return self::ERROR_NOTIFICATIONS_DISABLED;
44
+
45
+ $data = array();
46
+
47
+ //sender data
48
+ $data['sender_name'] = Mage::getStoreConfig('trans_email/ident_'. $templateSettings['identity'] .'/name');
49
+ $data['sender_email'] = Mage::getStoreConfig('trans_email/ident_'. $templateSettings['identity'] .'/email');
50
+
51
+ //shop data
52
+ if ($templateSettings['enabled_owner']) {
53
+ $data['owner_name'] = Mage::getStoreConfig('trans_email/ident_general/name');
54
+ $data['owner_email'] = Mage::getStoreConfig('trans_email/ident_general/email');
55
+ }
56
+
57
+ //client data
58
+ //check if client unsubscribed
59
+ try {
60
+ $unsubscribed = Mage::getModel('pptrack/trackunsubscribed')
61
+ ->load($trackModel->getId(), 'track_id');
62
+ }
63
+ catch (Exception $e) {
64
+ $unsubscribed = Mage::getModel('pptrack/trackunsubscribed');
65
+ }
66
+
67
+ if (!$unsubscribed->getId() && $templateSettings['enabled_client']) {
68
+ $data['client_name'] = $order->getCustomerName();
69
+ $data['client_email'] = $order->getCustomerEmail();
70
+ }
71
+
72
+ //email template data
73
+ $templateId = $templateSettings['template'];
74
+
75
+ Mage::getDesign()->setStore($store);
76
+ $emailTemplate = Mage::getModel('core/email_template');
77
+ $emailTemplate->emulateDesign($storeId);
78
+ if (is_numeric($templateId)) {
79
+ $emailTemplate->load($templateId);
80
+ } else {
81
+ $templateId = 'packpin_'. $status .'_email';
82
+
83
+ // $storeId = $order->getStore()->getId();
84
+ // $localeCode = Mage::getStoreConfig('general/locale/code', $storeId);
85
+ $localeCode = self::DEFAULT_LOCALE;
86
+
87
+ $emailTemplate->loadDefault($templateId, $localeCode);
88
+ }
89
+
90
+
91
+ if (Mage::getStoreConfig('pp_section_setttings/crosssell/cross_sell_email')) {
92
+ $crossSell = Mage::app()->getLayout()->createBlock('pptrack/crosssell')->setData(array('orderId' => $trackModel->getOrderId()))->setTemplate('pptrack/crosssell_email.phtml')->toHtml();
93
+ }
94
+ else {
95
+ $crossSell = '';
96
+ }
97
+
98
+ $variables = array(
99
+ 'email' => $order->getCustomerEmail(),
100
+ 'track' => $trackModel,
101
+ 'crossSell' => $crossSell
102
+ );
103
+
104
+ $processedTemplate = $emailTemplate->getProcessedTemplate($variables);
105
+ if (!$processedTemplate)
106
+ return array(
107
+ 'error' => self::ERROR_NO_TEMPLATE
108
+ );
109
+
110
+
111
+ $data['email_subject'] = $emailTemplate->getProcessedTemplateSubject($variables);
112
+ $data['email_body'] = $processedTemplate;
113
+
114
+ return $data;
115
+ }
116
+
117
+ return false;
118
+ }
119
+
120
+ public function test()
121
+ {
122
+ return array(
123
+ 'status' => 1
124
+ );
125
+ }
126
+
127
+ }
app/code/community/Packpin/Pptrack/Model/Carrier.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Carrier
5
+ *
6
+ * Model for pp_carriers table
7
+ */
8
+ class Packpin_Pptrack_Model_Carrier extends Mage_Core_Model_Abstract
9
+ {
10
+ /**
11
+ * Update once per day
12
+ */
13
+ const API_UPDATE_INTERVAL = 86400;
14
+
15
+ /**
16
+ * Append carrier code with prefix to prevent conflicts
17
+ */
18
+ const CODE_PREFIX = 'pp_';
19
+
20
+ const URL_ICONS = 'https://button.packpin.com/assets/images/carriers_v2/';
21
+
22
+ public $assocList = array();
23
+
24
+ protected function _construct()
25
+ {
26
+ $this->_init('pptrack/carrier');
27
+ }
28
+
29
+ /**
30
+ * Get carrier list if needed - update from API
31
+ * @param bool $fetchAll
32
+ * @return array
33
+ */
34
+ public function getList($fetchAll = false)
35
+ {
36
+ $collection = Mage::getModel('pptrack/carrier')
37
+ ->getCollection();
38
+
39
+ if (!$fetchAll)
40
+ $collection->addFieldToFilter('enabled', array('eq' => 1));
41
+
42
+ $carriers = $collection->getItems();
43
+
44
+ //check last updated
45
+ $config = Mage::getStoreConfig('pp_section_setttings/settings');
46
+ $updated = $config['last_carrier_update'];
47
+
48
+ //try to get info from API
49
+ if (!$carriers || !$updated || $updated + self::API_UPDATE_INTERVAL < time()) {
50
+ $helper = Mage::helper('pptrack');
51
+ $res = $helper->getCarrierList();
52
+ if ($res && $res["statusCode"] == 200) {
53
+ $list = $res["body"];
54
+
55
+ if (is_array($list)) {
56
+ $newList = array();
57
+
58
+ //prepare old list data for updates
59
+ $oldList = array();
60
+ foreach ($carriers as $item) {
61
+ $oldList[$item->code] = $item;
62
+ }
63
+
64
+ foreach ($list as $item) {
65
+ $model = Mage::getModel('pptrack/carrier')
66
+ ->load($item['code'], 'code');
67
+
68
+ if ($model->getId()) {
69
+ if (isset($oldList[$item['code']]))
70
+ unset($oldList[$item['code']]);
71
+ }
72
+ else {
73
+ $model->enabled = 1;
74
+ }
75
+
76
+ $model->code = $item['code'];
77
+ $model->name = $item['name'];
78
+ $model->phone = $item['phone'];
79
+ $model->homepage = $item['homepage'];
80
+
81
+ $model->save();
82
+
83
+ if ($fetchAll || $model->enabled)
84
+ $newList[] = $model;
85
+ }
86
+
87
+ //remove old no longer supported carriers.. should never happen o_0
88
+ foreach ($oldList as $model) {
89
+ $model->delete();
90
+ }
91
+
92
+ //update config
93
+ Mage::getModel('core/config')->saveConfig('pp_section_setttings/settings/last_carrier_update', time());
94
+
95
+ $carriers = $newList;
96
+ }
97
+ }
98
+ }
99
+
100
+ return $carriers;
101
+ }
102
+
103
+ /**
104
+ * Get list of carriers with carrier code as key
105
+ *
106
+ * @param bool $fetchAll
107
+ * @return array
108
+ */
109
+ public function getAssocList($fetchAll = false)
110
+ {
111
+ if (!$this->assocList) {
112
+ $this->assocList = array();
113
+ $list = $this->getList($fetchAll);
114
+
115
+ foreach ($list as $item) {
116
+ $this->assocList[$item->getCode()] = $item->getData('name');
117
+ }
118
+ }
119
+
120
+ return $this->assocList;
121
+ }
122
+
123
+ /**
124
+ * Get carrier code with prefix
125
+ *
126
+ * @return string
127
+ */
128
+ public function getPrefixedCode()
129
+ {
130
+ return self::CODE_PREFIX . $this->getCode();
131
+ }
132
+
133
+ public function getIconUrl()
134
+ {
135
+ return self::URL_ICONS . $this->getCode() . '.png';
136
+ }
137
+
138
+ /**
139
+ * Get carrier code from pp_carriers string on detect from custom carrier title
140
+ *
141
+ * @param string $carrierCode
142
+ * @param string|null $carrierTitle
143
+ * @return bool|string
144
+ */
145
+ public function detectCarrier($carrierCode, $carrierTitle = null)
146
+ {
147
+ $carrierList = $this->getAssocList();
148
+
149
+ $carrierCode = str_replace(Packpin_Pptrack_Model_Carrier::CODE_PREFIX, '', $carrierCode);
150
+
151
+ if (isset($carrierList[$carrierCode])) {
152
+ return $carrierCode;
153
+ }
154
+
155
+ //try to identify by custom carrier code
156
+ $regStr = implode('|', array_keys($carrierList));
157
+ if (preg_match("#$regStr#ui", $carrierCode, $m)) {
158
+ return $m[0];
159
+ }
160
+
161
+ //try to identify by carrier title
162
+ if ($carrierTitle) {
163
+ $titles = array();
164
+ foreach ($carrierList as $code => $title) {
165
+ $titles[$title] = $code;
166
+ }
167
+ $regStr2 = implode('|', $titles);
168
+ if (preg_match("#$regStr2#ui", $carrierTitle, $m)) {
169
+ return $titles[$m[0]];
170
+ }
171
+ }
172
+
173
+ return false;
174
+ }
175
+ }
app/code/community/Packpin/Pptrack/Model/EnableNotifications.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Validation
5
+ */
6
+ class Packpin_Pptrack_Model_Enablenotifications extends Mage_Core_Model_Config_Data
7
+ {
8
+
9
+ public function save()
10
+ {
11
+
12
+
13
+ $helper = Mage::helper('pptrack');
14
+
15
+ $apiKey = $this->_data['groups']['settings']['fields']['api_key']['value'];
16
+ $pluginStatus = $this->_data['groups']['settings']['fields']['status']['value'];
17
+ $notificationStatus = $this->_data['groups']['settings']['fields']['pp_enable_notifications']['value'];
18
+
19
+ $oldApiKey = Mage::getStoreConfig('pp_section_setttings/settings/api_key');
20
+ $oldPluginStatus = Mage::getStoreConfig('pp_section_setttings/settings/status');
21
+
22
+ // Change API key config so we can get proper API key instantly
23
+ Mage::app()->getStore()->setConfig('pp_section_setttings/settings/api_key', $apiKey);
24
+
25
+ // Check if API key is missing
26
+ if(!$apiKey) {
27
+ Mage::throwException(Mage::helper('pptrack')->__('You have to enter API key before saving config!'));
28
+ }
29
+
30
+ //Check if status set to disabled and API key changed
31
+ if(!$pluginStatus AND $oldApiKey !== $apiKey) {
32
+ $info = $helper->testApiKey();
33
+
34
+ if(!$info OR $info['statusCode'] == 400) {
35
+ if ($info['body']['reason']) {
36
+ Mage::getSingleton('core/session')->addWarning(Mage::helper('pptrack')->__($info['body']['reason']));
37
+ } else {
38
+ Mage::getSingleton('core/session')->addWarning(Mage::helper('pptrack')->__('Error sending data to API'));
39
+ }
40
+ }
41
+ }
42
+
43
+ // Check if plugin status set to Enable and API key changed then do API key check
44
+ if(($pluginStatus AND $oldApiKey !== $apiKey) OR ($pluginStatus AND !$oldPluginStatus)) {
45
+ $info = $helper->testApiKey();
46
+
47
+ if(!$info OR $info['statusCode'] == 400) {
48
+ if($info['body']['reason']) {
49
+ Mage::throwException(Mage::helper('pptrack')->__(Mage::helper('pptrack')->__($info['body']['reason'])));
50
+ }
51
+ else {
52
+ Mage::throwException(Mage::helper('pptrack')->__('Error sending data to API'));
53
+ }
54
+ }
55
+ }
56
+
57
+ // Check if plugin or notification status disabled then do API call to disable notifications connector
58
+ if(!$pluginStatus OR !$notificationStatus) {
59
+ $info = $helper->enableConnector('0');
60
+
61
+ if(!$info OR $info['statusCode'] == 400 AND Mage::getStoreConfig('pp_section_setttings/settings/pp_enable_notifications') == 1) {
62
+ if($info['body']['reason']) {
63
+ Mage::getSingleton('core/session')->addWarning(Mage::helper('pptrack')->__($info['body']['reason']));
64
+ }
65
+ else {
66
+ Mage::getSingleton('core/session')->addWarning(Mage::helper('pptrack')->__('Error sending data to API'));
67
+ }
68
+ }
69
+ }
70
+
71
+ // If API key exists and both plugin and notifications status set to enable call API to enable connector
72
+ if($apiKey AND $pluginStatus AND $notificationStatus) {
73
+
74
+ if($helper->createSoapUserAndRole($apiKey)) {
75
+ $info = $helper->enableConnector($notificationStatus);
76
+
77
+ if(!$info OR $info['statusCode'] == 400) {
78
+ if($info['body']['reason'] && !empty($info['body']['reason'])) {
79
+ Mage::throwException('Could not enable notifications: '.$info['body']['reason']);
80
+ }
81
+ else {
82
+ Mage::throwException('Could not enable notifications: Could not connect to API');
83
+ }
84
+ }
85
+ }
86
+ }
87
+ return parent::save();
88
+
89
+ }
90
+ }
app/code/community/Packpin/Pptrack/Model/Observer.php ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Observer
4
+ {
5
+
6
+ /**
7
+ * For static cache
8
+ *
9
+ * @var array
10
+ */
11
+ protected $_config = array();
12
+
13
+ /**
14
+ * Event fired before Tracking popup view (in admin shipments)
15
+ *
16
+ * @param Varien_Event_Observer $observer
17
+ * @return bool|void
18
+ */
19
+ public function trackingPopupPreDispatch(Varien_Event_Observer $observer)
20
+ {
21
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
22
+ if (!$enabled)
23
+ return false;
24
+
25
+ $shippingTrackModel = null;
26
+ $shippingList = null;
27
+
28
+ $hash = Mage::app()->getRequest()->getParam('hash');
29
+ $shippingInfoModel = Mage::getModel('shipping/info')->loadByHash($hash);
30
+ $shippingTrackId = $shippingInfoModel->getTrackId();
31
+ if ($shippingTrackId) {
32
+ $shippingTrackModel = Mage::getModel('sales/order_shipment_track')->load($shippingTrackId);
33
+ }
34
+ else {
35
+ $trackingInfo = $shippingInfoModel->getTrackingInfo();
36
+ if ($trackingInfo) {
37
+ $shippingList = current($trackingInfo);
38
+ }
39
+ }
40
+
41
+ //for multiple shipment popup
42
+ if ($shippingList) {
43
+ $orderId = $shippingInfoModel->getOrderId();
44
+ if (!$orderId) {
45
+ $shipId = $shippingInfoModel->getShipId();
46
+ if ($shipId) {
47
+ $shipModel = Mage::getModel('sales/order_shipment')->load($shipId);
48
+
49
+ $orderId = $shipModel->getOrderId();
50
+ }
51
+ }
52
+
53
+ $models = array();
54
+ foreach ($shippingList as $item) {
55
+ $trackModel = Mage::getModel('pptrack/track')
56
+ ->loadByOrder($orderId, $item['number']);
57
+ if ($trackModel->getId()) {
58
+ $models[] = $trackModel;
59
+ }
60
+ }
61
+
62
+ if ($models) {
63
+ Mage::register('models', $models);
64
+
65
+ //redirect to our controller :)
66
+ $request = Mage::app()->getRequest();
67
+ $request->initForward()
68
+ ->setControllerName('index')
69
+ ->setModuleName('pptrack')
70
+ ->setActionName('popup')
71
+ ->setDispatched(false);
72
+
73
+ return false;
74
+ }
75
+ }
76
+ //for single shipment popup
77
+ elseif ($shippingTrackModel->getId()) {
78
+ $trackData = $shippingTrackModel->getData();
79
+ $trackModel = Mage::getModel('pptrack/track')
80
+ ->loadByOrder($trackData['order_id'], $this->_getTrackingCode($trackData));
81
+ if ($trackModel->getId()) {
82
+ Mage::register('model', $trackModel);
83
+
84
+ //redirect to our controller :)
85
+ $request = Mage::app()->getRequest();
86
+ $request->initForward()
87
+ ->setControllerName('index')
88
+ ->setModuleName('pptrack')
89
+ ->setActionName('popup')
90
+ ->setDispatched(false);
91
+
92
+ return false;
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Observe Event after new tracking has been added to shipment
99
+ *
100
+ * @param Varien_Event_Observer $observer
101
+ * @return bool|void
102
+ */
103
+ public function afterShipmentSaved(Varien_Event_Observer $observer)
104
+ {
105
+ //plugin disabled
106
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
107
+ if (!$enabled)
108
+ return false;
109
+
110
+ $track = $observer->getEvent()->getTrack();
111
+ $order = $track->getShipment()->getOrder();
112
+
113
+
114
+ $trackData = $track->getData();
115
+ $orderData = $order->getData();
116
+ $addressData = $order->getShippingAddress()->getData();
117
+
118
+ //detect carrier
119
+ $carrierTitle = isset($trackData['title']) ? trim($trackData['title']) : null;
120
+ $carrierCode = Mage::getModel('pptrack/carrier')
121
+ ->detectCarrier($trackData['carrier_code'], $carrierTitle);
122
+ if (!$carrierCode)
123
+ return false;
124
+
125
+ $trackingCode = $this->_getTrackingCode($trackData);
126
+ $email = trim($orderData['customer_email']) ? $orderData['customer_email'] : null;
127
+ $phone = trim($addressData['telephone']) ? $addressData['telephone'] : null;
128
+
129
+ $collection = Mage::getModel('pptrack/track')
130
+ ->getCollection()
131
+ ->addFieldToFilter('code', array('eq' => $trackingCode))
132
+ ->addFieldToFilter('order_id', array('eq' => $order->getId()));
133
+ $trackModel = $collection->getFirstItem();
134
+ $trackModel->setSubmitted(Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_PENDING);
135
+
136
+ if (!$trackModel->getId()) {
137
+ $trackModel->setOrderId($order->getId());
138
+ $trackModel->setShipmentId($track->getId());
139
+ $trackModel->setCode($trackingCode);
140
+ $trackModel->setCarrierCode($carrierCode);
141
+ $trackModel->setCarrierName($trackData['title']);
142
+ $trackModel->setPhone($phone);
143
+ $trackModel->setEmail($email);
144
+
145
+ //tracking attributes
146
+ $trackModel->setPostalCode($addressData['postcode']);
147
+ $trackModel->setDestinationCountry($addressData['country_id']);
148
+ // $trackModel->setShipDate(date("Y-m-d"));
149
+
150
+ $trackModel->setStatus(Packpin_Pptrack_Model_Track::STATUS_PENDING);
151
+ }
152
+
153
+ $trackModel->save();
154
+ $trackModel->updateApi();
155
+ }
156
+
157
+ /**
158
+ * Observe Event after new tracking has been removed from shipment
159
+ *
160
+ * @param Varien_Event_Observer $observer
161
+ * @return bool|void
162
+ */
163
+ public function afterShipmentRemoved(Varien_Event_Observer $observer)
164
+ {
165
+ //plugin disabled
166
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
167
+ if (!$enabled)
168
+ return false;
169
+
170
+ $track = $observer->getEvent()->getTrack();
171
+ $order = $track->getShipment()->getOrder();
172
+
173
+ $trackData = $track->getData();
174
+ $trackingCode = $this->_getTrackingCode($trackData);
175
+
176
+ $collection = Mage::getModel('pptrack/track')
177
+ ->getCollection()
178
+ ->addFieldToFilter('code', array('eq' => $trackingCode))
179
+ ->addFieldToFilter('order_id', array('eq' => $order->getId()));
180
+ $trackModel = $collection->getFirstItem();
181
+
182
+ if ($trackModel->getId()) {
183
+ $trackModel->setSubmitted(Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_REMOVE_PENDING);
184
+ $trackModel->save();
185
+
186
+ $trackModel->updateApi();
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Get tracking code from Magento track data
192
+ * Up to ver 1.6.2.0 `number` field is used
193
+ * Later it's track_number
194
+ *
195
+ * @param array $trackData
196
+ *
197
+ * @return string
198
+ */
199
+ protected function _getTrackingCode($trackData)
200
+ {
201
+ $trackingCode = trim($trackData['track_number']) ? trim($trackData['track_number']) : trim($trackData['number']);
202
+
203
+ return $trackingCode;
204
+ }
205
+
206
+ /**
207
+ * @param Mage_Sales_Model_Order $order
208
+ *
209
+ * @return mixed
210
+ */
211
+ protected function _getConfig(Mage_Sales_Model_Order $order) {
212
+ $websiteId = $order->getStore()->getWebsiteId();
213
+
214
+ if (!isset($this->_config[$websiteId])) {
215
+ $config = Mage::app()->getWebsite($websiteId)->getConfig('pp_section_setttings');
216
+
217
+ $this->_config[$websiteId] = (object)((array)$config['settings']);
218
+ }
219
+
220
+ return $this->_config[$websiteId];
221
+ }
222
+
223
+ /**
224
+ * Run cron and check if we have trackings that were not sent to API
225
+ */
226
+ public function cron()
227
+ {
228
+ $enabled = Mage::getStoreConfig('pp_section_setttings/settings/status');
229
+ if (!$enabled)
230
+ return false;
231
+
232
+ set_time_limit(0);
233
+
234
+ $list = Mage::getModel('pptrack/track')
235
+ ->getCollection()
236
+ ->addFieldToFilter('submitted', array('neq' => Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_SENT))
237
+ ->load();
238
+
239
+ if ($list) {
240
+ foreach ($list as $trackModel) {
241
+ $trackModel->updateApi();
242
+ }
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Triggered after carriers are saved in admin configuration
248
+ */
249
+ public function saveCarriers(Varien_Event_Observer $observer)
250
+ {
251
+ $carriers = Mage::getModel('pptrack/carrier')->getList(true);
252
+ foreach ($carriers as $carrier) {
253
+ $configValue = (int) Mage::getStoreConfig('pp_section_carriers/carriers/' . $carrier->getCode());
254
+
255
+ if ($carrier->enabled != $configValue) {
256
+ $carrier->setEnabled($configValue);
257
+ $carrier->save();
258
+ }
259
+ }
260
+ }
261
+
262
+ }
app/code/community/Packpin/Pptrack/Model/Order/Shipment.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Order_Shipment extends Mage_Sales_Model_Order_Shipment {
4
+
5
+
6
+ /**
7
+ * Get all track and override tracking title to add tracking back link
8
+ *
9
+ * @return array
10
+ */
11
+ /*
12
+ public function getAllTracks()
13
+ {
14
+ $tracks = parent::getAllTracks();
15
+
16
+ $config = Mage::getStoreConfig('pp_section_setttings/settings');
17
+ if (!$config['status'])
18
+ return $tracks;
19
+
20
+ //check if function called from email template
21
+ //@FIXME maybe there is a better way to override this stuff o_0
22
+ $callers = debug_backtrace();
23
+ $args = $callers[1]['args'];
24
+ if (count($args) && strstr($args[0], 'template/email/order/shipment/track.phtml')) {
25
+ //override names
26
+ $newItems = array();
27
+ foreach ($tracks as $num => $item) {
28
+ $newTitle = $item->getTitle() . ' (Whata fuck)';
29
+ $item->title = $newTitle;
30
+ $newItems[] = $item;
31
+ }
32
+
33
+ $tracks = $newItems;
34
+ }
35
+
36
+ return $tracks;
37
+ }
38
+ */
39
+
40
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Carrier.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Carrier extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ protected function _construct()
6
+ {
7
+ $this->_init('pptrack/carrier', 'id');
8
+ }
9
+
10
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Carrier/Collection.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Carrier_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/carrier');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Setting.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Setting extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ protected function _construct()
6
+ {
7
+ $this->_init('pptrack/setting', 'id');
8
+ }
9
+
10
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Setting/Collection.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Setting_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/setting');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Track.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Track extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ protected function _construct()
6
+ {
7
+ $this->_init('pptrack/track', 'id');
8
+ }
9
+
10
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Track/Collection.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Track_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/track');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Trackdetail.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Trackdetail extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/trackdetail', 'id');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Trackdetail/Collection.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Trackdetail_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/trackdetail');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Trackunsubscribed.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Trackunsubscribed extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/trackunsubscribed', 'id');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Resource/Trackunsubscribed/Collection.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_Model_Resource_Trackunsubscribed_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ protected function _construct() {
6
+ $this->_init('pptrack/trackunsubscribed');
7
+ }
8
+ }
app/code/community/Packpin/Pptrack/Model/Setting.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Setting
5
+ *
6
+ * Model for pp_settings table
7
+ */
8
+ class Packpin_Pptrack_Model_Setting extends Mage_Core_Model_Abstract
9
+ {
10
+ const SETTING_CARRIER_UPDATED = 'carrier_updated';
11
+
12
+ protected function _construct()
13
+ {
14
+ $this->_init('pptrack/setting');
15
+ }
16
+
17
+
18
+ /**
19
+ * Get setting value
20
+ *
21
+ * @param string $setting
22
+ */
23
+ public function loadModelBySetting($setting)
24
+ {
25
+ $this->load($setting, 'setting');
26
+ }
27
+
28
+ }
app/code/community/Packpin/Pptrack/Model/Track.php ADDED
@@ -0,0 +1,455 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Track
5
+ *
6
+ * Model for pp_tracks table
7
+ */
8
+ class Packpin_Pptrack_Model_Track extends Mage_Core_Model_Abstract
9
+ {
10
+ protected function _construct()
11
+ {
12
+ $this->_init('pptrack/track');
13
+ }
14
+
15
+ const STATUS_PENDING = 'pending';
16
+ const STATUS_DELIVERED = 'delivered';
17
+ const STATUS_OUT_FOR_DELIVERY = 'out_for_delivery';
18
+ const STATUS_IN_TRANSIT = 'in_transit';
19
+ const STATUS_INFO_RECEIVED = 'info_received';
20
+ const STATUS_DISPATCHED_TO_OVERSEAS = 'to_overseas';
21
+ const STATUS_FAILED_ATTEMPT = 'failed_attempt';
22
+ const STATUS_EXCEPTION = 'exception';
23
+ const STATUS_NO_INFO = 'no_info';
24
+
25
+
26
+ /**
27
+ * Model created but not sent to API
28
+ */
29
+ const TYPE_SUBMITTED_PENDING = 0;
30
+
31
+ /**
32
+ * Model data sent
33
+ */
34
+ const TYPE_SUBMITTED_SENT = 1;
35
+
36
+ /**
37
+ * Model pending to be removed
38
+ */
39
+ const TYPE_SUBMITTED_REMOVE_PENDING = 2;
40
+
41
+ /**
42
+ * Data fields we can map with API data
43
+ *
44
+ * @var array
45
+ */
46
+ public static $mapCols = array(
47
+ 'status',
48
+ );
49
+
50
+ /**
51
+ * Tracking details
52
+ *
53
+ * @var null|array
54
+ */
55
+ protected $_details;
56
+
57
+ /**
58
+ * Shipping Info
59
+ *
60
+ * @var null|array
61
+ */
62
+ protected $_shippingInfo;
63
+
64
+ /**
65
+ * Carrier model
66
+ *
67
+ * @var
68
+ */
69
+ protected $_carrier;
70
+
71
+ /**
72
+ * Get list of statuses with order number
73
+ *
74
+ * @return array
75
+ */
76
+ public static function getOrderedStatusList()
77
+ {
78
+ return array(
79
+ self::STATUS_PENDING => 10,
80
+ self::STATUS_NO_INFO => 10,
81
+ self::STATUS_INFO_RECEIVED => 10,
82
+ self::STATUS_IN_TRANSIT => 30,
83
+ self::STATUS_DISPATCHED_TO_OVERSEAS => 30,
84
+ self::STATUS_FAILED_ATTEMPT => 30,
85
+ self::STATUS_EXCEPTION => 30,
86
+ self::STATUS_OUT_FOR_DELIVERY => 50,
87
+ self::STATUS_DELIVERED => 60,
88
+ );
89
+ }
90
+
91
+ /**
92
+ * Update unix times
93
+ *
94
+ * @return mixed
95
+ */
96
+ protected function _beforeSave()
97
+ {
98
+ //new model
99
+ if (!$this->getId()) {
100
+ $this->hash = $this->_generateHash();
101
+ $this->created_at = time();
102
+ }
103
+ $this->updated_at = time();
104
+
105
+ return parent::_beforeSave();
106
+ }
107
+
108
+ /**
109
+ * Generate UUID (v4) for usage in track details url backlink
110
+ *
111
+ * @return string
112
+ */
113
+ protected function _generateHash()
114
+ {
115
+ return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
116
+
117
+ // 32 bits for "time_low"
118
+ mt_rand(0, 0xffff), mt_rand(0, 0xffff),
119
+
120
+ // 16 bits for "time_mid"
121
+ mt_rand(0, 0xffff),
122
+
123
+ // 16 bits for "time_hi_and_version",
124
+ // four most significant bits holds version number 4
125
+ mt_rand(0, 0x0fff) | 0x4000,
126
+
127
+ // 16 bits, 8 bits for "clk_seq_hi_res",
128
+ // 8 bits for "clk_seq_low",
129
+ // two most significant bits holds zero and one for variant DCE1.1
130
+ mt_rand(0, 0x3fff) | 0x8000,
131
+
132
+ // 48 bits for "node"
133
+ mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
134
+ );
135
+ }
136
+
137
+ /**
138
+ * Updates model info from API
139
+ */
140
+ protected function _fetchData()
141
+ {
142
+ $helper = Mage::helper('pptrack');
143
+ $res = $helper->getTrackingInfo($this->getCarrierCode(), $this->getCode());
144
+
145
+ //map new data to current model
146
+ if ($res && $res["statusCode"] == 200) {
147
+ $info = $res["body"];
148
+
149
+ $this->updateInfo($info);
150
+
151
+ //Track details info
152
+ if (isset($info['track_details']) && $info['track_details']) {
153
+ //remove old details
154
+ $list = $this->getDetails();
155
+ foreach ($list as $model) {
156
+ $model->delete();
157
+ }
158
+ $this->_details = array();
159
+
160
+ foreach ($info['track_details'] as $detailInfo) {
161
+ $model = Mage::getModel('pptrack/trackdetail');
162
+ $model->track_id = $this->getId();
163
+ $model->updateInfo($detailInfo);
164
+ $this->_details[] = $model;
165
+ }
166
+ }
167
+
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Update Track info
173
+ *
174
+ * @param array $data
175
+ */
176
+ public function updateInfo($data)
177
+ {
178
+ foreach (self::$mapCols as $field) {
179
+ if (isset($data[$field]))
180
+ $this->$field = $data[$field];
181
+ }
182
+
183
+ $this->save();
184
+ }
185
+
186
+ /**
187
+ * Get Tracking info by order and tracking code
188
+ *
189
+ * @param int $orderId
190
+ * @param string $code
191
+ * @param bool $fetchData Fetch new data from API
192
+ * @return $this
193
+ */
194
+ public function loadByOrder($orderId, $code, $fetchData = true)
195
+ {
196
+ $collection = Mage::getModel('pptrack/track')
197
+ ->getCollection()
198
+ ->addFieldToFilter('code', array('eq' => $code))
199
+ ->addFieldToFilter('order_id', array('eq' => $orderId));
200
+ $trackModel = $collection->getFirstItem();
201
+ $this->setData($trackModel->getData());
202
+
203
+ if ($this->getId() && $fetchData) {
204
+ $this->_fetchData();
205
+ }
206
+
207
+ return $this;
208
+ }
209
+
210
+ /**
211
+ * Get Tracking info by carrier and tracking code
212
+ *
213
+ * @param string $carrier
214
+ * @param string $code
215
+ * @return $this
216
+ */
217
+ public function loadByCarrierAndCode($carrier, $code)
218
+ {
219
+ $collection = Mage::getModel('pptrack/track')
220
+ ->getCollection()
221
+ ->addFieldToFilter('code', array('eq' => $code))
222
+ ->addFieldToFilter('carrier_code', array('eq' => $carrier));
223
+ $trackModel = $collection->getFirstItem();
224
+ $this->setData($trackModel->getData());
225
+
226
+ return $this;
227
+ }
228
+
229
+ /**
230
+ * Get Tracking info by hash string
231
+ *
232
+ * @param string $hash
233
+ * @param bool $fetchData Fetch new data from API
234
+ */
235
+ public function loadInfoByHash($hash, $fetchData = true)
236
+ {
237
+ $this->load($hash, 'hash');
238
+
239
+ if ($this->getId() && $fetchData) {
240
+ $this->_fetchData();
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Get track details
246
+ *
247
+ * @return array
248
+ */
249
+ public function getDetails()
250
+ {
251
+ if ($this->_details === null) {
252
+ if ($this->isEmpty()) {
253
+ return array();
254
+ }
255
+
256
+ $this->_details = Mage::getModel('pptrack/trackdetail')
257
+ ->getCollection()
258
+ ->addFieldToFilter('track_id', array('eq' => $this->getId()))
259
+ ->getItems();
260
+ }
261
+
262
+ return $this->_details;
263
+ }
264
+
265
+ /**
266
+ * Get shipping information
267
+ *
268
+ * @return array
269
+ */
270
+ public function getShippingInfo()
271
+ {
272
+ if($this->_shippingInfo === null) {
273
+ if ($this->isEmpty()) {
274
+ return array();
275
+ }
276
+
277
+ $order = Mage::getModel('sales/order')->load($this->getOrderId());
278
+ if ($order->getId()) {
279
+ $address = $order->getShippingAddress();
280
+ if ($address->getId()) {
281
+ $shippingInfo = $address->getData();
282
+
283
+ $this->_shippingInfo = $shippingInfo;
284
+ }
285
+ }
286
+ }
287
+ return $this->_shippingInfo;
288
+ }
289
+
290
+ /**
291
+ * Get Track details url
292
+ */
293
+ public function getDetailsUrl()
294
+ {
295
+ $url = Mage::getUrl('pptrack') . '?h=' . $this->hash;
296
+
297
+ return $url;
298
+ }
299
+
300
+ public function getUnsubscribeLink()
301
+ {
302
+ $url = Mage::getUrl('pptrack/unsubscribe') . '?h=' . $this->hash;
303
+
304
+ return $url;
305
+ }
306
+
307
+ /**
308
+ * Try to sync this model with API
309
+ */
310
+ public function updateApi()
311
+ {
312
+ $helper = Mage::helper('pptrack');
313
+
314
+ $submitted = $this->getSubmitted();
315
+
316
+ if ($submitted == Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_PENDING) {
317
+ $res = $helper->addTrackingCode(
318
+ $this->getCarrierCode(),
319
+ $this->getCode(),
320
+ $this->getCarrierName(),
321
+ $this->getPostalCode(),
322
+ $this->getDestinationCountry(),
323
+ $this->getShipDate()
324
+ );
325
+
326
+ //400 statuscode goes for "tracking already in the list"
327
+ if ($res && in_array($res["statusCode"], array(201, 400))) {
328
+ $this->setSubmitted(Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_SENT);
329
+
330
+ $this->save();
331
+ }
332
+ }
333
+ elseif ($submitted == Packpin_Pptrack_Model_Track::TYPE_SUBMITTED_REMOVE_PENDING) {
334
+ $res = $helper->removeTrackingCode(
335
+ $this->getCarrierCode(),
336
+ $this->getCode()
337
+ );
338
+
339
+ //404 goes for already removed
340
+ if ($res && in_array($res["statusCode"], array(200, 204, 404))) {
341
+ $this->delete();
342
+ }
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Get given status css class compared to current status
348
+ *
349
+ * @param $status
350
+ * @return string
351
+ */
352
+ public function getStatusClass($status)
353
+ {
354
+ $list = self::getOrderedStatusList();
355
+
356
+ if (!isset($list[$status]) || !isset($list[$this->getStatus()]))
357
+ return '';
358
+
359
+ if ($list[$status] < $list[$this->getStatus()])
360
+ return 'done';
361
+ elseif ($list[$status] == $list[$this->getStatus()])
362
+ return 'active';
363
+
364
+ return '';
365
+ }
366
+
367
+ /**
368
+ * @return mixed
369
+ */
370
+ public function getOrderNumber()
371
+ {
372
+ $order = Mage::getModel('sales/order')->load($this->getOrderId());
373
+
374
+ return $order->getIncrementId();
375
+ }
376
+
377
+ /**
378
+ * Get carrier model
379
+ *
380
+ * @return array
381
+ */
382
+ public function getCarrier()
383
+ {
384
+ if ($this->_carrier === null) {
385
+ $this->_carrier = Mage::getModel('pptrack/carrier')
386
+ ->load($this->getCarrierCode(), 'code');
387
+ }
388
+
389
+ return $this->_carrier;
390
+ }
391
+
392
+ /**
393
+ * @return string
394
+ */
395
+ public function getCarrierIcon()
396
+ {
397
+ $carrier = $this->getCarrier();
398
+ if ($carrier && $carrier->getId()) {
399
+ return $carrier->getIconUrl();
400
+ }
401
+
402
+ return '';
403
+ }
404
+
405
+ /**
406
+ * @return string
407
+ */
408
+ public function getCarrierName()
409
+ {
410
+ $carrier = $this->getCarrier();
411
+ if ($carrier && $carrier->getId()) {
412
+ return $carrier->getName();
413
+ }
414
+
415
+ return '';
416
+ }
417
+
418
+ /**
419
+ * @return string
420
+ */
421
+ public function getCarrierPhone()
422
+ {
423
+ $carrier = $this->getCarrier();
424
+ if ($carrier && $carrier->getId()) {
425
+ return $carrier->getPhone();
426
+ }
427
+
428
+ return '';
429
+ }
430
+
431
+ /**
432
+ * @return string
433
+ */
434
+ public function getCarrierHomepage()
435
+ {
436
+ $carrier = $this->getCarrier();
437
+ if ($carrier && $carrier->getId()) {
438
+ return $carrier->getHomepage();
439
+ }
440
+
441
+ return '';
442
+ }
443
+
444
+ /**
445
+ * @return string
446
+ */
447
+ public function getShippingDate()
448
+ {
449
+ $time = $this->getCreatedAt();
450
+
451
+ $dateFormatted = Mage::helper('core')->formatTime(date("Y-m-d H:i:s", $time), 'medium', true);
452
+ return $dateFormatted;
453
+ }
454
+
455
+ }
app/code/community/Packpin/Pptrack/Model/Trackdetail.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Trackdetail
5
+ *
6
+ * Model for pp_track_details table
7
+ */
8
+ class Packpin_Pptrack_Model_Trackdetail extends Mage_Core_Model_Abstract
9
+ {
10
+ protected function _construct()
11
+ {
12
+ $this->_init('pptrack/trackdetail');
13
+ }
14
+
15
+ /**
16
+ * Data fields we can map with API data
17
+ *
18
+ * @var array
19
+ */
20
+ public static $mapCols = array(
21
+ 'carrier',
22
+ 'status',
23
+ 'status_string',
24
+ 'event_date',
25
+ 'event_time',
26
+ 'address',
27
+ 'country',
28
+ );
29
+
30
+ /**
31
+ * Update Track detail info
32
+ *
33
+ * @param array $data
34
+ */
35
+ public function updateInfo($data)
36
+ {
37
+ foreach (self::$mapCols as $field) {
38
+ if (isset($data[$field]))
39
+ $this->$field = $data[$field];
40
+ }
41
+
42
+ $this->save();
43
+ }
44
+
45
+ /**
46
+ * Get event location string
47
+ *
48
+ * @return mixed|string
49
+ */
50
+ public function getLocation()
51
+ {
52
+ if ($this->address)
53
+ return $this->address;
54
+
55
+ $params = array(
56
+ 'address',
57
+ 'country',
58
+ );
59
+ $address = '';
60
+ foreach ($params as $param) {
61
+ if ($this->$param) {
62
+ if ($address)
63
+ $address .= ', ';
64
+ $address .= ' ' . $this->$param;
65
+ }
66
+ }
67
+ return $address;
68
+ }
69
+
70
+
71
+ }
app/code/community/Packpin/Pptrack/Model/Trackunsubscribed.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Trackunsubscribed
5
+ *
6
+ * Model for pp_tracks_unsubscribed table
7
+ */
8
+ class Packpin_Pptrack_Model_Trackunsubscribed extends Mage_Core_Model_Abstract
9
+ {
10
+
11
+ protected function _construct()
12
+ {
13
+ $this->_init('pptrack/trackunsubscribed');
14
+ }
15
+
16
+ public function unsubscribeTrack($trackId)
17
+ {
18
+ $this->load($trackId, 'track_id');
19
+
20
+ if ($this->getId()) {
21
+ return false;
22
+ }
23
+ else {
24
+ $this->setTrackId($trackId);
25
+ $this->save();
26
+
27
+ return true;
28
+ }
29
+ }
30
+
31
+ }
app/code/community/Packpin/Pptrack/Model/Translate.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Packpin_Pptrack_Model_Translate
5
+ * Temporary override email processing to include back link to shop
6
+ *
7
+ * Used for dirty shipment back link injection
8
+ * Hope temporary o_0
9
+ */
10
+ class Packpin_Pptrack_Model_Translate extends Mage_Core_Model_Translate
11
+ {
12
+ /**
13
+ * Retrieve translated template file
14
+ *
15
+ * @param string $file
16
+ * @param string $type
17
+ * @param string $localeCode
18
+ * @return string
19
+ */
20
+ public function getTemplateFile($file, $type, $localeCode=null)
21
+ {
22
+ $fileContent = parent::getTemplateFile($file, $type, $localeCode);
23
+
24
+ $config = Mage::getStoreConfig('pp_section_setttings/settings');
25
+ if (!$config['status'])
26
+ return $fileContent;
27
+
28
+ if (in_array($file, array('sales/shipment_new.html', 'sales/shipment_new_guest.html'))) {
29
+ $newBlock = '{{block type=\'pptrack/trackings\' area=\'frontend\' template=\'pptrack/email/order/shipment/track.phtml\' shipment=$shipment order=$order}}';
30
+
31
+ //replace trackings table if found
32
+ if (preg_match('#{{[^}]+track\.phtml[^}]+}}#ui', $fileContent, $m)) {
33
+ $fileContent = preg_replace('#{{[^}]+track\.phtml[^}]+}}#ui', $newBlock, $fileContent);
34
+ }
35
+ }
36
+
37
+ return $fileContent;
38
+ }
39
+ }
app/code/community/Packpin/Pptrack/controllers/Adminhtml/PpnotificationsController.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Packpin_Pptrack_Adminhtml_PpnotificationsController extends Mage_Adminhtml_Controller_Action
3
+ {
4
+ protected function _initAction()
5
+ {
6
+ $this->loadLayout()
7
+ ->_setActiveMenu('packpin/pptrack');
8
+
9
+ return $this;
10
+ }
11
+
12
+ public function indexAction()
13
+ {
14
+ $this->_initAction()
15
+ ->_title($this->__("Packpin Notifications"))
16
+ ->renderLayout();
17
+ }
18
+
19
+ /**
20
+ * Notification setting page
21
+ */
22
+ public function settingsAction()
23
+ {
24
+ $this->_initAction()
25
+ ->_title($this->__("Packpin Notification Settings"))
26
+ ->renderLayout();
27
+ }
28
+
29
+ }
app/code/community/Packpin/Pptrack/controllers/IndexController.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_IndexController extends Mage_Core_Controller_Front_Action
4
+ {
5
+ public function indexAction()
6
+ {
7
+ $model = Mage::getModel('pptrack/track');
8
+
9
+ $hash = Mage::app()->getRequest()->getParam('h');
10
+ if ($hash) {
11
+ $model->loadInfoByHash($hash);
12
+ }
13
+
14
+ Mage::register('model', $model);
15
+
16
+ $this->loadLayout();
17
+ $this->getLayout()->getBlock("head")->setTitle($this->__("Shipment status"));
18
+ $breadcrumbs = $this->getLayout()->getBlock("breadcrumbs");
19
+ $breadcrumbs->addCrumb("home", array(
20
+ "label" => $this->__("Home Page"),
21
+ "title" => $this->__("Home Page"),
22
+ "link" => Mage::getBaseUrl()
23
+ ));
24
+
25
+ $breadcrumbs->addCrumb("shipment status", array(
26
+ "label" => $this->__("Shipment status"),
27
+ "title" => $this->__("Shipment status")
28
+ ));
29
+
30
+ $this->renderLayout();
31
+
32
+ }
33
+
34
+ public function popupAction()
35
+ {
36
+ $this->loadLayout();
37
+ $this->getLayout()->getBlock("head")->setTitle($this->__("Shipment status"));
38
+ $this->renderLayout();
39
+ }
40
+ }
app/code/community/Packpin/Pptrack/controllers/UnsubscribeController.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Packpin_Pptrack_UnsubscribeController extends Mage_Core_Controller_Front_Action
4
+ {
5
+ public function indexAction(){
6
+
7
+ $model = Mage::getModel('pptrack/track');
8
+ $hash = Mage::app()->getRequest()->getParam('h');
9
+ if ($hash) {
10
+ $model->loadInfoByHash($hash);
11
+
12
+ if($model->getId()) {
13
+ $unsubscribedModel = Mage::getModel('pptrack/trackunsubscribed');
14
+ $res = $unsubscribedModel->unsubscribeTrack($model->getId());
15
+ if($res) {
16
+ Mage::getSingleton('core/session')->addSuccess(Mage::helper('pptrack')->__('You have successfully unsubscribed from package status updates'));
17
+ }
18
+ else {
19
+ Mage::getSingleton('core/session')->addWarning(Mage::helper('pptrack')->__('Subscription not found or already unsubscribed!'));
20
+ }
21
+ }
22
+ else {
23
+ Mage::getSingleton('core/session')->addError(Mage::helper('pptrack')->__('Tracking info not found!'));
24
+ }
25
+ }
26
+
27
+ $this->loadLayout();
28
+ $this->getLayout()->getBlock("head")->setTitle($this->__("Unsubscribe"));
29
+ $this->renderLayout();
30
+ }
31
+ }
app/code/community/Packpin/Pptrack/etc/adminhtml.xml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <layout>
4
+ <updates>
5
+ <pptrack>
6
+ <file>pptrack.xml</file>
7
+ </pptrack>
8
+ </updates>
9
+ </layout>
10
+ <acl>
11
+ <resources>
12
+ <admin>
13
+ <children>
14
+ <system>
15
+ <children>
16
+ <config>
17
+ <children>
18
+ <pp_section_setttings translate="title" module="pptrack">
19
+ <title>Packpin General Settings Section</title>
20
+ <sort_order>51001</sort_order>
21
+ </pp_section_setttings>
22
+ <pp_section_notification_emails translate="title" module="pptrack">
23
+ <title>Packpin Notification Emails</title>
24
+ <sort_order>51002</sort_order>
25
+ </pp_section_notification_emails>
26
+ <pp_section_carriers translate="title" module="pptrack">
27
+ <title>Packpin Carrier Settings</title>
28
+ <sort_order>51003</sort_order>
29
+ </pp_section_carriers>
30
+ </children>
31
+ </config>
32
+ </children>
33
+ </system>
34
+ </children>
35
+ </admin>
36
+ </resources>
37
+ </acl>
38
+ </config>
app/code/community/Packpin/Pptrack/etc/api.xml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <api>
3
+ <resources>
4
+ <pptrack translate="title" module="pptrack">
5
+ <title>Packpin Email Resource</title>
6
+ <model>pptrack/api</model>
7
+ <methods>
8
+ <info translate="title" module="pptrack">
9
+ <title>Retrieve notification email info</title>
10
+ </info>
11
+ <test translate="title" module="pptrack">
12
+ <title>Test Packpin API connection</title>
13
+ </test>
14
+ </methods>
15
+ <faults module="pptrack">
16
+ <data_invalid>
17
+ <code>100</code >
18
+ <message>Invalid tracking data. Details in error message.</message>
19
+ </data_invalid>
20
+ <not_exists>
21
+ <code>102</code >
22
+ <message>Tracking code does not exist.</message>
23
+ </not_exists>
24
+ </faults>
25
+ </pptrack>
26
+ </resources>
27
+ <acl>
28
+ <resources>
29
+ <pptrack translate="title" module="pptrack">
30
+ <title>Packpin notifications</title>
31
+ <info translate="title" module="pptrack">
32
+ <title>Get Email Template Info</title>
33
+ <acl>pptrack/info</acl>
34
+ </info>
35
+ <test translate="title" module="pptrack">
36
+ <title>Test Packpin API connection</title>
37
+ <acl>pptrack/test</acl>
38
+ </test>
39
+ </pptrack>
40
+ </resources>
41
+ </acl>
42
+ </api>
43
+ </config>
app/code/community/Packpin/Pptrack/etc/config.xml ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Packpin_Pptrack>
5
+ <version>1.0.2</version>
6
+ </Packpin_Pptrack>
7
+ </modules>
8
+ <frontend>
9
+ <routers>
10
+ <pptrack>
11
+ <use>standard</use>
12
+ <args>
13
+ <module>Packpin_Pptrack</module>
14
+ <frontName>pptrack</frontName>
15
+ </args>
16
+ </pptrack>
17
+ </routers>
18
+ <layout>
19
+ <updates>
20
+ <pptrack>
21
+ <file>pptrack.xml</file>
22
+ </pptrack>
23
+ <pptrack_unsubscribe>
24
+ <file>pptrackunsubscribe.xml</file>
25
+ </pptrack_unsubscribe>
26
+ </updates>
27
+ </layout>
28
+ </frontend>
29
+ <global>
30
+ <models>
31
+ <packpinpptrackvalidation>
32
+ <class>Packpin_Pptrack_Model</class>
33
+ </packpinpptrackvalidation>
34
+ <pptrack>
35
+ <class>Packpin_Pptrack_Model</class>
36
+ <resourceModel>pptrack_resource</resourceModel>
37
+ </pptrack>
38
+ <pptrackcron>
39
+ <class>Packpin_Pptrack_Model</class>
40
+ <resourceModel>pptrack_resource</resourceModel>
41
+ </pptrackcron>
42
+ <pptrack_resource>
43
+ <class>Packpin_Pptrack_Model_Resource</class>
44
+ <entities>
45
+ <track>
46
+ <table>pp_tracks</table>
47
+ </track>
48
+ <trackunsubscribed>
49
+ <table>pp_tracks_unsubscribed</table>
50
+ </trackunsubscribed>
51
+ <trackdetail>
52
+ <table>pp_track_details</table>
53
+ </trackdetail>
54
+ <carrier>
55
+ <table>pp_carriers</table>
56
+ </carrier>
57
+ <setting>
58
+ <table>pp_settings</table>
59
+ </setting>
60
+ <notification_setting>
61
+ <table>pp_notification_settings</table>
62
+ </notification_setting>
63
+ <notification_template>
64
+ <table>pp_notification_templates</table>
65
+ </notification_template>
66
+ </entities>
67
+ </pptrack_resource>
68
+ <status>
69
+ <class>Packpin_Track_Model</class>
70
+ </status>
71
+ <cron_job>
72
+ <class>Packpin_Track_Model</class>
73
+ </cron_job>
74
+ <notification>
75
+ <class>Packpin_Track_Model</class>
76
+ </notification>
77
+ <sales>
78
+ <rewrite>
79
+ <order_shipment>Packpin_Pptrack_Model_Order_Shipment</order_shipment>
80
+ </rewrite>
81
+ </sales>
82
+ <core>
83
+ <rewrite>
84
+ <translate>Packpin_Pptrack_Model_Translate</translate>
85
+ </rewrite>
86
+ </core>
87
+ </models>
88
+ <helpers>
89
+ <pptrack>
90
+ <class>Packpin_Pptrack_Helper</class>
91
+ </pptrack>
92
+ </helpers>
93
+ <blocks>
94
+ <pptrack>
95
+ <class>Packpin_Pptrack_Block</class>
96
+ <trackings>
97
+ <class>Packpin_Pptrack_Block_Trackings</class>
98
+ </trackings>
99
+ </pptrack>
100
+ <pptrack_adminhtml>
101
+ <class>Packpin_Pptrack_Block_Adminhtml</class>
102
+ </pptrack_adminhtml>
103
+ <adminhtml>
104
+ <rewrite>
105
+ <sales_order_shipment_view_tracking>Packpin_Pptrack_Block_Adminhtml_Sales_Order_Shipment_View_Tracking</sales_order_shipment_view_tracking>
106
+ <sales_order_shipment_create_tracking>Packpin_Pptrack_Block_Adminhtml_Sales_Order_Shipment_Create_Tracking</sales_order_shipment_create_tracking>
107
+ </rewrite>
108
+ </adminhtml>
109
+ </blocks>
110
+ <resources>
111
+ <pptrack_setup>
112
+ <setup>
113
+ <module>Packpin_Pptrack</module>
114
+ </setup>
115
+ <connection>
116
+ <use>core_setup</use>
117
+ </connection>
118
+ </pptrack_setup>
119
+ <pptrack_write>
120
+ <connection>
121
+ <use>core_write</use>
122
+ </connection>
123
+ </pptrack_write>
124
+ <pptrack_read>
125
+ <connection>
126
+ <use>core_read</use>
127
+ </connection>
128
+ </pptrack_read>
129
+ </resources>
130
+ <events>
131
+ <sales_order_shipment_track_save_after>
132
+ <observers>
133
+ <pp_track_save>
134
+ <type>singleton</type>
135
+ <class>pptrack/observer</class>
136
+ <method>afterShipmentSaved</method>
137
+ </pp_track_save>
138
+ </observers>
139
+ </sales_order_shipment_track_save_after>
140
+ <sales_order_shipment_track_delete_after>
141
+ <observers>
142
+ <pp_track_delete>
143
+ <type>singleton</type>
144
+ <class>pptrack/observer</class>
145
+ <method>afterShipmentRemoved</method>
146
+ </pp_track_delete>
147
+ </observers>
148
+ </sales_order_shipment_track_delete_after>
149
+ <controller_action_predispatch_shipping_tracking_popup>
150
+ <observers>
151
+ <pp_tracking_popup_predispatch>
152
+ <type>singleton</type>
153
+ <class>pptrack/observer</class>
154
+ <method>trackingPopupPreDispatch</method>
155
+ </pp_tracking_popup_predispatch>
156
+ </observers>
157
+ </controller_action_predispatch_shipping_tracking_popup>
158
+ <admin_system_config_changed_section_pp_section_carriers>
159
+ <observers>
160
+ <module_name>
161
+ <type>singleton</type>
162
+ <class>pptrack/observer</class>
163
+ <method>saveCarriers</method>
164
+ </module_name>
165
+ </observers>
166
+ </admin_system_config_changed_section_pp_section_carriers>
167
+ </events>
168
+ <template>
169
+ <email>
170
+ <packpin_delivered_email>
171
+ <label>Packpin Delivered Notification Email</label>
172
+ <file>packpin/packpin_delivered_email.html</file>
173
+ <type>html</type>
174
+ </packpin_delivered_email>
175
+ <packpin_exception_email>
176
+ <label>Packpin Exception Notification Email</label>
177
+ <file>packpin/packpin_exception_email.html</file>
178
+ <type>html</type>
179
+ </packpin_exception_email>
180
+ <packpin_failed_attempt_email>
181
+ <label>Packpin Failed Attempt Notification Email</label>
182
+ <file>packpin/packpin_failed_attempt_email.html</file>
183
+ <type>html</type>
184
+ </packpin_failed_attempt_email>
185
+ <packpin_in_transit_email>
186
+ <label>Packpin in Transit Notification Email</label>
187
+ <file>packpin/packpin_in_transit_email.html</file>
188
+ <type>html</type>
189
+ </packpin_in_transit_email>
190
+ <packpin_info_received_email>
191
+ <label>Packpin Info Received Notification Email</label>
192
+ <file>packpin/packpin_info_received_email.html</file>
193
+ <type>html</type>
194
+ </packpin_info_received_email>
195
+ <packpin_out_for_delivery_email>
196
+ <label>Packpin Out for Delivery Notification Email</label>
197
+ <file>packpin/packpin_out_for_delivery_email.html</file>
198
+ <type>html</type>
199
+ </packpin_out_for_delivery_email>
200
+ </email>
201
+ </template>
202
+ </global>
203
+ <crontab>
204
+ <jobs>
205
+ <pptrack_check_tracks>
206
+ <schedule>
207
+ <cron_expr>1 */2 * * *</cron_expr>
208
+ </schedule>
209
+ <run>
210
+ <model>pptrack/observer::cron</model>
211
+ </run>
212
+ </pptrack_check_tracks>
213
+ </jobs>
214
+ </crontab>
215
+ <adminhtml>
216
+ <layout>
217
+ <updates>
218
+ <pptrack>
219
+ <file>pptrack.xml</file>
220
+ </pptrack>
221
+ </updates>
222
+ </layout>
223
+ </adminhtml>
224
+ <default>
225
+ <pp_section_setttings>
226
+ <crosssell>
227
+ <cross_sell_page>1</cross_sell_page>
228
+ <cross_sell_email>1</cross_sell_email>
229
+ <cross_sell_page_items>6</cross_sell_page_items>
230
+ <cross_sell_email_items>4</cross_sell_email_items>
231
+ </crosssell>
232
+ </pp_section_setttings>
233
+ <pp_section_notification_emails>
234
+ <info_received>
235
+ <enabled_client>1</enabled_client>
236
+ <identity>general</identity>
237
+ </info_received>
238
+ <in_transit>
239
+ <enabled_client>1</enabled_client>
240
+ <identity>general</identity>
241
+ </in_transit>
242
+ <out_for_delivery>
243
+ <enabled_client>1</enabled_client>
244
+ <identity>general</identity>
245
+ </out_for_delivery>
246
+ <delivered>
247
+ <enabled_client>1</enabled_client>
248
+ <identity>general</identity>
249
+ </delivered>
250
+ <exception>
251
+ <enabled_client>1</enabled_client>
252
+ <identity>general</identity>
253
+ </exception>
254
+ <failed_attempt>
255
+ <enabled_client>1</enabled_client>
256
+ <identity>general</identity>
257
+ </failed_attempt>
258
+ </pp_section_notification_emails>
259
+ </default>
260
+ </config>
app/code/community/Packpin/Pptrack/etc/system.xml ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <tabs>
4
+ <pp_tab translate="label" module="pptrack">
5
+ <label>Packpin</label>
6
+ <sort_order>51000</sort_order>
7
+ </pp_tab>
8
+ </tabs>
9
+ <sections>
10
+ <pp_section_setttings translate="label" module="pptrack">
11
+ <label>Packpin Settings</label>
12
+ <class>packpin-settings</class>
13
+ <tab>pp_tab</tab>
14
+ <frontend_type>text</frontend_type>
15
+ <sort_order>51001</sort_order>
16
+ <show_in_default>1</show_in_default>
17
+ <show_in_website>1</show_in_website>
18
+ <show_in_store>1</show_in_store>
19
+ <groups>
20
+ <settings translate="label">
21
+ <expanded>1</expanded>
22
+ <label>General settings</label>
23
+ <frontend_type>text</frontend_type>
24
+ <sort_order>1</sort_order>
25
+ <show_in_default>1</show_in_default>
26
+ <show_in_website>1</show_in_website>
27
+ <show_in_store>0</show_in_store>
28
+ <fields>
29
+ <status translate="label">
30
+ <label>Status</label>
31
+ <frontend_type>select</frontend_type>
32
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
33
+ <sort_order>11</sort_order>
34
+ <show_in_default>1</show_in_default>
35
+ <show_in_website>1</show_in_website>
36
+ <show_in_store>0</show_in_store>
37
+ </status>
38
+ <api_key translate="label">
39
+ <label><![CDATA[ API key <strong style="color:red">*</strong>]]></label>
40
+ <frontend_type>text</frontend_type>
41
+ <sort_order>10</sort_order>
42
+ <show_in_default>1</show_in_default>
43
+ <show_in_website>1</show_in_website>
44
+ <show_in_store>0</show_in_store>
45
+ <validate>required-entry</validate>
46
+ </api_key>
47
+ <last_cron>
48
+ <label>Last Cron Time</label>
49
+ <frontend_type>text</frontend_type>
50
+ <sort_order>101</sort_order>
51
+ <show_in_default>0</show_in_default>
52
+ <show_in_website>0</show_in_website>
53
+ <show_in_store>0</show_in_store>
54
+ </last_cron>
55
+ <last_carrier_update>
56
+ <label>Last Carrier Update</label>
57
+ <frontend_type>text</frontend_type>
58
+ <sort_order>102</sort_order>
59
+ <show_in_default>0</show_in_default>
60
+ <show_in_website>0</show_in_website>
61
+ <show_in_store>0</show_in_store>
62
+ </last_carrier_update>
63
+ <upgrade_note>
64
+ <label><![CDATA[<strong>How to setup</strong>]]></label>
65
+ <frontend_type>note</frontend_type>
66
+ <sort_order>1</sort_order>
67
+ <show_in_default>1</show_in_default>
68
+ <show_in_website>1</show_in_website>
69
+ <show_in_store>0</show_in_store>
70
+ <comment>
71
+ <![CDATA[
72
+ <ol>
73
+ <li style="margin-bottom:10px !important;">1. Sign up at <a href="https://panel.packpin.com/" target="_blank">panel.packpin.com</a></li>
74
+ <li style="margin-bottom:10px !important;">2. Go to <a href="https://panel.packpin.com/api_keys" taget="_blank">"API keys"</a> and generate new key</li>
75
+ <li style="margin-bottom:10px !important;">3. Copy API key and paste to the field below</li>
76
+ <li style="margin-bottom:10px !important;">4. Change status to "Enabled" and click "Save Config"</li>
77
+ <li>5. Now the plugin is active and running</li>
78
+ </ol>
79
+ ]]>
80
+ </comment>
81
+ </upgrade_note>
82
+ <disable_default_carriers translate="label">
83
+ <label>Disable default carriers</label>
84
+ <frontend_type>select</frontend_type>
85
+ <source_model>adminhtml/system_config_source_yesno</source_model>
86
+ <sort_order>20</sort_order>
87
+ <show_in_default>1</show_in_default>
88
+ <show_in_website>1</show_in_website>
89
+ <show_in_store>0</show_in_store>
90
+ </disable_default_carriers>
91
+ <pp_enable_notifications translate="label">
92
+ <backend_model>packpinpptrackvalidation/enableNotifications</backend_model>
93
+ <label>Enable Notifications</label>
94
+ <frontend_type>select</frontend_type>
95
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
96
+ <sort_order>21</sort_order>
97
+ <show_in_default>1</show_in_default>
98
+ <show_in_website>1</show_in_website>
99
+ <show_in_store>0</show_in_store>
100
+ <comment>In order to enable notifications we will create SOAP/XML-RPC role and user.</comment>
101
+ </pp_enable_notifications>
102
+ </fields>
103
+ </settings>
104
+ <crosssell>
105
+ <expanded>1</expanded>
106
+ <label>Cross-sell settings</label>
107
+ <frontend_type>text</frontend_type>
108
+ <sort_order>2</sort_order>
109
+ <show_in_default>1</show_in_default>
110
+ <show_in_website>1</show_in_website>
111
+ <show_in_store>0</show_in_store>
112
+ <fields>
113
+ <cross_sell_page translate="label">
114
+ <label>Show cross-sell items on shipment information page</label>
115
+ <frontend_type>select</frontend_type>
116
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
117
+ <sort_order>30</sort_order>
118
+ <show_in_default>1</show_in_default>
119
+ <show_in_website>1</show_in_website>
120
+ <show_in_store>0</show_in_store>
121
+ </cross_sell_page>
122
+ <cross_sell_page_items translate="label">
123
+ <label>Number of cross-sell items on page</label>
124
+ <frontend_type>text</frontend_type>
125
+ <sort_order>31</sort_order>
126
+ <show_in_default>1</show_in_default>
127
+ <show_in_website>1</show_in_website>
128
+ <show_in_store>0</show_in_store>
129
+ <comment>Recommended value is between 4 and 6</comment>
130
+ </cross_sell_page_items>
131
+ <cross_sell_email translate="label">
132
+ <label>Show cross-sell items in notification emails</label>
133
+ <frontend_type>select</frontend_type>
134
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
135
+ <sort_order>32</sort_order>
136
+ <show_in_default>1</show_in_default>
137
+ <show_in_website>1</show_in_website>
138
+ <show_in_store>0</show_in_store>
139
+ </cross_sell_email>
140
+ <cross_sell_email_items translate="label">
141
+ <label>Number of cross-sell items in emails</label>
142
+ <frontend_type>text</frontend_type>
143
+ <sort_order>33</sort_order>
144
+ <show_in_default>1</show_in_default>
145
+ <show_in_website>1</show_in_website>
146
+ <show_in_store>0</show_in_store>
147
+ </cross_sell_email_items>
148
+ </fields>
149
+ </crosssell>
150
+ </groups>
151
+ </pp_section_setttings>
152
+
153
+ <pp_section_notification_emails translate="label" module="sales">
154
+ <label>Notification Emails</label>
155
+ <class>packpin-settings</class>
156
+ <tab>pp_tab</tab>
157
+ <frontend_type>text</frontend_type>
158
+ <sort_order>51002</sort_order>
159
+ <show_in_default>1</show_in_default>
160
+ <show_in_website>1</show_in_website>
161
+ <show_in_store>1</show_in_store>
162
+ <groups>
163
+ <info_received translate="label">
164
+ <label>Info Received</label>
165
+ <frontend_type>text</frontend_type>
166
+ <sort_order>1</sort_order>
167
+ <show_in_default>1</show_in_default>
168
+ <show_in_website>1</show_in_website>
169
+ <show_in_store>1</show_in_store>
170
+ <fields>
171
+ <enabled_client translate="label">
172
+ <label>Enabled for client</label>
173
+ <frontend_type>select</frontend_type>
174
+ <source_model>adminhtml/system_config_source_yesno</source_model>
175
+ <sort_order>0</sort_order>
176
+ <show_in_default>1</show_in_default>
177
+ <show_in_website>1</show_in_website>
178
+ <show_in_store>1</show_in_store>
179
+ </enabled_client>
180
+ <enabled_owner translate="label">
181
+ <label>Enabled for owner</label>
182
+ <frontend_type>select</frontend_type>
183
+ <source_model>adminhtml/system_config_source_yesno</source_model>
184
+ <sort_order>0</sort_order>
185
+ <show_in_default>1</show_in_default>
186
+ <show_in_website>1</show_in_website>
187
+ <show_in_store>1</show_in_store>
188
+ </enabled_owner>
189
+ <identity translate="label">
190
+ <label>Sender Email</label>
191
+ <frontend_type>select</frontend_type>
192
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
193
+ <sort_order>1</sort_order>
194
+ <show_in_default>1</show_in_default>
195
+ <show_in_website>1</show_in_website>
196
+ <show_in_store>1</show_in_store>
197
+ </identity>
198
+ <template translate="label">
199
+ <label>Template</label>
200
+ <frontend_type>select</frontend_type>
201
+ <source_model>adminhtml/system_config_source_email_template</source_model>
202
+ <sort_order>2</sort_order>
203
+ <show_in_default>1</show_in_default>
204
+ <show_in_website>1</show_in_website>
205
+ <show_in_store>1</show_in_store>
206
+ </template>
207
+ </fields>
208
+ </info_received>
209
+
210
+ <in_transit translate="label">
211
+ <label>In Transit</label>
212
+ <frontend_type>text</frontend_type>
213
+ <sort_order>2</sort_order>
214
+ <show_in_default>1</show_in_default>
215
+ <show_in_website>1</show_in_website>
216
+ <show_in_store>1</show_in_store>
217
+ <fields>
218
+ <enabled_client translate="label">
219
+ <label>Enabled for client</label>
220
+ <frontend_type>select</frontend_type>
221
+ <source_model>adminhtml/system_config_source_yesno</source_model>
222
+ <sort_order>0</sort_order>
223
+ <show_in_default>1</show_in_default>
224
+ <show_in_website>1</show_in_website>
225
+ <show_in_store>1</show_in_store>
226
+ </enabled_client>
227
+ <enabled_owner translate="label">
228
+ <label>Enabled for owner</label>
229
+ <frontend_type>select</frontend_type>
230
+ <source_model>adminhtml/system_config_source_yesno</source_model>
231
+ <sort_order>0</sort_order>
232
+ <show_in_default>1</show_in_default>
233
+ <show_in_website>1</show_in_website>
234
+ <show_in_store>1</show_in_store>
235
+ </enabled_owner>
236
+ <identity translate="label">
237
+ <label>Sender Email</label>
238
+ <frontend_type>select</frontend_type>
239
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
240
+ <sort_order>1</sort_order>
241
+ <show_in_default>1</show_in_default>
242
+ <show_in_website>1</show_in_website>
243
+ <show_in_store>1</show_in_store>
244
+ </identity>
245
+ <template translate="label">
246
+ <label>Template</label>
247
+ <frontend_type>select</frontend_type>
248
+ <source_model>adminhtml/system_config_source_email_template</source_model>
249
+ <sort_order>2</sort_order>
250
+ <show_in_default>1</show_in_default>
251
+ <show_in_website>1</show_in_website>
252
+ <show_in_store>1</show_in_store>
253
+ </template>
254
+ </fields>
255
+ </in_transit>
256
+
257
+ <out_for_delivery translate="label">
258
+ <label>Out for Delivery</label>
259
+ <frontend_type>text</frontend_type>
260
+ <sort_order>3</sort_order>
261
+ <show_in_default>1</show_in_default>
262
+ <show_in_website>1</show_in_website>
263
+ <show_in_store>1</show_in_store>
264
+ <fields>
265
+ <enabled_client translate="label">
266
+ <label>Enabled for client</label>
267
+ <frontend_type>select</frontend_type>
268
+ <source_model>adminhtml/system_config_source_yesno</source_model>
269
+ <sort_order>0</sort_order>
270
+ <show_in_default>1</show_in_default>
271
+ <show_in_website>1</show_in_website>
272
+ <show_in_store>1</show_in_store>
273
+ </enabled_client>
274
+ <enabled_owner translate="label">
275
+ <label>Enabled for owner</label>
276
+ <frontend_type>select</frontend_type>
277
+ <source_model>adminhtml/system_config_source_yesno</source_model>
278
+ <sort_order>0</sort_order>
279
+ <show_in_default>1</show_in_default>
280
+ <show_in_website>1</show_in_website>
281
+ <show_in_store>1</show_in_store>
282
+ </enabled_owner>
283
+ <identity translate="label">
284
+ <label>Sender Email</label>
285
+ <frontend_type>select</frontend_type>
286
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
287
+ <sort_order>1</sort_order>
288
+ <show_in_default>1</show_in_default>
289
+ <show_in_website>1</show_in_website>
290
+ <show_in_store>1</show_in_store>
291
+ </identity>
292
+ <template translate="label">
293
+ <label>Template</label>
294
+ <frontend_type>select</frontend_type>
295
+ <source_model>adminhtml/system_config_source_email_template</source_model>
296
+ <sort_order>2</sort_order>
297
+ <show_in_default>1</show_in_default>
298
+ <show_in_website>1</show_in_website>
299
+ <show_in_store>1</show_in_store>
300
+ </template>
301
+ </fields>
302
+ </out_for_delivery>
303
+ <delivered translate="label">
304
+ <label>Delivered</label>
305
+ <frontend_type>text</frontend_type>
306
+ <sort_order>4</sort_order>
307
+ <show_in_default>1</show_in_default>
308
+ <show_in_website>1</show_in_website>
309
+ <show_in_store>1</show_in_store>
310
+ <fields>
311
+ <enabled_client translate="label">
312
+ <label>Enabled for client</label>
313
+ <frontend_type>select</frontend_type>
314
+ <source_model>adminhtml/system_config_source_yesno</source_model>
315
+ <sort_order>0</sort_order>
316
+ <show_in_default>1</show_in_default>
317
+ <show_in_website>1</show_in_website>
318
+ <show_in_store>1</show_in_store>
319
+ </enabled_client>
320
+ <enabled_owner translate="label">
321
+ <label>Enabled for owner</label>
322
+ <frontend_type>select</frontend_type>
323
+ <source_model>adminhtml/system_config_source_yesno</source_model>
324
+ <sort_order>0</sort_order>
325
+ <show_in_default>1</show_in_default>
326
+ <show_in_website>1</show_in_website>
327
+ <show_in_store>1</show_in_store>
328
+ </enabled_owner>
329
+ <identity translate="label">
330
+ <label>Sender Email</label>
331
+ <frontend_type>select</frontend_type>
332
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
333
+ <sort_order>1</sort_order>
334
+ <show_in_default>1</show_in_default>
335
+ <show_in_website>1</show_in_website>
336
+ <show_in_store>1</show_in_store>
337
+ </identity>
338
+ <template translate="label">
339
+ <label>Template</label>
340
+ <frontend_type>select</frontend_type>
341
+ <source_model>adminhtml/system_config_source_email_template</source_model>
342
+ <sort_order>2</sort_order>
343
+ <show_in_default>1</show_in_default>
344
+ <show_in_website>1</show_in_website>
345
+ <show_in_store>1</show_in_store>
346
+ </template>
347
+ </fields>
348
+ </delivered>
349
+
350
+ <exception translate="label">
351
+ <label>Exception</label>
352
+ <frontend_type>text</frontend_type>
353
+ <sort_order>5</sort_order>
354
+ <show_in_default>1</show_in_default>
355
+ <show_in_website>1</show_in_website>
356
+ <show_in_store>1</show_in_store>
357
+ <fields>
358
+ <enabled_client translate="label">
359
+ <label>Enabled for client</label>
360
+ <frontend_type>select</frontend_type>
361
+ <source_model>adminhtml/system_config_source_yesno</source_model>
362
+ <sort_order>0</sort_order>
363
+ <show_in_default>1</show_in_default>
364
+ <show_in_website>1</show_in_website>
365
+ <show_in_store>1</show_in_store>
366
+ </enabled_client>
367
+ <enabled_owner translate="label">
368
+ <label>Enabled for owner</label>
369
+ <frontend_type>select</frontend_type>
370
+ <source_model>adminhtml/system_config_source_yesno</source_model>
371
+ <sort_order>0</sort_order>
372
+ <show_in_default>1</show_in_default>
373
+ <show_in_website>1</show_in_website>
374
+ <show_in_store>1</show_in_store>
375
+ </enabled_owner>
376
+ <identity translate="label">
377
+ <label>Sender Email</label>
378
+ <frontend_type>select</frontend_type>
379
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
380
+ <sort_order>1</sort_order>
381
+ <show_in_default>1</show_in_default>
382
+ <show_in_website>1</show_in_website>
383
+ <show_in_store>1</show_in_store>
384
+ </identity>
385
+ <template translate="label">
386
+ <label>Template</label>
387
+ <frontend_type>select</frontend_type>
388
+ <source_model>adminhtml/system_config_source_email_template</source_model>
389
+ <sort_order>2</sort_order>
390
+ <show_in_default>1</show_in_default>
391
+ <show_in_website>1</show_in_website>
392
+ <show_in_store>1</show_in_store>
393
+ </template>
394
+ </fields>
395
+ </exception>
396
+ <failed_attempt translate="label">
397
+ <label>Failed Attempt</label>
398
+ <frontend_type>text</frontend_type>
399
+ <sort_order>6</sort_order>
400
+ <show_in_default>1</show_in_default>
401
+ <show_in_website>1</show_in_website>
402
+ <show_in_store>1</show_in_store>
403
+ <fields>
404
+ <enabled_client translate="label">
405
+ <label>Enabled for client</label>
406
+ <frontend_type>select</frontend_type>
407
+ <source_model>adminhtml/system_config_source_yesno</source_model>
408
+ <sort_order>0</sort_order>
409
+ <show_in_default>1</show_in_default>
410
+ <show_in_website>1</show_in_website>
411
+ <show_in_store>1</show_in_store>
412
+ </enabled_client>
413
+ <enabled_owner translate="label">
414
+ <label>Enabled for owner</label>
415
+ <frontend_type>select</frontend_type>
416
+ <source_model>adminhtml/system_config_source_yesno</source_model>
417
+ <sort_order>0</sort_order>
418
+ <show_in_default>1</show_in_default>
419
+ <show_in_website>1</show_in_website>
420
+ <show_in_store>1</show_in_store>
421
+ </enabled_owner>
422
+ <identity translate="label">
423
+ <label>Sender Email</label>
424
+ <frontend_type>select</frontend_type>
425
+ <source_model>adminhtml/system_config_source_email_identity</source_model>
426
+ <sort_order>1</sort_order>
427
+ <show_in_default>1</show_in_default>
428
+ <show_in_website>1</show_in_website>
429
+ <show_in_store>1</show_in_store>
430
+ </identity>
431
+ <template translate="label">
432
+ <label>Template</label>
433
+ <frontend_type>select</frontend_type>
434
+ <source_model>adminhtml/system_config_source_email_template</source_model>
435
+ <sort_order>2</sort_order>
436
+ <show_in_default>1</show_in_default>
437
+ <show_in_website>1</show_in_website>
438
+ <show_in_store>1</show_in_store>
439
+ </template>
440
+ </fields>
441
+ </failed_attempt>
442
+ </groups>
443
+ </pp_section_notification_emails>
444
+ <pp_section_carriers>
445
+ <label>Carrier Settings</label>
446
+ <class>packpin-settings</class>
447
+ <tab>pp_tab</tab>
448
+ <frontend_type>text</frontend_type>
449
+ <sort_order>51003</sort_order>
450
+ <show_in_default>1</show_in_default>
451
+ <show_in_website>1</show_in_website>
452
+ <show_in_store>0</show_in_store>
453
+ <groups>
454
+ <carriers translate="label">
455
+ <expanded>1</expanded>
456
+ <label>Enabled Carriers</label>
457
+ <frontend_type>text</frontend_type>
458
+ <frontend_model>pptrack/adminhtml_system_config_form_fieldset_carrier</frontend_model>
459
+ <sort_order>1</sort_order>
460
+ <show_in_default>1</show_in_default>
461
+ <show_in_website>1</show_in_website>
462
+ <show_in_store>0</show_in_store>
463
+ </carriers>
464
+ </groups>
465
+ </pp_section_carriers>
466
+ </sections>
467
+ </config>
app/code/community/Packpin/Pptrack/sql/pptrack_setup/mysql4-install-0.1.2.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $tableNameTrack = $installer->getTable('pptrack/track');
7
+ $tableNameDetails = $installer->getTable('pptrack/trackdetail');
8
+ $tableNameCarriers = $installer->getTable('pptrack/carrier');
9
+ $tableNameSettings = $installer->getTable('pptrack/setting');
10
+
11
+ $installer->run("DROP TABLE IF EXISTS `{$tableNameDetails}`;");
12
+ $installer->run("DROP TABLE IF EXISTS `{$tableNameTrack}`;");
13
+ $installer->run("DROP TABLE IF EXISTS `{$tableNameCarriers}`;");
14
+ $installer->run("DROP TABLE IF EXISTS `{$tableNameSettings}`;");
15
+
16
+ $sql=<<<SQLTEXT
17
+
18
+ CREATE TABLE IF NOT EXISTS `{$tableNameTrack}` (
19
+ `id` INT NOT NULL AUTO_INCREMENT ,
20
+ `hash` varchar(255) NOT NULL,
21
+ `order_id` varchar(255) NOT NULL,
22
+ `shipment_id` INT DEFAULT NULL,
23
+ `code` varchar(50) NOT NULL,
24
+ `carrier_code` varchar(50) DEFAULT NULL,
25
+ `carrier_name` varchar(255) DEFAULT NULL,
26
+ `postal_code` varchar(50) DEFAULT NULL,
27
+ `ship_date` varchar(50) DEFAULT NULL,
28
+ `destination_country` varchar(50) DEFAULT NULL,
29
+ `status` varchar(50) DEFAULT 'pending',
30
+ `email` varchar(255) DEFAULT NULL,
31
+ `phone` varchar(255) DEFAULT NULL,
32
+ `created_at` INT DEFAULT NULL,
33
+ `updated_at` INT DEFAULT NULL,
34
+ `submitted` INT NOT NULL DEFAULT '0',
35
+ PRIMARY KEY (`id`),
36
+ KEY `hash` (`hash`),
37
+ KEY `order_id` (`order_id`),
38
+ KEY `submitted` (`submitted`)
39
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
40
+
41
+
42
+ CREATE TABLE IF NOT EXISTS `{$tableNameDetails}` (
43
+ `id` INT NOT NULL AUTO_INCREMENT ,
44
+ `track_id` INT NOT NULL,
45
+ `carrier` varchar(50) DEFAULT NULL,
46
+ `status` varchar(50) NOT NULL,
47
+ `status_string` varchar(255) DEFAULT NULL,
48
+ `event_date` DATE DEFAULT NULL,
49
+ `event_time` TIME DEFAULT NULL,
50
+ `address` varchar(255) DEFAULT NULL,
51
+ `country` char(2) DEFAULT NULL,
52
+ PRIMARY KEY (`id`)
53
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
54
+
55
+
56
+ CREATE TABLE IF NOT EXISTS `{$tableNameCarriers}` (
57
+ `id` INT NOT NULL AUTO_INCREMENT ,
58
+ `code` varchar(50) NOT NULL,
59
+ `name` varchar(255) NOT NULL,
60
+ `phone` varchar(255) DEFAULT NULL,
61
+ `homepage` varchar(255) DEFAULT NULL,
62
+ `enabled` INT NOT NULL DEFAULT '1',
63
+ PRIMARY KEY (`id`)
64
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
65
+
66
+ CREATE TABLE IF NOT EXISTS `{$tableNameSettings}` (
67
+ `id` INT NOT NULL AUTO_INCREMENT ,
68
+ `setting` varchar(255) NOT NULL,
69
+ `value` varchar(255) NOT NULL,
70
+ PRIMARY KEY (`id`)
71
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
72
+
73
+ ALTER TABLE `{$tableNameDetails}`
74
+ ADD KEY `track_details_track_id_foreign` (`track_id`);
75
+
76
+ ALTER TABLE `{$tableNameDetails}`
77
+ ADD CONSTRAINT `track_details_track_id_foreign` FOREIGN KEY (`track_id`) REFERENCES `{$tableNameTrack}` (`id`) ON DELETE CASCADE;
78
+
79
+ ALTER TABLE `$tableNameSettings`
80
+ ADD UNIQUE KEY `pp_settings_setting_unique` (`setting`);
81
+
82
+ SQLTEXT;
83
+
84
+ $installer->run($sql);
85
+
86
+ $installer->endSetup();
app/code/community/Packpin/Pptrack/sql/pptrack_setup/mysql4-upgrade-0.1.2-0.1.5.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $tableNameUnsubscribe = $installer->getTable('pptrack/trackunsubscribed');
7
+
8
+
9
+ $sql=<<<SQLTEXT
10
+
11
+ CREATE TABLE IF NOT EXISTS `{$tableNameUnsubscribe}` (
12
+ `id` INT NOT NULL AUTO_INCREMENT ,
13
+ `track_id` INT NOT NULL,
14
+ PRIMARY KEY (`id`),
15
+ KEY `track_id` (`track_id`)
16
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
17
+
18
+ SQLTEXT;
19
+
20
+ $installer->run($sql);
21
+
22
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/pptrack.xml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="1.0.0">
3
+ <adminhtml_system_config_edit>
4
+ <reference name="head">
5
+ <action method="addCss">
6
+ <name>pptrack/css/pptrack.css</name>
7
+ </action>
8
+ </reference>
9
+ </adminhtml_system_config_edit>
10
+ </layout>
app/design/adminhtml/default/default/template/pptrack/system/config/fieldset/hint-owner.phtml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Packpin_Pptrack_Block_Adminhtml_System_Config_Fieldset_Hint
4
+ */
5
+ ?>
6
+ <h4><?php echo Mage::helper('pptrack')->__('Notify shop owner when status changed to') ?></h4>
app/design/frontend/base/default/layout/pptrack.xml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="1.0.0">
3
+ <pptrack_index_index>
4
+ <reference name="root">
5
+ <action method="setTemplate">
6
+ <template>page/1column.phtml</template>
7
+ </action>
8
+ </reference>
9
+ <reference name="head">
10
+ <action method="addCss">
11
+ <stylesheet>css/pptrack.css</stylesheet>
12
+ </action>
13
+ </reference>
14
+ <reference name="content">
15
+ <block type="pptrack/index" name="pptrack_index" template="pptrack/index.phtml">
16
+ <block type="pptrack/crosssell" name="pptrack_crosssell" template="pptrack/crosssell.phtml"/>
17
+ </block>
18
+ </reference>
19
+ </pptrack_index_index>
20
+ <pptrack_index_popup>
21
+ <reference name="root">
22
+ <action method="setTemplate">
23
+ <template>page/popup.phtml</template>
24
+ </action>
25
+ </reference>
26
+ <reference name="head">
27
+ <action method="addCss">
28
+ <stylesheet>css/pptrack.css</stylesheet>
29
+ </action>
30
+ </reference>
31
+ <reference name="content">
32
+ <block type="pptrack/index" name="pptrack_popup" template="pptrack/popup.phtml"/>
33
+ </reference>
34
+ </pptrack_index_popup>
35
+ <pptrack_unsubscribe_index>
36
+ <reference name="root">
37
+ <action method="setTemplate">
38
+ <template>page/1column.phtml</template>
39
+ </action>
40
+ </reference>
41
+ <reference name="head">
42
+ <action method="addCss">
43
+ <stylesheet>css/pptrack.css</stylesheet>
44
+ </action>
45
+ </reference>
46
+ <reference name="content">
47
+ <block type="pptrack/index" name="pptrack_unsubscribe_index" template="pptrack/unsubscribe.phtml"/>
48
+ </reference>
49
+ </pptrack_unsubscribe_index>
50
+ </layout>
app/design/frontend/base/default/template/pptrack/crosssell.phtml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $limit = Mage::getStoreConfig('pp_section_setttings/crosssell/cross_sell_page_items');
3
+ $collection = $this->getCrossSellingItemsByOrderId($this->getData('orderId'), $limit);
4
+ $count = count($collection);
5
+ ?>
6
+ <?php if($count): ?>
7
+ <div class="pptrack-crosssell">
8
+ <h2><?php echo $this->__('While waiting, we have something for you. Check offerings bellow:') ?></h2>
9
+ <ul class="pptrack-products-grid pptrack-products-grid--col-<?php echo $count ?>">
10
+ <?php foreach ($collection as $_item): ?>
11
+ <li>
12
+ <div class="pptrack-list-info-box-wrap">
13
+ <div class="pptrack-list-info-box">
14
+ <a class="pptrack-product-image" href="<?php echo $_item->getProductUrl() ?>" title="<?php echo $this->escapeHtml($_item->getName()) ?>">
15
+ <img src="<?php echo $this->helper('catalog/image')->init($_item, 'small_image')->resize(null, 150); ?>" alt="<?php echo $this->escapeHtml($_item->getName()) ?>" />
16
+ </a>
17
+ <h3 class="pptrack-product-name"><a href="<?php echo $_item->getProductUrl() ?>"><?php echo $this->escapeHtml($_item->getName()) ?></a></h3>
18
+ <?php echo $this->getPriceHtml($_item, true) ?>
19
+ </div>
20
+ </div>
21
+ <button type="button" title="<?php echo $this->__('Add to Cart') ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_item) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button>
22
+ </li>
23
+ <?php endforeach; ?>
24
+ </ul>
25
+ </div>
26
+ <script type="text/javascript">
27
+ function fixCrossBoxes() {
28
+ var max = 0;
29
+ $$(".pptrack-list-info-box").forEach(function (el) {
30
+ max = Math.max(max, el.getHeight());
31
+ });
32
+ $$(".pptrack-list-info-box-wrap").forEach(function (el) {
33
+ el.setStyle({
34
+ height: max + 'px'
35
+ });
36
+ });
37
+ }
38
+ window.onresize = function(event) {
39
+ fixCrossBoxes();
40
+ };
41
+
42
+ Event.observe(window, "load", function() {
43
+ fixCrossBoxes();
44
+
45
+ }, false);
46
+
47
+ </script>
48
+ <?php endif; ?>
app/design/frontend/base/default/template/pptrack/crosssell_email.phtml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $limit = Mage::getStoreConfig('pp_section_setttings/crosssell/cross_sell_email_items');
3
+ $collection = $this->getCrossSellingItemsByOrderId($this->getData('orderId'), $limit);
4
+ ?>
5
+
6
+ <?php if(count($collection)): ?>
7
+ <div style="margin-top:5px;font-size:12px;font-weight:400;text-align:center;;line-height:14px;">
8
+ While you are waiting, we have something for you.
9
+ <br>
10
+ Check the offerings bellow:
11
+ </div>
12
+ <div style="margin-top:20px;">
13
+ <table border="0" cellspacing="10" width="100%;">
14
+ <tr>
15
+ <?php foreach ($collection as $_item): ?>
16
+ <td valign="top" style="text-align:center !important;font-size:11px;background:#ffffff;padding:10px;">
17
+ <a style="display:block;text-decoration:none;" href="<?php echo $_item->getProductUrl() ?>" title="<?php echo $this->escapeHtml($_item->getName()) ?>">
18
+ <img style="max-width:100%;" src="<?php echo $this->helper('catalog/image')->init($_item, 'small_image')->resize(null, 100); ?>" alt="<?php echo $this->escapeHtml($_item->getName()) ?>" />
19
+ </a>
20
+ <a style="display:block;text-decoration:none;font-size:11px;font-weight:400;text-align:center;color:#333333;text-transform:uppercase;" href="<?php echo $_item->getProductUrl() ?>"><?php echo $this->escapeHtml($_item->getName()) ?></a>
21
+ <div style="margin-top:7px;font-size:11px;font-weight:700;text-align:center;">
22
+ <?php echo $this->getPriceHtml($_item, false) ?>
23
+ </div>
24
+ <a style="display:inline-block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;margin-top:3px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="<?php echo $_item->getProductUrl() ?>" title="<?php echo $this->escapeHtml($_item->getName()) ?>">
25
+ READ MORE
26
+ </a>
27
+ </td>
28
+ <?php endforeach; ?>
29
+ </tr>
30
+ </table>
31
+ </div>
32
+ <?php endif; ?>
app/design/frontend/base/default/template/pptrack/email/order/shipment/track.phtml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $_shipment=$this->getShipment() ?>
2
+ <?php $_order=$this->getOrder() ?>
3
+ <?php if ($_shipment && $_order && $_shipment->getAllTracks()): ?>
4
+ <table cellspacing="0" cellpadding="0" border="0" width="650" style="border:1px solid #EAEAEA;">
5
+ <thead>
6
+ <tr>
7
+ <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Shipped By') ?></th>
8
+ <th align="center" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Tracking Number') ?></th>
9
+ <th bgcolor="#EAEAEA" style="padding:3px 9px">&nbsp;</th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <?php $i=0; foreach ($_shipment->getAllTracks() as $_item): $i++ ?>
14
+ <tr <?php echo $i%2?'bgcolor="#F6F6F6"':'' ?>>
15
+ <td align="left" valign="top" style="padding:10px 9px 3px"><?php echo $this->escapeHtml($_item->getTitle()) ?></td>
16
+ <td align="center" valign="top" style="padding:10px 9px 3px"><?php echo $this->escapeHtml($_item->getNumber()) ?></td>
17
+ <td align="center" valign="top" style="padding:3px 9px">
18
+ <?php if ($this->shipmentTracked($_item, $_order)) : ?>
19
+ <?php $ppTrack = $this->getTrackModel(); ?>
20
+ <a href="<?php echo $ppTrack->getDetailsUrl() ?>" style="cursor:pointer;text-decoration:none;display:inline-block;padding:4px 14px;border:1px solid transparent;border-radius:6px;color:#ffffff;background: #24aaa3;"><img style="vertical-align: middle;margin-right:7px;" width="16" height="16" src="<?php echo $this->getSkinUrl('images/pptrack/truck.png') ?>" alt="track"><?php echo $this->__('Track your item') ?></a>
21
+ <?php endif; ?>
22
+ </td>
23
+ </tr>
24
+ <?php endforeach ?>
25
+ </tbody>
26
+ </table>
27
+ <?php endif; ?>
app/design/frontend/base/default/template/pptrack/index.phtml ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ($this->model)
3
+ $model = $this->model;
4
+ else
5
+ $model = Mage::registry('model');
6
+
7
+ $shippingInfo = $model->getShippingInfo();
8
+ $_helper = $this->helper('catalog/output');
9
+ ?>
10
+
11
+ <?php
12
+ if (Mage::getStoreConfig('pp_section_setttings/crosssell/cross_sell_page')) {
13
+ $child = $this->getChild("pptrack_crosssell");
14
+ if ($child) {
15
+ $child->setData("orderId", $model->getOrderId());
16
+ echo $this->getChildHtml('pptrack_crosssell');
17
+ }
18
+ }
19
+ ?>
20
+
21
+ <div style="clear:both;"></div>
22
+ <?php if (!$model->getStatus()): ?>
23
+ <br>
24
+ <br>
25
+ <h2><?php echo $this->__('No tracking info!'); ?></h2>
26
+ <br>
27
+ <?php else: ?>
28
+
29
+ <div class="pptrack-wrapper">
30
+ <h2><?php echo $this->__('Shipment Information'); ?></h2>
31
+ <br/>
32
+
33
+ <div class="pptrack-progress">
34
+ <div class="pptrack-progress-bar-wrapper">
35
+ <div class="pptrack-progress-bar-wrapper">
36
+ <ul class="pptrack-progress-bar <?php if ($model->getStatus() == 'delivered') echo "pptrack-progress-bar-done"; ?>">
37
+ <li class="<?php echo $model->getStatusClass(Packpin_Pptrack_Model_Track::STATUS_PENDING) ?>">
38
+ <div
39
+ class="pptrack-tracking-progress-bar-label"><?php echo $this->__('Dispatched'); ?></div>
40
+ <span class="pptrack-progress-bubble"></span>
41
+ </li>
42
+ <li class="<?php echo $model->getStatusClass(Packpin_Pptrack_Model_Track::STATUS_IN_TRANSIT) ?>">
43
+ <div
44
+ class="pptrack-tracking-progress-bar-label"><?php echo $this->__('In Transit'); ?></div>
45
+ <span class="pptrack-progress-bubble"></span>
46
+ </li>
47
+ <li class="<?php echo $model->getStatusClass(Packpin_Pptrack_Model_Track::STATUS_OUT_FOR_DELIVERY) ?>">
48
+ <div
49
+ class="pptrack-tracking-progress-bar-label"><?php echo $this->__('Out for delivery'); ?></div>
50
+ <span class="pptrack-progress-bubble"></span>
51
+ </li>
52
+ <li class="<?php echo $model->getStatusClass(Packpin_Pptrack_Model_Track::STATUS_DELIVERED) ?>">
53
+ <div class="pptrack-tracking-progress-bar-label"><?php echo $this->__('Delivered'); ?></div>
54
+ <span class="pptrack-progress-bubble"></span>
55
+ </li>
56
+ </ul>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ <br/>
61
+ <br/>
62
+
63
+ <div class="pptrack-tracking-info">
64
+ <h2><?php echo $this->__('Tracking Info'); ?></h2>
65
+
66
+ <div class="pptrack-tracking-info-details">
67
+ <?php $details = $model->getDetails(); ?>
68
+ <?php if (!$details) : ?>
69
+ <div class="pptrack-info-row">
70
+ <div class="pptrack-info-row-date"><?php echo date("Y-m-d", $model->created_at) ?>
71
+ <br/><?php echo date("H:i:s", $model->created_at) ?></div>
72
+ <div class="pptrack-info-row-details-wrapper">
73
+ <div class="pptrack-info-row-details">
74
+ <?php echo $this->__("Package prepared for dispatch") ?>
75
+ </div>
76
+ </div>
77
+ <div style="clear:both;display:table;"></div>
78
+ </div>
79
+ <?php else : ?>
80
+ <?php foreach ($details as $detail): ?>
81
+ <div class="pptrack-info-row">
82
+ <div>
83
+ <div class="pptrack-info-row-date"><?php echo $detail->getEventDate(); ?>
84
+ <br/><?php echo $detail->getEventTime(); ?></div>
85
+ <div class="pptrack-info-row-details-wrapper">
86
+ <div class="pptrack-info-row-details">
87
+ <?php echo $detail->getStatusString(); ?>
88
+ <div
89
+ class="pptrack-info-row-details-location"><?php echo $detail->getLocation() ?></div>
90
+ </div>
91
+ </div>
92
+ <div style="clear:both;display:table;"></div>
93
+ </div>
94
+ </div>
95
+ <?php endforeach; ?>
96
+ <?php endif; ?>
97
+ </div>
98
+ </div>
99
+ <div class="pptrack-tracking-general-info">
100
+ <h2>Info</h2>
101
+
102
+ <div class="pptrack-tracking-general-info-details">
103
+ <div class="pptrack-tracking-row">
104
+ <span class="pptrack-tracking-general-info-label"><?php echo $this->__('Order number'); ?></span>
105
+ <span class="pptrack-tracking-general-info-value"><?php echo $model->getOrderNumber(); ?></span>
106
+ <br style="clear: both;"/>
107
+ </div>
108
+ <div class="pptrack-tracking-row">
109
+ <span class="pptrack-tracking-general-info-label"><?php echo $this->__('Tracking code'); ?></span>
110
+ <span class="pptrack-tracking-general-info-value"><?php echo $model->getCode(); ?></span>
111
+ <br style="clear: both;"/>
112
+ </div>
113
+ <div class="pptrack-tracking-row">
114
+ <span class="pptrack-tracking-general-info-label"><?php echo $this->__('Shipped on'); ?></span>
115
+ <span class="pptrack-tracking-general-info-value"><?php echo $model->getShippingDate(); ?></span>
116
+ <br style="clear: both;"/>
117
+ </div>
118
+ <div class="pptrack-tracking-row">
119
+ <span class="pptrack-tracking-general-info-label"><?php echo $this->__('Ships to'); ?></span>
120
+ <span
121
+ class="pptrack-tracking-general-info-value"><?php echo $shippingInfo['firstname'] . ' ' . $shippingInfo['lastname']; ?>
122
+ <br/><?php echo $shippingInfo['street'] . ', ' . $shippingInfo['city']; ?>
123
+ <br/><?php echo $shippingInfo['region'] ? $shippingInfo['region'] . '<br />' : ''; ?><?php echo $shippingInfo['postcode']; ?> <?php echo Mage::app()->getLocale()->getCountryTranslation($shippingInfo['country_id']); ?></span>
124
+ <br style="clear: both;"/>
125
+ </div>
126
+
127
+ <br/>
128
+
129
+ <div class="pptrack-tracking-carrier-info-wrapper">
130
+ <span><?php echo $this->__('For questions regarding your shipment contact carrier directly'); ?></span><br/>
131
+ <br/>
132
+
133
+ <div class="pptrack-tracking-courier-logo">
134
+ <img src="<?php echo $model->getCarrierIcon() ?>"/>
135
+ </div>
136
+ <div class="pptrack-tracking-courier-info">
137
+ <h3><?php echo $model->getCarrierName() ?></h3>
138
+ <?php
139
+ $phone = $model->getCarrierPhone();
140
+ $homepage = $model->getCarrierHomepage();
141
+ ?>
142
+ <?php if ($phone) : ?>
143
+ <span><?php echo $phone ?></span><br/>
144
+ <?php endif; ?>
145
+ <?php if ($homepage) : ?>
146
+ <a href="<?php echo $homepage ?>"><?php echo $homepage ?></a>
147
+ <?php endif; ?>
148
+ </div>
149
+ <div style="clear:both;"></div>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ </div>
154
+ <?php endif; ?>
app/design/frontend/base/default/template/pptrack/popup.phtml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="page-title title-buttons">
2
+ <h1><?php echo $this->__('Tracking Information'); ?></h1>
3
+ <button class="button" onclick="window.close(); window.opener.focus();"><span><span><?php echo $this->__('Close Window') ?></span></span></button>
4
+ </div>
5
+ <br>
6
+ <?php $models = Mage::registry('models'); ?>
7
+ <?php if ($models) : ?>
8
+ <?php foreach ($models as $trackModel) : ?>
9
+ <table class="tracking-table-popup data-table" style="margin-bottom:25px;">
10
+ <colgroup><col width="15%">
11
+ <col>
12
+ </colgroup><tbody>
13
+ <tr class="first last odd">
14
+ <th class="label"><?php echo $trackModel->getCarrierName() ?>: </th>
15
+ <td class="value last"><?php echo $trackModel->getCode() ?></td>
16
+ </tr>
17
+ </tbody>
18
+ </table>
19
+ <?php echo $this->getLayout()->createBlock('pptrack/index')->setData(array('model' => $trackModel))->setTemplate('pptrack/index.phtml')->toHtml(); ?>
20
+ <div class="clearfix"></div>
21
+ <br>
22
+ <?php endforeach; ?>
23
+ <?php else : ?>
24
+ <?php echo $this->getLayout()->createBlock('pptrack/index')->setTemplate('pptrack/index.phtml')->toHtml(); ?>
25
+ <?php endif; ?>
26
+ <div class="clearfix"></div>
27
+ <div class="buttons-set" style="margin-top:20px;">
28
+ <button type="button" title="<?php echo $this->__('Close Window') ?>" class="button" onclick="window.close(); window.opener.focus();"><span><span><?php echo $this->__('Close Window') ?></span></span></button>
29
+ </div>
app/design/frontend/base/default/template/pptrack/unsubscribe.phtml ADDED
File without changes
app/etc/modules/Packpin_Pptrack.xml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Packpin_Pptrack>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <version>1.0.2</version>
8
+ </Packpin_Pptrack>
9
+ </modules>
10
+ </config>
app/locale/en_US/template/email/packpin/packpin_delivered_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
app/locale/en_US/template/email/packpin/packpin_exception_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
app/locale/en_US/template/email/packpin/packpin_failed_attempt_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
app/locale/en_US/template/email/packpin/packpin_in_transit_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
app/locale/en_US/template/email/packpin/packpin_info_received_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
app/locale/en_US/template/email/packpin/packpin_out_for_delivery_email.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--@subject Order shipment status has been updated. @-->
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <style>
7
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans:400,600,700&subset=latin,latin-ext);
8
+ </style>
9
+ </head>
10
+ <body style="background:#ebebeb;">
11
+ <div style="max-width:600px;margin-top:10px;margin-right:auto;margin-bottom:0;margin-left:auto;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background:#ffffff;font-family:'Open Sans',sans-serif;color:#333333;">
12
+ <div style="background:#ececed;">
13
+ <a style="display:block;text-decoration:none;text-align:center;padding-top:26px;padding-bottom:20px;padding-left:10px;padding-right:10px;" href="{{store url=""}}">
14
+ <img
15
+ {{if logo_width}}
16
+ width="{{var logo_width}}"
17
+ {{else}}
18
+ width="auto"
19
+ {{/if}}
20
+ {{if logo_height}}
21
+ height="{{var logo_height}}"
22
+ {{else}}
23
+ height="35"
24
+ {{/if}}
25
+ style="max-width:100%;" src="{{var logo_url}}" alt="{{var logo_alt}}" border="0"/>
26
+ </a>
27
+ <div style="font-size:18px;font-weight:700;text-align:center;padding-left:10px;padding-right:10px;">
28
+ YOUR PACKAGE STATUS HAS BEEN UPDATED!
29
+ </div>
30
+ {{var crossSell}}
31
+ <fieldset style="margin-top:20px;border-left-style:none;border-right-style:none;border-bottom-style:none;margin-left:10px;margin-right:10px;">
32
+ <legend style="font-size:14px;">YOUR PACKAGE INFORMATION</legend>
33
+ <table style="font-size:12px;margin-top:15px;line-height:20px;" border="0" cellspacing="0" cellpadding="0" width="100%;">
34
+ <tr>
35
+ <td valign="top" style="text-align:left;font-weight:600">
36
+ Order number:
37
+ </td>
38
+ <td valign="top" style="text-align:left;font-weight:400">
39
+ {{var track.getOrderNumber()}}
40
+ </td>
41
+ <td valign="top" style="text-align:left;font-weight:600">
42
+ Carrier:
43
+ </td>
44
+ <td valign="top" style="text-align:left;font-weight:400">
45
+ {{var track.getCarrierName()}}
46
+ </td>
47
+ </tr>
48
+ <tr>
49
+ <td valign="top" style="text-align:left;font-weight:600">
50
+ </td>
51
+ <td valign="top" style="text-align:left;font-weight:400">
52
+ </td>
53
+ <td valign="top" style="text-align:left;font-weight:600">
54
+ Tracking number:
55
+ </td>
56
+ <td valign="top" style="text-align:left;font-weight:400">
57
+ {{var track.getCode()}}
58
+ </td>
59
+ </tr>
60
+ <tr>
61
+ <td>&nbsp;</td>
62
+ </tr>
63
+ <tr>
64
+ <td valign="top" colspan="2" style="text-align:left;line-height:15px;">
65
+ If you have questions regarding shipment,
66
+ <br>
67
+ please contact carrier direcly.
68
+ </td>
69
+ <td valign="top" colspan="2">
70
+ <a style="white-space:nowrap;display:block;padding-top:2px;padding-bottom:2px;padding-left:7px;padding-right:7px;text-decoration:none;color:#ffffff;background-color:#484950;font-size:11px;text-align:center;" href="{{var track.getDetailsUrl()}}">
71
+ SEE FULL TRACKING INFO
72
+ </a>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </fieldset>
77
+ </div>
78
+ <div style="background:#c1c1c1;font-size:11px;line-height:15px;text-align:center;font-size:11px;padding-top:5px;padding-bottom:5px;">
79
+ This email was sent to {{var email}}
80
+ <br>
81
+ No longer wish to be notified about your shipment? <a style="text-decoration:underline;color:#333333;" href="{{var track.getUnsubscribeLink()}}">Unsubscribe</a>
82
+ </div>
83
+ </div>
84
+
85
+ </body>
86
+ </html>
package.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Packpin_Pptrack</name>
4
+ <version>1.0.2</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/gpl-license.php">GNU General Public License (GPL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Packpin shipment tracking extension</summary>
10
+ <description>With Packpin customers can track their goods on the same shop where they bought the product and they are getting email notifications every time a delivery status is changed. It is a completely new way online retailers provide delivery process for their customers.&#xD;
11
+ Packpin created shipment tracking and cross selling solution within email notifications and in-site shipment tracking. We boast an impressive 80.5% rate of opened tracking emails compared to the market average of 10.2%. Furthermore, 60.3% of customers will click through to the retailers website to see the shipment status. Customers will track their package up to 5 times. If this number is multiplied with the percentages from above, one will quickly understand the potential cross sales results Packpin can yield.&#xD;
12
+ &#xD;
13
+ - Support for ~60 carrier companies.&#xD;
14
+ - Automatically track all the shipments in one place.&#xD;
15
+ - We will auto-detect your carrier and display the results in a user friendly way.&#xD;
16
+ - Email notifications on shipment status change.&#xD;
17
+ - Cross sale possibility on shipment tracking page or notification email&#xD;
18
+ - Shipment tracking button on shipment notification email.&#xD;
19
+ - Tracking button in customer order.&#xD;
20
+ - Easy 10 minutes installation.</description>
21
+ <notes>Added detection for custom carriers (sometimes shipment list is updated through API and carrier codes match only partly)</notes>
22
+ <authors><author><name>Packpin Packpin</name><user>packpin</user><email>info@packpin.com</email></author></authors>
23
+ <date>2015-05-14</date>
24
+ <time>13:19:31</time>
25
+ <contents><target name="magecommunity"><dir name="Packpin"><dir name="Pptrack"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><dir name="Shipment"><dir name="Create"><file name="Tracking.php" hash="4a791af6ab6580a2485daf02b2df852e"/></dir><dir name="View"><file name="Tracking.php" hash="b8fb4c70f98fd1565685b1aaaf50989d"/></dir></dir></dir></dir><dir name="System"><dir name="Config"><dir name="Fieldset"><file name="Hint-owner.php" hash="3f3029efceb1d0e1c8f37f08aa21a371"/></dir><dir name="Form"><dir name="Fieldset"><file name="Carrier.php" hash="8dcd2c2fbfbd6eb5938f06e537c939e3"/></dir></dir></dir></dir></dir><file name="Crosssell.php" hash="1964eb986f699a500cd445cceed78c1c"/><file name="Index.php" hash="d2d92ae24bad53b4b6f360d04b58f35d"/><file name="Trackings.php" hash="3313a04f6ee29e1a93a940ba52d5af6b"/></dir><dir name="Helper"><file name="Data.php" hash="0c058e325ac9ab27fa7895b7a3bf69c5"/></dir><dir name="Model"><file name="Api.php" hash="457072243c2d681ed9d01470d705cea9"/><file name="Carrier.php" hash="bcff08d1c43bd3643a9f104a79fcdc42"/><file name="EnableNotifications.php" hash="e6417437f94e76370b3ea9d4493ffd01"/><file name="Observer.php" hash="ad5352f45180121691500d32bd1da85b"/><dir name="Order"><file name="Shipment.php" hash="97b3f6ad711842e3066300db6dc8a2c5"/></dir><dir name="Resource"><dir name="Carrier"><file name="Collection.php" hash="03005aa1067c8df71710d1224b9eb838"/></dir><file name="Carrier.php" hash="353d1d39c03e23dbbeacc181c1eb7ce9"/><dir name="Setting"><file name="Collection.php" hash="aa4e67bcd7016180fc6febf974533c93"/></dir><file name="Setting.php" hash="3eeee7198164abc0885e3c938b7d8bb4"/><dir name="Track"><file name="Collection.php" hash="cc6adf831c0248a202394e36d458b623"/></dir><file name="Track.php" hash="3f1d555d29f49ef8f6d2f6967d355ee8"/><dir name="Trackdetail"><file name="Collection.php" hash="941c6277814680ec85eb12c51ecf89d4"/></dir><file name="Trackdetail.php" hash="aedb43bb11215a694251e49ad9425eb6"/><dir name="Trackunsubscribed"><file name="Collection.php" hash="33f9820631af51c4e3aa62f34b5a7a3c"/></dir><file name="Trackunsubscribed.php" hash="038ffa7b345e528c808b03932baaf99c"/></dir><file name="Setting.php" hash="1f7b781d526211dcb29c78cb498033a2"/><file name="Track.php" hash="6d10a2d0f2b988198f937a78b072bc34"/><file name="Trackdetail.php" hash="3c73ff2978792c755758b35865b54467"/><file name="Trackunsubscribed.php" hash="47770b68d49a554c7e18250578ecddfc"/><file name="Translate.php" hash="dd80869c7e8dec6c0c3260db5cff3ccd"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="PpnotificationsController.php" hash="eb07f8257c9f13854e48c638bfe5e5c5"/></dir><file name="IndexController.php" hash="e8efcec6bf578d58bfe53bb6dadfb357"/><file name="UnsubscribeController.php" hash="635e1f44908436801b4e7b4c1222fcc5"/></dir><dir name="etc"><file name="adminhtml.xml" hash="b57c34e9a0ed06573f88bda77f12799d"/><file name="api.xml" hash="5986c3cfd16372143cf2d4d0d3252f38"/><file name="config.xml" hash="dc327ab14bb8cf663d7163b1200c17c7"/><file name="system.xml" hash="0fedaf802a5df88d780436e5020d1472"/></dir><dir name="sql"><dir name="pptrack_setup"><file name="mysql4-install-0.1.2.php" hash="41ddf13aef299e050bd4586c4473eb66"/><file name="mysql4-upgrade-0.1.2-0.1.5.php" hash="edfc436309165f115aeacf29df9d3398"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="pptrack.xml" hash="1c09bbc830e41dd6072f04bba5798d6f"/></dir><dir name="template"><dir name="pptrack"><file name="crosssell.phtml" hash="a9f57ccf4e28b7dd75a65d93a5de2ad9"/><file name="crosssell_email.phtml" hash="84a09283849c332a9a65c60f2a69c6e8"/><dir name="email"><dir name="order"><dir name="shipment"><file name="track.phtml" hash="86d49d54129bd81cb785a7a477d17359"/></dir></dir></dir><file name="index.phtml" hash="eae1dc520bd0609387035d68db86813f"/><file name="popup.phtml" hash="f8692aeedd28f2b13c92f626b2f6c6ad"/><file name="unsubscribe.phtml" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="pptrack.xml" hash="3925c9e5158320c220381d12fb3a2590"/></dir><dir name="template"><dir name="pptrack"><dir name="system"><dir name="config"><dir name="fieldset"><file name="hint-owner.phtml" hash="33cd6936463c08977363302ff372bbd4"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Packpin_Pptrack.xml" hash="28e229eb510938594fe9436e6a6b1488"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><file name="pptrack.css" hash="9f2f18629bdc2fb7e1fb589068f53698"/></dir><dir name="images"><dir name="pptrack"><file name="bulletIcon.png" hash="15f6fd65c7a62f940b7d17b9186a2b35"/><file name="checkedIcon.png" hash="cef38265bdd7675a0497a2296f5b7332"/><file name="postnlLogo.png" hash="3b4595ba4262c574c1147ed39e862092"/><file name="trackingStatus.png" hash="6dcf522f4e22b69bb25c3b3c199bb464"/><file name="truck.png" hash="3eb50f750a0fefa1903613e0bc26a2ee"/></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="pptrack"><dir name="css"><file name="pptrack.css" hash="70e0bb57247ff48334ec76f994b370ac"/></dir><dir name="images"><file name="pp_logo1.png" hash="1a79f10d0f028271ac0b2646243e39d1"/></dir></dir></dir></dir></dir></target><target name="magelocale"><dir name="en_US"><dir name="template"><dir name="email"><dir name="packpin"><file name="packpin_delivered_email.html" hash="c3e667a5d92022cfb7a4aedc7628cc53"/><file name="packpin_exception_email.html" hash="edd5a30297a5c00ff92883b0520501f7"/><file name="packpin_failed_attempt_email.html" hash="edd5a30297a5c00ff92883b0520501f7"/><file name="packpin_in_transit_email.html" hash="edd5a30297a5c00ff92883b0520501f7"/><file name="packpin_info_received_email.html" hash="edd5a30297a5c00ff92883b0520501f7"/><file name="packpin_out_for_delivery_email.html" hash="edd5a30297a5c00ff92883b0520501f7"/></dir></dir></dir></dir></target></contents>
26
+ <compatible/>
27
+ <dependencies><required><php><min>5.2.13</min><max>5.6.6</max></php></required></dependencies>
28
+ </package>
skin/adminhtml/default/default/pptrack/css/pptrack.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ul.tabs a.packpin-settings span,
2
+ ul.tabs a.packpin-settings:hover span {
3
+ background-image: url("../images/pp_logo1.png");
4
+ background-repeat: no-repeat;
5
+ background-position: 17px center;
6
+ line-height: 24px;
7
+ padding-left: 43px;
8
+ border-bottom: 1px dotted;
9
+ }
10
+ ul.tabs dd:last-child a.packpin-settings span,
11
+ ul.tabs dd:last-child a.packpin-settings:hover span {
12
+ border-bottom: none;
13
+ }
skin/adminhtml/default/default/pptrack/images/pp_logo1.png ADDED
Binary file
skin/frontend/base/default/css/pptrack.css ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .pptrack-index-index .main-container {
2
+ -webkit-font-smoothing: antialiased;
3
+ color: #676669;
4
+ }
5
+ .pptrack-wrapper {
6
+ -webkit-font-smoothing: antialiased;
7
+ color: #676669;
8
+ }
9
+ .pptrack-wrapper h3 {
10
+ color: #676669;
11
+ }
12
+
13
+ .pptrack-wrapper a {
14
+ color: #676669;
15
+ }
16
+
17
+ .pptrack-crossSellingItems {
18
+ padding-bottom: 50px;
19
+ }
20
+ .pptrack-progress {
21
+ height: 165px;
22
+ width: 100%;
23
+ background: #f5f5f5;
24
+ position: relative;
25
+ -webkit-border-radius: 2px;
26
+ -moz-border-radius: 2px;
27
+ border-radius: 2px;
28
+ }
29
+ ul.pptrack-progress-bar {
30
+ list-style: none;
31
+ margin: 65px 0 0;
32
+ padding: 0;
33
+ display: table;
34
+ width: 100%;
35
+ }
36
+ ul.pptrack-progress-bar li {
37
+ display: table-cell;
38
+ position: relative;
39
+ }
40
+ ul.pptrack-progress-bar li:before {
41
+ position: absolute;
42
+ content: "";
43
+ background: #dee2e7;
44
+ height: 5px;
45
+ width: 100%;
46
+ top: -2px;
47
+ }
48
+ ul.pptrack-progress-bar li:first-child:before {
49
+ width: 50%;
50
+ left: 50%;
51
+ }
52
+ ul.pptrack-progress-bar li:last-child:before {
53
+ width: 50%;
54
+ right: 50%;
55
+ }
56
+ .pptrack-tracking-progress-bar-label {
57
+ padding-top: 35px;
58
+ font-size: 22px;
59
+ font-weight: 300;
60
+ text-align: center;
61
+ }
62
+ .pptrack-progress-bubble {
63
+ margin: 0 auto;
64
+ top: -27px;
65
+ left: 0;
66
+ right: 0;
67
+ width: 50px;
68
+ height: 50px;
69
+ border-radius: 50%;
70
+ display: block;
71
+ position: absolute;
72
+ z-index:11;
73
+ background-color: #dee2e7;
74
+ }
75
+ ul.pptrack-progress-bar li.done .pptrack-progress-bubble {
76
+ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAAHuJ1aRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjFCNzRBMDdDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjFCNzRBMDhDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGMUI3NEEwNUM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGMUI3NEEwNkM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiRj1LEAAAEDSURBVHjaYvz//z8DFMxggTJAIowAAcQIk2GCijAABBADUOQOSBSKQYABIIAYkQwAgWaQzBmoipNAbABicEGV84AkAAKIAckMdLwWqtATxJGEch5CJe9D+VIwDciWMwPxeyAWBOK/yC4CCCB0F6LIAfEXJhyS7ED8DzkERJEkhYH4BxC/BGJukGMuQR2nAcRqUPYVmENh3tv+HwF2I3sd2ZF9UCsLkB0DEGD4Ag0XZgbiOUg2vgIJigGxDxBzEtAMiqo9SJrfA7EtzC/nkSSuA7EcmmZpIL6KpAYUc6rIamAMQSA+huxEII4H4hdIYieAWAibK9EF2IB4+X9UsBoqjtOrADVC1XccKndVAAAAAElFTkSuQmCC);
77
+ background-repeat: no-repeat;
78
+ background-position: center;
79
+ }
80
+ ul.pptrack-progress-bar li.active .pptrack-progress-bubble {
81
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAAEhcmxxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjFCNzRBMDNDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjFCNzRBMDRDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGMUI3NEEwMUM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGMUI3NEEwMkM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PstXMrQAAAC5SURBVHjaYvz//z8DEOQxABl5QPwfIIAYgfg4iPgPEEAgoeP/oQAggEAcNiD+DGJDpKGAiQEJAAQQSIYNSP9kQAUXQRIgQTY0CbB2diC+gCYuAxBADFBb86C2Hoe6gAEkeP4/JmBHcRYSOIFL4gsuiXyQHdJo5l8AqQUIMJirpHE4AgbOQ9WAXZv7n3iQizOkcICfoBA8x0A8OA9yEjvUQ4TARZBamKdhiSAfiE8D8RcoPg0VY4OpAwALNzuWsCcfvQAAAABJRU5ErkJggg==);
82
+ background-repeat: no-repeat;
83
+ background-position: center;
84
+ }
85
+ ul.pptrack-progress-bar li.done .pptrack-progress-bubble,
86
+ ul.pptrack-progress-bar li.active .pptrack-progress-bubble {
87
+ background-color: #e44539;
88
+ }
89
+
90
+ .pptrack-progress-bar-wrapper {
91
+ margin: 0 auto;
92
+ padding-top: 1px;
93
+ }
94
+
95
+ ul.pptrack-progress-bar li.done:after,
96
+ ul.pptrack-progress-bar li.active:after {
97
+ position: absolute;
98
+ content: "";
99
+ background: #e44539;
100
+ height: 5px;
101
+ width: 100%;
102
+ top: -2px;
103
+ z-index:10;
104
+ }
105
+ ul.pptrack-progress-bar li:first-child:after {
106
+ width: 50%;
107
+ left: 50%;
108
+ }
109
+ ul.pptrack-progress-bar li.active:after {
110
+ width: 50%;
111
+ right: 50%;
112
+ }
113
+ ul.pptrack-progress-bar li:first-child.active:after {
114
+ background: #DEE2E7;
115
+ }
116
+
117
+ ul.pptrack-progress-bar-done li:after,
118
+ ul.pptrack-progress-bar-done li:before{
119
+ background: #24AAA3 !important;
120
+ }
121
+ ul.pptrack-progress-bar-done li .pptrack-progress-bubble{
122
+ background: #24AAA3 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAALCAYAAAHuJ1aRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjFCNzRBMDdDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjFCNzRBMDhDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGMUI3NEEwNUM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGMUI3NEEwNkM5QTcxMUU0ODBGMEUzMjlGRkZDOTBDOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiRj1LEAAAEDSURBVHjaYvz//z8DFMxggTJAIowAAcQIk2GCijAABBADUOQOSBSKQYABIIAYkQwAgWaQzBmoipNAbABicEGV84AkAAKIAckMdLwWqtATxJGEch5CJe9D+VIwDciWMwPxeyAWBOK/yC4CCCB0F6LIAfEXJhyS7ED8DzkERJEkhYH4BxC/BGJukGMuQR2nAcRqUPYVmENh3tv+HwF2I3sd2ZF9UCsLkB0DEGD4Ag0XZgbiOUg2vgIJigGxDxBzEtAMiqo9SJrfA7EtzC/nkSSuA7EcmmZpIL6KpAYUc6rIamAMQSA+huxEII4H4hdIYieAWAibK9EF2IB4+X9UsBoqjtOrADVC1XccKndVAAAAAElFTkSuQmCC) no-repeat center !important;
123
+ }
124
+
125
+
126
+ .pptrack-tracking-info {
127
+ width: 100%;
128
+ }
129
+ .pptrack-tracking-info .pptrack-tracking-info-details {
130
+ border: 1px solid #e5e5e5;
131
+ -webkit-border-radius: 2px;
132
+ -moz-border-radius: 2px;
133
+ border-radius: 2px;
134
+ padding: 20px;
135
+ background: #ffffff;
136
+ }
137
+ .pptrack-tracking-general-info {
138
+ padding-top: 20px;
139
+ width: 100%
140
+ }
141
+ .pptrack-tracking-general-info .pptrack-tracking-general-info-details {
142
+ border: 1px solid #e5e5e5;
143
+ -webkit-border-radius: 2px;
144
+ -moz-border-radius: 2px;
145
+ border-radius: 2px;
146
+ padding: 18px;
147
+ background: #ffffff;
148
+ }
149
+ .pptrack-tracking-general-info-label {
150
+ width: 35%;
151
+ display: block;
152
+ float: left;
153
+ text-align: right;
154
+ font-weight: 600;
155
+ font-size: 14px;
156
+ }
157
+ .pptrack-tracking-general-info-value {
158
+ width: 60%;
159
+ display: block;
160
+ float: right;
161
+ text-align: left;
162
+ font-weight: 300;
163
+ font-size: 14px;
164
+ }
165
+ .pptrack-tracking-general-info .pptrack-tracking-row {
166
+ padding-bottom: 10px;
167
+ }
168
+
169
+ .pptrack-tracking-general-info .pptrack-tracking-carrier-info-wrapper {
170
+ background: #f5f5f5;
171
+ padding: 15px;
172
+ }
173
+ .pptrack-tracking-general-info .pptrack-tracking-carrier-info-wrapper span {
174
+ font-size: 10px;
175
+ font-weight: 300;
176
+ }
177
+ .pptrack-tracking-general-info .pptrack-tracking-courier-logo {
178
+ float: left;
179
+ padding-top: 10px;
180
+ }
181
+ .pptrack-tracking-general-info .pptrack-tracking-courier-info {
182
+ margin-left: 75px;
183
+ font-size: 14px;
184
+ font-weight: 300;
185
+ }
186
+ .pptrack-tracking-general-info .pptrack-tracking-courier-info span, .pptrack-tracking-general-info .pptrack-tracking-courier-info a {
187
+ font-size: 14px;
188
+ font-weight: 300;
189
+ }
190
+
191
+ .pptrack-info-row {
192
+ width: 100%;
193
+ border-bottom: 1px solid #f4f4f4;
194
+ position: relative;
195
+ font-weight: 300;
196
+ color: #676669;
197
+ }
198
+ .pptrack-info-row .pptrack-info-row-date {
199
+ float: left;
200
+ width: 85px;
201
+ text-align: right;
202
+ padding: 20px 0;
203
+ }
204
+ .pptrack-info-row .pptrack-info-row-details:before {
205
+ content: "";
206
+ position: absolute;
207
+ width: 68px;
208
+ top: 0;
209
+ left: 85px;
210
+ height: 101%;
211
+ background-color: #FFF;
212
+ background-image: url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzAxNCA3OS4xNTY3OTcsIDIwMTQvMDgvMjAtMDk6NTM6MDIgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkQ1NDA2NzgyQzlGQTExRTQ4MEYwRTMyOUZGRkM5MEM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkQ1NDA2NzgzQzlGQTExRTQ4MEYwRTMyOUZGRkM5MEM4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RjFCNzRBMDlDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RjFCNzRBMEFDOUE3MTFFNDgwRjBFMzI5RkZGQzkwQzgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCAABAAEDAREAAhEBAxEB/8QASgABAAAAAAAAAAAAAAAAAAAABwEBAAAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAAAAAAAAABEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AeAf/2Q==);
213
+ background-repeat: repeat-y;
214
+ background-position: center;
215
+ }
216
+ .pptrack-info-row:first-child .pptrack-info-row-details:before {
217
+ top: 50%;
218
+ height: 51%;
219
+ }
220
+ .pptrack-info-row:last-child .pptrack-info-row-details:before {
221
+ padding: 0;
222
+ height: 50%;
223
+ }
224
+
225
+ .pptrack-info-row .pptrack-info-row-details:after {
226
+ content: '';
227
+ position: absolute;
228
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTFBNzY3RjlDRTYyMTFFNDg1QTRENjhGQjYwRDQzNzUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTFBNzY3RkFDRTYyMTFFNDg1QTRENjhGQjYwRDQzNzUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUE3NjdGN0NFNjIxMUU0ODVBNEQ2OEZCNjBENDM3NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUE3NjdGOENFNjIxMUU0ODVBNEQ2OEZCNjBENDM3NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pq1Fb38AAAGWSURBVHjalFNBSwJREJ55ymrRQQ+hdRKSgi4d6pKnIOhWndpLlyBE8NgfyL+xl+iYXjrXJbrZD5CozCAkTAu1RGTVnb5d19BEyYFh3/u++ebNmzfL9NcyGYpaVS95aF5Z3YCQ+hamso9KZk5PDYXy4GY5Y/gskjTAfRq1WyFrL68nv0bE0bQRYZYXLFtEYoKCk4JbcK/rc8A3n/RE9le8lDZmFEsTyw8S8qPMWe4JHZNegg6iqywUYvaEHw/i77xuGFQPyhWCY252P40xJDERZx9SFtNcURBqAHbszCA1mmDc4zt2e0jTggr3jLicNVjqhAx+N1FMkXDYBTWawoR4FWJquDtzGjEqflMWq+d+2f88suV8upxV7XanjkbZ7+uVXjMm6BzeifMoVVCvh0kb3QUYgFfGJRCnofJpx6Fk/UGPi9Pd/H0pB+IUHVyA1+xhERGz77hhDWrgHAKXbjf8l0PjuXWTomJlcRsHXI97MhE6bnHzrKifjP4YzoxfGIqUrGF5BHqDWHIQneNp7gp6ojsY+yPAALTWnp+tBEoCAAAAAElFTkSuQmCC);
229
+ top: 40%;
230
+ width: 15px;
231
+ height: 15px;
232
+ left: 112px;
233
+ }
234
+ .pptrack-info-row:first-child .pptrack-info-row-details:after {
235
+ content: '';
236
+ position: absolute;
237
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDU0MDY3ODZDOUZBMTFFNDgwRjBFMzI5RkZGQzkwQzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDU0MDY3ODdDOUZBMTFFNDgwRjBFMzI5RkZGQzkwQzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENTQwNjc4NEM5RkExMUU0ODBGMEUzMjlGRkZDOTBDOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENTQwNjc4NUM5RkExMUU0ODBGMEUzMjlGRkZDOTBDOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsFC2UMAAAHrSURBVHjatJbfK0NhGMefs+awKSNapqWIXNgF+VmWH7WU8uNCSUr+C3dyJeXOnXLDBcrV1sqN8mOtJaT8vHEhFAnZIq1RfB+9q2HOe86cPfXpPes8z/e7d+153lepWp0jHWEHFaAcFINHcAUuwKus2KrxTgFeMANaNfJ2wDgIg490CZY/Ct3gCIQkBiTeh0S+W6+JD1wDDxkLj6jzyUz4W63T/2L95+5TTZxgm8yJbaH3y2QNqCaZqEJPSTVpBA1kbjQkNZMmU5SdmEqa8Na6s2TCuiqblGVSnWOx0HRjB41WSf/pZWziMmpgs1pp3ttD3e5KOn26l6W72KRAK2Oy3ksrXQPkUHO/PvO62N5LNY5iGt0K0sHjncykgE1iWhkL58fksuXTcmc/1RaV0BJWp81OI1sBOos+6Nl4jE1utTIuX2I0tBkgRVHI7xskK9bhjQBdPMf0/rq3CkZ9Dh4SssxCNY/Gqj20eH5C0UTcUGPyTt5AQJbJwrOn+0YN/KyfbMaJLPXJZGrHH4szwcwIizPm24AcAHGTDFinL90UjoImk0yahF7aQ+sENIP3DMW5rkXoaB6/e6AURAwaRETdrt6LBF952kAdCErEgyKvTdQZuhJxHIJ+HrpiWvMwLQJPYlLciD7TjE8BBgA1BWucPtPhQwAAAABJRU5ErkJggg==);
238
+ top: 40%;
239
+ width: 25px;
240
+ height: 25px;
241
+ left: 107px;
242
+ }
243
+
244
+
245
+ .pptrack-info-row:last-child {
246
+ border: 0;
247
+ }
248
+
249
+ .pptrack-info-row .pptrack-info-row-details-wrapper {
250
+ margin-left: 153px;
251
+ }
252
+ .pptrack-info-row .pptrack-info-row-details {
253
+ float: left;
254
+ width: 100%;
255
+ margin: 20px 0;
256
+ }
257
+
258
+ .pptrack-crosssell {
259
+ width: 100%;
260
+ margin-bottom: 30px;
261
+ overflow: auto;
262
+ }
263
+ .pptrack-list-info-box-wrap,
264
+ .pptrack-list-info-box {
265
+ display: block;
266
+ text-align: center;
267
+ }
268
+ .pptrack-product-name {
269
+ margin: 0;
270
+ }
271
+ ul.pptrack-products-grid {
272
+ width: 100%;
273
+ }
274
+ ul.pptrack-products-grid > li {
275
+ width: 48%;
276
+ float: left;
277
+ margin: 10px 1%;
278
+ text-align: center;
279
+ }
280
+ ul.pptrack-products-grid > li img {
281
+ max-width: 100%;
282
+ vertical-align: middle;
283
+ margin: 0 auto;
284
+ }
285
+
286
+ /* Small devices (tablets, 768px and up) */
287
+ @media (min-width: 768px) {
288
+ .pptrack-tracking-info {
289
+ width: 60% !important;
290
+ float: left;
291
+ }
292
+ .pptrack-tracking-general-info {
293
+ width: 38% !important;
294
+ float: right;
295
+ padding-top: 0;
296
+ }
297
+
298
+ ul.pptrack-products-grid > li {
299
+ width: 23% !important;
300
+ float: left;
301
+ margin: 10px 1%;
302
+ text-align: center;
303
+ }
304
+ }
305
+
306
+ /* Medium devices (desktops, 992px and up) */
307
+ @media (min-width: 992px) {
308
+
309
+ }
310
+
311
+ /* Large devices (large desktops, 1200px and up) */
312
+ @media (min-width: 1200px) {
313
+ ul.pptrack-products-grid--col-4 > li {
314
+ width: 23% !important;
315
+ float: left;
316
+ margin: 10px 1%;
317
+ text-align: center;
318
+ }
319
+ ul.pptrack-products-grid--col-5 > li {
320
+ width: 18% !important;
321
+ float: left;
322
+ margin: 10px 1%;
323
+ text-align: center;
324
+ }
325
+ ul.pptrack-products-grid--col-6 > li {
326
+ width: 14.6666666667% !important;
327
+ float: left;
328
+ margin: 10px 1%;
329
+ text-align: center;
330
+ }
331
+ ul.pptrack-products-grid--col-6 > li:nth-child(4) {
332
+ clear:none;
333
+ }
334
+ }
335
+
336
+ .clearfix:before,
337
+ .clearfix:after {
338
+ display: table;
339
+ content: " ";
340
+ }
341
+ .clearfix:after {
342
+ clear: both;
343
+ }
skin/frontend/base/default/images/pptrack/bulletIcon.png ADDED
Binary file
skin/frontend/base/default/images/pptrack/checkedIcon.png ADDED
Binary file
skin/frontend/base/default/images/pptrack/postnlLogo.png ADDED
Binary file
skin/frontend/base/default/images/pptrack/trackingStatus.png ADDED
Binary file
skin/frontend/base/default/images/pptrack/truck.png ADDED
Binary file