Tritac_ChannelEngine - Version 2.0.4

Version Notes

* Better support for multistore setups

Download this release

Release Info

Developer Christiaan de Ridder
Extension Tritac_ChannelEngine
Version 2.0.4
Comparing to
See all releases


Version 2.0.4

Files changed (49) hide show
  1. app/code/community/Tritac/ChannelEngine/Block/Adminhtml/System/Config/Feed.php +53 -0
  2. app/code/community/Tritac/ChannelEngine/Block/Head.php +11 -0
  3. app/code/community/Tritac/ChannelEngine/Block/Sales/Order/Grid.php +204 -0
  4. app/code/community/Tritac/ChannelEngine/Helper/Data.php +94 -0
  5. app/code/community/Tritac/ChannelEngine/Model/Carrier/Channelengine.php +56 -0
  6. app/code/community/Tritac/ChannelEngine/Model/Observer.php +673 -0
  7. app/code/community/Tritac/ChannelEngine/Model/Order.php +32 -0
  8. app/code/community/Tritac/ChannelEngine/Model/Payment/Method/Channelengine.php +22 -0
  9. app/code/community/Tritac/ChannelEngine/Model/Resource/Order.php +60 -0
  10. app/code/community/Tritac/ChannelEngine/Model/Resource/Order/Collection.php +7 -0
  11. app/code/community/Tritac/ChannelEngine/Model/Resource/Setup.php +4 -0
  12. app/code/community/Tritac/ChannelEngine/Model/System/Config/Source/Shipping.php +40 -0
  13. app/code/community/Tritac/ChannelEngine/controllers/Adminhtml/GenerateController.php +12 -0
  14. app/code/community/Tritac/ChannelEngine/controllers/TestController.php +372 -0
  15. app/code/community/Tritac/ChannelEngine/etc/adminhtml.xml +25 -0
  16. app/code/community/Tritac/ChannelEngine/etc/config.xml +170 -0
  17. app/code/community/Tritac/ChannelEngine/etc/system.xml +133 -0
  18. app/code/community/Tritac/ChannelEngine/sql/channelengine_setup/mysql4-install-0.1.0.0.php +67 -0
  19. app/code/community/Tritac/ChannelEngine/sql/channelengine_setup/mysql4-install-1.0.0.php +56 -0
  20. app/etc/modules/Tritac_ChannelEngine.xml +9 -0
  21. lib/Tritac/ChannelEngineApiClient/AddTrustExternalCARoot.crt +25 -0
  22. lib/Tritac/ChannelEngineApiClient/Client.php +262 -0
  23. lib/Tritac/ChannelEngineApiClient/Enums/CancellationLineStatus.php +8 -0
  24. lib/Tritac/ChannelEngineApiClient/Enums/CancellationStatus.php +9 -0
  25. lib/Tritac/ChannelEngineApiClient/Enums/Gender.php +8 -0
  26. lib/Tritac/ChannelEngineApiClient/Enums/MancoReason.php +8 -0
  27. lib/Tritac/ChannelEngineApiClient/Enums/OrderStatus.php +13 -0
  28. lib/Tritac/ChannelEngineApiClient/Enums/ReturnAcceptStatus.php +6 -0
  29. lib/Tritac/ChannelEngineApiClient/Enums/ReturnReason.php +10 -0
  30. lib/Tritac/ChannelEngineApiClient/Enums/ReturnStatus.php +6 -0
  31. lib/Tritac/ChannelEngineApiClient/Enums/ShipmentLineStatus.php +8 -0
  32. lib/Tritac/ChannelEngineApiClient/Enums/ShipmentStatus.php +5 -0
  33. lib/Tritac/ChannelEngineApiClient/Helpers/Collection.php +49 -0
  34. lib/Tritac/ChannelEngineApiClient/Helpers/HttpMethod.php +9 -0
  35. lib/Tritac/ChannelEngineApiClient/Helpers/JsonMapper.php +91 -0
  36. lib/Tritac/ChannelEngineApiClient/Models/Address.php +97 -0
  37. lib/Tritac/ChannelEngineApiClient/Models/BaseModel.php +23 -0
  38. lib/Tritac/ChannelEngineApiClient/Models/Cancellation.php +39 -0
  39. lib/Tritac/ChannelEngineApiClient/Models/CancellationLine.php +33 -0
  40. lib/Tritac/ChannelEngineApiClient/Models/Message.php +12 -0
  41. lib/Tritac/ChannelEngineApiClient/Models/Order.php +154 -0
  42. lib/Tritac/ChannelEngineApiClient/Models/OrderExtraDataItem.php +19 -0
  43. lib/Tritac/ChannelEngineApiClient/Models/OrderLine.php +146 -0
  44. lib/Tritac/ChannelEngineApiClient/Models/ReturnLine.php +46 -0
  45. lib/Tritac/ChannelEngineApiClient/Models/ReturnObject.php +64 -0
  46. lib/Tritac/ChannelEngineApiClient/Models/Shipment.php +73 -0
  47. lib/Tritac/ChannelEngineApiClient/Models/ShipmentLine.php +48 -0
  48. lib/Tritac/ChannelEngineApiClient/loader.php +14 -0
  49. package.xml +18 -0
app/code/community/Tritac/ChannelEngine/Block/Adminhtml/System/Config/Feed.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adminhtml system "generate feed" button
4
+ *
5
+ * @category Tritac
6
+ * @package Tritac_ChannelEngine
7
+ */
8
+ class Tritac_ChannelEngine_Block_Adminhtml_System_Config_Feed extends Mage_Adminhtml_Block_System_Config_Form_Field
9
+ {
10
+ /**
11
+ * Set template block template
12
+ *
13
+ * @return Tritac_ChannelEngine_Block_Adminhtml_System_Config_Feed
14
+ */
15
+ protected function _prepareLayout()
16
+ {
17
+ parent::_prepareLayout();
18
+ if (!$this->getTemplate()) {
19
+ $this->setTemplate('channelengine/system/config/feed/generate_button.phtml');
20
+ }
21
+ return $this;
22
+ }
23
+
24
+ /**
25
+ * Disable website scope
26
+ *
27
+ * @param Varien_Data_Form_Element_Abstract $element
28
+ * @return string
29
+ */
30
+ public function render(Varien_Data_Form_Element_Abstract $element)
31
+ {
32
+ $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
33
+ return parent::render($element);
34
+ }
35
+
36
+ /**
37
+ * Get the button and scripts contents
38
+ *
39
+ * @param Varien_Data_Form_Element_Abstract $element
40
+ * @return string
41
+ */
42
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
43
+ {
44
+ $originalData = $element->getOriginalData();
45
+ $this->addData(array(
46
+ 'button_label' => Mage::helper('channelengine')->__($originalData['button_label']),
47
+ 'html_id' => $element->getHtmlId(),
48
+ 'ajax_url' => Mage::getSingleton('adminhtml/url')->getUrl('channelengine/adminhtml_generate/ajax')
49
+ ));
50
+
51
+ return $this->_toHtml();
52
+ }
53
+ }
app/code/community/Tritac/ChannelEngine/Block/Head.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Block_Head extends Mage_Core_Block_Template
3
+ {
4
+ public function getAccountName() {
5
+
6
+ $storeId = Mage::app()->getStore()->getId();
7
+ $config = Mage::helper('channelengine')->getGeneralConfig();
8
+
9
+ return $config[$storeId]['tenant'];
10
+ }
11
+ }
app/code/community/Tritac/ChannelEngine/Block/Sales/Order/Grid.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Block_Sales_Order_Grid extends Mage_Adminhtml_Block_Widget_Grid {
3
+
4
+ public function __construct()
5
+ {
6
+ parent::__construct();
7
+ $this->setId('sales_order_grid');
8
+ $this->setUseAjax(true);
9
+ $this->setDefaultSort('created_at');
10
+ $this->setDefaultDir('DESC');
11
+ $this->setSaveParametersInSession(true);
12
+ }
13
+
14
+ /**
15
+ * Retrieve collection class
16
+ *
17
+ * @return string
18
+ */
19
+ protected function _getCollectionClass()
20
+ {
21
+ return 'sales/order_grid_collection';
22
+ }
23
+
24
+ protected function _prepareCollection()
25
+ {
26
+ $collection = Mage::getResourceModel($this->_getCollectionClass());
27
+ $joinTableName = Mage::getSingleton('core/resource')->getTableName('channelengine/order');
28
+ $collection->getSelect()->joinLeft(
29
+ array('channel_order_table' => $joinTableName),
30
+ 'channel_order_table.order_id=main_table.entity_id',
31
+ array('channel_name', 'channel_order_id')
32
+ );
33
+ $this->setCollection($collection);
34
+ return parent::_prepareCollection();
35
+ }
36
+
37
+ protected function _prepareColumns()
38
+ {
39
+ $this->addColumn('real_order_id', array(
40
+ 'header'=> Mage::helper('sales')->__('Order #'),
41
+ 'width' => '80px',
42
+ 'type' => 'text',
43
+ 'index' => 'increment_id',
44
+ ));
45
+
46
+ $this->addColumn('channel_order_id', array(
47
+ 'header'=> Mage::helper('sales')->__('ChannelEngine Order ID'),
48
+ 'width' => '80px',
49
+ 'type' => 'text',
50
+ 'index' => 'channel_order_id',
51
+ ));
52
+
53
+ $this->addColumn('channel_name', array(
54
+ 'header'=> Mage::helper('sales')->__('Channel Name'),
55
+ 'width' => '80px',
56
+ 'type' => 'text',
57
+ 'index' => 'channel_name',
58
+ ));
59
+
60
+ if (!Mage::app()->isSingleStoreMode()) {
61
+ $this->addColumn('store_id', array(
62
+ 'header' => Mage::helper('sales')->__('Purchased From (Store)'),
63
+ 'index' => 'store_id',
64
+ 'type' => 'store',
65
+ 'store_view'=> true,
66
+ 'display_deleted' => true,
67
+ ));
68
+ }
69
+
70
+ $this->addColumn('created_at', array(
71
+ 'header' => Mage::helper('sales')->__('Purchased On'),
72
+ 'index' => 'created_at',
73
+ 'type' => 'datetime',
74
+ 'width' => '100px',
75
+ ));
76
+
77
+ $this->addColumn('billing_name', array(
78
+ 'header' => Mage::helper('sales')->__('Bill to Name'),
79
+ 'index' => 'billing_name',
80
+ ));
81
+
82
+ $this->addColumn('shipping_name', array(
83
+ 'header' => Mage::helper('sales')->__('Ship to Name'),
84
+ 'index' => 'shipping_name',
85
+ ));
86
+
87
+ $this->addColumn('base_grand_total', array(
88
+ 'header' => Mage::helper('sales')->__('G.T. (Base)'),
89
+ 'index' => 'base_grand_total',
90
+ 'type' => 'currency',
91
+ 'currency' => 'base_currency_code',
92
+ ));
93
+
94
+ $this->addColumn('grand_total', array(
95
+ 'header' => Mage::helper('sales')->__('G.T. (Purchased)'),
96
+ 'index' => 'grand_total',
97
+ 'type' => 'currency',
98
+ 'currency' => 'order_currency_code',
99
+ ));
100
+
101
+ $this->addColumn('status', array(
102
+ 'header' => Mage::helper('sales')->__('Status'),
103
+ 'index' => 'status',
104
+ 'type' => 'options',
105
+ 'width' => '70px',
106
+ 'options' => Mage::getSingleton('sales/order_config')->getStatuses(),
107
+ ));
108
+
109
+ if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
110
+ $this->addColumn('action',
111
+ array(
112
+ 'header' => Mage::helper('sales')->__('Action'),
113
+ 'width' => '50px',
114
+ 'type' => 'action',
115
+ 'getter' => 'getId',
116
+ 'actions' => array(
117
+ array(
118
+ 'caption' => Mage::helper('sales')->__('View'),
119
+ 'url' => array('base'=>'*/sales_order/view'),
120
+ 'field' => 'order_id'
121
+ )
122
+ ),
123
+ 'filter' => false,
124
+ 'sortable' => false,
125
+ 'index' => 'stores',
126
+ 'is_system' => true,
127
+ ));
128
+ }
129
+ $this->addRssList('rss/order/new', Mage::helper('sales')->__('New Order RSS'));
130
+
131
+ $this->addExportType('*/*/exportCsv', Mage::helper('sales')->__('CSV'));
132
+ $this->addExportType('*/*/exportExcel', Mage::helper('sales')->__('Excel XML'));
133
+
134
+ return parent::_prepareColumns();
135
+ }
136
+
137
+ protected function _prepareMassaction()
138
+ {
139
+ $this->setMassactionIdField('entity_id');
140
+ $this->getMassactionBlock()->setFormFieldName('order_ids');
141
+ $this->getMassactionBlock()->setUseSelectAll(false);
142
+
143
+ if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/cancel')) {
144
+ $this->getMassactionBlock()->addItem('cancel_order', array(
145
+ 'label'=> Mage::helper('sales')->__('Cancel'),
146
+ 'url' => $this->getUrl('*/sales_order/massCancel'),
147
+ ));
148
+ }
149
+
150
+ if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/hold')) {
151
+ $this->getMassactionBlock()->addItem('hold_order', array(
152
+ 'label'=> Mage::helper('sales')->__('Hold'),
153
+ 'url' => $this->getUrl('*/sales_order/massHold'),
154
+ ));
155
+ }
156
+
157
+ if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/unhold')) {
158
+ $this->getMassactionBlock()->addItem('unhold_order', array(
159
+ 'label'=> Mage::helper('sales')->__('Unhold'),
160
+ 'url' => $this->getUrl('*/sales_order/massUnhold'),
161
+ ));
162
+ }
163
+
164
+ $this->getMassactionBlock()->addItem('pdfinvoices_order', array(
165
+ 'label'=> Mage::helper('sales')->__('Print Invoices'),
166
+ 'url' => $this->getUrl('*/sales_order/pdfinvoices'),
167
+ ));
168
+
169
+ $this->getMassactionBlock()->addItem('pdfshipments_order', array(
170
+ 'label'=> Mage::helper('sales')->__('Print Packingslips'),
171
+ 'url' => $this->getUrl('*/sales_order/pdfshipments'),
172
+ ));
173
+
174
+ $this->getMassactionBlock()->addItem('pdfcreditmemos_order', array(
175
+ 'label'=> Mage::helper('sales')->__('Print Credit Memos'),
176
+ 'url' => $this->getUrl('*/sales_order/pdfcreditmemos'),
177
+ ));
178
+
179
+ $this->getMassactionBlock()->addItem('pdfdocs_order', array(
180
+ 'label'=> Mage::helper('sales')->__('Print All'),
181
+ 'url' => $this->getUrl('*/sales_order/pdfdocs'),
182
+ ));
183
+
184
+ $this->getMassactionBlock()->addItem('print_shipping_label', array(
185
+ 'label'=> Mage::helper('sales')->__('Print Shipping Labels'),
186
+ 'url' => $this->getUrl('*/sales_order_shipment/massPrintShippingLabel'),
187
+ ));
188
+
189
+ return $this;
190
+ }
191
+
192
+ public function getRowUrl($row)
193
+ {
194
+ if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
195
+ return $this->getUrl('*/sales_order/view', array('order_id' => $row->getId()));
196
+ }
197
+ return false;
198
+ }
199
+
200
+ public function getGridUrl()
201
+ {
202
+ return $this->getUrl('*/*/grid', array('_current'=>true));
203
+ }
204
+ }
app/code/community/Tritac/ChannelEngine/Helper/Data.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Helper_Data extends Mage_Core_Helper_Abstract {
3
+
4
+ protected $_config = null;
5
+
6
+ /**
7
+ * Default expected shipment time (in weekdays)
8
+ *
9
+ * @var int
10
+ */
11
+ protected $_defaultTimeToShip = 5;
12
+
13
+ /**
14
+ * Get extension general config
15
+ *
16
+ * @param null $storeId
17
+ * @return array
18
+ */
19
+ public function getConfig($storeId = null)
20
+ {
21
+ if(empty($this->_config)) {
22
+ foreach(Mage::app()->getStores() as $_store) {
23
+ $this->_config[$_store->getId()] = Mage::getStoreConfig('channelengine', $_store->getId());
24
+ }
25
+ }
26
+
27
+ if($storeId) {
28
+ if(!isset($this->_config[$storeId])) {
29
+ return false;
30
+ }else{
31
+ return $this->_config[$storeId];
32
+ }
33
+ }
34
+
35
+ return $this->_config;
36
+ }
37
+
38
+ /**
39
+ * Get extension general config
40
+ *
41
+ * @return array
42
+ */
43
+ public function getGeneralConfig()
44
+ {
45
+ $result = array();
46
+
47
+ foreach($this->getConfig() as $storeId => $storeConfig) {
48
+ $result[$storeId] = $storeConfig['general'];
49
+ }
50
+
51
+ return $result;
52
+ }
53
+
54
+ /**
55
+ * Check required general config data
56
+ *
57
+ * @param null $storeId
58
+ * @return bool
59
+ */
60
+ public function checkGeneralConfig($storeId = null)
61
+ {
62
+ $config = Mage::getStoreConfig('channelengine/general', $storeId);
63
+
64
+ if(empty($config['api_key']) || empty($config['api_secret']) || empty($config['tenant'])) {
65
+ $storeMsg = ($storeId) ? 'for store '.$storeId : '';
66
+ Mage::log(
67
+ "Couldn't connect to ChannelEngine.
68
+ Please specify account keys {$storeMsg}
69
+ (System/Configuration/Tritac ChannelEngine/Settings/General)"
70
+ );
71
+ return false;
72
+ }
73
+
74
+ return true;
75
+ }
76
+
77
+ /**
78
+ * Get store expected shipment text
79
+ *
80
+ * @param $store_id
81
+ * @return DateTime
82
+ */
83
+ public function getExpectedShipmentDate($store_id)
84
+ {
85
+ $config = $this->getConfig($store_id);
86
+
87
+ $weekdays = (int) $config['shipping']['expected_date'];
88
+ if($weekdays <= 0)
89
+ $weekdays = $this->_defaultTimeToShip;
90
+
91
+ $expectedDate = date("Y-m-d", strtotime("{$weekdays} weekdays"));
92
+ return new DateTime($expectedDate);
93
+ }
94
+ }
app/code/community/Tritac/ChannelEngine/Model/Carrier/Channelengine.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Model_Carrier_Channelengine
3
+ extends Mage_Shipping_Model_Carrier_Abstract
4
+ implements Mage_Shipping_Model_Carrier_Interface
5
+ {
6
+
7
+ /** @var string Shipping method system code*/
8
+ protected $_code = 'channelengine';
9
+
10
+ protected $_isFixed = true;
11
+
12
+ /**
13
+ * Collect and get shipping rates
14
+ *
15
+ * @param Mage_Shipping_Model_Rate_Request $request
16
+ * @return bool|false|Mage_Core_Model_Abstract|Mage_Shipping_Model_Rate_Result|null
17
+ */
18
+ public function collectRates(Mage_Shipping_Model_Rate_Request $request)
19
+ {
20
+ if (!$this->getConfigFlag('active')) {
21
+ return false;
22
+ }
23
+
24
+ $result = Mage::getModel('shipping/rate_result');
25
+
26
+ $shippingPrice = false;
27
+
28
+ if(Mage::registry('channelengine_shipping_amount')) {
29
+ $shippingPrice = Mage::registry('channelengine_shipping_amount');
30
+ Mage::unregister('channelengine_shipping_amount');
31
+ }
32
+
33
+ if ($shippingPrice !== false) {
34
+ $method = Mage::getModel('shipping/rate_result_method');
35
+
36
+ $method->setCarrier($this->_code);
37
+ $method->setCarrierTitle($this->getConfigData('title'));
38
+
39
+ $method->setMethod($this->_code);
40
+ $method->setMethodTitle($this->getConfigData('name'));
41
+
42
+ $method->setPrice($shippingPrice);
43
+ $method->setCost($shippingPrice);
44
+
45
+ $result->append($method);
46
+ }
47
+
48
+ return $result;
49
+ }
50
+
51
+ public function getAllowedMethods()
52
+ {
53
+ return array('channelengine'=>'ChannelEngine');
54
+ }
55
+
56
+ }
app/code/community/Tritac/ChannelEngine/Model/Observer.php ADDED
@@ -0,0 +1,673 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Observer model
4
+ */
5
+ class Tritac_ChannelEngine_Model_Observer
6
+ {
7
+
8
+ /**
9
+ * API client
10
+ *
11
+ * @var Tritac_ChannelEngineApiClient_Client
12
+ */
13
+ protected $_client = null;
14
+
15
+ /**
16
+ * API config. API key, API secret, API tenant
17
+ *
18
+ * @var array
19
+ */
20
+ protected $_config = null;
21
+
22
+ /**
23
+ * ChannelEngine helper
24
+ *
25
+ * @var Tritac_ChannelEngine_Helper_Data
26
+ */
27
+ protected $_helper = null;
28
+
29
+ /**
30
+ * Retrieve and validate API config
31
+ * Initialize API client
32
+ */
33
+ public function __construct()
34
+ {
35
+ $this->_helper = Mage::helper('channelengine');
36
+ $this->_config = $this->_helper->getConfig();
37
+ /**
38
+ * Check required config parameters. Initialize API client.
39
+ */
40
+ foreach($this->_config as $storeId => $storeConfig) {
41
+ if($this->_helper->checkGeneralConfig($storeId)) {
42
+ $this->_client[$storeId] = new Tritac_ChannelEngineApiClient_Client(
43
+ $storeConfig['general']['api_key'],
44
+ $storeConfig['general']['api_secret'],
45
+ $storeConfig['general']['tenant']
46
+ );
47
+ }
48
+ }
49
+ }
50
+
51
+ public function getClients() {
52
+ var_export($this->_client);
53
+ die();
54
+ }
55
+
56
+ /**
57
+ * Fetch new orders from ChannelEngine.
58
+ * Uses for cronjob. Cronjob is set in extension config file.
59
+ *
60
+ * @return bool
61
+ */
62
+ public function fetchNewOrders()
63
+ {
64
+ /**
65
+ * Check if client is initialized
66
+ */
67
+ if(is_null($this->_client))
68
+ return false;
69
+
70
+ foreach($this->_client as $storeId => $_client) {
71
+ /**
72
+ * Retrieve new orders
73
+ */
74
+ $orders = $_client->getOrders(array(
75
+ Tritac_ChannelEngineApiClient_Enums_OrderStatus::NEW_ORDER
76
+ ));
77
+
78
+ /**
79
+ * Check new orders existing
80
+ */
81
+ if(is_null($orders) || $orders->count() == 0)
82
+ continue;
83
+
84
+ foreach($orders as $order) {
85
+
86
+ $billingAddress = $order->getBillingAddress();
87
+ $shippingAddress = $order->getShippingAddress();
88
+ if(empty($billingAddress)) continue;
89
+
90
+ $lines = $order->getLines();
91
+
92
+ if(!empty($lines)) {
93
+
94
+ // Initialize new quote
95
+ $quote = Mage::getModel('sales/quote')->setStoreId($storeId);
96
+
97
+ foreach($lines as $item) {
98
+
99
+ $productNo = $item->getMerchantProductNo();
100
+ $ids = explode('_', $productNo);
101
+ $productId = $ids[0];
102
+ // Load magento product
103
+ $_product = Mage::getModel('catalog/product')
104
+ ->setStoreId($storeId);
105
+ $productOptions = array();
106
+ $_product->load($productId);
107
+ if(count($ids) == 3) {
108
+ $productOptions = array($ids[1] => intval($ids[2]));
109
+ }
110
+
111
+ // Prepare product parameters for quote
112
+ $params = new Varien_Object();
113
+ $params->setQty($item->getQuantity());
114
+ $params->setOptions($productOptions);
115
+
116
+ // Add product to quote
117
+ try {
118
+ $_quoteItem = $quote->addProduct($_product, $params);
119
+ $_quoteItem->setChannelengineOrderLineId($item->getId());
120
+
121
+ } catch (Exception $e) {
122
+
123
+ Mage::getModel('adminnotification/inbox')->addCritical(
124
+ "An order (#{$order->getId()}) could not be imported",
125
+ "Reason: {$e->getMessage()} Please contact ChannelEngine support at <a href='mailto:support@channelengine.com'>support@channelengine.com</a> or +31(0)71-5288792"
126
+ );
127
+ Mage::logException($e);
128
+ continue 2;
129
+ }
130
+ }
131
+ }
132
+
133
+ $phone = $order->getPhone();
134
+ if(empty($phone))
135
+ $phone = '-';
136
+ // Prepare billing and shipping addresses
137
+ $billingData = array(
138
+ 'firstname' => $billingAddress->getFirstName(),
139
+ 'lastname' => $billingAddress->getLastName(),
140
+ 'email' => $order->getEmail(),
141
+ 'telephone' => $phone,
142
+ 'country_id' => $billingAddress->getCountryIso(),
143
+ 'postcode' => $billingAddress->getZipCode(),
144
+ 'city' => $billingAddress->getCity(),
145
+ 'street' =>
146
+ $billingAddress->getStreetName().' '.
147
+ $billingAddress->getHouseNr().
148
+ $billingAddress->getHouseNrAddition()
149
+ );
150
+ $shippingData = array(
151
+ 'firstname' => $shippingAddress->getFirstName(),
152
+ 'lastname' => $shippingAddress->getLastName(),
153
+ 'email' => $order->getEmail(),
154
+ 'telephone' => $phone,
155
+ 'country_id' => $shippingAddress->getCountryIso(),
156
+ 'postcode' => $shippingAddress->getZipCode(),
157
+ 'city' => $shippingAddress->getCity(),
158
+ 'street' =>
159
+ $shippingAddress->getStreetName().' '.
160
+ $shippingAddress->getHouseNr().
161
+ $shippingAddress->getHouseNrAddition()
162
+ );
163
+
164
+ // Register shipping cost. See Tritac_ChannelEngine_Model_Carrier_Channelengine::collectrates();
165
+ if($order->getShippingCostsInclVat() && floatval($order->getShippingCostsInclVat()) > 0) {
166
+ Mage::register('channelengine_shipping_amount', floatval($order->getShippingCostsInclVat()));
167
+ }
168
+
169
+ $quote->getBillingAddress()
170
+ ->addData($billingData);
171
+ $quote->getShippingAddress()
172
+ ->addData($shippingData)
173
+ ->setSaveInAddressBook(0)
174
+ ->setCollectShippingRates(true)
175
+ ->setShippingMethod('channelengine_channelengine');
176
+
177
+ $quote->collectTotals();
178
+
179
+ // Set guest customer
180
+ $quote->setCustomerId(null)
181
+ ->setCustomerEmail($quote->getBillingAddress()->getEmail())
182
+ ->setCustomerIsGuest(true)
183
+ ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
184
+
185
+ // Set custom payment method
186
+ $quote->setIsSystem(true);
187
+ $quote->getPayment()->importData(array('method' => 'channelengine'));
188
+
189
+ // Save quote and convert it to new order
190
+ try {
191
+
192
+ $quote->save();
193
+
194
+ $service = Mage::getModel('sales/service_quote', $quote);
195
+
196
+ $service->submitAll();
197
+
198
+ } catch (Exception $e) {
199
+ Mage::getModel('adminnotification/inbox')->addCritical(
200
+ "An order (#{$order->getId()}) could not be imported",
201
+ "Reason: {$e->getMessage()} Please contact ChannelEngine support at <a href='mailto:support@channelengine.com'>support@channelengine.com</a> or +31(0)71-5288792"
202
+ );
203
+ Mage::logException($e);
204
+ continue;
205
+ }
206
+
207
+ $_order = $service->getOrder();
208
+
209
+
210
+ if($_order->getIncrementId()) {
211
+
212
+ /**
213
+ * Create new invoice and save channel order
214
+ */
215
+ try {
216
+ // Initialize new invoice model
217
+ $invoice = Mage::getModel('sales/service_order', $_order)->prepareInvoice();
218
+ // Add comment to invoice
219
+ $invoice->addComment(
220
+ "Order paid on the marketplace.",
221
+ false,
222
+ true
223
+ );
224
+
225
+ // Register invoice. Register invoice items. Collect invoice totals.
226
+ $invoice->register();
227
+ $invoice->getOrder()->setIsInProcess(true);
228
+
229
+ // Initialize new channel order
230
+ $_channelOrder = Mage::getModel('channelengine/order');
231
+ $_channelOrder->setOrderId($_order->getId())
232
+ ->setChannelOrderId($order->getId())
233
+ ->setChannelName($order->getChannelName())
234
+ ->setDoSendMails($order->getDoSendMails())
235
+ ->setCanShipPartial($order->getCanShipPartialOrderLines());
236
+
237
+ $invoice->getOrder()
238
+ ->setCanShipPartiallyItem($order->getCanShipPartialOrderLines())
239
+ ->setCanShipPartially($order->getCanShipPartialOrderLines());
240
+
241
+ // Start new transaction
242
+ $transactionSave = Mage::getModel('core/resource_transaction')
243
+ ->addObject($invoice)
244
+ ->addObject($invoice->getOrder())
245
+ ->addObject($_channelOrder);
246
+ $transactionSave->save();
247
+
248
+ } catch (Exception $e) {
249
+ Mage::getModel('adminnotification/inbox')->addCritical(
250
+ "An invoice could not be created (order #{$_order->getIncrementId()}, channel order #{$order->getId()})",
251
+ "Reason: {$e->getMessage()} Please contact ChannelEngine support at <a href='mailto:support@channelengine.com'>support@channelengine.com</a> or +31(0)71-5288792"
252
+ );
253
+ Mage::logException($e);
254
+ continue;
255
+ }
256
+ Mage::log("Order #{$_order->getIncrementId()} was imported successfully.");
257
+ } else {
258
+ Mage::log("An order (#{$order->getId()}) could not be imported");
259
+ }
260
+ }
261
+ }
262
+
263
+ return true;
264
+ }
265
+
266
+ /**
267
+ * Post new shipment to ChannelEngine. This function is set in extension config file.
268
+ *
269
+ * @param Varien_Event_Observer $observer
270
+ * @return bool
271
+ * @throws Exception
272
+ */
273
+ public function saveShipment(Varien_Event_Observer $observer)
274
+ {
275
+ $event = $observer->getEvent();
276
+ /** @var $_shipment Mage_Sales_Model_Order_Shipment */
277
+ $_shipment = $event->getShipment();
278
+ /** @var $_order Mage_Sales_Model_Order */
279
+ $_order = $_shipment->getOrder();
280
+ $storeId = $_order->getStoreId();
281
+ $channelOrder = Mage::getModel('channelengine/order')->loadByOrderId($_order->getId());
282
+ $channelOrderId = $channelOrder->getChannelOrderId();
283
+
284
+ /**
285
+ * Check ChannelEngine order
286
+ */
287
+ if(!$channelOrderId)
288
+ return false;
289
+
290
+ /**
291
+ * Check if client is initialized
292
+ */
293
+ if(!isset($this->_client[$storeId]))
294
+ return false;
295
+
296
+ /**
297
+ * Throw new exception if user not added tracking information
298
+ */
299
+ if(!$_shipment->getAllTracks()) {
300
+ Mage::getSingleton('adminhtml/session')->addError(
301
+ $this->_helper->__("Tracking information can not be empty")
302
+ );
303
+ throw new Exception(
304
+ $this->_helper->__("Cannot save shipment without tracking information.")
305
+ );
306
+ }
307
+
308
+ foreach($_shipment->getAllTracks() as $_track) {
309
+ // Initialize new ChannelEngine shipment object
310
+ $shipment = new Tritac_ChannelEngineApiClient_Models_Shipment();
311
+ $shipment->setOrderId($channelOrderId);
312
+ $shipment->setMerchantShipmentNo($_shipment->getId());
313
+ $shipment->setTrackTraceNo($_track->getNumber());
314
+ $shipment->setMethod($_track->getTitle());
315
+
316
+ // Initialize new ChannelEngine collection of shipments
317
+ $linesCollection = new Tritac_ChannelEngineApiClient_Helpers_Collection('Tritac_ChannelEngineApiClient_Models_ShipmentLine');
318
+
319
+ foreach($_order->getAllItems() as $_orderItem) {
320
+
321
+ // Load saved order item from db, because current items changed but still not saved
322
+ $_orderItemOrigin = Mage::getModel('sales/order_item')->load($_orderItem->getId());
323
+
324
+ // Get shipment item that contains required qty to ship.
325
+ $_shipmentItem = null;
326
+ foreach ($_shipment->getItemsCollection() as $item) {
327
+ if ($item->getOrderItemId()==$_orderItem->getId()) {
328
+ $_shipmentItem = $item;
329
+ break;
330
+ }
331
+ }
332
+
333
+ if(is_null($_shipmentItem)) {
334
+ continue;
335
+ }
336
+
337
+ $qtyToShip = (int) $_shipmentItem->getQty();
338
+ $orderedQty = (int) $_orderItem->getQtyOrdered();
339
+ $shippedQty = (int) $_orderItemOrigin->getQtyShipped();
340
+
341
+ // Skip item if all qty already shipped
342
+ if($orderedQty == $shippedQty)
343
+ continue;
344
+
345
+ // If we send a part of an order, post with status IN_BACKORDER
346
+ if($qtyToShip < $orderedQty - $shippedQty) {
347
+ $shipmentLine = new Tritac_ChannelEngineApiClient_Models_ShipmentLine();
348
+ // Fill required data
349
+ $shipmentLine->setShipmentId($_shipment->getId());
350
+ $shipmentLine->setOrderLineId($_orderItem->getChannelengineOrderLineId());
351
+ $shipmentLine->setQuantity($orderedQty - $qtyToShip - $shippedQty);
352
+ $shipmentLine->setStatus(Tritac_ChannelEngineApiClient_Enums_ShipmentLineStatus::IN_BACKORDER);
353
+ $expectedDate = $this->_helper->getExpectedShipmentDate($storeId);
354
+ $shipmentLine->setExpectedDate($expectedDate->format('Y-m-d'));
355
+ $shipmentLines[] = $shipmentLine;
356
+ // Put shipment line to shipments collection
357
+ $linesCollection->append($shipmentLine);
358
+ }
359
+ // Initialize new ChannelEngine Shipment Line
360
+ if($qtyToShip > 0) {
361
+ $shipmentLine = new Tritac_ChannelEngineApiClient_Models_ShipmentLine();
362
+ // Fill required data
363
+ $shipmentLine->setShipmentId($_shipment->getId());
364
+ $shipmentLine->setOrderLineId($_orderItem->getChannelengineOrderLineId());
365
+ $shipmentLine->setQuantity($qtyToShip);
366
+ $shipmentLine->setStatus(Tritac_ChannelEngineApiClient_Enums_ShipmentLineStatus::SHIPPED);
367
+ $shipmentLines[] = $shipmentLine;
368
+ // Put shipment line to shipments collection
369
+ $linesCollection->append($shipmentLine);
370
+ }
371
+ }
372
+
373
+ $shipment->setLines($linesCollection);
374
+ // Post shipment to ChannelEngine
375
+ $this->_client[$storeId]->postShipment($shipment);
376
+
377
+ Mage::log("Shippment #{$_shipment->getId()} was placed successfully.");
378
+
379
+ return true;
380
+ }
381
+ }
382
+
383
+ /**
384
+ * Fetch new returns from channelengine
385
+ *
386
+ * @return bool
387
+ */
388
+ public function fetchReturns()
389
+ {
390
+ /**
391
+ * Check if client is initialized
392
+ */
393
+ if(is_null($this->_client))
394
+ return false;
395
+
396
+ foreach($this->_client as $storeId => $_client) {
397
+ /**
398
+ * Retrieve returns
399
+ */
400
+ $returns = $_client->getReturns(array(
401
+ Tritac_ChannelEngineApiClient_Enums_ReturnStatus::DECLARED
402
+ ));
403
+
404
+ /**
405
+ * Check declared returns
406
+ */
407
+ if(is_null($returns) || $returns->count() == 0)
408
+ return false;
409
+
410
+ foreach($returns as $return) {
411
+ $_channelOrder = Mage::getModel('channelengine/order')->loadByChannelOrderId($return->getOrderId());
412
+ $_order = Mage::getModel('sales/order')->load($_channelOrder->getOrderId());
413
+
414
+ if(!$_order->getIncrementId()) {
415
+ continue;
416
+ }
417
+
418
+
419
+ $link = "https://". $this->_config[$storeId]['general']['tenant'] .".channelengine.net/orders/view/". $return->getOrderId();
420
+ $status = $return->getStatus(); // Get return status
421
+ $reason = $return->getReason(); // Get return reason
422
+ $title = "A new return was declared in ChannelEngine (ChannelEngine Order #{$return->getOrderId()})";
423
+ $message = "Magento Order #: <a href='".
424
+ Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('order_id'=>$_order->getOrderId())).
425
+ "'>".
426
+ $_order->getIncrementId().
427
+ "</a><br />";
428
+ $message .= "Status: {$status}<br />";
429
+ $message .= "Reason: {$reason}<br />";
430
+ $message .= "For more details visit ChannelEngine your <a href='".$link."' target='_blank'>account</a>";
431
+
432
+ // Check if notification is already exist
433
+ $_resource = Mage::getSingleton('core/resource');
434
+ $_connectionRead = $_resource->getConnection('core_read');
435
+ $select = $_connectionRead->select()
436
+ ->from($_resource->getTableName('adminnotification/inbox'))
437
+ ->where('title = ?', $title)
438
+ ->where('is_remove != 1')
439
+ ->limit(1);
440
+ $data = $_connectionRead->fetchRow($select);
441
+
442
+ if ($data) {
443
+ continue;
444
+ }
445
+
446
+ // Add new notification
447
+ Mage::getModel('adminnotification/inbox')->addCritical(
448
+ $title,
449
+ $message,
450
+ $link
451
+ );
452
+ }
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Generate products feed for ChannelEngine
458
+ */
459
+ public function generateFeed()
460
+ {
461
+ $start_memory = memory_get_usage();
462
+
463
+ /**
464
+ * Prepare categories array
465
+ */
466
+ $categoryArray = array();
467
+ $parent = Mage::app()->getWebsite(true)->getDefaultStore()->getRootCategoryId();
468
+ $category = Mage::getModel('catalog/category');
469
+ if ($category->checkId($parent)) {
470
+ $storeCategories = $category->getCategories($parent, 0, true, true, true);
471
+ foreach($storeCategories as $_category) {
472
+ $categoryArray[$_category->getId()] = $_category->getData();
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Export products from each store.
478
+ * Note: products with undefined website id will not be export.
479
+ */
480
+ foreach(Mage::app()->getStores() as $_store) {
481
+
482
+ $path = Mage::getBaseDir('media') . DS . 'channelengine' . DS;
483
+ $storeConfig = $this->_helper->getConfig($_store->getId());
484
+ $name = $storeConfig['general']['tenant'].'_products.xml';
485
+ $file = $path . DS . $name;
486
+
487
+ $io = new Varien_Io_File();
488
+ $io->setAllowCreateFolders(true);
489
+ $io->open(array('path' => $path));
490
+ $io->streamOpen($file, 'w+');
491
+ $io->streamLock(true);
492
+ $io->streamWrite('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
493
+ $io->streamWrite('<Products xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . "\n");
494
+
495
+ /**
496
+ * Prepare custom options array
497
+ */
498
+ $storeId = $_store->getId();
499
+ $optionsArray = array();
500
+ $_options = Mage::getModel('catalog/product_option')
501
+ ->getCollection()
502
+ ->addTitleToResult($storeId)
503
+ ->addPriceToResult($storeId)
504
+ ->addValuesToResult($storeId)
505
+ ->setOrder('sort_order', 'asc');
506
+ foreach($_options as $_option) {
507
+ $productId = $_option->getProductId();
508
+ $optionId = $_option->getOptionId();
509
+ $optionsArray[$productId][$optionId] = $_option->getData();
510
+ if($_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN) {
511
+ $optionsArray[$productId][$optionId]['values'] = $_option->getValues();
512
+ }
513
+ }
514
+
515
+ /**
516
+ * Retrieve product collection
517
+ */
518
+ $collection = Mage::getModel('catalog/product')->getCollection()
519
+ ->addAttributeToSelect(array('name', 'description', 'image', 'url_key', 'price', 'cost', 'visibility', 'msrp'), 'left')
520
+ ->addFieldToFilter('type_id', 'simple')
521
+ ->addStoreFilter($_store)
522
+ ->addAttributeToFilter('status', 1)
523
+ ->addAttributeToSort('entity_id', 'DESC');
524
+
525
+ // Add qty and category fields to select
526
+ $collection->getSelect()
527
+ ->joinLeft(
528
+ array('csi' => Mage::getSingleton('core/resource')->getTableName('cataloginventory/stock_item')),
529
+ '`e`.`entity_id` = `csi`.`product_id`',
530
+ array('qty' => 'COALESCE(`qty`, 0)')
531
+ )
532
+ ->joinLeft(
533
+ array('ccp' => Mage::getSingleton('core/resource')->getTableName('catalog/category_product')),
534
+ '`e`.`entity_id` = `ccp`.`product_id`',
535
+ array('category_id' => 'MAX(`ccp`.`category_id`)')
536
+ )
537
+ ->group('e.entity_id');
538
+
539
+ Mage::getSingleton('core/resource_iterator')->walk(
540
+ $collection->getSelect(),
541
+ array(array($this, 'callbackGenerateFeed')),
542
+ array(
543
+ 'io' => $io,
544
+ 'categories' => $categoryArray,
545
+ 'options' => $optionsArray,
546
+ 'store' => $_store,
547
+ 'startMemory' => $start_memory,
548
+ )
549
+ );
550
+
551
+ $io->streamWrite('</Products>');
552
+ $io->streamUnlock();
553
+ $io->streamClose();
554
+
555
+ Mage::log("Product feed {$name} was generated successfully");
556
+ }
557
+
558
+ return true;
559
+ }
560
+
561
+ public function callbackGenerateFeed($args)
562
+ {
563
+ $io = $args['io'];
564
+ $product = $args['row'];
565
+ $categories = $args['categories'];
566
+ $options = $args['options'];
567
+ $_store = $args['store'];
568
+
569
+ $xml = '';
570
+
571
+ $product['store_id'] = $_store->getId();
572
+ /**
573
+ * Add product custom options to feed.
574
+ * Each option value will generate new product row
575
+ */
576
+ if(isset($options[$product['entity_id']])) {
577
+ $product['group_code'] = $product['entity_id'];
578
+ foreach($options[$product['entity_id']] as $option) {
579
+ if(isset($option['values'])) {
580
+ foreach($option['values'] as $_value) {
581
+ $product['id'] = $product['entity_id'].'_'.$option['option_id'].'_'.$_value->getId();
582
+ $additional['title'] = str_replace(' ', '_', $option['default_title']);
583
+ $additional['value'] = $_value->getDefaultTitle();
584
+ $xml .= $this->_getProductXml($product, $categories, $additional);
585
+ }
586
+ } else {
587
+ $product['id'] = $product['entity_id'].'_'.$option['option_id'];
588
+ $additional['title'] = str_replace(' ', '_', $option['default_title']);
589
+ $additional['value'] = '';
590
+ $xml .= $this->_getProductXml($product, $categories, $additional);
591
+ }
592
+ }
593
+ }else {
594
+ $product['id'] = $product['entity_id'];
595
+ $xml .= $this->_getProductXml($product, $categories);
596
+ }
597
+
598
+ $io->streamWrite($xml);
599
+ }
600
+
601
+ protected function _getProductXml($product, $categories, $additional = null)
602
+ {
603
+ $xml = "<Product>";
604
+ $xml .= "<Id>".$product['id']."</Id>";
605
+
606
+ // Add group code with product id if product have custom options
607
+ if(isset($product['group_code'])) {
608
+ $xml .= "<GroupCode><![CDATA[".$product['group_code']."]]></GroupCode>";
609
+ }
610
+ $xml .= "<Name><![CDATA[".$product['name']."]]></Name>";
611
+ $xml .= "<Description><![CDATA[".$product['description']."]]></Description>";
612
+ $xml .= "<Price><![CDATA[".$product['price']."]]></Price>";
613
+ $xml .= "<ListPrice><![CDATA[".$product['msrp']."]]></ListPrice>";
614
+ $xml .= "<PurchasePrice><![CDATA[".$product['cost']."]]></PurchasePrice>";
615
+
616
+ // Retrieve product stock qty
617
+ $xml .= "<Stock><![CDATA[".$product['qty']."]]></Stock>";
618
+ $xml .= "<SKU><![CDATA[".$product['sku']."]]></SKU>";
619
+
620
+ // VAT and Shipping Time are pre configured in extension settings
621
+ if(!empty($this->_config[$product['store_id']]['feed']['vat_rate'])) {
622
+ $vat = $this->_config[$product['store_id']]['feed']['vat_rate'];
623
+ $xml .= "<VAT><![CDATA[".$vat."]]></VAT>";
624
+ }
625
+
626
+ $shippingTime = ($product['qty'] > 0) ? $this->_config[$product['store_id']]['feed']['shipping_time'] : $this->_config[$product['store_id']]['feed']['shipping_time_oos'];
627
+
628
+ if($shippingTime) {
629
+ $xml .= "<ShippingTime><![CDATA[".$shippingTime."]]></ShippingTime>";
630
+ }
631
+
632
+ // Retrieve product url
633
+ $productModel = Mage::getModel('catalog/product');
634
+ $productModel->setData('entity_id', $product['entity_id']);
635
+ $productModel->setData('url_key', $product['url_key']);
636
+ $productModel->setData('store_id', Mage::app()->getWebsite(true)->getDefaultStore()->getId());
637
+ $url = $productModel->getProductUrl();
638
+ $xml .= "<Url><![CDATA[".$url."]]></Url>";
639
+
640
+ if(isset($product['image']) && $product['image'] != 'no_selection') {
641
+ $imgUrl = Mage::getSingleton('catalog/product_media_config')->getMediaUrl($product['image']);
642
+ $xml .= "<ImageUrl><![CDATA[".$imgUrl."]]></ImageUrl>";
643
+ }
644
+
645
+ // Prepare category path
646
+ if(!empty($product['category_id']) && !empty($categories)) {
647
+ $categoryId = $product['category_id'];
648
+ $categoryPathIds = explode('/', $categories[$categoryId]['path']);
649
+ $categoryPath = null;
650
+ foreach($categoryPathIds as $id) {
651
+ if($id > 2) {
652
+ $categoryPath .= ($categoryPath) ? ' > ':'';
653
+ $categoryPath .= $categories[$id]['name'];
654
+ }
655
+ }
656
+ if($categoryPath) {
657
+ $xml .= "<Category><![CDATA[".$categoryPath."]]></Category>";
658
+ }
659
+ }
660
+
661
+ if(isset($additional['title']) && isset($additional['value'])) {
662
+ $title = preg_replace("/[^a-zA-Z0-9]/", "", $additional['title']);
663
+ $xml .= sprintf("<%1\$s><![CDATA[%2\$s]]></%1\$s>",
664
+ $title,
665
+ $additional['value']
666
+ );
667
+ }
668
+
669
+ $xml .= "</Product>\n";
670
+
671
+ return $xml;
672
+ }
673
+ }
app/code/community/Tritac/ChannelEngine/Model/Order.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Model_Order extends Mage_Core_Model_Abstract {
3
+
4
+ protected function _construct()
5
+ {
6
+ $this->_init('channelengine/order');
7
+ }
8
+
9
+ /**
10
+ * Load channel order by magento order ID
11
+ *
12
+ * @param $orderId
13
+ * @return Tritac_ChannelEngine_Model_Order
14
+ */
15
+ public function loadByOrderId($orderId)
16
+ {
17
+ $this->_getResource()->loadByOrderId($this, $orderId);
18
+ return $this;
19
+ }
20
+
21
+ /**
22
+ * Load channel order by channel order ID
23
+ *
24
+ * @param $orderId
25
+ * @return Tritac_ChannelEngine_Model_Order
26
+ */
27
+ public function loadByChannelOrderId($orderId)
28
+ {
29
+ $this->_getResource()->loadByChannelOrderId($this, $orderId);
30
+ return $this;
31
+ }
32
+ }
app/code/community/Tritac/ChannelEngine/Model/Payment/Method/Channelengine.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * ChannelEngine Payment Method
4
+ */
5
+ class Tritac_ChannelEngine_Model_Payment_Method_Channelengine extends Mage_Payment_Model_Method_Abstract {
6
+
7
+ /**
8
+ * System payment method code
9
+ *
10
+ * @var string
11
+ */
12
+ protected $_code = 'channelengine';
13
+
14
+ public function isAvailable($quote = null)
15
+ {
16
+ if($quote->getIsSystem() && $quote->getPayment()->getMethod() == $this->_code) {
17
+ return true;
18
+ }
19
+
20
+ return false;
21
+ }
22
+ }
app/code/community/Tritac/ChannelEngine/Model/Resource/Order.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Model_Resource_Order extends Mage_Core_Model_Resource_Db_Abstract {
3
+
4
+ protected function _construct()
5
+ {
6
+ $this->_init('channelengine/order', 'entity_id');
7
+ }
8
+
9
+ /**
10
+ * Load channel order by magento order ID
11
+ *
12
+ * @param Tritac_ChannelEngine_Model_Order $order
13
+ * @param int $orderId
14
+ * @return Tritac_ChannelEngine_Model_Resource_Order
15
+ */
16
+ public function loadByOrderId(Tritac_ChannelEngine_Model_Order $order, $orderId)
17
+ {
18
+
19
+ $adapter = $this->_getReadAdapter();
20
+ $bind = array('order_id' => $orderId);
21
+ $select = $adapter->select()
22
+ ->from($this->getMainTable(), array($this->getIdFieldName()))
23
+ ->where('order_id = :order_id');
24
+
25
+ $entityId = $adapter->fetchOne($select, $bind);
26
+ if ($entityId) {
27
+ $this->load($order, $entityId );
28
+ } else {
29
+ $order->setData(array());
30
+ }
31
+
32
+ return $this;
33
+ }
34
+
35
+ /**
36
+ * Load channel order by channel order ID
37
+ *
38
+ * @param Tritac_ChannelEngine_Model_Order $order
39
+ * @param int $orderId
40
+ * @return Tritac_ChannelEngine_Model_Resource_Order
41
+ */
42
+ public function loadByChannelOrderId(Tritac_ChannelEngine_Model_Order $order, $orderId)
43
+ {
44
+
45
+ $adapter = $this->_getReadAdapter();
46
+ $bind = array('channel_order_id' => $orderId);
47
+ $select = $adapter->select()
48
+ ->from($this->getMainTable(), array($this->getIdFieldName()))
49
+ ->where('channel_order_id = :channel_order_id');
50
+
51
+ $entityId = $adapter->fetchOne($select, $bind);
52
+ if ($entityId) {
53
+ $this->load($order, $entityId );
54
+ } else {
55
+ $order->setData(array());
56
+ }
57
+
58
+ return $this;
59
+ }
60
+ }
app/code/community/Tritac/ChannelEngine/Model/Resource/Order/Collection.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Model_Resource_Order_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract {
3
+
4
+ protected function _construct() {
5
+ $this->_init('channelengine/order');
6
+ }
7
+ }
app/code/community/Tritac/ChannelEngine/Model/Resource/Setup.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ class Tritac_ChannelEngine_Model_Resource_Setup extends Mage_Catalog_Model_Resource_Setup {
4
+ }
app/code/community/Tritac/ChannelEngine/Model/System/Config/Source/Shipping.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Model_System_Config_Source_Shipping {
3
+
4
+ protected $_options = null;
5
+
6
+ public function toOptionArray() {
7
+
8
+ if(is_null($this->_options)) {
9
+ $_activeCarriers = Mage::getModel('shipping/config')->getActiveCarriers();
10
+
11
+ foreach($_activeCarriers as $carrierCode => $_carrier) {
12
+
13
+ if($_methods = $_carrier->getAllowedMethods()) {
14
+
15
+ if(!$title = Mage::getStoreConfig("carriers/{$_carrier->getId()}/title")) {
16
+ $title = $carrierCode;
17
+ }
18
+
19
+ $methods = array();
20
+
21
+ foreach($_methods as $methodCode => $method) {
22
+
23
+ $methods[] = array(
24
+ 'label' => $title.' – '.$method,
25
+ 'value' => $carrierCode.'_'.$methodCode
26
+ );
27
+ }
28
+
29
+ $this->_options[] = array(
30
+ 'label' => $title,
31
+ 'value' => $methods
32
+ );
33
+ }
34
+ }
35
+ }
36
+
37
+ return $this->_options;
38
+
39
+ }
40
+ }
app/code/community/Tritac/ChannelEngine/controllers/Adminhtml/GenerateController.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Tritac_ChannelEngine_Adminhtml_GenerateController extends Mage_Adminhtml_Controller_Action
3
+ {
4
+ public function ajaxAction() {
5
+
6
+ $observer = Mage::getModel('channelengine/observer');
7
+
8
+ if($observer->generateFeed()) {
9
+ $this->getResponse()->setBody(1);
10
+ }
11
+ }
12
+ }
app/code/community/Tritac/ChannelEngine/controllers/TestController.php ADDED
@@ -0,0 +1,372 @@